From 7e17f4fcf94e36bbdbdb79a22acb642aaf6a0f13 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 31 Oct 2014 02:33:33 +0000 Subject: [PATCH] start implementing ride update and station update --- src/audio/audio.h | 1 + src/ride/ride.c | 340 +++++++++++++++++++++++++++++++++++++++++++++- src/ride/ride.h | 9 +- 3 files changed, 345 insertions(+), 5 deletions(-) diff --git a/src/audio/audio.h b/src/audio/audio.h index 44e52fbaf6..eaa1797413 100644 --- a/src/audio/audio.h +++ b/src/audio/audio.h @@ -215,6 +215,7 @@ void unpause_sounds(); void stop_vehicle_sounds(); void sub_6BC348(); void sub_6BC6D8(); +int sub_6BC3AC(sint16 x, sint16 y, sint16 z, uint16 bx, uint32 ebp, uint16 di); // 0x009AF59C probably does the same job // once it's confirmed and calls in pause_sounds() are reversed, it can be used instead of this diff --git a/src/ride/ride.c b/src/ride/ride.c index 9eaca0a549..3176fc8ac6 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -20,6 +20,7 @@ #include #include "../addresses.h" +#include "../audio/audio.h" #include "../game.h" #include "../interface/window.h" #include "../localisation/localisation.h" @@ -106,6 +107,8 @@ const uint8 gRideClassifications[255] = { rct_ride_type **gRideTypeList = RCT2_ADDRESS(0x009ACFA4, rct_ride_type*); rct_ride* g_ride_list = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride); +static void ride_init_vehicle_speed(rct_ride *ride); + int ride_get_count() { rct_ride *ride; @@ -201,13 +204,346 @@ void ride_update_favourited_stat() window_invalidate_by_class(WC_RIDE_LIST); } +/** + * + * rct2: 0x006BC6D8 + */ +void ride_play_music() +{ + +} + +rct_map_element *ride_get_station_start_track_element(rct_ride *ride, int stationIndex) +{ + int x, y, z; + rct_map_element *mapElement; + + x = (ride->station_starts[stationIndex] & 0xFF) * 32; + y = (ride->station_starts[stationIndex] >> 8) * 32; + z = ride->station_heights[stationIndex] * 8; + + // 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_TRACK && x == mapElement->base_height) + return mapElement; + + mapElement++; + } while (!((mapElement - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + + return NULL; +} + +/** + * + * rct2: 0x006ABFFB + */ +void ride_update_station(rct_ride *ride, int stationIndex) +{ + int x, y, i, dl, dh, dx; + rct_map_element *mapElement; + rct_vehicle *vehicle; + rct_peep *peep; + + if (ride->station_starts[stationIndex] == 0xFFFF) + return; + + dl = 0; + if (ride->mode == RIDE_MODE_RACE) + goto loc_6AC1DF; + if (ride->mode == RIDE_MODE_BUMPERCAR) + goto loc_6AC12B; + if (ride->mode == RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED) + goto loc_6AC0A1; + if (ride->mode == RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED) + goto loc_6AC0A1; + + if (!(ride->lifecycle_flags & (RIDE_LIFECYCLE_BROKEN_DOWN | RIDE_LIFECYCLE_CRASHED))) { + if (ride->status != RIDE_STATUS_CLOSED) + goto loc_6AC076; + if (ride->num_riders != 0) + goto loc_6AC076; + } + + dh = ride->var_062[stationIndex] & 0x7F; + if (dh != 0 && dh != 0x7F && !(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 7)) + ride->var_062[stationIndex]--; + goto loc_6AC2AF; + +loc_6AC076: + dl = 1; + dh = ride->var_062[stationIndex] & 0x7F; + if (dh != 0) { + if (dh != 0x7F && !(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 31)) + ride->var_062[stationIndex]--; + dl = 0; + } + goto loc_6AC2AF; + +loc_6AC0A1: + mapElement = ride_get_station_start_track_element(ride, stationIndex); + + if (ride->status == RIDE_STATUS_CLOSED && ride->num_riders == 0) + goto loc_6AC10D; + + if (mapElement->flags & 0x20) + goto loc_6AC10D; + + dl = 1; + if (!(ride->var_062[stationIndex] & (1 << 7))) { + ride->var_062[stationIndex] |= (1 << 7); + goto loc_6AC2C7; + } + + if (mapElement->properties.track.sequence & 0x80) + goto loc_6AC2C7; + + goto loc_6AC2AF; + +loc_6AC10D: + dl = 0; + if (ride->var_062[stationIndex] & (1 << 7)) { + ride->var_062[stationIndex] &= ~(1 << 7); + goto loc_6AC2C7; + } + + if (mapElement->properties.track.sequence & 0x80) + goto loc_6AC2C7; + + goto loc_6AC2AF; + +loc_6AC12B: + if (ride->status == RIDE_STATUS_CLOSED) + goto loc_6AC2AF; + if (ride->lifecycle_flags & (RIDE_LIFECYCLE_BROKEN_DOWN | RIDE_LIFECYCLE_CRASHED)) + goto loc_6AC2AF; + if (ride->lifecycle_flags & RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING) + goto loc_6AC17B; + + for (i = 0; i < ride->num_vehicles; i++) { + vehicle = &(g_sprite_list[ride->vehicles[i]].vehicle); + if (vehicle->status != VEHICLE_STATUS_WAITING_TO_DEPART) + goto loc_6AC2AF; + } + goto loc_6AC1CA; + +loc_6AC17B: + dx = ride->var_0D0 * 32; + dl = dx & 0xFF; + dh = (dx >> 8) & 0xFF; + for (i = 0; i < ride->num_vehicles; i++) { + vehicle = &(g_sprite_list[ride->vehicles[i]].vehicle); + if (dh > vehicle->var_CE) + continue; + if (dh < vehicle->var_CE) + goto loc_6AC1B5; + if (dl > vehicle->var_51) + continue; + } + goto loc_6AC1C3; + +loc_6AC1B5: + ride->lifecycle_flags &= ~VEHICLE_STATUS_WAITING_TO_DEPART; + dh = 0; + goto loc_6AC2AF; + +loc_6AC1C3: + dl = 1; + goto loc_6AC2AF; + +loc_6AC1CA: + ride->lifecycle_flags |= VEHICLE_STATUS_WAITING_TO_DEPART; + ride->var_14D = 12; + dl = 1; + goto loc_6AC2AF; + +loc_6AC1DF: + if (ride->status == RIDE_STATUS_CLOSED) + goto loc_6AC2AF; + if (ride->lifecycle_flags & (RIDE_LIFECYCLE_BROKEN_DOWN | RIDE_LIFECYCLE_CRASHED)) + goto loc_6AC2AF; + if (ride->lifecycle_flags & VEHICLE_STATUS_WAITING_TO_DEPART) + goto loc_6AC236; + + for (i = 0; i < ride->num_vehicles; i++) { + vehicle = &(g_sprite_list[ride->vehicles[i]].vehicle); + if (vehicle->status == VEHICLE_STATUS_WAITING_TO_DEPART) + continue; + if (vehicle->status == VEHICLE_STATUS_DEPARTING) + continue; + + goto loc_6AC2AF; + } + goto loc_6AC29A; + +loc_6AC236: + dh = ride->var_0D0; + for (i = 0; i < ride->num_vehicles; i++) { + vehicle = &(g_sprite_list[ride->vehicles[i]].vehicle); + if (vehicle->status == VEHICLE_STATUS_WAITING_TO_DEPART) + continue; + if (dh > vehicle->var_CE) + continue; + + ride->lifecycle_flags &= ~VEHICLE_STATUS_WAITING_TO_DEPART; + if (vehicle->var_B3 == 0) + goto loc_6AC2AF; + + peep = &(g_sprite_list[vehicle->peep].peep); + ride->race_winner = peep->sprite_index; + ride->var_14D = 12; + goto loc_6AC2AF; + } + goto loc_6AC2AD; + +loc_6AC29A: + ride_init_vehicle_speed(ride); + ride->lifecycle_flags |= VEHICLE_STATUS_WAITING_TO_DEPART; + ride->var_14D = 12; + +loc_6AC2AD: + dl = 1; + +loc_6AC2AF: + if (dl != 0) { + if (ride->var_062[stationIndex] & (1 << 7)) + return; + ride->var_062[stationIndex] |= (1 << 7); + } else { + ride->var_062[stationIndex] &= ~(1 << 7); + return; + } + +loc_6AC2C7: + x = (ride->station_starts[stationIndex] & 0xFF) * 32; + y = (ride->station_starts[stationIndex] >> 8) * 32; + mapElement = ride_get_station_start_track_element(ride, stationIndex); + + mapElement->properties.track.sequence &= 0x7F; + if (dl != 0) + mapElement->properties.track.sequence |= 0x80; + + RCT2_CALLPROC_X(0x006ECB60, x, 0, y, 0, mapElement->clearance_height * 8, mapElement->base_height * 8, 0); +} + /** * * rct2: 0x006ABE4C */ void ride_update_all() { - RCT2_CALLPROC_EBPSAFE(0x006ABE4C); + // RCT2_CALLPROC_EBPSAFE(0x006ABE4C); + + rct_s6_info *s6Info = (rct_s6_info*)0x0141F570; + rct_ride *ride; + rct_vehicle *vehicle; + int i, j, x, y, z; + + // Remove all rides if certain flags are set (possible scenario editor?) + int *esi = (int*)0x9DCE9E; + if (esi[0x1BCA] & 2) { + if (s6Info->var_000 <= 2) + FOR_ALL_RIDES(i, ride) + ride->type = RIDE_TYPE_NULL; + return; + } + + // Something related to windows + RCT2_CALLPROC_EBPSAFE(0x006BC348); + + FOR_ALL_RIDES(i, ride) { + if (ride->var_1CA != 0) + ride->var_1CA--; + + if (RCT2_GLOBAL(0x0097D4F2 + (ride->type * 8), uint16) & 6) + goto loc_6ABFF0; + if (ride->status != RIDE_STATUS_OPEN) + goto loc_6ABF6F; + if (ride->lifecycle_flags & RIDE_LIFECYCLE_MUSIC) + goto loc_6ABF6F; + if (ride->type == RIDE_TYPE_CIRCUS_SHOW) + goto loc_6ABF21; + if (ride->lifecycle_flags & (RIDE_LIFECYCLE_6 | RIDE_LIFECYCLE_BROKEN_DOWN)) + goto loc_6ABF37; + if (ride->var_18C == 7) + goto loc_6ABF04; + if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) + goto loc_6ABEEA; + if (ride->var_18C == 6) + goto loc_6ABEEA; + if (ride->var_18C == 7) + goto loc_6ABEF9; + + loc_6ABEEA: + if (ride->var_1AC != 255) + ride->var_1AC++; + + loc_6ABEF9: + if (ride->var_1AC != 255) + goto loc_6ABF37; + + goto loc_6ABF6F; + + loc_6ABF04: + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 7) + goto loc_6ABF37; + + if (ride->var_1AC != 255) + ride->var_1AC++; + + goto loc_6ABF37; + + loc_6ABF21: + vehicle = &(g_sprite_list[ride->vehicles[0]].vehicle); + if (vehicle->status != VEHICLE_STATUS_DOING_CIRCUS_SHOW) + goto loc_6ABF6F; + + loc_6ABF37: + if (ride->var_15C != 255) + goto loc_6ABF76; + + uint8 *someKindOfMusicInfo = RCT2_ADDRESS(0x009AEF28, uint8*)[ride->music]; + uint8 someKindOfMusicInfoCount = *someKindOfMusicInfo++; + ride->var_15C = someKindOfMusicInfo[scenario_rand() % someKindOfMusicInfoCount]; + ride->var_188 = 0; + goto loc_6ABF76; + + loc_6ABF6F: + ride->var_15C = 255; + + loc_6ABF76: + if (ride->var_15C != 255) { + // Ride music of some sort, possibly break down power cut effect + x = (ride->station_starts[0] & 0xFF) * 32 + 16; + y = (ride->station_starts[0] >> 8) * 32 + 16; + z = ride->station_heights[0] * 8; + + uint8 bh = ride->var_15C; + int sampleRate = 22050; + if (!(ride->lifecycle_flags & (RIDE_LIFECYCLE_6 | RIDE_LIFECYCLE_BROKEN_DOWN))) { + sampleRate = ride->var_1AC * 70; + if (ride->var_18C != 7) + sampleRate *= -1; + sampleRate += 22050; + } + + ride->var_188 = sub_6BC3AC(x, y, z, (ride->var_15C << 8) | i, ride->var_188, sampleRate); + ride->var_15C = bh; + } + + loc_6ABFF0: + if (ride->type != RIDE_TYPE_MAZE) { + // Update stations + for (j = 0; j < 4; j++) + ride_update_station(ride, j); + } + + // loc_6AC335: + } + + ride_play_music(); } /** @@ -600,7 +936,7 @@ vehicle_colour ride_get_vehicle_colour(rct_ride *ride, int vehicleIndex) * set the speed of the go kart type vehicle at the start to a random value or alter if peep name is an easter egg * @param ride (esi) */ -void ride_init_vehicle_speed(rct_ride *ride) +static void ride_init_vehicle_speed(rct_ride *ride) { rct_ride_type *rideEntry; rct_vehicle *vehicle; diff --git a/src/ride/ride.h b/src/ride/ride.h index fe255e6920..dae21429a8 100644 --- a/src/ride/ride.h +++ b/src/ride/ride.h @@ -187,7 +187,8 @@ typedef struct { sint16 build_date; // 0x180 money16 upkeep_cost; // 0x182 uint16 race_winner; // 0x184 - uint8 pad_186[0x06]; + uint8 pad_186[0x02]; + uint32 var_188; uint8 var_18C; uint8 mechanic_status; // 0x18D uint16 mechanic; // 0x18E @@ -202,7 +203,9 @@ typedef struct { uint8 last_inspection; // 0x19B uint8 pad_19C[0x8]; uint32 var_1A4; - uint8 pad_1A8[6]; + uint8 pad_1A8[4]; + uint8 var_1AC; + uint8 pad_1AD; uint8 var_1AE; uint8 connected_message_throttle; // 0x1AF money32 income_per_hour; // 0x1B0 @@ -261,7 +264,7 @@ enum { RIDE_LIFECYCLE_NO_RAW_STATS = 1 << 3, RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING = 1 << 4, RIDE_LIFECYCLE_ON_RIDE_PHOTO = 1 << 5, - + RIDE_LIFECYCLE_6 = 1 << 6, RIDE_LIFECYCLE_BROKEN_DOWN = 1 << 7, RIDE_LIFECYCLE_CRASHED = 1 << 10,