mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-31 10:45:16 +01:00
Finish land and water game commands
This commit is contained in:
@@ -521,7 +521,7 @@ namespace OpenRCT2::Ui::Windows
|
||||
case WIDX_BACKGROUND:
|
||||
if (gMapSelectFlags & MAP_SELECT_FLAG_ENABLE)
|
||||
{
|
||||
auto surfaceSetStyleAction = SurfaceSetStyleAction(
|
||||
auto surfaceSetStyleAction = GameActions::SurfaceSetStyleAction(
|
||||
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y },
|
||||
gLandToolTerrainSurface, gLandToolTerrainEdge);
|
||||
|
||||
@@ -548,7 +548,7 @@ namespace OpenRCT2::Ui::Windows
|
||||
{
|
||||
if (gMapSelectFlags & MAP_SELECT_FLAG_ENABLE)
|
||||
{
|
||||
auto surfaceSetStyleAction = SurfaceSetStyleAction(
|
||||
auto surfaceSetStyleAction = GameActions::SurfaceSetStyleAction(
|
||||
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y },
|
||||
gLandToolTerrainSurface, gLandToolTerrainEdge);
|
||||
|
||||
|
||||
@@ -260,7 +260,7 @@ namespace OpenRCT2::Ui::Windows
|
||||
{
|
||||
gInputDragLast.y += dx;
|
||||
|
||||
auto waterRaiseAction = WaterRaiseAction(
|
||||
auto waterRaiseAction = GameActions::WaterRaiseAction(
|
||||
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y });
|
||||
GameActions::Execute(&waterRaiseAction);
|
||||
|
||||
@@ -276,7 +276,7 @@ namespace OpenRCT2::Ui::Windows
|
||||
{
|
||||
gInputDragLast.y += dx;
|
||||
|
||||
auto waterLowerAction = WaterLowerAction(
|
||||
auto waterLowerAction = GameActions::WaterLowerAction(
|
||||
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y });
|
||||
GameActions::Execute(&waterLowerAction);
|
||||
_waterToolRaiseCost = kMoney64Undefined;
|
||||
@@ -301,9 +301,9 @@ namespace OpenRCT2::Ui::Windows
|
||||
if (!(gMapSelectFlags & MAP_SELECT_FLAG_ENABLE))
|
||||
return;
|
||||
|
||||
auto waterLowerAction = WaterLowerAction(
|
||||
auto waterLowerAction = GameActions::WaterLowerAction(
|
||||
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y });
|
||||
auto waterRaiseAction = WaterRaiseAction(
|
||||
auto waterRaiseAction = GameActions::WaterRaiseAction(
|
||||
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y });
|
||||
|
||||
auto res = GameActions::Query(&waterLowerAction);
|
||||
@@ -392,9 +392,9 @@ namespace OpenRCT2::Ui::Windows
|
||||
if (!state_changed)
|
||||
return;
|
||||
|
||||
auto waterLowerAction = WaterLowerAction(
|
||||
auto waterLowerAction = GameActions::WaterLowerAction(
|
||||
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y });
|
||||
auto waterRaiseAction = WaterRaiseAction(
|
||||
auto waterRaiseAction = GameActions::WaterRaiseAction(
|
||||
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y });
|
||||
|
||||
auto res = GameActions::Query(&waterLowerAction);
|
||||
|
||||
@@ -21,210 +21,208 @@
|
||||
#include "../world/Park.h"
|
||||
#include "../world/tile_element/SurfaceElement.h"
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
SurfaceSetStyleAction::SurfaceSetStyleAction(MapRange range, ObjectEntryIndex surfaceStyle, ObjectEntryIndex edgeStyle)
|
||||
: _range(range)
|
||||
, _surfaceStyle(surfaceStyle)
|
||||
, _edgeStyle(edgeStyle)
|
||||
namespace OpenRCT2::GameActions
|
||||
{
|
||||
}
|
||||
|
||||
void SurfaceSetStyleAction::AcceptParameters(GameActionParameterVisitor& visitor)
|
||||
{
|
||||
visitor.Visit(_range);
|
||||
visitor.Visit("surfaceStyle", _surfaceStyle);
|
||||
visitor.Visit("edgeStyle", _edgeStyle);
|
||||
}
|
||||
|
||||
void SurfaceSetStyleAction::Serialise(DataSerialiser& stream)
|
||||
{
|
||||
GameAction::Serialise(stream);
|
||||
|
||||
stream << DS_TAG(_range) << DS_TAG(_surfaceStyle) << DS_TAG(_edgeStyle);
|
||||
}
|
||||
|
||||
GameActions::Result SurfaceSetStyleAction::Query() const
|
||||
{
|
||||
auto res = GameActions::Result();
|
||||
res.ErrorTitle = STR_CANT_CHANGE_LAND_TYPE;
|
||||
res.Expenditure = ExpenditureType::landscaping;
|
||||
|
||||
auto validRange = ClampRangeWithinMap(_range.Normalise());
|
||||
auto& objManager = OpenRCT2::GetContext()->GetObjectManager();
|
||||
if (_surfaceStyle != kObjectEntryIndexNull)
|
||||
SurfaceSetStyleAction::SurfaceSetStyleAction(MapRange range, ObjectEntryIndex surfaceStyle, ObjectEntryIndex edgeStyle)
|
||||
: _range(range)
|
||||
, _surfaceStyle(surfaceStyle)
|
||||
, _edgeStyle(edgeStyle)
|
||||
{
|
||||
const auto surfaceObj = static_cast<TerrainSurfaceObject*>(
|
||||
objManager.GetLoadedObject<TerrainSurfaceObject>(_surfaceStyle));
|
||||
|
||||
if (surfaceObj == nullptr)
|
||||
{
|
||||
LOG_ERROR("Invalid surface style %u", _surfaceStyle);
|
||||
return GameActions::Result(
|
||||
GameActions::Status::InvalidParameters, STR_CANT_CHANGE_LAND_TYPE, STR_UNKNOWN_OBJECT_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
if (_edgeStyle != kObjectEntryIndexNull)
|
||||
void SurfaceSetStyleAction::AcceptParameters(GameActionParameterVisitor& visitor)
|
||||
{
|
||||
const auto edgeObj = objManager.GetLoadedObject<TerrainEdgeObject>(_edgeStyle);
|
||||
|
||||
if (edgeObj == nullptr)
|
||||
{
|
||||
LOG_ERROR("Invalid edge style %u", _edgeStyle);
|
||||
return GameActions::Result(
|
||||
GameActions::Status::InvalidParameters, STR_CANT_CHANGE_LAND_TYPE, STR_UNKNOWN_OBJECT_TYPE);
|
||||
}
|
||||
visitor.Visit(_range);
|
||||
visitor.Visit("surfaceStyle", _surfaceStyle);
|
||||
visitor.Visit("edgeStyle", _edgeStyle);
|
||||
}
|
||||
|
||||
auto xMid = (validRange.GetLeft() + validRange.GetRight()) / 2 + 16;
|
||||
auto yMid = (validRange.GetTop() + validRange.GetBottom()) / 2 + 16;
|
||||
auto heightMid = TileElementHeight({ xMid, yMid });
|
||||
|
||||
res.Position.x = xMid;
|
||||
res.Position.y = yMid;
|
||||
res.Position.z = heightMid;
|
||||
|
||||
auto& gameState = getGameState();
|
||||
|
||||
// Do nothing if not in editor, sandbox mode or landscaping is forbidden
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !gameState.cheats.sandboxMode
|
||||
&& (gameState.park.flags & PARK_FLAGS_FORBID_LANDSCAPE_CHANGES))
|
||||
void SurfaceSetStyleAction::Serialise(DataSerialiser& stream)
|
||||
{
|
||||
return GameActions::Result(
|
||||
GameActions::Status::Disallowed, STR_CANT_CHANGE_LAND_TYPE, STR_FORBIDDEN_BY_THE_LOCAL_AUTHORITY);
|
||||
GameAction::Serialise(stream);
|
||||
|
||||
stream << DS_TAG(_range) << DS_TAG(_surfaceStyle) << DS_TAG(_edgeStyle);
|
||||
}
|
||||
|
||||
money64 surfaceCost = 0;
|
||||
money64 edgeCost = 0;
|
||||
for (CoordsXY coords = { validRange.GetLeft(), validRange.GetTop() }; coords.x <= validRange.GetRight();
|
||||
coords.x += kCoordsXYStep)
|
||||
Result SurfaceSetStyleAction::Query() const
|
||||
{
|
||||
for (coords.y = validRange.GetTop(); coords.y <= validRange.GetBottom(); coords.y += kCoordsXYStep)
|
||||
{
|
||||
if (!LocationValid(coords))
|
||||
continue;
|
||||
auto res = Result();
|
||||
res.ErrorTitle = STR_CANT_CHANGE_LAND_TYPE;
|
||||
res.Expenditure = ExpenditureType::landscaping;
|
||||
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !gameState.cheats.sandboxMode)
|
||||
auto validRange = ClampRangeWithinMap(_range.Normalise());
|
||||
auto& objManager = OpenRCT2::GetContext()->GetObjectManager();
|
||||
if (_surfaceStyle != kObjectEntryIndexNull)
|
||||
{
|
||||
const auto surfaceObj = static_cast<TerrainSurfaceObject*>(
|
||||
objManager.GetLoadedObject<TerrainSurfaceObject>(_surfaceStyle));
|
||||
|
||||
if (surfaceObj == nullptr)
|
||||
{
|
||||
if (!MapIsLocationInPark(coords))
|
||||
LOG_ERROR("Invalid surface style %u", _surfaceStyle);
|
||||
return Result(Status::InvalidParameters, STR_CANT_CHANGE_LAND_TYPE, STR_UNKNOWN_OBJECT_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
if (_edgeStyle != kObjectEntryIndexNull)
|
||||
{
|
||||
const auto edgeObj = objManager.GetLoadedObject<TerrainEdgeObject>(_edgeStyle);
|
||||
|
||||
if (edgeObj == nullptr)
|
||||
{
|
||||
LOG_ERROR("Invalid edge style %u", _edgeStyle);
|
||||
return Result(Status::InvalidParameters, STR_CANT_CHANGE_LAND_TYPE, STR_UNKNOWN_OBJECT_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
auto xMid = (validRange.GetLeft() + validRange.GetRight()) / 2 + 16;
|
||||
auto yMid = (validRange.GetTop() + validRange.GetBottom()) / 2 + 16;
|
||||
auto heightMid = TileElementHeight({ xMid, yMid });
|
||||
|
||||
res.Position.x = xMid;
|
||||
res.Position.y = yMid;
|
||||
res.Position.z = heightMid;
|
||||
|
||||
auto& gameState = getGameState();
|
||||
|
||||
// Do nothing if not in editor, sandbox mode or landscaping is forbidden
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !gameState.cheats.sandboxMode
|
||||
&& (gameState.park.flags & PARK_FLAGS_FORBID_LANDSCAPE_CHANGES))
|
||||
{
|
||||
return Result(Status::Disallowed, STR_CANT_CHANGE_LAND_TYPE, STR_FORBIDDEN_BY_THE_LOCAL_AUTHORITY);
|
||||
}
|
||||
|
||||
money64 surfaceCost = 0;
|
||||
money64 edgeCost = 0;
|
||||
for (CoordsXY coords = { validRange.GetLeft(), validRange.GetTop() }; coords.x <= validRange.GetRight();
|
||||
coords.x += kCoordsXYStep)
|
||||
{
|
||||
for (coords.y = validRange.GetTop(); coords.y <= validRange.GetBottom(); coords.y += kCoordsXYStep)
|
||||
{
|
||||
if (!LocationValid(coords))
|
||||
continue;
|
||||
}
|
||||
|
||||
auto surfaceElement = MapGetSurfaceElementAt(coords);
|
||||
if (surfaceElement == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_surfaceStyle != kObjectEntryIndexNull)
|
||||
{
|
||||
uint8_t curSurfaceStyle = surfaceElement->GetSurfaceObjectIndex();
|
||||
|
||||
if (_surfaceStyle != curSurfaceStyle)
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !gameState.cheats.sandboxMode)
|
||||
{
|
||||
const auto* surfaceObject = objManager.GetLoadedObject<TerrainSurfaceObject>(_surfaceStyle);
|
||||
if (surfaceObject != nullptr)
|
||||
if (!MapIsLocationInPark(coords))
|
||||
continue;
|
||||
}
|
||||
|
||||
auto surfaceElement = MapGetSurfaceElementAt(coords);
|
||||
if (surfaceElement == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_surfaceStyle != kObjectEntryIndexNull)
|
||||
{
|
||||
uint8_t curSurfaceStyle = surfaceElement->GetSurfaceObjectIndex();
|
||||
|
||||
if (_surfaceStyle != curSurfaceStyle)
|
||||
{
|
||||
surfaceCost += surfaceObject->Price;
|
||||
const auto* surfaceObject = objManager.GetLoadedObject<TerrainSurfaceObject>(_surfaceStyle);
|
||||
if (surfaceObject != nullptr)
|
||||
{
|
||||
surfaceCost += surfaceObject->Price;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_edgeStyle != kObjectEntryIndexNull)
|
||||
{
|
||||
uint8_t curEdgeStyle = surfaceElement->GetEdgeObjectIndex();
|
||||
|
||||
if (_edgeStyle != curEdgeStyle)
|
||||
{
|
||||
edgeCost += 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_edgeStyle != kObjectEntryIndexNull)
|
||||
{
|
||||
uint8_t curEdgeStyle = surfaceElement->GetEdgeObjectIndex();
|
||||
|
||||
if (_edgeStyle != curEdgeStyle)
|
||||
{
|
||||
edgeCost += 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
res.Cost = surfaceCost + edgeCost;
|
||||
|
||||
return res;
|
||||
}
|
||||
res.Cost = surfaceCost + edgeCost;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
GameActions::Result SurfaceSetStyleAction::Execute() const
|
||||
{
|
||||
auto res = GameActions::Result();
|
||||
res.ErrorTitle = STR_CANT_CHANGE_LAND_TYPE;
|
||||
res.Expenditure = ExpenditureType::landscaping;
|
||||
|
||||
auto validRange = ClampRangeWithinMap(_range.Normalise());
|
||||
auto xMid = (validRange.GetLeft() + validRange.GetRight()) / 2 + 16;
|
||||
auto yMid = (validRange.GetTop() + validRange.GetBottom()) / 2 + 16;
|
||||
auto heightMid = TileElementHeight({ xMid, yMid });
|
||||
|
||||
res.Position.x = xMid;
|
||||
res.Position.y = yMid;
|
||||
res.Position.z = heightMid;
|
||||
|
||||
money64 surfaceCost = 0;
|
||||
money64 edgeCost = 0;
|
||||
for (CoordsXY coords = { validRange.GetLeft(), validRange.GetTop() }; coords.x <= validRange.GetRight();
|
||||
coords.x += kCoordsXYStep)
|
||||
Result SurfaceSetStyleAction::Execute() const
|
||||
{
|
||||
for (coords.y = validRange.GetTop(); coords.y <= validRange.GetBottom(); coords.y += kCoordsXYStep)
|
||||
auto res = Result();
|
||||
res.ErrorTitle = STR_CANT_CHANGE_LAND_TYPE;
|
||||
res.Expenditure = ExpenditureType::landscaping;
|
||||
|
||||
auto validRange = ClampRangeWithinMap(_range.Normalise());
|
||||
auto xMid = (validRange.GetLeft() + validRange.GetRight()) / 2 + 16;
|
||||
auto yMid = (validRange.GetTop() + validRange.GetBottom()) / 2 + 16;
|
||||
auto heightMid = TileElementHeight({ xMid, yMid });
|
||||
|
||||
res.Position.x = xMid;
|
||||
res.Position.y = yMid;
|
||||
res.Position.z = heightMid;
|
||||
|
||||
money64 surfaceCost = 0;
|
||||
money64 edgeCost = 0;
|
||||
for (CoordsXY coords = { validRange.GetLeft(), validRange.GetTop() }; coords.x <= validRange.GetRight();
|
||||
coords.x += kCoordsXYStep)
|
||||
{
|
||||
if (!LocationValid(coords))
|
||||
continue;
|
||||
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !getGameState().cheats.sandboxMode)
|
||||
for (coords.y = validRange.GetTop(); coords.y <= validRange.GetBottom(); coords.y += kCoordsXYStep)
|
||||
{
|
||||
if (!MapIsLocationInPark(coords))
|
||||
if (!LocationValid(coords))
|
||||
continue;
|
||||
}
|
||||
|
||||
auto surfaceElement = MapGetSurfaceElementAt(coords);
|
||||
if (surfaceElement == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_surfaceStyle != kObjectEntryIndexNull)
|
||||
{
|
||||
uint8_t curSurfaceStyle = surfaceElement->GetSurfaceObjectIndex();
|
||||
|
||||
if (_surfaceStyle != curSurfaceStyle)
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !getGameState().cheats.sandboxMode)
|
||||
{
|
||||
auto& objManager = OpenRCT2::GetContext()->GetObjectManager();
|
||||
const auto* surfaceObject = objManager.GetLoadedObject<TerrainSurfaceObject>(_surfaceStyle);
|
||||
if (surfaceObject != nullptr)
|
||||
if (!MapIsLocationInPark(coords))
|
||||
continue;
|
||||
}
|
||||
|
||||
auto surfaceElement = MapGetSurfaceElementAt(coords);
|
||||
if (surfaceElement == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_surfaceStyle != kObjectEntryIndexNull)
|
||||
{
|
||||
uint8_t curSurfaceStyle = surfaceElement->GetSurfaceObjectIndex();
|
||||
|
||||
if (_surfaceStyle != curSurfaceStyle)
|
||||
{
|
||||
surfaceCost += surfaceObject->Price;
|
||||
auto& objManager = OpenRCT2::GetContext()->GetObjectManager();
|
||||
const auto* surfaceObject = objManager.GetLoadedObject<TerrainSurfaceObject>(_surfaceStyle);
|
||||
if (surfaceObject != nullptr)
|
||||
{
|
||||
surfaceCost += surfaceObject->Price;
|
||||
|
||||
surfaceElement->SetSurfaceObjectIndex(_surfaceStyle);
|
||||
surfaceElement->SetSurfaceObjectIndex(_surfaceStyle);
|
||||
|
||||
MapInvalidateTileFull(coords);
|
||||
FootpathRemoveLitter({ coords, TileElementHeight(coords) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_edgeStyle != kObjectEntryIndexNull)
|
||||
{
|
||||
uint8_t curEdgeStyle = surfaceElement->GetEdgeObjectIndex();
|
||||
|
||||
if (_edgeStyle != curEdgeStyle)
|
||||
{
|
||||
edgeCost += 100;
|
||||
|
||||
surfaceElement->SetEdgeObjectIndex(_edgeStyle);
|
||||
MapInvalidateTileFull(coords);
|
||||
FootpathRemoveLitter({ coords, TileElementHeight(coords) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_edgeStyle != kObjectEntryIndexNull)
|
||||
{
|
||||
uint8_t curEdgeStyle = surfaceElement->GetEdgeObjectIndex();
|
||||
|
||||
if (_edgeStyle != curEdgeStyle)
|
||||
if (surfaceElement->CanGrassGrow() && (surfaceElement->GetGrassLength() & 7) != GRASS_LENGTH_CLEAR_0)
|
||||
{
|
||||
edgeCost += 100;
|
||||
|
||||
surfaceElement->SetEdgeObjectIndex(_edgeStyle);
|
||||
surfaceElement->SetGrassLength(GRASS_LENGTH_CLEAR_0);
|
||||
MapInvalidateTileFull(coords);
|
||||
}
|
||||
}
|
||||
|
||||
if (surfaceElement->CanGrassGrow() && (surfaceElement->GetGrassLength() & 7) != GRASS_LENGTH_CLEAR_0)
|
||||
{
|
||||
surfaceElement->SetGrassLength(GRASS_LENGTH_CLEAR_0);
|
||||
MapInvalidateTileFull(coords);
|
||||
}
|
||||
}
|
||||
}
|
||||
res.Cost = surfaceCost + edgeCost;
|
||||
res.Cost = surfaceCost + edgeCost;
|
||||
|
||||
return res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
} // namespace OpenRCT2::GameActions
|
||||
|
||||
@@ -11,20 +11,23 @@
|
||||
|
||||
#include "GameAction.h"
|
||||
|
||||
class SurfaceSetStyleAction final : public GameActionBase<GameCommand::ChangeSurfaceStyle>
|
||||
namespace OpenRCT2::GameActions
|
||||
{
|
||||
private:
|
||||
MapRange _range;
|
||||
OpenRCT2::ObjectEntryIndex _surfaceStyle{};
|
||||
OpenRCT2::ObjectEntryIndex _edgeStyle{};
|
||||
class SurfaceSetStyleAction final : public GameActionBase<GameCommand::ChangeSurfaceStyle>
|
||||
{
|
||||
private:
|
||||
MapRange _range;
|
||||
ObjectEntryIndex _surfaceStyle{};
|
||||
ObjectEntryIndex _edgeStyle{};
|
||||
|
||||
public:
|
||||
SurfaceSetStyleAction() = default;
|
||||
SurfaceSetStyleAction(MapRange range, OpenRCT2::ObjectEntryIndex surfaceStyle, OpenRCT2::ObjectEntryIndex edgeStyle);
|
||||
public:
|
||||
SurfaceSetStyleAction() = default;
|
||||
SurfaceSetStyleAction(MapRange range, ObjectEntryIndex surfaceStyle, ObjectEntryIndex edgeStyle);
|
||||
|
||||
void AcceptParameters(GameActionParameterVisitor& visitor) override;
|
||||
void AcceptParameters(GameActionParameterVisitor& visitor) 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
|
||||
|
||||
@@ -16,151 +16,150 @@
|
||||
#include "../world/tile_element/SurfaceElement.h"
|
||||
#include "WaterSetHeightAction.h"
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
WaterLowerAction::WaterLowerAction(MapRange range)
|
||||
: _range(range)
|
||||
namespace OpenRCT2::GameActions
|
||||
{
|
||||
}
|
||||
|
||||
void WaterLowerAction::AcceptParameters(GameActionParameterVisitor& visitor)
|
||||
{
|
||||
visitor.Visit(_range);
|
||||
}
|
||||
|
||||
uint16_t WaterLowerAction::GetActionFlags() const
|
||||
{
|
||||
return GameAction::GetActionFlags();
|
||||
}
|
||||
|
||||
void WaterLowerAction::Serialise(DataSerialiser& stream)
|
||||
{
|
||||
GameAction::Serialise(stream);
|
||||
|
||||
stream << DS_TAG(_range);
|
||||
}
|
||||
|
||||
GameActions::Result WaterLowerAction::Query() const
|
||||
{
|
||||
return QueryExecute(false);
|
||||
}
|
||||
|
||||
GameActions::Result WaterLowerAction::Execute() const
|
||||
{
|
||||
return QueryExecute(true);
|
||||
}
|
||||
|
||||
GameActions::Result WaterLowerAction::QueryExecute(bool isExecuting) const
|
||||
{
|
||||
auto res = GameActions::Result();
|
||||
|
||||
auto validRange = ClampRangeWithinMap(_range);
|
||||
res.Position.x = ((validRange.GetLeft() + validRange.GetRight()) / 2) + 16;
|
||||
res.Position.y = ((validRange.GetTop() + validRange.GetBottom()) / 2) + 16;
|
||||
int16_t z = TileElementHeight(res.Position);
|
||||
int16_t waterHeight = TileElementWaterHeight(res.Position);
|
||||
if (waterHeight != 0)
|
||||
WaterLowerAction::WaterLowerAction(MapRange range)
|
||||
: _range(range)
|
||||
{
|
||||
z = waterHeight;
|
||||
}
|
||||
res.Position.z = z;
|
||||
res.Expenditure = ExpenditureType::landscaping;
|
||||
|
||||
uint8_t minHeight = GetLowestHeight(validRange);
|
||||
bool hasChanged = false;
|
||||
bool withinOwnership = false;
|
||||
for (int32_t y = validRange.GetTop(); y <= validRange.GetBottom(); y += kCoordsXYStep)
|
||||
void WaterLowerAction::AcceptParameters(GameActionParameterVisitor& visitor)
|
||||
{
|
||||
for (int32_t x = validRange.GetLeft(); x <= validRange.GetRight(); x += kCoordsXYStep)
|
||||
visitor.Visit(_range);
|
||||
}
|
||||
|
||||
uint16_t WaterLowerAction::GetActionFlags() const
|
||||
{
|
||||
return GameAction::GetActionFlags();
|
||||
}
|
||||
|
||||
void WaterLowerAction::Serialise(DataSerialiser& stream)
|
||||
{
|
||||
GameAction::Serialise(stream);
|
||||
|
||||
stream << DS_TAG(_range);
|
||||
}
|
||||
|
||||
Result WaterLowerAction::Query() const
|
||||
{
|
||||
return QueryExecute(false);
|
||||
}
|
||||
|
||||
Result WaterLowerAction::Execute() const
|
||||
{
|
||||
return QueryExecute(true);
|
||||
}
|
||||
|
||||
Result WaterLowerAction::QueryExecute(bool isExecuting) const
|
||||
{
|
||||
auto res = Result();
|
||||
|
||||
auto validRange = ClampRangeWithinMap(_range);
|
||||
res.Position.x = ((validRange.GetLeft() + validRange.GetRight()) / 2) + 16;
|
||||
res.Position.y = ((validRange.GetTop() + validRange.GetBottom()) / 2) + 16;
|
||||
int16_t z = TileElementHeight(res.Position);
|
||||
int16_t waterHeight = TileElementWaterHeight(res.Position);
|
||||
if (waterHeight != 0)
|
||||
{
|
||||
if (!LocationValid({ x, y }))
|
||||
continue;
|
||||
z = waterHeight;
|
||||
}
|
||||
res.Position.z = z;
|
||||
res.Expenditure = ExpenditureType::landscaping;
|
||||
|
||||
auto* surfaceElement = MapGetSurfaceElementAt(CoordsXY{ x, y });
|
||||
if (surfaceElement == nullptr)
|
||||
continue;
|
||||
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !getGameState().cheats.sandboxMode)
|
||||
uint8_t minHeight = GetLowestHeight(validRange);
|
||||
bool hasChanged = false;
|
||||
bool withinOwnership = false;
|
||||
for (int32_t y = validRange.GetTop(); y <= validRange.GetBottom(); y += kCoordsXYStep)
|
||||
{
|
||||
for (int32_t x = validRange.GetLeft(); x <= validRange.GetRight(); x += kCoordsXYStep)
|
||||
{
|
||||
if (!MapIsLocationInPark(CoordsXY{ x, y }))
|
||||
{
|
||||
if (!LocationValid({ x, y }))
|
||||
continue;
|
||||
|
||||
auto* surfaceElement = MapGetSurfaceElementAt(CoordsXY{ x, y });
|
||||
if (surfaceElement == nullptr)
|
||||
continue;
|
||||
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !getGameState().cheats.sandboxMode)
|
||||
{
|
||||
if (!MapIsLocationInPark(CoordsXY{ x, y }))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
withinOwnership = true;
|
||||
|
||||
uint8_t height = surfaceElement->GetWaterHeight() / kCoordsZStep;
|
||||
if (height == 0)
|
||||
continue;
|
||||
|
||||
if (height < minHeight)
|
||||
continue;
|
||||
|
||||
height -= 2;
|
||||
auto waterSetHeightAction = WaterSetHeightAction({ x, y }, height);
|
||||
waterSetHeightAction.SetFlags(GetFlags());
|
||||
auto result = isExecuting ? ExecuteNested(&waterSetHeightAction) : QueryNested(&waterSetHeightAction);
|
||||
if (result.Error == Status::Ok)
|
||||
{
|
||||
res.Cost += result.Cost;
|
||||
hasChanged = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.ErrorTitle = STR_CANT_LOWER_WATER_LEVEL_HERE;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
withinOwnership = true;
|
||||
|
||||
uint8_t height = surfaceElement->GetWaterHeight() / kCoordsZStep;
|
||||
if (height == 0)
|
||||
continue;
|
||||
|
||||
if (height < minHeight)
|
||||
continue;
|
||||
|
||||
height -= 2;
|
||||
auto waterSetHeightAction = WaterSetHeightAction({ x, y }, height);
|
||||
waterSetHeightAction.SetFlags(GetFlags());
|
||||
auto result = isExecuting ? GameActions::ExecuteNested(&waterSetHeightAction)
|
||||
: GameActions::QueryNested(&waterSetHeightAction);
|
||||
if (result.Error == GameActions::Status::Ok)
|
||||
{
|
||||
res.Cost += result.Cost;
|
||||
hasChanged = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.ErrorTitle = STR_CANT_LOWER_WATER_LEVEL_HERE;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!withinOwnership)
|
||||
{
|
||||
return GameActions::Result(
|
||||
GameActions::Status::Disallowed, STR_CANT_LOWER_WATER_LEVEL_HERE, STR_LAND_NOT_OWNED_BY_PARK);
|
||||
;
|
||||
}
|
||||
|
||||
if (isExecuting && hasChanged)
|
||||
{
|
||||
Audio::Play3D(Audio::SoundId::LayingOutWater, res.Position);
|
||||
}
|
||||
// Force ride construction to recheck area
|
||||
_currentTrackSelectionFlags.set(TrackSelectionFlag::recheck);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uint8_t WaterLowerAction::GetLowestHeight(const MapRange& validRange) const
|
||||
{
|
||||
// The lowest height to lower the water to is the highest water level in the selection
|
||||
uint8_t minHeight{ 0 };
|
||||
for (int32_t y = validRange.GetTop(); y <= validRange.GetBottom(); y += kCoordsXYStep)
|
||||
{
|
||||
for (int32_t x = validRange.GetLeft(); x <= validRange.GetRight(); x += kCoordsXYStep)
|
||||
if (!withinOwnership)
|
||||
{
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !getGameState().cheats.sandboxMode)
|
||||
return Result(Status::Disallowed, STR_CANT_LOWER_WATER_LEVEL_HERE, STR_LAND_NOT_OWNED_BY_PARK);
|
||||
;
|
||||
}
|
||||
|
||||
if (isExecuting && hasChanged)
|
||||
{
|
||||
Audio::Play3D(Audio::SoundId::LayingOutWater, res.Position);
|
||||
}
|
||||
// Force ride construction to recheck area
|
||||
_currentTrackSelectionFlags.set(TrackSelectionFlag::recheck);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uint8_t WaterLowerAction::GetLowestHeight(const MapRange& validRange) const
|
||||
{
|
||||
// The lowest height to lower the water to is the highest water level in the selection
|
||||
uint8_t minHeight{ 0 };
|
||||
for (int32_t y = validRange.GetTop(); y <= validRange.GetBottom(); y += kCoordsXYStep)
|
||||
{
|
||||
for (int32_t x = validRange.GetLeft(); x <= validRange.GetRight(); x += kCoordsXYStep)
|
||||
{
|
||||
if (!MapIsLocationInPark(CoordsXY{ x, y }))
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !getGameState().cheats.sandboxMode)
|
||||
{
|
||||
if (!MapIsLocationInPark(CoordsXY{ x, y }))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
auto* surfaceElement = MapGetSurfaceElementAt(CoordsXY{ x, y });
|
||||
if (surfaceElement == nullptr)
|
||||
continue;
|
||||
|
||||
uint8_t height = surfaceElement->GetWaterHeight() / kCoordsZStep;
|
||||
if (height == 0)
|
||||
continue;
|
||||
|
||||
if (height > minHeight)
|
||||
{
|
||||
minHeight = height;
|
||||
}
|
||||
}
|
||||
|
||||
auto* surfaceElement = MapGetSurfaceElementAt(CoordsXY{ x, y });
|
||||
if (surfaceElement == nullptr)
|
||||
continue;
|
||||
|
||||
uint8_t height = surfaceElement->GetWaterHeight() / kCoordsZStep;
|
||||
if (height == 0)
|
||||
continue;
|
||||
|
||||
if (height > minHeight)
|
||||
{
|
||||
minHeight = height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return minHeight;
|
||||
}
|
||||
return minHeight;
|
||||
}
|
||||
} // namespace OpenRCT2::GameActions
|
||||
|
||||
@@ -11,24 +11,27 @@
|
||||
|
||||
#include "GameAction.h"
|
||||
|
||||
class WaterLowerAction final : public GameActionBase<GameCommand::LowerWater>
|
||||
namespace OpenRCT2::GameActions
|
||||
{
|
||||
private:
|
||||
MapRange _range;
|
||||
class WaterLowerAction final : public GameActionBase<GameCommand::LowerWater>
|
||||
{
|
||||
private:
|
||||
MapRange _range;
|
||||
|
||||
public:
|
||||
WaterLowerAction() = default;
|
||||
WaterLowerAction(MapRange range);
|
||||
public:
|
||||
WaterLowerAction() = default;
|
||||
WaterLowerAction(MapRange range);
|
||||
|
||||
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 QueryExecute(bool isExecuting) const;
|
||||
uint8_t GetLowestHeight(const MapRange& validRange) const;
|
||||
};
|
||||
private:
|
||||
Result QueryExecute(bool isExecuting) const;
|
||||
uint8_t GetLowestHeight(const MapRange& validRange) const;
|
||||
};
|
||||
} // namespace OpenRCT2::GameActions
|
||||
|
||||
@@ -16,166 +16,165 @@
|
||||
#include "../world/tile_element/SurfaceElement.h"
|
||||
#include "WaterSetHeightAction.h"
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
WaterRaiseAction::WaterRaiseAction(MapRange range)
|
||||
: _range(range)
|
||||
namespace OpenRCT2::GameActions
|
||||
{
|
||||
}
|
||||
|
||||
void WaterRaiseAction::AcceptParameters(GameActionParameterVisitor& visitor)
|
||||
{
|
||||
visitor.Visit(_range);
|
||||
}
|
||||
|
||||
uint16_t WaterRaiseAction::GetActionFlags() const
|
||||
{
|
||||
return GameAction::GetActionFlags();
|
||||
}
|
||||
|
||||
void WaterRaiseAction::Serialise(DataSerialiser& stream)
|
||||
{
|
||||
GameAction::Serialise(stream);
|
||||
|
||||
stream << DS_TAG(_range);
|
||||
}
|
||||
|
||||
GameActions::Result WaterRaiseAction::Query() const
|
||||
{
|
||||
return QueryExecute(false);
|
||||
}
|
||||
|
||||
GameActions::Result WaterRaiseAction::Execute() const
|
||||
{
|
||||
return QueryExecute(true);
|
||||
}
|
||||
|
||||
GameActions::Result WaterRaiseAction::QueryExecute(bool isExecuting) const
|
||||
{
|
||||
auto res = GameActions::Result();
|
||||
|
||||
auto validRange = ClampRangeWithinMap(_range);
|
||||
res.Position.x = ((validRange.GetLeft() + validRange.GetRight()) / 2) + 16;
|
||||
res.Position.y = ((validRange.GetTop() + validRange.GetBottom()) / 2) + 16;
|
||||
int32_t z = TileElementHeight(res.Position);
|
||||
int16_t waterHeight = TileElementWaterHeight(res.Position);
|
||||
if (waterHeight != 0)
|
||||
WaterRaiseAction::WaterRaiseAction(MapRange range)
|
||||
: _range(range)
|
||||
{
|
||||
z = waterHeight;
|
||||
}
|
||||
res.Position.z = z;
|
||||
res.Expenditure = ExpenditureType::landscaping;
|
||||
|
||||
auto maxHeight = GetHighestHeight(validRange) / kCoordsZStep;
|
||||
bool hasChanged = false;
|
||||
bool withinOwnership = false;
|
||||
for (int32_t y = validRange.GetTop(); y <= validRange.GetBottom(); y += kCoordsXYStep)
|
||||
void WaterRaiseAction::AcceptParameters(GameActionParameterVisitor& visitor)
|
||||
{
|
||||
for (int32_t x = validRange.GetLeft(); x <= validRange.GetRight(); x += kCoordsXYStep)
|
||||
visitor.Visit(_range);
|
||||
}
|
||||
|
||||
uint16_t WaterRaiseAction::GetActionFlags() const
|
||||
{
|
||||
return GameAction::GetActionFlags();
|
||||
}
|
||||
|
||||
void WaterRaiseAction::Serialise(DataSerialiser& stream)
|
||||
{
|
||||
GameAction::Serialise(stream);
|
||||
|
||||
stream << DS_TAG(_range);
|
||||
}
|
||||
|
||||
Result WaterRaiseAction::Query() const
|
||||
{
|
||||
return QueryExecute(false);
|
||||
}
|
||||
|
||||
Result WaterRaiseAction::Execute() const
|
||||
{
|
||||
return QueryExecute(true);
|
||||
}
|
||||
|
||||
Result WaterRaiseAction::QueryExecute(bool isExecuting) const
|
||||
{
|
||||
auto res = Result();
|
||||
|
||||
auto validRange = ClampRangeWithinMap(_range);
|
||||
res.Position.x = ((validRange.GetLeft() + validRange.GetRight()) / 2) + 16;
|
||||
res.Position.y = ((validRange.GetTop() + validRange.GetBottom()) / 2) + 16;
|
||||
int32_t z = TileElementHeight(res.Position);
|
||||
int16_t waterHeight = TileElementWaterHeight(res.Position);
|
||||
if (waterHeight != 0)
|
||||
{
|
||||
if (!LocationValid({ x, y }))
|
||||
continue;
|
||||
z = waterHeight;
|
||||
}
|
||||
res.Position.z = z;
|
||||
res.Expenditure = ExpenditureType::landscaping;
|
||||
|
||||
auto surfaceElement = MapGetSurfaceElementAt(CoordsXY{ x, y });
|
||||
if (surfaceElement == nullptr)
|
||||
continue;
|
||||
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !getGameState().cheats.sandboxMode)
|
||||
auto maxHeight = GetHighestHeight(validRange) / kCoordsZStep;
|
||||
bool hasChanged = false;
|
||||
bool withinOwnership = false;
|
||||
for (int32_t y = validRange.GetTop(); y <= validRange.GetBottom(); y += kCoordsXYStep)
|
||||
{
|
||||
for (int32_t x = validRange.GetLeft(); x <= validRange.GetRight(); x += kCoordsXYStep)
|
||||
{
|
||||
if (!MapIsLocationInPark(CoordsXY{ x, y }))
|
||||
{
|
||||
if (!LocationValid({ x, y }))
|
||||
continue;
|
||||
|
||||
auto surfaceElement = MapGetSurfaceElementAt(CoordsXY{ x, y });
|
||||
if (surfaceElement == nullptr)
|
||||
continue;
|
||||
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !getGameState().cheats.sandboxMode)
|
||||
{
|
||||
if (!MapIsLocationInPark(CoordsXY{ x, y }))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
withinOwnership = true;
|
||||
withinOwnership = true;
|
||||
|
||||
uint8_t height = surfaceElement->GetWaterHeight() / kCoordsZStep;
|
||||
uint8_t height = surfaceElement->GetWaterHeight() / kCoordsZStep;
|
||||
|
||||
if (surfaceElement->BaseHeight > maxHeight)
|
||||
continue;
|
||||
|
||||
if (height != 0)
|
||||
{
|
||||
if (height > maxHeight)
|
||||
if (surfaceElement->BaseHeight > maxHeight)
|
||||
continue;
|
||||
if (height + 2 > UINT8_MAX)
|
||||
|
||||
if (height != 0)
|
||||
{
|
||||
height = UINT8_MAX;
|
||||
if (height > maxHeight)
|
||||
continue;
|
||||
if (height + 2 > UINT8_MAX)
|
||||
{
|
||||
height = UINT8_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
height += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
height += 2;
|
||||
height = surfaceElement->BaseHeight + 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
height = surfaceElement->BaseHeight + 2;
|
||||
}
|
||||
auto waterSetHeightAction = WaterSetHeightAction({ x, y }, height);
|
||||
waterSetHeightAction.SetFlags(GetFlags());
|
||||
auto result = isExecuting ? GameActions::ExecuteNested(&waterSetHeightAction)
|
||||
: GameActions::QueryNested(&waterSetHeightAction);
|
||||
if (result.Error == GameActions::Status::Ok)
|
||||
{
|
||||
res.Cost += result.Cost;
|
||||
hasChanged = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.ErrorTitle = STR_CANT_RAISE_WATER_LEVEL_HERE;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!withinOwnership)
|
||||
{
|
||||
return GameActions::Result(
|
||||
GameActions::Status::Disallowed, STR_CANT_RAISE_WATER_LEVEL_HERE, STR_LAND_NOT_OWNED_BY_PARK);
|
||||
}
|
||||
|
||||
if (isExecuting && hasChanged)
|
||||
{
|
||||
OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::LayingOutWater, res.Position);
|
||||
}
|
||||
// Force ride construction to recheck area
|
||||
_currentTrackSelectionFlags.set(TrackSelectionFlag::recheck);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uint16_t WaterRaiseAction::GetHighestHeight(const MapRange& validRange) const
|
||||
{
|
||||
// The highest height to raise the water to is the lowest water level in the selection
|
||||
uint16_t maxHeight = 255 * kCoordsZStep;
|
||||
for (int32_t y = validRange.GetTop(); y <= validRange.GetBottom(); y += kCoordsXYStep)
|
||||
{
|
||||
for (int32_t x = validRange.GetLeft(); x <= validRange.GetRight(); x += kCoordsXYStep)
|
||||
{
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !getGameState().cheats.sandboxMode)
|
||||
{
|
||||
if (!MapIsLocationInPark(CoordsXY{ x, y }))
|
||||
auto waterSetHeightAction = WaterSetHeightAction({ x, y }, height);
|
||||
waterSetHeightAction.SetFlags(GetFlags());
|
||||
auto result = isExecuting ? ExecuteNested(&waterSetHeightAction) : QueryNested(&waterSetHeightAction);
|
||||
if (result.Error == Status::Ok)
|
||||
{
|
||||
continue;
|
||||
res.Cost += result.Cost;
|
||||
hasChanged = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.ErrorTitle = STR_CANT_RAISE_WATER_LEVEL_HERE;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
auto* surfaceElement = MapGetSurfaceElementAt(CoordsXY{ x, y });
|
||||
if (surfaceElement == nullptr)
|
||||
continue;
|
||||
|
||||
auto height = surfaceElement->GetBaseZ();
|
||||
if (surfaceElement->GetWaterHeight() > 0)
|
||||
{
|
||||
height = surfaceElement->GetWaterHeight();
|
||||
}
|
||||
|
||||
if (maxHeight > height)
|
||||
{
|
||||
maxHeight = height;
|
||||
}
|
||||
}
|
||||
|
||||
if (!withinOwnership)
|
||||
{
|
||||
return Result(Status::Disallowed, STR_CANT_RAISE_WATER_LEVEL_HERE, STR_LAND_NOT_OWNED_BY_PARK);
|
||||
}
|
||||
|
||||
if (isExecuting && hasChanged)
|
||||
{
|
||||
OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::LayingOutWater, res.Position);
|
||||
}
|
||||
// Force ride construction to recheck area
|
||||
_currentTrackSelectionFlags.set(TrackSelectionFlag::recheck);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return maxHeight;
|
||||
}
|
||||
uint16_t WaterRaiseAction::GetHighestHeight(const MapRange& validRange) const
|
||||
{
|
||||
// The highest height to raise the water to is the lowest water level in the selection
|
||||
uint16_t maxHeight = 255 * kCoordsZStep;
|
||||
for (int32_t y = validRange.GetTop(); y <= validRange.GetBottom(); y += kCoordsXYStep)
|
||||
{
|
||||
for (int32_t x = validRange.GetLeft(); x <= validRange.GetRight(); x += kCoordsXYStep)
|
||||
{
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !getGameState().cheats.sandboxMode)
|
||||
{
|
||||
if (!MapIsLocationInPark(CoordsXY{ x, y }))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
auto* surfaceElement = MapGetSurfaceElementAt(CoordsXY{ x, y });
|
||||
if (surfaceElement == nullptr)
|
||||
continue;
|
||||
|
||||
auto height = surfaceElement->GetBaseZ();
|
||||
if (surfaceElement->GetWaterHeight() > 0)
|
||||
{
|
||||
height = surfaceElement->GetWaterHeight();
|
||||
}
|
||||
|
||||
if (maxHeight > height)
|
||||
{
|
||||
maxHeight = height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return maxHeight;
|
||||
}
|
||||
} // namespace OpenRCT2::GameActions
|
||||
|
||||
@@ -11,24 +11,27 @@
|
||||
|
||||
#include "GameAction.h"
|
||||
|
||||
class WaterRaiseAction final : public GameActionBase<GameCommand::RaiseWater>
|
||||
namespace OpenRCT2::GameActions
|
||||
{
|
||||
private:
|
||||
MapRange _range;
|
||||
class WaterRaiseAction final : public GameActionBase<GameCommand::RaiseWater>
|
||||
{
|
||||
private:
|
||||
MapRange _range;
|
||||
|
||||
public:
|
||||
WaterRaiseAction() = default;
|
||||
WaterRaiseAction(MapRange range);
|
||||
public:
|
||||
WaterRaiseAction() = default;
|
||||
WaterRaiseAction(MapRange range);
|
||||
|
||||
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 QueryExecute(bool isExecuting) const;
|
||||
uint16_t GetHighestHeight(const MapRange& validRange) const;
|
||||
};
|
||||
private:
|
||||
Result QueryExecute(bool isExecuting) const;
|
||||
uint16_t GetHighestHeight(const MapRange& validRange) const;
|
||||
};
|
||||
} // namespace OpenRCT2::GameActions
|
||||
|
||||
@@ -19,151 +19,149 @@
|
||||
#include "../world/Wall.h"
|
||||
#include "../world/tile_element/SurfaceElement.h"
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
WaterSetHeightAction::WaterSetHeightAction(const CoordsXY& coords, uint8_t height)
|
||||
: _coords(coords)
|
||||
, _height(height)
|
||||
namespace OpenRCT2::GameActions
|
||||
{
|
||||
}
|
||||
|
||||
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 * kCoordsZStep };
|
||||
|
||||
auto& gameState = getGameState();
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !gameState.cheats.sandboxMode
|
||||
&& gameState.park.flags & PARK_FLAGS_FORBID_LANDSCAPE_CHANGES)
|
||||
WaterSetHeightAction::WaterSetHeightAction(const CoordsXY& coords, uint8_t height)
|
||||
: _coords(coords)
|
||||
, _height(height)
|
||||
{
|
||||
return GameActions::Result(GameActions::Status::Disallowed, kStringIdNone, STR_FORBIDDEN_BY_THE_LOCAL_AUTHORITY);
|
||||
}
|
||||
|
||||
StringId errorMsg = CheckParameters();
|
||||
if (errorMsg != kStringIdNone)
|
||||
void WaterSetHeightAction::AcceptParameters(GameActionParameterVisitor& visitor)
|
||||
{
|
||||
return GameActions::Result(GameActions::Status::InvalidParameters, kStringIdNone, errorMsg);
|
||||
visitor.Visit(_coords);
|
||||
visitor.Visit("height", _height);
|
||||
}
|
||||
|
||||
if (!LocationValid(_coords))
|
||||
uint16_t WaterSetHeightAction::GetActionFlags() const
|
||||
{
|
||||
return GameActions::Result(GameActions::Status::NotOwned, kStringIdNone, STR_LAND_NOT_OWNED_BY_PARK);
|
||||
return GameAction::GetActionFlags();
|
||||
}
|
||||
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !gameState.cheats.sandboxMode)
|
||||
void WaterSetHeightAction::Serialise(DataSerialiser& stream)
|
||||
{
|
||||
if (!MapIsLocationInPark(_coords))
|
||||
GameAction::Serialise(stream);
|
||||
|
||||
stream << DS_TAG(_coords) << DS_TAG(_height);
|
||||
}
|
||||
|
||||
Result WaterSetHeightAction::Query() const
|
||||
{
|
||||
auto res = Result();
|
||||
res.Expenditure = ExpenditureType::landscaping;
|
||||
res.Position = { _coords, _height * kCoordsZStep };
|
||||
|
||||
auto& gameState = getGameState();
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !gameState.cheats.sandboxMode
|
||||
&& gameState.park.flags & PARK_FLAGS_FORBID_LANDSCAPE_CHANGES)
|
||||
{
|
||||
return GameActions::Result(GameActions::Status::Disallowed, kStringIdNone, STR_LAND_NOT_OWNED_BY_PARK);
|
||||
return Result(Status::Disallowed, kStringIdNone, STR_FORBIDDEN_BY_THE_LOCAL_AUTHORITY);
|
||||
}
|
||||
|
||||
StringId errorMsg = CheckParameters();
|
||||
if (errorMsg != kStringIdNone)
|
||||
{
|
||||
return Result(Status::InvalidParameters, kStringIdNone, errorMsg);
|
||||
}
|
||||
|
||||
if (!LocationValid(_coords))
|
||||
{
|
||||
return Result(Status::NotOwned, kStringIdNone, STR_LAND_NOT_OWNED_BY_PARK);
|
||||
}
|
||||
|
||||
if (gLegacyScene != LegacyScene::scenarioEditor && !gameState.cheats.sandboxMode)
|
||||
{
|
||||
if (!MapIsLocationInPark(_coords))
|
||||
{
|
||||
return Result(Status::Disallowed, kStringIdNone, 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 Result(Status::InvalidParameters, STR_ERR_INVALID_PARAMETER, STR_ERR_SURFACE_ELEMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
int32_t zHigh = surfaceElement->GetBaseZ();
|
||||
int32_t zLow = _height * kCoordsZStep;
|
||||
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 != Status::Ok)
|
||||
{
|
||||
return res2;
|
||||
}
|
||||
if (surfaceElement->HasTrackThatNeedsWater())
|
||||
{
|
||||
return Result(Status::Disallowed, STR_ERR_INVALID_PARAMETER, STR_ERR_TRACK_ON_THIS_TILE_NEEDS_WATER);
|
||||
}
|
||||
|
||||
res.Cost = 250;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
SurfaceElement* surfaceElement = MapGetSurfaceElementAt(_coords);
|
||||
if (surfaceElement == nullptr)
|
||||
Result WaterSetHeightAction::Execute() const
|
||||
{
|
||||
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);
|
||||
auto res = Result();
|
||||
res.Expenditure = ExpenditureType::landscaping;
|
||||
res.Position = { _coords, _height * kCoordsZStep };
|
||||
|
||||
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 Result(Status::InvalidParameters, STR_ERR_INVALID_PARAMETER, STR_ERR_SURFACE_ELEMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (_height > surfaceElement->BaseHeight)
|
||||
{
|
||||
surfaceElement->SetWaterHeight(_height * kCoordsZStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
surfaceElement->SetWaterHeight(0);
|
||||
}
|
||||
MapInvalidateTileFull(_coords);
|
||||
|
||||
res.Cost = 250;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int32_t zHigh = surfaceElement->GetBaseZ();
|
||||
int32_t zLow = _height * kCoordsZStep;
|
||||
if (surfaceElement->GetWaterHeight() > 0)
|
||||
StringId WaterSetHeightAction::CheckParameters() const
|
||||
{
|
||||
zHigh = surfaceElement->GetWaterHeight();
|
||||
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 kStringIdNone;
|
||||
}
|
||||
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 * kCoordsZStep };
|
||||
|
||||
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 * kCoordsZStep);
|
||||
}
|
||||
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 kStringIdNone;
|
||||
}
|
||||
} // namespace OpenRCT2::GameActions
|
||||
|
||||
@@ -11,24 +11,27 @@
|
||||
|
||||
#include "GameAction.h"
|
||||
|
||||
class WaterSetHeightAction final : public GameActionBase<GameCommand::SetWaterHeight>
|
||||
namespace OpenRCT2::GameActions
|
||||
{
|
||||
private:
|
||||
CoordsXY _coords;
|
||||
uint8_t _height{};
|
||||
class WaterSetHeightAction final : public GameActionBase<GameCommand::SetWaterHeight>
|
||||
{
|
||||
private:
|
||||
CoordsXY _coords;
|
||||
uint8_t _height{};
|
||||
|
||||
public:
|
||||
WaterSetHeightAction() = default;
|
||||
WaterSetHeightAction(const CoordsXY& coords, uint8_t height);
|
||||
public:
|
||||
WaterSetHeightAction() = default;
|
||||
WaterSetHeightAction(const CoordsXY& coords, uint8_t height);
|
||||
|
||||
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:
|
||||
StringId CheckParameters() const;
|
||||
};
|
||||
private:
|
||||
StringId CheckParameters() const;
|
||||
};
|
||||
} // namespace OpenRCT2::GameActions
|
||||
|
||||
Reference in New Issue
Block a user