1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 11:03:00 +01:00

Create struct for footpath slope

This commit is contained in:
Gymnasiast
2025-10-11 12:57:12 +02:00
parent 20ca7ea3e7
commit c2c834df15
12 changed files with 123 additions and 93 deletions

View File

@@ -51,7 +51,7 @@ using namespace OpenRCT2::Numerics;
namespace OpenRCT2::Ui::Windows
{
static money64 FootpathProvisionalSet(
ObjectEntryIndex type, ObjectEntryIndex railingsType, const CoordsXYZ& footpathLoc, int32_t slope,
ObjectEntryIndex type, ObjectEntryIndex railingsType, const CoordsXYZ& footpathLoc, FootpathSlope slope,
PathConstructFlags constructFlags);
enum class PathConstructionMode : uint8_t
@@ -82,7 +82,7 @@ namespace OpenRCT2::Ui::Windows
{
ObjectEntryIndex type;
CoordsXYZ position;
uint8_t slope;
FootpathSlope slope;
ProvisionalPathFlags flags;
ObjectEntryIndex surfaceIndex;
ObjectEntryIndex railingsIndex;
@@ -533,7 +533,7 @@ namespace OpenRCT2::Ui::Windows
FootpathPlacementResult FootpathGetPlacementFromScreenCoords(const ScreenCoordsXY& screenCoords)
{
if (_footpathPlaceZ > 0)
return { _footpathPlaceZ, kTileSlopeFlat };
return { _footpathPlaceZ, {} };
auto info = GetMapCoordinatesFromPos(
screenCoords, EnumsToFlags(ViewportInteractionItem::terrain, ViewportInteractionItem::footpath));
@@ -566,7 +566,7 @@ namespace OpenRCT2::Ui::Windows
ObjectEntryIndex railings = gFootpathSelection.Railings;
CoordsXYZ footpathLoc;
int32_t slope;
FootpathSlope slope;
FootpathGetNextPathInfo(&type, footpathLoc, &slope);
auto pathConstructFlags = FootpathCreateConstructFlags(type);
@@ -583,7 +583,7 @@ namespace OpenRCT2::Ui::Windows
_provisionalFootpath.flags.flip(ProvisionalPathFlag::showArrow);
CoordsXYZ footpathLoc;
int32_t slope;
FootpathSlope slope;
FootpathGetNextPathInfo(nullptr, footpathLoc, &slope);
gMapSelectArrowPosition = footpathLoc;
gMapSelectArrowDirection = _footpathConstructDirection;
@@ -946,10 +946,11 @@ namespace OpenRCT2::Ui::Windows
auto pathElement = info.Element->AsPath();
if (pathElement != nullptr)
{
auto slope = pathElement->GetSlopeDirection();
auto slopeDirection = pathElement->GetSlopeDirection();
FootpathSlope slope = { FootpathSlopeType::flat, slopeDirection };
if (pathElement->IsSloped())
{
slope |= FOOTPATH_PROPERTIES_FLAG_IS_SLOPED;
slope.type = FootpathSlopeType::sloped;
}
return { pathElement->GetBaseZ(), slope };
}
@@ -1166,7 +1167,7 @@ namespace OpenRCT2::Ui::Windows
FootpathUpdateProvisional();
ObjectEntryIndex type;
int32_t slope;
FootpathSlope slope;
CoordsXYZ footpathLoc;
FootpathGetNextPathInfo(&type, footpathLoc, &slope);
@@ -1416,7 +1417,7 @@ namespace OpenRCT2::Ui::Windows
*
* rct2: 0x006A7B20
*/
void FootpathGetNextPathInfo(ObjectEntryIndex* type, CoordsXYZ& footpathLoc, int32_t* slope)
void FootpathGetNextPathInfo(ObjectEntryIndex* type, CoordsXYZ& footpathLoc, FootpathSlope* slope)
{
auto direction = _footpathConstructDirection;
footpathLoc.x = _footpathConstructFromPosition.x + CoordsDirectionDelta[direction].x;
@@ -1426,14 +1427,14 @@ namespace OpenRCT2::Ui::Windows
{
*type = gFootpathSelection.GetSelectedSurface();
}
*slope = kTileSlopeFlat;
*slope = {};
if (_footpathConstructSlope != 0)
{
*slope = _footpathConstructDirection | kTileSlopeSCornerUp;
*slope = { FootpathSlopeType::sloped, _footpathConstructDirection };
if (_footpathConstructSlope != 2)
{
footpathLoc.z -= kPathHeightStep;
*slope ^= kTileSlopeECornerUp;
slope->direction = DirectionReverse(slope->direction);
}
}
}
@@ -1686,7 +1687,7 @@ namespace OpenRCT2::Ui::Windows
* rct2: 0x006A76FF
*/
static money64 FootpathProvisionalSet(
ObjectEntryIndex type, ObjectEntryIndex railingsType, const CoordsXYZ& footpathLoc, int32_t slope,
ObjectEntryIndex type, ObjectEntryIndex railingsType, const CoordsXYZ& footpathLoc, FootpathSlope slope,
PathConstructFlags constructFlags)
{
FootpathRemoveProvisional();
@@ -1725,7 +1726,7 @@ namespace OpenRCT2::Ui::Windows
VirtualFloorSetHeight(0);
}
else if (
_provisionalFootpath.slope == kTileSlopeFlat
_provisionalFootpath.slope.type == FootpathSlopeType::flat
|| _provisionalFootpath.position.z < _footpathConstructFromPosition.z)
{
// Going either straight on, or down.

View File

@@ -30,7 +30,7 @@
namespace OpenRCT2::GameActions
{
FootpathLayoutPlaceAction::FootpathLayoutPlaceAction(
const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, ObjectEntryIndex railingsType, uint8_t edges,
const CoordsXYZ& loc, FootpathSlope slope, ObjectEntryIndex type, ObjectEntryIndex railingsType, uint8_t edges,
PathConstructFlags constructFlags)
: _loc(loc)
, _slope(slope)
@@ -52,7 +52,8 @@ namespace OpenRCT2::GameActions
void FootpathLayoutPlaceAction::AcceptParameters(GameActionParameterVisitor& visitor)
{
visitor.Visit(_loc);
visitor.Visit("slope", _slope);
visitor.Visit("slopeType", _slope.type);
visitor.Visit("slopeDirection", _slope.direction);
visitor.Visit("object", _type);
visitor.Visit("railingsObject", _railingsType);
visitor.Visit("edges", _edges);
@@ -131,9 +132,9 @@ namespace OpenRCT2::GameActions
QuarterTile quarterTile{ 0b1111, 0 };
auto zLow = _loc.z;
auto zHigh = zLow + kPathClearance;
if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED)
if (_slope.type == FootpathSlopeType::sloped)
{
quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope & kTileElementDirectionMask);
quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope.direction);
zHigh += kPathHeightStep;
}
@@ -151,8 +152,8 @@ namespace OpenRCT2::GameActions
// 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 crossingMode = isQueue || (_slope.type != FootpathSlopeType::flat) ? CreateCrossingMode::none
: CreateCrossingMode::pathOverTrack;
auto canBuild = MapCanConstructWithClearAt(
{ _loc, zLow, zHigh }, &MapPlaceNonSceneryClearFunc, quarterTile, GetFlags(), kTileSlopeFlat, crossingMode);
if (!entrancePath && canBuild.Error != Status::Ok)
@@ -200,9 +201,9 @@ namespace OpenRCT2::GameActions
QuarterTile quarterTile{ 0b1111, 0 };
auto zLow = _loc.z;
auto zHigh = zLow + kPathClearance;
if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED)
if (_slope.type == FootpathSlopeType::sloped)
{
quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope & kTileElementDirectionMask);
quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope.direction);
zHigh += kPathHeightStep;
}
@@ -220,8 +221,8 @@ namespace OpenRCT2::GameActions
// 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 crossingMode = isQueue || (_slope.type != FootpathSlopeType::flat) ? CreateCrossingMode::none
: CreateCrossingMode::pathOverTrack;
auto canBuild = MapCanConstructWithClearAt(
{ _loc, zLow, zHigh }, &MapPlaceNonSceneryClearFunc, quarterTile, GAME_COMMAND_FLAG_APPLY | GetFlags(),
kTileSlopeFlat, crossingMode);
@@ -274,8 +275,8 @@ namespace OpenRCT2::GameActions
pathElement->SetSurfaceEntryIndex(_type);
pathElement->SetRailingsEntryIndex(_railingsType);
}
pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK);
pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED);
pathElement->SetSlopeDirection(_slope.direction);
pathElement->SetSloped(_slope.type == FootpathSlopeType::sloped);
pathElement->SetIsQueue(isQueue);
pathElement->SetAddition(0);
pathElement->SetRideIndex(RideId::GetNull());

