diff --git a/src/openrct2-ui/windows/NewRide.cpp b/src/openrct2-ui/windows/NewRide.cpp index e6a9a0f672..33eab91ade 100644 --- a/src/openrct2-ui/windows/NewRide.cpp +++ b/src/openrct2-ui/windows/NewRide.cpp @@ -705,7 +705,7 @@ static void window_new_ride_mouseup(rct_window* w, rct_widgetindex widgetIndex) window_close(w); break; case WIDX_LAST_DEVELOPMENT_BUTTON: - news_item_open_subject(NEWS_ITEM_RESEARCH, gResearchLastItem.rawValue); + news_item_open_subject(NEWS_ITEM_RESEARCH, gResearchLastItem->rawValue); break; case WIDX_RESEARCH_FUNDING_BUTTON: context_open_window_view(WV_FINANCES_RESEARCH); @@ -816,9 +816,9 @@ static void window_new_ride_invalidate(rct_window* w) if (_windowNewRideCurrentTab == WINDOW_NEW_RIDE_PAGE_RESEARCH) { window_new_ride_widgets[WIDX_LAST_DEVELOPMENT_BUTTON].type = WWT_EMPTY; - if (gResearchLastItem.rawValue != RESEARCHED_ITEMS_SEPARATOR) + if (gResearchLastItem.has_value()) { - uint8_t type = gResearchLastItem.type; + uint8_t type = gResearchLastItem->type; window_new_ride_widgets[WIDX_LAST_DEVELOPMENT_BUTTON].type = WWT_FLATBTN; window_new_ride_widgets[WIDX_LAST_DEVELOPMENT_BUTTON].image = (type == RESEARCH_ENTRY_TYPE_RIDE) ? SPR_NEW_RIDE : SPR_NEW_SCENERY; diff --git a/src/openrct2-ui/windows/Research.cpp b/src/openrct2-ui/windows/Research.cpp index 0e991b20a3..524314e549 100644 --- a/src/openrct2-ui/windows/Research.cpp +++ b/src/openrct2-ui/windows/Research.cpp @@ -280,7 +280,7 @@ static void window_research_development_mouseup(rct_window* w, rct_widgetindex w window_research_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_LAST_DEVELOPMENT_BUTTON: - news_item_open_subject(NEWS_ITEM_RESEARCH, gResearchLastItem.rawValue); + news_item_open_subject(NEWS_ITEM_RESEARCH, gResearchLastItem->rawValue); break; } } @@ -312,9 +312,9 @@ static void window_research_development_invalidate(rct_window* w) window_research_set_pressed_tab(w); window_research_development_widgets[WIDX_LAST_DEVELOPMENT_BUTTON].type = WWT_EMPTY; - if (gResearchLastItem.rawValue != RESEARCHED_ITEMS_SEPARATOR) + if (gResearchLastItem.has_value()) { - uint8_t type = gResearchLastItem.type; + uint8_t type = gResearchLastItem->type; window_research_development_widgets[WIDX_LAST_DEVELOPMENT_BUTTON].type = WWT_FLATBTN; window_research_development_widgets[WIDX_LAST_DEVELOPMENT_BUTTON].image = type == RESEARCH_ENTRY_TYPE_RIDE ? SPR_NEW_RIDE @@ -362,10 +362,10 @@ void window_research_development_page_paint(rct_window* w, rct_drawpixelinfo* dp stringId = STR_RESEARCH_UNKNOWN; if (gResearchProgressStage != RESEARCH_STAGE_INITIAL_RESEARCH) { - stringId = ResearchCategoryNames[gResearchNextItem.category]; + stringId = ResearchCategoryNames[gResearchNextItem->category]; if (gResearchProgressStage != RESEARCH_STAGE_DESIGNING) { - stringId = gResearchNextItem.GetName(); + stringId = gResearchNextItem->GetName(); } } gfx_draw_string_left_wrapped(dpi, &stringId, x, y, 296, STR_RESEARCH_TYPE_LABEL, COLOUR_BLACK); @@ -397,10 +397,10 @@ void window_research_development_page_paint(rct_window* w, rct_drawpixelinfo* dp y = w->y + w->widgets[WIDX_LAST_DEVELOPMENT_GROUP + baseWidgetIndex].top + 12; rct_string_id lastDevelopmentFormat; - if (gResearchLastItem.rawValue != RESEARCHED_ITEMS_SEPARATOR) + if (gResearchLastItem.has_value()) { - stringId = gResearchLastItem.GetName(); - uint8_t type = gResearchLastItem.type; + stringId = gResearchLastItem->GetName(); + uint8_t type = gResearchLastItem->type; lastDevelopmentFormat = (type == RESEARCH_ENTRY_TYPE_RIDE) ? STR_RESEARCH_RIDE_LABEL : STR_RESEARCH_SCENERY_LABEL; gfx_draw_string_left_wrapped(dpi, &stringId, x, y, 266, lastDevelopmentFormat, COLOUR_BLACK); diff --git a/src/openrct2/management/Research.cpp b/src/openrct2/management/Research.cpp index 8c97d8a708..0b0501ba7b 100644 --- a/src/openrct2/management/Research.cpp +++ b/src/openrct2/management/Research.cpp @@ -46,10 +46,10 @@ uint8_t gResearchFundingLevel; uint8_t gResearchPriorities; uint16_t gResearchProgress; uint8_t gResearchProgressStage; -ResearchItem gResearchLastItem; +std::optional gResearchLastItem; uint8_t gResearchExpectedMonth; uint8_t gResearchExpectedDay; -ResearchItem gResearchNextItem; +std::optional gResearchNextItem; // 0x01358844[500] ResearchItem gResearchItems[MAX_RESEARCH_ITEMS]; @@ -368,7 +368,7 @@ void research_update() research_invalidate_related_windows(); break; case RESEARCH_STAGE_COMPLETING_DESIGN: - research_finish_item(&gResearchNextItem); + research_finish_item(&*gResearchNextItem); gResearchProgress = 0; gResearchProgressStage = RESEARCH_STAGE_INITIAL_RESEARCH; research_calculate_expected_date(); @@ -400,7 +400,7 @@ void research_reset_current_item() research_finish_item(&researchItem); } - gResearchLastItem.rawValue = RESEARCHED_ITEMS_SEPARATOR; + gResearchLastItem = std::nullopt; gResearchProgressStage = RESEARCH_STAGE_INITIAL_RESEARCH; gResearchProgress = 0; } diff --git a/src/openrct2/management/Research.h b/src/openrct2/management/Research.h index 3459afa376..1b8d55adb4 100644 --- a/src/openrct2/management/Research.h +++ b/src/openrct2/management/Research.h @@ -10,6 +10,7 @@ #pragma once #include "../common.h" +#include "../core/Optional.hpp" #include "../object/ObjectLimits.h" #include "../ride/Ride.h" @@ -99,8 +100,8 @@ extern uint16_t gResearchProgress; extern uint8_t gResearchProgressStage; extern uint8_t gResearchExpectedMonth; extern uint8_t gResearchExpectedDay; -extern ResearchItem gResearchLastItem; -extern ResearchItem gResearchNextItem; +extern std::optional gResearchLastItem; +extern std::optional gResearchNextItem; extern std::vector gResearchItemsUninvented; extern std::vector gResearchItemsInvented; diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index e1e8c79e30..a6cd533629 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -2388,13 +2388,29 @@ private: gResearchExpectedDay = _s4.next_research_expected_day; gResearchExpectedMonth = _s4.next_research_expected_month; - ConvertResearchEntry(&gResearchNextItem, _s4.next_research_item, _s4.next_research_type); - if (gResearchNextItem.IsInventedEndMarker()) + if (_s4.last_research_flags == 0xFF) { + gResearchLastItem = std::nullopt; + } + else + { + ResearchItem researchItem = {}; + ConvertResearchEntry(&researchItem, _s4.last_research_item, _s4.last_research_type); + gResearchLastItem = researchItem; + } + + if (_s4.next_research_flags == 0xFF) + { + gResearchNextItem = std::nullopt; gResearchProgressStage = RESEARCH_STAGE_INITIAL_RESEARCH; gResearchProgress = 0; } - ConvertResearchEntry(&gResearchLastItem, _s4.last_research_item, _s4.last_research_type); + else + { + ResearchItem researchItem = {}; + ConvertResearchEntry(&researchItem, _s4.next_research_item, _s4.next_research_type); + gResearchNextItem = researchItem; + } } static std::bitset GetRideTypesPresentInResearchList( diff --git a/src/openrct2/rct2/S6Exporter.cpp b/src/openrct2/rct2/S6Exporter.cpp index 5567f98043..942e7c7816 100644 --- a/src/openrct2/rct2/S6Exporter.cpp +++ b/src/openrct2/rct2/S6Exporter.cpp @@ -241,11 +241,24 @@ void S6Exporter::Export() _s6.active_research_types = gResearchPriorities; _s6.research_progress_stage = gResearchProgressStage; - _s6.last_researched_item_subject = gResearchLastItem.rawValue; + if (gResearchLastItem.has_value()) + _s6.last_researched_item_subject = gResearchLastItem->rawValue; + else + _s6.last_researched_item_subject = -1; // pad_01357CF8 - _s6.next_research_item = gResearchNextItem.rawValue; _s6.research_progress = gResearchProgress; - _s6.next_research_category = gResearchNextItem.category; + + if (gResearchNextItem.has_value()) + { + _s6.next_research_item = gResearchNextItem->rawValue; + _s6.next_research_category = gResearchNextItem->category; + } + else + { + _s6.next_research_item = -1; + _s6.next_research_category = 0; + } + _s6.next_research_expected_day = gResearchExpectedDay; _s6.next_research_expected_month = gResearchExpectedMonth; _s6.guest_initial_happiness = gGuestInitialHappiness; diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 71b659f886..e64ce58500 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -262,11 +262,18 @@ public: gResearchPriorities = _s6.active_research_types; gResearchProgressStage = _s6.research_progress_stage; - gResearchLastItem.rawValue = _s6.last_researched_item_subject; + if (_s6.last_researched_item_subject != RCT12_RESEARCHED_ITEMS_SEPARATOR) + gResearchLastItem = std::make_optional( + ResearchItem{ _s6.last_researched_item_subject, RESEARCH_CATEGORY_TRANSPORT }); + else + gResearchLastItem = std::nullopt; // pad_01357CF8 - gResearchNextItem.rawValue = _s6.next_research_item; + if (_s6.next_research_item != RCT12_RESEARCHED_ITEMS_SEPARATOR) + gResearchNextItem = std::make_optional(ResearchItem{ _s6.next_research_item, _s6.next_research_category }); + else + gResearchNextItem = std::nullopt; + gResearchProgress = _s6.research_progress; - gResearchNextItem.category = _s6.next_research_category; gResearchExpectedDay = _s6.next_research_expected_day; gResearchExpectedMonth = _s6.next_research_expected_month; gGuestInitialHappiness = _s6.guest_initial_happiness; diff --git a/src/openrct2/scenario/Scenario.h b/src/openrct2/scenario/Scenario.h index 56e06876e0..ee3d2f7e84 100644 --- a/src/openrct2/scenario/Scenario.h +++ b/src/openrct2/scenario/Scenario.h @@ -162,9 +162,9 @@ struct rct_s6_data // SC6[10] uint8_t active_research_types; uint8_t research_progress_stage; - uint32_t last_researched_item_subject; + int32_t last_researched_item_subject; uint8_t pad_01357CF8[1000]; - uint32_t next_research_item; + int32_t next_research_item; uint16_t research_progress; uint8_t next_research_category; uint8_t next_research_expected_day; diff --git a/src/openrct2/world/Park.cpp b/src/openrct2/world/Park.cpp index 6d342f2804..e11bb9ff16 100644 --- a/src/openrct2/world/Park.cpp +++ b/src/openrct2/world/Park.cpp @@ -268,7 +268,7 @@ void Park::Initialise() gParkRating = 0; _guestGenerationProbability = 0; gTotalRideValueForMoney = 0; - gResearchLastItem.rawValue = RESEARCHED_ITEMS_SEPARATOR; + gResearchLastItem = std::nullopt; gMarketingCampaigns.clear(); research_reset_items();