mirror of https://github.com/OpenRCT2/OpenRCT2.git
166 lines
4.7 KiB
C++
166 lines
4.7 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 "WaterSetHeightAction.h"
|
|
|
|
#include "../GameState.h"
|
|
#include "../OpenRCT2.h"
|
|
#include "../management/Finance.h"
|
|
#include "../world/ConstructionClearance.h"
|
|
#include "../world/Park.h"
|
|
#include "../world/Surface.h"
|
|
|
|
using namespace OpenRCT2;
|
|
|
|
WaterSetHeightAction::WaterSetHeightAction(const CoordsXY& coords, uint8_t height)
|
|
: _coords(coords)
|
|
, _height(height)
|
|
{
|
|
}
|
|
|
|
void WaterSetHeightAction::AcceptParameters(GameActionParameterVisitor& visitor)
|
|
{
|
|
visitor.Visit(_coords);
|
|
visitor.Visit("height", _height);
|
|
}
|
|
|
|
uint16_t WaterSetHeightAction::GetActionFlags() const
|
|
{
|
|
return GameAction::GetActionFlags();
|
|
}
|
|
|
|
void WaterSetHeightAction::Serialise(DataSerialiser& stream)
|
|
{
|
|
GameAction::Serialise(stream);
|
|
|
|
stream << DS_TAG(_coords) << DS_TAG(_height);
|
|
}
|
|
|
|
GameActions::Result WaterSetHeightAction::Query() const
|
|
{
|
|
auto res = GameActions::Result();
|
|
res.Expenditure = ExpenditureType::Landscaping;
|
|
res.Position = { _coords, _height * COORDS_Z_STEP };
|
|
|
|
if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !GetGameState().Cheats.SandboxMode
|
|
&& GetGameState().Park.Flags & PARK_FLAGS_FORBID_LANDSCAPE_CHANGES)
|
|
{
|
|
return GameActions::Result(GameActions::Status::Disallowed, STR_NONE, STR_FORBIDDEN_BY_THE_LOCAL_AUTHORITY);
|
|
}
|
|
|
|
StringId errorMsg = CheckParameters();
|
|
if (errorMsg != STR_NONE)
|
|
{
|
|
return GameActions::Result(GameActions::Status::InvalidParameters, STR_NONE, errorMsg);
|
|
}
|
|
|
|
if (!LocationValid(_coords))
|
|
{
|
|
return GameActions::Result(GameActions::Status::NotOwned, STR_NONE, STR_LAND_NOT_OWNED_BY_PARK);
|
|
}
|
|
|
|
if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !GetGameState().Cheats.SandboxMode)
|
|
{
|
|
if (!MapIsLocationInPark(_coords))
|
|
{
|
|
return GameActions::Result(GameActions::Status::Disallowed, STR_NONE, STR_LAND_NOT_OWNED_BY_PARK);
|
|
}
|
|
}
|
|
|
|
SurfaceElement* surfaceElement = MapGetSurfaceElementAt(_coords);
|
|
if (surfaceElement == nullptr)
|
|
{
|
|
LOG_ERROR("No surface element at: x %u, y %u", _coords.x, _coords.y);
|
|
return GameActions::Result(
|
|
GameActions::Status::InvalidParameters, STR_ERR_INVALID_PARAMETER, STR_ERR_SURFACE_ELEMENT_NOT_FOUND);
|
|
}
|
|
|
|
int32_t zHigh = surfaceElement->GetBaseZ();
|
|
int32_t zLow = _height * COORDS_Z_STEP;
|
|
if (surfaceElement->GetWaterHeight() > 0)
|
|
{
|
|
zHigh = surfaceElement->GetWaterHeight();
|
|
}
|
|
if (zLow > zHigh)
|
|
{
|
|
int32_t temp = zHigh;
|
|
zHigh = zLow;
|
|
zLow = temp;
|
|
}
|
|
|
|
if (auto res2 = MapCanConstructAt({ _coords, zLow, zHigh }, { 0b1111, 0b1111 }); res2.Error != GameActions::Status::Ok)
|
|
{
|
|
return res2;
|
|
}
|
|
if (surfaceElement->HasTrackThatNeedsWater())
|
|
{
|
|
return GameActions::Result(
|
|
GameActions::Status::Disallowed, STR_ERR_INVALID_PARAMETER, STR_ERR_TRACK_ON_THIS_TILE_NEEDS_WATER);
|
|
}
|
|
|
|
res.Cost = 250;
|
|
|
|
return res;
|
|
}
|
|
|
|
GameActions::Result WaterSetHeightAction::Execute() const
|
|
{
|
|
auto res = GameActions::Result();
|
|
res.Expenditure = ExpenditureType::Landscaping;
|
|
res.Position = { _coords, _height * COORDS_Z_STEP };
|
|
|
|
int32_t surfaceHeight = TileElementHeight(_coords);
|
|
FootpathRemoveLitter({ _coords, surfaceHeight });
|
|
if (!GetGameState().Cheats.DisableClearanceChecks)
|
|
WallRemoveAtZ({ _coords, surfaceHeight });
|
|
|
|
SurfaceElement* surfaceElement = MapGetSurfaceElementAt(_coords);
|
|
if (surfaceElement == nullptr)
|
|
{
|
|
LOG_ERROR("No surface element at: x %u, y %u", _coords.x, _coords.y);
|
|
return GameActions::Result(
|
|
GameActions::Status::InvalidParameters, STR_ERR_INVALID_PARAMETER, STR_ERR_SURFACE_ELEMENT_NOT_FOUND);
|
|
}
|
|
|
|
if (_height > surfaceElement->BaseHeight)
|
|
{
|
|
surfaceElement->SetWaterHeight(_height * COORDS_Z_STEP);
|
|
}
|
|
else
|
|
{
|
|
surfaceElement->SetWaterHeight(0);
|
|
}
|
|
MapInvalidateTileFull(_coords);
|
|
|
|
res.Cost = 250;
|
|
|
|
return res;
|
|
}
|
|
|
|
StringId WaterSetHeightAction::CheckParameters() const
|
|
{
|
|
auto mapSizeMax = GetMapSizeMaxXY();
|
|
if (_coords.x > mapSizeMax.x || _coords.y > mapSizeMax.y)
|
|
{
|
|
return STR_OFF_EDGE_OF_MAP;
|
|
}
|
|
|
|
if (_height < kMinimumWaterHeight)
|
|
{
|
|
return STR_TOO_LOW;
|
|
}
|
|
|
|
if (_height > kMaximumWaterHeight)
|
|
{
|
|
return STR_TOO_HIGH;
|
|
}
|
|
|
|
return STR_NONE;
|
|
}
|