diff --git a/src/openrct2/scenario/Scenario.cpp b/src/openrct2/scenario/Scenario.cpp index c42215b3b6..7c05456d97 100644 --- a/src/openrct2/scenario/Scenario.cpp +++ b/src/openrct2/scenario/Scenario.cpp @@ -7,12 +7,17 @@ * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ -#include "../audio/audio.h" +#include "Scenario.h" + #include "../Cheats.h" -#include "../config/Config.h" +#include "../Context.h" #include "../FileClassifier.h" #include "../Game.h" #include "../GameState.h" +#include "../OpenRCT2.h" +#include "../ParkImporter.h" +#include "../audio/audio.h" +#include "../config/Config.h" #include "../interface/Viewport.h" #include "../localisation/Date.h" #include "../localisation/Localisation.h" @@ -24,14 +29,14 @@ #include "../network/network.h" #include "../object/Object.h" #include "../object/ObjectList.h" -#include "../OpenRCT2.h" -#include "../ParkImporter.h" #include "../peep/Staff.h" #include "../platform/platform.h" #include "../rct1/RCT1.h" #include "../ride/Ride.h" +#include "../ride/Track.h" #include "../util/SawyerCoding.h" #include "../util/Util.h" +#include "../windows/Intent.h" #include "../world/Climate.h" #include "../world/Map.h" #include "../world/Park.h" @@ -40,20 +45,11 @@ #include "../world/Water.h" #include "ScenarioRepository.h" #include "ScenarioSources.h" -#include "Scenario.h" -#include "../Context.h" -#include "../ride/Track.h" -#include "../windows/Intent.h" const rct_string_id ScenarioCategoryStringIds[SCENARIO_CATEGORY_COUNT] = { - STR_BEGINNER_PARKS, - STR_CHALLENGING_PARKS, - STR_EXPERT_PARKS, - STR_REAL_PARKS, - STR_OTHER_PARKS, + STR_BEGINNER_PARKS, STR_CHALLENGING_PARKS, STR_EXPERT_PARKS, STR_REAL_PARKS, STR_OTHER_PARKS, - STR_DLC_PARKS, - STR_BUILD_YOUR_OWN_PARKS, + STR_DLC_PARKS, STR_BUILD_YOUR_OWN_PARKS, }; rct_s6_info gS6Info; @@ -94,7 +90,6 @@ void scenario_begin() gScenarioSrand0 ^= platform_get_ticks(); gScenarioSrand1 ^= platform_get_ticks(); - gParkFlags &= ~PARK_FLAGS_NO_MONEY; if (gParkFlags & PARK_FLAGS_NO_MONEY_SCENARIO) gParkFlags |= PARK_FLAGS_NO_MONEY; @@ -119,21 +114,27 @@ void scenario_begin() scenario_normalise_name(normalisedName, sizeof(normalisedName), gS6Info.name); rct_string_id localisedStringIds[3]; - if (language_get_localised_scenario_strings(normalisedName, localisedStringIds)) { - if (localisedStringIds[0] != STR_NONE) { + if (language_get_localised_scenario_strings(normalisedName, localisedStringIds)) + { + if (localisedStringIds[0] != STR_NONE) + { safe_strcpy(gScenarioName, language_get_string(localisedStringIds[0]), 32); } - if (localisedStringIds[1] != STR_NONE) { + if (localisedStringIds[1] != STR_NONE) + { park_set_name(language_get_string(localisedStringIds[1])); } - if (localisedStringIds[2] != STR_NONE) { + if (localisedStringIds[2] != STR_NONE) + { safe_strcpy(gScenarioDetails, language_get_string(localisedStringIds[2]), 256); } } - else { - auto stex = (rct_stex_entry *)object_entry_get_chunk(OBJECT_TYPE_SCENARIO_TEXT, 0); - if (stex != nullptr) { - char *buffer = gCommonStringFormatBuffer; + else + { + auto stex = (rct_stex_entry*)object_entry_get_chunk(OBJECT_TYPE_SCENARIO_TEXT, 0); + if (stex != nullptr) + { + char* buffer = gCommonStringFormatBuffer; // Set localised park name format_string(buffer, 256, stex->park_name, nullptr); @@ -180,7 +181,8 @@ void scenario_begin() gParkRatingCasualtyPenalty = 0; // Open park with free entry when there is no money - if (gParkFlags & PARK_FLAGS_NO_MONEY) { + if (gParkFlags & PARK_FLAGS_NO_MONEY) + { gParkFlags |= PARK_FLAGS_PARK_OPEN; gParkEntranceFee = 0; } @@ -231,7 +233,7 @@ void scenario_success() * * rct2: 0x006695E8 */ -void scenario_success_submit_name(const char *name) +void scenario_success_submit_name(const char* name) { if (scenario_repository_try_record_highscore(gScenarioFileName, gScenarioCompanyValueRecord, name)) { @@ -250,14 +252,17 @@ static void scenario_entrance_fee_too_high_check() money16 totalRideValueForMoney = gTotalRideValueForMoney; money16 max_fee = totalRideValueForMoney + (totalRideValueForMoney / 2); - if ((gParkFlags & PARK_FLAGS_PARK_OPEN) && park_get_entrance_fee() > max_fee) { - for (int32_t i = 0; i < MAX_PARK_ENTRANCES && gParkEntrances[i].x != LOCATION_NULL; i++) { + if ((gParkFlags & PARK_FLAGS_PARK_OPEN) && park_get_entrance_fee() > max_fee) + { + for (int32_t i = 0; i < MAX_PARK_ENTRANCES && gParkEntrances[i].x != LOCATION_NULL; i++) + { x = gParkEntrances[i].x + 16; y = gParkEntrances[i].y + 16; } uint32_t packed_xy = (y << 16) | x; - if (gConfigNotifications.park_warnings) { + if (gConfigNotifications.park_warnings) + { news_item_add_to_queue(NEWS_ITEM_BLANK, STR_ENTRANCE_FEE_TOO_HI, packed_xy); } } @@ -265,31 +270,34 @@ static void scenario_entrance_fee_too_high_check() void scenario_autosave_check() { - if (gLastAutoSaveUpdate == AUTOSAVE_PAUSE) return; + if (gLastAutoSaveUpdate == AUTOSAVE_PAUSE) + return; // Milliseconds since last save uint32_t timeSinceSave = platform_get_ticks() - gLastAutoSaveUpdate; bool shouldSave = false; - switch (gConfigGeneral.autosave_frequency) { - case AUTOSAVE_EVERY_MINUTE: - shouldSave = timeSinceSave >= 1 * 60 * 1000; - break; - case AUTOSAVE_EVERY_5MINUTES: - shouldSave = timeSinceSave >= 5 * 60 * 1000; - break; - case AUTOSAVE_EVERY_15MINUTES: - shouldSave = timeSinceSave >= 15 * 60 * 1000; - break; - case AUTOSAVE_EVERY_30MINUTES: - shouldSave = timeSinceSave >= 30 * 60 * 1000; - break; - case AUTOSAVE_EVERY_HOUR: - shouldSave = timeSinceSave >= 60 * 60 * 1000; - break; + switch (gConfigGeneral.autosave_frequency) + { + case AUTOSAVE_EVERY_MINUTE: + shouldSave = timeSinceSave >= 1 * 60 * 1000; + break; + case AUTOSAVE_EVERY_5MINUTES: + shouldSave = timeSinceSave >= 5 * 60 * 1000; + break; + case AUTOSAVE_EVERY_15MINUTES: + shouldSave = timeSinceSave >= 15 * 60 * 1000; + break; + case AUTOSAVE_EVERY_30MINUTES: + shouldSave = timeSinceSave >= 30 * 60 * 1000; + break; + case AUTOSAVE_EVERY_HOUR: + shouldSave = timeSinceSave >= 60 * 60 * 1000; + break; } - if (shouldSave) { + if (shouldSave) + { gLastAutoSaveUpdate = AUTOSAVE_PAUSE; game_autosave(); } @@ -299,18 +307,19 @@ static void scenario_day_update() { finance_update_daily_profit(); peep_update_days_in_queue(); - switch (gScenarioObjectiveType) { - case OBJECTIVE_10_ROLLERCOASTERS: - case OBJECTIVE_GUESTS_AND_RATING: - case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: - case OBJECTIVE_FINISH_5_ROLLERCOASTERS: - case OBJECTIVE_REPLAY_LOAN_AND_PARK_VALUE: - scenario_objective_check(); - break; - default: - if (gConfigGeneral.allow_early_completion) + switch (gScenarioObjectiveType) + { + case OBJECTIVE_10_ROLLERCOASTERS: + case OBJECTIVE_GUESTS_AND_RATING: + case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: + case OBJECTIVE_FINISH_5_ROLLERCOASTERS: + case OBJECTIVE_REPLAY_LOAN_AND_PARK_VALUE: scenario_objective_check(); - break; + break; + default: + if (gConfigGeneral.allow_early_completion) + scenario_objective_check(); + break; } // Lower the casualty penalty @@ -333,11 +342,13 @@ static void scenario_week_update() ride_check_all_reachable(); ride_update_favourited_stat(); - auto water_type = (rct_water_type *)object_entry_get_chunk(OBJECT_TYPE_WATER, 0); + auto water_type = (rct_water_type*)object_entry_get_chunk(OBJECT_TYPE_WATER, 0); - if (month <= MONTH_APRIL && water_type != nullptr && water_type->flags & WATER_FLAGS_ALLOW_DUCKS) { + if (month <= MONTH_APRIL && water_type != nullptr && water_type->flags & WATER_FLAGS_ALLOW_DUCKS) + { // 100 attempts at finding some water to create a few ducks at - for (int32_t i = 0; i < 100; i++) { + for (int32_t i = 0; i < 100; i++) + { if (scenario_create_ducks()) break; } @@ -362,23 +373,34 @@ static void scenario_update_daynight_cycle() float currentDayNightCycle = gDayNightCycle; gDayNightCycle = 0; - if (gScreenFlags == SCREEN_FLAGS_PLAYING && gConfigGeneral.day_night_cycle) { + if (gScreenFlags == SCREEN_FLAGS_PLAYING && gConfigGeneral.day_night_cycle) + { float monthFraction = gDateMonthTicks / (float)0x10000; - if (monthFraction < (1 / 8.0f)) { + if (monthFraction < (1 / 8.0f)) + { gDayNightCycle = 0.0f; - } else if (monthFraction < (3 / 8.0f)) { + } + else if (monthFraction < (3 / 8.0f)) + { gDayNightCycle = (monthFraction - (1 / 8.0f)) / (2 / 8.0f); - } else if (monthFraction < (5 / 8.0f)) { + } + else if (monthFraction < (5 / 8.0f)) + { gDayNightCycle = 1.0f; - } else if (monthFraction < (7 / 8.0f)) { + } + else if (monthFraction < (7 / 8.0f)) + { gDayNightCycle = 1.0f - ((monthFraction - (5 / 8.0f)) / (2 / 8.0f)); - } else { + } + else + { gDayNightCycle = 0.0f; } } // Only update palette if day / night cycle has changed - if (gDayNightCycle != currentDayNightCycle) { + if (gDayNightCycle != currentDayNightCycle) + { platform_update_palette(gGamePalette, 10, 236); } } @@ -425,7 +447,7 @@ static int32_t scenario_create_ducks() x = (x + 64) * 32; y = (y + 64) * 32; - if (!map_is_location_in_park({x, y})) + if (!map_is_location_in_park({ x, y })) return 0; centreWaterZ = (tile_element_height(x, y) >> 16) & 0xFFFF; @@ -436,8 +458,10 @@ static int32_t scenario_create_ducks() x2 = x - (32 * 3); y2 = y - (32 * 3); c = 0; - for (i = 0; i < 7; i++) { - for (j = 0; j < 7; j++) { + for (i = 0; i < 7; i++) + { + for (j = 0; j < 7; j++) + { waterZ = (tile_element_height(x2, y2) >> 16) & 0xFFFF; if (waterZ == centreWaterZ) c++; @@ -456,7 +480,8 @@ static int32_t scenario_create_ducks() x += 16; y += 16; c = (scenario_rand() & 3) + 2; - for (i = 0; i < c; i++) { + for (i = 0; i < c; i++) + { r = scenario_rand(); x2 = (r >> 16) & 0x7F; y2 = (r & 0xFFFF) & 0x7F; @@ -475,10 +500,10 @@ static int32_t scenario_create_ducks() #ifndef DEBUG_DESYNC uint32_t scenario_rand() #else -static FILE *fp = nullptr; -static const char *realm = "LC"; +static FILE* fp = nullptr; +static const char* realm = "LC"; -uint32_t dbg_scenario_rand(const char *file, const char *function, const uint32_t line, const void *data) +uint32_t dbg_scenario_rand(const char* file, const char* function, const uint32_t line, const void* data) #endif { uint32_t originalSrand0 = gScenarioSrand0; @@ -510,7 +535,8 @@ uint32_t dbg_scenario_rand(const char *file, const char *function, const uint32_ { fprintf(fp, "Tick: %d, Rand: %08X - REF: %s:%u %s (%p)\n", gCurrentTicks, gScenarioSrand1, file, line, function, data); } - if (!gInUpdateCode && !gInMapInitCode) { + if (!gInUpdateCode && !gInMapInitCode) + { log_warning("scenario_rand called from outside game update"); assert(false); } @@ -520,7 +546,7 @@ uint32_t dbg_scenario_rand(const char *file, const char *function, const uint32_ } #ifdef DEBUG_DESYNC -void dbg_report_desync(uint32_t tick, uint32_t srand0, uint32_t server_srand0, const char *clientHash, const char *serverHash) +void dbg_report_desync(uint32_t tick, uint32_t srand0, uint32_t server_srand0, const char* clientHash, const char* serverHash) { if (fp == nullptr) { @@ -539,24 +565,29 @@ void dbg_report_desync(uint32_t tick, uint32_t srand0, uint32_t server_srand0, c { const bool sprites_mismatch = serverHash[0] != '\0' && strcmp(clientHash, serverHash); - fprintf(fp, "[%s] !! DESYNC !! Tick: %d, Client Hash: %s, Server Hash: %s, Client Rand: %08X, Server Rand: %08X - %s\n", realm, - tick, - clientHash, - ( (serverHash[0] != '\0') ? serverHash : "" ), - srand0, - server_srand0, - (sprites_mismatch ? "Sprite hash mismatch" : "scenario rand mismatch")); + fprintf( + fp, + "[%s] !! DESYNC !! Tick: %d, Client Hash: %s, Server Hash: %s, Client Rand: %08X, Server Rand: %08X - %s\n", + realm, + tick, + clientHash, + ((serverHash[0] != '\0') ? serverHash : ""), + srand0, + server_srand0, + (sprites_mismatch ? "Sprite hash mismatch" : "scenario rand mismatch")); } } #endif uint32_t scenario_rand_max(uint32_t max) { - if (max < 2) return 0; + if (max < 2) + return 0; if ((max & (max - 1)) == 0) return scenario_rand() & (max - 1); uint32_t rand, cap = ~((uint32_t)0) - (~((uint32_t)0) % max) - 1; - do { + do + { rand = scenario_rand(); } while (rand > cap); return rand % max; @@ -570,18 +601,16 @@ static bool scenario_prepare_rides_for_save() { int32_t isFiveCoasterObjective = gScenarioObjectiveType == OBJECTIVE_FINISH_5_ROLLERCOASTERS; int32_t i; - Ride * ride; + Ride* ride; uint8_t rcs = 0; - FOR_ALL_RIDES(i, ride) + FOR_ALL_RIDES (i, ride) { - const rct_ride_entry * rideEntry = get_ride_entry(ride->subtype); - + const rct_ride_entry* rideEntry = get_ride_entry(ride->subtype); + // If there are more than 5 roller coasters, only mark the first five. - if (isFiveCoasterObjective && - rideEntry != nullptr && - (ride_entry_has_category(rideEntry, RIDE_CATEGORY_ROLLERCOASTER) && - rcs < 5)) + if (isFiveCoasterObjective && rideEntry != nullptr + && (ride_entry_has_category(rideEntry, RIDE_CATEGORY_ROLLERCOASTER) && rcs < 5)) { ride->lifecycle_flags |= RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK; rcs++; @@ -627,8 +656,7 @@ static bool scenario_prepare_rides_for_save() it.element->flags &= ~TILE_ELEMENT_FLAG_INDESTRUCTIBLE_TRACK_PIECE; } } - } - while (tile_element_iterator_next(&it)); + } while (tile_element_iterator_next(&it)); return true; } @@ -641,8 +669,9 @@ bool scenario_prepare_for_save() { gS6Info.entry.flags = 255; - auto stex = (rct_stex_entry *)object_entry_get_chunk(OBJECT_TYPE_SCENARIO_TEXT, 0); - if (stex != nullptr) { + auto stex = (rct_stex_entry*)object_entry_get_chunk(OBJECT_TYPE_SCENARIO_TEXT, 0); + if (stex != nullptr) + { char buffer[256]; format_string(buffer, 256, stex->scenario_name, nullptr); safe_strcpy(gS6Info.name, buffer, sizeof(gS6Info.name)); @@ -676,19 +705,24 @@ bool scenario_prepare_for_save() /** * Modifies the given S6 data so that ghost elements, rides with no track elements or unused banners / user strings are saved. */ -void scenario_fix_ghosts(rct_s6_data *s6) +void scenario_fix_ghosts(rct_s6_data* s6) { // Remove all ghost elements - rct_tile_element *destinationElement = s6->tile_elements; + rct_tile_element* destinationElement = s6->tile_elements; - for (int32_t y = 0; y < MAXIMUM_MAP_SIZE_TECHNICAL; y++) { - for (int32_t x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++) { - rct_tile_element *originalElement = map_get_first_element_at(x, y); - do { - if (originalElement->flags & TILE_ELEMENT_FLAG_GHOST) { + for (int32_t y = 0; y < MAXIMUM_MAP_SIZE_TECHNICAL; y++) + { + for (int32_t x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++) + { + rct_tile_element* originalElement = map_get_first_element_at(x, y); + do + { + if (originalElement->flags & TILE_ELEMENT_FLAG_GHOST) + { BannerIndex bannerIndex = tile_element_get_banner_index(originalElement); - if (bannerIndex != BANNER_INDEX_NULL) { - rct_banner *banner = &s6->banners[bannerIndex]; + if (bannerIndex != BANNER_INDEX_NULL) + { + rct_banner* banner = &s6->banners[bannerIndex]; if (banner->type != BANNER_NULL) { banner->type = BANNER_NULL; @@ -696,7 +730,9 @@ void scenario_fix_ghosts(rct_s6_data *s6) s6->custom_strings[(banner->string_idx % RCT12_MAX_USER_STRINGS)][0] = 0; } } - } else { + } + else + { *destinationElement++ = *originalElement; } } while (!(originalElement++)->IsLastForTile()); @@ -707,14 +743,16 @@ void scenario_fix_ghosts(rct_s6_data *s6) } } -void scenario_remove_trackless_rides(rct_s6_data *s6) +void scenario_remove_trackless_rides(rct_s6_data* s6) { bool rideHasTrack[MAX_RIDES]; ride_all_has_any_track_elements(rideHasTrack); - for (int32_t i = 0; i < RCT12_MAX_RIDES_IN_PARK; i++) { - rct2_ride * ride = &s6->rides[i]; + for (int32_t i = 0; i < RCT12_MAX_RIDES_IN_PARK; i++) + { + rct2_ride* ride = &s6->rides[i]; - if (rideHasTrack[i] || ride->type == RIDE_TYPE_NULL) { + if (rideHasTrack[i] || ride->type == RIDE_TYPE_NULL) + { continue; } @@ -734,11 +772,14 @@ static void scenario_objective_check_guests_by() int16_t objectiveGuests = gScenarioObjectiveNumGuests; int16_t currentMonthYear = gDateMonthsElapsed; - if (currentMonthYear == MONTH_COUNT * objectiveYear || gConfigGeneral.allow_early_completion) { - if (parkRating >= 600 && guestsInPark >= objectiveGuests) { + if (currentMonthYear == MONTH_COUNT * objectiveYear || gConfigGeneral.allow_early_completion) + { + if (parkRating >= 600 && guestsInPark >= objectiveGuests) + { scenario_success(); } - else if (currentMonthYear == MONTH_COUNT * objectiveYear) { + else if (currentMonthYear == MONTH_COUNT * objectiveYear) + { scenario_failure(); } } @@ -751,21 +792,24 @@ static void scenario_objective_check_park_value_by() money32 objectiveParkValue = gScenarioObjectiveCurrency; money32 parkValue = gParkValue; - if (currentMonthYear == MONTH_COUNT * objectiveYear || gConfigGeneral.allow_early_completion) { - if (parkValue >= objectiveParkValue) { + if (currentMonthYear == MONTH_COUNT * objectiveYear || gConfigGeneral.allow_early_completion) + { + if (parkValue >= objectiveParkValue) + { scenario_success(); } - else if (currentMonthYear == MONTH_COUNT * objectiveYear) { + else if (currentMonthYear == MONTH_COUNT * objectiveYear) + { scenario_failure(); } } } /** -* Checks if there are 10 rollercoasters of different subtype with -* excitement >= 600 . -* rct2: -**/ + * Checks if there are 10 rollercoasters of different subtype with + * excitement >= 600 . + * rct2: + **/ static void scenario_objective_check_10_rollercoasters() { int32_t i, rcs = 0; @@ -774,17 +818,19 @@ static void scenario_objective_check_10_rollercoasters() memset(type_already_counted, 0, 256); - FOR_ALL_RIDES(i, ride) { + FOR_ALL_RIDES (i, ride) + { uint8_t subtype_id = ride->subtype; - rct_ride_entry *rideEntry = get_ride_entry(subtype_id); - if (rideEntry == nullptr) { + rct_ride_entry* rideEntry = get_ride_entry(subtype_id); + if (rideEntry == nullptr) + { continue; } - if (rideEntry != nullptr && - ride_entry_has_category(rideEntry, RIDE_CATEGORY_ROLLERCOASTER) && - ride->status == RIDE_STATUS_OPEN && - ride->excitement >= RIDE_RATING(6,00) && type_already_counted[subtype_id] == 0){ + if (rideEntry != nullptr && ride_entry_has_category(rideEntry, RIDE_CATEGORY_ROLLERCOASTER) + && ride->status == RIDE_STATUS_OPEN && ride->excitement >= RIDE_RATING(6, 00) + && type_already_counted[subtype_id] == 0) + { type_already_counted[subtype_id]++; rcs++; } @@ -800,31 +846,47 @@ static void scenario_objective_check_10_rollercoasters() */ static void scenario_objective_check_guests_and_rating() { - if (gParkRating < 700 && gDateMonthsElapsed >= 1) { + if (gParkRating < 700 && gDateMonthsElapsed >= 1) + { gScenarioParkRatingWarningDays++; - if (gScenarioParkRatingWarningDays == 1) { - if (gConfigNotifications.park_rating_warnings) { + if (gScenarioParkRatingWarningDays == 1) + { + if (gConfigNotifications.park_rating_warnings) + { news_item_add_to_queue(NEWS_ITEM_GRAPH, STR_PARK_RATING_WARNING_4_WEEKS_REMAINING, 0); } - } else if (gScenarioParkRatingWarningDays == 8) { - if (gConfigNotifications.park_rating_warnings) { + } + else if (gScenarioParkRatingWarningDays == 8) + { + if (gConfigNotifications.park_rating_warnings) + { news_item_add_to_queue(NEWS_ITEM_GRAPH, STR_PARK_RATING_WARNING_3_WEEKS_REMAINING, 0); } - } else if (gScenarioParkRatingWarningDays == 15) { - if (gConfigNotifications.park_rating_warnings) { + } + else if (gScenarioParkRatingWarningDays == 15) + { + if (gConfigNotifications.park_rating_warnings) + { news_item_add_to_queue(NEWS_ITEM_GRAPH, STR_PARK_RATING_WARNING_2_WEEKS_REMAINING, 0); } - } else if (gScenarioParkRatingWarningDays == 22) { - if (gConfigNotifications.park_rating_warnings) { + } + else if (gScenarioParkRatingWarningDays == 22) + { + if (gConfigNotifications.park_rating_warnings) + { news_item_add_to_queue(NEWS_ITEM_GRAPH, STR_PARK_RATING_WARNING_1_WEEK_REMAINING, 0); } - } else if (gScenarioParkRatingWarningDays == 29) { + } + else if (gScenarioParkRatingWarningDays == 29) + { news_item_add_to_queue(NEWS_ITEM_GRAPH, STR_PARK_HAS_BEEN_CLOSED_DOWN, 0); gParkFlags &= ~PARK_FLAGS_PARK_OPEN; scenario_failure(); gGuestInitialHappiness = 50; } - } else if (gScenarioCompletedCompanyValue != (money32)0x80000001) { + } + else if (gScenarioCompletedCompanyValue != (money32)0x80000001) + { gScenarioParkRatingWarningDays = 0; } @@ -836,7 +898,8 @@ static void scenario_objective_check_guests_and_rating() static void scenario_objective_check_monthly_ride_income() { money32 lastMonthRideIncome = gExpenditureTable[1][RCT_EXPENDITURE_TYPE_PARK_RIDE_TICKETS]; - if (lastMonthRideIncome >= gScenarioObjectiveCurrency) { + if (lastMonthRideIncome >= gScenarioObjectiveCurrency) + { scenario_success(); } } @@ -855,17 +918,19 @@ static void scenario_objective_check_10_rollercoasters_length() memset(type_already_counted, 0, 256); - FOR_ALL_RIDES(i, ride) { + FOR_ALL_RIDES (i, ride) + { uint8_t subtype_id = ride->subtype; - rct_ride_entry *rideEntry = get_ride_entry(subtype_id); - if (rideEntry == nullptr) { + rct_ride_entry* rideEntry = get_ride_entry(subtype_id); + if (rideEntry == nullptr) + { continue; } - if (ride_entry_has_category(rideEntry, RIDE_CATEGORY_ROLLERCOASTER) && - ride->status == RIDE_STATUS_OPEN && - ride->excitement >= RIDE_RATING(7,00) && type_already_counted[subtype_id] == 0){ - - if ((ride_get_total_length(ride) >> 16) > objective_length) { + if (ride_entry_has_category(rideEntry, RIDE_CATEGORY_ROLLERCOASTER) && ride->status == RIDE_STATUS_OPEN + && ride->excitement >= RIDE_RATING(7, 00) && type_already_counted[subtype_id] == 0) + { + if ((ride_get_total_length(ride) >> 16) > objective_length) + { type_already_counted[subtype_id]++; rcs++; } @@ -883,19 +948,18 @@ static void scenario_objective_check_finish_5_rollercoasters() // Originally, this did not check for null rides, neither did it check if // the rides are even rollercoasters, never mind the right rollercoasters to be finished. int32_t i; - Ride * ride; + Ride* ride; int32_t rcs = 0; - FOR_ALL_RIDES(i, ride) + FOR_ALL_RIDES (i, ride) { - const rct_ride_entry * rideEntry = get_ride_entry(ride->subtype); + const rct_ride_entry* rideEntry = get_ride_entry(ride->subtype); if (rideEntry == nullptr) { continue; } - if (ride->status != RIDE_STATUS_CLOSED && - ride->excitement >= objectiveRideExcitement && - (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) && // Set on partially finished coasters + if (ride->status != RIDE_STATUS_CLOSED && ride->excitement >= objectiveRideExcitement + && (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) && // Set on partially finished coasters ride_entry_has_category(rideEntry, RIDE_CATEGORY_ROLLERCOASTER)) rcs++; } @@ -916,14 +980,13 @@ static void scenario_objective_check_replay_loan_and_park_value() static void scenario_objective_check_monthly_food_income() { - money32 * lastMonthExpenditure = gExpenditureTable[1]; - int32_t lastMonthProfit = - lastMonthExpenditure[RCT_EXPENDITURE_TYPE_SHOP_SHOP_SALES] + - lastMonthExpenditure[RCT_EXPENDITURE_TYPE_SHOP_STOCK] + - lastMonthExpenditure[RCT_EXPENDITURE_TYPE_FOODDRINK_SALES] + - lastMonthExpenditure[RCT_EXPENDITURE_TYPE_FOODDRINK_STOCK]; + money32* lastMonthExpenditure = gExpenditureTable[1]; + int32_t lastMonthProfit = lastMonthExpenditure[RCT_EXPENDITURE_TYPE_SHOP_SHOP_SALES] + + lastMonthExpenditure[RCT_EXPENDITURE_TYPE_SHOP_STOCK] + lastMonthExpenditure[RCT_EXPENDITURE_TYPE_FOODDRINK_SALES] + + lastMonthExpenditure[RCT_EXPENDITURE_TYPE_FOODDRINK_STOCK]; - if (lastMonthProfit >= gScenarioObjectiveCurrency) { + if (lastMonthProfit >= gScenarioObjectiveCurrency) + { scenario_success(); } } @@ -934,38 +997,39 @@ static void scenario_objective_check_monthly_food_income() */ static void scenario_objective_check() { - if (gScenarioCompletedCompanyValue != MONEY32_UNDEFINED) { + if (gScenarioCompletedCompanyValue != MONEY32_UNDEFINED) + { return; } - switch (gScenarioObjectiveType) { - case OBJECTIVE_GUESTS_BY: - scenario_objective_check_guests_by(); - break; - case OBJECTIVE_PARK_VALUE_BY: - scenario_objective_check_park_value_by(); - break; - case OBJECTIVE_10_ROLLERCOASTERS: - scenario_objective_check_10_rollercoasters(); - break; - case OBJECTIVE_GUESTS_AND_RATING: - scenario_objective_check_guests_and_rating(); - break; - case OBJECTIVE_MONTHLY_RIDE_INCOME: - scenario_objective_check_monthly_ride_income(); - break; - case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: - scenario_objective_check_10_rollercoasters_length(); - break; - case OBJECTIVE_FINISH_5_ROLLERCOASTERS: - scenario_objective_check_finish_5_rollercoasters(); - break; - case OBJECTIVE_REPLAY_LOAN_AND_PARK_VALUE: - scenario_objective_check_replay_loan_and_park_value(); - break; - case OBJECTIVE_MONTHLY_FOOD_INCOME: - scenario_objective_check_monthly_food_income(); - break; + switch (gScenarioObjectiveType) + { + case OBJECTIVE_GUESTS_BY: + scenario_objective_check_guests_by(); + break; + case OBJECTIVE_PARK_VALUE_BY: + scenario_objective_check_park_value_by(); + break; + case OBJECTIVE_10_ROLLERCOASTERS: + scenario_objective_check_10_rollercoasters(); + break; + case OBJECTIVE_GUESTS_AND_RATING: + scenario_objective_check_guests_and_rating(); + break; + case OBJECTIVE_MONTHLY_RIDE_INCOME: + scenario_objective_check_monthly_ride_income(); + break; + case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: + scenario_objective_check_10_rollercoasters_length(); + break; + case OBJECTIVE_FINISH_5_ROLLERCOASTERS: + scenario_objective_check_finish_5_rollercoasters(); + break; + case OBJECTIVE_REPLAY_LOAN_AND_PARK_VALUE: + scenario_objective_check_replay_loan_and_park_value(); + break; + case OBJECTIVE_MONTHLY_FOOD_INCOME: + scenario_objective_check_monthly_food_income(); + break; } } - diff --git a/src/openrct2/scenario/Scenario.h b/src/openrct2/scenario/Scenario.h index ff18bd5b04..9cdc2d9ca0 100644 --- a/src/openrct2/scenario/Scenario.h +++ b/src/openrct2/scenario/Scenario.h @@ -30,12 +30,13 @@ struct ParkLoadResult; * SV6/SC6 header chunk * size: 0x20 */ -struct rct_s6_header { - uint8_t type; // 0x00 - uint8_t classic_flag; // 0x01 - uint16_t num_packed_objects; // 0x02 - uint32_t version; // 0x04 - uint32_t magic_number; // 0x08 +struct rct_s6_header +{ + uint8_t type; // 0x00 + uint8_t classic_flag; // 0x01 + uint16_t num_packed_objects; // 0x02 + uint32_t version; // 0x04 + uint32_t magic_number; // 0x08 uint8_t pad_0C[0x14]; }; assert_struct_size(rct_s6_header, 0x20); @@ -44,21 +45,23 @@ assert_struct_size(rct_s6_header, 0x20); * SC6 information chunk * size: 0x198 */ -struct rct_s6_info { +struct rct_s6_info +{ uint8_t editor_step; - uint8_t category; // 0x01 - uint8_t objective_type; // 0x02 - uint8_t objective_arg_1; // 0x03 - int32_t objective_arg_2; // 0x04 - int16_t objective_arg_3; // 0x08 + uint8_t category; // 0x01 + uint8_t objective_type; // 0x02 + uint8_t objective_arg_1; // 0x03 + int32_t objective_arg_2; // 0x04 + int16_t objective_arg_3; // 0x08 uint8_t pad_00A[0x3E]; - char name[64]; // 0x48 - char details[256]; // 0x88 - rct_object_entry entry; // 0x188 + char name[64]; // 0x48 + char details[256]; // 0x88 + rct_object_entry entry; // 0x188 }; assert_struct_size(rct_s6_info, 0x198); -enum SCENARIO_SOURCE { +enum SCENARIO_SOURCE +{ SCENARIO_SOURCE_RCT1, SCENARIO_SOURCE_RCT1_AA, SCENARIO_SOURCE_RCT1_LL, @@ -69,16 +72,18 @@ enum SCENARIO_SOURCE { SCENARIO_SOURCE_OTHER, }; -struct rct_stex_entry { - rct_string_id scenario_name; // 0x00 - rct_string_id park_name; // 0x02 - rct_string_id details; // 0x04 +struct rct_stex_entry +{ + rct_string_id scenario_name; // 0x00 + rct_string_id park_name; // 0x02 + rct_string_id details; // 0x04 uint8_t var_06; }; assert_struct_size(rct_stex_entry, 7); // This will be useful for backwards compatibility -struct rct_s6_data { +struct rct_s6_data +{ // SC6[0] rct_s6_header header; @@ -281,7 +286,7 @@ struct rct_s6_data { uint8_t current_rain_level; uint8_t next_rain_level; rct12_news_item news_items[RCT12_MAX_NEWS_ITEMS]; - char rct1_scenario_name[62]; // Unused in RCT2 + char rct1_scenario_name[62]; // Unused in RCT2 uint16_t rct1_scenario_slot_index; // Unused in RCT2 uint32_t rct1_scenario_flags; // Unused in RCT2 uint16_t wide_path_tile_loop_x; @@ -291,13 +296,15 @@ struct rct_s6_data { assert_struct_size(rct_s6_data, 0x46b44a); #pragma pack(pop) -enum { +enum +{ SCENARIO_FLAGS_VISIBLE = (1 << 0), SCENARIO_FLAGS_COMPLETED = (1 << 1), SCENARIO_FLAGS_SIXFLAGS = (1 << 2) }; -enum { +enum +{ S6_TYPE_SAVEDGAME, S6_TYPE_SCENARIO }; @@ -305,7 +312,8 @@ enum { #define S6_RCT2_VERSION 120001 #define S6_MAGIC_NUMBER 0x00031144 -enum { +enum +{ // RCT2 categories (keep order) SCENARIO_CATEGORY_BEGINNER, SCENARIO_CATEGORY_CHALLENGING, @@ -320,7 +328,8 @@ enum { SCENARIO_CATEGORY_COUNT }; -enum { +enum +{ OBJECTIVE_NONE, OBJECTIVE_GUESTS_BY, OBJECTIVE_PARK_VALUE_BY, @@ -335,12 +344,14 @@ enum { OBJECTIVE_MONTHLY_FOOD_INCOME }; -enum { +enum +{ SCENARIO_SELECT_MODE_DIFFICULTY, SCENARIO_SELECT_MODE_ORIGIN, }; -enum { +enum +{ AUTOSAVE_EVERY_MINUTE, AUTOSAVE_EVERY_5MINUTES, AUTOSAVE_EVERY_15MINUTES, @@ -378,15 +389,15 @@ extern uint32_t gLastAutoSaveUpdate; extern char gScenarioFileName[260]; -void load_from_sc6(const char *path); +void load_from_sc6(const char* path); void scenario_begin(); void scenario_update(); #ifdef DEBUG_DESYNC -uint32_t dbg_scenario_rand(const char *file, const char *function, const uint32_t line, const void *data); +uint32_t dbg_scenario_rand(const char* file, const char* function, const uint32_t line, const void* data); #define scenario_rand() dbg_scenario_rand(__FILE__, __FUNCTION__, __LINE__, NULL) #define scenario_rand_data(data) dbg_scenario_rand(__FILE__, __FUNCTION__, __LINE__, data) -void dbg_report_desync(uint32_t tick, uint32_t srand0, uint32_t server_srand0, const char *clientHash, const char *serverHash); +void dbg_report_desync(uint32_t tick, uint32_t srand0, uint32_t server_srand0, const char* clientHash, const char* serverHash); #else uint32_t scenario_rand(); #endif @@ -394,12 +405,12 @@ uint32_t scenario_rand(); uint32_t scenario_rand_max(uint32_t max); bool scenario_prepare_for_save(); -int32_t scenario_save(const utf8 * path, int32_t flags); -void scenario_remove_trackless_rides(rct_s6_data *s6); -void scenario_fix_ghosts(rct_s6_data *s6); +int32_t scenario_save(const utf8* path, int32_t flags); +void scenario_remove_trackless_rides(rct_s6_data* s6); +void scenario_fix_ghosts(rct_s6_data* s6); void scenario_failure(); void scenario_success(); -void scenario_success_submit_name(const char *name); +void scenario_success_submit_name(const char* name); void scenario_autosave_check(); #endif diff --git a/src/openrct2/scenario/ScenarioRepository.cpp b/src/openrct2/scenario/ScenarioRepository.cpp index eb23f04fdc..a84a131929 100644 --- a/src/openrct2/scenario/ScenarioRepository.cpp +++ b/src/openrct2/scenario/ScenarioRepository.cpp @@ -7,10 +7,13 @@ * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ -#include -#include -#include +#include "ScenarioRepository.h" + #include "../Context.h" +#include "../Game.h" +#include "../ParkImporter.h" +#include "../PlatformEnvironment.h" +#include "../config/Config.h" #include "../core/Console.hpp" #include "../core/File.h" #include "../core/FileIndex.hpp" @@ -19,34 +22,36 @@ #include "../core/Path.hpp" #include "../core/String.hpp" #include "../core/Util.hpp" -#include "../ParkImporter.h" -#include "../PlatformEnvironment.h" -#include "../rct12/SawyerChunkReader.h" -#include "ScenarioRepository.h" -#include "ScenarioSources.h" - -#include "../config/Config.h" #include "../localisation/Language.h" #include "../localisation/Localisation.h" #include "../localisation/LocalisationService.h" #include "../platform/platform.h" +#include "../rct12/SawyerChunkReader.h" #include "Scenario.h" -#include "../Game.h" +#include "ScenarioSources.h" + +#include +#include +#include using namespace OpenRCT2; static int32_t ScenarioCategoryCompare(int32_t categoryA, int32_t categoryB) { - if (categoryA == categoryB) return 0; - if (categoryA == SCENARIO_CATEGORY_DLC) return -1; - if (categoryB == SCENARIO_CATEGORY_DLC) return 1; - if (categoryA == SCENARIO_CATEGORY_BUILD_YOUR_OWN) return -1; - if (categoryB == SCENARIO_CATEGORY_BUILD_YOUR_OWN) return 1; + if (categoryA == categoryB) + return 0; + if (categoryA == SCENARIO_CATEGORY_DLC) + return -1; + if (categoryB == SCENARIO_CATEGORY_DLC) + return 1; + if (categoryA == SCENARIO_CATEGORY_BUILD_YOUR_OWN) + return -1; + if (categoryB == SCENARIO_CATEGORY_BUILD_YOUR_OWN) + return 1; return Math::Sign(categoryA - categoryB); } -static int32_t scenario_index_entry_CompareByCategory(const scenario_index_entry &entryA, - const scenario_index_entry &entryB) +static int32_t scenario_index_entry_CompareByCategory(const scenario_index_entry& entryA, const scenario_index_entry& entryB) { // Order by category if (entryA.category != entryB.category) @@ -55,21 +60,21 @@ static int32_t scenario_index_entry_CompareByCategory(const scenario_index_entry } // Then by source game / name - switch (entryA.category) { - default: - if (entryA.source_game != entryB.source_game) - { - return entryA.source_game - entryB.source_game; - } - return strcmp(entryA.name, entryB.name); - case SCENARIO_CATEGORY_REAL: - case SCENARIO_CATEGORY_OTHER: - return strcmp(entryA.name, entryB.name); + switch (entryA.category) + { + default: + if (entryA.source_game != entryB.source_game) + { + return entryA.source_game - entryB.source_game; + } + return strcmp(entryA.name, entryB.name); + case SCENARIO_CATEGORY_REAL: + case SCENARIO_CATEGORY_OTHER: + return strcmp(entryA.name, entryB.name); } } -static int32_t scenario_index_entry_CompareByIndex(const scenario_index_entry &entryA, - const scenario_index_entry &entryB) +static int32_t scenario_index_entry_CompareByIndex(const scenario_index_entry& entryA, const scenario_index_entry& entryB) { // Order by source game if (entryA.source_game != entryB.source_game) @@ -79,37 +84,38 @@ static int32_t scenario_index_entry_CompareByIndex(const scenario_index_entry &e // Then by index / category / name uint8_t sourceGame = entryA.source_game; - switch (sourceGame) { - default: - if (entryA.source_index == -1 && entryB.source_index == -1) - { - if (entryA.category == entryB.category) + switch (sourceGame) + { + default: + if (entryA.source_index == -1 && entryB.source_index == -1) { - return scenario_index_entry_CompareByCategory(entryA, entryB); + if (entryA.category == entryB.category) + { + return scenario_index_entry_CompareByCategory(entryA, entryB); + } + else + { + return ScenarioCategoryCompare(entryA.category, entryB.category); + } + } + else if (entryA.source_index == -1) + { + return 1; + } + else if (entryB.source_index == -1) + { + return -1; } else { - return ScenarioCategoryCompare(entryA.category, entryB.category); + return entryA.source_index - entryB.source_index; } - } - else if (entryA.source_index == -1) - { - return 1; - } - else if (entryB.source_index == -1) - { - return -1; - } - else - { - return entryA.source_index - entryB.source_index; - } - case SCENARIO_SOURCE_REAL: - return scenario_index_entry_CompareByCategory(entryA, entryB); + case SCENARIO_SOURCE_REAL: + return scenario_index_entry_CompareByCategory(entryA, entryB); } } -static void scenario_highscore_free(scenario_highscore_entry * highscore) +static void scenario_highscore_free(scenario_highscore_entry* highscore) { SafeFree(highscore->fileName); SafeFree(highscore->name); @@ -124,21 +130,21 @@ private: static constexpr auto PATTERN = "*.sc4;*.sc6"; public: - explicit ScenarioFileIndex(const IPlatformEnvironment& env) : - FileIndex("scenario index", - MAGIC_NUMBER, - VERSION, - env.GetFilePath(PATHID::CACHE_SCENARIOS), - std::string(PATTERN), - std::vector({ - env.GetDirectoryPath(DIRBASE::RCT1, DIRID::SCENARIO), - env.GetDirectoryPath(DIRBASE::RCT2, DIRID::SCENARIO), - env.GetDirectoryPath(DIRBASE::USER, DIRID::SCENARIO) })) + explicit ScenarioFileIndex(const IPlatformEnvironment& env) + : FileIndex( + "scenario index", + MAGIC_NUMBER, + VERSION, + env.GetFilePath(PATHID::CACHE_SCENARIOS), + std::string(PATTERN), + std::vector({ env.GetDirectoryPath(DIRBASE::RCT1, DIRID::SCENARIO), + env.GetDirectoryPath(DIRBASE::RCT2, DIRID::SCENARIO), + env.GetDirectoryPath(DIRBASE::USER, DIRID::SCENARIO) })) { } protected: - std::tuple Create(int32_t, const std::string &path) const override + std::tuple Create(int32_t, const std::string& path) const override { scenario_index_entry entry; auto timestamp = File::GetLastModified(path); @@ -152,7 +158,7 @@ protected: } } - void Serialise(IStream * stream, const scenario_index_entry &item) const override + void Serialise(IStream* stream, const scenario_index_entry& item) const override { stream->Write(item.path, sizeof(item.path)); stream->WriteValue(item.timestamp); @@ -172,7 +178,7 @@ protected: stream->Write(item.details, sizeof(item.details)); } - scenario_index_entry Deserialise(IStream * stream) const override + scenario_index_entry Deserialise(IStream* stream) const override { scenario_index_entry item; @@ -201,7 +207,7 @@ private: /** * Reads basic information from a scenario file. */ - static bool GetScenarioInfo(const std::string &path, uint64_t timestamp, scenario_index_entry * entry) + static bool GetScenarioInfo(const std::string& path, uint64_t timestamp, scenario_index_entry* entry) { log_verbose("GetScenarioInfo(%s, %d, ...)", path.c_str(), timestamp); try @@ -222,7 +228,7 @@ private: result = true; } } - catch (const std::exception &) + catch (const std::exception&) { } return result; @@ -248,14 +254,14 @@ private: } } } - catch (const std::exception &) + catch (const std::exception&) { Console::Error::WriteLine("Unable to read scenario: '%s'", path.c_str()); } return false; } - static scenario_index_entry CreateNewScenarioEntry(const std::string &path, uint64_t timestamp, rct_s6_info * s6Info) + static scenario_index_entry CreateNewScenarioEntry(const std::string& path, uint64_t timestamp, rct_s6_info* s6Info) { scenario_index_entry entry = {}; @@ -280,8 +286,8 @@ private: ScenarioSources::NormaliseName(entry.name, sizeof(entry.name), entry.name); } - // entry.name will be translated later so keep the untranslated name here - String::Set(entry.internal_name, sizeof(entry.internal_name), entry.name); + // entry.name will be translated later so keep the untranslated name here + String::Set(entry.internal_name, sizeof(entry.internal_name), entry.name); String::Set(entry.details, sizeof(entry.details), s6Info->details); @@ -325,8 +331,8 @@ private: public: explicit ScenarioRepository(const std::shared_ptr& env) - : _env(env), - _fileIndex(*env) + : _env(env) + , _fileIndex(*env) { } @@ -359,9 +365,9 @@ public: return _scenarios.size(); } - const scenario_index_entry * GetByIndex(size_t index) const override + const scenario_index_entry* GetByIndex(size_t index) const override { - const scenario_index_entry * result = nullptr; + const scenario_index_entry* result = nullptr; if (index < _scenarios.size()) { result = &_scenarios[index]; @@ -369,11 +375,11 @@ public: return result; } - const scenario_index_entry * GetByFilename(const utf8 * filename) const override + const scenario_index_entry* GetByFilename(const utf8* filename) const override { - for (const auto &scenario : _scenarios) + for (const auto& scenario : _scenarios) { - const utf8 * scenarioFilename = Path::GetFileName(scenario.path); + const utf8* scenarioFilename = Path::GetFileName(scenario.path); // Note: this is always case insensitive search for cross platform consistency if (String::Equals(filename, scenarioFilename, true)) @@ -384,24 +390,27 @@ public: return nullptr; } - const scenario_index_entry * GetByInternalName(const utf8 * name) const override { - for (size_t i = 0; i < _scenarios.size(); i++) { - const scenario_index_entry * scenario = &_scenarios[i]; - - if (scenario->source_game == SCENARIO_SOURCE_OTHER && scenario->sc_id == SC_UNIDENTIFIED) - continue; - - // Note: this is always case insensitive search for cross platform consistency - if (String::Equals(name, scenario->internal_name, true)) { - return &_scenarios[i]; - } - } - return nullptr; - } - - const scenario_index_entry * GetByPath(const utf8 * path) const override + const scenario_index_entry* GetByInternalName(const utf8* name) const override { - for (const auto &scenario : _scenarios) + for (size_t i = 0; i < _scenarios.size(); i++) + { + const scenario_index_entry* scenario = &_scenarios[i]; + + if (scenario->source_game == SCENARIO_SOURCE_OTHER && scenario->sc_id == SC_UNIDENTIFIED) + continue; + + // Note: this is always case insensitive search for cross platform consistency + if (String::Equals(name, scenario->internal_name, true)) + { + return &_scenarios[i]; + } + } + return nullptr; + } + + const scenario_index_entry* GetByPath(const utf8* path) const override + { + for (const auto& scenario : _scenarios) { if (Path::Equals(path, scenario.path)) { @@ -411,19 +420,19 @@ public: return nullptr; } - bool TryRecordHighscore(int32_t language, const utf8 * scenarioFileName, money32 companyValue, const utf8 * name) override + bool TryRecordHighscore(int32_t language, const utf8* scenarioFileName, money32 companyValue, const utf8* name) override { // Scan the scenarios so we have a fresh list to query. This is to prevent the issue of scenario completions // not getting recorded, see #4951. Scan(language); - scenario_index_entry * scenario = GetByFilename(scenarioFileName); + scenario_index_entry* scenario = GetByFilename(scenarioFileName); if (scenario != nullptr) { // Check if record company value has been broken or the highscore is the same but no name is registered - scenario_highscore_entry * highscore = scenario->highscore; - if (highscore == nullptr || companyValue > highscore->company_value || - (String::IsNullOrEmpty(highscore->name) && companyValue == highscore->company_value)) + scenario_highscore_entry* highscore = scenario->highscore; + if (highscore == nullptr || companyValue > highscore->company_value + || (String::IsNullOrEmpty(highscore->name) && companyValue == highscore->company_value)) { if (highscore == nullptr) { @@ -451,16 +460,16 @@ public: } private: - scenario_index_entry * GetByFilename(const utf8 * filename) + scenario_index_entry* GetByFilename(const utf8* filename) { - const ScenarioRepository * repo = this; - return (scenario_index_entry *)repo->GetByFilename(filename); + const ScenarioRepository* repo = this; + return (scenario_index_entry*)repo->GetByFilename(filename); } - scenario_index_entry * GetByPath(const utf8 * path) + scenario_index_entry* GetByPath(const utf8* path) { - const ScenarioRepository * repo = this; - return (scenario_index_entry *)repo->GetByPath(path); + const ScenarioRepository* repo = this; + return (scenario_index_entry*)repo->GetByPath(path); } /** @@ -483,7 +492,7 @@ private: * @param srcPath Full path to mp.dat * @param dstPath Full path to sc21.dat */ - void ConvertMegaPark(const std::string &srcPath, const std::string &dstPath) + void ConvertMegaPark(const std::string& srcPath, const std::string& dstPath) { auto directory = Path::GetDirectory(dstPath); platform_ensure_directory_exists(directory.c_str()); @@ -499,7 +508,7 @@ private: File::WriteAllBytes(dstPath, mpdat.data(), mpdat.size()); } - void AddScenario(const scenario_index_entry &entry) + void AddScenario(const scenario_index_entry& entry) { auto filename = Path::GetFileName(entry.path); @@ -539,19 +548,17 @@ private: { if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) { - std::sort(_scenarios.begin(), _scenarios.end(), [](const scenario_index_entry &a, - const scenario_index_entry &b) -> bool - { - return scenario_index_entry_CompareByIndex(a, b) < 0; - }); + std::sort( + _scenarios.begin(), _scenarios.end(), [](const scenario_index_entry& a, const scenario_index_entry& b) -> bool { + return scenario_index_entry_CompareByIndex(a, b) < 0; + }); } else { - std::sort(_scenarios.begin(), _scenarios.end(), [](const scenario_index_entry &a, - const scenario_index_entry &b) -> bool - { - return scenario_index_entry_CompareByCategory(a, b) < 0; - }); + std::sort( + _scenarios.begin(), _scenarios.end(), [](const scenario_index_entry& a, const scenario_index_entry& b) -> bool { + return scenario_index_entry_CompareByCategory(a, b) < 0; + }); } } @@ -578,14 +585,14 @@ private: uint32_t numHighscores = fs.ReadValue(); for (uint32_t i = 0; i < numHighscores; i++) { - scenario_highscore_entry * highscore = InsertHighscore(); + scenario_highscore_entry* highscore = InsertHighscore(); highscore->fileName = fs.ReadString(); highscore->name = fs.ReadString(); highscore->company_value = fs.ReadValue(); highscore->timestamp = fs.ReadValue(); } } - catch (const std::exception &) + catch (const std::exception&) { Console::Error::WriteLine("Error reading highscores."); } @@ -603,7 +610,7 @@ private: LoadLegacyScores(rct2Path); } - void LoadLegacyScores(const std::string &path) + void LoadLegacyScores(const std::string& path) { if (!platform_file_exists(path.c_str())) { @@ -631,7 +638,7 @@ private: if (scBasic.Flags & SCENARIO_FLAGS_COMPLETED) { bool notFound = true; - for (auto &highscore : _highscores) + for (auto& highscore : _highscores) { if (String::Equals(scBasic.Path, highscore->fileName, true)) { @@ -651,7 +658,7 @@ private: } if (notFound) { - scenario_highscore_entry * highscore = InsertHighscore(); + scenario_highscore_entry* highscore = InsertHighscore(); highscore->fileName = String::Duplicate(scBasic.Path); std::string name = rct2_to_utf8(scBasic.CompletedBy, RCT2_LANGUAGE_ID_ENGLISH_UK); highscore->name = String::Duplicate(name.c_str()); @@ -661,7 +668,7 @@ private: } } } - catch (const std::exception &) + catch (const std::exception&) { Console::Error::WriteLine("Error reading legacy scenario scores file: '%s'", path.c_str()); } @@ -681,7 +688,7 @@ private: _highscores.clear(); } - scenario_highscore_entry * InsertHighscore() + scenario_highscore_entry* InsertHighscore() { auto highscore = new scenario_highscore_entry(); memset(highscore, 0, sizeof(scenario_highscore_entry)); @@ -691,9 +698,9 @@ private: void AttachHighscores() { - for (auto &highscore : _highscores) + for (auto& highscore : _highscores) { - scenario_index_entry * scenerio = GetByFilename(highscore->fileName); + scenario_index_entry* scenerio = GetByFilename(highscore->fileName); if (scenerio != nullptr) { scenerio->highscore = highscore; @@ -711,14 +718,14 @@ private: fs.WriteValue((uint32_t)_highscores.size()); for (size_t i = 0; i < _highscores.size(); i++) { - const scenario_highscore_entry * highscore = _highscores[i]; + const scenario_highscore_entry* highscore = _highscores[i]; fs.WriteString(highscore->fileName); fs.WriteString(highscore->name); fs.WriteValue(highscore->company_value); fs.WriteValue(highscore->timestamp); } } - catch (const std::exception &) + catch (const std::exception&) { Console::Error::WriteLine("Unable to save highscores to '%s'", path.c_str()); } @@ -730,32 +737,31 @@ std::unique_ptr CreateScenarioRepository(const std::shared_ return std::make_unique(env); } -IScenarioRepository * GetScenarioRepository() +IScenarioRepository* GetScenarioRepository() { return GetContext()->GetScenarioRepository(); } void scenario_repository_scan() { - IScenarioRepository * repo = GetScenarioRepository(); + IScenarioRepository* repo = GetScenarioRepository(); repo->Scan(LocalisationService_GetCurrentLanguage()); } size_t scenario_repository_get_count() { - IScenarioRepository * repo = GetScenarioRepository(); + IScenarioRepository* repo = GetScenarioRepository(); return repo->GetCount(); } -const scenario_index_entry *scenario_repository_get_by_index(size_t index) +const scenario_index_entry* scenario_repository_get_by_index(size_t index) { - IScenarioRepository * repo = GetScenarioRepository(); + IScenarioRepository* repo = GetScenarioRepository(); return repo->GetByIndex(index); } -bool scenario_repository_try_record_highscore(const utf8 * scenarioFileName, money32 companyValue, const utf8 * name) +bool scenario_repository_try_record_highscore(const utf8* scenarioFileName, money32 companyValue, const utf8* name) { - IScenarioRepository * repo = GetScenarioRepository(); + IScenarioRepository* repo = GetScenarioRepository(); return repo->TryRecordHighscore(LocalisationService_GetCurrentLanguage(), scenarioFileName, companyValue, name); } - diff --git a/src/openrct2/scenario/ScenarioRepository.h b/src/openrct2/scenario/ScenarioRepository.h index d179512549..8d9cd7df0a 100644 --- a/src/openrct2/scenario/ScenarioRepository.h +++ b/src/openrct2/scenario/ScenarioRepository.h @@ -9,37 +9,38 @@ #pragma once -#include #include "../common.h" +#include + struct rct_object_entry; struct scenario_highscore_entry { - utf8 * fileName; - utf8 * name; - money32 company_value; - datetime64 timestamp; + utf8* fileName; + utf8* name; + money32 company_value; + datetime64 timestamp; }; struct scenario_index_entry { - utf8 path[MAX_PATH]; - uint64_t timestamp; + utf8 path[MAX_PATH]; + uint64_t timestamp; // Category / sequence - uint8_t category; - uint8_t source_game; - int16_t source_index; - uint16_t sc_id; + uint8_t category; + uint8_t source_game; + int16_t source_index; + uint16_t sc_id; // Objective - uint8_t objective_type; - uint8_t objective_arg_1; - int32_t objective_arg_2; - int16_t objective_arg_3; - scenario_highscore_entry * highscore; - + uint8_t objective_type; + uint8_t objective_arg_1; + int32_t objective_arg_2; + int16_t objective_arg_3; + scenario_highscore_entry* highscore; + utf8 internal_name[64]; // Untranslated name utf8 name[64]; // Translated name utf8 details[256]; @@ -60,22 +61,23 @@ interface IScenarioRepository virtual void Scan(int32_t language) abstract; virtual size_t GetCount() const abstract; - virtual const scenario_index_entry * GetByIndex(size_t index) const abstract; - virtual const scenario_index_entry * GetByFilename(const utf8 * filename) const abstract; - /** - * Does not return custom scenarios due to the fact that they may have the same name. - */ - virtual const scenario_index_entry * GetByInternalName(const utf8 * name) const abstract; - virtual const scenario_index_entry * GetByPath(const utf8 * path) const abstract; + virtual const scenario_index_entry* GetByIndex(size_t index) const abstract; + virtual const scenario_index_entry* GetByFilename(const utf8* filename) const abstract; + /** + * Does not return custom scenarios due to the fact that they may have the same name. + */ + virtual const scenario_index_entry* GetByInternalName(const utf8* name) const abstract; + virtual const scenario_index_entry* GetByPath(const utf8* path) const abstract; - virtual bool TryRecordHighscore(int32_t language, const utf8 * scenarioFileName, money32 companyValue, const utf8 * name) abstract; + virtual bool TryRecordHighscore(int32_t language, const utf8* scenarioFileName, money32 companyValue, const utf8* name) + abstract; }; std::unique_ptr CreateScenarioRepository(const std::shared_ptr& env); -IScenarioRepository * GetScenarioRepository(); +IScenarioRepository* GetScenarioRepository(); -void scenario_repository_scan(); -size_t scenario_repository_get_count(); -const scenario_index_entry *scenario_repository_get_by_index(size_t index); -bool scenario_repository_try_record_highscore(const utf8 * scenarioFileName, money32 companyValue, const utf8 * name); -void scenario_translate(scenario_index_entry * scenarioEntry, const struct rct_object_entry * stexObjectEntry); +void scenario_repository_scan(); +size_t scenario_repository_get_count(); +const scenario_index_entry* scenario_repository_get_by_index(size_t index); +bool scenario_repository_try_record_highscore(const utf8* scenarioFileName, money32 companyValue, const utf8* name); +void scenario_translate(scenario_index_entry* scenarioEntry, const struct rct_object_entry* stexObjectEntry); diff --git a/src/openrct2/scenario/ScenarioSources.cpp b/src/openrct2/scenario/ScenarioSources.cpp index e4a87a93ba..4759851067 100644 --- a/src/openrct2/scenario/ScenarioSources.cpp +++ b/src/openrct2/scenario/ScenarioSources.cpp @@ -7,29 +7,29 @@ * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ +#include "ScenarioSources.h" + #include "../core/Guard.hpp" #include "../core/String.hpp" #include "../core/Util.hpp" -#include "ScenarioSources.h" - #include "Scenario.h" namespace ScenarioSources { struct ScenarioAlias { - const utf8 * Original; - const utf8 * Alternative; + const utf8* Original; + const utf8* Alternative; }; struct ScenarioTitleDescriptor { - const uint8_t Id; - const utf8 * Title; - const uint8_t Category; + const uint8_t Id; + const utf8* Title; + const uint8_t Category; }; - #pragma region Scenario Data +#pragma region Scenario Data // clang-format off static constexpr const ScenarioAlias ScenarioAliases[] = @@ -316,9 +316,9 @@ namespace ScenarioSources }; // clang-format on - #pragma endregion +#pragma endregion - bool TryGetByName(const utf8 * name, source_desc * outDesc) + bool TryGetByName(const utf8* name, source_desc* outDesc) { Guard::ArgumentNotNull(outDesc, GUARD_LINE); @@ -327,7 +327,7 @@ namespace ScenarioSources { for (size_t j = 0; j < ScenarioTitlesBySource[i].count; j++) { - const ScenarioTitleDescriptor *desc = &ScenarioTitlesBySource[i].titles[j]; + const ScenarioTitleDescriptor* desc = &ScenarioTitlesBySource[i].titles[j]; if (String::Equals(name, desc->Title, true)) { outDesc->title = desc->Title; @@ -349,7 +349,7 @@ namespace ScenarioSources return false; } - bool TryGetById(uint8_t id, source_desc * outDesc) + bool TryGetById(uint8_t id, source_desc* outDesc) { Guard::ArgumentNotNull(outDesc, GUARD_LINE); @@ -358,7 +358,7 @@ namespace ScenarioSources { for (size_t j = 0; j < ScenarioTitlesBySource[i].count; j++) { - const ScenarioTitleDescriptor * desc = &ScenarioTitlesBySource[i].titles[j]; + const ScenarioTitleDescriptor* desc = &ScenarioTitlesBySource[i].titles[j]; if (id == desc->Id) { outDesc->title = desc->Title; @@ -380,7 +380,7 @@ namespace ScenarioSources return false; } - void NormaliseName(utf8 * buffer, size_t bufferSize, const utf8 * name) + void NormaliseName(utf8* buffer, size_t bufferSize, const utf8* name) { size_t nameLength = String::LengthOf(name); @@ -403,7 +403,7 @@ namespace ScenarioSources // American scenario titles should be converted to British name // Don't worry, names will be translated using language packs later - for (const ScenarioAlias &alias : ScenarioAliases) + for (const ScenarioAlias& alias : ScenarioAliases) { if (String::Equals(alias.Alternative, name)) { @@ -414,18 +414,17 @@ namespace ScenarioSources } } // namespace ScenarioSources -bool scenario_get_source_desc(const utf8 * name, source_desc * outDesc) +bool scenario_get_source_desc(const utf8* name, source_desc* outDesc) { return ScenarioSources::TryGetByName(name, outDesc); } -bool scenario_get_source_desc_by_id(uint8_t id, source_desc * outDesc) +bool scenario_get_source_desc_by_id(uint8_t id, source_desc* outDesc) { return ScenarioSources::TryGetById(id, outDesc); } -void scenario_normalise_name(utf8 * buffer, size_t bufferSize, utf8 * name) +void scenario_normalise_name(utf8* buffer, size_t bufferSize, utf8* name) { ScenarioSources::NormaliseName(buffer, bufferSize, name); } - diff --git a/src/openrct2/scenario/ScenarioSources.h b/src/openrct2/scenario/ScenarioSources.h index 445077a379..7a0f597249 100644 --- a/src/openrct2/scenario/ScenarioSources.h +++ b/src/openrct2/scenario/ScenarioSources.h @@ -13,24 +13,23 @@ struct source_desc { - const utf8 * title; - uint8_t id; - uint8_t source; - int32_t index; - uint8_t category; + const utf8* title; + uint8_t id; + uint8_t source; + int32_t index; + uint8_t category; }; namespace ScenarioSources { - bool TryGetByName(const utf8 * name, source_desc * outDesc); - bool TryGetById(uint8_t id, source_desc * outDesc); - void NormaliseName(utf8 * buffer, size_t bufferSize, const utf8 * name); -} - -bool scenario_get_source_desc(const utf8 *name, source_desc *outDesc); -bool scenario_get_source_desc_by_id(uint8_t id, source_desc *outDesc); -void scenario_normalise_name(utf8 *buffer, size_t bufferSize, utf8 *name); + bool TryGetByName(const utf8* name, source_desc* outDesc); + bool TryGetById(uint8_t id, source_desc* outDesc); + void NormaliseName(utf8* buffer, size_t bufferSize, const utf8* name); +} // namespace ScenarioSources +bool scenario_get_source_desc(const utf8* name, source_desc* outDesc); +bool scenario_get_source_desc_by_id(uint8_t id, source_desc* outDesc); +void scenario_normalise_name(utf8* buffer, size_t bufferSize, utf8* name); // RCT1 scenario index map enum