Implement railing override logic

This commit is contained in:
Ted John 2021-04-14 01:34:07 +01:00
parent 476ee6ff5c
commit 23c709c197
12 changed files with 155 additions and 111 deletions

View File

@ -19,6 +19,7 @@
#include <openrct2/core/Guard.hpp> #include <openrct2/core/Guard.hpp>
#include <openrct2/localisation/Localisation.h> #include <openrct2/localisation/Localisation.h>
#include <openrct2/localisation/StringIds.h> #include <openrct2/localisation/StringIds.h>
#include <openrct2/object/FootpathObject.h>
#include <openrct2/object/TerrainEdgeObject.h> #include <openrct2/object/TerrainEdgeObject.h>
#include <openrct2/object/TerrainSurfaceObject.h> #include <openrct2/object/TerrainSurfaceObject.h>
#include <openrct2/ride/RideData.h> #include <openrct2/ride/RideData.h>
@ -1813,7 +1814,9 @@ static void window_tile_inspector_paint(rct_window* w, rct_drawpixelinfo* dpi)
{ {
// Details // Details
// Path name // Path name
rct_string_id pathNameId = tileElement->AsPath()->GetSurfaceEntry()->string_idx; auto legacyFootpathEntry = reinterpret_cast<rct_footpath_entry*>(
tileElement->AsPath()->GetSurfaceEntry()->GetLegacyData());
rct_string_id pathNameId = legacyFootpathEntry->string_idx;
DrawTextBasic(dpi, screenCoords, STR_TILE_INSPECTOR_PATH_NAME, &pathNameId, { COLOUR_WHITE }); DrawTextBasic(dpi, screenCoords, STR_TILE_INSPECTOR_PATH_NAME, &pathNameId, { COLOUR_WHITE });
// Path addition // Path addition

View File

@ -182,6 +182,7 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementUpdateExecute(PathElement*
} }
pathElement->SetSurfaceEntryIndex(_type & ~FOOTPATH_ELEMENT_INSERT_QUEUE); pathElement->SetSurfaceEntryIndex(_type & ~FOOTPATH_ELEMENT_INSERT_QUEUE);
pathElement->SetRailingEntryIndex(OBJECT_ENTRY_INDEX_NULL);
bool isQueue = _type & FOOTPATH_ELEMENT_INSERT_QUEUE; bool isQueue = _type & FOOTPATH_ELEMENT_INSERT_QUEUE;
pathElement->SetIsQueue(isQueue); pathElement->SetIsQueue(isQueue);
@ -348,6 +349,7 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementInsertExecute(GameActions::
pathElement->SetClearanceZ(zHigh); pathElement->SetClearanceZ(zHigh);
pathElement->SetSurfaceEntryIndex(_type & ~FOOTPATH_ELEMENT_INSERT_QUEUE); pathElement->SetSurfaceEntryIndex(_type & ~FOOTPATH_ELEMENT_INSERT_QUEUE);
pathElement->SetRailingEntryIndex(OBJECT_ENTRY_INDEX_NULL);
pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK); pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK);
pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED); pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED);
pathElement->SetIsQueue(_type & FOOTPATH_ELEMENT_INSERT_QUEUE); pathElement->SetIsQueue(_type & FOOTPATH_ELEMENT_INSERT_QUEUE);

View File

@ -235,6 +235,7 @@ GameActions::Result::Ptr FootpathPlaceFromTrackAction::ElementInsertExecute(Game
pathElement->SetClearanceZ(zHigh); pathElement->SetClearanceZ(zHigh);
pathElement->SetSurfaceEntryIndex(_type & ~FOOTPATH_ELEMENT_INSERT_QUEUE); pathElement->SetSurfaceEntryIndex(_type & ~FOOTPATH_ELEMENT_INSERT_QUEUE);
pathElement->SetRailingEntryIndex(OBJECT_ENTRY_INDEX_NULL);
pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK); pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK);
pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED); pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED);
pathElement->SetIsQueue(_type & FOOTPATH_ELEMENT_INSERT_QUEUE); pathElement->SetIsQueue(_type & FOOTPATH_ELEMENT_INSERT_QUEUE);

View File

@ -16,6 +16,7 @@
#include "../world/Location.hpp" #include "../world/Location.hpp"
struct TileElement; struct TileElement;
enum class RailingEntrySupportType : uint8_t;
enum class ViewportInteractionItem : uint8_t; enum class ViewportInteractionItem : uint8_t;
struct attached_paint_struct struct attached_paint_struct
@ -190,6 +191,17 @@ struct paint_session
} }
}; };
struct FootpathPaintInfo
{
uint32_t SurfaceImageId{};
uint32_t BridgeImageId{};
uint32_t RailingsImageId{};
uint32_t SurfaceFlags{};
uint32_t RailingFlags{};
uint8_t ScrollingMode{};
RailingEntrySupportType SupportType{};
};
extern paint_session gPaintSession; extern paint_session gPaintSession;
// Globals for paint clipping // Globals for paint clipping

View File

