1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-18 04:23:20 +01:00

Allow setting path railings from Footpath window (WIP)

This commit is contained in:
Gymnasiast
2021-04-14 13:56:23 +02:00
parent 6c76036ac2
commit 8d8036eb2b
7 changed files with 108 additions and 35 deletions

View File

@@ -18,6 +18,7 @@
#include <openrct2/actions/FootpathPlaceAction.h>
#include <openrct2/audio/audio.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/object/FootpathRailingsObject.h>
#include <openrct2/object/ObjectLimits.h>
#include <openrct2/platform/platform.h>
#include <openrct2/sprites.h>
@@ -26,10 +27,12 @@
#include <openrct2/world/Surface.h>
static constexpr const rct_string_id WINDOW_TITLE = STR_FOOTPATHS;
static constexpr const int32_t WH = 381;
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 _selectedRailings = OBJECT_ENTRY_INDEX_NULL;
// clang-format off
enum
{
@@ -53,6 +56,7 @@ enum WINDOW_FOOTPATH_WIDGET_IDX
WIDX_TYPE_GROUP,
WIDX_FOOTPATH_TYPE,
WIDX_QUEUELINE_TYPE,
WIDX_RAILINGS_TYPE,
WIDX_DIRECTION_GROUP,
WIDX_DIRECTION_NW,
@@ -76,29 +80,30 @@ static rct_widget window_footpath_widgets[] = {
WINDOW_SHIM(WINDOW_TITLE, WW, WH),
// Type group
MakeWidget({ 3, 17}, {100, 55}, WindowWidgetType::Groupbox, WindowColour::Primary , STR_TYPE ),
MakeWidget({ 3, 17}, {100, 95}, WindowWidgetType::Groupbox, WindowColour::Primary , STR_TYPE ),
MakeWidget({ 6, 30}, { 47, 36}, WindowWidgetType::FlatBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_FOOTPATH_TIP ),
MakeWidget({53, 30}, { 47, 36}, WindowWidgetType::FlatBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_QUEUE_LINE_PATH_TIP ),
MakeWidget({29, 69}, { 47, 36}, WindowWidgetType::FlatBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_FOOTPATH_TIP ),
// Direction group
MakeWidget({ 3, 75}, {100, 77}, WindowWidgetType::Groupbox, WindowColour::Primary , STR_DIRECTION ),
MakeWidget({53, 87}, { 45, 29}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_CONSTRUCTION_DIRECTION_NE, STR_DIRECTION_TIP ),
MakeWidget({53, 116}, { 45, 29}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_CONSTRUCTION_DIRECTION_SE, STR_DIRECTION_TIP ),
MakeWidget({ 8, 116}, { 45, 29}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_CONSTRUCTION_DIRECTION_SW, STR_DIRECTION_TIP ),
MakeWidget({ 8, 87}, { 45, 29}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_CONSTRUCTION_DIRECTION_NW, STR_DIRECTION_TIP ),
MakeWidget({ 3, 115}, {100, 77}, WindowWidgetType::Groupbox, WindowColour::Primary , STR_DIRECTION ),
MakeWidget({53, 127}, { 45, 29}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_CONSTRUCTION_DIRECTION_NE, STR_DIRECTION_TIP ),
MakeWidget({53, 156}, { 45, 29}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_CONSTRUCTION_DIRECTION_SE, STR_DIRECTION_TIP ),
MakeWidget({ 8, 156}, { 45, 29}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_CONSTRUCTION_DIRECTION_SW, STR_DIRECTION_TIP ),
MakeWidget({ 8, 127}, { 45, 29}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_CONSTRUCTION_DIRECTION_NW, STR_DIRECTION_TIP ),
// Slope group
MakeWidget({ 3, 155}, {100, 41}, WindowWidgetType::Groupbox, WindowColour::Primary , STR_SLOPE ),
MakeWidget({17, 167}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_RIDE_CONSTRUCTION_SLOPE_DOWN, STR_SLOPE_DOWN_TIP ),
MakeWidget({41, 167}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_RIDE_CONSTRUCTION_SLOPE_LEVEL, STR_LEVEL_TIP ),
MakeWidget({65, 167}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_RIDE_CONSTRUCTION_SLOPE_UP, STR_SLOPE_UP_TIP ),
MakeWidget({ 8, 202}, { 90, 90}, WindowWidgetType::FlatBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_CONSTRUCT_THE_SELECTED_FOOTPATH_SECTION_TIP),
MakeWidget({30, 295}, { 46, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_DEMOLISH_CURRENT_SECTION, STR_REMOVE_PREVIOUS_FOOTPATH_SECTION_TIP ),
MakeWidget({ 3, 195}, {100, 41}, WindowWidgetType::Groupbox, WindowColour::Primary , STR_SLOPE ),
MakeWidget({17, 207}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_RIDE_CONSTRUCTION_SLOPE_DOWN, STR_SLOPE_DOWN_TIP ),
MakeWidget({41, 207}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_RIDE_CONSTRUCTION_SLOPE_LEVEL, STR_LEVEL_TIP ),
MakeWidget({65, 207}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_RIDE_CONSTRUCTION_SLOPE_UP, STR_SLOPE_UP_TIP ),
MakeWidget({ 8, 242}, { 90, 90}, WindowWidgetType::FlatBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_CONSTRUCT_THE_SELECTED_FOOTPATH_SECTION_TIP),
MakeWidget({30, 335}, { 46, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_DEMOLISH_CURRENT_SECTION, STR_REMOVE_PREVIOUS_FOOTPATH_SECTION_TIP ),
// Mode group
MakeWidget({ 3, 321}, {100, 54}, WindowWidgetType::Groupbox, WindowColour::Primary ),
MakeWidget({13, 332}, { 36, 36}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_CONSTRUCTION_FOOTPATH_LAND, STR_CONSTRUCT_FOOTPATH_ON_LAND_TIP ),
MakeWidget({57, 332}, { 36, 36}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_CONSTRUCTION_FOOTPATH_BRIDGE, STR_CONSTRUCT_BRIDGE_OR_TUNNEL_FOOTPATH_TIP ),
MakeWidget({ 3, 361}, {100, 54}, WindowWidgetType::Groupbox, WindowColour::Primary ),
MakeWidget({13, 372}, { 36, 36}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_CONSTRUCTION_FOOTPATH_LAND, STR_CONSTRUCT_FOOTPATH_ON_LAND_TIP ),
MakeWidget({57, 372}, { 36, 36}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_CONSTRUCTION_FOOTPATH_BRIDGE, STR_CONSTRUCT_BRIDGE_OR_TUNNEL_FOOTPATH_TIP ),
{WIDGETS_END},
};
@@ -165,6 +170,7 @@ static constexpr const uint8_t ConstructionPreviewImages[][4] = {
static void window_footpath_mousedown_direction(int32_t direction);
static void window_footpath_mousedown_slope(int32_t slope);
static void window_footpath_show_footpath_types_dialog(rct_window* w, rct_widget* widget, bool showQueues);
static void window_footpath_show_railings_types_dialog(rct_window* w, rct_widget* widget);
static void window_footpath_set_provisional_path_at_point(const ScreenCoordsXY& screenCoords);
static void window_footpath_set_selection_start_bridge_at_point(const ScreenCoordsXY& screenCoords);
static void window_footpath_place_path_at_point(const ScreenCoordsXY& screenCoords);
@@ -205,12 +211,12 @@ rct_window* window_footpath_open()
return window;
}
window = WindowCreate(ScreenCoordsXY(0, 29), 106, 381, &window_footpath_events, WC_FOOTPATH, 0);
window = WindowCreate(ScreenCoordsXY(0, 29), WW, WH, &window_footpath_events, WC_FOOTPATH, 0);
window->widgets = window_footpath_widgets;
window->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_FOOTPATH_TYPE) | (1 << WIDX_QUEUELINE_TYPE)
| (1 << WIDX_DIRECTION_NW) | (1 << WIDX_DIRECTION_NE) | (1 << WIDX_DIRECTION_SW) | (1 << WIDX_DIRECTION_SE)
| (1 << WIDX_SLOPEDOWN) | (1 << WIDX_LEVEL) | (1 << WIDX_SLOPEUP) | (1 << WIDX_CONSTRUCT) | (1 << WIDX_REMOVE)
| (1 << WIDX_CONSTRUCT_ON_LAND) | (1 << WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL);
| (1 << WIDX_RAILINGS_TYPE) | (1 << WIDX_DIRECTION_NW) | (1 << WIDX_DIRECTION_NE) | (1 << WIDX_DIRECTION_SW)
| (1 << WIDX_DIRECTION_SE) | (1 << WIDX_SLOPEDOWN) | (1 << WIDX_LEVEL) | (1 << WIDX_SLOPEUP) | (1 << WIDX_CONSTRUCT)
| (1 << WIDX_REMOVE) | (1 << WIDX_CONSTRUCT_ON_LAND) | (1 << WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL);
WindowInitScrollWidgets(window);
window_push_others_right(window);
@@ -308,6 +314,9 @@ static void window_footpath_mousedown(rct_window* w, rct_widgetindex widgetIndex
case WIDX_QUEUELINE_TYPE:
window_footpath_show_footpath_types_dialog(w, widget, true);
break;
case WIDX_RAILINGS_TYPE:
window_footpath_show_railings_types_dialog(w, widget);
break;
case WIDX_DIRECTION_NW:
window_footpath_mousedown_direction(0);
break;
@@ -346,6 +355,16 @@ static void window_footpath_dropdown(rct_window* w, rct_widgetindex widgetIndex,
{
gFootpathSelectedType = SELECTED_PATH_TYPE_QUEUE;
}
else if (widgetIndex == WIDX_RAILINGS_TYPE)
{
if (dropdownIndex != -1)
_selectedRailings = dropdownIndex;
footpath_provisional_update();
_window_footpath_cost = MONEY32_UNDEFINED;
w->Invalidate();
return;
}
else
{
return;
@@ -471,7 +490,7 @@ static void window_footpath_update_provisional_path_for_bridge_mode(rct_window*
{
CoordsXYZ footpathLoc;
footpath_get_next_path_info(&type, footpathLoc, &slope);
_window_footpath_cost = footpath_provisional_set(type, footpathLoc, slope);
_window_footpath_cost = footpath_provisional_set(type, _selectedRailings, footpathLoc, slope);
widget_invalidate(w, WIDX_CONSTRUCT);
}
@@ -578,6 +597,14 @@ static void window_footpath_invalidate(rct_window* w)
}
window_footpath_widgets[WIDX_FOOTPATH_TYPE].image = pathImage;
window_footpath_widgets[WIDX_QUEUELINE_TYPE].image = queueImage;
auto railingsImage = static_cast<uint32_t>(SPR_NONE);
auto railingsEntry = get_path_railings_entry(_selectedRailings);
if (railingsEntry != nullptr)
{
railingsImage = railingsEntry->PreviewImageId;
}
window_footpath_widgets[WIDX_RAILINGS_TYPE].image = railingsImage;
}
/**
@@ -677,6 +704,32 @@ static void window_footpath_show_footpath_types_dialog(rct_window* w, rct_widget
36, itemsPerRow);
}
static void window_footpath_show_railings_types_dialog(rct_window* w, rct_widget* widget)
{
uint32_t numRailingsTypes = 0;
// If the game is in sandbox mode, also show paths that are normally restricted to the scenario editor
for (int32_t i = 0; i < MAX_FOOTPATH_RAILINGS_OBJECTS; i++)
{
FootpathRailingsObject* railingsEntry = get_path_railings_entry(i);
if (railingsEntry == nullptr)
{
continue;
}
int32_t image = railingsEntry->PreviewImageId;
gDropdownItemsFormat[numRailingsTypes] = STR_NONE;
gDropdownItemsArgs[numRailingsTypes] = image;
numRailingsTypes++;
}
auto itemsPerRow = DropdownGetAppropriateImageDropdownItemsPerRow(numRailingsTypes);
WindowDropdownShowImage(
w->windowPos.x + widget->left, w->windowPos.y + widget->top, widget->height() + 1, w->colours[1], 0, numRailingsTypes,
47, 36, itemsPerRow);
}
/**
*
* rct2: 0x006A8111 0x006A8135 0x006A815C 0x006A8183
@@ -772,7 +825,7 @@ static void window_footpath_set_provisional_path_at_point(const ScreenCoordsXY&
}
int32_t pathType = (gFootpathSelectedType << 7) + (gFootpathSelectedId & 0xFF);
_window_footpath_cost = footpath_provisional_set(pathType, { info.Loc, z }, slope);
_window_footpath_cost = footpath_provisional_set(pathType, _selectedRailings, { info.Loc, z }, slope);
window_invalidate_by_class(WC_FOOTPATH);
}
}
@@ -869,7 +922,7 @@ static void window_footpath_place_path_at_point(const ScreenCoordsXY& screenCoor
// Try and place path
gGameCommandErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE;
auto footpathPlaceAction = FootpathPlaceAction({ info.Loc, z }, slope, selectedType);
auto footpathPlaceAction = FootpathPlaceAction({ info.Loc, z }, slope, selectedType, _selectedRailings);
footpathPlaceAction.SetCallback([](const GameAction* ga, const GameActions::Result* result) {
if (result->Error == GameActions::Status::Ok)
{
@@ -958,7 +1011,7 @@ static void window_footpath_construct()
footpath_get_next_path_info(&type, footpathLoc, &slope);
gGameCommandErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE;
auto footpathPlaceAction = FootpathPlaceAction(footpathLoc, slope, type, gFootpathConstructDirection);
auto footpathPlaceAction = FootpathPlaceAction(footpathLoc, slope, type, _selectedRailings, gFootpathConstructDirection);
footpathPlaceAction.SetCallback([=](const GameAction* ga, const GameActions::Result* result) {
if (result->Error == GameActions::Status::Ok)
{

View File

@@ -25,10 +25,12 @@
using namespace OpenRCT2;
FootpathPlaceAction::FootpathPlaceAction(const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, Direction direction)
FootpathPlaceAction::FootpathPlaceAction(
const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, ObjectEntryIndex railingsType, Direction direction)
: _loc(loc)
, _slope(slope)
, _type(type)
, _railingsType(railingsType)
, _direction(direction)
{
}
@@ -37,6 +39,7 @@ void FootpathPlaceAction::AcceptParameters(GameActionParameterVisitor& visitor)
{
visitor.Visit(_loc);
visitor.Visit("object", _type);
visitor.Visit("railingsObject", _railingsType);
visitor.Visit("direction", _direction);
visitor.Visit("slope", _slope);
}
@@ -182,7 +185,7 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementUpdateExecute(PathElement*
}
pathElement->SetSurfaceEntryIndex(_type & ~FOOTPATH_ELEMENT_INSERT_QUEUE);
pathElement->SetRailingEntryIndex(OBJECT_ENTRY_INDEX_NULL);
pathElement->SetRailingEntryIndex(_railingsType);
bool isQueue = _type & FOOTPATH_ELEMENT_INSERT_QUEUE;
pathElement->SetIsQueue(isQueue);
@@ -349,7 +352,7 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementInsertExecute(GameActions::
pathElement->SetClearanceZ(zHigh);
pathElement->SetSurfaceEntryIndex(_type & ~FOOTPATH_ELEMENT_INSERT_QUEUE);
pathElement->SetRailingEntryIndex(OBJECT_ENTRY_INDEX_NULL);
pathElement->SetRailingEntryIndex(_railingsType);
pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK);
pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED);
pathElement->SetIsQueue(_type & FOOTPATH_ELEMENT_INSERT_QUEUE);

View File

@@ -18,11 +18,14 @@ private:
CoordsXYZ _loc;
uint8_t _slope{};
ObjectEntryIndex _type{};
ObjectEntryIndex _railingsType{};
Direction _direction{ INVALID_DIRECTION };
public:
FootpathPlaceAction() = default;
FootpathPlaceAction(const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, Direction direction = INVALID_DIRECTION);
FootpathPlaceAction(
const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, ObjectEntryIndex railingsType,
Direction direction = INVALID_DIRECTION);
void AcceptParameters(GameActionParameterVisitor & visitor) override;

View File

@@ -1,4 +1,4 @@
/*****************************************************************************
/*****************************************************************************
* Copyright (c) 2014-2020 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
@@ -829,8 +829,8 @@ paint_struct* PaintAddImageAsChild(
int32_t bound_box_length_y, int32_t bound_box_length_z, int32_t z_offset, int32_t bound_box_offset_x,
int32_t bound_box_offset_y, int32_t bound_box_offset_z)
{
assert(bound_box_length_x > 0);
assert(bound_box_length_y > 0);
/*assert(bound_box_length_x > 0);
assert(bound_box_length_y > 0);*/
return PaintAddImageAsChild(
session, image_id, { x_offset, y_offset, z_offset }, { bound_box_length_x, bound_box_length_y, bound_box_length_z },
{ bound_box_offset_x, bound_box_offset_y, bound_box_offset_z });

View File

@@ -147,13 +147,14 @@ money32 footpath_remove(const CoordsXYZ& footpathLoc, int32_t flags)
*
* rct2: 0x006A76FF
*/
money32 footpath_provisional_set(int32_t type, const CoordsXYZ& footpathLoc, int32_t slope)
money32 footpath_provisional_set(
ObjectEntryIndex type, ObjectEntryIndex railingsType, const CoordsXYZ& footpathLoc, int32_t slope)
{
money32 cost;
footpath_provisional_remove();
auto footpathPlaceAction = FootpathPlaceAction(footpathLoc, slope, type);
auto footpathPlaceAction = FootpathPlaceAction(footpathLoc, slope, type, railingsType);
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;
@@ -2275,6 +2276,16 @@ PathSurfaceEntry* get_path_surface_entry(ObjectEntryIndex entryIndex)
return result;
}
FootpathRailingsObject* get_path_railings_entry(ObjectEntryIndex entryIndex)
{
auto& objMgr = OpenRCT2::GetContext()->GetObjectManager();
auto obj = objMgr.GetLoadedObject(ObjectType::FootpathRailings, entryIndex);
if (obj == nullptr)
return nullptr;
return static_cast<FootpathRailingsObject*>(obj);
}
ride_id_t PathElement::GetRideIndex() const
{
return rideIndex;

View File

@@ -177,7 +177,8 @@ extern const CoordsXY BenchUseOffsets[NumOrthogonalDirections * 2];
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(int32_t type, const CoordsXYZ& footpathLoc, int32_t slope);
money32 footpath_provisional_set(
ObjectEntryIndex type, ObjectEntryIndex railingsType, const CoordsXYZ& footpathLoc, int32_t slope);
void footpath_provisional_remove();
void footpath_provisional_update();
CoordsXY footpath_get_coordinates_from_pos(const ScreenCoordsXY& screenCoords, int32_t* direction, TileElement** tileElement);
@@ -196,6 +197,7 @@ void footpath_remove_edges_at(const CoordsXY& footpathPos, TileElement* tileElem
int32_t entrance_get_directions(const TileElement* tileElement);
PathSurfaceEntry* get_path_surface_entry(ObjectEntryIndex entryIndex);
FootpathRailingsObject* get_path_railings_entry(ObjectEntryIndex entryIndex);
void footpath_queue_chain_reset();
void footpath_queue_chain_push(ride_id_t rideIndex);

View File

@@ -1554,7 +1554,8 @@ void map_restore_provisional_elements()
if (gFootpathProvisionalFlags & PROVISIONAL_PATH_FLAG_1)
{
gFootpathProvisionalFlags &= ~PROVISIONAL_PATH_FLAG_1;
footpath_provisional_set(gFootpathProvisionalType, gFootpathProvisionalPosition, gFootpathProvisionalSlope);
footpath_provisional_set(
gFootpathProvisionalType, OBJECT_ENTRY_INDEX_NULL, gFootpathProvisionalPosition, gFootpathProvisionalSlope);
}
if (window_find_by_class(WC_RIDE_CONSTRUCTION) != nullptr)
{