diff --git a/distribution/changelog.txt b/distribution/changelog.txt index b22c11044b..a8c22517cb 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -10,6 +10,7 @@ - Change: [#11449] Remove complete circuit requirement from Air Powered Vertical Coaster (for RCT1 parity). - Fix: [#1148] Research funding dropdown not shown in finances window. - Fix: [#6119] Advertising campaign for ride window not updated properly (original bug). +- Fix: [#7006] Submarine Ride is in the wrong research group. - Fix: [#11072] Land and water tools working out of bounds (original bug). - Fix: [#11259] Custom JSON object breaks saves. - Fix: [#11290] Perform funds checking for all peeps entering a ride. diff --git a/src/openrct2-ui/windows/EditorObjectSelection.cpp b/src/openrct2-ui/windows/EditorObjectSelection.cpp index 1838abc86c..a7378fb392 100644 --- a/src/openrct2-ui/windows/EditorObjectSelection.cpp +++ b/src/openrct2-ui/windows/EditorObjectSelection.cpp @@ -1293,7 +1293,8 @@ static void editor_load_selected_objects() { rct_ride_entry* rideEntry = get_ride_entry(entryIndex); uint8_t rideType = ride_entry_get_first_non_null_ride_type(rideEntry); - research_insert_ride_entry(rideType, entryIndex, rideEntry->category[0], true); + uint8_t category = RideTypeDescriptors[rideType].Category; + research_insert_ride_entry(rideType, entryIndex, category, true); } else if (objectType == OBJECT_TYPE_SCENERY_GROUP) { diff --git a/src/openrct2/interface/InteractiveConsole.cpp b/src/openrct2/interface/InteractiveConsole.cpp index 164b5b93d2..29ec47519e 100644 --- a/src/openrct2/interface/InteractiveConsole.cpp +++ b/src/openrct2/interface/InteractiveConsole.cpp @@ -1094,7 +1094,8 @@ static int32_t cc_load_object(InteractiveConsole& console, const arguments_t& ar for (int32_t j = 0; j < MAX_RIDE_TYPES_PER_RIDE_ENTRY; j++) { rideType = rideEntry->ride_type[j]; - research_insert_ride_entry(rideType, groupIndex, rideEntry->category[0], true); + uint8_t category = RideTypeDescriptors[rideType].Category; + research_insert_ride_entry(rideType, groupIndex, category, true); } gSilentResearch = true; diff --git a/src/openrct2/management/Research.cpp b/src/openrct2/management/Research.cpp index fba808e36a..7a4539f0c0 100644 --- a/src/openrct2/management/Research.cpp +++ b/src/openrct2/management/Research.cpp @@ -488,7 +488,11 @@ void research_populate_list_random() int32_t researched = (scenario_rand() & 0xFF) > 128; for (auto rideType : rideEntry->ride_type) { - research_insert_ride_entry(rideType, i, rideEntry->category[0], researched); + if (rideType != RIDE_TYPE_NULL) + { + uint8_t category = RideTypeDescriptors[rideType].Category; + research_insert_ride_entry(rideType, i, category, researched); + } } } @@ -521,10 +525,13 @@ bool research_insert_ride_entry(uint8_t rideType, ObjectEntryIndex entryIndex, u void research_insert_ride_entry(ObjectEntryIndex entryIndex, bool researched) { rct_ride_entry* rideEntry = get_ride_entry(entryIndex); - uint8_t category = rideEntry->category[0]; for (auto rideType : rideEntry->ride_type) { - research_insert_ride_entry(rideType, entryIndex, category, researched); + if (rideType != RIDE_TYPE_NULL) + { + uint8_t category = RideTypeDescriptors[rideType].Category; + research_insert_ride_entry(rideType, entryIndex, category, researched); + } } } diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index e450a73ef2..2e0745f9fb 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -60,9 +60,8 @@ void RideObject::ReadLegacy(IReadObjectContext* context, IStream* stream) _legacyType.intensity_multiplier = stream->ReadValue(); _legacyType.nausea_multiplier = stream->ReadValue(); _legacyType.max_height = stream->ReadValue(); - _legacyType.enabledTrackPieces = stream->ReadValue(); - _legacyType.category[0] = stream->ReadValue(); - _legacyType.category[1] = stream->ReadValue(); + // Skipping a uint64_t for the enabled track pieces and two uint8_ts for the categories. + stream->Seek(10, STREAM_SEEK_CURRENT); _legacyType.shop_item = stream->ReadValue(); _legacyType.shop_item_secondary = stream->ReadValue(); @@ -382,32 +381,32 @@ std::string RideObject::GetCapacity() const void RideObject::SetRepositoryItem(ObjectRepositoryItem* item) const { + // Find the first non-null ride type, to be used when checking the ride group and determining the category. + uint8_t firstRideType = ride_entry_get_first_non_null_ride_type(&_legacyType); + uint8_t category = RideTypeDescriptors[firstRideType].Category; + for (int32_t i = 0; i < RCT2_MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++) { item->RideInfo.RideType[i] = _legacyType.ride_type[i]; } for (int32_t i = 0; i < RCT2_MAX_CATEGORIES_PER_RIDE; i++) { - item->RideInfo.RideCategory[i] = _legacyType.category[i]; + item->RideInfo.RideCategory[i] = category; } - uint8_t flags = 0; - item->RideInfo.RideFlags = flags; - - // Find the first non-null ride type, to be used when checking the ride group - uint8_t rideTypeIdx = ride_entry_get_first_non_null_ride_type(&_legacyType); + item->RideInfo.RideFlags = 0; // Determines the ride group. Will fall back to 0 if there is none found. uint8_t rideGroupIndex = 0; - const RideGroup* rideGroup = RideGroupManager::GetRideGroup(rideTypeIdx, &_legacyType); + const RideGroup* rideGroup = RideGroupManager::GetRideGroup(firstRideType, &_legacyType); // If the ride group is nullptr, the track type does not have ride groups. if (rideGroup != nullptr) { for (uint8_t i = rideGroupIndex + 1; i < MAX_RIDE_GROUPS_PER_RIDE_TYPE; i++) { - const RideGroup* irg = RideGroupManager::RideGroupFind(rideTypeIdx, i); + const RideGroup* irg = RideGroupManager::RideGroupFind(firstRideType, i); if (irg != nullptr) { @@ -547,17 +546,6 @@ void RideObject::ReadJson(IReadObjectContext* context, const json_t* root) _legacyType.ride_type[i] = rideType; } - auto rideCategories = ObjectJsonHelpers::GetJsonStringArray(json_object_get(properties, "category")); - if (rideCategories.size() >= 1) - { - _legacyType.category[0] = ParseRideCategory(rideCategories[0]); - _legacyType.category[1] = _legacyType.category[0]; - } - if (rideCategories.size() >= 2) - { - _legacyType.category[1] = ParseRideCategory(rideCategories[1]); - } - _legacyType.max_height = ObjectJsonHelpers::GetInteger(properties, "maxHeight"); // This needs to be set for both shops/facilities _and_ regular rides. diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 8b5dcb0969..519a67c9ac 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -2603,11 +2603,12 @@ private: if (rideEntry != nullptr) { + auto rideType = ride_entry_get_first_non_null_ride_type(rideEntry); dst->entryIndex = entryIndex; - dst->baseRideType = ride_entry_get_first_non_null_ride_type(rideEntry); + dst->baseRideType = rideType; dst->type = RESEARCH_ENTRY_TYPE_RIDE; dst->flags = 0; - dst->category = rideEntry->category[0]; + dst->category = RideTypeDescriptors[rideType].Category; } } } @@ -2621,11 +2622,12 @@ private: if (rideEntry != nullptr) { + auto rideType = ride_entry_get_first_non_null_ride_type(rideEntry); dst->entryIndex = entryIndex; - dst->baseRideType = ride_entry_get_first_non_null_ride_type(rideEntry); + dst->baseRideType = rideType; dst->type = RESEARCH_ENTRY_TYPE_RIDE; dst->flags = 0; - dst->category = rideEntry->category[0]; + dst->category = RideTypeDescriptors[rideType].Category; } } } diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index bdfd7c0608..029678d49f 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -7509,15 +7509,8 @@ void fix_invalid_vehicle_sprite_sizes() bool ride_entry_has_category(const rct_ride_entry* rideEntry, uint8_t category) { - for (int32_t i = 0; i < MAX_CATEGORIES_PER_RIDE; i++) - { - if (rideEntry->category[i] == category) - { - return true; - } - } - - return false; + auto rideType = ride_entry_get_first_non_null_ride_type(rideEntry); + return RideTypeDescriptors[rideType].Category == category; } int32_t ride_get_entry_index(int32_t rideType, int32_t rideSubType) diff --git a/src/openrct2/ride/Ride.h b/src/openrct2/ride/Ride.h index 55f9329ded..884abbcac8 100644 --- a/src/openrct2/ride/Ride.h +++ b/src/openrct2/ride/Ride.h @@ -94,40 +94,36 @@ assert_struct_size(rct_ride_name, 4); /** * Ride type structure. - * size: unknown */ struct rct_ride_entry { rct_ride_name naming; - uint32_t images_offset; // 0x004. The first three images are previews. They correspond to the ride_type[] array. - uint32_t flags; // 0x008 - uint8_t ride_type[RCT2_MAX_RIDE_TYPES_PER_RIDE_ENTRY]; // 0x00C - uint8_t min_cars_in_train; // 0x00F - uint8_t max_cars_in_train; // 0x010 - uint8_t cars_per_flat_ride; // 0x011 + // The first three images are previews. They correspond to the ride_type[] array. + uint32_t images_offset; + uint32_t flags; + uint8_t ride_type[RCT2_MAX_RIDE_TYPES_PER_RIDE_ENTRY]; + uint8_t min_cars_in_train; + uint8_t max_cars_in_train; + uint8_t cars_per_flat_ride; // Number of cars that can't hold passengers - uint8_t zero_cars; // 0x012 - // The index to the vehicle type displayed in - // the vehicle tab. - uint8_t tab_vehicle; // 0x013 - uint8_t default_vehicle; // 0x014 - // Convert from first - fourth vehicle to - // vehicle structure - uint8_t front_vehicle; // 0x015 - uint8_t second_vehicle; // 0x016 - uint8_t rear_vehicle; // 0x017 - uint8_t third_vehicle; // 0x018 - uint8_t pad_019; // 0x019 - rct_ride_entry_vehicle vehicles[RCT2_MAX_VEHICLES_PER_RIDE_ENTRY]; // 0x01A - vehicle_colour_preset_list* vehicle_preset_list; // 0x1AE - int8_t excitement_multiplier; // 0x1B2 - int8_t intensity_multiplier; // 0x1B3 - int8_t nausea_multiplier; // 0x1B4 - uint8_t max_height; // 0x1B5 - uint64_t enabledTrackPieces; // 0x1B6 - uint8_t category[RCT2_MAX_CATEGORIES_PER_RIDE]; // 0x1BE - uint8_t shop_item; // 0x1C0 - uint8_t shop_item_secondary; // 0x1C1 + uint8_t zero_cars; + // The index to the vehicle type displayed in the vehicle tab. + uint8_t tab_vehicle; + uint8_t default_vehicle; + // Convert from first - fourth vehicle to vehicle structure + uint8_t front_vehicle; + uint8_t second_vehicle; + uint8_t rear_vehicle; + uint8_t third_vehicle; + uint8_t pad_019; + rct_ride_entry_vehicle vehicles[RCT2_MAX_VEHICLES_PER_RIDE_ENTRY]; + vehicle_colour_preset_list* vehicle_preset_list; + int8_t excitement_multiplier; + int8_t intensity_multiplier; + int8_t nausea_multiplier; + uint8_t max_height; + uint8_t shop_item; + uint8_t shop_item_secondary; rct_string_id capacity; void* obj;