2016-05-04 19:24:41 +02:00
# pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
2014-04-28 18:35:12 +02:00
/*****************************************************************************
* OpenRCT2 , an open source clone of Roller Coaster Tycoon 2.
*
2016-05-04 19:24:41 +02:00
* OpenRCT2 is the work of many authors , a full list can be found in contributors . md
* For more information , visit https : //github.com/OpenRCT2/OpenRCT2
2014-04-28 18:35:12 +02:00
*
* OpenRCT2 is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
2016-05-04 19:24:41 +02:00
*
* A full copy of the GNU General Public License can be found in licence . txt
2014-04-28 18:35:12 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-05-04 19:24:41 +02:00
# pragma endregion
2014-04-28 18:35:12 +02:00
2014-10-06 18:36:58 +02:00
# include "../addresses.h"
# include "../audio/audio.h"
# include "../game.h"
# include "../localisation/localisation.h"
2014-11-15 19:22:06 +01:00
# include "../input.h"
2014-10-06 18:36:58 +02:00
# include "../sprites.h"
# include "../interface/widget.h"
# include "../interface/window.h"
2014-11-15 19:22:06 +01:00
# include "../interface/viewport.h"
# include "../world/footpath.h"
# include "../world/map.h"
2014-10-06 18:36:58 +02:00
# include "dropdown.h"
2015-06-01 17:02:09 +02:00
# include "../interface/themes.h"
2015-06-09 17:19:05 +02:00
# include "../cheats.h"
2014-04-28 18:35:12 +02:00
2014-04-30 17:57:27 +02:00
enum {
PATH_CONSTRUCTION_MODE_LAND ,
2014-12-17 21:45:27 +01:00
PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL ,
PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL
2014-04-30 17:57:27 +02:00
} ;
2014-05-17 16:06:18 +02:00
enum {
SELECTED_PATH_TYPE_NORMAL ,
SELECTED_PATH_TYPE_QUEUE
} ;
2014-05-19 21:10:32 +02:00
enum WINDOW_FOOTPATH_WIDGET_IDX {
2014-04-28 18:35:12 +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 ,
} ;
static rct_widget window_footpath_widgets [ ] = {
{ WWT_FRAME , 0 , 0 , 105 , 0 , 380 , 0x0FFFFFFFF , STR_NONE } ,
{ WWT_CAPTION , 0 , 1 , 104 , 1 , 14 , STR_FOOTPATHS , STR_WINDOW_TITLE_TIP } ,
{ WWT_CLOSEBOX , 0 , 93 , 103 , 2 , 13 , STR_CLOSE_X , STR_CLOSE_WINDOW_TIP } ,
// Type group
{ WWT_GROUPBOX , 0 , 3 , 102 , 17 , 71 , STR_TYPE , STR_NONE } ,
{ WWT_FLATBTN , 1 , 6 , 52 , 30 , 65 , 0xFFFFFFFF , STR_FOOTPATH_TIP } ,
{ WWT_FLATBTN , 1 , 53 , 99 , 30 , 65 , 0xFFFFFFFF , STR_QUEUE_LINE_PATH_TIP } ,
// Direction group
{ WWT_GROUPBOX , 0 , 3 , 102 , 75 , 151 , STR_DIRECTION , STR_NONE } ,
{ WWT_FLATBTN , 1 , 53 , 97 , 87 , 115 , 5635 , STR_DIRECTION_TIP } ,
{ WWT_FLATBTN , 1 , 53 , 97 , 116 , 144 , 5636 , STR_DIRECTION_TIP } ,
{ WWT_FLATBTN , 1 , 8 , 52 , 116 , 144 , 5637 , STR_DIRECTION_TIP } ,
{ WWT_FLATBTN , 1 , 8 , 52 , 87 , 115 , 5638 , STR_DIRECTION_TIP } ,
// Slope group
{ WWT_GROUPBOX , 0 , 3 , 102 , 155 , 195 , STR_SLOPE , STR_NONE } ,
{ WWT_FLATBTN , 1 , 17 , 40 , 167 , 190 , 5145 , STR_SLOPE_DOWN_TIP } ,
{ WWT_FLATBTN , 1 , 41 , 64 , 167 , 190 , 5146 , STR_LEVEL_TIP } ,
{ WWT_FLATBTN , 1 , 65 , 88 , 167 , 190 , 5147 , STR_SLOPE_UP_TIP } ,
{ WWT_FLATBTN , 1 , 8 , 97 , 202 , 291 , 0xFFFFFFFF , STR_CONSTRUCT_THE_SELECTED_FOOTPATH_SECTION_TIP } ,
{ WWT_FLATBTN , 1 , 30 , 75 , 295 , 318 , 5162 , STR_REMOVE_PREVIOUS_FOOTPATH_SECTION_TIP } ,
// Mode group
{ WWT_GROUPBOX , 0 , 3 , 102 , 321 , 374 , 0xFFFFFFFF , STR_NONE } ,
{ WWT_FLATBTN , 1 , 13 , 48 , 332 , 367 , 5639 , STR_CONSTRUCT_FOOTPATH_ON_LAND_TIP } ,
{ WWT_FLATBTN , 1 , 57 , 92 , 332 , 367 , 5640 , STR_CONSTRUCT_BRIDGE_OR_TUNNEL_FOOTPATH_TIP } ,
{ WIDGETS_END } ,
} ;
2015-07-10 02:39:16 +02:00
static void window_footpath_close ( rct_window * w ) ;
static void window_footpath_mouseup ( rct_window * w , int widgetIndex ) ;
2014-12-16 23:03:56 +01:00
static void window_footpath_mousedown ( int widgetIndex , rct_window * w , rct_widget * widget ) ;
2015-07-10 02:39:16 +02:00
static void window_footpath_dropdown ( rct_window * w , int widgetIndex , int dropdownIndex ) ;
2014-05-19 19:47:14 +02:00
static void window_footpath_update ( rct_window * w ) ;
2015-07-10 02:39:16 +02:00
static void window_footpath_toolupdate ( rct_window * w , int widgetIndex , int x , int y ) ;
static void window_footpath_tooldown ( rct_window * w , int widgetIndex , int x , int y ) ;
static void window_footpath_tooldrag ( rct_window * w , int widgetIndex , int x , int y ) ;
static void window_footpath_toolup ( rct_window * w , int widgetIndex , int x , int y ) ;
static void window_footpath_invalidate ( rct_window * w ) ;
static void window_footpath_paint ( rct_window * w , rct_drawpixelinfo * dpi ) ;
static rct_window_event_list window_footpath_events = {
2014-04-28 19:37:38 +02:00
window_footpath_close ,
2014-04-28 18:35:12 +02:00
window_footpath_mouseup ,
2015-07-10 02:39:16 +02:00
NULL ,
2014-04-29 04:12:52 +02:00
window_footpath_mousedown ,
window_footpath_dropdown ,
2015-07-10 02:39:16 +02:00
NULL ,
2014-04-29 04:12:52 +02:00
window_footpath_update ,
2015-07-10 02:39:16 +02:00
NULL ,
NULL ,
2014-04-29 04:12:52 +02:00
window_footpath_toolupdate ,
window_footpath_tooldown ,
window_footpath_tooldrag ,
window_footpath_toolup ,
2015-07-10 02:39:16 +02:00
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
2014-04-28 19:37:38 +02:00
window_footpath_invalidate ,
2014-04-28 18:35:12 +02:00
window_footpath_paint ,
2015-07-10 02:39:16 +02:00
NULL
2014-04-28 18:35:12 +02:00
} ;
2015-12-19 23:54:15 +01:00
static money32 _window_footpath_cost ;
static sint8 _window_footpath_provisional_path_arrow_timer ;
static uint8 _lastUpdatedCameraRotation = UINT8_MAX ;
2016-04-15 20:16:48 +02:00
static bool _footpathErrorOccured ;
2014-04-28 19:37:38 +02:00
2015-02-21 00:40:52 +01:00
static void window_footpath_mousedown_direction ( int direction ) ;
static void window_footpath_mousedown_slope ( int slope ) ;
2014-04-29 23:25:37 +02:00
static void window_footpath_show_footpath_types_dialog ( rct_window * w , rct_widget * widget , int showQueues ) ;
2014-04-30 14:38:27 +02:00
static void window_footpath_set_provisional_path_at_point ( int x , int y ) ;
2015-03-23 22:28:44 +01:00
static void window_footpath_set_selection_start_bridge_at_point ( int screenX , int screenY ) ;
2014-04-30 14:38:27 +02:00
static void window_footpath_place_path_at_point ( int x , int y ) ;
2014-12-17 21:45:27 +01:00
static void window_footpath_start_bridge_at_point ( int screenX , int screenY ) ;
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 ( ) ;
static void footpath_get_next_path_info ( int * type , int * x , int * y , int * z , int * slope ) ;
2016-05-15 20:08:02 +02:00
static void 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
*/
void window_footpath_open ( )
{
// Check if window is already open
2016-05-15 20:08:02 +02:00
rct_window * window = window_bring_to_front_by_class ( WC_FOOTPATH ) ;
2014-04-28 18:35:12 +02:00
if ( window ! = NULL )
return ;
window = window_create (
0 ,
29 ,
106 ,
381 ,
2015-07-10 02:39:16 +02:00
& window_footpath_events ,
2014-04-28 18:35:12 +02:00
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 ) ;
window_init_scroll_widgets ( window ) ;
2014-09-01 22:06:50 +02:00
window_push_others_right ( window ) ;
2014-04-28 18:35:12 +02:00
show_gridlines ( ) ;
2015-06-09 17:19:05 +02:00
// If a restricted path was selected when the game is no longer in Sandbox mode, reset it
2016-05-15 20:08:02 +02:00
rct_footpath_entry * pathEntry = get_footpath_entry ( gFootpathSelectedId ) ;
if ( pathEntry ! = ( rct_footpath_entry * ) - 1 & & ( pathEntry - > flags & 4 ) & & ! gCheatsSandboxMode ) {
pathEntry = ( rct_footpath_entry * ) - 1 ;
}
// Select the default path if we don't have one
if ( pathEntry = = ( rct_footpath_entry * ) - 1 ) {
footpath_select_default ( ) ;
2015-06-09 17:19:05 +02:00
}
2014-04-30 17:57:27 +02:00
tool_cancel ( ) ;
2016-04-15 20:16:48 +02:00
gFootpathConstructionMode = PATH_CONSTRUCTION_MODE_LAND ;
2014-04-30 17:57:27 +02:00
tool_set ( window , WIDX_CONSTRUCT_ON_LAND , 17 ) ;
2016-01-04 23:53:03 +01:00
gInputFlags | = INPUT_FLAG_6 ;
2016-04-15 20:16:48 +02:00
_footpathErrorOccured = false ;
2014-12-17 21:45:27 +01:00
window_footpath_set_enabled_and_pressed_widgets ( ) ;
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
*/
2015-07-10 02:39:16 +02:00
static void window_footpath_close ( rct_window * w )
2014-04-28 19:37:38 +02:00
{
2015-03-22 22:18:36 +01:00
footpath_provisional_update ( ) ;
2014-09-02 19:10:49 +02:00
viewport_set_visibility ( 0 ) ;
2014-12-17 21:45:27 +01:00
map_invalidate_map_selection_tiles ( ) ;
2016-05-14 01:54:13 +02:00
gMapSelectFlags & = ~ MAP_SELECT_FLAG_ENABLE_CONSTRUCT ;
2014-10-16 03:02:43 +02:00
window_invalidate_by_class ( WC_TOP_TOOLBAR ) ;
2014-04-28 19:37:38 +02:00
hide_gridlines ( ) ;
}
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
*/
2015-07-10 02:39:16 +02:00
static void window_footpath_mouseup ( rct_window * w , int widgetIndex )
2014-04-28 18:35:12 +02:00
{
switch ( widgetIndex ) {
case WIDX_CLOSE :
window_close ( w ) ;
break ;
2014-04-29 04:12:52 +02:00
case WIDX_CONSTRUCT :
2014-04-30 20:35:37 +02:00
window_footpath_construct ( ) ;
2014-04-29 04:12:52 +02:00
break ;
case WIDX_REMOVE :
2014-04-30 20:35:37 +02:00
window_footpath_remove ( ) ;
2014-04-29 04:12:52 +02:00
break ;
case WIDX_CONSTRUCT_ON_LAND :
2016-04-15 20:16:48 +02:00
if ( gFootpathConstructionMode = = PATH_CONSTRUCTION_MODE_LAND )
2014-04-30 17:57:27 +02:00
break ;
2014-04-30 20:35:37 +02:00
2014-12-16 23:03:56 +01:00
_window_footpath_cost = MONEY32_UNDEFINED ;
2014-04-30 17:57:27 +02:00
tool_cancel ( ) ;
2015-03-22 22:18:36 +01:00
footpath_provisional_update ( ) ;
2014-12-17 21:45:27 +01:00
map_invalidate_map_selection_tiles ( ) ;
2016-05-14 01:54:13 +02:00
gMapSelectFlags & = ~ MAP_SELECT_FLAG_ENABLE_CONSTRUCT ;
2016-04-15 20:16:48 +02:00
gFootpathConstructionMode = PATH_CONSTRUCTION_MODE_LAND ;
2014-04-30 17:57:27 +02:00
tool_set ( w , WIDX_CONSTRUCT_ON_LAND , 17 ) ;
2016-01-04 23:53:03 +01:00
gInputFlags | = INPUT_FLAG_6 ;
2016-04-15 20:16:48 +02:00
_footpathErrorOccured = false ;
2014-12-17 21:45:27 +01:00
window_footpath_set_enabled_and_pressed_widgets ( ) ;
2014-04-29 04:12:52 +02:00
break ;
case WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL :
2016-04-15 20:16:48 +02:00
if ( gFootpathConstructionMode = = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL )
2014-04-30 17:57:27 +02:00
break ;
2014-04-30 20:35:37 +02:00
2014-12-16 23:03:56 +01:00
_window_footpath_cost = MONEY32_UNDEFINED ;
2014-05-08 17:08:52 +02:00
tool_cancel ( ) ;
2015-03-22 22:18:36 +01:00
footpath_provisional_update ( ) ;
2014-12-17 21:45:27 +01:00
map_invalidate_map_selection_tiles ( ) ;
2016-05-14 01:54:13 +02:00
gMapSelectFlags & = ~ MAP_SELECT_FLAG_ENABLE_CONSTRUCT ;
2016-04-15 20:16:48 +02:00
gFootpathConstructionMode = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL ;
2014-04-30 17:57:27 +02:00
tool_set ( w , WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL , 12 ) ;
2016-01-04 23:53:03 +01:00
gInputFlags | = INPUT_FLAG_6 ;
2016-04-15 20:16:48 +02:00
_footpathErrorOccured = false ;
2014-12-17 21:45:27 +01:00
window_footpath_set_enabled_and_pressed_widgets ( ) ;
2014-04-29 04:12:52 +02:00
break ;
}
}
/**
2015-10-20 20:16:30 +02:00
*
2014-04-29 04:12:52 +02:00
* rct2 : 0x006A7EC5
*/
2014-05-28 23:22:09 +02:00
static void window_footpath_mousedown ( int widgetIndex , rct_window * w , rct_widget * widget )
2014-04-29 04:12:52 +02:00
{
switch ( widgetIndex ) {
case WIDX_FOOTPATH_TYPE :
2014-04-29 23:25:37 +02:00
window_footpath_show_footpath_types_dialog ( w , widget , 0 ) ;
2014-04-29 04:12:52 +02:00
break ;
case WIDX_QUEUELINE_TYPE :
2014-04-29 23:25:37 +02:00
window_footpath_show_footpath_types_dialog ( w , widget , 1 ) ;
2014-04-29 04:12:52 +02:00
break ;
case WIDX_DIRECTION_NW :
2015-02-21 00:40:52 +01:00
window_footpath_mousedown_direction ( 0 ) ;
2014-04-29 04:12:52 +02:00
break ;
case WIDX_DIRECTION_NE :
2015-02-21 00:40:52 +01:00
window_footpath_mousedown_direction ( 1 ) ;
2014-04-29 04:12:52 +02:00
break ;
case WIDX_DIRECTION_SW :
2015-02-21 00:40:52 +01:00
window_footpath_mousedown_direction ( 2 ) ;
2014-04-29 04:12:52 +02:00
break ;
case WIDX_DIRECTION_SE :
2015-02-21 00:40:52 +01:00
window_footpath_mousedown_direction ( 3 ) ;
2014-04-29 04:12:52 +02:00
break ;
case WIDX_SLOPEDOWN :
2015-02-21 00:40:52 +01:00
window_footpath_mousedown_slope ( 6 ) ;
2014-04-29 04:12:52 +02:00
break ;
case WIDX_LEVEL :
2015-02-21 00:40:52 +01:00
window_footpath_mousedown_slope ( 0 ) ;
2014-04-29 04:12:52 +02:00
break ;
case WIDX_SLOPEUP :
2015-02-21 00:40:52 +01:00
window_footpath_mousedown_slope ( 2 ) ;
2014-04-29 04:12:52 +02:00
break ;
}
}
/**
2015-10-20 20:16:30 +02:00
*
2014-04-29 04:12:52 +02:00
* rct2 : 0x006A7F18
*/
2015-07-10 02:39:16 +02:00
static void window_footpath_dropdown ( rct_window * w , int widgetIndex , int dropdownIndex )
2014-04-29 04:12:52 +02:00
{
2014-04-30 02:59:11 +02:00
int i , j , pathId ;
2016-05-15 17:11:34 +02:00
rct_footpath_entry * pathType ;
2014-04-29 04:12:52 +02:00
2014-04-29 23:25:37 +02:00
if ( widgetIndex = = WIDX_FOOTPATH_TYPE )
2016-04-15 20:16:48 +02:00
gFootpathSelectedType = SELECTED_PATH_TYPE_NORMAL ;
2014-04-29 23:25:37 +02:00
else if ( widgetIndex = = WIDX_QUEUELINE_TYPE )
2016-04-15 20:16:48 +02:00
gFootpathSelectedType = SELECTED_PATH_TYPE_QUEUE ;
2014-04-29 23:25:37 +02:00
else
return ;
2015-10-20 20:16:30 +02:00
2014-04-30 02:59:11 +02:00
// Get path id
2014-04-29 23:25:37 +02:00
pathId = dropdownIndex ;
if ( pathId = = - 1 ) {
2016-04-15 20:16:48 +02:00
pathId = gFootpathSelectedId ;
2014-04-29 23:25:37 +02:00
} else {
int flags = 4 ;
2016-04-23 12:16:46 +02:00
if ( ( gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR ) | | gCheatsSandboxMode )
2014-04-29 23:25:37 +02:00
flags = 0 ;
2014-04-30 02:59:11 +02:00
j = 0 ;
for ( i = 0 ; i < 16 ; i + + ) {
2016-05-15 17:07:19 +02:00
pathType = get_footpath_entry ( i ) ;
2016-05-15 17:11:34 +02:00
if ( pathType = = ( rct_footpath_entry * ) - 1 )
2014-04-29 23:25:37 +02:00
continue ;
if ( pathType - > flags & flags )
continue ;
2015-06-09 17:19:05 +02:00
// Skip queue lines of scenario editor-only paths (only applicable when the game is in sandbox mode)
2015-06-09 20:11:48 +02:00
if ( widgetIndex = = WIDX_QUEUELINE_TYPE & & ( pathType - > flags & 4 ) )
2015-06-09 17:19:05 +02:00
continue ;
2014-04-30 02:59:11 +02:00
if ( j = = pathId )
break ;
j + + ;
}
2014-04-29 23:25:37 +02:00
pathId = i ;
2014-04-29 04:12:52 +02:00
}
2014-04-29 23:25:37 +02:00
2014-04-30 02:59:11 +02:00
// Set selected path id
2016-04-15 20:16:48 +02:00
gFootpathSelectedId = pathId ;
2015-03-22 22:18:36 +01:00
footpath_provisional_update ( ) ;
2014-12-16 23:03:56 +01:00
_window_footpath_cost = MONEY32_UNDEFINED ;
2014-04-29 23:25:37 +02:00
window_invalidate ( w ) ;
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
*/
2015-07-10 02:39:16 +02:00
static void window_footpath_toolupdate ( rct_window * w , int widgetIndex , int x , int y )
2014-04-29 04:12:52 +02:00
{
if ( widgetIndex = = WIDX_CONSTRUCT_ON_LAND ) {
2014-04-30 14:38:27 +02:00
window_footpath_set_provisional_path_at_point ( x , y ) ;
2014-04-29 04:12:52 +02:00
} else if ( widgetIndex = = WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL ) {
2015-03-23 22:28:44 +01:00
window_footpath_set_selection_start_bridge_at_point ( x , y ) ;
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
*/
2015-07-10 02:39:16 +02:00
static void window_footpath_tooldown ( rct_window * w , int widgetIndex , int x , int y )
2014-04-29 04:12:52 +02:00
{
2014-12-17 21:45:27 +01:00
if ( widgetIndex = = WIDX_CONSTRUCT_ON_LAND )
2014-04-30 14:38:27 +02:00
window_footpath_place_path_at_point ( x , y ) ;
2014-12-17 21:45:27 +01:00
else if ( widgetIndex = = WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL )
window_footpath_start_bridge_at_point ( x , y ) ;
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
*/
2015-07-10 02:39:16 +02:00
static void window_footpath_tooldrag ( rct_window * w , int widgetIndex , int x , int y )
2014-04-29 04:12:52 +02:00
{
if ( widgetIndex = = WIDX_CONSTRUCT_ON_LAND ) {
2015-03-22 21:50:16 +01:00
window_footpath_place_path_at_point ( x , y ) ;
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
*/
2015-07-10 02:39:16 +02:00
static void window_footpath_toolup ( rct_window * w , int widgetIndex , int x , int y )
2014-04-29 04:12:52 +02:00
{
if ( widgetIndex = = WIDX_CONSTRUCT_ON_LAND ) {
2016-04-15 20:16:48 +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
*/
static void window_footpath_update_provisional_path_for_bridge_mode ( rct_window * w )
{
int type , x , y , z , slope ;
2016-04-15 20:16:48 +02:00
if ( gFootpathConstructionMode ! = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL )
2014-12-17 21:45:27 +01:00
return ;
2015-11-02 22:55:06 +01:00
// Recheck area for construction. Set by ride_construction window
2016-04-15 20:16:48 +02:00
if ( gFootpathProvisionalFlags & PROVISIONAL_PATH_FLAG_2 ) {
2015-11-02 22:55:06 +01:00
footpath_provisional_remove ( ) ;
2016-04-15 20:16:48 +02:00
gFootpathProvisionalFlags & = ~ PROVISIONAL_PATH_FLAG_2 ;
2015-11-02 22:55:06 +01:00
}
2014-12-17 21:45:27 +01:00
// Update provisional bridge mode path
2016-04-15 20:16:48 +02:00
if ( ! ( gFootpathProvisionalFlags & PROVISIONAL_PATH_FLAG_1 ) ) {
2014-12-17 21:45:27 +01:00
footpath_get_next_path_info ( & type , & x , & y , & z , & slope ) ;
_window_footpath_cost = footpath_provisional_set ( type , x , y , z , slope ) ;
widget_invalidate ( w , WIDX_CONSTRUCT ) ;
}
// Update little directional arrow on provisional bridge mode path
if ( - - _window_footpath_provisional_path_arrow_timer < 0 ) {
_window_footpath_provisional_path_arrow_timer = 5 ;
2016-04-15 20:16:48 +02:00
gFootpathProvisionalFlags ^ = PROVISIONAL_PATH_FLAG_SHOW_ARROW ;
2014-12-17 21:45:27 +01:00
footpath_get_next_path_info ( & type , & x , & y , & z , & slope ) ;
2016-05-14 01:54:13 +02:00
gMapSelectArrowPosition . x = x ;
gMapSelectArrowPosition . y = y ;
gMapSelectArrowPosition . z = z * 8 ;
gMapSelectArrowDirection = gFootpathConstructDirection ;
2016-04-15 20:16:48 +02:00
if ( gFootpathProvisionalFlags & PROVISIONAL_PATH_FLAG_SHOW_ARROW )
2016-05-14 01:54:13 +02:00
gMapSelectFlags | = MAP_SELECT_FLAG_ENABLE_ARROW ;
2014-12-17 21:45:27 +01:00
else
2016-05-14 01:54:13 +02:00
gMapSelectFlags & = ~ MAP_SELECT_FLAG_ENABLE_ARROW ;
2014-12-17 21:45:27 +01:00
map_invalidate_tile_full ( x , y ) ;
}
}
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
*/
2014-05-19 19:47:14 +02:00
static void window_footpath_update ( rct_window * w )
2014-04-29 04:12:52 +02:00
{
2014-10-16 03:02:43 +02:00
widget_invalidate ( w , WIDX_CONSTRUCT ) ;
2014-12-17 21:45:27 +01:00
window_footpath_update_provisional_path_for_bridge_mode ( w ) ;
2014-04-29 04:12:52 +02:00
2015-12-19 23:54:15 +01:00
// #2502: The camera might have changed rotation, so we need to update which directional buttons are pressed
uint8 currentRotation = get_current_rotation ( ) ;
if ( _lastUpdatedCameraRotation ! = currentRotation ) {
_lastUpdatedCameraRotation = currentRotation ;
window_footpath_set_enabled_and_pressed_widgets ( ) ;
}
2014-04-29 04:12:52 +02:00
// Check tool
2016-04-15 20:16:48 +02:00
if ( gFootpathConstructionMode = = PATH_CONSTRUCTION_MODE_LAND ) {
2016-01-04 23:53:03 +01:00
if ( ! ( gInputFlags & INPUT_FLAG_TOOL_ACTIVE ) )
2014-04-29 04:12:52 +02:00
window_close ( w ) ;
2016-04-15 19:26:47 +02:00
else if ( gCurrentToolWidget . window_classification ! = WC_FOOTPATH )
2014-04-29 04:12:52 +02:00
window_close ( w ) ;
2016-04-15 19:26:47 +02:00
else if ( gCurrentToolWidget . widget_index ! = WIDX_CONSTRUCT_ON_LAND )
2014-04-29 04:12:52 +02:00
window_close ( w ) ;
2016-04-15 20:16:48 +02:00
} else if ( gFootpathConstructionMode = = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL ) {
2016-01-04 23:53:03 +01:00
if ( ! ( gInputFlags & INPUT_FLAG_TOOL_ACTIVE ) )
2014-04-29 04:12:52 +02:00
window_close ( w ) ;
2016-04-15 19:26:47 +02:00
else if ( gCurrentToolWidget . window_classification ! = WC_FOOTPATH )
2014-04-29 04:12:52 +02:00
window_close ( w ) ;
2016-04-15 19:26:47 +02:00
else if ( gCurrentToolWidget . widget_index ! = WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL )
2014-04-29 04:12:52 +02:00
window_close ( w ) ;
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
*/
2015-07-10 02:39:16 +02:00
static void window_footpath_invalidate ( rct_window * w )
2014-04-28 19:37:38 +02:00
{
int selectedPath ;
2016-05-15 17:11:34 +02:00
rct_footpath_entry * pathType ;
2014-04-28 19:37:38 +02:00
2015-05-29 18:04:53 +02:00
colour_scheme_update ( w ) ;
2015-10-20 20:16:30 +02:00
2014-04-28 19:37:38 +02:00
// Press / unpress footpath and queue type buttons
w - > pressed_widgets & = ~ ( 1 < < WIDX_FOOTPATH_TYPE ) ;
w - > pressed_widgets & = ~ ( 1 < < WIDX_QUEUELINE_TYPE ) ;
2016-04-15 20:16:48 +02:00
w - > pressed_widgets | = gFootpathSelectedType = = SELECTED_PATH_TYPE_NORMAL ?
2014-04-28 19:37:38 +02:00
( 1 < < WIDX_FOOTPATH_TYPE ) :
( 1 < < WIDX_QUEUELINE_TYPE ) ;
// Enable / disable construct button
2014-12-17 21:45:27 +01:00
window_footpath_widgets [ WIDX_CONSTRUCT ] . type =
2016-04-15 20:16:48 +02:00
gFootpathConstructionMode = = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL ?
2014-12-17 21:45:27 +01:00
WWT_IMGBTN : WWT_EMPTY ;
2014-04-28 19:37:38 +02:00
// Set footpath and queue type button images
2016-04-15 20:16:48 +02:00
selectedPath = gFootpathSelectedId ;
2016-05-15 17:07:19 +02:00
pathType = get_footpath_entry ( selectedPath ) ;
2014-04-28 19:37:38 +02:00
int pathImage = 71 + pathType - > image ;
window_footpath_widgets [ WIDX_FOOTPATH_TYPE ] . image = pathImage ;
2015-06-09 17:19:05 +02:00
// Disable queue line button when the path is scenario editor-only (and therefore usually shouldn't have one)
if ( ! ( pathType - > flags & 4 ) ) {
window_footpath_widgets [ WIDX_QUEUELINE_TYPE ] . image = pathImage + 1 ;
window_footpath_widgets [ WIDX_QUEUELINE_TYPE ] . type = WWT_FLATBTN ;
} else {
window_footpath_widgets [ WIDX_QUEUELINE_TYPE ] . type = WWT_EMPTY ;
2015-10-20 20:16:30 +02:00
}
2015-06-09 17:19:05 +02:00
// Disable queue line button if in Scenario Editor
2016-04-23 12:16:46 +02:00
if ( gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR )
2014-04-28 19:37:38 +02:00
window_footpath_widgets [ WIDX_QUEUELINE_TYPE ] . type = WWT_EMPTY ;
}
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
*/
2015-07-10 02:39:16 +02:00
static void window_footpath_paint ( rct_window * w , rct_drawpixelinfo * dpi )
2014-04-28 18:35:12 +02:00
{
2014-04-28 19:37:38 +02:00
int x , y , image , selectedPath ;
2016-05-15 17:11:34 +02:00
rct_footpath_entry * pathType ;
2014-04-28 18:35:12 +02:00
window_draw_widgets ( w , dpi ) ;
2014-04-28 19:37:38 +02:00
if ( ! ( w - > disabled_widgets & ( 1 < < WIDX_CONSTRUCT ) ) ) {
// Get construction image
2016-04-15 20:16:48 +02:00
image = ( gFootpathConstructDirection + get_current_rotation ( ) ) % 4 ;
if ( gFootpathConstructSlope = = 2 )
2014-04-28 19:37:38 +02:00
image + = 4 ;
2016-04-15 20:16:48 +02:00
else if ( gFootpathConstructSlope = = 6 )
2014-04-28 19:37:38 +02:00
image + = 8 ;
image = RCT2_ADDRESS ( 0x0098D7E0 , uint8 ) [ image ] ;
2016-04-15 20:16:48 +02:00
selectedPath = gFootpathSelectedId ;
2016-05-15 17:07:19 +02:00
pathType = get_footpath_entry ( selectedPath ) ;
2014-04-28 19:37:38 +02:00
image + = pathType - > image ;
2016-04-15 20:16:48 +02:00
if ( gFootpathSelectedType ! = SELECTED_PATH_TYPE_NORMAL )
2014-04-28 19:37:38 +02:00
image + = 51 ;
// Draw construction image
x = w - > x + ( window_footpath_widgets [ WIDX_CONSTRUCT ] . left + window_footpath_widgets [ WIDX_CONSTRUCT ] . right ) / 2 ;
y = w - > y + window_footpath_widgets [ WIDX_CONSTRUCT ] . bottom - 60 ;
2014-08-08 20:16:57 +02:00
gfx_draw_sprite ( dpi , image , x , y , 0 ) ;
2014-04-28 19:37:38 +02:00
// Draw build this... label
x = w - > x + ( window_footpath_widgets [ WIDX_CONSTRUCT ] . left + window_footpath_widgets [ WIDX_CONSTRUCT ] . right ) / 2 ;
y = w - > y + window_footpath_widgets [ WIDX_CONSTRUCT ] . bottom - 23 ;
gfx_draw_string_centred ( dpi , STR_BUILD_THIS , x , y , 0 , 0 ) ;
}
// Draw cost
x = w - > x + ( window_footpath_widgets [ WIDX_CONSTRUCT ] . left + window_footpath_widgets [ WIDX_CONSTRUCT ] . right ) / 2 ;
y = w - > y + window_footpath_widgets [ WIDX_CONSTRUCT ] . bottom - 12 ;
2014-12-16 23:03:56 +01:00
if ( _window_footpath_cost ! = MONEY32_UNDEFINED )
2016-04-23 01:51:22 +02:00
if ( ! ( gParkFlags & PARK_FLAGS_NO_MONEY ) )
2014-04-28 19:37:38 +02:00
gfx_draw_string_centred ( dpi , STR_COST_LABEL , x , y , 0 , & _window_footpath_cost ) ;
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
*/
static void window_footpath_show_footpath_types_dialog ( rct_window * w , rct_widget * widget , int showQueues )
{
int i , flags , numPathTypes , image ;
2016-05-15 17:11:34 +02:00
rct_footpath_entry * pathType ;
2014-04-29 23:25:37 +02:00
numPathTypes = 0 ;
flags = 4 ;
2015-06-09 17:19:05 +02:00
// If the game is in sandbox mode, also show paths that are normally restricted to the scenario editor, but not their queues (since these usually shouldn't have one)
2016-04-23 12:16:46 +02:00
if ( ( gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR ) | | ( gCheatsSandboxMode & & ! showQueues ) )
2014-04-29 23:25:37 +02:00
flags = 0 ;
for ( i = 0 ; i < 16 ; i + + ) {
2016-05-15 17:07:19 +02:00
pathType = get_footpath_entry ( i ) ;
2016-05-15 17:11:34 +02:00
if ( pathType = = ( rct_footpath_entry * ) - 1 )
2014-04-29 23:25:37 +02:00
continue ;
if ( pathType - > flags & flags )
continue ;
image = pathType - > image + 71 ;
if ( showQueues )
image + + ;
gDropdownItemsFormat [ numPathTypes ] = - 1 ;
gDropdownItemsArgs [ numPathTypes ] = image ;
numPathTypes + + ;
}
window_dropdown_show_image (
w - > x + widget - > left , w - > y + widget - > top , widget - > bottom - widget - > top + 1 ,
w - > colours [ 1 ] ,
0 ,
numPathTypes ,
47 ,
36 ,
gAppropriateImageDropdownItemsPerRow [ numPathTypes ]
) ;
2014-04-30 02:59:11 +02:00
}
2015-02-21 00:40:52 +01:00
/**
*
* rct2 : 0x006A8111 0x006A8135 0x006A815C 0x006A8183
*/
static void window_footpath_mousedown_direction ( int direction )
{
2015-03-22 22:18:36 +01:00
footpath_provisional_update ( ) ;
2016-04-15 20:16:48 +02:00
gFootpathConstructDirection = ( direction - get_current_rotation ( ) ) & 3 ;
2015-02-21 00:40:52 +01:00
_window_footpath_cost = MONEY32_UNDEFINED ;
window_footpath_set_enabled_and_pressed_widgets ( ) ;
}
/**
*
* rct2 : 0x006A81AA 0x006A81C5 0x006A81E0
*/
static void window_footpath_mousedown_slope ( int slope )
{
2015-03-22 22:18:36 +01:00
footpath_provisional_update ( ) ;
2016-04-15 20:16:48 +02:00
gFootpathConstructSlope = slope ;
2015-02-21 00:40:52 +01:00
_window_footpath_cost = MONEY32_UNDEFINED ;
window_footpath_set_enabled_and_pressed_widgets ( ) ;
}
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
*/
2014-04-30 14:38:27 +02:00
static void window_footpath_set_provisional_path_at_point ( int x , int y )
2014-04-30 02:59:11 +02:00
{
2015-04-16 20:09:07 +02:00
int slope , pathType , interactionType ;
2014-04-30 02:59:11 +02:00
rct_map_element * mapElement ;
2014-12-17 21:45:27 +01:00
map_invalidate_selection_rect ( ) ;
2016-05-14 01:54:13 +02:00
gMapSelectFlags & = ~ MAP_SELECT_FLAG_ENABLE_ARROW ;
2014-04-30 02:59:11 +02:00
2015-05-27 19:05:57 +02:00
rct_xy16 mapCoord = { 0 } ;
get_map_coordinates_from_pos ( x , y , VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN , & mapCoord . x , & mapCoord . y , & interactionType , & mapElement , NULL ) ;
x = mapCoord . x ;
y = mapCoord . y ;
2014-04-30 02:59:11 +02:00
2015-04-16 20:09:07 +02:00
if ( interactionType = = VIEWPORT_INTERACTION_ITEM_NONE ) {
2016-05-14 01:54:13 +02:00
gMapSelectFlags & = ~ MAP_SELECT_FLAG_ENABLE ;
2015-03-22 22:18:36 +01:00
footpath_provisional_update ( ) ;
2014-04-30 02:59:11 +02:00
} else {
// Check for change
2016-04-15 20:16:48 +02:00
if (
( gFootpathProvisionalFlags & PROVISIONAL_PATH_FLAG_1 ) & &
gFootpathProvisionalPosition . x = = x & &
gFootpathProvisionalPosition . y = = y & &
gFootpathProvisionalPosition . z = = mapElement - > base_height
) {
2014-04-30 02:59:11 +02:00
return ;
2016-04-15 20:16:48 +02:00
}
2014-04-30 02:59:11 +02:00
// Set map selection
2016-05-14 01:54:13 +02:00
gMapSelectFlags | = MAP_SELECT_FLAG_ENABLE ;
gMapSelectType = MAP_SELECT_TYPE_FULL ;
gMapSelectPositionA . x = x ;
gMapSelectPositionA . y = y ;
gMapSelectPositionB . x = x ;
gMapSelectPositionB . y = y ;
2014-04-30 02:59:11 +02:00
2015-03-22 22:18:36 +01:00
footpath_provisional_update ( ) ;
2014-04-30 02:59:11 +02:00
// Set provisional path
2014-04-30 14:38:27 +02:00
slope = RCT2_ADDRESS ( 0x0098D8B4 , uint8 ) [ mapElement - > properties . surface . slope & 0x1F ] ;
2015-04-16 20:09:07 +02:00
if ( interactionType = = VIEWPORT_INTERACTION_ITEM_FOOTPATH )
2014-04-30 14:38:27 +02:00
slope = mapElement - > properties . surface . slope & 7 ;
2016-04-15 20:16:48 +02:00
pathType = ( gFootpathSelectedType < < 7 ) + ( gFootpathSelectedId & 0xFF ) ;
2014-04-30 02:59:11 +02:00
2014-12-16 23:03:56 +01:00
_window_footpath_cost = footpath_provisional_set ( pathType , x , y , mapElement - > base_height , slope ) ;
window_invalidate_by_class ( WC_FOOTPATH ) ;
2014-04-30 02:59:11 +02:00
}
}
2015-03-23 22:28:44 +01:00
/**
*
* rct2 : 0x006A8388
*/
static void window_footpath_set_selection_start_bridge_at_point ( int screenX , int screenY )
{
int x , y , direction ;
rct_map_element * mapElement ;
map_invalidate_selection_rect ( ) ;
2016-05-14 01:54:13 +02:00
gMapSelectFlags & = ~ MAP_SELECT_FLAG_ENABLE ;
gMapSelectFlags & = ~ MAP_SELECT_FLAG_ENABLE_ARROW ;
2015-03-23 22:28:44 +01:00
2015-03-30 17:28:36 +02:00
footpath_bridge_get_info_from_pos ( screenX , screenY , & x , & y , & direction , & mapElement ) ;
2015-06-03 19:02:41 +02:00
if ( x = = ( sint16 ) 0x8000 )
2015-03-23 22:28:44 +01:00
return ;
2016-05-14 01:54:13 +02:00
gMapSelectFlags | = MAP_SELECT_FLAG_ENABLE ;
gMapSelectFlags | = MAP_SELECT_FLAG_ENABLE_ARROW ;
gMapSelectType = MAP_SELECT_TYPE_FULL ;
gMapSelectPositionA . x = x ;
gMapSelectPositionB . x = x ;
gMapSelectPositionA . y = y ;
gMapSelectPositionB . y = y ;
2015-03-23 22:28:44 +01:00
2016-05-14 01:54:13 +02:00
gMapSelectArrowDirection = direction ;
gMapSelectArrowPosition . x = x ;
gMapSelectArrowPosition . y = y ;
2015-03-23 22:28:44 +01:00
int z = mapElement - > base_height ;
2015-03-24 15:12:09 +01:00
if ( map_element_get_type ( mapElement ) = = MAP_ELEMENT_TYPE_SURFACE ) {
2015-03-23 22:28:44 +01:00
uint8 slope = mapElement - > properties . surface . slope ;
if ( slope & 0xf )
z + = 2 ; // Add 2 for a slope
if ( slope & 0x10 )
z + = 2 ; // Add another 2 for a steep slope
}
2016-05-14 01:54:13 +02:00
gMapSelectArrowPosition . z = z < < 3 ;
2015-03-23 22:28:44 +01:00
map_invalidate_selection_rect ( ) ;
}
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
*/
2014-04-30 14:38:27 +02:00
static void window_footpath_place_path_at_point ( int x , int y )
2014-04-30 02:59:11 +02:00
{
2015-04-16 20:09:07 +02:00
int interactionType , presentType , selectedType , z , cost ;
2014-04-30 02:59:11 +02:00
rct_map_element * mapElement ;
2016-04-15 20:16:48 +02:00
if ( _footpathErrorOccured )
2014-04-30 02:59:11 +02:00
return ;
2015-03-22 22:18:36 +01:00
footpath_provisional_update ( ) ;
2014-04-30 02:59:11 +02:00
2015-05-27 19:05:57 +02:00
rct_xy16 mapCoord = { 0 } ;
get_map_coordinates_from_pos ( x , y , VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN , & mapCoord . x , & mapCoord . y , & interactionType , & mapElement , NULL ) ;
x = mapCoord . x ;
y = mapCoord . y ;
2015-04-16 20:09:07 +02:00
if ( interactionType = = VIEWPORT_INTERACTION_ITEM_NONE )
2014-04-30 02:59:11 +02:00
return ;
// Set path
2014-05-02 04:06:30 +02:00
presentType = RCT2_ADDRESS ( 0x0098D8B4 , uint8 ) [ mapElement - > properties . path . type & 0x1F ] ;
2015-04-16 20:09:07 +02:00
if ( interactionType = = VIEWPORT_INTERACTION_ITEM_FOOTPATH )
2014-05-02 04:06:30 +02:00
presentType = mapElement - > properties . path . type & 7 ;
z = mapElement - > base_height ;
2016-04-15 20:16:48 +02:00
selectedType = ( gFootpathSelectedType < < 7 ) + ( gFootpathSelectedId & 0xFF ) ;
2014-04-30 02:59:11 +02:00
2014-04-30 14:38:27 +02:00
// Try and place path
2016-04-15 18:54:46 +02:00
gGameCommandErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE ;
2014-12-18 23:31:05 +01:00
cost = footpath_place ( selectedType , x , y , z , presentType , GAME_COMMAND_FLAG_APPLY ) ;
2014-04-30 14:38:27 +02:00
2014-05-23 13:15:08 +02:00
if ( cost = = MONEY32_UNDEFINED ) {
2016-04-15 20:16:48 +02:00
_footpathErrorOccured = true ;
2016-05-16 20:05:37 +02:00
} else if ( gFootpathPrice ! = 0 ) {
2015-08-17 00:25:17 +02:00
// bp = RCT2_ADDRESS_COMMAND_MAP_Z
// dx = RCT2_ADDRESS_COMMAND_MAP_Y
// cx = RCT2_ADDRESS_COMMAND_MAP_X
2016-04-24 18:53:39 +02:00
audio_play_sound_at_location ( SOUND_PLACE_ITEM , gCommandPosition . x , gCommandPosition . y , gCommandPosition . z ) ;
2014-04-30 02:59:11 +02: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 : 0x006A840F
*/
static void window_footpath_start_bridge_at_point ( int screenX , int screenY )
{
int x , y , z , direction ;
rct_map_element * mapElement ;
2015-03-30 17:28:36 +02:00
footpath_bridge_get_info_from_pos ( screenX , screenY , & x , & y , & direction , & mapElement ) ;
2015-06-03 19:02:41 +02:00
if ( x = = ( sint16 ) 0x8000 )
2014-12-17 21:45:27 +01:00
return ;
2015-01-22 01:19:05 +01:00
if ( map_element_get_type ( mapElement ) = = MAP_ELEMENT_TYPE_SURFACE ) {
2015-03-23 00:34:00 +01: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.
uint8_t slope = mapElement - > properties . surface . slope ;
2014-12-17 21:45:27 +01:00
z = mapElement - > base_height ;
2015-03-23 00:34:00 +01:00
if ( slope & 0x10 ) {
// Steep diagonal slope
z + = 4 ;
2015-03-23 15:32:03 +01:00
} else if ( slope & 0x0f ) {
2015-03-23 00:34:00 +01:00
// Normal slope
2014-12-17 21:45:27 +01:00
z + = 2 ;
2015-03-23 00:34:00 +01:00
}
2014-12-17 21:45:27 +01:00
} else {
z = mapElement - > base_height ;
2015-01-22 01:19:05 +01:00
if ( map_element_get_type ( mapElement ) = = MAP_ELEMENT_TYPE_PATH ) {
2014-12-17 21:45:27 +01:00
if ( mapElement - > properties . path . type & 4 ) {
if ( direction = = ( mapElement - > properties . path . type & 3 ) )
z + = 2 ;
}
}
}
2015-10-20 20:16:30 +02:00
2014-12-17 21:45:27 +01:00
tool_cancel ( ) ;
2016-04-15 20:16:48 +02:00
gFootpathConstructFromPosition . x = x ;
gFootpathConstructFromPosition . y = y ;
gFootpathConstructFromPosition . z = z * 8 ;
gFootpathConstructDirection = direction ;
gFootpathProvisionalFlags = 0 ;
2014-12-17 21:45:27 +01:00
_window_footpath_provisional_path_arrow_timer = 0 ;
2016-04-15 20:16:48 +02:00
gFootpathConstructSlope = 0 ;
gFootpathConstructionMode = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL ;
gFootpathConstructValidDirections = 255 ;
2014-12-17 21:45:27 +01:00
window_footpath_set_enabled_and_pressed_widgets ( ) ;
}
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 ( )
{
2015-03-23 02:59:46 +01:00
_window_footpath_cost = MONEY32_UNDEFINED ;
footpath_provisional_update ( ) ;
int type , x , y , z , slope ;
footpath_get_next_path_info ( & type , & x , & y , & z , & slope ) ;
2015-03-23 15:32:03 +01:00
// Try to place the path at the desired location
2016-04-15 18:54:46 +02:00
gGameCommandErrorTitle = 0x498 ;
2015-03-23 02:59:46 +01:00
money32 cost = footpath_place ( type , x , y , z , slope , 0 ) ;
if ( cost ! = MONEY32_UNDEFINED ) {
2015-03-23 15:32:03 +01:00
// It is possible, let's remove walls between the old and new piece of path
2016-04-15 20:16:48 +02:00
uint8 direction = gFootpathConstructDirection ;
2015-03-23 02:59:46 +01:00
map_remove_intersecting_walls ( x , y , z , z + 4 + ( slope & 0xf ? 2 : 0 ) , direction ^ 2 ) ;
map_remove_intersecting_walls (
x - TileDirectionDelta [ direction ] . x ,
y - TileDirectionDelta [ direction ] . y ,
2015-03-23 15:32:03 +01:00
z , z + 4 , direction
) ;
2015-03-23 02:59:46 +01:00
}
2015-03-23 15:32:03 +01:00
// Actually place the path now
2016-04-15 18:54:46 +02:00
gGameCommandErrorTitle = 0x498 ;
2015-03-23 02:59:46 +01:00
cost = footpath_place ( type , x , y , z , slope , GAME_COMMAND_FLAG_APPLY ) ;
2015-03-23 15:32:03 +01:00
2015-03-23 02:59:46 +01:00
if ( cost ! = MONEY32_UNDEFINED ) {
2015-11-18 01:03:15 +01:00
audio_play_sound_at_location (
2015-03-23 15:32:03 +01:00
SOUND_PLACE_ITEM ,
2016-04-15 20:16:48 +02:00
gFootpathConstructFromPosition . x ,
gFootpathConstructFromPosition . y ,
gFootpathConstructFromPosition . z
2015-03-23 15:32:03 +01:00
) ;
2015-03-23 02:59:46 +01:00
2016-04-15 20:16:48 +02:00
if ( gFootpathConstructSlope = = 0 ) {
gFootpathConstructValidDirections = 0xFF ;
2015-03-23 02:59:46 +01:00
} else {
2016-04-15 20:16:48 +02:00
gFootpathConstructValidDirections = gFootpathConstructDirection ;
2015-03-23 02:59:46 +01:00
}
2016-05-17 21:51:11 +02:00
if ( gFootpathGroundFlags & ELEMENT_IS_UNDERGROUND )
2015-03-23 02:59:46 +01:00
viewport_set_visibility ( 1 ) ;
2015-03-23 12:47:16 +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.
2016-04-15 20:16:48 +02:00
if ( gFootpathConstructSlope = = 2 )
2015-03-23 02:59:46 +01:00
z + = 2 ;
2016-04-15 20:16:48 +02:00
gFootpathConstructFromPosition . x = x ;
gFootpathConstructFromPosition . y = y ;
gFootpathConstructFromPosition . z = z < < 3 ;
2015-03-23 02:59:46 +01:00
}
window_footpath_set_enabled_and_pressed_widgets ( ) ;
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
*/
2015-01-15 00:38:48 +01:00
static void footpath_remove_map_element ( rct_map_element * mapElement )
2014-04-30 20:35:37 +02:00
{
2014-12-17 21:45:27 +01:00
int x , y , z ;
2014-04-30 20:35:37 +02:00
2014-12-17 21:45:27 +01:00
z = mapElement - > base_height ;
2014-04-30 20:35:37 +02:00
int pathType = mapElement - > properties . path . type ;
if ( pathType & 4 ) {
pathType & = 3 ;
pathType ^ = 2 ;
2016-04-15 20:16:48 +02:00
if ( pathType = = gFootpathConstructDirection )
2014-12-17 21:45:27 +01:00
z + = 2 ;
2014-04-30 20:35:37 +02:00
}
2014-12-17 21:45:27 +01:00
2014-04-30 20:35:37 +02:00
// Find a connected edge
2016-04-15 20:16:48 +02:00
int edge = gFootpathConstructDirection ^ 2 ;
2014-04-30 20:35:37 +02:00
if ( ! ( mapElement - > properties . path . edges & ( 1 < < edge ) ) ) {
2014-12-16 23:03:56 +01:00
edge = ( edge + 1 ) & 3 ;
2014-04-30 20:35:37 +02:00
if ( ! ( mapElement - > properties . path . edges & ( 1 < < edge ) ) ) {
2014-12-16 23:03:56 +01:00
edge = ( edge + 2 ) & 3 ;
2014-04-30 20:35:37 +02:00
if ( ! ( mapElement - > properties . path . edges & ( 1 < < edge ) ) ) {
2014-12-16 23:03:56 +01:00
edge = ( edge - 1 ) & 3 ;
2014-04-30 20:35:37 +02:00
if ( ! ( mapElement - > properties . path . edges & ( 1 < < edge ) ) )
edge ^ = 2 ;
}
}
}
2014-12-17 21:45:27 +01:00
2014-04-30 20:35:37 +02:00
// Remove path
2016-04-15 18:54:46 +02:00
gGameCommandErrorTitle = STR_CANT_REMOVE_FOOTPATH_FROM_HERE ;
2014-11-15 19:22:06 +01:00
footpath_remove (
2016-04-15 20:16:48 +02:00
gFootpathConstructFromPosition . x ,
gFootpathConstructFromPosition . y ,
2014-11-15 19:22:06 +01:00
mapElement - > base_height ,
1
) ;
2014-04-30 20:35:37 +02:00
// Move selection
edge ^ = 2 ;
2016-04-15 20:16:48 +02:00
x = gFootpathConstructFromPosition . x - TileDirectionDelta [ edge ] . x ;
y = gFootpathConstructFromPosition . y - TileDirectionDelta [ edge ] . y ;
gFootpathConstructFromPosition . x = x ;
gFootpathConstructFromPosition . y = y ;
gFootpathConstructFromPosition . z = z < < 3 ;
gFootpathConstructDirection = edge ;
gFootpathConstructValidDirections = 255 ;
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
*/
static rct_map_element * footpath_get_map_element_to_remove ( )
{
rct_map_element * mapElement ;
int x , y , z , zLow ;
2016-04-15 20:16:48 +02:00
x = gFootpathConstructFromPosition . x / 32 ;
y = gFootpathConstructFromPosition . y / 32 ;
2014-12-17 21:45:27 +01:00
if ( x > = 256 | | y > = 256 )
return NULL ;
2016-04-15 20:16:48 +02:00
z = ( gFootpathConstructFromPosition . z > > 3 ) & 0xFF ;
2014-12-17 21:45:27 +01:00
zLow = z - 2 ;
2015-01-22 01:19:05 +01:00
mapElement = map_get_first_element_at ( x , y ) ;
2014-12-17 21:45:27 +01:00
do {
2015-01-22 01:19:05 +01:00
if ( map_element_get_type ( mapElement ) = = MAP_ELEMENT_TYPE_PATH ) {
2014-12-17 21:45:27 +01:00
if ( mapElement - > base_height = = z ) {
if ( mapElement - > properties . path . type & 4 )
2016-04-15 20:16:48 +02:00
if ( ( ( mapElement - > properties . path . type & 3 ) ^ 2 ) ! = gFootpathConstructDirection )
2014-12-17 21:45:27 +01:00
continue ;
return mapElement ;
} else if ( mapElement - > base_height = = zLow ) {
if ( ! ( mapElement - > properties . path . type & 4 ) )
2016-04-15 20:16:48 +02:00
if ( ( mapElement - > properties . path . type & 3 ) = = gFootpathConstructDirection )
2014-12-17 21:45:27 +01:00
continue ;
2015-10-20 20:16:30 +02:00
2014-12-17 21:45:27 +01:00
return mapElement ;
}
}
2015-01-22 01:19:05 +01:00
} while ( ! map_element_is_last_for_tile ( mapElement + + ) ) ;
2014-12-17 21:45:27 +01:00
return NULL ;
}
/**
2015-10-20 20:16:30 +02:00
*
2014-12-17 21:45:27 +01:00
* rct2 : 0x006A7863
*/
static void window_footpath_remove ( )
{
rct_map_element * mapElement ;
_window_footpath_cost = MONEY32_UNDEFINED ;
2015-03-22 22:18:36 +01:00
footpath_provisional_update ( ) ;
2014-12-17 21:45:27 +01:00
mapElement = footpath_get_map_element_to_remove ( ) ;
if ( mapElement ! = NULL )
footpath_remove_map_element ( mapElement ) ;
window_footpath_set_enabled_and_pressed_widgets ( ) ;
}
/**
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 ( )
{
rct_window * w ;
uint64 pressedWidgets , disabledWidgets ;
int currentRotation , direction , slope ;
w = window_find_by_class ( WC_FOOTPATH ) ;
if ( w = = NULL )
return ;
2016-04-15 20:16:48 +02:00
if ( gFootpathConstructionMode = = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL ) {
2014-12-17 21:45:27 +01:00
map_invalidate_map_selection_tiles ( ) ;
2016-05-14 01:54:13 +02:00
gMapSelectFlags | = MAP_SELECT_FLAG_ENABLE_CONSTRUCT ;
gMapSelectFlags | = MAP_SELECT_FLAG_GREEN ;
2014-12-17 21:45:27 +01:00
2016-04-15 20:16:48 +02:00
direction = gFootpathConstructDirection ;
gMapSelectionTiles [ 0 ] . x = gFootpathConstructFromPosition . x + TileDirectionDelta [ direction ] . x ;
gMapSelectionTiles [ 0 ] . y = gFootpathConstructFromPosition . y + TileDirectionDelta [ direction ] . y ;
2014-12-17 21:45:27 +01:00
gMapSelectionTiles [ 1 ] . x = - 1 ;
map_invalidate_map_selection_tiles ( ) ;
}
pressedWidgets = w - > pressed_widgets & 0xFFFF887F ;
disabledWidgets = 0 ;
2015-10-30 11:00:35 +01:00
currentRotation = get_current_rotation ( ) ;
2016-04-15 20:16:48 +02:00
if ( gFootpathConstructionMode > = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL ) {
2014-12-17 21:45:27 +01:00
// Set pressed directional widget
2016-04-15 20:16:48 +02:00
direction = ( gFootpathConstructDirection + currentRotation ) & 3 ;
2014-12-17 21:45:27 +01:00
pressedWidgets | = ( 1LL < < ( WIDX_DIRECTION_NW + direction ) ) ;
// Set pressed slope widget
2016-04-15 20:16:48 +02:00
slope = gFootpathConstructSlope ;
2014-12-17 21:45:27 +01:00
if ( slope = = 6 )
pressedWidgets | = ( 1 < < WIDX_SLOPEDOWN ) ;
else if ( slope = = 0 )
pressedWidgets | = ( 1 < < WIDX_LEVEL ) ;
else
pressedWidgets | = ( 1 < < WIDX_SLOPEUP ) ;
// Enable / disable directional widgets
2016-04-15 20:16:48 +02:00
direction = gFootpathConstructValidDirections ;
2014-12-17 21:45:27 +01:00
if ( direction ! = 255 ) {
disabledWidgets | =
( 1 < < WIDX_DIRECTION_NW ) |
( 1 < < WIDX_DIRECTION_NE ) |
( 1 < < WIDX_DIRECTION_SW ) |
( 1 < < WIDX_DIRECTION_SE ) ;
direction = ( direction + currentRotation ) & 3 ;
disabledWidgets & = ~ ( 1 < < ( WIDX_DIRECTION_NW + direction ) ) ;
}
} else {
// Disable all bridge mode widgets
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 ) ;
}
w - > pressed_widgets = pressedWidgets ;
w - > disabled_widgets = disabledWidgets ;
window_invalidate ( w ) ;
}
/**
2015-10-20 20:16:30 +02:00
*
2014-12-17 21:45:27 +01:00
* rct2 : 0x006A7B20
*/
static void footpath_get_next_path_info ( int * type , int * x , int * y , int * z , int * slope )
{
int direction ;
2016-04-15 20:16:48 +02:00
direction = gFootpathConstructDirection ;
* x = gFootpathConstructFromPosition . x + TileDirectionDelta [ direction ] . x ;
* y = gFootpathConstructFromPosition . y + TileDirectionDelta [ direction ] . y ;
* z = gFootpathConstructFromPosition . z / 8 ;
* type = ( gFootpathSelectedType < < 7 ) + ( gFootpathSelectedId & 0xFF ) ;
2014-12-17 21:45:27 +01:00
* slope = 0 ;
2016-04-15 20:16:48 +02:00
if ( gFootpathConstructSlope ! = 0 ) {
* slope = gFootpathConstructDirection | 4 ;
if ( gFootpathConstructSlope ! = 2 ) {
2014-12-17 21:45:27 +01:00
* z - = 2 ;
* slope ^ = 2 ;
}
}
2015-06-09 17:19:05 +02:00
}
2016-05-15 20:08:02 +02:00
static void footpath_select_default ( )
{
// Select first available footpath
gFootpathSelectedId = 0 ;
for ( int i = 0 ; i < object_entry_group_counts [ OBJECT_TYPE_PATHS ] ; i + + ) {
rct_footpath_entry * pathEntry = get_footpath_entry ( i ) ;
if ( pathEntry ! = ( rct_footpath_entry * ) - 1 ) {
gFootpathSelectedId = i ;
// Prioritise non-restricted path
if ( ! ( pathEntry - > flags & 4 ) ) {
break ;
}
}
}
}