From ad84e6d076c03068ed7b24686f1967909b947168 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Wed, 5 Nov 2014 02:55:29 +0000 Subject: [PATCH] implement ride_modify and supporting methods --- src/input.c | 2 +- src/localisation/string_ids.h | 3 + src/peep/peep.h | 4 +- src/ride/ride.c | 510 +++++++++++++++++++++++++++++++--- src/ride/ride.h | 10 +- src/ride/station.c | 18 ++ src/ride/station.h | 1 + src/windows/ride.c | 2 +- src/world/map.c | 11 +- src/world/map.h | 1 + 10 files changed, 521 insertions(+), 41 deletions(-) diff --git a/src/input.c b/src/input.c index cd3a70bade..64b13245db 100644 --- a/src/input.c +++ b/src/input.c @@ -827,7 +827,7 @@ static void game_handle_input_mouse(int x, int y, int state) RCT2_CALLPROC_X(0x006B4857, eax, 0, ecx, (int)map_element, 0, 0, 0); break; case 3: - RCT2_CALLPROC_X(0x006CC056, eax, 0, ecx, (int)map_element, 0, 0, 0); + ride_modify(map_element, eax, ecx); break; case 5: RCT2_CALLPROC_X(0x006E08D2, eax, 0, ecx, (int)map_element, 0, 0, 0); diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index 01dbcfe9a4..da55f8fe13 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -1053,6 +1053,9 @@ enum { STR_SELECT_MUSIC_STYLE_TIP = 3045, + STR_THIS_RIDE_CANNOT_BE_MODIFIED = 3046, + STR_LOCAL_AUTHORITY_FORBIDS_DEMOLITION_OR_MODIFICATIONS_TO_THIS_RIDE = 3047, + STR_WHITE = 3055, STR_TRANSLUCENT = 3056, STR_CONSTRUCTION_MARKER = 3057, diff --git a/src/peep/peep.h b/src/peep/peep.h index 24f2cac38c..22a35ed190 100644 --- a/src/peep/peep.h +++ b/src/peep/peep.h @@ -182,6 +182,8 @@ enum PEEP_THOUGHT_TYPE { }; enum PEEP_STATE { + PEEP_STATE_0 = 0, + PEEP_STATE_QUEUING_FRONT = 2, PEEP_STATE_ON_RIDE = 3, PEEP_STATE_LEAVING_RIDE = 4, @@ -321,7 +323,7 @@ typedef struct { sint16 var_18; sint16 var_1A; sint16 var_1C; - uint8 sprite_direction; + uint8 sprite_direction; // 0x1E uint8 pad_1F[3]; uint16 name_string_idx; // 0x22 uint16 next_x; // 0x24 diff --git a/src/ride/ride.c b/src/ride/ride.c index 428fcf8a96..2dc0d6eaec 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -451,6 +451,42 @@ void reset_all_ride_build_dates() #pragma region Construction +static int ride_check_if_construction_allowed(rct_ride *ride) +{ + if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) { + RCT2_GLOBAL(0x013CE952 + 6, uint16) = ride->name; + RCT2_GLOBAL(0x013CE952 + 8, uint32) = ride->name_arguments; + window_error_open(STR_CANT_START_CONSTRUCTION_ON, STR_HAS_BROKEN_DOWN_AND_REQUIRES_FIXING); + return 0; + } + + if (ride->status != RIDE_STATUS_CLOSED) { + RCT2_GLOBAL(0x013CE952 + 6, uint16) = ride->name; + RCT2_GLOBAL(0x013CE952 + 8, uint32) = ride->name_arguments; + window_error_open(STR_CANT_START_CONSTRUCTION_ON, STR_MUST_BE_CLOSED_FIRST); + return 0; + } + + return 1; +} + +static rct_window *ride_create_or_find_construction_window(int rideIndex) +{ + rct_window *w; + + w = window_find_by_class(WC_RIDE_CONSTRUCTION); + if (w == NULL || w->number != rideIndex) { + window_close_construction_windows(); + RCT2_GLOBAL(0x00F440A7, uint8) = rideIndex; + w = window_construction_open(rideIndex); + } else { + RCT2_CALLPROC_X(0x006C9627, 0, 0, 0, 0, 0, 0, 0); + RCT2_GLOBAL(0x00F440A7, uint8) = rideIndex; + } + + return w; +} + int ride_create_ride(ride_list_item listItem) { int eax, ebx, ecx, edx, esi, edi, ebp; @@ -490,54 +526,444 @@ void ride_construct_new(ride_list_item listItem) window_close_by_number(WC_RIDE, rideIndex); } +/** + * + * rct2: 0x006C84CE + */ +static void sub_6C84CE() +{ + RCT2_CALLPROC_X(0x006C84CE, 0, 0, 0, 0, 0, 0, 0); +} + +/** + * + * rct2: 0x006DD4D5 + */ +static void ride_remove_cable_lift(rct_ride *ride) +{ + uint16 spriteIndex; + rct_vehicle *vehicle; + + if (ride->lifecycle_flags & RIDE_LIFECYCLE_CABLE_LIFT) { + ride->lifecycle_flags &= ~RIDE_LIFECYCLE_CABLE_LIFT; + spriteIndex = ride->cable_lift; + do { + vehicle = &(g_sprite_list[spriteIndex].vehicle); + RCT2_CALLPROC_X(0x006EC473, 0, 0, 0, 0, (int)vehicle, 0, 0); + RCT2_CALLPROC_X(0x0069EDB6, 0, 0, 0, 0, (int)vehicle, 0, 0); + spriteIndex = vehicle->next_vehicle_on_train; + } while (spriteIndex != SPRITE_INDEX_NULL); + } +} + +/** + * + * rct2: 0x006DD506 + */ +static void ride_remove_vehicles(rct_ride *ride) +{ + int i; + uint16 spriteIndex; + rct_vehicle *vehicle; + + if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK) { + ride->lifecycle_flags &= ~RIDE_LIFECYCLE_ON_TRACK; + ride->lifecycle_flags &= ~(RIDE_LIFECYCLE_TEST_IN_PROGRESS | RIDE_LIFECYCLE_11); + + for (i = 0; i < 32; i++) { + spriteIndex = ride->vehicles[i]; + while (spriteIndex != SPRITE_INDEX_NULL) { + vehicle = &(g_sprite_list[spriteIndex].vehicle); + RCT2_CALLPROC_X(0x006EC473, 0, 0, 0, 0, (int)vehicle, 0, 0); + RCT2_CALLPROC_X(0x0069EDB6, 0, 0, 0, 0, (int)vehicle, 0, 0); + spriteIndex = vehicle->next_vehicle_on_train; + } + + ride->vehicles[i] = SPRITE_INDEX_NULL; + } + + for (i = 0; i < 4; i++) + ride->var_066[i] = 255; + } +} + +/** + * + * rct2: 0x006DD4AC + */ +static void ride_clear_for_construction(int rideIndex) +{ + rct_ride *ride; + rct_window *w; + + ride = GET_RIDE(rideIndex); + + ride_measurement_clear(ride); + + ride->lifecycle_flags &= ~(RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN); + ride->var_14D |= 0x0C; + + ride_remove_cable_lift(ride); + ride_remove_vehicles(ride); + + w = window_find_by_number(WC_RIDE, rideIndex); + if (w != NULL) + window_event_helper(w, 0, WE_RESIZE); +} + +/** + * + * rct2: 0x006664DF + */ +static void ride_remove_peeps(int rideIndex) +{ + int i, stationIndex, x, y, z, exitX, exitY, exitZ, exitDirection; + uint16 xy, spriteIndex; + rct_ride *ride; + rct_map_element *mapElement; + rct_peep *peep; + + ride = GET_RIDE(rideIndex); + + // Find first station + stationIndex = -1; + for (i = 0; i < 4; i++) { + if (ride->station_starts[i] != 0xFFFF) { + stationIndex = i; + break; + } + } + + // Get exit position and direction + exitDirection = 255; + if (stationIndex != -1) { + xy = ride->exits[stationIndex]; + if (xy != 0xFFFF) { + exitX = xy & 0xFF; + exitY = xy >> 8; + exitZ = ride->station_heights[stationIndex]; + mapElement = ride_get_station_exit_element(ride, exitX, exitY, exitZ); + + exitDirection = mapElement->type & 3; + exitX = (exitX * 32) - (RCT2_ADDRESS(0x00981D6C, sint16)[exitDirection * 2] * 20) + 16; + exitY = (exitY * 32) - (RCT2_ADDRESS(0x00981D6E, sint16)[exitDirection * 2] * 20) + 16; + exitZ = (exitZ * 8) + 2; + + // Reverse direction + exitDirection ^= 2; + + exitDirection *= 8; + } + } + + // Place all the peeps at exit + FOR_ALL_PEEPS(spriteIndex, peep) { + if ( + peep->state == PEEP_STATE_QUEUING_FRONT || + peep->state == PEEP_STATE_ENTERING_RIDE || + peep->state == PEEP_STATE_LEAVING_RIDE || + peep->state == PEEP_STATE_ON_RIDE + ) { + if (peep->current_ride != rideIndex) + continue; + + RCT2_CALLPROC_X(0x0069A409, 0, 0, 0, 0, (int)peep, 0, 0); + if (peep->state == PEEP_STATE_QUEUING_FRONT && peep->var_2C == 0) + RCT2_CALLPROC_X(0x006966A9, 0, 0, 0, 0, (int)peep, 0, 0); + + RCT2_CALLPROC_X(0x006EC473, 0, 0, 0, 0, (int)peep, 0, 0); + + if (exitDirection == 255) { + x = peep->next_x + 16; + y = peep->next_y + 16; + z = (peep->next_z & 0xFF) * 8; + if ((peep->next_z >> 8) & 4) + z += 8; + z++; + RCT2_CALLPROC_X(0x0069E9D3, exitX, 0, exitY, exitZ, (int)peep, 0, 0); + } else { + RCT2_CALLPROC_X(0x0069E9D3, exitX, 0, exitY, exitZ, (int)peep, 0, 0); + peep->sprite_direction = exitDirection; + } + + RCT2_CALLPROC_X(0x006EC473, 0, 0, 0, 0, (int)peep, 0, 0); + peep->state = PEEP_STATE_0; + RCT2_CALLPROC_X(0x00693BE5, 0, 0, 0, 0, (int)peep, 0, 0); + + peep->happiness = min(peep->happiness, peep->happiness_growth_rate) / 2; + peep->happiness_growth_rate = peep->happiness; + peep->var_45 |= 2; + } + } + + ride->num_riders = 0; + ride->var_15D = 0; + ride->var_14D |= 4; +} + +void sub_6C683D(int x, int y, int z, int direction, int type, int esi, int edi, int ebp) +{ + RCT2_CALLPROC_X(0x006C683D, x, (direction << 8) | type, y, z, esi, edi, ebp); +} + +void sub_6CE254() +{ + RCT2_CALLPROC_X(0x006CE254, 0, 0, 0, 0, 0, 0, 0); +} + + +void sub_6C96C0() +{ + RCT2_CALLPROC_X(0x006C96C0, 0, 0, 0, 0, 0, 0, 0); +} + +static void sub_6C9627() +{ + switch (RCT2_GLOBAL(0x00F440A6, uint8)) { + case 3: + sub_6C683D( + RCT2_GLOBAL(0x00F440A8, uint16), + RCT2_GLOBAL(0x00F440AA, uint16), + RCT2_GLOBAL(0x00F440AC, uint16), + RCT2_GLOBAL(0x00F440AE, uint8) & 3, + RCT2_GLOBAL(0x00F440AF, uint8), + 0, + 0, + 1 + ); + break; + case 6: + case 7: + case 8: + sub_6CE254(); + break; + default: + if (RCT2_GLOBAL(0x00F440B0, uint8) & 1) { + RCT2_GLOBAL(0x00F440B0, uint8) &= ~1; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint8) &= ~4; + map_invalidate_tile_full(RCT2_GLOBAL(0x00F440A8, uint16), RCT2_GLOBAL(0x00F440AA, uint16)); + } + sub_6C96C0(); + break; + } +} + +/** + * + * rct2: 0x006C9296 + */ +static void sub_6C9296() +{ + RCT2_CALLPROC_X(0x006C9296, 0, 0, 0, 0, 0, 0, 0); +} + +/** + * + * rct2: 0x006C93B8 + */ +static void sub_6C93B8() +{ + RCT2_CALLPROC_X(0x006C93B8, 0, 0, 0, 0, 0, 0, 0); +} + +/** + * + * rct2: 0x006CC2CA + */ +static int ride_modify_entrance_or_exit(rct_map_element *mapElement, int x, int y) +{ + int rideIndex, entranceType; + rct_window *constructionWindow; + + rideIndex = mapElement->properties.entrance.ride_index; + + entranceType = mapElement->properties.entrance.type; + if (entranceType != ENTRANCE_TYPE_RIDE_ENTRANCE && entranceType != ENTRANCE_TYPE_RIDE_EXIT) + return 0; + + int bl = (mapElement->properties.entrance.index & 0x70) >> 4; + + // Get or create construction window for ride + constructionWindow = window_find_by_class(WC_RIDE_CONSTRUCTION); + if (constructionWindow == NULL) { + if (!sub_6CC3FB(rideIndex)) + return 0; + + constructionWindow = window_find_by_class(WC_RIDE_CONSTRUCTION); + if (constructionWindow == NULL) + return 0; + } + + sub_6C9627(); + if ( + RCT2_GLOBAL(0x00F440A6, uint8) != 5 || + !(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint8) & INPUT_FLAG_TOOL_ACTIVE) || + RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_RIDE_CONSTRUCTION + ) { + // Replace entrance / exit + tool_set(constructionWindow, entranceType == 0 ? 29 : 30, 12); + RCT2_GLOBAL(0x00F44191, uint8) = entranceType; + RCT2_GLOBAL(0x00F44192, uint8) = rideIndex; + RCT2_GLOBAL(0x00F44193, uint8) = bl; + RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint8) |= INPUT_FLAG_6; + int al = RCT2_GLOBAL(0x00F440A6, uint8); + if (al != 5) { + RCT2_GLOBAL(0x00F440A6, uint8) = 5; + RCT2_GLOBAL(0x00F440CC, uint8) = al; + } + + sub_6C84CE(); + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~2; + } else { + // Remove entrance / exit + game_do_command(x, 9, y, rideIndex, GAME_COMMAND_13, bl, 0); + RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) = entranceType == ENTRANCE_TYPE_RIDE_ENTRANCE ? 29 : 30; + RCT2_GLOBAL(0x00F44191, uint8) = entranceType; + } + + window_invalidate_by_class(WC_RIDE_CONSTRUCTION); + return 1; +} + +/** + * + * rct2: 0x006CC287 + */ +int ride_modify_maze(rct_map_element *mapElement, int x, int y) +{ + RCT2_GLOBAL(0x00F440A7, uint8) = mapElement->properties.track.ride_index; + RCT2_GLOBAL(0x00F440A6, uint8) = 6; + RCT2_GLOBAL(0x00F440A8, uint16) = x; + RCT2_GLOBAL(0x00F440AA, uint16) = y; + RCT2_GLOBAL(0x00F440AC, uint16) = mapElement->base_height * 8; + RCT2_GLOBAL(0x00F440B0, uint8) = 0; + RCT2_GLOBAL(0x00F440B1, uint8) = 0; + RCT2_CALLPROC_X(0x006CD887, 0, 0, 0, 0, 0, 0, 0); + return 1; +} + /** * * rct2: 0x006CC056 */ -int ride_try_construct(rct_map_element *trackMapElement) +int ride_modify(rct_map_element *mapElement, int x, int y) { - // Success stored in carry flag which can't be accessed after call using is macro - RCT2_CALLPROC_X(0x006CC056, 0, 0, 0, (int)trackMapElement, 0, 0, 0); + int rideIndex, z, direction, type; + rct_ride *ride; + rct_window *constructionWindow; + + rideIndex = mapElement->properties.track.ride_index; + ride = GET_RIDE(rideIndex); + + if (!ride_check_if_construction_allowed(ride)) + return 0; + + if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE) { + RCT2_GLOBAL(0x013CE952 + 6, uint16) = ride->name; + RCT2_GLOBAL(0x013CE952 + 8, uint32) = ride->name_arguments; + window_error_open(STR_CANT_START_CONSTRUCTION_ON, STR_LOCAL_AUTHORITY_FORBIDS_DEMOLITION_OR_MODIFICATIONS_TO_THIS_RIDE); + return 0; + } + + if (ride->lifecycle_flags & RIDE_LIFECYCLE_19) { + RCT2_GLOBAL(0x013CE952 + 6, uint16) = ride->name; + RCT2_GLOBAL(0x013CE952 + 8, uint32) = ride->name_arguments; + window_error_open(STR_CANT_START_CONSTRUCTION_ON, STR_THIS_RIDE_CANNOT_BE_MODIFIED); + return 0; + } + + ride_clear_for_construction(rideIndex); + ride_remove_peeps(rideIndex); + + // Check if element is a station entrance or exit + if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_ENTRANCE) + return ride_modify_entrance_or_exit(mapElement, x, y); + + constructionWindow = ride_create_or_find_construction_window(rideIndex); + + if (ride->type == RIDE_TYPE_MAZE) + return ride_modify_maze(mapElement, x, y); + + if (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x100) { + int outX, outY; + mapElement = ride_find_track_gap(mapElement, &outX, &outY); + } + + z = mapElement->base_height * 8; + direction = mapElement->type & 3; + type = mapElement->properties.track.type; + sub_6C683D(x, y, z, direction, type, 0, 0, 0); + + RCT2_GLOBAL(0x00F440A7, uint8) = rideIndex; + RCT2_GLOBAL(0x00F440A6, uint8) = 3; + RCT2_GLOBAL(0x00F440A8, uint16) = x; + RCT2_GLOBAL(0x00F440AA, uint16) = y; + RCT2_GLOBAL(0x00F440AC, uint16) = z; + RCT2_GLOBAL(0x00F440AE, uint8) = direction; + RCT2_GLOBAL(0x00F440AF, uint8) = type; + RCT2_GLOBAL(0x00F440B0, uint8) = 0; + RCT2_GLOBAL(0x00F440B1, uint8) = 0; + + if (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x8000) { + sub_6C84CE(); + return 1; + } + + sub_6C9296(); + if (RCT2_GLOBAL(0x00F440A6, uint8) == 1) { + sub_6C84CE(); + return 1; + } + + RCT2_GLOBAL(0x00F440A6, uint8) = 3; + RCT2_GLOBAL(0x00F440A8, uint16) = x; + RCT2_GLOBAL(0x00F440AA, uint16) = y; + RCT2_GLOBAL(0x00F440AC, uint16) = z; + RCT2_GLOBAL(0x00F440AE, uint8) = direction; + RCT2_GLOBAL(0x00F440AF, uint8) = type; + RCT2_GLOBAL(0x00F440B0, uint8) = 0; + RCT2_GLOBAL(0x00F440B1, uint8) = 0; + + sub_6C93B8(); + + if (RCT2_GLOBAL(0x00F440A6, uint8) != 2) { + RCT2_GLOBAL(0x00F440A6, uint8) = 3; + RCT2_GLOBAL(0x00F440A8, uint16) = x; + RCT2_GLOBAL(0x00F440AA, uint16) = y; + RCT2_GLOBAL(0x00F440AC, uint16) = z; + RCT2_GLOBAL(0x00F440AE, uint8) = direction; + RCT2_GLOBAL(0x00F440AF, uint8) = type; + RCT2_GLOBAL(0x00F440B0, uint8) = 0; + RCT2_GLOBAL(0x00F440B1, uint8) = 0; + } + + sub_6C84CE(); return 1; + + // Success stored in carry flag which can't be accessed after call using is macro + // RCT2_CALLPROC_X(0x006CC056, 0, 0, 0, (int)trackMapElement, 0, 0, 0); + // return 1; } /** * * rct2: 0x006CC3FB */ -void sub_6CC3FB(int rideIndex) +int sub_6CC3FB(int rideIndex) { rct_ride *ride; rct_window *w; tool_cancel(); ride = GET_RIDE(rideIndex); - if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) { - RCT2_GLOBAL(0x013CE952 + 6, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 8, uint32) = ride->name_arguments; - window_error_open(STR_CANT_START_CONSTRUCTION_ON, STR_HAS_BROKEN_DOWN_AND_REQUIRES_FIXING); - return; - } - if (ride->status != RIDE_STATUS_CLOSED) { - RCT2_GLOBAL(0x013CE952 + 6, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 8, uint32) = ride->name_arguments; - window_error_open(STR_CANT_START_CONSTRUCTION_ON, STR_MUST_BE_CLOSED_FIRST); - return; - } + if (!ride_check_if_construction_allowed(ride)) + return 0; - RCT2_CALLPROC_X(0x006DD4AC, 0, 0, 0, rideIndex, 0, 0, 0); - RCT2_CALLPROC_X(0x006664DF, 0, 0, 0, rideIndex, 0, 0, 0); + ride_clear_for_construction(rideIndex); + ride_remove_peeps(rideIndex); - w = window_find_by_class(WC_RIDE_CONSTRUCTION); - if (w == NULL || w->number != rideIndex) { - window_close_construction_windows(); - RCT2_GLOBAL(0x00F440A7, uint8) = rideIndex; - w = window_construction_open(rideIndex); - } else { - RCT2_CALLPROC_X(0x006C9627, 0, 0, 0, 0, 0, 0, 0); - RCT2_GLOBAL(0x00F440A7, uint8) = rideIndex; - } + w = ride_create_or_find_construction_window(rideIndex); tool_set(w, 23, 12); RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; @@ -563,8 +989,8 @@ void sub_6CC3FB(int rideIndex) RCT2_GLOBAL(0x00F44159, uint8) = 0; RCT2_GLOBAL(0x00F4415C, uint8) = 0; - RCT2_CALLPROC_X(0x006C84CE, 0, 0, 0, 0, 0, ride->type, 0); - // return 0; + sub_6C84CE(); + return 1; } #pragma endregion @@ -1158,13 +1584,15 @@ rct_peep *ride_find_closest_mechanic(rct_ride *ride, int forInspection) } // Get station start track element and position - x = (xy & 0xFF) * 32; - y = (xy >> 8) * 32; - z = ride->station_heights[stationIndex] * 8; - mapElement = ride_get_station_start_track_element(ride, stationIndex); + x = xy & 0xFF; + y = xy >> 8; + z = ride->station_heights[stationIndex]; + mapElement = ride_get_station_exit_element(ride, x, y, z); if (mapElement == NULL) return NULL; + x *= 32; + y *= 32; direction = mapElement->type & 3; x -= RCT2_ADDRESS(0x00993CCC, sint16)[direction * 2]; y -= RCT2_ADDRESS(0x00993CCE, sint16)[direction * 2]; @@ -1321,6 +1749,22 @@ static void ride_music_update(int rideIndex) #pragma region Measurement functions +/** + * + * rct2: 0x006B642B + */ +void ride_measurement_clear(rct_ride *ride) +{ + rct_ride_measurement *measurement; + + if (ride->measurement_index == 255) + return; + + measurement = GET_RIDE_MEASUREMENT(ride->measurement_index); + measurement->ride_index = 255; + ride->measurement_index = 255; +} + /** * rct2: 0x006B64F2 */ diff --git a/src/ride/ride.h b/src/ride/ride.h index de0628764b..6e2e29e1bf 100644 --- a/src/ride/ride.h +++ b/src/ride/ride.h @@ -98,7 +98,7 @@ typedef struct { uint8 station_heights[4]; // 0x05A uint8 pad_05E[0x4]; uint8 station_depart[4]; // 0x062 - uint8 pad_066[0x4]; + uint8 var_066[4]; uint16 entrances[4]; // 0x06A uint16 exits[4]; // 0x072 uint8 pad_07A[0x0C]; @@ -241,7 +241,8 @@ typedef struct { uint16 total_air_time; // 0x1F4 uint8 pad_1F6; uint8 num_circuits; // 0x1F7 - uint8 pad_1F8[0x8]; + uint8 pad_1F8[6]; + uint16 cable_lift; // 0x1FE uint16 queue_length[4]; // 0x200 uint8 pad_208[0x58]; } rct_ride; @@ -611,7 +612,7 @@ void ride_check_all_reachable(); 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(ride_list_item listItem); -int ride_try_construct(rct_map_element *trackMapElement); +int ride_modify(rct_map_element *trackMapElement, int x, int y); 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); @@ -620,10 +621,11 @@ 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); +void ride_measurement_clear(rct_ride *ride); void ride_measurements_update(); rct_ride_measurement *ride_get_measurement(int rideIndex, rct_string_id *message); void ride_breakdown_add_news_item(int rideIndex); rct_peep *ride_find_closest_mechanic(rct_ride *ride, int forInspection); -void sub_6CC3FB(int rideIndex); +int sub_6CC3FB(int rideIndex); #endif diff --git a/src/ride/station.c b/src/ride/station.c index 38b7b5f792..ae5f4ac149 100644 --- a/src/ride/station.c +++ b/src/ride/station.c @@ -305,5 +305,23 @@ rct_map_element *ride_get_station_start_track_element(rct_ride *ride, int statio mapElement++; } while (!((mapElement - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + return NULL; +} + +rct_map_element *ride_get_station_exit_element(rct_ride *ride, int x, int y, int z) +{ + rct_map_element *mapElement; + + // Get first element of the tile + mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x); + + // Find the station track element + do { + if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_ENTRANCE && z == mapElement->base_height) + return mapElement; + + mapElement++; + } while (!((mapElement - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + return NULL; } \ No newline at end of file diff --git a/src/ride/station.h b/src/ride/station.h index 17ed09e9be..b71f1dc27d 100644 --- a/src/ride/station.h +++ b/src/ride/station.h @@ -27,5 +27,6 @@ void ride_update_station(rct_ride *ride, int stationIndex); rct_map_element *ride_get_station_start_track_element(rct_ride *ride, int stationIndex); +rct_map_element *ride_get_station_exit_element(rct_ride *ride, int x, int y, int z); #endif \ No newline at end of file diff --git a/src/windows/ride.c b/src/windows/ride.c index 89dd5a0990..fcc3542378 100644 --- a/src/windows/ride.c +++ b/src/windows/ride.c @@ -1387,7 +1387,7 @@ void window_ride_construct(rct_window *w) trackMapElement = ride_find_track_gap(trackMapElement, &trackX, &trackY); w = window_get_main(); - if (w != NULL && ride_try_construct(trackMapElement)) + if (w != NULL && ride_modify(trackMapElement, trackX, trackY)) window_scroll_to_location(w, trackX, trackY, trackMapElement->base_height * 8); } } diff --git a/src/world/map.c b/src/world/map.c index b1da00915b..606bd9f50d 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -534,7 +534,7 @@ money32 map_try_clear_scenery(int x, int y, rct_map_element *mapElement, int fla // Remove element if (flags & 1) { - RCT2_CALLPROC_X(0x006EC6D7, x, 0, y, 0, 0, 0, 0); + map_invalidate_tile_full(x, y); RCT2_CALLPROC_X(0x0068B280, 0, 0, 0, 0, (int)mapElement, 0, 0); } return RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY ? 0 : cost; @@ -670,4 +670,13 @@ void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi (*ebp & 0xFFFF) / 32, *ebx & 0xFF ); +} + +/** + * + * rct2: 0x006EC6D7 + */ +void map_invalidate_tile_full(int x, int y) +{ + RCT2_CALLPROC_X(0x006EC6D7, x, 0, y, 0, 0, 0, 0); } \ No newline at end of file diff --git a/src/world/map.h b/src/world/map.h index 4ff0115588..a658d959b6 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -208,6 +208,7 @@ void sub_6A876D(); int sub_664F72(int x, int y, int z); int map_is_location_in_park(int x, int y); void map_invalidate_tile(int x, int y, int zLow, int zHigh); +void map_invalidate_tile_full(int x, int y); void fountain_update_all();