@ -1204,7 +1204,7 @@ bool metal_b_supports_paint_setup(
*/ */
bool path_a_supports_paint_setup( bool path_a_supports_paint_setup(
paint_session* session, int32_t supportType, int32_t special, int32_t height, uint32_t imageColourFlags, paint_session* session, int32_t supportType, int32_t special, int32_t height, uint32_t imageColourFlags,
FootpathRailingsObject* railingEntry, bool* underground) const FootpathPaintInfo& pathPaintInfo, bool* underground)
{ {
if (underground != nullptr) if (underground != nullptr)
{ {
@ -1237,7 +1237,7 @@ bool path_a_supports_paint_setup(
if (session->Support.slope & 0x20) if (session->Support.slope & 0x20)
{ {
// save dx2 // save dx2
PaintAddImageAsParent(session, (railingEntry->BridgeImageId + 48) | imageColourFlags, 0, 0, 32, 32, 0, baseHeight - 2); PaintAddImageAsParent(session, (pathPaintInfo.BridgeImageId + 48) | imageColourFlags, 0, 0, 32, 32, 0, baseHeight - 2);
hasSupports = true; hasSupports = true;
} }
else if (session->Support.slope & 0x10) else if (session->Support.slope & 0x10)
@ -1251,7 +1251,7 @@ bool path_a_supports_paint_setup(
} }
uint32_t imageId = (supportType * 24) + word_97B3C4[session->Support.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK] uint32_t imageId = (supportType * 24) + word_97B3C4[session->Support.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK]
+ railingEntry->BridgeImageId; + pathPaintInfo.BridgeImageId;
PaintAddImageAsParent(session, imageId | imageColourFlags, 0, 0, 32, 32, 11, baseHeight, 0, 0, baseHeight + 2); PaintAddImageAsParent(session, imageId | imageColourFlags, 0, 0, 32, 32, 11, baseHeight, 0, 0, baseHeight + 2);
baseHeight += 16; baseHeight += 16;
@ -1272,7 +1272,7 @@ bool path_a_supports_paint_setup(
} }
uint32_t ebx = (supportType * 24) + word_97B3C4[session->Support.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK] uint32_t ebx = (supportType * 24) + word_97B3C4[session->Support.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK]
+ railingEntry->BridgeImageId; + pathPaintInfo.BridgeImageId;
PaintAddImageAsParent(session, ebx | imageColourFlags, 0, 0, 32, 32, 11, baseHeight, 0, 0, baseHeight + 2); PaintAddImageAsParent(session, ebx | imageColourFlags, 0, 0, 32, 32, 11, baseHeight, 0, 0, baseHeight + 2);
@ -1284,7 +1284,7 @@ bool path_a_supports_paint_setup(
{ {
if (baseHeight & 0x10 || heightSteps == 1 || baseHeight + 16 == session->WaterHeight) if (baseHeight & 0x10 || heightSteps == 1 || baseHeight + 16 == session->WaterHeight)
{ {
uint32_t imageId = (supportType * 24) + railingEntry->BridgeImageId + 23; uint32_t imageId = (supportType * 24) + pathPaintInfo.BridgeImageId + 23;
PaintAddImageAsParent(session, imageId | imageColourFlags, 0, 0, 32, 32, ((heightSteps == 1) ? 7 : 12), baseHeight); PaintAddImageAsParent(session, imageId | imageColourFlags, 0, 0, 32, 32, ((heightSteps == 1) ? 7 : 12), baseHeight);
heightSteps -= 1; heightSteps -= 1;
@ -1293,7 +1293,7 @@ bool path_a_supports_paint_setup(
} }
else else
{ {
uint32_t imageId = (supportType * 24) + railingEntry->BridgeImageId + 22; uint32_t imageId = (supportType * 24) + pathPaintInfo.BridgeImageId + 22;
PaintAddImageAsParent( PaintAddImageAsParent(
session, imageId | imageColourFlags, 0, 0, 32, 32, ((heightSteps == 2) ? 23 : 28), baseHeight); session, imageId | imageColourFlags, 0, 0, 32, 32, ((heightSteps == 2) ? 23 : 28), baseHeight);
@ -1307,7 +1307,7 @@ bool path_a_supports_paint_setup(
{ {
uint16_t specialIndex = (special - 1) & 0xFFFF; uint16_t specialIndex = (special - 1) & 0xFFFF;
uint32_t imageId = railingEntry->BridgeImageId + 55 + specialIndex; uint32_t imageId = pathPaintInfo.BridgeImageId + 55 + specialIndex;
unk_supports_desc supportsDesc = byte_98D8D4[specialIndex]; unk_supports_desc supportsDesc = byte_98D8D4[specialIndex];
unk_supports_desc_bound_box boundBox = supportsDesc.bounding_box; unk_supports_desc_bound_box boundBox = supportsDesc.bounding_box;
@ -1352,7 +1352,7 @@ bool path_a_supports_paint_setup(
*/ */
bool path_b_supports_paint_setup( bool path_b_supports_paint_setup(
paint_session* session, int32_t segment, int32_t special, int32_t height, uint32_t imageColourFlags, paint_session* session, int32_t segment, int32_t special, int32_t height, uint32_t imageColourFlags,
FootpathRailingsObject* railingEntry) const FootpathPaintInfo& pathPaintInfo)
{ {
support_height* supportSegments = session->SupportSegments; support_height* supportSegments = session->SupportSegments;
@ -1374,7 +1374,7 @@ bool path_b_supports_paint_setup(
uint16_t baseHeight; uint16_t baseHeight;
if ((supportSegments[segment].slope & 0x20) || (height - supportSegments[segment].height < 6) if ((supportSegments[segment].slope & 0x20) || (height - supportSegments[segment].height < 6)
|| !(railingEntry->Flags & RAILING_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE)) || !(pathPaintInfo.RailingFlags & RAILING_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE))
{ {
baseHeight = supportSegments[segment].height; baseHeight = supportSegments[segment].height;
} }
@ -1384,7 +1384,7 @@ bool path_b_supports_paint_setup(
baseHeight = supportSegments[segment].height; baseHeight = supportSegments[segment].height;
PaintAddImageAsParent( PaintAddImageAsParent(
session, (railingEntry->BridgeImageId + 37 + imageOffset) | imageColourFlags, SupportBoundBoxes[segment].x, session, (pathPaintInfo.BridgeImageId + 37 + imageOffset) | imageColourFlags, SupportBoundBoxes[segment].x,
SupportBoundBoxes[segment].y, 0, 0, 5, baseHeight); SupportBoundBoxes[segment].y, 0, 0, 5, baseHeight);
baseHeight += 6; baseHeight += 6;
} }
@ -1403,7 +1403,7 @@ bool path_b_supports_paint_setup(
if (heightDiff > 0) if (heightDiff > 0)
{ {
PaintAddImageAsParent( PaintAddImageAsParent(
session, (railingEntry->BridgeImageId + 20 + (heightDiff - 1)) | imageColourFlags, SupportBoundBoxes[segment].x, session, (pathPaintInfo.BridgeImageId + 20 + (heightDiff - 1)) | imageColourFlags, SupportBoundBoxes[segment].x,
SupportBoundBoxes[segment].y, 0, 0, heightDiff - 1, baseHeight); SupportBoundBoxes[segment].y, 0, 0, heightDiff - 1, baseHeight);
} }
@ -1436,7 +1436,7 @@ bool path_b_supports_paint_setup(
} }
PaintAddImageAsParent( PaintAddImageAsParent(
session, (railingEntry->BridgeImageId + 20 + (z - 1)) | imageColourFlags, SupportBoundBoxes[segment].x, session, (pathPaintInfo.BridgeImageId + 20 + (z - 1)) | imageColourFlags, SupportBoundBoxes[segment].x,
SupportBoundBoxes[segment].y, 0, 0, (z - 1), baseHeight); SupportBoundBoxes[segment].y, 0, 0, (z - 1), baseHeight);
baseHeight += z; baseHeight += z;
@ -1447,7 +1447,7 @@ bool path_b_supports_paint_setup(
break; break;
} }
uint32_t imageId = railingEntry->BridgeImageId + 20 + (z - 1); uint32_t imageId = pathPaintInfo.BridgeImageId + 20 + (z - 1);
if (z == 16) if (z == 16)
{ {
imageId += 1; imageId += 1;
@ -1482,7 +1482,7 @@ bool path_b_supports_paint_setup(
break; break;
} }
uint32_t imageId = railingEntry->BridgeImageId + 20 + (z - 1); uint32_t imageId = pathPaintInfo.BridgeImageId + 20 + (z - 1);
PaintAddImageAsParent( PaintAddImageAsParent(
session, imageId | imageColourFlags, SupportBoundBoxes[segment].x, SupportBoundBoxes[segment].y, 0, 0, 0, session, imageId | imageColourFlags, SupportBoundBoxes[segment].x, SupportBoundBoxes[segment].y, 0, 0, 0,
baseHeight, SupportBoundBoxes[segment].x, SupportBoundBoxes[segment].y, baseHeight); baseHeight, SupportBoundBoxes[segment].x, SupportBoundBoxes[segment].y, baseHeight);

View File

@ -13,6 +13,8 @@
#include "../common.h" #include "../common.h"
#include "../world/Footpath.h" #include "../world/Footpath.h"
struct FootpathPaintInfo;
constexpr const uint8_t NumVanillaWoodenSupportTypes = 49; constexpr const uint8_t NumVanillaWoodenSupportTypes = 49;
bool wooden_a_supports_paint_setup( bool wooden_a_supports_paint_setup(
@ -25,10 +27,10 @@ bool metal_b_supports_paint_setup(
paint_session* session, uint8_t supportType, uint8_t segment, int32_t special, int32_t height, uint32_t imageColourFlags); paint_session* session, uint8_t supportType, uint8_t segment, int32_t special, int32_t height, uint32_t imageColourFlags);
bool path_a_supports_paint_setup( bool path_a_supports_paint_setup(
paint_session* session, int32_t supportType, int32_t special, int32_t height, uint32_t imageColourFlags, paint_session* session, int32_t supportType, int32_t special, int32_t height, uint32_t imageColourFlags,
FootpathRailingsObject* railingEntry, bool* underground); const FootpathPaintInfo& pathPaintInfo, bool* underground);
bool path_b_supports_paint_setup( bool path_b_supports_paint_setup(
paint_session* session, int32_t supportType, int32_t special, int32_t height, uint32_t imageColourFlags, paint_session* session, int32_t supportType, int32_t special, int32_t height, uint32_t imageColourFlags,
FootpathRailingsObject* railingEntry); const FootpathPaintInfo& pathPaintInfo);
// There are 13 types of metal supports. A graphic showing all of them is available here: // There are 13 types of metal supports. A graphic showing all of them is available here:
// https://cloud.githubusercontent.com/assets/737603/19420485/7eaba28e-93ec-11e6-83cb-03190accc094.png // https://cloud.githubusercontent.com/assets/737603/19420485/7eaba28e-93ec-11e6-83cb-03190accc094.png

View File

@ -13,6 +13,7 @@
#include "../../drawing/LightFX.h" #include "../../drawing/LightFX.h"
#include "../../interface/Viewport.h" #include "../../interface/Viewport.h"
#include "../../localisation/Localisation.h" #include "../../localisation/Localisation.h"
#include "../../object/FootpathObject.h"
#include "../../object/FootpathRailingsObject.h" #include "../../object/FootpathRailingsObject.h"
#include "../../object/ObjectList.h" #include "../../object/ObjectList.h"
#include "../../object/ObjectManager.h" #include "../../object/ObjectManager.h"
@ -85,11 +86,11 @@ static constexpr const uint8_t byte_98D8A4[] = {
// clang-format on // clang-format on
void path_paint_box_support( void path_paint_box_support(
paint_session* session, const TileElement* tileElement, int32_t height, PathSurfaceEntry* footpathEntry, paint_session* session, const TileElement* tileElement, int32_t height, const FootpathPaintInfo& pathPaintInfo,
FootpathRailingsObject* railingEntry, bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags); bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags);
void path_paint_pole_support( void path_paint_pole_support(
paint_session* session, const TileElement* tileElement, int16_t height, PathSurfaceEntry* footpathEntry, paint_session* session, const TileElement* tileElement, int16_t height, const FootpathPaintInfo& pathPaintInfo,
FootpathRailingsObject* railingEntry, bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags); bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags);
/* rct2: 0x006A5AE5 */ /* rct2: 0x006A5AE5 */
static void path_bit_lights_paint( static void path_bit_lights_paint(
@ -325,9 +326,9 @@ static void path_bit_jumping_fountains_paint(
*/ */
static void sub_6A4101( static void sub_6A4101(
paint_session* session, const TileElement* tile_element, uint16_t height, uint32_t connectedEdges, bool hasSupports, paint_session* session, const TileElement* tile_element, uint16_t height, uint32_t connectedEdges, bool hasSupports,
PathSurfaceEntry* surfaceEntry, FootpathRailingsObject* railingEntry, uint32_t imageFlags) const FootpathPaintInfo& pathPaintInfo, uint32_t imageFlags)
{ {
uint32_t base_image_id = railingEntry->RailingsImageId | imageFlags; uint32_t base_image_id = pathPaintInfo.RailingsImageId | imageFlags;
if (tile_element->AsPath()->IsQueue()) if (tile_element->AsPath()->IsQueue())
{ {
@ -449,7 +450,7 @@ static void sub_6A4101(
auto ride = get_ride(tile_element->AsPath()->GetRideIndex()); auto ride = get_ride(tile_element->AsPath()->GetRideIndex());
if (direction < 2 && ride != nullptr && imageFlags == 0) if (direction < 2 && ride != nullptr && imageFlags == 0)
{ {
uint16_t scrollingMode = railingEntry->ScrollingMode; uint16_t scrollingMode = pathPaintInfo.ScrollingMode;
scrollingMode += direction; scrollingMode += direction;
auto ft = Formatter(); auto ft = Formatter();
@ -492,12 +493,12 @@ static void sub_6A4101(
uint32_t drawnCorners = 0; uint32_t drawnCorners = 0;
// If the path is not drawn over the supports, then no corner sprites will be drawn (making double-width paths // If the path is not drawn over the supports, then no corner sprites will be drawn (making double-width paths
// look like connected series of intersections). // look like connected series of intersections).
if (railingEntry->Flags & RAILING_ENTRY_FLAG_DRAW_PATH_OVER_SUPPORTS) if (pathPaintInfo.RailingFlags & RAILING_ENTRY_FLAG_DRAW_PATH_OVER_SUPPORTS)
{ {
drawnCorners = (connectedEdges & FOOTPATH_PROPERTIES_EDGES_CORNERS_MASK) >> 4; drawnCorners = (connectedEdges & FOOTPATH_PROPERTIES_EDGES_CORNERS_MASK) >> 4;
} }
auto slopeRailingsSupported = !(surfaceEntry->flags & FOOTPATH_ENTRY_FLAG_NO_SLOPE_RAILINGS); auto slopeRailingsSupported = !(pathPaintInfo.SurfaceFlags & FOOTPATH_ENTRY_FLAG_NO_SLOPE_RAILINGS);
if ((hasSupports || slopeRailingsSupported) && tile_element->AsPath()->IsSloped()) if ((hasSupports || slopeRailingsSupported) && tile_element->AsPath()->IsSloped())
{ {
switch ((tile_element->AsPath()->GetSlopeDirection() + session->CurrentRotation) switch ((tile_element->AsPath()->GetSlopeDirection() + session->CurrentRotation)
@ -673,8 +674,7 @@ static void sub_6A4101(
*/ */
static void sub_6A3F61( static void sub_6A3F61(
paint_session* session, const TileElement* tile_element, uint16_t connectedEdges, uint16_t height, paint_session* session, const TileElement* tile_element, uint16_t connectedEdges, uint16_t height,
PathSurfaceEntry* surfaceEntry, FootpathRailingsObject* railingEntry, uint32_t imageFlags, uint32_t sceneryImageFlags, const FootpathPaintInfo& pathPaintInfo, uint32_t imageFlags, uint32_t sceneryImageFlags, bool hasSupports)
bool hasSupports)
{ {
// eax -- // eax --
// ebx -- // ebx --
@ -754,7 +754,7 @@ static void sub_6A3F61(
// Redundant zoom-level check removed // Redundant zoom-level check removed
if (paintScenery) if (paintScenery)
sub_6A4101(session, tile_element, height, connectedEdges, hasSupports, surfaceEntry, railingEntry, imageFlags); sub_6A4101(session, tile_element, height, connectedEdges, hasSupports, pathPaintInfo, imageFlags);
} }
// This is about tunnel drawing // This is about tunnel drawing
@ -944,20 +944,42 @@ void path_paint(paint_session* session, uint16_t height, const TileElement* tile
PaintAddImageAsParent(session, imageId, 16, 16, 1, 1, 0, heightMarkerBaseZ); PaintAddImageAsParent(session, imageId, 16, 16, 1, 1, 0, heightMarkerBaseZ);
} }
PathSurfaceEntry* footpathEntry = tile_element->AsPath()->GetSurfaceEntry(); auto footpathObj = tile_element->AsPath()->GetSurfaceEntry();
auto railingEntry = tile_element->AsPath()->GetRailingEntry(); if (footpathObj != nullptr)
{
auto surfaceEntry = tile_element->AsPath()->IsQueue() ? footpathObj->GetQueueEntry()
: footpathObj->GetPathSurfaceEntry();
auto railingsEntry = footpathObj->GetPathRailingsEntry();
if (footpathEntry != nullptr && railingEntry != nullptr) FootpathPaintInfo pathPaintInfo;
pathPaintInfo.SurfaceImageId = surfaceEntry->image;
pathPaintInfo.SurfaceFlags = surfaceEntry->flags;
auto railingObj = tile_element->AsPath()->GetRailingEntry();
if (railingObj != nullptr)
{ {
if (railingEntry->SupportType == RailingEntrySupportType::Pole) pathPaintInfo.BridgeImageId = railingObj->BridgeImageId;
{ pathPaintInfo.RailingsImageId = railingObj->RailingsImageId;
path_paint_pole_support( pathPaintInfo.RailingFlags = railingObj->Flags;
session, tile_element, height, footpathEntry, railingEntry, hasSupports, imageFlags, sceneryImageFlags); pathPaintInfo.ScrollingMode = railingObj->ScrollingMode;
pathPaintInfo.SupportType = railingObj->SupportType;
} }
else else
{ {
path_paint_box_support( pathPaintInfo.BridgeImageId = railingsEntry->bridge_image;
session, tile_element, height, footpathEntry, railingEntry, hasSupports, imageFlags, sceneryImageFlags); pathPaintInfo.RailingsImageId = railingsEntry->railings_image;
pathPaintInfo.RailingFlags = railingsEntry->flags;
pathPaintInfo.ScrollingMode = railingsEntry->scrolling_mode;
pathPaintInfo.SupportType = railingsEntry->support_type;
}
if (pathPaintInfo.SupportType == RailingEntrySupportType::Pole)
{
path_paint_pole_support(session, tile_element, height, pathPaintInfo, hasSupports, imageFlags, sceneryImageFlags);
}
else
{
path_paint_box_support(session, tile_element, height, pathPaintInfo, hasSupports, imageFlags, sceneryImageFlags);
} }
} }
@ -994,8 +1016,8 @@ void path_paint(paint_session* session, uint16_t height, const TileElement* tile
} }
void path_paint_box_support( void path_paint_box_support(
paint_session* session, const TileElement* tileElement, int32_t height, PathSurfaceEntry* footpathEntry, paint_session* session, const TileElement* tileElement, int32_t height, const FootpathPaintInfo& pathPaintInfo,
FootpathRailingsObject* railingEntry, bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags) bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags)
{ {
const PathElement* pathElement = tileElement->AsPath(); const PathElement* pathElement = tileElement->AsPath();
@ -1011,20 +1033,18 @@ void path_paint_box_support(
uint16_t edi = edges | (corners << 4); uint16_t edi = edges | (corners << 4);
uint32_t imageId; uint32_t imageId = pathPaintInfo.SurfaceImageId;
if (tileElement->AsPath()->IsSloped()) if (tileElement->AsPath()->IsSloped())
{ {
imageId = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) imageId += ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation)
& FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK) & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)
+ 16; + 16;
} }
else else
{ {
imageId = byte_98D6E0[edi]; imageId += byte_98D6E0[edi];
} }
imageId += footpathEntry->image;
if (!session->DidPassSurface) if (!session->DidPassSurface)
{ {
boundBoxOffset.x = 3; boundBoxOffset.x = 3;
@ -1059,11 +1079,11 @@ void path_paint_box_support(
{ {
image_id = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) image_id = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation)
& FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK) & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)
+ railingEntry->BridgeImageId + 51; + pathPaintInfo.BridgeImageId + 51;
} }
else else
{ {
image_id = byte_98D8A4[edges] + railingEntry->BridgeImageId + 49; image_id = byte_98D8A4[edges] + pathPaintInfo.BridgeImageId + 49;
} }
PaintAddImageAsParent( PaintAddImageAsParent(
@ -1071,7 +1091,7 @@ void path_paint_box_support(
height + boundingBoxZOffset); height + boundingBoxZOffset);
// TODO: Revert this when path import works correctly. // TODO: Revert this when path import works correctly.
if (!pathElement->IsQueue() && !(railingEntry->Flags & RAILING_ENTRY_FLAG_DRAW_PATH_OVER_SUPPORTS)) if (!pathElement->IsQueue() && !(pathPaintInfo.RailingFlags & RAILING_ENTRY_FLAG_DRAW_PATH_OVER_SUPPORTS))
{ {
// don't draw // don't draw
} }
@ -1083,7 +1103,7 @@ void path_paint_box_support(
} }
} }
sub_6A3F61(session, tileElement, edi, height, footpathEntry, railingEntry, imageFlags, sceneryImageFlags, hasSupports); sub_6A3F61(session, tileElement, edi, height, pathPaintInfo, imageFlags, sceneryImageFlags, hasSupports);
uint16_t ax = 0; uint16_t ax = 0;
if (tileElement->AsPath()->IsSloped()) if (tileElement->AsPath()->IsSloped())
@ -1091,14 +1111,8 @@ void path_paint_box_support(
ax = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) & 0x3) + 1; ax = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) & 0x3) + 1;
} }
if (byte_98D8A4[edges] == 0) auto supportType = byte_98D8A4[edges] == 0 ? 0 : 1;
{ path_a_supports_paint_setup(session, supportType, ax, height, imageFlags, pathPaintInfo, nullptr);
path_a_supports_paint_setup(session, 0, ax, height, imageFlags, railingEntry, nullptr);
}
else
{
path_a_supports_paint_setup(session, 1, ax, height, imageFlags, railingEntry, nullptr);
}
height += 32; height += 32;
if (tileElement->AsPath()->IsSloped()) if (tileElement->AsPath()->IsSloped())
@ -1144,8 +1158,8 @@ void path_paint_box_support(
} }
void path_paint_pole_support( void path_paint_pole_support(
paint_session* session, const TileElement* tileElement, int16_t height, PathSurfaceEntry* footpathEntry, paint_session* session, const TileElement* tileElement, int16_t height, const FootpathPaintInfo& pathPaintInfo,
FootpathRailingsObject* railingEntry, bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags) bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags)
{ {
const PathElement* pathElement = tileElement->AsPath(); const PathElement* pathElement = tileElement->AsPath();
@ -1162,18 +1176,16 @@ void path_paint_pole_support(
uint16_t edi = edges | (corners << 4); uint16_t edi = edges | (corners << 4);
uint32_t imageId; uint32_t imageId = pathPaintInfo.SurfaceImageId;
if (tileElement->AsPath()->IsSloped()) if (tileElement->AsPath()->IsSloped())
{ {
imageId = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) & 3) + 16; imageId += ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) & 3) + 16;
} }
else else
{ {
imageId = byte_98D6E0[edi]; imageId += byte_98D6E0[edi];
} }
imageId += footpathEntry->image;
// Below Surface // Below Surface
if (!session->DidPassSurface) if (!session->DidPassSurface)
{ {
@ -1209,11 +1221,11 @@ void path_paint_pole_support(
{ {
bridgeImage = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) bridgeImage = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation)
& FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK) & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)
+ railingEntry->BridgeImageId + 16; + pathPaintInfo.BridgeImageId + 16;
} }
else else
{ {
bridgeImage = edges + railingEntry->BridgeImageId; bridgeImage = edges + pathPaintInfo.BridgeImageId;
bridgeImage |= imageFlags; bridgeImage |= imageFlags;
} }
@ -1222,7 +1234,7 @@ void path_paint_pole_support(
boundBoxOffset.y, height + boundingBoxZOffset); boundBoxOffset.y, height + boundingBoxZOffset);
// TODO: Revert this when path import works correctly. // TODO: Revert this when path import works correctly.
if (pathElement->IsQueue() || (railingEntry->Flags & RAILING_ENTRY_FLAG_DRAW_PATH_OVER_SUPPORTS)) if (pathElement->IsQueue() || (pathPaintInfo.RailingFlags & RAILING_ENTRY_FLAG_DRAW_PATH_OVER_SUPPORTS))
{ {
PaintAddImageAsChild( PaintAddImageAsChild(
session, imageId | imageFlags, 0, 0, boundBoxSize.x, boundBoxSize.y, 0, height, boundBoxOffset.x, session, imageId | imageFlags, 0, 0, boundBoxSize.x, boundBoxSize.y, 0, height, boundBoxOffset.x,
@ -1230,8 +1242,7 @@ void path_paint_pole_support(
} }
} }
sub_6A3F61( sub_6A3F61(session, tileElement, edi, height, pathPaintInfo, imageFlags, sceneryImageFlags,
session, tileElement, edi, height, footpathEntry, railingEntry, imageFlags, sceneryImageFlags,
hasSupports); // TODO: arguments hasSupports); // TODO: arguments
uint16_t ax = 0; uint16_t ax = 0;
@ -1251,7 +1262,7 @@ void path_paint_pole_support(
{ {
if (!(edges & (1 << i))) if (!(edges & (1 << i)))
{ {
path_b_supports_paint_setup(session, supports[i], ax, height, imageFlags, railingEntry); path_b_supports_paint_setup(session, supports[i], ax, height, imageFlags, pathPaintInfo);
} }
} }

View File

@ -1132,6 +1132,7 @@ public:
auto src2 = src->AsPath(); auto src2 = src->AsPath();
dst2->SetSurfaceEntryIndex(src2->GetEntryIndex()); dst2->SetSurfaceEntryIndex(src2->GetEntryIndex());
dst2->SetRailingEntryIndex(OBJECT_ENTRY_INDEX_NULL);
dst2->SetQueueBannerDirection(src2->GetQueueBannerDirection()); dst2->SetQueueBannerDirection(src2->GetQueueBannerDirection());
dst2->SetSloped(src2->IsSloped()); dst2->SetSloped(src2->IsSloped());
dst2->SetSlopeDirection(src2->GetSlopeDirection()); dst2->SetSlopeDirection(src2->GetSlopeDirection());
@ -1567,6 +1568,14 @@ public:
} }
RCT12AddDefaultObjects(objectList); RCT12AddDefaultObjects(objectList);
// Add default railings
objectList.SetObject(ObjectType::FootpathRailings, 0, "rct2.railings.wood");
objectList.SetObject(ObjectType::FootpathRailings, 1, "rct2.railings.concrete");
objectList.SetObject(ObjectType::FootpathRailings, 2, "rct2.railings.space");
objectList.SetObject(ObjectType::FootpathRailings, 3, "rct2.railings.black");
objectList.SetObject(ObjectType::FootpathRailings, 4, "rct2.railings.brown");
return objectList; return objectList;
} }
}; };

View File

@ -272,12 +272,12 @@ void EntranceElement::SetSequenceIndex(uint8_t newSequenceIndex)
SequenceIndex |= (newSequenceIndex & 0xF); SequenceIndex |= (newSequenceIndex & 0xF);
} }
PathSurfaceIndex EntranceElement::GetPathType() const ObjectEntryIndex EntranceElement::GetPathType() const
{ {
return PathType; return PathType;
} }
void EntranceElement::SetPathType(PathSurfaceIndex newPathType) void EntranceElement::SetPathType(ObjectEntryIndex newPathType)
{ {
PathType = newPathType; PathType = newPathType;
} }

View File

@ -1649,37 +1649,53 @@ void PathElement::SetAdditionIsGhost(bool isGhost)
Flags2 |= FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_GHOST; Flags2 |= FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_GHOST;
} }
PathSurfaceIndex PathElement::GetSurfaceEntryIndex() const ObjectEntryIndex PathElement::GetSurfaceEntryIndex() const
{ {
return SurfaceIndex; return SurfaceIndex;
} }
PathRailingsIndex PathElement::GetRailingEntryIndex() const ObjectEntryIndex PathElement::GetRailingEntryIndex() const
{ {
if (RailingsIndex == std::numeric_limits<uint8_t>::max())
{
return OBJECT_ENTRY_INDEX_NULL;
}
return RailingsIndex; return RailingsIndex;
} }
PathSurfaceEntry* PathElement::GetSurfaceEntry() const FootpathObject* PathElement::GetSurfaceEntry() const
{ {
if (!IsQueue()) auto& objMgr = OpenRCT2::GetContext()->GetObjectManager();
return get_path_surface_entry(GetSurfaceEntryIndex()); return static_cast<FootpathObject*>(objMgr.GetLoadedObject(ObjectType::Paths, GetSurfaceEntryIndex()));
else
return get_path_surface_entry(GetSurfaceEntryIndex() + MAX_PATH_OBJECTS);
} }
FootpathRailingsObject* PathElement::GetRailingEntry() const FootpathRailingsObject* PathElement::GetRailingEntry() const
{ {
return get_path_railings_entry(GetRailingEntryIndex()); auto entryIndex = GetRailingEntryIndex();
if (entryIndex == OBJECT_ENTRY_INDEX_NULL)
{
return nullptr;
} }
void PathElement::SetSurfaceEntryIndex(PathSurfaceIndex newIndex) auto& objMgr = OpenRCT2::GetContext()->GetObjectManager();
{ return static_cast<FootpathRailingsObject*>(objMgr.GetLoadedObject(ObjectType::FootpathRailings, entryIndex));
SurfaceIndex = newIndex & ~FOOTPATH_ELEMENT_INSERT_QUEUE;
} }
void PathElement::SetRailingEntryIndex(PathRailingsIndex newEntryIndex) void PathElement::SetSurfaceEntryIndex(ObjectEntryIndex newIndex)
{ {
RailingsIndex = newEntryIndex; SurfaceIndex = newIndex;
}
void PathElement::SetRailingEntryIndex(ObjectEntryIndex newEntryIndex)
{
if (newEntryIndex == OBJECT_ENTRY_INDEX_NULL)
{
RailingsIndex = std::numeric_limits<uint8_t>::max();
}
else
{
RailingsIndex = static_cast<uint8_t>(newEntryIndex);
}
} }
uint8_t PathElement::GetQueueBannerDirection() const uint8_t PathElement::GetQueueBannerDirection() const
@ -2243,7 +2259,7 @@ void footpath_remove_edges_at(const CoordsXY& footpathPos, TileElement* tileElem
tileElement->AsPath()->SetEdgesAndCorners(0); tileElement->AsPath()->SetEdgesAndCorners(0);
} }
PathSurfaceEntry* get_path_surface_entry(PathSurfaceIndex entryIndex) PathSurfaceEntry* get_path_surface_entry(ObjectEntryIndex entryIndex)
{ {
PathSurfaceEntry* result = nullptr; PathSurfaceEntry* result = nullptr;
auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); auto& objMgr = OpenRCT2::GetContext()->GetObjectManager();
@ -2259,12 +2275,6 @@ PathSurfaceEntry* get_path_surface_entry(PathSurfaceIndex entryIndex)
return result; return result;
} }
FootpathRailingsObject* get_path_railings_entry(PathRailingsIndex entryIndex)
{
auto& objMgr = OpenRCT2::GetContext()->GetObjectManager();
return static_cast<FootpathRailingsObject*>(objMgr.GetLoadedObject(ObjectType::FootpathRailings, entryIndex));
}
ride_id_t PathElement::GetRideIndex() const ride_id_t PathElement::GetRideIndex() const
{ {
return rideIndex; return rideIndex;

View File

@ -29,12 +29,6 @@ constexpr auto PATH_CLEARANCE = 4 * COORDS_Z_STEP;
#define FOOTPATH_ELEMENT_INSERT_QUEUE 0x80 #define FOOTPATH_ELEMENT_INSERT_QUEUE 0x80
using PathSurfaceIndex = uint16_t;
constexpr PathSurfaceIndex PATH_SURFACE_INDEX_NULL = static_cast<PathSurfaceIndex>(-1);
using PathRailingsIndex = uint8_t;
constexpr PathRailingsIndex PATH_RAILINGS_INDEX_NULL = static_cast<PathRailingsIndex>(-1);
enum class RailingEntrySupportType : uint8_t enum class RailingEntrySupportType : uint8_t
{ {
Box = 0, Box = 0,
@ -201,8 +195,7 @@ int32_t footpath_is_connected_to_map_edge(const CoordsXYZ& footpathPos, int32_t
void footpath_remove_edges_at(const CoordsXY& footpathPos, TileElement* tileElement); void footpath_remove_edges_at(const CoordsXY& footpathPos, TileElement* tileElement);
int32_t entrance_get_directions(const TileElement* tileElement); int32_t entrance_get_directions(const TileElement* tileElement);
PathSurfaceEntry* get_path_surface_entry(PathSurfaceIndex entryIndex); PathSurfaceEntry* get_path_surface_entry(ObjectEntryIndex entryIndex);
FootpathRailingsObject* get_path_railings_entry(PathRailingsIndex entryIndex);
void footpath_queue_chain_reset(); void footpath_queue_chain_reset();
void footpath_queue_chain_push(ride_id_t rideIndex); void footpath_queue_chain_push(ride_id_t rideIndex);

View File

@ -22,6 +22,7 @@ struct rct_footpath_entry;
class LargeSceneryObject; class LargeSceneryObject;
class TerrainSurfaceObject; class TerrainSurfaceObject;
class TerrainEdgeObject; class TerrainEdgeObject;
class FootpathObject;
class FootpathRailingsObject; class FootpathRailingsObject;
using track_type_t = uint16_t; using track_type_t = uint16_t;
@ -254,10 +255,10 @@ struct PathElement : TileElementBase
static constexpr TileElementType ElementType = TileElementType::Path; static constexpr TileElementType ElementType = TileElementType::Path;
private: private:
PathSurfaceIndex SurfaceIndex; // 5 ObjectEntryIndex SurfaceIndex; // 5
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-private-field" #pragma clang diagnostic ignored "-Wunused-private-field"
PathRailingsIndex RailingsIndex; // 7 uint8_t RailingsIndex; // 7
#pragma clang diagnostic pop #pragma clang diagnostic pop
uint8_t Additions; // 8 (0 means no addition) uint8_t Additions; // 8 (0 means no addition)
uint8_t EdgesAndCorners; // 9 (edges in lower 4 bits, corners in upper 4) uint8_t EdgesAndCorners; // 9 (edges in lower 4 bits, corners in upper 4)
@ -275,13 +276,13 @@ private:
#pragma clang diagnostic pop #pragma clang diagnostic pop
public: public:
PathSurfaceIndex GetSurfaceEntryIndex() const; ObjectEntryIndex GetSurfaceEntryIndex() const;
PathSurfaceEntry* GetSurfaceEntry() const; FootpathObject* GetSurfaceEntry() const;
void SetSurfaceEntryIndex(PathSurfaceIndex newIndex); void SetSurfaceEntryIndex(ObjectEntryIndex newIndex);
PathRailingsIndex GetRailingEntryIndex() const; ObjectEntryIndex GetRailingEntryIndex() const;
FootpathRailingsObject* GetRailingEntry() const; FootpathRailingsObject* GetRailingEntry() const;
void SetRailingEntryIndex(PathRailingsIndex newIndex); void SetRailingEntryIndex(ObjectEntryIndex newIndex);
uint8_t GetQueueBannerDirection() const; uint8_t GetQueueBannerDirection() const;
void SetQueueBannerDirection(uint8_t direction); void SetQueueBannerDirection(uint8_t direction);
@ -560,7 +561,7 @@ private:
uint8_t entranceType; // 5 uint8_t entranceType; // 5
uint8_t SequenceIndex; // 6. Only uses the lower nibble. uint8_t SequenceIndex; // 6. Only uses the lower nibble.
uint8_t StationIndex; // 7 uint8_t StationIndex; // 7
PathSurfaceIndex PathType; // 8 ObjectEntryIndex PathType; // 8
ride_id_t rideIndex; // 9 ride_id_t rideIndex; // 9
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-private-field" #pragma clang diagnostic ignored "-Wunused-private-field"
@ -580,8 +581,8 @@ public:
uint8_t GetSequenceIndex() const; uint8_t GetSequenceIndex() const;
void SetSequenceIndex(uint8_t newSequenceIndex); void SetSequenceIndex(uint8_t newSequenceIndex);
PathSurfaceIndex GetPathType() const; ObjectEntryIndex GetPathType() const;
void SetPathType(PathSurfaceIndex newPathType); void SetPathType(ObjectEntryIndex newPathType);
}; };
assert_struct_size(EntranceElement, 16); assert_struct_size(EntranceElement, 16);