From 508ce63c75a7c6887a8b47dcec60244ebba48bea Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Tue, 9 Sep 2014 17:17:08 +0100 Subject: [PATCH] finish operating tab on ride window --- src/ride_data.c | 95 +++++++++++++++++++++++ src/ride_data.h | 1 + src/window_ride.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 283 insertions(+) diff --git a/src/ride_data.c b/src/ride_data.c index f1b91e2751..48ea5644ff 100644 --- a/src/ride_data.c +++ b/src/ride_data.c @@ -10,6 +10,7 @@ #include #include "rct2.h" +#include "ride.h" #include "ride_data.h" const bool hasRunningTrack[0x60] = { @@ -676,4 +677,98 @@ const rct_ride_name_convention RideNameConvention[96] = { { 1229, 1243, 1257, 0 }, // 58 Mine Ride { 1264, 1243, 1257, 0 }, // 59 LIM Launched Roller Coaster { 1229, 1243, 1257, 0 } +}; + +const uint8 RideAvailableModes[] = { + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 00 Spiral Roller coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 01 Stand Up Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 02 Suspended Swinging + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 03 Inverted + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 04 Steel Mini Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_SHUTTLE, 0xFF, // 05 Mini Railroad + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_SHUTTLE, 0xFF, // 06 Monorail + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 07 Mini Suspended Coaster + RIDE_MODE_BOAT_HIRE, 0xFF, // 08 Bumper Boats + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 09 Wooden Wild Mine/Mouse + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 0A Steeplechase/Motorbike/Soap Box Derby + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 0B Car Ride + RIDE_MODE_UPWARD_LAUNCH, RIDE_MODE_DOWNWARD_LAUNCH, 0xFF, // 0C Launched Freefall + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 0D Bobsleigh Coaster + RIDE_MODE_ROTATING_LIFT, 0xFF, // 0E Observation Tower + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, RIDE_MODE_REVERSE_INCLINE_LAUNCHED_SHUTTLE, RIDE_MODE_POWERED_LAUNCH, 0xFF, // 0F Looping Roller Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 10 Dinghy Slide + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 11 Mine Train Coaster + RIDE_MODE_STATION_TO_STATION, 0xFF, // 12 Chairlift + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0x23, 2, 0xFF, // 13 Corkscrew Roller Coaster + RIDE_MODE_MAZE, 0xFF, // 14 Maze + RIDE_MODE_SINGLE_RIDE_PER_ADMISSION, RIDE_MODE_UNLIMITED_RIDES_PER_ADMISSION, 0xFF, // 15 Spiral Slide + RIDE_MODE_RACE, RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 16 Go Karts + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 17 Log Flume + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 18 River Rapids + RIDE_MODE_BUMPERCAR, 0xFF, // 19 Bumper Cars + RIDE_MODE_SWING, 0xFF, // 1A Pirate Ship + RIDE_MODE_SWING, 0xFF, // 1B Swinging Inverter Ship + RIDE_MODE_SHOP_STALL, 0xFF, // 1C Food Stall + RIDE_MODE_SHOP_STALL, 0xFF, // 1D (none) + RIDE_MODE_SHOP_STALL, 0xFF, // 1E Drink Stall + RIDE_MODE_SHOP_STALL, 0xFF, // 1F (none) + RIDE_MODE_SHOP_STALL, 0xFF, // 20 Shop (all types) + RIDE_MODE_ROTATION, 0xFF, // 21 Merry Go Round + RIDE_MODE_SHOP_STALL, 0xFF, // 22 Balloon Stall (maybe) + RIDE_MODE_SHOP_STALL, 0xFF, // 23 Information Kiosk + RIDE_MODE_SHOP_STALL, 0xFF, // 24 Bathroom + RIDE_MODE_FORWARD_ROTATION, RIDE_MODE_BACKWARD_ROTATION, 0xFF, // 25 Ferris Wheel + RIDE_MODE_FILM_AVENGING_AVIATORS, RIDE_MODE_FILM_THRILL_RIDERS, 0xFF, // 26 Motion Simulator + RIDE_MODE_3D_FILM_MOUSE_TAILS, RIDE_MODE_3D_FILM_STORM_CHASERS, RIDE_MODE_3D_FILM_SPACE_RAIDERS, 0xFF, // 27 3D Cinema + RIDE_MODE_BEGINNERS, RIDE_MODE_INTENSE, RIDE_MODE_BERSERK, 0xFF, // 28 Gravitron + RIDE_MODE_SPACE_RINGS, 0xFF, // 29 Space Rings + RIDE_MODE_LIM_POWERED_LAUNCH, 0xFF, // 2A Reverse Freefall Coaster + RIDE_MODE_SHUTTLE, 0xFF, // 2B Elevator + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 2C Vertical Drop Roller Coaster + RIDE_MODE_SHOP_STALL, 0xFF, // 2D ATM + RIDE_MODE_ROTATION, 0xFF, // 2E Twist + RIDE_MODE_HAUNTED_HOUSE, 0xFF, // 2F Haunted House + RIDE_MODE_SHOP_STALL, 0xFF, // 30 First Aid + RIDE_MODE_CIRCUS_SHOW, 0xFF, // 31 Circus Show + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 32 Ghost Train + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 33 Twister Roller Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 34 Wooden Roller Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 35 Side-Friction Roller Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 36 Wild Mouse + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 37 Multi Dimension Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 38 (none) + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 39 Flying Roller Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 3A (none) + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 3B Virginia Reel + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 3C Splash Boats + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 3D Mini Helicopters + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 3E Lay-down Roller Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_SHUTTLE, 0xFF, // 3F Suspended Monorail + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 40 (none) + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 41 Reverser Roller Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 42 Heartline Twister Roller Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 43 Mini Golf + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 44 Giga Coaster + RIDE_MODE_FREEFALL_DROP, 0xFF, // 45 Roto-Drop + RIDE_MODE_BUMPERCAR, 0xFF, // 46 Flying Saucers + RIDE_MODE_CROOKED_HOUSE, 0xFF, // 47 Crooked House + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 48 Monorail Cycles + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 2, 0xFF, // 49 Compact Inverted Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 4A Water Coaster + RIDE_MODE_POWERED_LAUNCH, 0xFF, // 4B Air Powered Vertical Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 4C Inverted Hairpin Coaster + RIDE_MODE_SWING, 0xFF, // 4D Magic Carpet + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 4E Submarine Ride + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 4F River Rafts + RIDE_MODE_SHOP_STALL, 0xFF, // 50 (none) + RIDE_MODE_ROTATION, 0xFF, // 51 Enterprise + RIDE_MODE_SHOP_STALL, 0xFF, // 52 (none) + RIDE_MODE_SHOP_STALL, 0xFF, // 53 (none) + RIDE_MODE_SHOP_STALL, 0xFF, // 54 (none) + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 55 (none) + RIDE_MODE_POWERED_LAUNCH, 0xFF, // 56 Inverted Impulse Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 57 Mini Roller Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 58 Mine Ride + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 59 LIM Launched Roller Coaster + RIDE_MODE_POWERED_LAUNCH_35, RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED, 0xFF // 60 (none) }; \ No newline at end of file diff --git a/src/ride_data.h b/src/ride_data.h index 846ce84a9f..0d0bcb658b 100644 --- a/src/ride_data.h +++ b/src/ride_data.h @@ -41,5 +41,6 @@ extern const bool rideUnknownData2[0x60]; extern const uint8 rideUnknownData3[0x60]; extern const rct_ride_name_convention RideNameConvention[96]; +extern const uint8 RideAvailableModes[]; #endif \ No newline at end of file diff --git a/src/window_ride.c b/src/window_ride.c index 6c7d33e160..0348217aa0 100644 --- a/src/window_ride.c +++ b/src/window_ride.c @@ -1696,6 +1696,156 @@ static void window_ride_main_paint() #pragma region Operating +static void set_operating_setting(int rideNumber, uint8 setting, uint8 value) +{ + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_CHANGE_OPERATING_MODE; + game_do_command(0, (value << 8) | 1, 0, (setting << 8) | rideNumber, GAME_COMMAND_11, 0, 0); +} + +static void window_ride_mode_tweak_set(rct_window *w, uint8 value) +{ + rct_ride *ride = GET_RIDE(w->number); + + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1362; + if (ride->mode == RIDE_MODE_STATION_TO_STATION) + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1361; + if (ride->mode == RIDE_MODE_RACE) + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1738; + if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x2000) + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1746; + if (ride->mode == RIDE_MODE_BUMPERCAR) + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1751; + if (ride->mode == RIDE_MODE_SWING) + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1768; + if (ride->mode == RIDE_MODE_ROTATION) + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1868; + if ( + ride->mode == RIDE_MODE_ROTATION || + ride->mode == RIDE_MODE_FORWARD_ROTATION || + ride->mode == RIDE_MODE_BACKWARD_ROTATION + ) + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1868; + + game_do_command(0, (value << 8) | 1, 0, (4 << 8) | w->number, GAME_COMMAND_11, 0, 0); +} + +/** + * + * rct2: 0x006B11D5 + */ +static void window_ride_mode_tweak_increase(rct_window *w) +{ + rct_ride *ride = GET_RIDE(w->number); + uint8 value = ride->var_0D0; + if (value < RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8) + 5, uint8)) + value += ride->mode == RIDE_MODE_BUMPERCAR ? 10 : 1; + + window_ride_mode_tweak_set(w, value); +} + +/** + * + * rct2: 0x006B120A + */ +static void window_ride_mode_tweak_decrease(rct_window *w) +{ + rct_ride *ride = GET_RIDE(w->number); + uint8 value = ride->var_0D0; + if (value > RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8) + 4, uint8)) + value -= ride->mode == RIDE_MODE_BUMPERCAR ? 10 : 1; + + window_ride_mode_tweak_set(w, value); +} + +/** + * + * rct2: 0x006B1631 + */ +static void window_ride_mode_dropdown(rct_window *w, rct_widget *widget) +{ + rct_ride_type *rideEntry, **rideEntries = (rct_ride_type**)0x009ACFA4; + rct_widget *dropdownWidget; + rct_ride *ride; + const uint8 *availableModes, *mode; + int i, numAvailableModes; + + dropdownWidget = widget - 1; + ride = GET_RIDE(w->number); + rideEntry = rideEntries[ride->subtype]; + + // Seek to available modes for this ride + availableModes = RideAvailableModes; + for (i = 0; i < ride->type; i++) { + while (*(availableModes++) != 255) { } + } + + // Count number of available modes + mode = availableModes; + numAvailableModes = -1; + do { + numAvailableModes++; + } while (*(mode++) != 255); + + // ? + if (rideEntry->var_008 & 0x8000) + numAvailableModes--; + + // ? + if (rideEntry->var_008 & 0x20000) { + availableModes += 2; + numAvailableModes -= 2; + } + + // Create dropdown list + for (i = 0; i < numAvailableModes; i++) { + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = STR_RIDE_MODE_START + 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, + numAvailableModes, + widget->right - dropdownWidget->left + ); + + // Set checked item + for (i = 0; i < numAvailableModes; i++) + if (ride->mode == availableModes[i]) + gDropdownItemsChecked = 1 << i; +} + +/** + * + * rct2: 0x006B15C0 + */ +static void window_ride_load_dropdown(rct_window *w, rct_widget *widget) +{ + rct_widget *dropdownWidget; + int i; + + dropdownWidget = widget - 1; + rct_ride *ride = GET_RIDE(w->number); + + for (i = 0; i < 5; i++) { + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = STR_QUARTER_LOAD + i; + } + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0, + 5, + widget->right - dropdownWidget->left + ); + + gDropdownItemsChecked = (1 << (ride->depart_flags & RIDE_DEPART_WAIT_FOR_LOAD_MASK)); +} + /** * * rct2: 0x006B10A7 @@ -1704,9 +1854,12 @@ static void window_ride_operating_mouseup() { short widgetIndex; rct_window *w; + rct_ride *ride; window_widget_get_registers(w, widgetIndex); + ride = GET_RIDE(w->number); + switch (widgetIndex) { case WIDX_CLOSE: window_close(w); @@ -1724,14 +1877,19 @@ static void window_ride_operating_mouseup() window_ride_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_LOAD_CHECKBOX: + set_operating_setting(w->number, 1, ride->depart_flags ^ RIDE_DEPART_WAIT_FOR_LOAD); break; case WIDX_LEAVE_WHEN_ANOTHER_ARRIVES_CHECKBOX: + set_operating_setting(w->number, 1, ride->depart_flags ^ RIDE_DEPART_LEAVE_WHEN_ANOTHER_ARRIVES); break; case WIDX_MINIMUM_LENGTH_CHECKBOX: + set_operating_setting(w->number, 1, ride->depart_flags ^ RIDE_DEPART_WAIT_FOR_MINIMUM_LENGTH); break; case WIDX_MAXIMUM_LENGTH_CHECKBOX: + set_operating_setting(w->number, 1, ride->depart_flags ^ RIDE_DEPART_WAIT_FOR_MAXIMUM_LENGTH); break; case WIDX_SYNCHRONISE_WITH_ADJACENT_STATIONS_CHECKBOX: + set_operating_setting(w->number, 1, ride->depart_flags ^ RIDE_DEPART_SYNCHRONISE_WITH_ADJACENT_STATIONS); break; } } @@ -1755,30 +1913,44 @@ static void window_ride_operating_resize() */ static void window_ride_operating_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) { + rct_ride *ride = GET_RIDE(w->number); + 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: + set_operating_setting(w->number, 8, min(ride->lift_hill_speed + 1, RCT2_GLOBAL(0x0097D7CA + (ride->type * 4), uint8))); break; case WIDX_LIFT_HILL_SPEED_DECREASE: + set_operating_setting(w->number, 8, max(RCT2_GLOBAL(0x0097D7C9 + (ride->type * 4), uint8), ride->lift_hill_speed - 1)); break; case WIDX_MINIMUM_LENGTH_INCREASE: + set_operating_setting(w->number, 2, min(ride->min_waiting_time + 1, 250)); break; case WIDX_MINIMUM_LENGTH_DECREASE: + set_operating_setting(w->number, 2, max(0, ride->min_waiting_time - 1)); break; case WIDX_MAXIMUM_LENGTH_INCREASE: + set_operating_setting(w->number, 3, min(ride->max_waiting_time + 1, 250)); break; case WIDX_MAXIMUM_LENGTH_DECREASE: + set_operating_setting(w->number, 3, max(0, ride->max_waiting_time - 1)); 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: + set_operating_setting(w->number, 9, min(ride->num_circuits + 1, 7)); break; case WIDX_OPERATE_NUMBER_OF_CIRCUITS_DECREASE: + set_operating_setting(w->number, 9, max(1, ride->num_circuits - 1)); break; } } @@ -1791,13 +1963,28 @@ static void window_ride_operating_dropdown() { rct_window *w; short widgetIndex, dropdownIndex; + rct_ride *ride; + const uint8 *availableModes; + int i; window_dropdown_get_registers(w, widgetIndex, dropdownIndex); + if (dropdownIndex == -1) + return; + + ride = GET_RIDE(w->number); + switch (widgetIndex) { case WIDX_MODE_DROPDOWN: + // Seek to available modes for this ride + availableModes = RideAvailableModes; + for (i = 0; i < ride->type; i++) { + while (*(availableModes++) != 255) { } + } + set_operating_setting(w->number, 0, availableModes[dropdownIndex]); break; case WIDX_LOAD_DROPDOWN: + set_operating_setting(w->number, 1, (ride->depart_flags & ~RIDE_DEPART_WAIT_FOR_LOAD_MASK) | dropdownIndex); break; } }