mirror of https://github.com/OpenRCT2/OpenRCT2.git
194 lines
5.8 KiB
C++
194 lines
5.8 KiB
C++
/*****************************************************************************
|
|
* Copyright (c) 2014-2024 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.
|
|
*****************************************************************************/
|
|
|
|
#include "FootpathRemoveAction.h"
|
|
|
|
#include "../Cheats.h"
|
|
#include "../GameState.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 "BannerRemoveAction.h"
|
|
|
|
using namespace OpenRCT2;
|
|
|
|
FootpathRemoveAction::FootpathRemoveAction(const CoordsXYZ& location)
|
|
: _loc(location)
|
|
{
|
|
}
|
|
|
|
void FootpathRemoveAction::AcceptParameters(GameActionParameterVisitor& visitor)
|
|
{
|
|
visitor.Visit(_loc);
|
|
}
|
|
|
|
uint16_t FootpathRemoveAction::GetActionFlags() const
|
|
{
|
|
return GameAction::GetActionFlags();
|
|
}
|
|
|
|
void FootpathRemoveAction::Serialise(DataSerialiser& stream)
|
|
{
|
|
GameAction::Serialise(stream);
|
|
|
|
stream << DS_TAG(_loc);
|
|
}
|
|
|
|
GameActions::Result FootpathRemoveAction::Query() const
|
|
{
|
|
auto res = GameActions::Result();
|
|
res.Cost = 0;
|
|
res.Expenditure = ExpenditureType::Landscaping;
|
|
res.Position = { _loc.x + 16, _loc.y + 16, _loc.z };
|
|
|
|
if (!LocationValid(_loc))
|
|
{
|
|
return GameActions::Result(
|
|
GameActions::Status::InvalidParameters, STR_CANT_REMOVE_FOOTPATH_FROM_HERE, STR_OFF_EDGE_OF_MAP);
|
|
}
|
|
|
|
if (!((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) || GetGameState().Cheats.SandboxMode) && !MapIsLocationOwned(_loc))
|
|
{
|
|
return GameActions::Result(
|
|
GameActions::Status::NotOwned, STR_CANT_REMOVE_FOOTPATH_FROM_HERE, STR_LAND_NOT_OWNED_BY_PARK);
|
|
}
|
|
|
|
TileElement* footpathElement = GetFootpathElement();
|
|
if (footpathElement == nullptr)
|
|
{
|
|
return GameActions::Result(
|
|
GameActions::Status::InvalidParameters, STR_CANT_REMOVE_FOOTPATH_FROM_HERE, STR_ERR_PATH_ELEMENT_NOT_FOUND);
|
|
}
|
|
|
|
res.Cost = GetRefundPrice(footpathElement);
|
|
|
|
return res;
|
|
}
|
|
|
|
GameActions::Result FootpathRemoveAction::Execute() const
|
|
{
|
|
auto res = GameActions::Result();
|
|
res.Cost = 0;
|
|
res.Expenditure = ExpenditureType::Landscaping;
|
|
res.Position = { _loc.x + 16, _loc.y + 16, _loc.z };
|
|
|
|
if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST))
|
|
{
|
|
FootpathInterruptPeeps(_loc);
|
|
FootpathRemoveLitter(_loc);
|
|
}
|
|
|
|
TileElement* footpathElement = GetFootpathElement();
|
|
if (footpathElement != nullptr)
|
|
{
|
|
FootpathQueueChainReset();
|
|
auto bannerRes = RemoveBannersAtElement(_loc, footpathElement);
|
|
if (bannerRes.Error == GameActions::Status::Ok)
|
|
{
|
|
res.Cost += bannerRes.Cost;
|
|
}
|
|
FootpathRemoveEdgesAt(_loc, footpathElement);
|
|
MapInvalidateTileFull(_loc);
|
|
TileElementRemove(footpathElement);
|
|
FootpathUpdateQueueChains();
|
|
|
|
auto& gameState = GetGameState();
|
|
// Remove the spawn point (if there is one in the current tile)
|
|
gameState.PeepSpawns.erase(
|
|
std::remove_if(
|
|
gameState.PeepSpawns.begin(), gameState.PeepSpawns.end(),
|
|
[this](const CoordsXYZ& spawn) {
|
|
{
|
|
return spawn.ToTileStart() == _loc.ToTileStart();
|
|
}
|
|
}),
|
|
gameState.PeepSpawns.end());
|
|
}
|
|
else
|
|
{
|
|
return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_REMOVE_FOOTPATH_FROM_HERE, STR_NONE);
|
|
}
|
|
|
|
res.Cost += GetRefundPrice(footpathElement);
|
|
|
|
return res;
|
|
}
|
|
|
|
TileElement* FootpathRemoveAction::GetFootpathElement() const
|
|
{
|
|
bool getGhostPath = GetFlags() & GAME_COMMAND_FLAG_GHOST;
|
|
|
|
// FIXME: This is a hack to get the footpath element. It should be done in a better way.
|
|
TileElement* tileElement = MapGetFootpathElement(_loc)->as<TileElement>();
|
|
TileElement* footpathElement = nullptr;
|
|
if (tileElement != nullptr)
|
|
{
|
|
if (getGhostPath && !tileElement->IsGhost())
|
|
{
|
|
while (!(tileElement++)->IsLastForTile())
|
|
{
|
|
if (tileElement->GetType() != TileElementType::Path && !tileElement->IsGhost())
|
|
{
|
|
continue;
|
|
}
|
|
footpathElement = tileElement;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
footpathElement = tileElement;
|
|
}
|
|
}
|
|
|
|
return footpathElement;
|
|
}
|
|
|
|
money64 FootpathRemoveAction::GetRefundPrice(TileElement* footpathElement) const
|
|
{
|
|
money64 cost = -10.00_GBP;
|
|
return cost;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006BA23E
|
|
*/
|
|
GameActions::Result FootpathRemoveAction::RemoveBannersAtElement(const CoordsXY& loc, TileElement* tileElement) const
|
|
{
|
|
auto result = GameActions::Result();
|
|
while (!(tileElement++)->IsLastForTile())
|
|
{
|
|
if (tileElement->GetType() == TileElementType::Path)
|
|
return result;
|
|
|
|
if (tileElement->GetType() != TileElementType::Banner)
|
|
continue;
|
|
|
|
auto bannerRemoveAction = BannerRemoveAction({ loc, tileElement->GetBaseZ(), tileElement->AsBanner()->GetPosition() });
|
|
bool isGhost = tileElement->IsGhost();
|
|
auto bannerFlags = GetFlags() | (isGhost ? static_cast<uint32_t>(GAME_COMMAND_FLAG_GHOST) : 0);
|
|
bannerRemoveAction.SetFlags(bannerFlags);
|
|
auto res = GameActions::ExecuteNested(&bannerRemoveAction);
|
|
// Ghost removal is free
|
|
if (res.Error == GameActions::Status::Ok && !isGhost)
|
|
{
|
|
result.Cost += res.Cost;
|
|
}
|
|
tileElement--;
|
|
}
|
|
return result;
|
|
}
|