From 23c709c197411474263f5595eb063908e2db0b88 Mon Sep 17 00:00:00 2001 From: Ted John Date: Wed, 14 Apr 2021 01:34:07 +0100 Subject: [PATCH] Implement railing override logic --- src/openrct2-ui/windows/TileInspector.cpp | 5 +- src/openrct2/actions/FootpathPlaceAction.cpp | 2 + .../actions/FootpathPlaceFromTrackAction.cpp | 1 + src/openrct2/paint/Paint.h | 12 ++ src/openrct2/paint/Supports.cpp | 28 ++-- src/openrct2/paint/Supports.h | 6 +- .../paint/tile_element/Paint.Path.cpp | 121 ++++++++++-------- src/openrct2/rct2/S6Importer.cpp | 9 ++ src/openrct2/world/Entrance.cpp | 4 +- src/openrct2/world/Footpath.cpp | 48 ++++--- src/openrct2/world/Footpath.h | 9 +- src/openrct2/world/TileElement.h | 21 +-- 12 files changed, 155 insertions(+), 111 deletions(-) diff --git a/src/openrct2-ui/windows/TileInspector.cpp b/src/openrct2-ui/windows/TileInspector.cpp index f101e8c08f..aff5c388bf 100644 --- a/src/openrct2-ui/windows/TileInspector.cpp +++ b/src/openrct2-ui/windows/TileInspector.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -1813,7 +1814,9 @@ static void window_tile_inspector_paint(rct_window* w, rct_drawpixelinfo* dpi) { // Details // Path name - rct_string_id pathNameId = tileElement->AsPath()->GetSurfaceEntry()->string_idx; + auto legacyFootpathEntry = reinterpret_cast( + tileElement->AsPath()->GetSurfaceEntry()->GetLegacyData()); + rct_string_id pathNameId = legacyFootpathEntry->string_idx; DrawTextBasic(dpi, screenCoords, STR_TILE_INSPECTOR_PATH_NAME, &pathNameId, { COLOUR_WHITE }); // Path addition diff --git a/src/openrct2/actions/FootpathPlaceAction.cpp b/src/openrct2/actions/FootpathPlaceAction.cpp index 8b8af8aec7..cdb5352778 100644 --- a/src/openrct2/actions/FootpathPlaceAction.cpp +++ b/src/openrct2/actions/FootpathPlaceAction.cpp @@ -182,6 +182,7 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementUpdateExecute(PathElement* } pathElement->SetSurfaceEntryIndex(_type & ~FOOTPATH_ELEMENT_INSERT_QUEUE); + pathElement->SetRailingEntryIndex(OBJECT_ENTRY_INDEX_NULL); bool isQueue = _type & FOOTPATH_ELEMENT_INSERT_QUEUE; pathElement->SetIsQueue(isQueue); @@ -348,6 +349,7 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementInsertExecute(GameActions:: pathElement->SetClearanceZ(zHigh); pathElement->SetSurfaceEntryIndex(_type & ~FOOTPATH_ELEMENT_INSERT_QUEUE); + pathElement->SetRailingEntryIndex(OBJECT_ENTRY_INDEX_NULL); pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK); pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED); pathElement->SetIsQueue(_type & FOOTPATH_ELEMENT_INSERT_QUEUE); diff --git a/src/openrct2/actions/FootpathPlaceFromTrackAction.cpp b/src/openrct2/actions/FootpathPlaceFromTrackAction.cpp index ea9407091c..1904116eb1 100644 --- a/src/openrct2/actions/FootpathPlaceFromTrackAction.cpp +++ b/src/openrct2/actions/FootpathPlaceFromTrackAction.cpp @@ -235,6 +235,7 @@ GameActions::Result::Ptr FootpathPlaceFromTrackAction::ElementInsertExecute(Game pathElement->SetClearanceZ(zHigh); pathElement->SetSurfaceEntryIndex(_type & ~FOOTPATH_ELEMENT_INSERT_QUEUE); + pathElement->SetRailingEntryIndex(OBJECT_ENTRY_INDEX_NULL); pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK); pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED); pathElement->SetIsQueue(_type & FOOTPATH_ELEMENT_INSERT_QUEUE); diff --git a/src/openrct2/paint/Paint.h b/src/openrct2/paint/Paint.h index d8535de0de..64b0ee21be 100644 --- a/src/openrct2/paint/Paint.h +++ b/src/openrct2/paint/Paint.h @@ -16,6 +16,7 @@ #include "../world/Location.hpp" struct TileElement; +enum class RailingEntrySupportType : uint8_t; enum class ViewportInteractionItem : uint8_t; 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; // Globals for paint clipping diff --git a/src/openrct2/paint/Supports.cpp b/src/openrct2/paint/Supports.cpp index e279e6d05f..82f3529a64 100644 --- a/src/openrct2/paint/Supports.cpp +++ b/src/openrct2/paint/Supports.cpp @@ -1204,7 +1204,7 @@ bool metal_b_supports_paint_setup( */ bool path_a_supports_paint_setup( 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) { @@ -1237,7 +1237,7 @@ bool path_a_supports_paint_setup( if (session->Support.slope & 0x20) { // 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; } 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] - + railingEntry->BridgeImageId; + + pathPaintInfo.BridgeImageId; PaintAddImageAsParent(session, imageId | imageColourFlags, 0, 0, 32, 32, 11, baseHeight, 0, 0, baseHeight + 2); 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] - + railingEntry->BridgeImageId; + + pathPaintInfo.BridgeImageId; 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) { - 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); heightSteps -= 1; @@ -1293,7 +1293,7 @@ bool path_a_supports_paint_setup( } else { - uint32_t imageId = (supportType * 24) + railingEntry->BridgeImageId + 22; + uint32_t imageId = (supportType * 24) + pathPaintInfo.BridgeImageId + 22; PaintAddImageAsParent( 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; - uint32_t imageId = railingEntry->BridgeImageId + 55 + specialIndex; + uint32_t imageId = pathPaintInfo.BridgeImageId + 55 + specialIndex; unk_supports_desc supportsDesc = byte_98D8D4[specialIndex]; 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( 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; @@ -1374,7 +1374,7 @@ bool path_b_supports_paint_setup( uint16_t baseHeight; 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; } @@ -1384,7 +1384,7 @@ bool path_b_supports_paint_setup( baseHeight = supportSegments[segment].height; 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); baseHeight += 6; } @@ -1403,7 +1403,7 @@ bool path_b_supports_paint_setup( if (heightDiff > 0) { 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); } @@ -1436,7 +1436,7 @@ bool path_b_supports_paint_setup( } 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); baseHeight += z; @@ -1447,7 +1447,7 @@ bool path_b_supports_paint_setup( break; } - uint32_t imageId = railingEntry->BridgeImageId + 20 + (z - 1); + uint32_t imageId = pathPaintInfo.BridgeImageId + 20 + (z - 1); if (z == 16) { imageId += 1; @@ -1482,7 +1482,7 @@ bool path_b_supports_paint_setup( break; } - uint32_t imageId = railingEntry->BridgeImageId + 20 + (z - 1); + uint32_t imageId = pathPaintInfo.BridgeImageId + 20 + (z - 1); PaintAddImageAsParent( session, imageId | imageColourFlags, SupportBoundBoxes[segment].x, SupportBoundBoxes[segment].y, 0, 0, 0, baseHeight, SupportBoundBoxes[segment].x, SupportBoundBoxes[segment].y, baseHeight); diff --git a/src/openrct2/paint/Supports.h b/src/openrct2/paint/Supports.h index 5a76a8cca0..c2ff09dbae 100644 --- a/src/openrct2/paint/Supports.h +++ b/src/openrct2/paint/Supports.h @@ -13,6 +13,8 @@ #include "../common.h" #include "../world/Footpath.h" +struct FootpathPaintInfo; + constexpr const uint8_t NumVanillaWoodenSupportTypes = 49; 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); bool path_a_supports_paint_setup( 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( 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: // https://cloud.githubusercontent.com/assets/737603/19420485/7eaba28e-93ec-11e6-83cb-03190accc094.png diff --git a/src/openrct2/paint/tile_element/Paint.Path.cpp b/src/openrct2/paint/tile_element/Paint.Path.cpp index 6a8e60fd9d..b232fb565f 100644 --- a/src/openrct2/paint/tile_element/Paint.Path.cpp +++ b/src/openrct2/paint/tile_element/Paint.Path.cpp @@ -13,6 +13,7 @@ #include "../../drawing/LightFX.h" #include "../../interface/Viewport.h" #include "../../localisation/Localisation.h" +#include "../../object/FootpathObject.h" #include "../../object/FootpathRailingsObject.h" #include "../../object/ObjectList.h" #include "../../object/ObjectManager.h" @@ -85,11 +86,11 @@ static constexpr const uint8_t byte_98D8A4[] = { // clang-format on void path_paint_box_support( - paint_session* session, const TileElement* tileElement, int32_t height, PathSurfaceEntry* footpathEntry, - FootpathRailingsObject* railingEntry, bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags); + paint_session* session, const TileElement* tileElement, int32_t height, const FootpathPaintInfo& pathPaintInfo, + bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags); void path_paint_pole_support( - paint_session* session, const TileElement* tileElement, int16_t height, PathSurfaceEntry* footpathEntry, - FootpathRailingsObject* railingEntry, bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags); + paint_session* session, const TileElement* tileElement, int16_t height, const FootpathPaintInfo& pathPaintInfo, + bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags); /* rct2: 0x006A5AE5 */ static void path_bit_lights_paint( @@ -325,9 +326,9 @@ static void path_bit_jumping_fountains_paint( */ static void sub_6A4101( 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()) { @@ -449,7 +450,7 @@ static void sub_6A4101( auto ride = get_ride(tile_element->AsPath()->GetRideIndex()); if (direction < 2 && ride != nullptr && imageFlags == 0) { - uint16_t scrollingMode = railingEntry->ScrollingMode; + uint16_t scrollingMode = pathPaintInfo.ScrollingMode; scrollingMode += direction; auto ft = Formatter(); @@ -492,12 +493,12 @@ static void sub_6A4101( uint32_t drawnCorners = 0; // 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). - 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; } - 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()) { switch ((tile_element->AsPath()->GetSlopeDirection() + session->CurrentRotation) @@ -673,8 +674,7 @@ static void sub_6A4101( */ static void sub_6A3F61( paint_session* session, const TileElement* tile_element, uint16_t connectedEdges, uint16_t height, - PathSurfaceEntry* surfaceEntry, FootpathRailingsObject* railingEntry, uint32_t imageFlags, uint32_t sceneryImageFlags, - bool hasSupports) + const FootpathPaintInfo& pathPaintInfo, uint32_t imageFlags, uint32_t sceneryImageFlags, bool hasSupports) { // eax -- // ebx -- @@ -754,7 +754,7 @@ static void sub_6A3F61( // Redundant zoom-level check removed 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 @@ -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); } - PathSurfaceEntry* footpathEntry = tile_element->AsPath()->GetSurfaceEntry(); - auto railingEntry = tile_element->AsPath()->GetRailingEntry(); - - if (footpathEntry != nullptr && railingEntry != nullptr) + auto footpathObj = tile_element->AsPath()->GetSurfaceEntry(); + if (footpathObj != nullptr) { - if (railingEntry->SupportType == RailingEntrySupportType::Pole) + auto surfaceEntry = tile_element->AsPath()->IsQueue() ? footpathObj->GetQueueEntry() + : footpathObj->GetPathSurfaceEntry(); + auto railingsEntry = footpathObj->GetPathRailingsEntry(); + + FootpathPaintInfo pathPaintInfo; + pathPaintInfo.SurfaceImageId = surfaceEntry->image; + pathPaintInfo.SurfaceFlags = surfaceEntry->flags; + + auto railingObj = tile_element->AsPath()->GetRailingEntry(); + if (railingObj != nullptr) { - path_paint_pole_support( - session, tile_element, height, footpathEntry, railingEntry, hasSupports, imageFlags, sceneryImageFlags); + pathPaintInfo.BridgeImageId = railingObj->BridgeImageId; + pathPaintInfo.RailingsImageId = railingObj->RailingsImageId; + pathPaintInfo.RailingFlags = railingObj->Flags; + pathPaintInfo.ScrollingMode = railingObj->ScrollingMode; + pathPaintInfo.SupportType = railingObj->SupportType; } else { - path_paint_box_support( - session, tile_element, height, footpathEntry, railingEntry, hasSupports, imageFlags, sceneryImageFlags); + pathPaintInfo.BridgeImageId = railingsEntry->bridge_image; + 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( - paint_session* session, const TileElement* tileElement, int32_t height, PathSurfaceEntry* footpathEntry, - FootpathRailingsObject* railingEntry, bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags) + paint_session* session, const TileElement* tileElement, int32_t height, const FootpathPaintInfo& pathPaintInfo, + bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags) { const PathElement* pathElement = tileElement->AsPath(); @@ -1011,20 +1033,18 @@ void path_paint_box_support( uint16_t edi = edges | (corners << 4); - uint32_t imageId; + uint32_t imageId = pathPaintInfo.SurfaceImageId; if (tileElement->AsPath()->IsSloped()) { - imageId = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) - & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK) + imageId += ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) + & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK) + 16; } else { - imageId = byte_98D6E0[edi]; + imageId += byte_98D6E0[edi]; } - imageId += footpathEntry->image; - if (!session->DidPassSurface) { boundBoxOffset.x = 3; @@ -1059,11 +1079,11 @@ void path_paint_box_support( { image_id = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK) - + railingEntry->BridgeImageId + 51; + + pathPaintInfo.BridgeImageId + 51; } else { - image_id = byte_98D8A4[edges] + railingEntry->BridgeImageId + 49; + image_id = byte_98D8A4[edges] + pathPaintInfo.BridgeImageId + 49; } PaintAddImageAsParent( @@ -1071,7 +1091,7 @@ void path_paint_box_support( height + boundingBoxZOffset); // 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 } @@ -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; if (tileElement->AsPath()->IsSloped()) @@ -1091,14 +1111,8 @@ void path_paint_box_support( ax = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) & 0x3) + 1; } - if (byte_98D8A4[edges] == 0) - { - 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); - } + auto supportType = byte_98D8A4[edges] == 0 ? 0 : 1; + path_a_supports_paint_setup(session, supportType, ax, height, imageFlags, pathPaintInfo, nullptr); height += 32; if (tileElement->AsPath()->IsSloped()) @@ -1144,8 +1158,8 @@ void path_paint_box_support( } void path_paint_pole_support( - paint_session* session, const TileElement* tileElement, int16_t height, PathSurfaceEntry* footpathEntry, - FootpathRailingsObject* railingEntry, bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags) + paint_session* session, const TileElement* tileElement, int16_t height, const FootpathPaintInfo& pathPaintInfo, + bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags) { const PathElement* pathElement = tileElement->AsPath(); @@ -1162,18 +1176,16 @@ void path_paint_pole_support( uint16_t edi = edges | (corners << 4); - uint32_t imageId; + uint32_t imageId = pathPaintInfo.SurfaceImageId; if (tileElement->AsPath()->IsSloped()) { - imageId = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) & 3) + 16; + imageId += ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) & 3) + 16; } else { - imageId = byte_98D6E0[edi]; + imageId += byte_98D6E0[edi]; } - imageId += footpathEntry->image; - // Below Surface if (!session->DidPassSurface) { @@ -1209,11 +1221,11 @@ void path_paint_pole_support( { bridgeImage = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK) - + railingEntry->BridgeImageId + 16; + + pathPaintInfo.BridgeImageId + 16; } else { - bridgeImage = edges + railingEntry->BridgeImageId; + bridgeImage = edges + pathPaintInfo.BridgeImageId; bridgeImage |= imageFlags; } @@ -1222,7 +1234,7 @@ void path_paint_pole_support( boundBoxOffset.y, height + boundingBoxZOffset); // 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( session, imageId | imageFlags, 0, 0, boundBoxSize.x, boundBoxSize.y, 0, height, boundBoxOffset.x, @@ -1230,9 +1242,8 @@ void path_paint_pole_support( } } - sub_6A3F61( - session, tileElement, edi, height, footpathEntry, railingEntry, imageFlags, sceneryImageFlags, - hasSupports); // TODO: arguments + sub_6A3F61(session, tileElement, edi, height, pathPaintInfo, imageFlags, sceneryImageFlags, + hasSupports); // TODO: arguments uint16_t ax = 0; if (tileElement->AsPath()->IsSloped()) @@ -1251,7 +1262,7 @@ void path_paint_pole_support( { 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); } } diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 0681a9dd64..5ba5b56e74 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -1132,6 +1132,7 @@ public: auto src2 = src->AsPath(); dst2->SetSurfaceEntryIndex(src2->GetEntryIndex()); + dst2->SetRailingEntryIndex(OBJECT_ENTRY_INDEX_NULL); dst2->SetQueueBannerDirection(src2->GetQueueBannerDirection()); dst2->SetSloped(src2->IsSloped()); dst2->SetSlopeDirection(src2->GetSlopeDirection()); @@ -1567,6 +1568,14 @@ public: } 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; } }; diff --git a/src/openrct2/world/Entrance.cpp b/src/openrct2/world/Entrance.cpp index 103c21e29b..f22ca88455 100644 --- a/src/openrct2/world/Entrance.cpp +++ b/src/openrct2/world/Entrance.cpp @@ -272,12 +272,12 @@ void EntranceElement::SetSequenceIndex(uint8_t newSequenceIndex) SequenceIndex |= (newSequenceIndex & 0xF); } -PathSurfaceIndex EntranceElement::GetPathType() const +ObjectEntryIndex EntranceElement::GetPathType() const { return PathType; } -void EntranceElement::SetPathType(PathSurfaceIndex newPathType) +void EntranceElement::SetPathType(ObjectEntryIndex newPathType) { PathType = newPathType; } diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index 784108b9ef..4a8db5f073 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -1649,37 +1649,53 @@ void PathElement::SetAdditionIsGhost(bool isGhost) Flags2 |= FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_GHOST; } -PathSurfaceIndex PathElement::GetSurfaceEntryIndex() const +ObjectEntryIndex PathElement::GetSurfaceEntryIndex() const { return SurfaceIndex; } -PathRailingsIndex PathElement::GetRailingEntryIndex() const +ObjectEntryIndex PathElement::GetRailingEntryIndex() const { + if (RailingsIndex == std::numeric_limits::max()) + { + return OBJECT_ENTRY_INDEX_NULL; + } return RailingsIndex; } -PathSurfaceEntry* PathElement::GetSurfaceEntry() const +FootpathObject* PathElement::GetSurfaceEntry() const { - if (!IsQueue()) - return get_path_surface_entry(GetSurfaceEntryIndex()); - else - return get_path_surface_entry(GetSurfaceEntryIndex() + MAX_PATH_OBJECTS); + auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); + return static_cast(objMgr.GetLoadedObject(ObjectType::Paths, GetSurfaceEntryIndex())); } FootpathRailingsObject* PathElement::GetRailingEntry() const { - return get_path_railings_entry(GetRailingEntryIndex()); + auto entryIndex = GetRailingEntryIndex(); + if (entryIndex == OBJECT_ENTRY_INDEX_NULL) + { + return nullptr; + } + + auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); + return static_cast(objMgr.GetLoadedObject(ObjectType::FootpathRailings, entryIndex)); } -void PathElement::SetSurfaceEntryIndex(PathSurfaceIndex newIndex) +void PathElement::SetSurfaceEntryIndex(ObjectEntryIndex newIndex) { - SurfaceIndex = newIndex & ~FOOTPATH_ELEMENT_INSERT_QUEUE; + SurfaceIndex = newIndex; } -void PathElement::SetRailingEntryIndex(PathRailingsIndex newEntryIndex) +void PathElement::SetRailingEntryIndex(ObjectEntryIndex newEntryIndex) { - RailingsIndex = newEntryIndex; + if (newEntryIndex == OBJECT_ENTRY_INDEX_NULL) + { + RailingsIndex = std::numeric_limits::max(); + } + else + { + RailingsIndex = static_cast(newEntryIndex); + } } uint8_t PathElement::GetQueueBannerDirection() const @@ -2243,7 +2259,7 @@ void footpath_remove_edges_at(const CoordsXY& footpathPos, TileElement* tileElem tileElement->AsPath()->SetEdgesAndCorners(0); } -PathSurfaceEntry* get_path_surface_entry(PathSurfaceIndex entryIndex) +PathSurfaceEntry* get_path_surface_entry(ObjectEntryIndex entryIndex) { PathSurfaceEntry* result = nullptr; auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); @@ -2259,12 +2275,6 @@ PathSurfaceEntry* get_path_surface_entry(PathSurfaceIndex entryIndex) return result; } -FootpathRailingsObject* get_path_railings_entry(PathRailingsIndex entryIndex) -{ - auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); - return static_cast(objMgr.GetLoadedObject(ObjectType::FootpathRailings, entryIndex)); -} - ride_id_t PathElement::GetRideIndex() const { return rideIndex; diff --git a/src/openrct2/world/Footpath.h b/src/openrct2/world/Footpath.h index e54a51b8f1..f0facb21a1 100644 --- a/src/openrct2/world/Footpath.h +++ b/src/openrct2/world/Footpath.h @@ -29,12 +29,6 @@ constexpr auto PATH_CLEARANCE = 4 * COORDS_Z_STEP; #define FOOTPATH_ELEMENT_INSERT_QUEUE 0x80 -using PathSurfaceIndex = uint16_t; -constexpr PathSurfaceIndex PATH_SURFACE_INDEX_NULL = static_cast(-1); - -using PathRailingsIndex = uint8_t; -constexpr PathRailingsIndex PATH_RAILINGS_INDEX_NULL = static_cast(-1); - enum class RailingEntrySupportType : uint8_t { 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); int32_t entrance_get_directions(const TileElement* tileElement); -PathSurfaceEntry* get_path_surface_entry(PathSurfaceIndex entryIndex); -FootpathRailingsObject* get_path_railings_entry(PathRailingsIndex entryIndex); +PathSurfaceEntry* get_path_surface_entry(ObjectEntryIndex entryIndex); void footpath_queue_chain_reset(); void footpath_queue_chain_push(ride_id_t rideIndex); diff --git a/src/openrct2/world/TileElement.h b/src/openrct2/world/TileElement.h index 0ecce3ff17..0f33f8b5de 100644 --- a/src/openrct2/world/TileElement.h +++ b/src/openrct2/world/TileElement.h @@ -22,6 +22,7 @@ struct rct_footpath_entry; class LargeSceneryObject; class TerrainSurfaceObject; class TerrainEdgeObject; +class FootpathObject; class FootpathRailingsObject; using track_type_t = uint16_t; @@ -254,10 +255,10 @@ struct PathElement : TileElementBase static constexpr TileElementType ElementType = TileElementType::Path; private: - PathSurfaceIndex SurfaceIndex; // 5 + ObjectEntryIndex SurfaceIndex; // 5 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-private-field" - PathRailingsIndex RailingsIndex; // 7 + uint8_t RailingsIndex; // 7 #pragma clang diagnostic pop uint8_t Additions; // 8 (0 means no addition) uint8_t EdgesAndCorners; // 9 (edges in lower 4 bits, corners in upper 4) @@ -275,13 +276,13 @@ private: #pragma clang diagnostic pop public: - PathSurfaceIndex GetSurfaceEntryIndex() const; - PathSurfaceEntry* GetSurfaceEntry() const; - void SetSurfaceEntryIndex(PathSurfaceIndex newIndex); + ObjectEntryIndex GetSurfaceEntryIndex() const; + FootpathObject* GetSurfaceEntry() const; + void SetSurfaceEntryIndex(ObjectEntryIndex newIndex); - PathRailingsIndex GetRailingEntryIndex() const; + ObjectEntryIndex GetRailingEntryIndex() const; FootpathRailingsObject* GetRailingEntry() const; - void SetRailingEntryIndex(PathRailingsIndex newIndex); + void SetRailingEntryIndex(ObjectEntryIndex newIndex); uint8_t GetQueueBannerDirection() const; void SetQueueBannerDirection(uint8_t direction); @@ -560,7 +561,7 @@ private: uint8_t entranceType; // 5 uint8_t SequenceIndex; // 6. Only uses the lower nibble. uint8_t StationIndex; // 7 - PathSurfaceIndex PathType; // 8 + ObjectEntryIndex PathType; // 8 ride_id_t rideIndex; // 9 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-private-field" @@ -580,8 +581,8 @@ public: uint8_t GetSequenceIndex() const; void SetSequenceIndex(uint8_t newSequenceIndex); - PathSurfaceIndex GetPathType() const; - void SetPathType(PathSurfaceIndex newPathType); + ObjectEntryIndex GetPathType() const; + void SetPathType(ObjectEntryIndex newPathType); }; assert_struct_size(EntranceElement, 16);