2014-04-28 18:35:12 +02:00
|
|
|
/*****************************************************************************
|
2020-07-21 15:04:34 +02:00
|
|
|
* Copyright (c) 2014-2020 OpenRCT2 developers
|
2014-04-28 18:35:12 +02:00
|
|
|
*
|
2018-06-15 14:07:34 +02:00
|
|
|
* For a complete list of all authors, please refer to contributors.md
|
|
|
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
2014-04-28 18:35:12 +02:00
|
|
|
*
|
2018-06-15 14:07:34 +02:00
|
|
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
2014-04-28 18:35:12 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
2018-06-22 23:21:44 +02:00
|
|
|
#include <openrct2-ui/interface/Dropdown.h>
|
|
|
|
#include <openrct2-ui/interface/Viewport.h>
|
|
|
|
#include <openrct2-ui/interface/Widget.h>
|
2017-08-12 23:06:12 +02:00
|
|
|
#include <openrct2-ui/windows/Window.h>
|
2017-12-13 13:02:24 +01:00
|
|
|
#include <openrct2/Cheats.h>
|
2017-11-30 18:17:06 +01:00
|
|
|
#include <openrct2/Game.h>
|
2017-12-12 14:52:57 +01:00
|
|
|
#include <openrct2/Input.h>
|
2018-06-22 23:21:44 +02:00
|
|
|
#include <openrct2/OpenRCT2.h>
|
2019-03-01 18:17:46 +01:00
|
|
|
#include <openrct2/actions/FootpathPlaceAction.hpp>
|
2018-06-22 23:21:44 +02:00
|
|
|
#include <openrct2/audio/audio.h>
|
2018-01-06 18:32:25 +01:00
|
|
|
#include <openrct2/localisation/Localisation.h>
|
2018-01-02 20:36:42 +01:00
|
|
|
#include <openrct2/object/ObjectLimits.h>
|
2020-10-03 19:41:56 +02:00
|
|
|
#include <openrct2/platform/platform.h>
|
2017-09-18 17:05:28 +02:00
|
|
|
#include <openrct2/sprites.h>
|
2018-01-11 10:59:26 +01:00
|
|
|
#include <openrct2/world/Footpath.h>
|
2018-03-19 23:28:40 +01:00
|
|
|
#include <openrct2/world/Park.h>
|
2018-06-22 23:21:44 +02:00
|
|
|
#include <openrct2/world/Surface.h>
|
2014-04-28 18:35:12 +02:00
|
|
|
|
2020-05-05 22:26:14 +02:00
|
|
|
static constexpr const rct_string_id WINDOW_TITLE = STR_FOOTPATHS;
|
|
|
|
static constexpr const int32_t WH = 381;
|
|
|
|
static constexpr const int32_t WW = 106;
|
2020-10-03 19:41:56 +02:00
|
|
|
static constexpr const uint16_t ARROW_PULSE_DURATION = 200;
|
2019-10-19 04:02:31 +02:00
|
|
|
|
2018-05-16 20:41:29 +02:00
|
|
|
// clang-format off
|
2017-09-25 11:39:16 +02:00
|
|
|
enum
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
PATH_CONSTRUCTION_MODE_LAND,
|
|
|
|
PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL,
|
|
|
|
PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL
|
2014-04-30 17:57:27 +02:00
|
|
|
};
|
|
|
|
|
2017-09-25 11:39:16 +02:00
|
|
|
enum
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
SELECTED_PATH_TYPE_NORMAL,
|
|
|
|
SELECTED_PATH_TYPE_QUEUE
|
2014-05-17 16:06:18 +02:00
|
|
|
};
|
|
|
|
|
2017-09-25 11:39:16 +02:00
|
|
|
enum WINDOW_FOOTPATH_WIDGET_IDX
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
WIDX_BACKGROUND,
|
|
|
|
WIDX_TITLE,
|
|
|
|
WIDX_CLOSE,
|
|
|
|
|
|
|
|
WIDX_TYPE_GROUP,
|
|
|
|
WIDX_FOOTPATH_TYPE,
|
|
|
|
WIDX_QUEUELINE_TYPE,
|
|
|
|
|
|
|
|
WIDX_DIRECTION_GROUP,
|
|
|
|
WIDX_DIRECTION_NW,
|
|
|
|
WIDX_DIRECTION_NE,
|
|
|
|
WIDX_DIRECTION_SW,
|
|
|
|
WIDX_DIRECTION_SE,
|
|
|
|
|
|
|
|
WIDX_SLOPE_GROUP,
|
|
|
|
WIDX_SLOPEDOWN,
|
|
|
|
WIDX_LEVEL,
|
|
|
|
WIDX_SLOPEUP,
|
|
|
|
WIDX_CONSTRUCT,
|
|
|
|
WIDX_REMOVE,
|
|
|
|
|
|
|
|
WIDX_MODE_GROUP,
|
|
|
|
WIDX_CONSTRUCT_ON_LAND,
|
|
|
|
WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL,
|
2014-04-28 18:35:12 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static rct_widget window_footpath_widgets[] = {
|
2020-05-09 16:44:21 +02:00
|
|
|
WINDOW_SHIM(WINDOW_TITLE, WW, WH),
|
2020-07-16 20:48:25 +02:00
|
|
|
|
2017-06-06 23:24:18 +02:00
|
|
|
// Type group
|
2020-08-29 04:31:31 +02:00
|
|
|
MakeWidget({ 3, 17}, {100, 55}, WWT_GROUPBOX, WindowColour::Primary , STR_TYPE ),
|
|
|
|
MakeWidget({ 6, 30}, { 47, 36}, WWT_FLATBTN, WindowColour::Secondary, 0xFFFFFFFF, STR_FOOTPATH_TIP ),
|
|
|
|
MakeWidget({53, 30}, { 47, 36}, WWT_FLATBTN, WindowColour::Secondary, 0xFFFFFFFF, STR_QUEUE_LINE_PATH_TIP ),
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Direction group
|
2020-08-29 04:31:31 +02:00
|
|
|
MakeWidget({ 3, 75}, {100, 77}, WWT_GROUPBOX, WindowColour::Primary , STR_DIRECTION ),
|
|
|
|
MakeWidget({53, 87}, { 45, 29}, WWT_FLATBTN, WindowColour::Secondary, SPR_CONSTRUCTION_DIRECTION_NE, STR_DIRECTION_TIP ),
|
|
|
|
MakeWidget({53, 116}, { 45, 29}, WWT_FLATBTN, WindowColour::Secondary, SPR_CONSTRUCTION_DIRECTION_SE, STR_DIRECTION_TIP ),
|
|
|
|
MakeWidget({ 8, 116}, { 45, 29}, WWT_FLATBTN, WindowColour::Secondary, SPR_CONSTRUCTION_DIRECTION_SW, STR_DIRECTION_TIP ),
|
|
|
|
MakeWidget({ 8, 87}, { 45, 29}, WWT_FLATBTN, WindowColour::Secondary, SPR_CONSTRUCTION_DIRECTION_NW, STR_DIRECTION_TIP ),
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Slope group
|
2020-08-29 04:31:31 +02:00
|
|
|
MakeWidget({ 3, 155}, {100, 41}, WWT_GROUPBOX, WindowColour::Primary , STR_SLOPE ),
|
|
|
|
MakeWidget({17, 167}, { 24, 24}, WWT_FLATBTN, WindowColour::Secondary, SPR_RIDE_CONSTRUCTION_SLOPE_DOWN, STR_SLOPE_DOWN_TIP ),
|
|
|
|
MakeWidget({41, 167}, { 24, 24}, WWT_FLATBTN, WindowColour::Secondary, SPR_RIDE_CONSTRUCTION_SLOPE_LEVEL, STR_LEVEL_TIP ),
|
|
|
|
MakeWidget({65, 167}, { 24, 24}, WWT_FLATBTN, WindowColour::Secondary, SPR_RIDE_CONSTRUCTION_SLOPE_UP, STR_SLOPE_UP_TIP ),
|
|
|
|
MakeWidget({ 8, 202}, { 90, 90}, WWT_FLATBTN, WindowColour::Secondary, 0xFFFFFFFF, STR_CONSTRUCT_THE_SELECTED_FOOTPATH_SECTION_TIP),
|
|
|
|
MakeWidget({30, 295}, { 46, 24}, WWT_FLATBTN, WindowColour::Secondary, SPR_DEMOLISH_CURRENT_SECTION, STR_REMOVE_PREVIOUS_FOOTPATH_SECTION_TIP ),
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Mode group
|
2020-08-29 04:31:31 +02:00
|
|
|
MakeWidget({ 3, 321}, {100, 54}, WWT_GROUPBOX, WindowColour::Primary ),
|
|
|
|
MakeWidget({13, 332}, { 36, 36}, WWT_FLATBTN, WindowColour::Secondary, SPR_CONSTRUCTION_FOOTPATH_LAND, STR_CONSTRUCT_FOOTPATH_ON_LAND_TIP ),
|
|
|
|
MakeWidget({57, 332}, { 36, 36}, WWT_FLATBTN, WindowColour::Secondary, SPR_CONSTRUCTION_FOOTPATH_BRIDGE, STR_CONSTRUCT_BRIDGE_OR_TUNNEL_FOOTPATH_TIP ),
|
2017-09-25 11:39:16 +02:00
|
|
|
{WIDGETS_END},
|
2014-04-28 18:35:12 +02:00
|
|
|
};
|
|
|
|
|
2017-09-25 11:39:16 +02:00
|
|
|
static void window_footpath_close(rct_window * w);
|
|
|
|
static void window_footpath_mouseup(rct_window * w, rct_widgetindex widgetIndex);
|
|
|
|
static void window_footpath_mousedown(rct_window * w, rct_widgetindex widgetIndex, rct_widget * widget);
|
2018-06-20 17:28:51 +02:00
|
|
|
static void window_footpath_dropdown(rct_window * w, rct_widgetindex widgetIndex, int32_t dropdownIndex);
|
2017-09-25 11:39:16 +02:00
|
|
|
static void window_footpath_update(rct_window * w);
|
2020-02-29 03:43:29 +01:00
|
|
|
static void window_footpath_toolupdate(rct_window * w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords);
|
|
|
|
static void window_footpath_tooldown(rct_window * w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords);
|
|
|
|
static void window_footpath_tooldrag(rct_window * w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords);
|
|
|
|
static void window_footpath_toolup(rct_window * w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords);
|
2017-09-25 11:39:16 +02:00
|
|
|
static void window_footpath_invalidate(rct_window * w);
|
|
|
|
static void window_footpath_paint(rct_window * w, rct_drawpixelinfo * dpi);
|
2015-07-10 02:39:16 +02:00
|
|
|
|
2020-09-28 20:36:15 +02:00
|
|
|
static rct_window_event_list window_footpath_events([](auto& events)
|
|
|
|
{
|
|
|
|
events.close = &window_footpath_close;
|
|
|
|
events.mouse_up = &window_footpath_mouseup;
|
|
|
|
events.mouse_down = &window_footpath_mousedown;
|
|
|
|
events.dropdown = &window_footpath_dropdown;
|
|
|
|
events.update = &window_footpath_update;
|
|
|
|
events.tool_update = &window_footpath_toolupdate;
|
|
|
|
events.tool_down = &window_footpath_tooldown;
|
|
|
|
events.tool_drag = &window_footpath_tooldrag;
|
|
|
|
events.tool_up = &window_footpath_toolup;
|
|
|
|
events.invalidate = &window_footpath_invalidate;
|
|
|
|
events.paint = &window_footpath_paint;
|
|
|
|
});
|
2018-05-16 20:41:29 +02:00
|
|
|
// clang-format on
|
2014-04-28 18:35:12 +02:00
|
|
|
|
2015-12-19 23:54:15 +01:00
|
|
|
static money32 _window_footpath_cost;
|
2020-10-03 19:41:56 +02:00
|
|
|
static uint32_t _footpathConstructionNextArrowPulse = 0;
|
2018-06-22 23:21:44 +02:00
|
|
|
static uint8_t _lastUpdatedCameraRotation = UINT8_MAX;
|
|
|
|
static bool _footpathErrorOccured;
|
2014-04-28 19:37:38 +02:00
|
|
|
|
2016-08-11 21:30:15 +02:00
|
|
|
/** rct2: 0x0098D8B4 */
|
2018-06-20 17:28:51 +02:00
|
|
|
static constexpr const uint8_t DefaultPathSlope[] = {
|
2017-06-06 23:24:18 +02:00
|
|
|
0,
|
2018-01-03 10:57:37 +01:00
|
|
|
SLOPE_IS_IRREGULAR_FLAG,
|
|
|
|
SLOPE_IS_IRREGULAR_FLAG,
|
|
|
|
FOOTPATH_PROPERTIES_FLAG_IS_SLOPED | 2,
|
|
|
|
SLOPE_IS_IRREGULAR_FLAG,
|
|
|
|
SLOPE_IS_IRREGULAR_FLAG,
|
|
|
|
FOOTPATH_PROPERTIES_FLAG_IS_SLOPED | 3,
|
2018-11-01 11:04:32 +01:00
|
|
|
RAISE_FOOTPATH_FLAG,
|
2018-01-03 10:57:37 +01:00
|
|
|
SLOPE_IS_IRREGULAR_FLAG,
|
|
|
|
FOOTPATH_PROPERTIES_FLAG_IS_SLOPED | 1,
|
|
|
|
SLOPE_IS_IRREGULAR_FLAG,
|
2018-11-01 11:04:32 +01:00
|
|
|
RAISE_FOOTPATH_FLAG,
|
2018-01-03 10:57:37 +01:00
|
|
|
FOOTPATH_PROPERTIES_FLAG_IS_SLOPED | 0,
|
2018-11-01 11:04:32 +01:00
|
|
|
RAISE_FOOTPATH_FLAG,
|
|
|
|
RAISE_FOOTPATH_FLAG,
|
2018-01-03 10:57:37 +01:00
|
|
|
SLOPE_IS_IRREGULAR_FLAG,
|
2016-08-11 21:30:15 +02:00
|
|
|
};
|
|
|
|
|
2016-08-11 22:31:47 +02:00
|
|
|
/** rct2: 0x0098D7E0 */
|
2018-06-20 17:28:51 +02:00
|
|
|
static constexpr const uint8_t ConstructionPreviewImages[][4] = {
|
2018-06-22 23:21:44 +02:00
|
|
|
{ 5, 10, 5, 10 }, // Flat
|
|
|
|
{ 16, 17, 18, 19 }, // Upwards
|
|
|
|
{ 18, 19, 16, 17 }, // Downwards
|
2016-08-11 22:31:47 +02:00
|
|
|
};
|
|
|
|
|
2018-06-20 17:28:51 +02:00
|
|
|
static void window_footpath_mousedown_direction(int32_t direction);
|
|
|
|
static void window_footpath_mousedown_slope(int32_t slope);
|
2018-06-22 23:21:44 +02:00
|
|
|
static void window_footpath_show_footpath_types_dialog(rct_window* w, rct_widget* widget, bool showQueues);
|
2020-02-29 03:43:29 +01:00
|
|
|
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);
|
|
|
|
static void window_footpath_start_bridge_at_point(const ScreenCoordsXY& screenCoords);
|
2014-04-30 20:35:37 +02:00
|
|
|
static void window_footpath_construct();
|
|
|
|
static void window_footpath_remove();
|
2014-12-17 21:45:27 +01:00
|
|
|
static void window_footpath_set_enabled_and_pressed_widgets();
|
2019-12-12 11:21:05 +01:00
|
|
|
static void footpath_get_next_path_info(int32_t* type, CoordsXYZ& footpathLoc, int32_t* slope);
|
2017-07-03 22:46:07 +02:00
|
|
|
static bool footpath_select_default();
|
2014-04-29 23:25:37 +02:00
|
|
|
|
2014-04-28 18:35:12 +02:00
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-28 18:35:12 +02:00
|
|
|
* rct2: 0x006A7C43
|
|
|
|
*/
|
2018-06-22 23:21:44 +02:00
|
|
|
rct_window* window_footpath_open()
|
2014-04-28 18:35:12 +02:00
|
|
|
{
|
2017-07-03 22:46:07 +02:00
|
|
|
// If a restricted path was selected when the game is no longer in Sandbox mode, reset it
|
2019-01-20 21:38:38 +01:00
|
|
|
PathSurfaceEntry* pathEntry = get_path_surface_entry(gFootpathSelectedId);
|
2018-06-22 23:21:44 +02:00
|
|
|
if (pathEntry != nullptr && (pathEntry->flags & FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR) && !gCheatsSandboxMode)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-10-15 15:53:16 +02:00
|
|
|
pathEntry = nullptr;
|
2017-07-03 22:46:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Select the default path if we don't have one
|
2017-10-15 15:53:16 +02:00
|
|
|
if (pathEntry == nullptr)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
|
|
|
if (!footpath_select_default())
|
|
|
|
{
|
2017-07-03 22:46:07 +02:00
|
|
|
// No path objects to select from, don't open window
|
2017-08-12 23:06:12 +02:00
|
|
|
return nullptr;
|
2017-07-03 22:46:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-06 23:24:18 +02:00
|
|
|
// Check if window is already open
|
2018-06-22 23:21:44 +02:00
|
|
|
rct_window* window = window_bring_to_front_by_class(WC_FOOTPATH);
|
2017-08-12 23:06:12 +02:00
|
|
|
if (window != nullptr)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-08-12 23:06:12 +02:00
|
|
|
return window;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2020-11-04 05:52:23 +01:00
|
|
|
window = WindowCreate(ScreenCoordsXY(0, 29), 106, 381, &window_footpath_events, WC_FOOTPATH, 0);
|
2017-06-06 23:24:18 +02:00
|
|
|
window->widgets = window_footpath_widgets;
|
2018-06-22 23:21:44 +02:00
|
|
|
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);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2020-11-04 05:52:23 +01:00
|
|
|
WindowInitScrollWidgets(window);
|
2017-06-06 23:24:18 +02:00
|
|
|
window_push_others_right(window);
|
|
|
|
show_gridlines();
|
|
|
|
|
|
|
|
tool_cancel();
|
|
|
|
gFootpathConstructionMode = PATH_CONSTRUCTION_MODE_LAND;
|
|
|
|
tool_set(window, WIDX_CONSTRUCT_ON_LAND, TOOL_PATH_DOWN);
|
|
|
|
input_set_flag(INPUT_FLAG_6, true);
|
|
|
|
_footpathErrorOccured = false;
|
|
|
|
window_footpath_set_enabled_and_pressed_widgets();
|
2017-08-12 23:06:12 +02:00
|
|
|
|
|
|
|
return window;
|
2014-04-28 18:35:12 +02:00
|
|
|
}
|
|
|
|
|
2014-04-28 19:37:38 +02:00
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-28 19:37:38 +02:00
|
|
|
* rct2: 0x006A852F
|
|
|
|
*/
|
2018-06-22 23:21:44 +02:00
|
|
|
static void window_footpath_close(rct_window* w)
|
2014-04-28 19:37:38 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
footpath_provisional_update();
|
|
|
|
viewport_set_visibility(0);
|
|
|
|
map_invalidate_map_selection_tiles();
|
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_CONSTRUCT;
|
|
|
|
window_invalidate_by_class(WC_TOP_TOOLBAR);
|
|
|
|
hide_gridlines();
|
2014-04-28 19:37:38 +02:00
|
|
|
}
|
|
|
|
|
2014-04-28 18:35:12 +02:00
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-28 18:35:12 +02:00
|
|
|
* rct2: 0x006A7E92
|
|
|
|
*/
|
2018-06-22 23:21:44 +02:00
|
|
|
static void window_footpath_mouseup(rct_window* w, rct_widgetindex widgetIndex)
|
2014-04-28 18:35:12 +02:00
|
|
|
{
|
2017-09-25 11:39:16 +02:00
|
|
|
switch (widgetIndex)
|
|
|
|
{
|
2018-06-22 23:21:44 +02:00
|
|
|
case WIDX_CLOSE:
|
|
|
|
window_close(w);
|
2017-06-06 23:24:18 +02:00
|
|
|
break;
|
2018-06-22 23:21:44 +02:00
|
|
|
case WIDX_CONSTRUCT:
|
|
|
|
window_footpath_construct();
|
|
|
|
break;
|
|
|
|
case WIDX_REMOVE:
|
|
|
|
window_footpath_remove();
|
|
|
|
break;
|
|
|
|
case WIDX_CONSTRUCT_ON_LAND:
|
|
|
|
if (gFootpathConstructionMode == PATH_CONSTRUCTION_MODE_LAND)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2018-06-22 23:21:44 +02:00
|
|
|
_window_footpath_cost = MONEY32_UNDEFINED;
|
|
|
|
tool_cancel();
|
|
|
|
footpath_provisional_update();
|
|
|
|
map_invalidate_map_selection_tiles();
|
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_CONSTRUCT;
|
|
|
|
gFootpathConstructionMode = PATH_CONSTRUCTION_MODE_LAND;
|
|
|
|
tool_set(w, WIDX_CONSTRUCT_ON_LAND, TOOL_PATH_DOWN);
|
|
|
|
input_set_flag(INPUT_FLAG_6, true);
|
|
|
|
_footpathErrorOccured = false;
|
|
|
|
window_footpath_set_enabled_and_pressed_widgets();
|
2017-06-06 23:24:18 +02:00
|
|
|
break;
|
2018-06-22 23:21:44 +02:00
|
|
|
case WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL:
|
|
|
|
if (gFootpathConstructionMode == PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2018-06-22 23:21:44 +02:00
|
|
|
_window_footpath_cost = MONEY32_UNDEFINED;
|
|
|
|
tool_cancel();
|
|
|
|
footpath_provisional_update();
|
|
|
|
map_invalidate_map_selection_tiles();
|
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_CONSTRUCT;
|
|
|
|
gFootpathConstructionMode = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL;
|
|
|
|
tool_set(w, WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL, TOOL_CROSSHAIR);
|
|
|
|
input_set_flag(INPUT_FLAG_6, true);
|
|
|
|
_footpathErrorOccured = false;
|
|
|
|
window_footpath_set_enabled_and_pressed_widgets();
|
|
|
|
break;
|
2017-06-06 23:24:18 +02:00
|
|
|
}
|
2014-04-29 04:12:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-29 04:12:52 +02:00
|
|
|
* rct2: 0x006A7EC5
|
|
|
|
*/
|
2018-06-22 23:21:44 +02:00
|
|
|
static void window_footpath_mousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget)
|
2014-04-29 04:12:52 +02:00
|
|
|
{
|
2017-09-25 11:39:16 +02:00
|
|
|
switch (widgetIndex)
|
|
|
|
{
|
2018-06-22 23:21:44 +02:00
|
|
|
case WIDX_FOOTPATH_TYPE:
|
|
|
|
window_footpath_show_footpath_types_dialog(w, widget, false);
|
|
|
|
break;
|
|
|
|
case WIDX_QUEUELINE_TYPE:
|
|
|
|
window_footpath_show_footpath_types_dialog(w, widget, true);
|
|
|
|
break;
|
|
|
|
case WIDX_DIRECTION_NW:
|
|
|
|
window_footpath_mousedown_direction(0);
|
|
|
|
break;
|
|
|
|
case WIDX_DIRECTION_NE:
|
|
|
|
window_footpath_mousedown_direction(1);
|
|
|
|
break;
|
|
|
|
case WIDX_DIRECTION_SW:
|
|
|
|
window_footpath_mousedown_direction(2);
|
|
|
|
break;
|
|
|
|
case WIDX_DIRECTION_SE:
|
|
|
|
window_footpath_mousedown_direction(3);
|
|
|
|
break;
|
|
|
|
case WIDX_SLOPEDOWN:
|
|
|
|
window_footpath_mousedown_slope(6);
|
|
|
|
break;
|
|
|
|
case WIDX_LEVEL:
|
|
|
|
window_footpath_mousedown_slope(0);
|
|
|
|
break;
|
|
|
|
case WIDX_SLOPEUP:
|
|
|
|
window_footpath_mousedown_slope(2);
|
|
|
|
break;
|
2017-06-06 23:24:18 +02:00
|
|
|
}
|
2014-04-29 04:12:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-29 04:12:52 +02:00
|
|
|
* rct2: 0x006A7F18
|
|
|
|
*/
|
2018-06-22 23:21:44 +02:00
|
|
|
static void window_footpath_dropdown(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex)
|
2014-04-29 04:12:52 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
if (widgetIndex == WIDX_FOOTPATH_TYPE)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
gFootpathSelectedType = SELECTED_PATH_TYPE_NORMAL;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
else if (widgetIndex == WIDX_QUEUELINE_TYPE)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
gFootpathSelectedType = SELECTED_PATH_TYPE_QUEUE;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
else
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
return;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Get path id
|
2018-06-20 17:28:51 +02:00
|
|
|
int32_t pathId = dropdownIndex;
|
2017-09-25 11:39:16 +02:00
|
|
|
if (pathId == -1)
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
pathId = gFootpathSelectedId;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bool showEditorPaths = ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) || gCheatsSandboxMode);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2018-06-20 17:28:51 +02:00
|
|
|
int32_t i = 0, j = 0;
|
2017-09-25 11:39:16 +02:00
|
|
|
for (; i < MAX_PATH_OBJECTS; i++)
|
|
|
|
{
|
2019-01-20 21:38:38 +01:00
|
|
|
PathSurfaceEntry* pathType = get_path_surface_entry(i);
|
2017-10-15 15:53:16 +02:00
|
|
|
if (pathType == nullptr)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
continue;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
|
|
|
if ((pathType->flags & FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR) && !showEditorPaths)
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
continue;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
if (j == pathId)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
break;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
j++;
|
|
|
|
}
|
|
|
|
pathId = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set selected path id
|
|
|
|
gFootpathSelectedId = pathId;
|
|
|
|
footpath_provisional_update();
|
|
|
|
_window_footpath_cost = MONEY32_UNDEFINED;
|
2019-06-15 17:20:16 +02:00
|
|
|
w->Invalidate();
|
2014-04-29 04:12:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-29 04:12:52 +02:00
|
|
|
* rct2: 0x006A8032
|
|
|
|
*/
|
2020-02-29 03:43:29 +01:00
|
|
|
static void window_footpath_toolupdate(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords)
|
2014-04-29 04:12:52 +02:00
|
|
|
{
|
2017-09-25 11:39:16 +02:00
|
|
|
if (widgetIndex == WIDX_CONSTRUCT_ON_LAND)
|
|
|
|
{
|
2019-11-12 03:10:51 +01:00
|
|
|
window_footpath_set_provisional_path_at_point(screenCoords);
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
|
|
|
else if (widgetIndex == WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL)
|
|
|
|
{
|
2019-11-12 03:10:51 +01:00
|
|
|
window_footpath_set_selection_start_bridge_at_point(screenCoords);
|
2017-06-06 23:24:18 +02:00
|
|
|
}
|
2014-04-29 04:12:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-29 04:12:52 +02:00
|
|
|
* rct2: 0x006A8047
|
|
|
|
*/
|
2020-02-29 03:43:29 +01:00
|
|
|
static void window_footpath_tooldown(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords)
|
2014-04-29 04:12:52 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
if (widgetIndex == WIDX_CONSTRUCT_ON_LAND)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2019-11-12 03:10:51 +01:00
|
|
|
window_footpath_place_path_at_point(screenCoords);
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
else if (widgetIndex == WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2019-11-12 03:10:51 +01:00
|
|
|
window_footpath_start_bridge_at_point(screenCoords);
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2014-04-29 04:12:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-29 04:12:52 +02:00
|
|
|
* rct2: 0x006A8067
|
|
|
|
*/
|
2020-02-29 03:43:29 +01:00
|
|
|
static void window_footpath_tooldrag(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords)
|
2014-04-29 04:12:52 +02:00
|
|
|
{
|
2017-09-25 11:39:16 +02:00
|
|
|
if (widgetIndex == WIDX_CONSTRUCT_ON_LAND)
|
|
|
|
{
|
2019-11-12 03:10:51 +01:00
|
|
|
window_footpath_place_path_at_point(screenCoords);
|
2017-06-06 23:24:18 +02:00
|
|
|
}
|
2014-04-29 04:12:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-29 04:12:52 +02:00
|
|
|
* rct2: 0x006A8066
|
|
|
|
*/
|
2020-02-29 03:43:29 +01:00
|
|
|
static void window_footpath_toolup(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords)
|
2014-04-29 04:12:52 +02:00
|
|
|
{
|
2017-09-25 11:39:16 +02:00
|
|
|
if (widgetIndex == WIDX_CONSTRUCT_ON_LAND)
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
_footpathErrorOccured = false;
|
|
|
|
}
|
2014-04-29 04:12:52 +02:00
|
|
|
}
|
|
|
|
|
2014-12-17 21:45:27 +01:00
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-12-17 21:45:27 +01:00
|
|
|
* rct2: 0x006A7760
|
|
|
|
*/
|
2018-06-22 23:21:44 +02:00
|
|
|
static void window_footpath_update_provisional_path_for_bridge_mode(rct_window* w)
|
2014-12-17 21:45:27 +01:00
|
|
|
{
|
2019-12-12 11:21:05 +01:00
|
|
|
int32_t type, slope;
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
if (gFootpathConstructionMode != PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
return;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Recheck area for construction. Set by ride_construction window
|
2017-09-25 11:39:16 +02:00
|
|
|
if (gFootpathProvisionalFlags & PROVISIONAL_PATH_FLAG_2)
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
footpath_provisional_remove();
|
|
|
|
gFootpathProvisionalFlags &= ~PROVISIONAL_PATH_FLAG_2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update provisional bridge mode path
|
2017-09-25 11:39:16 +02:00
|
|
|
if (!(gFootpathProvisionalFlags & PROVISIONAL_PATH_FLAG_1))
|
|
|
|
{
|
2019-12-12 11:21:05 +01:00
|
|
|
CoordsXYZ footpathLoc;
|
|
|
|
footpath_get_next_path_info(&type, footpathLoc, &slope);
|
|
|
|
_window_footpath_cost = footpath_provisional_set(type, footpathLoc, slope);
|
2017-06-06 23:24:18 +02:00
|
|
|
widget_invalidate(w, WIDX_CONSTRUCT);
|
|
|
|
}
|
|
|
|
|
2020-10-03 19:41:56 +02:00
|
|
|
auto curTime = platform_get_ticks();
|
|
|
|
|
2017-06-06 23:24:18 +02:00
|
|
|
// Update little directional arrow on provisional bridge mode path
|
2020-10-03 19:41:56 +02:00
|
|
|
if (_footpathConstructionNextArrowPulse < curTime)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2020-10-03 19:41:56 +02:00
|
|
|
_footpathConstructionNextArrowPulse = curTime + ARROW_PULSE_DURATION;
|
|
|
|
|
2017-06-06 23:24:18 +02:00
|
|
|
gFootpathProvisionalFlags ^= PROVISIONAL_PATH_FLAG_SHOW_ARROW;
|
2019-12-12 11:21:05 +01:00
|
|
|
CoordsXYZ footpathLoc;
|
|
|
|
footpath_get_next_path_info(&type, footpathLoc, &slope);
|
2019-12-30 17:51:35 +01:00
|
|
|
gMapSelectArrowPosition = footpathLoc;
|
2017-06-06 23:24:18 +02:00
|
|
|
gMapSelectArrowDirection = gFootpathConstructDirection;
|
|
|
|
if (gFootpathProvisionalFlags & PROVISIONAL_PATH_FLAG_SHOW_ARROW)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE_ARROW;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
else
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_ARROW;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2019-12-28 09:44:33 +01:00
|
|
|
map_invalidate_tile_full(footpathLoc);
|
2017-06-06 23:24:18 +02:00
|
|
|
}
|
2014-12-17 21:45:27 +01:00
|
|
|
}
|
|
|
|
|
2014-04-29 04:12:52 +02:00
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-29 04:12:52 +02:00
|
|
|
* rct2: 0x006A84BB
|
|
|
|
*/
|
2018-06-22 23:21:44 +02:00
|
|
|
static void window_footpath_update(rct_window* w)
|
2014-04-29 04:12:52 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
widget_invalidate(w, WIDX_CONSTRUCT);
|
|
|
|
window_footpath_update_provisional_path_for_bridge_mode(w);
|
|
|
|
|
|
|
|
// #2502: The camera might have changed rotation, so we need to update which directional buttons are pressed
|
2018-06-20 17:28:51 +02:00
|
|
|
uint8_t currentRotation = get_current_rotation();
|
2017-09-25 11:39:16 +02:00
|
|
|
if (_lastUpdatedCameraRotation != currentRotation)
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
_lastUpdatedCameraRotation = currentRotation;
|
|
|
|
window_footpath_set_enabled_and_pressed_widgets();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check tool
|
2017-09-25 11:39:16 +02:00
|
|
|
if (gFootpathConstructionMode == PATH_CONSTRUCTION_MODE_LAND)
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
if (!(input_test_flag(INPUT_FLAG_TOOL_ACTIVE)))
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
window_close(w);
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
else if (gCurrentToolWidget.window_classification != WC_FOOTPATH)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
window_close(w);
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
else if (gCurrentToolWidget.widget_index != WIDX_CONSTRUCT_ON_LAND)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
window_close(w);
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (gFootpathConstructionMode == PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL)
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
if (!(input_test_flag(INPUT_FLAG_TOOL_ACTIVE)))
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
window_close(w);
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
else if (gCurrentToolWidget.window_classification != WC_FOOTPATH)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
window_close(w);
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
else if (gCurrentToolWidget.widget_index != WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
window_close(w);
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
}
|
2014-04-28 18:35:12 +02:00
|
|
|
}
|
|
|
|
|
2014-04-28 19:37:38 +02:00
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-28 19:37:38 +02:00
|
|
|
* rct2: 0x006A7D1C
|
|
|
|
*/
|
2018-06-22 23:21:44 +02:00
|
|
|
static void window_footpath_invalidate(rct_window* w)
|
2014-04-28 19:37:38 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
// Press / unpress footpath and queue type buttons
|
|
|
|
w->pressed_widgets &= ~(1 << WIDX_FOOTPATH_TYPE);
|
|
|
|
w->pressed_widgets &= ~(1 << WIDX_QUEUELINE_TYPE);
|
2018-07-21 11:50:45 +02:00
|
|
|
w->pressed_widgets |= gFootpathSelectedType == SELECTED_PATH_TYPE_NORMAL ? (1 << WIDX_FOOTPATH_TYPE)
|
|
|
|
: (1 << WIDX_QUEUELINE_TYPE);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Enable / disable construct button
|
2018-07-21 11:50:45 +02:00
|
|
|
window_footpath_widgets[WIDX_CONSTRUCT].type = gFootpathConstructionMode == PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL
|
|
|
|
? WWT_IMGBTN
|
|
|
|
: WWT_EMPTY;
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Set footpath and queue type button images
|
2020-04-18 13:32:48 +02:00
|
|
|
auto pathImage = static_cast<uint32_t>(SPR_NONE);
|
|
|
|
auto queueImage = static_cast<uint32_t>(SPR_NONE);
|
2019-03-09 13:37:12 +01:00
|
|
|
auto pathEntry = get_path_surface_entry(gFootpathSelectedId);
|
|
|
|
if (pathEntry != nullptr)
|
|
|
|
{
|
|
|
|
pathImage = pathEntry->preview;
|
|
|
|
// Editor-only paths might lack a queue image
|
|
|
|
queueImage = (pathEntry->flags & FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR) ? pathImage : pathImage + 1;
|
|
|
|
}
|
2018-06-22 23:21:44 +02:00
|
|
|
window_footpath_widgets[WIDX_FOOTPATH_TYPE].image = pathImage;
|
2017-09-25 11:39:16 +02:00
|
|
|
window_footpath_widgets[WIDX_QUEUELINE_TYPE].image = queueImage;
|
2014-04-28 19:37:38 +02:00
|
|
|
}
|
|
|
|
|
2014-04-28 18:35:12 +02:00
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-28 18:35:12 +02:00
|
|
|
* rct2: 0x006A7D8B
|
|
|
|
*/
|
2018-06-22 23:21:44 +02:00
|
|
|
static void window_footpath_paint(rct_window* w, rct_drawpixelinfo* dpi)
|
2014-04-28 18:35:12 +02:00
|
|
|
{
|
2020-05-17 20:29:56 +02:00
|
|
|
ScreenCoordsXY screenCoords;
|
2020-11-04 05:52:23 +01:00
|
|
|
WindowDrawWidgets(w, dpi);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2017-09-25 11:39:16 +02:00
|
|
|
if (!(w->disabled_widgets & (1 << WIDX_CONSTRUCT)))
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
// Get construction image
|
2018-06-20 17:28:51 +02:00
|
|
|
uint8_t direction = (gFootpathConstructDirection + get_current_rotation()) % 4;
|
2018-06-22 23:21:44 +02:00
|
|
|
uint8_t slope = 0;
|
2017-06-06 23:24:18 +02:00
|
|
|
if (gFootpathConstructSlope == 2)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-11-18 12:58:27 +01:00
|
|
|
slope = TILE_ELEMENT_SLOPE_N_CORNER_UP;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
else if (gFootpathConstructSlope == 6)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-11-18 12:58:27 +01:00
|
|
|
slope = TILE_ELEMENT_SLOPE_E_CORNER_UP;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2018-06-20 17:28:51 +02:00
|
|
|
int32_t image = ConstructionPreviewImages[slope][direction];
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2019-04-01 21:58:57 +02:00
|
|
|
int32_t selectedPath = gFootpathSelectedId + (MAX_PATH_OBJECTS * gFootpathSelectedType);
|
2019-01-20 21:38:38 +01:00
|
|
|
PathSurfaceEntry* pathType = get_path_surface_entry(selectedPath);
|
2019-03-16 12:37:32 +01:00
|
|
|
image += pathType->image;
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Draw construction image
|
2020-06-23 23:32:34 +02:00
|
|
|
screenCoords = w->windowPos
|
2020-06-25 10:31:15 +02:00
|
|
|
+ ScreenCoordsXY{ window_footpath_widgets[WIDX_CONSTRUCT].midX(),
|
2020-06-23 23:32:34 +02:00
|
|
|
window_footpath_widgets[WIDX_CONSTRUCT].bottom - 60 };
|
|
|
|
gfx_draw_sprite(dpi, image, screenCoords, 0);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Draw build this... label
|
2020-06-23 23:32:34 +02:00
|
|
|
screenCoords = w->windowPos
|
2020-06-25 10:31:15 +02:00
|
|
|
+ ScreenCoordsXY{ window_footpath_widgets[WIDX_CONSTRUCT].midX(),
|
2020-06-23 23:32:34 +02:00
|
|
|
window_footpath_widgets[WIDX_CONSTRUCT].bottom - 23 };
|
2020-05-17 20:29:56 +02:00
|
|
|
gfx_draw_string_centred(dpi, STR_BUILD_THIS, screenCoords, COLOUR_BLACK, nullptr);
|
2017-06-06 23:24:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Draw cost
|
2020-06-23 23:32:34 +02:00
|
|
|
screenCoords = w->windowPos
|
2020-06-25 10:31:15 +02:00
|
|
|
+ ScreenCoordsXY{ window_footpath_widgets[WIDX_CONSTRUCT].midX(), window_footpath_widgets[WIDX_CONSTRUCT].bottom - 12 };
|
2017-06-06 23:24:18 +02:00
|
|
|
if (_window_footpath_cost != MONEY32_UNDEFINED)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
if (!(gParkFlags & PARK_FLAGS_NO_MONEY))
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2020-05-17 20:29:56 +02:00
|
|
|
gfx_draw_string_centred(dpi, STR_COST_LABEL, screenCoords, COLOUR_BLACK, &_window_footpath_cost);
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
|
|
|
}
|
2014-04-29 23:25:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-29 23:25:37 +02:00
|
|
|
* rct2: 0x006A7F88
|
|
|
|
*/
|
2018-06-22 23:21:44 +02:00
|
|
|
static void window_footpath_show_footpath_types_dialog(rct_window* w, rct_widget* widget, bool showQueues)
|
2014-04-29 23:25:37 +02:00
|
|
|
{
|
2020-03-06 15:06:28 +01:00
|
|
|
int32_t i, image;
|
2019-01-20 21:38:38 +01:00
|
|
|
PathSurfaceEntry* pathType;
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2020-03-06 15:06:28 +01:00
|
|
|
uint32_t numPathTypes = 0;
|
2017-09-25 11:39:16 +02:00
|
|
|
// 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);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2017-09-25 11:39:16 +02:00
|
|
|
for (i = 0; i < MAX_PATH_OBJECTS; i++)
|
|
|
|
{
|
2019-01-20 21:38:38 +01:00
|
|
|
pathType = get_path_surface_entry(i);
|
2017-10-15 15:53:16 +02:00
|
|
|
if (pathType == nullptr)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
continue;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
|
|
|
if ((pathType->flags & FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR) && !showEditorPaths)
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
continue;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2019-01-20 21:38:38 +01:00
|
|
|
image = pathType->preview;
|
2017-09-25 11:39:16 +02:00
|
|
|
// Editor-only paths usually lack queue images. In this case, use the main path image
|
|
|
|
if (showQueues && !(pathType->flags & FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR))
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
image++;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2018-05-16 22:22:17 +02:00
|
|
|
gDropdownItemsFormat[numPathTypes] = STR_NONE;
|
2018-06-22 23:21:44 +02:00
|
|
|
gDropdownItemsArgs[numPathTypes] = image;
|
2017-06-06 23:24:18 +02:00
|
|
|
numPathTypes++;
|
|
|
|
}
|
|
|
|
|
2020-11-03 09:16:06 +01:00
|
|
|
auto itemsPerRow = DropdownGetAppropriateImageDropdownItemsPerRow(numPathTypes);
|
|
|
|
WindowDropdownShowImage(
|
2020-06-25 03:44:00 +02:00
|
|
|
w->windowPos.x + widget->left, w->windowPos.y + widget->top, widget->height() + 1, w->colours[1], 0, numPathTypes, 47,
|
|
|
|
36, itemsPerRow);
|
2014-04-30 02:59:11 +02:00
|
|
|
}
|
|
|
|
|
2015-02-21 00:40:52 +01:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006A8111 0x006A8135 0x006A815C 0x006A8183
|
|
|
|
*/
|
2018-06-20 17:28:51 +02:00
|
|
|
static void window_footpath_mousedown_direction(int32_t direction)
|
2015-02-21 00:40:52 +01:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
footpath_provisional_update();
|
|
|
|
gFootpathConstructDirection = (direction - get_current_rotation()) & 3;
|
2018-06-22 23:21:44 +02:00
|
|
|
_window_footpath_cost = MONEY32_UNDEFINED;
|
2017-06-06 23:24:18 +02:00
|
|
|
window_footpath_set_enabled_and_pressed_widgets();
|
2015-02-21 00:40:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-06-22 23:21:44 +02:00
|
|
|
*
|
|
|
|
* rct2: 0x006A81AA 0x006A81C5 0x006A81E0
|
|
|
|
*/
|
2018-06-20 17:28:51 +02:00
|
|
|
static void window_footpath_mousedown_slope(int32_t slope)
|
2015-02-21 00:40:52 +01:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
footpath_provisional_update();
|
|
|
|
gFootpathConstructSlope = slope;
|
2018-06-22 23:21:44 +02:00
|
|
|
_window_footpath_cost = MONEY32_UNDEFINED;
|
2017-06-06 23:24:18 +02:00
|
|
|
window_footpath_set_enabled_and_pressed_widgets();
|
2015-02-21 00:40:52 +01:00
|
|
|
}
|
|
|
|
|
2014-04-30 02:59:11 +02:00
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-30 02:59:11 +02:00
|
|
|
* rct2: 0x006A81FB
|
|
|
|
*/
|
2020-02-29 03:43:29 +01:00
|
|
|
static void window_footpath_set_provisional_path_at_point(const ScreenCoordsXY& screenCoords)
|
2014-04-30 02:59:11 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
map_invalidate_selection_rect();
|
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_ARROW;
|
|
|
|
|
2020-08-02 09:32:59 +02:00
|
|
|
auto info = get_map_coordinates_from_pos(
|
|
|
|
screenCoords, VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2020-08-02 09:32:59 +02:00
|
|
|
if (info.SpriteType == VIEWPORT_INTERACTION_ITEM_NONE || info.Element == nullptr)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
|
|
|
|
footpath_provisional_update();
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
// Check for change
|
2020-08-02 09:32:59 +02:00
|
|
|
if ((gFootpathProvisionalFlags & PROVISIONAL_PATH_FLAG_1)
|
|
|
|
&& gFootpathProvisionalPosition == CoordsXYZ{ info.Loc, info.Element->GetBaseZ() })
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set map selection
|
|
|
|
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
|
|
|
|
gMapSelectType = MAP_SELECT_TYPE_FULL;
|
2020-08-02 09:32:59 +02:00
|
|
|
gMapSelectPositionA = info.Loc;
|
|
|
|
gMapSelectPositionB = info.Loc;
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
footpath_provisional_update();
|
|
|
|
|
|
|
|
// Set provisional path
|
2018-06-20 17:28:51 +02:00
|
|
|
int32_t slope = 0;
|
2020-08-02 09:32:59 +02:00
|
|
|
switch (info.SpriteType)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2018-06-22 23:21:44 +02:00
|
|
|
case VIEWPORT_INTERACTION_ITEM_TERRAIN:
|
2019-02-24 17:39:22 +01:00
|
|
|
{
|
2020-08-02 09:32:59 +02:00
|
|
|
auto surfaceElement = info.Element->AsSurface();
|
2019-02-24 17:39:22 +01:00
|
|
|
if (surfaceElement != nullptr)
|
|
|
|
{
|
|
|
|
slope = DefaultPathSlope[surfaceElement->GetSlope() & TILE_ELEMENT_SURFACE_RAISED_CORNERS_MASK];
|
|
|
|
}
|
2018-06-22 23:21:44 +02:00
|
|
|
break;
|
2019-02-24 17:39:22 +01:00
|
|
|
}
|
2018-06-22 23:21:44 +02:00
|
|
|
case VIEWPORT_INTERACTION_ITEM_FOOTPATH:
|
2019-02-24 17:39:22 +01:00
|
|
|
{
|
2020-08-02 09:32:59 +02:00
|
|
|
auto pathElement = info.Element->AsPath();
|
2019-02-24 17:39:22 +01:00
|
|
|
if (pathElement != nullptr)
|
|
|
|
{
|
|
|
|
slope = pathElement->GetSlopeDirection();
|
|
|
|
if (pathElement->IsSloped())
|
|
|
|
{
|
|
|
|
slope |= FOOTPATH_PROPERTIES_FLAG_IS_SLOPED;
|
|
|
|
}
|
|
|
|
}
|
2018-06-22 23:21:44 +02:00
|
|
|
break;
|
2019-02-24 17:39:22 +01:00
|
|
|
}
|
2020-08-02 09:32:59 +02:00
|
|
|
default:
|
|
|
|
break;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2020-08-02 09:32:59 +02:00
|
|
|
auto z = info.Element->GetBaseZ();
|
2018-11-01 11:04:32 +01:00
|
|
|
if (slope & RAISE_FOOTPATH_FLAG)
|
|
|
|
{
|
|
|
|
slope &= ~RAISE_FOOTPATH_FLAG;
|
2019-12-30 16:03:51 +01:00
|
|
|
z += PATH_HEIGHT_STEP;
|
2018-11-01 11:04:32 +01:00
|
|
|
}
|
2018-06-20 17:28:51 +02:00
|
|
|
int32_t pathType = (gFootpathSelectedType << 7) + (gFootpathSelectedId & 0xFF);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2020-08-02 09:32:59 +02:00
|
|
|
_window_footpath_cost = footpath_provisional_set(pathType, { info.Loc, z }, slope);
|
2017-06-06 23:24:18 +02:00
|
|
|
window_invalidate_by_class(WC_FOOTPATH);
|
|
|
|
}
|
2014-04-30 02:59:11 +02:00
|
|
|
}
|
|
|
|
|
2015-03-23 22:28:44 +01:00
|
|
|
/**
|
2018-06-22 23:21:44 +02:00
|
|
|
*
|
|
|
|
* rct2: 0x006A8388
|
|
|
|
*/
|
2020-02-29 03:43:29 +01:00
|
|
|
static void window_footpath_set_selection_start_bridge_at_point(const ScreenCoordsXY& screenCoords)
|
2015-03-23 22:28:44 +01:00
|
|
|
{
|
2020-01-13 02:27:30 +01:00
|
|
|
int32_t direction;
|
2018-11-01 13:53:50 +01:00
|
|
|
TileElement* tileElement;
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
map_invalidate_selection_rect();
|
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
|
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_ARROW;
|
|
|
|
|
2020-01-13 02:27:30 +01:00
|
|
|
auto mapCoords = footpath_bridge_get_info_from_pos(screenCoords, &direction, &tileElement);
|
|
|
|
if (mapCoords.isNull())
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
return;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
|
|
|
|
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE_ARROW;
|
|
|
|
gMapSelectType = MAP_SELECT_TYPE_FULL;
|
2020-01-13 02:27:30 +01:00
|
|
|
gMapSelectPositionA = mapCoords;
|
|
|
|
gMapSelectPositionB = mapCoords;
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2019-12-27 15:26:40 +01:00
|
|
|
int32_t z = tileElement->GetBaseZ();
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2018-05-02 19:27:04 +02:00
|
|
|
if (tileElement->GetType() == TILE_ELEMENT_TYPE_SURFACE)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2018-09-14 14:54:12 +02:00
|
|
|
uint8_t slope = tileElement->AsSurface()->GetSlope();
|
2017-11-18 12:58:27 +01:00
|
|
|
if (slope & TILE_ELEMENT_SLOPE_ALL_CORNERS_UP)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2019-12-30 16:03:51 +01:00
|
|
|
z += PATH_HEIGHT_STEP;
|
2017-09-25 11:39:16 +02:00
|
|
|
} // Add 2 for a slope
|
2017-11-18 12:58:27 +01:00
|
|
|
if (slope & TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT)
|
2019-12-30 16:03:51 +01:00
|
|
|
z += PATH_HEIGHT_STEP; // Add another 2 for a steep slope
|
2017-06-06 23:24:18 +02:00
|
|
|
}
|
|
|
|
|
2020-01-13 02:27:30 +01:00
|
|
|
gMapSelectArrowPosition = CoordsXYZ{ mapCoords, z };
|
2019-12-30 17:51:35 +01:00
|
|
|
gMapSelectArrowDirection = direction;
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
map_invalidate_selection_rect();
|
2015-03-23 22:28:44 +01:00
|
|
|
}
|
|
|
|
|
2014-04-30 02:59:11 +02:00
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-30 02:59:11 +02:00
|
|
|
* rct2: 0x006A82C5
|
|
|
|
*/
|
2020-02-29 03:43:29 +01:00
|
|
|
static void window_footpath_place_path_at_point(const ScreenCoordsXY& screenCoords)
|
2014-04-30 02:59:11 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
if (_footpathErrorOccured)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
return;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
footpath_provisional_update();
|
|
|
|
|
2020-08-02 09:32:59 +02:00
|
|
|
const auto info = get_map_coordinates_from_pos(
|
|
|
|
screenCoords, VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2020-08-02 09:32:59 +02:00
|
|
|
if (info.SpriteType == VIEWPORT_INTERACTION_ITEM_NONE)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
return;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Set path
|
2020-08-02 09:32:59 +02:00
|
|
|
auto slope = 0;
|
|
|
|
switch (info.SpriteType)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2018-06-22 23:21:44 +02:00
|
|
|
case VIEWPORT_INTERACTION_ITEM_TERRAIN:
|
2020-08-02 09:32:59 +02:00
|
|
|
slope = DefaultPathSlope[info.Element->AsSurface()->GetSlope() & TILE_ELEMENT_SURFACE_RAISED_CORNERS_MASK];
|
2018-06-22 23:21:44 +02:00
|
|
|
break;
|
|
|
|
case VIEWPORT_INTERACTION_ITEM_FOOTPATH:
|
2020-08-02 09:32:59 +02:00
|
|
|
slope = info.Element->AsPath()->GetSlopeDirection();
|
|
|
|
if (info.Element->AsPath()->IsSloped())
|
2018-09-16 16:17:35 +02:00
|
|
|
{
|
2020-08-02 09:32:59 +02:00
|
|
|
slope |= FOOTPATH_PROPERTIES_FLAG_IS_SLOPED;
|
2018-09-16 16:17:35 +02:00
|
|
|
}
|
2018-06-22 23:21:44 +02:00
|
|
|
break;
|
2020-08-02 09:32:59 +02:00
|
|
|
default:
|
|
|
|
break;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2020-08-02 09:32:59 +02:00
|
|
|
auto z = info.Element->GetBaseZ();
|
|
|
|
if (slope & RAISE_FOOTPATH_FLAG)
|
2018-11-01 11:04:32 +01:00
|
|
|
{
|
2020-08-02 09:32:59 +02:00
|
|
|
slope &= ~RAISE_FOOTPATH_FLAG;
|
2019-12-30 16:03:51 +01:00
|
|
|
z += PATH_HEIGHT_STEP;
|
2018-11-01 11:04:32 +01:00
|
|
|
}
|
2020-08-02 09:32:59 +02:00
|
|
|
auto selectedType = (gFootpathSelectedType << 7) + (gFootpathSelectedId & 0xFF);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Try and place path
|
|
|
|
gGameCommandErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE;
|
2020-08-02 09:32:59 +02:00
|
|
|
auto footpathPlaceAction = FootpathPlaceAction({ info.Loc, z }, slope, selectedType);
|
2020-10-15 03:04:39 +02:00
|
|
|
footpathPlaceAction.SetCallback([](const GameAction* ga, const GameActions::Result* result) {
|
|
|
|
if (result->Error == GameActions::Status::Ok)
|
2019-03-01 13:57:58 +01:00
|
|
|
{
|
2019-03-01 18:17:46 +01:00
|
|
|
// Don't play sound if it is no cost to prevent multiple sounds. TODO: make this work in no money scenarios
|
|
|
|
if (result->Cost != 0)
|
|
|
|
{
|
2020-10-06 23:34:42 +02:00
|
|
|
OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::PlaceItem, result->Position);
|
2019-03-01 18:17:46 +01:00
|
|
|
}
|
2019-03-01 13:57:58 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_footpathErrorOccured = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
GameActions::Execute(&footpathPlaceAction);
|
2014-04-30 20:35:37 +02:00
|
|
|
}
|
|
|
|
|
2014-12-17 21:45:27 +01:00
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-12-17 21:45:27 +01:00
|
|
|
* rct2: 0x006A840F
|
|
|
|
*/
|
2020-02-29 03:43:29 +01:00
|
|
|
static void window_footpath_start_bridge_at_point(const ScreenCoordsXY& screenCoords)
|
2014-12-17 21:45:27 +01:00
|
|
|
{
|
2020-01-13 02:27:30 +01:00
|
|
|
int32_t z, direction;
|
2018-11-01 13:53:50 +01:00
|
|
|
TileElement* tileElement;
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2020-01-13 02:27:30 +01:00
|
|
|
auto mapCoords = footpath_bridge_get_info_from_pos(screenCoords, &direction, &tileElement);
|
|
|
|
if (mapCoords.isNull())
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
return;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2018-05-02 19:27:04 +02:00
|
|
|
if (tileElement->GetType() == TILE_ELEMENT_TYPE_SURFACE)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
// If we start the path on a slope, the arrow is slightly raised, so we
|
|
|
|
// expect the path to be slightly raised as well.
|
2018-09-14 14:54:12 +02:00
|
|
|
uint8_t slope = tileElement->AsSurface()->GetSlope();
|
2019-12-27 15:26:40 +01:00
|
|
|
z = tileElement->GetBaseZ();
|
2017-11-18 12:58:27 +01:00
|
|
|
if (slope & TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
// Steep diagonal slope
|
2019-12-30 16:03:51 +01:00
|
|
|
z += 2 * PATH_HEIGHT_STEP;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-11-18 12:58:27 +01:00
|
|
|
else if (slope & TILE_ELEMENT_SLOPE_ALL_CORNERS_UP)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
// Normal slope
|
2019-12-30 16:03:51 +01:00
|
|
|
z += PATH_HEIGHT_STEP;
|
2017-06-06 23:24:18 +02:00
|
|
|
}
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-27 15:26:40 +01:00
|
|
|
z = tileElement->GetBaseZ();
|
2018-05-02 19:27:04 +02:00
|
|
|
if (tileElement->GetType() == TILE_ELEMENT_TYPE_PATH)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2018-10-04 15:40:55 +02:00
|
|
|
if (tileElement->AsPath()->IsSloped())
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2018-10-04 15:40:55 +02:00
|
|
|
if (direction == (tileElement->AsPath()->GetSlopeDirection()))
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2019-12-30 16:03:51 +01:00
|
|
|
z += PATH_HEIGHT_STEP;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tool_cancel();
|
2020-01-13 02:27:30 +01:00
|
|
|
gFootpathConstructFromPosition = { mapCoords, z };
|
2018-06-22 23:21:44 +02:00
|
|
|
gFootpathConstructDirection = direction;
|
|
|
|
gFootpathProvisionalFlags = 0;
|
|
|
|
gFootpathConstructSlope = 0;
|
|
|
|
gFootpathConstructionMode = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL;
|
2020-03-05 18:27:36 +01:00
|
|
|
gFootpathConstructValidDirections = INVALID_DIRECTION;
|
2017-06-06 23:24:18 +02:00
|
|
|
window_footpath_set_enabled_and_pressed_widgets();
|
2014-12-17 21:45:27 +01:00
|
|
|
}
|
|
|
|
|
2014-04-30 20:35:37 +02:00
|
|
|
/**
|
2015-12-11 16:38:37 +01:00
|
|
|
* Construct a piece of footpath while in bridge building mode.
|
2014-04-30 20:35:37 +02:00
|
|
|
* rct2: 0x006A79B7
|
|
|
|
*/
|
|
|
|
static void window_footpath_construct()
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
_window_footpath_cost = MONEY32_UNDEFINED;
|
|
|
|
footpath_provisional_update();
|
|
|
|
|
2019-12-12 11:21:05 +01:00
|
|
|
int32_t type, slope;
|
|
|
|
CoordsXYZ footpathLoc;
|
|
|
|
footpath_get_next_path_info(&type, footpathLoc, &slope);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
gGameCommandErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE;
|
2019-12-12 11:21:05 +01:00
|
|
|
auto footpathPlaceAction = FootpathPlaceAction(footpathLoc, slope, type, gFootpathConstructDirection);
|
2020-10-15 03:04:39 +02:00
|
|
|
footpathPlaceAction.SetCallback([=](const GameAction* ga, const GameActions::Result* result) {
|
|
|
|
if (result->Error == GameActions::Status::Ok)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2020-10-06 23:34:42 +02:00
|
|
|
OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::PlaceItem, result->Position);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2019-03-01 18:17:46 +01:00
|
|
|
if (gFootpathConstructSlope == 0)
|
|
|
|
{
|
2020-03-05 18:27:36 +01:00
|
|
|
gFootpathConstructValidDirections = INVALID_DIRECTION;
|
2019-03-01 18:17:46 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gFootpathConstructValidDirections = gFootpathConstructDirection;
|
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2019-03-01 18:17:46 +01:00
|
|
|
if (gFootpathGroundFlags & ELEMENT_IS_UNDERGROUND)
|
|
|
|
{
|
|
|
|
viewport_set_visibility(1);
|
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2019-12-12 11:21:05 +01:00
|
|
|
gFootpathConstructFromPosition = footpathLoc;
|
2019-03-01 18:17:46 +01:00
|
|
|
// If we have just built an upwards slope, the next path to construct is
|
|
|
|
// a bit higher. Note that the z returned by footpath_get_next_path_info
|
|
|
|
// already is lowered if we are building a downwards slope.
|
|
|
|
if (gFootpathConstructSlope == 2)
|
|
|
|
{
|
2019-12-30 16:03:51 +01:00
|
|
|
gFootpathConstructFromPosition.z += PATH_HEIGHT_STEP;
|
2019-03-01 18:17:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
window_footpath_set_enabled_and_pressed_widgets();
|
|
|
|
});
|
|
|
|
GameActions::Execute(&footpathPlaceAction);
|
2014-04-30 20:35:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-12-17 21:45:27 +01:00
|
|
|
* rct2: 0x006A78EF
|
2014-04-30 20:35:37 +02:00
|
|
|
*/
|
2018-11-01 13:53:50 +01:00
|
|
|
static void footpath_remove_tile_element(TileElement* tileElement)
|
2014-04-30 20:35:37 +02:00
|
|
|
{
|
2019-12-27 15:26:40 +01:00
|
|
|
auto z = tileElement->GetBaseZ();
|
2018-10-04 15:40:55 +02:00
|
|
|
if (tileElement->AsPath()->IsSloped())
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2018-10-04 15:40:55 +02:00
|
|
|
uint8_t slopeDirection = tileElement->AsPath()->GetSlopeDirection();
|
2019-01-05 16:41:19 +01:00
|
|
|
slopeDirection = direction_reverse(slopeDirection);
|
2018-10-04 15:40:55 +02:00
|
|
|
if (slopeDirection == gFootpathConstructDirection)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2019-12-30 16:03:51 +01:00
|
|
|
z += PATH_HEIGHT_STEP;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Find a connected edge
|
2019-01-05 16:41:19 +01:00
|
|
|
int32_t edge = direction_reverse(gFootpathConstructDirection);
|
2018-10-05 13:11:44 +02:00
|
|
|
if (!(tileElement->AsPath()->GetEdges() & (1 << edge)))
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
edge = (edge + 1) & 3;
|
2018-10-05 13:11:44 +02:00
|
|
|
if (!(tileElement->AsPath()->GetEdges() & (1 << edge)))
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
edge = (edge + 2) & 3;
|
2018-10-05 13:11:44 +02:00
|
|
|
if (!(tileElement->AsPath()->GetEdges() & (1 << edge)))
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
edge = (edge - 1) & 3;
|
2018-10-05 13:11:44 +02:00
|
|
|
if (!(tileElement->AsPath()->GetEdges() & (1 << edge)))
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2019-01-05 16:41:19 +01:00
|
|
|
edge = direction_reverse(edge);
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-22 22:14:02 +01:00
|
|
|
gFootpathConstructFromPosition.z = tileElement->GetBaseZ();
|
2017-06-06 23:24:18 +02:00
|
|
|
// Remove path
|
2019-12-12 11:21:05 +01:00
|
|
|
footpath_remove(gFootpathConstructFromPosition, GAME_COMMAND_FLAG_APPLY);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Move selection
|
2019-12-22 13:45:23 +01:00
|
|
|
edge = direction_reverse(edge);
|
2019-12-12 11:21:05 +01:00
|
|
|
gFootpathConstructFromPosition.x -= CoordsDirectionDelta[edge].x;
|
|
|
|
gFootpathConstructFromPosition.y -= CoordsDirectionDelta[edge].y;
|
2019-12-27 15:26:40 +01:00
|
|
|
gFootpathConstructFromPosition.z = z;
|
2019-12-22 13:45:23 +01:00
|
|
|
gFootpathConstructDirection = edge;
|
2020-03-05 18:27:36 +01:00
|
|
|
gFootpathConstructValidDirections = INVALID_DIRECTION;
|
2014-12-17 21:45:27 +01:00
|
|
|
}
|
2014-04-30 20:35:37 +02:00
|
|
|
|
2014-12-17 21:45:27 +01:00
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-12-17 21:45:27 +01:00
|
|
|
* rct2: 0x006A7873
|
|
|
|
*/
|
2018-11-01 13:53:50 +01:00
|
|
|
static TileElement* footpath_get_tile_element_to_remove()
|
2014-12-17 21:45:27 +01:00
|
|
|
{
|
2018-11-01 13:53:50 +01:00
|
|
|
TileElement* tileElement;
|
2020-02-22 14:20:28 +01:00
|
|
|
int32_t z, zLow;
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2020-02-22 14:20:28 +01:00
|
|
|
if (!map_is_location_valid(gFootpathConstructFromPosition))
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-08-15 10:07:44 +02:00
|
|
|
return nullptr;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2020-02-22 14:20:28 +01:00
|
|
|
z = std::min(255 * COORDS_Z_STEP, gFootpathConstructFromPosition.z);
|
2020-03-07 21:07:18 +01:00
|
|
|
zLow = z - PATH_HEIGHT_STEP;
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2020-02-22 14:20:28 +01:00
|
|
|
tileElement = map_get_first_element_at(gFootpathConstructFromPosition);
|
2017-09-25 11:39:16 +02:00
|
|
|
do
|
|
|
|
{
|
2019-10-13 14:24:19 +02:00
|
|
|
if (tileElement == nullptr)
|
|
|
|
break;
|
2018-05-02 19:27:04 +02:00
|
|
|
if (tileElement->GetType() == TILE_ELEMENT_TYPE_PATH)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2020-02-22 14:20:28 +01:00
|
|
|
if (tileElement->GetBaseZ() == z)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2018-10-04 15:40:55 +02:00
|
|
|
if (tileElement->AsPath()->IsSloped())
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2019-01-05 16:41:19 +01:00
|
|
|
if (direction_reverse(tileElement->AsPath()->GetSlopeDirection()) != gFootpathConstructDirection)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
continue;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2017-10-31 14:03:45 +01:00
|
|
|
return tileElement;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2020-02-22 14:20:28 +01:00
|
|
|
else if (tileElement->GetBaseZ() == zLow)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2018-10-04 15:40:55 +02:00
|
|
|
if (!tileElement->AsPath()->IsSloped())
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2018-10-04 15:40:55 +02:00
|
|
|
if ((tileElement->AsPath()->GetSlopeDirection()) == gFootpathConstructDirection)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
continue;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2017-10-31 14:03:45 +01:00
|
|
|
return tileElement;
|
2017-06-06 23:24:18 +02:00
|
|
|
}
|
|
|
|
}
|
2018-06-22 23:21:44 +02:00
|
|
|
} while (!(tileElement++)->IsLastForTile());
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2017-08-15 10:07:44 +02:00
|
|
|
return nullptr;
|
2014-12-17 21:45:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-12-17 21:45:27 +01:00
|
|
|
* rct2: 0x006A7863
|
|
|
|
*/
|
|
|
|
static void window_footpath_remove()
|
|
|
|
{
|
2018-11-01 13:53:50 +01:00
|
|
|
TileElement* tileElement;
|
2014-12-17 21:45:27 +01:00
|
|
|
|
2017-06-06 23:24:18 +02:00
|
|
|
_window_footpath_cost = MONEY32_UNDEFINED;
|
|
|
|
footpath_provisional_update();
|
2014-12-17 21:45:27 +01:00
|
|
|
|
2017-10-31 14:03:45 +01:00
|
|
|
tileElement = footpath_get_tile_element_to_remove();
|
|
|
|
if (tileElement != nullptr)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-10-31 14:03:45 +01:00
|
|
|
footpath_remove_tile_element(tileElement);
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2014-12-17 21:45:27 +01:00
|
|
|
|
2017-06-06 23:24:18 +02:00
|
|
|
window_footpath_set_enabled_and_pressed_widgets();
|
2014-12-17 21:45:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-12-17 21:45:27 +01:00
|
|
|
* rct2: 0x006A855C
|
|
|
|
*/
|
|
|
|
static void window_footpath_set_enabled_and_pressed_widgets()
|
|
|
|
{
|
2018-06-22 23:21:44 +02:00
|
|
|
rct_window* w = window_find_by_class(WC_FOOTPATH);
|
2017-08-15 10:07:44 +02:00
|
|
|
if (w == nullptr)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
return;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2017-09-25 11:39:16 +02:00
|
|
|
if (gFootpathConstructionMode == PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL)
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
map_invalidate_map_selection_tiles();
|
|
|
|
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE_CONSTRUCT;
|
|
|
|
gMapSelectFlags |= MAP_SELECT_FLAG_GREEN;
|
|
|
|
|
2018-06-20 17:28:51 +02:00
|
|
|
int32_t direction = gFootpathConstructDirection;
|
2019-03-28 19:29:51 +01:00
|
|
|
gMapSelectionTiles.clear();
|
|
|
|
gMapSelectionTiles.push_back({ gFootpathConstructFromPosition.x + CoordsDirectionDelta[direction].x,
|
|
|
|
gFootpathConstructFromPosition.y + CoordsDirectionDelta[direction].y });
|
2017-06-06 23:24:18 +02:00
|
|
|
map_invalidate_map_selection_tiles();
|
|
|
|
}
|
|
|
|
|
2018-06-22 23:21:44 +02:00
|
|
|
uint64_t pressedWidgets = w->pressed_widgets
|
|
|
|
& ~((1LL << WIDX_DIRECTION_NW) | (1LL << WIDX_DIRECTION_NE) | (1LL << WIDX_DIRECTION_SW) | (1LL << WIDX_DIRECTION_SE)
|
|
|
|
| (1LL << WIDX_SLOPEDOWN) | (1LL << WIDX_LEVEL) | (1LL << WIDX_SLOPEUP));
|
2018-06-20 17:28:51 +02:00
|
|
|
uint64_t disabledWidgets = 0;
|
|
|
|
int32_t currentRotation = get_current_rotation();
|
2017-09-25 11:39:16 +02:00
|
|
|
if (gFootpathConstructionMode >= PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL)
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
// Set pressed directional widget
|
2018-06-20 17:28:51 +02:00
|
|
|
int32_t direction = (gFootpathConstructDirection + currentRotation) & 3;
|
2017-06-06 23:24:18 +02:00
|
|
|
pressedWidgets |= (1LL << (WIDX_DIRECTION_NW + direction));
|
|
|
|
|
|
|
|
// Set pressed slope widget
|
2018-06-20 17:28:51 +02:00
|
|
|
int32_t slope = gFootpathConstructSlope;
|
2017-11-18 12:58:27 +01:00
|
|
|
if (slope == TILE_ELEMENT_SLOPE_SE_SIDE_UP)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
pressedWidgets |= (1 << WIDX_SLOPEDOWN);
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-11-18 12:58:27 +01:00
|
|
|
else if (slope == TILE_ELEMENT_SLOPE_FLAT)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
pressedWidgets |= (1 << WIDX_LEVEL);
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
else
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
pressedWidgets |= (1 << WIDX_SLOPEUP);
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Enable / disable directional widgets
|
|
|
|
direction = gFootpathConstructValidDirections;
|
2020-03-05 18:27:36 +01:00
|
|
|
if (direction != INVALID_DIRECTION)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2018-07-21 11:50:45 +02:00
|
|
|
disabledWidgets |= (1 << WIDX_DIRECTION_NW) | (1 << WIDX_DIRECTION_NE) | (1 << WIDX_DIRECTION_SW)
|
|
|
|
| (1 << WIDX_DIRECTION_SE);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
direction = (direction + currentRotation) & 3;
|
|
|
|
disabledWidgets &= ~(1 << (WIDX_DIRECTION_NW + direction));
|
|
|
|
}
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
// Disable all bridge mode widgets
|
2018-06-22 23:21:44 +02:00
|
|
|
disabledWidgets |= (1 << WIDX_DIRECTION_GROUP) | (1 << WIDX_DIRECTION_NW) | (1 << WIDX_DIRECTION_NE)
|
|
|
|
| (1 << WIDX_DIRECTION_SW) | (1 << WIDX_DIRECTION_SE) | (1 << WIDX_SLOPE_GROUP) | (1 << WIDX_SLOPEDOWN)
|
|
|
|
| (1 << WIDX_LEVEL) | (1 << WIDX_SLOPEUP) | (1 << WIDX_CONSTRUCT) | (1 << WIDX_REMOVE);
|
2017-06-06 23:24:18 +02:00
|
|
|
}
|
|
|
|
|
2018-06-22 23:21:44 +02:00
|
|
|
w->pressed_widgets = pressedWidgets;
|
2017-06-06 23:24:18 +02:00
|
|
|
w->disabled_widgets = disabledWidgets;
|
2019-06-15 17:20:16 +02:00
|
|
|
w->Invalidate();
|
2014-12-17 21:45:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-12-17 21:45:27 +01:00
|
|
|
* rct2: 0x006A7B20
|
|
|
|
*/
|
2019-12-12 11:21:05 +01:00
|
|
|
static void footpath_get_next_path_info(int32_t* type, CoordsXYZ& footpathLoc, int32_t* slope)
|
2014-12-17 21:45:27 +01:00
|
|
|
{
|
2018-06-20 17:28:51 +02:00
|
|
|
int32_t direction;
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
direction = gFootpathConstructDirection;
|
2019-12-12 11:21:05 +01:00
|
|
|
footpathLoc.x = gFootpathConstructFromPosition.x + CoordsDirectionDelta[direction].x;
|
|
|
|
footpathLoc.y = gFootpathConstructFromPosition.y + CoordsDirectionDelta[direction].y;
|
|
|
|
footpathLoc.z = gFootpathConstructFromPosition.z;
|
2018-06-22 23:21:44 +02:00
|
|
|
*type = (gFootpathSelectedType << 7) + (gFootpathSelectedId & 0xFF);
|
2017-11-18 12:58:27 +01:00
|
|
|
*slope = TILE_ELEMENT_SLOPE_FLAT;
|
2017-09-25 11:39:16 +02:00
|
|
|
if (gFootpathConstructSlope != 0)
|
|
|
|
{
|
2017-11-18 12:58:27 +01:00
|
|
|
*slope = gFootpathConstructDirection | TILE_ELEMENT_SLOPE_S_CORNER_UP;
|
2017-09-25 11:39:16 +02:00
|
|
|
if (gFootpathConstructSlope != 2)
|
|
|
|
{
|
2019-12-30 16:03:51 +01:00
|
|
|
footpathLoc.z -= PATH_HEIGHT_STEP;
|
2017-11-18 12:58:27 +01:00
|
|
|
*slope ^= TILE_ELEMENT_SLOPE_E_CORNER_UP;
|
2017-06-06 23:24:18 +02:00
|
|
|
}
|
|
|
|
}
|
2015-06-09 17:19:05 +02:00
|
|
|
}
|
2016-05-15 20:08:02 +02:00
|
|
|
|
2017-07-03 22:46:07 +02:00
|
|
|
static bool footpath_select_default()
|
2016-05-15 20:08:02 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
// Select first available footpath
|
2018-06-22 23:21:44 +02:00
|
|
|
int32_t footpathId = -1;
|
2020-11-09 10:36:37 +01:00
|
|
|
for (int32_t i = 0; i < object_entry_group_counts[ObjectType::Paths]; i++)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2019-01-20 21:38:38 +01:00
|
|
|
PathSurfaceEntry* pathEntry = get_path_surface_entry(i);
|
2017-10-15 15:53:16 +02:00
|
|
|
if (pathEntry != nullptr)
|
2017-09-25 11:39:16 +02:00
|
|
|
{
|
2017-07-03 22:46:07 +02:00
|
|
|
footpathId = i;
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Prioritise non-restricted path
|
2017-09-25 11:39:16 +02:00
|
|
|
if (!(pathEntry->flags & FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR))
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-09-25 11:39:16 +02:00
|
|
|
if (footpathId == -1)
|
|
|
|
{
|
2017-07-03 22:46:07 +02:00
|
|
|
return false;
|
2017-09-25 11:39:16 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-07-03 22:46:07 +02:00
|
|
|
gFootpathSelectedId = footpathId;
|
|
|
|
return true;
|
|
|
|
}
|
2016-05-15 20:08:02 +02:00
|
|
|
}
|