View File

@@ -18,7 +18,7 @@ namespace OpenRCT2::GameActions
{
private:
CoordsXYZ _loc;
uint8_t _slope{};
FootpathSlope _slope{};
ObjectEntryIndex _type{};
ObjectEntryIndex _railingsType{};
uint8_t _edges{};
@@ -27,7 +27,7 @@ namespace OpenRCT2::GameActions
public:
FootpathLayoutPlaceAction() = default;
FootpathLayoutPlaceAction(
const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, ObjectEntryIndex railingsType, uint8_t edges,
const CoordsXYZ& loc, FootpathSlope slope, ObjectEntryIndex type, ObjectEntryIndex railingsType, uint8_t edges,
PathConstructFlags constructFlags = 0);
void AcceptParameters(GameActionParameterVisitor&) final;

View File

@@ -39,7 +39,7 @@
namespace OpenRCT2::GameActions
{
FootpathPlaceAction::FootpathPlaceAction(
const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, ObjectEntryIndex railingsType, Direction direction,
const CoordsXYZ& loc, FootpathSlope slope, ObjectEntryIndex type, ObjectEntryIndex railingsType, Direction direction,
PathConstructFlags constructFlags)
: _loc(loc)
, _slope(slope)
@@ -56,7 +56,8 @@ namespace OpenRCT2::GameActions
visitor.Visit("object", _type);
visitor.Visit("railingsObject", _railingsType);
visitor.Visit("direction", _direction);
visitor.Visit("slope", _slope);
visitor.Visit("slopeType", _slope.type);
visitor.Visit("slopeDirection", _slope.direction);
visitor.Visit("constructFlags", _constructFlags);
}
@@ -92,7 +93,7 @@ namespace OpenRCT2::GameActions
return Result(Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_LAND_NOT_OWNED_BY_PARK);
}
if (_slope & SLOPE_IS_IRREGULAR_FLAG)
if (_slope.type == FootpathSlopeType::irregular || _slope.type == FootpathSlopeType::raise)
{
return Result(Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_LAND_SLOPE_UNSUITABLE);
}
@@ -116,7 +117,7 @@ namespace OpenRCT2::GameActions
auto intent = Intent(INTENT_ACTION_REMOVE_PROVISIONAL_FOOTPATH);
ContextBroadcastIntent(&intent);
auto tileElement = MapGetFootpathElementSlope(_loc, _slope);
auto tileElement = MapGetFootpathElementWithSlope(_loc, _slope);
if (tileElement == nullptr)
{
return ElementInsertQuery(std::move(res));
@@ -149,14 +150,15 @@ namespace OpenRCT2::GameActions
auto zLow = _loc.z;
auto zHigh = zLow + kPathClearance;
WallRemoveIntersectingWalls(
{ _loc, zLow, zHigh + ((_slope & kTileSlopeRaisedCornersMask) ? 16 : 0) }, DirectionReverse(_direction));
{ _loc, zLow, zHigh + ((_slope.type == FootpathSlopeType::sloped) ? 16 : 0) },
DirectionReverse(_direction));
WallRemoveIntersectingWalls(
{ _loc.x - CoordsDirectionDelta[_direction].x, _loc.y - CoordsDirectionDelta[_direction].y, zLow, zHigh },
_direction);
}
}
auto tileElement = MapGetFootpathElementSlope(_loc, _slope);
auto tileElement = MapGetFootpathElementWithSlope(_loc, _slope);
if (tileElement == nullptr)
{
return ElementInsertExecute(std::move(res));
@@ -295,9 +297,9 @@ namespace OpenRCT2::GameActions
QuarterTile quarterTile{ 0b1111, 0 };
auto zLow = _loc.z;
auto zHigh = zLow + kPathClearance;
if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED)
if (_slope.type == FootpathSlopeType::sloped)
{
quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope & kTileElementDirectionMask);
quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope.direction);
zHigh += kPathHeightStep;
}
@@ -315,8 +317,8 @@ namespace OpenRCT2::GameActions
// 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 crossingMode = isQueue || (_slope.type != FootpathSlopeType::flat) ? CreateCrossingMode::none
: CreateCrossingMode::pathOverTrack;
auto canBuild = MapCanConstructWithClearAt(
{ _loc, zLow, zHigh }, &MapPlaceNonSceneryClearFunc, quarterTile, GetFlags(), kTileSlopeFlat, crossingMode);
if (!entrancePath && canBuild.Error != Status::Ok)
@@ -363,9 +365,9 @@ namespace OpenRCT2::GameActions
QuarterTile quarterTile{ 0b1111, 0 };
auto zLow = _loc.z;
auto zHigh = zLow + kPathClearance;
if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED)
if (_slope.type == FootpathSlopeType::sloped)
{
quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope & kTileElementDirectionMask);
quarterTile = QuarterTile{ 0b1111, 0b1100 }.Rotate(_slope.direction);
zHigh += kPathHeightStep;
}
@@ -383,8 +385,8 @@ namespace OpenRCT2::GameActions
// 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 crossingMode = isQueue || (_slope.type != FootpathSlopeType::flat) ? CreateCrossingMode::none
: CreateCrossingMode::pathOverTrack;
auto canBuild = MapCanConstructWithClearAt(
{ _loc, zLow, zHigh }, &MapPlaceNonSceneryClearFunc, quarterTile, GAME_COMMAND_FLAG_APPLY | GetFlags(),
kTileSlopeFlat, crossingMode);
@@ -436,8 +438,8 @@ namespace OpenRCT2::GameActions
pathElement->SetSurfaceEntryIndex(_type);
pathElement->SetRailingsEntryIndex(_railingsType);
}
pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK);
pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED);
pathElement->SetSlopeDirection(_slope.direction);
pathElement->SetSloped(_slope.type == FootpathSlopeType::sloped);
pathElement->SetIsQueue(isQueue);
pathElement->SetAddition(0);
pathElement->SetRideIndex(RideId::GetNull());
@@ -525,10 +527,9 @@ namespace OpenRCT2::GameActions
MapInvalidateTileFull(_loc);
}
PathElement* FootpathPlaceAction::MapGetFootpathElementSlope(const CoordsXYZ& footpathPos, int32_t slope) const
PathElement* FootpathPlaceAction::MapGetFootpathElementWithSlope(const CoordsXYZ& footpathPos, FootpathSlope slope) const
{
const bool isSloped = slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED;
const auto slopeDirection = slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK;
const bool isSloped = slope.type == FootpathSlopeType::sloped;
for (auto* pathElement : TileElementsView<PathElement>(footpathPos))
{
@@ -536,7 +537,7 @@ namespace OpenRCT2::GameActions
continue;
if (pathElement->IsSloped() != isSloped)
continue;
if (pathElement->GetSlopeDirection() != slopeDirection)
if (pathElement->GetSlopeDirection() != slope.direction)
continue;
return pathElement;
}

View File

@@ -18,7 +18,7 @@ namespace OpenRCT2::GameActions
{
private:
CoordsXYZ _loc;
uint8_t _slope{};
FootpathSlope _slope{};
ObjectEntryIndex _type{};
ObjectEntryIndex _railingsType{};
Direction _direction{ kInvalidDirection };
@@ -27,7 +27,7 @@ namespace OpenRCT2::GameActions
public:
FootpathPlaceAction() = default;
FootpathPlaceAction(
const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, ObjectEntryIndex railingsType,
const CoordsXYZ& loc, FootpathSlope slope, ObjectEntryIndex type, ObjectEntryIndex railingsType,
Direction direction = kInvalidDirection, PathConstructFlags constructFlags = 0);
void AcceptParameters(GameActionParameterVisitor&) final;
@@ -44,7 +44,7 @@ namespace OpenRCT2::GameActions
Result ElementInsertExecute(Result res) const;
void AutomaticallySetPeepSpawn() const;
void RemoveIntersectingWalls(PathElement* pathElement) const;
PathElement* MapGetFootpathElementSlope(const CoordsXYZ& footpathPos, int32_t slope) const;
PathElement* MapGetFootpathElementWithSlope(const CoordsXYZ& footpathPos, FootpathSlope slope) const;
bool IsSameAsPathElement(const PathElement* pathElement) const;
bool IsSameAsEntranceElement(const EntranceElement& entranceElement) const;
};

View File

@@ -17,6 +17,7 @@
#include "../ride/RideColour.h"
#include "../ride/TrackDesign.h"
#include "../world/Banner.h"
#include "../world/Footpath.h"
#include "../world/Location.hpp"
#include "../world/tile_element/TileElement.h"
#include "DataSerialiserTag.h"
@@ -989,3 +990,28 @@ struct DataSerializerTraitsT<Banner>
stream->Write(msg, strlen(msg));
}
};
template<>
struct DataSerializerTraitsT<FootpathSlope>
{
static void encode(OpenRCT2::IStream* stream, const FootpathSlope& slope)
{
uint8_t combined = (EnumValue(slope.type) << 2) | (slope.direction % kNumOrthogonalDirections);
stream->WriteValue(combined);
}
static void decode(OpenRCT2::IStream* stream, FootpathSlope& slope)
{
auto combined = stream->ReadValue<uint8_t>();
auto type = static_cast<FootpathSlopeType>(combined >> 2);
Direction direction = combined & 0b00000011;
slope = FootpathSlope{ type, direction };
}
static void log(OpenRCT2::IStream* stream, const FootpathSlope& slope)
{
char msg[128] = {};
snprintf(msg, sizeof(msg), "FootpathSlope(type = %d, direction = %d)", EnumValue(slope.type), slope.direction);
stream->Write(msg, strlen(msg));
}
};

