From 5029f754edbcc92c23a27ac938bb88131cc451ac Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Wed, 17 Jun 2020 16:52:48 +0200 Subject: [PATCH 1/2] Fix #7324: Research window shows vehicle name instead of ride name --- data/language/en-GB.txt | 2 + distribution/changelog.txt | 1 + src/openrct2-ui/windows/Research.cpp | 52 ++++++++-- src/openrct2/localisation/StringIds.h | 3 + src/openrct2/management/Research.cpp | 136 ++++++++++++++++++++----- src/openrct2/management/Research.h | 32 +++--- src/openrct2/object/RideObject.cpp | 26 +---- src/openrct2/rct1/S4Importer.cpp | 1 + src/openrct2/rct2/S6Importer.cpp | 2 + src/openrct2/ride/RideGroupManager.cpp | 27 +++++ src/openrct2/ride/RideGroupManager.h | 2 + 11 files changed, 213 insertions(+), 71 deletions(-) diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index 5b57d654d6..fca3b5a2be 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -3670,6 +3670,8 @@ STR_6372 :The specified path contains a RollerCoaster Tycoon 1 installation, STR_6373 :Toggle clearance checks STR_6374 :C STR_6375 :Unknown Ride +STR_6376 :{WINDOW_COLOUR_2}Ride vehicle:{NEWLINE}{BLACK}{STRINGID} for {STRINGID} +STR_6377 :{WINDOW_COLOUR_2}Type: {BLACK}{STRINGID} for {STRINGID} ############# # Scenarios # diff --git a/distribution/changelog.txt b/distribution/changelog.txt index acd8bf986b..2a7934aeeb 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -22,6 +22,7 @@ - Fix: [#5451] Guests scream on every descent, no matter how small. - Fix: [#6119] Advertising campaign for ride window not updated properly (original bug). - Fix: [#7006] Submarine Ride is in the wrong research group. +- Fix: [#7324] Research window shows vehicle name instead of ride name. - Fix: [#10634] Guests are unable to use uphill paths out of toilets. - Fix: [#10876] When removing a path, its guest entry point is not removed. - Fix: [#10876] There can be multiple peep spawns on the same location. diff --git a/src/openrct2-ui/windows/Research.cpp b/src/openrct2-ui/windows/Research.cpp index 267a6ac421..6abff4439b 100644 --- a/src/openrct2-ui/windows/Research.cpp +++ b/src/openrct2-ui/windows/Research.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -362,16 +363,33 @@ void window_research_development_page_paint(rct_window* w, rct_drawpixelinfo* dp else { // Research type - stringId = STR_RESEARCH_UNKNOWN; + rct_string_id strings[2] = { STR_RESEARCH_UNKNOWN, 0 }; + rct_string_id label = STR_RESEARCH_TYPE_LABEL; if (gResearchProgressStage != RESEARCH_STAGE_INITIAL_RESEARCH) { - stringId = ResearchCategoryNames[gResearchNextItem->category]; + strings[0] = ResearchCategoryNames[gResearchNextItem->category]; if (gResearchProgressStage != RESEARCH_STAGE_DESIGNING) { - stringId = gResearchNextItem->GetName(); + strings[0] = gResearchNextItem->GetName(); + if (gResearchNextItem->type == RESEARCH_ENTRY_TYPE_RIDE) + { + auto rtd = RideTypeDescriptors[gResearchNextItem->baseRideType]; + if (!rtd.HasFlag(RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY)) + { + if (gResearchNextItem->flags & RESEARCH_ENTRY_FLAG_FIRST_OF_TYPE) + { + strings[0] = rtd.Naming.Name; + } + else + { + strings[1] = rtd.Naming.Name; + label = STR_RESEARCH_TYPE_LABEL_VEHICLE; + } + } + } } } - gfx_draw_string_left_wrapped(dpi, &stringId, x, y, 296, STR_RESEARCH_TYPE_LABEL, COLOUR_BLACK); + gfx_draw_string_left_wrapped(dpi, &strings, x, y, 296, label, COLOUR_BLACK); y += 25; // Progress @@ -402,11 +420,31 @@ void window_research_development_page_paint(rct_window* w, rct_drawpixelinfo* dp rct_string_id lastDevelopmentFormat; if (gResearchLastItem.has_value()) { - stringId = gResearchLastItem->GetName(); + rct_string_id strings[2] = { gResearchLastItem->GetName(), 0 }; uint8_t type = gResearchLastItem->type; - lastDevelopmentFormat = (type == RESEARCH_ENTRY_TYPE_RIDE) ? STR_RESEARCH_RIDE_LABEL : STR_RESEARCH_SCENERY_LABEL; + if (type == RESEARCH_ENTRY_TYPE_SCENERY) + { + lastDevelopmentFormat = STR_RESEARCH_SCENERY_LABEL; + } + else + { + lastDevelopmentFormat = STR_RESEARCH_RIDE_LABEL; + auto rtd = RideTypeDescriptors[gResearchLastItem->baseRideType]; + if (!rtd.HasFlag(RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY)) + { + if (gResearchLastItem->flags & RESEARCH_ENTRY_FLAG_FIRST_OF_TYPE) + { + strings[0] = rtd.Naming.Name; + } + else + { + strings[1] = rtd.Naming.Name; + lastDevelopmentFormat = STR_RESEARCH_VEHICLE_LABEL; + } + } + } - gfx_draw_string_left_wrapped(dpi, &stringId, x, y, 266, lastDevelopmentFormat, COLOUR_BLACK); + gfx_draw_string_left_wrapped(dpi, &strings, x, y, 266, lastDevelopmentFormat, COLOUR_BLACK); } } diff --git a/src/openrct2/localisation/StringIds.h b/src/openrct2/localisation/StringIds.h index 3b9fe75f0f..ed96a21580 100644 --- a/src/openrct2/localisation/StringIds.h +++ b/src/openrct2/localisation/StringIds.h @@ -3911,6 +3911,9 @@ enum STR_UNKNOWN_RIDE = 6375, + STR_RESEARCH_VEHICLE_LABEL = 6376, + STR_RESEARCH_TYPE_LABEL_VEHICLE = 6377, + // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working /* MAX_STR_COUNT = 32768 */ // MAX_STR_COUNT - upper limit for number of strings, not the current count strings }; diff --git a/src/openrct2/management/Research.cpp b/src/openrct2/management/Research.cpp index 2d437ab995..ac279738a7 100644 --- a/src/openrct2/management/Research.cpp +++ b/src/openrct2/management/Research.cpp @@ -201,21 +201,8 @@ void research_finish_item(ResearchItem* researchItem) if (rideEntry != nullptr && base_ride_type != RIDE_TYPE_NULL) { - bool ride_group_was_invented_before = false; - bool ride_type_was_invented_before = ride_type_is_invented(base_ride_type); rct_string_id availabilityString; - // Determine if the ride group this entry belongs to was invented before. - if (RideTypeDescriptors[base_ride_type].HasFlag(RIDE_TYPE_FLAG_HAS_RIDE_GROUPS)) - { - const RideGroup* rideGroup = RideGroupManager::GetRideGroup(base_ride_type, rideEntry); - - if (rideGroup->IsInvented()) - { - ride_group_was_invented_before = true; - } - } - ride_type_set_invented(base_ride_type); openrct2_assert(base_ride_type < RIDE_TYPE_COUNT, "Invalid base_ride_type = %d", base_ride_type); @@ -256,17 +243,10 @@ void research_finish_item(ResearchItem* researchItem) auto ft = Formatter::Common(); - // If a vehicle should be listed separately (maze, mini golf, flat rides, shops) - if (RideTypeDescriptors[base_ride_type].HasFlag(RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY)) - { - availabilityString = STR_NEWS_ITEM_RESEARCH_NEW_RIDE_AVAILABLE; - ft.Add(rideEntry->naming.Name); - } - // If a vehicle is the first to be invented for its ride group, show the ride group name. - else if ( - !ride_type_was_invented_before - || (RideTypeDescriptors[base_ride_type].HasFlag(RIDE_TYPE_FLAG_HAS_RIDE_GROUPS) - && !ride_group_was_invented_before)) + // If a vehicle is the first to be invented for its ride type or group, show the ride type/group name. + // Independently listed vehicles (like all flat rides and shops) should always be announced as such. + if (RideTypeDescriptors[base_ride_type].HasFlag(RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY) + || researchItem->flags & RESEARCH_ENTRY_FLAG_FIRST_OF_TYPE) { RideNaming naming = get_ride_naming(base_ride_type, rideEntry); availabilityString = STR_NEWS_ITEM_RESEARCH_NEW_RIDE_AVAILABLE; @@ -740,11 +720,11 @@ void research_remove_flags() { for (auto& researchItem : gResearchItemsUninvented) { - researchItem.flags = 0; + researchItem.flags &= ~(RESEARCH_ENTRY_FLAG_RIDE_ALWAYS_RESEARCHED | RESEARCH_ENTRY_FLAG_SCENERY_SET_ALWAYS_RESEARCHED); } for (auto& researchItem : gResearchItemsInvented) { - researchItem.flags = 0; + researchItem.flags &= ~(RESEARCH_ENTRY_FLAG_RIDE_ALWAYS_RESEARCHED | RESEARCH_ENTRY_FLAG_SCENERY_SET_ALWAYS_RESEARCHED); } } @@ -910,3 +890,107 @@ bool ResearchItem::Exists() const } return false; } + +static std::bitset _seenRideType = {}; +static std::bitset _seenRideGroup = {}; + +static void research_update_first_of_type(ResearchItem* researchItem) +{ + if (researchItem->IsNull()) + return; + + if (researchItem->type != RESEARCH_ENTRY_TYPE_RIDE) + return; + + auto rideType = researchItem->baseRideType; + if (rideType >= RIDE_TYPE_COUNT) + return; + + const auto& rtd = RideTypeDescriptors[rideType]; + if (rtd.HasFlag(RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY)) + { + researchItem->flags |= RESEARCH_ENTRY_FLAG_FIRST_OF_TYPE; + return; + } + + if (!rtd.HasFlag(RIDE_TYPE_FLAG_HAS_RIDE_GROUPS)) + { + if (!_seenRideType[rideType]) + researchItem->flags |= RESEARCH_ENTRY_FLAG_FIRST_OF_TYPE; + + _seenRideType[rideType] = true; + } + else + { + const auto& entry = get_ride_entry(researchItem->entryIndex); + if (entry != nullptr) + { + auto rideGroupIndex = RideGroupManager::GetRideGroupIndex(rideType, entry); + assert(rideGroupIndex < MAX_RIDE_GROUPS_PER_RIDE_TYPE); + + if (!_seenRideGroup[rideType * rideGroupIndex]) + researchItem->flags |= RESEARCH_ENTRY_FLAG_FIRST_OF_TYPE; + + _seenRideGroup[rideType * rideGroupIndex] = true; + } + } +} + +void research_determine_first_of_type() +{ + _seenRideType.reset(); + _seenRideGroup.reset(); + + for (auto& researchItem : gResearchItemsInvented) + { + if (researchItem.type != RESEARCH_ENTRY_TYPE_RIDE) + continue; + + auto rideType = researchItem.baseRideType; + if (rideType >= RIDE_TYPE_COUNT) + continue; + + const auto& rtd = RideTypeDescriptors[rideType]; + if (rtd.HasFlag(RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY)) + continue; + + // The next research item is also present in gResearchItemsInvented, even though it isn't invented yet(!) + if (gResearchNextItem.has_value() && !gResearchNextItem->IsNull() && researchItem.Equals(&gResearchNextItem.value())) + continue; + + if (!rtd.HasFlag(RIDE_TYPE_FLAG_HAS_RIDE_GROUPS)) + { + _seenRideType[rideType] = true; + log_error("Seen %d", rideType); + } + else + { + const auto& entry = get_ride_entry(researchItem.entryIndex); + if (entry != nullptr) + { + auto rideGroupIndex = RideGroupManager::GetRideGroupIndex(rideType, entry); + assert(rideGroupIndex < MAX_RIDE_GROUPS_PER_RIDE_TYPE); + _seenRideGroup[rideType * rideGroupIndex] = true; + log_error("Seen rgi %d ri %d", rideGroupIndex, rideType); + } + } + } + + if (gResearchLastItem.has_value()) + { + auto tmpVal = gResearchLastItem.value(); + research_update_first_of_type(&tmpVal); + gResearchLastItem = tmpVal; + } + if (gResearchNextItem.has_value()) + { + auto tmpVal = gResearchNextItem.value(); + research_update_first_of_type(&tmpVal); + gResearchNextItem = tmpVal; + } + + for (auto& researchItem : gResearchItemsUninvented) + { + research_update_first_of_type(&researchItem); + } +} diff --git a/src/openrct2/management/Research.h b/src/openrct2/management/Research.h index 2ff01d3211..384d6f6155 100644 --- a/src/openrct2/management/Research.h +++ b/src/openrct2/management/Research.h @@ -17,6 +17,19 @@ struct rct_ride_entry; +enum +{ + RESEARCH_ENTRY_TYPE_SCENERY = 0, + RESEARCH_ENTRY_TYPE_RIDE = 1, +}; + +enum +{ + RESEARCH_ENTRY_FLAG_FIRST_OF_TYPE = (1 << 0), + RESEARCH_ENTRY_FLAG_SCENERY_SET_ALWAYS_RESEARCHED = (1 << 5), + RESEARCH_ENTRY_FLAG_RIDE_ALWAYS_RESEARCHED = (1 << 6), +}; + struct ResearchItem { union @@ -67,7 +80,7 @@ struct ResearchItem retItem.entryIndex = OpenRCT2EntryIndexToRCTEntryIndex(entryIndex); retItem.baseRideType = baseRideType; retItem.type = type; - retItem.flags = flags; + retItem.flags = (flags & ~RESEARCH_ENTRY_FLAG_FIRST_OF_TYPE); retItem.category = category; } @@ -95,18 +108,6 @@ struct ResearchItem } }; -enum -{ - RESEARCH_ENTRY_TYPE_SCENERY = 0, - RESEARCH_ENTRY_TYPE_RIDE = 1, -}; - -enum -{ - RESEARCH_ENTRY_FLAG_SCENERY_SET_ALWAYS_RESEARCHED = (1 << 5), - RESEARCH_ENTRY_FLAG_RIDE_ALWAYS_RESEARCHED = (1 << 6), -}; - // Only used to mark as null nowadays. Deprecated. TODO: remove. #define RESEARCH_ITEM_NULL 0xFFFFFFFF @@ -192,3 +193,8 @@ void research_fix(); void research_items_make_all_unresearched(); void research_items_make_all_researched(); void research_items_shuffle(); +/** + * Determines if a newly invented ride entry should be listed as a new ride + * or as a new vehicle for a pre-existing ride. + */ +void research_determine_first_of_type(); diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 4828f424ed..c746d6ff7a 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -399,31 +399,7 @@ void RideObject::SetRepositoryItem(ObjectRepositoryItem* item) const } 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(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(firstRideType, i); - - if (irg != nullptr) - { - if (irg->Equals(rideGroup)) - { - rideGroupIndex = i; - break; - } - } - } - } - - item->RideInfo.RideGroupIndex = rideGroupIndex; + item->RideInfo.RideGroupIndex = RideGroupManager::GetRideGroupIndex(firstRideType, &_legacyType); } void RideObject::ReadLegacyVehicle( diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 45416519b3..165504f652 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -210,6 +210,7 @@ public: game_convert_news_items_to_utf8(); map_count_remaining_land_rights(); + research_determine_first_of_type(); } bool GetDetails(scenario_index_entry* dst) override diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index e70c265d34..48dfe382f2 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -487,6 +487,8 @@ public: OWNERSHIP_OWNED); // clang-format on } + + research_determine_first_of_type(); } void ImportRides() diff --git a/src/openrct2/ride/RideGroupManager.cpp b/src/openrct2/ride/RideGroupManager.cpp index 57ea49d0c8..f3c3d3595c 100644 --- a/src/openrct2/ride/RideGroupManager.cpp +++ b/src/openrct2/ride/RideGroupManager.cpp @@ -245,3 +245,30 @@ const RideGroup* RideGroupManager::RideGroupFind(const uint8_t rideType, const u return nullptr; } } + +uint8_t RideGroupManager::GetRideGroupIndex(const uint8_t rideType, const rct_ride_entry* rideEntry) +{ + uint8_t rideGroupIndex = 0; + + const RideGroup* rideGroup = RideGroupManager::GetRideGroup(rideType, rideEntry); + + // 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(rideType, i); + + if (irg != nullptr) + { + if (irg->Equals(rideGroup)) + { + rideGroupIndex = i; + break; + } + } + } + } + + return rideGroupIndex; +} diff --git a/src/openrct2/ride/RideGroupManager.h b/src/openrct2/ride/RideGroupManager.h index 9b79cb3018..64b50872e0 100644 --- a/src/openrct2/ride/RideGroupManager.h +++ b/src/openrct2/ride/RideGroupManager.h @@ -32,6 +32,8 @@ class RideGroupManager { public: static const RideGroup* GetRideGroup(const uint8_t trackType, const rct_ride_entry* rideEntry); + /** Will fall back to 0 if there is none found. */ + static uint8_t GetRideGroupIndex(const uint8_t trackType, const rct_ride_entry* rideEntry); static const RideGroup* RideGroupFind(const uint8_t rideType, const uint8_t index); }; From f8699d1244993b81c72c19590c6f45669db4d0df Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Fri, 19 Jun 2020 23:35:18 +0200 Subject: [PATCH 2/2] Apply review requests; fix error; remove debug code --- src/openrct2-ui/windows/Research.cpp | 6 +-- src/openrct2/management/Research.cpp | 60 +++++++++++++++++----------- 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/openrct2-ui/windows/Research.cpp b/src/openrct2-ui/windows/Research.cpp index 6abff4439b..b0711e0367 100644 --- a/src/openrct2-ui/windows/Research.cpp +++ b/src/openrct2-ui/windows/Research.cpp @@ -363,7 +363,7 @@ void window_research_development_page_paint(rct_window* w, rct_drawpixelinfo* dp else { // Research type - rct_string_id strings[2] = { STR_RESEARCH_UNKNOWN, 0 }; + std::array strings = { STR_RESEARCH_UNKNOWN, 0 }; rct_string_id label = STR_RESEARCH_TYPE_LABEL; if (gResearchProgressStage != RESEARCH_STAGE_INITIAL_RESEARCH) { @@ -417,10 +417,10 @@ void window_research_development_page_paint(rct_window* w, rct_drawpixelinfo* dp x = w->windowPos.x + 10; y = w->windowPos.y + w->widgets[WIDX_LAST_DEVELOPMENT_GROUP + baseWidgetIndex].top + 12; - rct_string_id lastDevelopmentFormat; if (gResearchLastItem.has_value()) { - rct_string_id strings[2] = { gResearchLastItem->GetName(), 0 }; + rct_string_id lastDevelopmentFormat = STR_EMPTY; + std::array strings = { gResearchLastItem->GetName(), 0 }; uint8_t type = gResearchLastItem->type; if (type == RESEARCH_ENTRY_TYPE_SCENERY) { diff --git a/src/openrct2/management/Research.cpp b/src/openrct2/management/Research.cpp index ac279738a7..db8caaa443 100644 --- a/src/openrct2/management/Research.cpp +++ b/src/openrct2/management/Research.cpp @@ -904,7 +904,10 @@ static void research_update_first_of_type(ResearchItem* researchItem) auto rideType = researchItem->baseRideType; if (rideType >= RIDE_TYPE_COUNT) + { + log_error("Research item has non-existant ride type index %d", rideType); return; + } const auto& rtd = RideTypeDescriptors[rideType]; if (rtd.HasFlag(RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY)) @@ -936,12 +939,35 @@ static void research_update_first_of_type(ResearchItem* researchItem) } } +static void research_mark_ride_type_as_seen(const ResearchItem& researchItem) +{ + auto rideType = researchItem.baseRideType; + if (rideType >= RIDE_TYPE_COUNT) + return; + + const auto& rtd = RideTypeDescriptors[rideType]; + if (!rtd.HasFlag(RIDE_TYPE_FLAG_HAS_RIDE_GROUPS)) + { + _seenRideType[rideType] = true; + } + else + { + const auto& entry = get_ride_entry(researchItem.entryIndex); + if (entry != nullptr) + { + auto rideGroupIndex = RideGroupManager::GetRideGroupIndex(rideType, entry); + assert(rideGroupIndex < MAX_RIDE_GROUPS_PER_RIDE_TYPE); + _seenRideGroup[rideType * rideGroupIndex] = true; + } + } +} + void research_determine_first_of_type() { _seenRideType.reset(); _seenRideGroup.reset(); - for (auto& researchItem : gResearchItemsInvented) + for (const auto& researchItem : gResearchItemsInvented) { if (researchItem.type != RESEARCH_ENTRY_TYPE_RIDE) continue; @@ -954,39 +980,27 @@ void research_determine_first_of_type() if (rtd.HasFlag(RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY)) continue; + // The last research item will also be present in gResearchItemsInvented. + // Avoid marking its ride type as "invented" prematurely. + if (gResearchLastItem.has_value() && !gResearchLastItem->IsNull() && researchItem.Equals(&gResearchLastItem.value())) + continue; + // The next research item is also present in gResearchItemsInvented, even though it isn't invented yet(!) if (gResearchNextItem.has_value() && !gResearchNextItem->IsNull() && researchItem.Equals(&gResearchNextItem.value())) continue; - if (!rtd.HasFlag(RIDE_TYPE_FLAG_HAS_RIDE_GROUPS)) - { - _seenRideType[rideType] = true; - log_error("Seen %d", rideType); - } - else - { - const auto& entry = get_ride_entry(researchItem.entryIndex); - if (entry != nullptr) - { - auto rideGroupIndex = RideGroupManager::GetRideGroupIndex(rideType, entry); - assert(rideGroupIndex < MAX_RIDE_GROUPS_PER_RIDE_TYPE); - _seenRideGroup[rideType * rideGroupIndex] = true; - log_error("Seen rgi %d ri %d", rideGroupIndex, rideType); - } - } + research_mark_ride_type_as_seen(researchItem); } if (gResearchLastItem.has_value()) { - auto tmpVal = gResearchLastItem.value(); - research_update_first_of_type(&tmpVal); - gResearchLastItem = tmpVal; + research_update_first_of_type(&gResearchLastItem.value()); + research_mark_ride_type_as_seen(gResearchLastItem.value()); } if (gResearchNextItem.has_value()) { - auto tmpVal = gResearchNextItem.value(); - research_update_first_of_type(&tmpVal); - gResearchNextItem = tmpVal; + research_update_first_of_type(&gResearchNextItem.value()); + research_mark_ride_type_as_seen(gResearchNextItem.value()); } for (auto& researchItem : gResearchItemsUninvented)