#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers /***************************************************************************** * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. * * 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 * * 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. * * A full copy of the GNU General Public License can be found in licence.txt *****************************************************************************/ #pragma endregion #include "../audio/audio.h" #include "../cheats.h" #include "../config/Config.h" #include "../game.h" #include "../input.h" #include "../interface/themes.h" #include "../interface/viewport.h" #include "../interface/widget.h" #include "../interface/window.h" #include "../localisation/date.h" #include "../localisation/localisation.h" #include "../network/network.h" #include "../object/ObjectManager.h" #include "../object/ObjectRepository.h" #include "../peep/staff.h" #include "../rct1.h" #include "../rct2.h" #include "../ride/ride.h" #include "../ride/ride_data.h" #include "../ride/RideGroupManager.h" #include "../ride/track.h" #include "../ride/track_data.h" #include "../ride/track_design.h" #include "../sprites.h" #include "../windows/error.h" #include "../world/map.h" #include "../world/sprite.h" #include "dropdown.h" enum { WINDOW_RIDE_PAGE_MAIN, WINDOW_RIDE_PAGE_VEHICLE, WINDOW_RIDE_PAGE_OPERATING, WINDOW_RIDE_PAGE_MAINTENANCE, WINDOW_RIDE_PAGE_COLOUR, WINDOW_RIDE_PAGE_MUSIC, WINDOW_RIDE_PAGE_MEASUREMENTS, WINDOW_RIDE_PAGE_GRAPHS, WINDOW_RIDE_PAGE_INCOME, WINDOW_RIDE_PAGE_CUSTOMER, WINDOW_RIDE_PAGE_COUNT }; #pragma region Widgets enum { WIDX_BACKGROUND, WIDX_TITLE, WIDX_CLOSE, WIDX_PAGE_BACKGROUND, WIDX_TAB_1, WIDX_TAB_2, WIDX_TAB_3, WIDX_TAB_4, WIDX_TAB_5, WIDX_TAB_6, WIDX_TAB_7, WIDX_TAB_8, WIDX_TAB_9, WIDX_TAB_10, WIDX_VIEWPORT = 14, WIDX_VIEW, WIDX_VIEW_DROPDOWN, WIDX_STATUS, WIDX_OPEN, WIDX_CONSTRUCTION, WIDX_RENAME, WIDX_LOCATE, WIDX_DEMOLISH, WIDX_CLOSE_LIGHT, WIDX_TEST_LIGHT, WIDX_OPEN_LIGHT, WIDX_RIDE_TYPE, WIDX_RIDE_TYPE_INCREASE, WIDX_RIDE_TYPE_DECREASE, WIDX_RIDE_TYPE_APPLY, WIDX_VEHICLE_TYPE = 14, WIDX_VEHICLE_TYPE_DROPDOWN, WIDX_VEHICLE_TRAINS_PREVIEW, WIDX_VEHICLE_TRAINS, WIDX_VEHICLE_TRAINS_INCREASE, WIDX_VEHICLE_TRAINS_DECREASE, WIDX_VEHICLE_CARS_PER_TRAIN, WIDX_VEHICLE_CARS_PER_TRAIN_INCREASE, WIDX_VEHICLE_CARS_PER_TRAIN_DECREASE, WIDX_MODE_TWEAK = 14, WIDX_MODE_TWEAK_INCREASE, WIDX_MODE_TWEAK_DECREASE, WIDX_LIFT_HILL_SPEED, WIDX_LIFT_HILL_SPEED_INCREASE, WIDX_LIFT_HILL_SPEED_DECREASE, WIDX_LOAD_CHECKBOX, WIDX_LEAVE_WHEN_ANOTHER_ARRIVES_CHECKBOX, WIDX_MINIMUM_LENGTH_CHECKBOX, WIDX_MINIMUM_LENGTH, WIDX_MINIMUM_LENGTH_INCREASE, WIDX_MINIMUM_LENGTH_DECREASE, WIDX_MAXIMUM_LENGTH_CHECKBOX, WIDX_MAXIMUM_LENGTH, WIDX_MAXIMUM_LENGTH_INCREASE, WIDX_MAXIMUM_LENGTH_DECREASE, WIDX_SYNCHRONISE_WITH_ADJACENT_STATIONS_CHECKBOX, WIDX_MODE_TWEAK_LABEL, WIDX_LIFT_HILL_SPEED_LABEL, WIDX_MODE, WIDX_MODE_DROPDOWN, WIDX_LOAD, WIDX_LOAD_DROPDOWN, WIDX_OPERATE_NUMBER_OF_CIRCUITS_LABEL, WIDX_OPERATE_NUMBER_OF_CIRCUITS, WIDX_OPERATE_NUMBER_OF_CIRCUITS_INCREASE, WIDX_OPERATE_NUMBER_OF_CIRCUITS_DECREASE, WIDX_INSPECTION_INTERVAL = 14, WIDX_INSPECTION_INTERVAL_DROPDOWN, WIDX_LOCATE_MECHANIC, WIDX_FORCE_BREAKDOWN, WIDX_TRACK_PREVIEW = 14, WIDX_TRACK_COLOUR_SCHEME, WIDX_TRACK_COLOUR_SCHEME_DROPDOWN, WIDX_TRACK_MAIN_COLOUR, WIDX_TRACK_ADDITIONAL_COLOUR, WIDX_TRACK_SUPPORT_COLOUR, WIDX_MAZE_STYLE, WIDX_MAZE_STYLE_DROPDOWN, WIDX_PAINT_INDIVIDUAL_AREA, WIDX_ENTRANCE_PREVIEW, WIDX_ENTRANCE_STYLE, WIDX_ENTRANCE_STYLE_DROPDOWN, WIDX_VEHICLE_PREVIEW, WIDX_VEHICLE_COLOUR_SCHEME, WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN, WIDX_VEHICLE_COLOUR_INDEX, WIDX_VEHICLE_COLOUR_INDEX_DROPDOWN, WIDX_VEHICLE_MAIN_COLOUR, WIDX_VEHICLE_ADDITIONAL_COLOUR_1, WIDX_VEHICLE_ADDITIONAL_COLOUR_2, WIDX_PLAY_MUSIC = 14, WIDX_MUSIC, WIDX_MUSIC_DROPDOWN, WIDX_SAVE_TRACK_DESIGN = 14, WIDX_SELECT_NEARBY_SCENERY, WIDX_RESET_SELECTION, WIDX_SAVE_DESIGN, WIDX_CANCEL_DESIGN, WIDX_GRAPH = 14, WIDX_GRAPH_VELOCITY, WIDX_GRAPH_ALTITUDE, WIDX_GRAPH_VERTICAL, WIDX_GRAPH_LATERAL, WIDX_PRIMARY_PRICE_LABEL = 14, WIDX_PRIMARY_PRICE, WIDX_PRIMARY_PRICE_INCREASE, WIDX_PRIMARY_PRICE_DECREASE, WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK, WIDX_SECONDARY_PRICE_LABEL, WIDX_SECONDARY_PRICE, WIDX_SECONDARY_PRICE_INCREASE, WIDX_SECONDARY_PRICE_DECREASE, WIDX_SECONDARY_PRICE_SAME_THROUGHOUT_PARK, WIDX_SHOW_GUESTS_THOUGHTS = 14, WIDX_SHOW_GUESTS_ON_RIDE, WIDX_SHOW_GUESTS_QUEUING }; #define RCT1_LIGHT_OFFSET 4 #define MAIN_RIDE_WIDGETS \ { WWT_FRAME, 0, 0, 315, 0, 206, 0xFFFFFFFF, STR_NONE }, \ { WWT_CAPTION, 0, 1, 314, 1, 14, STR_RIDE_WINDOW_TITLE, STR_WINDOW_TITLE_TIP }, \ { WWT_CLOSEBOX, 0, 303, 313, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, \ { WWT_RESIZE, 1, 0, 315, 43, 179, 0xFFFFFFFF, STR_NONE }, \ { WWT_TAB, 1, 3, 33, 17, 43, 0x20000000 | SPR_TAB, STR_VIEW_OF_RIDE_ATTRACTION_TIP }, \ { WWT_TAB, 1, 34, 64, 17, 46, 0x20000000 | SPR_TAB, STR_VEHICLE_DETAILS_AND_OPTIONS_TIP }, \ { WWT_TAB, 1, 65, 95, 17, 43, 0x20000000 | SPR_TAB, STR_OPERATING_OPTIONS_TIP }, \ { WWT_TAB, 1, 96, 126, 17, 43, 0x20000000 | SPR_TAB, STR_MAINTENANCE_OPTIONS_TIP }, \ { WWT_TAB, 1, 127, 157, 17, 43, 0x20000000 | SPR_TAB, STR_COLOUR_SCHEME_OPTIONS_TIP }, \ { WWT_TAB, 1, 158, 188, 17, 43, 0x20000000 | SPR_TAB, STR_SOUND_AND_MUSIC_OPTIONS_TIP }, \ { WWT_TAB, 1, 189, 219, 17, 43, 0x20000000 | SPR_TAB, STR_MEASUREMENTS_AND_TEST_DATA_TIP }, \ { WWT_TAB, 1, 220, 250, 17, 43, 0x20000000 | SPR_TAB, STR_GRAPHS_TIP }, \ { WWT_TAB, 1, 251, 281, 17, 43, 0x20000000 | SPR_TAB, STR_INCOME_AND_COSTS_TIP }, \ { WWT_TAB, 1, 282, 312, 17, 43, 0x20000000 | SPR_TAB, STR_CUSTOMER_INFORMATION_TIP } // 0x009ADC34 static rct_widget window_ride_main_widgets[] = { MAIN_RIDE_WIDGETS, { WWT_VIEWPORT, 1, 3, 290, 60, 166, 0xFFFFFFFE, STR_NONE }, { WWT_DROPDOWN, 1, 35, 256, 46, 57, 0xFFFFFFFF, STR_VIEW_SELECTION }, { WWT_DROPDOWN_BUTTON, 1, 245, 255, 47, 56, STR_DROPDOWN_GLYPH, STR_VIEW_SELECTION }, { WWT_12, 1, 3, 290, 167, 177, 0xFFFFFFFF, STR_NONE }, { WWT_FLATBTN, 1, 291, 314, 46, 69, 0xFFFFFFFF, STR_OPEN_CLOSE_OR_TEST_RIDE }, { WWT_FLATBTN, 1, 291, 314, 70, 93, SPR_CONSTRUCTION, STR_CONSTRUCTION }, { WWT_FLATBTN, 1, 291, 314, 94, 117, SPR_RENAME, STR_NAME_RIDE_TIP }, { WWT_FLATBTN, 1, 291, 314, 118, 141, SPR_LOCATE, STR_LOCATE_SUBJECT_TIP }, { WWT_FLATBTN, 1, 291, 314, 142, 165, SPR_DEMOLISH, STR_DEMOLISH_RIDE_TIP }, { WWT_IMGBTN, 1, 296, 309, 48, 61, SPR_G2_RCT1_CLOSE_BUTTON_0, STR_CLOSE_RIDE_TIP }, { WWT_IMGBTN, 1, 296, 309, 62, 75, SPR_G2_RCT1_TEST_BUTTON_0, STR_TEST_RIDE_TIP }, { WWT_IMGBTN, 1, 296, 309, 76, 89, SPR_G2_RCT1_OPEN_BUTTON_0, STR_OPEN_RIDE_TIP }, // Ride type spinner + apply button { WWT_SPINNER, 1, 3, 253, 180, 191, STR_ARG_6_STRINGID, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 242, 252, 181, 185, STR_NUMERIC_UP, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 242, 252, 186, 190, STR_NUMERIC_DOWN, STR_NONE }, { WWT_CLOSEBOX, 1, 260, 307, 180, 191, STR_APPLY, STR_NONE }, { WIDGETS_END }, }; // 0x009ADDA8 static rct_widget window_ride_vehicle_widgets[] = { MAIN_RIDE_WIDGETS, { WWT_DROPDOWN, 1, 7, 308, 50, 61, 0xFFFFFFFF, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 51, 60, STR_DROPDOWN_GLYPH, STR_NONE }, { WWT_SCROLL, 1, 7, 308, 141, 183, 0, STR_NONE }, { WWT_SPINNER, 1, 7, 151, 190, 201, STR_RIDE_VEHICLE_COUNT, STR_MAX_VEHICLES_TIP }, { WWT_DROPDOWN_BUTTON, 1, 140, 150, 191, 195, STR_NUMERIC_UP, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 140, 150, 196, 200, STR_NUMERIC_DOWN, STR_NONE }, { WWT_SPINNER, 1, 164, 308, 190, 201, STR_1_CAR_PER_TRAIN, STR_MAX_CARS_PER_TRAIN_TIP }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 191, 195, STR_NUMERIC_UP, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 196, 200, STR_NUMERIC_DOWN, STR_NONE }, { WIDGETS_END }, }; // 0x009ADEFC static rct_widget window_ride_operating_widgets[] = { MAIN_RIDE_WIDGETS, { WWT_SPINNER, 1, 157, 308, 61, 72, STR_ARG_18_STRINGID, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 62, 66, STR_NUMERIC_UP, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 67, 71, STR_NUMERIC_DOWN, STR_NONE }, { WWT_SPINNER, 1, 157, 308, 75, 86, STR_LIFT_HILL_CHAIN_SPEED_VALUE, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 76, 80, STR_NUMERIC_UP, STR_SELECT_LIFT_HILL_CHAIN_SPEED_TIP }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 81, 85, STR_NUMERIC_DOWN, STR_SELECT_LIFT_HILL_CHAIN_SPEED_TIP }, { WWT_CHECKBOX, 1, 7, 86, 109, 120, STR_WAIT_FOR, STR_WAIT_FOR_PASSENGERS_BEFORE_DEPARTING_TIP }, { WWT_CHECKBOX, 1, 7, 308, 124, 135, 0xFFFFFFFF, STR_NONE }, { WWT_CHECKBOX, 1, 7, 156, 139, 150, STR_MINIMUM_WAITING_TIME, STR_MINIMUM_LENGTH_BEFORE_DEPARTING_TIP }, { WWT_SPINNER, 1, 157, 308, 139, 150, STR_ARG_10_STRINGID, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 140, 144, STR_NUMERIC_UP, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 145, 149, STR_NUMERIC_DOWN, STR_NONE }, { WWT_CHECKBOX, 1, 7, 156, 154, 165, STR_MAXIMUM_WAITING_TIME, STR_MAXIMUM_LENGTH_BEFORE_DEPARTING_TIP }, { WWT_SPINNER, 1, 157, 308, 154, 165, STR_ARG_14_STRINGID, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 155, 159, STR_NUMERIC_UP, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 160, 164, STR_NUMERIC_DOWN, STR_NONE }, { WWT_CHECKBOX, 1, 7, 308, 169, 180, STR_SYNCHRONISE_WITH_ADJACENT_STATIONS, STR_SYNCHRONISE_WITH_ADJACENT_STATIONS_TIP }, { WWT_24, 1, 7, 149, 61, 72, 0xFFFFFFFF, STR_NONE }, { WWT_24, 1, 7, 149, 75, 86, STR_LIFT_HILL_CHAIN_SPEED, STR_NONE }, { WWT_DROPDOWN, 1, 7, 308, 47, 58, 0xFFFFFFFF, STR_SELECT_OPERATING_MODE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 48, 57, STR_DROPDOWN_GLYPH, STR_SELECT_OPERATING_MODE }, { WWT_DROPDOWN, 1, 87, 308, 109, 120, 0xFFFFFFFF, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 110, 119, STR_DROPDOWN_GLYPH, STR_NONE }, { WWT_24, 1, 7, 149, 89, 100, STR_NUMBER_OF_CIRCUITS, STR_NUMBER_OF_CIRCUITS_TIP }, { WWT_SPINNER, 1, 157, 308, 89, 100, STR_NUMBER_OF_CIRCUITS_VALUE, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 90, 94, STR_NUMERIC_UP, STR_SELECT_NUMBER_OF_CIRCUITS_TIP }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 95, 99, STR_NUMERIC_DOWN, STR_SELECT_NUMBER_OF_CIRCUITS_TIP }, { WIDGETS_END }, }; // 0x009AE190 static rct_widget window_ride_maintenance_widgets[] = { MAIN_RIDE_WIDGETS, { WWT_DROPDOWN, 1, 107, 308, 71, 82, 0, STR_SELECT_HOW_OFTEN_A_MECHANIC_SHOULD_CHECK_THIS_RIDE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 72, 81, STR_DROPDOWN_GLYPH, STR_SELECT_HOW_OFTEN_A_MECHANIC_SHOULD_CHECK_THIS_RIDE }, { WWT_FLATBTN, 1, 289, 312, 108, 131, 0xFFFFFFFF, STR_LOCATE_NEAREST_AVAILABLE_MECHANIC_TIP }, { WWT_FLATBTN, 1, 265, 288, 108, 131, SPR_NO_ENTRY, STR_DEBUG_FORCE_BREAKDOWN_TIP }, { WIDGETS_END }, }; // 0x009AE2A4 static rct_widget window_ride_colour_widgets[] = { MAIN_RIDE_WIDGETS, { WWT_SPINNER, 1, 3, 70, 47, 93, 0xFFFFFFFF, STR_NONE }, { WWT_DROPDOWN, 1, 74, 312, 49, 60, STR_ARG_14_STRINGID, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 301, 311, 50, 59, STR_DROPDOWN_GLYPH, STR_COLOUR_SCHEME_TO_CHANGE_TIP }, { WWT_COLOURBTN, 1, 79, 90, 74, 85, 0xFFFFFFFF, STR_SELECT_MAIN_COLOUR_TIP }, { WWT_COLOURBTN, 1, 99, 110, 74, 85, 0xFFFFFFFF, STR_SELECT_ADDITIONAL_COLOUR_1_TIP }, { WWT_COLOURBTN, 1, 119, 130, 74, 85, 0xFFFFFFFF, STR_SELECT_SUPPORT_STRUCTURE_COLOUR_TIP }, { WWT_DROPDOWN, 1, 74, 312, 49, 60, 0xFFFFFFFF, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 301, 311, 50, 59, STR_DROPDOWN_GLYPH, STR_NONE }, { WWT_FLATBTN, 1, 289, 312, 68, 91, SPR_PAINTBRUSH, STR_PAINT_INDIVIDUAL_AREA_TIP }, { WWT_SPINNER, 1, 245, 312, 101, 147, 0xFFFFFFFF, STR_NONE }, { WWT_DROPDOWN, 1, 3, 241, 103, 114, 0, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 230, 240, 104, 113, STR_DROPDOWN_GLYPH, STR_SELECT_STYLE_OF_ENTRANCE_EXIT_STATION_TIP }, { WWT_SCROLL, 1, 3, 70, 157, 203, 0, STR_NONE }, { WWT_DROPDOWN, 1, 74, 312, 157, 168, STR_ARG_6_STRINGID, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 301, 311, 158, 167, STR_DROPDOWN_GLYPH, STR_SELECT_VEHICLE_COLOUR_SCHEME_TIP }, { WWT_DROPDOWN, 1, 74, 312, 173, 184, 0xFFFFFFFF, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 301, 311, 174, 183, STR_DROPDOWN_GLYPH, STR_SELECT_VEHICLE_TO_MODIFY_TIP }, { WWT_COLOURBTN, 1, 79, 90, 190, 201, 0xFFFFFFFF, STR_SELECT_MAIN_COLOUR_TIP }, { WWT_COLOURBTN, 1, 99, 110, 190, 201, 0xFFFFFFFF, STR_SELECT_ADDITIONAL_COLOUR_1_TIP }, { WWT_COLOURBTN, 1, 119, 130, 190, 201, 0xFFFFFFFF, STR_SELECT_ADDITIONAL_COLOUR_2_TIP }, { WIDGETS_END }, }; // 0x009AE4C8 static rct_widget window_ride_music_widgets[] = { MAIN_RIDE_WIDGETS, { WWT_CHECKBOX, 1, 7, 308, 47, 58, STR_PLAY_MUSIC, STR_SELECT_MUSIC_TIP }, { WWT_DROPDOWN, 1, 7, 308, 62, 73, 0, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 63, 72, STR_DROPDOWN_GLYPH, STR_SELECT_MUSIC_STYLE_TIP }, { WIDGETS_END }, }; // 0x009AE5DC static rct_widget window_ride_measurements_widgets[] = { MAIN_RIDE_WIDGETS, { WWT_FLATBTN, 1, 288, 311, 164, 187, SPR_FLOPPY, STR_SAVE_TRACK_DESIGN }, { WWT_DROPDOWN_BUTTON, 1, 4, 157, 128, 139, STR_SELECT_NEARBY_SCENERY, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 158, 311, 128, 139, STR_RESET_SELECTION, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 4, 157, 178, 189, STR_DESIGN_SAVE, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 158, 311, 178, 189, STR_DESIGN_CANCEL, STR_NONE }, { WIDGETS_END }, }; // 0x009AE710 static rct_widget window_ride_graphs_widgets[] = { MAIN_RIDE_WIDGETS, { WWT_SCROLL, 1, 3, 308, 46, 157, SCROLL_HORIZONTAL, STR_LOGGING_DATA_FROM_TIP }, { WWT_DROPDOWN_BUTTON, 1, 3, 75, 163, 176, STR_RIDE_STATS_VELOCITY, STR_SHOW_GRAPH_OF_VELOCITY_AGAINST_TIME_TIP }, { WWT_DROPDOWN_BUTTON, 1, 76, 148, 163, 176, STR_RIDE_STATS_ALTITUDE, STR_SHOW_GRAPH_OF_ALTITUDE_AGAINST_TIME_TIP }, { WWT_DROPDOWN_BUTTON, 1, 149, 221, 163, 176, STR_RIDE_STATS_VERT_G, STR_SHOW_GRAPH_OF_VERTICAL_ACCELERATION_AGAINST_TIME_TIP }, { WWT_DROPDOWN_BUTTON, 1, 222, 294, 163, 176, STR_RIDE_STATS_LAT_G, STR_SHOW_GRAPH_OF_LATERAL_ACCELERATION_AGAINST_TIME_TIP }, { WIDGETS_END }, }; // 0x009AE844 static rct_widget window_ride_income_widgets[] = { MAIN_RIDE_WIDGETS, { WWT_24, 1, 5, 144, 50, 61, 0xFFFFFFFF, STR_NONE }, { WWT_SPINNER, 1, 147, 308, 50, 61, STR_ARG_6_CURRENCY2DP, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 51, 55, STR_NUMERIC_UP, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 56, 60, STR_NUMERIC_DOWN, STR_NONE }, { WWT_CHECKBOX, 1, 5, 310, 61, 72, STR_SAME_PRICE_THROUGHOUT_PARK, STR_SAME_PRICE_THROUGHOUT_PARK_TIP }, { WWT_24, 1, 5, 144, 89, 100, 0xFFFFFFFF, STR_NONE }, { WWT_SPINNER, 1, 147, 308, 89, 100, STR_RIDE_SECONDARY_PRICE_VALUE, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 90, 94, STR_NUMERIC_UP, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 297, 307, 95, 99, STR_NUMERIC_DOWN, STR_NONE }, { WWT_CHECKBOX, 1, 5, 310, 100, 111, STR_SAME_PRICE_THROUGHOUT_PARK, STR_SAME_PRICE_THROUGHOUT_PARK_TIP }, { WIDGETS_END }, }; // 0x009AE9C8 static rct_widget window_ride_customer_widgets[] = { MAIN_RIDE_WIDGETS, { WWT_FLATBTN, 1, 289, 312, 54, 77, SPR_SHOW_GUESTS_THOUGHTS_ABOUT_THIS_RIDE_ATTRACTION, STR_SHOW_GUESTS_THOUGHTS_ABOUT_THIS_RIDE_ATTRACTION_TIP }, { WWT_FLATBTN, 1, 289, 312, 78, 101, SPR_SHOW_GUESTS_ON_THIS_RIDE_ATTRACTION, STR_SHOW_GUESTS_ON_THIS_RIDE_ATTRACTION_TIP }, { WWT_FLATBTN, 1, 289, 312, 102, 125, SPR_SHOW_GUESTS_QUEUING_FOR_THIS_RIDE_ATTRACTION, STR_SHOW_GUESTS_QUEUING_FOR_THIS_RIDE_ATTRACTION_TIP }, { WIDGETS_END }, }; static rct_widget *window_ride_page_widgets[] = { window_ride_main_widgets, window_ride_vehicle_widgets, window_ride_operating_widgets, window_ride_maintenance_widgets, window_ride_colour_widgets, window_ride_music_widgets, window_ride_measurements_widgets, window_ride_graphs_widgets, window_ride_income_widgets, window_ride_customer_widgets }; #define MAIN_RIDE_ENABLED_WIDGETS \ (1ULL << WIDX_CLOSE) | \ (1ULL << WIDX_TAB_1) | \ (1ULL << WIDX_TAB_2) | \ (1ULL << WIDX_TAB_3) | \ (1ULL << WIDX_TAB_4) | \ (1ULL << WIDX_TAB_5) | \ (1ULL << WIDX_TAB_6) | \ (1ULL << WIDX_TAB_7) | \ (1ULL << WIDX_TAB_8) | \ (1ULL << WIDX_TAB_9) | \ (1ULL << WIDX_TAB_10) const uint64 window_ride_page_enabled_widgets[] = { MAIN_RIDE_ENABLED_WIDGETS | (1ULL << WIDX_VIEW) | (1ULL << WIDX_VIEW_DROPDOWN) | (1ULL << WIDX_OPEN) | (1ULL << WIDX_CONSTRUCTION) | (1ULL << WIDX_RENAME) | (1ULL << WIDX_LOCATE) | (1ULL << WIDX_DEMOLISH) | (1ULL << WIDX_CLOSE_LIGHT) | (1ULL << WIDX_TEST_LIGHT) | (1ULL << WIDX_OPEN_LIGHT) | (1ULL << WIDX_RIDE_TYPE) | (1ULL << WIDX_RIDE_TYPE_INCREASE) | (1ULL << WIDX_RIDE_TYPE_DECREASE) | (1ULL << WIDX_RIDE_TYPE_APPLY), MAIN_RIDE_ENABLED_WIDGETS | (1ULL << WIDX_VEHICLE_TYPE) | (1ULL << WIDX_VEHICLE_TYPE_DROPDOWN) | (1ULL << WIDX_VEHICLE_TRAINS) | (1ULL << WIDX_VEHICLE_TRAINS_INCREASE) | (1ULL << WIDX_VEHICLE_TRAINS_DECREASE) | (1ULL << WIDX_VEHICLE_CARS_PER_TRAIN) | (1ULL << WIDX_VEHICLE_CARS_PER_TRAIN_INCREASE) | (1ULL << WIDX_VEHICLE_CARS_PER_TRAIN_DECREASE), MAIN_RIDE_ENABLED_WIDGETS | (1ULL << WIDX_MODE_TWEAK_INCREASE) | (1ULL << WIDX_MODE_TWEAK_DECREASE) | (1ULL << WIDX_LIFT_HILL_SPEED_INCREASE) | (1ULL << WIDX_LIFT_HILL_SPEED_DECREASE) | (1ULL << WIDX_LOAD_CHECKBOX) | (1ULL << WIDX_LEAVE_WHEN_ANOTHER_ARRIVES_CHECKBOX) | (1ULL << WIDX_MINIMUM_LENGTH_CHECKBOX) | (1ULL << WIDX_MINIMUM_LENGTH_INCREASE) | (1ULL << WIDX_MINIMUM_LENGTH_DECREASE) | (1ULL << WIDX_MAXIMUM_LENGTH_CHECKBOX) | (1ULL << WIDX_MAXIMUM_LENGTH_INCREASE) | (1ULL << WIDX_MAXIMUM_LENGTH_DECREASE) | (1ULL << WIDX_SYNCHRONISE_WITH_ADJACENT_STATIONS_CHECKBOX) | (1ULL << WIDX_MODE) | (1ULL << WIDX_MODE_DROPDOWN) | (1ULL << WIDX_LOAD) | (1ULL << WIDX_LOAD_DROPDOWN) | (1ULL << WIDX_OPERATE_NUMBER_OF_CIRCUITS_INCREASE) | (1ULL << WIDX_OPERATE_NUMBER_OF_CIRCUITS_DECREASE), MAIN_RIDE_ENABLED_WIDGETS | (1ULL << WIDX_INSPECTION_INTERVAL) | (1ULL << WIDX_INSPECTION_INTERVAL_DROPDOWN) | (1ULL << WIDX_LOCATE_MECHANIC) | (1ULL << WIDX_FORCE_BREAKDOWN), MAIN_RIDE_ENABLED_WIDGETS | (1ULL << WIDX_TRACK_COLOUR_SCHEME_DROPDOWN) | (1ULL << WIDX_TRACK_MAIN_COLOUR) | (1ULL << WIDX_TRACK_ADDITIONAL_COLOUR) | (1ULL << WIDX_TRACK_SUPPORT_COLOUR) | (1ULL << WIDX_MAZE_STYLE) | (1ULL << WIDX_MAZE_STYLE_DROPDOWN) | (1ULL << WIDX_PAINT_INDIVIDUAL_AREA) | (1ULL << WIDX_ENTRANCE_STYLE) | (1ULL << WIDX_ENTRANCE_STYLE_DROPDOWN) | (1ULL << WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN) | (1ULL << WIDX_VEHICLE_COLOUR_INDEX) | (1ULL << WIDX_VEHICLE_COLOUR_INDEX_DROPDOWN) | (1ULL << WIDX_VEHICLE_MAIN_COLOUR) | (1ULL << WIDX_VEHICLE_ADDITIONAL_COLOUR_1) | (1ULL << WIDX_VEHICLE_ADDITIONAL_COLOUR_2), MAIN_RIDE_ENABLED_WIDGETS | (1ULL << WIDX_PLAY_MUSIC) | (1ULL << WIDX_MUSIC) | (1ULL << WIDX_MUSIC_DROPDOWN), MAIN_RIDE_ENABLED_WIDGETS | (1ULL << WIDX_SAVE_TRACK_DESIGN) | (1ULL << WIDX_SELECT_NEARBY_SCENERY) | (1ULL << WIDX_RESET_SELECTION) | (1ULL << WIDX_SAVE_DESIGN) | (1ULL << WIDX_CANCEL_DESIGN), MAIN_RIDE_ENABLED_WIDGETS | (1ULL << WIDX_GRAPH_VELOCITY) | (1ULL << WIDX_GRAPH_ALTITUDE) | (1ULL << WIDX_GRAPH_VERTICAL) | (1ULL << WIDX_GRAPH_LATERAL), MAIN_RIDE_ENABLED_WIDGETS | (1ULL << WIDX_PRIMARY_PRICE_INCREASE) | (1ULL << WIDX_PRIMARY_PRICE_DECREASE) | (1ULL << WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK) | (1ULL << WIDX_SECONDARY_PRICE_INCREASE) | (1ULL << WIDX_SECONDARY_PRICE_DECREASE) | (1ULL << WIDX_SECONDARY_PRICE_SAME_THROUGHOUT_PARK), MAIN_RIDE_ENABLED_WIDGETS | (1ULL << WIDX_SHOW_GUESTS_THOUGHTS) | (1ULL << WIDX_SHOW_GUESTS_ON_RIDE) | (1ULL << WIDX_SHOW_GUESTS_QUEUING), }; const uint64 window_ride_page_hold_down_widgets[] = { 0, (1ULL << WIDX_VEHICLE_TRAINS_INCREASE) | (1ULL << WIDX_VEHICLE_TRAINS_DECREASE) | (1ULL << WIDX_VEHICLE_CARS_PER_TRAIN_INCREASE) | (1ULL << WIDX_VEHICLE_CARS_PER_TRAIN_DECREASE), (1ULL << WIDX_MODE_TWEAK_INCREASE) | (1ULL << WIDX_MODE_TWEAK_DECREASE) | (1ULL << WIDX_LIFT_HILL_SPEED_INCREASE) | (1ULL << WIDX_LIFT_HILL_SPEED_DECREASE) | (1ULL << WIDX_MINIMUM_LENGTH_INCREASE) | (1ULL << WIDX_MINIMUM_LENGTH_DECREASE) | (1ULL << WIDX_MAXIMUM_LENGTH_INCREASE) | (1ULL << WIDX_MAXIMUM_LENGTH_DECREASE), 0, 0, 0, 0, 0, (1ULL << WIDX_PRIMARY_PRICE_INCREASE) | (1ULL << WIDX_PRIMARY_PRICE_DECREASE) | (1ULL << WIDX_SECONDARY_PRICE_INCREASE) | (1ULL << WIDX_SECONDARY_PRICE_DECREASE), 0 }; #pragma endregion #pragma region Events static void window_ride_init_viewport(rct_window *w); static void window_ride_main_mouseup(rct_window *w, rct_widgetindex widgetIndex); static void window_ride_main_resize(rct_window *w); static void window_ride_main_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget); static void window_ride_main_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex); static void window_ride_main_update(rct_window *w); static void window_ride_main_textinput(rct_window *w, rct_widgetindex widgetIndex, char *text); static void window_ride_main_viewport_rotate(rct_window *w); static void window_ride_main_invalidate(rct_window *w); static void window_ride_main_paint(rct_window *w, rct_drawpixelinfo *dpi); static void window_ride_vehicle_mouseup(rct_window *w, rct_widgetindex widgetIndex); static void window_ride_vehicle_resize(rct_window *w); static void window_ride_vehicle_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget); static void window_ride_vehicle_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex); static void window_ride_vehicle_update(rct_window *w); static void window_ride_vehicle_invalidate(rct_window *w); static void window_ride_vehicle_paint(rct_window *w, rct_drawpixelinfo *dpi); static void window_ride_vehicle_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32 scrollIndex); static void window_ride_operating_mouseup(rct_window *w, rct_widgetindex widgetIndex); static void window_ride_operating_resize(rct_window *w); static void window_ride_operating_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget); static void window_ride_operating_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex); static void window_ride_operating_update(rct_window *w); static void window_ride_operating_invalidate(rct_window *w); static void window_ride_operating_paint(rct_window *w, rct_drawpixelinfo *dpi); static void window_ride_maintenance_mouseup(rct_window *w, rct_widgetindex widgetIndex); static void window_ride_maintenance_resize(rct_window *w); static void window_ride_maintenance_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget); static void window_ride_maintenance_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex); static void window_ride_maintenance_update(rct_window *w); static void window_ride_maintenance_invalidate(rct_window *w); static void window_ride_maintenance_paint(rct_window *w, rct_drawpixelinfo *dpi); static void window_ride_colour_close(rct_window *w); static void window_ride_colour_mouseup(rct_window *w, rct_widgetindex widgetIndex); static void window_ride_colour_resize(rct_window *w); static void window_ride_colour_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget); static void window_ride_colour_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex); static void window_ride_colour_update(rct_window *w); static void window_ride_colour_tooldown(rct_window *w, rct_widgetindex widgetIndex, sint32 x, sint32 y); static void window_ride_colour_tooldrag(rct_window *w, rct_widgetindex widgetIndex, sint32 x, sint32 y); static void window_ride_colour_invalidate(rct_window *w); static void window_ride_colour_paint(rct_window *w, rct_drawpixelinfo *dpi); static void window_ride_colour_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32 scrollIndex); static void window_ride_music_mouseup(rct_window *w, rct_widgetindex widgetIndex); static void window_ride_music_resize(rct_window *w); static void window_ride_music_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget); static void window_ride_music_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex); static void window_ride_music_update(rct_window *w); static void window_ride_music_invalidate(rct_window *w); static void window_ride_music_paint(rct_window *w, rct_drawpixelinfo *dpi); static void window_ride_measurements_close(rct_window *w); static void window_ride_measurements_mouseup(rct_window *w, rct_widgetindex widgetIndex); static void window_ride_measurements_resize(rct_window *w); static void window_ride_measurements_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget); static void window_ride_measurements_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex); static void window_ride_measurements_update(rct_window *w); static void window_ride_measurements_tooldown(rct_window *w, rct_widgetindex widgetIndex, sint32 x, sint32 y); static void window_ride_measurements_tooldrag(rct_window *w, rct_widgetindex widgetIndex, sint32 x, sint32 y); static void window_ride_measurements_toolabort(rct_window *w, rct_widgetindex widgetIndex); static void window_ride_measurements_invalidate(rct_window *w); static void window_ride_measurements_paint(rct_window *w, rct_drawpixelinfo *dpi); static void window_ride_graphs_mouseup(rct_window *w, rct_widgetindex widgetIndex); static void window_ride_graphs_resize(rct_window *w); static void window_ride_graphs_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget); static void window_ride_graphs_update(rct_window *w); static void window_ride_graphs_scrollgetheight(rct_window *w, sint32 scrollIndex, sint32 *width, sint32 *height); static void window_ride_graphs_15(rct_window *w, sint32 scrollIndex, sint32 scrollAreaType); static void window_ride_graphs_tooltip(rct_window* w, rct_widgetindex widgetIndex, rct_string_id *stringId); static void window_ride_graphs_invalidate(rct_window *w); static void window_ride_graphs_paint(rct_window *w, rct_drawpixelinfo *dpi); static void window_ride_graphs_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32 scrollIndex); static void window_ride_income_mouseup(rct_window *w, rct_widgetindex widgetIndex); static void window_ride_income_resize(rct_window *w); static void window_ride_income_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget); static void window_ride_income_update(rct_window *w); static void window_ride_income_invalidate(rct_window *w); static void window_ride_income_paint(rct_window *w, rct_drawpixelinfo *dpi); static void window_ride_customer_mouseup(rct_window *w, rct_widgetindex widgetIndex); static void window_ride_customer_resize(rct_window *w); static void window_ride_customer_update(rct_window *w); static void window_ride_customer_invalidate(rct_window *w); static void window_ride_customer_paint(rct_window *w, rct_drawpixelinfo *dpi); static void window_ride_set_colours(); static void window_ride_set_page(rct_window *w, sint32 page); // 0x0098DFD4 static rct_window_event_list window_ride_main_events = { NULL, window_ride_main_mouseup, window_ride_main_resize, window_ride_main_mousedown, window_ride_main_dropdown, NULL, window_ride_main_update, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, window_ride_main_textinput, window_ride_main_viewport_rotate, NULL, NULL, NULL, NULL, window_ride_main_invalidate, window_ride_main_paint, NULL }; // 0x0098E204 static rct_window_event_list window_ride_vehicle_events = { NULL, window_ride_vehicle_mouseup, window_ride_vehicle_resize, window_ride_vehicle_mousedown, window_ride_vehicle_dropdown, NULL, window_ride_vehicle_update, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, window_ride_vehicle_invalidate, window_ride_vehicle_paint, window_ride_vehicle_scrollpaint }; // 0x0098E0B4 static rct_window_event_list window_ride_operating_events = { NULL, window_ride_operating_mouseup, window_ride_operating_resize, window_ride_operating_mousedown, window_ride_operating_dropdown, NULL, window_ride_operating_update, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, window_ride_operating_invalidate, window_ride_operating_paint, NULL }; // 0x0098E124 static rct_window_event_list window_ride_maintenance_events = { NULL, window_ride_maintenance_mouseup, window_ride_maintenance_resize, window_ride_maintenance_mousedown, window_ride_maintenance_dropdown, NULL, window_ride_maintenance_update, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, window_ride_maintenance_invalidate, window_ride_maintenance_paint, NULL }; // 0x0098E044 static rct_window_event_list window_ride_colour_events = { window_ride_colour_close, window_ride_colour_mouseup, window_ride_colour_resize, window_ride_colour_mousedown, window_ride_colour_dropdown, NULL, window_ride_colour_update, NULL, NULL, NULL, window_ride_colour_tooldown, window_ride_colour_tooldrag, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, window_ride_colour_invalidate, window_ride_colour_paint, window_ride_colour_scrollpaint }; // 0x0098E194 static rct_window_event_list window_ride_music_events = { NULL, window_ride_music_mouseup, window_ride_music_resize, window_ride_music_mousedown, window_ride_music_dropdown, NULL, window_ride_music_update, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, window_ride_music_invalidate, window_ride_music_paint, NULL }; // 0x0098DE14 static rct_window_event_list window_ride_measurements_events = { window_ride_measurements_close, window_ride_measurements_mouseup, window_ride_measurements_resize, window_ride_measurements_mousedown, window_ride_measurements_dropdown, NULL, window_ride_measurements_update, NULL, NULL, NULL, window_ride_measurements_tooldown, window_ride_measurements_tooldrag, NULL, window_ride_measurements_toolabort, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, window_ride_measurements_invalidate, window_ride_measurements_paint, NULL }; // 0x0098DF64 static rct_window_event_list window_ride_graphs_events = { NULL, window_ride_graphs_mouseup, window_ride_graphs_resize, window_ride_graphs_mousedown, NULL, NULL, window_ride_graphs_update, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, window_ride_graphs_scrollgetheight, NULL, NULL, NULL, NULL, NULL, window_ride_graphs_15, window_ride_graphs_tooltip, NULL, NULL, window_ride_graphs_invalidate, window_ride_graphs_paint, window_ride_graphs_scrollpaint }; // 0x0098DEF4 static rct_window_event_list window_ride_income_events = { NULL, window_ride_income_mouseup, window_ride_income_resize, window_ride_income_mousedown, NULL, NULL, window_ride_income_update, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, window_ride_income_invalidate, window_ride_income_paint, NULL }; // 0x0098DE84 static rct_window_event_list window_ride_customer_events = { NULL, window_ride_customer_mouseup, window_ride_customer_resize, NULL, NULL, NULL, window_ride_customer_update, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, window_ride_customer_invalidate, window_ride_customer_paint, NULL }; static rct_window_event_list *window_ride_page_events[] = { &window_ride_main_events, &window_ride_vehicle_events, &window_ride_operating_events, &window_ride_maintenance_events, &window_ride_colour_events, &window_ride_music_events, &window_ride_measurements_events, &window_ride_graphs_events, &window_ride_income_events, &window_ride_customer_events }; #pragma endregion static uint8 _rideType; static bool _collectTrackDesignScenery = false; static sint32 _lastSceneryX = 0; static sint32 _lastSceneryY = 0; static void set_operating_setting(sint32 rideNumber, uint8 setting, uint8 value); // Cached overall view for each ride // (Re)calculated when the ride window is opened typedef struct ride_overall_view_t { sint16 x, y, z; uint8 zoom; } ride_overall_view; ride_overall_view ride_overall_views[MAX_RIDES] = {0}; const sint32 window_ride_tab_animation_divisor[] = { 0, 0, 2, 2, 4, 2, 8, 8, 2, 0 }; const sint32 window_ride_tab_animation_frames[] = { 0, 0, 4, 16, 8, 16, 8, 8, 8, 0 }; static const rct_string_id RatingNames[] = { STR_RATING_LOW, STR_RATING_MEDIUM, STR_RATING_HIGH, STR_RATING_VERY_HIGH, STR_RATING_EXTREME, STR_RATING_ULTRA_EXTREME, }; static const rct_string_id RideBreakdownReasonNames[] = { STR_RIDE_BREAKDOWN_SAFETY_CUT_OUT , STR_RIDE_BREAKDOWN_RESTRAINTS_STUCK_CLOSED, STR_RIDE_BREAKDOWN_RESTRAINTS_STUCK_OPEN, STR_RIDE_BREAKDOWN_DOORS_STUCK_CLOSED, STR_RIDE_BREAKDOWN_DOORS_STUCK_OPEN, STR_RIDE_BREAKDOWN_VEHICLE_MALFUNCTION, STR_RIDE_BREAKDOWN_BRAKES_FAILURE, STR_RIDE_BREAKDOWN_CONTROL_FAILURE }; static const rct_string_id ColourSchemeNames[] = { STR_MAIN_COLOUR_SCHEME, STR_ALTERNATIVE_COLOUR_SCHEME_1, STR_ALTERNATIVE_COLOUR_SCHEME_2, STR_ALTERNATIVE_COLOUR_SCHEME_3, }; static const rct_string_id VehicleLoadNames[] = { STR_QUARTER_LOAD, STR_HALF_LOAD, STR_THREE_QUARTER_LOAD, STR_FULL_LOAD, STR_ANY_LOAD, }; static const rct_string_id VehicleColourSchemeNames[] = { STR_ALL_VEHICLES_IN_SAME_COLOURS , STR_DIFFERENT_COLOURS_PER , STR_DIFFERENT_COLOURS_PER_VEHICLE , }; static const rct_string_id VehicleStatusNames[] = { STR_MOVING_TO_END_OF, // VEHICLE_STATUS_MOVING_TO_END_OF_STATION STR_WAITING_FOR_PASSENGERS_AT, // VEHICLE_STATUS_WAITING_FOR_PASSENGERS STR_WAITING_TO_DEPART, // VEHICLE_STATUS_WAITING_TO_DEPART STR_DEPARTING, // VEHICLE_STATUS_DEPARTING STR_TRAVELLING_AT_0, // VEHICLE_STATUS_TRAVELLING STR_ARRIVING_AT, // VEHICLE_STATUS_ARRIVING STR_UNLOADING_PASSENGERS_AT, // VEHICLE_STATUS_UNLOADING_PASSENGERS STR_TRAVELLING_AT_1, // VEHICLE_STATUS_TRAVELLING_BOAT STR_CRASHING, // VEHICLE_STATUS_CRASHING STR_CRASHED_0, // VEHICLE_STATUS_CRASHED STR_TRAVELLING_AT_2, // VEHICLE_STATUS_TRAVELLING_DODGEMS STR_SWINGING, // VEHICLE_STATUS_SWINGING STR_ROTATING_0, // VEHICLE_STATUS_ROTATING STR_ROTATING_1, // VEHICLE_STATUS_FERRIS_WHEEL_ROTATING STR_OPERATING_0, // VEHICLE_STATUS_SIMULATOR_OPERATING STR_SHOWING_FILM, // VEHICLE_STATUS_SHOWING_FILM STR_ROTATING_2, // VEHICLE_STATUS_SPACE_RINGS_OPERATING STR_OPERATING_1, // VEHICLE_STATUS_TOP_SPIN_OPERATING STR_OPERATING_2, // VEHICLE_STATUS_HAUNTED_HOUSE_OPERATING STR_DOING_CIRCUS_SHOW, // VEHICLE_STATUS_DOING_CIRCUS_SHOW STR_OPERATING_3, // VEHICLE_STATUS_CROOKED_HOUSE_OPERATING STR_WAITING_FOR_CABLE_LIFT, // VEHICLE_STATUS_WAITING_FOR_CABLE_LIFT STR_TRAVELLING_AT_3, // VEHICLE_STATUS_TRAVELLING_CABLE_LIFT STR_STOPPING_0, // VEHICLE_STATUS_STOPPING STR_WAITING_FOR_PASSENGERS, // VEHICLE_STATUS_WAITING_FOR_PASSENGERS_17 STR_WAITING_TO_START, // VEHICLE_STATUS_WAITING_TO_START STR_STARTING, // VEHICLE_STATUS_STARTING STR_OPERATING, // VEHICLE_STATUS_OPERATING_1A STR_STOPPING_1, // VEHICLE_STATUS_STOPPING_1B STR_UNLOADING_PASSENGERS, // VEHICLE_STATUS_UNLOADING_PASSENGERS_1C STR_STOPPED_BY_BLOCK_BRAKES, // VEHICLE_STATUS_STOPPED_BY_BLOCK_BRAKES }; static const rct_string_id SingleSessionVehicleStatusNames[] = { STR_STOPPING_0, // VEHICLE_STATUS_MOVING_TO_END_OF_STATION STR_WAITING_FOR_PASSENGERS, // VEHICLE_STATUS_WAITING_FOR_PASSENGERS STR_WAITING_TO_START, // VEHICLE_STATUS_WAITING_TO_DEPART STR_STARTING, // VEHICLE_STATUS_DEPARTING STR_OPERATING, // VEHICLE_STATUS_TRAVELLING STR_STOPPING_1, // VEHICLE_STATUS_ARRIVING STR_UNLOADING_PASSENGERS, // VEHICLE_STATUS_UNLOADING_PASSENGERS }; static const rct_string_id MusicStyleNames[] = { STR_MUSIC_STYLE_DODGEMS_BEAT, STR_MUSIC_STYLE_FAIRGROUND_ORGAN, STR_MUSIC_STYLE_ROMAN_FANFARE, STR_MUSIC_STYLE_ORIENTAL, STR_MUSIC_STYLE_MARTIAN, STR_MUSIC_STYLE_JUNGLE_DRUMS, STR_MUSIC_STYLE_EGYPTIAN, STR_MUSIC_STYLE_TOYLAND, STR_MUSIC_STYLE_CIRCUS_SHOW, STR_MUSIC_STYLE_SPACE, STR_MUSIC_STYLE_HORROR, STR_MUSIC_STYLE_TECHNO, STR_MUSIC_STYLE_GENTLE, STR_MUSIC_STYLE_SUMMER, STR_MUSIC_STYLE_WATER, STR_MUSIC_STYLE_WILD_WEST, STR_MUSIC_STYLE_JURASSIC, STR_MUSIC_STYLE_ROCK, STR_MUSIC_STYLE_RAGTIME, STR_MUSIC_STYLE_FANTASY, STR_MUSIC_STYLE_ROCK_STYLE_2, STR_MUSIC_STYLE_ICE, STR_MUSIC_STYLE_SNOW, STR_MUSIC_STYLE_CUSTOM_MUSIC_1, STR_MUSIC_STYLE_CUSTOM_MUSIC_2, STR_MUSIC_STYLE_MEDIEVAL, STR_MUSIC_STYLE_URBAN, STR_MUSIC_STYLE_ORGAN, STR_MUSIC_STYLE_MECHANICAL, STR_MUSIC_STYLE_MODERN, STR_MUSIC_STYLE_PIRATES, STR_MUSIC_STYLE_ROCK_STYLE_3, STR_MUSIC_STYLE_CANDY_STYLE, }; typedef struct window_ride_maze_design_option { rct_string_id text; uint32 sprite; } window_ride_maze_design_option; static const window_ride_maze_design_option MazeOptions[] = { { STR_RIDE_DESIGN_MAZE_BRICK_WALLS, SPR_RIDE_DESIGN_PREVIEW_MAZE_BRICK_WALLS }, { STR_RIDE_DESIGN_MAZE_HEDGES, SPR_RIDE_DESIGN_PREVIEW_MAZE_HEDGES }, { STR_RIDE_DESIGN_MAZE_ICE_BLOCKS, SPR_RIDE_DESIGN_PREVIEW_MAZE_ICE_BLOCKS }, { STR_RIDE_DESIGN_MAZE_WOODEN_FENCES, SPR_RIDE_DESIGN_PREVIEW_MAZE_WOODEN_FENCES }, }; typedef struct window_ride_colour_preview { uint32 track; uint32 supports; } window_ride_colour_preview; static const window_ride_colour_preview TrackColourPreviews[] = { { SPR_RIDE_DESIGN_PREVIEW_SPIRAL_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_SPIRAL_ROLLER_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_STAND_UP_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_STAND_UP_ROLLER_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_SUSPENDED_SWINGING_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_SUSPENDED_SWINGING_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_INVERTED_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_INVERTED_ROLLER_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_JUNIOR_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_JUNIOR_ROLLER_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_MINIATURE_RAILWAY_TRACK, SPR_RIDE_DESIGN_PREVIEW_MINIATURE_RAILWAY_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_MONORAIL_TRACK, SPR_RIDE_DESIGN_PREVIEW_MONORAIL_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_MINI_SUSPENDED_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_MINI_SUSPENDED_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_BOAT_RIDE_TRACK, SPR_RIDE_DESIGN_PREVIEW_BOAT_RIDE_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_WOODEN_WILD_MOUSE_TRACK, SPR_RIDE_DESIGN_PREVIEW_WOODEN_WILD_MOUSE_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_STEEPLECHASE_TRACK, SPR_RIDE_DESIGN_PREVIEW_STEEPLECHASE_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_CAR_RIDE_TRACK, SPR_RIDE_DESIGN_PREVIEW_CAR_RIDE_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_LAUNCHED_FREEFALL_TRACK, SPR_RIDE_DESIGN_PREVIEW_LAUNCHED_FREEFALL_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_BOBSLEIGH_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_BOBSLEIGH_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_OBSERVATION_TOWER_TRACK, SPR_RIDE_DESIGN_PREVIEW_OBSERVATION_TOWER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_LOOPING_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_LOOPING_ROLLER_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_DINGHY_SLIDE_TRACK, SPR_RIDE_DESIGN_PREVIEW_DINGHY_SLIDE_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_MINE_TRAIN_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_MINE_TRAIN_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_CHAIRLIFT_TRACK, SPR_RIDE_DESIGN_PREVIEW_CHAIRLIFT_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_CORKSCREW_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_CORKSCREW_ROLLER_COASTER_SUPPORTS}, { 0, 0 }, // MAZE { SPR_RIDE_DESIGN_PREVIEW_SPIRAL_SLIDE_TRACK, 0}, { SPR_RIDE_DESIGN_PREVIEW_GO_KARTS_TRACK, SPR_RIDE_DESIGN_PREVIEW_GO_KARTS_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_LOG_FLUME_TRACK, SPR_RIDE_DESIGN_PREVIEW_LOG_FLUME_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_RIVER_RAPIDS_TRACK, SPR_RIDE_DESIGN_PREVIEW_RIVER_RAPIDS_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_DODGEMS_TRACK, SPR_RIDE_DESIGN_PREVIEW_DODGEMS_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_PIRATE_SHIP_TRACK, SPR_RIDE_DESIGN_PREVIEW_PIRATE_SHIP_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_SWINGING_INVERTER_SHIP_TRACK, SPR_RIDE_DESIGN_PREVIEW_SWINGING_INVERTER_SHIP_SUPPORTS}, { 0, 0 }, // FOOD_STALL { 0, 0 }, // 1D { 0, 0 }, // DRINK_STALL { 0, 0 }, // 1F { 0, 0 }, // SHOP { 0, 0 }, // MERRY_GO_ROUND { 0, 0 }, // 22 { 0, 0 }, // INFORMATION_KIOSK { 0, 0 }, // TOILETS { SPR_RIDE_DESIGN_PREVIEW_FERRIS_WHEEL_TRACK, 0}, { 0, 0 }, // MOTION_SIMULATOR { 0, 0 }, // 3D_CINEMA { SPR_RIDE_DESIGN_PREVIEW_TOP_SPIN_TRACK, 0}, { 0, 0 }, // SPACE_RINGS { SPR_RIDE_DESIGN_PREVIEW_REVERSE_FREEFALL_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_REVERSE_FREEFALL_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_LIFT_TRACK, 0}, { SPR_RIDE_DESIGN_PREVIEW_VERTICAL_DROP_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_VERTICAL_DROP_ROLLER_COASTER_SUPPORTS}, { 0, 0 }, // CASH_MACHINE { 0, 0 }, // TWIST_TRACK { 0, 0 }, // HAUNTED_HOUSE { 0, 0 }, // FIRST_AID { 0, 0 }, // CIRCUS_SHOW { SPR_RIDE_DESIGN_PREVIEW_GHOST_TRAIN_TRACK, SPR_RIDE_DESIGN_PREVIEW_GHOST_TRAIN_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_TWISTER_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_TWISTER_ROLLER_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_WOODEN_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_WOODEN_ROLLER_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_SIDE_FRICTION_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_SIDE_FRICTION_ROLLER_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_WILD_MOUSE_TRACK, SPR_RIDE_DESIGN_PREVIEW_WILD_MOUSE_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_MULTI_DIMENSION_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_MULTI_DIMENSION_ROLLER_COASTER_SUPPORTS}, { 0, 0 }, // 38 { SPR_RIDE_DESIGN_PREVIEW_FLYING_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_FLYING_ROLLER_COASTER_SUPPORTS}, { 0, 0 }, // 3A { SPR_RIDE_DESIGN_PREVIEW_VIRGINIA_REEL_TRACK, SPR_RIDE_DESIGN_PREVIEW_VIRGINIA_REEL_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_SPLASH_BOATS_TRACK, SPR_RIDE_DESIGN_PREVIEW_SPLASH_BOATS_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_MINI_HELICOPTERS_TRACK, SPR_RIDE_DESIGN_PREVIEW_MINI_HELICOPTERS_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_LAY_DOWN_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_LAY_DOWN_ROLLER_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_SUSPENDED_MONORAIL_TRACK, SPR_RIDE_DESIGN_PREVIEW_SUSPENDED_MONORAIL_SUPPORTS}, { 0, 0 }, // 40 { SPR_RIDE_DESIGN_PREVIEW_REVERSER_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_REVERSER_ROLLER_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_HEARTLINE_TWISTER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_HEARTLINE_TWISTER_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_MINI_GOLF_TRACK, SPR_RIDE_DESIGN_PREVIEW_MINI_GOLF_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_GIGA_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_GIGA_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_ROTO_DROP_TRACK, SPR_RIDE_DESIGN_PREVIEW_ROTO_DROP_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_FLYING_SAUCERS_TRACK, 0}, { 0, 0 }, // CROOKED_HOUSE { SPR_RIDE_DESIGN_PREVIEW_MONORAIL_CYCLES_TRACK, SPR_RIDE_DESIGN_PREVIEW_MONORAIL_CYCLES_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_COMPACT_INVERTED_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_COMPACT_INVERTED_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_WATER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_WATER_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_AIR_POWERED_VERTICAL_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_AIR_POWERED_VERTICAL_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_INVERTED_HAIRPIN_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_INVERTED_HAIRPIN_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_MAGIC_CARPET_TRACK, SPR_RIDE_DESIGN_PREVIEW_MAGIC_CARPET_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_SUBMARINE_RIDE_TRACK, SPR_RIDE_DESIGN_PREVIEW_SUBMARINE_RIDE_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_RIVER_RAFTS_TRACK, SPR_RIDE_DESIGN_PREVIEW_RIVER_RAFTS_SUPPORTS}, { 0, 0 }, // 50 { 0, 0 }, // ENTERPRISE { 0, 0 }, // 52 { 0, 0 }, // 53 { 0, 0 }, // 54 { 0, 0 }, // 55 { SPR_RIDE_DESIGN_PREVIEW_INVERTED_IMPULSE_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_INVERTED_IMPULSE_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_MINI_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_MINI_ROLLER_COASTER_SUPPORTS}, { SPR_RIDE_DESIGN_PREVIEW_MINE_RIDE_TRACK, SPR_RIDE_DESIGN_PREVIEW_MINE_RIDE_SUPPORTS}, { 0, 0 }, // 59 { SPR_RIDE_DESIGN_PREVIEW_LIM_LAUNCHED_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_LIM_LAUNCHED_ROLLER_COASTER_SUPPORTS}, }; typedef struct rct_window_graphs_y_axis { uint8 interval; sint8 unit; sint8 unit_interval; rct_string_id label; } rct_window_graphs_y_axis; /** rct2: 0x0098DD98 */ static const rct_window_graphs_y_axis window_graphs_y_axi[] = { {11, 0, 10, STR_RIDE_STATS_VELOCITY_FORMAT}, // GRAPH_VELOCITY {10, 0, 15, STR_RIDE_STATS_ALTITUDE_FORMAT}, // GRAPH_ALTITUDE {13, -3, 1, STR_RIDE_STATS_G_FORCE_FORMAT}, // GRAPH_VERTICAL {13, -4, 1, STR_RIDE_STATS_G_FORCE_FORMAT}, // GRAPH_LATERAL }; static void window_ride_draw_tab_image(rct_drawpixelinfo *dpi, rct_window *w, sint32 page, sint32 spriteIndex) { rct_widgetindex widgetIndex = WIDX_TAB_1 + page; if (!(w->disabled_widgets & (1LL << widgetIndex))) { if (w->page == page) { sint32 frame = w->frame_no / window_ride_tab_animation_divisor[w->page]; spriteIndex += (frame % window_ride_tab_animation_frames[w->page]); } gfx_draw_sprite(dpi, spriteIndex, w->x + w->widgets[widgetIndex].left, w->y + w->widgets[widgetIndex].top, 0); } } /** * * rct2: 0x006B2E88 */ static void window_ride_draw_tab_main(rct_drawpixelinfo *dpi, rct_window *w) { rct_widgetindex widgetIndex = WIDX_TAB_1 + WINDOW_RIDE_PAGE_MAIN; if (!(w->disabled_widgets & (1LL << widgetIndex))) { sint32 spriteIndex = 0; sint32 rideType = get_ride(w->number)->type; switch (gRideClassifications[rideType]) { case RIDE_CLASS_RIDE: spriteIndex = SPR_TAB_RIDE_0; if (w->page == WINDOW_RIDE_PAGE_MAIN) spriteIndex += (w->frame_no / 4) % 16; break; case RIDE_CLASS_SHOP_OR_STALL: spriteIndex = SPR_TAB_SHOPS_AND_STALLS_0; if (w->page == WINDOW_RIDE_PAGE_MAIN) spriteIndex += (w->frame_no / 4) % 16; break; case RIDE_CLASS_KIOSK_OR_FACILITY: spriteIndex = SPR_TAB_KIOSKS_AND_FACILITIES_0; if (w->page == WINDOW_RIDE_PAGE_MAIN) spriteIndex += (w->frame_no / 4) % 8; break; } gfx_draw_sprite(dpi, spriteIndex, w->x + w->widgets[widgetIndex].left, w->y + w->widgets[widgetIndex].top, 0); } } /** * * rct2: 0x006B2B68 */ static void window_ride_draw_tab_vehicle(rct_drawpixelinfo *dpi, rct_window *w) { rct_widgetindex widgetIndex = WIDX_TAB_1 + WINDOW_RIDE_PAGE_VEHICLE; rct_widget *widget = &w->widgets[widgetIndex]; if (!(w->disabled_widgets & (1LL << widgetIndex))) { sint32 x = widget->left + 1; sint32 y = widget->top + 1; sint32 width = widget->right - x; sint32 height = widget->bottom - 3 - y; if (w->page == WINDOW_RIDE_PAGE_VEHICLE) height += 4; x += w->x; y += w->y; rct_drawpixelinfo clipDPI; if (!clip_drawpixelinfo(&clipDPI, dpi, x, y, width, height)) { return; } x = (widget->right - widget->left) / 2; y = (widget->bottom - widget->top) - 12; rct_ride *ride = get_ride(w->number); rct_ride_entry *rideEntry = get_ride_entry_by_ride(ride); if (rideEntry->flags & RIDE_ENTRY_FLAG_VEHICLE_TAB_SCALE_HALF) { clipDPI.zoom_level = 1; clipDPI.width *= 2; clipDPI.height *= 2; x *= 2; y *= 2; clipDPI.x *= 2; clipDPI.y *= 2; } const uint8 vehicle = ride_entry_get_vehicle_at_position(ride->subtype, ride->num_cars_per_train, rideEntry->tab_vehicle); rct_ride_entry_vehicle* rideVehicleEntry = &rideEntry->vehicles[vehicle]; vehicle_colour vehicleColour = ride_get_vehicle_colour(ride, 0); sint32 spriteIndex = 32; if (w->page == WINDOW_RIDE_PAGE_VEHICLE) spriteIndex += w->frame_no; spriteIndex /= (rideVehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_11) ? 4 : 2; spriteIndex &= rideVehicleEntry->rotation_frame_mask; spriteIndex *= rideVehicleEntry->var_16; spriteIndex += rideVehicleEntry->base_image_id; spriteIndex |= (vehicleColour.additional_1 << 24) | (vehicleColour.main << 19); spriteIndex |= 0x80000000; gfx_draw_sprite(&clipDPI, spriteIndex, x, y, vehicleColour.additional_2); } } /** * * rct2: 0x006B2F42 */ static void window_ride_draw_tab_customer(rct_drawpixelinfo *dpi, rct_window *w) { rct_widgetindex widgetIndex = WIDX_TAB_1 + WINDOW_RIDE_PAGE_CUSTOMER; if (!(w->disabled_widgets & (1LL << widgetIndex))) { rct_widget *widget = &w->widgets[widgetIndex]; sint32 spriteIndex = 0; if (w->page == WINDOW_RIDE_PAGE_CUSTOMER) spriteIndex = w->var_492 & ~3; spriteIndex += g_peep_animation_entries[PEEP_SPRITE_TYPE_NORMAL].sprite_animation->base_image; spriteIndex += 1; spriteIndex |= 0xA9E00000; gfx_draw_sprite(dpi, spriteIndex, w->x + (widget->left + widget->right) / 2, w->y + widget->bottom - 6, 0); } } /** * * rct2: 0x006B2B35 */ static void window_ride_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w) { window_ride_draw_tab_vehicle(dpi, w); window_ride_draw_tab_image(dpi, w, WINDOW_RIDE_PAGE_OPERATING, SPR_TAB_GEARS_0); window_ride_draw_tab_image(dpi, w, WINDOW_RIDE_PAGE_MAINTENANCE, SPR_TAB_WRENCH_0); window_ride_draw_tab_image(dpi, w, WINDOW_RIDE_PAGE_INCOME, SPR_TAB_ADMISSION_0); window_ride_draw_tab_main(dpi, w); window_ride_draw_tab_image(dpi, w, WINDOW_RIDE_PAGE_MEASUREMENTS, SPR_TAB_TIMER_0); window_ride_draw_tab_image(dpi, w, WINDOW_RIDE_PAGE_COLOUR, SPR_TAB_PAINT_0); window_ride_draw_tab_image(dpi, w, WINDOW_RIDE_PAGE_GRAPHS, SPR_TAB_GRAPH_A_0); window_ride_draw_tab_customer(dpi, w); window_ride_draw_tab_image(dpi, w, WINDOW_RIDE_PAGE_MUSIC, SPR_TAB_MUSIC_0); } /** * * rct2: 0x006AEB9F */ static void window_ride_disable_tabs(rct_window *w) { uint32 disabled_tabs = 0; rct_ride *ride = get_ride(w->number & 0xFF); uint8 ride_type = ride->type; // ecx if (!ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_HAS_DATA_LOGGING)) disabled_tabs |= (1 << WIDX_TAB_8); // 0x800 if (ride_type == RIDE_TYPE_MINI_GOLF) disabled_tabs |= (1 << WIDX_TAB_2 | 1 << WIDX_TAB_3 | 1 << WIDX_TAB_4); // 0xE0 if (ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_NO_VEHICLES)) disabled_tabs |= (1 << WIDX_TAB_2); // 0x20 if ( !ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_MAIN) && !ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_ADDITIONAL) && !ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_SUPPORTS) && !ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_HAS_VEHICLE_COLOURS) && !(RideData4[ride->type].flags & RIDE_TYPE_FLAG4_HAS_ENTRANCE_EXIT) ) { disabled_tabs |= (1 << WIDX_TAB_5); // 0x100 } if (ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_IS_SHOP)) disabled_tabs |= (1 << WIDX_TAB_3 | 1 << WIDX_TAB_4 | 1 << WIDX_TAB_7); // 0x4C0 if (!(RideData4[ride->type].flags & RIDE_TYPE_FLAG4_ALLOW_MUSIC)) { disabled_tabs |= (1 << WIDX_TAB_6); // 0x200 } if (ride_type == RIDE_TYPE_CASH_MACHINE || ride_type == RIDE_TYPE_FIRST_AID || (gParkFlags & PARK_FLAGS_NO_MONEY) != 0) disabled_tabs |= (1 << WIDX_TAB_9); // 0x1000 if ((gScreenFlags & SCREEN_FLAGS_TRACK_DESIGNER) != 0) disabled_tabs |= (1 << WIDX_TAB_4 | 1 << WIDX_TAB_6 | 1 << WIDX_TAB_9 | 1 << WIDX_TAB_10); // 0x3280 rct_ride_entry *type = get_ride_entry(ride->subtype); if (type == NULL) { disabled_tabs |= 1 << WIDX_TAB_2 | 1 << WIDX_TAB_3 | 1 << WIDX_TAB_4 | 1 << WIDX_TAB_5 | 1 << WIDX_TAB_6 | 1 << WIDX_TAB_7 | 1 << WIDX_TAB_8 | 1 << WIDX_TAB_9 | 1 << WIDX_TAB_10; } else if ((type->flags & RIDE_ENTRY_FLAG_DISABLE_COLOUR_TAB) != 0) disabled_tabs |= (1 << WIDX_TAB_5); // 0x100 w->disabled_widgets = disabled_tabs; } static void window_ride_update_overall_view(uint8 ride_index) { // Calculate x, y, z bounds of the entire ride using its track elements map_element_iterator it; map_element_iterator_begin(&it); sint32 minx = INT_MAX, miny = INT_MAX, minz = INT_MAX; sint32 maxx = INT_MIN, maxy = INT_MIN, maxz = INT_MIN; while (map_element_iterator_next(&it)) { if (map_element_get_type(it.element) != MAP_ELEMENT_TYPE_TRACK) continue; if (it.element->properties.track.ride_index != ride_index) continue; sint32 x = it.x * 32; sint32 y = it.y * 32; sint32 z1 = it.element->base_height * 8; sint32 z2 = it.element->clearance_height * 8; minx = min(minx, x); miny = min(miny, y); minz = min(minz, z1); maxx = max(maxx, x); maxy = max(maxy, y); maxz = max(maxz, z2); } ride_overall_view *view = &ride_overall_views[ride_index]; view->x = (minx + maxx) / 2; view->y = (miny + maxy) / 2; view->z = (minz + maxz) / 2 + 8; // Calculate size to determine from how far away to view the ride sint32 dx = maxx - minx; sint32 dy = maxy - miny; sint32 dz = maxz - minz; sint32 size = (sint32) sqrt(dx*dx + dy*dy + dz*dz); // Each farther zoom level shows twice as many tiles (log) // Appropriate zoom is lowered by one to fill the entire view with the ride double zoom = ceil(log(size / 80)) - 1; view->zoom = (uint8)clamp(0, zoom, 3); } /** * * rct2: 0x006AEAB4 */ static rct_window *window_ride_open(sint32 rideIndex) { rct_window *w; rct_ride *ride; w = window_create_auto_pos(316, 207, window_ride_page_events[0], WC_RIDE, WF_10 | WF_RESIZABLE); w->widgets = window_ride_page_widgets[WINDOW_RIDE_PAGE_MAIN]; w->enabled_widgets = window_ride_page_enabled_widgets[WINDOW_RIDE_PAGE_MAIN]; w->number = rideIndex; w->page = 0; w->var_48C = 0; w->frame_no = 0; w->list_information_type = 0; w->var_492 = 0; w->ride_colour = 0; window_ride_disable_tabs(w); w->min_width = 316; w->min_height = 180; w->max_width = 500; w->max_height = 450; ride = get_ride(rideIndex); _rideType = ride->type; window_ride_update_overall_view((uint8) rideIndex); return w; } /** * * rct2: 0x006ACC28 */ rct_window *window_ride_main_open(sint32 rideIndex) { rct_window *w; w = window_bring_to_front_by_number(WC_RIDE, rideIndex); if (w == NULL) { w = window_ride_open(rideIndex); w->ride.var_482 = -1; } if (input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) { if (w->classification == gCurrentToolWidget.window_classification && w->number == gCurrentToolWidget.window_number ) { tool_cancel(); } } if (w->page != WINDOW_RIDE_PAGE_MAIN) { window_ride_set_page(w, WINDOW_RIDE_PAGE_MAIN); } w->ride.view = 0; window_ride_init_viewport(w); return w; } /** * * rct2: 0x006ACCCE */ rct_window *window_ride_open_station(sint32 rideIndex, sint32 stationIndex) { sint32 i; rct_ride *ride; rct_window *w; ride = get_ride(rideIndex); if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_VEHICLES)) return window_ride_main_open(rideIndex); w = window_bring_to_front_by_number(WC_RIDE, rideIndex); if (w == NULL) { w = window_ride_open(rideIndex); w->ride.var_482 = -1; } if ( input_test_flag(INPUT_FLAG_TOOL_ACTIVE) && gCurrentToolWidget.window_classification == w->classification && gCurrentToolWidget.window_number == w->number ) { tool_cancel(); } _rideType = ride->type; w->page = WINDOW_RIDE_PAGE_MAIN; w->width = 316; w->height = 180; window_invalidate(w); w->widgets = window_ride_page_widgets[w->page]; w->enabled_widgets = window_ride_page_enabled_widgets[w->page]; w->hold_down_widgets = window_ride_page_hold_down_widgets[w->page]; w->event_handlers = window_ride_page_events[w->page]; w->pressed_widgets = 0; window_ride_disable_tabs(w); window_init_scroll_widgets(w); // View for (i = stationIndex; i >= 0; i--) { if (ride->station_starts[i] == 0xFFFF) stationIndex--; } w->ride.view = 1 + ride->num_vehicles + stationIndex; window_ride_init_viewport(w); return w; } rct_window *window_ride_open_track(rct_map_element *mapElement) { sint32 rideIndex = mapElement->properties.track.ride_index; if ( (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) || (TrackSequenceProperties[mapElement->properties.track.type][0] & TRACK_SEQUENCE_FLAG_ORIGIN) ) { // Open ride window in station view return window_ride_open_station(rideIndex, map_get_station(mapElement)); } else { // Open ride window in overview mode. return window_ride_main_open(rideIndex); } } /** * * rct2: 0x006ACAC2 */ rct_window *window_ride_open_vehicle(rct_vehicle *vehicle) { rct_vehicle *headVehicle = vehicle_get_head(vehicle); uint16 headVehicleSpriteIndex = headVehicle->sprite_index; sint32 rideIndex = headVehicle->ride; rct_ride *ride = get_ride(rideIndex); // Get view index sint32 view = 1; for (sint32 i = 0; i < MAX_VEHICLES_PER_RIDE; i++) { if (ride->vehicles[i] == headVehicleSpriteIndex) break; view++; } rct_window *w = window_find_by_number(WC_RIDE, rideIndex); if (w != NULL) { window_invalidate(w); if ( input_test_flag(INPUT_FLAG_TOOL_ACTIVE) && gCurrentToolWidget.window_classification == w->classification && gCurrentToolWidget.window_number == w->number ) { tool_cancel(); } sint32 openedPeepWindow = 0; if (w->ride.view == view) { sint32 numPeepsLeft = vehicle->num_peeps; for (sint32 i = 0; i < 32 && numPeepsLeft > 0; i++) { uint16 peepSpriteIndex = vehicle->peep[i]; if (peepSpriteIndex == SPRITE_INDEX_NULL) continue; numPeepsLeft--; rct_window *w2 = window_find_by_number(WC_PEEP, peepSpriteIndex); if (w2 == NULL) { rct_peep *peep = &(get_sprite(peepSpriteIndex)->peep); window_guest_open(peep); openedPeepWindow = 1; break; } } } w = openedPeepWindow ? window_find_by_number(WC_RIDE, rideIndex) : window_bring_to_front_by_number(WC_RIDE, rideIndex); } if (w == NULL) { w = window_ride_open(rideIndex); w->ride.var_482 = -1; } _rideType = ride->type; w->page = WINDOW_RIDE_PAGE_MAIN; w->width = 316; w->height = 180; window_invalidate(w); w->widgets = window_ride_page_widgets[w->page]; w->enabled_widgets = window_ride_page_enabled_widgets[w->page]; w->hold_down_widgets = window_ride_page_hold_down_widgets[w->page]; w->event_handlers = window_ride_page_events[w->page]; w->pressed_widgets = 0; window_ride_disable_tabs(w); window_init_scroll_widgets(w); w->ride.view = view; window_ride_init_viewport(w); window_invalidate(w); return w; } /** * * rct2: 0x006AF1D2 */ static void window_ride_set_page(rct_window *w, sint32 page) { sint32 listen; if (input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) if (w->classification == gCurrentToolWidget.window_classification && w->number == gCurrentToolWidget.window_number) tool_cancel(); // Set listen only to viewport listen = 0; if (page == WINDOW_RIDE_PAGE_MAIN && w->page == WINDOW_RIDE_PAGE_MAIN && w->viewport != NULL && !(w->viewport->flags & VIEWPORT_FLAG_SOUND_ON)) listen++; w->page = page; w->frame_no = 0; w->var_492 = 0; //There doesn't seem to be any need for this call, and it can sometimes modify the reported number of cars per train, so I've removed it //if (page == WINDOW_RIDE_PAGE_VEHICLE) { //ride_update_max_vehicles(w->number); //} if (w->viewport != NULL) { w->viewport->width = 0; w->viewport = NULL; } w->enabled_widgets = window_ride_page_enabled_widgets[page]; w->hold_down_widgets = window_ride_page_hold_down_widgets[page]; w->event_handlers = window_ride_page_events[page]; w->pressed_widgets = 0; w->widgets = window_ride_page_widgets[page]; window_ride_disable_tabs(w); window_invalidate(w); window_event_resize_call(w); window_event_invalidate_call(w); window_init_scroll_widgets(w); window_invalidate(w); if (listen != 0 && w->viewport != NULL) w->viewport->flags |= VIEWPORT_FLAG_SOUND_ON; } static void window_ride_set_pressed_tab(rct_window *w) { sint32 i; for (i = 0; i < WINDOW_RIDE_PAGE_COUNT; i++) w->pressed_widgets &= ~(1 << (WIDX_TAB_1 + i)); w->pressed_widgets |= 1LL << (WIDX_TAB_1 + w->page); } static void window_ride_anchor_border_widgets(rct_window *w) { w->widgets[WIDX_BACKGROUND].right = w->width - 1; w->widgets[WIDX_BACKGROUND].bottom = w->height - 1; w->widgets[WIDX_PAGE_BACKGROUND].right = w->width - 1; w->widgets[WIDX_PAGE_BACKGROUND].bottom = w->height - 1; w->widgets[WIDX_TITLE].right = w->width - 2; w->widgets[WIDX_CLOSE].left = w->width - 13; w->widgets[WIDX_CLOSE].right = w->width - 3; } #pragma region Main /** * * rct2: 0x006AF994 */ static void window_ride_init_viewport(rct_window *w) { if (w->page != WINDOW_RIDE_PAGE_MAIN) return; rct_ride* ride = get_ride(w->number); sint32 eax = w->viewport_focus_coordinates.var_480 - 1; union{ sprite_focus sprite; coordinate_focus coordinate; } focus; focus.coordinate.x = 0; focus.coordinate.y = 0; focus.coordinate.z = 0; focus.sprite.sprite_id = SPRITE_INDEX_NULL; focus.coordinate.zoom = 0; focus.coordinate.rotation = get_current_rotation(); focus.coordinate.width = 0; focus.coordinate.height = 0; if (eax >= 0 && eax < ride->num_vehicles && ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK){ focus.sprite.sprite_id = ride->vehicles[eax]; rct_ride_entry* ride_entry = get_ride_entry_by_ride(ride); if (ride_entry && ride_entry->tab_vehicle != 0){ rct_vehicle* vehicle = GET_VEHICLE(focus.sprite.sprite_id); if (vehicle->next_vehicle_on_train != SPRITE_INDEX_NULL) { focus.sprite.sprite_id = vehicle->next_vehicle_on_train; } } if (focus.sprite.sprite_id != SPRITE_INDEX_NULL) { focus.sprite.type |= VIEWPORT_FOCUS_TYPE_SPRITE; } } else if (eax >= ride->num_vehicles && eax < (ride->num_vehicles + ride->num_stations)){ sint32 stationIndex = -1; sint32 count = eax - ride->num_vehicles; do { stationIndex++; if (ride->station_starts[stationIndex] != 0xFFFF) count--; } while (count >= 0); eax = ride->station_starts[stationIndex]; focus.coordinate.x = (eax & 0xFF) << 5; focus.coordinate.y = (eax & 0xFF00) >> 3; focus.coordinate.z = ride->station_heights[stationIndex] << 3; focus.sprite.type |= VIEWPORT_FOCUS_TYPE_COORDINATE; } else{ if (eax > 0){ w->viewport_focus_coordinates.var_480 = 0; } ride_overall_view *view = &ride_overall_views[w->number]; focus.coordinate.x = view->x; focus.coordinate.y = view->y; focus.coordinate.z = view->z; focus.coordinate.zoom = view->zoom; focus.sprite.type |= VIEWPORT_FOCUS_TYPE_COORDINATE; } focus.coordinate.var_480 = w->viewport_focus_coordinates.var_480; uint16 viewport_flags = 0; if (w->viewport != NULL) { if (focus.coordinate.x == w->viewport_focus_coordinates.x && focus.coordinate.y == w->viewport_focus_coordinates.y && focus.coordinate.z == w->viewport_focus_coordinates.z && focus.coordinate.rotation == w->viewport_focus_coordinates.rotation && focus.coordinate.zoom == w->viewport_focus_coordinates.zoom && focus.coordinate.width == w->width && focus.coordinate.height == w->height ) { return; } viewport_flags = w->viewport->flags; w->viewport->width = 0; w->viewport = NULL; viewport_update_pointers(); } else if (gConfigGeneral.always_show_gridlines) { viewport_flags |= VIEWPORT_FLAG_GRIDLINES; } window_event_invalidate_call(w); w->viewport_focus_coordinates.x = focus.coordinate.x; w->viewport_focus_coordinates.y = focus.coordinate.y; w->viewport_focus_coordinates.z = focus.coordinate.z; w->viewport_focus_coordinates.rotation = focus.coordinate.rotation; w->viewport_focus_coordinates.zoom = focus.coordinate.zoom; w->viewport_focus_coordinates.width = w->width; w->viewport_focus_coordinates.height = w->height; //rct2: 0x006aec9c only used here so brought it into the function if (!w->viewport && ride->overall_view != 0xFFFF){ rct_widget* view_widget = &w->widgets[WIDX_VIEWPORT]; sint32 x = view_widget->left + 1 + w->x; sint32 y = view_widget->top + 1 + w->y; sint32 width = view_widget->right - view_widget->left - 1; sint32 height = view_widget->bottom - view_widget->top - 1; viewport_create( w, x, y, width, height, focus.coordinate.zoom, focus.coordinate.x, focus.coordinate.y & VIEWPORT_FOCUS_Y_MASK, focus.coordinate.z, focus.sprite.type & VIEWPORT_FOCUS_TYPE_MASK, focus.sprite.sprite_id); w->flags |= WF_NO_SCROLLING; window_invalidate(w); } if (w->viewport){ w->viewport->flags = viewport_flags; window_invalidate(w); } } /** * * rct2: 0x006AF315 */ static void window_ride_rename(rct_window *w) { rct_ride *ride; ride = get_ride(w->number); set_format_arg(16, uint32, ride->name_arguments); window_text_input_open(w, WIDX_RENAME, STR_RIDE_ATTRACTION_NAME, STR_ENTER_NEW_NAME_FOR_THIS_RIDE_ATTRACTION, ride->name, ride->name_arguments, 32); } /** * * rct2: 0x006AF17E */ static void window_ride_main_mouseup(rct_window *w, rct_widgetindex widgetIndex) { uint8 rideIndex; rct_ride *ride; sint32 status; switch (widgetIndex) { case WIDX_CLOSE: window_close(w); break; case WIDX_TAB_1: case WIDX_TAB_2: case WIDX_TAB_3: case WIDX_TAB_4: case WIDX_TAB_5: case WIDX_TAB_6: case WIDX_TAB_7: case WIDX_TAB_8: case WIDX_TAB_9: case WIDX_TAB_10: window_ride_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_CONSTRUCTION: rideIndex = (uint8)w->number; ride_construct(rideIndex); if (window_find_by_number(WC_RIDE_CONSTRUCTION, rideIndex) != NULL) { window_close(w); } break; case WIDX_RENAME: window_ride_rename(w); break; case WIDX_LOCATE: window_scroll_to_viewport(w); break; case WIDX_DEMOLISH: window_ride_demolish_prompt_open(w->number); break; case WIDX_CLOSE_LIGHT: case WIDX_TEST_LIGHT: case WIDX_OPEN_LIGHT: ride = get_ride(w->number); switch (widgetIndex) { default: case WIDX_CLOSE_LIGHT: status = RIDE_STATUS_CLOSED; gGameCommandErrorTitle = STR_CANT_CLOSE; break; case WIDX_TEST_LIGHT: status = RIDE_STATUS_TESTING; gGameCommandErrorTitle = STR_CANT_TEST; break; case WIDX_OPEN_LIGHT: status = RIDE_STATUS_OPEN; gGameCommandErrorTitle = STR_CANT_OPEN; break; } set_format_arg(6, rct_string_id, ride->name); set_format_arg(8, uint32, ride->name_arguments); ride_set_status(w->number, status); break; } } /** * * rct2: 0x006AF4A2 */ static void window_ride_main_resize(rct_window *w) { const sint32 offset = gCheatsAllowArbitraryRideTypeChanges ? 15 : 0; w->flags |= WF_RESIZABLE; sint32 minHeight = 180 + offset; if (theme_get_flags() & UITHEME_FLAG_USE_LIGHTS_RIDE) minHeight = 200 + offset + RCT1_LIGHT_OFFSET - (ride_type_has_flag(get_ride(w->number)->type, RIDE_TYPE_FLAG_NO_TEST_MODE) ? 14 : 0); window_set_resize(w, 316, minHeight, 500, 450); window_ride_init_viewport(w); } /** * * rct2: 0x006AF825 */ static void window_ride_show_view_dropdown(rct_window *w, rct_widget *widget) { rct_widget *dropdownWidget = widget - 1; rct_ride *ride = get_ride(w->number); sint32 numItems = 1; if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_VEHICLES)) { numItems += ride->num_stations; numItems += ride->num_vehicles; } window_dropdown_show_text_custom_width( w->x + dropdownWidget->left, w->y + dropdownWidget->top, dropdownWidget->bottom - dropdownWidget->top + 1, w->colours[1], 0, 0, numItems, widget->right - dropdownWidget->left ); // First item gDropdownItemsFormat[0] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[0] = STR_OVERALL_VIEW; sint32 currentItem = 1; // Vehicles sint32 name = RideComponentNames[RideNameConvention[ride->type].vehicle].number; for (sint32 i = 1; i <= ride->num_vehicles; i++) { gDropdownItemsFormat[currentItem] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[currentItem] = name | (currentItem << 16); currentItem++; } // Stations name = RideComponentNames[RideNameConvention[ride->type].station].number; for (sint32 i = 1; i <= ride->num_stations; i++) { gDropdownItemsFormat[currentItem] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[currentItem] = name | (i << 16); currentItem++; } // Set highlighted item if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)) { sint32 j = 2; for (sint32 i = 0; i < ride->num_vehicles; i++) { gDropdownItemsDisabled |= j; j <<= 1; } } // Set checked item dropdown_set_checked(w->ride.view, true); } /** * * rct2: 0x006AF64C */ static void window_ride_show_open_dropdown(rct_window *w, rct_widget *widget) { rct_ride *ride; sint32 numItems, highlightedIndex = 0, checkedIndex; ride = get_ride(w->number); numItems = 0; gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[numItems] = STR_CLOSE_RIDE; numItems++; if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE)) { gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[numItems] = STR_TEST_RIDE; numItems++; } gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[numItems] = STR_OPEN_RIDE; numItems++; window_dropdown_show_text( w->x + widget->left, w->y + widget->top, widget->bottom - widget->top + 1, w->colours[1], 0, numItems ); checkedIndex = ride->status; switch (ride->status) { case RIDE_STATUS_CLOSED: highlightedIndex = 0; if ((ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED) || (ride->lifecycle_flags & RIDE_LIFECYCLE_HAS_STALLED_VEHICLE)) break; highlightedIndex = 2; if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE)) break; if (ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED) break; highlightedIndex = 1; break; case RIDE_STATUS_TESTING: highlightedIndex = 2; if (ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED) break; highlightedIndex = 0; break; case RIDE_STATUS_OPEN: highlightedIndex = 0; break; } if (checkedIndex != RIDE_STATUS_CLOSED) checkedIndex = 3 - checkedIndex; if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE)) { if (checkedIndex != 0) checkedIndex--; if (highlightedIndex != 0) highlightedIndex--; } dropdown_set_checked(checkedIndex, true); gDropdownDefaultIndex = highlightedIndex; } /** * * rct2: 0x006AF1BD */ static void window_ride_main_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget) { switch (widgetIndex) { case WIDX_VIEW_DROPDOWN: window_ride_show_view_dropdown(w, widget); break; case WIDX_OPEN: window_ride_show_open_dropdown(w, widget); break; case WIDX_RIDE_TYPE_INCREASE: if (_rideType >= 90) { _rideType = 90; } else { _rideType++; } widget_invalidate(w, WIDX_RIDE_TYPE); break; case WIDX_RIDE_TYPE_DECREASE: if (_rideType == 0) { _rideType = 0; } else { _rideType--; } widget_invalidate(w, WIDX_RIDE_TYPE); break; case WIDX_RIDE_TYPE_APPLY: if (_rideType <= 90) { set_operating_setting(w->number, RIDE_SETTING_RIDE_TYPE, _rideType); } window_invalidate_all(); break; } } /** * * rct2: 0x006AF300 */ static void window_ride_main_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex) { rct_ride *ride; sint32 status = 0; switch (widgetIndex) { case WIDX_VIEW_DROPDOWN: if (dropdownIndex == -1) { dropdownIndex = w->ride.view; ride = get_ride(w->number); dropdownIndex++; if (dropdownIndex != 0 && dropdownIndex <= ride->num_vehicles && !(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)) dropdownIndex = ride->num_vehicles + 1; if (dropdownIndex >= gDropdownNumItems) dropdownIndex = 0; } w->ride.view = dropdownIndex; window_ride_init_viewport(w); window_invalidate(w); break; case WIDX_OPEN: if (dropdownIndex == -1) dropdownIndex = gDropdownHighlightedIndex; ride = get_ride(w->number); if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE) && dropdownIndex != 0) dropdownIndex++; switch (dropdownIndex) { case 0: status = RIDE_STATUS_CLOSED; gGameCommandErrorTitle = STR_CANT_CLOSE; break; case 1: status = RIDE_STATUS_TESTING; gGameCommandErrorTitle = STR_CANT_TEST; break; case 2: status = RIDE_STATUS_OPEN; gGameCommandErrorTitle = STR_CANT_OPEN; break; } set_format_arg(6, rct_string_id, ride->name); set_format_arg(8, uint32, ride->name_arguments); ride_set_status(w->number, status); break; } } /** * * rct2: 0x006AF40F */ static void window_ride_main_update(rct_window *w) { // Update tab animation w->frame_no++; window_event_invalidate_call(w); widget_invalidate(w, WIDX_TAB_1); // Update status rct_ride *ride = get_ride(w->number); if (!(ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_MAIN)) { if (w->ride.view == 0) return; if (w->ride.view <= ride->num_vehicles) { sint32 vehicleIndex = w->ride.view - 1; uint16 vehicleSpriteIndex = ride->vehicles[vehicleIndex]; if (vehicleSpriteIndex == SPRITE_INDEX_NULL) return; rct_vehicle *vehicle = &(get_sprite(vehicleSpriteIndex)->vehicle); if ( vehicle->status != 4 && vehicle->status != 22 && vehicle->status != 10 && vehicle->status != 7 ) { return; } } } ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_MAIN; widget_invalidate(w, WIDX_STATUS); } /** * * rct2: 0x006AF2F9 */ static void window_ride_main_textinput(rct_window *w, rct_widgetindex widgetIndex, char *text) { if (widgetIndex != WIDX_RENAME || text == NULL) return; ride_set_name(w->number, text); } /** * * rct2: 0x006AF55A */ static void window_ride_main_viewport_rotate(rct_window *w) { window_ride_init_viewport(w); } /** * * rct2: 0x006AECF6 */ static void window_ride_main_invalidate(rct_window *w) { rct_widget *widgets; sint32 i, height; widgets = window_ride_page_widgets[w->page]; if (w->widgets != widgets) { w->widgets = widgets; window_init_scroll_widgets(w); } window_ride_set_pressed_tab(w); rct_ride *ride = get_ride(w->number); w->disabled_widgets &= ~((1 << WIDX_DEMOLISH) | (1 << WIDX_CONSTRUCTION)); if (ride->lifecycle_flags & (RIDE_LIFECYCLE_INDESTRUCTIBLE | RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK)) w->disabled_widgets |= (1 << WIDX_DEMOLISH); set_format_arg(0, rct_string_id, ride->name); set_format_arg(2, uint32, ride->name_arguments); set_format_arg(6, uint16, RideNaming[_rideType].name); uint32 spriteIds[] = { SPR_CLOSED, SPR_OPEN, SPR_TESTING, }; window_ride_main_widgets[WIDX_OPEN].image = spriteIds[ride->status]; window_ride_main_widgets[WIDX_CLOSE_LIGHT].image = SPR_G2_RCT1_CLOSE_BUTTON_0 + (ride->status == RIDE_STATUS_CLOSED) * 2 + widget_is_pressed(w, WIDX_CLOSE_LIGHT); window_ride_main_widgets[WIDX_TEST_LIGHT].image = SPR_G2_RCT1_TEST_BUTTON_0 + (ride->status == RIDE_STATUS_TESTING) * 2 + widget_is_pressed(w, WIDX_TEST_LIGHT); window_ride_main_widgets[WIDX_OPEN_LIGHT].image = SPR_G2_RCT1_OPEN_BUTTON_0 + (ride->status == RIDE_STATUS_OPEN) * 2 + widget_is_pressed(w, WIDX_OPEN_LIGHT); window_ride_anchor_border_widgets(w); const sint32 offset = gCheatsAllowArbitraryRideTypeChanges ? 15 : 0; // Anchor main page specific widgets window_ride_main_widgets[WIDX_VIEWPORT].right = w->width - 26; window_ride_main_widgets[WIDX_VIEWPORT].bottom = w->height - (14 + offset); window_ride_main_widgets[WIDX_STATUS].right = w->width - 26; window_ride_main_widgets[WIDX_STATUS].top = w->height - (13 + offset); window_ride_main_widgets[WIDX_STATUS].bottom = w->height - (3 + offset); window_ride_main_widgets[WIDX_VIEW].right = w->width - 60; window_ride_main_widgets[WIDX_VIEW_DROPDOWN].right = w->width - 61; window_ride_main_widgets[WIDX_VIEW_DROPDOWN].left = w->width - 71; window_ride_main_widgets[WIDX_RIDE_TYPE].right = w->width - 87; window_ride_main_widgets[WIDX_RIDE_TYPE].top = w->height - 17; window_ride_main_widgets[WIDX_RIDE_TYPE].bottom = w->height - 4; window_ride_main_widgets[WIDX_RIDE_TYPE_INCREASE].right = w->width - 88; window_ride_main_widgets[WIDX_RIDE_TYPE_INCREASE].left = w->width - 98; window_ride_main_widgets[WIDX_RIDE_TYPE_INCREASE].top = w->height - 16; window_ride_main_widgets[WIDX_RIDE_TYPE_INCREASE].bottom = w->height - 11; window_ride_main_widgets[WIDX_RIDE_TYPE_DECREASE].right = w->width - 88; window_ride_main_widgets[WIDX_RIDE_TYPE_DECREASE].left = w->width - 98; window_ride_main_widgets[WIDX_RIDE_TYPE_DECREASE].top = w->height - 10; window_ride_main_widgets[WIDX_RIDE_TYPE_DECREASE].bottom = w->height - 5; window_ride_main_widgets[WIDX_RIDE_TYPE_APPLY].left = w->width - 83; window_ride_main_widgets[WIDX_RIDE_TYPE_APPLY].right = w->width - 26; window_ride_main_widgets[WIDX_RIDE_TYPE_APPLY].top = w->height - 17; window_ride_main_widgets[WIDX_RIDE_TYPE_APPLY].bottom = w->height - 4; if (!gCheatsAllowArbitraryRideTypeChanges) { window_ride_main_widgets[WIDX_RIDE_TYPE].type = WWT_EMPTY; window_ride_main_widgets[WIDX_RIDE_TYPE_INCREASE].type = WWT_EMPTY; window_ride_main_widgets[WIDX_RIDE_TYPE_DECREASE].type = WWT_EMPTY; window_ride_main_widgets[WIDX_RIDE_TYPE_APPLY].type = WWT_EMPTY; } else { window_ride_main_widgets[WIDX_RIDE_TYPE].type = WWT_SPINNER; window_ride_main_widgets[WIDX_RIDE_TYPE_INCREASE].type = WWT_DROPDOWN_BUTTON; window_ride_main_widgets[WIDX_RIDE_TYPE_DECREASE].type = WWT_DROPDOWN_BUTTON; window_ride_main_widgets[WIDX_RIDE_TYPE_APPLY].type = WWT_CLOSEBOX; } window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); if (theme_get_flags() & UITHEME_FLAG_USE_LIGHTS_RIDE) { window_ride_main_widgets[WIDX_OPEN].type = WWT_EMPTY; window_ride_main_widgets[WIDX_CLOSE_LIGHT].type = WWT_IMGBTN; window_ride_main_widgets[WIDX_TEST_LIGHT].type = (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE) ? WWT_EMPTY : WWT_IMGBTN); window_ride_main_widgets[WIDX_OPEN_LIGHT].type = WWT_IMGBTN; height = 62; if (window_ride_main_widgets[WIDX_TEST_LIGHT].type != WWT_EMPTY) { window_ride_main_widgets[WIDX_TEST_LIGHT].top = height; window_ride_main_widgets[WIDX_TEST_LIGHT].bottom = height + 13; height += 14; } window_ride_main_widgets[WIDX_OPEN_LIGHT].top = height; window_ride_main_widgets[WIDX_OPEN_LIGHT].bottom = height + 13; height += 14 - 24 + RCT1_LIGHT_OFFSET; w->min_height = 200 + RCT1_LIGHT_OFFSET - (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE) ? 14 : 0); if (w->height < w->min_height) window_event_resize_call(w); } else { window_ride_main_widgets[WIDX_OPEN].type = WWT_FLATBTN; window_ride_main_widgets[WIDX_CLOSE_LIGHT].type = WWT_EMPTY; window_ride_main_widgets[WIDX_TEST_LIGHT].type = WWT_EMPTY; window_ride_main_widgets[WIDX_OPEN_LIGHT].type = WWT_EMPTY; height = 46; } for (i = WIDX_CLOSE_LIGHT; i <= WIDX_OPEN_LIGHT; i++) { window_ride_main_widgets[i].left = w->width - 20; window_ride_main_widgets[i].right = w->width - 7; } for (i = WIDX_OPEN; i <= WIDX_DEMOLISH; i++, height += 24) { window_ride_main_widgets[i].left = w->width - 25; window_ride_main_widgets[i].right = w->width - 2; window_ride_main_widgets[i].top = height; window_ride_main_widgets[i].bottom = height + 23; } } /** * * rct2: 0x006AF10A */ static rct_string_id window_ride_get_status_overall_view(rct_window *w, void *arguments) { sint32 argument; rct_string_id formatSecondary, stringId; ride_get_status(w->number, &formatSecondary, &argument); *(uint16*)((uintptr_t)arguments + 0) = formatSecondary; *(uintptr_t*)((uintptr_t)arguments + 2) = argument; stringId = STR_RED_OUTLINED_STRING; if (formatSecondary != STR_BROKEN_DOWN && formatSecondary != STR_CRASHED) stringId = STR_BLACK_STRING; return stringId; } /** * * rct2: 0x006AEFEF */ static rct_string_id window_ride_get_status_vehicle(rct_window *w, void *arguments) { rct_ride *ride; rct_vehicle *vehicle; sint32 vehicleIndex; uint16 vehicleSpriteIndex; rct_string_id stringId; ride = get_ride(w->number); vehicleIndex = w->ride.view - 1; vehicleSpriteIndex = ride->vehicles[vehicleIndex]; if (vehicleSpriteIndex == SPRITE_INDEX_NULL) return 0; vehicle = &(get_sprite(vehicleSpriteIndex)->vehicle); if (vehicle->status != VEHICLE_STATUS_CRASHING && vehicle->status != VEHICLE_STATUS_CRASHED) { sint32 trackType = vehicle->track_type >> 2; if (trackType == TRACK_ELEM_BLOCK_BRAKES || trackType == TRACK_ELEM_CABLE_LIFT_HILL || trackType == TRACK_ELEM_25_DEG_UP_TO_FLAT || trackType == TRACK_ELEM_60_DEG_UP_TO_FLAT || trackType == TRACK_ELEM_DIAG_25_DEG_UP_TO_FLAT || trackType == TRACK_ELEM_DIAG_60_DEG_UP_TO_FLAT) { if (track_piece_is_available_for_ride_type(ride->type, TRACK_BLOCK_BRAKES) && vehicle->velocity == 0) { *(rct_string_id*)(uintptr_t)arguments = STR_STOPPED_BY_BLOCK_BRAKES; return STR_BLACK_STRING; } } } stringId = VehicleStatusNames[vehicle->status]; // Get speed in mph *((uint16*)((uintptr_t)arguments + 2)) = (abs(vehicle->velocity) * 9) >> 18; if (ride->type == RIDE_TYPE_MINI_GOLF) return 0; if ((RideData4[ride->type].flags & RIDE_TYPE_FLAG4_SINGLE_SESSION) && vehicle->status <= VEHICLE_STATUS_UNLOADING_PASSENGERS) { stringId = SingleSessionVehicleStatusNames[vehicle->status]; } const ride_component_name stationName = RideComponentNames[RideNameConvention[ride->type].station]; *(rct_string_id*)((uintptr_t)arguments + 4) = (ride->num_stations > 1) ? stationName.number : stationName.singular; *((uint16*)((uintptr_t)arguments + 6)) = vehicle->current_station + 1; *(rct_string_id*)((uintptr_t)arguments + 0) = stringId; return stringId != STR_CRASHING && stringId != STR_CRASHED_0 ? STR_BLACK_STRING : STR_RED_OUTLINED_STRING; } /** * * rct2: 0x006AEF65 */ static rct_string_id window_ride_get_status_station(rct_window *w, void *arguments) { rct_ride *ride = get_ride(w->number); sint32 count = w->ride.view - ride->num_vehicles - 1; sint32 stationIndex = -1; rct_string_id stringId = 0; do { stationIndex++; if (ride->station_starts[stationIndex] != 0xFFFF) count--; } while (count >= 0); // Entrance / exit if (ride->status == RIDE_STATUS_CLOSED) { if (ride->entrances[stationIndex] == 0xFFFF) stringId = STR_NO_ENTRANCE; else if (ride->exits[stationIndex] == 0xFFFF) stringId = STR_NO_EXIT; } else { if (ride->entrances[stationIndex] == 0xFFFF) stringId = STR_EXIT_ONLY; } // Queue length if (stringId == 0) { sint32 queueLength = ride->queue_length[stationIndex]; set_format_arg_body(arguments, 2, (uintptr_t)queueLength, sizeof(uint16)); stringId = STR_QUEUE_EMPTY; if (queueLength == 1) stringId = STR_QUEUE_ONE_PERSON; else if (queueLength > 1) stringId = STR_QUEUE_PEOPLE; } set_format_arg_body(arguments, 0, (uintptr_t)stringId, sizeof(rct_string_id)); return STR_BLACK_STRING; } /** * * rct2: 0x006AEE73 */ static rct_string_id window_ride_get_status(rct_window *w, void *arguments) { rct_ride *ride = get_ride(w->number); if (w->ride.view == 0) return window_ride_get_status_overall_view(w, arguments); if (w->ride.view <= ride->num_vehicles) return window_ride_get_status_vehicle(w, arguments); if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) return window_ride_get_status_overall_view(w, arguments); return window_ride_get_status_station(w, arguments); } /** * * rct2: 0x006AEE73 */ static void window_ride_main_paint(rct_window *w, rct_drawpixelinfo *dpi) { rct_ride *ride; rct_widget *widget; rct_string_id stringId; window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); // Viewport and ear icon if (w->viewport != NULL) { window_draw_viewport(dpi, w); if (w->viewport->flags & VIEWPORT_FLAG_SOUND_ON) gfx_draw_sprite(dpi, SPR_HEARING_VIEWPORT, w->x + 2, w->y + 2, 0); } // View dropdown ride = get_ride(w->number); stringId = STR_OVERALL_VIEW; if (w->ride.view != 0) { stringId = RideComponentNames[RideNameConvention[ride->type].vehicle].number; if (w->ride.view > ride->num_vehicles) { set_format_arg(2, uint16, w->ride.view - ride->num_vehicles); stringId = RideComponentNames[RideNameConvention[ride->type].station].number; } else { set_format_arg(2, uint16, w->ride.view); } } set_format_arg(0, uint16, stringId); widget = &window_ride_main_widgets[WIDX_VIEW]; gfx_draw_string_centred( dpi, STR_WINDOW_COLOUR_2_STRINGID, w->x + (widget->left + widget->right - 11) / 2, w->y + widget->top, COLOUR_BLACK, gCommonFormatArgs ); // Status widget = &window_ride_main_widgets[WIDX_STATUS]; gfx_draw_string_centred_clipped( dpi, window_ride_get_status(w, gCommonFormatArgs), gCommonFormatArgs, COLOUR_BLACK, w->x + (widget->left + widget->right) / 2, w->y + widget->top, widget->right - widget->left ); } #pragma endregion #pragma region Vehicle /** * * rct2: 0x006B272D */ static void window_ride_vehicle_mouseup(rct_window *w, rct_widgetindex widgetIndex) { switch (widgetIndex) { case WIDX_CLOSE: window_close(w); break; case WIDX_TAB_1: case WIDX_TAB_2: case WIDX_TAB_3: case WIDX_TAB_4: case WIDX_TAB_5: case WIDX_TAB_6: case WIDX_TAB_7: case WIDX_TAB_8: case WIDX_TAB_9: case WIDX_TAB_10: window_ride_set_page(w, widgetIndex - WIDX_TAB_1); break; } } /** * * rct2: 0x006B2ABB */ static void window_ride_vehicle_resize(rct_window *w) { window_set_resize(w, 316, 208, 316, 208); } /** * * rct2: 0x006B2748 */ static void window_ride_vehicle_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget) { rct_widget *dropdownWidget = widget - 1; rct_ride *ride; rct_ride_entry *rideEntry, *currentRideEntry; const ride_group * rideGroup, * currentRideGroup; sint32 numItems, rideEntryIndex, selectedIndex, rideTypeIterator, rideTypeIteratorMax; uint8 *rideEntryIndexPtr; bool selectionShouldBeExpanded; ride = get_ride(w->number); rideEntry = get_ride_entry_by_ride(ride); if(gCheatsShowVehiclesFromOtherTrackTypes && !(ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_FLAT_RIDE) || ride->type==RIDE_TYPE_MAZE || ride->type==RIDE_TYPE_MINI_GOLF)) { selectionShouldBeExpanded=true; rideTypeIterator=0; rideTypeIteratorMax=90; } else { selectionShouldBeExpanded=false; rideTypeIterator=ride->type; rideTypeIteratorMax=ride->type; } switch (widgetIndex) { case WIDX_VEHICLE_TYPE_DROPDOWN: selectedIndex = -1; numItems = 0; // Dropdowns with more items start acting weird, so cap it to 63. for (; rideTypeIterator<=rideTypeIteratorMax && numItems<=63; rideTypeIterator++) { if(selectionShouldBeExpanded && ride_type_has_flag(rideTypeIterator, RIDE_TYPE_FLAG_FLAT_RIDE)) continue; if(selectionShouldBeExpanded && (rideTypeIterator==RIDE_TYPE_MAZE || rideTypeIterator==RIDE_TYPE_MINI_GOLF)) continue; rideEntryIndexPtr = get_ride_entry_indices_for_ride_type(rideTypeIterator); for (uint8 *currentRideEntryIndex = rideEntryIndexPtr; *currentRideEntryIndex != RIDE_ENTRY_INDEX_NULL && numItems <= 63; currentRideEntryIndex++) { rideEntryIndex = *currentRideEntryIndex; currentRideEntry = get_ride_entry(rideEntryIndex); // Skip if vehicle wants to be separate, unless subtype switching is enabled if ((currentRideEntry->flags & (RIDE_ENTRY_FLAG_SEPARATE_RIDE | RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME)) && !(gConfigInterface.select_by_track_type || selectionShouldBeExpanded)) continue; // Skip if vehicle type is not invented yet if (!ride_entry_is_invented(rideEntryIndex)) continue; // Skip if vehicle does not belong to the same ride group if (track_type_has_ride_groups(ride->type) && !selectionShouldBeExpanded) { rideGroup = get_ride_group(ride->type, rideEntry); currentRideGroup = get_ride_group(ride->type, currentRideEntry); if (!ride_groups_are_equal(rideGroup, currentRideGroup)) continue; } if (ride->subtype == rideEntryIndex) selectedIndex = numItems; gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[numItems] = (rideEntryIndex << 16) | currentRideEntry->name; numItems++; } } window_dropdown_show_text_custom_width( w->x + dropdownWidget->left, w->y + dropdownWidget->top, dropdownWidget->bottom - dropdownWidget->top + 1, w->colours[1], 0, DROPDOWN_FLAG_STAY_OPEN, numItems, widget->right - dropdownWidget->left ); dropdown_set_checked(selectedIndex, true); break; case WIDX_VEHICLE_TRAINS_INCREASE: if (ride->num_vehicles < 32) ride_set_num_vehicles(w->number, ride->num_vehicles + 1); break; case WIDX_VEHICLE_TRAINS_DECREASE: if (ride->num_vehicles > 1) ride_set_num_vehicles(w->number, ride->num_vehicles - 1); break; case WIDX_VEHICLE_CARS_PER_TRAIN_INCREASE: if (ride->num_cars_per_train < 255) ride_set_num_cars_per_vehicle(w->number, ride->num_cars_per_train + 1); break; case WIDX_VEHICLE_CARS_PER_TRAIN_DECREASE: if (ride->num_cars_per_train > rideEntry->zero_cars + 1) ride_set_num_cars_per_vehicle(w->number, ride->num_cars_per_train - 1); break; } } /** * * rct2: 0x006B2767 */ static void window_ride_vehicle_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex) { if (dropdownIndex == -1) return; switch (widgetIndex) { case WIDX_VEHICLE_TYPE_DROPDOWN: dropdownIndex = (gDropdownItemsArgs[dropdownIndex] >> 16) & 0xFFFF; ride_set_ride_entry(w->number, dropdownIndex); break; } } /** * * rct2: 0x006B2AA1 */ static void window_ride_vehicle_update(rct_window *w) { w->frame_no++; window_event_invalidate_call(w); widget_invalidate(w, WIDX_TAB_2); } /** * * rct2: 0x006B222C */ static void window_ride_vehicle_invalidate(rct_window *w) { rct_widget *widgets; rct_ride *ride; rct_ride_entry *rideEntry; rct_string_id stringId; sint32 carsPerTrain; widgets = window_ride_page_widgets[w->page]; if (w->widgets != widgets) { w->widgets = widgets; window_init_scroll_widgets(w); } window_ride_set_pressed_tab(w); ride = get_ride(w->number); rideEntry = get_ride_entry_by_ride(ride); set_format_arg(0, rct_string_id, ride->name); set_format_arg(2, uint32, ride->name_arguments); // Widget setup carsPerTrain = ride->num_cars_per_train - rideEntry->zero_cars; // Vehicle type window_ride_vehicle_widgets[WIDX_VEHICLE_TYPE].text = rideEntry->name; // Always show a dropdown button when changing subtypes is allowed if ((rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE) && !(gConfigInterface.select_by_track_type || gCheatsShowVehiclesFromOtherTrackTypes)) { window_ride_vehicle_widgets[WIDX_VEHICLE_TYPE].type = WWT_14; window_ride_vehicle_widgets[WIDX_VEHICLE_TYPE_DROPDOWN].type = WWT_EMPTY; w->enabled_widgets &= ~(1 << WIDX_VEHICLE_TYPE); } else { window_ride_vehicle_widgets[WIDX_VEHICLE_TYPE].type = WWT_DROPDOWN; window_ride_vehicle_widgets[WIDX_VEHICLE_TYPE_DROPDOWN].type = WWT_DROPDOWN_BUTTON; w->enabled_widgets |= (1 << WIDX_VEHICLE_TYPE); } // Trains if (rideEntry->cars_per_flat_ride > 1 || gCheatsDisableTrainLengthLimit) { window_ride_vehicle_widgets[WIDX_VEHICLE_TRAINS].type = WWT_SPINNER; window_ride_vehicle_widgets[WIDX_VEHICLE_TRAINS_INCREASE].type = WWT_DROPDOWN_BUTTON; window_ride_vehicle_widgets[WIDX_VEHICLE_TRAINS_DECREASE].type = WWT_DROPDOWN_BUTTON; } else { window_ride_vehicle_widgets[WIDX_VEHICLE_TRAINS].type = WWT_EMPTY; window_ride_vehicle_widgets[WIDX_VEHICLE_TRAINS_INCREASE].type = WWT_EMPTY; window_ride_vehicle_widgets[WIDX_VEHICLE_TRAINS_DECREASE].type = WWT_EMPTY; } // Cars per train if (rideEntry->zero_cars + 1 < rideEntry->max_cars_in_train||gCheatsDisableTrainLengthLimit) { window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN].type = WWT_SPINNER; window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN_INCREASE].type = WWT_DROPDOWN_BUTTON; window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN_DECREASE].type = WWT_DROPDOWN_BUTTON; } else { window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN].type = WWT_EMPTY; window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN_INCREASE].type = WWT_EMPTY; window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN_DECREASE].type = WWT_EMPTY; } set_format_arg(6, uint16, carsPerTrain); ride_component_type vehicleType = RideNameConvention[ride->type].vehicle; stringId = RideComponentNames[vehicleType].count; if (ride->num_vehicles > 1) { stringId = RideComponentNames[vehicleType].count_plural; } set_format_arg(8, rct_string_id, stringId); set_format_arg(10, uint16, ride->num_vehicles); stringId = RideComponentNames[vehicleType].count; if (ride->max_trains > 1) { stringId = RideComponentNames[vehicleType].count_plural; } set_format_arg(12, rct_string_id, stringId); set_format_arg(14, uint16, ride->max_trains); set_format_arg(16, uint16, max(1, ride->min_max_cars_per_train & 0xF) - rideEntry->zero_cars); stringId = RideComponentNames[RIDE_COMPONENT_TYPE_CAR].singular; if ((ride->min_max_cars_per_train & 0xF) - rideEntry->zero_cars > 1) { stringId = RideComponentNames[RIDE_COMPONENT_TYPE_CAR].plural; } set_format_arg(18, rct_string_id, stringId); window_ride_anchor_border_widgets(w); window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); if (ride->num_cars_per_train > (rideEntry->zero_cars + 1)) { window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN].text = STR_X_CARS_PER_TRAIN; } else { window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN].text = STR_1_CAR_PER_TRAIN; } } /** * * rct2: 0x006B23DC */ static void window_ride_vehicle_paint(rct_window *w, rct_drawpixelinfo *dpi) { rct_ride *ride; rct_ride_entry *rideEntry; sint32 x, y; sint16 factor; window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); ride = get_ride(w->number); rideEntry = get_ride_entry_by_ride(ride); x = w->x + 8; y = w->y + 64; // Description y += gfx_draw_string_left_wrapped(dpi, &rideEntry->description, x, y, 300, STR_BLACK_STRING, COLOUR_BLACK); y += 5; // Capacity void * loadedObject = object_manager_get_loaded_object_by_index(ride->subtype); if (loadedObject != NULL) { const utf8 * capacity = object_get_capacity(loadedObject); set_format_arg(0, rct_string_id, STR_STRING); set_format_arg(2, utf8 *, capacity); gfx_draw_string_left(dpi, STR_CAPACITY, gCommonFormatArgs, COLOUR_BLACK, x, y); } y += 5; if (!(rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE) || rideTypeShouldLoseSeparateFlag(rideEntry)) { // Excitement Factor factor = rideEntry->excitement_multipler; if (factor > 0) { y += 10; gfx_draw_string_left(dpi, STR_EXCITEMENT_FACTOR, &factor, COLOUR_BLACK, x, y); } // Intensity Factor factor = rideEntry->intensity_multipler; if (factor > 0) { y += 10; gfx_draw_string_left(dpi, STR_INTENSITY_FACTOR, &factor, COLOUR_BLACK, x, y); } // Nausea Factor factor = rideEntry->nausea_multipler; if (factor > 0) { y += 10; gfx_draw_string_left(dpi, STR_NAUSEA_FACTOR, &factor, COLOUR_BLACK, x, y); } } } typedef struct rct_vehichle_paintinfo { sint16 x; sint16 y; sint32 sprite_index; sint32 tertiary_colour; } rct_vehichle_paintinfo; rct_vehichle_paintinfo _sprites_to_draw[144]; /** * * rct2: 0x006B2502 */ static void window_ride_vehicle_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32 scrollIndex) { rct_ride *ride = get_ride(w->number); rct_ride_entry *rideEntry = get_ride_entry_by_ride(ride); // Background gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width, dpi->y + dpi->height, PALETTE_INDEX_12); rct_widget *widget = &window_ride_vehicle_widgets[WIDX_VEHICLE_TRAINS_PREVIEW]; sint32 startX = max(2, ((widget->right - widget->left) - ((ride->num_vehicles - 1) * 36)) / 2 - 25); sint32 startY = widget->bottom - widget->top - 4; rct_ride_entry_vehicle* rideVehicleEntry = &rideEntry->vehicles[ride_entry_get_vehicle_at_position(ride->subtype, ride->num_cars_per_train, 0)]; startY += rideVehicleEntry->tab_height; // For each train for (sint32 i = 0; i < ride->num_vehicles; i++) { rct_vehichle_paintinfo *nextSpriteToDraw = _sprites_to_draw; sint32 x = startX; sint32 y = startY; // For each car in train for (sint32 j = 0; j < ride->num_cars_per_train; j++) { rideVehicleEntry = &rideEntry->vehicles[ride_entry_get_vehicle_at_position(ride->subtype, ride->num_cars_per_train, j)]; x += rideVehicleEntry->spacing / 17432; y -= (rideVehicleEntry->spacing / 2) / 17432; // Get colour of vehicle sint32 vehicleColourIndex = 0; switch (ride->colour_scheme_type & 3) { case VEHICLE_COLOUR_SCHEME_SAME: vehicleColourIndex = 0; break; case VEHICLE_COLOUR_SCHEME_PER_TRAIN: vehicleColourIndex = i; break; case VEHICLE_COLOUR_SCHEME_PER_VEHICLE: vehicleColourIndex = j; break; } vehicle_colour vehicleColour = ride_get_vehicle_colour(ride, vehicleColourIndex); sint32 spriteIndex = 16; if (rideVehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_11) spriteIndex /= 2; spriteIndex &= rideVehicleEntry->rotation_frame_mask; spriteIndex *= rideVehicleEntry->var_16; spriteIndex += rideVehicleEntry->base_image_id; spriteIndex |= (vehicleColour.additional_1 << 24) | (vehicleColour.main << 19); spriteIndex |= 0x80000000; nextSpriteToDraw->x = x; nextSpriteToDraw->y = y; nextSpriteToDraw->sprite_index = spriteIndex; nextSpriteToDraw->tertiary_colour = vehicleColour.additional_2; nextSpriteToDraw++; x += rideVehicleEntry->spacing / 17432; y -= (rideVehicleEntry->spacing / 2) / 17432; } if (ride->type == RIDE_TYPE_REVERSER_ROLLER_COASTER) { rct_vehichle_paintinfo tmp = *(nextSpriteToDraw - 1); *(nextSpriteToDraw - 1) = *(nextSpriteToDraw - 2); *(nextSpriteToDraw - 2) = tmp; } rct_vehichle_paintinfo *current = nextSpriteToDraw; while (--current >= _sprites_to_draw) gfx_draw_sprite(dpi, current->sprite_index, current->x, current->y, current->tertiary_colour); startX += 36; } } #pragma endregion #pragma region Operating static void set_operating_setting(sint32 rideNumber, uint8 setting, uint8 value) { gGameCommandErrorTitle = STR_CANT_CHANGE_OPERATING_MODE; game_do_command(0, (value << 8) | 1, 0, (setting << 8) | rideNumber, GAME_COMMAND_SET_RIDE_SETTING, 0, 0); } static void window_ride_mode_tweak_set(rct_window *w, uint8 value) { rct_ride *ride = get_ride(w->number); gGameCommandErrorTitle = STR_CANT_CHANGE_LAUNCH_SPEED; if (ride->mode == RIDE_MODE_STATION_TO_STATION) gGameCommandErrorTitle = STR_CANT_CHANGE_SPEED; if (ride->mode == RIDE_MODE_RACE) gGameCommandErrorTitle = STR_CANT_CHANGE_NUMBER_OF_LAPS; if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_VEHICLES)) gGameCommandErrorTitle = STR_CANT_CHANGE_THIS; if (ride->mode == RIDE_MODE_BUMPERCAR) gGameCommandErrorTitle = STR_CANT_CHANGE_TIME_LIMIT; if (ride->mode == RIDE_MODE_SWING) gGameCommandErrorTitle = STR_CANT_CHANGE_NUMBER_OF_SWINGS; if ( ride->mode == RIDE_MODE_ROTATION || ride->mode == RIDE_MODE_FORWARD_ROTATION || ride->mode == RIDE_MODE_BACKWARD_ROTATION ) gGameCommandErrorTitle = STR_CANT_CHANGE_NUMBER_OF_ROTATIONS; set_operating_setting(w->number, RIDE_SETTING_OPERATION_OPTION, value); } /** * * rct2: 0x006B11D5 */ static void window_ride_mode_tweak_increase(rct_window *w) { rct_ride *ride = get_ride(w->number); uint8 maxValue = RideProperties[ride->type].max_value; uint8 minValue = gCheatsFastLiftHill ? 0 : RideProperties[ride->type].min_value; if (gCheatsFastLiftHill) { maxValue = 255; } uint8 increment = ride->mode == RIDE_MODE_BUMPERCAR ? 10 : 1; window_ride_mode_tweak_set(w, clamp(minValue, ride->operation_option + increment, maxValue)); } /** * * rct2: 0x006B120A */ static void window_ride_mode_tweak_decrease(rct_window *w) { rct_ride *ride = get_ride(w->number); uint8 maxValue = RideProperties[ride->type].max_value; uint8 minValue = gCheatsFastLiftHill ? 0 : RideProperties[ride->type].min_value; if (gCheatsFastLiftHill) { maxValue = 255; } uint8 decrement = ride->mode == RIDE_MODE_BUMPERCAR ? 10 : 1; window_ride_mode_tweak_set(w, clamp(minValue, ride->operation_option - decrement, maxValue)); } /** * * rct2: 0x006B1631 */ static void window_ride_mode_dropdown(rct_window *w, rct_widget *widget) { rct_ride_entry *rideEntry; rct_widget *dropdownWidget; rct_ride *ride; const uint8 *availableModes, *mode; sint32 i, numAvailableModes; dropdownWidget = widget - 1; ride = get_ride(w->number); rideEntry = get_ride_entry_by_ride(ride); // Seek to available modes for this ride availableModes = ride_seek_available_modes(ride); // Count number of available modes mode = availableModes; numAvailableModes = -1; do { numAvailableModes++; } while (*(mode++) != 255); // Hide the last operating mode if the vehicle is not intended for it. if (rideEntry->flags & RIDE_ENTRY_DISABLE_LAST_OPERATING_MODE && !gCheatsShowAllOperatingModes) numAvailableModes--; // If the vehicle is not intended for them, hide those two modes (these are usually (or perhaps always) both continuous circuit modes). if ((rideEntry->flags & RIDE_ENTRY_DISABLE_FIRST_TWO_OPERATING_MODES) && !gCheatsShowAllOperatingModes) { availableModes += 2; numAvailableModes -= 2; } // Create dropdown list for (i = 0; i < numAvailableModes; i++) { gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[i] = RideModeNames[availableModes[i]]; } window_dropdown_show_text_custom_width( w->x + dropdownWidget->left, w->y + dropdownWidget->top, dropdownWidget->bottom - dropdownWidget->top + 1, w->colours[1], 0, DROPDOWN_FLAG_STAY_OPEN, numAvailableModes, widget->right - dropdownWidget->left ); // Set checked item for (i = 0; i < numAvailableModes; i++) { if (ride->mode == availableModes[i]) { dropdown_set_checked(i, true); } } } /** * * rct2: 0x006B15C0 */ static void window_ride_load_dropdown(rct_window *w, rct_widget *widget) { rct_widget *dropdownWidget; sint32 i; dropdownWidget = widget - 1; rct_ride *ride = get_ride(w->number); for (i = 0; i < 5; i++) { gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[i] = VehicleLoadNames[i]; } window_dropdown_show_text_custom_width( w->x + dropdownWidget->left, w->y + dropdownWidget->top, dropdownWidget->bottom - dropdownWidget->top + 1, w->colours[1], 0, DROPDOWN_FLAG_STAY_OPEN, 5, widget->right - dropdownWidget->left ); dropdown_set_checked(ride->depart_flags & RIDE_DEPART_WAIT_FOR_LOAD_MASK, true); } /** * * rct2: 0x006B10A7 */ static void window_ride_operating_mouseup(rct_window *w, rct_widgetindex widgetIndex) { rct_ride *ride; ride = get_ride(w->number); switch (widgetIndex) { case WIDX_CLOSE: window_close(w); break; case WIDX_TAB_1: case WIDX_TAB_2: case WIDX_TAB_3: case WIDX_TAB_4: case WIDX_TAB_5: case WIDX_TAB_6: case WIDX_TAB_7: case WIDX_TAB_8: case WIDX_TAB_9: case WIDX_TAB_10: window_ride_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_LOAD_CHECKBOX: set_operating_setting(w->number, RIDE_SETTING_DEPARTURE, ride->depart_flags ^ RIDE_DEPART_WAIT_FOR_LOAD); break; case WIDX_LEAVE_WHEN_ANOTHER_ARRIVES_CHECKBOX: set_operating_setting(w->number, RIDE_SETTING_DEPARTURE, ride->depart_flags ^ RIDE_DEPART_LEAVE_WHEN_ANOTHER_ARRIVES); break; case WIDX_MINIMUM_LENGTH_CHECKBOX: set_operating_setting(w->number, RIDE_SETTING_DEPARTURE, ride->depart_flags ^ RIDE_DEPART_WAIT_FOR_MINIMUM_LENGTH); break; case WIDX_MAXIMUM_LENGTH_CHECKBOX: set_operating_setting(w->number, RIDE_SETTING_DEPARTURE, ride->depart_flags ^ RIDE_DEPART_WAIT_FOR_MAXIMUM_LENGTH); break; case WIDX_SYNCHRONISE_WITH_ADJACENT_STATIONS_CHECKBOX: set_operating_setting(w->number, RIDE_SETTING_DEPARTURE, ride->depart_flags ^ RIDE_DEPART_SYNCHRONISE_WITH_ADJACENT_STATIONS); break; } } /** * * rct2: 0x006B1715 */ static void window_ride_operating_resize(rct_window *w) { window_set_resize(w, 316, 186, 316, 186); } /** * * rct2: 0x006B10F4 */ static void window_ride_operating_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget) { rct_ride *ride = get_ride(w->number); uint8 upper_bound, lower_bound; switch (widgetIndex) { case WIDX_MODE_TWEAK_INCREASE: window_ride_mode_tweak_increase(w); break; case WIDX_MODE_TWEAK_DECREASE: window_ride_mode_tweak_decrease(w); break; case WIDX_LIFT_HILL_SPEED_INCREASE: upper_bound = gCheatsFastLiftHill ? 255 : RideLiftData[ride->type].maximum_speed; lower_bound = gCheatsFastLiftHill ? 0 : RideLiftData[ride->type].minimum_speed; set_operating_setting(w->number, RIDE_SETTING_LIFT_HILL_SPEED, clamp(lower_bound, ride->lift_hill_speed + 1, upper_bound)); break; case WIDX_LIFT_HILL_SPEED_DECREASE: upper_bound = gCheatsFastLiftHill ? 255 : RideLiftData[ride->type].maximum_speed; lower_bound = gCheatsFastLiftHill ? 0 : RideLiftData[ride->type].minimum_speed; set_operating_setting(w->number, RIDE_SETTING_LIFT_HILL_SPEED, clamp(lower_bound, ride->lift_hill_speed - 1, upper_bound)); break; case WIDX_MINIMUM_LENGTH_INCREASE: upper_bound = 250; lower_bound = 0; set_operating_setting(w->number, RIDE_SETTING_MIN_WAITING_TIME, clamp(lower_bound, ride->min_waiting_time + 1, upper_bound)); break; case WIDX_MINIMUM_LENGTH_DECREASE: upper_bound = 250; lower_bound = 0; set_operating_setting(w->number, RIDE_SETTING_MIN_WAITING_TIME, clamp(lower_bound, ride->min_waiting_time - 1, upper_bound)); break; case WIDX_MAXIMUM_LENGTH_INCREASE: upper_bound = 250; lower_bound = 0; set_operating_setting(w->number, RIDE_SETTING_MAX_WAITING_TIME, clamp(lower_bound, ride->max_waiting_time + 1, upper_bound)); break; case WIDX_MAXIMUM_LENGTH_DECREASE: upper_bound = 250; lower_bound = 0; set_operating_setting(w->number, RIDE_SETTING_MAX_WAITING_TIME, clamp(lower_bound, ride->max_waiting_time - 1, upper_bound)); break; case WIDX_MODE_DROPDOWN: window_ride_mode_dropdown(w, widget); break; case WIDX_LOAD_DROPDOWN: window_ride_load_dropdown(w, widget); break; case WIDX_OPERATE_NUMBER_OF_CIRCUITS_INCREASE: upper_bound = gCheatsFastLiftHill ? 255 : 20; lower_bound = 1; set_operating_setting(w->number, RIDE_SETTING_NUM_CIRCUITS, clamp(lower_bound, ride->num_circuits + 1, upper_bound)); break; case WIDX_OPERATE_NUMBER_OF_CIRCUITS_DECREASE: upper_bound = gCheatsFastLiftHill ? 255 : 20; lower_bound = 1; set_operating_setting(w->number, RIDE_SETTING_NUM_CIRCUITS, clamp(lower_bound, ride->num_circuits - 1, upper_bound)); break; } } /** * * rct2: 0x006B1165 */ static void window_ride_operating_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex) { rct_ride *ride; const uint8 *availableModes; if (dropdownIndex == -1) return; ride = get_ride(w->number); switch (widgetIndex) { case WIDX_MODE_DROPDOWN: // Seek to available modes for this ride availableModes = ride_seek_available_modes(ride); set_operating_setting(w->number, RIDE_SETTING_MODE, availableModes[dropdownIndex]); break; case WIDX_LOAD_DROPDOWN: set_operating_setting(w->number, RIDE_SETTING_DEPARTURE, (ride->depart_flags & ~RIDE_DEPART_WAIT_FOR_LOAD_MASK) | dropdownIndex); break; } } /** * * rct2: 0x006B178E */ static void window_ride_operating_update(rct_window *w) { rct_ride *ride; w->frame_no++; window_event_invalidate_call(w); widget_invalidate(w, WIDX_TAB_3); ride = get_ride(w->number); if (ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_OPERATING) { ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_OPERATING; window_invalidate(w); } } /** * * rct2: 0x006B0B30 */ static void window_ride_operating_invalidate(rct_window *w) { rct_widget *widgets; rct_ride *ride; rct_ride_entry *rideEntry; rct_string_id format, caption, tooltip; widgets = window_ride_page_widgets[w->page]; if (w->widgets != widgets) { w->widgets = widgets; window_init_scroll_widgets(w); } window_ride_set_pressed_tab(w); ride = get_ride(w->number); rideEntry = get_ride_entry_by_ride(ride); set_format_arg(0, rct_string_id, ride->name); set_format_arg(2, uint32, ride->name_arguments); // Widget setup w->pressed_widgets &= ~( (1ULL << WIDX_LOAD_CHECKBOX) | (1ULL << WIDX_LEAVE_WHEN_ANOTHER_ARRIVES_CHECKBOX) | (1ULL << WIDX_MINIMUM_LENGTH_CHECKBOX) | (1ULL << WIDX_MAXIMUM_LENGTH_CHECKBOX) | (1ULL << WIDX_SYNCHRONISE_WITH_ADJACENT_STATIONS_CHECKBOX) ); // Lift hill speed if ((rideEntry->enabledTrackPiecesA & (1UL << TRACK_LIFT_HILL)) && track_piece_is_available_for_ride_type(ride->type, TRACK_LIFT_HILL)) { window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED_LABEL].type = WWT_24; window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED].type = WWT_SPINNER; window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED_INCREASE].type = WWT_DROPDOWN_BUTTON; window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED_DECREASE].type = WWT_DROPDOWN_BUTTON; set_format_arg(20, uint16, ride->lift_hill_speed); } else { window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED_LABEL].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED_INCREASE].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED_DECREASE].type = WWT_EMPTY; } // Number of circuits if (ride_can_have_multiple_circuits(ride)) { window_ride_operating_widgets[WIDX_OPERATE_NUMBER_OF_CIRCUITS_LABEL].type = WWT_24; window_ride_operating_widgets[WIDX_OPERATE_NUMBER_OF_CIRCUITS].type = WWT_SPINNER; window_ride_operating_widgets[WIDX_OPERATE_NUMBER_OF_CIRCUITS_INCREASE].type = WWT_DROPDOWN_BUTTON; window_ride_operating_widgets[WIDX_OPERATE_NUMBER_OF_CIRCUITS_DECREASE].type = WWT_DROPDOWN_BUTTON; set_format_arg(22, uint16, ride->num_circuits); } else { window_ride_operating_widgets[WIDX_OPERATE_NUMBER_OF_CIRCUITS_LABEL].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_OPERATE_NUMBER_OF_CIRCUITS].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_OPERATE_NUMBER_OF_CIRCUITS_INCREASE].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_OPERATE_NUMBER_OF_CIRCUITS_DECREASE].type = WWT_EMPTY; } // Leave if another vehicle arrives at station if ( ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_LEAVE_WHEN_ANOTHER_VEHICLE_ARRIVES_AT_STATION) && ride->num_vehicles > 1 && ride->mode != RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED && ride->mode != RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED ) { window_ride_operating_widgets[WIDX_LEAVE_WHEN_ANOTHER_ARRIVES_CHECKBOX].type = WWT_CHECKBOX; window_ride_operating_widgets[WIDX_LEAVE_WHEN_ANOTHER_ARRIVES_CHECKBOX].tooltip = STR_LEAVE_IF_ANOTHER_VEHICLE_ARRIVES_TIP; window_ride_operating_widgets[WIDX_LEAVE_WHEN_ANOTHER_ARRIVES_CHECKBOX].text = RideNameConvention[ride->type].vehicle == RIDE_COMPONENT_TYPE_BOAT ? STR_LEAVE_IF_ANOTHER_BOAT_ARRIVES : STR_LEAVE_IF_ANOTHER_TRAIN_ARRIVES; } else { window_ride_operating_widgets[WIDX_LEAVE_WHEN_ANOTHER_ARRIVES_CHECKBOX].type = WWT_EMPTY; } // Synchronise with adjacent stations if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_CAN_SYNCHRONISE_ADJACENT_STATIONS)) { window_ride_operating_widgets[WIDX_SYNCHRONISE_WITH_ADJACENT_STATIONS_CHECKBOX].type = WWT_CHECKBOX; window_ride_operating_widgets[WIDX_SYNCHRONISE_WITH_ADJACENT_STATIONS_CHECKBOX].image = STR_SYNCHRONISE_WITH_ADJACENT_STATIONS; window_ride_operating_widgets[WIDX_SYNCHRONISE_WITH_ADJACENT_STATIONS_CHECKBOX].tooltip = STR_SYNCHRONISE_WITH_ADJACENT_STATIONS_TIP; } else { window_ride_operating_widgets[WIDX_SYNCHRONISE_WITH_ADJACENT_STATIONS_CHECKBOX].type = WWT_EMPTY; } // Mode window_ride_operating_widgets[WIDX_MODE].text = RideModeNames[ride->mode]; // Waiting window_ride_operating_widgets[WIDX_LOAD].text = VehicleLoadNames[(ride->depart_flags & RIDE_DEPART_WAIT_FOR_LOAD_MASK)]; if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_LOAD_OPTIONS)) { window_ride_operating_widgets[WIDX_LOAD_CHECKBOX].type = WWT_CHECKBOX; window_ride_operating_widgets[WIDX_LOAD].type = WWT_DROPDOWN; window_ride_operating_widgets[WIDX_LOAD_DROPDOWN].type = WWT_DROPDOWN_BUTTON; window_ride_operating_widgets[WIDX_MINIMUM_LENGTH_CHECKBOX].type = WWT_CHECKBOX; window_ride_operating_widgets[WIDX_MINIMUM_LENGTH].type = WWT_SPINNER; window_ride_operating_widgets[WIDX_MINIMUM_LENGTH_INCREASE].type = WWT_DROPDOWN_BUTTON; window_ride_operating_widgets[WIDX_MINIMUM_LENGTH_DECREASE].type = WWT_DROPDOWN_BUTTON; window_ride_operating_widgets[WIDX_MAXIMUM_LENGTH_CHECKBOX].type = WWT_CHECKBOX; window_ride_operating_widgets[WIDX_MAXIMUM_LENGTH].type = WWT_SPINNER; window_ride_operating_widgets[WIDX_MAXIMUM_LENGTH_INCREASE].type = WWT_DROPDOWN_BUTTON; window_ride_operating_widgets[WIDX_MAXIMUM_LENGTH_DECREASE].type = WWT_DROPDOWN_BUTTON; set_format_arg(10, rct_string_id, STR_FORMAT_SECONDS); set_format_arg(12, uint16, ride->min_waiting_time); set_format_arg(14, rct_string_id, STR_FORMAT_SECONDS); set_format_arg(16, uint16, ride->max_waiting_time); if (ride->depart_flags & RIDE_DEPART_WAIT_FOR_LOAD) w->pressed_widgets |= (1 << WIDX_LOAD_CHECKBOX); } else { window_ride_operating_widgets[WIDX_LOAD_CHECKBOX].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_LOAD].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_LOAD_DROPDOWN].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_MINIMUM_LENGTH_CHECKBOX].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_MINIMUM_LENGTH].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_MINIMUM_LENGTH_INCREASE].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_MINIMUM_LENGTH_DECREASE].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_MAXIMUM_LENGTH_CHECKBOX].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_MAXIMUM_LENGTH].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_MAXIMUM_LENGTH_INCREASE].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_MAXIMUM_LENGTH_DECREASE].type = WWT_EMPTY; } if (ride->depart_flags & RIDE_DEPART_LEAVE_WHEN_ANOTHER_ARRIVES) w->pressed_widgets |= (1 << WIDX_LEAVE_WHEN_ANOTHER_ARRIVES_CHECKBOX); if (ride->depart_flags & RIDE_DEPART_SYNCHRONISE_WITH_ADJACENT_STATIONS) w->pressed_widgets |= (1 << WIDX_SYNCHRONISE_WITH_ADJACENT_STATIONS_CHECKBOX); if (ride->depart_flags & RIDE_DEPART_WAIT_FOR_MINIMUM_LENGTH) w->pressed_widgets |= (1 << WIDX_MINIMUM_LENGTH_CHECKBOX); if (ride->depart_flags & RIDE_DEPART_WAIT_FOR_MAXIMUM_LENGTH) w->pressed_widgets |= (1 << WIDX_MAXIMUM_LENGTH_CHECKBOX); // Mode specific functionality set_format_arg(18, uint16, ride->operation_option); switch (ride->mode) { case RIDE_MODE_POWERED_LAUNCH_PASSTROUGH: case RIDE_MODE_POWERED_LAUNCH: case RIDE_MODE_UPWARD_LAUNCH: case RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED: set_format_arg(18, uint16, (ride->launch_speed * 9) / 4); format = STR_RIDE_MODE_SPEED_VALUE; caption = STR_LAUNCH_SPEED; tooltip = STR_LAUNCH_SPEED_TIP; break; case RIDE_MODE_STATION_TO_STATION: set_format_arg(18, uint16, (ride->speed * 9) / 4); format = STR_RIDE_MODE_SPEED_VALUE; caption = STR_SPEED; tooltip = STR_SPEED_TIP; break; case RIDE_MODE_RACE: set_format_arg(18, uint16, ride->num_laps); format = STR_NUMBER_OF_LAPS_VALUE; caption = STR_NUMBER_OF_LAPS; tooltip = STR_NUMBER_OF_LAPS_TIP; break; case RIDE_MODE_BUMPERCAR: format = STR_RIDE_MODE_TIME_LIMIT_VALUE; caption = STR_TIME_LIMIT; tooltip = STR_TIME_LIMIT_TIP; break; case RIDE_MODE_SWING: format = STR_RIDE_MODE_NUMBER_OF_SWINGS_VALUE; caption = STR_NUMBER_OF_SWINGS; tooltip = STR_NUMBER_OF_SWINGS_TIP; break; case RIDE_MODE_ROTATION: case RIDE_MODE_FORWARD_ROTATION: case RIDE_MODE_BACKWARD_ROTATION: format = STR_NUMBER_OF_ROTATIONS_VALUE; caption = STR_NUMBER_OF_ROTATIONS; tooltip = STR_NUMBER_OF_ROTATIONS_TIP; break; default: format = STR_MAX_PEOPLE_ON_RIDE_VALUE; caption = STR_MAX_PEOPLE_ON_RIDE; tooltip = STR_MAX_PEOPLE_ON_RIDE_TIP; if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_VEHICLES)) format = 0; break; } if (format != 0) { if (ride->type == RIDE_TYPE_TWIST) { uint16 arg; memcpy(&arg, gCommonFormatArgs + 18, sizeof(uint16)); set_format_arg(18, uint16, arg * 3); } window_ride_operating_widgets[WIDX_MODE_TWEAK_LABEL].type = WWT_24; window_ride_operating_widgets[WIDX_MODE_TWEAK_LABEL].text = caption; window_ride_operating_widgets[WIDX_MODE_TWEAK_LABEL].tooltip = tooltip; window_ride_operating_widgets[WIDX_MODE_TWEAK].type = WWT_SPINNER; window_ride_operating_widgets[WIDX_MODE_TWEAK].text = format; window_ride_operating_widgets[WIDX_MODE_TWEAK_INCREASE].type = WWT_DROPDOWN_BUTTON; window_ride_operating_widgets[WIDX_MODE_TWEAK_DECREASE].type = WWT_DROPDOWN_BUTTON; w->pressed_widgets &= ~(1 << WIDX_LEAVE_WHEN_ANOTHER_ARRIVES_CHECKBOX); } else { window_ride_operating_widgets[WIDX_MODE_TWEAK_LABEL].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_MODE_TWEAK].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_MODE_TWEAK_INCREASE].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_MODE_TWEAK_DECREASE].type = WWT_EMPTY; } window_ride_anchor_border_widgets(w); window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); } /** * * rct2: 0x006B1001 */ static void window_ride_operating_paint(rct_window *w, rct_drawpixelinfo *dpi) { rct_ride *ride; uint16 blockSections; window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); ride = get_ride(w->number); // Horizontal rule between mode settings and depart settings gfx_fill_rect_inset( dpi, w->x + window_ride_operating_widgets[WIDX_PAGE_BACKGROUND].left + 4, w->y + 103, w->x + window_ride_operating_widgets[WIDX_PAGE_BACKGROUND].right - 5, w->y + 104, w->colours[1], INSET_RECT_FLAG_BORDER_INSET ); // Number of block sections if (ride->mode == RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED || ride->mode == RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED) { blockSections = ride->num_block_brakes + ride->num_stations; gfx_draw_string_left(dpi, STR_BLOCK_SECTIONS, &blockSections, COLOUR_BLACK, w->x + 21, ride->mode == RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED ? w->y + 89 : w->y + 61); } } #pragma endregion #pragma region Maintenance /** * * rct2: 0x006B1AE4 */ static void window_ride_locate_mechanic(rct_window *w) { rct_ride *ride; rct_peep *mechanic; ride = get_ride(w->number); // First check if there is a mechanic assigned mechanic = ride_get_assigned_mechanic(ride); // Otherwise find the closest mechanic if (mechanic == NULL) mechanic = ride_find_closest_mechanic(ride, 1); if (mechanic == NULL) window_error_open(STR_UNABLE_TO_LOCATE_MECHANIC, STR_NONE); else window_staff_open(mechanic); } /** * * rct2: 0x006B7D08 */ static void window_ride_maintenance_draw_bar(rct_window *w, rct_drawpixelinfo *dpi, sint32 x, sint32 y, sint32 value, sint32 unk) { gfx_fill_rect_inset(dpi, x, y, x + 149, y + 8, w->colours[1], INSET_RECT_F_30); if (unk & (1u << 31)) { unk &= ~(1u << 31); if (game_is_not_paused() && (gCurrentTicks & 8)) return; } value = ((186 * ((value * 2) & 0xFF)) >> 8) & 0xFF; if (value > 2) { gfx_fill_rect_inset(dpi, x + 2, y + 1, x + value + 1, y + 7, unk, 0); } } /** * * rct2: 0x006B1AAD */ static void window_ride_maintenance_mouseup(rct_window *w, rct_widgetindex widgetIndex) { switch (widgetIndex) { case WIDX_CLOSE: window_close(w); break; case WIDX_TAB_1: case WIDX_TAB_2: case WIDX_TAB_3: case WIDX_TAB_4: case WIDX_TAB_5: case WIDX_TAB_6: case WIDX_TAB_7: case WIDX_TAB_8: case WIDX_TAB_9: case WIDX_TAB_10: window_ride_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_LOCATE_MECHANIC: window_ride_locate_mechanic(w); break; } } /** * * rct2: 0x006B1D70 */ static void window_ride_maintenance_resize(rct_window *w) { window_set_resize(w, 316, 135, 316, 135); } /** * * rct2: 0x006B1ACE */ static void window_ride_maintenance_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget) { rct_ride *ride = get_ride(w->number); rct_ride_entry *ride_type = get_ride_entry(ride->subtype); if (ride_type == NULL) { return; } rct_widget *dropdownWidget = widget; sint32 j, num_items; switch (widgetIndex) { case WIDX_INSPECTION_INTERVAL_DROPDOWN: dropdownWidget--; for (sint32 i = 0; i < 7; i++) { gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[i] = RideInspectionIntervalNames[i]; } window_dropdown_show_text_custom_width( w->x + dropdownWidget->left, w->y + dropdownWidget->top, dropdownWidget->bottom - dropdownWidget->top + 1, w->colours[1], 0, DROPDOWN_FLAG_STAY_OPEN, 7, widget->right - dropdownWidget->left ); dropdown_set_checked(ride->inspection_interval, true); break; case WIDX_FORCE_BREAKDOWN: num_items = 1; for (j = 0; j < MAX_RIDE_TYPES_PER_RIDE_ENTRY; j++) { if (ride_type->ride_type[j] != 0xFF) break; } gDropdownItemsFormat[0] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[0] = STR_DEBUG_FIX_RIDE; for (sint32 i = 0; i < 8; i++) { assert(j < countof(ride_type->ride_type)); if (RideAvailableBreakdowns[ride_type->ride_type[j]] & (uint8)(1 << i)) { if (i == BREAKDOWN_BRAKES_FAILURE && (ride->mode == RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED || ride->mode == RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED)) { if (ride->num_vehicles != 1) continue; } gDropdownItemsFormat[num_items] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[num_items] = RideBreakdownReasonNames[i]; num_items++; } } if (num_items == 1) { window_error_open(STR_DEBUG_NO_BREAKDOWNS_AVAILABLE, STR_NONE); } else { window_dropdown_show_text( w->x + dropdownWidget->left, w->y + dropdownWidget->top, dropdownWidget->bottom - dropdownWidget->top + 1, w->colours[1], DROPDOWN_FLAG_STAY_OPEN, num_items ); num_items = 1; sint32 breakdownReason = ride->breakdown_reason_pending; if (breakdownReason != BREAKDOWN_NONE && (ride->lifecycle_flags & RIDE_LIFECYCLE_BREAKDOWN_PENDING)) { for (sint32 i = 0; i < 8; i++) { if (RideAvailableBreakdowns[ride_type->ride_type[j]] & (uint8)(1 << i)) { if (i == BREAKDOWN_BRAKES_FAILURE && (ride->mode == RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED || ride->mode == RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED)) { if (ride->num_vehicles != 1) continue; } if (i == breakdownReason) { dropdown_set_checked(num_items, true); break; } gDropdownItemsFormat[num_items] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[num_items] = RideBreakdownReasonNames[i]; num_items++; } } } if ((ride->lifecycle_flags & RIDE_LIFECYCLE_BREAKDOWN_PENDING) == 0) { gDropdownItemsDisabled = (1 << 0); } } break; } } /** * * rct2: 0x006B1AD9 */ static void window_ride_maintenance_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex) { if (dropdownIndex == -1) return; rct_vehicle *vehicle; rct_ride *ride = get_ride(w->number); rct_ride_entry *ride_type = get_ride_entry(ride->subtype); switch (widgetIndex) { case WIDX_INSPECTION_INTERVAL_DROPDOWN: gGameCommandErrorTitle = STR_CANT_CHANGE_OPERATING_MODE; game_do_command(0, (dropdownIndex << 8) | 1, 0, (5 << 8) | w->number, GAME_COMMAND_SET_RIDE_SETTING, 0, 0); break; case WIDX_FORCE_BREAKDOWN: if (dropdownIndex == 0) { switch (ride->breakdown_reason_pending) { case BREAKDOWN_SAFETY_CUT_OUT: if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)) break; for (sint32 i = 0; i < ride->num_vehicles; ++i) { uint16 spriteId = ride->vehicles[i]; while (spriteId != SPRITE_INDEX_NULL) { vehicle = GET_VEHICLE(spriteId); vehicle->update_flags &= ~( VEHICLE_UPDATE_FLAG_BROKEN_CAR | VEHICLE_UPDATE_FLAG_7 | VEHICLE_UPDATE_FLAG_BROKEN_TRAIN ); spriteId = vehicle->next_vehicle_on_train; } } break; case BREAKDOWN_RESTRAINTS_STUCK_CLOSED: case BREAKDOWN_RESTRAINTS_STUCK_OPEN: case BREAKDOWN_DOORS_STUCK_CLOSED: case BREAKDOWN_DOORS_STUCK_OPEN: vehicle = &(get_sprite(ride->vehicles[ride->broken_vehicle])->vehicle); vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_BROKEN_CAR; break; case BREAKDOWN_VEHICLE_MALFUNCTION: vehicle = &(get_sprite(ride->vehicles[ride->broken_vehicle])->vehicle); vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_BROKEN_TRAIN; break; } ride->lifecycle_flags &= ~(RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN); window_invalidate_by_number(WC_RIDE, w->number); break; } if (ride->lifecycle_flags & (RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN | RIDE_LIFECYCLE_CRASHED)) { window_error_open(STR_DEBUG_CANT_FORCE_BREAKDOWN, STR_DEBUG_RIDE_ALREADY_BROKEN); } else if (ride->status == RIDE_STATUS_CLOSED) { window_error_open(STR_DEBUG_CANT_FORCE_BREAKDOWN, STR_DEBUG_RIDE_IS_CLOSED); } else { sint32 j; for (j = 0; j < MAX_RIDE_TYPES_PER_RIDE_ENTRY; j++) { if (ride_type->ride_type[j] != 0xFF) break; } sint32 i; sint32 num_items = 1; for (i = 0; i < 8; i++) { assert(j < countof(ride_type->ride_type)); if (RideAvailableBreakdowns[ride_type->ride_type[j]] & (uint8)(1 << i)) { if (i == BREAKDOWN_BRAKES_FAILURE && (ride->mode == RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED || ride->mode == RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED)) { if (ride->num_vehicles != 1) continue; } if (num_items == dropdownIndex) break; num_items++; } } ride_prepare_breakdown(w->number, i); } break; } } /** * * rct2: 0x006B1D37 */ static void window_ride_maintenance_update(rct_window *w) { rct_ride *ride; w->frame_no++; window_event_invalidate_call(w); widget_invalidate(w, WIDX_TAB_4); ride = get_ride(w->number); if (ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_MAINTENANCE) { ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_MAINTENANCE; window_invalidate(w); } } /** * * rct2: 0x006B17C8 */ static void window_ride_maintenance_invalidate(rct_window *w) { rct_widget *widgets; widgets = window_ride_page_widgets[w->page]; if (w->widgets != widgets) { w->widgets = widgets; window_init_scroll_widgets(w); } window_ride_set_pressed_tab(w); rct_ride *ride = get_ride(w->number); set_format_arg(0, rct_string_id, ride->name); set_format_arg(2, uint32, ride->name_arguments); window_ride_maintenance_widgets[WIDX_INSPECTION_INTERVAL].text = RideInspectionIntervalNames[ride->inspection_interval]; window_ride_anchor_border_widgets(w); window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); if (gConfigGeneral.debugging_tools && network_get_mode() == NETWORK_MODE_NONE) { window_ride_maintenance_widgets[WIDX_FORCE_BREAKDOWN].type = WWT_FLATBTN; } else { window_ride_maintenance_widgets[WIDX_FORCE_BREAKDOWN].type = WWT_EMPTY; } } /** * * rct2: 0x006B1877 */ static void window_ride_maintenance_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); rct_ride *ride = get_ride(w->number); // Locate mechanic button image rct_widget *widget = &window_ride_maintenance_widgets[WIDX_LOCATE_MECHANIC]; sint32 x = w->x + widget->left; sint32 y = w->y + widget->top; gfx_draw_sprite(dpi, (gStaffMechanicColour << 24) | 0xA0000000 | SPR_MECHANIC, x, y, 0); // Inspection label widget = &window_ride_maintenance_widgets[WIDX_INSPECTION_INTERVAL]; x = w->x + 4; y = w->y + widget->top + 1; gfx_draw_string_left(dpi, STR_INSPECTION, NULL, COLOUR_BLACK, x, y); // Reliability widget = &window_ride_maintenance_widgets[WIDX_PAGE_BACKGROUND]; x = w->x + widget->left + 4; y = w->y + widget->top + 4; uint16 reliability = ride->reliability >> 8; gfx_draw_string_left(dpi, STR_RELIABILITY_LABEL_1757, &reliability, COLOUR_BLACK, x, y); window_ride_maintenance_draw_bar(w, dpi, x + 103, y, max(10, reliability), COLOUR_BRIGHT_GREEN); y += 11; uint16 downTime = ride->downtime; gfx_draw_string_left(dpi, STR_DOWN_TIME_LABEL_1889, &downTime, COLOUR_BLACK, x, y); window_ride_maintenance_draw_bar(w, dpi, x + 103, y, downTime, COLOUR_BRIGHT_RED); y += 26; // Last inspection uint16 lastInspection = ride->last_inspection; // Use singular form for 1 minute of time or less rct_string_id stringId; if (lastInspection <= 1) stringId = STR_TIME_SINCE_LAST_INSPECTION_MINUTE; else if (lastInspection <= 240) stringId = STR_TIME_SINCE_LAST_INSPECTION_MINUTES; else stringId = STR_TIME_SINCE_LAST_INSPECTION_MORE_THAN_4_HOURS; gfx_draw_string_left(dpi, stringId, &lastInspection, COLOUR_BLACK, x, y); y += 12; // Last / current breakdown if (ride->breakdown_reason == BREAKDOWN_NONE) return; stringId = (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) ? STR_CURRENT_BREAKDOWN : STR_LAST_BREAKDOWN; rct_string_id breakdownMessage = RideBreakdownReasonNames[ride->breakdown_reason]; gfx_draw_string_left(dpi, stringId, &breakdownMessage, COLOUR_BLACK, x, y); y += 10; // Mechanic status if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) { rct_peep *peep; uint16 spriteIndex; switch (ride->mechanic_status) { case RIDE_MECHANIC_STATUS_CALLING: stringId = STR_NO_MECHANICS_ARE_HIRED_MESSAGE; FOR_ALL_STAFF(spriteIndex, peep) { if (peep->staff_type == STAFF_TYPE_MECHANIC) { stringId = STR_CALLING_MECHANIC; break; } } break; case RIDE_MECHANIC_STATUS_HEADING: stringId = STR_MEHCANIC_IS_HEADING_FOR_THE_RIDE; break; case RIDE_MECHANIC_STATUS_FIXING: case RIDE_MECHANIC_STATUS_HAS_FIXED_STATION_BRAKES: stringId = STR_MEHCANIC_IS_FIXING_THE_RIDE; break; default: stringId = 0; break; } if (stringId != 0) { if (stringId == STR_CALLING_MECHANIC || stringId == STR_NO_MECHANICS_ARE_HIRED_MESSAGE) { gfx_draw_string_left_wrapped(dpi, NULL, x + 4, y, 280, stringId, COLOUR_BLACK); } else { rct_peep *mechanicSprite = &(get_sprite(ride->mechanic)->peep); if (peep_is_mechanic(mechanicSprite)) { set_format_arg(0, rct_string_id, mechanicSprite->name_string_idx); set_format_arg(2, uint32, mechanicSprite->id); gfx_draw_string_left_wrapped(dpi, gCommonFormatArgs, x + 4, y, 280, stringId, COLOUR_BLACK); } } } } } #pragma endregion #pragma region Colour const uint8 window_ride_entrance_style_list[] = { RIDE_ENTRANCE_STYLE_PLAIN, RIDE_ENTRANCE_STYLE_CANVAS_TENT, RIDE_ENTRANCE_STYLE_WOODEN, RIDE_ENTRANCE_STYLE_CASTLE_BROWN, RIDE_ENTRANCE_STYLE_CASTLE_GREY, RIDE_ENTRANCE_STYLE_LOG_CABIN, RIDE_ENTRANCE_STYLE_JUNGLE, RIDE_ENTRANCE_STYLE_CLASSICAL_ROMAN, RIDE_ENTRANCE_STYLE_ABSTRACT, RIDE_ENTRANCE_STYLE_SNOW_ICE, RIDE_ENTRANCE_STYLE_PAGODA, RIDE_ENTRANCE_STYLE_SPACE, RIDE_ENTRANCE_STYLE_NONE }; static uint32 window_ride_get_colour_button_image(sint32 colour) { return 0x60000000 | (colour << 19) | SPR_PALETTE_BTN; } static sint32 window_ride_has_track_colour(rct_ride *ride, sint32 trackColour) { uint16 colourUse = RideEntranceDefinitions[ride->entrance_style].colour_use_flags; switch (trackColour) { case 0: return ((colourUse & 1) && !ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) || ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_MAIN); case 1: return ((colourUse & 2) && !ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) || ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_ADDITIONAL); case 2: return ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_SUPPORTS); default: return 0; } } static void window_ride_set_track_colour_scheme(rct_window *w, sint32 x, sint32 y) { rct_map_element *mapElement; uint8 newColourScheme; sint32 interactionType, z, direction; newColourScheme = (uint8)w->ride_colour; rct_xy16 mapCoord = { 0 }; get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_RIDE, &mapCoord.x, &mapCoord.y, &interactionType, &mapElement, NULL); x = mapCoord.x; y = mapCoord.y; if (interactionType != VIEWPORT_INTERACTION_ITEM_RIDE) return; if (mapElement->properties.track.ride_index != w->number) return; if ((mapElement->properties.track.colour & 3) == newColourScheme) return; z = mapElement->base_height * 8; direction = mapElement->type & MAP_ELEMENT_DIRECTION_MASK; sub_6C683D(&x, &y, &z, direction, mapElement->properties.track.type, newColourScheme, NULL, 4); } /** * * rct2: 0x006B04FA */ static void window_ride_colour_close(rct_window *w) { if (!(input_test_flag(INPUT_FLAG_TOOL_ACTIVE))) return; if (gCurrentToolWidget.window_classification != w->classification) return; if (gCurrentToolWidget.window_number != w->number) return; tool_cancel(); } /** * * rct2: 0x006B02A1 */ static void window_ride_colour_mouseup(rct_window *w, rct_widgetindex widgetIndex) { switch (widgetIndex) { case WIDX_CLOSE: window_close(w); break; case WIDX_TAB_1: case WIDX_TAB_2: case WIDX_TAB_3: case WIDX_TAB_4: case WIDX_TAB_5: case WIDX_TAB_6: case WIDX_TAB_7: case WIDX_TAB_8: case WIDX_TAB_9: case WIDX_TAB_10: window_ride_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_PAINT_INDIVIDUAL_AREA: tool_set(w, WIDX_PAINT_INDIVIDUAL_AREA, TOOL_PAINT_DOWN); break; } } /** * * rct2: 0x006B0AB6 */ static void window_ride_colour_resize(rct_window *w) { window_set_resize(w, 316, 207, 316, 207); } /** * * rct2: 0x006B02C6 */ static void window_ride_colour_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget) { rct_ride *ride; uint16 colourSchemeIndex; vehicle_colour vehicleColour; rct_widget *dropdownWidget; rct_ride_entry *rideEntry; sint32 i, numItems; rct_string_id stringId; ride = get_ride(w->number); rideEntry = get_ride_entry_by_ride(ride); colourSchemeIndex = w->ride_colour; dropdownWidget = widget - 1; switch (widgetIndex) { case WIDX_TRACK_COLOUR_SCHEME_DROPDOWN: for (i = 0; i < RCT12_NUM_COLOUR_SCHEMES; i++) { gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[i] = ColourSchemeNames[i]; } window_dropdown_show_text_custom_width( w->x + dropdownWidget->left, w->y + dropdownWidget->top, dropdownWidget->bottom - dropdownWidget->top + 1, w->colours[1], 0, DROPDOWN_FLAG_STAY_OPEN, 4, widget->right - dropdownWidget->left ); dropdown_set_checked(colourSchemeIndex, true); break; case WIDX_TRACK_MAIN_COLOUR: window_dropdown_show_colour(w, widget, w->colours[1], ride->track_colour_main[colourSchemeIndex]); break; case WIDX_TRACK_ADDITIONAL_COLOUR: window_dropdown_show_colour(w, widget, w->colours[1], ride->track_colour_additional[colourSchemeIndex]); break; case WIDX_TRACK_SUPPORT_COLOUR: window_dropdown_show_colour(w, widget, w->colours[1], ride->track_colour_supports[colourSchemeIndex]); break; case WIDX_MAZE_STYLE_DROPDOWN: for (i = 0; i < 4; i++) { gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[i] = MazeOptions[i].text; } window_dropdown_show_text_custom_width( w->x + dropdownWidget->left, w->y + dropdownWidget->top, dropdownWidget->bottom - dropdownWidget->top + 1, w->colours[1], 0, DROPDOWN_FLAG_STAY_OPEN, 4, widget->right - dropdownWidget->left ); dropdown_set_checked(ride->track_colour_supports[colourSchemeIndex], true); break; case WIDX_ENTRANCE_STYLE_DROPDOWN: gDropdownItemsChecked = 0; for (i = 0; i < countof(window_ride_entrance_style_list); i++) { gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[i] = RideEntranceDefinitions[window_ride_entrance_style_list[i]].string_id; if (ride->entrance_style == window_ride_entrance_style_list[i]) { dropdown_set_checked(i, true); } } uint64 checked = gDropdownItemsChecked; window_dropdown_show_text_custom_width( w->x + dropdownWidget->left, w->y + dropdownWidget->top, dropdownWidget->bottom - dropdownWidget->top + 1, w->colours[1], 0, DROPDOWN_FLAG_STAY_OPEN, countof(window_ride_entrance_style_list), widget->right - dropdownWidget->left ); gDropdownItemsChecked = checked; break; case WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN: for (i = 0; i < 3; i++) { gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[i] = (RideComponentNames[RideNameConvention[ride->type].vehicle].singular << 16) | VehicleColourSchemeNames[i]; } window_dropdown_show_text_custom_width( w->x + dropdownWidget->left, w->y + dropdownWidget->top, dropdownWidget->bottom - dropdownWidget->top + 1, w->colours[1], 0, DROPDOWN_FLAG_STAY_OPEN, rideEntry->max_cars_in_train > 1 ? 3 : 2, widget->right - dropdownWidget->left ); dropdown_set_checked(ride->colour_scheme_type & 3, true); break; case WIDX_VEHICLE_COLOUR_INDEX_DROPDOWN: numItems = ride->num_vehicles; if ((ride->colour_scheme_type & 3) != VEHICLE_COLOUR_SCHEME_PER_TRAIN) numItems = ride->num_cars_per_train; stringId = (ride->colour_scheme_type & 3) == VEHICLE_COLOUR_SCHEME_PER_TRAIN ? STR_RIDE_COLOUR_TRAIN_OPTION : STR_RIDE_COLOUR_VEHICLE_OPTION; for (i = 0; i < 32; i++) { gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[i] = ((sint64)(i + 1) << 32) | ((RideComponentNames[RideNameConvention[ride->type].vehicle].capitalised) << 16) | stringId; } window_dropdown_show_text_custom_width( w->x + dropdownWidget->left, w->y + dropdownWidget->top, dropdownWidget->bottom - dropdownWidget->top + 1, w->colours[1], 0, DROPDOWN_FLAG_STAY_OPEN, numItems, widget->right - dropdownWidget->left ); dropdown_set_checked(w->var_48C, true); break; case WIDX_VEHICLE_MAIN_COLOUR: vehicleColour = ride_get_vehicle_colour(ride, w->var_48C); window_dropdown_show_colour(w, widget, w->colours[1], vehicleColour.main); break; case WIDX_VEHICLE_ADDITIONAL_COLOUR_1: vehicleColour = ride_get_vehicle_colour(ride, w->var_48C); window_dropdown_show_colour(w, widget, w->colours[1], vehicleColour.additional_1); break; case WIDX_VEHICLE_ADDITIONAL_COLOUR_2: vehicleColour = ride_get_vehicle_colour(ride, w->var_48C); window_dropdown_show_colour(w, widget, w->colours[1], vehicleColour.additional_2); break; } } /** * * rct2: 0x006B0331 */ static void window_ride_colour_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex) { if (dropdownIndex == -1) return; switch (widgetIndex) { case WIDX_TRACK_COLOUR_SCHEME_DROPDOWN: w->ride_colour = (uint16)dropdownIndex; window_invalidate(w); break; case WIDX_TRACK_MAIN_COLOUR: game_do_command(0, (0 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->ride_colour, 0); break; case WIDX_TRACK_ADDITIONAL_COLOUR: game_do_command(0, (1 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->ride_colour, 0); break; case WIDX_TRACK_SUPPORT_COLOUR: game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->ride_colour, 0); break; case WIDX_MAZE_STYLE_DROPDOWN: game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->ride_colour, 0); break; case WIDX_ENTRANCE_STYLE_DROPDOWN: game_do_command(0, (6 << 8) | 1, 0, (window_ride_entrance_style_list[dropdownIndex] << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0); break; case WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN: game_do_command(0, (5 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0); w->var_48C = 0; break; case WIDX_VEHICLE_COLOUR_INDEX_DROPDOWN: w->var_48C = dropdownIndex; window_invalidate(w); break; case WIDX_VEHICLE_MAIN_COLOUR: game_do_command(0, (2 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->var_48C, 0); break; case WIDX_VEHICLE_ADDITIONAL_COLOUR_1: game_do_command(0, (3 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->var_48C, 0); break; case WIDX_VEHICLE_ADDITIONAL_COLOUR_2: game_do_command(0, (7 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->var_48C, 0); break; } } /** * * rct2: 0x006B0A8F */ static void window_ride_colour_update(rct_window *w) { w->frame_no++; window_event_invalidate_call(w); widget_invalidate(w, WIDX_TAB_5); widget_invalidate(w, WIDX_VEHICLE_PREVIEW); } /** * * rct2: 0x006B04EC */ static void window_ride_colour_tooldown(rct_window *w, rct_widgetindex widgetIndex, sint32 x, sint32 y) { if (widgetIndex == WIDX_PAINT_INDIVIDUAL_AREA) window_ride_set_track_colour_scheme(w, x, y); } /** * * rct2: 0x006B04F3 */ static void window_ride_colour_tooldrag(rct_window *w, rct_widgetindex widgetIndex, sint32 x, sint32 y) { if (widgetIndex == WIDX_PAINT_INDIVIDUAL_AREA) window_ride_set_track_colour_scheme(w, x, y); } /** * * rct2: 0x006AFB36 */ static void window_ride_colour_invalidate(rct_window *w) { rct_widget *widgets; rct_ride_entry *rideEntry; rct_ride *ride; track_colour trackColour; vehicle_colour vehicleColour; widgets = window_ride_page_widgets[w->page]; if (w->widgets != widgets) { w->widgets = widgets; window_init_scroll_widgets(w); } window_ride_set_pressed_tab(w); ride = get_ride(w->number); rideEntry = get_ride_entry_by_ride(ride); set_format_arg(0, rct_string_id, ride->name); set_format_arg(2, uint32, ride->name_arguments); // Track colours sint32 colourScheme = w->ride_colour; trackColour = ride_get_track_colour(ride, colourScheme); // Maze style if (ride->type == RIDE_TYPE_MAZE) { window_ride_colour_widgets[WIDX_MAZE_STYLE].type = WWT_DROPDOWN; window_ride_colour_widgets[WIDX_MAZE_STYLE_DROPDOWN].type = WWT_DROPDOWN_BUTTON; window_ride_colour_widgets[WIDX_MAZE_STYLE].text = MazeOptions[trackColour.supports].text; } else { window_ride_colour_widgets[WIDX_MAZE_STYLE].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_MAZE_STYLE_DROPDOWN].type = WWT_EMPTY; } // Track, multiple colour schemes if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_SUPPORTS_MULTIPLE_TRACK_COLOUR)) { window_ride_colour_widgets[WIDX_TRACK_COLOUR_SCHEME].type = WWT_DROPDOWN; window_ride_colour_widgets[WIDX_TRACK_COLOUR_SCHEME_DROPDOWN].type = WWT_DROPDOWN_BUTTON; window_ride_colour_widgets[WIDX_PAINT_INDIVIDUAL_AREA].type = WWT_FLATBTN; } else { window_ride_colour_widgets[WIDX_TRACK_COLOUR_SCHEME].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_TRACK_COLOUR_SCHEME_DROPDOWN].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_PAINT_INDIVIDUAL_AREA].type = WWT_EMPTY; } // Track main colour if (window_ride_has_track_colour(ride, 0)) { window_ride_colour_widgets[WIDX_TRACK_MAIN_COLOUR].type = WWT_COLOURBTN; window_ride_colour_widgets[WIDX_TRACK_MAIN_COLOUR].image = window_ride_get_colour_button_image(trackColour.main); } else { window_ride_colour_widgets[WIDX_TRACK_MAIN_COLOUR].type = WWT_EMPTY; } // Track additional colour if (window_ride_has_track_colour(ride, 1)) { window_ride_colour_widgets[WIDX_TRACK_ADDITIONAL_COLOUR].type = WWT_COLOURBTN; window_ride_colour_widgets[WIDX_TRACK_ADDITIONAL_COLOUR].image = window_ride_get_colour_button_image(trackColour.additional); } else { window_ride_colour_widgets[WIDX_TRACK_ADDITIONAL_COLOUR].type = WWT_EMPTY; } // Track supports colour if (window_ride_has_track_colour(ride, 2) && ride->type != RIDE_TYPE_MAZE) { window_ride_colour_widgets[WIDX_TRACK_SUPPORT_COLOUR].type = WWT_COLOURBTN; window_ride_colour_widgets[WIDX_TRACK_SUPPORT_COLOUR].image = window_ride_get_colour_button_image(trackColour.supports); } else { window_ride_colour_widgets[WIDX_TRACK_SUPPORT_COLOUR].type = WWT_EMPTY; } // Track preview if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_MAIN | RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_ADDITIONAL | RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_SUPPORTS)) window_ride_colour_widgets[WIDX_TRACK_PREVIEW].type = WWT_SPINNER; else window_ride_colour_widgets[WIDX_TRACK_PREVIEW].type = WWT_EMPTY; // Entrance style if (RideData4[ride->type].flags & RIDE_TYPE_FLAG4_HAS_ENTRANCE_EXIT) { window_ride_colour_widgets[WIDX_ENTRANCE_PREVIEW].type = WWT_SPINNER; window_ride_colour_widgets[WIDX_ENTRANCE_STYLE].type = WWT_DROPDOWN; window_ride_colour_widgets[WIDX_ENTRANCE_STYLE_DROPDOWN].type = WWT_DROPDOWN_BUTTON; window_ride_colour_widgets[WIDX_ENTRANCE_STYLE].text = RideEntranceDefinitions[ride->entrance_style].string_id; } else { window_ride_colour_widgets[WIDX_ENTRANCE_PREVIEW].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_ENTRANCE_STYLE].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_ENTRANCE_STYLE_DROPDOWN].type = WWT_EMPTY; } // Vehicle colours if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_VEHICLES) && ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_VEHICLE_COLOURS)) { sint32 vehicleColourSchemeType = ride->colour_scheme_type & 3; if (vehicleColourSchemeType == 0) w->var_48C = 0; vehicleColour = ride_get_vehicle_colour(ride, w->var_48C); window_ride_colour_widgets[WIDX_VEHICLE_PREVIEW].type = WWT_SCROLL; window_ride_colour_widgets[WIDX_VEHICLE_MAIN_COLOUR].type = WWT_COLOURBTN; window_ride_colour_widgets[WIDX_VEHICLE_MAIN_COLOUR].image = window_ride_get_colour_button_image(vehicleColour.main); uint32 colourFlags = 0; for (sint32 i = 0; i < ride->num_cars_per_train; i++) { uint8 vehicleTypeIndex = ride_entry_get_vehicle_at_position(ride->subtype, ride->num_cars_per_train, i); colourFlags |= rideEntry->vehicles[vehicleTypeIndex].flags_b; colourFlags = ror32(colourFlags, 16); colourFlags |= rideEntry->vehicles[vehicleTypeIndex].flags_a; colourFlags = ror32(colourFlags, 16); } // Additional colours if (colourFlags & 1) { window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_1].type = WWT_COLOURBTN; window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_1].image = window_ride_get_colour_button_image(vehicleColour.additional_1); if (colourFlags & 0x2000000) { window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_2].type = WWT_COLOURBTN; window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_2].image = window_ride_get_colour_button_image(vehicleColour.additional_2); } else { window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_2].type = WWT_EMPTY; } } else { window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_1].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_2].type = WWT_EMPTY; } // Vehicle colour scheme type if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_16) && (ride->num_cars_per_train | ride->num_vehicles) > 1) { window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_SCHEME].type = WWT_DROPDOWN; window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN].type = WWT_DROPDOWN_BUTTON; } else { window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_SCHEME].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN].type = WWT_EMPTY; } set_format_arg( 6, rct_string_id, VehicleColourSchemeNames[vehicleColourSchemeType]); set_format_arg( 8, rct_string_id, RideComponentNames[RideNameConvention[ride->type].vehicle].singular); set_format_arg(10, rct_string_id, RideComponentNames[RideNameConvention[ride->type].vehicle].capitalised); set_format_arg(12, uint16, w->var_48C + 1); // Vehicle index if (vehicleColourSchemeType != 0) { window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_INDEX].type = WWT_DROPDOWN; window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_INDEX_DROPDOWN].type = WWT_DROPDOWN_BUTTON; window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_INDEX].text = vehicleColourSchemeType == 1 ? STR_RIDE_COLOUR_TRAIN_VALUE : STR_RIDE_COLOUR_VEHICLE_VALUE; } else { window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_INDEX].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_INDEX_DROPDOWN].type = WWT_EMPTY; } } else { window_ride_colour_widgets[WIDX_VEHICLE_PREVIEW].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_SCHEME].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_INDEX].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_INDEX_DROPDOWN].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_VEHICLE_MAIN_COLOUR].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_1].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_2].type = WWT_EMPTY; } set_format_arg(14, rct_string_id, ColourSchemeNames[colourScheme]); window_ride_anchor_border_widgets(w); window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); } /** * * rct2: 0x006AFF3E */ static void window_ride_colour_paint(rct_window *w, rct_drawpixelinfo *dpi) { // TODO: This should use lists and identified sprites rct_drawpixelinfo clippedDpi; rct_widget *widget; rct_ride *ride; rct_ride_entry *rideEntry; ride = get_ride(w->number); rideEntry = get_ride_entry_by_ride(ride); window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); // Track / shop item preview widget = &window_ride_colour_widgets[WIDX_TRACK_PREVIEW]; if (widget->type != WWT_EMPTY) gfx_fill_rect(dpi, w->x + widget->left + 1, w->y + widget->top + 1, w->x + widget->right - 1, w->y + widget->bottom - 1, PALETTE_INDEX_12); track_colour trackColour = ride_get_track_colour(ride, w->ride_colour); // if (rideEntry->shop_item == 0xFF) { sint32 x = w->x + widget->left; sint32 y = w->y + widget->top; // Track if (ride->type == RIDE_TYPE_MAZE) { sint32 spriteIndex = MazeOptions[trackColour.supports].sprite; gfx_draw_sprite(dpi, spriteIndex, x, y, 0); } else { sint32 spriteIndex = TrackColourPreviews[ride->type].track; if (spriteIndex != 0) { spriteIndex |= (trackColour.additional << 24) | (trackColour.main << 19); spriteIndex |= 0xA0000000; gfx_draw_sprite(dpi, spriteIndex, x, y, 0); } // Supports spriteIndex = TrackColourPreviews[ride->type].supports; if (spriteIndex != 0) { spriteIndex |= trackColour.supports << 19; spriteIndex |= 0x20000000; gfx_draw_sprite(dpi, spriteIndex, x, y, 0); } } } else { sint32 x = w->x + (widget->left + widget->right) / 2 - 8; sint32 y = w->y + (widget->bottom + widget->top) / 2 - 6; uint8 shopItem = rideEntry->shop_item_secondary == 255 ? rideEntry->shop_item : rideEntry->shop_item_secondary; sint32 spriteIndex = ShopItemImage[shopItem]; spriteIndex |= ride->track_colour_main[0] << 19; spriteIndex |= 0x20000000; gfx_draw_sprite(dpi, spriteIndex, x, y, 0); } // Entrance preview trackColour = ride_get_track_colour(ride, 0); widget = &w->widgets[WIDX_ENTRANCE_PREVIEW]; if (widget->type != WWT_EMPTY) { if (clip_drawpixelinfo( &clippedDpi, dpi, w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left, widget->bottom - widget->top )) { gfx_clear(&clippedDpi, PALETTE_INDEX_12); if (ride->entrance_style != RIDE_ENTRANCE_STYLE_NONE) { const rct_ride_entrance_definition *entranceStyle = &RideEntranceDefinitions[ride->entrance_style]; sint32 terniaryColour = 0; if (entranceStyle->base_image_id & 0x40000000) { terniaryColour = 0x40000000 | (GlassPaletteIds[trackColour.main] << 19); } sint32 spriteIndex = (trackColour.additional << 24) | (trackColour.main << 19); spriteIndex |= 0xA0000000; spriteIndex += RideEntranceDefinitions[ride->entrance_style].sprite_index; // Back gfx_draw_sprite(&clippedDpi, spriteIndex, 34, 20, terniaryColour); // Front gfx_draw_sprite(&clippedDpi, spriteIndex + 4, 34, 20, terniaryColour); // Glass if (terniaryColour != 0) gfx_draw_sprite(&clippedDpi, ((spriteIndex + 20) & 0x7FFFF) + terniaryColour, 34, 20, terniaryColour); } } } } /** * * rct2: 0x006B0192 */ static void window_ride_colour_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32 scrollIndex) { rct_ride *ride; rct_ride_entry *rideEntry; rct_widget *vehiclePreviewWidget; sint32 trainCarIndex, x, y, spriteIndex; vehicle_colour vehicleColour; ride = get_ride(w->number); rideEntry = get_ride_entry_by_ride(ride); vehiclePreviewWidget = &window_ride_colour_widgets[WIDX_VEHICLE_PREVIEW]; vehicleColour = ride_get_vehicle_colour(ride, w->var_48C); // Background colour gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width - 1, dpi->y + dpi->height - 1, PALETTE_INDEX_12); // ? x = (vehiclePreviewWidget->right - vehiclePreviewWidget->left) / 2; y = vehiclePreviewWidget->bottom - vehiclePreviewWidget->top - 15; // ? trainCarIndex = (ride->colour_scheme_type & 3) == RIDE_COLOUR_SCHEME_DIFFERENT_PER_CAR ? w->var_48C : rideEntry->tab_vehicle; rct_ride_entry_vehicle* rideVehicleEntry = &rideEntry->vehicles[ride_entry_get_vehicle_at_position(ride->subtype, ride->num_cars_per_train, trainCarIndex)]; y += rideVehicleEntry->tab_height; // Draw the coloured spinning vehicle spriteIndex = (rideVehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_11) ? w->frame_no / 4 : w->frame_no / 2; spriteIndex &= rideVehicleEntry->rotation_frame_mask; spriteIndex *= rideVehicleEntry->var_16; spriteIndex += rideVehicleEntry->base_image_id; spriteIndex |= (vehicleColour.additional_1 << 24) | (vehicleColour.main << 19); spriteIndex |= 0x80000000; gfx_draw_sprite(dpi, spriteIndex, x, y, vehicleColour.additional_2); } #pragma endregion #pragma region Music const uint8 MusicStyleOrder[] = { MUSIC_STYLE_GENTLE, MUSIC_STYLE_SUMMER, MUSIC_STYLE_WATER, MUSIC_STYLE_RAGTIME, MUSIC_STYLE_TECHNO, MUSIC_STYLE_MECHANICAL, MUSIC_STYLE_MODERN, MUSIC_STYLE_WILD_WEST, MUSIC_STYLE_PIRATES, MUSIC_STYLE_ROCK, MUSIC_STYLE_ROCK_STYLE_2, MUSIC_STYLE_ROCK_STYLE_3, MUSIC_STYLE_FANTASY, MUSIC_STYLE_HORROR, MUSIC_STYLE_TOYLAND, MUSIC_STYLE_CANDY_STYLE, MUSIC_STYLE_ROMAN_FANFARE, MUSIC_STYLE_ORIENTAL, MUSIC_STYLE_MARTIAN, MUSIC_STYLE_SPACE, MUSIC_STYLE_JUNGLE_DRUMS, MUSIC_STYLE_JURASSIC, MUSIC_STYLE_EGYPTIAN, MUSIC_STYLE_DODGEMS_BEAT, MUSIC_STYLE_SNOW, MUSIC_STYLE_ICE, MUSIC_STYLE_MEDIEVAL, MUSIC_STYLE_URBAN, MUSIC_STYLE_ORGAN }; static uint8 window_ride_current_music_style_order[42]; /** * * rct2: 0x006B215D */ static void window_ride_toggle_music(rct_window *w) { rct_ride *ride = get_ride(w->number); sint32 activateMusic = (ride->lifecycle_flags & RIDE_LIFECYCLE_MUSIC) ? 0 : 1; gGameCommandErrorTitle = STR_CANT_CHANGE_OPERATING_MODE; game_do_command(0, (activateMusic << 8) | 1, 0, (6 << 8) | w->number, GAME_COMMAND_SET_RIDE_SETTING, 0, 0); } /** * * rct2: 0x006B1ED7 */ static void window_ride_music_mouseup(rct_window *w, rct_widgetindex widgetIndex) { switch (widgetIndex) { case WIDX_CLOSE: window_close(w); break; case WIDX_TAB_1: case WIDX_TAB_2: case WIDX_TAB_3: case WIDX_TAB_4: case WIDX_TAB_5: case WIDX_TAB_6: case WIDX_TAB_7: case WIDX_TAB_8: case WIDX_TAB_9: case WIDX_TAB_10: window_ride_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_PLAY_MUSIC: window_ride_toggle_music(w); break; } } /** * * rct2: 0x006AF4A2 */ static void window_ride_music_resize(rct_window *w) { w->flags |= WF_RESIZABLE; window_set_resize(w, 316, 81, 316, 81); } /** * * rct2: 0x006B1EFC */ static void window_ride_music_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget) { rct_widget *dropdownWidget; sint32 i; if (widgetIndex != WIDX_MUSIC_DROPDOWN) return; dropdownWidget = widget - 1; rct_ride *ride = get_ride(w->number); sint32 numItems = 0; if (ride->type == RIDE_TYPE_MERRY_GO_ROUND) { window_ride_current_music_style_order[numItems++] = MUSIC_STYLE_FAIRGROUND_ORGAN; } else { for (i = 0; i < countof(MusicStyleOrder); i++) window_ride_current_music_style_order[numItems++] = MusicStyleOrder[i]; if (gRideMusicInfoList[36]->length != 0) window_ride_current_music_style_order[numItems++] = MUSIC_STYLE_CUSTOM_MUSIC_1; if (gRideMusicInfoList[37]->length != 0) window_ride_current_music_style_order[numItems++] = MUSIC_STYLE_CUSTOM_MUSIC_2; } for (i = 0; i < numItems; i++) { gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[i] = MusicStyleNames[window_ride_current_music_style_order[i]]; } window_dropdown_show_text_custom_width( w->x + dropdownWidget->left, w->y + dropdownWidget->top, dropdownWidget->bottom - dropdownWidget->top + 1, w->colours[1], 0, DROPDOWN_FLAG_STAY_OPEN, numItems, widget->right - dropdownWidget->left ); for (i = 0; i < numItems; i++) { if (window_ride_current_music_style_order[i] == ride->music) { dropdown_set_checked(i, true); } } } /** * * rct2: 0x006B1F03 */ static void window_ride_music_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex) { uint8 musicStyle; if (widgetIndex != WIDX_MUSIC_DROPDOWN || dropdownIndex == -1) return; musicStyle = window_ride_current_music_style_order[dropdownIndex]; gGameCommandErrorTitle = STR_CANT_CHANGE_OPERATING_MODE; game_do_command(0, (musicStyle << 8) | 1, 0, (7 << 8) | w->number, GAME_COMMAND_SET_RIDE_SETTING, 0, 0); } /** * * rct2: 0x006B2198 */ static void window_ride_music_update(rct_window *w) { w->frame_no++; window_event_invalidate_call(w); widget_invalidate(w, WIDX_TAB_6); } /** * * rct2: 0x006B1DEA */ static void window_ride_music_invalidate(rct_window *w) { rct_widget *widgets; sint32 isMusicActivated; widgets = window_ride_page_widgets[w->page]; if (w->widgets != widgets) { w->widgets = widgets; window_init_scroll_widgets(w); } window_ride_set_pressed_tab(w); rct_ride *ride = get_ride(w->number); set_format_arg(0, rct_string_id, ride->name); set_format_arg(2, uint32, ride->name_arguments); // Set selected music window_ride_music_widgets[WIDX_MUSIC].text = MusicStyleNames[ride->music]; // Set music activated isMusicActivated = ride->lifecycle_flags & (RIDE_LIFECYCLE_MUSIC); if (isMusicActivated) { w->pressed_widgets |= (1 << WIDX_PLAY_MUSIC); w->disabled_widgets &= ~(1 << WIDX_MUSIC); w->disabled_widgets &= ~(1 << WIDX_MUSIC_DROPDOWN); } else { w->pressed_widgets &= ~(1 << WIDX_PLAY_MUSIC); w->disabled_widgets |= (1 << WIDX_MUSIC); w->disabled_widgets |= (1 << WIDX_MUSIC_DROPDOWN); } window_ride_anchor_border_widgets(w); window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); } /** * * rct2: 0x006B1ECC */ static void window_ride_music_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); } #pragma endregion #pragma region Measurements static rct_string_id get_rating_name(ride_rating rating) { sint32 index = clamp(0, rating >> 8, countof(RatingNames) - 1); return RatingNames[index]; } /** * * rct2: 0x006D2804 when al == 0*/ static void cancel_scenery_selection(){ gGamePaused &= ~GAME_PAUSED_SAVING_TRACK; gTrackDesignSaveMode = false; audio_unpause_sounds(); rct_window* main_w = window_get_main(); if (main_w){ main_w->viewport->flags &= ~(VIEWPORT_FLAG_HIDE_VERTICAL | VIEWPORT_FLAG_HIDE_BASE); } gfx_invalidate_screen(); tool_cancel(); } /** * * rct2: 0x006D27A3 */ static void setup_scenery_selection(rct_window* w) { if (gTrackDesignSaveMode){ cancel_scenery_selection(); } while (tool_set(w, WIDX_BACKGROUND, TOOL_CROSSHAIR)); gTrackDesignSaveRideIndex = (uint8)w->number; track_design_save_init(); gGamePaused |= GAME_PAUSED_SAVING_TRACK; gTrackDesignSaveMode = true; audio_pause_sounds(); rct_window* w_main = window_get_main(); if (w_main){ w_main->viewport->flags |= (VIEWPORT_FLAG_HIDE_VERTICAL | VIEWPORT_FLAG_HIDE_BASE); } gfx_invalidate_screen(); } /** * * rct2: 0x006D3026 */ static void window_ride_measurements_design_reset() { track_design_save_reset_scenery(); } /** * * rct2: 0x006D303D */ static void window_ride_measurements_design_select_nearby_scenery() { track_design_save_select_nearby_scenery(gTrackDesignSaveRideIndex); } /** * * rct2: 0x006AD4DA */ void window_ride_measurements_design_cancel() { if (gTrackDesignSaveMode) { cancel_scenery_selection(); } } /** * * rct2: 0x006AD4CD */ static void window_ride_measurements_design_save(rct_window *w) { track_design_save((uint8)w->number); } /** * * rct2: 0x006AD4DA */ static void window_ride_measurements_close(rct_window *w) { window_ride_measurements_design_cancel(); } /** * * rct2: 0x006AD478 */ static void window_ride_measurements_mouseup(rct_window *w, rct_widgetindex widgetIndex) { switch (widgetIndex) { case WIDX_CLOSE: window_close(w); break; case WIDX_TAB_1: case WIDX_TAB_2: case WIDX_TAB_3: case WIDX_TAB_4: case WIDX_TAB_5: case WIDX_TAB_6: case WIDX_TAB_7: case WIDX_TAB_8: case WIDX_TAB_9: case WIDX_TAB_10: window_ride_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_SELECT_NEARBY_SCENERY: window_ride_measurements_design_select_nearby_scenery(); break; case WIDX_RESET_SELECTION: window_ride_measurements_design_reset(); break; case WIDX_SAVE_DESIGN: window_ride_measurements_design_save(w); break; case WIDX_CANCEL_DESIGN: window_ride_measurements_design_cancel(); break; } } /** * * rct2: 0x006AD564 */ static void window_ride_measurements_resize(rct_window *w) { window_set_resize(w, 316, 202, 316, 202); } /** * * rct2: 0x006AD4AB */ static void window_ride_measurements_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget) { if (widgetIndex != WIDX_SAVE_TRACK_DESIGN) return; gDropdownItemsFormat[0] = STR_SAVE_TRACK_DESIGN_ITEM; gDropdownItemsFormat[1] = STR_SAVE_TRACK_DESIGN_WITH_SCENERY_ITEM; window_dropdown_show_text( w->x + widget->left, w->y + widget->top, widget->bottom - widget->top + 1, w->colours[1], 0, 2 ); gDropdownDefaultIndex = 0; if (gScreenFlags & SCREEN_FLAGS_TRACK_DESIGNER) gDropdownItemsDisabled |= 2; } /** * * rct2: 0x006AD4B2 */ static void window_ride_measurements_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex) { if (widgetIndex != WIDX_SAVE_TRACK_DESIGN) return; if (dropdownIndex == -1) dropdownIndex = gDropdownHighlightedIndex; if (dropdownIndex == 0) track_design_save((uint8)w->number); else setup_scenery_selection(w); } /** * * rct2: 0x006AD5DD */ static void window_ride_measurements_update(rct_window *w) { w->frame_no++; window_event_invalidate_call(w); widget_invalidate(w, WIDX_TAB_7); } /** * * rct2: 0x006D2AE7 */ static void window_ride_measurements_tooldown(rct_window *w, rct_widgetindex widgetIndex, sint32 x, sint32 y) { rct_map_element *mapElement; sint16 mapX, mapY; sint32 interactionType; _lastSceneryX = x; _lastSceneryY = y; _collectTrackDesignScenery = true; // Default to true in case user does not select anything valid get_map_coordinates_from_pos(x, y, 0xFCCF, &mapX, &mapY, &interactionType, &mapElement, NULL); switch (interactionType) { case VIEWPORT_INTERACTION_ITEM_SCENERY: case VIEWPORT_INTERACTION_ITEM_LARGE_SCENERY: case VIEWPORT_INTERACTION_ITEM_WALL: case VIEWPORT_INTERACTION_ITEM_FOOTPATH: _collectTrackDesignScenery = !track_design_save_contains_map_element(mapElement); track_design_save_select_map_element(interactionType, mapX, mapY, mapElement, _collectTrackDesignScenery); break; } } static void window_ride_measurements_tooldrag(rct_window *w, rct_widgetindex widgetIndex, sint32 x, sint32 y) { if (x == _lastSceneryX && y == _lastSceneryY) return; _lastSceneryX = x; _lastSceneryY = y; rct_map_element *mapElement; sint16 mapX, mapY; sint32 interactionType; get_map_coordinates_from_pos(x, y, 0xFCCF, &mapX, &mapY, &interactionType, &mapElement, NULL); switch (interactionType) { case VIEWPORT_INTERACTION_ITEM_SCENERY: case VIEWPORT_INTERACTION_ITEM_LARGE_SCENERY: case VIEWPORT_INTERACTION_ITEM_WALL: case VIEWPORT_INTERACTION_ITEM_FOOTPATH: track_design_save_select_map_element(interactionType, mapX, mapY, mapElement, _collectTrackDesignScenery); break; } } /** * * rct2: 0x006AD4DA */ static void window_ride_measurements_toolabort(rct_window *w, rct_widgetindex widgetIndex) { window_ride_measurements_design_cancel(); } /** * * rct2: 0x006ACDBC */ static void window_ride_measurements_invalidate(rct_window *w) { rct_widget *widgets; widgets = window_ride_page_widgets[w->page]; if (w->widgets != widgets) { w->widgets = widgets; window_init_scroll_widgets(w); } window_ride_set_pressed_tab(w); rct_ride *ride = get_ride(w->number); set_format_arg(0, rct_string_id, ride->name); set_format_arg(2, uint32, ride->name_arguments); window_ride_measurements_widgets[WIDX_SAVE_TRACK_DESIGN].tooltip = STR_SAVE_TRACK_DESIGN_NOT_POSSIBLE; window_ride_measurements_widgets[WIDX_SAVE_TRACK_DESIGN].type = WWT_EMPTY; if (gTrackDesignSaveMode && gTrackDesignSaveRideIndex == w->number) { window_ride_measurements_widgets[WIDX_SELECT_NEARBY_SCENERY].type = WWT_DROPDOWN_BUTTON; window_ride_measurements_widgets[WIDX_RESET_SELECTION].type = WWT_DROPDOWN_BUTTON; window_ride_measurements_widgets[WIDX_SAVE_DESIGN].type = WWT_DROPDOWN_BUTTON; window_ride_measurements_widgets[WIDX_CANCEL_DESIGN].type = WWT_DROPDOWN_BUTTON; } else { window_ride_measurements_widgets[WIDX_SELECT_NEARBY_SCENERY].type = WWT_EMPTY; window_ride_measurements_widgets[WIDX_RESET_SELECTION].type = WWT_EMPTY; window_ride_measurements_widgets[WIDX_SAVE_DESIGN].type = WWT_EMPTY; window_ride_measurements_widgets[WIDX_CANCEL_DESIGN].type = WWT_EMPTY; if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK)) { window_ride_measurements_widgets[WIDX_SAVE_TRACK_DESIGN].type = WWT_FLATBTN; w->disabled_widgets |= (1 << WIDX_SAVE_TRACK_DESIGN); if (ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED) { if (ride->excitement != RIDE_RATING_UNDEFINED) { w->disabled_widgets &= ~(1 << WIDX_SAVE_TRACK_DESIGN); window_ride_measurements_widgets[WIDX_SAVE_TRACK_DESIGN].tooltip = STR_SAVE_TRACK_DESIGN; } } } } window_ride_anchor_border_widgets(w); window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); } /** * * rct2: 0x006ACF07 */ static void window_ride_measurements_paint(rct_window *w, rct_drawpixelinfo *dpi) { sint16 holes, maxSpeed, averageSpeed, drops, highestDropHeight, inversions, time; sint32 maxPositiveVerticalGs, maxNegativeVerticalGs, maxLateralGs, totalAirTime, length; window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); if (window_ride_measurements_widgets[WIDX_SAVE_DESIGN].type == WWT_DROPDOWN_BUTTON) { rct_widget *widget = &window_ride_measurements_widgets[WIDX_PAGE_BACKGROUND]; sint32 x = w->x + (widget->right - widget->left) / 2; sint32 y = w->y + widget->top + 40; gfx_draw_string_centred_wrapped(dpi, NULL, x, y, w->width - 8, STR_CLICK_ITEMS_OF_SCENERY_TO_SELECT, COLOUR_BLACK); x = w->x + 4; y = w->y + window_ride_measurements_widgets[WIDX_SELECT_NEARBY_SCENERY].bottom + 17; gfx_fill_rect_inset(dpi, x, y, w->x + 312, y + 1, w->colours[1], INSET_RECT_FLAG_BORDER_INSET); } else { rct_ride *ride = get_ride(w->number); sint32 x = w->x + window_ride_measurements_widgets[WIDX_PAGE_BACKGROUND].left + 4; sint32 y = w->y + window_ride_measurements_widgets[WIDX_PAGE_BACKGROUND].top + 4; if (ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED) { // Excitement rct_string_id ratingName = get_rating_name(ride->excitement); set_format_arg(0, uint32, ride->excitement); set_format_arg(4, rct_string_id, ratingName); rct_string_id stringId = ride->excitement == RIDE_RATING_UNDEFINED ? STR_EXCITEMENT_RATING_NOT_YET_AVAILABLE : STR_EXCITEMENT_RATING; gfx_draw_string_left(dpi, stringId, gCommonFormatArgs, COLOUR_BLACK, x, y); y += 10; // Intensity ratingName = get_rating_name(ride->intensity); set_format_arg(0, uint32, ride->intensity); set_format_arg(4, rct_string_id, ratingName); stringId = STR_INTENSITY_RATING; if (ride->excitement == RIDE_RATING_UNDEFINED) stringId = STR_INTENSITY_RATING_NOT_YET_AVAILABLE; else if (ride->intensity >= RIDE_RATING(10,00)) stringId = STR_INTENSITY_RATING_RED; gfx_draw_string_left(dpi, stringId, gCommonFormatArgs, COLOUR_BLACK, x, y); y += 10; // Nausea ratingName = get_rating_name(ride->nausea); set_format_arg(0, uint32, ride->nausea); set_format_arg(4, rct_string_id, ratingName); stringId = ride->excitement == RIDE_RATING_UNDEFINED ? STR_NAUSEA_RATING_NOT_YET_AVAILABLE : STR_NAUSEA_RATING; gfx_draw_string_left(dpi, stringId, gCommonFormatArgs, COLOUR_BLACK, x, y); y += 20; // Horizontal rule gfx_fill_rect_inset(dpi, x, y - 6, x + 303, y - 5, w->colours[1], INSET_RECT_FLAG_BORDER_INSET); if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_NO_RAW_STATS)) { if (ride->type == RIDE_TYPE_MINI_GOLF) { // Holes holes = ride->holes & 0x1F; gfx_draw_string_left(dpi, STR_HOLES, &holes, COLOUR_BLACK, x, y); y += 10; } else { // Max speed maxSpeed = (ride->max_speed * 9) >> 18; gfx_draw_string_left(dpi, STR_MAX_SPEED, &maxSpeed, COLOUR_BLACK, x, y); y += 10; // Average speed averageSpeed = (ride->average_speed * 9) >> 18; gfx_draw_string_left(dpi, STR_AVERAGE_SPEED, &averageSpeed, COLOUR_BLACK, x, y); y += 10; // Ride time sint32 numTimes = 0; for (sint32 i = 0; i < ride->num_stations; i++) { time = ride->time[numTimes]; if (time != 0) { set_format_arg(0 + (numTimes * 4), uint16, STR_RIDE_TIME_ENTRY_WITH_SEPARATOR); set_format_arg(2 + (numTimes * 4), uint16, time); numTimes++; } } if (numTimes == 0) { set_format_arg(0, rct_string_id, STR_RIDE_TIME_ENTRY); set_format_arg(2, uint16, 0); numTimes++; } else { //sadly, STR_RIDE_TIME_ENTRY_WITH_SEPARATOR are defined with the separator AFTER an entry //therefore we set the last entry to use the no-separator format now, post-format set_format_arg(0 + ((numTimes - 1) * 4), uint16, STR_RIDE_TIME_ENTRY); } set_format_arg(0 + (numTimes * 4), uint16, 0); set_format_arg(2 + (numTimes * 4), uint16, 0); set_format_arg(4 + (numTimes * 4), uint16, 0); set_format_arg(6 + (numTimes * 4), uint16, 0); gfx_draw_string_left_clipped(dpi, STR_RIDE_TIME, gCommonFormatArgs, COLOUR_BLACK, x, y, 308); y += 10; } // Ride length sint32 numLengths = 0; for (sint32 i = 0; i < ride->num_stations; i++) { length = ride->length[numLengths]; if (length != 0) { length >>= 16; set_format_arg(0 + (numLengths * 4), uint16, STR_RIDE_LENGTH_ENTRY_WITH_SEPARATOR); set_format_arg(2 + (numLengths * 4), uint16, (length & 0xFFFF)); numLengths++; } } if (numLengths == 0) { set_format_arg(0, rct_string_id, STR_RIDE_LENGTH_ENTRY); set_format_arg(2, uint16, 0); numLengths++; } else { //sadly, STR_RIDE_LENGTH_ENTRY_WITH_SEPARATOR are defined with the separator AFTER an entry //therefore we set the last entry to use the no-separator format now, post-format set_format_arg(0 + ((numLengths - 1) * 4), rct_string_id, STR_RIDE_LENGTH_ENTRY); } set_format_arg(0 + (numLengths * 4), uint16, 0); set_format_arg(2 + (numLengths * 4), uint16, 0); set_format_arg(4 + (numLengths * 4), uint16, 0); set_format_arg(6 + (numLengths * 4), uint16, 0); gfx_draw_string_left_clipped(dpi, STR_RIDE_LENGTH, gCommonFormatArgs, COLOUR_BLACK, x, y, 308); y += 10; if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_G_FORCES)) { // Max. positive vertical G's maxPositiveVerticalGs = ride->max_positive_vertical_g; stringId = maxPositiveVerticalGs >= FIXED_2DP(5,00) ? STR_MAX_POSITIVE_VERTICAL_G_RED : STR_MAX_POSITIVE_VERTICAL_G; gfx_draw_string_left(dpi, stringId, &maxPositiveVerticalGs, COLOUR_BLACK, x, y); y += 10; // Max. negative vertical G's maxNegativeVerticalGs = ride->max_negative_vertical_g; stringId = maxNegativeVerticalGs <= -FIXED_2DP(2,00) ? STR_MAX_NEGATIVE_VERTICAL_G_RED : STR_MAX_NEGATIVE_VERTICAL_G; gfx_draw_string_left(dpi, stringId, &maxNegativeVerticalGs, COLOUR_BLACK, x, y); y += 10; // Max lateral G's maxLateralGs = ride->max_lateral_g; stringId = maxLateralGs >= FIXED_2DP(2,80) ? STR_MAX_LATERAL_G_RED : STR_MAX_LATERAL_G; gfx_draw_string_left(dpi, stringId, &maxLateralGs, COLOUR_BLACK, x, y); y += 10; // Total 'air' time totalAirTime = ride->total_air_time * 3; gfx_draw_string_left(dpi, STR_TOTAL_AIR_TIME, &totalAirTime, COLOUR_BLACK, x, y); y += 10; } if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_DROPS)) { // Drops drops = ride->drops & 0x3F; gfx_draw_string_left(dpi, STR_DROPS, &drops, COLOUR_BLACK, x, y); y += 10; // Highest drop height highestDropHeight = (ride->highest_drop_height * 3) / 4; gfx_draw_string_left(dpi, STR_HIGHEST_DROP_HEIGHT, &highestDropHeight, COLOUR_BLACK, x, y); y += 10; } if (ride->type != RIDE_TYPE_MINI_GOLF) { // Inversions inversions = ride->inversions & 0x1F; if (inversions != 0) { gfx_draw_string_left(dpi, STR_INVERSIONS, &inversions, COLOUR_BLACK, x, y); y += 10; } } } } else { gfx_draw_string_left(dpi, STR_NO_TEST_RESULTS_YET, NULL, COLOUR_BLACK, x, y); } } } #pragma endregion #pragma region Graphs enum { GRAPH_VELOCITY, GRAPH_ALTITUDE, GRAPH_VERTICAL, GRAPH_LATERAL }; /** * * rct2: 0x006AE8A6 */ static void window_ride_set_graph(rct_window *w, sint32 type) { if ((w->list_information_type & 0xFF) == type) { w->list_information_type ^= 0x8000; } else { w->list_information_type &= 0xFF00; w->list_information_type |= type; } window_invalidate(w); } /** * * rct2: 0x006AE85D */ static void window_ride_graphs_mouseup(rct_window *w, rct_widgetindex widgetIndex) { switch (widgetIndex) { case WIDX_CLOSE: window_close(w); break; case WIDX_TAB_1: case WIDX_TAB_2: case WIDX_TAB_3: case WIDX_TAB_4: case WIDX_TAB_5: case WIDX_TAB_6: case WIDX_TAB_7: case WIDX_TAB_8: case WIDX_TAB_9: case WIDX_TAB_10: window_ride_set_page(w, widgetIndex - WIDX_TAB_1); break; } } /** * * rct2: 0x006AE8DA */ static void window_ride_graphs_resize(rct_window *w) { window_set_resize(w, 316, 180, 500, 450); } /** * * rct2: 0x006AE878 */ static void window_ride_graphs_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget) { switch (widgetIndex) { case WIDX_GRAPH_VELOCITY: window_ride_set_graph(w, GRAPH_VELOCITY); break; case WIDX_GRAPH_ALTITUDE: window_ride_set_graph(w, GRAPH_ALTITUDE); break; case WIDX_GRAPH_VERTICAL: window_ride_set_graph(w, GRAPH_VERTICAL); break; case WIDX_GRAPH_LATERAL: window_ride_set_graph(w, GRAPH_LATERAL); break; } } /** * * rct2: 0x006AE95D */ static void window_ride_graphs_update(rct_window *w) { rct_widget *widget; rct_ride_measurement *measurement; sint32 x; w->frame_no++; window_event_invalidate_call(w); widget_invalidate(w, WIDX_TAB_8); window_event_invalidate_call(w); widget_invalidate(w, WIDX_GRAPH); widget = &window_ride_graphs_widgets[WIDX_GRAPH]; x = w->scrolls[0].h_left; if (!(w->list_information_type & 0x8000)) { measurement = ride_get_measurement(w->number, NULL); x = measurement == NULL ? 0 : measurement->current_item - (((widget->right - widget->left) / 4) * 3); } w->scrolls[0].h_left = clamp(0, x, w->scrolls[0].h_right - ((widget->right - widget->left) - 2)); widget_scroll_update_thumbs(w, WIDX_GRAPH); } /** * * rct2: 0x006AEA75 */ static void window_ride_graphs_scrollgetheight(rct_window *w, sint32 scrollIndex, sint32 *width, sint32 *height) { rct_ride_measurement *measurement; window_event_invalidate_call(w); // Set minimum size *width = window_ride_graphs_widgets[WIDX_GRAPH].right - window_ride_graphs_widgets[WIDX_GRAPH].left - 2; // Get measurement size measurement = ride_get_measurement(w->number, NULL); if (measurement != NULL) *width = max(*width, measurement->num_items); } /** * * rct2: 0x006AE953 */ static void window_ride_graphs_15(rct_window *w, sint32 scrollIndex, sint32 scrollAreaType) { w->list_information_type |= 0x8000; } /** * * rct2: 0x006AEA05 */ static void window_ride_graphs_tooltip(rct_window* w, rct_widgetindex widgetIndex, rct_string_id *stringId) { if (widgetIndex == WIDX_GRAPH) { set_format_arg(0, rct_string_id, STR_GRAPH); rct_string_id message; rct_ride_measurement *measurement = ride_get_measurement(w->number, &message); if (measurement != NULL && (measurement->flags & RIDE_MEASUREMENT_FLAG_RUNNING)) { set_format_arg(4, uint16, measurement->vehicle_index + 1); rct_ride *ride = get_ride(w->number); set_format_arg(2, rct_string_id, RideComponentNames[RideNameConvention[ride->type].vehicle].count); } else { *stringId = message; } } else { *stringId = STR_NONE; } } /** * * rct2: 0x006AE372 */ static void window_ride_graphs_invalidate(rct_window *w) { rct_widget *widgets; rct_ride *ride; sint32 x, y; widgets = window_ride_page_widgets[w->page]; if (w->widgets != widgets) { w->widgets = widgets; window_init_scroll_widgets(w); } window_ride_set_pressed_tab(w); ride = get_ride(w->number); set_format_arg(0, rct_string_id, ride->name); set_format_arg(2, uint32, ride->name_arguments); // Set pressed graph button type w->pressed_widgets &= ~(1 << WIDX_GRAPH_VELOCITY); w->pressed_widgets &= ~(1 << WIDX_GRAPH_ALTITUDE); w->pressed_widgets &= ~(1 << WIDX_GRAPH_VERTICAL); w->pressed_widgets &= ~(1 << WIDX_GRAPH_LATERAL); w->pressed_widgets |= (1LL << (WIDX_GRAPH_VELOCITY + (w->list_information_type & 0xFF))); // Hide graph buttons that are not applicable if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_G_FORCES)) { window_ride_graphs_widgets[WIDX_GRAPH_VERTICAL].type = WWT_DROPDOWN_BUTTON; window_ride_graphs_widgets[WIDX_GRAPH_LATERAL].type = WWT_DROPDOWN_BUTTON; } else { window_ride_graphs_widgets[WIDX_GRAPH_VERTICAL].type = WWT_EMPTY; window_ride_graphs_widgets[WIDX_GRAPH_LATERAL].type = WWT_EMPTY; } // Anchor graph widget x = w->width - 4; y = w->height - 18; window_ride_graphs_widgets[WIDX_GRAPH].right = x; window_ride_graphs_widgets[WIDX_GRAPH].bottom = y; y += 3; window_ride_graphs_widgets[WIDX_GRAPH_VELOCITY].top = y; window_ride_graphs_widgets[WIDX_GRAPH_ALTITUDE].top = y; window_ride_graphs_widgets[WIDX_GRAPH_VERTICAL].top = y; window_ride_graphs_widgets[WIDX_GRAPH_LATERAL].top = y; y += 11; window_ride_graphs_widgets[WIDX_GRAPH_VELOCITY].bottom = y; window_ride_graphs_widgets[WIDX_GRAPH_ALTITUDE].bottom = y; window_ride_graphs_widgets[WIDX_GRAPH_VERTICAL].bottom = y; window_ride_graphs_widgets[WIDX_GRAPH_LATERAL].bottom = y; window_ride_anchor_border_widgets(w); window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); } /** * * rct2: 0x006AE4BC */ static void window_ride_graphs_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); } /** * * rct2: 0x006AE4C7 */ static void window_ride_graphs_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32 scrollIndex) { gfx_clear(dpi, ColourMapA[COLOUR_SATURATED_GREEN].darker); rct_widget *widget = &window_ride_graphs_widgets[WIDX_GRAPH]; rct_string_id stringId; rct_ride_measurement *measurement = ride_get_measurement(w->number, &stringId); if (measurement == NULL) { // No measurement message sint32 x = (widget->right - widget->left) / 2; sint32 y = (widget->bottom - widget->top) / 2 - 5; sint32 width = widget->right - widget->left - 2; gfx_draw_string_centred_wrapped(dpi, gCommonFormatArgs, x, y, width, stringId, COLOUR_BLACK); return; } // Vertical grid lines const uint8 lightColour = ColourMapA[COLOUR_SATURATED_GREEN].mid_light; const uint8 darkColour = ColourMapA[COLOUR_SATURATED_GREEN].mid_dark; sint32 time = 0; for (sint32 x = 0; x < dpi->x + dpi->width; x += 80) { if (x + 80 >= dpi->x) { gfx_fill_rect(dpi, x + 0, dpi->y, x + 0, dpi->y + dpi->height - 1, lightColour); gfx_fill_rect(dpi, x + 16, dpi->y, x + 16, dpi->y + dpi->height - 1, darkColour); gfx_fill_rect(dpi, x + 32, dpi->y, x + 32, dpi->y + dpi->height - 1, darkColour); gfx_fill_rect(dpi, x + 48, dpi->y, x + 48, dpi->y + dpi->height - 1, darkColour); gfx_fill_rect(dpi, x + 64, dpi->y, x + 64, dpi->y + dpi->height - 1, darkColour); } time += 5; } // Horizontal grid lines sint32 listType = w->list_information_type & 0xFF; sint16 yUnit = window_graphs_y_axi[listType].unit; rct_string_id stringID = window_graphs_y_axi[listType].label; sint16 yUnitInterval = window_graphs_y_axi[listType].unit_interval; sint16 yInterval = window_graphs_y_axi[listType].interval; // Scale modifier if (listType == GRAPH_ALTITUDE) { yUnit -= gMapBaseZ * 3; } for (sint32 y = widget->bottom - widget->top - 13; y >= 8; y -= yInterval, yUnit += yUnitInterval) { // Minor / major line sint32 colour = yUnit == 0 ? lightColour : darkColour; gfx_fill_rect(dpi, dpi->x, y, dpi->x + dpi->width - 1, y, colour); sint16 scaled_yUnit = yUnit; // Scale modifier if (listType == GRAPH_ALTITUDE) scaled_yUnit /= 2; gfx_draw_string_left(dpi, stringID, &scaled_yUnit, COLOUR_BLACK, w->scrolls[0].h_left + 1, y - 4); } // Time marks time = 0; for (sint32 x = 0; x < dpi->x + dpi->width; x += 80) { if (x + 80 >= dpi->x) gfx_draw_string_left(dpi, STR_RIDE_STATS_TIME, &time, COLOUR_BLACK, x + 2, 1); time += 5; } // Plot sint32 x = dpi->x; sint32 top, bottom; for (sint32 width = 0; width < dpi->width; width++, x++) { if (x < 0 || x >= measurement->num_items - 1) continue; switch (listType) { case GRAPH_VELOCITY: top = measurement->velocity[x] / 2; bottom = measurement->velocity[x + 1] / 2; break; case GRAPH_ALTITUDE: top = measurement->altitude[x]; bottom = measurement->altitude[x + 1]; break; case GRAPH_VERTICAL: top = measurement->vertical[x] + 39; bottom = measurement->vertical[x + 1] + 39; break; case GRAPH_LATERAL: top = measurement->lateral[x] + 52; bottom = measurement->lateral[x + 1] + 52; break; default: log_error("Wrong graph type %d", listType); top = bottom = 0; } top = widget->bottom - widget->top - top - 13; bottom = widget->bottom - widget->top - bottom - 13; if (top > bottom) { sint32 tmp = top; top = bottom; bottom = tmp; } gfx_fill_rect(dpi, x, top, x, bottom, x > measurement->current_item ? PALETTE_INDEX_17 : PALETTE_INDEX_21); } } #pragma endregion #pragma region Income static void update_same_price_throughout_flags(uint32 shop_item) { uint32 newFlags; if (shop_item_is_photo(shop_item)) { newFlags = gSamePriceThroughoutParkA; newFlags ^= (1 << SHOP_ITEM_PHOTO); game_do_command(0, 1, 0, (0x2 << 8), GAME_COMMAND_SET_PARK_OPEN, newFlags, shop_item); newFlags = gSamePriceThroughoutParkB; newFlags ^= (1 << (SHOP_ITEM_PHOTO2 - 32)) | (1 << (SHOP_ITEM_PHOTO3 - 32)) | (1 << (SHOP_ITEM_PHOTO4 - 32)); game_do_command(0, 1, 0, (0x3 << 8), GAME_COMMAND_SET_PARK_OPEN, newFlags, shop_item); } else { if (shop_item < 32) { newFlags = gSamePriceThroughoutParkA; newFlags ^= (1u << shop_item); game_do_command(0, 1, 0, (0x2 << 8), GAME_COMMAND_SET_PARK_OPEN, newFlags, shop_item); } else { newFlags = gSamePriceThroughoutParkB; newFlags ^= (1u << (shop_item - 32)); game_do_command(0, 1, 0, (0x3 << 8), GAME_COMMAND_SET_PARK_OPEN, newFlags, shop_item); } } } /** * * rct2: 0x006ADEFD */ static void window_ride_income_toggle_primary_price(rct_window *w) { rct_ride *ride; rct_ride_entry *ride_type; uint32 shop_item; money16 price; ride = get_ride(w->number); ride_type = get_ride_entry(ride->subtype); if (ride->type == RIDE_TYPE_TOILETS) { shop_item = SHOP_ITEM_ADMISSION; } else { shop_item = ride_type->shop_item; if (shop_item == 0xFFFF) return; } update_same_price_throughout_flags(shop_item); price = ride->price; game_do_command(0, 1, 0, w->number, GAME_COMMAND_SET_RIDE_PRICE, price, 0); } /** * * rct2: 0x006AE06E */ static void window_ride_income_toggle_secondary_price(rct_window *w) { rct_ride *ride; rct_ride_entry *ride_type; uint32 shop_item; money16 price; ride = get_ride(w->number); ride_type = get_ride_entry(ride->subtype); shop_item = ride_type->shop_item_secondary; if (shop_item == 0xFF) shop_item = RidePhotoItems[ride->type]; update_same_price_throughout_flags(shop_item); price = ride->price_secondary; game_do_command(0, 1, 0, (1 << 8) | w->number, GAME_COMMAND_SET_RIDE_PRICE, price, 0); } /** * * rct2: 0x006AE1E4 */ static void window_ride_income_increase_primary_price(rct_window *w) { rct_ride *ride; rct_ride_entry *ride_type; ride = get_ride(w->number); ride_type = get_ride_entry(ride->subtype); if ((gParkFlags & PARK_FLAGS_PARK_FREE_ENTRY) == 0) { if (ride->type != RIDE_TYPE_TOILETS && ride_type->shop_item == 0xFF) { if (!gCheatsUnlockAllPrices) return; } } money16 price = ride->price; if (price < MONEY(20, 00)) price++; game_do_command(0, 1, 0, w->number, GAME_COMMAND_SET_RIDE_PRICE, price, 0); } /** * * rct2: 0x006AE237 */ static void window_ride_income_decrease_primary_price(rct_window *w) { rct_ride *ride; rct_ride_entry *ride_type; ride = get_ride(w->number); ride_type = get_ride_entry(ride->subtype); if ((gParkFlags & PARK_FLAGS_PARK_FREE_ENTRY) == 0) { if (ride->type != RIDE_TYPE_TOILETS && ride_type->shop_item == 0xFF) { if (!gCheatsUnlockAllPrices) return; } } money16 price = ride->price; if (price > MONEY(0, 00)) price--; game_do_command(0, 1, 0, w->number, GAME_COMMAND_SET_RIDE_PRICE, price, 0); } /** * * rct2: 0x006AE269 */ static void window_ride_income_increase_secondary_price(rct_window *w) { rct_ride *ride; ride = get_ride(w->number); money16 price = ride->price_secondary; if (price < MONEY(20, 00)) price++; game_do_command(0, 1, 0, (w->number & 0x00FF) | 0x0100, GAME_COMMAND_SET_RIDE_PRICE, price, 0); } /** * * rct2: 0x006AE28D */ static void window_ride_income_decrease_secondary_price(rct_window *w) { rct_ride *ride; ride = get_ride(w->number); money16 price = ride->price_secondary; if (price > MONEY(0, 00)) price--; game_do_command(0, 1, 0, (w->number & 0x00FF) | 0x0100, GAME_COMMAND_SET_RIDE_PRICE, price, 0); } /** * * rct2: 0x006ADEA9 */ static void window_ride_income_mouseup(rct_window *w, rct_widgetindex widgetIndex) { switch (widgetIndex) { case WIDX_CLOSE: window_close(w); break; case WIDX_TAB_1: case WIDX_TAB_2: case WIDX_TAB_3: case WIDX_TAB_4: case WIDX_TAB_5: case WIDX_TAB_6: case WIDX_TAB_7: case WIDX_TAB_8: case WIDX_TAB_9: case WIDX_TAB_10: window_ride_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK: window_ride_income_toggle_primary_price(w); break; case WIDX_SECONDARY_PRICE_SAME_THROUGHOUT_PARK: window_ride_income_toggle_secondary_price(w); break; } } /** * * rct2: 0x006AE2F8 */ static void window_ride_income_resize(rct_window *w) { window_set_resize(w, 316, 177, 316, 177); } /** * * rct2: 0x006ADED4 */ static void window_ride_income_mousedown(rct_widgetindex widgetIndex, rct_window *w, rct_widget *widget) { switch (widgetIndex) { case WIDX_PRIMARY_PRICE_INCREASE: window_ride_income_increase_primary_price(w); break; case WIDX_PRIMARY_PRICE_DECREASE: window_ride_income_decrease_primary_price(w); break; case WIDX_SECONDARY_PRICE_INCREASE: window_ride_income_increase_secondary_price(w); break; case WIDX_SECONDARY_PRICE_DECREASE: window_ride_income_decrease_secondary_price(w); break; } } /** * * rct2: 0x006AE2BF */ static void window_ride_income_update(rct_window *w) { rct_ride *ride; w->frame_no++; window_event_invalidate_call(w); widget_invalidate(w, WIDX_TAB_9); ride = get_ride(w->number); if (ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_INCOME) { ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_INCOME; window_invalidate(w); } } /** * * rct2: 0x006ADAA3 */ static void window_ride_income_invalidate(rct_window *w) { rct_widget *widgets; rct_ride_entry *rideEntry; sint32 primaryItem, secondaryItem; widgets = window_ride_page_widgets[w->page]; if (w->widgets != widgets) { w->widgets = widgets; window_init_scroll_widgets(w); } window_ride_set_pressed_tab(w); rct_ride *ride = get_ride(w->number); set_format_arg(0, rct_string_id, ride->name); set_format_arg(2, uint32, ride->name_arguments); rideEntry = get_ride_entry_by_ride(ride); // Primary item w->pressed_widgets &= ~(1 << WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK); w->disabled_widgets &= ~(1 << WIDX_PRIMARY_PRICE); window_ride_income_widgets[WIDX_PRIMARY_PRICE_LABEL].tooltip = STR_NONE; window_ride_income_widgets[WIDX_PRIMARY_PRICE].tooltip = STR_NONE; // If the park doesn't have free entry, lock the admission price, unless the cheat to unlock all prices is activated. if ((!(gParkFlags & PARK_FLAGS_PARK_FREE_ENTRY) && rideEntry->shop_item == SHOP_ITEM_NONE && ride->type != RIDE_TYPE_TOILETS) && (!gCheatsUnlockAllPrices)) { w->disabled_widgets |= (1 << WIDX_PRIMARY_PRICE); window_ride_income_widgets[WIDX_PRIMARY_PRICE_LABEL].tooltip = STR_RIDE_INCOME_ADMISSION_PAY_FOR_ENTRY_TIP; window_ride_income_widgets[WIDX_PRIMARY_PRICE].tooltip = STR_RIDE_INCOME_ADMISSION_PAY_FOR_ENTRY_TIP; } window_ride_income_widgets[WIDX_PRIMARY_PRICE_LABEL].text = STR_RIDE_INCOME_ADMISSION_PRICE; window_ride_income_widgets[WIDX_SECONDARY_PRICE_LABEL].text = STR_SHOP_ITEM_PRICE_LABEL_ON_RIDE_PHOTO; window_ride_income_widgets[WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK].type = WWT_EMPTY; window_ride_income_widgets[WIDX_PRIMARY_PRICE].text = STR_ARG_6_CURRENCY2DP; money16 ridePrimaryPrice = ride_get_price(ride); set_format_arg(6, money32, ridePrimaryPrice); if (ridePrimaryPrice == 0) window_ride_income_widgets[WIDX_PRIMARY_PRICE].text = STR_FREE; primaryItem = SHOP_ITEM_ADMISSION; if (ride->type == RIDE_TYPE_TOILETS || ((primaryItem = rideEntry->shop_item) != SHOP_ITEM_NONE)) { window_ride_income_widgets[WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK].type = WWT_CHECKBOX; if (shop_item_has_common_price(primaryItem)) w->pressed_widgets |= (1 << WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK); window_ride_income_widgets[WIDX_PRIMARY_PRICE_LABEL].text = ShopItemStringIds[primaryItem].price_label; } // Get secondary item secondaryItem = RidePhotoItems[ride->type]; if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO)) { if ((secondaryItem = rideEntry->shop_item_secondary) != SHOP_ITEM_NONE) { window_ride_income_widgets[WIDX_SECONDARY_PRICE_LABEL].text = ShopItemStringIds[secondaryItem].price_label; } } if (secondaryItem == SHOP_ITEM_NONE) { // Hide secondary item widgets window_ride_income_widgets[WIDX_SECONDARY_PRICE_LABEL].type = WWT_EMPTY; window_ride_income_widgets[WIDX_SECONDARY_PRICE].type = WWT_EMPTY; window_ride_income_widgets[WIDX_SECONDARY_PRICE_INCREASE].type = WWT_EMPTY; window_ride_income_widgets[WIDX_SECONDARY_PRICE_DECREASE].type = WWT_EMPTY; window_ride_income_widgets[WIDX_SECONDARY_PRICE_SAME_THROUGHOUT_PARK].type = WWT_EMPTY; } else { // Set same price throughout park checkbox w->pressed_widgets &= ~(1 << WIDX_SECONDARY_PRICE_SAME_THROUGHOUT_PARK); if (shop_item_has_common_price(secondaryItem)) w->pressed_widgets |= (1 << WIDX_SECONDARY_PRICE_SAME_THROUGHOUT_PARK); // Show widgets window_ride_income_widgets[WIDX_SECONDARY_PRICE_LABEL].type = WWT_24; window_ride_income_widgets[WIDX_SECONDARY_PRICE].type = WWT_SPINNER; window_ride_income_widgets[WIDX_SECONDARY_PRICE_INCREASE].type = WWT_DROPDOWN_BUTTON; window_ride_income_widgets[WIDX_SECONDARY_PRICE_DECREASE].type = WWT_DROPDOWN_BUTTON; window_ride_income_widgets[WIDX_SECONDARY_PRICE_SAME_THROUGHOUT_PARK].type = WWT_CHECKBOX; // Set secondary item price window_ride_income_widgets[WIDX_SECONDARY_PRICE].text = STR_RIDE_SECONDARY_PRICE_VALUE; set_format_arg(10, money32, ride->price_secondary); if (ride->price_secondary == 0) window_ride_income_widgets[WIDX_SECONDARY_PRICE].text = STR_FREE; } window_ride_anchor_border_widgets(w); window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); } /** * * rct2: 0x006ADCE5 */ static void window_ride_income_paint(rct_window *w, rct_drawpixelinfo *dpi) { rct_ride *ride; rct_ride_entry *rideEntry; rct_string_id stringId; money32 profit, costPerHour; sint32 x, y, primaryItem, secondaryItem; window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); ride = get_ride(w->number); rideEntry = get_ride_entry_by_ride(ride); x = w->x + window_ride_income_widgets[WIDX_PAGE_BACKGROUND].left + 4; y = w->y + window_ride_income_widgets[WIDX_PAGE_BACKGROUND].top + 29; // Primary item profit / loss per item sold primaryItem = rideEntry->shop_item; if (primaryItem != SHOP_ITEM_NONE) { profit = ride->price; stringId = STR_PROFIT_PER_ITEM_SOLD; profit -= get_shop_item_cost(primaryItem); if (profit < 0) { profit *= -1; stringId = STR_LOSS_PER_ITEM_SOLD; } gfx_draw_string_left(dpi, stringId, &profit, COLOUR_BLACK, x, y); } y += 39; // Secondary item profit / loss per item sold secondaryItem = RidePhotoItems[ride->type]; if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO)) secondaryItem = rideEntry->shop_item_secondary; if (secondaryItem != SHOP_ITEM_NONE) { profit = ride->price_secondary; stringId = STR_PROFIT_PER_ITEM_SOLD; profit -= get_shop_item_cost(secondaryItem); if (profit < 0) { profit *= -1; stringId = STR_LOSS_PER_ITEM_SOLD; } gfx_draw_string_left(dpi, stringId, &profit, COLOUR_BLACK, x, y); } y += 15; // Income per hour if (ride->income_per_hour != MONEY32_UNDEFINED) { gfx_draw_string_left(dpi, STR_INCOME_PER_HOUR, &ride->income_per_hour, COLOUR_BLACK, x, y); y += 10; } // Running cost per hour costPerHour = ride->upkeep_cost * 16; stringId = ride->upkeep_cost == (money16)(uint16)0xFFFF ? STR_RUNNING_COST_UNKNOWN : STR_RUNNING_COST_PER_HOUR; gfx_draw_string_left(dpi, stringId, &costPerHour, COLOUR_BLACK, x, y); y += 10; // Profit per hour if (ride->profit != MONEY32_UNDEFINED) { gfx_draw_string_left(dpi, STR_PROFIT_PER_HOUR, &ride->profit, COLOUR_BLACK, x, y); y += 10; } y += 5; // Total profit gfx_draw_string_left(dpi, STR_TOTAL_PROFIT, &ride->total_profit, COLOUR_BLACK, x, y); } #pragma endregion #pragma region Customer /** * * rct2: 0x006AD986 */ static void window_ride_customer_mouseup(rct_window *w, rct_widgetindex widgetIndex) { switch (widgetIndex) { case WIDX_CLOSE: window_close(w); break; case WIDX_TAB_1: case WIDX_TAB_2: case WIDX_TAB_3: case WIDX_TAB_4: case WIDX_TAB_5: case WIDX_TAB_6: case WIDX_TAB_7: case WIDX_TAB_8: case WIDX_TAB_9: case WIDX_TAB_10: window_ride_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_SHOW_GUESTS_THOUGHTS: window_guest_list_open_with_filter(GLFT_GUESTS_THINKING_ABOUT_RIDE, w->number); break; case WIDX_SHOW_GUESTS_ON_RIDE: window_guest_list_open_with_filter(GLFT_GUESTS_ON_RIDE, w->number); break; case WIDX_SHOW_GUESTS_QUEUING: window_guest_list_open_with_filter(GLFT_GUESTS_IN_QUEUE, w->number); break; } } /** * * rct2: 0x006ADA29 */ static void window_ride_customer_resize(rct_window *w) { w->flags |= WF_RESIZABLE; window_set_resize(w, 316, 149, 316, 149); } /** * * rct2: 0x006AD9DD */ static void window_ride_customer_update(rct_window *w) { rct_ride *ride; w->var_492++; if (w->var_492 >= 24) w->var_492 = 0; window_event_invalidate_call(w); widget_invalidate(w, WIDX_TAB_10); ride = get_ride(w->number); if (ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_CUSTOMER) { ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_CUSTOMER; window_invalidate(w); } } /** * * rct2: 0x006AD5F8 */ static void window_ride_customer_invalidate(rct_window *w) { rct_widget *widgets; widgets = window_ride_page_widgets[w->page]; if (w->widgets != widgets) { w->widgets = widgets; window_init_scroll_widgets(w); } window_ride_set_pressed_tab(w); rct_ride *ride = get_ride(w->number); set_format_arg(0, rct_string_id, ride->name); set_format_arg(2, uint32, ride->name_arguments); window_ride_customer_widgets[WIDX_SHOW_GUESTS_THOUGHTS].type = WWT_FLATBTN; if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) { window_ride_customer_widgets[WIDX_SHOW_GUESTS_ON_RIDE].type = WWT_EMPTY; window_ride_customer_widgets[WIDX_SHOW_GUESTS_QUEUING].type = WWT_EMPTY; } else { window_ride_customer_widgets[WIDX_SHOW_GUESTS_ON_RIDE].type = WWT_FLATBTN; window_ride_customer_widgets[WIDX_SHOW_GUESTS_QUEUING].type = WWT_FLATBTN; } window_ride_anchor_border_widgets(w); window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); } /** * * rct2: 0x006AD6CD */ static void window_ride_customer_paint(rct_window *w, rct_drawpixelinfo *dpi) { rct_ride *ride; sint32 x, y; uint8 shopItem; sint16 popularity, satisfaction, queueTime, age; sint32 customersPerHour; rct_string_id stringId; window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); ride = get_ride(w->number); x = w->x + window_ride_customer_widgets[WIDX_PAGE_BACKGROUND].left + 4; y = w->y + window_ride_customer_widgets[WIDX_PAGE_BACKGROUND].top + 4; // Customers currently on ride if (gRideClassifications[ride->type] == RIDE_CLASS_RIDE) { sint16 customersOnRide = ride->num_riders; gfx_draw_string_left(dpi, STR_CUSTOMERS_ON_RIDE, &customersOnRide, COLOUR_BLACK, x, y); y += 10; } // Customers per hour customersPerHour = ride_customers_per_hour(ride); gfx_draw_string_left(dpi, STR_CUSTOMERS_PER_HOUR, &customersPerHour, COLOUR_BLACK, x, y); y += 10; // Popularity popularity = ride->popularity; if (popularity == 255) { stringId = STR_POPULARITY_UNKNOWN; } else { stringId = STR_POPULARITY_PERCENT; popularity *= 4; } gfx_draw_string_left(dpi, stringId, &popularity, COLOUR_BLACK, x, y); y += 10; // Satisfaction satisfaction = ride->satisfaction; if (satisfaction == 255) { stringId = STR_SATISFACTION_UNKNOWN; } else { stringId = STR_SATISFACTION_PERCENT; satisfaction *= 5; } gfx_draw_string_left(dpi, stringId, &satisfaction, COLOUR_BLACK, x, y); y += 10; // Queue time if (gRideClassifications[ride->type] == RIDE_CLASS_RIDE) { queueTime = ride_get_max_queue_time(ride); stringId = queueTime == 1 ? STR_QUEUE_TIME_MINUTE : STR_QUEUE_TIME_MINUTES; y += gfx_draw_string_left_wrapped(dpi, &queueTime, x, y, 308, stringId, COLOUR_BLACK); y += 5; } // Primary shop items sold shopItem = get_ride_entry_by_ride(ride)->shop_item; if (shopItem != SHOP_ITEM_NONE) { set_format_arg(0, rct_string_id, ShopItemStringIds[shopItem].plural); set_format_arg(2, uint32, ride->no_primary_items_sold); gfx_draw_string_left(dpi, STR_ITEMS_SOLD, gCommonFormatArgs, COLOUR_BLACK, x, y); y += 10; } // Secondary shop items sold / on-ride photos sold shopItem = (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO) ? RidePhotoItems[ride->type] : get_ride_entry_by_ride(ride)->shop_item_secondary; if (shopItem != SHOP_ITEM_NONE) { set_format_arg(0, rct_string_id, ShopItemStringIds[shopItem].plural); set_format_arg(2, uint32, ride->no_secondary_items_sold); gfx_draw_string_left(dpi, STR_ITEMS_SOLD, gCommonFormatArgs, COLOUR_BLACK, x, y); y += 10; } // Total customers gfx_draw_string_left(dpi, STR_TOTAL_CUSTOMERS, &ride->total_customers, COLOUR_BLACK, x, y); y += 10; // Guests favourite if (gRideClassifications[ride->type] == RIDE_CLASS_RIDE) { stringId = ride->guests_favourite == 1 ? STR_FAVOURITE_RIDE_OF_GUEST : STR_FAVOURITE_RIDE_OF_GUESTS; gfx_draw_string_left(dpi, stringId, &ride->guests_favourite, COLOUR_BLACK, x, y); y += 10; } y += 2; // Age //If the ride has a build date that is in the future, show it as built this year. age = max((gDateMonthsElapsed - ride->build_date) / 8, 0); stringId = age == 0 ? STR_BUILT_THIS_YEAR : age == 1 ? STR_BUILT_LAST_YEAR : STR_BUILT_YEARS_AGO; gfx_draw_string_left(dpi, stringId, &age, COLOUR_BLACK, x, y); } #pragma endregion