View File

@@ -194,7 +194,7 @@ static void PathPaintSlopedFences(
PaintSession& session, const PathElement& pathElement, uint16_t height, ImageId imageId, bool isQueue)
{
auto queueOffset = isQueue ? 14 : 0;
switch ((pathElement.GetSlopeDirection() + session.CurrentRotation) & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)
switch ((pathElement.GetSlopeDirection() + session.CurrentRotation) % kNumOrthogonalDirections)
{
case 0:
PaintAddImageAsParent(
@@ -630,7 +630,7 @@ static void PathPaintFencesAdditionsTunnels(
}
// This is about tunnel drawing
uint8_t direction = (pathElement.GetSlopeDirection() + session.CurrentRotation) & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK;
uint8_t direction = (pathElement.GetSlopeDirection() + session.CurrentRotation) % kNumOrthogonalDirections;
bool sloped = pathElement.IsSloped();
if (connectedEdges & EDGE_SE)
@@ -864,8 +864,7 @@ static ImageIndex PathPaintGetBaseImage(
ImageIndex surfaceBaseImageIndex = pathPaintInfo.SurfaceImageId;
if (pathElement.IsSloped())
{
auto directionOffset = (pathElement.GetSlopeDirection() + session.CurrentRotation)
& FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK;
auto directionOffset = (pathElement.GetSlopeDirection() + session.CurrentRotation) % kNumOrthogonalDirections;
surfaceBaseImageIndex += 16 + directionOffset;
}
else
@@ -973,8 +972,7 @@ void PathPaintBoxSupport(
ImageIndex bridgeBaseImageIndex;
if (pathElement.IsSloped())
{
auto directionOffset = (pathElement.GetSlopeDirection() + session.CurrentRotation)
& FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK;
auto directionOffset = (pathElement.GetSlopeDirection() + session.CurrentRotation) % kNumOrthogonalDirections;
bridgeBaseImageIndex = pathPaintInfo.BridgeImageId + 51 + directionOffset;
}
else
@@ -1028,8 +1026,7 @@ void PathPaintPoleSupport(
ImageIndex bridgeBaseImageIndex;
if (pathElement.IsSloped())
{
bridgeBaseImageIndex = ((pathElement.GetSlopeDirection() + session.CurrentRotation)
& FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)
bridgeBaseImageIndex = ((pathElement.GetSlopeDirection() + session.CurrentRotation) % kNumOrthogonalDirections)
+ pathPaintInfo.BridgeImageId + 16;
}
else

View File

@@ -655,9 +655,10 @@ static void ApplyPathFixes(const json_t& scenarioPatch)
for (auto coordinate : coordinates)
{
auto slope = direction != kInvalidDirection ? direction + 4 : 0;
auto slopeType = direction != kInvalidDirection ? FootpathSlopeType::sloped : FootpathSlopeType::flat;
auto footpathPlaceAction = GameActions::FootpathPlaceAction(
coordinate.ToCoordsXYZ(), slope, surfaceObjIndex, railingsObjIndex, direction, constructionFlags);
coordinate.ToCoordsXYZ(), { slopeType, direction }, surfaceObjIndex, railingsObjIndex, direction,
constructionFlags);
auto& gameState = getGameState();
auto result = footpathPlaceAction.Execute(gameState);
if (result.Error != GameActions::Status::Ok)

View File

@@ -1196,9 +1196,10 @@ static GameActions::Result TrackDesignPlaceSceneryElement(
{
flags |= GAME_COMMAND_FLAG_REPLAY;
}
uint8_t slope = (scenery.getSlopeDirection() + rotation) & 0x3;
uint8_t slopeDirection = (scenery.getSlopeDirection() + rotation) & 0x3;
FootpathSlope slope = { FootpathSlopeType::flat, slopeDirection };
if (scenery.hasSlope())
slope |= FOOTPATH_PROPERTIES_FLAG_IS_SLOPED;
slope.type = FootpathSlopeType::sloped;
uint8_t edges = Numerics::rol4(scenery.getEdges(), rotation);
PathConstructFlags constructFlags = 0;
if (scenery.isQueue())

View File

@@ -102,23 +102,13 @@ static constexpr uint8_t connected_path_count[] = {
};
/** rct2: 0x0098D8B4 */
static constexpr uint8_t kDefaultPathSlope[] = {
0,
SLOPE_IS_IRREGULAR_FLAG,
SLOPE_IS_IRREGULAR_FLAG,
FOOTPATH_PROPERTIES_FLAG_IS_SLOPED | 2,
SLOPE_IS_IRREGULAR_FLAG,
SLOPE_IS_IRREGULAR_FLAG,
FOOTPATH_PROPERTIES_FLAG_IS_SLOPED | 3,
RAISE_FOOTPATH_FLAG,
SLOPE_IS_IRREGULAR_FLAG,
FOOTPATH_PROPERTIES_FLAG_IS_SLOPED | 1,
SLOPE_IS_IRREGULAR_FLAG,
RAISE_FOOTPATH_FLAG,
FOOTPATH_PROPERTIES_FLAG_IS_SLOPED | 0,
RAISE_FOOTPATH_FLAG,
RAISE_FOOTPATH_FLAG,
SLOPE_IS_IRREGULAR_FLAG,
static constexpr FootpathSlope kDefaultPathSlope[] = {
{ FootpathSlopeType::flat }, { FootpathSlopeType::irregular }, { FootpathSlopeType::irregular },
{ FootpathSlopeType::sloped, 2 }, { FootpathSlopeType::irregular }, { FootpathSlopeType::irregular },
{ FootpathSlopeType::sloped, 3 }, { FootpathSlopeType::raise }, { FootpathSlopeType::irregular },
{ FootpathSlopeType::sloped, 1 }, { FootpathSlopeType::irregular }, { FootpathSlopeType::raise },
{ FootpathSlopeType::sloped, 0 }, { FootpathSlopeType::raise }, { FootpathSlopeType::raise },
{ FootpathSlopeType::irregular },
};
static bool entrance_has_direction(const EntranceElement& entranceElement, int32_t direction)
@@ -1923,10 +1913,10 @@ FootpathPlacementResult FootpathGetOnTerrainPlacement(const TileCoordsXY& locati
FootpathPlacementResult FootpathGetOnTerrainPlacement(const SurfaceElement& surfaceElement)
{
int32_t baseZ = surfaceElement.GetBaseZ();
uint8_t slope = kDefaultPathSlope[surfaceElement.GetSlope() & kTileSlopeRaisedCornersMask];
if (slope & RAISE_FOOTPATH_FLAG)
auto slope = kDefaultPathSlope[surfaceElement.GetSlope() & kTileSlopeRaisedCornersMask];
if (slope.type == FootpathSlopeType::raise)
{
slope &= ~RAISE_FOOTPATH_FLAG;
slope.type = FootpathSlopeType::flat;
baseZ += kPathHeightStep;
}

View File

@@ -76,10 +76,31 @@ struct FootpathSelection
}
};
enum class FootpathSlopeType : uint8_t
{
flat,
sloped,
/**
* Land has one corner down, raise the Z coordinate and place a flat piece.
*/
raise,
/**
* Terrain has a shape that allows for two different path slopes, and as such it cannot autoplace a piece
* without further context of the surrounding paths.
*/
irregular,
};
struct FootpathSlope
{
FootpathSlopeType type{};
Direction direction{};
};
struct FootpathPlacementResult
{
int32_t baseZ{};
uint8_t slope{};
FootpathSlope slope{};
bool isValid()
{

View File

@@ -32,15 +32,6 @@ namespace OpenRCT2
FOOTPATH_ELEMENT_TYPE_DIRECTION_MASK = (1 << 6) | (1 << 7),
};
// Masks and flags for values stored in TileElement.properties.path.type
enum
{
FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK = (1 << 0) | (1 << 1),
FOOTPATH_PROPERTIES_FLAG_IS_SLOPED = (1 << 2),
FOOTPATH_PROPERTIES_FLAG_HAS_QUEUE_BANNER = (1 << 3),
FOOTPATH_PROPERTIES_TYPE_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7),
};
// Masks and flags for values stored in TileElement.properties.path.edges
enum
{