From 4013479094c9ae8f5fd700def2104f60cb594556 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 16 Feb 2019 20:39:41 +0000 Subject: [PATCH] Refactor marketing to be a single vector --- src/openrct2-ui/windows/Finances.cpp | 80 +++++------ src/openrct2/actions/ParkMarketingAction.hpp | 14 +- src/openrct2/interface/InteractiveConsole.cpp | 10 +- src/openrct2/management/Marketing.cpp | 129 ++++++++++++------ src/openrct2/management/Marketing.h | 24 +++- src/openrct2/rct1/S4Importer.cpp | 19 ++- src/openrct2/rct2/S6Exporter.cpp | 21 ++- src/openrct2/rct2/S6Exporter.h | 1 + src/openrct2/rct2/S6Importer.cpp | 25 +++- src/openrct2/scenario/Scenario.cpp | 2 +- src/openrct2/world/Park.cpp | 17 +-- 11 files changed, 225 insertions(+), 117 deletions(-) diff --git a/src/openrct2-ui/windows/Finances.cpp b/src/openrct2-ui/windows/Finances.cpp index 1a448a5f22..4f0cc9306e 100644 --- a/src/openrct2-ui/windows/Finances.cpp +++ b/src/openrct2-ui/windows/Finances.cpp @@ -1127,8 +1127,6 @@ static void window_finances_marketing_update(rct_window* w) */ static void window_finances_marketing_invalidate(rct_window* w) { - int32_t i; - if (w->widgets != _windowFinancesPageWidgets[WINDOW_FINANCES_PAGE_MARKETING]) { w->widgets = _windowFinancesPageWidgets[WINDOW_FINANCES_PAGE_MARKETING]; @@ -1138,11 +1136,7 @@ static void window_finances_marketing_invalidate(rct_window* w) window_finances_set_pressed_tab(w); // Count number of active campaigns - int32_t numActiveCampaigns = 0; - for (i = 0; i < ADVERTISING_CAMPAIGN_COUNT; i++) - if (gMarketingCampaignDaysLeft[i] != 0) - numActiveCampaigns++; - + int32_t numActiveCampaigns = (int32_t)gMarketingCampaigns.size(); int32_t y = std::max(1, numActiveCampaigns) * LIST_ROW_HEIGHT + 92; // Update group box positions @@ -1151,22 +1145,21 @@ static void window_finances_marketing_invalidate(rct_window* w) // Update new campaign button visibility y += 3; - for (i = 0; i < ADVERTISING_CAMPAIGN_COUNT; i++) + for (int32_t i = 0; i < ADVERTISING_CAMPAIGN_COUNT; i++) { - rct_widget* campaignButton = &_windowFinancesMarketingWidgets[WIDX_CAMPAIGN_1 + i]; - - campaignButton->type = WWT_EMPTY; - - if (gMarketingCampaignDaysLeft[i] != 0) - continue; - - if (!marketing_is_campaign_type_applicable(i)) - continue; - - campaignButton->type = WWT_BUTTON; - campaignButton->top = y; - campaignButton->bottom = y + BUTTON_FACE_HEIGHT + 1; - y += BUTTON_FACE_HEIGHT + 2; + auto campaignButton = &_windowFinancesMarketingWidgets[WIDX_CAMPAIGN_1 + i]; + auto campaign = marketing_get_campaign(i); + if (campaign == nullptr && marketing_is_campaign_type_applicable(i)) + { + campaignButton->type = WWT_BUTTON; + campaignButton->top = y; + campaignButton->bottom = y + BUTTON_FACE_HEIGHT + 1; + y += BUTTON_FACE_HEIGHT + 2; + } + else + { + campaignButton->type = WWT_EMPTY; + } } } @@ -1176,19 +1169,16 @@ static void window_finances_marketing_invalidate(rct_window* w) */ static void window_finances_marketing_paint(rct_window* w, rct_drawpixelinfo* dpi) { - int32_t i, x, y, weeksRemaining; - Ride* ride; - window_draw_widgets(w, dpi); window_finances_draw_tab_images(dpi, w); - x = w->x + 8; - y = w->y + 62; - + int32_t x = w->x + 8; + int32_t y = w->y + 62; int32_t noCampaignsActive = 1; - for (i = 0; i < ADVERTISING_CAMPAIGN_COUNT; i++) + for (int32_t i = 0; i < ADVERTISING_CAMPAIGN_COUNT; i++) { - if (gMarketingCampaignDaysLeft[i] == 0) + auto campaign = marketing_get_campaign(i); + if (campaign == nullptr) continue; noCampaignsActive = 0; @@ -1200,12 +1190,14 @@ static void window_finances_marketing_paint(rct_window* w, rct_drawpixelinfo* dp { case ADVERTISING_CAMPAIGN_RIDE_FREE: case ADVERTISING_CAMPAIGN_RIDE: - ride = get_ride(gMarketingCampaignRideIndex[i]); + { + auto ride = get_ride(campaign->RideId); set_format_arg(0, rct_string_id, ride->name); set_format_arg(2, uint32_t, ride->name_arguments); break; + } case ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE: - set_format_arg(0, rct_string_id, ShopItemStringIds[gMarketingCampaignRideIndex[i]].plural); + set_format_arg(0, rct_string_id, ShopItemStringIds[campaign->ShopItemType].plural); break; } @@ -1213,7 +1205,7 @@ static void window_finances_marketing_paint(rct_window* w, rct_drawpixelinfo* dp gfx_draw_string_left_clipped(dpi, MarketingCampaignNames[i][1], gCommonFormatArgs, COLOUR_BLACK, x + 4, y, 296); // Duration - weeksRemaining = (gMarketingCampaignDaysLeft[i] % 128); + uint16_t weeksRemaining = campaign->WeeksLeft; gfx_draw_string_left( dpi, weeksRemaining == 1 ? STR_1_WEEK_REMAINING : STR_X_WEEKS_REMAINING, &weeksRemaining, COLOUR_BLACK, x + 304, y); @@ -1228,20 +1220,18 @@ static void window_finances_marketing_paint(rct_window* w, rct_drawpixelinfo* dp y += 34; // Draw campaign button text - for (i = 0; i < ADVERTISING_CAMPAIGN_COUNT; i++) + for (int32_t i = 0; i < ADVERTISING_CAMPAIGN_COUNT; i++) { - rct_widget* campaginButton = &_windowFinancesMarketingWidgets[WIDX_CAMPAIGN_1 + i]; + auto campaignButton = &_windowFinancesMarketingWidgets[WIDX_CAMPAIGN_1 + i]; + if (campaignButton->type != WWT_EMPTY) + { + // Draw button text + money32 pricePerWeek = AdvertisingCampaignPricePerWeek[i]; + gfx_draw_string_left(dpi, MarketingCampaignNames[i][0], nullptr, COLOUR_BLACK, x + 4, y); + gfx_draw_string_left(dpi, STR_MARKETING_PER_WEEK, &pricePerWeek, COLOUR_BLACK, x + 310, y); - if (campaginButton->type == WWT_EMPTY) - continue; - - money32 pricePerWeek = AdvertisingCampaignPricePerWeek[i]; - - // Draw button text - gfx_draw_string_left(dpi, MarketingCampaignNames[i][0], nullptr, COLOUR_BLACK, x + 4, y); - gfx_draw_string_left(dpi, STR_MARKETING_PER_WEEK, &pricePerWeek, COLOUR_BLACK, x + 310, y); - - y += BUTTON_FACE_HEIGHT + 2; + y += BUTTON_FACE_HEIGHT + 2; + } } } diff --git a/src/openrct2/actions/ParkMarketingAction.hpp b/src/openrct2/actions/ParkMarketingAction.hpp index 8f28965559..8b8179671c 100644 --- a/src/openrct2/actions/ParkMarketingAction.hpp +++ b/src/openrct2/actions/ParkMarketingAction.hpp @@ -68,8 +68,18 @@ public: GameActionResult::Ptr Execute() const override { - gMarketingCampaignDaysLeft[_type] = _numWeeks | CAMPAIGN_ACTIVE_FLAG; - gMarketingCampaignRideIndex[_type] = _item; + MarketingCampaign campaign{}; + campaign.Type = _type; + campaign.WeeksLeft = _numWeeks; + if (campaign.Type == ADVERTISING_CAMPAIGN_RIDE_FREE || campaign.Type == ADVERTISING_CAMPAIGN_RIDE) + { + campaign.RideId = _item; + } + else if (campaign.Type == ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE) + { + campaign.ShopItemType = _item; + } + marketing_new_campaign(campaign); // We are only interested in invalidating the finances (marketing) window auto windowManager = OpenRCT2::GetContext()->GetUiContext()->GetWindowManager(); diff --git a/src/openrct2/interface/InteractiveConsole.cpp b/src/openrct2/interface/InteractiveConsole.cpp index 580ccc3599..c547e4e7af 100644 --- a/src/openrct2/interface/InteractiveConsole.cpp +++ b/src/openrct2/interface/InteractiveConsole.cpp @@ -526,9 +526,9 @@ static int32_t cc_get(InteractiveConsole& console, const arguments_t& argv) console.WriteFormatLine( "guest_prefer_more_intense_rides %d", (gParkFlags & PARK_FLAGS_PREF_MORE_INTENSE_RIDES) != 0); } - else if (argv[0] == "forbid_marketing_campagns") + else if (argv[0] == "forbid_marketing_campaigns") { - console.WriteFormatLine("forbid_marketing_campagns %d", (gParkFlags & PARK_FLAGS_FORBID_MARKETING_CAMPAIGN) != 0); + console.WriteFormatLine("forbid_marketing_campaigns %d", (gParkFlags & PARK_FLAGS_FORBID_MARKETING_CAMPAIGN) != 0); } else if (argv[0] == "forbid_landscape_changes") { @@ -757,10 +757,10 @@ static int32_t cc_set(InteractiveConsole& console, const arguments_t& argv) SET_FLAG(gParkFlags, PARK_FLAGS_PREF_MORE_INTENSE_RIDES, int_val[0]); console.Execute("get guest_prefer_more_intense_rides"); } - else if (argv[0] == "forbid_marketing_campagns" && invalidArguments(&invalidArgs, int_valid[0])) + else if (argv[0] == "forbid_marketing_campaigns" && invalidArguments(&invalidArgs, int_valid[0])) { SET_FLAG(gParkFlags, PARK_FLAGS_FORBID_MARKETING_CAMPAIGN, int_val[0]); - console.Execute("get forbid_marketing_campagns"); + console.Execute("get forbid_marketing_campaigns"); } else if (argv[0] == "forbid_landscape_changes" && invalidArguments(&invalidArgs, int_valid[0])) { @@ -1542,7 +1542,7 @@ static constexpr const utf8* console_variable_table[] = { "guest_initial_thirst", "guest_prefer_less_intense_rides", "guest_prefer_more_intense_rides", - "forbid_marketing_campagn", + "forbid_marketing_campaign", "forbid_landscape_changes", "forbid_tree_removal", "forbid_high_construction", diff --git a/src/openrct2/management/Marketing.cpp b/src/openrct2/management/Marketing.cpp index b8a0645b1f..0b3c6afb64 100644 --- a/src/openrct2/management/Marketing.cpp +++ b/src/openrct2/management/Marketing.cpp @@ -34,16 +34,17 @@ static constexpr const int32_t AdvertisingCampaignGuestGenerationProbabilities[] 400, 300, 200, 200, 250, 200, }; -uint8_t gMarketingCampaignDaysLeft[20]; -ride_id_t gMarketingCampaignRideIndex[22]; +std::vector gMarketingCampaigns; -int32_t marketing_get_campaign_guest_generation_probability(int32_t campaign) +int32_t marketing_get_campaign_guest_generation_probability(int32_t campaignType) { - int32_t probability = AdvertisingCampaignGuestGenerationProbabilities[campaign]; - Ride* ride; + auto campaign = marketing_get_campaign(campaignType); + if (campaign == nullptr) + return 0; // Lower probability of guest generation if price was already low - switch (campaign) + int32_t probability = AdvertisingCampaignGuestGenerationProbabilities[campaign->Type]; + switch (campaign->Type) { case ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE: if (park_get_entrance_fee() < MONEY(4, 00)) @@ -54,65 +55,81 @@ int32_t marketing_get_campaign_guest_generation_probability(int32_t campaign) probability /= 8; break; case ADVERTISING_CAMPAIGN_RIDE_FREE: - ride = get_ride(gMarketingCampaignRideIndex[campaign]); + { + auto ride = get_ride(campaign->RideId); if (ride->price < MONEY(0, 30)) probability /= 8; break; + } } return probability; } +static void marketing_raise_finished_notification(const MarketingCampaign& campaign) +{ + if (gConfigNotifications.park_marketing_campaign_finished) + { + // This sets the string parameters for the marketing types that have an argument. + if (campaign.Type == ADVERTISING_CAMPAIGN_RIDE_FREE || campaign.Type == ADVERTISING_CAMPAIGN_RIDE) + { + Ride* ride = get_ride(campaign.RideId); + set_format_arg(0, rct_string_id, ride->name); + set_format_arg(2, uint32_t, ride->name_arguments); + } + else if (campaign.Type == ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE) + { + set_format_arg(0, rct_string_id, ShopItemStringIds[campaign.ShopItemType].plural); + } + + news_item_add_to_queue(NEWS_ITEM_MONEY, MarketingCampaignNames[campaign.Type][2], 0); + } +} + /** * Update status of marketing campaigns and send produce a news item when they have finished. * rct2: 0x0069E0C1 */ void marketing_update() { - for (int32_t campaign = 0; campaign < ADVERTISING_CAMPAIGN_COUNT; campaign++) + if (gCheatsNeverendingMarketing) + return; + + for (auto it = gMarketingCampaigns.begin(); it != gMarketingCampaigns.end();) { - if (gCheatsNeverendingMarketing) - continue; - - int32_t active = (gMarketingCampaignDaysLeft[campaign] & CAMPAIGN_ACTIVE_FLAG) != 0; - if (gMarketingCampaignDaysLeft[campaign] == 0) - continue; - - window_invalidate_by_class(WC_FINANCES); - - // High bit marks the campaign as inactive, on first check the campaign is set active - // this makes campaigns run a full x weeks even when started in the middle of a week - gMarketingCampaignDaysLeft[campaign] &= ~CAMPAIGN_ACTIVE_FLAG; - if (active) - continue; - - if (--gMarketingCampaignDaysLeft[campaign] != 0) - continue; - - int32_t campaignItem = gMarketingCampaignRideIndex[campaign]; - - // This sets the string parameters for the marketing types that have an argument. - if (campaign == ADVERTISING_CAMPAIGN_RIDE_FREE || campaign == ADVERTISING_CAMPAIGN_RIDE) + auto& campaign = *it; + if (campaign.Flags & MarketingCampaignFlags::FIRST_WEEK) { - Ride* ride = get_ride(campaignItem); - set_format_arg(0, rct_string_id, ride->name); - set_format_arg(2, uint32_t, ride->name_arguments); + // This ensures the campaign is active for x full weeks if started within the + // middle of a week. + campaign.Flags &= ~MarketingCampaignFlags::FIRST_WEEK; } - else if (campaign == ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE) + else if (campaign.WeeksLeft > 0) { - set_format_arg(0, rct_string_id, ShopItemStringIds[campaignItem].plural); + campaign.WeeksLeft--; } - if (gConfigNotifications.park_marketing_campaign_finished) + if (campaign.WeeksLeft == 0) { - news_item_add_to_queue(NEWS_ITEM_MONEY, MarketingCampaignNames[campaign][2], 0); + marketing_raise_finished_notification(campaign); + it = gMarketingCampaigns.erase(it); + } + else + { + ++it; } } + + window_invalidate_by_class(WC_FINANCES); } -void marketing_set_guest_campaign(rct_peep* peep, int32_t campaign) +void marketing_set_guest_campaign(rct_peep* peep, int32_t campaignType) { - switch (campaign) + auto campaign = marketing_get_campaign(campaignType); + if (campaign == nullptr) + return; + + switch (campaign->Type) { case ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE: peep->item_standard_flags |= PEEP_ITEM_VOUCHER; @@ -121,8 +138,8 @@ void marketing_set_guest_campaign(rct_peep* peep, int32_t campaign) case ADVERTISING_CAMPAIGN_RIDE_FREE: peep->item_standard_flags |= PEEP_ITEM_VOUCHER; peep->voucher_type = VOUCHER_TYPE_RIDE_FREE; - peep->voucher_arguments = gMarketingCampaignRideIndex[campaign]; - peep->guest_heading_to_ride_id = gMarketingCampaignRideIndex[campaign]; + peep->voucher_arguments = campaign->RideId; + peep->guest_heading_to_ride_id = campaign->RideId; peep->peep_is_lost_countdown = 240; break; case ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE: @@ -132,12 +149,12 @@ void marketing_set_guest_campaign(rct_peep* peep, int32_t campaign) case ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE: peep->item_standard_flags |= PEEP_ITEM_VOUCHER; peep->voucher_type = VOUCHER_TYPE_FOOD_OR_DRINK_FREE; - peep->voucher_arguments = gMarketingCampaignRideIndex[campaign]; + peep->voucher_arguments = campaign->ShopItemType; break; case ADVERTISING_CAMPAIGN_PARK: break; case ADVERTISING_CAMPAIGN_RIDE: - peep->guest_heading_to_ride_id = gMarketingCampaignRideIndex[campaign]; + peep->guest_heading_to_ride_id = campaign->RideId; peep->peep_is_lost_countdown = 240; break; } @@ -194,3 +211,29 @@ bool marketing_is_campaign_type_applicable(int32_t campaignType) return true; } } + +MarketingCampaign* marketing_get_campaign(int32_t campaignType) +{ + for (auto& campaign : gMarketingCampaigns) + { + if (campaign.Type == campaignType) + { + return &campaign; + } + } + return nullptr; +} + +void marketing_new_campaign(const MarketingCampaign& campaign) +{ + // Do not allow same campaign twice, just overwrite + auto currentCampaign = marketing_get_campaign(campaign.Type); + if (currentCampaign != nullptr) + { + *currentCampaign = campaign; + } + else + { + gMarketingCampaigns.push_back(campaign); + } +} diff --git a/src/openrct2/management/Marketing.h b/src/openrct2/management/Marketing.h index ab4a8e52d7..dcddde76b9 100644 --- a/src/openrct2/management/Marketing.h +++ b/src/openrct2/management/Marketing.h @@ -13,6 +13,8 @@ #include "../common.h" #include "../peep/Peep.h" +#include + enum { ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE, @@ -37,11 +39,29 @@ enum CAMPAIGN_ACTIVE_FLAG = (1 << 7) }; +struct MarketingCampaign +{ + uint8_t Type{}; + uint8_t WeeksLeft{}; + uint8_t Flags{}; + union + { + ride_id_t RideId{}; + uint8_t ShopItemType; + }; +}; + +namespace MarketingCampaignFlags +{ + constexpr uint8_t FIRST_WEEK = 1 << 0; +} + extern const money16 AdvertisingCampaignPricePerWeek[ADVERTISING_CAMPAIGN_COUNT]; -extern uint8_t gMarketingCampaignDaysLeft[20]; -extern ride_id_t gMarketingCampaignRideIndex[22]; +extern std::vector gMarketingCampaigns; int32_t marketing_get_campaign_guest_generation_probability(int32_t campaign); void marketing_update(); void marketing_set_guest_campaign(rct_peep* peep, int32_t campaign); bool marketing_is_campaign_type_applicable(int32_t campaignType); +MarketingCampaign* marketing_get_campaign(int32_t campaignType); +void marketing_new_campaign(const MarketingCampaign& campaign); diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 470f3e9922..98bcef0446 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -1849,10 +1849,23 @@ private: gTotalIncomeFromAdmissions = _s4.admission_total_income; // TODO marketing campaigns not working - for (size_t i = 0; i < 6; i++) + for (size_t i = 0; i < ADVERTISING_CAMPAIGN_COUNT; i++) { - gMarketingCampaignDaysLeft[i] = _s4.marketing_status[i]; - gMarketingCampaignRideIndex[i] = _s4.marketing_assoc[i]; + if (_s4.marketing_status[i] & CAMPAIGN_ACTIVE_FLAG) + { + MarketingCampaign campaign; + campaign.Type = (uint8_t)i; + campaign.WeeksLeft = _s4.marketing_status[i] & ~CAMPAIGN_ACTIVE_FLAG; + if (campaign.Type == ADVERTISING_CAMPAIGN_RIDE_FREE || campaign.Type == ADVERTISING_CAMPAIGN_RIDE) + { + campaign.RideId = _s4.marketing_assoc[i]; + } + else if (campaign.Type == ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE) + { + campaign.ShopItemType = _s4.marketing_assoc[i]; + } + gMarketingCampaigns.push_back(campaign); + } } } diff --git a/src/openrct2/rct2/S6Exporter.cpp b/src/openrct2/rct2/S6Exporter.cpp index a44f43f279..04739883d6 100644 --- a/src/openrct2/rct2/S6Exporter.cpp +++ b/src/openrct2/rct2/S6Exporter.cpp @@ -277,8 +277,7 @@ void S6Exporter::Export() // pad_013580FA _s6.objective_currency = gScenarioObjectiveCurrency; _s6.objective_guests = gScenarioObjectiveNumGuests; - std::memcpy(_s6.campaign_weeks_left, gMarketingCampaignDaysLeft, sizeof(_s6.campaign_weeks_left)); - std::memcpy(_s6.campaign_ride_index, gMarketingCampaignRideIndex, sizeof(_s6.campaign_ride_index)); + ExportMarketingCampaigns(); std::memcpy(_s6.balance_history, gCashHistory, sizeof(_s6.balance_history)); @@ -746,6 +745,24 @@ void S6Exporter::ExportResearchList() std::memcpy(_s6.research_items, gResearchItems, sizeof(_s6.research_items)); } +void S6Exporter::ExportMarketingCampaigns() +{ + std::memset(_s6.campaign_weeks_left, 0, sizeof(_s6.campaign_weeks_left)); + std::memset(_s6.campaign_ride_index, 0, sizeof(_s6.campaign_ride_index)); + for (const auto& campaign : gMarketingCampaigns) + { + _s6.campaign_weeks_left[campaign.Type] = campaign.WeeksLeft; + if (campaign.Type == ADVERTISING_CAMPAIGN_RIDE_FREE || campaign.Type == ADVERTISING_CAMPAIGN_RIDE) + { + _s6.campaign_ride_index[campaign.Type] = campaign.RideId; + } + else if (campaign.Type == ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE) + { + _s6.campaign_ride_index[campaign.Type] = campaign.ShopItemType; + } + } +} + enum : uint32_t { S6_SAVE_FLAG_EXPORT = 1 << 0, diff --git a/src/openrct2/rct2/S6Exporter.h b/src/openrct2/rct2/S6Exporter.h index 5a5d333f5c..315051a6cc 100644 --- a/src/openrct2/rct2/S6Exporter.h +++ b/src/openrct2/rct2/S6Exporter.h @@ -46,5 +46,6 @@ private: void ExportResearchedRideEntries(); void ExportResearchedSceneryItems(); void ExportResearchList(); + void ExportMarketingCampaigns(); void ExportPeepSpawns(); }; diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 86bb9ebe8f..997f6ed410 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -295,8 +295,7 @@ public: // pad_013580FA gScenarioObjectiveCurrency = _s6.objective_currency; gScenarioObjectiveNumGuests = _s6.objective_guests; - std::memcpy(gMarketingCampaignDaysLeft, _s6.campaign_weeks_left, sizeof(_s6.campaign_weeks_left)); - std::memcpy(gMarketingCampaignRideIndex, _s6.campaign_ride_index, sizeof(_s6.campaign_ride_index)); + ImportMarketingCampaigns(); gCurrentExpenditure = _s6.current_expenditure; gCurrentProfit = _s6.current_profit; @@ -1028,6 +1027,28 @@ public: assert(false); } } + + void ImportMarketingCampaigns() + { + for (size_t i = 0; i < ADVERTISING_CAMPAIGN_COUNT; i++) + { + if (_s6.campaign_weeks_left[i] & CAMPAIGN_ACTIVE_FLAG) + { + MarketingCampaign campaign{}; + campaign.Type = (uint8_t)i; + campaign.WeeksLeft = _s6.campaign_weeks_left[i] & ~CAMPAIGN_ACTIVE_FLAG; + if (campaign.Type == ADVERTISING_CAMPAIGN_RIDE_FREE || campaign.Type == ADVERTISING_CAMPAIGN_RIDE) + { + campaign.RideId = _s6.campaign_ride_index[i]; + } + else if (campaign.Type == ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE) + { + campaign.ShopItemType = _s6.campaign_ride_index[i]; + } + gMarketingCampaigns.push_back(campaign); + } + } + } }; std::unique_ptr ParkImporter::CreateS6(IObjectRepository& objectRepository) diff --git a/src/openrct2/scenario/Scenario.cpp b/src/openrct2/scenario/Scenario.cpp index 77fcdbbac7..4fe401478b 100644 --- a/src/openrct2/scenario/Scenario.cpp +++ b/src/openrct2/scenario/Scenario.cpp @@ -162,7 +162,7 @@ void scenario_begin() map_count_remaining_land_rights(); staff_reset_stats(); gLastEntranceStyle = 0; - std::fill_n(gMarketingCampaignDaysLeft, sizeof(gMarketingCampaignDaysLeft), 0x00); + gMarketingCampaigns.clear(); gParkRatingCasualtyPenalty = 0; // Open park with free entry when there is no money diff --git a/src/openrct2/world/Park.cpp b/src/openrct2/world/Park.cpp index 42be26cb09..de9ad8617c 100644 --- a/src/openrct2/world/Park.cpp +++ b/src/openrct2/world/Park.cpp @@ -541,11 +541,7 @@ void Park::Initialise() _guestGenerationProbability = 0; gTotalRideValueForMoney = 0; gResearchLastItem.rawValue = RESEARCHED_ITEMS_SEPARATOR; - - for (size_t i = 0; i < 20; i++) - { - gMarketingCampaignDaysLeft[i] = 0; - } + gMarketingCampaigns.clear(); research_reset_items(); finance_init(); @@ -967,15 +963,12 @@ void Park::GenerateGuests() } // Extra guests generated by advertising campaigns - for (int32_t campaign = 0; campaign < ADVERTISING_CAMPAIGN_COUNT; campaign++) + for (const auto& campaign : gMarketingCampaigns) { - if (gMarketingCampaignDaysLeft[campaign] != 0) + // Random chance of guest generation + if ((int32_t)scenario_rand_max(0xFFFF) < marketing_get_campaign_guest_generation_probability(campaign.Type)) { - // Random chance of guest generation - if ((int32_t)(scenario_rand() & 0xFFFF) < marketing_get_campaign_guest_generation_probability(campaign)) - { - GenerateGuestFromCampaign(campaign); - } + GenerateGuestFromCampaign(campaign.Type); } } }