Fix research importing

This commit is contained in:
Ted John 2021-04-28 23:56:12 +01:00
parent 8f8ff7a04d
commit 274e0f1d6f
4 changed files with 100 additions and 137 deletions

View File

@ -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.

View File

@ -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<ResearchItem>& 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<RIDE_TYPE_COUNT> _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;

View File

@ -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<ResearchCategory>(oldResearchItem.category);
}
}
bool operator==(const ResearchItem& rhs) const;
};
// Only used to mark as null nowadays. Deprecated. TODO: remove.

View File

@ -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<uint8_t>((sceneryEntryIndex >> 8) & 0xFF),
static_cast<uint16_t>(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;