From bcb803df963d19f8d23fec595e6e7d1ef79600f8 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Tue, 26 Aug 2025 14:48:16 +0200 Subject: [PATCH] Move Footpath game actions into GameActions namespace --- .../interface/ViewportInteraction.cpp | 3 +- src/openrct2-ui/windows/Footpath.cpp | 6 +- src/openrct2-ui/windows/Scenery.cpp | 5 +- src/openrct2/actions/CustomAction.cpp | 77 +- src/openrct2/actions/CustomAction.h | 35 +- .../actions/FootpathAdditionPlaceAction.cpp | 284 +++--- .../actions/FootpathAdditionPlaceAction.h | 29 +- .../actions/FootpathAdditionRemoveAction.cpp | 154 ++-- .../actions/FootpathAdditionRemoveAction.h | 27 +- .../actions/FootpathLayoutPlaceAction.cpp | 516 ++++++----- .../actions/FootpathLayoutPlaceAction.h | 49 +- src/openrct2/actions/FootpathPlaceAction.cpp | 867 +++++++++--------- src/openrct2/actions/FootpathPlaceAction.h | 63 +- src/openrct2/rct12/ScenarioPatcher.cpp | 2 +- src/openrct2/ride/TrackDesign.cpp | 2 +- src/openrct2/scripting/ScriptEngine.cpp | 6 +- src/openrct2/scripting/ScriptEngine.h | 3 +- src/openrct2/world/Scenery.cpp | 2 +- 18 files changed, 1066 insertions(+), 1064 deletions(-) diff --git a/src/openrct2-ui/interface/ViewportInteraction.cpp b/src/openrct2-ui/interface/ViewportInteraction.cpp index da28743d22..cd2521f76b 100644 --- a/src/openrct2-ui/interface/ViewportInteraction.cpp +++ b/src/openrct2-ui/interface/ViewportInteraction.cpp @@ -662,7 +662,8 @@ namespace OpenRCT2::Ui */ static void ViewportInteractionRemovePathAddition(const PathElement& pathElement, const CoordsXY& mapCoords) { - auto footpathAdditionRemoveAction = FootpathAdditionRemoveAction({ mapCoords.x, mapCoords.y, pathElement.GetBaseZ() }); + auto footpathAdditionRemoveAction = GameActions::FootpathAdditionRemoveAction( + { mapCoords.x, mapCoords.y, pathElement.GetBaseZ() }); GameActions::Execute(&footpathAdditionRemoveAction); } diff --git a/src/openrct2-ui/windows/Footpath.cpp b/src/openrct2-ui/windows/Footpath.cpp index c6b315914b..963c4f2606 100644 --- a/src/openrct2-ui/windows/Footpath.cpp +++ b/src/openrct2-ui/windows/Footpath.cpp @@ -1145,7 +1145,7 @@ namespace OpenRCT2::Ui::Windows auto selectedType = gFootpathSelection.GetSelectedSurface(); PathConstructFlags constructFlags = FootpathCreateConstructFlags(selectedType); - auto footpathPlaceAction = FootpathPlaceAction( + auto footpathPlaceAction = GameActions::FootpathPlaceAction( { *mapPos, baseZ }, slope, selectedType, gFootpathSelection.Railings, kInvalidDirection, constructFlags); footpathPlaceAction.SetCallback([this](const GameAction* ga, const GameActions::Result* result) { if (result->Error == GameActions::Status::Ok) @@ -1237,7 +1237,7 @@ namespace OpenRCT2::Ui::Windows PathConstructFlags constructFlags = FootpathCreateConstructFlags(type); - auto footpathPlaceAction = FootpathPlaceAction( + auto footpathPlaceAction = GameActions::FootpathPlaceAction( footpathLoc, slope, type, gFootpathSelection.Railings, _footpathConstructDirection, constructFlags); footpathPlaceAction.SetCallback([footpathLoc](const GameAction* ga, const GameActions::Result* result) { @@ -1756,7 +1756,7 @@ namespace OpenRCT2::Ui::Windows FootpathRemoveProvisional(); - auto footpathPlaceAction = FootpathPlaceAction( + auto footpathPlaceAction = GameActions::FootpathPlaceAction( footpathLoc, slope, type, railingsType, kInvalidDirection, constructFlags); footpathPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED); auto res = GameActions::Execute(&footpathPlaceAction); diff --git a/src/openrct2-ui/windows/Scenery.cpp b/src/openrct2-ui/windows/Scenery.cpp index 6656defb24..178c44b69c 100644 --- a/src/openrct2-ui/windows/Scenery.cpp +++ b/src/openrct2-ui/windows/Scenery.cpp @@ -2131,7 +2131,7 @@ namespace OpenRCT2::Ui::Windows SceneryRemoveGhostToolPlacement(); // 6e265b - auto footpathAdditionPlaceAction = FootpathAdditionPlaceAction(loc, entryIndex); + auto footpathAdditionPlaceAction = GameActions::FootpathAdditionPlaceAction(loc, entryIndex); footpathAdditionPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED); footpathAdditionPlaceAction.SetCallback([=](const GameAction* ga, const GameActions::Result* result) { if (result->Error != GameActions::Status::Ok) @@ -3093,7 +3093,8 @@ namespace OpenRCT2::Ui::Windows if (gridPos.IsNull()) return; - auto footpathAdditionPlaceAction = FootpathAdditionPlaceAction({ gridPos, z }, selectedScenery); + auto footpathAdditionPlaceAction = GameActions::FootpathAdditionPlaceAction( + { gridPos, z }, selectedScenery); footpathAdditionPlaceAction.SetCallback([](const GameAction* ga, const GameActions::Result* result) { if (result->Error != GameActions::Status::Ok) diff --git a/src/openrct2/actions/CustomAction.cpp b/src/openrct2/actions/CustomAction.cpp index a474abce63..11fae91d5f 100644 --- a/src/openrct2/actions/CustomAction.cpp +++ b/src/openrct2/actions/CustomAction.cpp @@ -13,51 +13,52 @@ #include "../Context.h" #include "../scripting/ScriptEngine.h" -using namespace OpenRCT2; - -CustomAction::CustomAction(const std::string& id, const std::string& json, const std::string& pluginName) - : _id(id) - , _json(json) - , _pluginName(pluginName) +namespace OpenRCT2::GameActions { -} + CustomAction::CustomAction(const std::string& id, const std::string& json, const std::string& pluginName) + : _id(id) + , _json(json) + , _pluginName(pluginName) + { + } -std::string CustomAction::GetId() const -{ - return _id; -} + std::string CustomAction::GetId() const + { + return _id; + } -std::string CustomAction::GetJson() const -{ - return _json; -} + std::string CustomAction::GetJson() const + { + return _json; + } -std::string CustomAction::GetPluginName() const -{ - return _pluginName; -} + std::string CustomAction::GetPluginName() const + { + return _pluginName; + } -uint16_t CustomAction::GetActionFlags() const -{ - return GameAction::GetActionFlags() | GameActions::Flags::AllowWhilePaused; -} + uint16_t CustomAction::GetActionFlags() const + { + return GameAction::GetActionFlags() | Flags::AllowWhilePaused; + } -void CustomAction::Serialise(DataSerialiser& stream) -{ - GameAction::Serialise(stream); - stream << DS_TAG(_id) << DS_TAG(_json); -} + void CustomAction::Serialise(DataSerialiser& stream) + { + GameAction::Serialise(stream); + stream << DS_TAG(_id) << DS_TAG(_json); + } -GameActions::Result CustomAction::Query() const -{ - auto& scriptingEngine = OpenRCT2::GetContext()->GetScriptEngine(); - return scriptingEngine.QueryOrExecuteCustomGameAction(*this, false); -} + Result CustomAction::Query() const + { + auto& scriptingEngine = GetContext()->GetScriptEngine(); + return scriptingEngine.QueryOrExecuteCustomGameAction(*this, false); + } -GameActions::Result CustomAction::Execute() const -{ - auto& scriptingEngine = OpenRCT2::GetContext()->GetScriptEngine(); - return scriptingEngine.QueryOrExecuteCustomGameAction(*this, true); -} + Result CustomAction::Execute() const + { + auto& scriptingEngine = GetContext()->GetScriptEngine(); + return scriptingEngine.QueryOrExecuteCustomGameAction(*this, true); + } +} // namespace OpenRCT2::GameActions #endif diff --git a/src/openrct2/actions/CustomAction.h b/src/openrct2/actions/CustomAction.h index 9e8253f36a..c7b41ec9bb 100644 --- a/src/openrct2/actions/CustomAction.h +++ b/src/openrct2/actions/CustomAction.h @@ -13,26 +13,29 @@ #include "GameAction.h" -class CustomAction final : public GameActionBase +namespace OpenRCT2::GameActions { -private: - std::string _id; - std::string _json; - std::string _pluginName; + class CustomAction final : public GameActionBase + { + private: + std::string _id; + std::string _json; + std::string _pluginName; -public: - CustomAction() = default; - CustomAction(const std::string& id, const std::string& json, const std::string& pluginName); + public: + CustomAction() = default; + CustomAction(const std::string& id, const std::string& json, const std::string& pluginName); - std::string GetId() const; - std::string GetJson() const; - std::string GetPluginName() const; + std::string GetId() const; + std::string GetJson() const; + std::string GetPluginName() const; - uint16_t GetActionFlags() const override; + uint16_t GetActionFlags() const override; - void Serialise(DataSerialiser& stream) override; - OpenRCT2::GameActions::Result Query() const override; - OpenRCT2::GameActions::Result Execute() const override; -}; + void Serialise(DataSerialiser& stream) override; + Result Query() const override; + Result Execute() const override; + }; +} // namespace OpenRCT2::GameActions #endif diff --git a/src/openrct2/actions/FootpathAdditionPlaceAction.cpp b/src/openrct2/actions/FootpathAdditionPlaceAction.cpp index c1811d996c..2421678859 100644 --- a/src/openrct2/actions/FootpathAdditionPlaceAction.cpp +++ b/src/openrct2/actions/FootpathAdditionPlaceAction.cpp @@ -24,177 +24,169 @@ #include "../world/Scenery.h" #include "../world/tile_element/PathElement.h" -using namespace OpenRCT2; - -FootpathAdditionPlaceAction::FootpathAdditionPlaceAction(const CoordsXYZ& loc, ObjectEntryIndex pathItemType) - : _loc(loc) - , _entryIndex(pathItemType) +namespace OpenRCT2::GameActions { -} - -void FootpathAdditionPlaceAction::AcceptParameters(GameActionParameterVisitor& visitor) -{ - visitor.Visit(_loc); - visitor.Visit("object", _entryIndex); -} - -uint16_t FootpathAdditionPlaceAction::GetActionFlags() const -{ - return GameAction::GetActionFlags(); -} - -void FootpathAdditionPlaceAction::Serialise(DataSerialiser& stream) -{ - GameAction::Serialise(stream); - - stream << DS_TAG(_loc) << DS_TAG(_entryIndex); -} - -GameActions::Result FootpathAdditionPlaceAction::Query() const -{ - auto res = GameActions::Result(); - res.Expenditure = ExpenditureType::landscaping; - res.Position = _loc; - if (!LocationValid(_loc)) + FootpathAdditionPlaceAction::FootpathAdditionPlaceAction(const CoordsXYZ& loc, ObjectEntryIndex pathItemType) + : _loc(loc) + , _entryIndex(pathItemType) { - return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_OFF_EDGE_OF_MAP); } - if (!(gLegacyScene == LegacyScene::scenarioEditor || getGameState().cheats.sandboxMode) && !MapIsLocationOwned(_loc)) + void FootpathAdditionPlaceAction::AcceptParameters(GameActionParameterVisitor& visitor) { - return GameActions::Result(GameActions::Status::Disallowed, STR_CANT_POSITION_THIS_HERE, STR_LAND_NOT_OWNED_BY_PARK); + visitor.Visit(_loc); + visitor.Visit("object", _entryIndex); } - if (_loc.z < kFootpathMinHeight) + uint16_t FootpathAdditionPlaceAction::GetActionFlags() const { - return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_TOO_LOW); + return GameAction::GetActionFlags(); } - if (_loc.z > kFootpathMaxHeight) + void FootpathAdditionPlaceAction::Serialise(DataSerialiser& stream) { - return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_TOO_HIGH); + GameAction::Serialise(stream); + + stream << DS_TAG(_loc) << DS_TAG(_entryIndex); } - auto tileElement = MapGetFootpathElement(_loc); - if (tileElement == nullptr) + Result FootpathAdditionPlaceAction::Query() const { - LOG_ERROR("No path element at x = %d, y = %d, z = %d", _loc.x, _loc.y, _loc.z); - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_ERR_PATH_ELEMENT_NOT_FOUND); - } - - auto pathElement = tileElement->AsPath(); - if (pathElement->IsLevelCrossing(_loc)) - { - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, - STR_CANNOT_BUILD_PATH_ADDITIONS_ON_LEVEL_CROSSINGS); - } - - // No change - if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && pathElement->GetAdditionEntryIndex() == _entryIndex - && !(pathElement->IsBroken())) - { - return res; - } - - auto* pathAdditionEntry = ObjectManager::GetObjectEntry(_entryIndex); - if (pathAdditionEntry == nullptr) - { - LOG_ERROR("Unknown footpath addition entry for entryIndex %d", _entryIndex); - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_UNKNOWN_OBJECT_TYPE); - } - uint16_t sceneryFlags = pathAdditionEntry->flags; - - if ((sceneryFlags & PATH_ADDITION_FLAG_DONT_ALLOW_ON_SLOPE) && pathElement->IsSloped()) - { - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_CANT_BUILD_THIS_ON_SLOPED_FOOTPATH); - } - - if ((sceneryFlags & PATH_ADDITION_FLAG_DONT_ALLOW_ON_QUEUE) && pathElement->IsQueue()) - { - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_CANNOT_PLACE_THESE_ON_QUEUE_LINE_AREA); - } - - if (!(sceneryFlags & (PATH_ADDITION_FLAG_JUMPING_FOUNTAIN_WATER | PATH_ADDITION_FLAG_JUMPING_FOUNTAIN_SNOW)) - && (pathElement->GetEdges()) == 0x0F) - { - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_CAN_ONLY_BE_PLACED_ON_PATH_EDGES); - } - - if ((sceneryFlags & PATH_ADDITION_FLAG_IS_QUEUE_SCREEN) && !pathElement->IsQueue()) - { - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_CAN_ONLY_PLACE_THESE_ON_QUEUE_AREA); - } - - res.Cost = pathAdditionEntry->price; - - // Should place a ghost? - if (GetFlags() & GAME_COMMAND_FLAG_GHOST) - { - // Check if there is something on the path already - if (pathElement->HasAddition()) + auto res = Result(); + res.Expenditure = ExpenditureType::landscaping; + res.Position = _loc; + if (!LocationValid(_loc)) { - return GameActions::Result(GameActions::Status::ItemAlreadyPlaced, STR_CANT_POSITION_THIS_HERE, kStringIdNone); + return Result(Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_OFF_EDGE_OF_MAP); } - } - return res; -} -GameActions::Result FootpathAdditionPlaceAction::Execute() const -{ - auto res = GameActions::Result(); - res.Position = _loc; - res.Expenditure = ExpenditureType::landscaping; + if (!(gLegacyScene == LegacyScene::scenarioEditor || getGameState().cheats.sandboxMode) && !MapIsLocationOwned(_loc)) + { + return Result(Status::Disallowed, STR_CANT_POSITION_THIS_HERE, STR_LAND_NOT_OWNED_BY_PARK); + } - auto tileElement = MapGetFootpathElement(_loc); - auto pathElement = tileElement->AsPath(); + if (_loc.z < kFootpathMinHeight) + { + return Result(Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_TOO_LOW); + } - if (pathElement == nullptr) - { - LOG_ERROR("No path element at x = %d, y = %d, z = %d", _loc.x, _loc.y, _loc.z); - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_ERR_PATH_ELEMENT_NOT_FOUND); - } + if (_loc.z > kFootpathMaxHeight) + { + return Result(Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_TOO_HIGH); + } - // No change - if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && pathElement->GetAdditionEntryIndex() == _entryIndex - && !(pathElement->IsBroken()) && !pathElement->AdditionIsGhost()) - { + auto tileElement = MapGetFootpathElement(_loc); + if (tileElement == nullptr) + { + LOG_ERROR("No path element at x = %d, y = %d, z = %d", _loc.x, _loc.y, _loc.z); + return Result(Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_ERR_PATH_ELEMENT_NOT_FOUND); + } + + auto pathElement = tileElement->AsPath(); + if (pathElement->IsLevelCrossing(_loc)) + { + return Result( + Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_CANNOT_BUILD_PATH_ADDITIONS_ON_LEVEL_CROSSINGS); + } + + // No change + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && pathElement->GetAdditionEntryIndex() == _entryIndex + && !(pathElement->IsBroken())) + { + return res; + } + + auto* pathAdditionEntry = ObjectManager::GetObjectEntry(_entryIndex); + if (pathAdditionEntry == nullptr) + { + LOG_ERROR("Unknown footpath addition entry for entryIndex %d", _entryIndex); + return Result(Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_UNKNOWN_OBJECT_TYPE); + } + uint16_t sceneryFlags = pathAdditionEntry->flags; + + if ((sceneryFlags & PATH_ADDITION_FLAG_DONT_ALLOW_ON_SLOPE) && pathElement->IsSloped()) + { + return Result(Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_CANT_BUILD_THIS_ON_SLOPED_FOOTPATH); + } + + if ((sceneryFlags & PATH_ADDITION_FLAG_DONT_ALLOW_ON_QUEUE) && pathElement->IsQueue()) + { + return Result(Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_CANNOT_PLACE_THESE_ON_QUEUE_LINE_AREA); + } + + if (!(sceneryFlags & (PATH_ADDITION_FLAG_JUMPING_FOUNTAIN_WATER | PATH_ADDITION_FLAG_JUMPING_FOUNTAIN_SNOW)) + && (pathElement->GetEdges()) == 0x0F) + { + return Result(Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_CAN_ONLY_BE_PLACED_ON_PATH_EDGES); + } + + if ((sceneryFlags & PATH_ADDITION_FLAG_IS_QUEUE_SCREEN) && !pathElement->IsQueue()) + { + return Result(Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_CAN_ONLY_PLACE_THESE_ON_QUEUE_AREA); + } + + res.Cost = pathAdditionEntry->price; + + // Should place a ghost? + if (GetFlags() & GAME_COMMAND_FLAG_GHOST) + { + // Check if there is something on the path already + if (pathElement->HasAddition()) + { + return Result(Status::ItemAlreadyPlaced, STR_CANT_POSITION_THIS_HERE, kStringIdNone); + } + } return res; } - auto* pathAdditionEntry = OpenRCT2::ObjectManager::GetObjectEntry(_entryIndex); - if (pathAdditionEntry == nullptr) + Result FootpathAdditionPlaceAction::Execute() const { - LOG_ERROR("Unknown footpath addition entry for entryIndex %d", _entryIndex); - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_UNKNOWN_OBJECT_TYPE); - } + auto res = Result(); + res.Position = _loc; + res.Expenditure = ExpenditureType::landscaping; - res.Cost = pathAdditionEntry->price; + auto tileElement = MapGetFootpathElement(_loc); + auto pathElement = tileElement->AsPath(); - if (GetFlags() & GAME_COMMAND_FLAG_GHOST) - { - pathElement->SetAdditionIsGhost(true); - } - else - { - FootpathInterruptPeeps(_loc); - pathElement->SetAdditionIsGhost(false); - } + if (pathElement == nullptr) + { + LOG_ERROR("No path element at x = %d, y = %d, z = %d", _loc.x, _loc.y, _loc.z); + return Result(Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_ERR_PATH_ELEMENT_NOT_FOUND); + } - pathElement->SetAdditionEntryIndex(_entryIndex); - pathElement->SetIsBroken(false); - if (pathAdditionEntry->flags & PATH_ADDITION_FLAG_IS_BIN) - { - pathElement->SetAdditionStatus(255); + // No change + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && pathElement->GetAdditionEntryIndex() == _entryIndex + && !(pathElement->IsBroken()) && !pathElement->AdditionIsGhost()) + { + return res; + } + + auto* pathAdditionEntry = OpenRCT2::ObjectManager::GetObjectEntry(_entryIndex); + if (pathAdditionEntry == nullptr) + { + LOG_ERROR("Unknown footpath addition entry for entryIndex %d", _entryIndex); + return Result(Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_UNKNOWN_OBJECT_TYPE); + } + + res.Cost = pathAdditionEntry->price; + + if (GetFlags() & GAME_COMMAND_FLAG_GHOST) + { + pathElement->SetAdditionIsGhost(true); + } + else + { + FootpathInterruptPeeps(_loc); + pathElement->SetAdditionIsGhost(false); + } + + pathElement->SetAdditionEntryIndex(_entryIndex); + pathElement->SetIsBroken(false); + if (pathAdditionEntry->flags & PATH_ADDITION_FLAG_IS_BIN) + { + pathElement->SetAdditionStatus(255); + } + MapInvalidateTileFull(_loc); + return res; } - MapInvalidateTileFull(_loc); - return res; -} +} // namespace OpenRCT2::GameActions diff --git a/src/openrct2/actions/FootpathAdditionPlaceAction.h b/src/openrct2/actions/FootpathAdditionPlaceAction.h index 14fe4fa4ed..8e81475ab1 100644 --- a/src/openrct2/actions/FootpathAdditionPlaceAction.h +++ b/src/openrct2/actions/FootpathAdditionPlaceAction.h @@ -11,21 +11,24 @@ #include "GameAction.h" -class FootpathAdditionPlaceAction final : public GameActionBase +namespace OpenRCT2::GameActions { -private: - CoordsXYZ _loc; - OpenRCT2::ObjectEntryIndex _entryIndex{}; + class FootpathAdditionPlaceAction final : public GameActionBase + { + private: + CoordsXYZ _loc; + ObjectEntryIndex _entryIndex{}; -public: - FootpathAdditionPlaceAction() = default; - FootpathAdditionPlaceAction(const CoordsXYZ& loc, OpenRCT2::ObjectEntryIndex pathItemType); + public: + FootpathAdditionPlaceAction() = default; + FootpathAdditionPlaceAction(const CoordsXYZ& loc, ObjectEntryIndex pathItemType); - void AcceptParameters(GameActionParameterVisitor& visitor) override; + void AcceptParameters(GameActionParameterVisitor& visitor) override; - uint16_t GetActionFlags() const override; + uint16_t GetActionFlags() const override; - void Serialise(DataSerialiser& stream) override; - OpenRCT2::GameActions::Result Query() const override; - OpenRCT2::GameActions::Result Execute() const override; -}; + void Serialise(DataSerialiser& stream) override; + Result Query() const override; + Result Execute() const override; + }; +} // namespace OpenRCT2::GameActions diff --git a/src/openrct2/actions/FootpathAdditionRemoveAction.cpp b/src/openrct2/actions/FootpathAdditionRemoveAction.cpp index f506cfdf3c..d1645283d4 100644 --- a/src/openrct2/actions/FootpathAdditionRemoveAction.cpp +++ b/src/openrct2/actions/FootpathAdditionRemoveAction.cpp @@ -21,99 +21,97 @@ #include "../world/Park.h" #include "../world/tile_element/PathElement.h" -using namespace OpenRCT2; - -FootpathAdditionRemoveAction::FootpathAdditionRemoveAction(const CoordsXYZ& loc) - : _loc(loc) +namespace OpenRCT2::GameActions { -} - -void FootpathAdditionRemoveAction::AcceptParameters(GameActionParameterVisitor& visitor) -{ - visitor.Visit(_loc); -} - -uint16_t FootpathAdditionRemoveAction::GetActionFlags() const -{ - return GameAction::GetActionFlags(); -} - -void FootpathAdditionRemoveAction::Serialise(DataSerialiser& stream) -{ - GameAction::Serialise(stream); - - stream << DS_TAG(_loc); -} - -GameActions::Result FootpathAdditionRemoveAction::Query() const -{ - if (!LocationValid(_loc)) + FootpathAdditionRemoveAction::FootpathAdditionRemoveAction(const CoordsXYZ& loc) + : _loc(loc) { - return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_REMOVE_THIS, STR_OFF_EDGE_OF_MAP); } - if (!(gLegacyScene == LegacyScene::scenarioEditor || getGameState().cheats.sandboxMode) && !MapIsLocationOwned(_loc)) + void FootpathAdditionRemoveAction::AcceptParameters(GameActionParameterVisitor& visitor) { - return GameActions::Result(GameActions::Status::Disallowed, STR_CANT_REMOVE_THIS, STR_LAND_NOT_OWNED_BY_PARK); + visitor.Visit(_loc); } - if (_loc.z < kFootpathMinHeight) + uint16_t FootpathAdditionRemoveAction::GetActionFlags() const { - return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_REMOVE_THIS, STR_TOO_LOW); + return GameAction::GetActionFlags(); } - if (_loc.z > kFootpathMaxHeight) + void FootpathAdditionRemoveAction::Serialise(DataSerialiser& stream) { - return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_REMOVE_THIS, STR_TOO_HIGH); + GameAction::Serialise(stream); + + stream << DS_TAG(_loc); } - auto tileElement = MapGetFootpathElement(_loc); - if (tileElement == nullptr) + Result FootpathAdditionRemoveAction::Query() const { - LOG_ERROR("No path element at x = %d, y = %d, z = %d", _loc.x, _loc.y, _loc.z); - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_CANT_REMOVE_THIS, STR_ERR_PATH_ELEMENT_NOT_FOUND); + if (!LocationValid(_loc)) + { + return Result(Status::InvalidParameters, STR_CANT_REMOVE_THIS, STR_OFF_EDGE_OF_MAP); + } + + if (!(gLegacyScene == LegacyScene::scenarioEditor || getGameState().cheats.sandboxMode) && !MapIsLocationOwned(_loc)) + { + return Result(Status::Disallowed, STR_CANT_REMOVE_THIS, STR_LAND_NOT_OWNED_BY_PARK); + } + + if (_loc.z < kFootpathMinHeight) + { + return Result(Status::InvalidParameters, STR_CANT_REMOVE_THIS, STR_TOO_LOW); + } + + if (_loc.z > kFootpathMaxHeight) + { + return Result(Status::InvalidParameters, STR_CANT_REMOVE_THIS, STR_TOO_HIGH); + } + + auto tileElement = MapGetFootpathElement(_loc); + if (tileElement == nullptr) + { + LOG_ERROR("No path element at x = %d, y = %d, z = %d", _loc.x, _loc.y, _loc.z); + return Result(Status::InvalidParameters, STR_CANT_REMOVE_THIS, STR_ERR_PATH_ELEMENT_NOT_FOUND); + } + + auto pathElement = tileElement->AsPath(); + if (pathElement == nullptr) + { + LOG_ERROR("No path element at x = %d, y = %d, z = %d", _loc.x, _loc.y, _loc.z); + return Result(Status::InvalidParameters, STR_CANT_REMOVE_THIS, STR_ERR_PATH_ELEMENT_NOT_FOUND); + } + + if (!pathElement->AdditionIsGhost() && (GetFlags() & GAME_COMMAND_FLAG_GHOST)) + { + LOG_WARNING("Tried to remove non ghost during ghost removal."); + return Result(Status::Disallowed, STR_CANT_REMOVE_THIS, kStringIdNone); + } + auto res = Result(); + res.Position = _loc; + res.Cost = 0.00_GBP; + return res; } - auto pathElement = tileElement->AsPath(); - if (pathElement == nullptr) + Result FootpathAdditionRemoveAction::Execute() const { - LOG_ERROR("No path element at x = %d, y = %d, z = %d", _loc.x, _loc.y, _loc.z); - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_CANT_REMOVE_THIS, STR_ERR_PATH_ELEMENT_NOT_FOUND); + auto* pathElement = MapGetFootpathElement(_loc); + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST)) + { + FootpathInterruptPeeps(_loc); + } + + if (pathElement == nullptr) + { + LOG_ERROR("No path element at x = %d, y = %d, z = %d", _loc.x, _loc.y, _loc.z); + return Result(Status::InvalidParameters, STR_CANT_REMOVE_THIS, STR_ERR_PATH_ELEMENT_NOT_FOUND); + } + + pathElement->SetAddition(0); + MapInvalidateTileFull(_loc); + + auto res = Result(); + res.Position = _loc; + res.Cost = 0.00_GBP; + return res; } - - if (!pathElement->AdditionIsGhost() && (GetFlags() & GAME_COMMAND_FLAG_GHOST)) - { - LOG_WARNING("Tried to remove non ghost during ghost removal."); - return GameActions::Result(GameActions::Status::Disallowed, STR_CANT_REMOVE_THIS, kStringIdNone); - } - auto res = GameActions::Result(); - res.Position = _loc; - res.Cost = 0.00_GBP; - return res; -} - -GameActions::Result FootpathAdditionRemoveAction::Execute() const -{ - auto* pathElement = MapGetFootpathElement(_loc); - if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST)) - { - FootpathInterruptPeeps(_loc); - } - - if (pathElement == nullptr) - { - LOG_ERROR("No path element at x = %d, y = %d, z = %d", _loc.x, _loc.y, _loc.z); - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_CANT_REMOVE_THIS, STR_ERR_PATH_ELEMENT_NOT_FOUND); - } - - pathElement->SetAddition(0); - MapInvalidateTileFull(_loc); - - auto res = GameActions::Result(); - res.Position = _loc; - res.Cost = 0.00_GBP; - return res; -} +} // namespace OpenRCT2::GameActions diff --git a/src/openrct2/actions/FootpathAdditionRemoveAction.h b/src/openrct2/actions/FootpathAdditionRemoveAction.h index 761ebe03d5..e43166f8ed 100644 --- a/src/openrct2/actions/FootpathAdditionRemoveAction.h +++ b/src/openrct2/actions/FootpathAdditionRemoveAction.h @@ -11,20 +11,23 @@ #include "GameAction.h" -class FootpathAdditionRemoveAction final : public GameActionBase +namespace OpenRCT2::GameActions { -private: - CoordsXYZ _loc; + class FootpathAdditionRemoveAction final : public GameActionBase + { + private: + CoordsXYZ _loc; -public: - FootpathAdditionRemoveAction() = default; - FootpathAdditionRemoveAction(const CoordsXYZ& loc); + public: + FootpathAdditionRemoveAction() = default; + FootpathAdditionRemoveAction(const CoordsXYZ& loc); - void AcceptParameters(GameActionParameterVisitor& visitor) override; + void AcceptParameters(GameActionParameterVisitor& visitor) override; - uint16_t GetActionFlags() const override; + uint16_t GetActionFlags() const override; - void Serialise(DataSerialiser& stream) override; - OpenRCT2::GameActions::Result Query() const override; - OpenRCT2::GameActions::Result Execute() const override; -}; + void Serialise(DataSerialiser& stream) override; + Result Query() const override; + Result Execute() const override; + }; +} // namespace OpenRCT2::GameActions diff --git a/src/openrct2/actions/FootpathLayoutPlaceAction.cpp b/src/openrct2/actions/FootpathLayoutPlaceAction.cpp index 6eb5371e60..7a189db203 100644 --- a/src/openrct2/actions/FootpathLayoutPlaceAction.cpp +++ b/src/openrct2/actions/FootpathLayoutPlaceAction.cpp @@ -26,295 +26,291 @@ #include "../world/tile_element/Slope.h" #include "../world/tile_element/SurfaceElement.h" -using namespace OpenRCT2; - -FootpathLayoutPlaceAction::FootpathLayoutPlaceAction( - const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, ObjectEntryIndex railingsType, uint8_t edges, - PathConstructFlags constructFlags) - : _loc(loc) - , _slope(slope) - , _type(type) - , _railingsType(railingsType) - , _edges(edges) - , _constructFlags(constructFlags) +namespace OpenRCT2::GameActions { -} - -void FootpathLayoutPlaceAction::Serialise(DataSerialiser& stream) -{ - GameAction::Serialise(stream); - - stream << DS_TAG(_loc) << DS_TAG(_slope) << DS_TAG(_type) << DS_TAG(_railingsType) << DS_TAG(_edges) - << DS_TAG(_constructFlags); -} - -void FootpathLayoutPlaceAction::AcceptParameters(GameActionParameterVisitor& visitor) -{ - visitor.Visit(_loc); - visitor.Visit("slope", _slope); - visitor.Visit("object", _type); - visitor.Visit("railingsObject", _railingsType); - visitor.Visit("edges", _edges); - visitor.Visit("constructFlags", _constructFlags); -} - -uint16_t FootpathLayoutPlaceAction::GetActionFlags() const -{ - return GameAction::GetActionFlags(); -} - -GameActions::Result FootpathLayoutPlaceAction::Query() const -{ - auto res = GameActions::Result(); - res.Cost = 0; - res.Expenditure = ExpenditureType::landscaping; - res.Position = _loc.ToTileCentre(); - - gFootpathGroundFlags = 0; - - if (!LocationValid(_loc) || MapIsEdge(_loc)) + FootpathLayoutPlaceAction::FootpathLayoutPlaceAction( + const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, ObjectEntryIndex railingsType, uint8_t edges, + PathConstructFlags constructFlags) + : _loc(loc) + , _slope(slope) + , _type(type) + , _railingsType(railingsType) + , _edges(edges) + , _constructFlags(constructFlags) { - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_OFF_EDGE_OF_MAP); } - if (!(gLegacyScene == LegacyScene::scenarioEditor || getGameState().cheats.sandboxMode) && !MapIsLocationOwned(_loc)) + void FootpathLayoutPlaceAction::Serialise(DataSerialiser& stream) { - return GameActions::Result( - GameActions::Status::Disallowed, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_LAND_NOT_OWNED_BY_PARK); + GameAction::Serialise(stream); + + stream << DS_TAG(_loc) << DS_TAG(_slope) << DS_TAG(_type) << DS_TAG(_railingsType) << DS_TAG(_edges) + << DS_TAG(_constructFlags); } - if (_loc.z < kFootpathMinHeight) + void FootpathLayoutPlaceAction::AcceptParameters(GameActionParameterVisitor& visitor) { - return GameActions::Result( - GameActions::Status::Disallowed, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_TOO_LOW); + visitor.Visit(_loc); + visitor.Visit("slope", _slope); + visitor.Visit("object", _type); + visitor.Visit("railingsObject", _railingsType); + visitor.Visit("edges", _edges); + visitor.Visit("constructFlags", _constructFlags); } - if (_loc.z > kFootpathMaxHeight) + uint16_t FootpathLayoutPlaceAction::GetActionFlags() const { - return GameActions::Result( - GameActions::Status::Disallowed, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_TOO_HIGH); + return GameAction::GetActionFlags(); } - return ElementInsertQuery(std::move(res)); -} - -GameActions::Result FootpathLayoutPlaceAction::Execute() const -{ - auto res = GameActions::Result(); - res.Cost = 0; - res.Expenditure = ExpenditureType::landscaping; - res.Position = _loc.ToTileCentre(); - - if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST)) + Result FootpathLayoutPlaceAction::Query() const { - FootpathInterruptPeeps(_loc); - } - - gFootpathGroundFlags = 0; - - // Force ride construction to recheck area - _currentTrackSelectionFlags.set(TrackSelectionFlag::recheck); - - return ElementInsertExecute(std::move(res)); -} - -GameActions::Result FootpathLayoutPlaceAction::ElementInsertQuery(GameActions::Result res) const -{ - bool entrancePath = false, entranceIsSamePath = false; - - if (!MapCheckCapacityAndReorganise(_loc)) - { - return GameActions::Result( - GameActions::Status::NoFreeElements, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, - STR_TILE_ELEMENT_LIMIT_REACHED); - } - - res.Cost = 12.00_GBP; - - QuarterTile quarterTile{ 0b1111, 0 }; - auto zLow = _loc.z; - auto zHigh = zLow + kPathClearance; - if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED) - { - quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope & kTileElementDirectionMask); - zHigh += kPathHeightStep; - } - - auto entranceElement = MapGetParkEntranceElementAt(_loc, 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 (IsSameAsEntranceElement(*entranceElement)) - entranceIsSamePath = true; - else - res.Cost -= 6.00_GBP; - } - - // Do not attempt to build a crossing with a queue or a sloped path. - auto isQueue = _constructFlags & PathConstructFlag::IsQueue; - auto crossingMode = isQueue || (_slope != kTileSlopeFlat) ? CreateCrossingMode::none : CreateCrossingMode::pathOverTrack; - auto canBuild = MapCanConstructWithClearAt( - { _loc, zLow, zHigh }, &MapPlaceNonSceneryClearFunc, quarterTile, GetFlags(), crossingMode); - if (!entrancePath && canBuild.Error != GameActions::Status::Ok) - { - canBuild.ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE; - return canBuild; - } - res.Cost += canBuild.Cost; - - const auto clearanceData = canBuild.GetData(); - gFootpathGroundFlags = clearanceData.GroundFlags; - - if (!getGameState().cheats.disableClearanceChecks && (clearanceData.GroundFlags & ELEMENT_IS_UNDERWATER)) - { - return GameActions::Result( - GameActions::Status::Disallowed, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_CANT_BUILD_THIS_UNDERWATER); - } - - auto surfaceElement = MapGetSurfaceElementAt(_loc); - if (surfaceElement == nullptr) - { - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, - STR_ERR_SURFACE_ELEMENT_NOT_FOUND); - } - int32_t supportHeight = zLow - surfaceElement->GetBaseZ(); - res.Cost += supportHeight < 0 ? 20.00_GBP : (supportHeight / kPathHeightStep) * 5.00_GBP; - - // Prevent the place sound from being spammed - if (entranceIsSamePath) + auto res = Result(); res.Cost = 0; + res.Expenditure = ExpenditureType::landscaping; + res.Position = _loc.ToTileCentre(); - return res; -} + gFootpathGroundFlags = 0; -GameActions::Result FootpathLayoutPlaceAction::ElementInsertExecute(GameActions::Result res) const -{ - bool entrancePath = false, entranceIsSamePath = false; - - if (!(GetFlags() & (GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_GHOST))) - { - FootpathRemoveLitter(_loc); - } - - res.Cost = 12.00_GBP; - - QuarterTile quarterTile{ 0b1111, 0 }; - auto zLow = _loc.z; - auto zHigh = zLow + kPathClearance; - if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED) - { - quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope & kTileElementDirectionMask); - zHigh += kPathHeightStep; - } - - auto entranceElement = MapGetParkEntranceElementAt(_loc, 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 (IsSameAsEntranceElement(*entranceElement)) - entranceIsSamePath = true; - else - res.Cost -= 6.00_GBP; - } - - // Do not attempt to build a crossing with a queue or a sloped path. - auto isQueue = _constructFlags & PathConstructFlag::IsQueue; - auto crossingMode = isQueue || (_slope != kTileSlopeFlat) ? CreateCrossingMode::none : CreateCrossingMode::pathOverTrack; - auto canBuild = MapCanConstructWithClearAt( - { _loc, zLow, zHigh }, &MapPlaceNonSceneryClearFunc, quarterTile, GAME_COMMAND_FLAG_APPLY | GetFlags(), crossingMode); - if (!entrancePath && canBuild.Error != GameActions::Status::Ok) - { - canBuild.ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE; - return canBuild; - } - res.Cost += canBuild.Cost; - - const auto clearanceData = canBuild.GetData(); - gFootpathGroundFlags = clearanceData.GroundFlags; - - auto surfaceElement = MapGetSurfaceElementAt(_loc); - if (surfaceElement == nullptr) - { - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, - STR_ERR_SURFACE_ELEMENT_NOT_FOUND); - } - int32_t supportHeight = zLow - surfaceElement->GetBaseZ(); - res.Cost += supportHeight < 0 ? 20.00_GBP : (supportHeight / kPathHeightStep) * 5.00_GBP; - - if (entrancePath) - { - if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && !entranceIsSamePath) + if (!LocationValid(_loc) || MapIsEdge(_loc)) { + return Result(Status::InvalidParameters, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_OFF_EDGE_OF_MAP); + } + + if (!(gLegacyScene == LegacyScene::scenarioEditor || getGameState().cheats.sandboxMode) && !MapIsLocationOwned(_loc)) + { + return Result(Status::Disallowed, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_LAND_NOT_OWNED_BY_PARK); + } + + if (_loc.z < kFootpathMinHeight) + { + return Result(Status::Disallowed, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_TOO_LOW); + } + + if (_loc.z > kFootpathMaxHeight) + { + return Result(Status::Disallowed, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_TOO_HIGH); + } + + return ElementInsertQuery(std::move(res)); + } + + Result FootpathLayoutPlaceAction::Execute() const + { + auto res = Result(); + res.Cost = 0; + res.Expenditure = ExpenditureType::landscaping; + res.Position = _loc.ToTileCentre(); + + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST)) + { + FootpathInterruptPeeps(_loc); + } + + gFootpathGroundFlags = 0; + + // Force ride construction to recheck area + _currentTrackSelectionFlags.set(TrackSelectionFlag::recheck); + + return ElementInsertExecute(std::move(res)); + } + + Result FootpathLayoutPlaceAction::ElementInsertQuery(Result res) const + { + bool entrancePath = false, entranceIsSamePath = false; + + if (!MapCheckCapacityAndReorganise(_loc)) + { + return Result( + Status::NoFreeElements, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_TILE_ELEMENT_LIMIT_REACHED); + } + + res.Cost = 12.00_GBP; + + QuarterTile quarterTile{ 0b1111, 0 }; + auto zLow = _loc.z; + auto zHigh = zLow + kPathClearance; + if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED) + { + quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope & kTileElementDirectionMask); + zHigh += kPathHeightStep; + } + + auto entranceElement = MapGetParkEntranceElementAt(_loc, 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 (IsSameAsEntranceElement(*entranceElement)) + entranceIsSamePath = true; + else + res.Cost -= 6.00_GBP; + } + + // Do not attempt to build a crossing with a queue or a sloped path. + auto isQueue = _constructFlags & PathConstructFlag::IsQueue; + auto crossingMode = isQueue || (_slope != kTileSlopeFlat) ? CreateCrossingMode::none + : CreateCrossingMode::pathOverTrack; + auto canBuild = MapCanConstructWithClearAt( + { _loc, zLow, zHigh }, &MapPlaceNonSceneryClearFunc, quarterTile, GetFlags(), crossingMode); + if (!entrancePath && canBuild.Error != Status::Ok) + { + canBuild.ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE; + return canBuild; + } + res.Cost += canBuild.Cost; + + const auto clearanceData = canBuild.GetData(); + gFootpathGroundFlags = clearanceData.GroundFlags; + + if (!getGameState().cheats.disableClearanceChecks && (clearanceData.GroundFlags & ELEMENT_IS_UNDERWATER)) + { + return Result(Status::Disallowed, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_CANT_BUILD_THIS_UNDERWATER); + } + + auto surfaceElement = MapGetSurfaceElementAt(_loc); + if (surfaceElement == nullptr) + { + return Result( + Status::InvalidParameters, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_ERR_SURFACE_ELEMENT_NOT_FOUND); + } + int32_t supportHeight = zLow - surfaceElement->GetBaseZ(); + res.Cost += supportHeight < 0 ? 20.00_GBP : (supportHeight / kPathHeightStep) * 5.00_GBP; + + // Prevent the place sound from being spammed + if (entranceIsSamePath) + res.Cost = 0; + + return res; + } + + Result FootpathLayoutPlaceAction::ElementInsertExecute(Result res) const + { + bool entrancePath = false, entranceIsSamePath = false; + + if (!(GetFlags() & (GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_GHOST))) + { + FootpathRemoveLitter(_loc); + } + + res.Cost = 12.00_GBP; + + QuarterTile quarterTile{ 0b1111, 0 }; + auto zLow = _loc.z; + auto zHigh = zLow + kPathClearance; + if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED) + { + quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope & kTileElementDirectionMask); + zHigh += kPathHeightStep; + } + + auto entranceElement = MapGetParkEntranceElementAt(_loc, 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 (IsSameAsEntranceElement(*entranceElement)) + entranceIsSamePath = true; + else + res.Cost -= 6.00_GBP; + } + + // Do not attempt to build a crossing with a queue or a sloped path. + auto isQueue = _constructFlags & PathConstructFlag::IsQueue; + auto crossingMode = isQueue || (_slope != kTileSlopeFlat) ? CreateCrossingMode::none + : CreateCrossingMode::pathOverTrack; + auto canBuild = MapCanConstructWithClearAt( + { _loc, zLow, zHigh }, &MapPlaceNonSceneryClearFunc, quarterTile, GAME_COMMAND_FLAG_APPLY | GetFlags(), + crossingMode); + if (!entrancePath && canBuild.Error != Status::Ok) + { + canBuild.ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE; + return canBuild; + } + res.Cost += canBuild.Cost; + + const auto clearanceData = canBuild.GetData(); + gFootpathGroundFlags = clearanceData.GroundFlags; + + auto surfaceElement = MapGetSurfaceElementAt(_loc); + if (surfaceElement == nullptr) + { + return Result( + Status::InvalidParameters, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_ERR_SURFACE_ELEMENT_NOT_FOUND); + } + int32_t supportHeight = zLow - surfaceElement->GetBaseZ(); + res.Cost += supportHeight < 0 ? 20.00_GBP : (supportHeight / kPathHeightStep) * 5.00_GBP; + + if (entrancePath) + { + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && !entranceIsSamePath) + { + if (_constructFlags & PathConstructFlag::IsLegacyPathObject) + { + entranceElement->SetLegacyPathEntryIndex(_type); + } + else + { + entranceElement->SetSurfaceEntryIndex(_type); + } + MapInvalidateTileFull(_loc); + } + } + else + { + auto* pathElement = TileElementInsert(_loc, 0b1111); + Guard::Assert(pathElement != nullptr); + + pathElement->SetClearanceZ(zHigh); if (_constructFlags & PathConstructFlag::IsLegacyPathObject) { - entranceElement->SetLegacyPathEntryIndex(_type); + pathElement->SetLegacyPathEntryIndex(_type); } else { - entranceElement->SetSurfaceEntryIndex(_type); + pathElement->SetSurfaceEntryIndex(_type); + pathElement->SetRailingsEntryIndex(_railingsType); } + pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK); + pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED); + pathElement->SetIsQueue(isQueue); + pathElement->SetAddition(0); + pathElement->SetRideIndex(RideId::GetNull()); + pathElement->SetAdditionStatus(255); + pathElement->SetIsBroken(false); + pathElement->SetEdges(_edges); + pathElement->SetCorners(0); + pathElement->SetGhost(GetFlags() & GAME_COMMAND_FLAG_GHOST); + MapInvalidateTileFull(_loc); } - } - else - { - auto* pathElement = TileElementInsert(_loc, 0b1111); - Guard::Assert(pathElement != nullptr); - pathElement->SetClearanceZ(zHigh); + // Prevent the place sound from being spammed + if (entranceIsSamePath) + res.Cost = 0; + + return res; + } + + bool FootpathLayoutPlaceAction::IsSameAsEntranceElement(const EntranceElement& entranceElement) const + { + if (entranceElement.HasLegacyPathEntry()) + { + if (_constructFlags & PathConstructFlag::IsLegacyPathObject) + { + return entranceElement.GetLegacyPathEntryIndex() == _type; + } + + return false; + } + if (_constructFlags & PathConstructFlag::IsLegacyPathObject) { - pathElement->SetLegacyPathEntryIndex(_type); - } - else - { - pathElement->SetSurfaceEntryIndex(_type); - pathElement->SetRailingsEntryIndex(_railingsType); - } - pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK); - pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED); - pathElement->SetIsQueue(isQueue); - pathElement->SetAddition(0); - pathElement->SetRideIndex(RideId::GetNull()); - pathElement->SetAdditionStatus(255); - pathElement->SetIsBroken(false); - pathElement->SetEdges(_edges); - pathElement->SetCorners(0); - pathElement->SetGhost(GetFlags() & GAME_COMMAND_FLAG_GHOST); - - MapInvalidateTileFull(_loc); - } - - // Prevent the place sound from being spammed - if (entranceIsSamePath) - res.Cost = 0; - - return res; -} - -bool FootpathLayoutPlaceAction::IsSameAsEntranceElement(const EntranceElement& entranceElement) const -{ - if (entranceElement.HasLegacyPathEntry()) - { - if (_constructFlags & PathConstructFlag::IsLegacyPathObject) - { - return entranceElement.GetLegacyPathEntryIndex() == _type; + return false; } - return false; + return entranceElement.GetSurfaceEntryIndex() == _type; } - - if (_constructFlags & PathConstructFlag::IsLegacyPathObject) - { - return false; - } - - return entranceElement.GetSurfaceEntryIndex() == _type; -} +} // namespace OpenRCT2::GameActions diff --git a/src/openrct2/actions/FootpathLayoutPlaceAction.h b/src/openrct2/actions/FootpathLayoutPlaceAction.h index 4434007df0..576baf8465 100644 --- a/src/openrct2/actions/FootpathLayoutPlaceAction.h +++ b/src/openrct2/actions/FootpathLayoutPlaceAction.h @@ -12,32 +12,35 @@ #include "../world/Footpath.h" #include "GameAction.h" -class FootpathLayoutPlaceAction final : public GameActionBase +namespace OpenRCT2::GameActions { -private: - CoordsXYZ _loc; - uint8_t _slope{}; - OpenRCT2::ObjectEntryIndex _type{}; - OpenRCT2::ObjectEntryIndex _railingsType{}; - uint8_t _edges{}; - PathConstructFlags _constructFlags{}; + class FootpathLayoutPlaceAction final : public GameActionBase + { + private: + CoordsXYZ _loc; + uint8_t _slope{}; + ObjectEntryIndex _type{}; + ObjectEntryIndex _railingsType{}; + uint8_t _edges{}; + PathConstructFlags _constructFlags{}; -public: - FootpathLayoutPlaceAction() = default; - FootpathLayoutPlaceAction( - const CoordsXYZ& loc, uint8_t slope, OpenRCT2::ObjectEntryIndex type, OpenRCT2::ObjectEntryIndex railingsType, - uint8_t edges, PathConstructFlags constructFlags = 0); + public: + FootpathLayoutPlaceAction() = default; + FootpathLayoutPlaceAction( + const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, ObjectEntryIndex railingsType, uint8_t edges, + PathConstructFlags constructFlags = 0); - void AcceptParameters(GameActionParameterVisitor& visitor) override; + void AcceptParameters(GameActionParameterVisitor& visitor) override; - uint16_t GetActionFlags() const override; + uint16_t GetActionFlags() const override; - void Serialise(DataSerialiser& stream) override; - OpenRCT2::GameActions::Result Query() const override; - OpenRCT2::GameActions::Result Execute() const override; + void Serialise(DataSerialiser& stream) override; + Result Query() const override; + Result Execute() const override; -private: - OpenRCT2::GameActions::Result ElementInsertQuery(OpenRCT2::GameActions::Result res) const; - OpenRCT2::GameActions::Result ElementInsertExecute(OpenRCT2::GameActions::Result res) const; - bool IsSameAsEntranceElement(const OpenRCT2::EntranceElement& entranceElement) const; -}; + private: + Result ElementInsertQuery(Result res) const; + Result ElementInsertExecute(Result res) const; + bool IsSameAsEntranceElement(const EntranceElement& entranceElement) const; + }; +} // namespace OpenRCT2::GameActions diff --git a/src/openrct2/actions/FootpathPlaceAction.cpp b/src/openrct2/actions/FootpathPlaceAction.cpp index 5f19db237e..047e4376e6 100644 --- a/src/openrct2/actions/FootpathPlaceAction.cpp +++ b/src/openrct2/actions/FootpathPlaceAction.cpp @@ -35,399 +35,212 @@ #include -using namespace OpenRCT2; - -FootpathPlaceAction::FootpathPlaceAction( - const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, ObjectEntryIndex railingsType, Direction direction, - PathConstructFlags constructFlags) - : _loc(loc) - , _slope(slope) - , _type(type) - , _railingsType(railingsType) - , _direction(direction) - , _constructFlags(constructFlags) +namespace OpenRCT2::GameActions { -} - -void FootpathPlaceAction::AcceptParameters(GameActionParameterVisitor& visitor) -{ - visitor.Visit(_loc); - visitor.Visit("object", _type); - visitor.Visit("railingsObject", _railingsType); - visitor.Visit("direction", _direction); - visitor.Visit("slope", _slope); - visitor.Visit("constructFlags", _constructFlags); -} - -uint16_t FootpathPlaceAction::GetActionFlags() const -{ - return GameAction::GetActionFlags(); -} - -void FootpathPlaceAction::Serialise(DataSerialiser& stream) -{ - GameAction::Serialise(stream); - - stream << DS_TAG(_loc) << DS_TAG(_slope) << DS_TAG(_type) << DS_TAG(_railingsType) << DS_TAG(_direction) - << DS_TAG(_constructFlags); -} - -GameActions::Result FootpathPlaceAction::Query() const -{ - auto res = GameActions::Result(); - res.Cost = 0; - res.Expenditure = ExpenditureType::landscaping; - res.Position = _loc.ToTileCentre(); - - gFootpathGroundFlags = 0; - - if (!LocationValid(_loc) || MapIsEdge(_loc)) + FootpathPlaceAction::FootpathPlaceAction( + const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, ObjectEntryIndex railingsType, Direction direction, + PathConstructFlags constructFlags) + : _loc(loc) + , _slope(slope) + , _type(type) + , _railingsType(railingsType) + , _direction(direction) + , _constructFlags(constructFlags) { - return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_BUILD_FOOTPATH_HERE, STR_OFF_EDGE_OF_MAP); } - if (!(gLegacyScene == LegacyScene::scenarioEditor || getGameState().cheats.sandboxMode) && !MapIsLocationOwned(_loc)) + void FootpathPlaceAction::AcceptParameters(GameActionParameterVisitor& visitor) { - return GameActions::Result(GameActions::Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_LAND_NOT_OWNED_BY_PARK); + visitor.Visit(_loc); + visitor.Visit("object", _type); + visitor.Visit("railingsObject", _railingsType); + visitor.Visit("direction", _direction); + visitor.Visit("slope", _slope); + visitor.Visit("constructFlags", _constructFlags); } - if (_slope & SLOPE_IS_IRREGULAR_FLAG) + uint16_t FootpathPlaceAction::GetActionFlags() const { - return GameActions::Result(GameActions::Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_LAND_SLOPE_UNSUITABLE); + return GameAction::GetActionFlags(); } - if (_loc.z < kFootpathMinHeight) + void FootpathPlaceAction::Serialise(DataSerialiser& stream) { - return GameActions::Result(GameActions::Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_TOO_LOW); + GameAction::Serialise(stream); + + stream << DS_TAG(_loc) << DS_TAG(_slope) << DS_TAG(_type) << DS_TAG(_railingsType) << DS_TAG(_direction) + << DS_TAG(_constructFlags); } - if (_loc.z > kFootpathMaxHeight) + Result FootpathPlaceAction::Query() const { - return GameActions::Result(GameActions::Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_TOO_HIGH); - } + auto res = Result(); + res.Cost = 0; + res.Expenditure = ExpenditureType::landscaping; + res.Position = _loc.ToTileCentre(); - if (_direction != kInvalidDirection && !DirectionValid(_direction)) - { - LOG_ERROR("Direction invalid. direction = %u", _direction); - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_CANT_BUILD_FOOTPATH_HERE, STR_ERR_VALUE_OUT_OF_RANGE); - } + gFootpathGroundFlags = 0; - auto intent = Intent(INTENT_ACTION_REMOVE_PROVISIONAL_FOOTPATH); - ContextBroadcastIntent(&intent); - - auto tileElement = MapGetFootpathElementSlope(_loc, _slope); - if (tileElement == nullptr) - { - return ElementInsertQuery(std::move(res)); - } - return ElementUpdateQuery(tileElement, std::move(res)); -} - -GameActions::Result FootpathPlaceAction::Execute() const -{ - auto res = GameActions::Result(); - res.Cost = 0; - res.Expenditure = ExpenditureType::landscaping; - res.Position = _loc.ToTileCentre(); - - if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST)) - { - FootpathInterruptPeeps(_loc); - } - - gFootpathGroundFlags = 0; - - // Force ride construction to recheck area - _currentTrackSelectionFlags.set(TrackSelectionFlag::recheck); - - if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST)) - { - if (_direction != kInvalidDirection && !getGameState().cheats.disableClearanceChecks) + if (!LocationValid(_loc) || MapIsEdge(_loc)) { - // It is possible, let's remove walls between the old and new piece of path - auto zLow = _loc.z; - auto zHigh = zLow + kPathClearance; - WallRemoveIntersectingWalls( - { _loc, zLow, zHigh + ((_slope & kTileSlopeRaisedCornersMask) ? 16 : 0) }, DirectionReverse(_direction)); - WallRemoveIntersectingWalls( - { _loc.x - CoordsDirectionDelta[_direction].x, _loc.y - CoordsDirectionDelta[_direction].y, zLow, zHigh }, - _direction); + return Result(Status::InvalidParameters, STR_CANT_BUILD_FOOTPATH_HERE, STR_OFF_EDGE_OF_MAP); } + + if (!(gLegacyScene == LegacyScene::scenarioEditor || getGameState().cheats.sandboxMode) && !MapIsLocationOwned(_loc)) + { + return Result(Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_LAND_NOT_OWNED_BY_PARK); + } + + if (_slope & SLOPE_IS_IRREGULAR_FLAG) + { + return Result(Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_LAND_SLOPE_UNSUITABLE); + } + + if (_loc.z < kFootpathMinHeight) + { + return Result(Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_TOO_LOW); + } + + if (_loc.z > kFootpathMaxHeight) + { + return Result(Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_TOO_HIGH); + } + + if (_direction != kInvalidDirection && !DirectionValid(_direction)) + { + LOG_ERROR("Direction invalid. direction = %u", _direction); + return Result(Status::InvalidParameters, STR_CANT_BUILD_FOOTPATH_HERE, STR_ERR_VALUE_OUT_OF_RANGE); + } + + auto intent = Intent(INTENT_ACTION_REMOVE_PROVISIONAL_FOOTPATH); + ContextBroadcastIntent(&intent); + + auto tileElement = MapGetFootpathElementSlope(_loc, _slope); + if (tileElement == nullptr) + { + return ElementInsertQuery(std::move(res)); + } + return ElementUpdateQuery(tileElement, std::move(res)); } - auto tileElement = MapGetFootpathElementSlope(_loc, _slope); - if (tileElement == nullptr) + Result FootpathPlaceAction::Execute() const { - return ElementInsertExecute(std::move(res)); - } - return ElementUpdateExecute(tileElement, std::move(res)); -} + auto res = Result(); + res.Cost = 0; + res.Expenditure = ExpenditureType::landscaping; + res.Position = _loc.ToTileCentre(); + + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST)) + { + FootpathInterruptPeeps(_loc); + } + + gFootpathGroundFlags = 0; + + // Force ride construction to recheck area + _currentTrackSelectionFlags.set(TrackSelectionFlag::recheck); + + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST)) + { + if (_direction != kInvalidDirection && !getGameState().cheats.disableClearanceChecks) + { + // It is possible, let's remove walls between the old and new piece of path + auto zLow = _loc.z; + auto zHigh = zLow + kPathClearance; + WallRemoveIntersectingWalls( + { _loc, zLow, zHigh + ((_slope & kTileSlopeRaisedCornersMask) ? 16 : 0) }, DirectionReverse(_direction)); + WallRemoveIntersectingWalls( + { _loc.x - CoordsDirectionDelta[_direction].x, _loc.y - CoordsDirectionDelta[_direction].y, zLow, zHigh }, + _direction); + } + } + + auto tileElement = MapGetFootpathElementSlope(_loc, _slope); + if (tileElement == nullptr) + { + return ElementInsertExecute(std::move(res)); + } + return ElementUpdateExecute(tileElement, std::move(res)); + } + + bool FootpathPlaceAction::IsSameAsPathElement(const PathElement* pathElement) const + { + // Check if both this action and the element is queue + if (pathElement->IsQueue() != ((_constructFlags & PathConstructFlag::IsQueue) != 0)) + return false; + + auto footpathObj = pathElement->GetLegacyPathEntry(); + if (footpathObj == nullptr) + { + if (_constructFlags & PathConstructFlag::IsLegacyPathObject) + { + return false; + } + + return pathElement->GetSurfaceEntryIndex() == _type && pathElement->GetRailingsEntryIndex() == _railingsType; + } + + if (_constructFlags & PathConstructFlag::IsLegacyPathObject) + { + return pathElement->GetLegacyPathEntryIndex() == _type; + } -bool FootpathPlaceAction::IsSameAsPathElement(const PathElement* pathElement) const -{ - // Check if both this action and the element is queue - if (pathElement->IsQueue() != ((_constructFlags & PathConstructFlag::IsQueue) != 0)) return false; + } - auto footpathObj = pathElement->GetLegacyPathEntry(); - if (footpathObj == nullptr) + bool FootpathPlaceAction::IsSameAsEntranceElement(const EntranceElement& entranceElement) const { + if (entranceElement.HasLegacyPathEntry()) + { + if (_constructFlags & PathConstructFlag::IsLegacyPathObject) + { + return entranceElement.GetLegacyPathEntryIndex() == _type; + } + + return false; + } + if (_constructFlags & PathConstructFlag::IsLegacyPathObject) { return false; } - return pathElement->GetSurfaceEntryIndex() == _type && pathElement->GetRailingsEntryIndex() == _railingsType; + return entranceElement.GetSurfaceEntryIndex() == _type; } - if (_constructFlags & PathConstructFlag::IsLegacyPathObject) + Result FootpathPlaceAction::ElementUpdateQuery(PathElement* pathElement, Result res) const { - return pathElement->GetLegacyPathEntryIndex() == _type; - } - - return false; -} - -bool FootpathPlaceAction::IsSameAsEntranceElement(const EntranceElement& entranceElement) const -{ - if (entranceElement.HasLegacyPathEntry()) - { - if (_constructFlags & PathConstructFlag::IsLegacyPathObject) + if (_constructFlags & PathConstructFlag::IsQueue && pathElement->IsLevelCrossing(_loc)) { - return entranceElement.GetLegacyPathEntryIndex() == _type; + return Result(Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_QUEUE_PATHS_CANNOT_BE_USED_FOR_LEVEL_CROSSINGS); } - return false; - } - - if (_constructFlags & PathConstructFlag::IsLegacyPathObject) - { - return false; - } - - return entranceElement.GetSurfaceEntryIndex() == _type; -} - -GameActions::Result FootpathPlaceAction::ElementUpdateQuery(PathElement* pathElement, GameActions::Result res) const -{ - if (_constructFlags & PathConstructFlag::IsQueue && pathElement->IsLevelCrossing(_loc)) - { - return GameActions::Result( - GameActions::Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_QUEUE_PATHS_CANNOT_BE_USED_FOR_LEVEL_CROSSINGS); - } - - if (!IsSameAsPathElement(pathElement)) - { - res.Cost += 6.00_GBP; - } - - if (GetFlags() & GAME_COMMAND_FLAG_GHOST && !pathElement->IsGhost()) - { - return GameActions::Result(GameActions::Status::Unknown, STR_CANT_BUILD_FOOTPATH_HERE, kStringIdNone); - } - return res; -} - -GameActions::Result FootpathPlaceAction::ElementUpdateExecute(PathElement* pathElement, GameActions::Result res) const -{ - if (!IsSameAsPathElement(pathElement)) - { - res.Cost += 6.00_GBP; - } - - FootpathQueueChainReset(); - - if (!(GetFlags() & GAME_COMMAND_FLAG_TRACK_DESIGN)) - { - FootpathRemoveEdgesAt(_loc, reinterpret_cast(pathElement)); - } - - if (_constructFlags & PathConstructFlag::IsLegacyPathObject) - { - pathElement->SetLegacyPathEntryIndex(_type); - } - else - { - pathElement->SetSurfaceEntryIndex(_type); - pathElement->SetRailingsEntryIndex(_railingsType); - } - - pathElement->SetIsQueue((_constructFlags & PathConstructFlag::IsQueue) != 0); - - auto* elem = pathElement->GetAdditionEntry(); - if (elem != nullptr) - { - if (_constructFlags & PathConstructFlag::IsQueue) + if (!IsSameAsPathElement(pathElement)) { - // remove any addition that isn't a TV or a lamp - if ((elem->flags & PATH_ADDITION_FLAG_IS_QUEUE_SCREEN) == 0 && (elem->flags & PATH_ADDITION_FLAG_LAMP) == 0) - { - pathElement->SetIsBroken(false); - pathElement->SetAddition(0); - } + res.Cost += 6.00_GBP; } - else + + if (GetFlags() & GAME_COMMAND_FLAG_GHOST && !pathElement->IsGhost()) { - // remove all TVs - if ((elem->flags & PATH_ADDITION_FLAG_IS_QUEUE_SCREEN) != 0) - { - pathElement->SetIsBroken(false); - pathElement->SetAddition(0); - } + return Result(Status::Unknown, STR_CANT_BUILD_FOOTPATH_HERE, kStringIdNone); } + return res; } - RemoveIntersectingWalls(pathElement); - return res; -} - -GameActions::Result FootpathPlaceAction::ElementInsertQuery(GameActions::Result res) const -{ - bool entrancePath = false, entranceIsSamePath = false; - - if (!MapCheckCapacityAndReorganise(_loc)) + Result FootpathPlaceAction::ElementUpdateExecute(PathElement* pathElement, Result res) const { - return GameActions::Result(GameActions::Status::NoFreeElements, STR_CANT_BUILD_FOOTPATH_HERE, kStringIdNone); - } - - res.Cost = 12.00_GBP; - - QuarterTile quarterTile{ 0b1111, 0 }; - auto zLow = _loc.z; - auto zHigh = zLow + kPathClearance; - if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED) - { - quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope & kTileElementDirectionMask); - zHigh += kPathHeightStep; - } - - auto entranceElement = MapGetParkEntranceElementAt(_loc, 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 (IsSameAsEntranceElement(*entranceElement)) - entranceIsSamePath = true; - else - res.Cost -= 6.00_GBP; - } - - // Do not attempt to build a crossing with a queue or a sloped path. - auto isQueue = _constructFlags & PathConstructFlag::IsQueue; - auto crossingMode = isQueue || (_slope != kTileSlopeFlat) ? CreateCrossingMode::none : CreateCrossingMode::pathOverTrack; - auto canBuild = MapCanConstructWithClearAt( - { _loc, zLow, zHigh }, &MapPlaceNonSceneryClearFunc, quarterTile, GetFlags(), crossingMode); - if (!entrancePath && canBuild.Error != GameActions::Status::Ok) - { - canBuild.ErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE; - return canBuild; - } - res.Cost += canBuild.Cost; - - const auto clearanceData = canBuild.GetData(); - - gFootpathGroundFlags = clearanceData.GroundFlags; - if (!getGameState().cheats.disableClearanceChecks && (clearanceData.GroundFlags & ELEMENT_IS_UNDERWATER)) - { - return GameActions::Result( - GameActions::Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_CANT_BUILD_THIS_UNDERWATER); - } - - auto surfaceElement = MapGetSurfaceElementAt(_loc); - if (surfaceElement == nullptr) - { - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_CANT_BUILD_FOOTPATH_HERE, STR_ERR_SURFACE_ELEMENT_NOT_FOUND); - } - int32_t supportHeight = zLow - surfaceElement->GetBaseZ(); - res.Cost += supportHeight < 0 ? 20.00_GBP : (supportHeight / kPathHeightStep) * 5.00_GBP; - - // Prevent the place sound from being spammed - if (entranceIsSamePath) - res.Cost = 0; - - return res; -} - -GameActions::Result FootpathPlaceAction::ElementInsertExecute(GameActions::Result res) const -{ - bool entrancePath = false, entranceIsSamePath = false; - - if (!(GetFlags() & (GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_GHOST))) - { - FootpathRemoveLitter(_loc); - } - - res.Cost = 12.00_GBP; - - QuarterTile quarterTile{ 0b1111, 0 }; - auto zLow = _loc.z; - auto zHigh = zLow + kPathClearance; - if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED) - { - quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope & kTileElementDirectionMask); - zHigh += kPathHeightStep; - } - - auto entranceElement = MapGetParkEntranceElementAt(_loc, 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 (IsSameAsEntranceElement(*entranceElement)) - entranceIsSamePath = true; - else - res.Cost -= 6.00_GBP; - } - - // Do not attempt to build a crossing with a queue or a sloped. - auto isQueue = _constructFlags & PathConstructFlag::IsQueue; - auto crossingMode = isQueue || (_slope != kTileSlopeFlat) ? CreateCrossingMode::none : CreateCrossingMode::pathOverTrack; - auto canBuild = MapCanConstructWithClearAt( - { _loc, zLow, zHigh }, &MapPlaceNonSceneryClearFunc, quarterTile, GAME_COMMAND_FLAG_APPLY | GetFlags(), crossingMode); - if (!entrancePath && canBuild.Error != GameActions::Status::Ok) - { - canBuild.ErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE; - return canBuild; - } - res.Cost += canBuild.Cost; - - const auto clearanceData = canBuild.GetData(); - gFootpathGroundFlags = clearanceData.GroundFlags; - - auto surfaceElement = MapGetSurfaceElementAt(_loc); - if (surfaceElement == nullptr) - { - return GameActions::Result( - GameActions::Status::InvalidParameters, STR_CANT_BUILD_FOOTPATH_HERE, STR_ERR_SURFACE_ELEMENT_NOT_FOUND); - } - int32_t supportHeight = zLow - surfaceElement->GetBaseZ(); - res.Cost += supportHeight < 0 ? 20.00_GBP : (supportHeight / kPathHeightStep) * 5.00_GBP; - - if (entrancePath) - { - if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && !entranceIsSamePath) + if (!IsSameAsPathElement(pathElement)) { - if (_constructFlags & PathConstructFlag::IsLegacyPathObject) - { - entranceElement->SetLegacyPathEntryIndex(_type); - } - else - { - entranceElement->SetSurfaceEntryIndex(_type); - } - MapInvalidateTileFull(_loc); + res.Cost += 6.00_GBP; + } + + FootpathQueueChainReset(); + + if (!(GetFlags() & GAME_COMMAND_FLAG_TRACK_DESIGN)) + { + FootpathRemoveEdgesAt(_loc, reinterpret_cast(pathElement)); } - } - else - { - auto* pathElement = TileElementInsert(_loc, 0b1111); - Guard::Assert(pathElement != nullptr); - pathElement->SetClearanceZ(zHigh); if (_constructFlags & PathConstructFlag::IsLegacyPathObject) { pathElement->SetLegacyPathEntryIndex(_type); @@ -437,110 +250,296 @@ GameActions::Result FootpathPlaceAction::ElementInsertExecute(GameActions::Resul pathElement->SetSurfaceEntryIndex(_type); pathElement->SetRailingsEntryIndex(_railingsType); } - pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK); - pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED); - pathElement->SetIsQueue(isQueue); - pathElement->SetAddition(0); - pathElement->SetRideIndex(RideId::GetNull()); - pathElement->SetAdditionStatus(255); - pathElement->SetIsBroken(false); - pathElement->SetGhost(GetFlags() & GAME_COMMAND_FLAG_GHOST); - FootpathQueueChainReset(); + pathElement->SetIsQueue((_constructFlags & PathConstructFlag::IsQueue) != 0); - if (!(GetFlags() & GAME_COMMAND_FLAG_TRACK_DESIGN)) + auto* elem = pathElement->GetAdditionEntry(); + if (elem != nullptr) { - FootpathRemoveEdgesAt(_loc, pathElement->as()); - } - if (gLegacyScene == LegacyScene::scenarioEditor && !(GetFlags() & GAME_COMMAND_FLAG_GHOST)) - { - AutomaticallySetPeepSpawn(); + if (_constructFlags & PathConstructFlag::IsQueue) + { + // remove any addition that isn't a TV or a lamp + if ((elem->flags & PATH_ADDITION_FLAG_IS_QUEUE_SCREEN) == 0 && (elem->flags & PATH_ADDITION_FLAG_LAMP) == 0) + { + pathElement->SetIsBroken(false); + pathElement->SetAddition(0); + } + } + else + { + // remove all TVs + if ((elem->flags & PATH_ADDITION_FLAG_IS_QUEUE_SCREEN) != 0) + { + pathElement->SetIsBroken(false); + pathElement->SetAddition(0); + } + } } RemoveIntersectingWalls(pathElement); + return res; } - // Prevent the place sound from being spammed - if (entranceIsSamePath) - res.Cost = 0; - - return res; -} - -/** - * - * rct2: 0x006A65AD - */ -void FootpathPlaceAction::AutomaticallySetPeepSpawn() const -{ - auto mapSizeUnits = GetMapSizeUnits(); - uint8_t direction = 0; - if (_loc.x != kCoordsXYStep) + Result FootpathPlaceAction::ElementInsertQuery(Result res) const { - direction++; - if (_loc.y != mapSizeUnits.y - kCoordsXYStep) + bool entrancePath = false, entranceIsSamePath = false; + + if (!MapCheckCapacityAndReorganise(_loc)) { - direction++; - if (_loc.x != mapSizeUnits.x - kCoordsXYStep) + return Result(Status::NoFreeElements, STR_CANT_BUILD_FOOTPATH_HERE, kStringIdNone); + } + + res.Cost = 12.00_GBP; + + QuarterTile quarterTile{ 0b1111, 0 }; + auto zLow = _loc.z; + auto zHigh = zLow + kPathClearance; + if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED) + { + quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope & kTileElementDirectionMask); + zHigh += kPathHeightStep; + } + + auto entranceElement = MapGetParkEntranceElementAt(_loc, 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 (IsSameAsEntranceElement(*entranceElement)) + entranceIsSamePath = true; + else + res.Cost -= 6.00_GBP; + } + + // Do not attempt to build a crossing with a queue or a sloped path. + auto isQueue = _constructFlags & PathConstructFlag::IsQueue; + auto crossingMode = isQueue || (_slope != kTileSlopeFlat) ? CreateCrossingMode::none + : CreateCrossingMode::pathOverTrack; + auto canBuild = MapCanConstructWithClearAt( + { _loc, zLow, zHigh }, &MapPlaceNonSceneryClearFunc, quarterTile, GetFlags(), crossingMode); + if (!entrancePath && canBuild.Error != Status::Ok) + { + canBuild.ErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE; + return canBuild; + } + res.Cost += canBuild.Cost; + + const auto clearanceData = canBuild.GetData(); + + gFootpathGroundFlags = clearanceData.GroundFlags; + if (!getGameState().cheats.disableClearanceChecks && (clearanceData.GroundFlags & ELEMENT_IS_UNDERWATER)) + { + return Result(Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_CANT_BUILD_THIS_UNDERWATER); + } + + auto surfaceElement = MapGetSurfaceElementAt(_loc); + if (surfaceElement == nullptr) + { + return Result(Status::InvalidParameters, STR_CANT_BUILD_FOOTPATH_HERE, STR_ERR_SURFACE_ELEMENT_NOT_FOUND); + } + int32_t supportHeight = zLow - surfaceElement->GetBaseZ(); + res.Cost += supportHeight < 0 ? 20.00_GBP : (supportHeight / kPathHeightStep) * 5.00_GBP; + + // Prevent the place sound from being spammed + if (entranceIsSamePath) + res.Cost = 0; + + return res; + } + + Result FootpathPlaceAction::ElementInsertExecute(Result res) const + { + bool entrancePath = false, entranceIsSamePath = false; + + if (!(GetFlags() & (GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_GHOST))) + { + FootpathRemoveLitter(_loc); + } + + res.Cost = 12.00_GBP; + + QuarterTile quarterTile{ 0b1111, 0 }; + auto zLow = _loc.z; + auto zHigh = zLow + kPathClearance; + if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED) + { + quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope & kTileElementDirectionMask); + zHigh += kPathHeightStep; + } + + auto entranceElement = MapGetParkEntranceElementAt(_loc, 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 (IsSameAsEntranceElement(*entranceElement)) + entranceIsSamePath = true; + else + res.Cost -= 6.00_GBP; + } + + // Do not attempt to build a crossing with a queue or a sloped. + auto isQueue = _constructFlags & PathConstructFlag::IsQueue; + auto crossingMode = isQueue || (_slope != kTileSlopeFlat) ? CreateCrossingMode::none + : CreateCrossingMode::pathOverTrack; + auto canBuild = MapCanConstructWithClearAt( + { _loc, zLow, zHigh }, &MapPlaceNonSceneryClearFunc, quarterTile, GAME_COMMAND_FLAG_APPLY | GetFlags(), + crossingMode); + if (!entrancePath && canBuild.Error != Status::Ok) + { + canBuild.ErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE; + return canBuild; + } + res.Cost += canBuild.Cost; + + const auto clearanceData = canBuild.GetData(); + gFootpathGroundFlags = clearanceData.GroundFlags; + + auto surfaceElement = MapGetSurfaceElementAt(_loc); + if (surfaceElement == nullptr) + { + return Result(Status::InvalidParameters, STR_CANT_BUILD_FOOTPATH_HERE, STR_ERR_SURFACE_ELEMENT_NOT_FOUND); + } + int32_t supportHeight = zLow - surfaceElement->GetBaseZ(); + res.Cost += supportHeight < 0 ? 20.00_GBP : (supportHeight / kPathHeightStep) * 5.00_GBP; + + if (entrancePath) + { + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && !entranceIsSamePath) { - direction++; - if (_loc.y != kCoordsXYStep) - return; + if (_constructFlags & PathConstructFlag::IsLegacyPathObject) + { + entranceElement->SetLegacyPathEntryIndex(_type); + } + else + { + entranceElement->SetSurfaceEntryIndex(_type); + } + MapInvalidateTileFull(_loc); } } - } - - auto& gameState = getGameState(); - if (gameState.peepSpawns.empty()) - { - gameState.peepSpawns.emplace_back(); - } - PeepSpawn* peepSpawn = &gameState.peepSpawns[0]; - peepSpawn->x = _loc.x + (DirectionOffsets[direction].x * 15) + 16; - peepSpawn->y = _loc.y + (DirectionOffsets[direction].y * 15) + 16; - peepSpawn->direction = direction; - peepSpawn->z = _loc.z; -} - -void FootpathPlaceAction::RemoveIntersectingWalls(PathElement* pathElement) const -{ - if (pathElement->IsSloped() && !(GetFlags() & GAME_COMMAND_FLAG_GHOST)) - { - auto direction = pathElement->GetSlopeDirection(); - int32_t z = pathElement->GetBaseZ(); - WallRemoveIntersectingWalls({ _loc, z, z + (6 * kCoordsZStep) }, DirectionReverse(direction)); - WallRemoveIntersectingWalls({ _loc, z, z + (6 * kCoordsZStep) }, direction); - // Removing walls may have made the pointer invalid, so find it again - pathElement = MapGetFootpathElement(CoordsXYZ(_loc, z)); - if (pathElement == nullptr) + else { - LOG_ERROR("Something went wrong. Could not refind footpath."); - return; + auto* pathElement = TileElementInsert(_loc, 0b1111); + Guard::Assert(pathElement != nullptr); + + pathElement->SetClearanceZ(zHigh); + if (_constructFlags & PathConstructFlag::IsLegacyPathObject) + { + pathElement->SetLegacyPathEntryIndex(_type); + } + else + { + pathElement->SetSurfaceEntryIndex(_type); + pathElement->SetRailingsEntryIndex(_railingsType); + } + pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK); + pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED); + pathElement->SetIsQueue(isQueue); + pathElement->SetAddition(0); + pathElement->SetRideIndex(RideId::GetNull()); + pathElement->SetAdditionStatus(255); + pathElement->SetIsBroken(false); + pathElement->SetGhost(GetFlags() & GAME_COMMAND_FLAG_GHOST); + + FootpathQueueChainReset(); + + if (!(GetFlags() & GAME_COMMAND_FLAG_TRACK_DESIGN)) + { + FootpathRemoveEdgesAt(_loc, pathElement->as()); + } + if (gLegacyScene == LegacyScene::scenarioEditor && !(GetFlags() & GAME_COMMAND_FLAG_GHOST)) + { + AutomaticallySetPeepSpawn(); + } + + RemoveIntersectingWalls(pathElement); } + + // Prevent the place sound from being spammed + if (entranceIsSamePath) + res.Cost = 0; + + return res; } - if (!(GetFlags() & GAME_COMMAND_FLAG_TRACK_DESIGN)) - FootpathConnectEdges(_loc, reinterpret_cast(pathElement), GetFlags()); - - FootpathUpdateQueueChains(); - MapInvalidateTileFull(_loc); -} - -PathElement* FootpathPlaceAction::MapGetFootpathElementSlope(const CoordsXYZ& footpathPos, int32_t slope) const -{ - const bool isSloped = slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED; - const auto slopeDirection = slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK; - - for (auto* pathElement : TileElementsView(footpathPos)) + /** + * + * rct2: 0x006A65AD + */ + void FootpathPlaceAction::AutomaticallySetPeepSpawn() const { - if (pathElement->GetBaseZ() != footpathPos.z) - continue; - if (pathElement->IsSloped() != isSloped) - continue; - if (pathElement->GetSlopeDirection() != slopeDirection) - continue; - return pathElement; + auto mapSizeUnits = GetMapSizeUnits(); + uint8_t direction = 0; + if (_loc.x != kCoordsXYStep) + { + direction++; + if (_loc.y != mapSizeUnits.y - kCoordsXYStep) + { + direction++; + if (_loc.x != mapSizeUnits.x - kCoordsXYStep) + { + direction++; + if (_loc.y != kCoordsXYStep) + return; + } + } + } + + auto& gameState = getGameState(); + if (gameState.peepSpawns.empty()) + { + gameState.peepSpawns.emplace_back(); + } + PeepSpawn* peepSpawn = &gameState.peepSpawns[0]; + peepSpawn->x = _loc.x + (DirectionOffsets[direction].x * 15) + 16; + peepSpawn->y = _loc.y + (DirectionOffsets[direction].y * 15) + 16; + peepSpawn->direction = direction; + peepSpawn->z = _loc.z; } - return nullptr; -} + void FootpathPlaceAction::RemoveIntersectingWalls(PathElement* pathElement) const + { + if (pathElement->IsSloped() && !(GetFlags() & GAME_COMMAND_FLAG_GHOST)) + { + auto direction = pathElement->GetSlopeDirection(); + int32_t z = pathElement->GetBaseZ(); + WallRemoveIntersectingWalls({ _loc, z, z + (6 * kCoordsZStep) }, DirectionReverse(direction)); + WallRemoveIntersectingWalls({ _loc, z, z + (6 * kCoordsZStep) }, direction); + // Removing walls may have made the pointer invalid, so find it again + pathElement = MapGetFootpathElement(CoordsXYZ(_loc, z)); + if (pathElement == nullptr) + { + LOG_ERROR("Something went wrong. Could not refind footpath."); + return; + } + } + + if (!(GetFlags() & GAME_COMMAND_FLAG_TRACK_DESIGN)) + FootpathConnectEdges(_loc, reinterpret_cast(pathElement), GetFlags()); + + FootpathUpdateQueueChains(); + MapInvalidateTileFull(_loc); + } + + PathElement* FootpathPlaceAction::MapGetFootpathElementSlope(const CoordsXYZ& footpathPos, int32_t slope) const + { + const bool isSloped = slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED; + const auto slopeDirection = slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK; + + for (auto* pathElement : TileElementsView(footpathPos)) + { + if (pathElement->GetBaseZ() != footpathPos.z) + continue; + if (pathElement->IsSloped() != isSloped) + continue; + if (pathElement->GetSlopeDirection() != slopeDirection) + continue; + return pathElement; + } + + return nullptr; + } +} // namespace OpenRCT2::GameActions diff --git a/src/openrct2/actions/FootpathPlaceAction.h b/src/openrct2/actions/FootpathPlaceAction.h index dcd3fb2bd5..d4b6abe423 100644 --- a/src/openrct2/actions/FootpathPlaceAction.h +++ b/src/openrct2/actions/FootpathPlaceAction.h @@ -12,39 +12,40 @@ #include "../world/Footpath.h" #include "GameAction.h" -class FootpathPlaceAction final : public GameActionBase +namespace OpenRCT2::GameActions { -private: - CoordsXYZ _loc; - uint8_t _slope{}; - OpenRCT2::ObjectEntryIndex _type{}; - OpenRCT2::ObjectEntryIndex _railingsType{}; - Direction _direction{ kInvalidDirection }; - PathConstructFlags _constructFlags{}; + class FootpathPlaceAction final : public GameActionBase + { + private: + CoordsXYZ _loc; + uint8_t _slope{}; + ObjectEntryIndex _type{}; + ObjectEntryIndex _railingsType{}; + Direction _direction{ kInvalidDirection }; + PathConstructFlags _constructFlags{}; -public: - FootpathPlaceAction() = default; - FootpathPlaceAction( - const CoordsXYZ& loc, uint8_t slope, OpenRCT2::ObjectEntryIndex type, OpenRCT2::ObjectEntryIndex railingsType, - Direction direction = kInvalidDirection, PathConstructFlags constructFlags = 0); - void AcceptParameters(GameActionParameterVisitor& visitor) override; + public: + FootpathPlaceAction() = default; + FootpathPlaceAction( + const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, ObjectEntryIndex railingsType, + Direction direction = kInvalidDirection, PathConstructFlags constructFlags = 0); + void AcceptParameters(GameActionParameterVisitor& visitor) override; - uint16_t GetActionFlags() const override; + uint16_t GetActionFlags() const override; - void Serialise(DataSerialiser& stream) override; - OpenRCT2::GameActions::Result Query() const override; - OpenRCT2::GameActions::Result Execute() const override; + void Serialise(DataSerialiser& stream) override; + Result Query() const override; + Result Execute() const override; -private: - OpenRCT2::GameActions::Result ElementUpdateQuery( - OpenRCT2::PathElement* pathElement, OpenRCT2::GameActions::Result res) const; - OpenRCT2::GameActions::Result ElementUpdateExecute( - OpenRCT2::PathElement* pathElement, OpenRCT2::GameActions::Result res) const; - OpenRCT2::GameActions::Result ElementInsertQuery(OpenRCT2::GameActions::Result res) const; - OpenRCT2::GameActions::Result ElementInsertExecute(OpenRCT2::GameActions::Result res) const; - void AutomaticallySetPeepSpawn() const; - void RemoveIntersectingWalls(OpenRCT2::PathElement* pathElement) const; - OpenRCT2::PathElement* MapGetFootpathElementSlope(const CoordsXYZ& footpathPos, int32_t slope) const; - bool IsSameAsPathElement(const OpenRCT2::PathElement* pathElement) const; - bool IsSameAsEntranceElement(const OpenRCT2::EntranceElement& entranceElement) const; -}; + private: + Result ElementUpdateQuery(PathElement* pathElement, Result res) const; + Result ElementUpdateExecute(PathElement* pathElement, Result res) const; + Result ElementInsertQuery(Result res) const; + Result ElementInsertExecute(Result res) const; + void AutomaticallySetPeepSpawn() const; + void RemoveIntersectingWalls(PathElement* pathElement) const; + PathElement* MapGetFootpathElementSlope(const CoordsXYZ& footpathPos, int32_t slope) const; + bool IsSameAsPathElement(const PathElement* pathElement) const; + bool IsSameAsEntranceElement(const EntranceElement& entranceElement) const; + }; +} // namespace OpenRCT2::GameActions diff --git a/src/openrct2/rct12/ScenarioPatcher.cpp b/src/openrct2/rct12/ScenarioPatcher.cpp index ad5db38144..a4eaa1603b 100644 --- a/src/openrct2/rct12/ScenarioPatcher.cpp +++ b/src/openrct2/rct12/ScenarioPatcher.cpp @@ -656,7 +656,7 @@ static void ApplyPathFixes(const json_t& scenarioPatch) for (auto coordinate : coordinates) { auto slope = direction != kInvalidDirection ? direction + 4 : 0; - auto footpathPlaceAction = FootpathPlaceAction( + auto footpathPlaceAction = GameActions::FootpathPlaceAction( coordinate.ToCoordsXYZ(), slope, surfaceObjIndex, railingsObjIndex, direction, constructionFlags); auto result = footpathPlaceAction.Execute(); if (result.Error != GameActions::Status::Ok) diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index bada10e428..d0e2abf33c 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -1199,7 +1199,7 @@ static GameActions::Result TrackDesignPlaceSceneryElement( constructFlags |= PathConstructFlag::IsQueue; if (entryInfo->Type == ObjectType::paths) constructFlags |= PathConstructFlag::IsLegacyPathObject; - auto footpathPlaceAction = FootpathLayoutPlaceAction( + auto footpathPlaceAction = GameActions::FootpathLayoutPlaceAction( { mapCoord.x, mapCoord.y, z }, slope, entryInfo->Index, entryInfo->SecondaryIndex, edges, constructFlags); footpathPlaceAction.SetFlags(flags); auto res = flags & GAME_COMMAND_FLAG_APPLY ? GameActions::ExecuteNested(&footpathPlaceAction) diff --git a/src/openrct2/scripting/ScriptEngine.cpp b/src/openrct2/scripting/ScriptEngine.cpp index ced148ede9..353f720adf 100644 --- a/src/openrct2/scripting/ScriptEngine.cpp +++ b/src/openrct2/scripting/ScriptEngine.cpp @@ -1072,7 +1072,7 @@ void ScriptEngine::RemoveNetworkPlugins() } } -GameActions::Result ScriptEngine::QueryOrExecuteCustomGameAction(const CustomAction& customAction, bool isExecute) +GameActions::Result ScriptEngine::QueryOrExecuteCustomGameAction(const GameActions::CustomAction& customAction, bool isExecute) { std::string actionz = customAction.GetId(); auto kvp = _customActions.find(actionz); @@ -1473,7 +1473,7 @@ void ScriptEngine::RunGameActionHooks(const GameAction& action, GameActions::Res auto actionId = action.GetType(); if (action.GetType() == GameCommand::Custom) { - auto customAction = static_cast(action); + auto customAction = static_cast(action); obj.Set("action", customAction.GetId()); auto dukArgs = DuktapeTryParseJson(_context, customAction.GetJson()); @@ -1559,7 +1559,7 @@ std::unique_ptr ScriptEngine::CreateGameAction( auto jsonz = duk_json_encode(ctx, -1); auto json = std::string(jsonz); duk_pop(ctx); - auto customAction = std::make_unique(actionid, json, pluginName); + auto customAction = std::make_unique(actionid, json, pluginName); if (customAction->GetPlayer() == -1 && NetworkGetMode() != NETWORK_MODE_NONE) { diff --git a/src/openrct2/scripting/ScriptEngine.h b/src/openrct2/scripting/ScriptEngine.h index 38919c5cbf..dcb2ae9a36 100644 --- a/src/openrct2/scripting/ScriptEngine.h +++ b/src/openrct2/scripting/ScriptEngine.h @@ -248,7 +248,8 @@ namespace OpenRCT2::Scripting void AddNetworkPlugin(std::string_view code); void RemoveNetworkPlugins(); - [[nodiscard]] GameActions::Result QueryOrExecuteCustomGameAction(const CustomAction& action, bool isExecute); + [[nodiscard]] GameActions::Result QueryOrExecuteCustomGameAction( + const GameActions::CustomAction& action, bool isExecute); bool RegisterCustomAction( const std::shared_ptr& plugin, std::string_view action, const DukValue& query, const DukValue& execute); void RunGameActionHooks(const GameAction& action, GameActions::Result& result, bool isExecute); diff --git a/src/openrct2/world/Scenery.cpp b/src/openrct2/world/Scenery.cpp index 199140f4ef..43400bf304 100644 --- a/src/openrct2/world/Scenery.cpp +++ b/src/openrct2/world/Scenery.cpp @@ -260,7 +260,7 @@ void SceneryRemoveGhostToolPlacement() if (tileElement->GetBaseZ() != gSceneryGhostPosition.z) continue; - auto footpathAdditionRemoveAction = FootpathAdditionRemoveAction(gSceneryGhostPosition); + auto footpathAdditionRemoveAction = GameActions::FootpathAdditionRemoveAction(gSceneryGhostPosition); footpathAdditionRemoveAction.SetFlags( GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST); GameActions::Execute(&footpathAdditionRemoveAction);