diff --git a/src/addresses.h b/src/addresses.h index 22f3f1d3f6..9263eef9b9 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -107,6 +107,8 @@ #define RCT2_ADDRESS_RUN_INTRO_TICK_PART 0x009AC319 +#define RCT2_ADDRESS_RIDE_ENTRIES 0x009ACFA4 + #define RCT2_ADDRESS_INSTALLED_OBJECT_LIST 0x009ADAE8 #define RCT2_ADDRESS_CURRENT_SOUND_DEVICE 0x009AF280 diff --git a/src/award.c b/src/award.c index e8449a55b3..041efa7263 100644 --- a/src/award.c +++ b/src/award.c @@ -474,10 +474,12 @@ static int award_is_deserved_best_custom_designed_rides(int awardType, int activ } /** At least 5 colourful rides and more than half of the rides are colourful. */ +const uint8 dazzling_ride_colours[] = { 5, 14, 20, 30 }; static int award_is_deserved_most_dazzling_ride_colours(int awardType, int activeAwardTypes) { - int i, countedRides, colourfulRides; + int i, j, countedRides, colourfulRides; rct_ride *ride; + uint8 mainTrackColour; if (activeAwardTypes & (1 << PARK_AWARD_MOST_DISAPPOINTING)) return 0; @@ -489,8 +491,14 @@ static int award_is_deserved_most_dazzling_ride_colours(int awardType, int activ continue; countedRides++; - if (ride->var_1BC == 5 || ride->var_1BC == 14 || ride->var_1BC == 20 || ride->var_1BC == 30) - colourfulRides++; + + mainTrackColour = ride->track_colour_main[0]; + for (j = 0; j < countof(dazzling_ride_colours); j++) { + if (mainTrackColour == dazzling_ride_colours[j]) { + colourfulRides++; + break; + } + } } return (colourfulRides >= 5 && colourfulRides >= countedRides - colourfulRides); diff --git a/src/finance.c b/src/finance.c index efedfdff63..447f4fb71b 100644 --- a/src/finance.c +++ b/src/finance.c @@ -130,7 +130,7 @@ void finance_pay_ride_upkeep() if (ride->status != RIDE_STATUS_CLOSED && !(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) { sint16 upkeep = ride->upkeep_cost; if (upkeep != -1) { - ride->var_154 -= upkeep; + ride->total_profit -= upkeep; ride->var_14D |= 2; finance_payment(upkeep, RCT2_EXPENDITURE_TYPE_RIDE_UPKEEP); } diff --git a/src/game.h b/src/game.h index b3d4f15adb..d10b3f533e 100644 --- a/src/game.h +++ b/src/game.h @@ -32,7 +32,7 @@ enum GAME_COMMAND { GAME_COMMAND_7, GAME_COMMAND_SET_RIDE_OPEN, // 8 GAME_COMMAND_9, - GAME_COMMAND_10, + GAME_COMMAND_SET_RIDE_NAME, GAME_COMMAND_11, GAME_COMMAND_12, GAME_COMMAND_13, diff --git a/src/news_item.c b/src/news_item.c index b4c7ec3f29..f00f99553b 100644 --- a/src/news_item.c +++ b/src/news_item.c @@ -212,7 +212,7 @@ void news_item_get_subject_location(int type, int subject, int *x, int *y, int * } // Find the first car of the train peep is on - vehicle = &(g_sprite_list[ride->train_car_map[peep->current_train]]).vehicle; + vehicle = &(g_sprite_list[ride->vehicles[peep->current_train]]).vehicle; // Find the actual car peep is on for (i = 0; i < peep->current_car; i++) vehicle = &(g_sprite_list[vehicle->next_vehicle_on_train]).vehicle; diff --git a/src/park.c b/src/park.c index 3621c3db7f..ed937cab47 100644 --- a/src/park.c +++ b/src/park.c @@ -395,7 +395,7 @@ static int park_calculate_guest_generation_probability() continue; if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)) continue; - if (ride->var_0E4 < 0x2580000) + if (ride->length[0] < (600 << 16)) continue; if (ride->excitement < RIDE_RATING(6,00)) continue; diff --git a/src/peep.c b/src/peep.c index f86c26b1c2..d798790f79 100644 --- a/src/peep.c +++ b/src/peep.c @@ -27,6 +27,7 @@ #include "ride.h" #include "sprite.h" #include "sprites.h" +#include "staff.h" #include "window.h" static void peep_update(rct_peep *peep); @@ -716,3 +717,12 @@ int peep_check_cheatcode(int index, rct_peep *peep) return 1; } + +int peep_is_mechanic(rct_peep *peep) +{ + return ( + peep->sprite_identifier == SPRITE_IDENTIFIER_PEEP && + peep->type == PEEP_TYPE_STAFF && + peep->staff_type == STAFF_TYPE_MECHANIC + ); +} diff --git a/src/peep.h b/src/peep.h index 05cc200039..78569e99be 100644 --- a/src/peep.h +++ b/src/peep.h @@ -457,6 +457,6 @@ void get_arguments_from_thought(rct_peep_thought thought, uint32* argument_1, ui int get_peep_face_sprite_small(rct_peep *peep); int get_peep_face_sprite_large(rct_peep *peep); int peep_check_cheatcode(int index, rct_peep *peep); - +int peep_is_mechanic(rct_peep *peep); #endif diff --git a/src/rct2.h b/src/rct2.h index 643aec1c29..6589990001 100644 --- a/src/rct2.h +++ b/src/rct2.h @@ -84,7 +84,7 @@ typedef fixed32_1dp money32; // would write FIXED_2DP(3,65) #define FIXED_XDP(x, whole, fraction) ((whole) * (10 * x) + (fraction)) #define FIXED_1DP(whole, fraction) FIXED_XDP(1, whole, fraction) -#define FIXED_2DP(whole, fraction) FIXED_XDP(2, whole, fraction) +#define FIXED_2DP(whole, fraction) FIXED_XDP(10, whole, fraction) // Construct a money value in the format MONEY(10,70) to represent 10.70. Fractional part must be two digits. #define MONEY(whole, fraction) ((whole) * 10 + ((fraction) / 10)) diff --git a/src/ride.c b/src/ride.c index 1c2e31db13..a13c4dc12d 100644 --- a/src/ride.c +++ b/src/ride.c @@ -23,6 +23,7 @@ #include "game.h" #include "map.h" #include "news_item.h" +#include "staff.h" #include "sprite.h" #include "ride.h" #include "scenario.h" @@ -476,6 +477,118 @@ int ride_try_construct(rct_map_element *trackMapElement) return 1; } +/** + * + * rct2: 0x006AF561 + */ +void ride_get_status(int rideIndex, int *formatSecondary, int *argument) +{ + rct_ride *ride = &g_ride_list[rideIndex]; + + if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED) { + *formatSecondary = STR_CRASHED; + return; + } + if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) { + *formatSecondary = STR_BROKEN_DOWN; + return; + } + if (ride->status == RIDE_STATUS_CLOSED) { + *formatSecondary = STR_CLOSED; + return; + } + if (ride->status == RIDE_STATUS_TESTING) { + *formatSecondary = STR_TEST_RUN; + return; + } + rct_peep *peep = GET_PEEP(ride->race_winner); + if (ride->mode == RIDE_MODE_RACE && !(ride->lifecycle_flags & RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING) && ride->race_winner != 0xFFFF && peep->sprite_identifier == SPRITE_IDENTIFIER_PEEP) { + if (peep->name_string_idx == STR_GUEST) { + *argument = peep->id; + *formatSecondary = STR_RACE_WON_BY_GUEST; + } else { + *argument = peep->name_string_idx; + *formatSecondary = STR_RACE_WON_BY; + } + } else { + if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x20000)) { + *argument = ride->num_riders; + *formatSecondary = STR_PERSON_ON_RIDE; + if(*argument != 1) + *formatSecondary = STR_PEOPLE_ON_RIDE; + + } else { + *formatSecondary = STR_OPEN; + } + } +} + +rct_peep *ride_get_assigned_mechanic(rct_ride *ride) +{ + rct_peep *peep; + + if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) { + if ( + ride->mechanic_status == RIDE_MECHANIC_STATUS_HEADING || + ride->mechanic_status == 3 || + ride->mechanic_status == 4 + ) { + peep = &(g_sprite_list[ride->mechanic].peep); + if (peep_is_mechanic(peep)) + return peep; + } + } + + return NULL; +} + +int ride_get_total_length(rct_ride *ride) +{ + int i, totalLength = 0; + for (i = 0; i < ride->num_stations; i++) + totalLength += ride->length[i]; + return totalLength; +} + +int ride_can_have_multiple_circuits(rct_ride *ride) +{ + if (!(RCT2_GLOBAL(0x0097D4F2 + (ride->type * 8), uint16) & 0x200)) + return 0; + + // Only allow circuit or launch modes + if ( + ride->mode != RIDE_MODE_CONTINUOUS_CIRCUIT && + ride->mode != RIDE_MODE_REVERSE_INCLINE_LAUNCHED_SHUTTLE && + ride->mode != RIDE_MODE_POWERED_LAUNCH + ) { + return 0; + } + + // Must have no more than one vehicle and one station + if (ride->num_vehicles > 1 || ride->num_stations > 1) + return 0; + + return 1; +} + +track_colour ride_get_track_colour(rct_ride *ride, int colourScheme) +{ + track_colour result; + result.main = ride->track_colour_main[colourScheme]; + result.additional = ride->track_colour_additional[colourScheme]; + result.supports = ride->track_colour_supports[colourScheme]; + return result; +} + +vehicle_colour ride_get_vehicle_colour(rct_ride *ride, int vehicleIndex) +{ + vehicle_colour result; + result.main = ride->vehicle_colours[vehicleIndex] & 0xFF; + result.additional_1 = ride->vehicle_colours[vehicleIndex] >> 8; + result.additional_2 = ride->vehicle_colours_extended[vehicleIndex]; + return result; +} + /** * * rct2: 0x006AC988 @@ -487,10 +600,10 @@ void ride_init_vehicle_speed(rct_ride *ride) int ecx = -1; while (1) { ecx++; - if (ecx >= ride->var_0C8) { + if (ecx >= ride->num_vehicles) { break; } - rct_vehicle *vehicle = &g_sprite_list[ride->train_car_map[ecx]].vehicle; + rct_vehicle *vehicle = &g_sprite_list[ride->vehicles[ecx]].vehicle; vehicle->var_48 &= (1 << 6); uint8 r = scenario_rand(); r = 0xC; @@ -522,4 +635,22 @@ void ride_init_vehicle_speed(rct_ride *ride) } } } +} + +rct_ride_type *ride_get_entry(rct_ride *ride) +{ + return GET_RIDE_ENTRY(ride->subtype); +} + +uint8 *get_ride_entry_indices_for_ride_type(uint8 rideType) +{ + uint8 *typeToRideEntryIndexMap = (uint8*)0x009E32F8; + uint8 *entryIndexList = typeToRideEntryIndexMap; + while (rideType > 0) { + do { + entryIndexList++; + } while (*(entryIndexList - 1) != 255); + rideType--; + } + return entryIndexList; } \ No newline at end of file diff --git a/src/ride.h b/src/ride.h index 13ee2c4090..0c27f18ca6 100644 --- a/src/ride.h +++ b/src/ride.h @@ -22,6 +22,7 @@ #define _RIDE_H_ #include "map.h" +#include "peep.h" #include "rct2.h" #include "string_ids.h" @@ -49,15 +50,22 @@ typedef struct { uint32 var_008; uint8 var_00C; uint8 var_00D; - uint8 pad_00E[0x5]; + uint8 pad_00E; + uint8 var_00F; + uint8 var_010; + uint8 var_011; + uint8 var_012; uint8 var_013; uint8 pad_014[0x19E]; sint8 excitement_multipler; // 0x1B2 sint8 intensity_multipler; // 0x1B3 sint8 nausea_multipler; // 0x1B4 - uint8 pad_1B5[0x09]; + uint8 pad_1B5; + uint32 var_1B6; + uint8 pad_1BA[0x04]; uint8 category[2]; // 0x1BE uint8 shop_item; // 0x1C0 + uint8 shop_item_secondary; // 0x1C1 } rct_ride_type; /** @@ -72,7 +80,7 @@ typedef struct { uint16 pad_002; uint8 mode; // 0x004 uint8 colour_scheme_type; // 0x005 - uint16 car_colours[32]; // 0x006 + uint16 vehicle_colours[32]; // 0x006 uint8 pad_046[0x03]; // 0 = closed, 1 = open, 2 = test uint8 status; // 0x049 @@ -81,32 +89,38 @@ typedef struct { uint16 overall_view; // 0x050 00XX = X, XX00 = Y (* 32 + 16) uint16 station_starts[4]; // 0x052 uint8 station_heights[4]; // 0x05A - uint8 pad_05E[4]; - uint8 var_62[4]; - uint8 pad_66[4]; + uint8 pad_05E[0xC]; uint16 entrances[4]; // 0x06A uint16 exits[4]; // 0x072 uint8 pad_07A[0x0C]; - uint16 train_car_map[1]; // 0x086 Points to the first car in the train - uint8 pad_088[0x3F]; + uint16 vehicles[32]; // 0x086 Points to the first car in the train + uint8 depart_flags; // 0x0C6 // Not sure if these should be uint or sint. - uint8 var_0C7; - uint8 var_0C8; // Number of train cars? - uint8 var_0C9; - - uint8 pad_0CA[0x06]; + uint8 num_stations; // 0x0C7 + uint8 num_vehicles; // 0x0C8 + uint8 num_cars_per_train; // 0x0C9 + uint8 pad_0CA[0x2]; + uint8 var_0CC; + uint8 var_0CD; + uint8 min_waiting_time; // 0x0CE + uint8 max_waiting_time; // 0x0CF uint8 var_0D0; - uint8 pad_0D1[0x13]; - sint32 var_0E4; - sint32 var_0E8; - sint32 var_0EC; - sint32 var_0F0; - uint8 pad_0F4[0x20]; - uint8 var_114; - // Track length? Number of track segments? - uint8 var_115; - uint8 pad_116[0x0E]; + uint8 pad_0D1[0x7]; + sint32 max_speed; // 0x0D8 + sint32 average_speed; // 0x0DC + uint8 pad_0E0[0x4]; + sint32 length[4]; // 0x0E4 + uint16 time[4]; // 0x0F4 + fixed16_2dp max_positive_vertical_g; // 0x0FC + fixed16_2dp max_negative_vertical_g; // 0x0FE + fixed16_2dp max_lateral_g; // 0x100 + uint8 pad_102[0x12]; + uint8 inversions; // 0x114 (???X XXXX) holes for mini golf + uint8 drops; // 0x115 (??XX XXXX) + uint8 pad_116; + uint8 highest_drop_height; // 0x117 + uint8 pad_118[0x0C]; sint16 var_124; sint16 var_126; sint16 var_128; @@ -119,61 +133,81 @@ typedef struct { sint16 var_136; money16 price; // 0x138 uint8 pad_13A[0x06]; - sint16 excitement; // 0x140 - sint16 intensity; // 0x142 - uint16 nausea; // 0x144 + ride_rating excitement; // 0x140 + ride_rating intensity; // 0x142 + ride_rating nausea; // 0x144 uint16 reliability; // 0x146 uint16 pad_148; uint16 var_14A; uint8 pad_14C; uint8 var_14D; - uint8 pad_14E[0x06]; - uint32 var_154; + uint8 pad_14E[0x02]; + uint32 total_customers; // 0x150 + money32 total_profit; // 0x154 uint16 var_158; uint8 pad_15A; uint8 num_riders; // 0x15B uint8 pad_15C[0x24]; - uint16 build_date; - sint16 upkeep_cost; // 0x182 + sint16 build_date; // 0x180 + money16 upkeep_cost; // 0x182 uint16 race_winner; // 0x184 uint8 pad_186[0x06]; uint8 var_18C; - uint8 pad_18D[0x09]; + uint8 mechanic_status; // 0x18D + uint16 mechanic; // 0x18E + uint8 pad_190[0x03]; + uint8 breakdown_reason; // 0x193 + money16 price_secondary; // 0x194 uint16 var_196; // used in computing excitement, nausea, etc uint8 var_198; uint8 var_199; - uint8 pad_19A[0x14]; + uint8 inspection_interval; // 0x19A + uint8 last_inspection; // 0x19B + uint8 pad_19C[0x8]; + uint32 var_1A4; + uint8 pad_1A8[6]; uint8 var_1AE; - uint8 connected_message_throttle; - uint32 pad_1B0; - sint32 profit; // 0x1B4 + uint8 connected_message_throttle; // 0x1AF + money32 income_per_hour; // 0x1B0 + money32 profit; // 0x1B4 uint8 queue_time[4]; // 0x1B8 - uint8 var_1BC; - uint8 pad_1BD[0xD]; - uint16 var_1CA; - uint8 var_1CC; - uint8 var_1CD; + uint8 track_colour_main[4]; // 0x1BC + uint8 track_colour_additional[4]; // 0x1C0 + uint8 track_colour_supports[4]; // 0x1C4 + uint8 music; // 0x1C8 + uint8 entrance_style; // 0x1C9 + uint8 pad_1CA[0x02]; + uint8 num_block_brakes; // 0x1CC + uint8 lift_hill_speed; // 0x1CD uint16 guests_favourite; // 0x1CE uint32 lifecycle_flags; // 0x1D0 - uint8 var_1D4; - uint8 pad_1D5[0x1F]; - // Example value for wild mouse ride is d5 (before it's been constructed) - // I tried searching the IDA file for "1F4" but couldn't find places where - // this is written to. - uint16 var_1F4; - uint8 pad_1F6[0x0a]; + uint8 vehicle_colours_extended[32]; // 0x1D4 + uint16 total_air_time; // 0x1F4 + uint8 pad_1F6; + uint8 num_circuits; // 0x1F7 + uint8 pad_1F8[0x8]; uint16 queue_length[4]; // 0x200 uint8 pad_208[0x58]; } rct_ride; +#define RIDE_MEASUREMENT_MAX_ITEMS 4800 + /** * Ride measurement structure. * size: 0x04B0C */ typedef struct { uint8 var_00; - uint8 pad_01[0x4B0B]; + uint8 var_01; + uint8 pad_02[4]; + uint16 num_items; // 0x0006 + uint16 current_item; // 0x0008 + uint16 var_0A; + sint8 vertical[RIDE_MEASUREMENT_MAX_ITEMS]; // 0x000C + sint8 lateral[RIDE_MEASUREMENT_MAX_ITEMS]; // 0x12CC + uint8 velocity[RIDE_MEASUREMENT_MAX_ITEMS]; // 0x258C + uint8 altitude[RIDE_MEASUREMENT_MAX_ITEMS]; // 0x384C } rct_ride_measurement; enum { @@ -184,7 +218,7 @@ enum { // Constants used by the lifecycle_flags property at 0x1D0 enum { - RIDE_LIFECYCLE_ON_TRACK = 1, + RIDE_LIFECYCLE_ON_TRACK = 1 << 0, RIDE_LIFECYCLE_TESTED = 1 << 1, RIDE_LIFECYCLE_TEST_IN_PROGRESS = 1 << 2, RIDE_LIFECYCLE_NO_RAW_STATS = 1 << 3, @@ -194,13 +228,14 @@ enum { RIDE_LIFECYCLE_BROKEN_DOWN = 1 << 7, RIDE_LIFECYCLE_CRASHED = 1 << 10, - + RIDE_LIFECYCLE_11 = 1 << 11, RIDE_LIFECYCLE_EVER_BEEN_OPENED = 1 << 12, RIDE_LIFECYCLE_MUSIC = 1 << 13, RIDE_LIFECYCLE_INDESTRUCTIBLE = 1 << 14, RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK = 1 << 15, - RIDE_LIFECYCLE_CABLE_LIFT = 1 << 17 + RIDE_LIFECYCLE_CABLE_LIFT = 1 << 17, + RIDE_LIFECYCLE_19 = 1 << 19 }; enum { @@ -305,9 +340,9 @@ enum { }; enum { - RIDE_MODE_NORMAL = 0, + RIDE_MODE_NORMAL, RIDE_MODE_CONTINUOUS_CIRCUIT, - RIDE_MODE_REVERSE_INCLINED_SHUTTLE, + RIDE_MODE_REVERSE_INCLINE_LAUNCHED_SHUTTLE, RIDE_MODE_POWERED_LAUNCH, // RCT1 style? RIDE_MODE_SHUTTLE, RIDE_MODE_BOAT_HIRE, @@ -328,7 +363,7 @@ enum { RIDE_MODE_3D_FILM_MOUSE_TAILS, RIDE_MODE_SPACE_RINGS, RIDE_MODE_BEGINNERS, - RIDE_MODE_LIM_POWERED_LAUNCH, // 0x17 + RIDE_MODE_LIM_POWERED_LAUNCH, RIDE_MODE_FILM_THRILL_RIDERS, RIDE_MODE_3D_FILM_STORM_CHASERS, RIDE_MODE_3D_FILM_SPACE_RAIDERS, @@ -340,7 +375,7 @@ enum { RIDE_MODE_CROOKED_HOUSE, RIDE_MODE_FREEFALL_DROP, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, - RIDE_MODE_POWERED_LAUNCH2, // 0x23. RCT2 style? + RIDE_MODE_POWERED_LAUNCH_35, // RCT2 style? RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED }; @@ -359,6 +394,109 @@ enum { RIDE_GROUP_SHOP }; +enum { + MUSIC_STYLE_DODGEMS_BEAT, + MUSIC_STYLE_FAIRGROUND_ORGAN, + MUSIC_STYLE_ROMAN_FANFARE, + MUSIC_STYLE_ORIENTAL, + MUSIC_STYLE_MARTIAN, + MUSIC_STYLE_JUNGLE_DRUMS, + MUSIC_STYLE_EGYPTIAN, + MUSIC_STYLE_TOYLAND, + MUSIC_STYLE_8, + MUSIC_STYLE_SPACE, + MUSIC_STYLE_HORROR, + MUSIC_STYLE_TECHNO, + MUSIC_STYLE_GENTLE, + MUSIC_STYLE_SUMMER, + MUSIC_STYLE_WATER, + MUSIC_STYLE_WILD_WEST, + MUSIC_STYLE_JURASSIC, + MUSIC_STYLE_ROCK, + MUSIC_STYLE_RAGTIME, + MUSIC_STYLE_FANTASY, + MUSIC_STYLE_ROCK_STYLE_2, + MUSIC_STYLE_ICE, + MUSIC_STYLE_SNOW, + MUSIC_STYLE_CUSTOM_MUSIC_1, + MUSIC_STYLE_CUSTOM_MUSIC_2, + MUSIC_STYLE_MEDIEVAL, + MUSIC_STYLE_URBAN, + MUSIC_STYLE_ORGAN, + MUSIC_STYLE_MECHANICAL, + MUSIC_STYLE_MODERN, + MUSIC_STYLE_PIRATES, + MUSIC_STYLE_ROCK_STYLE_3, + MUSIC_STYLE_CANDY_STYLE +}; + +enum { + BREAKDOWN_NONE = 255, + BREAKDOWN_SAFETY_CUT_OUT = 0, + BREAKDOWN_RESTRAINTS_STUCK_CLOSED, + BREAKDOWN_RESTRAINTS_STUCK_OPEN, + BREAKDOWN_DOORS_STUCK_CLOSED, + BREAKDOWN_DOORS_STUCK_OPEN, + BREAKDOWN_VEHICLE_MALFUNCTION, + BREAKDOWN_BRAKES_FAILURE, + BREAKDOWN_CONTROL_FAILURE +}; + +enum { + RIDE_MECHANIC_STATUS_CALLING = 1, + RIDE_MECHANIC_STATUS_HEADING = 2, + RIDE_MECHANIC_STATUS_FIXING = 3, +}; + +enum { + RIDE_DEPART_WAIT_FOR_LOAD_MASK = 7, + RIDE_DEPART_WAIT_FOR_LOAD = 1 << 3, + RIDE_DEPART_LEAVE_WHEN_ANOTHER_ARRIVES = 1 << 4, + RIDE_DEPART_SYNCHRONISE_WITH_ADJACENT_STATIONS = 1 << 5, + RIDE_DEPART_WAIT_FOR_MINIMUM_LENGTH = 1 << 6, + RIDE_DEPART_WAIT_FOR_MAXIMUM_LENGTH = 1 << 7 +}; + +enum { + RIDE_COLOUR_SCHEME_MAIN, + RIDE_COLOUR_SCHEME_ADDITIONAL_1, + RIDE_COLOUR_SCHEME_ADDITIONAL_2, + RIDE_COLOUR_SCHEME_ADDITIONAL_3 +}; + +enum { + VEHICLE_COLOUR_SCHEME_SAME, + VEHICLE_COLOUR_SCHEME_PER_TRAIN, + VEHICLE_COLOUR_SCHEME_PER_VEHICLE +}; + +enum { + RIDE_ENTRANCE_STYLE_PLAIN, + RIDE_ENTRANCE_STYLE_WOODEN, + RIDE_ENTRANCE_STYLE_CANVAS_TENT, + RIDE_ENTRANCE_STYLE_CASTLE_GREY, + RIDE_ENTRANCE_STYLE_CASTLE_BROWN, + RIDE_ENTRANCE_STYLE_JUNGLE, + RIDE_ENTRANCE_STYLE_LOG_CABIN, + RIDE_ENTRANCE_STYLE_CLASSICAL_ROMAN, + RIDE_ENTRANCE_STYLE_ABSTRACT, + RIDE_ENTRANCE_STYLE_SNOW_ICE, + RIDE_ENTRANCE_STYLE_PAGODA, + RIDE_ENTRANCE_STYLE_SPACE +}; + +typedef struct { + uint8 main; + uint8 additional; + uint8 supports; +} track_colour; + +typedef struct { + uint8 main; + uint8 additional_1; + uint8 additional_2; +} vehicle_colour; + #define MAX_RIDES 255 #define MAX_RIDE_MEASUREMENTS 8 @@ -373,6 +511,7 @@ extern rct_ride* g_ride_list; /** Helper macros until rides are stored in this module. */ #define GET_RIDE(x) (&g_ride_list[x]) #define GET_RIDE_MEASUREMENT(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_MEASUREMENTS, rct_ride_measurement)[x])) +#define GET_RIDE_ENTRY(x) RCT2_ADDRESS(RCT2_ADDRESS_RIDE_ENTRIES, rct_ride_type*)[x] /** * Helper macro loop for enumerating through all the non null rides. @@ -394,6 +533,13 @@ rct_map_element *sub_6CAF80(int rideIndex, int *outX, int *outY); rct_map_element *ride_find_track_gap(rct_map_element *startTrackElement, int *outX, int *outY); void ride_construct_new(int list_item); int ride_try_construct(rct_map_element *trackMapElement); -void ride_init_vehicle_speed(rct_ride *ride); +void ride_get_status(int rideIndex, int *formatSecondary, int *argument); +rct_peep *ride_get_assigned_mechanic(rct_ride *ride); +int ride_get_total_length(rct_ride *ride); +int ride_can_have_multiple_circuits(rct_ride *ride); +track_colour ride_get_track_colour(rct_ride *ride, int colourScheme); +vehicle_colour ride_get_vehicle_colour(rct_ride *ride, int vehicleIndex); +rct_ride_type *ride_get_entry(rct_ride *ride); +uint8 *get_ride_entry_indices_for_ride_type(uint8 rideType); #endif diff --git a/src/ride_data.c b/src/ride_data.c index 086ee8870a..387156f9a7 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] = { @@ -583,4 +584,192 @@ const uint8 rideUnknownData3[0x60] = { 10, // 57 Mini Roller Coaster 10, // 58 Mine Ride 10, // 59 LIM Launched Roller Coaster +}; + +const rct_ride_name_convention RideNameConvention[96] = { + { 1229, 1243, 1257, 0 }, // 00 Spiral Roller coaster + { 1229, 1243, 1257, 0 }, // 01 Stand Up Coaster + { 1229, 1243, 1257, 0 }, // 02 Suspended Swinging + { 1229, 1243, 1257, 0 }, // 03 Inverted + { 1229, 1243, 1257, 0 }, // 04 Steel Mini Coaster + { 1229, 1243, 1257, 0 }, // 05 Mini Railroad + { 1229, 1243, 1257, 0 }, // 06 Monorail + { 1264, 1243, 1257, 0 }, // 07 Mini Suspended Coaster + { 1236, 1250, 1250, 0 }, // 08 Bumper Boats + { 1264, 1243, 1257, 0 }, // 09 Wooden Wild Mine/Mouse + { 1264, 1243, 1257, 0 }, // 0a Steeplechase/Motorbike/Soap Box Derby + { 1264, 1243, 1257, 0 }, // 0b Car Ride + { 1264, 1243, 1257, 0 }, // 0c Launched Freefall + { 1229, 1243, 1257, 0 }, // 0d Bobsleigh Coaster + { 1292, 1243, 1257, 0 }, // 0e Observation Tower + { 1229, 1243, 1257, 0 }, // 0f Looping Roller Coaster + { 1236, 1243, 1257, 0 }, // 10 Dinghy Slide + { 1229, 1243, 1257, 0 }, // 11 Mine Train Coaster + { 1264, 1243, 1257, 0 }, // 12 Chairlift + { 1229, 1243, 1257, 0 }, // 13 Corkscrew Roller Coaster + { 1229, 1243, 1257, 0 }, // 14 Maze + { 1229, 1271, 1257, 0 }, // 15 Spiral Slide + { 1264, 1243, 1257, 0 }, // 16 Go Karts + { 1236, 1243, 1257, 0 }, // 17 Log Flume + { 1236, 1243, 1257, 0 }, // 18 River Rapids + { 1264, 1271, 1257, 0 }, // 19 Bumper Cars + { 1285, 1278, 1257, 0 }, // 1a Pirate Ship + { 1285, 1278, 1257, 0 }, // 1b Swinging Inverter Ship + { 1264, 1271, 1257, 0 }, // 1c Food Stall + { 1264, 1271, 1257, 0 }, // 1d (none) + { 1264, 1271, 1257, 0 }, // 1e Drink Stall + { 1264, 1271, 1257, 0 }, // 1f (none) + { 1264, 1271, 1257, 0 }, // 20 Shop (all types) + { 1264, 1278, 1257, 0 }, // 21 Merry Go Round + { 1264, 1271, 1257, 0 }, // 22 Balloon Stall (maybe) + { 1264, 1271, 1257, 0 }, // 23 Information Kiosk + { 1264, 1271, 1257, 0 }, // 24 Bathroom + { 1299, 1278, 1257, 0 }, // 25 Ferris Wheel + { 1264, 1278, 1257, 0 }, // 26 Motion Simulator + { 1271, 1278, 1257, 0 }, // 27 3D Cinema + { 1264, 1278, 1257, 0 }, // 28 Gravitron + { 1306, 1278, 1257, 0 }, // 29 Space Rings + { 1264, 1243, 1257, 0 }, // 2a Reverse Freefall Coaster + { 1292, 1243, 1257, 0 }, // 2b Elevator + { 1229, 1243, 1257, 0 }, // 2c Vertical Drop Roller Coaster + { 1264, 1271, 1257, 0 }, // 2d ATM + { 1278, 1278, 1257, 0 }, // 2e Twist + { 1271, 1278, 1257, 0 }, // 2f Haunted House + { 1264, 1271, 1257, 0 }, // 30 First Aid + { 1271, 1278, 1257, 0 }, // 31 Circus Show + { 1264, 1243, 1257, 0 }, // 32 Ghost Train + { 1229, 1243, 1257, 0 }, // 33 Twister Roller Coaster + { 1229, 1243, 1257, 0 }, // 34 Wooden Roller Coaster + { 1229, 1243, 1257, 0 }, // 35 Side-Friction Roller Coaster + { 1264, 1243, 1257, 0 }, // 36 Wild Mouse + { 1229, 1243, 1257, 0 }, // 37 Multi Dimension Coaster + { 1229, 1243, 1257, 0 }, // 38 (none) + { 1229, 1243, 1257, 0 }, // 39 Flying Roller Coaster + { 1229, 1243, 1257, 0 }, // 3a (none) + { 1264, 1243, 1257, 0 }, // 3b Virginia Reel + { 1236, 1243, 1257, 0 }, // 3c Splash Boats + { 1264, 1243, 1257, 0 }, // 3d Mini Helicopters + { 1229, 1243, 1257, 0 }, // 3e Lay-down Roller Coaster + { 1229, 1243, 1257, 0 }, // 3f Suspended Monorail + { 1229, 1243, 1257, 0 }, // 40 (none) + { 1264, 1243, 1257, 0 }, // 41 Reverser Roller Coaster + { 1264, 1243, 1257, 0 }, // 42 Heartline Twister Roller Coaster + { 1313, 1320, 1257, 0 }, // 43 Mini Golf + { 1229, 1243, 1257, 0 }, // 44 Giga Coaster + { 1264, 1243, 1257, 0 }, // 45 Roto-Drop + { 1264, 1271, 1257, 0 }, // 46 Flying Saucers + { 1271, 1278, 1257, 0 }, // 47 Crooked House + { 1264, 1243, 1257, 0 }, // 48 Monorail Cycles + { 1229, 1243, 1257, 0 }, // 49 Compact Inverted Coaster + { 1236, 1243, 1257, 0 }, // 4a Water Coaster + { 1229, 1243, 1257, 0 }, // 4b Air Powered Vertical Coaster + { 1264, 1243, 1257, 0 }, // 4c Inverted Hairpin Coaster + { 1264, 1278, 1257, 0 }, // 4d Magic Carpet + { 1236, 1243, 1250, 0 }, // 4e Submarine Ride + { 1236, 1243, 1257, 0 }, // 4f River Rafts + { 1264, 1271, 1257, 0 }, // 50 (none) + { 1299, 1278, 1257, 0 }, // 51 Enterprise + { 1264, 1271, 1257, 0 }, // 52 (none) + { 1264, 1271, 1257, 0 }, // 53 (none) + { 1264, 1271, 1257, 0 }, // 54 (none) + { 1229, 1243, 1257, 0 }, // 55 (none) + { 1229, 1243, 1257, 0 }, // 56 Inverted Impulse Coaster + { 1264, 1243, 1257, 0 }, // 57 Mini Roller Coaster + { 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 d107ad6aac..0d0bcb658b 100644 --- a/src/ride_data.h +++ b/src/ride_data.h @@ -23,6 +23,14 @@ #include #include "rct2.h" +#include "string_ids.h" + +typedef struct { + rct_string_id vehicle_name; + rct_string_id structure_name; + rct_string_id station_name; + rct_string_id unk_name; +} rct_ride_name_convention; extern const bool hasRunningTrack[0x60]; extern const uint8 initialUpkeepCosts[0x60]; @@ -32,4 +40,7 @@ extern const uint8 rideUnknownData1[0x60]; 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/ride_ratings.c b/src/ride_ratings.c index d18fef2753..64553970d6 100644 --- a/src/ride_ratings.c +++ b/src/ride_ratings.c @@ -56,9 +56,9 @@ void crooked_house_excitement(rct_ride *ride) ride->var_14D |= 2; // clear all bits except lowest 5 - ride->var_114 &= 0x1f; + ride->inversions &= 0x1F; // set 6th,7th,8th bits - ride->var_114 |= 0xE0; + ride->inversions |= 0xE0; } /** @@ -75,27 +75,22 @@ uint16 compute_upkeep(rct_ride *ride) uint16 upkeep = initialUpkeepCosts[ride->type]; uint16 trackCost = costPerTrackPiece[ride->type]; - uint8 dl = ride->var_115; + uint8 dl = ride->drops; dl = dl >> 6; dl = dl & 3; upkeep += trackCost * dl; - uint32 cuml = ride->var_0E4; - cuml += ride->var_0E8; - cuml += ride->var_0EC; - cuml += ride->var_0F0; - cuml = cuml >> 0x10; + uint32 totalLength = (ride->length[0] + ride->length[1] + ride->length[2] + ride->length[3]) >> 16; // The data originally here was 20's and 0's. The 20's all represented // rides that had tracks. The 0's were fixed rides like crooked house or // bumper cars. // Data source is 0x0097E3AC if (hasRunningTrack[ride->type]) { - cuml = cuml * 20; + totalLength *= 20; } - cuml = cuml >> 0x0A; - upkeep += (uint16)cuml; + upkeep += (uint16)(totalLength >> 10); if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO) { // The original code read from a table starting at 0x0097E3AE and @@ -130,24 +125,24 @@ uint16 compute_upkeep(rct_ride *ride) // various variables set on the ride itself. // https://gist.github.com/kevinburke/e19b803cd2769d96c540 - upkeep += rideUnknownData1[ride->type] * ride->var_0C8; + upkeep += rideUnknownData1[ride->type] * ride->num_vehicles; // either set to 3 or 0, extra boosts for some rides including mini golf if (rideUnknownData2[ride->type]) { - upkeep += 3 * ride->var_0C9; + upkeep += 3 * ride->num_cars_per_train; } // slight upkeep boosts for some rides - 5 for mini railroad, 10 for log // flume/rapids, 10 for roller coaster, 28 for giga coaster - upkeep += rideUnknownData3[ride->type] * ride->var_0C7; + upkeep += rideUnknownData3[ride->type] * ride->num_stations; - if (ride->mode == RIDE_MODE_REVERSE_INCLINED_SHUTTLE) { + if (ride->mode == RIDE_MODE_REVERSE_INCLINE_LAUNCHED_SHUTTLE) { upkeep += 30; } else if (ride->mode == RIDE_MODE_POWERED_LAUNCH) { upkeep += 160; } else if (ride->mode == RIDE_MODE_LIM_POWERED_LAUNCH) { upkeep += 320; - } else if (ride->mode == RIDE_MODE_POWERED_LAUNCH2 || + } else if (ride->mode == RIDE_MODE_POWERED_LAUNCH_35 || ride->mode == RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED) { upkeep += 220; } @@ -184,7 +179,7 @@ rating_tuple per_ride_rating_adjustments(rct_ride *ride, ride_rating excitement, // more detail: https://gist.github.com/kevinburke/d951e74e678b235eef3e uint16 ridetype_var = RCT2_GLOBAL(0x0097D4F2 + ride->type * 8, uint16); if (ridetype_var & 0x80) { - uint16 ax = ride->var_1F4; + uint16 ax = ride->total_air_time; if (rideType->var_008 & 0x800) { // 65e86e ax = ax - 96; @@ -244,7 +239,7 @@ ride_rating apply_intensity_penalty(ride_rating excitement, ride_rating intensit */ void sub_655FD6(rct_ride *ride) { - uint8 al = ride->var_1CD; + uint8 al = ride->lift_hill_speed; // No idea what this address is; maybe like compensation of some kind? The // maximum possible value? // List of ride names/values is here: diff --git a/src/scenario.c b/src/scenario.c index a2fe85aa31..4851a038d6 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -419,13 +419,7 @@ void scenario_objective8_check() ride->status == RIDE_STATUS_OPEN && ride->excitement >= RIDE_RATING(7,00) && type_already_counted[subtype_id] == 0){ - // this calculates the length, no idea why it's done so complicated though. - uint8 limit = ride->var_0C7; - uint32 sum = 0; - for (int j = 0; j < limit; ++j) { - sum += ((uint32*)&ride->var_0E4)[j]; - } - if ((sum >> 16) > (uint32)objective_length) { + if ((ride_get_total_length(ride) >> 16) > objective_length) { type_already_counted[subtype_id]++; rcs++; } diff --git a/src/sprites.h b/src/sprites.h index ba86b98915..78116c46d0 100644 --- a/src/sprites.h +++ b/src/sprites.h @@ -44,6 +44,8 @@ enum { SPR_RESIZE = 5058, + SPR_CONSTRUCTION = 5164, + SPR_DEMOLISH = 5165, SPR_HEARING_VIEWPORT = 5166, SPR_LOCATE = 5167, SPR_RENAME = 5168, diff --git a/src/string_ids.h b/src/string_ids.h index 5719fd97aa..49d8eced3d 100644 --- a/src/string_ids.h +++ b/src/string_ids.h @@ -252,6 +252,20 @@ enum { STR_LOWER_COST_AMOUNT = 985, STR_COST_AMOUNT = 986, + STR_CONSTRUCTION = 990, + + STR_DEMOLISH_RIDE_TIP = 992, + + STR_OVERALL_VIEW = 996, + STR_VIEW_SELECTION = 997, + + STR_CANT_OPEN = 1002, + STR_CANT_TEST = 1003, + STR_CANT_CLOSE = 1004, + STR_CANT_START_CONSTRUCTION_ON = 1005, + STR_MUST_BE_CLOSED_FIRST = 1006, + STR_UNABLE_TO_CREATE_ENOUGH_VEHICLES = 1007, + STR_OPEN_CLOSE_OR_TEST_RIDE = 1008, STR_OPEN_OR_CLOSE_ALL_RIDES = 1009, STR_OPEN_OR_CLOSE_PARK_TIP = 1010, STR_CLOSE_ALL = 1011, @@ -259,6 +273,8 @@ enum { STR_CLOSE_PARK = 1013, STR_OPEN_PARK = 1014, + STR_CANT_CHANGE_OPERATING_MODE = 1017, + STR_LOCATE_SUBJECT_TIP = 1027, STR_LOAD_GAME_DIALOG_TITLE = 1036, @@ -268,6 +284,99 @@ enum { STR_RCT2_LANDSCAPE_FILE = 1045, STR_RIDES_IN_PARK_TIP = 1053, + STR_NAME_RIDE_TIP = 1054, + + STR_RIDE_ATTRACTION_NAME = 1057, + STR_ENTER_NEW_NAME_FOR_THIS_RIDE_ATTRACTION = 1058, + STR_CANT_RENAME_RIDE_ATTRACTION = 1059, + STR_INVALID_RIDE_ATTRACTION_NAME = 1060, + + STR_RIDE_MODE_START = 1061, + STR_RIDE_MODE_NORMAL = STR_RIDE_MODE_START + 0, + STR_RIDE_MODE_CONTINUOUS_CIRCUIT = STR_RIDE_MODE_START + 1, + STR_RIDE_MODE_REVERSE_INCLINE_LAUNCHED_SHUTTLE = STR_RIDE_MODE_START + 2, + STR_RIDE_MODE_POWERED_LAUNCH = STR_RIDE_MODE_START + 3, + STR_RIDE_MODE_SHUTTLE = STR_RIDE_MODE_START + 4, + STR_RIDE_MODE_BOAT_HIRE = STR_RIDE_MODE_START + 5, + STR_RIDE_MODE_UPWARD_LAUNCH = STR_RIDE_MODE_START + 6, + STR_RIDE_MODE_ROTATING_LIFT = STR_RIDE_MODE_START + 7, + STR_RIDE_MODE_STATION_TO_STATION = STR_RIDE_MODE_START + 8, + STR_RIDE_MODE_SINGLE_RIDE_PER_ADMISSION = STR_RIDE_MODE_START + 9, + STR_RIDE_MODE_UNLIMITED_RIDES_PER_ADMISSION = STR_RIDE_MODE_START + 10, + STR_RIDE_MODE_MAZE = STR_RIDE_MODE_START + 11, + STR_RIDE_MODE_RACE = STR_RIDE_MODE_START + 12, + STR_RIDE_MODE_BUMPER_CAR = STR_RIDE_MODE_START + 13, + STR_RIDE_MODE_SWING = STR_RIDE_MODE_START + 14, + STR_RIDE_MODE_SHOP_STALL = STR_RIDE_MODE_START + 15, + STR_RIDE_MODE_ROTATION = STR_RIDE_MODE_START + 16, + STR_RIDE_MODE_FORWARD_ROTATION = STR_RIDE_MODE_START + 17, + STR_RIDE_MODE_BACKWARD_ROTATION = STR_RIDE_MODE_START + 18, + STR_RIDE_MODE_FILM_AVENGING_AVIATORS = STR_RIDE_MODE_START + 19, + STR_RIDE_MODE_3D_FILM_MOUSE_TAILS = STR_RIDE_MODE_START + 20, + STR_RIDE_MODE_SPACE_RINGS = STR_RIDE_MODE_START + 21, + STR_RIDE_MODE_BEGINNERS = STR_RIDE_MODE_START + 22, + STR_RIDE_MODE_LIM_POWERED_LAUNCH = STR_RIDE_MODE_START + 23, + STR_RIDE_MODE_FILM_THRILL_RIDERS = STR_RIDE_MODE_START + 24, + STR_RIDE_MODE_3D_FILM_STORM_CHASERS = STR_RIDE_MODE_START + 25, + STR_RIDE_MODE_3D_FILM_SPACE_RAIDERS = STR_RIDE_MODE_START + 26, + STR_RIDE_MODE_INTENSE = STR_RIDE_MODE_START + 27, + STR_RIDE_MODE_BERSERK = STR_RIDE_MODE_START + 28, + STR_RIDE_MODE_HAUNTED_HOUSE = STR_RIDE_MODE_START + 29, + STR_RIDE_MODE_CIRCUS_SHOW = STR_RIDE_MODE_START + 30, + STR_RIDE_MODE_DOWNWARD_LAUNCH = STR_RIDE_MODE_START + 31, + STR_RIDE_MODE_CROOKED_HOUSE = STR_RIDE_MODE_START + 32, + STR_RIDE_MODE_FREEFALL_DROP = STR_RIDE_MODE_START + 33, + STR_RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED = STR_RIDE_MODE_START + 34, + STR_RIDE_MODE_POWERED_LAUNCH_35 = STR_RIDE_MODE_START + 35, + STR_RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED_MODE = STR_RIDE_MODE_START + 36, + + STR_MOVING_TO_END_OF = 1098, + STR_WAITING_FOR_PASSENGERS_AT = 1099, + STR_WAITING_TO_DEPART = 1100, + STR_DEPARTING = 1101, + STR_TRAVELLING_AT_0 = 1102, + STR_ARRIVING_AT = 1103, + STR_UNLOADING_PASSENGERS_AT = 1104, + STR_TRAVELLING_AT_1 = 1105, + STR_CRASHING = 1106, + STR_CRASHED_0 = 1107, + STR_TRAVELLING_AT_2 = 1108, + STR_SWINGING = 1109, + STR_ROTATING_0 = 1110, + STR_ROTATING_1 = 1111, + STR_OPERATING_0 = 1112, + STR_SHOWING_FILM = 1113, + STR_ROTATING_2 = 1114, + STR_OPERATING_1 = 1115, + STR_OPERATING_2 = 1116, + STR_DOING_CIRCUS_SHOW = 1117, + STR_OPERATING_3 = 1118, + STR_WAITING_FOR_CABLE_LIFT = 1119, + STR_TRAVELLING_AT_3 = 1120, + STR_STOPPING_0 = 1121, + STR_WAITING_FOR_PASSENGERS = 1122, + STR_WAITING_TO_START = 1123, + STR_STARTING = 1124, + STR_OPERATING = 1125, + STR_STOPPING_1 = 1126, + STR_UNLOADING_PASSENGERS = 1127, + STR_STOPPED_BY_BLOCK_BRAKES = 1128, + STR_ALL_VEHICLES_IN_SAME_COLOURS = 1129, + STR_DIFFERENT_COLOURS_PER = 1130, + STR_DIFFERENT_COLOURS_PER_VEHICLE = 1131, + + STR_SELECT_MAIN_COLOUR_TIP = 1136, + STR_SELECT_ADDITIONAL_COLOUR_1_TIP = 1137, + STR_SELECT_ADDITIONAL_COLOUR_2_TIP = 1138, + STR_SELECT_SUPPORT_STRUCTURE_COLOUR_TIP = 1139, + STR_SELECT_VEHICLE_COLOUR_SCHEME_TIP = 1140, + STR_SELECT_VEHICLE_TO_MODIFY_TIP = 1141, + + STR_QUARTER_LOAD = 1148, + STR_HALF_LOAD = 1149, + STR_THREE_QUARTER_LOAD = 1150, + STR_FULL_LOAD = 1151, + STR_ANY_LOAD = 1152, STR_PLACE_SCENERY_TIP = 1159, STR_ADJUST_WATER_TIP = 1160, @@ -305,10 +414,24 @@ enum { STR_QUEUE_PEOPLE = 1203, STR_QUEUE_TIME_LABEL = 1204, STR_QUEUE_TIME_PLURAL_LABEL = 1205, + STR_WAIT_FOR = 1206, + + STR_LEAVE_IF_ANOTHER_TRAIN_ARRIVES = 1207, + STR_LEAVE_IF_ANOTHER_BOAT_ARRIVES = 1208, + STR_WAIT_FOR_PASSENGERS_BEFORE_DEPARTING_TIP = 1209, + STR_LEAVE_IF_ANOTHER_VEHICLE_ARRIVES_TIP = 1210, + STR_MINIMUM_WAITING_TIME = 1211, + STR_MAXIMUM_WAITING_TIME = 1212, + STR_MINIMUM_LENGTH_BEFORE_DEPARTING_TIP = 1213, + STR_MAXIMUM_LENGTH_BEFORE_DEPARTING_TIP = 1214, + STR_SYNCHRONISE_WITH_ADJACENT_STATIONS = 1215, + STR_SYNCHRONISE_WITH_ADJACENT_STATIONS_TIP = 1216, STR_NUMERIC_UP = 1218, STR_NUMERIC_DOWN = 1219, - + STR_EXIT_ONLY = 1220, + STR_NO_ENTRANCE = 1221, + STR_NO_EXIT = 1222, STR_TRANSPORT_RIDES_TIP = 1223, STR_GENTLE_RIDES_TIP = 1224, STR_ROLLER_COASTERS_TIP = 1225, @@ -317,13 +440,47 @@ enum { STR_SHOPS_STALLS_TIP = 1228, STR_ROTATE_OBJECTS_90 = 1327, + STR_LAUNCH_SPEED = 1329, + STR_LAUNCH_SPEED_TIP = 1330, + + STR_NO_TEST_RESULTS_YET = 1339, + STR_MAX_SPEED = 1340, + STR_RIDE_TIME = 1341, + STR_RIDE_LENGTH = 1344, + STR_AVERAGE_SPEED = 1347, + STR_MAX_POSITIVE_VERTICAL_G = 1348, + STR_MAX_POSITIVE_VERTICAL_G_RED = 1349, + STR_MAX_NEGATIVE_VERTICAL_G = 1350, + STR_MAX_NEGATIVE_VERTICAL_G_RED = 1351, + STR_MAX_LATERAL_G = 1352, + STR_MAX_LATERAL_G_RED = 1353, + STR_HIGHEST_DROP_HEIGHT = 1354, + STR_DROPS = 1355, + STR_INVERSIONS = 1356, + STR_HOLES = 1357, + STR_TOTAL_AIR_TIME = 1358, + STR_QUEUE_TIME_MINUTE = 1359, + STR_QUEUE_TIME_MINUTES = 1360, + + STR_VIEW_OF_RIDE_ATTRACTION_TIP = 1392, + STR_VEHICLE_DETAILS_AND_OPTIONS_TIP = 1393, + STR_OPERATING_OPTIONS_TIP = 1394, + STR_MAINTENANCE_OPTIONS_TIP = 1395, + STR_COLOUR_SCHEME_OPTIONS_TIP = 1396, + STR_SOUND_AND_MUSIC_OPTIONS_TIP = 1397, + STR_MEASUREMENTS_AND_TEST_DATA_TIP = 1398, + STR_GRAPHS_TIP = 1399, STR_BUILD_THIS = 1407, STR_COST_LABEL = 1408, + STR_LOGGING_DATA_FROM_TIP = 1422, STR_QUEUE_LINE_PATH_TIP = 1423, STR_FOOTPATH_TIP = 1424, + STR_CUSTOMERS_PER_HOUR = 1427, + STR_RIDE_INCOME_ADMISSION_PRICE = 1428, + STR_FREE = 1430, STR_WALKING = 1431, STR_HEADING_FOR = 1432, @@ -347,15 +504,37 @@ enum { STR_GUESTS = 1463, STR_STAFF = 1468, + + STR_SPEED = 1471, + STR_SPEED_TIP = 1472, + STR_EXCITEMENT_RATING = 1473, + STR_EXCITEMENT_RATING_NOT_YET_AVAILABLE = 1474, + STR_INTENSITY_RATING = 1475, + STR_INTENSITY_RATING_NOT_YET_AVAILABLE = 1476, + STR_INTENSITY_RATING_RED = 1477, + STR_NAUSEA_RATING = 1478, + STR_NAUSEA_RATING_NOT_YET_AVAILABLE = 1479, + STR_THOUGHT_START = 1480, STR_CONSTRUCT_FOOTPATH_ON_LAND_TIP = 1655, STR_CONSTRUCT_BRIDGE_OR_TUNNEL_FOOTPATH_TIP = 1656, + STR_SATISFACTION_UNKNOWN = 1668, + STR_SATISFACTION_PERCENT = 1669, + STR_TOTAL_CUSTOMERS = 1670, + STR_TOTAL_PROFIT = 1671, + + STR_POPULARITY_UNKNOWN = 1677, + STR_POPULARITY_PERCENT = 1678, + STR_GUESTS_TIP = 1693, STR_STAFF_TIP = 1694, + STR_INCOME_AND_COSTS_TIP = 1695, + STR_CUSTOMER_INFORMATION_TIP = 1696, + STR_TOO_MANY_PEOPLE_IN_GAME = 1699, STR_HIRE_HANDYMAN = 1700, STR_HIRE_MECHANIC = 1701, @@ -376,12 +555,25 @@ enum { STR_CANT_OPEN_PARK = 1723, STR_CANT_CLOSE_PARK = 1724, + STR_NUMBER_OF_LAPS = 1734, + STR_NUMBER_OF_LAPS_TIP = 1735, + STR_RACE_WON_BY_GUEST = 1739, STR_RACE_WON_BY = 1740, + STR_MAX_PEOPLE_ON_RIDE = 1742, + STR_MAX_PEOPLE_ON_RIDE_TIP = 1743, + + STR_TIME_LIMIT = 1747, + STR_TIME_LIMIT_TIP = 1748, + STR_INDIVIDUAL_GUESTS_TIP = 1752, STR_SUMMARISED_GUESTS_TIP = 1753, STR_ADMISSION_PRICE = 1756, + STR_RELIABILITY_LABEL_1757 = 1757, + + STR_NUMBER_OF_SWINGS = 1769, + STR_NUMBER_OF_SWINGS_TIP = 1770, STR_OFF = 1775, STR_ON = 1776, @@ -394,6 +586,18 @@ enum { STR_FIXING_RIDE = 1794, STR_ANSWERING_RADIO_CALL = 1795, + STR_SAFETY_CUT_OUT = 1800, + STR_RESTRAINTS_STUCK_CLOSED = 1801, + STR_RESTRAINTS_STUCK_OPEN = 1802, + STR_DOORS_STUCK_CLOSED = 1803, + STR_DOORS_STUCK_OPEN = 1804, + STR_VEHICLE_MALFUNCTION = 1805, + STR_BRAKES_FAILURE = 1806, + STR_CONTROL_FAILURE = 1807, + + STR_LAST_BREAKDOWN = 1808, + STR_CURRENT_BREAKDOWN = 1809, + STR_ACTIONS = 1814, STR_THOUGHTS = STR_ACTIONS + 1, STR_INFORMATION_TYPE_TIP = 1816, @@ -404,6 +608,10 @@ enum { STR_GUESTS_FILTER_THINKING = STR_GUESTS_FILTER + 1, STR_GUESTS_FILTER_THINKING_ABOUT = STR_GUESTS_FILTER + 2, + STR_SHOW_GUESTS_THOUGHTS_ABOUT_THIS_RIDE_ATTRACTION_TIP = 1823, + STR_SHOW_GUESTS_ON_THIS_RIDE_ATTRACTION_TIP = 1824, + STR_SHOW_GUESTS_QUEUING_FOR_THIS_RIDE_ATTRACTION_TIP = 1825, + STR_STATUS = 1826, STR_POPULARITY = 1827, STR_SATISFACTION = 1828, @@ -425,6 +633,18 @@ enum { STR_RIDE_LIST_INFORMATION_TYPE_TIP = 1844, STR_NUM_GUESTS = 1846, + STR_PLAY_MUSIC = 1849, + STR_SELECT_MUSIC_TIP = 1850, + STR_RUNNING_COST_PER_HOUR = 1851, + STR_RUNNING_COST_UNKNOWN = 1852, + STR_BUILT_THIS_YEAR = 1853, + STR_BUILT_LAST_YEAR = 1854, + STR_BUILT_YEARS_AGO = 1855, + + STR_PROFIT_PER_ITEM_SOLD = 1856, + STR_LOSS_PER_ITEM_SOLD = 1857, + STR_COST_PER_MONTH = 1858, + STR_HANDYMAN_PLURAL = 1859, STR_MECHANIC_PLURAL = 1860, STR_SECURITY_GUARD_PLURAL = 1861, @@ -435,8 +655,32 @@ enum { STR_ENTERTAINER_SINGULAR = 1866, STR_STAFF_LIST_COUNTER = 1867, + STR_NUMBER_OF_ROTATIONS = 1869, + STR_NUMBER_OF_ROTATIONS_TIP = 1870, + + STR_INCOME_PER_HOUR = 1873, + STR_PROFIT_PER_HOUR = 1874, + + STR_INSPECT_RIDES = 1876, + STR_FIX_RIDES = 1877, + STR_INSPECTION = 1878, + + STR_EVERY_10_MINUTES = 1879, + STR_EVERY_20_MINUTES = 1880, + STR_EVERY_30_MINUTES = 1881, + STR_EVERY_45_MINUTES = 1882, + STR_EVERY_HOUR = 1883, + STR_EVERY_2_HOURS = 1884, + STR_NEVER = 1885, + STR_INSPECTING_RIDE = 1886, + STR_TIME_SINCE_LAST_INSPECTION_MINUTES = 1887, + STR_TIME_SINCE_LAST_INSPECTION_MORE_THAN_4_HOURS = 1888, + STR_DOWN_TIME_LABEL_1889 = 1889, + STR_SELECT_HOW_OFTEN_A_MECHANIC_SHOULD_CHECK_THIS_RIDE = 1890, + + STR_ITEMS_SOLD = 1894, STR_BUILD_RIDE_TIP = 1895, STR_FINANCES_SUMMARY_EXPENDITURE_INCOME = 1896, STR_FINANCES_SUMMARY_RIDE_CONSTRUCTION = 1897, @@ -481,6 +725,16 @@ enum { STR_MARKETING = 1953, STR_RESEARCH_FUNDING = 1954, + STR_NUMBER_OF_CIRCUITS = 1955, + STR_NUMBER_OF_CIRCUITS_TIP = 1956, + + STR_ON_RIDE_PHOTO_PRICE = 1963, + + STR_MAIN_COLOUR_SCHEME = 2971, + STR_ALTERNATIVE_COLOUR_SCHEME_1 = 2972, + STR_ALTERNATIVE_COLOUR_SCHEME_2 = 2973, + STR_ALTERNATIVE_COLOUR_SCHEME_3 = 2974, + STR_ITEM_START = 1988, STR_ITEM_SINGULAR_START = 2044, STR_ITEM2_START = 2090, @@ -609,12 +863,12 @@ enum { STR_LOW = 2369, STR_AVERAGE = 2370, STR_HIGH = 2371, - //STR_LOW = 2372, - STR_MEDIUM = 2373, - //STR_HIGH = 2374, - STR_VERY_HIGH = 2375, - STR_EXTREME = 2376, - STR_ULTRA_EXTREME = 2377, + STR_RATING_LOW = 2372, + STR_RATING_MEDIUM = 2373, + STR_RATING_HIGH = 2374, + STR_RATING_VERY_HIGH = 2375, + STR_RATING_EXTREME = 2376, + STR_RATING_ULTRA_EXTREME = 2377, STR_ADJUST_SMALLER_LAND_TIP = 2378, STR_ADJUST_LARGER_LAND_TIP = 2379, @@ -709,6 +963,13 @@ enum { STR_RESEARCH_NEW_SHOPS_AND_STALLS = 2475, STR_RESEARCH_NEW_SCENERY_AND_THEMING = 2476, + STR_SELECT_OPERATING_MODE = 2477, + + STR_SHOW_GRAPH_OF_VELOCITY_AGAINST_TIME_TIP = 2478, + STR_SHOW_GRAPH_OF_ALTITUDE_AGAINST_TIME_TIP = 2479, + STR_SHOW_GRAPH_OF_VERTICAL_ACCELERATION_AGAINST_TIME_TIP = 2480, + STR_SHOW_GRAPH_OF_LATERAL_ACCELERATION_AGAINST_TIME_TIP = 2481, + STR_PROFIT_PER_WEEK_AND_PARK_VALUE_TIP = 2482, STR_FINANCES_WEEKLY_PROFIT_POSITIVE = 2483, STR_FINANCES_WEEKLY_PROFIT_LOSS = 2484, @@ -808,19 +1069,83 @@ enum { STR_LICENCE_AGREEMENT_NOTICE_1 = 2969, STR_LICENCE_AGREEMENT_NOTICE_2 = 2970, + STR_COLOUR_SCHEME_TO_CHANGE_TIP = 2975, + STR_PAINT_INDIVIDUAL_AREA_TIP = 2976, + STR_UNABLE_TO_LOAD_FILE = 3010, STR_FILE_CONTAINS_INVALID_DATA = 3011, + STR_MUSIC_STYLE_START = 3012, + STR_DODGEMS_BEAT_STYLE = STR_MUSIC_STYLE_START + 0, + STR_FAIRGROUND_ORGAN_STYLE = STR_MUSIC_STYLE_START + 1, + STR_ROMAN_FANFARE_STYLE = STR_MUSIC_STYLE_START + 2, + STR_ORIENTAL_STYLE = STR_MUSIC_STYLE_START + 3, + STR_MARTIAN_STYLE = STR_MUSIC_STYLE_START + 4, + STR_JUNGLE_DRUMS_STYLE = STR_MUSIC_STYLE_START + 5, + STR_EGYPTIAN_STYLE = STR_MUSIC_STYLE_START + 6, + STR_TOYLAND_STYLE = STR_MUSIC_STYLE_START + 7, + // STR_??? = STR_MUSIC_STYLE_START + 8, + STR_SPACE_STYLE = STR_MUSIC_STYLE_START + 9, + STR_HORROR_STYLE = STR_MUSIC_STYLE_START + 10, + STR_TECHNO_STYLE = STR_MUSIC_STYLE_START + 11, + STR_GENTLE_STYLE = STR_MUSIC_STYLE_START + 12, + STR_SUMMER_STYLE = STR_MUSIC_STYLE_START + 13, + STR_WATER_STYLE = STR_MUSIC_STYLE_START + 14, + STR_WILD_WEST_STYLE = STR_MUSIC_STYLE_START + 15, + STR_JURASSIC_STYLE = STR_MUSIC_STYLE_START + 16, + STR_ROCK_STYLE = STR_MUSIC_STYLE_START + 17, + STR_RAGTIME_STYLE = STR_MUSIC_STYLE_START + 18, + STR_FANTASY_STYLE = STR_MUSIC_STYLE_START + 19, + STR_ROCK_STYLE_2 = STR_MUSIC_STYLE_START + 20, + STR_ICE_STYLE = STR_MUSIC_STYLE_START + 21, + STR_SNOW_STYLE = STR_MUSIC_STYLE_START + 22, + STR_CUSTOM_MUSIC_1 = STR_MUSIC_STYLE_START + 23, + STR_CUSTOM_MUSIC_2 = STR_MUSIC_STYLE_START + 24, + STR_MEDIEVAL_STYLE = STR_MUSIC_STYLE_START + 25, + STR_URBAN_STYLE = STR_MUSIC_STYLE_START + 26, + STR_ORGAN_STYLE = STR_MUSIC_STYLE_START + 27, + STR_MECHANICAL_STYLE = STR_MUSIC_STYLE_START + 28, + STR_MODERN_STYLE = STR_MUSIC_STYLE_START + 29, + STR_PIRATES_STYLE = STR_MUSIC_STYLE_START + 30, + STR_ROCK_STYLE_3 = STR_MUSIC_STYLE_START + 31, + STR_CANDY_STYLE = STR_MUSIC_STYLE_START + 32, + + STR_SELECT_MUSIC_STYLE_TIP = 3045, + STR_WHITE = 3055, STR_TRANSLUCENT = 3056, STR_CONSTRUCTION_MARKER = 3057, + STR_BRICK_WALLS = 3058, + STR_HEDGES = 3059, + STR_ICE_BLOCKS = 3060, + STR_WOODEN_FENCES = 3061, + STR_BEGINNER_PARKS = 3064, STR_CHALLENGING_PARKS = STR_BEGINNER_PARKS + 1, STR_EXPERT_PARKS = STR_BEGINNER_PARKS + 2, STR_REAL_PARKS = STR_BEGINNER_PARKS + 3, STR_OTHER_PARKS = STR_BEGINNER_PARKS + 4, + STR_SAME_PRICE_THROUGHOUT_PARK = 3071, + STR_SAME_PRICE_THROUGHOUT_PARK_TIP = 3072, + + STR_PLAIN_ENTRANCE = 3078, + STR_WOODEN_ENTRANCE = 3079, + STR_CANVAS_TENT_ENTRANCE = 3080, + STR_CASTLE_ENTRANCE_GREY = 3081, + STR_CASTLE_ENTRANCE_BROWN = 3082, + STR_JUNGLE_ENTRANCE = 3083, + STR_LOG_CABIN_ENTRANCE = 3084, + STR_CLASSICAL_ROMAN_ENTRANCE = 3085, + STR_ABSTRACT_ENTRANCE = 3086, + STR_SNOW_ICE_ENTRANCE = 3087, + STR_PAGODA_ENTRANCE = 3088, + STR_SPACE_ENTRANCE = 3089, + + STR_SELECT_STYLE_OF_ENTRANCE_EXIT_STATION_TIP = 3090, + STR_SELECT_LIFT_HILL_CHAIN_SPEED_TIP = 3097, + STR_SELECT_COLOUR = 3099, STR_SELECT_SECONDARY_COLOUR = 3100, STR_SELECT_TERNARY_COLOUR = 3101, @@ -828,6 +1153,30 @@ enum { STR_LIST_RIDES_TIP = 3104, STR_LIST_SHOPS_AND_STALLS_TIP = 3105, STR_LIST_KIOSKS_AND_FACILITIES_TIP = 3106, + STR_CLOSE_RIDE = 3107, + STR_TEST_RIDE = 3108, + STR_OPEN_RIDE = 3109, + STR_BLOCK_SECTIONS = 3110, + + STR_SAVE_TRACK_DESIGN = 3115, + STR_SAVE_TRACK_DESIGN_NOT_POSSIBLE = 3116, + + STR_CALLING_MECHANIC = 3117, + STR_MEHCANIC_IS_HEADING_FOR_THE_RIDE = 3118, + STR_MEHCANIC_IS_FIXING_THE_RIDE = 3119, + STR_LOCATE_NEAREST_AVAILABLE_MECHANIC_TIP = 3120, + + STR_FAVOURITE_RIDE_OF_GUEST = 3122, + STR_FAVOURITE_RIDE_OF_GUESTS = 3123, + + STR_SAVE_TRACK_DESIGN_ITEM = 3128, + STR_SAVE_TRACK_DESIGN_WITH_SCENERY_ITEM = 3129, + STR_DESIGN_SAVE = 3130, + STR_DESIGN_CANCEL = 3131, + STR_CLICK_ITEMS_OF_SCENERY_TO_SELECT = 3132, + + STR_SELECT_NEARBY_SCENERY = 3137, + STR_RESET_SELECTION = 3138, STR_SCROLL_LEFT_TIP = 3145, STR_SCROLL_RIGHT_TIP = STR_SCROLL_LEFT_TIP + 1, diff --git a/src/vehicle.c b/src/vehicle.c index 6cd47e648a..5c802c1c93 100644 --- a/src/vehicle.c +++ b/src/vehicle.c @@ -89,7 +89,7 @@ void sub_6BB9FF(rct_vehicle* vehicle) v18 = 64; } i->var_4 = (sint16)(((v15.both / v18) - 0x8000) >> 4); - sint32 v19 = vehicle->var_28; + sint32 v19 = vehicle->velocity; int testaddr = (vehicle->var_31 * 0x65); testaddr += (int)RCT2_ADDRESS(0x009ACFA4, rct_ride_type*)[vehicle->var_D6]; @@ -138,7 +138,7 @@ int sub_6BC2F3(rct_vehicle* vehicle) do { result += vehicle_temp->var_46; } while (vehicle_temp->next_vehicle_on_train != (uint16)-1 && (vehicle_temp = GET_VEHICLE(vehicle_temp->next_vehicle_on_train))); - sint32 v4 = vehicle->var_28; + sint32 v4 = vehicle->velocity; if (v4 < 0) { v4 = -v4; } diff --git a/src/vehicle.h b/src/vehicle.h index fd290675a9..668f16a350 100644 --- a/src/vehicle.h +++ b/src/vehicle.h @@ -48,20 +48,23 @@ typedef struct { rct_widthheight view; // 0x1A uint16 var_1E; uint8 pad_20[0x08]; - sint32 var_28; + sint32 velocity; // 0x28 uint8 pad_2C[0x04]; uint8 ride; // 0x30 uint8 var_31; uint8 pad_32[0x02]; uint16 var_34; - uint8 pad_36[0x08]; + sint16 var_36; + uint8 pad_38[0x06]; uint16 next_vehicle_on_train; // 0x3E uint32 var_40; uint16 var_44; uint16 var_46; uint16 var_48; - uint8 pad_4A[0x06]; - uint8 var_50; + uint8 pad_4A; + uint8 var_4B; + uint8 pad_4C[0x4]; + uint8 status; uint8 var_51; uint16 peep; // 0x52 uint8 pad_54[0x2C]; @@ -84,6 +87,40 @@ typedef struct { uint8 var_D6; } rct_vehicle; +enum { + VEHICLE_STATUS_MOVING_TO_END_OF_STATION, + VEHICLE_STATUS_WAITING_FOR_PASSENGERS, + VEHICLE_STATUS_WAITING_TO_DEPART, + VEHICLE_STATUS_DEPARTING, + VEHICLE_STATUS_TRAVELLING, + VEHICLE_STATUS_ARRIVING, + VEHICLE_STATUS_UNLOADING_PASSENGERS, + VEHICLE_STATUS_TRAVELLING_07, + VEHICLE_STATUS_CRASHING, + VEHICLE_STATUS_CRASHED, + VEHICLE_STATUS_TRAVELLING_0A, + VEHICLE_STATUS_SWINGING, + VEHICLE_STATUS_ROTATING, + VEHICLE_STATUS_ROTATING_0D, + VEHICLE_STATUS_OPERATING, + VEHICLE_STATUS_SHOWING_FILM, + VEHICLE_STATUS_ROTATING_10, + VEHICLE_STATUS_OPERATING_11, + VEHICLE_STATUS_OPERATING_12, + VEHICLE_STATUS_DOING_CIRCUS_SHOW, + VEHICLE_STATUS_OPERATING_13, + VEHICLE_STATUS_WAITING_FOR_CABLE_LIFT, + VEHICLE_STATUS_TRAVELLING_15, + VEHICLE_STATUS_STOPPING, + VEHICLE_STATUS_WAITING_FOR_PASSENGERS_17, + VEHICLE_STATUS_WAITING_TO_START, + VEHICLE_STATUS_STARTING, + VEHICLE_STATUS_OPERATING_1A, + VEHICLE_STATUS_STOPPING_1B, + VEHICLE_STATUS_UNLOADING_PASSENGERS_1C, + VEHICLE_STATUS_STOPPED_BY_BLOCK_BRAKES +}; + void vehicle_update_all(); int sub_6BC2F3(rct_vehicle* vehicle); void sub_6BB9FF(rct_vehicle* vehicle); diff --git a/src/window.c b/src/window.c index 27961ed470..7f12a29de5 100644 --- a/src/window.c +++ b/src/window.c @@ -1576,13 +1576,13 @@ void RCT2_CALLPROC_WE_MOUSE_DOWN(int address, int widgetIndex, rct_window*w, rc } /* Based on rct2: 0x6987ED and another version from window_park */ -void window_align_tabs( rct_window *w, uint8 start_tab_id, uint8 end_tab_id ) +void window_align_tabs(rct_window *w, uint8 start_tab_id, uint8 end_tab_id) { - int x = w->widgets[start_tab_id].left; + int i, x = w->widgets[start_tab_id].left; int tab_width = w->widgets[start_tab_id].right - w->widgets[start_tab_id].left; - for (int i = start_tab_id; i < end_tab_id; ++i){ - if ( !(w->disabled_widgets & (1LL << i)) ){ + for (i = start_tab_id; i <= end_tab_id; i++) { + if (!(w->disabled_widgets & (1LL << i))) { w->widgets[i].left = x; w->widgets[i].right = x + tab_width; x += tab_width + 1; diff --git a/src/window.h b/src/window.h index 4acc523d48..8b9ac54cd9 100644 --- a/src/window.h +++ b/src/window.h @@ -158,8 +158,9 @@ typedef struct{ } map_variables; typedef struct { - sint16 var_480; + sint16 view; sint32 var_482; + sint32 var_486; } ride_variables; typedef struct { @@ -343,6 +344,7 @@ enum { WC_SAVE_PROMPT = 14, WC_RIDE_LIST = 15, WC_CONSTRUCT_RIDE = 16, + WC_DEMOLISH_RIDE_PROMPT = 17, WC_SCENERY = 18, WC_OPTIONS = 19, WC_FOOTPATH = 20, @@ -514,6 +516,12 @@ void RCT2_CALLPROC_WE_MOUSE_DOWN(int address, int widgetIndex, rct_window*w, rct __asm mov widgetIndex, dx \ __asm mov w, esi + #define window_textinput_get_registers(w, widgetIndex, result, text) \ + __asm mov result, cl \ + __asm mov widgetIndex, dx \ + __asm mov w, esi \ + __asm mov text, edi + #define window_paint_get_registers(w, dpi) \ __asm mov w, esi \ __asm mov dpi, edi @@ -547,6 +555,12 @@ void RCT2_CALLPROC_WE_MOUSE_DOWN(int address, int widgetIndex, rct_window*w, rct __asm__ ( "mov %["#widgetIndex"], dx " : [widgetIndex] "+m" (widgetIndex) ); \ __asm__ ( "mov %["#w"], esi " : [w] "+m" (w) ); + #define window_textinput_get_registers(w, widgetIndex, result, text) \ + __asm__ ( "mov %[result], cl " : [result] "+m" (result) ); \ + __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); \ + __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); \ + __asm__ ( "mov %[text], edi " : [text] "+m" (text) ); + #define window_paint_get_registers(w, dpi) \ __asm__ ( "mov %["#w"], esi " : [w] "+m" (w) ); \ __asm__ ( "mov %["#dpi"], edi " : [dpi] "+m" (dpi) ); diff --git a/src/window_dropdown.c b/src/window_dropdown.c index eba3061ed0..1c5b32dcf0 100644 --- a/src/window_dropdown.c +++ b/src/window_dropdown.c @@ -44,13 +44,13 @@ static rct_widget window_dropdown_widgets[] = { { WIDGETS_END }, }; -int _dropdown_num_items; int _dropdown_num_columns; int _dropdown_num_rows; int _dropdown_item_width; int _dropdown_item_height; int _dropdown_highlighted_index; +int gDropdownNumItems; uint16 gDropdownItemsFormat[64]; sint64 gDropdownItemsArgs[64]; // Replaces 0x009DED38 @@ -149,7 +149,7 @@ void window_dropdown_show_text_custom_width(int x, int y, int extray, uint8 colo _dropdown_item_height = flags & 0x3F; // Set the widgets - _dropdown_num_items = num_items; + gDropdownNumItems = num_items; _dropdown_num_rows = num_items; window_dropdown_widgets[WIDX_BACKGROUND].bottom = _dropdown_item_height * num_items + 3; window_dropdown_widgets[WIDX_BACKGROUND].right = _dropdown_item_width + 3; @@ -175,7 +175,7 @@ void window_dropdown_show_text_custom_width(int x, int y, int extray, uint8 colo RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, sint8) = INPUT_STATE_DROPDOWN_ACTIVE; // Copy the following properties until all use of it is decompiled - RCT2_GLOBAL(0x009DEBA0, sint16) = _dropdown_num_items; + RCT2_GLOBAL(0x009DEBA0, sint16) = gDropdownNumItems; RCT2_GLOBAL(0x009DED44, sint32) = _dropdown_num_columns; RCT2_GLOBAL(0x009DED48, sint32) = _dropdown_num_rows; RCT2_GLOBAL(0x009DED40, sint32) = _dropdown_item_width; @@ -216,10 +216,10 @@ void window_dropdown_show_image(int x, int y, int extray, uint8 colour, uint8 fl // Set and calculate num items, rows and columns _dropdown_item_width = itemWidth; _dropdown_item_height = itemHeight; - _dropdown_num_items = numItems; + gDropdownNumItems = numItems; _dropdown_num_columns = numColumns; - _dropdown_num_rows = _dropdown_num_items / _dropdown_num_columns; - if (_dropdown_num_items % _dropdown_num_columns != 0) + _dropdown_num_rows = gDropdownNumItems / _dropdown_num_columns; + if (gDropdownNumItems % _dropdown_num_columns != 0) _dropdown_num_rows++; // Calculate position and size @@ -253,7 +253,7 @@ void window_dropdown_show_image(int x, int y, int extray, uint8 colour, uint8 fl RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, sint8) = INPUT_STATE_DROPDOWN_ACTIVE; // Copy the following properties until all use of it is decompiled - RCT2_GLOBAL(0x009DEBA0, sint16) = _dropdown_num_items; + RCT2_GLOBAL(0x009DEBA0, sint16) = gDropdownNumItems; RCT2_GLOBAL(0x009DED44, sint32) = _dropdown_num_columns; RCT2_GLOBAL(0x009DED48, sint32) = _dropdown_num_rows; RCT2_GLOBAL(0x009DED40, sint32) = _dropdown_item_width; @@ -278,7 +278,7 @@ static void window_dropdown_paint() _dropdown_highlighted_index = RCT2_GLOBAL(0x009DEBA2, sint16); { int i, cell_x, cell_y, l, t, r, b, item, image, colour; - for (i = 0; i < _dropdown_num_items; i++) { + for (i = 0; i < gDropdownNumItems; i++) { cell_x = i % _dropdown_num_columns; cell_y = i / _dropdown_num_columns; @@ -379,3 +379,16 @@ int dropdown_index_from_point(int x, int y, rct_window* w){ return dropdown_index; } + +/** + * rct2: 0x006ED43D + * al: dropdown colour + * ah: selected colour + * esi: window + * edi: widget + * ebp: unknown + */ +void window_dropdown_show_colour(rct_window *w, rct_widget *widget, uint8 dropdownColour, uint8 selectedColour) +{ + RCT2_CALLPROC_X(0x006ED43D, (selectedColour << 8) | dropdownColour, 0, 0, 0, (int)w, (int)widget, 0xFFFFFFFF); +} diff --git a/src/window_dropdown.h b/src/window_dropdown.h index 9a63f80bb4..584c3c0664 100644 --- a/src/window_dropdown.h +++ b/src/window_dropdown.h @@ -27,6 +27,7 @@ extern int gAppropriateImageDropdownItemsPerRow[]; +extern int gDropdownNumItems; extern uint16 gDropdownItemsFormat[64]; extern sint64 gDropdownItemsArgs[64]; extern uint32 gDropdownItemsChecked; @@ -36,5 +37,6 @@ void window_dropdown_show_text_custom_width(int x, int y, int extray, uint8 colo void window_dropdown_show_image(int x, int y, int extray, uint8 colour, uint8 flags, int numItems, int itemWidth, int itemHeight, int numColumns); void window_dropdown_close(); int dropdown_index_from_point(int x, int y, rct_window* w); +void window_dropdown_show_colour(rct_window *w, rct_widget *widget, uint8 dropdownColour, uint8 selectedColour); #endif \ No newline at end of file diff --git a/src/window_new_ride.c b/src/window_new_ride.c index 2cadf1970f..6985a4878f 100644 --- a/src/window_new_ride.c +++ b/src/window_new_ride.c @@ -279,19 +279,6 @@ void window_new_ride_init_vars() { RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_RIDE_LIST_INFORMATION_TYPE, uint8) = 0; } -uint8 *get_ride_entry_indices_for_ride_type(uint8 rideType) -{ - uint8 *typeToRideEntryIndexMap = (uint8*)0x009E32F8; - uint8 *entryIndexList = typeToRideEntryIndexMap; - while (rideType > 0) { - do { - entryIndexList++; - } while (*(entryIndexList - 1) != 255); - rideType--; - } - return entryIndexList; -} - /** * * rct2: 0x006B6F3E diff --git a/src/window_park.c b/src/window_park.c index f32ecc823c..62abaec285 100644 --- a/src/window_park.c +++ b/src/window_park.c @@ -866,30 +866,7 @@ static void window_park_entrance_textinput() rct_window *w; char *text; - #ifdef _MSC_VER - __asm mov result, cl - #else - __asm__ ( "mov %[result], cl " : [result] "+m" (result) ); - #endif - - #ifdef _MSC_VER - __asm mov widgetIndex, dx - #else - __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); - #endif - - #ifdef _MSC_VER - __asm mov w, esi - #else - __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); - #endif - - #ifdef _MSC_VER - __asm mov text, edi - #else - __asm__ ( "mov %[text], edi " : [text] "+m" (text) ); - #endif - + window_textinput_get_registers(w, widgetIndex, result, text); if (widgetIndex == WIDX_RENAME) { if (result) { diff --git a/src/window_peep.c b/src/window_peep.c index e061b4ccf4..2238f77de6 100644 --- a/src/window_peep.c +++ b/src/window_peep.c @@ -717,7 +717,7 @@ void window_peep_viewport_init(rct_window* w){ rct_ride* ride = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[peep->current_ride]); if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK){ - rct_vehicle* train = GET_VEHICLE(ride->train_car_map[peep->current_train]); + rct_vehicle* train = GET_VEHICLE(ride->vehicles[peep->current_train]); int car = peep->current_car; for (; car != 0; car--){ @@ -1379,6 +1379,33 @@ void window_peep_stats_invalidate(){ window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_6); } +/** +* +* rct2: 0x0066ECC1 +* +* ebp: colour, contains flag 0x80000000 for blinking +*/ +void window_peep_stats_bars_paint(int value, int x, int y, rct_window *w, rct_drawpixelinfo *dpi, int colour){ + //RCT2_CALLPROC_X(0x6974FC, value, 0, x, y, (int)w, (int)dpi, colour); + + value *= 0x76; + value >>= 8; + + gfx_fill_rect_inset(dpi, x + 0x3A, y + 1, x + 0x3A + 0x79, y + 9, w->colours[1], 0x30); + + int blink_flag = colour & (1 << 0x1F); //0x80000000 + colour &= ~(1 << 0x1F); + if (!blink_flag || + RCT2_GLOBAL(0x009DEA6E, uint8) != 0 || + (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 8) == 0) + { + if (value <= 2) + return; + gfx_fill_rect_inset(dpi, x + 0x3C, y + 2, x + 0x3C + value - 1, y + 8, colour, 0); + } + +} + /* rct2: 0x0069711D */ void window_peep_stats_paint(){ rct_window *w; @@ -1412,7 +1439,7 @@ void window_peep_stats_paint(){ if (happiness < 50){ ebp |= 0x80000000; } - RCT2_CALLPROC_X(0x6974FC, happiness, (int)peep, x, y, (int)w, (int)dpi, ebp); + window_peep_stats_bars_paint(happiness, x, y, w, dpi, ebp); //Energy y += 10; @@ -1424,7 +1451,7 @@ void window_peep_stats_paint(){ ebp |= 0x80000000; } if (energy < 10)energy = 10; - RCT2_CALLPROC_X(0x6974FC, energy, (int)peep, x, y, (int)w, (int)dpi, ebp); + window_peep_stats_bars_paint(energy, x, y, w, dpi, ebp); //Hunger y += 10; @@ -1443,7 +1470,7 @@ void window_peep_stats_paint(){ if (hunger > 170){ ebp |= 0x80000000; } - RCT2_CALLPROC_X(0x6974FC, hunger, (int)peep, x, y, (int)w, (int)dpi, ebp); + window_peep_stats_bars_paint(hunger, x, y, w, dpi, ebp); //Thirst y += 10; @@ -1462,7 +1489,7 @@ void window_peep_stats_paint(){ if (thirst > 170){ ebp |= 0x80000000; } - RCT2_CALLPROC_X(0x6974FC, thirst, (int)peep, x, y, (int)w, (int)dpi, ebp); + window_peep_stats_bars_paint(thirst, x, y, w, dpi, ebp); //Nausea y += 10; @@ -1478,7 +1505,7 @@ void window_peep_stats_paint(){ if (nausea > 120){ ebp |= 0x80000000; } - RCT2_CALLPROC_X(0x6974FC, nausea, (int)peep, x, y, (int)w, (int)dpi, ebp); + window_peep_stats_bars_paint(nausea, x, y, w, dpi, ebp); //Bathroom y += 10; @@ -1496,7 +1523,7 @@ void window_peep_stats_paint(){ if (bathroom > 160){ ebp |= 0x80000000; } - RCT2_CALLPROC_X(0x6974FC, bathroom, (int)peep, x, y, (int)w, (int)dpi, ebp); + window_peep_stats_bars_paint(bathroom, x, y, w, dpi, ebp); // Time in park y += 11; @@ -2178,4 +2205,4 @@ void window_peep_inventory_paint(){ if (!no_items){ gfx_draw_string_left(dpi, 2293, (void*)0, 0, x, y); } -} \ No newline at end of file +} diff --git a/src/window_ride.c b/src/window_ride.c index 66b9e2a23b..a96f0241da 100644 --- a/src/window_ride.c +++ b/src/window_ride.c @@ -21,48 +21,1074 @@ #include #include "addresses.h" #include "game.h" +#include "map.h" #include "ride.h" +#include "ride_data.h" +#include "staff.h" #include "string_ids.h" #include "sprite.h" #include "sprites.h" +#include "viewport.h" #include "widget.h" #include "window.h" #include "window_dropdown.h" +#define var_496(w) RCT2_GLOBAL((int)w + 0x496, uint16) + +enum WINDOW_PARK_PAGE { + WINDOW_PARK_PAGE_MAIN, + WINDOW_PARK_PAGE_VEHICLE, + WINDOW_PARK_PAGE_OPERATING, + WINDOW_PARK_PAGE_MAINTENANCE, + WINDOW_PARK_PAGE_COLOUR, + WINDOW_PARK_PAGE_MUSIC, + WINDOW_PARK_PAGE_MEASUREMENTS, + WINDOW_PARK_PAGE_GRAPHS, + WINDOW_PARK_PAGE_INCOME, + WINDOW_PARK_PAGE_CUSTOMER, + WINDOW_PARK_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_VEHICLE_TYPE = 14, + WIDX_VEHICLE_TYPE_DROPDOWN, + WIDX_VEHICLE_TRAINS_PREVIEW, + WIDX_VEHICLE_TRAINS, + WIDX_VEHICLE_TRAINS_DROPDOWN, + WIDX_VEHICLE_CARS_PER_TRAIN, + WIDX_VEHICLE_CARS_PER_TRAIN_DROPDOWN, + + 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_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 +}; + +// 0x009ADC34 +static rct_widget window_ride_main_widgets[] = { + { WWT_FRAME, 0, 0, 315, 0, 206, 0x0FFFFFFFF, STR_NONE }, + { WWT_CAPTION, 0, 1, 314, 1, 14, 0x3DD, 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, 0x0FFFFFFFF, STR_NONE }, + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_VIEW_OF_RIDE_ATTRACTION_TIP }, + { WWT_TAB, 1, 34, 64, 17, 46, 0x2000144E, STR_VEHICLE_DETAILS_AND_OPTIONS_TIP }, + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_OPERATING_OPTIONS_TIP }, + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_MAINTENANCE_OPTIONS_TIP }, + { WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_COLOUR_SCHEME_OPTIONS_TIP }, + { WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_SOUND_AND_MUSIC_OPTIONS_TIP }, + { WWT_TAB, 1, 189, 219, 17, 43, 0x2000144E, STR_MEASUREMENTS_AND_TEST_DATA_TIP }, + { WWT_TAB, 1, 220, 250, 17, 43, 0x2000144E, STR_GRAPHS_TIP }, + { WWT_TAB, 1, 251, 281, 17, 43, 0x2000144E, STR_INCOME_AND_COSTS_TIP }, + { WWT_TAB, 1, 282, 312, 17, 43, 0x2000144E, STR_CUSTOMER_INFORMATION_TIP }, + + { WWT_VIEWPORT, 1, 3, 290, 60, 166, 0x0FFFFFFFE, STR_NONE }, + { WWT_DROPDOWN, 1, 35, 256, 46, 57, 0x0FFFFFFFF, STR_VIEW_SELECTION }, + { WWT_DROPDOWN_BUTTON, 1, 245, 255, 47, 56, 876, STR_VIEW_SELECTION }, + { WWT_12, 1, 3, 290, 167, 177, 0x0FFFFFFFF, STR_NONE }, + { WWT_FLATBTN, 1, 291, 314, 46, 69, 0x0FFFFFFFF, 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 }, + { WIDGETS_END }, +}; + +// 0x009ADDA8 +static rct_widget window_ride_vehicle_widgets[] = { + { WWT_FRAME, 0, 0, 315, 0, 206, 0x0FFFFFFFF, STR_NONE }, + { WWT_CAPTION, 0, 1, 314, 1, 14, 0x3DD, 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, 0x0FFFFFFFF, STR_NONE }, + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_VIEW_OF_RIDE_ATTRACTION_TIP }, + { WWT_TAB, 1, 34, 64, 17, 46, 0x2000144E, STR_VEHICLE_DETAILS_AND_OPTIONS_TIP }, + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_OPERATING_OPTIONS_TIP }, + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_MAINTENANCE_OPTIONS_TIP }, + { WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_COLOUR_SCHEME_OPTIONS_TIP }, + { WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_SOUND_AND_MUSIC_OPTIONS_TIP }, + { WWT_TAB, 1, 189, 219, 17, 43, 0x2000144E, STR_MEASUREMENTS_AND_TEST_DATA_TIP }, + { WWT_TAB, 1, 220, 250, 17, 43, 0x2000144E, STR_GRAPHS_TIP }, + { WWT_TAB, 1, 251, 281, 17, 43, 0x2000144E, STR_INCOME_AND_COSTS_TIP }, + { WWT_TAB, 1, 282, 312, 17, 43, 0x2000144E, STR_CUSTOMER_INFORMATION_TIP }, + + { WWT_DROPDOWN, 1, 7, 308, 50, 61, 0xFFFFFFFF, STR_NONE }, + { WWT_DROPDOWN_BUTTON, 1, 297, 307, 51, 60, 876, STR_NONE }, + { WWT_SCROLL, 1, 7, 308, 141, 183, 0, STR_NONE }, + { WWT_DROPDOWN, 1, 7, 151, 190, 201, 1021, STR_NONE }, + { WWT_DROPDOWN_BUTTON, 1, 140, 150, 191, 200, 876, STR_NONE }, + { WWT_DROPDOWN, 1, 164, 308, 190, 201, 1022, STR_NONE }, + { WWT_DROPDOWN_BUTTON, 1, 297, 307, 191, 200, 876, STR_NONE }, + { WIDGETS_END }, +}; + +// 0x009ADEFC +static rct_widget window_ride_operating_widgets[] = { + { WWT_FRAME, 0, 0, 315, 0, 206, 0x0FFFFFFFF, STR_NONE }, + { WWT_CAPTION, 0, 1, 314, 1, 14, 0x3DD, 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, 0x0FFFFFFFF, STR_NONE }, + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_VIEW_OF_RIDE_ATTRACTION_TIP }, + { WWT_TAB, 1, 34, 64, 17, 46, 0x2000144E, STR_VEHICLE_DETAILS_AND_OPTIONS_TIP }, + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_OPERATING_OPTIONS_TIP }, + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_MAINTENANCE_OPTIONS_TIP }, + { WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_COLOUR_SCHEME_OPTIONS_TIP }, + { WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_SOUND_AND_MUSIC_OPTIONS_TIP }, + { WWT_TAB, 1, 189, 219, 17, 43, 0x2000144E, STR_MEASUREMENTS_AND_TEST_DATA_TIP }, + { WWT_TAB, 1, 220, 250, 17, 43, 0x2000144E, STR_GRAPHS_TIP }, + { WWT_TAB, 1, 251, 281, 17, 43, 0x2000144E, STR_INCOME_AND_COSTS_TIP }, + { WWT_TAB, 1, 282, 312, 17, 43, 0x2000144E, STR_CUSTOMER_INFORMATION_TIP }, + + { WWT_SPINNER, 1, 157, 308, 61, 72, 874, 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, 3096, 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, 870, 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, 872, 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, 3095, STR_NONE }, + { WWT_DROPDOWN, 1, 7, 308, 47, 58, 0xFFFFFFFF, STR_SELECT_OPERATING_MODE }, + { WWT_DROPDOWN_BUTTON, 1, 297, 307, 48, 57, 876, STR_SELECT_OPERATING_MODE }, + { WWT_DROPDOWN, 1, 87, 308, 109, 120, 0xFFFFFFFF, STR_NONE }, + { WWT_DROPDOWN_BUTTON, 1, 297, 307, 110, 119, 876, 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, 1957, STR_NONE }, + { WWT_DROPDOWN_BUTTON, 1, 297, 307, 90, 94, STR_NUMERIC_UP, STR_SELECT_LIFT_HILL_CHAIN_SPEED_TIP }, + { WWT_DROPDOWN_BUTTON, 1, 297, 307, 95, 99, STR_NUMERIC_DOWN, STR_SELECT_LIFT_HILL_CHAIN_SPEED_TIP }, + { WIDGETS_END }, +}; + +// 0x009AE190 +static rct_widget window_ride_maintenance_widgets[] = { + { WWT_FRAME, 0, 0, 315, 0, 206, 0x0FFFFFFFF, STR_NONE }, + { WWT_CAPTION, 0, 1, 314, 1, 14, 0x3DD, 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, 0x0FFFFFFFF, STR_NONE }, + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_VIEW_OF_RIDE_ATTRACTION_TIP }, + { WWT_TAB, 1, 34, 64, 17, 46, 0x2000144E, STR_VEHICLE_DETAILS_AND_OPTIONS_TIP }, + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_OPERATING_OPTIONS_TIP }, + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_MAINTENANCE_OPTIONS_TIP }, + { WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_COLOUR_SCHEME_OPTIONS_TIP }, + { WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_SOUND_AND_MUSIC_OPTIONS_TIP }, + { WWT_TAB, 1, 189, 219, 17, 43, 0x2000144E, STR_MEASUREMENTS_AND_TEST_DATA_TIP }, + { WWT_TAB, 1, 220, 250, 17, 43, 0x2000144E, STR_GRAPHS_TIP }, + { WWT_TAB, 1, 251, 281, 17, 43, 0x2000144E, STR_INCOME_AND_COSTS_TIP }, + { WWT_TAB, 1, 282, 312, 17, 43, 0x2000144E, STR_CUSTOMER_INFORMATION_TIP }, + + { 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, 876, STR_SELECT_HOW_OFTEN_A_MECHANIC_SHOULD_CHECK_THIS_RIDE }, + { WWT_FLATBTN, 1, 289, 312, 108, 131, 0xFFFFFFFF, STR_LOCATE_NEAREST_AVAILABLE_MECHANIC_TIP }, + { WIDGETS_END }, +}; + +// 0x009AE2A4 +static rct_widget window_ride_colour_widgets[] = { + { WWT_FRAME, 0, 0, 315, 0, 206, 0x0FFFFFFFF, STR_NONE }, + { WWT_CAPTION, 0, 1, 314, 1, 14, 0x3DD, 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, 0x0FFFFFFFF, STR_NONE }, + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_VIEW_OF_RIDE_ATTRACTION_TIP }, + { WWT_TAB, 1, 34, 64, 17, 46, 0x2000144E, STR_VEHICLE_DETAILS_AND_OPTIONS_TIP }, + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_OPERATING_OPTIONS_TIP }, + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_MAINTENANCE_OPTIONS_TIP }, + { WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_COLOUR_SCHEME_OPTIONS_TIP }, + { WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_SOUND_AND_MUSIC_OPTIONS_TIP }, + { WWT_TAB, 1, 189, 219, 17, 43, 0x2000144E, STR_MEASUREMENTS_AND_TEST_DATA_TIP }, + { WWT_TAB, 1, 220, 250, 17, 43, 0x2000144E, STR_GRAPHS_TIP }, + { WWT_TAB, 1, 251, 281, 17, 43, 0x2000144E, STR_INCOME_AND_COSTS_TIP }, + { WWT_TAB, 1, 282, 312, 17, 43, 0x2000144E, STR_CUSTOMER_INFORMATION_TIP }, + + { WWT_SPINNER, 1, 3, 70, 47, 93, 0xFFFFFFFF, STR_NONE }, + { WWT_DROPDOWN, 1, 74, 312, 49, 60, 872, STR_NONE }, + { WWT_DROPDOWN_BUTTON, 1, 301, 311, 50, 59, 876, STR_COLOUR_SCHEME_TO_CHANGE_TIP }, + { WWT_COLORBTN, 1, 79, 90, 74, 85, 0xFFFFFFFF, STR_SELECT_MAIN_COLOUR_TIP }, + { WWT_COLORBTN, 1, 99, 110, 74, 85, 0xFFFFFFFF, STR_SELECT_ADDITIONAL_COLOUR_1_TIP }, + { WWT_COLORBTN, 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, 876, STR_NONE }, + { WWT_FLATBTN, 1, 289, 312, 68, 91, 5173, 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, 876, 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, 868, STR_NONE }, + { WWT_DROPDOWN_BUTTON, 1, 301, 311, 158, 167, 876, STR_SELECT_VEHICLE_COLOUR_SCHEME_TIP }, + { WWT_DROPDOWN, 1, 74, 312, 173, 184, 0xFFFFFFFF, STR_NONE }, + { WWT_DROPDOWN_BUTTON, 1, 301, 311, 174, 183, 876, STR_SELECT_VEHICLE_TO_MODIFY_TIP }, + { WWT_COLORBTN, 1, 79, 90, 190, 201, 0xFFFFFFFF, STR_SELECT_MAIN_COLOUR_TIP }, + { WWT_COLORBTN, 1, 99, 110, 190, 201, 0xFFFFFFFF, STR_SELECT_ADDITIONAL_COLOUR_1_TIP }, + { WWT_COLORBTN, 1, 119, 130, 190, 201, 0xFFFFFFFF, STR_SELECT_ADDITIONAL_COLOUR_2_TIP }, + { WIDGETS_END }, +}; + +// 0x009AE4C8 +static rct_widget window_ride_music_widgets[] = { + { WWT_FRAME, 0, 0, 315, 0, 206, 0x0FFFFFFFF, STR_NONE }, + { WWT_CAPTION, 0, 1, 314, 1, 14, 0x3DD, 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, 0x0FFFFFFFF, STR_NONE }, + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_VIEW_OF_RIDE_ATTRACTION_TIP }, + { WWT_TAB, 1, 34, 64, 17, 46, 0x2000144E, STR_VEHICLE_DETAILS_AND_OPTIONS_TIP }, + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_OPERATING_OPTIONS_TIP }, + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_MAINTENANCE_OPTIONS_TIP }, + { WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_COLOUR_SCHEME_OPTIONS_TIP }, + { WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_SOUND_AND_MUSIC_OPTIONS_TIP }, + { WWT_TAB, 1, 189, 219, 17, 43, 0x2000144E, STR_MEASUREMENTS_AND_TEST_DATA_TIP }, + { WWT_TAB, 1, 220, 250, 17, 43, 0x2000144E, STR_GRAPHS_TIP }, + { WWT_TAB, 1, 251, 281, 17, 43, 0x2000144E, STR_INCOME_AND_COSTS_TIP }, + { WWT_TAB, 1, 282, 312, 17, 43, 0x2000144E, STR_CUSTOMER_INFORMATION_TIP }, + + { 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, 876, STR_SELECT_MUSIC_STYLE_TIP }, + { WIDGETS_END }, +}; + +// 0x009AE5DC +static rct_widget window_ride_measurements_widgets[] = { + { WWT_FRAME, 0, 0, 315, 0, 206, 0x0FFFFFFFF, STR_NONE }, + { WWT_CAPTION, 0, 1, 314, 1, 14, 0x3DD, 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, 0x0FFFFFFFF, STR_NONE }, + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_VIEW_OF_RIDE_ATTRACTION_TIP }, + { WWT_TAB, 1, 34, 64, 17, 46, 0x2000144E, STR_VEHICLE_DETAILS_AND_OPTIONS_TIP }, + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_OPERATING_OPTIONS_TIP }, + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_MAINTENANCE_OPTIONS_TIP }, + { WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_COLOUR_SCHEME_OPTIONS_TIP }, + { WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_SOUND_AND_MUSIC_OPTIONS_TIP }, + { WWT_TAB, 1, 189, 219, 17, 43, 0x2000144E, STR_MEASUREMENTS_AND_TEST_DATA_TIP }, + { WWT_TAB, 1, 220, 250, 17, 43, 0x2000144E, STR_GRAPHS_TIP }, + { WWT_TAB, 1, 251, 281, 17, 43, 0x2000144E, STR_INCOME_AND_COSTS_TIP }, + { WWT_TAB, 1, 282, 312, 17, 43, 0x2000144E, STR_CUSTOMER_INFORMATION_TIP }, + + { WWT_FLATBTN, 1, 288, 311, 164, 187, 5183, 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[] = { + { WWT_FRAME, 0, 0, 315, 0, 206, 0x0FFFFFFFF, STR_NONE }, + { WWT_CAPTION, 0, 1, 314, 1, 14, 0x3DD, 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, 0x0FFFFFFFF, STR_NONE }, + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_VIEW_OF_RIDE_ATTRACTION_TIP }, + { WWT_TAB, 1, 34, 64, 17, 46, 0x2000144E, STR_VEHICLE_DETAILS_AND_OPTIONS_TIP }, + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_OPERATING_OPTIONS_TIP }, + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_MAINTENANCE_OPTIONS_TIP }, + { WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_COLOUR_SCHEME_OPTIONS_TIP }, + { WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_SOUND_AND_MUSIC_OPTIONS_TIP }, + { WWT_TAB, 1, 189, 219, 17, 43, 0x2000144E, STR_MEASUREMENTS_AND_TEST_DATA_TIP }, + { WWT_TAB, 1, 220, 250, 17, 43, 0x2000144E, STR_GRAPHS_TIP }, + { WWT_TAB, 1, 251, 281, 17, 43, 0x2000144E, STR_INCOME_AND_COSTS_TIP }, + { WWT_TAB, 1, 282, 312, 17, 43, 0x2000144E, STR_CUSTOMER_INFORMATION_TIP }, + + { WWT_SCROLL, 1, 3, 308, 46, 157, 1, STR_LOGGING_DATA_FROM_TIP }, + { WWT_DROPDOWN_BUTTON, 1, 3, 75, 163, 176, 1415, STR_SHOW_GRAPH_OF_VELOCITY_AGAINST_TIME_TIP }, + { WWT_DROPDOWN_BUTTON, 1, 76, 148, 163, 176, 1416, STR_SHOW_GRAPH_OF_ALTITUDE_AGAINST_TIME_TIP }, + { WWT_DROPDOWN_BUTTON, 1, 149, 221, 163, 176, 1417, STR_SHOW_GRAPH_OF_VERTICAL_ACCELERATION_AGAINST_TIME_TIP }, + { WWT_DROPDOWN_BUTTON, 1, 222, 294, 163, 176, 1418, STR_SHOW_GRAPH_OF_LATERAL_ACCELERATION_AGAINST_TIME_TIP }, + { WIDGETS_END }, +}; + +// 0x009AE844 +static rct_widget window_ride_income_widgets[] = { + { WWT_FRAME, 0, 0, 315, 0, 206, 0x0FFFFFFFF, STR_NONE }, + { WWT_CAPTION, 0, 1, 314, 1, 14, 0x3DD, 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, 0x0FFFFFFFF, STR_NONE }, + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_VIEW_OF_RIDE_ATTRACTION_TIP }, + { WWT_TAB, 1, 34, 64, 17, 46, 0x2000144E, STR_VEHICLE_DETAILS_AND_OPTIONS_TIP }, + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_OPERATING_OPTIONS_TIP }, + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_MAINTENANCE_OPTIONS_TIP }, + { WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_COLOUR_SCHEME_OPTIONS_TIP }, + { WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_SOUND_AND_MUSIC_OPTIONS_TIP }, + { WWT_TAB, 1, 189, 219, 17, 43, 0x2000144E, STR_MEASUREMENTS_AND_TEST_DATA_TIP }, + { WWT_TAB, 1, 220, 250, 17, 43, 0x2000144E, STR_GRAPHS_TIP }, + { WWT_TAB, 1, 251, 281, 17, 43, 0x2000144E, STR_INCOME_AND_COSTS_TIP }, + { WWT_TAB, 1, 282, 312, 17, 43, 0x2000144E, STR_CUSTOMER_INFORMATION_TIP }, + + { WWT_24, 1, 5, 144, 50, 61, 0xFFFFFFFF, STR_NONE }, + { WWT_SPINNER, 1, 147, 308, 50, 61, 1429, 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, 1799, 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[] = { + { WWT_FRAME, 0, 0, 315, 0, 206, 0x0FFFFFFFF, STR_NONE }, + { WWT_CAPTION, 0, 1, 314, 1, 14, 0x3DD, 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, 0x0FFFFFFFF, STR_NONE }, + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_VIEW_OF_RIDE_ATTRACTION_TIP }, + { WWT_TAB, 1, 34, 64, 17, 46, 0x2000144E, STR_VEHICLE_DETAILS_AND_OPTIONS_TIP }, + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_OPERATING_OPTIONS_TIP }, + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_MAINTENANCE_OPTIONS_TIP }, + { WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_COLOUR_SCHEME_OPTIONS_TIP }, + { WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_SOUND_AND_MUSIC_OPTIONS_TIP }, + { WWT_TAB, 1, 189, 219, 17, 43, 0x2000144E, STR_MEASUREMENTS_AND_TEST_DATA_TIP }, + { WWT_TAB, 1, 220, 250, 17, 43, 0x2000144E, STR_GRAPHS_TIP }, + { WWT_TAB, 1, 251, 281, 17, 43, 0x2000144E, STR_INCOME_AND_COSTS_TIP }, + { WWT_TAB, 1, 282, 312, 17, 43, 0x2000144E, STR_CUSTOMER_INFORMATION_TIP }, + + { WWT_FLATBTN, 1, 289, 312, 54, 77, 5184, STR_SHOW_GUESTS_THOUGHTS_ABOUT_THIS_RIDE_ATTRACTION_TIP }, + { WWT_FLATBTN, 1, 289, 312, 78, 101, 5186, STR_SHOW_GUESTS_ON_THIS_RIDE_ATTRACTION_TIP }, + { WWT_FLATBTN, 1, 289, 312, 102, 125, 5185, STR_SHOW_GUESTS_QUEUING_FOR_THIS_RIDE_ATTRACTION_TIP }, + { WIDGETS_END }, +}; + static rct_widget *window_ride_page_widgets[] = { - (rct_widget*)0x009ADC34, - (rct_widget*)0x009ADDA8, - (rct_widget*)0x009ADEFC, - (rct_widget*)0x009AE190, - (rct_widget*)0x009AE2A4, - (rct_widget*)0x009AE4C8, - (rct_widget*)0x009AE5DC, - (rct_widget*)0x009AE710, - (rct_widget*)0x009AE844, - (rct_widget*)0x009AE9C8 + 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 +}; + +const uint64 window_ride_page_enabled_widgets[] = { + 0x00000000007DBFF4, + 0x00000000001EFFF4, + 0x0000019E777DBFF4, + 0x000000000001FFF4, + 0x00000003F37F3FF4, + 0x000000000001FFF4, + 0x000000000007FFF4, + 0x000000000007BFF4, + 0x0000000000E73FF4, + 0x000000000001FFF4 }; #pragma endregion #pragma region Events +static void window_ride_emptysub() { } + +static void window_ride_main_mouseup(); +static void window_ride_main_resize(); +static void window_ride_main_mousedown(int widgetIndex, rct_window *w, rct_widget *widget); +static void window_ride_main_dropdown(); +static void window_ride_main_update(rct_window *w); +static void window_ride_main_textinput(); +static void window_ride_main_unknown_14(); +static void window_ride_main_invalidate(); +static void window_ride_main_paint(); + +static void window_ride_vehicle_mouseup(); +static void window_ride_vehicle_resize(); +static void window_ride_vehicle_mousedown(int widgetIndex, rct_window *w, rct_widget *widget); +static void window_ride_vehicle_dropdown(); +static void window_ride_vehicle_update(rct_window *w); +static void window_ride_vehicle_invalidate(); +static void window_ride_vehicle_paint(); +static void window_ride_vehicle_scrollpaint(); + +static void window_ride_operating_mouseup(); +static void window_ride_operating_resize(); +static void window_ride_operating_mousedown(int widgetIndex, rct_window *w, rct_widget *widget); +static void window_ride_operating_dropdown(); +static void window_ride_operating_update(rct_window *w); +static void window_ride_operating_invalidate(); +static void window_ride_operating_paint(); + +static void window_ride_maintenance_mouseup(); +static void window_ride_maintenance_resize(); +static void window_ride_maintenance_mousedown(int widgetIndex, rct_window *w, rct_widget *widget); +static void window_ride_maintenance_dropdown(); +static void window_ride_maintenance_update(rct_window *w); +static void window_ride_maintenance_invalidate(); +static void window_ride_maintenance_paint(); + +static void window_ride_colour_close(); +static void window_ride_colour_mouseup(); +static void window_ride_colour_resize(); +static void window_ride_colour_mousedown(int widgetIndex, rct_window *w, rct_widget *widget); +static void window_ride_colour_dropdown(); +static void window_ride_colour_update(rct_window *w); +static void window_ride_colour_tooldown(); +static void window_ride_colour_tooldrag(); +static void window_ride_colour_invalidate(); +static void window_ride_colour_paint(); +static void window_ride_colour_scrollpaint(); + +static void window_ride_music_mouseup(); +static void window_ride_music_resize(); +static void window_ride_music_mousedown(int widgetIndex, rct_window *w, rct_widget *widget); +static void window_ride_music_dropdown(); +static void window_ride_music_update(rct_window *w); +static void window_ride_music_invalidate(); +static void window_ride_music_paint(); + +static void window_ride_measurements_close(); +static void window_ride_measurements_mouseup(); +static void window_ride_measurements_resize(); +static void window_ride_measurements_mousedown(int widgetIndex, rct_window *w, rct_widget *widget); +static void window_ride_measurements_dropdown(); +static void window_ride_measurements_update(rct_window *w); +static void window_ride_measurements_tooldown(); +static void window_ride_measurements_toolabort(); +static void window_ride_measurements_invalidate(); +static void window_ride_measurements_paint(); + +static void window_ride_graphs_mouseup(); +static void window_ride_graphs_resize(); +static void window_ride_graphs_mousedown(int widgetIndex, rct_window *w, rct_widget *widget); +static void window_ride_graphs_update(rct_window *w); +static void window_ride_graphs_scrollgetheight(); +static void window_ride_graphs_15(); +static void window_ride_graphs_tooltip(); +static void window_ride_graphs_invalidate(); +static void window_ride_graphs_paint(); +static void window_ride_graphs_scrollpaint(); + +static void window_ride_income_mouseup(); +static void window_ride_income_resize(); +static void window_ride_income_mousedown(int widgetIndex, rct_window *w, rct_widget *widget); +static void window_ride_income_update(rct_window *w); +static void window_ride_income_invalidate(); +static void window_ride_income_paint(); + +static void window_ride_customer_mouseup(); +static void window_ride_customer_resize(); +static void window_ride_customer_update(rct_window *w); +static void window_ride_customer_invalidate(); +static void window_ride_customer_paint(); + +// 0x0098DFD4 +static void* window_ride_main_events[] = { + window_ride_emptysub, + window_ride_main_mouseup, + window_ride_main_resize, + window_ride_main_mousedown, + window_ride_main_dropdown, + window_ride_emptysub, + window_ride_main_update, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_main_textinput, + window_ride_main_unknown_14, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_main_invalidate, + window_ride_main_paint, + window_ride_emptysub +}; + +// 0x0098E204 +static void* window_ride_vehicle_events[] = { + window_ride_emptysub, + window_ride_vehicle_mouseup, + window_ride_vehicle_resize, + window_ride_vehicle_mousedown, + window_ride_vehicle_dropdown, + window_ride_emptysub, + window_ride_vehicle_update, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_vehicle_invalidate, + window_ride_vehicle_paint, + window_ride_vehicle_scrollpaint +}; + +// 0x0098E0B4 +static void* window_ride_operating_events[] = { + window_ride_emptysub, + window_ride_operating_mouseup, + window_ride_operating_resize, + window_ride_operating_mousedown, + window_ride_operating_dropdown, + window_ride_emptysub, + window_ride_operating_update, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_operating_invalidate, + window_ride_operating_paint, + window_ride_emptysub +}; + +// 0x0098E124 +static void* window_ride_maintenance_events[] = { + window_ride_emptysub, + window_ride_maintenance_mouseup, + window_ride_maintenance_resize, + window_ride_maintenance_mousedown, + window_ride_maintenance_dropdown, + window_ride_emptysub, + window_ride_maintenance_update, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_maintenance_invalidate, + window_ride_maintenance_paint, + window_ride_emptysub +}; + +// 0x0098E044 +static void* window_ride_colour_events[] = { + window_ride_colour_close, + window_ride_colour_mouseup, + window_ride_colour_resize, + window_ride_colour_mousedown, + window_ride_colour_dropdown, + window_ride_emptysub, + window_ride_colour_update, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_colour_tooldown, + window_ride_colour_tooldrag, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_colour_invalidate, + window_ride_colour_paint, + window_ride_colour_scrollpaint +}; + +// 0x0098E194 +static void* window_ride_music_events[] = { + window_ride_emptysub, + window_ride_music_mouseup, + window_ride_music_resize, + window_ride_music_mousedown, + window_ride_music_dropdown, + window_ride_emptysub, + window_ride_music_update, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_music_invalidate, + window_ride_music_paint, + window_ride_emptysub +}; + +// 0x0098DE14 +static void* window_ride_measurements_events[] = { + window_ride_emptysub, + window_ride_measurements_mouseup, + window_ride_measurements_resize, + window_ride_measurements_mousedown, + window_ride_measurements_dropdown, + window_ride_emptysub, + window_ride_measurements_update, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_measurements_tooldown, + window_ride_emptysub, + window_ride_emptysub, + window_ride_measurements_toolabort, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_measurements_invalidate, + window_ride_measurements_paint, + window_ride_emptysub +}; + +// 0x0098DF64 +static void* window_ride_graphs_events[] = { + window_ride_emptysub, + window_ride_graphs_mouseup, + window_ride_graphs_resize, + window_ride_graphs_mousedown, + window_ride_emptysub, + window_ride_emptysub, + window_ride_graphs_update, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_graphs_scrollgetheight, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_graphs_15, + window_ride_graphs_tooltip, + window_ride_emptysub, + window_ride_emptysub, + window_ride_graphs_invalidate, + window_ride_graphs_paint, + window_ride_graphs_scrollpaint +}; + +// 0x0098DEF4 +static void* window_ride_income_events[] = { + window_ride_emptysub, + window_ride_income_mouseup, + window_ride_income_resize, + window_ride_income_mousedown, + window_ride_emptysub, + window_ride_emptysub, + window_ride_income_update, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_income_invalidate, + window_ride_income_paint, + window_ride_emptysub +}; + +// 0x0098DE84 +static void* window_ride_customer_events[] = { + window_ride_emptysub, + window_ride_customer_mouseup, + window_ride_customer_resize, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_customer_update, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_emptysub, + window_ride_customer_invalidate, + window_ride_customer_paint, + window_ride_emptysub +}; + static uint32* window_ride_page_events[] = { - (uint32*)0x0098DFD4, - (uint32*)0x0098E204, - (uint32*)0x0098E0B4, - (uint32*)0x0098E124, - (uint32*)0x0098E044, - (uint32*)0x0098E194, - (uint32*)0x0098DE14, - (uint32*)0x0098DF64, - (uint32*)0x0098DEF4, - (uint32*)0x0098DE84 + (uint32*)window_ride_main_events, + (uint32*)window_ride_vehicle_events, + (uint32*)window_ride_operating_events, + (uint32*)window_ride_maintenance_events, + (uint32*)window_ride_colour_events, + (uint32*)window_ride_music_events, + (uint32*)window_ride_measurements_events, + (uint32*)window_ride_graphs_events, + (uint32*)window_ride_income_events, + (uint32*)window_ride_customer_events }; #pragma endregion +const int window_ride_tab_animation_divisor[] = { 0, 0, 2, 2, 4, 2, 8, 8, 2, 0 }; +const int window_ride_tab_animation_frames[] = { 0, 0, 4, 16, 8, 16, 8, 8, 8, 0 }; + +// WINDOW_PARK_PAGE_MAIN, +// WINDOW_PARK_PAGE_VEHICLE, +// WINDOW_PARK_PAGE_OPERATING, +// WINDOW_PARK_PAGE_MAINTENANCE, +// WINDOW_PARK_PAGE_COLOUR, +// WINDOW_PARK_PAGE_MUSIC, +// WINDOW_PARK_PAGE_MEASUREMENTS, +// WINDOW_PARK_PAGE_GRAPHS, +// WINDOW_PARK_PAGE_INCOME, +// WINDOW_PARK_PAGE_CUSTOMER + +static void window_ride_draw_tab_image(rct_drawpixelinfo *dpi, rct_window *w, int page, int spriteIndex) +{ + int widgetIndex = WIDX_TAB_1 + page; + + if (!(w->disabled_widgets & (1LL << widgetIndex))) { + if (w->page == page) { + int 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) +{ + int widgetIndex = WIDX_TAB_1 + WINDOW_PARK_PAGE_MAIN; + + if (!(w->disabled_widgets & (1LL << widgetIndex))) { + int spriteIndex; + int rideType = GET_RIDE(w->number)->type; + + switch (gRideClassifications[rideType]) { + case RIDE_CLASS_RIDE: + spriteIndex = 5442; + if (w->page == WINDOW_PARK_PAGE_MAIN) + spriteIndex += (w->frame_no / 4) % 16; + break; + case RIDE_CLASS_SHOP_OR_STALL: + spriteIndex = 5351; + if (w->page == WINDOW_PARK_PAGE_MAIN) + spriteIndex += (w->frame_no / 4) % 16; + break; + case RIDE_CLASS_KIOSK_OR_FACILITY: + spriteIndex = 5367; + if (w->page == WINDOW_PARK_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_ride *ride; + rct_widget *widget; + int widgetIndex, spriteIndex, x, y, width, height; + uint8 *ebp; + rct_ride_type *rideEntry; + vehicle_colour vehicleColour; + + widgetIndex = WIDX_TAB_1 + WINDOW_PARK_PAGE_VEHICLE; + widget = &w->widgets[widgetIndex]; + + if (!(w->disabled_widgets & (1LL << widgetIndex))) { + x = widget->left + 1; + y = widget->top + 1; + width = widget->right - x; + height = widget->bottom - 3 - y; + if (w->page == WINDOW_PARK_PAGE_VEHICLE) + height += 4; + + x += w->x; + y += w->y; + + dpi = clip_drawpixelinfo(dpi, x, width, y, height); + if (dpi == NULL) + return; + + x = (widget->right - widget->left) / 2; + y = (widget->bottom - widget->top) - 12; + + ride = GET_RIDE(w->number); + RCT2_CALLPROC_X(0x006DE4CD, (ride->num_cars_per_train << 8) | ride->subtype, 0, 0, 0, 0, 0, 0); + + rideEntry = ride_get_entry(ride); + if (rideEntry->var_008 & 1) { + dpi->zoom_level = 1; + dpi->width *= 2; + dpi->height *= 2; + x *= 2; + y *= 2; + dpi->x *= 2; + dpi->y *= 2; + } + + ebp = (uint8*)rideEntry + (RCT2_ADDRESS(0x00F64E38, uint8)[rideEntry->var_013] * 101); + height += RCT2_GLOBAL(ebp + 0x24, sint8); + + vehicleColour = ride_get_vehicle_colour(ride, 0); + + spriteIndex = 32; + if (w->page == WINDOW_PARK_PAGE_VEHICLE) + spriteIndex += w->frame_no; + spriteIndex /= (RCT2_GLOBAL(ebp + 0x2C, uint16) & 0x800) ? 4 : 2; + spriteIndex &= RCT2_GLOBAL(ebp + 0x1A, uint16); + spriteIndex *= RCT2_GLOBAL(ebp + 0x30, uint16); + spriteIndex += RCT2_GLOBAL(ebp + 0x32, uint32); + spriteIndex |= (vehicleColour.additional_1 << 24) | (vehicleColour.main << 19); + spriteIndex |= 0x80000000; + + gfx_draw_sprite(dpi, spriteIndex, x, y, vehicleColour.additional_2); + } +} + +/** + * + * rct2: 0x006B2F42 + */ +static void window_ride_draw_tab_customer(rct_drawpixelinfo *dpi, rct_window *w) +{ + int spriteIndex; + int widgetIndex = WIDX_TAB_1 + WINDOW_PARK_PAGE_CUSTOMER; + rct_widget *widget = &w->widgets[widgetIndex]; + + if (!(w->disabled_widgets & (1LL << widgetIndex))) { + spriteIndex = 0; + if (w->page == WINDOW_PARK_PAGE_CUSTOMER) + spriteIndex = w->var_492 & ~3; + + spriteIndex += RCT2_GLOBAL(RCT2_GLOBAL(0x00982708, uint32), uint32); + 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_PARK_PAGE_OPERATING, 5201); + window_ride_draw_tab_image(dpi, w, WINDOW_PARK_PAGE_MAINTENANCE, 5205); + window_ride_draw_tab_image(dpi, w, WINDOW_PARK_PAGE_INCOME, 5253); + window_ride_draw_tab_main(dpi, w); + window_ride_draw_tab_image(dpi, w, WINDOW_PARK_PAGE_MEASUREMENTS, 5229); + window_ride_draw_tab_image(dpi, w, WINDOW_PARK_PAGE_COLOUR, 5221); + window_ride_draw_tab_image(dpi, w, WINDOW_PARK_PAGE_GRAPHS, 5237); + window_ride_draw_tab_customer(dpi, w); + window_ride_draw_tab_image(dpi, w, WINDOW_PARK_PAGE_MUSIC, 5335); +} + /** * * rct2: 0x006AEAB4 @@ -70,10 +1096,13 @@ static uint32* window_ride_page_events[] = { rct_window *window_ride_open(int rideIndex) { rct_window *w; + rct_ride *ride; + uint8 *rideEntryIndexPtr; + int numSubTypes, quadIndex, bitIndex; w = window_create_auto_pos(316, 180, window_ride_page_events[0], WC_RIDE, 0x400); w->widgets = window_ride_page_widgets[0]; - w->enabled_widgets = 0x007DBFF4; + w->enabled_widgets = window_ride_page_enabled_widgets[0]; w->number = rideIndex; w->page = 0; @@ -92,27 +1121,18 @@ rct_window *window_ride_open(int rideIndex) w->colours[1] = 26; w->colours[2] = 11; - rct_ride *ride = &g_ride_list[rideIndex]; - uint8 *edx = (uint8*)0x009E32F8; - if (ride->type != RIDE_TYPE_NULL) { - int rideType = ride->type; - do { - edx++; - if (*(edx - 1) != 0xFF) - continue; - } while (rideType-- != 0); - } - - int eax, ebx = 0, ecx; - while (*edx != 0xFF) { - eax = *edx++; - ecx = eax >> 5; - eax &= 0x1F; - if (!(RCT2_ADDRESS(0x001357424, uint32)[ecx] & (1 << eax))) + ride = GET_RIDE(rideIndex); + numSubTypes = 0; + rideEntryIndexPtr = get_ride_entry_indices_for_ride_type(ride->type); + for (; *rideEntryIndexPtr != 0xFF; rideEntryIndexPtr++) { + quadIndex = *rideEntryIndexPtr >> 5; + bitIndex = *rideEntryIndexPtr & 0x1F; + if (!(RCT2_ADDRESS(0x01357424, uint32)[quadIndex] & (1 << bitIndex))) continue; - ebx++; + + numSubTypes++; } - RCT2_GLOBAL((int)w + 496, uint16) = ebx; + var_496(w) = numSubTypes; return w; } @@ -149,6 +1169,4436 @@ void window_ride_main_open(int rideIndex) w->pressed_widgets = 0; RCT2_CALLPROC_X(0x006AEB9F, 0, 0, 0, 0, (int)w, 0, 0); window_init_scroll_widgets(w); - w->ride.var_480 = 0; + w->ride.view = 0; RCT2_CALLPROC_X(0x006AF994, 0, 0, 0, 0, (int)w, 0, 0); -} \ No newline at end of file +} + +/** + * + * rct2: 0x006AF1D2 + */ +static void window_ride_set_page(rct_window *w, int page) +{ + int listen; + + if (RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3)) + if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)) + tool_cancel(); + + // Set listen only to viewport + listen = 0; + if (page == WINDOW_PARK_PAGE_MAIN && w->page == WINDOW_PARK_PAGE_MAIN && w->viewport != NULL && !(w->viewport->flags & VIEWPORT_FLAG_SOUND_ON)) + listen++; + + w->page = page; + w->frame_no = 0; + w->var_492 = 0; + if (w->viewport != NULL) { + w->viewport->width = 0; + w->viewport = NULL; + } + + w->enabled_widgets = window_ride_page_enabled_widgets[page]; + w->var_020 = RCT2_ADDRESS(0x0098DD68, uint32)[page]; + w->event_handlers = window_ride_page_events[page]; + w->widgets = window_ride_page_widgets[page]; + RCT2_CALLPROC_X(0x006AEB9F, 0, 0, 0, 0, (int)w, 0, 0); + window_invalidate(w); + + RCT2_CALLPROC_X(w->event_handlers[WE_RESIZE], 0, 0, 0, 0, (int)w, 0, 0); + RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0); + + 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) +{ + int i; + for (i = 0; i < WINDOW_PARK_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) +{ + RCT2_CALLPROC_X(0x006AF994, 0, 0, 0, 0, (int)w, 0, 0); +} + +/** + * + * rct2: 0x006B4971 + */ +static void window_ride_construct(rct_window *w) +{ + int rideIndex = w->number; + + window_close_by_id(WC_RIDE_CONSTRUCTION | 0x80, rideIndex); + w = window_find_by_id(WC_RIDE, rideIndex); + if (w == NULL) + return; + + rct_map_element *trackMapElement; + int trackX, trackY; + + trackMapElement = sub_6CAF80(rideIndex, &trackX, &trackY); + if (trackMapElement == (rct_map_element*)-1) { + RCT2_CALLPROC_X(0x006CC3FB, 0, 0, 0, rideIndex, 0, 0, 0); + } else { + trackMapElement = ride_find_track_gap(trackMapElement, &trackX, &trackY); + + w = window_get_main(); + if (w != NULL && ride_try_construct(trackMapElement)) + window_scroll_to_location(w, trackX, trackY, trackMapElement->base_height * 8); + } +} + +/** + * + * rct2: 0x006AF315 + */ +static void window_ride_rename(rct_window *w) +{ + rct_ride *ride; + + ride = GET_RIDE(w->number); + RCT2_GLOBAL(0x013CE962, uint32) = ride->name_arguments; + window_show_textinput(w, WIDX_RENAME, STR_RIDE_ATTRACTION_NAME, STR_ENTER_NEW_NAME_FOR_THIS_RIDE_ATTRACTION, ride->name); +} + +/** + * + * rct2: 0x006AF3B3 + */ +static void window_ride_locate(rct_window *w) +{ + rct_window *mainWindow; + int xy, x, y, z; + + if (w->viewport->width == 0) + return; + + xy = w->ride.var_482; + z = w->ride.var_486; + if (xy == -1) + return; + + if (xy & 0x80000000) { + rct_sprite *sprite = &g_sprite_list[xy]; + x = sprite->unknown.x; + y = sprite->unknown.y; + z = sprite->unknown.z; + } else { + x = (xy & ~0xC0000000) & 0xFFFF; + y = (xy & ~0xC0000000) >> 16; + z = z >> 16; + } + + mainWindow = window_get_main(); + if (mainWindow != NULL) + window_scroll_to_location(mainWindow, x, y, z); +} + +/** + * + * rct2: 0x006B486A + */ +static void window_ride_demolish(rct_window *w) +{ + rct_window *demolishWindow; + int x, y, screenWidth, screenHeight; + + demolishWindow = window_bring_to_front_by_id(WC_DEMOLISH_RIDE_PROMPT, w->number); + if (demolishWindow != NULL) + return; + + screenWidth = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16); + screenHeight = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16); + x = screenWidth / 2 - 100; + y = max(28, screenHeight / 2 - 50); + + demolishWindow = window_create(x, y, 200, 100, (uint32*)0x0098E2E4, WC_DEMOLISH_RIDE_PROMPT, 0); + demolishWindow->widgets = (rct_widget*)0x009AEBA0; + demolishWindow->enabled_widgets = 4 | 8 | 16; + window_init_scroll_widgets(demolishWindow); + demolishWindow->flags |= WF_TRANSPARENT; + demolishWindow->number = w->number; + demolishWindow->colours[0] = 154; +} + +/** + * + * rct2: 0x006AF17E + */ +static void window_ride_main_mouseup() +{ + short widgetIndex; + rct_window *w; + + window_widget_get_registers(w, 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_CONSTRUCTION: + window_ride_construct(w); + break; + case WIDX_RENAME: + window_ride_rename(w); + break; + case WIDX_LOCATE: + window_ride_locate(w); + break; + case WIDX_DEMOLISH: + window_ride_demolish(w); + break; + } +} + +/** + * + * rct2: 0x006AF4A2 + */ +static void window_ride_main_resize() +{ + rct_window *w; + rct_viewport *viewport; + int width, height; + + window_get_register(w); + + w->flags |= WF_RESIZABLE; + window_set_resize(w, 316, 180, 500, 450); + + viewport = w->viewport; + if (viewport != NULL) { + width = w->width - 30; + height = w->height - 75; + if (viewport->width != width || viewport->height != height) { + viewport->width = width; + viewport->height = height; + viewport->view_width = width << viewport->zoom; + viewport->view_height = height << viewport->zoom; + } + } + + window_ride_init_viewport(w); +} + +/** + * + * rct2: 0x006AF825 + */ +static void window_ride_show_view_dropdown(rct_window *w, rct_widget *widget) +{ + rct_widget *dropdownWidget; + rct_ride *ride; + int numItems, currentItem, i, j, name; + + dropdownWidget = widget - 1; + ride = GET_RIDE(w->number); + + numItems = 1; + if (!(RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x2000)) { + 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, + numItems, + widget->right - dropdownWidget->left + ); + + // First item + gDropdownItemsFormat[0] = 1142; + gDropdownItemsArgs[0] = STR_OVERALL_VIEW; + currentItem = 1; + + // Vehicles + name = RideNameConvention[ride->type].vehicle_name + 6; + for (i = 1; i <= ride->num_vehicles; i++) { + gDropdownItemsFormat[currentItem] = 1142; + gDropdownItemsArgs[currentItem] = name | (currentItem << 16); + currentItem++; + } + + // Stations + name = RideNameConvention[ride->type].station_name + 6; + for (i = 1; i <= ride->num_stations; i++) { + gDropdownItemsFormat[currentItem] = 1142; + gDropdownItemsArgs[currentItem] = name | (i << 16); + currentItem++; + } + + // Set highlighted item + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)) { + j = 2; + for (i = 0; i < ride->num_vehicles; i++) { + RCT2_GLOBAL(0x009DED34, uint32) |= j; + j <<= 1; + } + } + + // Set checked item + gDropdownItemsChecked |= (1 << w->ride.view); +} + +/** + * + * rct2: 0x006AF64C + */ +static void window_ride_show_open_dropdown(rct_window *w, rct_widget *widget) +{ + rct_ride *ride; + int numItems, highlightedIndex, checkedIndex; + + ride = GET_RIDE(w->number); + + numItems = 0; + gDropdownItemsFormat[numItems] = 1142; + gDropdownItemsArgs[numItems] = STR_CLOSE_RIDE; + numItems++; + + if (!(RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x800)) { + gDropdownItemsFormat[numItems] = 1142; + gDropdownItemsArgs[numItems] = STR_TEST_RIDE; + numItems++; + } + + gDropdownItemsFormat[numItems] = 1142; + 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_11)) + break; + + highlightedIndex = 2; + if (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x800) + 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 (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x800) { + if (checkedIndex != 0) + checkedIndex--; + if (highlightedIndex != 0) + highlightedIndex--; + } + + gDropdownItemsChecked |= (1 << checkedIndex); + RCT2_GLOBAL(0x009DEBA2, sint16) = highlightedIndex; +} + +/** + * + * rct2: 0x006AF1BD + */ +static void window_ride_main_mousedown(int 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; + } +} + +/** + * + * rct2: 0x006AF300 + */ +static void window_ride_main_dropdown() +{ + rct_ride *ride; + rct_window *w; + int status; + short widgetIndex, dropdownIndex; + + window_dropdown_get_registers(w, widgetIndex, dropdownIndex); + + 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; + RCT2_CALLPROC_X(0x006AF994, 0, 0, 0, 0, (int)w, 0, 0); + window_invalidate(w); + break; + case WIDX_OPEN: + if (dropdownIndex == -1) + dropdownIndex = RCT2_GLOBAL(0x009DEBA2, sint16); + + ride = GET_RIDE(w->number); + if ((RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x800) && dropdownIndex != 0) + dropdownIndex++; + + switch (dropdownIndex) { + case 0: + status = RIDE_STATUS_CLOSED; + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, rct_string_id) = 1004; + break; + case 1: + status = RIDE_STATUS_TESTING; + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, rct_string_id) = 1003; + break; + case 2: + status = RIDE_STATUS_OPEN; + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, rct_string_id) = 1002; + break; + } + + RCT2_GLOBAL(0x013CE952 + 6, uint16) = ride->overall_view; + RCT2_GLOBAL(0x013CE952 + 8, uint32) = ride->name_arguments; + game_do_command(0, 1, 0, w->number | (status << 8), GAME_COMMAND_SET_RIDE_OPEN, 0, 0); + break; + } +} + +/** + * + * rct2: 0x006AF40F + */ +static void window_ride_main_update(rct_window *w) +{ + rct_ride *ride; + int vehicleIndex; + uint16 vehicleSpriteIndex; + rct_vehicle *vehicle; + + // Update tab animation + w->frame_no++; + RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0); + widget_invalidate(WC_RIDE, w->number, WIDX_TAB_1); + + // Update status + ride = GET_RIDE(w->number); + if (!(ride->var_14D & 4)) { + if (w->ride.view == 0) + return; + + if (w->ride.view <= ride->num_vehicles) { + vehicleIndex = w->ride.view - 1; + vehicleSpriteIndex = ride->vehicles[vehicleIndex]; + if (vehicleSpriteIndex == 0xFFFF) + return; + + vehicle = &(g_sprite_list[vehicleSpriteIndex].vehicle); + if ( + vehicle->status != 4 && + vehicle->status != 22 && + vehicle->status != 10 && + vehicle->status != 7 + ) { + return; + } + } + } + + ride->var_14D &= ~4; + widget_invalidate(WC_RIDE, w->number, WIDX_STATUS); +} + +/** + * + * rct2: 0x006AF2F9 + */ +static void window_ride_main_textinput() +{ + uint8 result; + short widgetIndex; + rct_window *w; + char *text; + + window_textinput_get_registers(w, widgetIndex, result, text); + + if (widgetIndex != WIDX_RENAME || !result) + return; + + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_RENAME_RIDE_ATTRACTION; + game_do_command(1, (w->number << 8) | 1, 0, *((int*)(text + 0)), GAME_COMMAND_SET_RIDE_NAME, *((int*)(text + 8)), *((int*)(text + 4))); + game_do_command(2, (w->number << 8) | 1, 0, *((int*)(text + 12)), GAME_COMMAND_SET_RIDE_NAME, *((int*)(text + 20)), *((int*)(text + 16))); + game_do_command(0, (w->number << 8) | 1, 0, *((int*)(text + 24)), GAME_COMMAND_SET_RIDE_NAME, *((int*)(text + 32)), *((int*)(text + 28))); +} + +/** + * + * rct2: 0x006AF55A + */ +static void window_ride_main_unknown_14() +{ + rct_window *w; + + window_get_register(w); + + window_ride_init_viewport(w); +} + +/** + * + * rct2: 0x006AECF6 + */ +static void window_ride_main_invalidate() +{ + rct_window *w; + rct_widget *widgets; + int i; + + window_get_register(w); + + 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 << 22) | (1 << 19)); + if (ride->lifecycle_flags & (RIDE_LIFECYCLE_INDESTRUCTIBLE | RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK)) + w->disabled_widgets |= (1 << 22); + if (ride->lifecycle_flags & RIDE_LIFECYCLE_19) + w->disabled_widgets |= (1 << 19); + + RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; + RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + window_ride_main_widgets[WIDX_OPEN].image = SPR_CLOSED + ride->status; + + window_ride_anchor_border_widgets(w); + + // 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; + window_ride_main_widgets[WIDX_STATUS].right = w->width - 26; + window_ride_main_widgets[WIDX_STATUS].top = w->height - 13; + window_ride_main_widgets[WIDX_STATUS].bottom = w->height - 3; + for (i = WIDX_OPEN; i <= WIDX_DEMOLISH; i++) { + window_ride_main_widgets[i].left = w->width - 25; + window_ride_main_widgets[i].right = w->width - 2; + } + 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_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); +} + +/** + * + * rct2: 0x006AF10A + */ +static rct_string_id window_ride_get_status_overall_view(rct_window *w, void *arguments) +{ + int formatSecondary, argument; + rct_string_id stringId; + + ride_get_status(w->number, &formatSecondary, &argument); + RCT2_GLOBAL((int)arguments + 0, uint16) = formatSecondary; + RCT2_GLOBAL((int)arguments + 2, uint32) = argument; + stringId = STR_LOSS; + if (formatSecondary != STR_BROKEN_DOWN && formatSecondary != STR_CRASHED) + stringId = STR_COST; + + return stringId; +} + +/** + * + * rct2: 0x006AEFEF + */ +static rct_string_id window_ride_get_status_vehicle(rct_window *w, void *arguments) +{ + rct_ride *ride; + rct_vehicle *vehicle; + int vehicleIndex; + uint16 vehicleSpriteIndex; + rct_string_id stringId; + + ride = GET_RIDE(w->number); + + vehicleIndex = w->ride.view - 1; + vehicleSpriteIndex = ride->vehicles[vehicleIndex]; + if (vehicleSpriteIndex == 0xFFFF) + return 0; + + vehicle = &(g_sprite_list[vehicleSpriteIndex].vehicle); + if (vehicle->status != VEHICLE_STATUS_CRASHING && vehicle->status != VEHICLE_STATUS_CRASHED) { + int ax = vehicle->var_36 / 4; + if (ax == 216 || ax == 123 || ax == 9 || ax == 63 || ax == 147 || ax == 155) { + if (!(RCT2_ADDRESS(0x01357644, uint32)[ride->type] & 0x40) && vehicle->velocity == 0) { + RCT2_GLOBAL((int)arguments + 0, uint16) = STR_STOPPED_BY_BLOCK_BRAKES; + return 1191; + } + } + } + + stringId = STR_MOVING_TO_END_OF + vehicle->status; + + // Get speed in mph + RCT2_GLOBAL((int)arguments + 2, uint16) = (abs(vehicle->velocity) * 9) >> 18; + + if (ride->type == RIDE_TYPE_MINI_GOLF) + return 0; + + if ((RCT2_GLOBAL(0x0097D4F2 + (ride->type * 8), uint16) & 0x100) && stringId > 1104) + stringId += 23; + + RCT2_GLOBAL((int)arguments + 4, uint16) = RideNameConvention[ride->type].station_name; + RCT2_GLOBAL((int)arguments + 6, uint16) = vehicle->var_4B + 1; + if (ride->num_stations > 1) + RCT2_GLOBAL((int)arguments + 4, uint16) += 6; + + RCT2_GLOBAL((int)arguments + 0, uint16) = stringId; + return stringId != 1106 && stringId != 1107 ? 1191 : 1192; +} + +/** + * + * rct2: 0x006AEF65 + */ +static rct_string_id window_ride_get_status_station(rct_window *w, void *arguments) +{ + rct_ride *ride; + int stationIndex, count, queueLength; + rct_string_id stringId; + + ride = GET_RIDE(w->number); + + count = w->ride.view - ride->num_vehicles - 1; + stationIndex = -1; + do { + stationIndex++; + if (ride->station_starts[stationIndex] != 0xFFFF) + count--; + } while (count >= 0); + + stringId = 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) { + queueLength = ride->queue_length[stationIndex]; + RCT2_GLOBAL((int)arguments + 2, uint16) = queueLength; + stringId = STR_QUEUE_EMPTY; + if (queueLength == 1) + stringId++; + else if (queueLength > 1) + stringId += 2; + } + + RCT2_GLOBAL((int)arguments + 0, uint16) = stringId; + return 1191; +} + +/** + * + * 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_paint_get_registers(w, dpi); + + 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 = RideNameConvention[ride->type].vehicle_name + 6; + if (w->ride.view > ride->num_vehicles) { + RCT2_GLOBAL(0x013CE952 + 2, uint16) = w->ride.view - ride->num_vehicles; + stringId = RideNameConvention[ride->type].station_name + 6; + } else { + RCT2_GLOBAL(0x013CE952 + 2, uint16) = w->ride.view; + } + } + RCT2_GLOBAL(0x013CE952, uint16) = stringId; + + widget = &window_ride_main_widgets[WIDX_VIEW]; + gfx_draw_string_centred( + dpi, + 1193, + w->x + (widget->left + widget->right - 11) / 2, + w->y + widget->top, + 0, + (void*)0x013CE952 + ); + + // Status + widget = &window_ride_main_widgets[WIDX_STATUS]; + gfx_draw_string_centred_clipped( + dpi, + window_ride_get_status(w, (void*)0x013CE952), + (void*)0x013CE952, + 0, + w->x + (widget->left + widget->right) / 2, + w->y + widget->top - 1, + widget->right - widget->left + ); +} + +#pragma endregion + +#pragma region Vehicle + +/** + * + * rct2: 0x006B272D + */ +static void window_ride_vehicle_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); + 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_get_register(w); + + window_set_resize(w, 316, 208, 316, 208); +} + +/** + * + * rct2: 0x006B2748 + */ +static void window_ride_vehicle_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) +{ + rct_widget *dropdownWidget = widget - 1; + rct_ride *ride; + rct_ride_type *rideEntry, *currentRideEntry; + rct_string_id stringId; + int i, minCars, maxCars, cars, numItems, quadIndex, bitIndex, rideEntryIndex, selectedIndex; + uint8 *rideEntryIndexPtr, *currentRideEntryIndex; + + ride = GET_RIDE(w->number); + rideEntry = ride_get_entry(ride); + + switch (widgetIndex) { + case WIDX_VEHICLE_TYPE_DROPDOWN: + rideEntryIndexPtr = get_ride_entry_indices_for_ride_type(ride->type); + currentRideEntryIndex; + + selectedIndex = -1; + numItems = 0; + for (currentRideEntryIndex = rideEntryIndexPtr; *currentRideEntryIndex != 0xFF; currentRideEntryIndex++) { + rideEntryIndex = *currentRideEntryIndex; + currentRideEntry = GET_RIDE_ENTRY(rideEntryIndex); + if (currentRideEntry->var_008 & 0x3000) + continue; + + quadIndex = rideEntryIndex >> 5; + bitIndex = rideEntryIndex & 0x1F; + if (!(RCT2_ADDRESS(0x01357424, uint32)[quadIndex] & (1 << bitIndex))) + continue; + + if (ride->subtype == rideEntryIndex) + selectedIndex = numItems; + + gDropdownItemsFormat[numItems] = 1142; + 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], + 0x80, + numItems, + widget->right - dropdownWidget->left + ); + + gDropdownItemsChecked = (1 << selectedIndex); + break; + case WIDX_VEHICLE_TRAINS_DROPDOWN: + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0x80, + ride->var_0CC, + widget->right - dropdownWidget->left + ); + + stringId = RideNameConvention[ride->type].vehicle_name + 4; + for (i = 0; i < 32; i++) { + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = ((i + 1) << 16) | (i == 0 ? stringId : stringId + 1); + } + + gDropdownItemsChecked = (1 << (ride->num_vehicles - 1)); + break; + case WIDX_VEHICLE_CARS_PER_TRAIN_DROPDOWN: + minCars = (ride->var_0CD >> 4); + maxCars = (ride->var_0CD & 0x0F); + + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0x80, + maxCars - minCars + 1, + widget->right - dropdownWidget->left + ); + + for (i = 0; i < 12; i++) { + cars = minCars + i; + + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = 1024; + if (cars - rideEntry->var_012 > 1) + gDropdownItemsArgs[i]++; + gDropdownItemsArgs[i] |= (cars - rideEntry->var_012) << 16; + } + + gDropdownItemsChecked = (1 << (ride->num_cars_per_train - minCars)); + break; + } +} + +/** + * + * rct2: 0x006B2767 + */ +static void window_ride_vehicle_dropdown() +{ + rct_window *w; + short widgetIndex, dropdownIndex; + rct_ride *ride; + rct_ride_type *rideEntry; + + window_dropdown_get_registers(w, widgetIndex, dropdownIndex); + + if (dropdownIndex == -1) + return; + + ride = GET_RIDE(w->number); + rideEntry = ride_get_entry(ride); + + switch (widgetIndex) { + case WIDX_VEHICLE_TYPE_DROPDOWN: + dropdownIndex = (gDropdownItemsArgs[dropdownIndex] >> 16) & 0xFFFF; + + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, rct_string_id) = 1018; + game_do_command(0, (2 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_9, 0, 0); + break; + case WIDX_VEHICLE_TRAINS_DROPDOWN: + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, rct_string_id) = 1020; + game_do_command(0, (0 << 8) | 1, 0, ((dropdownIndex + 1) << 8) | w->number, GAME_COMMAND_9, 0, 0); + break; + case WIDX_VEHICLE_CARS_PER_TRAIN_DROPDOWN: + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, rct_string_id) = 1019; + game_do_command(0, (1 << 8) | 1, 0, ((rideEntry->var_00F + dropdownIndex) << 8) | w->number, GAME_COMMAND_9, 0, 0); + break; + } +} + +/** + * + * rct2: 0x006B2AA1 + */ +static void window_ride_vehicle_update(rct_window *w) +{ + w->frame_no++; + RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0); + widget_invalidate(WC_RIDE, w->number, WIDX_TAB_2); +} + +/** + * + * rct2: 0x006B222C + */ +static void window_ride_vehicle_invalidate() +{ + rct_window *w; + rct_widget *widgets; + rct_ride *ride; + rct_ride_type *rideEntry; + rct_string_id stringId; + int carsPerTrain; + + window_get_register(w); + + 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 = ride_get_entry(ride); + + RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; + RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + + // Widget setup + carsPerTrain = ride->num_cars_per_train - rideEntry->var_012; + + // Vehicle type + window_ride_vehicle_widgets[WIDX_VEHICLE_TYPE].image = rideEntry->name; + if (var_496(w) <= 1 && (w->enabled_widgets & (1 << WIDX_TAB_10))) { + 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->var_011 > 1) { + window_ride_vehicle_widgets[WIDX_VEHICLE_TRAINS].type = WWT_DROPDOWN; + window_ride_vehicle_widgets[WIDX_VEHICLE_TRAINS_DROPDOWN].type = WWT_DROPDOWN_BUTTON; + } else { + window_ride_vehicle_widgets[WIDX_VEHICLE_TRAINS].type = WWT_EMPTY; + window_ride_vehicle_widgets[WIDX_VEHICLE_TRAINS_DROPDOWN].type = WWT_EMPTY; + } + + // Cars per train + if (rideEntry->var_012 + 1 < rideEntry->var_010) { + window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN].image = carsPerTrain > 1 ? 1023 : 1022; + window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN].type = WWT_DROPDOWN; + window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN_DROPDOWN].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_DROPDOWN].type = WWT_EMPTY; + } + + RCT2_GLOBAL(0x013CE952 + 6, uint16) = carsPerTrain; + stringId = RideNameConvention[ride->type].vehicle_name + 4; + if (ride->num_vehicles > 1) + stringId++; + RCT2_GLOBAL(0x013CE952 + 8, uint16) = stringId; + RCT2_GLOBAL(0x013CE952 + 10, uint16) = ride->num_vehicles; + + window_ride_anchor_border_widgets(w); + window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); +} + +/** + * + * rct2: 0x006B23DC + */ +static void window_ride_vehicle_paint() +{ + rct_window *w; + rct_drawpixelinfo *dpi; + rct_ride *ride; + rct_ride_type *rideEntry; + rct_string_id stringId; + int x, y; + sint16 factor; + + window_paint_get_registers(w, dpi); + + window_draw_widgets(w, dpi); + window_ride_draw_tab_images(dpi, w); + + ride = GET_RIDE(w->number); + rideEntry = ride_get_entry(ride); + + x = w->x + 8; + y = w->y + 64; + + // Description + y += gfx_draw_string_left_wrapped(dpi, &rideEntry->description, x, y, 300, 1191, 0); + y += 5; + + // Capacity + stringId = rideEntry->description + 1; + gfx_draw_string_left(dpi, 3142, &stringId, 0, x, y); + y += 15; + + if (!(rideEntry->var_008 & 0x2000) && var_496(w) > 1) { + // Excitement Factor + factor = rideEntry->excitement_multipler; + gfx_draw_string_left(dpi, 3125, &factor, 0, x, y); + y += 10; + + // Intensity Factor + factor = rideEntry->intensity_multipler; + gfx_draw_string_left(dpi, 3126, &factor, 0, x, y); + y += 10; + + // Nausea Factor + factor = rideEntry->nausea_multipler; + gfx_draw_string_left(dpi, 3127, &factor, 0, x, y); + y += 10; + } +} + +typedef struct { + short x; + short y; + int sprite_index; + int 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; + rct_ride *ride; + rct_ride_type *rideEntry; + rct_widget *widget; + int x, y, startX, startY, i, j, vehicleColourIndex, spriteIndex, ebp; + rct_vehichle_paintinfo *nextSpriteToDraw, *current, tmp; + vehicle_colour vehicleColour; + + window_paint_get_registers(w, dpi); + + ride = GET_RIDE(w->number); + rideEntry = ride_get_entry(ride); + + // Background + gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width, dpi->y + dpi->height, 12); + + RCT2_CALLPROC_X(0x006DE4CD, (ride->num_cars_per_train << 8) | ride->subtype, 0, 0, 0, 0, 0, 0); + + widget = &window_ride_vehicle_widgets[WIDX_VEHICLE_TRAINS_PREVIEW]; + startX = max(2, ((widget->right - widget->left) - ((ride->num_vehicles - 1) * 36)) / 2 - 25); + startY = widget->bottom - widget->top - 4; + + ebp = (int)rideEntry + (RCT2_ADDRESS(0x00F64E38, uint8)[0] * 101); + startY += RCT2_GLOBAL(ebp + 0x24, sint8); + + // For each train + for (i = 0; i < ride->num_vehicles; i++) { + nextSpriteToDraw = _sprites_to_draw; + x = startX; + y = startY; + + // For each car in train + for (j = 0; j < ride->num_cars_per_train; j++) { + int ebp = (int)rideEntry + (RCT2_ADDRESS(0x00F64E38, uint8)[j] * 101); + x += RCT2_GLOBAL(ebp + 0x1E, uint32) / 17432; + y -= (RCT2_GLOBAL(ebp + 0x1E, uint32) / 2) / 17432; + + // Get colour of vehicle + 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; + } + vehicleColour = ride_get_vehicle_colour(ride, vehicleColourIndex); + + spriteIndex = 16; + if (RCT2_GLOBAL(ebp + 0x2C, uint16) & 0x800) + spriteIndex /= 2; + + spriteIndex &= RCT2_GLOBAL(ebp + 0x1A, uint16); + spriteIndex *= RCT2_GLOBAL(ebp + 0x30, uint16); + spriteIndex += RCT2_GLOBAL(ebp + 0x32, uint32); + 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 += RCT2_GLOBAL(ebp + 0x1E, uint32) / 17432; + y -= (RCT2_GLOBAL(ebp + 0x1E, uint32) / 2) / 17432; + } + + if (ride->type == RIDE_TYPE_REVERSER_ROLLER_COASTER) { + tmp = *(nextSpriteToDraw - 1); + *(nextSpriteToDraw - 1) = *(nextSpriteToDraw - 2); + *(nextSpriteToDraw - 2) = tmp; + } + + 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(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; + rct_widget *dropdownWidget; + rct_ride *ride; + const uint8 *availableModes, *mode; + int i, numAvailableModes; + + dropdownWidget = widget - 1; + ride = GET_RIDE(w->number); + rideEntry = ride_get_entry(ride); + + // 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 + */ +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); + 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, 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; + } +} + +/** + * + * rct2: 0x006B1715 + */ +static void window_ride_operating_resize() +{ + rct_window *w; + + window_get_register(w); + + window_set_resize(w, 316, 186, 316, 186); +} + +/** + * + * rct2: 0x006B10F4 + */ +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; + } +} + +/** + * + * rct2: 0x006B1165 + */ +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; + } +} + +/** + * + * rct2: 0x006B178E + */ +static void window_ride_operating_update(rct_window *w) +{ + rct_ride *ride; + + w->frame_no++; + RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0); + widget_invalidate(WC_RIDE, w->number, WIDX_TAB_3); + + ride = GET_RIDE(w->number); + if (ride->var_14D & 10) { + ride->var_14D &= ~10; + window_invalidate(w); + } +} + +/** + * + * rct2: 0x006B0B30 + */ +static void window_ride_operating_invalidate() +{ + rct_window *w; + rct_widget *widgets; + rct_ride *ride; + rct_ride_type *rideEntry; + rct_string_id format, caption, tooltip; + + window_get_register(w); + + 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 = ride_get_entry(ride); + + RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; + RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + + // Widget setup + w->pressed_widgets &= ~0x44700000; + + // Lift hill speed + if ((rideEntry->var_1B6 & RCT2_ADDRESS(0x01357444, uint32)[ride->type]) & 8) { + 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; + RCT2_GLOBAL(0x013CE966, 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; + RCT2_GLOBAL(0x013CE968, 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 ( + (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x10) && + 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].image = RideNameConvention[ride->type].vehicle_name == 1236 ? + 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 (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x20) { + 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].image = STR_RIDE_MODE_START + ride->mode; + + // Waiting + window_ride_operating_widgets[WIDX_LOAD].image = STR_QUARTER_LOAD + (ride->depart_flags & RIDE_DEPART_WAIT_FOR_LOAD_MASK); + if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x4000) { + 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; + + RCT2_GLOBAL(0x013CE952 + 10, uint16) = 1217; + RCT2_GLOBAL(0x013CE95E, uint16) = ride->min_waiting_time; + RCT2_GLOBAL(0x013CE960, uint16) = 1217; + RCT2_GLOBAL(0x013CE962, 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 + RCT2_GLOBAL(0x013CE964, uint16) = ride->var_0D0; + switch (ride->mode) { + case RIDE_MODE_POWERED_LAUNCH: + case RIDE_MODE_POWERED_LAUNCH_35: + case RIDE_MODE_UPWARD_LAUNCH: + case RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED: + RCT2_GLOBAL(0x013CE964, uint16) = (ride->var_0D0 * 9) / 4; + format = 1331; + caption = STR_LAUNCH_SPEED; + tooltip = STR_LAUNCH_SPEED_TIP; + case RIDE_MODE_STATION_TO_STATION: + RCT2_GLOBAL(0x013CE964, uint16) = (ride->var_0D0 * 9) / 4; + caption = STR_SPEED; + tooltip = STR_SPEED_TIP; + break; + case RIDE_MODE_RACE: + RCT2_GLOBAL(0x013CE964, uint16) = ride->var_0D0; + format = 1736; + caption = STR_NUMBER_OF_LAPS; + tooltip = STR_NUMBER_OF_LAPS_TIP; + break; + case RIDE_MODE_BUMPERCAR: + format = 1749; + caption = STR_TIME_LIMIT; + tooltip = STR_TIME_LIMIT_TIP; + break; + case RIDE_MODE_SWING: + format = 1771; + 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 = 1871; + caption = STR_NUMBER_OF_ROTATIONS; + tooltip = STR_NUMBER_OF_ROTATIONS_TIP; + break; + default: + format = 1736; + caption = STR_MAX_PEOPLE_ON_RIDE; + tooltip = STR_MAX_PEOPLE_ON_RIDE_TIP; + if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x2000)) + format = 0; + break; + } + + if (format != 0) { + if (ride->type == RIDE_TYPE_TWIST) + RCT2_GLOBAL(0x013CE964, uint16) *= 3; + + window_ride_operating_widgets[WIDX_MODE_TWEAK_LABEL].type = WWT_24; + window_ride_operating_widgets[WIDX_MODE_TWEAK_LABEL].image = 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].image = 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_paint_get_registers(w, dpi); + + 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], + 0x20 + ); + + // 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, 0, w->x + 21, ride->mode == 36 ? w->y + 76 : w->y + 61); + } +} + +#pragma endregion + +#pragma region Maintenance + +/** + * + * rct2: 0x006B1AE4 + */ +static void window_ride_locate_mechanic(rct_window *w) +{ + rct_peep *peep; + rct_ride *ride = GET_RIDE(w->number); + + peep = ride_get_assigned_mechanic(ride); + if (peep != NULL) { + window_staff_peep_open(peep); + } else { + // Presumebly looks for the closest mechanic + RCT2_CALLPROC_X(0x006B1B3E, 0, w->number * 0x260, 0, 0, (int)w, 0, 0); + } +} + +/** + * + * rct2: 0x006B7D08 + */ +static void window_ride_maintenance_draw_bar(rct_window *w, rct_drawpixelinfo *dpi, int x, int y, int value, int unk) +{ + gfx_fill_rect_inset(dpi, x, y, x + 149, y + 8, w->colours[1], 0x30); + if (unk & (1 << 31)) { + unk &= ~(1 << 31); + if (RCT2_GLOBAL(0x009DEA6E, uint8) == 0 && (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 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 + 8, unk, 0); + } +} + +/** + * + * rct2: 0x006B1AAD + */ +static void window_ride_maintenance_mouseup() +{ + short widgetIndex; + rct_window *w; + + window_widget_get_registers(w, 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_get_register(w); + + window_set_resize(w, 316, 135, 316, 135); +} + +/** + * + * rct2: 0x006B1ACE + */ +static void window_ride_maintenance_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) +{ + rct_widget *dropdownWidget; + int i; + + if (widgetIndex != WIDX_INSPECTION_INTERVAL_DROPDOWN) + return; + + dropdownWidget = widget - 1; + rct_ride *ride = GET_RIDE(w->number); + + for (i = 0; i < 7; i++) { + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = STR_EVERY_10_MINUTES + i; + } + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0, + 7, + widget->right - dropdownWidget->left + ); + + gDropdownItemsChecked = (1 << ride->inspection_interval); +} + +/** + * + * rct2: 0x006B1AD9 + */ +static void window_ride_maintenance_dropdown() +{ + rct_window *w; + rct_ride *ride; + short widgetIndex, dropdownIndex; + + window_dropdown_get_registers(w, widgetIndex, dropdownIndex); + + if (widgetIndex != WIDX_INSPECTION_INTERVAL_DROPDOWN || dropdownIndex == -1) + return; + + ride = GET_RIDE(w->number); + + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_CHANGE_OPERATING_MODE; + game_do_command(0, (dropdownIndex << 8) | 1, 0, (5 << 8) | w->number, GAME_COMMAND_11, 0, 0); +} + +/** + * + * rct2: 0x006B1D37 + */ +static void window_ride_maintenance_update(rct_window *w) +{ + rct_ride *ride; + + w->frame_no++; + RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0); + widget_invalidate(WC_RIDE, w->number, WIDX_TAB_4); + + ride = GET_RIDE(w->number); + if (ride->var_14D & 20) { + ride->var_14D &= ~20; + window_invalidate(w); + } +} + +/** + * + * rct2: 0x006B17C8 + */ +static void window_ride_maintenance_invalidate() +{ + rct_window *w; + rct_widget *widgets; + + window_get_register(w); + + 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); + RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; + RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + + window_ride_maintenance_widgets[WIDX_INSPECTION_INTERVAL].image = STR_EVERY_10_MINUTES + ride->inspection_interval; + + window_ride_anchor_border_widgets(w); + window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); +} + +/** + * + * rct2: 0x006B1877 + */ +static void window_ride_maintenance_paint() +{ + rct_window *w; + rct_drawpixelinfo *dpi; + rct_ride *ride; + rct_widget *widget; + rct_peep *mechanicSprite; + int x, y; + uint16 reliability, downTime, lastInspection; + rct_string_id stringId, breakdownMessage; + + window_paint_get_registers(w, dpi); + + window_draw_widgets(w, dpi); + window_ride_draw_tab_images(dpi, w); + + ride = GET_RIDE(w->number); + + // Locate mechanic button image + widget = &window_ride_maintenance_widgets[WIDX_LOCATE_MECHANIC]; + x = w->x + widget->left; + y = w->y + widget->top; + gfx_draw_sprite(dpi, (RCT2_GLOBAL(RCT2_ADDRESS_MECHANIC_COLOUR, uint8) << 24) | 0xA0000000 | 5196, 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, 0, x, y); + + // Reliability + widget = &window_ride_maintenance_widgets[WIDX_PAGE_BACKGROUND]; + x = w->x + widget->left + 4; + y = w->y + widget->top + 4; + + reliability = ride->var_196 >> 8; + gfx_draw_string_left(dpi, STR_RELIABILITY_LABEL_1757, &reliability, 0, x, y); + window_ride_maintenance_draw_bar(w, dpi, x + 103, y, max(10, reliability), 14); + y += 11; + + // Down time + downTime = ride->var_199; + gfx_draw_string_left(dpi, STR_DOWN_TIME_LABEL_1889, &downTime, 0, x, y); + window_ride_maintenance_draw_bar(w, dpi, x + 103, y, downTime, 28); + y += 26; + + // Last inspection + lastInspection = ride->last_inspection; + stringId = lastInspection <= 240 ? + STR_TIME_SINCE_LAST_INSPECTION_MINUTES : + STR_TIME_SINCE_LAST_INSPECTION_MORE_THAN_4_HOURS; + gfx_draw_string_left(dpi, stringId, &lastInspection, 0, 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; + breakdownMessage = STR_SAFETY_CUT_OUT + ride->breakdown_reason; + gfx_draw_string_left(dpi, stringId, &breakdownMessage, 0, x, y); + y += 10; + + // Mechanic status + if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) { + switch (ride->mechanic_status) { + case RIDE_MECHANIC_STATUS_CALLING: + stringId = STR_CALLING_MECHANIC; + break; + case RIDE_MECHANIC_STATUS_HEADING: + stringId = STR_MEHCANIC_IS_HEADING_FOR_THE_RIDE; + break; + case RIDE_MECHANIC_STATUS_FIXING: + case 4: + stringId = STR_MEHCANIC_IS_FIXING_THE_RIDE; + break; + default: + stringId = 0; + break; + } + + if (stringId != 0) { + if (stringId == STR_CALLING_MECHANIC) { + gfx_draw_string_left_wrapped(dpi, NULL, x + 4, y, 280, stringId, 0); + } else { + mechanicSprite = &(g_sprite_list[ride->mechanic].peep); + if (peep_is_mechanic(mechanicSprite)) { + RCT2_GLOBAL(0x013CE952 + 0, uint16) = mechanicSprite->name_string_idx; + RCT2_GLOBAL(0x013CE952 + 2, uint32) = mechanicSprite->id; + gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x + 4, y, 280, stringId, 0); + } + } + } + } +} + +#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_LOG_CABIN, + RIDE_ENTRANCE_STYLE_CLASSICAL_ROMAN, + RIDE_ENTRANCE_STYLE_ABSTRACT, + RIDE_ENTRANCE_STYLE_SNOW_ICE, + RIDE_ENTRANCE_STYLE_PAGODA, + RIDE_ENTRANCE_STYLE_SPACE +}; + +static uint32 window_ride_get_colour_button_image(int colour) +{ + return 0x60000000 | (colour << 19) | 5059; +} + +static int window_ride_has_track_colour(rct_ride *ride, int trackColour) +{ + uint16 unk_1 = RCT2_GLOBAL(0x00993E20 + (ride->entrance_style * 8), uint16); + uint32 unk_2 = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32); + + switch (trackColour) { + case 0: return ((unk_1 & 1) && !(unk_2 & 0x20000)) || (unk_2 & 1); + case 1: return ((unk_1 & 2) && !(unk_2 & 0x20000)) || (unk_2 & 2); + case 2: return unk_2 & 4; + default: return 0; + } +} + +static void window_ride_set_track_colour_scheme(rct_window *w, int x, int y) +{ + rct_map_element *mapElement; + uint8 newColourScheme; + + newColourScheme = (uint8)(*((uint16*)&w->var_494)); + + // Get map coordinates from point + int eax, ebx, ecx, edx, esi, edi, ebp; + eax = x; + ebx = y; + edx = -5; + RCT2_CALLFUNC_X(0x00685ADC, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + x = eax & 0xFFFF; + y = ecx & 0xFFFF; + mapElement = (rct_map_element*)edx; + + if ((ebx & 0xFF) != 3) + return; + if (mapElement->properties.track.ride_index != w->number) + return; + if ((mapElement->properties.track.colour & 3) == newColourScheme) + return; + + RCT2_CALLPROC_X( + 0x006C683D, + x, + ((mapElement->type & 3) << 8) | mapElement->properties.track.type, + y, + mapElement->base_height << 3, + newColourScheme, + 0, + 4 + ); +} + +/** + * + * rct2: 0x006B04FA + */ +static void window_ride_colour_close() +{ + rct_window *w; + + window_get_register(w); + + if (!(RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3))) + return; + + if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != w->classification) + return; + + if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) != w->number) + return; + + tool_cancel(); +} + +/** + * + * rct2: 0x006B02A1 + */ +static void window_ride_colour_mouseup() +{ + short widgetIndex; + rct_window *w; + + window_widget_get_registers(w, 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, 23); + break; + } +} + +/** + * + * rct2: 0x006B0AB6 + */ +static void window_ride_colour_resize() +{ + rct_window *w; + + window_get_register(w); + + window_set_resize(w, 316, 207, 316, 207); +} + +/** + * + * rct2: 0x006B02C6 + */ +static void window_ride_colour_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) +{ + rct_ride *ride; + uint16 colourSchemeIndex; + vehicle_colour vehicleColour; + rct_widget *dropdownWidget; + rct_ride_type *rideEntry; + int i, numItems; + rct_string_id stringId; + + ride = GET_RIDE(w->number); + rideEntry = ride_get_entry(ride); + colourSchemeIndex = *((uint16*)&w->var_494); + dropdownWidget = widget - 1; + + switch (widgetIndex) { + case WIDX_TRACK_COLOUR_SCHEME_DROPDOWN: + for (i = 0; i < 4; i++) { + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = STR_MAIN_COLOUR_SCHEME + i; + } + + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0, + 4, + widget->right - dropdownWidget->left + ); + + gDropdownItemsChecked = 1 << colourSchemeIndex; + 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] = 1142; + gDropdownItemsArgs[i] = STR_BRICK_WALLS + i; + } + + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0, + 4, + widget->right - dropdownWidget->left + ); + + gDropdownItemsChecked = 1 << ride->track_colour_supports[colourSchemeIndex]; + break; + case WIDX_ENTRANCE_STYLE_DROPDOWN: + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0x80, + countof(window_ride_entrance_style_list), + widget->right - dropdownWidget->left + ); + + for (i = 0; i < countof(window_ride_entrance_style_list); i++) { + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = STR_PLAIN_ENTRANCE + window_ride_entrance_style_list[i]; + + if (ride->entrance_style == window_ride_entrance_style_list[i]) + gDropdownItemsChecked = 1 << i; + } + break; + case WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN: + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0, + rideEntry->var_010 > 1 ? 3 : 2, + widget->right - dropdownWidget->left + ); + + for (i = 0; i < 3; i++) { + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = (RideNameConvention[ride->type].vehicle_name << 16) | (STR_ALL_VEHICLES_IN_SAME_COLOURS + i); + } + gDropdownItemsChecked = 1 << (ride->colour_scheme_type & 3); + 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; + + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0x80, + numItems, + widget->right - dropdownWidget->left + ); + + stringId = (ride->colour_scheme_type & 3) == VEHICLE_COLOUR_SCHEME_PER_TRAIN ? 1135 : 1133; + for (i = 0; i < 32; i++) { + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = ((sint64)(i + 1) << 32) | ((RideNameConvention[ride->type].vehicle_name + 2) << 16) | stringId; + } + gDropdownItemsChecked = 1 << w->var_48C; + 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; + short widgetIndex, dropdownIndex; + + window_dropdown_get_registers(w, widgetIndex, dropdownIndex); + + if (dropdownIndex == -1) + return; + + switch (widgetIndex) { + case WIDX_TRACK_COLOUR_SCHEME_DROPDOWN: + *((uint16*)&w->var_494) = dropdownIndex; + window_invalidate(w); + break; + case WIDX_TRACK_MAIN_COLOUR: + game_do_command(0, (0 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 0); + break; + case WIDX_TRACK_ADDITIONAL_COLOUR: + game_do_command(0, (1 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 0); + break; + case WIDX_TRACK_SUPPORT_COLOUR: + game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 0); + break; + case WIDX_MAZE_STYLE_DROPDOWN: + game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 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_0, 0, 0); + break; + case WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN: + game_do_command(0, (5 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, 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_0, 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_0, 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_0, w->var_48C, 0); + break; + } +} + +/** + * + * rct2: 0x006B0A8F + */ +static void window_ride_colour_update(rct_window *w) +{ + w->frame_no++; + RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0); + widget_invalidate(WC_RIDE, w->number, WIDX_TAB_5); + widget_invalidate(WC_RIDE, w->number, WIDX_VEHICLE_PREVIEW); +} + +/** + * + * rct2: 0x006B04EC + */ +static void window_ride_colour_tooldown() +{ + rct_window *w; + short widgetIndex, x, y; + + window_tool_get_registers(w, widgetIndex, x, 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; + short widgetIndex, x, y; + + window_tool_get_registers(w, widgetIndex, x, 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_type *rideEntry; + rct_ride *ride; + track_colour trackColour; + vehicle_colour vehicleColour; + int vehicleColourSchemeType; + + window_get_register(w); + + 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 = ride_get_entry(ride); + + RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; + RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + + // Track colours + int colourScheme = *((uint16*)&w->var_494); + 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].image = STR_BRICK_WALLS + trackColour.supports; + } 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 (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x80000000) { + 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_COLORBTN; + 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_COLORBTN; + 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_COLORBTN; + 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 (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 7) + window_ride_colour_widgets[WIDX_TRACK_PREVIEW].type = WWT_SPINNER; + else + window_ride_colour_widgets[WIDX_TRACK_PREVIEW].type = WWT_EMPTY; + + // Entrance style + if (RCT2_GLOBAL(0x0097D4F2 + (ride->type * 8), uint16) & 0x20) { + 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].image = STR_PLAIN_ENTRANCE + ride->entrance_style; + } 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 ( + !(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x2000) && + (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x4000000) + ) { + 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_COLORBTN; + window_ride_colour_widgets[WIDX_VEHICLE_MAIN_COLOUR].image = window_ride_get_colour_button_image(vehicleColour.main); + + RCT2_CALLPROC_X(0x006DE4CD, (ride->num_cars_per_train << 8) | ride->subtype, 0, 0, 0, 0, 0, 0); + + uint8 *unk; + uint32 unk_eax = 0; + for (unk = (uint8*)0x00F64E38; *unk != 0xFF; unk++) { + unk_eax |= RCT2_GLOBAL((int)rideEntry + 0x2E + (*unk * 101), uint16); + unk_eax = ror32(unk_eax, 16); + unk_eax |= RCT2_GLOBAL((int)rideEntry + 0x2C + (*unk * 101), uint16); + unk_eax = ror32(unk_eax, 16); + } + + // Additional colours + if (unk_eax & 1) { + window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_1].type = WWT_COLORBTN; + window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_1].image = window_ride_get_colour_button_image(vehicleColour.additional_1); + if (unk_eax & 0x2000000) { + window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_2].type = WWT_COLORBTN; + 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 ( + !(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x10000) && + (ride->num_stations | 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; + + RCT2_GLOBAL(0x013CE952 + 6, uint16) = STR_ALL_VEHICLES_IN_SAME_COLOURS + vehicleColourSchemeType; + RCT2_GLOBAL(0x013CE952 + 8, uint16) = RideNameConvention[ride->type].vehicle_name; + RCT2_GLOBAL(0x013CE952 + 10, uint16) = RideNameConvention[ride->type].vehicle_name + 2; + RCT2_GLOBAL(0x013CE952 + 12, uint16) = w->var_48C + 1; + } else { + window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_SCHEME].type = WWT_EMPTY; + window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN].type = WWT_EMPTY; + } + + // 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].image = vehicleColourSchemeType == 1 ? 1134 : 1132; + } 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; + } + + RCT2_GLOBAL(0x013CE960, uint16) = STR_MAIN_COLOUR_SCHEME + 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, *clippedDpi; + rct_widget *widget; + rct_ride *ride; + rct_ride_type *rideEntry; + int x, y, spriteIndex, terniaryColour; + track_colour trackColour; + + window_paint_get_registers(w, dpi); + + ride = GET_RIDE(w->number); + rideEntry = ride_get_entry(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, 12); + + trackColour = ride_get_track_colour(ride, *((uint16*)&w->var_494)); + + // + if (rideEntry->shop_item == 0xFF) { + x = w->x + widget->left; + y = w->y + widget->top; + + // Track + if (ride->type == RIDE_TYPE_MAZE) { + spriteIndex = 21990 + trackColour.supports; + gfx_draw_sprite(dpi, spriteIndex, x, y, 0); + } else { + spriteIndex = 14222 + (ride->type * 2); + spriteIndex |= (trackColour.additional << 24) | (trackColour.main << 19); + spriteIndex |= 0xA0000000; + gfx_draw_sprite(dpi, spriteIndex, x, y, 0); + + // Supports + spriteIndex = 14222 + (ride->type * 2) + 1; + spriteIndex |= trackColour.supports << 19; + spriteIndex |= 0x20000000; + gfx_draw_sprite(dpi, spriteIndex, x, y, 0); + } + } else { + x = w->x + (widget->left + widget->right) / 2 - 8; + y = w->y + (widget->bottom + widget->top) / 2 - 6; + + uint8 shopItem = rideEntry->shop_item_secondary == 255 ? rideEntry->shop_item : rideEntry->shop_item_secondary; + spriteIndex = 5061 + shopItem; + spriteIndex |= ride->track_colour_main[trackColour.main] << 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) { + clippedDpi = clip_drawpixelinfo( + dpi, w->x + widget->left + 1, widget->right - widget->left, w->y + widget->top + 1, widget->bottom - widget->top + ); + if (clippedDpi != NULL) { + gfx_clear(clippedDpi, 0x0C0C0C0C); + + terniaryColour = 0; + if (RCT2_GLOBAL(0x00993E1C + (ride->entrance_style * 8), uint32) & 0x40000000) + terniaryColour = 0x40000000 | ((trackColour.main + 112) << 19); + + spriteIndex = (trackColour.additional << 24) | (trackColour.main << 19); + spriteIndex |= 0xA0000000; + spriteIndex += RCT2_GLOBAL(0x00993E7C + (ride->entrance_style * 8), uint32); + + // Back + gfx_draw_sprite(clippedDpi, spriteIndex, 34, 20, terniaryColour); + + // Front + gfx_draw_sprite(clippedDpi, spriteIndex + 4, 34, 20, terniaryColour); + + // ? + 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; + rct_ride *ride; + rct_ride_type *rideEntry; + rct_widget *vehiclePreviewWidget; + uint8 *unk; + int colour, x, y, spriteIndex; + vehicle_colour vehicleColour; + + window_paint_get_registers(w, dpi); + + ride = GET_RIDE(w->number); + rideEntry = ride_get_entry(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, dpi->y + dpi->height, 12); + + // ? + x = dpi->x + (vehiclePreviewWidget->right - vehiclePreviewWidget->left) / 2; + y = dpi->y + vehiclePreviewWidget->bottom - vehiclePreviewWidget->top - 15; + RCT2_CALLPROC_X(0x006DE4CD, (ride->num_cars_per_train << 8) | ride->subtype, (int)ride, x, y, (int)w, (int)dpi, 0); + + // ? + colour = (ride->colour_scheme_type & 3) == RIDE_COLOUR_SCHEME_DIFFERENT_PER_CAR ? + w->var_48C : rideEntry->var_013; + colour = RCT2_ADDRESS(0x00F64E38, uint8)[colour]; + unk = (uint8*)rideEntry + (colour * 101); + + y += RCT2_GLOBAL(unk + 0x24, sint8); + + // Draw the coloured spinning vehicle + spriteIndex = RCT2_GLOBAL(unk + 0x2C, uint8) & 0x800 ? w->frame_no / 4 : w->frame_no / 2; + spriteIndex &= RCT2_GLOBAL(unk + 0x1A, uint16); + spriteIndex *= RCT2_GLOBAL(unk + 0x30, uint16); + spriteIndex += RCT2_GLOBAL(unk + 0x32, uint32); + 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); + + int activateMusic = (ride->lifecycle_flags & RIDE_LIFECYCLE_MUSIC) ? 0 : 1; + + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_CHANGE_OPERATING_MODE; + game_do_command(0, (activateMusic << 8) | 1, 0, (6 << 8) | w->number, GAME_COMMAND_11, 0, 0); +} + +/** + * + * rct2: 0x006B1ED7 + */ +static void window_ride_music_mouseup() +{ + short widgetIndex; + rct_window *w; + + window_widget_get_registers(w, 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; + + window_get_register(w); + + w->flags |= WF_RESIZABLE; + window_set_resize(w, 316, 81, 316, 81); +} + +/** + * + * rct2: 0x006B1EFC + */ +static void window_ride_music_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) +{ + rct_widget *dropdownWidget; + int i; + + if (widgetIndex != WIDX_MUSIC_DROPDOWN) + return; + + dropdownWidget = widget - 1; + rct_ride *ride = GET_RIDE(w->number); + + int 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 (RCT2_GLOBAL(0x009AF164, uint32) != 0) + window_ride_current_music_style_order[numItems++] = MUSIC_STYLE_CUSTOM_MUSIC_1; + if (RCT2_GLOBAL(0x009AF16E, uint32) != 0) + window_ride_current_music_style_order[numItems++] = MUSIC_STYLE_CUSTOM_MUSIC_2; + } + + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0, + numItems, + widget->right - dropdownWidget->left + ); + + for (i = 0; i < numItems; i++) { + gDropdownItemsFormat[i] = 1142; + if (window_ride_current_music_style_order[i] == ride->music) + gDropdownItemsChecked = (1 << i); + gDropdownItemsArgs[i] = STR_MUSIC_STYLE_START + window_ride_current_music_style_order[i]; + } +} + +/** + * + * rct2: 0x006B1F03 + */ +static void window_ride_music_dropdown() +{ + rct_window *w; + rct_ride *ride; + uint8 musicStyle; + short widgetIndex, dropdownIndex; + + window_dropdown_get_registers(w, widgetIndex, dropdownIndex); + + if (widgetIndex != WIDX_MUSIC_DROPDOWN || dropdownIndex == -1) + return; + + ride = GET_RIDE(w->number); + musicStyle = window_ride_current_music_style_order[dropdownIndex]; + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_CHANGE_OPERATING_MODE; + game_do_command(0, (musicStyle << 8) | 1, 0, (7 << 8) | w->number, GAME_COMMAND_11, 0, 0); +} + +/** + * + * rct2: 0x006B2198 + */ +static void window_ride_music_update(rct_window *w) +{ + w->frame_no++; + RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0); + widget_invalidate(WC_RIDE, w->number, WIDX_TAB_6); +} + +/** + * + * rct2: 0x006B1DEA + */ +static void window_ride_music_invalidate() +{ + rct_window *w; + rct_widget *widgets; + int isMusicActivated; + + window_get_register(w); + + 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); + RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; + RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + + // Set selected music + window_ride_music_widgets[WIDX_MUSIC].image = STR_MUSIC_STYLE_START + 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_paint_get_registers(w, dpi); + + window_draw_widgets(w, dpi); + window_ride_draw_tab_images(dpi, w); +} + +#pragma endregion + +#pragma region Measurements + +/** + * + * rct2: 0x006D3026 + */ +static void window_ride_measurements_design_reset() +{ + RCT2_CALLPROC_EBPSAFE(0x006D3026); +} + +/** + * + * rct2: 0x006D303D + */ +static void window_ride_measurements_design_select_nearby_scenery() +{ + RCT2_CALLPROC_EBPSAFE(0x006D303D); +} + +/** + * + * rct2: 0x006AD4CD + */ +static void window_ride_measurements_design_save(rct_window *w) +{ + RCT2_CALLPROC_X(0x006D2804, 1, 0, 0, 0, (int)w, 0, 0); +} + +/** + * + * rct2: 0x006AD4DA + */ +static void window_ride_measurements_design_cancel() +{ + if (RCT2_GLOBAL(0x009DEA6F, uint8) & 1) + RCT2_CALLPROC_X(0x006D2804, 0, 0, 0, 0, 0, 0, 0); +} + +/** + * + * rct2: 0x006AD4DA + */ +static void window_ride_measurements_close() +{ + window_ride_measurements_design_cancel(); +} + +/** + * + * rct2: 0x006AD478 + */ +static void window_ride_measurements_mouseup() +{ + short widgetIndex; + rct_window *w; + + window_widget_get_registers(w, 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_get_register(w); + + window_set_resize(w, 316, 202, 316, 202); +} + +/** + * + * rct2: 0x006AD4AB + */ +static void window_ride_measurements_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) +{ + if (widgetIndex != WIDX_SAVE_TRACK_DESIGN) + return; + + rct_ride *ride = GET_RIDE(w->number); + + 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 + ); + RCT2_GLOBAL(0x009DEBA2, sint16) = 0; + if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) + RCT2_GLOBAL(0x009DED34, uint32) |= 2; +} + +/** + * + * rct2: 0x006AD4B2 + */ +static void window_ride_measurements_dropdown() +{ + rct_window *w; + short widgetIndex, dropdownIndex; + + window_dropdown_get_registers(w, widgetIndex, dropdownIndex); + + if (widgetIndex != WIDX_SAVE_TRACK_DESIGN) + return; + + if (dropdownIndex == -1) + dropdownIndex = RCT2_GLOBAL(0x009DEBA2, sint16); + + if (dropdownIndex == 0) + RCT2_CALLPROC_X(0x006D264D, 0, 0, 0, 0, (int)w, 0, 0); + else + RCT2_CALLPROC_X(0x006D27A3, 0, 0, 0, 0, (int)w, 0, 0); +} + +/** + * + * rct2: 0x006AD5DD + */ +static void window_ride_measurements_update(rct_window *w) +{ + w->frame_no++; + RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0); + widget_invalidate(WC_RIDE, w->number, WIDX_TAB_7); +} + +/** + * + * rct2: 0x006AD4EB + */ +static void window_ride_measurements_tooldown() +{ + rct_window *w; + + window_get_register(w); + + RCT2_CALLPROC_X(0x006D2AE7, 0, 0, 0, 0, (int)w, 0, 0); +} + +/** + * + * rct2: 0x006AD4DA + */ +static void window_ride_measurements_toolabort(rct_window *w) +{ + window_ride_measurements_design_cancel(); +} + +/** + * + * rct2: 0x006ACDBC + */ +static void window_ride_measurements_invalidate() +{ + rct_window *w; + rct_widget *widgets; + + window_get_register(w); + + 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); + RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; + RCT2_GLOBAL(0x013CE952 + 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 ((RCT2_GLOBAL(0x009DEA6F, uint8) & 1) && RCT2_GLOBAL(0x00F64DE8, uint8) == 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->lifecycle_flags & RIDE_LIFECYCLE_19)) { + if (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x10000000) { + 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 != -1) { + 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; + rct_widget *widget; + rct_ride *ride; + rct_string_id stringId; + int x, y, i, numTimes, numLengths; + sint16 holes, maxSpeed, averageSpeed, drops, highestDropHeight, inversions, time; + sint32 maxPositiveVerticalGs, maxNegativeVerticalGs, maxLateralGs, totalAirTime, length; + + window_paint_get_registers(w, dpi); + + window_draw_widgets(w, dpi); + window_ride_draw_tab_images(dpi, w); + + if (window_ride_measurements_widgets[WIDX_SAVE_DESIGN].type == WWT_DROPDOWN_BUTTON) { + widget = &window_ride_measurements_widgets[WIDX_PAGE_BACKGROUND]; + + x = w->x + (widget->right - widget->left) / 2; + 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, 0); + + 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], 0x20); + } else { + ride = GET_RIDE(w->number); + + if (ride->lifecycle_flags & RIDE_LIFECYCLE_19) + gfx_draw_sprite(dpi, 23225, w->x + w->width - 53, w->y + w->height - 73, 0); + + x = w->x + window_ride_measurements_widgets[WIDX_PAGE_BACKGROUND].left + 4; + y = w->y + window_ride_measurements_widgets[WIDX_PAGE_BACKGROUND].top + 4; + + if (ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED) { + // Excitement + RCT2_GLOBAL(0x013CE952 + 0, uint32) = ride->excitement; + RCT2_GLOBAL(0x013CE952 + 4, uint16) = STR_RATING_LOW + min(ride->excitement >> 8, 5); + stringId = ride->excitement == -1 ? STR_EXCITEMENT_RATING_NOT_YET_AVAILABLE : STR_EXCITEMENT_RATING; + gfx_draw_string_left(dpi, stringId, (void*)0x013CE952, 0, x, y); + y += 10; + + // Intensity + RCT2_GLOBAL(0x013CE952 + 0, uint32) = ride->intensity; + RCT2_GLOBAL(0x013CE952 + 4, uint16) = STR_RATING_LOW + min(ride->intensity >> 8, 5); + + stringId = STR_INTENSITY_RATING; + if (ride->excitement == -1) + 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, (void*)0x013CE952, 0, x, y); + y += 10; + + // Nausea + RCT2_GLOBAL(0x013CE952 + 0, uint32) = ride->nausea; + RCT2_GLOBAL(0x013CE952 + 4, uint16) = STR_RATING_LOW + min(ride->nausea >> 8, 5); + stringId = ride->excitement == -1 ? STR_NAUSEA_RATING_NOT_YET_AVAILABLE : STR_NAUSEA_RATING; + gfx_draw_string_left(dpi, stringId, (void*)0x013CE952, 0, x, y); + y += 20; + + // Horizontal rule + gfx_fill_rect_inset(dpi, x, y - 6, x + 303, y - 5, w->colours[1], 0x20); + + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_NO_RAW_STATS)) { + if (ride->type == RIDE_TYPE_MINI_GOLF) { + // Holes + holes = ride->inversions & 0x1F; + gfx_draw_string_left(dpi, STR_HOLES, &holes, 0, x, y); + y += 10; + } else { + // Max speed + maxSpeed = (ride->max_speed * 9) >> 18; + gfx_draw_string_left(dpi, STR_MAX_SPEED, &maxSpeed, 0, x, y); + y += 10; + + // Average speed + averageSpeed = (ride->average_speed * 9) >> 18; + gfx_draw_string_left(dpi, STR_AVERAGE_SPEED, &averageSpeed, 0, x, y); + y += 10; + + // Ride time + numTimes = 0; + for (i = 0; i < ride->num_stations; i++) { + time = ride->time[numTimes]; + if (time != 0) { + RCT2_GLOBAL(0x013CE952 + 0 + (numTimes * 4), uint16) = 1343; + RCT2_GLOBAL(0x013CE952 + 2 + (numTimes * 4), uint16) = time; + numTimes++; + } + } + if (numTimes == 0) { + RCT2_GLOBAL(0x013CE952 + 0, uint16) = 1343; + RCT2_GLOBAL(0x013CE952 + 2, uint16) = 0; + numTimes++; + } + RCT2_GLOBAL(0x013CE94E + (numTimes * 4), uint16) = 1342; + RCT2_GLOBAL(0x013CE952 + 0 + (numTimes * 4), uint16) = 0; + RCT2_GLOBAL(0x013CE952 + 2 + (numTimes * 4), uint16) = 0; + RCT2_GLOBAL(0x013CE952 + 4 + (numTimes * 4), uint16) = 0; + RCT2_GLOBAL(0x013CE952 + 6 + (numTimes * 4), uint16) = 0; + gfx_draw_string_left_clipped(dpi, STR_RIDE_TIME, (void*)0x013CE952, 0, x, y, 308); + y += 10; + } + + // Ride length + numLengths = 0; + for (i = 0; i < ride->num_stations; i++) { + length = ride->length[numLengths]; + if (length != 0) { + length >>= 16; + RCT2_GLOBAL(0x013CE952 + 0 + (numLengths * 4), uint16) = 1346; + RCT2_GLOBAL(0x013CE952 + 2 + (numLengths * 4), uint16) = (length & 0xFFFF); + numLengths++; + } + } + if (numLengths == 0) { + RCT2_GLOBAL(0x013CE952 + 0, uint16) = 1346; + RCT2_GLOBAL(0x013CE952 + 2, uint16) = 0; + numLengths++; + } + RCT2_GLOBAL(0x013CE94E + (numLengths * 4), uint16) = 1345; + RCT2_GLOBAL(0x013CE952 + 0 + (numLengths * 4), uint16) = 0; + RCT2_GLOBAL(0x013CE952 + 2 + (numLengths * 4), uint16) = 0; + RCT2_GLOBAL(0x013CE952 + 4 + (numLengths * 4), uint16) = 0; + RCT2_GLOBAL(0x013CE952 + 6 + (numLengths * 4), uint16) = 0; + gfx_draw_string_left_clipped(dpi, STR_RIDE_LENGTH, (void*)0x013CE952, 0, x, y, 308); + y += 10; + + if (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x80) { + // 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, 0, 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, 0, 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, 0, x, y); + y += 10; + + // Total 'air' time + totalAirTime = ride->total_air_time * 3; + gfx_draw_string_left(dpi, STR_TOTAL_AIR_TIME, &totalAirTime, 0, x, y); + y += 10; + } + + if (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x400) { + // Drops + drops = ride->drops & 0x3F; + gfx_draw_string_left(dpi, STR_DROPS, &drops, 0, x, y); + y += 10; + + // Highest drop height + highestDropHeight = (ride->highest_drop_height * 3) / 4; + gfx_draw_string_left(dpi, STR_HIGHEST_DROP_HEIGHT, &highestDropHeight, 0, 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, 0, x, y); + y += 10; + } + } + } + } else { + gfx_draw_string_left(dpi, STR_NO_TEST_RESULTS_YET, NULL, 0, x, y); + } + } +} + +#pragma endregion + +#pragma region Graphs + +enum { + GRAPH_VELOCITY, + GRAPH_ALTITUDE, + GRAPH_VERTICAL, + GRAPH_LATERAL +}; + +/** + * + * rct2: 0x006B66D9 + */ +rct_ride_measurement *ride_get_measurement(int rideIndex, rct_string_id *message) +{ + int eax, ebx, ecx, edx, esi, edi, ebp; + edx = rideIndex; + + RCT2_CALLFUNC_X(0x006B66D9, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + eax &= 0xFFFF; + + if ((eax & 0xFF) < 10) { + eax &= 0xFF; + return GET_RIDE_MEASUREMENT(eax); + } else { + if (message != NULL) + *message = eax; + return NULL; + } +} + +/** + * + * rct2: 0x006AE8A6 + */ +static void window_ride_set_graph(rct_window *w, int 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() +{ + short widgetIndex; + rct_window *w; + + window_widget_get_registers(w, 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_get_register(w); + + window_set_resize(w, 316, 180, 500, 450); +} + +/** + * + * rct2: 0x006AE878 + */ +static void window_ride_graphs_mousedown(int 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; + int x; + + w->frame_no++; + RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0); + widget_invalidate(WC_RIDE, w->number, WIDX_TAB_8); + RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0); + widget_invalidate(WC_RIDE, w->number, 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; + rct_ride_measurement *measurement; + int width, height; + + window_get_register(w); + + RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0); + + // Set minimum size + width = window_ride_graphs_widgets[WIDX_GRAPH].right - window_ride_graphs_widgets[WIDX_GRAPH].left - 2; + height = 0; + + // Get measurement size + measurement = ride_get_measurement(w->number, NULL); + if (measurement != NULL) + width = max(width, measurement->num_items); + + // Return size + #ifdef _MSC_VER + __asm mov ecx, width + #else + __asm__ ( "mov ecx, 0 " ); + #endif + + #ifdef _MSC_VER + __asm mov edx, height + #else + __asm__ ( "mov edx, %[height] " : [height] "+m" (height) ); + #endif +} + +/** + * + * rct2: 0x006AE953 + */ +static void window_ride_graphs_15() +{ + rct_window *w; + + window_get_register(w); + + w->list_information_type |= 0x8000; +} + +/** + * + * rct2: 0x006AEA05 + */ +static void window_ride_graphs_tooltip() +{ + rct_window *w; + short unused, widgetIndex, result; + rct_ride *ride; + rct_ride_measurement *measurement; + rct_string_id stringId; + + window_dropdown_get_registers(w, unused, widgetIndex); + + result = -1; + if (widgetIndex == WIDX_GRAPH) { + RCT2_GLOBAL(0x013CE952, uint16) = 3158; + measurement = ride_get_measurement(w->number, &stringId); + if (measurement != NULL && (measurement->var_01 & 1)) { + RCT2_GLOBAL(0x013CE952 + 4, uint16) = measurement->var_0A + 1; + ride = GET_RIDE(w->number); + RCT2_GLOBAL(0x013CE952 + 2, uint16) = RideNameConvention[ride->type].vehicle_name + 6; + result = 0; + } else { + result = stringId; + } + } + + #ifdef _MSC_VER + __asm mov ax, result + #else + __asm__ ( "mov ax, %[result] " : [result] "+m" (result) ); + #endif +} + +/** + * + * rct2: 0x006AE372 + */ +static void window_ride_graphs_invalidate() +{ + rct_window *w; + rct_widget *widgets; + rct_ride *ride; + int x, y; + + window_get_register(w); + + 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); + + RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; + RCT2_GLOBAL(0x013CE952 + 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 (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x80) { + 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_paint_get_registers(w, 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; + rct_ride_measurement *measurement; + rct_widget *widget; + int x, y, width, time, listType, colour, top, bottom, tmp; + rct_string_id stringId; + + window_paint_get_registers(w, dpi); + + gfx_clear(dpi, RCT2_GLOBAL(0x0141FC9D, uint8) * 0x01010101); + + widget = &window_ride_graphs_widgets[WIDX_GRAPH]; + listType = w->list_information_type & 0xFF; + measurement = ride_get_measurement(w->number, &stringId); + if (measurement == NULL) { + // No measurement message + x = (widget->right - widget->left) / 2; + y = (widget->bottom - widget->top) / 2 - 5; + width = widget->right - widget->left - 2; + gfx_draw_string_centred_wrapped(dpi, (void*)0x013CE952, x, y, width, stringId, 0); + return; + } + + // Vertical grid lines + time = 0; + for (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, RCT2_GLOBAL(0x0141FCA0, uint8)); + gfx_fill_rect(dpi, x + 16, dpi->y, x + 16, dpi->y + dpi->height - 1, RCT2_GLOBAL(0x0141FC9F, uint8)); + gfx_fill_rect(dpi, x + 32, dpi->y, x + 32, dpi->y + dpi->height - 1, RCT2_GLOBAL(0x0141FC9F, uint8)); + gfx_fill_rect(dpi, x + 48, dpi->y, x + 48, dpi->y + dpi->height - 1, RCT2_GLOBAL(0x0141FC9F, uint8)); + gfx_fill_rect(dpi, x + 64, dpi->y, x + 64, dpi->y + dpi->height - 1, RCT2_GLOBAL(0x0141FC9F, uint8)); + } + time += 5; + } + + // Horizontal grid lines + y = widget->bottom - widget->top - 13; + short yUnit = RCT2_GLOBAL(0x0098DD9A + (listType * 8), uint16); + short ax = RCT2_GLOBAL(0x0098DD9E + (listType * 8), uint16); + short yUnitInterval = RCT2_GLOBAL(0x0098DD9C + (listType * 8), uint16); + short yInterval = RCT2_GLOBAL(0x0098DD98 + (listType * 8), uint16); + + // Scale modifier + if (ax == 1420) { + short unk = RCT2_GLOBAL(0x01359208, uint16); + yUnit -= RCT2_GLOBAL(0x01359208, uint16); + unk *= 2; + yUnit -= unk; + } + + for (y = widget->bottom - widget->top - 13; y >= 8; y -= yInterval, yUnit += yUnitInterval) { + // Minor / major line + colour = yUnit == 0 ? + RCT2_GLOBAL(0x0141FCA0, uint8) : + RCT2_GLOBAL(0x0141FC9F, uint8); + + gfx_fill_rect(dpi, dpi->x, y, dpi->x + dpi->width - 1, y, colour); + + // Scale modifier + if (ax == 1420) + yUnit /= 2; + + gfx_draw_string_left(dpi, ax, &yUnit, 0, w->scrolls[0].h_left + 1, y - 4); + } + + // Time marks + x = 0; + time = 0; + for (x = 0; x < dpi->x + dpi->width; x += 80) { + if (x + 80 >= dpi->x) + gfx_draw_string_left(dpi, 1414, &time, 0, x + 2, 1); + time += 5; + } + + // Plot + x = dpi->x; + for (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; + } + + top = widget->bottom - widget->top - top - 13; + bottom = widget->bottom - widget->top - bottom - 13; + if (top > bottom) { + tmp = top; + top = bottom; + bottom = tmp; + } + gfx_fill_rect(dpi, x, top, x, bottom, x > measurement->current_item ? 17 : 21); + } +} + +#pragma endregion + +#pragma region Income + +/** + * + * rct2: 0x006ADEFD + */ +static void window_ride_income_toggle_primary_price(rct_window *w) +{ + RCT2_CALLPROC_X(0x006ADEFD, 0, 0, 0, 0, (int)w, 0, 0); +} + +/** + * + * rct2: 0x006AE06E + */ +static void window_ride_income_toggle_secondary_price(rct_window *w) +{ + RCT2_CALLPROC_X(0x006AE06E, 0, 0, 0, 0, (int)w, 0, 0); +} + +/** + * + * rct2: 0x006AE1E4 + */ +static void window_ride_income_increase_primary_price(rct_window *w) +{ + RCT2_CALLPROC_X(0x006AE1E4, 0, 0, 0, 0, (int)w, 0, 0); +} + +/** + * + * rct2: 0x006AE237 + */ +static void window_ride_income_decrease_primary_price(rct_window *w) +{ + RCT2_CALLPROC_X(0x006AE237, 0, 0, 0, 0, (int)w, 0, 0); +} + +/** + * + * rct2: 0x006AE269 + */ +static void window_ride_income_increase_secondary_price(rct_window *w) +{ + RCT2_CALLPROC_X(0x006AE269, 0, 0, 0, 0, (int)w, 0, 0); +} + +/** + * + * rct2: 0x006AE28D + */ +static void window_ride_income_decrease_secondary_price(rct_window *w) +{ + RCT2_CALLPROC_X(0x006AE28D, 0, 0, 0, 0, (int)w, 0, 0); +} + +/** + * + * rct2: 0x006ADEA9 + */ +static void window_ride_income_mouseup() +{ + short widgetIndex; + rct_window *w; + + window_widget_get_registers(w, 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_get_register(w); + + window_set_resize(w, 316, 177, 316, 177); +} + +/** + * + * rct2: 0x006ADED4 + */ +static void window_ride_income_mousedown(int 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++; + RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0); + widget_invalidate(WC_RIDE, w->number, WIDX_TAB_9); + + ride = GET_RIDE(w->number); + if (ride->var_14D & 2) { + ride->var_14D &= ~2; + window_invalidate(w); + } +} + +/** + * + * rct2: 0x006ADAA3 + */ +static void window_ride_income_invalidate() +{ + rct_window *w; + rct_widget *widgets; + rct_ride_type *rideEntry; + rct_string_id stringId; + int primaryItem, secondaryItem; + + window_get_register(w); + + 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); + RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; + RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + + rideEntry = ride_get_entry(ride); + + // Primary item + w->pressed_widgets &= ~(1 << WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK); + w->disabled_widgets &= ~(1 << WIDX_PRIMARY_PRICE); + if ( + !(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_FREE_ENTRY) && + rideEntry->shop_item == 255 && + ride->type != RIDE_TYPE_BATHROOM + ) { + w->disabled_widgets |= (1 << WIDX_PRIMARY_PRICE); + } + + window_ride_income_widgets[WIDX_PRIMARY_PRICE_LABEL].image = STR_RIDE_INCOME_ADMISSION_PRICE; + window_ride_income_widgets[WIDX_SECONDARY_PRICE_LABEL].image = STR_ON_RIDE_PHOTO_PRICE; + window_ride_income_widgets[WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK].type = WWT_EMPTY; + + window_ride_income_widgets[WIDX_PRIMARY_PRICE].image = 1429; + RCT2_GLOBAL(0x013CE952 + 6, money32) = ride->price; + if (ride->price == 0) + window_ride_income_widgets[WIDX_PRIMARY_PRICE].image = STR_FREE; + + primaryItem = 31; + if (ride->type != RIDE_TYPE_BATHROOM) { + if ((primaryItem = (sint8)rideEntry->shop_item) != -1) { + window_ride_income_widgets[WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK].type = WWT_CHECKBOX; + if (primaryItem < 32) { + if (RCT2_GLOBAL(0x01358838, uint32) & (1 << primaryItem)) + w->pressed_widgets |= (1 << WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK); + + if (primaryItem != 31) + window_ride_income_widgets[WIDX_PRIMARY_PRICE_LABEL].image = 1960 + primaryItem; + } else { + primaryItem -= 32; + if (RCT2_GLOBAL(0x0135934C, uint32) & (1 << primaryItem)) + w->pressed_widgets |= (1 << WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK); + + window_ride_income_widgets[WIDX_PRIMARY_PRICE_LABEL].image = 2100 + primaryItem; + } + } + } + + // Get secondary item + secondaryItem = RCT2_GLOBAL(0x0097D7CB + (ride->type * 4), uint8); + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO)) { + if ((secondaryItem = (sint8)rideEntry->shop_item_secondary) != -1) { + // Set secondary item label + stringId = 1960 + secondaryItem; + if (stringId >= 1992) + stringId += 108; + + window_ride_income_widgets[WIDX_SECONDARY_PRICE_LABEL].image = stringId; + } + } + + if (secondaryItem == -1) { + // 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 (secondaryItem < 32) { + if (RCT2_GLOBAL(0x01358838, uint32) & (1 << secondaryItem)) + w->pressed_widgets |= (1 << WIDX_SECONDARY_PRICE_SAME_THROUGHOUT_PARK); + } else { + secondaryItem -= 32; + if (RCT2_GLOBAL(0x0135884C, uint32) & (1 << 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].image = 1799; + RCT2_GLOBAL(0x013CE952 + 10, money32) = ride->price_secondary; + if (ride->price_secondary == 0) + window_ride_income_widgets[WIDX_SECONDARY_PRICE].image = 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_type *rideEntry; + rct_string_id stringId; + money32 profit, costPerHour; + int x, y, primaryItem, secondaryItem; + + window_paint_get_registers(w, dpi); + + window_draw_widgets(w, dpi); + window_ride_draw_tab_images(dpi, w); + + ride = GET_RIDE(w->number); + rideEntry = ride_get_entry(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 = (sint8)rideEntry->shop_item; + if (primaryItem != -1) { + profit = ride->price; + + stringId = STR_PROFIT_PER_ITEM_SOLD; + profit -= primaryItem < 32 ? + RCT2_GLOBAL(0x00982164 + (primaryItem * 8), uint16) : + RCT2_GLOBAL(0x00982144 + (primaryItem * 8), uint16); + if (profit < 0) { + profit *= -1; + stringId = STR_LOSS_PER_ITEM_SOLD; + } + + gfx_draw_string_left(dpi, stringId, &profit, 0, x, y); + } + y += 39; + + // Secondary item profit / loss per item sold + secondaryItem = RCT2_GLOBAL(0x0097D7CB + (ride->type * 4), uint8); + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO)) + secondaryItem = (sint8)rideEntry->shop_item_secondary; + + if (secondaryItem != -1) { + profit = ride->price_secondary; + + stringId = STR_PROFIT_PER_ITEM_SOLD; + profit -= primaryItem < 32 ? + RCT2_GLOBAL(0x00982164 + (primaryItem * 8), uint16) : + RCT2_GLOBAL(0x00982144 + (primaryItem * 8), uint16); + if (profit < 0) { + profit *= -1; + stringId = STR_LOSS_PER_ITEM_SOLD; + } + + gfx_draw_string_left(dpi, stringId, &profit, 0, 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, 0, x, y); + y += 10; + } + + // Running cost per hour + costPerHour = ride->upkeep_cost * 16; + stringId = ride->upkeep_cost == 0xFFFF ? STR_RUNNING_COST_UNKNOWN : STR_RUNNING_COST_PER_HOUR; + gfx_draw_string_left(dpi, stringId, &costPerHour, 0, x, y); + y += 10; + + // Profit per hour + if (ride->profit != MONEY32_UNDEFINED) { + gfx_draw_string_left(dpi, STR_PROFIT_PER_HOUR, &ride->profit, 0, x, y); + y += 10; + } + y += 5; + + // Total profit + gfx_draw_string_left(dpi, STR_TOTAL_PROFIT, &ride->total_profit, 0, x, y); +} + +#pragma endregion + +#pragma region Customer + +/** + * + * rct2: 0x006AD986 + */ +static void window_ride_customer_mouseup() +{ + short widgetIndex; + rct_window *w; + + window_widget_get_registers(w, 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: + RCT2_CALLPROC_X(0x006993BA, 2, w->number, 0, 0, 0, 0, 0); + break; + case WIDX_SHOW_GUESTS_ON_RIDE: + RCT2_CALLPROC_X(0x006993BA, 0, w->number, 0, 0, 0, 0, 0); + break; + case WIDX_SHOW_GUESTS_QUEUING: + RCT2_CALLPROC_X(0x006993BA, 1, w->number, 0, 0, 0, 0, 0); + break; + } +} + +/** + * + * rct2: 0x006ADA29 + */ +static void window_ride_customer_resize() +{ + rct_window *w; + + window_get_register(w); + + w->flags |= WF_RESIZABLE; + window_set_resize(w, 316, 139, 316, 139); +} + +/** + * + * 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; + + RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0); + widget_invalidate(WC_RIDE, w->number, WIDX_TAB_10); + + ride = GET_RIDE(w->number); + if (ride->var_14D & 1) { + ride->var_14D &= ~1; + window_invalidate(w); + } +} + +/** + * + * rct2: 0x006AD5F8 + */ +static void window_ride_customer_invalidate() +{ + rct_window *w; + rct_widget *widgets; + + window_get_register(w); + + 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); + RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; + RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + + if (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) * 0x20000) { + window_ride_customer_widgets[WIDX_SHOW_GUESTS_THOUGHTS].type = WWT_FLATBTN; + window_ride_customer_widgets[WIDX_SHOW_GUESTS_ON_RIDE].type = WWT_FLATBTN; + window_ride_customer_widgets[WIDX_SHOW_GUESTS_QUEUING].type = WWT_FLATBTN; + } else { + window_ride_customer_widgets[WIDX_SHOW_GUESTS_ON_RIDE].type = WWT_EMPTY; + window_ride_customer_widgets[WIDX_SHOW_GUESTS_QUEUING].type = WWT_EMPTY; + } + + 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; + int x, y; + uint8 shopItem; + sint16 popularity, satisfaction, queueTime, age; + sint32 customersPerHour; + rct_string_id stringId; + + window_paint_get_registers(w, dpi); + + 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 per hour + customersPerHour = ride->var_124 + ride->var_126 + ride->var_128 + ride->var_12A + ride->var_12C + + ride->var_12E + ride->age + ride->running_cost + ride->var_134 + ride->var_136; + customersPerHour *= 12; + gfx_draw_string_left(dpi, STR_CUSTOMERS_PER_HOUR, &customersPerHour, 0, x, y); + y += 10; + + // Popularity + popularity = ride->var_158 & 0xFF; + if (popularity == 255) { + stringId = STR_POPULARITY_UNKNOWN; + } else { + stringId = STR_POPULARITY_PERCENT; + popularity *= 4; + } + gfx_draw_string_left(dpi, stringId, &popularity, 0, x, y); + y += 10; + + // Satisfaction + satisfaction = ride->var_14A & 0xFF; + if (satisfaction == 255) { + stringId = STR_SATISFACTION_UNKNOWN; + } else { + stringId = STR_SATISFACTION_PERCENT; + satisfaction *= 5; + } + gfx_draw_string_left(dpi, stringId, &satisfaction, 0, x, y); + y += 10; + + // Queue time + 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, 0); + y += 5; + + // Primary shop items sold + shopItem = ride_get_entry(ride)->shop_item; + if (shopItem != 0xFF) { + stringId = 2016 + shopItem; + if (stringId >= 2048) + stringId += 96; + + RCT2_GLOBAL(0x013CE952 + 0, uint16) = stringId; + RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->var_1A4; + gfx_draw_string_left(dpi, STR_ITEMS_SOLD, (void*)0x013CE952, 0, x, y); + y += 10; + } + + // Secondary shop items sold / on-ride photos sold + shopItem = ride->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO ? + RCT2_GLOBAL(0x0097D7CB + (ride->type * 4), uint8) : + ride_get_entry(ride)->shop_item_secondary; + if (shopItem != 0xFF) { + stringId = 2016 + shopItem; + if (stringId >= 2048) + stringId += 96; + + RCT2_GLOBAL(0x013CE952 + 0, uint16) = stringId; + RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->var_1A4; + gfx_draw_string_left(dpi, STR_ITEMS_SOLD, (void*)0x013CE952, 0, x, y); + y += 10; + } + + // Total customers + gfx_draw_string_left(dpi, STR_TOTAL_CUSTOMERS, &ride->total_customers, 0, 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, 0, x, y); + y += 10; + } + y += 2; + + // Age + age = (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16) - ride->build_date) / 8; + stringId = age == 0 ? + STR_BUILT_THIS_YEAR : + age == 1 ? + STR_BUILT_LAST_YEAR : + STR_BUILT_YEARS_AGO; + gfx_draw_string_left(dpi, stringId, &age, 0, x, y); +} + +#pragma endregion \ No newline at end of file diff --git a/src/window_ride_list.c b/src/window_ride_list.c index 0298a93c9e..598955a548 100644 --- a/src/window_ride_list.c +++ b/src/window_ride_list.c @@ -432,52 +432,6 @@ static void window_ride_list_paint() window_ride_list_draw_tab_images(dpi, w); } -/** - * - * rct2: 0x006AF561 - */ -static void ride_get_status(int rideIndex, int *formatSecondary, int *argument) -{ - rct_ride *ride = &g_ride_list[rideIndex]; - - if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED) { - *formatSecondary = STR_CRASHED; - return; - } - if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) { - *formatSecondary = STR_BROKEN_DOWN; - return; - } - if (ride->status == RIDE_STATUS_CLOSED) { - *formatSecondary = STR_CLOSED; - return; - } - if (ride->status == RIDE_STATUS_TESTING) { - *formatSecondary = STR_TEST_RUN; - return; - } - rct_peep *peep = GET_PEEP(ride->race_winner); - if (ride->mode == RIDE_MODE_RACE && !(ride->lifecycle_flags & RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING) && ride->race_winner != 0xFFFF && peep->sprite_identifier == SPRITE_IDENTIFIER_PEEP) { - if (peep->name_string_idx == STR_GUEST) { - *argument = peep->id; - *formatSecondary = STR_RACE_WON_BY_GUEST; - } else { - *argument = peep->name_string_idx; - *formatSecondary = STR_RACE_WON_BY; - } - } else { - if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x20000)) { - *argument = ride->num_riders; - *formatSecondary = STR_PERSON_ON_RIDE; - if(*argument != 1) - *formatSecondary = STR_PEOPLE_ON_RIDE; - - } else { - *formatSecondary = STR_OPEN; - } - } -} - /** * * rct2: 0x006B3240