From 274e0f1d6f3b0f2221f064e000acb4e05023bcaf Mon Sep 17 00:00:00 2001 From: Ted John Date: Wed, 28 Apr 2021 23:56:12 +0100 Subject: [PATCH] Fix research importing --- .../windows/EditorInventionsList.cpp | 4 +- src/openrct2/management/Research.cpp | 171 ++++++++++-------- src/openrct2/management/Research.h | 3 +- src/openrct2/rct2/S6Importer.cpp | 59 ------ 4 files changed, 100 insertions(+), 137 deletions(-) diff --git a/src/openrct2-ui/windows/EditorInventionsList.cpp b/src/openrct2-ui/windows/EditorInventionsList.cpp index 5423b56611..911af98b0e 100644 --- a/src/openrct2-ui/windows/EditorInventionsList.cpp +++ b/src/openrct2-ui/windows/EditorInventionsList.cpp @@ -162,7 +162,7 @@ static void move_research_item(ResearchItem* beforeItem, int32_t scrollIndex) { for (size_t i = 0; i < researchList.size(); i++) { - if (researchList[i].Equals(beforeItem)) + if (researchList[i] == *beforeItem) { researchList.insert((researchList.begin() + i), _editorInventionsListDraggedItem); return; @@ -610,7 +610,7 @@ static void window_editor_inventions_list_scrollpaint(rct_window* w, rct_drawpix gfx_filter_rect(dpi, 0, top, boxWidth, bottom, FilterPaletteID::PaletteDarken1); } - if (researchItem.Equals(&_editorInventionsListDraggedItem)) + if (researchItem == _editorInventionsListDraggedItem) continue; // TODO: this parameter by itself produces very light text. diff --git a/src/openrct2/management/Research.cpp b/src/openrct2/management/Research.cpp index 63c3256deb..4f5f2e5e45 100644 --- a/src/openrct2/management/Research.cpp +++ b/src/openrct2/management/Research.cpp @@ -421,7 +421,7 @@ void research_remove(ResearchItem* researchItem) for (auto it = gResearchItemsUninvented.begin(); it != gResearchItemsUninvented.end(); it++) { auto& researchItem2 = *it; - if (researchItem2.Equals(researchItem)) + if (researchItem2 == *researchItem) { gResearchItemsUninvented.erase(it); return; @@ -430,7 +430,7 @@ void research_remove(ResearchItem* researchItem) for (auto it = gResearchItemsInvented.begin(); it != gResearchItemsInvented.end(); it++) { auto& researchItem2 = *it; - if (researchItem2.Equals(researchItem)) + if (researchItem2 == *researchItem) { gResearchItemsInvented.erase(it); return; @@ -731,18 +731,17 @@ void research_remove_flags() } } -void research_fix() +static void research_remove_null_items(std::vector& items) { - // Fix invalid research items - for (auto it = gResearchItemsInvented.begin(); it != gResearchItemsInvented.end();) + for (auto it = items.begin(); it != items.end();) { auto& researchItem = *it; if (researchItem.type == Research::EntryType::Ride) { - rct_ride_entry* rideEntry = get_ride_entry(researchItem.entryIndex); + const auto* rideEntry = get_ride_entry(researchItem.entryIndex); if (rideEntry == nullptr) { - it = gResearchItemsInvented.erase(it); + it = items.erase(it); } else { @@ -751,10 +750,10 @@ void research_fix() } else { - rct_scenery_group_entry* sceneryGroupEntry = get_scenery_group_entry(researchItem.entryIndex); + const auto* sceneryGroupEntry = get_scenery_group_entry(researchItem.entryIndex); if (sceneryGroupEntry == nullptr) { - it = gResearchItemsInvented.erase(it); + it = items.erase(it); } else { @@ -762,74 +761,96 @@ void research_fix() } } } - for (auto it = gResearchItemsUninvented.begin(); it != gResearchItemsUninvented.end();) +} + +static void research_mark_item_as_researched(const ResearchItem& item) +{ + if (item.type == Research::EntryType::Ride) { - auto& researchItem = *it; - if (researchItem.type == Research::EntryType::Ride) + const auto* rideEntry = get_ride_entry(item.entryIndex); + if (rideEntry != nullptr) { - rct_ride_entry* rideEntry = get_ride_entry(researchItem.entryIndex); - if (rideEntry == nullptr) + ride_entry_set_invented(item.entryIndex); + for (auto rideType : rideEntry->ride_type) { - it = gResearchItemsUninvented.erase(it); - } - else - { - it++; - } - } - else - { - rct_scenery_group_entry* sceneryGroupEntry = get_scenery_group_entry(researchItem.entryIndex); - if (sceneryGroupEntry == nullptr) - { - it = gResearchItemsUninvented.erase(it); - } - else - { - it++; - } - } - } - - research_update_uncompleted_types(); - if (gResearchUncompletedCategories == 0) - gResearchProgressStage = RESEARCH_STAGE_FINISHED_ALL; - - // Sometimes ride entries are not in the research table. - // If all research is done, simply insert all of them as researched. - // For good measure, also include scenery groups. - if (gResearchProgressStage == RESEARCH_STAGE_FINISHED_ALL) - { - for (ObjectEntryIndex i = 0; i < MAX_RIDE_OBJECTS; i++) - { - const rct_ride_entry* rideEntry = get_ride_entry(i); - - if (rideEntry != nullptr) - { - research_insert_ride_entry(i, true); - ride_entry_set_invented(i); - - for (uint8_t j = 0; j < MAX_RIDE_TYPES_PER_RIDE_ENTRY; j++) + if (rideType != RIDE_TYPE_NULL) { - uint32_t rideType = rideEntry->ride_type[j]; - if (rideType != RIDE_TYPE_NULL) - { - ride_type_set_invented(rideEntry->ride_type[j]); - } + ride_type_set_invented(rideType); } } } - - for (uint8_t i = 0; i < MAX_SCENERY_GROUP_OBJECTS; i++) + } + else if (item.type == Research::EntryType::Scenery) + { + const auto sgEntry = get_scenery_group_entry(item.entryIndex); + if (sgEntry != nullptr) { - const rct_scenery_group_entry* groupEntry = get_scenery_group_entry(i); - - if (groupEntry != nullptr) - research_insert_scenery_group_entry(i, true); + for (auto i = 0; i < sgEntry->entry_count; i++) + { + auto sceneryEntryIndex = sgEntry->scenery_entries[i]; + scenery_set_invented(sceneryEntryIndex); + } } } } +static void research_rebuild_invented_tables() +{ + set_every_ride_type_not_invented(); + set_every_ride_entry_invented(); + set_every_ride_entry_not_invented(); + set_all_scenery_items_not_invented(); + for (const auto& item : gResearchItemsInvented) + { + // Ignore item, if the research of it is in progress + if (gResearchProgressStage == RESEARCH_STAGE_DESIGNING || gResearchProgressStage == RESEARCH_STAGE_COMPLETING_DESIGN) + { + if (item == gResearchNextItem) + { + continue; + } + } + + research_mark_item_as_researched(item); + } +} + +static void research_add_all_missing_items(bool isResearched) +{ + for (ObjectEntryIndex i = 0; i < MAX_RIDE_OBJECTS; i++) + { + const auto* rideEntry = get_ride_entry(i); + if (rideEntry != nullptr) + { + research_insert_ride_entry(i, isResearched); + } + } + + for (ObjectEntryIndex i = 0; i < MAX_SCENERY_GROUP_OBJECTS; i++) + { + const auto* groupEntry = get_scenery_group_entry(i); + if (groupEntry != nullptr) + { + research_insert_scenery_group_entry(i, isResearched); + } + } +} + +void research_fix() +{ + // Remove null entries from the research list + research_remove_null_items(gResearchItemsInvented); + research_remove_null_items(gResearchItemsUninvented); + + // Add missing entries to the research list + // If research is complete, mark all the missing items as available + research_add_all_missing_items(gResearchProgressStage == RESEARCH_STAGE_FINISHED_ALL); + + // Now rebuild all the tables that say whether a ride or scenery item is invented + research_rebuild_invented_tables(); + research_update_uncompleted_types(); +} + void research_items_make_all_unresearched() { gResearchItemsUninvented.insert( @@ -870,23 +891,18 @@ void ResearchItem::SetNull() entryIndex = OBJECT_ENTRY_INDEX_NULL; } -bool ResearchItem::Equals(const ResearchItem* otherItem) const -{ - return (entryIndex == otherItem->entryIndex && baseRideType == otherItem->baseRideType && type == otherItem->type); -} - bool ResearchItem::Exists() const { for (auto const& researchItem : gResearchItemsUninvented) { - if (researchItem.Equals(this)) + if (researchItem == *this) { return true; } } for (auto const& researchItem : gResearchItemsInvented) { - if (researchItem.Equals(this)) + if (researchItem == *this) { return true; } @@ -932,6 +948,11 @@ rct_string_id ResearchItem::GetCategoryName() const return _researchCategoryNames[categoryValue]; } +bool ResearchItem::operator==(const ResearchItem& rhs) const +{ + return (entryIndex == rhs.entryIndex && baseRideType == rhs.baseRideType && type == rhs.type); +} + static std::bitset _seenRideType = {}; static void research_update_first_of_type(ResearchItem* researchItem) @@ -988,11 +1009,11 @@ void research_determine_first_of_type() // 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())) + if (gResearchLastItem.has_value() && !gResearchLastItem->IsNull() && researchItem == *gResearchLastItem) continue; // The next research item is (sometimes?) also present in gResearchItemsInvented, even though it isn't invented yet(!) - if (gResearchNextItem.has_value() && !gResearchNextItem->IsNull() && researchItem.Equals(&gResearchNextItem.value())) + if (gResearchNextItem.has_value() && !gResearchNextItem->IsNull() && researchItem == *gResearchNextItem) continue; research_mark_ride_type_as_seen(researchItem); @@ -1012,7 +1033,7 @@ void research_determine_first_of_type() for (auto& researchItem : gResearchItemsUninvented) { // The next research item is (sometimes?) also present in gResearchItemsUninvented - if (gResearchNextItem.has_value() && !gResearchNextItem->IsNull() && researchItem.Equals(&gResearchNextItem.value())) + if (gResearchNextItem.has_value() && !gResearchNextItem->IsNull() && researchItem == *gResearchNextItem) { // Copy the "first of type" flag. researchItem.flags = gResearchNextItem->flags; diff --git a/src/openrct2/management/Research.h b/src/openrct2/management/Research.h index c3a730bb4c..ba0560a031 100644 --- a/src/openrct2/management/Research.h +++ b/src/openrct2/management/Research.h @@ -62,7 +62,6 @@ struct ResearchItem bool IsNull() const; void SetNull(); - bool Equals(const ResearchItem* otherItem) const; bool Exists() const; bool IsAlwaysResearched() const; rct_string_id GetName() const; @@ -127,6 +126,8 @@ struct ResearchItem category = static_cast(oldResearchItem.category); } } + + bool operator==(const ResearchItem& rhs) const; }; // Only used to mark as null nowadays. Deprecated. TODO: remove. diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index da5b303ab6..be77058cc7 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -237,8 +237,6 @@ public: gGuestChangeModifier = _s6.guest_count_change_modifier; gResearchFundingLevel = _s6.current_research_level; // pad_01357400 - ImportResearchedRideTypes(); - ImportResearchedRideEntries(); // _s6.researched_track_types_a // _s6.researched_track_types_b @@ -259,8 +257,6 @@ public: gStaffMechanicColour = _s6.mechanic_colour; gStaffSecurityColour = _s6.security_colour; - ImportResearchedSceneryItems(); - gParkRating = _s6.park_rating; std::memcpy(gParkRatingHistory, _s6.park_rating_history, sizeof(_s6.park_rating_history)); @@ -861,61 +857,6 @@ public: } } - void ImportResearchedRideTypes() - { - set_every_ride_type_not_invented(); - - for (int32_t rideType = 0; rideType < RCT2_RIDE_TYPE_COUNT; rideType++) - { - int32_t quadIndex = rideType >> 5; - int32_t bitIndex = rideType & 0x1F; - bool invented = (_s6.researched_ride_types[quadIndex] & (1UL << bitIndex)); - - if (invented) - ride_type_set_invented(rideType); - } - } - - void ImportResearchedRideEntries() - { - set_every_ride_entry_not_invented(); - - for (int32_t rideEntryIndex = 0; rideEntryIndex < MAX_RIDE_OBJECTS; rideEntryIndex++) - { - int32_t quadIndex = rideEntryIndex >> 5; - int32_t bitIndex = rideEntryIndex & 0x1F; - bool invented = (_s6.researched_ride_entries[quadIndex] & (1UL << bitIndex)); - - if (invented) - ride_entry_set_invented(rideEntryIndex); - } - } - - void ImportResearchedSceneryItems() - { - set_all_scenery_items_not_invented(); - - for (uint16_t sceneryEntryIndex = 0; sceneryEntryIndex < RCT2_MAX_RESEARCHED_SCENERY_ITEMS; sceneryEntryIndex++) - { - int32_t quadIndex = sceneryEntryIndex >> 5; - int32_t bitIndex = sceneryEntryIndex & 0x1F; - bool invented = (_s6.researched_scenery_items[quadIndex] & (1UL << bitIndex)); - - if (invented) - { - ScenerySelection scenerySelection = { static_cast((sceneryEntryIndex >> 8) & 0xFF), - static_cast(sceneryEntryIndex & 0xFF) }; - - // SV6 has room for 8 types of scenery, and sometimes scenery of non-existing types 5 and 6 is marked as - // "invented". - if (scenerySelection.SceneryType < SCENERY_TYPE_COUNT) - { - scenery_set_invented(scenerySelection); - } - } - } - } - void ImportResearchList() { bool invented = true;