From 72398151a7155ddf1e010c438f713db0889b5284 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 12 Sep 2015 18:17:25 +0100 Subject: [PATCH] implement ride_create_cable_lift --- projects/openrct2.vcxproj | 1 + src/common.h | 4 +- src/localisation/string_ids.h | 1 + src/network/http.cpp | 5 +- src/ride/ride.c | 95 ++++++++++++++++++++++++++++++++--- src/ride/ride.h | 6 +-- src/ride/track.c | 6 +-- src/ride/vehicle.c | 75 ++++++++++++++++++++++++++- src/ride/vehicle.h | 30 +++++++---- 9 files changed, 196 insertions(+), 27 deletions(-) diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index cd66b434b3..491574e929 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -300,6 +300,7 @@ {D24D94F6-2A74-480C-B512-629C306CE92F} openrct2 openrct2 + 10.0.10240.0 diff --git a/src/common.h b/src/common.h index 4ea6488767..a965995ce0 100644 --- a/src/common.h +++ b/src/common.h @@ -29,7 +29,9 @@ #define SafeDelete(x) if ((x) != nullptr) { delete (x); (x) = nullptr; } #define SafeDeleteArray(x) if ((x) != nullptr) { delete[] (x); (x) = nullptr; } -#define interface struct +#ifndef interface + #define interface struct +#endif #define abstract = 0 #endif \ No newline at end of file diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index c725353b63..8840ff8ae0 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -1662,6 +1662,7 @@ enum { STR_THIS_DESIGN_WILL_BE_BUILT_WITH_AN_ALTERNATIVE_VEHICLE_TYPE = 3136, STR_SELECT_NEARBY_SCENERY = 3137, STR_RESET_SELECTION = 3138, + STR_CABLE_LIFT_UNABLE_TO_WORK_IN_THIS_OPERATING_MODE = 3139, STR_MULTICIRCUIT_NOT_POSSIBLE_WITH_CABLE_LIFT_HILL = 3141, diff --git a/src/network/http.cpp b/src/network/http.cpp index a2ad158bec..306bde03ed 100644 --- a/src/network/http.cpp +++ b/src/network/http.cpp @@ -10,9 +10,12 @@ void http_dispose() { } #else #include -#include #include +// cURL includes windows.h, but we don't need all of it. +#define WIN32_LEAN_AND_MEAN +#include + typedef struct { char *ptr; int length; diff --git a/src/ride/ride.c b/src/ride/ride.c index dbe9271617..2eb5de507d 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -4212,22 +4212,103 @@ void ride_set_start_finish_points(int rideIndex, rct_xy_element *startElement) } } +/** + * + * rct2: 0x0069ED9E + */ +static int sub_69ED9E() +{ + int miscSpriteCount = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_COUNT_MISC, uint16); + int unkCount = RCT2_GLOBAL(0x013573C8, uint16); + return max(0, miscSpriteCount + unkCount - 300); +} + /** * * rct2: 0x006DD84C */ -int sub_6DD84C(rct_ride *ride, int rideIndex, rct_xy_element *element, int isApplying) +int ride_create_vehicles(rct_ride *ride, int rideIndex, rct_xy_element *element, int isApplying) { return RCT2_CALLPROC_X(0x006DD84C, element->x, isApplying, element->y, rideIndex, (int)ride, (int)element->element, 0) & 0x100; } +static bool sub_6D31A6(rct_ride *ride) +{ + return !(RCT2_CALLPROC_X(0x006D31A6, 0, 0, 0, 0, 0, (int)ride, 0) & 0x100); +} + /** * * rct2: 0x006DF4D4 */ -int sub_6DF4D4(rct_ride *ride, rct_xy_element *element, int isApplying) +bool ride_create_cable_lift(int rideIndex, bool isApplying) { - return RCT2_CALLPROC_X(0x006DF4D4, element->x, isApplying, element->y, 0, (int)ride, (int)element->element, 0) & 0x100; + rct_ride *ride = GET_RIDE(rideIndex); + + if (ride->mode != RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED && + ride->mode != RIDE_MODE_CONTINUOUS_CIRCUIT + ) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CABLE_LIFT_UNABLE_TO_WORK_IN_THIS_OPERATING_MODE; + return false; + } + + if (ride->num_circuits > 1) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_MULTICIRCUIT_NOT_POSSIBLE_WITH_CABLE_LIFT_HILL; + return false; + } + + if (sub_69ED9E() <= 5) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_UNABLE_TO_CREATE_ENOUGH_VEHICLES; + return false; + } + + if (!sub_6D31A6(ride)) { + return false; + } + + if (!isApplying) { + return true; + } + + int x = ride->cable_lift_x; + int y = ride->cable_lift_y; + int z = ride->cable_lift_z; + rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5); + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue; + if (mapElement->base_height != z) continue; + break; + } while (!map_element_is_last_for_tile(mapElement++)); + int direction = mapElement->type & MAP_ELEMENT_DIRECTION_MASK; + + rct_vehicle *head = NULL; + rct_vehicle *tail = NULL; + uint32 ebx = 0; + for (int i = 0; i < 5; i++) { + uint32 edx = ror32(0x15478, 10); + uint16 var_44 = edx & 0xFFFF; + edx = rol32(edx, 10) >> 1; + ebx -= edx; + uint32 var_24 = ebx; + ebx -= edx; + + rct_vehicle *current = cable_lift_segment_create(rideIndex, x, y, z, direction, var_44, var_24, i == 0); + current->next_vehicle_on_train = SPRITE_INDEX_NULL; + if (i == 0) { + head = current; + } else { + tail->next_vehicle_on_train = current->sprite_index; + tail->next_or_first_vehicle_on_train = current->sprite_index; + current->prev_vehicle_on_train = tail->sprite_index; + } + tail = current; + } + head->prev_vehicle_on_train = tail->sprite_index; + tail->next_or_first_vehicle_on_train = head->sprite_index; + + ride->lifecycle_flags |= RIDE_LIFECYCLE_CABLE_LIFT; + sub_6DEF56(head); + return true; } /** @@ -4440,7 +4521,7 @@ int ride_is_valid_for_test(int rideIndex, int goingToBeOpen, int isApplying) !ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_13) && !(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK) ) { - if (sub_6DD84C(ride, rideIndex, &trackElement, isApplying)) + if (ride_create_vehicles(ride, rideIndex, &trackElement, isApplying)) return 0; } @@ -4449,7 +4530,7 @@ int ride_is_valid_for_test(int rideIndex, int goingToBeOpen, int isApplying) (ride->lifecycle_flags & RIDE_LIFECYCLE_16) && !(ride->lifecycle_flags & RIDE_LIFECYCLE_CABLE_LIFT) ) { - if (sub_6DF4D4(ride, &trackElement, isApplying)) + if (!ride_create_cable_lift(rideIndex, isApplying)) return 0; } @@ -4563,7 +4644,7 @@ int ride_is_valid_for_open(int rideIndex, int goingToBeOpen, int isApplying) !ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_13) && !(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK) ) { - if (sub_6DD84C(ride, rideIndex, &trackElement, isApplying)) + if (ride_create_vehicles(ride, rideIndex, &trackElement, isApplying)) return 0; } @@ -4572,7 +4653,7 @@ int ride_is_valid_for_open(int rideIndex, int goingToBeOpen, int isApplying) (ride->lifecycle_flags & RIDE_LIFECYCLE_16) && !(ride->lifecycle_flags & RIDE_LIFECYCLE_CABLE_LIFT) ) { - if (sub_6DF4D4(ride, &trackElement, isApplying)) + if (!ride_create_cable_lift(rideIndex, isApplying)) return 0; } diff --git a/src/ride/ride.h b/src/ride/ride.h index a0135572f6..68c99f8543 100644 --- a/src/ride/ride.h +++ b/src/ride/ride.h @@ -349,9 +349,9 @@ typedef struct { uint16 total_air_time; // 0x1F4 uint8 pad_1F6; uint8 num_circuits; // 0x1F7 - sint16 var_1F8; - sint16 var_1FA; - uint8 var_1FC; + sint16 cable_lift_x; // 0x1F8 + sint16 cable_lift_y; // 0x1FA + uint8 cable_lift_z; // 0x1FC uint8 pad_1FD; uint16 cable_lift; // 0x1FE uint16 queue_length[4]; // 0x200 diff --git a/src/ride/track.c b/src/ride/track.c index 4430c7aa93..258b20e1f4 100644 --- a/src/ride/track.c +++ b/src/ride/track.c @@ -4223,9 +4223,9 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in if (trackBlock->index != 0) break; ride->lifecycle_flags |= RIDE_LIFECYCLE_16; - ride->var_1F8 = x; - ride->var_1FA = y; - ride->var_1FC = baseZ; + ride->cable_lift_x = x; + ride->cable_lift_y = y; + ride->cable_lift_z = baseZ; break; case 0xD8: ride->num_block_brakes++; diff --git a/src/ride/vehicle.c b/src/ride/vehicle.c index f3647fe600..6fcb060c28 100644 --- a/src/ride/vehicle.c +++ b/src/ride/vehicle.c @@ -23,11 +23,12 @@ #include "../audio/mixer.h" #include "../config.h" #include "../interface/viewport.h" +#include "../openrct2.h" #include "../world/sprite.h" #include "ride.h" #include "ride_data.h" +#include "track.h" #include "vehicle.h" -#include "../openrct2.h" static void vehicle_update(rct_vehicle *vehicle); @@ -639,4 +640,74 @@ rct_vehicle *vehicle_get_head(rct_vehicle *vehicle) int vehicle_is_used_in_pairs(rct_vehicle *vehicle) { return vehicle->num_seats & VEHICLE_SEAT_PAIR_FLAG; -} \ No newline at end of file +} + +/** + * + * rct2: 0x006DEF56 + */ +void sub_6DEF56(rct_vehicle *cableLift) +{ + RCT2_CALLPROC_X(0x006DEF56, 0, 0, 0, 0, (int)cableLift, 0, 0); +} + +rct_vehicle *cable_lift_segment_create(int rideIndex, int x, int y, int z, int direction, uint16 var_44, uint32 var_24, bool head) +{ + rct_ride *ride = GET_RIDE(rideIndex); + rct_vehicle *current = &(create_sprite(1)->vehicle); + current->sprite_identifier = SPRITE_IDENTIFIER_VEHICLE; + current->ride = rideIndex; + current->ride_subtype = 0xFF; + if (head) { + move_sprite_to_list((rct_sprite*)current, SPRITE_LINKEDLIST_OFFSET_VEHICLE); + ride->cable_lift = current->sprite_index; + } + current->var_01 = head ? 0 : 1; + current->var_44 = var_44; + current->var_24 = var_24; + current->sprite_width = 10; + current->sprite_height_negative = 10; + current->sprite_height_positive = 10; + current->var_46 = 100; + current->num_seats = 0; + current->speed = 20; + current->var_C3 = 80; + current->velocity = 0; + current->var_2C = 0; + current->var_4A = 0; + current->var_4C = 0; + current->var_4E = 0; + current->var_B5 = 0; + current->var_BA = 0; + current->var_B6 = 0; + current->var_B8 = 0; + current->sound1_id = 0xFF; + current->sound2_id = 0xFF; + current->var_C4 = 0; + current->var_C5 = 0; + current->var_C8 = 0; + current->var_CC = 0xFF; + current->var_1F = 0; + current->var_20 = 0; + for (int j = 0; j < 32; j++) { + current->peep[j] = SPRITE_INDEX_NULL; + } + current->var_CD = 0; + current->sprite_direction = direction << 3; + current->var_38 = x; + current->var_3A = y; + + z = z * 8; + current->var_3C = z; + z += RCT2_GLOBAL(0x0097D21A + (ride->type * 8), uint8); + + sprite_move(16, 16, z, (rct_sprite*)current); + current->var_36 = (TRACK_ELEM_CABLE_LIFT_HILL << 2) | (current->sprite_direction >> 3); + current->var_34 = 164; + current->var_48 = 2; + current->status = VEHICLE_STATUS_MOVING_TO_END_OF_STATION; + current->var_51 = 0; + current->num_peeps = 0; + current->next_free_seat = 0; + return current; +} diff --git a/src/ride/vehicle.h b/src/ride/vehicle.h index b2c95e4f7d..dc7327cb98 100644 --- a/src/ride/vehicle.h +++ b/src/ride/vehicle.h @@ -53,9 +53,11 @@ typedef struct { sint16 sprite_bottom; // 0x1C uint8 sprite_direction; // 0x1E uint8 var_1F; - uint8 pad_20[0x08]; + uint8 var_20; + uint8 pad_21[3]; + uint32 var_24; sint32 velocity; // 0x28 - uint8 pad_2C[0x04]; + uint32 var_2C; uint8 ride; // 0x30 uint8 vehicle_type; // 0x31 rct_vehicle_colour colours; // 0x32 @@ -69,31 +71,37 @@ typedef struct { uint16 var_3C; uint16 next_vehicle_on_train; // 0x3E uint16 prev_vehicle_on_train; // 0x40 - uint16 pad_42; + uint16 next_or_first_vehicle_on_train; // 0x42 uint16 var_44; uint16 var_46; uint16 var_48; - uint8 pad_4A; + uint8 var_4A; uint8 current_station; // 0x4B - uint8 pad_4C[0x4]; + uint16 var_4C; + uint16 var_4E; uint8 status; // 0x50 uint8 var_51; uint16 peep[32]; // 0x52 uint8 peep_tshirt_colours[32]; // 0x92 uint8 num_seats; // 0xB2 uint8 num_peeps; // 0xB3 - uint8 next_free_seat; // 0xB4 - uint8 pad_B5[0x06]; + uint8 next_free_seat; // 0xB4 + uint8 var_B5; + uint16 var_B6; + uint16 var_B8; + uint8 var_BA; uint8 sound1_id; // 0xBB uint8 sound1_volume; // 0xBC uint8 sound2_id; // 0xBD uint8 sound2_volume; // 0xBE sint8 var_BF; - uint8 pad_C0[0x02]; + uint8 pad_C0[2]; uint8 speed; // 0xC2 - uint8 pad_C3[2]; + uint8 var_C3; + uint8 var_C4; uint8 var_C5; - uint8 pad_C6[6]; + uint8 pad_C6[2]; + uint32 var_C8; uint8 var_CC; uint8 var_CD; union { @@ -151,6 +159,8 @@ void vehicle_get_g_forces(rct_vehicle *vehicle, int *verticalG, int *lateralG); void vehicle_set_map_toolbar(rct_vehicle *vehicle); int vehicle_is_used_in_pairs(rct_vehicle *vehicle); rct_vehicle *vehicle_get_head(rct_vehicle *vehicle); +void sub_6DEF56(rct_vehicle *cableLift); +rct_vehicle *cable_lift_segment_create(int rideIndex, int x, int y, int z, int direction, uint16 var_44, uint32 var_24, bool head); /** Helper macro until rides are stored in this module. */ #define GET_VEHICLE(sprite_index) &(g_sprite_list[sprite_index].vehicle)