diff --git a/src/scenario.h b/src/scenario.h index 339e4b088f..41d3ffa3b4 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -434,6 +434,7 @@ typedef struct { uint8 category; uint8 source_game; sint16 source_index; + uint16 sc_id; // Objective uint8 objective_type; @@ -448,6 +449,7 @@ typedef struct { typedef struct { const utf8 *title; + uint8 id; uint8 source; sint32 index; uint8 category; diff --git a/src/scenario_list.c b/src/scenario_list.c index 2efe09d81b..3604a3d806 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -170,10 +170,12 @@ static void scenario_list_add(const utf8 *path, uint64 timestamp) // Look up and store information regarding the origins of this scenario. source_desc desc; if (scenario_get_source_desc(newEntry->name, &desc)) { + newEntry->sc_id = desc.id; newEntry->source_index = desc.index; newEntry->source_game = desc.source; newEntry->category = desc.category; } else { + newEntry->sc_id = SC_UNIDENTIFIED; newEntry->source_index = -1; if (newEntry->category == SCENARIO_CATEGORY_REAL) { newEntry->source_game = SCENARIO_SOURCE_REAL; diff --git a/src/scenario_sources.c b/src/scenario_sources.c index 7ad8858213..90fddcd7e8 100644 --- a/src/scenario_sources.c +++ b/src/scenario_sources.c @@ -219,6 +219,7 @@ bool scenario_get_source_desc(const utf8 *name, source_desc *outDesc) const scenario_title_desc *desc = &ScenarioTitlesBySource[i].titles[j]; if (_strcmpi(name, desc->title) == 0) { outDesc->title = desc->title; + outDesc->id = desc->id; outDesc->source = i; outDesc->index = currentIndex; outDesc->category = desc->category; @@ -228,6 +229,8 @@ bool scenario_get_source_desc(const utf8 *name, source_desc *outDesc) } } + outDesc->title = NULL; + outDesc->id = SC_UNIDENTIFIED; outDesc->source = SCENARIO_SOURCE_OTHER; outDesc->index = -1; outDesc->category = SCENARIO_CATEGORY_OTHER; @@ -244,6 +247,7 @@ bool scenario_get_source_desc_by_id(uint8 id, source_desc *outDesc) const scenario_title_desc *desc = &ScenarioTitlesBySource[i].titles[j]; if (id == desc->id) { outDesc->title = desc->title; + outDesc->id = desc->id; outDesc->source = i; outDesc->index = currentIndex; outDesc->category = desc->category; @@ -253,6 +257,8 @@ bool scenario_get_source_desc_by_id(uint8 id, source_desc *outDesc) } } + outDesc->title = NULL; + outDesc->id = SC_UNIDENTIFIED; outDesc->source = SCENARIO_SOURCE_OTHER; outDesc->index = -1; outDesc->category = SCENARIO_CATEGORY_OTHER; diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index 1b6e706acf..373c2d58ff 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -506,6 +506,11 @@ static void initialise_list_items(rct_window *w) int length = 0; _listItems = malloc(capacity * sizeof(sc_list_item)); + // Mega park unlock + const uint32 rct1RequiredCompletedScenarios = (1 << SC_MEGA_PARK) - 1; + uint32 rct1CompletedScenarios = 0; + int megaParkListItemIndex = -1; + int numUnlocks = INITIAL_NUM_UNLOCKED_SCENARIOS; uint8 currentHeading = UINT8_MAX; for (int i = 0; i < gScenarioListCount; i++) { @@ -555,6 +560,16 @@ static void initialise_list_items(rct_window *w) listItem->scenario.is_locked = numUnlocks <= 0; if (scenario->highscore == NULL) { numUnlocks--; + } else { + // Mark RCT1 scenario as completed + if (scenario->sc_id < SC_MEGA_PARK) { + rct1CompletedScenarios |= 1 << scenario->sc_id; + } + } + + // If scenario is Mega Park, keep a reference to it + if (scenario->sc_id == SC_MEGA_PARK) { + megaParkListItemIndex = length - 1; } } else { listItem->scenario.is_locked = false; @@ -564,6 +579,31 @@ static void initialise_list_items(rct_window *w) length++; _listItems = realloc(_listItems, length * sizeof(sc_list_item)); _listItems[length - 1].type = LIST_ITEM_TYPE_END; + + // Mega park handling + if (megaParkListItemIndex != -1) { + bool megaParkLocked = (rct1CompletedScenarios & rct1RequiredCompletedScenarios) != rct1RequiredCompletedScenarios; + _listItems[megaParkListItemIndex].scenario.is_locked = megaParkLocked; +#ifdef HIDE_MEGA_PARK + if (megaParkLocked) { + // Remove mega park + int remainingItems = length - megaParkListItemIndex - 1; + memmove(&_listItems[megaParkListItemIndex], &_listItems[megaParkListItemIndex + 1], remainingItems); + + // Remove empty headings + int i = 0; + for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) { + if (listItem->type == LIST_ITEM_TYPE_HEADING && (listItem + 1)->type != LIST_ITEM_TYPE_SCENARIO) { + remainingItems = length - i - 1; + memmove(&_listItems[i], &_listItems[i + 1], remainingItems); + listItem--; + } else { + i++; + } + } + } +#endif + } } static bool is_scenario_visible(rct_window *w, scenario_index_entry *scenario)