From ef69c01da56677d6c1510853c78d9e097be761dd Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Fri, 1 Mar 2019 09:50:50 +0000 Subject: [PATCH 1/9] Create FootpathSceneryRemoveAction to split up footpath place --- .../interface/ViewportInteraction.cpp | 13 +-- src/openrct2/Game.h | 2 + .../actions/FootpathSceneryPlaceAction.hpp | 64 +++++++++++ .../actions/FootpathSceneryRemoveAction.hpp | 105 ++++++++++++++++++ .../actions/GameActionRegistration.cpp | 4 + src/openrct2/core/DataSerialiserTraits.h | 26 +++++ src/openrct2/world/Scenery.cpp | 7 +- 7 files changed, 208 insertions(+), 13 deletions(-) create mode 100644 src/openrct2/actions/FootpathSceneryPlaceAction.hpp create mode 100644 src/openrct2/actions/FootpathSceneryRemoveAction.hpp diff --git a/src/openrct2-ui/interface/ViewportInteraction.cpp b/src/openrct2-ui/interface/ViewportInteraction.cpp index b0bf8c4fb3..57fb23e329 100644 --- a/src/openrct2-ui/interface/ViewportInteraction.cpp +++ b/src/openrct2-ui/interface/ViewportInteraction.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -507,16 +508,8 @@ static void viewport_interaction_remove_footpath(TileElement* tileElement, int32 */ static void viewport_interaction_remove_footpath_item(TileElement* tileElement, int32_t x, int32_t y) { - int32_t type = tileElement->AsPath()->GetPathEntryIndex(); - if (tileElement->AsPath()->IsQueue()) - type |= 0x80; - - int32_t slopeData = tileElement->AsPath()->GetSlopeDirection(); - if (tileElement->AsPath()->IsSloped()) - slopeData |= FOOTPATH_PROPERTIES_FLAG_IS_SLOPED; - - gGameCommandErrorTitle = STR_CANT_REMOVE_THIS; - game_do_command(x, (slopeData << 8) | 1, y, (type << 8) | tileElement->base_height, GAME_COMMAND_PLACE_PATH, 0, 0); + auto footpathSceneryRemoveAction = FootpathSceneryRemoveAction({x, y, tileElement->base_height * 8}); + GameActions::Execute(&footpathSceneryRemoveAction); } /** diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index 3d210d9289..4ad216a95c 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -94,6 +94,8 @@ enum GAME_COMMAND GAME_COMMAND_SET_CLIMATE, // GA GAME_COMMAND_SET_COLOUR_SCHEME, // GA GAME_COMMAND_SET_STAFF_COSTUME, // GA + GAME_COMMAND_PLACE_FOOTPATH_SCENERY, // GA + GAME_COMMAND_REMOVE_FOOTPATH_SCENERY, // GA GAME_COMMAND_COUNT, }; diff --git a/src/openrct2/actions/FootpathSceneryPlaceAction.hpp b/src/openrct2/actions/FootpathSceneryPlaceAction.hpp new file mode 100644 index 0000000000..1c76b5f365 --- /dev/null +++ b/src/openrct2/actions/FootpathSceneryPlaceAction.hpp @@ -0,0 +1,64 @@ +/***************************************************************************** + * 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 "../Cheats.h" +#include "../OpenRCT2.h" +#include "../core/MemoryStream.h" +#include "../interface/Window.h" +#include "../localisation/StringIds.h" +#include "../management/Finance.h" +#include "../world/Footpath.h" +#include "../world/Location.hpp" +#include "../world/Park.h" +#include "../world/Wall.h" +#include "GameAction.h" + +DEFINE_GAME_ACTION(FootpathSceneryPlaceAction, GAME_COMMAND_PLACE_FOOTPATH_SCENERY, GameActionResult) +{ +private: + int32_t _x; + int32_t _y; + int32_t _z; + +public: + FootpathSceneryPlaceAction() = default; + FootpathSceneryPlaceAction(int32_t x, int32_t y, int32_t z) + : _x(x) + , _y(y) + , _z(z) + { + } + + uint16_t GetActionFlags() const override + { + return GameAction::GetActionFlags(); + } + + void Serialise(DataSerialiser & stream) override + { + GameAction::Serialise(stream); + + stream << DS_TAG(_x) << DS_TAG(_y) << DS_TAG(_z); + } + + GameActionResult::Ptr Query() const override + { + GameActionResult::Ptr res = std::make_unique(); + + return res; + } + + GameActionResult::Ptr Execute() const override + { + GameActionResult::Ptr res = std::make_unique(); + return res; + } +}; diff --git a/src/openrct2/actions/FootpathSceneryRemoveAction.hpp b/src/openrct2/actions/FootpathSceneryRemoveAction.hpp new file mode 100644 index 0000000000..b810f830e6 --- /dev/null +++ b/src/openrct2/actions/FootpathSceneryRemoveAction.hpp @@ -0,0 +1,105 @@ +/***************************************************************************** + * 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 "../Cheats.h" +#include "../OpenRCT2.h" +#include "../core/MemoryStream.h" +#include "../interface/Window.h" +#include "../localisation/StringIds.h" +#include "../management/Finance.h" +#include "../world/Footpath.h" +#include "../world/Location.hpp" +#include "../world/Park.h" +#include "../world/Wall.h" +#include "GameAction.h" + +DEFINE_GAME_ACTION(FootpathSceneryRemoveAction, GAME_COMMAND_REMOVE_FOOTPATH_SCENERY, GameActionResult) +{ +private: + CoordsXYZ _loc; + +public: + FootpathSceneryRemoveAction() = default; + FootpathSceneryRemoveAction(CoordsXYZ loc) + : _loc(loc) + { + } + + uint16_t GetActionFlags() const override + { + return GameAction::GetActionFlags(); + } + + void Serialise(DataSerialiser & stream) override + { + GameAction::Serialise(stream); + + stream << DS_TAG(_loc); + } + + GameActionResult::Ptr Query() const override + { + if (!map_is_location_valid({_loc.x, _loc.y})) + { + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_REMOVE_THIS, STR_OFF_EDGE_OF_MAP); + } + + if (!((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) || gCheatsSandboxMode) + && !map_is_location_owned(_loc.x, _loc.y, _loc.z / 8)) + { + return MakeResult(GA_ERROR::DISALLOWED, STR_CANT_REMOVE_THIS, STR_LAND_NOT_OWNED_BY_PARK); + } + + if (_loc.z / 8 < 2) + { + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_REMOVE_THIS, STR_TOO_LOW); + } + + if (_loc.z / 8 > 248) + { + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_REMOVE_THIS, STR_TOO_HIGH); + } + + auto tileElement = map_get_footpath_element(_loc.x / 32, _loc.y / 32, _loc.z / 8); + auto pathElement = tileElement->AsPath(); + + if (pathElement == nullptr) + { + log_error("Could not find path element."); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_REMOVE_THIS); + } + auto res = MakeResult(); + res->Cost = MONEY(0, 0); + return res; + } + + GameActionResult::Ptr Execute() const override + { + auto tileElement = map_get_footpath_element(_loc.x / 32, _loc.y / 32, _loc.z / 8); + auto pathElement = tileElement->AsPath(); + + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST)) + { + footpath_interrupt_peeps(_loc.x, _loc.y, _loc.z); + } + + if (pathElement == nullptr) + { + log_error("Could not find path element."); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_REMOVE_THIS); + } + + pathElement->SetAddition(0); + auto res = MakeResult(); + res->Cost = MONEY(0, 0); + return res; + } +}; diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index f99e9a3e07..24ffea581e 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -11,6 +11,8 @@ #include "ClearAction.hpp" #include "ClimateSetAction.hpp" #include "FootpathRemoveAction.hpp" +#include "FootpathSceneryPlaceAction.hpp" +#include "FootpathSceneryRemoveAction.hpp" #include "GameAction.h" #include "GuestSetNameAction.hpp" #include "LandSetHeightAction.hpp" @@ -56,6 +58,8 @@ namespace GameActions Register(); Register(); Register(); + Register(); + Register(); Register(); Register(); Register(); diff --git a/src/openrct2/core/DataSerialiserTraits.h b/src/openrct2/core/DataSerialiserTraits.h index e415f18bab..99c71baddb 100644 --- a/src/openrct2/core/DataSerialiserTraits.h +++ b/src/openrct2/core/DataSerialiserTraits.h @@ -343,6 +343,32 @@ template<> struct DataSerializerTraits } }; +template<> struct DataSerializerTraits +{ + static void encode(IStream* stream, const CoordsXYZ& coord) + { + stream->WriteValue(ByteSwapBE(coord.x)); + stream->WriteValue(ByteSwapBE(coord.y)); + stream->WriteValue(ByteSwapBE(coord.z)); + } + + static void decode(IStream* stream, CoordsXYZ& coord) + { + auto x = ByteSwapBE(stream->ReadValue()); + auto y = ByteSwapBE(stream->ReadValue()); + auto z = ByteSwapBE(stream->ReadValue()); + coord = CoordsXYZ{ x, y, z }; + } + + static void log(IStream* stream, const CoordsXYZ& coord) + { + char msg[128] = {}; + snprintf( + msg, sizeof(msg), "CoordsXYZ(x = %d, y = %d, z = %d)", coord.x, coord.y, coord.z); + stream->Write(msg, strlen(msg)); + } +}; + template<> struct DataSerializerTraits { static void encode(IStream* stream, const CoordsXYZD& coord) diff --git a/src/openrct2/world/Scenery.cpp b/src/openrct2/world/Scenery.cpp index 6aed6e3766..914d5018c2 100644 --- a/src/openrct2/world/Scenery.cpp +++ b/src/openrct2/world/Scenery.cpp @@ -14,6 +14,7 @@ #include "../Game.h" #include "../actions/LargeSceneryRemoveAction.hpp" #include "../actions/SmallSceneryRemoveAction.hpp" +#include "../actions/FootpathSceneryRemoveAction.hpp" #include "../actions/WallRemoveAction.hpp" #include "../common.h" #include "../localisation/Localisation.h" @@ -205,9 +206,9 @@ void scenery_remove_ghost_tool_placement() if (tileElement->base_height != z) continue; - game_do_command( - x, 233 | (gSceneryPlacePathSlope << 8), y, z | (gSceneryPlacePathType << 8), GAME_COMMAND_PLACE_PATH, - gSceneryGhostPathObjectType & 0xFFFF0000, 0); + auto footpathSceneryRemoveAction = FootpathSceneryRemoveAction({x, y, z * 8}); + footpathSceneryRemoveAction.SetFlags(GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_GHOST); + GameActions::Execute(&footpathSceneryRemoveAction); break; } while (!(tileElement++)->IsLastForTile()); } From 510d71ab68513d6ecebae2b6d92597ca6cca22ca Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Fri, 1 Mar 2019 10:53:52 +0000 Subject: [PATCH 2/9] Add FootpathSceneryPlaceAction --- src/openrct2-ui/windows/TopToolbar.cpp | 58 ++++--- .../actions/FootpathSceneryPlaceAction.hpp | 163 ++++++++++++++++-- .../actions/FootpathSceneryRemoveAction.hpp | 10 ++ src/openrct2/network/NetworkAction.cpp | 2 + src/openrct2/world/Footpath.cpp | 82 +-------- 5 files changed, 200 insertions(+), 115 deletions(-) diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index ec6ce4a1ff..d28c609c2c 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1816,14 +1817,18 @@ static void window_top_toolbar_scenery_tool_down(int16_t x, int16_t y, rct_windo } case SCENERY_TYPE_PATH_ITEM: { - int32_t flags = GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_PATH_SCENERY | (parameter_1 & 0xFF00); + auto pathItemType = parameter_3 & 0xFF; + int32_t z = (parameter_2 & 0xFF) * 8; + auto footpathSceneryPlaceAction = FootpathSceneryPlaceAction({ gridX, gridY, z }, pathItemType); - gGameCommandErrorTitle = STR_CANT_POSITION_THIS_HERE; - int32_t cost = game_do_command(gridX, flags, gridY, parameter_2, GAME_COMMAND_PLACE_PATH, parameter_3, 0); - if (cost != MONEY32_UNDEFINED) - { - audio_play_sound_at_location(SOUND_PLACE_ITEM, gCommandPosition.x, gCommandPosition.y, gCommandPosition.z); - } + footpathSceneryPlaceAction.SetCallback([](const GameAction* ga, const GameActionResult* result) { + if (result->Error != GA_ERROR::OK) + { + return; + } + audio_play_sound_at_location(SOUND_PLACE_ITEM, result->Position.x, result->Position.y, result->Position.z); + }); + auto res = GameActions::Execute(&footpathSceneryPlaceAction); break; } case SCENERY_TYPE_WALL: @@ -2489,27 +2494,32 @@ static money32 try_place_ghost_scenery( break; } case 1: + { // Path Bits // 6e265b - cost = game_do_command( - map_tile.x, - (parameter_1 & 0xFF00) - | (GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_5 - | GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_PATH_SCENERY), - map_tile.y, parameter_2, GAME_COMMAND_PLACE_PATH, parameter_3, 0); + auto pathItemType = parameter_3 & 0xFF; + int32_t z = (parameter_2 & 0xFF) * 8; + auto footpathSceneryPlaceAction = FootpathSceneryPlaceAction({ map_tile.x, map_tile.y, z }, pathItemType); + footpathSceneryPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED); + footpathSceneryPlaceAction.SetCallback([=](const GameAction* ga, const GameActionResult* result) { + if (result->Error != GA_ERROR::OK) + { + return; + } + gSceneryGhostPosition.x = map_tile.x; + gSceneryGhostPosition.y = map_tile.y; + gSceneryGhostPosition.z = (parameter_2 & 0xFF); + gSceneryPlacePathSlope = ((parameter_1 >> 8) & 0xFF); + gSceneryPlacePathType = ((parameter_2 >> 8) & 0xFF); + gSceneryGhostPathObjectType = parameter_3; - if (cost == MONEY32_UNDEFINED) - return cost; - - gSceneryGhostPosition.x = map_tile.x; - gSceneryGhostPosition.y = map_tile.y; - gSceneryGhostPosition.z = (parameter_2 & 0xFF); - gSceneryPlacePathSlope = ((parameter_1 >> 8) & 0xFF); - gSceneryPlacePathType = ((parameter_2 >> 8) & 0xFF); - gSceneryGhostPathObjectType = parameter_3; - - gSceneryGhostType |= SCENERY_GHOST_FLAG_1; + gSceneryGhostType |= SCENERY_GHOST_FLAG_1; + }); + auto res = GameActions::Execute(&footpathSceneryPlaceAction); + if (res->Error != GA_ERROR::OK) + return MONEY32_UNDEFINED; break; + } case 2: // Walls // 6e26b0 diff --git a/src/openrct2/actions/FootpathSceneryPlaceAction.hpp b/src/openrct2/actions/FootpathSceneryPlaceAction.hpp index 1c76b5f365..3afff671b6 100644 --- a/src/openrct2/actions/FootpathSceneryPlaceAction.hpp +++ b/src/openrct2/actions/FootpathSceneryPlaceAction.hpp @@ -24,16 +24,14 @@ DEFINE_GAME_ACTION(FootpathSceneryPlaceAction, GAME_COMMAND_PLACE_FOOTPATH_SCENERY, GameActionResult) { private: - int32_t _x; - int32_t _y; - int32_t _z; + CoordsXYZ _loc; + uint8_t _pathItemType; public: FootpathSceneryPlaceAction() = default; - FootpathSceneryPlaceAction(int32_t x, int32_t y, int32_t z) - : _x(x) - , _y(y) - , _z(z) + FootpathSceneryPlaceAction(CoordsXYZ loc, uint8_t pathItemType) + : _loc(loc) + , _pathItemType(pathItemType) { } @@ -46,19 +44,164 @@ public: { GameAction::Serialise(stream); - stream << DS_TAG(_x) << DS_TAG(_y) << DS_TAG(_z); + stream << DS_TAG(_loc) << DS_TAG(_pathItemType); } GameActionResult::Ptr Query() const override { - GameActionResult::Ptr res = std::make_unique(); + auto res = MakeResult(); + res->ExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; + res->Position = _loc; + if (!map_is_location_valid({ _loc.x, _loc.y })) + { + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE, STR_OFF_EDGE_OF_MAP); + } + if (!((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) || gCheatsSandboxMode) + && !map_is_location_owned(_loc.x, _loc.y, _loc.z / 8)) + { + return MakeResult(GA_ERROR::DISALLOWED, STR_CANT_POSITION_THIS_HERE, STR_LAND_NOT_OWNED_BY_PARK); + } + + if (_loc.z / 8 < 2) + { + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE, STR_TOO_LOW); + } + + if (_loc.z / 8 > 248) + { + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE, STR_TOO_HIGH); + } + + auto tileElement = map_get_footpath_element(_loc.x / 32, _loc.y / 32, _loc.z / 8); + auto pathElement = tileElement->AsPath(); + + if (pathElement == nullptr) + { + log_error("Could not find path element."); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE); + } + + // No change + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && pathElement->GetAddition() == _pathItemType + && !(pathElement->IsBroken())) + { + if (GetFlags() & GAME_COMMAND_FLAG_4) + return MakeResult(GA_ERROR::UNKNOWN, STR_CANT_POSITION_THIS_HERE); + + return res; + } + + if (_pathItemType != 0) + { + rct_scenery_entry* sceneryEntry = get_footpath_item_entry(_pathItemType - 1); + if (sceneryEntry == nullptr) + { + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE); + } + uint16_t sceneryFlags = sceneryEntry->path_bit.flags; + + if ((sceneryFlags & PATH_BIT_FLAG_DONT_ALLOW_ON_SLOPE) && pathElement->IsSloped()) + { + return MakeResult( + GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE, STR_CANT_BUILD_THIS_ON_SLOPED_FOOTPATH); + } + + if ((sceneryFlags & PATH_BIT_FLAG_DONT_ALLOW_ON_QUEUE) && pathElement->IsQueue()) + { + return MakeResult( + GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE, STR_CANNOT_PLACE_THESE_ON_QUEUE_LINE_AREA); + } + + if (!(sceneryFlags & (PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER | PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW)) + && (pathElement->GetEdges()) == 0x0F) + { + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE); + } + + if ((sceneryFlags & PATH_BIT_FLAG_IS_QUEUE_SCREEN) && !pathElement->IsQueue()) + { + return MakeResult( + GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE, STR_CAN_ONLY_PLACE_THESE_ON_QUEUE_AREA); + } + + res->Cost = sceneryEntry->path_bit.price; + } + + if (GetFlags() & GAME_COMMAND_FLAG_4) + return MakeResult(GA_ERROR::UNKNOWN, STR_CANT_POSITION_THIS_HERE); + + // Should place a ghost? + if (GetFlags() & GAME_COMMAND_FLAG_GHOST) + { + // Check if there is something on the path already + if (pathElement->HasAddition()) + { + return MakeResult(GA_ERROR::ITEM_ALREADY_PLACED, STR_CANT_POSITION_THIS_HERE); + } + } return res; } GameActionResult::Ptr Execute() const override { - GameActionResult::Ptr res = std::make_unique(); + auto res = MakeResult(); + res->Position = _loc; + res->ExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; + + auto tileElement = map_get_footpath_element(_loc.x / 32, _loc.y / 32, _loc.z / 8); + auto pathElement = tileElement->AsPath(); + + if (pathElement == nullptr) + { + log_error("Could not find path element."); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE); + } + + // No change + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && pathElement->GetAddition() == _pathItemType + && !(pathElement->IsBroken()) && !pathElement->AdditionIsGhost()) + { + return res; + } + + if (_pathItemType != 0) + { + rct_scenery_entry* sceneryEntry = get_footpath_item_entry(_pathItemType - 1); + if (sceneryEntry == nullptr) + { + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE); + } + + res->Cost = sceneryEntry->path_bit.price; + } + + if (GetFlags() & GAME_COMMAND_FLAG_GHOST) + { + pathElement->SetAdditionIsGhost(true); + } + else + { + footpath_interrupt_peeps(_loc.x, _loc.y, _loc.z); + } + + if ((_pathItemType != 0 && !(GetFlags() & GAME_COMMAND_FLAG_GHOST)) + || (_pathItemType == 0 && pathElement->AdditionIsGhost())) + { + pathElement->SetAdditionIsGhost(false); + } + + pathElement->SetAddition(_pathItemType); + pathElement->SetIsBroken(false); + if (_pathItemType != 0) + { + rct_scenery_entry* scenery_entry = get_footpath_item_entry(_pathItemType - 1); + if (scenery_entry != nullptr && scenery_entry->path_bit.flags & PATH_BIT_FLAG_IS_BIN) + { + pathElement->SetAdditionStatus(255); + } + } + map_invalidate_tile_full(_loc.x, _loc.y); return res; } }; diff --git a/src/openrct2/actions/FootpathSceneryRemoveAction.hpp b/src/openrct2/actions/FootpathSceneryRemoveAction.hpp index b810f830e6..5c64b0318e 100644 --- a/src/openrct2/actions/FootpathSceneryRemoveAction.hpp +++ b/src/openrct2/actions/FootpathSceneryRemoveAction.hpp @@ -76,7 +76,14 @@ public: log_error("Could not find path element."); return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_REMOVE_THIS); } + + if (!pathElement->AdditionIsGhost() && (GetFlags() & GAME_COMMAND_FLAG_GHOST)) + { + log_error("Tried to remove non ghost during ghost removal."); + return MakeResult(GA_ERROR::DISALLOWED, STR_CANT_REMOVE_THIS); + } auto res = MakeResult(); + res->Position = _loc; res->Cost = MONEY(0, 0); return res; } @@ -98,7 +105,10 @@ public: } pathElement->SetAddition(0); + map_invalidate_tile_full(_loc.x, _loc.y); + auto res = MakeResult(); + res->Position = _loc; res->Cost = MONEY(0, 0); return res; } diff --git a/src/openrct2/network/NetworkAction.cpp b/src/openrct2/network/NetworkAction.cpp index f89ac947a0..af28b7e488 100644 --- a/src/openrct2/network/NetworkAction.cpp +++ b/src/openrct2/network/NetworkAction.cpp @@ -153,6 +153,8 @@ const std::array NetworkActions::Action GAME_COMMAND_PLACE_PATH, GAME_COMMAND_PLACE_PATH_FROM_TRACK, GAME_COMMAND_REMOVE_PATH, + GAME_COMMAND_PLACE_FOOTPATH_SCENERY, + GAME_COMMAND_REMOVE_FOOTPATH_SCENERY, }, }, NetworkAction{ diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index 6b4c100d4c..31d155d839 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -324,87 +324,7 @@ static money32 footpath_element_update( } else if (pathItemType != 0) { - if (!(flags & GAME_COMMAND_FLAG_GHOST) && tileElement->AsPath()->GetAddition() == pathItemType - && !(tileElement->AsPath()->IsBroken())) - { - if (flags & GAME_COMMAND_FLAG_4) - return MONEY32_UNDEFINED; - - return gParkFlags & PARK_FLAGS_NO_MONEY ? 0 : gFootpathPrice; - } - - if (pathItemType != 0) - { - rct_scenery_entry* scenery_entry = get_footpath_item_entry(pathItemType - 1); - uint16_t unk6 = scenery_entry->path_bit.flags; - - if ((unk6 & PATH_BIT_FLAG_DONT_ALLOW_ON_SLOPE) && tileElement->AsPath()->IsSloped()) - { - gGameCommandErrorText = STR_CANT_BUILD_THIS_ON_SLOPED_FOOTPATH; - return MONEY32_UNDEFINED; - } - - if ((unk6 & PATH_BIT_FLAG_DONT_ALLOW_ON_QUEUE) && tileElement->AsPath()->IsQueue()) - { - gGameCommandErrorText = STR_CANNOT_PLACE_THESE_ON_QUEUE_LINE_AREA; - return MONEY32_UNDEFINED; - } - - if (!(unk6 & (PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER | PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW)) - && (tileElement->AsPath()->GetEdges()) == 0x0F) - { - gGameCommandErrorText = STR_NONE; - return MONEY32_UNDEFINED; - } - - if ((unk6 & PATH_BIT_FLAG_IS_QUEUE_SCREEN) && !tileElement->AsPath()->IsQueue()) - { - gGameCommandErrorText = STR_CAN_ONLY_PLACE_THESE_ON_QUEUE_AREA; - return MONEY32_UNDEFINED; - } - - gFootpathPrice += scenery_entry->path_bit.price; - } - - if (flags & GAME_COMMAND_FLAG_4) - return MONEY32_UNDEFINED; - - // Should place a ghost? - if (flags & GAME_COMMAND_FLAG_GHOST) - { - // Check if there is something on the path already - if (tileElement->AsPath()->HasAddition()) - { - gGameCommandErrorText = STR_NONE; - return MONEY32_UNDEFINED; - } - - // There is nothing yet - check if we should place a ghost - if (flags & GAME_COMMAND_FLAG_APPLY) - tileElement->AsPath()->SetAdditionIsGhost(true); - } - - if (!(flags & GAME_COMMAND_FLAG_APPLY)) - return gParkFlags & PARK_FLAGS_NO_MONEY ? 0 : gFootpathPrice; - - if ((pathItemType != 0 && !(flags & GAME_COMMAND_FLAG_GHOST)) - || (pathItemType == 0 && tileElement->AsPath()->AdditionIsGhost())) - { - tileElement->AsPath()->SetAdditionIsGhost(false); - } - - tileElement->AsPath()->SetAddition(pathItemType); - tileElement->AsPath()->SetIsBroken(false); - if (pathItemType != 0) - { - rct_scenery_entry* scenery_entry = get_footpath_item_entry(pathItemType - 1); - if (scenery_entry != nullptr && scenery_entry->path_bit.flags & PATH_BIT_FLAG_IS_BIN) - { - tileElement->AsPath()->SetAdditionStatus(255); - } - } - map_invalidate_tile_full(x, y); - return gParkFlags & PARK_FLAGS_NO_MONEY ? 0 : gFootpathPrice; + Guard::Assert(false, "No longer in use. Use FootpathScenery{Place/Remove}Action."); } if (flags & GAME_COMMAND_FLAG_4) From c8fd5174ae8d36851b78f736001b5ac9e89807ca Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Fri, 1 Mar 2019 12:57:58 +0000 Subject: [PATCH 3/9] Implement footpathplace --- src/openrct2-ui/windows/Footpath.cpp | 28 +- src/openrct2/actions/FootpathPlaceAction.hpp | 437 ++++++++++++++++++ .../actions/GameActionRegistration.cpp | 2 + src/openrct2/world/Footpath.cpp | 6 +- src/openrct2/world/Footpath.h | 2 + 5 files changed, 458 insertions(+), 17 deletions(-) create mode 100644 src/openrct2/actions/FootpathPlaceAction.hpp diff --git a/src/openrct2-ui/windows/Footpath.cpp b/src/openrct2-ui/windows/Footpath.cpp index 69b285aa19..2bb43bcd9d 100644 --- a/src/openrct2-ui/windows/Footpath.cpp +++ b/src/openrct2-ui/windows/Footpath.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -847,7 +848,7 @@ static void window_footpath_set_selection_start_bridge_at_point(int32_t screenX, */ static void window_footpath_place_path_at_point(int32_t x, int32_t y) { - int32_t interactionType, currentType, selectedType, z, cost; + int32_t interactionType, currentType, selectedType, z; TileElement* tileElement; if (_footpathErrorOccured) @@ -894,19 +895,18 @@ static void window_footpath_place_path_at_point(int32_t x, int32_t y) // Try and place path gGameCommandErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE; - cost = footpath_place(selectedType, x, y, z, currentType, GAME_COMMAND_FLAG_APPLY); - - if (cost == MONEY32_UNDEFINED) - { - _footpathErrorOccured = true; - } - else if (gFootpathPrice != 0) - { - // bp = RCT2_ADDRESS_COMMAND_MAP_Z - // dx = RCT2_ADDRESS_COMMAND_MAP_Y - // cx = RCT2_ADDRESS_COMMAND_MAP_X - audio_play_sound_at_location(SOUND_PLACE_ITEM, gCommandPosition.x, gCommandPosition.y, gCommandPosition.z); - } + auto footpathPlaceAction = FootpathPlaceAction({ x, y, z * 8 }, currentType, selectedType); + footpathPlaceAction.SetCallback([](const GameAction* ga, const GameActionResult* result) { + if (result->Error == GA_ERROR::OK) + { + audio_play_sound_at_location(SOUND_PLACE_ITEM, result->Position.x, result->Position.y, result->Position.z); + } + else + { + _footpathErrorOccured = true; + } + }); + GameActions::Execute(&footpathPlaceAction); } /** diff --git a/src/openrct2/actions/FootpathPlaceAction.hpp b/src/openrct2/actions/FootpathPlaceAction.hpp new file mode 100644 index 0000000000..deaab17a53 --- /dev/null +++ b/src/openrct2/actions/FootpathPlaceAction.hpp @@ -0,0 +1,437 @@ +/***************************************************************************** + * 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 "../Cheats.h" +#include "../OpenRCT2.h" +#include "../core/MemoryStream.h" +#include "../interface/Window.h" +#include "../localisation/StringIds.h" +#include "../management/Finance.h" +#include "../world/Footpath.h" +#include "../world/Location.hpp" +#include "../world/Park.h" +#include "../world/Surface.h" +#include "../world/Wall.h" +#include "GameAction.h" + +DEFINE_GAME_ACTION(FootpathPlaceAction, GAME_COMMAND_PLACE_PATH, GameActionResult) +{ +private: + CoordsXYZ _loc; + uint8_t _slope; + uint8_t _type; + uint8_t _direction = 0xFF; + +public: + FootpathPlaceAction() = default; + FootpathPlaceAction(CoordsXYZ loc, uint8_t slope, uint8_t type, uint8_t direction = 0xFF) + : _loc(loc) + , _slope(slope) + , _type(type) + , _direction(direction) + { + } + + uint16_t GetActionFlags() const override + { + return GameAction::GetActionFlags(); + } + + void Serialise(DataSerialiser & stream) override + { + GameAction::Serialise(stream); + + stream << DS_TAG(_loc) << DS_TAG(_slope) << DS_TAG(_type) << DS_TAG(_direction); + } + + GameActionResult::Ptr Query() const override + { + GameActionResult::Ptr res = std::make_unique(); + res->Cost = 0; + res->ExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; + res->Position = _loc; + res->Position.x += 16; + res->Position.y += 16; + + gFootpathGroundFlags = 0; + + if (map_is_edge({ _loc.x, _loc.y })) + { + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_BUILD_FOOTPATH_HERE, STR_OFF_EDGE_OF_MAP); + } + + if (!((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) || gCheatsSandboxMode) + && !map_is_location_owned(_loc.x, _loc.y, _loc.z)) + { + return MakeResult(GA_ERROR::DISALLOWED, STR_CANT_BUILD_FOOTPATH_HERE, STR_LAND_NOT_OWNED_BY_PARK); + } + + if (_slope & SLOPE_IS_IRREGULAR_FLAG) + { + return MakeResult(GA_ERROR::DISALLOWED, STR_CANT_BUILD_FOOTPATH_HERE, STR_LAND_SLOPE_UNSUITABLE); + } + + if (_loc.z / 8 < 2) + { + return MakeResult(GA_ERROR::DISALLOWED, STR_CANT_BUILD_FOOTPATH_HERE, STR_TOO_LOW); + } + + if (_loc.z / 8 > 248) + { + return MakeResult(GA_ERROR::DISALLOWED, STR_CANT_BUILD_FOOTPATH_HERE, STR_TOO_HIGH); + } + + if (_direction != 0xFF && _direction > 15) + { + log_error("Direction invalid. direction = %u", _direction); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_BUILD_FOOTPATH_HERE); + } + + footpath_provisional_remove(); + auto tileElement = map_get_footpath_element_slope((_loc.x / 32), (_loc.y / 32), _loc.z / 8, _slope); + if (tileElement == nullptr) + { + return footpath_element_insert_query(std::move(res)); + } + else + { + return footpath_element_update_query(tileElement, std::move(res)); + } + } + + GameActionResult::Ptr Execute() const override + { + GameActionResult::Ptr res = std::make_unique(); + res->Cost = 0; + res->ExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; + res->Position = _loc; + res->Position.x += 16; + res->Position.y += 16; + + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST)) + { + footpath_interrupt_peeps(_loc.x, _loc.y, _loc.z); + } + + gFootpathGroundFlags = 0; + + // Force ride construction to recheck area + _currentTrackSelectionFlags |= TRACK_SELECTION_FLAG_RECHECK; + + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST)) + { + if (_direction != 0xFF && !gCheatsDisableClearanceChecks) + { + // It is possible, let's remove walls between the old and new piece of path + auto zLow = _loc.z / 8; + auto zHigh = zLow + 4; + wall_remove_intersecting_walls( + _loc.x, _loc.y, zLow, zHigh + ((_slope & TILE_ELEMENT_SURFACE_RAISED_CORNERS_MASK) ? 2 : 0), + direction_reverse(_direction)); + wall_remove_intersecting_walls( + _loc.x - CoordsDirectionDelta[_direction].x, _loc.y - CoordsDirectionDelta[_direction].y, zLow, zHigh, + _direction); + } + } + + auto tileElement = map_get_footpath_element_slope((_loc.x / 32), (_loc.y / 32), _loc.z / 8, _slope); + if (tileElement == nullptr) + { + return footpath_element_insert_execute(std::move(res)); + } + else + { + return footpath_element_update_execute(tileElement, std::move(res)); + } + } + +private: + GameActionResult::Ptr footpath_element_update_query(PathElement * pathElement, GameActionResult::Ptr res) const + { + const int32_t newFootpathType = (_type & (FOOTPATH_PROPERTIES_TYPE_MASK >> 4)); + const bool newPathIsQueue = ((_type >> 7) == 1); + if (pathElement->GetPathEntryIndex() != newFootpathType || pathElement->IsQueue() != newPathIsQueue) + { + res->Cost += MONEY(6, 00); + } + + if (GetFlags() & GAME_COMMAND_FLAG_4) + { + return MakeResult(GA_ERROR::UNKNOWN, STR_CANT_BUILD_FOOTPATH_HERE); + } + return res; + } + + GameActionResult::Ptr footpath_element_update_execute(PathElement * pathElement, GameActionResult::Ptr res) const + { + const int32_t newFootpathType = (_type & (FOOTPATH_PROPERTIES_TYPE_MASK >> 4)); + const bool newPathIsQueue = ((_type >> 7) == 1); + if (pathElement->GetPathEntryIndex() != newFootpathType || pathElement->IsQueue() != newPathIsQueue) + { + res->Cost += MONEY(6, 00); + } + + footpath_queue_chain_reset(); + + if (!(GetFlags() & GAME_COMMAND_FLAG_PATH_SCENERY)) + { + footpath_remove_edges_at(_loc.x, _loc.y, (TileElement*)pathElement); + } + + pathElement->SetPathEntryIndex(_type); + if (_type & (1 << 7)) + { + pathElement->SetIsQueue(true); + } + else + { + pathElement->SetIsQueue(false); + } + pathElement->SetAddition(0); + pathElement->SetIsBroken(false); + + loc_6A6620(pathElement); + return res; + } + + GameActionResult::Ptr footpath_element_insert_query(GameActionResult::Ptr res) const + { + bool entrancePath = false, entranceIsSamePath = false; + + if (!map_check_free_elements_and_reorganise(1)) + { + return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_CANT_BUILD_FOOTPATH_HERE); + } + + res->Cost = MONEY(12, 00); + + QuarterTile quarterTile{ 0b1111, 0 }; + auto zLow = _loc.z / 8; + auto zHigh = zLow + 4; + if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED) + { + quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope & TILE_ELEMENT_DIRECTION_MASK); + zHigh += 2; + } + + auto entranceElement = map_get_park_entrance_element_at(_loc.x, _loc.y, zLow, false); + // Make sure the entrance part is the middle + if (entranceElement != nullptr && (entranceElement->GetSequenceIndex()) == 0) + { + entrancePath = true; + // Make the price the same as replacing a path + if (entranceElement->GetPathType() == (_type & 0xF)) + entranceIsSamePath = true; + else + res->Cost -= MONEY(6, 00); + } + + // Do not attempt to build a crossing with a queue or a sloped. + uint8_t crossingMode = (_type & FOOTPATH_ELEMENT_INSERT_QUEUE) || (_slope != TILE_ELEMENT_SLOPE_FLAT) + ? CREATE_CROSSING_MODE_NONE + : CREATE_CROSSING_MODE_PATH_OVER_TRACK; + if (!entrancePath + && !map_can_construct_with_clear_at( + _loc.x, _loc.y, zLow, zHigh, &map_place_non_scenery_clear_func, quarterTile, GetFlags(), &res->Cost, + crossingMode)) + { + return MakeResult(GA_ERROR::NO_CLEARANCE, STR_CANT_BUILD_FOOTPATH_HERE, gGameCommandErrorText, gCommonFormatArgs); + } + + gFootpathGroundFlags = gMapGroundFlags; + if (!gCheatsDisableClearanceChecks && (gMapGroundFlags & ELEMENT_IS_UNDERWATER)) + { + return MakeResult(GA_ERROR::DISALLOWED, STR_CANT_BUILD_FOOTPATH_HERE, STR_CANT_BUILD_THIS_UNDERWATER); + } + + auto tileElement = map_get_surface_element_at({ _loc.x, _loc.y }); + if (tileElement == nullptr) + { + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_BUILD_FOOTPATH_HERE); + } + auto surfaceElement = tileElement->AsSurface(); + int32_t supportHeight = zLow - surfaceElement->base_height; + res->Cost += supportHeight < 0 ? MONEY(20, 00) : (supportHeight / 2) * MONEY(5, 00); + + // Prevent the place sound from being spammed + if (entranceIsSamePath) + res->Cost = 0; + + return res; + } + + GameActionResult::Ptr footpath_element_insert_execute(GameActionResult::Ptr res) const + { + bool entrancePath = false, entranceIsSamePath = false; + + if (!(GetFlags() & (GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_GHOST))) + { + footpath_remove_litter(_loc.x, _loc.y, _loc.z); + } + + res->Cost = MONEY(12, 00); + + QuarterTile quarterTile{ 0b1111, 0 }; + auto zLow = _loc.z / 8; + auto zHigh = zLow + 4; + if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED) + { + quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope & TILE_ELEMENT_DIRECTION_MASK); + zHigh += 2; + } + + auto entranceElement = map_get_park_entrance_element_at(_loc.x, _loc.y, zLow, false); + // Make sure the entrance part is the middle + if (entranceElement != nullptr && (entranceElement->GetSequenceIndex()) == 0) + { + entrancePath = true; + // Make the price the same as replacing a path + if (entranceElement->GetPathType() == (_type & 0xF)) + entranceIsSamePath = true; + else + res->Cost -= MONEY(6, 00); + } + + // Do not attempt to build a crossing with a queue or a sloped. + uint8_t crossingMode = (_type & FOOTPATH_ELEMENT_INSERT_QUEUE) || (_slope != TILE_ELEMENT_SLOPE_FLAT) + ? CREATE_CROSSING_MODE_NONE + : CREATE_CROSSING_MODE_PATH_OVER_TRACK; + if (!entrancePath + && !map_can_construct_with_clear_at( + _loc.x, _loc.y, zLow, zHigh, &map_place_non_scenery_clear_func, quarterTile, GetFlags(), &res->Cost, + crossingMode)) + { + return MakeResult(GA_ERROR::NO_CLEARANCE, STR_CANT_BUILD_FOOTPATH_HERE, gGameCommandErrorText, gCommonFormatArgs); + } + + gFootpathGroundFlags = gMapGroundFlags; + + auto tileElement = map_get_surface_element_at({ _loc.x, _loc.y }); + if (tileElement == nullptr) + { + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_BUILD_FOOTPATH_HERE); + } + auto surfaceElement = tileElement->AsSurface(); + int32_t supportHeight = zLow - surfaceElement->base_height; + res->Cost += supportHeight < 0 ? MONEY(20, 00) : (supportHeight / 2) * MONEY(5, 00); + + if (entrancePath) + { + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && !entranceIsSamePath) + { + // Set the path type but make sure it's not a queue as that will not show up + entranceElement->SetPathType(_type & 0x7F); + map_invalidate_tile_full(_loc.x, _loc.y); + } + } + else + { + tileElement = tile_element_insert(_loc.x / 32, _loc.y / 32, zLow, 0b1111); + assert(tileElement != nullptr); + tileElement->SetType(TILE_ELEMENT_TYPE_PATH); + PathElement* pathElement = tileElement->AsPath(); + pathElement->clearance_height = zHigh; + pathElement->SetPathEntryIndex(_type); + pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK); + if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED) + { + pathElement->SetSloped(true); + } + if (_type & FOOTPATH_ELEMENT_INSERT_QUEUE) + { + pathElement->SetIsQueue(true); + } + pathElement->SetAddition(0); + pathElement->SetRideIndex(RIDE_ID_NULL); + pathElement->SetAdditionStatus(255); + pathElement->SetIsBroken(false); + if (GetFlags() & GAME_COMMAND_FLAG_GHOST) + { + pathElement->SetGhost(true); + } + footpath_queue_chain_reset(); + + if (!(GetFlags() & GAME_COMMAND_FLAG_PATH_SCENERY)) + { + footpath_remove_edges_at(_loc.x, _loc.y, tileElement); + } + if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !(GetFlags() & GAME_COMMAND_FLAG_GHOST)) + { + automatically_set_peep_spawn(); + } + + loc_6A6620(pathElement); + } + + // Prevent the place sound from being spammed + if (entranceIsSamePath) + res->Cost = 0; + + return res; + } + /** + * + * rct2: 0x006A65AD + */ + void automatically_set_peep_spawn() const + { + uint8_t direction = 0; + if (_loc.x != 32) + { + direction++; + if (_loc.y != gMapSizeUnits - 32) + { + direction++; + if (_loc.x != gMapSizeUnits - 32) + { + direction++; + if (_loc.y != 32) + return; + } + } + } + + if (gPeepSpawns.size() == 0) + { + gPeepSpawns.emplace_back(); + } + PeepSpawn* peepSpawn = &gPeepSpawns[0]; + peepSpawn->x = _loc.x + (word_981D6C[direction].x * 15) + 16; + peepSpawn->y = _loc.y + (word_981D6C[direction].y * 15) + 16; + peepSpawn->direction = direction; + peepSpawn->z = _loc.z; + } + + void loc_6A6620(PathElement * pathElement) const + { + if (pathElement->IsSloped() && !(GetFlags() & GAME_COMMAND_FLAG_GHOST)) + { + int32_t direction = pathElement->GetSlopeDirection(); + int32_t z = pathElement->base_height; + wall_remove_intersecting_walls(_loc.x, _loc.y, z, z + 6, direction_reverse(direction)); + wall_remove_intersecting_walls(_loc.x, _loc.y, z, z + 6, direction); + // Removing walls may have made the pointer invalid, so find it again + auto tileElement = map_get_footpath_element(_loc.x / 32, _loc.y / 32, z); + if (tileElement == nullptr) + { + log_error("Something went wrong. Could not refind footpath."); + return; + } + pathElement = tileElement->AsPath(); + } + + if (!(GetFlags() & GAME_COMMAND_FLAG_PATH_SCENERY)) + footpath_connect_edges(_loc.x, _loc.y, (TileElement*)pathElement, GetFlags()); + + footpath_update_queue_chains(); + map_invalidate_tile_full(_loc.x, _loc.y); + } +}; diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index 24ffea581e..c24a8e0a7f 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -10,6 +10,7 @@ #include "BannerSetNameAction.hpp" #include "ClearAction.hpp" #include "ClimateSetAction.hpp" +#include "FootpathPlaceAction.hpp" #include "FootpathRemoveAction.hpp" #include "FootpathSceneryPlaceAction.hpp" #include "FootpathSceneryRemoveAction.hpp" @@ -57,6 +58,7 @@ namespace GameActions { Register(); Register(); + Register(); Register(); Register(); Register(); diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index 31d155d839..83aad6085f 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -156,7 +156,7 @@ TileElement* map_get_footpath_element(int32_t x, int32_t y, int32_t z) return nullptr; } -static TileElement* map_get_footpath_element_slope(int32_t x, int32_t y, int32_t z, int32_t slope) +PathElement* map_get_footpath_element_slope(int32_t x, int32_t y, int32_t z, int32_t slope) { TileElement* tileElement; bool isSloped = slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED; @@ -168,7 +168,7 @@ static TileElement* map_get_footpath_element_slope(int32_t x, int32_t y, int32_t && (tileElement->AsPath()->IsSloped() == isSloped) && (tileElement->AsPath()->GetSlopeDirection() == (slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK))) { - return tileElement; + return tileElement->AsPath(); } } while (!(tileElement++)->IsLastForTile()); @@ -424,7 +424,7 @@ static money32 footpath_place_real( } footpath_provisional_remove(); - tileElement = map_get_footpath_element_slope((x / 32), (y / 32), z, slope); + tileElement = (TileElement*)map_get_footpath_element_slope((x / 32), (y / 32), z, slope); if (tileElement == nullptr) { return footpath_element_insert(type, x, y, z, slope, flags, pathItemType); diff --git a/src/openrct2/world/Footpath.h b/src/openrct2/world/Footpath.h index 9e209bc25d..3a68d408aa 100644 --- a/src/openrct2/world/Footpath.h +++ b/src/openrct2/world/Footpath.h @@ -170,6 +170,8 @@ extern const LocationXY16 BinUseOffsets[4]; extern const LocationXY16 BenchUseOffsets[8]; TileElement* map_get_footpath_element(int32_t x, int32_t y, int32_t z); +struct PathElement; +PathElement* map_get_footpath_element_slope(int32_t x, int32_t y, int32_t z, int32_t slope); void footpath_interrupt_peeps(int32_t x, int32_t y, int32_t z); void game_command_place_footpath( int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp); From bcced4016f02d236a5c9f46b5a54eb4d86378121 Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Fri, 1 Mar 2019 17:17:46 +0000 Subject: [PATCH 4/9] Use new action --- src/openrct2-ui/windows/Footpath.cpp | 77 +++++++++++--------- src/openrct2/actions/FootpathPlaceAction.hpp | 30 ++++---- src/openrct2/world/Footpath.cpp | 13 ++-- 3 files changed, 63 insertions(+), 57 deletions(-) diff --git a/src/openrct2-ui/windows/Footpath.cpp b/src/openrct2-ui/windows/Footpath.cpp index 2bb43bcd9d..3a01b4cf8b 100644 --- a/src/openrct2-ui/windows/Footpath.cpp +++ b/src/openrct2-ui/windows/Footpath.cpp @@ -11,11 +11,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include @@ -899,7 +899,11 @@ static void window_footpath_place_path_at_point(int32_t x, int32_t y) footpathPlaceAction.SetCallback([](const GameAction* ga, const GameActionResult* result) { if (result->Error == GA_ERROR::OK) { - audio_play_sound_at_location(SOUND_PLACE_ITEM, result->Position.x, result->Position.y, result->Position.z); + // Don't play sound if it is no cost to prevent multiple sounds. TODO: make this work in no money scenarios + if (result->Cost != 0) + { + audio_play_sound_at_location(SOUND_PLACE_ITEM, result->Position.x, result->Position.y, result->Position.z); + } } else { @@ -982,43 +986,44 @@ static void window_footpath_construct() footpath_get_next_path_info(&type, &x, &y, &z, &slope); gGameCommandErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE; - money32 cost = footpath_place_remove_intersecting( - type, x, y, z, slope, GAME_COMMAND_FLAG_APPLY, gFootpathConstructDirection); - - if (cost != MONEY32_UNDEFINED) - { - audio_play_sound_at_location( - SOUND_PLACE_ITEM, gFootpathConstructFromPosition.x, gFootpathConstructFromPosition.y, - gFootpathConstructFromPosition.z); - - if (gFootpathConstructSlope == 0) + auto footpathPlaceAction = FootpathPlaceAction({ x, y, z * 8 }, slope, type, gFootpathConstructDirection); + footpathPlaceAction.SetCallback([=](const GameAction* ga, const GameActionResult* result) { + if (result->Error == GA_ERROR::OK) { - gFootpathConstructValidDirections = 0xFF; - } - else - { - gFootpathConstructValidDirections = gFootpathConstructDirection; - } + audio_play_sound_at_location(SOUND_PLACE_ITEM, result->Position.x, result->Position.y, result->Position.z); - if (gFootpathGroundFlags & ELEMENT_IS_UNDERGROUND) - { - viewport_set_visibility(1); + if (gFootpathConstructSlope == 0) + { + gFootpathConstructValidDirections = 0xFF; + } + else + { + gFootpathConstructValidDirections = gFootpathConstructDirection; + } + + if (gFootpathGroundFlags & ELEMENT_IS_UNDERGROUND) + { + viewport_set_visibility(1); + } + + // If we have just built an upwards slope, the next path to construct is + // a bit higher. Note that the z returned by footpath_get_next_path_info + // already is lowered if we are building a downwards slope. + if (gFootpathConstructSlope == 2) + { + gFootpathConstructFromPosition.z = (z + 2) * 8; + } + else + { + gFootpathConstructFromPosition.z = z * 8; + } + + gFootpathConstructFromPosition.x = x; + gFootpathConstructFromPosition.y = y; } - - // If we have just built an upwards slope, the next path to construct is - // a bit higher. Note that the z returned by footpath_get_next_path_info - // already is lowered if we are building a downwards slope. - if (gFootpathConstructSlope == 2) - { - z += 2; - } - - gFootpathConstructFromPosition.x = x; - gFootpathConstructFromPosition.y = y; - gFootpathConstructFromPosition.z = z << 3; - } - - window_footpath_set_enabled_and_pressed_widgets(); + window_footpath_set_enabled_and_pressed_widgets(); + }); + GameActions::Execute(&footpathPlaceAction); } /** diff --git a/src/openrct2/actions/FootpathPlaceAction.hpp b/src/openrct2/actions/FootpathPlaceAction.hpp index deaab17a53..c0aa6730cb 100644 --- a/src/openrct2/actions/FootpathPlaceAction.hpp +++ b/src/openrct2/actions/FootpathPlaceAction.hpp @@ -99,11 +99,11 @@ public: auto tileElement = map_get_footpath_element_slope((_loc.x / 32), (_loc.y / 32), _loc.z / 8, _slope); if (tileElement == nullptr) { - return footpath_element_insert_query(std::move(res)); + return ElementInsertQuery(std::move(res)); } else { - return footpath_element_update_query(tileElement, std::move(res)); + return ElementUpdateQuery(tileElement, std::move(res)); } } @@ -145,16 +145,16 @@ public: auto tileElement = map_get_footpath_element_slope((_loc.x / 32), (_loc.y / 32), _loc.z / 8, _slope); if (tileElement == nullptr) { - return footpath_element_insert_execute(std::move(res)); + return ElementInsertExecute(std::move(res)); } else { - return footpath_element_update_execute(tileElement, std::move(res)); + return ElementUpdateExecute(tileElement, std::move(res)); } } private: - GameActionResult::Ptr footpath_element_update_query(PathElement * pathElement, GameActionResult::Ptr res) const + GameActionResult::Ptr ElementUpdateQuery(PathElement * pathElement, GameActionResult::Ptr res) const { const int32_t newFootpathType = (_type & (FOOTPATH_PROPERTIES_TYPE_MASK >> 4)); const bool newPathIsQueue = ((_type >> 7) == 1); @@ -163,14 +163,14 @@ private: res->Cost += MONEY(6, 00); } - if (GetFlags() & GAME_COMMAND_FLAG_4) + if (GetFlags() & GAME_COMMAND_FLAG_GHOST && !pathElement->IsGhost()) { return MakeResult(GA_ERROR::UNKNOWN, STR_CANT_BUILD_FOOTPATH_HERE); } return res; } - GameActionResult::Ptr footpath_element_update_execute(PathElement * pathElement, GameActionResult::Ptr res) const + GameActionResult::Ptr ElementUpdateExecute(PathElement * pathElement, GameActionResult::Ptr res) const { const int32_t newFootpathType = (_type & (FOOTPATH_PROPERTIES_TYPE_MASK >> 4)); const bool newPathIsQueue = ((_type >> 7) == 1); @@ -198,11 +198,11 @@ private: pathElement->SetAddition(0); pathElement->SetIsBroken(false); - loc_6A6620(pathElement); + RemoveIntersectingWalls(pathElement); return res; } - GameActionResult::Ptr footpath_element_insert_query(GameActionResult::Ptr res) const + GameActionResult::Ptr ElementInsertQuery(GameActionResult::Ptr res) const { bool entrancePath = false, entranceIsSamePath = false; @@ -268,7 +268,7 @@ private: return res; } - GameActionResult::Ptr footpath_element_insert_execute(GameActionResult::Ptr res) const + GameActionResult::Ptr ElementInsertExecute(GameActionResult::Ptr res) const { bool entrancePath = false, entranceIsSamePath = false; @@ -306,7 +306,7 @@ private: : CREATE_CROSSING_MODE_PATH_OVER_TRACK; if (!entrancePath && !map_can_construct_with_clear_at( - _loc.x, _loc.y, zLow, zHigh, &map_place_non_scenery_clear_func, quarterTile, GetFlags(), &res->Cost, + _loc.x, _loc.y, zLow, zHigh, &map_place_non_scenery_clear_func, quarterTile, GAME_COMMAND_FLAG_APPLY | GetFlags(), &res->Cost, crossingMode)) { return MakeResult(GA_ERROR::NO_CLEARANCE, STR_CANT_BUILD_FOOTPATH_HERE, gGameCommandErrorText, gCommonFormatArgs); @@ -365,10 +365,10 @@ private: } if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !(GetFlags() & GAME_COMMAND_FLAG_GHOST)) { - automatically_set_peep_spawn(); + AutomaticallySetPeepSpawn(); } - loc_6A6620(pathElement); + RemoveIntersectingWalls(pathElement); } // Prevent the place sound from being spammed @@ -381,7 +381,7 @@ private: * * rct2: 0x006A65AD */ - void automatically_set_peep_spawn() const + void AutomaticallySetPeepSpawn() const { uint8_t direction = 0; if (_loc.x != 32) @@ -410,7 +410,7 @@ private: peepSpawn->z = _loc.z; } - void loc_6A6620(PathElement * pathElement) const + void RemoveIntersectingWalls(PathElement * pathElement) const { if (pathElement->IsSloped() && !(GetFlags() & GAME_COMMAND_FLAG_GHOST)) { diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index 83aad6085f..0b1fe5b44a 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -11,6 +11,7 @@ #include "../Context.h" #include "../Game.h" #include "../OpenRCT2.h" +#include "../actions/FootpathPlaceAction.hpp" #include "../actions/FootpathRemoveAction.hpp" #include "../core/Guard.hpp" #include "../localisation/Localisation.h" @@ -667,11 +668,11 @@ money32 footpath_provisional_set(int32_t type, int32_t x, int32_t y, int32_t z, footpath_provisional_remove(); - cost = footpath_place( - type, x, y, z, slope, - GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_4 | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED - | GAME_COMMAND_FLAG_APPLY); - if (cost != MONEY32_UNDEFINED) + auto footpathPlaceAction = FootpathPlaceAction({ x, y, z * 8 }, slope, type); + footpathPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED); + auto res = GameActions::Execute(&footpathPlaceAction); + cost = res->Error == GA_ERROR::OK ? res->Cost : MONEY32_UNDEFINED; + if (res->Error == GA_ERROR::OK) { gFootpathProvisionalType = type; gFootpathProvisionalPosition.x = x; @@ -695,7 +696,7 @@ money32 footpath_provisional_set(int32_t type, int32_t x, int32_t y, int32_t z, if (!scenery_tool_is_active()) { - if (cost == MONEY32_UNDEFINED) + if (res->Error != GA_ERROR::OK) { // If we can't build this, don't show a virtual floor. virtual_floor_set_height(0); From 29de97f5b1a0b3670ec1412092a9309b9e991c22 Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Fri, 1 Mar 2019 17:27:04 +0000 Subject: [PATCH 5/9] Remove references to old game command --- src/openrct2/Game.cpp | 2 +- src/openrct2/Game.h | 2 +- src/openrct2/actions/FootpathPlaceAction.hpp | 26 +- src/openrct2/world/Footpath.cpp | 331 ------------------- src/openrct2/world/Footpath.h | 5 - 5 files changed, 24 insertions(+), 342 deletions(-) diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index cd9885e30a..7a46e8b733 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -1277,7 +1277,7 @@ GAME_COMMAND_POINTER* new_game_command_table[GAME_COMMAND_COUNT] = { nullptr, nullptr, nullptr, - game_command_place_footpath, + nullptr, game_command_place_footpath_from_track, nullptr, game_command_change_surface_style, diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index 4ad216a95c..5e888e817d 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -35,7 +35,7 @@ enum GAME_COMMAND GAME_COMMAND_REMOVE_SCENERY, // GA GAME_COMMAND_PLACE_SCENERY, // GA GAME_COMMAND_SET_WATER_HEIGHT, // GA - GAME_COMMAND_PLACE_PATH, + GAME_COMMAND_PLACE_PATH, // GA GAME_COMMAND_PLACE_PATH_FROM_TRACK, GAME_COMMAND_REMOVE_PATH, GAME_COMMAND_CHANGE_SURFACE_STYLE, diff --git a/src/openrct2/actions/FootpathPlaceAction.hpp b/src/openrct2/actions/FootpathPlaceAction.hpp index c0aa6730cb..a7da888ecf 100644 --- a/src/openrct2/actions/FootpathPlaceAction.hpp +++ b/src/openrct2/actions/FootpathPlaceAction.hpp @@ -240,8 +240,8 @@ private: : CREATE_CROSSING_MODE_PATH_OVER_TRACK; if (!entrancePath && !map_can_construct_with_clear_at( - _loc.x, _loc.y, zLow, zHigh, &map_place_non_scenery_clear_func, quarterTile, GetFlags(), &res->Cost, - crossingMode)) + _loc.x, _loc.y, zLow, zHigh, &map_place_non_scenery_clear_func, quarterTile, GetFlags(), &res->Cost, + crossingMode)) { return MakeResult(GA_ERROR::NO_CLEARANCE, STR_CANT_BUILD_FOOTPATH_HERE, gGameCommandErrorText, gCommonFormatArgs); } @@ -306,8 +306,8 @@ private: : CREATE_CROSSING_MODE_PATH_OVER_TRACK; if (!entrancePath && !map_can_construct_with_clear_at( - _loc.x, _loc.y, zLow, zHigh, &map_place_non_scenery_clear_func, quarterTile, GAME_COMMAND_FLAG_APPLY | GetFlags(), &res->Cost, - crossingMode)) + _loc.x, _loc.y, zLow, zHigh, &map_place_non_scenery_clear_func, quarterTile, + GAME_COMMAND_FLAG_APPLY | GetFlags(), &res->Cost, crossingMode)) { return MakeResult(GA_ERROR::NO_CLEARANCE, STR_CANT_BUILD_FOOTPATH_HERE, gGameCommandErrorText, gCommonFormatArgs); } @@ -434,4 +434,22 @@ private: footpath_update_queue_chains(); map_invalidate_tile_full(_loc.x, _loc.y); } + + PathElement* map_get_footpath_element_slope(int32_t x, int32_t y, int32_t z, int32_t slope) const + { + TileElement* tileElement; + bool isSloped = slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED; + + tileElement = map_get_first_element_at(x, y); + do + { + if (tileElement->GetType() == TILE_ELEMENT_TYPE_PATH && tileElement->base_height == z + && (tileElement->AsPath()->IsSloped() == isSloped) + && (tileElement->AsPath()->GetSlopeDirection() == (slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK))) + { + return tileElement->AsPath(); + } + } while (!(tileElement++)->IsLastForTile()); + return nullptr; + } }; diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index 0b1fe5b44a..7222e6bf9e 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -110,39 +110,6 @@ static bool entrance_has_direction(TileElement* tileElement, int32_t direction) return entrance_get_directions(tileElement) & (1 << (direction & 3)); } -/** - * - * rct2: 0x006A65AD - */ -static void automatically_set_peep_spawn(CoordsXYZ location) -{ - uint8_t direction = 0; - if (location.x != 32) - { - direction++; - if (location.y != gMapSizeUnits - 32) - { - direction++; - if (location.x != gMapSizeUnits - 32) - { - direction++; - if (location.y != 32) - return; - } - } - } - - if (gPeepSpawns.size() == 0) - { - gPeepSpawns.emplace_back(); - } - PeepSpawn* peepSpawn = &gPeepSpawns[0]; - peepSpawn->x = location.x + (word_981D6C[direction].x * 15) + 16; - peepSpawn->y = location.y + (word_981D6C[direction].y * 15) + 16; - peepSpawn->direction = direction; - peepSpawn->z = location.z; -} - TileElement* map_get_footpath_element(int32_t x, int32_t y, int32_t z) { TileElement* tileElement; @@ -157,285 +124,11 @@ TileElement* map_get_footpath_element(int32_t x, int32_t y, int32_t z) return nullptr; } -PathElement* map_get_footpath_element_slope(int32_t x, int32_t y, int32_t z, int32_t slope) -{ - TileElement* tileElement; - bool isSloped = slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED; - - tileElement = map_get_first_element_at(x, y); - do - { - if (tileElement->GetType() == TILE_ELEMENT_TYPE_PATH && tileElement->base_height == z - && (tileElement->AsPath()->IsSloped() == isSloped) - && (tileElement->AsPath()->GetSlopeDirection() == (slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK))) - { - return tileElement->AsPath(); - } - } while (!(tileElement++)->IsLastForTile()); - - return nullptr; -} - -static void loc_6A6620(int32_t flags, int32_t x, int32_t y, TileElement* tileElement) -{ - if (tileElement->AsPath()->IsSloped() && !(flags & GAME_COMMAND_FLAG_GHOST)) - { - int32_t direction = tileElement->AsPath()->GetSlopeDirection(); - int32_t z = tileElement->base_height; - wall_remove_intersecting_walls(x, y, z, z + 6, direction_reverse(direction)); - wall_remove_intersecting_walls(x, y, z, z + 6, direction); - // Removing walls may have made the pointer invalid, so find it again - tileElement = map_get_footpath_element(x / 32, y / 32, z); - } - - if (!(flags & GAME_COMMAND_FLAG_PATH_SCENERY)) - footpath_connect_edges(x, y, tileElement, flags); - - footpath_update_queue_chains(); - map_invalidate_tile_full(x, y); -} - /** rct2: 0x0098D7EC */ static constexpr const QuarterTile SlopedFootpathQuarterTiles[] = { { 0b1111, 0b1100 }, { 0b1111, 0b1001 }, { 0b1111, 0b0011 }, { 0b1111, 0b0110 } }; -static money32 footpath_element_insert( - int32_t type, int32_t x, int32_t y, int32_t z, int32_t slope, int32_t flags, uint8_t pathItemType) -{ - TileElement* tileElement; - EntranceElement* entranceElement; - int32_t zHigh; - bool entrancePath = false, entranceIsSamePath = false; - - if (!map_check_free_elements_and_reorganise(1)) - return MONEY32_UNDEFINED; - - if ((flags & GAME_COMMAND_FLAG_APPLY) && !(flags & (GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_GHOST))) - footpath_remove_litter(x, y, gCommandPosition.z); - - // loc_6A649D: - gFootpathPrice += MONEY(12, 00); - - QuarterTile quarterTile{ 0b1111, 0 }; - zHigh = z + 4; - if (slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED) - { - quarterTile = SlopedFootpathQuarterTiles[slope & TILE_ELEMENT_DIRECTION_MASK]; - zHigh += 2; - } - - entranceElement = map_get_park_entrance_element_at(x, y, z, false); - // Make sure the entrance part is the middle - if (entranceElement != nullptr && (entranceElement->GetSequenceIndex()) == 0) - { - entrancePath = true; - // Make the price the same as replacing a path - if (entranceElement->GetPathType() == (type & 0xF)) - entranceIsSamePath = true; - else - gFootpathPrice -= MONEY(6, 00); - } - - // Do not attempt to build a crossing with a queue or a sloped. - uint8_t crossingMode = (type & FOOTPATH_ELEMENT_INSERT_QUEUE) || (slope != TILE_ELEMENT_SLOPE_FLAT) - ? CREATE_CROSSING_MODE_NONE - : CREATE_CROSSING_MODE_PATH_OVER_TRACK; - if (!entrancePath - && !map_can_construct_with_clear_at( - x, y, z, zHigh, &map_place_non_scenery_clear_func, quarterTile, flags, &gFootpathPrice, crossingMode)) - return MONEY32_UNDEFINED; - - gFootpathGroundFlags = gMapGroundFlags; - if (!gCheatsDisableClearanceChecks && (gMapGroundFlags & ELEMENT_IS_UNDERWATER)) - { - gGameCommandErrorText = STR_CANT_BUILD_THIS_UNDERWATER; - return MONEY32_UNDEFINED; - } - - tileElement = map_get_surface_element_at({ x, y }); - - if (tileElement == nullptr) - { - return MONEY32_UNDEFINED; - } - - int32_t supportHeight = z - tileElement->base_height; - gFootpathPrice += supportHeight < 0 ? MONEY(20, 00) : (supportHeight / 2) * MONEY(5, 00); - - if (flags & GAME_COMMAND_FLAG_APPLY) - { - if (entrancePath) - { - if (!(flags & GAME_COMMAND_FLAG_GHOST) && !entranceIsSamePath) - { - // Set the path type but make sure it's not a queue as that will not show up - entranceElement->SetPathType(type & 0x7F); - map_invalidate_tile_full(x, y); - } - } - else - { - tileElement = tile_element_insert(x / 32, y / 32, z, 0x0F); - assert(tileElement != nullptr); - tileElement->SetType(TILE_ELEMENT_TYPE_PATH); - PathElement* pathElement = tileElement->AsPath(); - pathElement->clearance_height = z + 4 + ((slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK) ? 2 : 0); - pathElement->SetPathEntryIndex(type); - pathElement->SetSlopeDirection(slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK); - if (slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED) - pathElement->SetSloped(true); - if (type & FOOTPATH_ELEMENT_INSERT_QUEUE) - pathElement->SetIsQueue(true); - pathElement->SetAddition(pathItemType); - pathElement->SetRideIndex(RIDE_ID_NULL); - pathElement->SetAdditionStatus(255); - pathElement->SetIsBroken(false); - if (flags & GAME_COMMAND_FLAG_GHOST) - pathElement->SetGhost(true); - - footpath_queue_chain_reset(); - - if (!(flags & GAME_COMMAND_FLAG_PATH_SCENERY)) - footpath_remove_edges_at(x, y, tileElement); - - if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !(flags & GAME_COMMAND_FLAG_GHOST)) - automatically_set_peep_spawn({ x, y, tileElement->base_height * 8 }); - - loc_6A6620(flags, x, y, tileElement); - } - } - - // Prevent the place sound from being spammed - if (entranceIsSamePath) - gFootpathPrice = 0; - - return gParkFlags & PARK_FLAGS_NO_MONEY ? 0 : gFootpathPrice; -} - -static money32 footpath_element_update( - int32_t x, int32_t y, TileElement* tileElement, int32_t type, int32_t flags, uint8_t pathItemType) -{ - const int32_t newFootpathType = (type & (FOOTPATH_PROPERTIES_TYPE_MASK >> 4)); - const bool newPathIsQueue = ((type >> 7) == 1); - - if (tileElement->AsPath()->GetPathEntryIndex() != newFootpathType || tileElement->AsPath()->IsQueue() != newPathIsQueue) - { - gFootpathPrice += MONEY(6, 00); - } - else if (pathItemType != 0) - { - Guard::Assert(false, "No longer in use. Use FootpathScenery{Place/Remove}Action."); - } - - if (flags & GAME_COMMAND_FLAG_4) - return MONEY32_UNDEFINED; - - if (flags & GAME_COMMAND_FLAG_APPLY) - { - footpath_queue_chain_reset(); - - if (!(flags & GAME_COMMAND_FLAG_PATH_SCENERY)) - footpath_remove_edges_at(x, y, tileElement); - - tileElement->AsPath()->SetPathEntryIndex(type); - if (type & (1 << 7)) - tileElement->AsPath()->SetIsQueue(true); - else - tileElement->AsPath()->SetIsQueue(false); - tileElement->AsPath()->SetAddition(pathItemType); - tileElement->AsPath()->SetIsBroken(false); - - loc_6A6620(flags, x, y, tileElement); - } - - return gParkFlags & PARK_FLAGS_NO_MONEY ? 0 : gFootpathPrice; -} - -static money32 footpath_place_real( - int32_t type, int32_t x, int32_t y, int32_t z, int32_t slope, int32_t flags, uint8_t pathItemType, bool clearDirection, - int32_t direction) -{ - TileElement* tileElement; - - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; - gCommandPosition.x = x + 16; - gCommandPosition.y = y + 16; - gCommandPosition.z = z * 8; - - if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && game_is_paused() && !gCheatsBuildInPauseMode) - { - gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; - return MONEY32_UNDEFINED; - } - - if ((flags & GAME_COMMAND_FLAG_APPLY) && !(flags & GAME_COMMAND_FLAG_GHOST)) - footpath_interrupt_peeps(x, y, z * 8); - - gFootpathPrice = 0; - gFootpathGroundFlags = 0; - - if (map_is_edge({ x, y })) - { - gGameCommandErrorText = STR_OFF_EDGE_OF_MAP; - return MONEY32_UNDEFINED; - } - - if (!((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) || gCheatsSandboxMode) && !map_is_location_owned(x, y, z * 8)) - return MONEY32_UNDEFINED; - - if (slope & SLOPE_IS_IRREGULAR_FLAG) - { - gGameCommandErrorText = STR_LAND_SLOPE_UNSUITABLE; - return MONEY32_UNDEFINED; - } - - if (z < 2) - { - gGameCommandErrorText = STR_TOO_LOW; - return MONEY32_UNDEFINED; - } - - if (z > 248) - { - gGameCommandErrorText = STR_TOO_HIGH; - return MONEY32_UNDEFINED; - } - - // Force ride construction to recheck area - _currentTrackSelectionFlags |= TRACK_SELECTION_FLAG_RECHECK; - - if (gGameCommandNestLevel == 1 && !(flags & GAME_COMMAND_FLAG_GHOST)) - { - 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); - - if (clearDirection && !gCheatsDisableClearanceChecks) - { - direction = direction & 0xF; - // It is possible, let's remove walls between the old and new piece of path - wall_remove_intersecting_walls( - x, y, z, z + 4 + ((slope & TILE_ELEMENT_SURFACE_RAISED_CORNERS_MASK) ? 2 : 0), direction_reverse(direction)); - wall_remove_intersecting_walls( - x - CoordsDirectionDelta[direction].x, y - CoordsDirectionDelta[direction].y, z, z + 4, direction); - } - } - - footpath_provisional_remove(); - tileElement = (TileElement*)map_get_footpath_element_slope((x / 32), (y / 32), z, slope); - if (tileElement == nullptr) - { - return footpath_element_insert(type, x, y, z, slope, flags, pathItemType); - } - else - { - return footpath_element_update(x, y, tileElement, type, flags, pathItemType); - } -} - /** * * rct2: 0x006BA23E @@ -455,18 +148,6 @@ void remove_banners_at_element(int32_t x, int32_t y, TileElement* tileElement) } } -/** - * - * rct2: 0x006A61DE - */ -void game_command_place_footpath( - int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, [[maybe_unused]] int32_t* esi, int32_t* edi, int32_t* ebp) -{ - *ebx = footpath_place_real( - (*edx >> 8) & 0xFF, *eax & 0xFFFF, *ecx & 0xFFFF, *edx & 0xFF, (*ebx >> 8) & 0xFF, *ebx & 0xFF, *edi & 0xFF, - (*ebp & FOOTPATH_CLEAR_DIRECTIONAL) >> 8, *ebp & 0xFF); -} - static money32 footpath_place_from_track( int32_t type, int32_t x, int32_t y, int32_t z, int32_t slope, int32_t edges, int32_t flags) { @@ -632,18 +313,6 @@ void game_command_place_footpath_from_track( (*ebx >> 8) & 0xF, *ebx & 0xFF); } -money32 footpath_place(int32_t type, int32_t x, int32_t y, int32_t z, int32_t slope, int32_t flags) -{ - return game_do_command(x, (slope << 8) | flags, y, (type << 8) | z, GAME_COMMAND_PLACE_PATH, 0, 0); -} - -money32 footpath_place_remove_intersecting( - int32_t type, int32_t x, int32_t y, int32_t z, int32_t slope, int32_t flags, int32_t direction) -{ - return game_do_command( - x, (slope << 8) | flags, y, (type << 8) | z, GAME_COMMAND_PLACE_PATH, 0, FOOTPATH_CLEAR_DIRECTIONAL | direction); -} - money32 footpath_remove(int32_t x, int32_t y, int32_t z, int32_t flags) { auto action = FootpathRemoveAction(x, y, z); diff --git a/src/openrct2/world/Footpath.h b/src/openrct2/world/Footpath.h index 3a68d408aa..8364a44f72 100644 --- a/src/openrct2/world/Footpath.h +++ b/src/openrct2/world/Footpath.h @@ -173,15 +173,10 @@ TileElement* map_get_footpath_element(int32_t x, int32_t y, int32_t z); struct PathElement; PathElement* map_get_footpath_element_slope(int32_t x, int32_t y, int32_t z, int32_t slope); void footpath_interrupt_peeps(int32_t x, int32_t y, int32_t z); -void game_command_place_footpath( - 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_footpath_from_track( 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_footpath( int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp); -money32 footpath_place(int32_t type, int32_t x, int32_t y, int32_t z, int32_t slope, int32_t flags); -money32 footpath_place_remove_intersecting( - int32_t type, int32_t x, int32_t y, int32_t z, int32_t slope, int32_t flags, int32_t direction); money32 footpath_remove(int32_t x, int32_t y, int32_t z, int32_t flags); money32 footpath_provisional_set(int32_t type, int32_t x, int32_t y, int32_t z, int32_t slope); void footpath_provisional_remove(); From 540be7c7be0e08ca06ba1d9908b23a6e5b4c6b77 Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Sat, 2 Mar 2019 07:44:15 +0000 Subject: [PATCH 6/9] Provide a conversion from old game command. Note doesn't handle footpath scenery or clear direction mode --- src/openrct2-ui/interface/ViewportInteraction.cpp | 4 ++-- src/openrct2/ReplayManager.cpp | 11 +++++++++++ src/openrct2/actions/FootpathPlaceAction.hpp | 8 ++++---- src/openrct2/actions/FootpathSceneryPlaceAction.hpp | 4 ++-- src/openrct2/actions/FootpathSceneryRemoveAction.hpp | 2 +- src/openrct2/core/DataSerialiserTraits.h | 3 +-- src/openrct2/world/Scenery.cpp | 4 ++-- 7 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/openrct2-ui/interface/ViewportInteraction.cpp b/src/openrct2-ui/interface/ViewportInteraction.cpp index 57fb23e329..0b9b40fb20 100644 --- a/src/openrct2-ui/interface/ViewportInteraction.cpp +++ b/src/openrct2-ui/interface/ViewportInteraction.cpp @@ -16,10 +16,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -508,7 +508,7 @@ static void viewport_interaction_remove_footpath(TileElement* tileElement, int32 */ static void viewport_interaction_remove_footpath_item(TileElement* tileElement, int32_t x, int32_t y) { - auto footpathSceneryRemoveAction = FootpathSceneryRemoveAction({x, y, tileElement->base_height * 8}); + auto footpathSceneryRemoveAction = FootpathSceneryRemoveAction({ x, y, tileElement->base_height * 8 }); GameActions::Execute(&footpathSceneryRemoveAction); } diff --git a/src/openrct2/ReplayManager.cpp b/src/openrct2/ReplayManager.cpp index a15298b2e6..0b9c2312ed 100644 --- a/src/openrct2/ReplayManager.cpp +++ b/src/openrct2/ReplayManager.cpp @@ -14,6 +14,7 @@ #include "OpenRCT2.h" #include "ParkImporter.h" #include "PlatformEnvironment.h" +#include "actions/FootpathPlaceAction.hpp" #include "actions/GameAction.h" #include "actions/RideEntranceExitPlaceAction.hpp" #include "actions/RideSetSetting.hpp" @@ -515,6 +516,16 @@ namespace OpenRCT2 result.action->SetFlags(command.ebx & 0xFF); break; } + case GAME_COMMAND_PLACE_PATH: + { + CoordsXYZ loc = { (int32_t)(command.eax & 0xFFFF), (int32_t)(command.ecx & 0xFFFF), + (int32_t)(command.edx & 0xFF) * 8 }; + uint8_t slope = (command.ebx >> 8) & 0xFF; + uint8_t type = (command.edx >> 8) & 0xFF; + result.action = std::make_unique(loc, slope, type); + result.action->SetFlags(command.ebx & 0xFF); + break; + } default: throw std::runtime_error("Deprecated game command requires replay translation."); } diff --git a/src/openrct2/actions/FootpathPlaceAction.hpp b/src/openrct2/actions/FootpathPlaceAction.hpp index a7da888ecf..3f89d9ec2b 100644 --- a/src/openrct2/actions/FootpathPlaceAction.hpp +++ b/src/openrct2/actions/FootpathPlaceAction.hpp @@ -240,8 +240,8 @@ private: : CREATE_CROSSING_MODE_PATH_OVER_TRACK; if (!entrancePath && !map_can_construct_with_clear_at( - _loc.x, _loc.y, zLow, zHigh, &map_place_non_scenery_clear_func, quarterTile, GetFlags(), &res->Cost, - crossingMode)) + _loc.x, _loc.y, zLow, zHigh, &map_place_non_scenery_clear_func, quarterTile, GetFlags(), &res->Cost, + crossingMode)) { return MakeResult(GA_ERROR::NO_CLEARANCE, STR_CANT_BUILD_FOOTPATH_HERE, gGameCommandErrorText, gCommonFormatArgs); } @@ -306,8 +306,8 @@ private: : CREATE_CROSSING_MODE_PATH_OVER_TRACK; if (!entrancePath && !map_can_construct_with_clear_at( - _loc.x, _loc.y, zLow, zHigh, &map_place_non_scenery_clear_func, quarterTile, - GAME_COMMAND_FLAG_APPLY | GetFlags(), &res->Cost, crossingMode)) + _loc.x, _loc.y, zLow, zHigh, &map_place_non_scenery_clear_func, quarterTile, + GAME_COMMAND_FLAG_APPLY | GetFlags(), &res->Cost, crossingMode)) { return MakeResult(GA_ERROR::NO_CLEARANCE, STR_CANT_BUILD_FOOTPATH_HERE, gGameCommandErrorText, gCommonFormatArgs); } diff --git a/src/openrct2/actions/FootpathSceneryPlaceAction.hpp b/src/openrct2/actions/FootpathSceneryPlaceAction.hpp index 3afff671b6..b21e64cccf 100644 --- a/src/openrct2/actions/FootpathSceneryPlaceAction.hpp +++ b/src/openrct2/actions/FootpathSceneryPlaceAction.hpp @@ -159,8 +159,8 @@ public: } // No change - if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && pathElement->GetAddition() == _pathItemType - && !(pathElement->IsBroken()) && !pathElement->AdditionIsGhost()) + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && pathElement->GetAddition() == _pathItemType && !(pathElement->IsBroken()) + && !pathElement->AdditionIsGhost()) { return res; } diff --git a/src/openrct2/actions/FootpathSceneryRemoveAction.hpp b/src/openrct2/actions/FootpathSceneryRemoveAction.hpp index 5c64b0318e..183d036fe2 100644 --- a/src/openrct2/actions/FootpathSceneryRemoveAction.hpp +++ b/src/openrct2/actions/FootpathSceneryRemoveAction.hpp @@ -47,7 +47,7 @@ public: GameActionResult::Ptr Query() const override { - if (!map_is_location_valid({_loc.x, _loc.y})) + if (!map_is_location_valid({ _loc.x, _loc.y })) { return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_REMOVE_THIS, STR_OFF_EDGE_OF_MAP); } diff --git a/src/openrct2/core/DataSerialiserTraits.h b/src/openrct2/core/DataSerialiserTraits.h index 99c71baddb..d2edf0dd46 100644 --- a/src/openrct2/core/DataSerialiserTraits.h +++ b/src/openrct2/core/DataSerialiserTraits.h @@ -363,8 +363,7 @@ template<> struct DataSerializerTraits static void log(IStream* stream, const CoordsXYZ& coord) { char msg[128] = {}; - snprintf( - msg, sizeof(msg), "CoordsXYZ(x = %d, y = %d, z = %d)", coord.x, coord.y, coord.z); + snprintf(msg, sizeof(msg), "CoordsXYZ(x = %d, y = %d, z = %d)", coord.x, coord.y, coord.z); stream->Write(msg, strlen(msg)); } }; diff --git a/src/openrct2/world/Scenery.cpp b/src/openrct2/world/Scenery.cpp index 914d5018c2..212232ccc2 100644 --- a/src/openrct2/world/Scenery.cpp +++ b/src/openrct2/world/Scenery.cpp @@ -12,9 +12,9 @@ #include "../Cheats.h" #include "../Context.h" #include "../Game.h" +#include "../actions/FootpathSceneryRemoveAction.hpp" #include "../actions/LargeSceneryRemoveAction.hpp" #include "../actions/SmallSceneryRemoveAction.hpp" -#include "../actions/FootpathSceneryRemoveAction.hpp" #include "../actions/WallRemoveAction.hpp" #include "../common.h" #include "../localisation/Localisation.h" @@ -206,7 +206,7 @@ void scenery_remove_ghost_tool_placement() if (tileElement->base_height != z) continue; - auto footpathSceneryRemoveAction = FootpathSceneryRemoveAction({x, y, z * 8}); + auto footpathSceneryRemoveAction = FootpathSceneryRemoveAction({ x, y, z * 8 }); footpathSceneryRemoveAction.SetFlags(GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_GHOST); GameActions::Execute(&footpathSceneryRemoveAction); break; From 2290d9de786b4ace1969cdeba4ff76021450f0d8 Mon Sep 17 00:00:00 2001 From: Tom Lankhorst Date: Fri, 1 Mar 2019 23:11:03 +0100 Subject: [PATCH 7/9] Add files to xcode project --- OpenRCT2.xcodeproj/project.pbxproj | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 4ca488c0ba..ee856509ab 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -34,6 +34,9 @@ 2A5C1368221E9F9000F8C245 /* TrackRemoveAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2A5C1367221E9F9000F8C245 /* TrackRemoveAction.hpp */; }; 2A61CAFB2229E5C50095AD67 /* RideEntranceExitPlaceAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2A61CAFA2229E5C50095AD67 /* RideEntranceExitPlaceAction.hpp */; }; 2A61CAF92229E59F0095AD67 /* WaterSetHeightAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2A61CAF82229E59F0095AD67 /* WaterSetHeightAction.hpp */; }; + 2A61CAF52229E5720095AD67 /* FootpathSceneryPlaceAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2A61CAF22229E5720095AD67 /* FootpathSceneryPlaceAction.hpp */; }; + 2A61CAF62229E5720095AD67 /* FootpathSceneryRemoveAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2A61CAF32229E5720095AD67 /* FootpathSceneryRemoveAction.hpp */; }; + 2A61CAF72229E5720095AD67 /* FootpathPlaceAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2A61CAF42229E5720095AD67 /* FootpathPlaceAction.hpp */; }; 2AA050322209A8E300D3A922 /* StaffSetCostumeAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2AA050302209A8E300D3A922 /* StaffSetCostumeAction.hpp */; }; 2AA050332209A8E300D3A922 /* StaffSetOrdersAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2AA050312209A8E300D3A922 /* StaffSetOrdersAction.hpp */; }; 2AAFD7FA220DD2DC002461A4 /* TrackPlaceAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2AAFD7F9220DD2DC002461A4 /* TrackPlaceAction.hpp */; }; @@ -642,6 +645,9 @@ 2A5C1367221E9F9000F8C245 /* TrackRemoveAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TrackRemoveAction.hpp; sourceTree = ""; }; 2A61CAFA2229E5C50095AD67 /* RideEntranceExitPlaceAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RideEntranceExitPlaceAction.hpp; sourceTree = ""; }; 2A61CAF82229E59F0095AD67 /* WaterSetHeightAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = WaterSetHeightAction.hpp; sourceTree = ""; }; + 2A61CAF22229E5720095AD67 /* FootpathSceneryPlaceAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FootpathSceneryPlaceAction.hpp; sourceTree = ""; }; + 2A61CAF32229E5720095AD67 /* FootpathSceneryRemoveAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FootpathSceneryRemoveAction.hpp; sourceTree = ""; }; + 2A61CAF42229E5720095AD67 /* FootpathPlaceAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FootpathPlaceAction.hpp; sourceTree = ""; }; 2AA050302209A8E300D3A922 /* StaffSetCostumeAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaffSetCostumeAction.hpp; sourceTree = ""; }; 2AA050312209A8E300D3A922 /* StaffSetOrdersAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaffSetOrdersAction.hpp; sourceTree = ""; }; 2AAFD7F9220DD2DC002461A4 /* TrackPlaceAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TrackPlaceAction.hpp; sourceTree = ""; }; @@ -2030,6 +2036,9 @@ children = ( 2A61CAFA2229E5C50095AD67 /* RideEntranceExitPlaceAction.hpp */, 2A61CAF82229E59F0095AD67 /* WaterSetHeightAction.hpp */, + 2A61CAF42229E5720095AD67 /* FootpathPlaceAction.hpp */, + 2A61CAF22229E5720095AD67 /* FootpathSceneryPlaceAction.hpp */, + 2A61CAF32229E5720095AD67 /* FootpathSceneryRemoveAction.hpp */, 2ACBAB162226850A0034FB91 /* RideSetSetting.hpp */, 2A43D2B92225B8D900E8F73B /* LoadOrQuitAction.hpp */, 2A43D2B72225B8D900E8F73B /* RideSetVehiclesAction.hpp */, @@ -3346,6 +3355,7 @@ C6352B951F477032006CCEE3 /* RideCreateAction.hpp in Headers */, C6352B851F477022006CCEE3 /* DataSerialiserTraits.h in Headers */, 939A359F20C12FDE00630B3F /* Paint.Surface.h in Headers */, + 2A61CAF62229E5720095AD67 /* FootpathSceneryRemoveAction.hpp in Headers */, C67B28192002D7F200109C93 /* Window_internal.h in Headers */, C6352B971F477032006CCEE3 /* SetParkEntranceFeeAction.hpp in Headers */, 2AA050332209A8E300D3A922 /* StaffSetOrdersAction.hpp in Headers */, @@ -3362,6 +3372,7 @@ 2A43D2BA2225B8D900E8F73B /* RideSetVehiclesAction.hpp in Headers */, 2A43D2C02225B91A00E8F73B /* RideSetVehiclesAction.hpp in Headers */, 2AA050322209A8E300D3A922 /* StaffSetCostumeAction.hpp in Headers */, + 2A61CAF72229E5720095AD67 /* FootpathPlaceAction.hpp in Headers */, 2A43D2C22225B91A00E8F73B /* LoadOrQuitAction.hpp in Headers */, C62D838B1FD36D6F008C04F1 /* EditorObjectSelectionSession.h in Headers */, 2A43D2BC2225B8D900E8F73B /* LoadOrQuitAction.hpp in Headers */, @@ -3369,6 +3380,7 @@ 939A35A220C12FFD00630B3F /* InteractiveConsole.h in Headers */, 2ACBAB172226850A0034FB91 /* RideSetSetting.hpp in Headers */, 93CBA4C320A7502E00867D56 /* Imaging.h in Headers */, + 2A61CAF52229E5720095AD67 /* FootpathSceneryPlaceAction.hpp in Headers */, 9308DA05209908090079EE96 /* Surface.h in Headers */, 93DE9753209C3C1000FB1CC8 /* GameState.h in Headers */, C6352B841F477022006CCEE3 /* DataSerialiser.h in Headers */, From da24ea53b86f24b101f22dbd8b9dc80411919a4f Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Sat, 2 Mar 2019 15:19:01 +0000 Subject: [PATCH 8/9] Fix formating add missing include --- src/openrct2/Game.h | 12 ++++++------ src/openrct2/actions/FootpathPlaceAction.hpp | 2 +- src/openrct2/actions/FootpathSceneryPlaceAction.hpp | 3 ++- src/openrct2/actions/FootpathSceneryRemoveAction.hpp | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index 5e888e817d..99961ed78e 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -37,7 +37,7 @@ enum GAME_COMMAND GAME_COMMAND_SET_WATER_HEIGHT, // GA GAME_COMMAND_PLACE_PATH, // GA GAME_COMMAND_PLACE_PATH_FROM_TRACK, - GAME_COMMAND_REMOVE_PATH, + GAME_COMMAND_REMOVE_PATH, // GA GAME_COMMAND_CHANGE_SURFACE_STYLE, GAME_COMMAND_SET_RIDE_PRICE, // GA GAME_COMMAND_SET_GUEST_NAME, // GA @@ -90,11 +90,11 @@ enum GAME_COMMAND GAME_COMMAND_BALLOON_PRESS, GAME_COMMAND_MODIFY_TILE, GAME_COMMAND_EDIT_SCENARIO_OPTIONS, - GAME_COMMAND_PLACE_PEEP_SPAWN, // GA, TODO: refactor to separate array for just game actions - GAME_COMMAND_SET_CLIMATE, // GA - GAME_COMMAND_SET_COLOUR_SCHEME, // GA - GAME_COMMAND_SET_STAFF_COSTUME, // GA - GAME_COMMAND_PLACE_FOOTPATH_SCENERY, // GA + GAME_COMMAND_PLACE_PEEP_SPAWN, // GA, TODO: refactor to separate array for just game actions + GAME_COMMAND_SET_CLIMATE, // GA + GAME_COMMAND_SET_COLOUR_SCHEME, // GA + GAME_COMMAND_SET_STAFF_COSTUME, // GA + GAME_COMMAND_PLACE_FOOTPATH_SCENERY, // GA GAME_COMMAND_REMOVE_FOOTPATH_SCENERY, // GA GAME_COMMAND_COUNT, }; diff --git a/src/openrct2/actions/FootpathPlaceAction.hpp b/src/openrct2/actions/FootpathPlaceAction.hpp index 3f89d9ec2b..e3c3a4b122 100644 --- a/src/openrct2/actions/FootpathPlaceAction.hpp +++ b/src/openrct2/actions/FootpathPlaceAction.hpp @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2018 OpenRCT2 developers + * 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 diff --git a/src/openrct2/actions/FootpathSceneryPlaceAction.hpp b/src/openrct2/actions/FootpathSceneryPlaceAction.hpp index b21e64cccf..7e7a3f7377 100644 --- a/src/openrct2/actions/FootpathSceneryPlaceAction.hpp +++ b/src/openrct2/actions/FootpathSceneryPlaceAction.hpp @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2018 OpenRCT2 developers + * 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 @@ -18,6 +18,7 @@ #include "../world/Footpath.h" #include "../world/Location.hpp" #include "../world/Park.h" +#include "../world/Scenery.h" #include "../world/Wall.h" #include "GameAction.h" diff --git a/src/openrct2/actions/FootpathSceneryRemoveAction.hpp b/src/openrct2/actions/FootpathSceneryRemoveAction.hpp index 183d036fe2..9d96e1dc66 100644 --- a/src/openrct2/actions/FootpathSceneryRemoveAction.hpp +++ b/src/openrct2/actions/FootpathSceneryRemoveAction.hpp @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2018 OpenRCT2 developers + * 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 From cfeeeab9b9771703d7dcc81dcc4ebafef0398b05 Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Mon, 4 Mar 2019 16:58:57 +0000 Subject: [PATCH 9/9] Increment network version --- src/openrct2/network/Network.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/network/Network.cpp b/src/openrct2/network/Network.cpp index f44b60b45a..3b59f27056 100644 --- a/src/openrct2/network/Network.cpp +++ b/src/openrct2/network/Network.cpp @@ -31,7 +31,7 @@ // This string specifies which version of network stream current build uses. // It is used for making sure only compatible builds get connected, even within // single OpenRCT2 version. -#define NETWORK_STREAM_VERSION "53" +#define NETWORK_STREAM_VERSION "54" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION static Peep* _pickup_peep = nullptr;