diff --git a/src/openrct2-ui/windows/Footpath.cpp b/src/openrct2-ui/windows/Footpath.cpp index fc94552e3d..b69532673c 100644 --- a/src/openrct2-ui/windows/Footpath.cpp +++ b/src/openrct2-ui/windows/Footpath.cpp @@ -12,15 +12,18 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include +#include #include #include #include @@ -32,9 +35,10 @@ static constexpr const int32_t WH = 421; static constexpr const int32_t WW = 106; static constexpr const uint16_t ARROW_PULSE_DURATION = 200; +static ObjectEntryIndex _selectedPath = OBJECT_ENTRY_INDEX_NULL; static ObjectEntryIndex _selectedQueue = OBJECT_ENTRY_INDEX_NULL; static ObjectEntryIndex _selectedRailings = OBJECT_ENTRY_INDEX_NULL; -static std::vector _dropdownEntries; +static std::vector> _dropdownEntries; // clang-format off enum @@ -346,16 +350,32 @@ static void window_footpath_dropdown(rct_window* w, rct_widgetindex widgetIndex, if (widgetIndex == WIDX_FOOTPATH_TYPE) { gFootpathSelectedType = SELECTED_PATH_TYPE_NORMAL; - gFootpathSelectedId = entryIndex; + if (entryIndex.first == ObjectType::Paths) + { + _selectedPath = entryIndex.second; + } + else + { + _selectedPath = OBJECT_ENTRY_INDEX_NULL; + gFootpathSelectedId = entryIndex.second; + } } else if (widgetIndex == WIDX_QUEUELINE_TYPE) { gFootpathSelectedType = SELECTED_PATH_TYPE_QUEUE; - _selectedQueue = entryIndex; + if (entryIndex.first == ObjectType::Paths) + { + _selectedPath = entryIndex.second; + } + else + { + _selectedPath = OBJECT_ENTRY_INDEX_NULL; + _selectedQueue = entryIndex.second; + } } else if (widgetIndex == WIDX_RAILINGS_TYPE) { - _selectedRailings = entryIndex; + _selectedRailings = entryIndex.second; } else { @@ -429,7 +449,6 @@ static void window_footpath_toolup(rct_window* w, rct_widgetindex widgetIndex, c */ static void window_footpath_update_provisional_path_for_bridge_mode(rct_window* w) { - ObjectEntryIndex type; int32_t slope; if (gFootpathConstructionMode != PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL) @@ -447,10 +466,21 @@ static void window_footpath_update_provisional_path_for_bridge_mode(rct_window* // Update provisional bridge mode path if (!(gFootpathProvisionalFlags & PROVISIONAL_PATH_FLAG_1)) { + ObjectEntryIndex type; + ObjectEntryIndex railings = _selectedRailings; + CoordsXYZ footpathLoc; footpath_get_next_path_info(&type, footpathLoc, &slope); - auto isQueue = gFootpathSelectedType == SELECTED_PATH_TYPE_QUEUE; - _window_footpath_cost = footpath_provisional_set(type, _selectedRailings, footpathLoc, slope, isQueue); + PathConstructFlags pathConstructFlags = 0; + if (gFootpathSelectedType == SELECTED_PATH_TYPE_QUEUE) + pathConstructFlags |= PathConstructFlag::IsQueue; + if (_selectedPath != OBJECT_ENTRY_INDEX_NULL) + { + pathConstructFlags |= PathConstructFlag::IsPathObject; + type = _selectedPath; + } + + _window_footpath_cost = footpath_provisional_set(type, railings, footpathLoc, slope, pathConstructFlags); widget_invalidate(w, WIDX_CONSTRUCT); } @@ -463,7 +493,7 @@ static void window_footpath_update_provisional_path_for_bridge_mode(rct_window* gFootpathProvisionalFlags ^= PROVISIONAL_PATH_FLAG_SHOW_ARROW; CoordsXYZ footpathLoc; - footpath_get_next_path_info(&type, footpathLoc, &slope); + footpath_get_next_path_info(nullptr, footpathLoc, &slope); gMapSelectArrowPosition = footpathLoc; gMapSelectArrowDirection = gFootpathConstructDirection; if (gFootpathProvisionalFlags & PROVISIONAL_PATH_FLAG_SHOW_ARROW) @@ -545,31 +575,57 @@ static void window_footpath_invalidate(rct_window* w) ? WindowWidgetType::ImgBtn : WindowWidgetType::Empty; - // Set footpath and queue type button images - auto pathImage = static_cast(SPR_NONE); - auto queueImage = static_cast(SPR_NONE); - auto pathEntry = get_path_surface_entry(gFootpathSelectedId); - if (pathEntry != nullptr) + if (_selectedPath == OBJECT_ENTRY_INDEX_NULL) { - pathImage = pathEntry->PreviewImageId; - } + // Set footpath and queue type button images + auto pathImage = static_cast(SPR_NONE); + auto queueImage = static_cast(SPR_NONE); + auto pathEntry = get_path_surface_entry(gFootpathSelectedId); + if (pathEntry != nullptr) + { + pathImage = pathEntry->PreviewImageId; + } - pathEntry = get_path_surface_entry(_selectedQueue); - if (pathEntry != nullptr) + pathEntry = get_path_surface_entry(_selectedQueue); + if (pathEntry != nullptr) + { + queueImage = pathEntry->PreviewImageId; + } + + window_footpath_widgets[WIDX_FOOTPATH_TYPE].image = pathImage; + window_footpath_widgets[WIDX_QUEUELINE_TYPE].image = queueImage; + + // Set railing + auto railingsImage = static_cast(SPR_NONE); + auto railingsEntry = get_path_railings_entry(_selectedRailings); + if (railingsEntry != nullptr) + { + railingsImage = railingsEntry->PreviewImageId; + } + window_footpath_widgets[WIDX_RAILINGS_TYPE].image = railingsImage; + window_footpath_widgets[WIDX_RAILINGS_TYPE].type = WindowWidgetType::FlatBtn; + } + else { - queueImage = pathEntry->PreviewImageId; - } + auto& objManager = OpenRCT2::GetContext()->GetObjectManager(); - window_footpath_widgets[WIDX_FOOTPATH_TYPE].image = pathImage; - window_footpath_widgets[WIDX_QUEUELINE_TYPE].image = queueImage; + // Set footpath and queue type button images + auto pathImage = static_cast(SPR_NONE); + auto queueImage = static_cast(SPR_NONE); + auto pathObj = static_cast(objManager.GetLoadedObject(ObjectType::Paths, _selectedPath)); + if (pathObj != nullptr) + { + auto pathEntry = reinterpret_cast(pathObj->GetLegacyData()); + pathImage = pathEntry->image + 71; + queueImage = pathEntry->image + 72; + } - auto railingsImage = static_cast(SPR_NONE); - auto railingsEntry = get_path_railings_entry(_selectedRailings); - if (railingsEntry != nullptr) - { - railingsImage = railingsEntry->PreviewImageId; + window_footpath_widgets[WIDX_FOOTPATH_TYPE].image = pathImage; + window_footpath_widgets[WIDX_QUEUELINE_TYPE].image = queueImage; + + // Hide railing button + window_footpath_widgets[WIDX_RAILINGS_TYPE].type = WindowWidgetType::Empty; } - window_footpath_widgets[WIDX_RAILINGS_TYPE].image = railingsImage; } /** @@ -595,12 +651,30 @@ static void window_footpath_paint(rct_window* w, rct_drawpixelinfo* dpi) slope = TILE_ELEMENT_SLOPE_E_CORNER_UP; } - auto selectedPath = gFootpathSelectedType == SELECTED_PATH_TYPE_QUEUE ? _selectedQueue : gFootpathSelectedId; - const auto* pathType = get_path_surface_entry(selectedPath); - if (pathType != nullptr) + std::optional baseImage; + if (_selectedPath == OBJECT_ENTRY_INDEX_NULL) { - int32_t image = ConstructionPreviewImages[slope][direction]; - image += pathType->BaseImageId; + auto selectedPath = gFootpathSelectedType == SELECTED_PATH_TYPE_QUEUE ? _selectedQueue : gFootpathSelectedId; + const auto* pathType = get_path_surface_entry(selectedPath); + if (pathType != nullptr) + { + baseImage = pathType->BaseImageId; + } + } + else + { + auto& objManager = OpenRCT2::GetContext()->GetObjectManager(); + auto* pathObj = static_cast(objManager.GetLoadedObject(ObjectType::Paths, _selectedPath)); + if (pathObj != nullptr) + { + auto pathEntry = reinterpret_cast(pathObj->GetLegacyData()); + baseImage = pathEntry->image; + } + } + + if (baseImage) + { + auto image = *baseImage + ConstructionPreviewImages[slope][direction]; // Draw construction image screenCoords = w->windowPos @@ -635,6 +709,8 @@ static void window_footpath_paint(rct_window* w, rct_drawpixelinfo* dpi) */ static void window_footpath_show_footpath_types_dialog(rct_window* w, rct_widget* widget, bool showQueues) { + auto& objManager = OpenRCT2::GetContext()->GetObjectManager(); + uint32_t numPathTypes = 0; // If the game is in sandbox mode, also show paths that are normally restricted to the scenario editor bool showEditorPaths = ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) || gCheatsSandboxMode); @@ -643,7 +719,7 @@ static void window_footpath_show_footpath_types_dialog(rct_window* w, rct_widget std::optional defaultIndex; for (size_t i = 0; i < MAX_FOOTPATH_SURFACE_OBJECTS; i++) { - const auto* pathType = get_path_surface_entry(i); + const auto* pathType = static_cast(objManager.GetLoadedObject(ObjectType::FootpathSurface, i)); if (pathType == nullptr) { continue; @@ -656,14 +732,39 @@ static void window_footpath_show_footpath_types_dialog(rct_window* w, rct_widget { continue; } - if (i == (showQueues ? _selectedQueue : gFootpathSelectedId)) + if (_selectedPath == OBJECT_ENTRY_INDEX_NULL && i == (showQueues ? _selectedQueue : gFootpathSelectedId)) { defaultIndex = numPathTypes; } gDropdownItemsFormat[numPathTypes] = STR_NONE; gDropdownItemsArgs[numPathTypes] = pathType->PreviewImageId; - _dropdownEntries.push_back(i); + _dropdownEntries.push_back({ ObjectType::FootpathSurface, i }); + numPathTypes++; + } + + for (size_t i = 0; i < MAX_PATH_OBJECTS; i++) + { + auto* pathObj = static_cast(objManager.GetLoadedObject(ObjectType::Paths, i)); + if (pathObj == nullptr) + { + continue; + } + + auto pathEntry = reinterpret_cast(pathObj->GetLegacyData()); + if ((pathEntry->flags & FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR) && !showEditorPaths) + { + continue; + } + + if (_selectedPath != OBJECT_ENTRY_INDEX_NULL && _selectedPath == i) + { + defaultIndex = numPathTypes; + } + + gDropdownItemsFormat[numPathTypes] = STR_NONE; + gDropdownItemsArgs[numPathTypes] = pathEntry->image + (showQueues ? 72 : 71); + _dropdownEntries.push_back({ ObjectType::Paths, i }); numPathTypes++; } @@ -696,7 +797,7 @@ static void window_footpath_show_railings_types_dialog(rct_window* w, rct_widget gDropdownItemsFormat[numRailingsTypes] = STR_NONE; gDropdownItemsArgs[numRailingsTypes] = railingsEntry->PreviewImageId; - _dropdownEntries.push_back(i); + _dropdownEntries.push_back({ ObjectType::FootpathRailings, i }); numRailingsTypes++; } @@ -802,9 +903,23 @@ static void window_footpath_set_provisional_path_at_point(const ScreenCoordsXY& z += PATH_HEIGHT_STEP; } - auto isQueue = gFootpathSelectedType == SELECTED_PATH_TYPE_QUEUE; - auto pathType = isQueue ? _selectedQueue : gFootpathSelectedId; - _window_footpath_cost = footpath_provisional_set(pathType, _selectedRailings, { info.Loc, z }, slope, isQueue); + PathConstructFlags constructFlags = 0; + auto pathType = gFootpathSelectedId; + if (gFootpathSelectedType == SELECTED_PATH_TYPE_QUEUE) + { + constructFlags |= PathConstructFlag::IsQueue; + pathType = _selectedQueue; + } + else + { + pathType = gFootpathSelectedId; + } + if (_selectedPath != OBJECT_ENTRY_INDEX_NULL) + { + constructFlags |= PathConstructFlag::IsPathObject; + pathType = _selectedPath; + } + _window_footpath_cost = footpath_provisional_set(pathType, _selectedRailings, { info.Loc, z }, slope, constructFlags); window_invalidate_by_class(WC_FOOTPATH); } } @@ -897,13 +1012,23 @@ static void window_footpath_place_path_at_point(const ScreenCoordsXY& screenCoor slope &= ~RAISE_FOOTPATH_FLAG; z += PATH_HEIGHT_STEP; } - auto selectedType = gFootpathSelectedType == SELECTED_PATH_TYPE_QUEUE ? _selectedQueue : gFootpathSelectedId; // Try and place path gGameCommandErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE; - auto isQueue = gFootpathSelectedType == SELECTED_PATH_TYPE_QUEUE; + auto selectedType = gFootpathSelectedId; + PathConstructFlags constructFlags = 0; + if (gFootpathSelectedType == SELECTED_PATH_TYPE_QUEUE) + { + constructFlags |= PathConstructFlag::IsQueue; + selectedType = _selectedQueue; + } + if (_selectedPath != OBJECT_ENTRY_INDEX_NULL) + { + constructFlags |= PathConstructFlag::IsPathObject; + selectedType = _selectedPath; + } auto footpathPlaceAction = FootpathPlaceAction( - { info.Loc, z }, slope, selectedType, _selectedRailings, INVALID_DIRECTION, isQueue); + { info.Loc, z }, slope, selectedType, _selectedRailings, INVALID_DIRECTION, constructFlags); footpathPlaceAction.SetCallback([](const GameAction* ga, const GameActions::Result* result) { if (result->Error == GameActions::Status::Ok) { @@ -993,9 +1118,16 @@ static void window_footpath_construct() footpath_get_next_path_info(&type, footpathLoc, &slope); gGameCommandErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE; - auto isQueue = gFootpathSelectedType == SELECTED_PATH_TYPE_QUEUE; + PathConstructFlags constructFlags = 0; + if (gFootpathSelectedType == SELECTED_PATH_TYPE_QUEUE) + constructFlags |= PathConstructFlag::IsQueue; + if (_selectedPath != OBJECT_ENTRY_INDEX_NULL) + { + constructFlags |= PathConstructFlag::IsPathObject; + type = _selectedPath; + } auto footpathPlaceAction = FootpathPlaceAction( - footpathLoc, slope, type, _selectedRailings, gFootpathConstructDirection, isQueue); + footpathLoc, slope, type, _selectedRailings, gFootpathConstructDirection, constructFlags); footpathPlaceAction.SetCallback([=](const GameAction* ga, const GameActions::Result* result) { if (result->Error == GameActions::Status::Ok) { @@ -1239,11 +1371,13 @@ static void footpath_get_next_path_info(ObjectEntryIndex* type, CoordsXYZ& footp footpathLoc.z = gFootpathConstructFromPosition.z; if (gFootpathSelectedType == SELECTED_PATH_TYPE_QUEUE) { - *type = _selectedQueue; + if (type != nullptr) + *type = _selectedQueue; } else { - *type = gFootpathSelectedId; + if (type != nullptr) + *type = gFootpathSelectedId; } *slope = TILE_ELEMENT_SLOPE_FLAT; if (gFootpathConstructSlope != 0) diff --git a/src/openrct2/actions/FootpathPlaceAction.cpp b/src/openrct2/actions/FootpathPlaceAction.cpp index deb078b00b..848d1db175 100644 --- a/src/openrct2/actions/FootpathPlaceAction.cpp +++ b/src/openrct2/actions/FootpathPlaceAction.cpp @@ -27,13 +27,13 @@ using namespace OpenRCT2; FootpathPlaceAction::FootpathPlaceAction( const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, ObjectEntryIndex railingsType, Direction direction, - bool isQueue) + PathConstructFlags constructFlags) : _loc(loc) , _slope(slope) , _type(type) , _railingsType(railingsType) , _direction(direction) - , _isQueue(isQueue) + , _constructFlags(constructFlags) { } @@ -44,7 +44,7 @@ void FootpathPlaceAction::AcceptParameters(GameActionParameterVisitor& visitor) visitor.Visit("railingsObject", _railingsType); visitor.Visit("direction", _direction); visitor.Visit("slope", _slope); - visitor.Visit("isQueue", _isQueue); + visitor.Visit("constructFlags", _constructFlags); } uint16_t FootpathPlaceAction::GetActionFlags() const @@ -56,7 +56,7 @@ void FootpathPlaceAction::Serialise(DataSerialiser& stream) { GameAction::Serialise(stream); - stream << DS_TAG(_loc) << DS_TAG(_slope) << DS_TAG(_type) << DS_TAG(_direction) << DS_TAG(_isQueue); + stream << DS_TAG(_loc) << DS_TAG(_slope) << DS_TAG(_type) << DS_TAG(_direction) << DS_TAG(_constructFlags); } GameActions::Result::Ptr FootpathPlaceAction::Query() const @@ -155,10 +155,40 @@ GameActions::Result::Ptr FootpathPlaceAction::Execute() const } } +bool FootpathPlaceAction::IsSameAsPathElement(const PathElement* pathElement) const +{ + // Check if both this action and the element is queue + if (pathElement->IsQueue() != ((_constructFlags & PathConstructFlag::IsQueue) != 0)) + return false; + + auto footpathObj = pathElement->GetPathEntry(); + if (footpathObj == nullptr) + { + if (_constructFlags & PathConstructFlag::IsPathObject) + { + return false; + } + else + { + return pathElement->GetSurfaceEntryIndex() == _type && pathElement->GetRailingEntryIndex() == _railingsType; + } + } + else + { + if (_constructFlags & PathConstructFlag::IsPathObject) + { + return pathElement->GetPathEntryIndex() == _type; + } + else + { + return false; + } + } +} + GameActions::Result::Ptr FootpathPlaceAction::ElementUpdateQuery(PathElement* pathElement, GameActions::Result::Ptr res) const { - if (pathElement->GetSurfaceEntryIndex() != _type || pathElement->GetRailingEntryIndex() != _railingsType - || pathElement->IsQueue() != _isQueue) + if (!IsSameAsPathElement(pathElement)) { res->Cost += MONEY(6, 00); } @@ -172,8 +202,7 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementUpdateQuery(PathElement* pa GameActions::Result::Ptr FootpathPlaceAction::ElementUpdateExecute(PathElement* pathElement, GameActions::Result::Ptr res) const { - if (pathElement->GetSurfaceEntryIndex() != _type || pathElement->GetRailingEntryIndex() != _railingsType - || pathElement->IsQueue() != _isQueue) + if (!IsSameAsPathElement(pathElement)) { res->Cost += MONEY(6, 00); } @@ -185,14 +214,22 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementUpdateExecute(PathElement* footpath_remove_edges_at(_loc, reinterpret_cast(pathElement)); } - pathElement->SetSurfaceEntryIndex(_type); - pathElement->SetRailingEntryIndex(_railingsType); - pathElement->SetIsQueue(_isQueue); + if (_constructFlags & PathConstructFlag::IsPathObject) + { + pathElement->SetPathEntryIndex(_type); + } + else + { + pathElement->SetSurfaceEntryIndex(_type); + pathElement->SetRailingEntryIndex(_railingsType); + } + + pathElement->SetIsQueue((_constructFlags & PathConstructFlag::IsQueue) != 0); rct_scenery_entry* elem = pathElement->GetAdditionEntry(); if (elem != nullptr) { - if (_isQueue) + if (_constructFlags & PathConstructFlag::IsQueue) { // remove any addition that isn't a TV or a lamp if ((elem->path_bit.flags & PATH_BIT_FLAG_IS_QUEUE_SCREEN) == 0 && (elem->path_bit.flags & PATH_BIT_FLAG_LAMP) == 0) @@ -249,8 +286,9 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementInsertQuery(GameActions::Re } // Do not attempt to build a crossing with a queue or a sloped. - uint8_t crossingMode = _isQueue || (_slope != TILE_ELEMENT_SLOPE_FLAT) ? CREATE_CROSSING_MODE_NONE - : CREATE_CROSSING_MODE_PATH_OVER_TRACK; + auto isQueue = _constructFlags & PathConstructFlag::IsQueue; + uint8_t crossingMode = isQueue || (_slope != TILE_ELEMENT_SLOPE_FLAT) ? CREATE_CROSSING_MODE_NONE + : CREATE_CROSSING_MODE_PATH_OVER_TRACK; if (!entrancePath && !map_can_construct_with_clear_at( { _loc, zLow, zHigh }, &map_place_non_scenery_clear_func, quarterTile, GetFlags(), &res->Cost, crossingMode)) @@ -313,8 +351,9 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementInsertExecute(GameActions:: } // Do not attempt to build a crossing with a queue or a sloped. - uint8_t crossingMode = _isQueue || (_slope != TILE_ELEMENT_SLOPE_FLAT) ? CREATE_CROSSING_MODE_NONE - : CREATE_CROSSING_MODE_PATH_OVER_TRACK; + auto isQueue = _constructFlags & PathConstructFlag::IsQueue; + uint8_t crossingMode = isQueue || (_slope != TILE_ELEMENT_SLOPE_FLAT) ? CREATE_CROSSING_MODE_NONE + : CREATE_CROSSING_MODE_PATH_OVER_TRACK; if (!entrancePath && !map_can_construct_with_clear_at( { _loc, zLow, zHigh }, &map_place_non_scenery_clear_func, quarterTile, GAME_COMMAND_FLAG_APPLY | GetFlags(), @@ -338,7 +377,14 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementInsertExecute(GameActions:: { if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && !entranceIsSamePath) { - entranceElement->SetSurfaceEntryIndex(_type); + if (_constructFlags & PathConstructFlag::IsPathObject) + { + entranceElement->SetPathEntryIndex(_type); + } + else + { + entranceElement->SetSurfaceEntryIndex(_type); + } map_invalidate_tile_full(_loc); } } @@ -348,11 +394,18 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementInsertExecute(GameActions:: Guard::Assert(pathElement != nullptr); pathElement->SetClearanceZ(zHigh); - pathElement->SetSurfaceEntryIndex(_type); - pathElement->SetRailingEntryIndex(_railingsType); + if (_constructFlags & PathConstructFlag::IsPathObject) + { + pathElement->SetPathEntryIndex(_type); + } + else + { + pathElement->SetSurfaceEntryIndex(_type); + pathElement->SetRailingEntryIndex(_railingsType); + } pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK); pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED); - pathElement->SetIsQueue(_isQueue); + pathElement->SetIsQueue(isQueue); pathElement->SetAddition(0); pathElement->SetRideIndex(RIDE_ID_NULL); pathElement->SetAdditionStatus(255); diff --git a/src/openrct2/actions/FootpathPlaceAction.h b/src/openrct2/actions/FootpathPlaceAction.h index 777769c740..2e208f24d7 100644 --- a/src/openrct2/actions/FootpathPlaceAction.h +++ b/src/openrct2/actions/FootpathPlaceAction.h @@ -20,14 +20,13 @@ private: ObjectEntryIndex _type{}; ObjectEntryIndex _railingsType{}; Direction _direction{ INVALID_DIRECTION }; - bool _isQueue{}; + PathConstructFlags _constructFlags{}; public: FootpathPlaceAction() = default; FootpathPlaceAction( const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, ObjectEntryIndex railingsType, - Direction direction = INVALID_DIRECTION, - bool isQueue = false); + Direction direction = INVALID_DIRECTION, PathConstructFlags constructFlags = 0); void AcceptParameters(GameActionParameterVisitor & visitor) override; @@ -45,4 +44,5 @@ private: void AutomaticallySetPeepSpawn() const; void RemoveIntersectingWalls(PathElement * pathElement) const; PathElement* map_get_footpath_element_slope(const CoordsXYZ& footpathPos, int32_t slope) const; + bool IsSameAsPathElement(const PathElement* pathElement) const; }; diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index e6671a3bbd..7a9b1d334f 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -47,7 +47,7 @@ CoordsXYZ gFootpathProvisionalPosition; ObjectEntryIndex gFootpathProvisionalSurfaceIndex; ObjectEntryIndex gFootpathProvisionalRailingsIndex; uint8_t gFootpathProvisionalSlope; -bool gFootpathProvisionalIsQueue; +PathConstructFlags gFootpathProvisionalConstructFlags; uint8_t gFootpathConstructionMode; uint16_t gFootpathSelectedId; uint8_t gFootpathSelectedType; @@ -151,13 +151,14 @@ money32 footpath_remove(const CoordsXYZ& footpathLoc, int32_t flags) * rct2: 0x006A76FF */ money32 footpath_provisional_set( - ObjectEntryIndex type, ObjectEntryIndex railingsType, const CoordsXYZ& footpathLoc, int32_t slope, bool isQueue) + ObjectEntryIndex type, ObjectEntryIndex railingsType, const CoordsXYZ& footpathLoc, int32_t slope, + PathConstructFlags constructFlags) { money32 cost; footpath_provisional_remove(); - auto footpathPlaceAction = FootpathPlaceAction(footpathLoc, slope, type, railingsType, INVALID_DIRECTION, isQueue); + auto footpathPlaceAction = FootpathPlaceAction(footpathLoc, slope, type, railingsType, INVALID_DIRECTION, constructFlags); footpathPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED); auto res = GameActions::Execute(&footpathPlaceAction); cost = res->Error == GameActions::Status::Ok ? res->Cost : MONEY32_UNDEFINED; @@ -167,7 +168,7 @@ money32 footpath_provisional_set( gFootpathProvisionalRailingsIndex = railingsType; gFootpathProvisionalPosition = footpathLoc; gFootpathProvisionalSlope = slope; - gFootpathProvisionalIsQueue = isQueue; + gFootpathProvisionalConstructFlags = constructFlags; gFootpathProvisionalFlags |= PROVISIONAL_PATH_FLAG_1; if (gFootpathGroundFlags & ELEMENT_IS_UNDERGROUND) diff --git a/src/openrct2/world/Footpath.h b/src/openrct2/world/Footpath.h index f103d66e28..1bd9488929 100644 --- a/src/openrct2/world/Footpath.h +++ b/src/openrct2/world/Footpath.h @@ -155,12 +155,19 @@ enum FOOTPATH_CONNECTED_MAP_EDGE_IGNORE_NO_ENTRY = (1 << 7) }; +using PathConstructFlags = uint8_t; +namespace PathConstructFlag +{ + constexpr PathConstructFlags IsQueue = 1 << 0; + constexpr PathConstructFlags IsPathObject = 1 << 1; +} // namespace PathConstructFlag + extern uint8_t gFootpathProvisionalFlags; extern CoordsXYZ gFootpathProvisionalPosition; extern ObjectEntryIndex gFootpathProvisionalSurfaceIndex; extern ObjectEntryIndex gFootpathProvisionalRailingsIndex; extern uint8_t gFootpathProvisionalSlope; -extern bool gFootpathProvisionalIsQueue; +extern PathConstructFlags gFootpathProvisionalConstructFlags; extern uint8_t gFootpathConstructionMode; extern uint16_t gFootpathSelectedId; extern uint8_t gFootpathSelectedType; @@ -180,7 +187,8 @@ TileElement* map_get_footpath_element(const CoordsXYZ& coords); void footpath_interrupt_peeps(const CoordsXYZ& footpathPos); money32 footpath_remove(const CoordsXYZ& footpathLoc, int32_t flags); money32 footpath_provisional_set( - ObjectEntryIndex type, ObjectEntryIndex railingsType, const CoordsXYZ& footpathLoc, int32_t slope, bool isQueue); + ObjectEntryIndex type, ObjectEntryIndex railingsType, const CoordsXYZ& footpathLoc, int32_t slope, + PathConstructFlags constructFlags); void footpath_provisional_remove(); void footpath_provisional_update(); CoordsXY footpath_get_coordinates_from_pos(const ScreenCoordsXY& screenCoords, int32_t* direction, TileElement** tileElement); diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 6abf8e0860..b2322d3279 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -1556,7 +1556,7 @@ void map_restore_provisional_elements() gFootpathProvisionalFlags &= ~PROVISIONAL_PATH_FLAG_1; footpath_provisional_set( gFootpathProvisionalSurfaceIndex, gFootpathProvisionalRailingsIndex, gFootpathProvisionalPosition, - gFootpathProvisionalSlope, gFootpathProvisionalIsQueue); + gFootpathProvisionalSlope, gFootpathProvisionalConstructFlags); } if (window_find_by_class(WC_RIDE_CONSTRUCTION) != nullptr) {