diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index c67891ee19..87cb5837f5 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -26,6 +26,7 @@ + @@ -67,6 +68,7 @@ + diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters index 8000ad144c..4da48f42e3 100644 --- a/projects/openrct2.vcxproj.filters +++ b/projects/openrct2.vcxproj.filters @@ -135,6 +135,9 @@ Header Files + + Header Files + @@ -323,6 +326,9 @@ Source Files + + Source Files + diff --git a/src/game.c b/src/game.c index d1529dacab..0a9e82f4ab 100644 --- a/src/game.c +++ b/src/game.c @@ -1022,7 +1022,7 @@ void handle_shortcut_command(int shortcutIndex) case SHORTCUT_SHOW_FINANCIAL_INFORMATION: if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & 0x800)) - RCT2_CALLPROC_EBPSAFE(0x0069DDF1); + window_finances_open(); break; case SHORTCUT_SHOW_RESEARCH_INFORMATION: if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) { diff --git a/src/marketing.c b/src/marketing.c new file mode 100644 index 0000000000..15b7192035 --- /dev/null +++ b/src/marketing.c @@ -0,0 +1,126 @@ +/***************************************************************************** + * Copyright (c) 2014 Ted John + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * This file is part of OpenRCT2. + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *****************************************************************************/ + +#include "addresses.h" +#include "marketing.h" +#include "news_item.h" +#include "rct2.h" +#include "ride.h" +#include "string_ids.h" +#include "window.h" + +const int advertisingCampaignGuestGenerationProbabilities[] = { 400, 300, 200, 200, 250, 200 }; + +int marketing_get_campaign_guest_generation_probability(int campaign) +{ + int probability = advertisingCampaignGuestGenerationProbabilities[campaign]; + rct_ride *ride; + + // Lower probability of guest generation if price was already low + switch (campaign) { + case ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE: + if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) < 4) + probability /= 8; + break; + case ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE: + if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) < 6) + probability /= 8; + break; + case ADVERTISING_CAMPAIGN_RIDE_FREE: + ride = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[RCT2_ADDRESS(0x01358116, uint8)[campaign]]); + if (ride->price < 3) + probability /= 8; + break; + } + + return probability; +} + +/* + * Update status of marketing campaigns and send produce a news item when they have finished. + * rct2: 0x0069E0C1 + **/ +void marketing_update() +{ + for (int campaign = 0; campaign < ADVERTISING_CAMPAIGN_COUNT; campaign++) { + uint8 campaign_weeks_left = RCT2_ADDRESS(0x01358102, uint8)[campaign]; + if (campaign_weeks_left == 0) + continue; + + window_invalidate_by_id(WC_FINANCES, 0); + + // High bit marks the campaign as inactive, on first check the campaign is set actice + // this makes campaigns run a full x weeks even when started in the middle of a week + RCT2_ADDRESS(0x01358102, uint8)[campaign] &= ~(1 << 7); + if (campaign_weeks_left & (1 << 7)) + continue; + + RCT2_ADDRESS(0x01358102, uint8)[campaign]--; + if (campaign_weeks_left - 1 != 0) + continue; + + int campaign_item = RCT2_ADDRESS(0x01358116, uint8)[campaign]; + + // This sets the string parameters for the marketing types that have an argument. + if (campaign == ADVERTISING_CAMPAIGN_RIDE_FREE || campaign == ADVERTISING_CAMPAIGN_RIDE) { + RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(0x01362942 + 304 * campaign_item, uint16); + RCT2_GLOBAL(0x013CE954, uint32) = RCT2_GLOBAL(0x01362944 + 152 * campaign_item, uint32); + } else if (campaign == ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE) { + campaign_item += 2016; + if (campaign_item >= 2048) + campaign_item += 96; + RCT2_GLOBAL(0x013CE952, uint16) = campaign_item; + } + + news_item_add_to_queue(NEWS_ITEM_MONEY, STR_MARKETING_FINISHED_BASE + campaign, 0); + } +} + +void marketing_set_guest_campaign(rct_peep *peep, int campaign) +{ + switch (campaign) { + case ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE: + peep->item_standard_flags |= PEEP_ITEM_VOUCHER; + peep->var_F0 = 0; + break; + case ADVERTISING_CAMPAIGN_RIDE_FREE: + peep->item_standard_flags |= PEEP_ITEM_VOUCHER; + peep->var_F0 = 1; + peep->var_F1 = RCT2_ADDRESS(0x01358116, uint8)[campaign]; + peep->var_C5 = RCT2_ADDRESS(0x01358116, uint8)[campaign]; + peep->var_C6 = 240; + break; + case ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE: + peep->item_standard_flags |= PEEP_ITEM_VOUCHER; + peep->var_F0 = 2; + break; + case ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE: + peep->item_standard_flags |= PEEP_ITEM_VOUCHER; + peep->var_F0 = 3; + peep->var_F1 = RCT2_ADDRESS(0x01358116, uint8)[campaign]; + break; + case ADVERTISING_CAMPAIGN_PARK: + break; + case ADVERTISING_CAMPAIGN_RIDE: + peep->var_C5 = RCT2_ADDRESS(0x01358116, uint8)[campaign]; + peep->var_C6 = 240; + break; + } +} \ No newline at end of file diff --git a/src/marketing.h b/src/marketing.h new file mode 100644 index 0000000000..43e99796c9 --- /dev/null +++ b/src/marketing.h @@ -0,0 +1,40 @@ +/***************************************************************************** + * Copyright (c) 2014 Ted John + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * This file is part of OpenRCT2. + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *****************************************************************************/ + +#ifndef _MARKETING_H_ +#define _MARKETING_H_ + +#include "peep.h" + +enum { + ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE, + ADVERTISING_CAMPAIGN_RIDE_FREE, + ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE, + ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE, + ADVERTISING_CAMPAIGN_PARK, + ADVERTISING_CAMPAIGN_RIDE, + ADVERTISING_CAMPAIGN_COUNT +}; + +int marketing_get_campaign_guest_generation_probability(int campaign); +void marketing_update(); +void marketing_set_guest_campaign(rct_peep *peep, int campaign); + +#endif \ No newline at end of file diff --git a/src/news_item.c b/src/news_item.c index c286097201..5e32c37f5b 100644 --- a/src/news_item.c +++ b/src/news_item.c @@ -299,8 +299,7 @@ void news_item_open_subject(int type, int subject) { RCT2_CALLPROC_X(0x006989E9, 0, 0, 0, (int)peep, 0, 0, 0); break; case NEWS_ITEM_MONEY: - // Open finances window - RCT2_CALLPROC_EBPSAFE(0x0069DDF1); + window_finances_open(); break; case NEWS_ITEM_RESEARCH: diff --git a/src/park.c b/src/park.c index 8d65ef999b..191880ff0c 100644 --- a/src/park.c +++ b/src/park.c @@ -22,6 +22,7 @@ #include "addresses.h" #include "finance.h" #include "map.h" +#include "marketing.h" #include "park.h" #include "peep.h" #include "ride.h" @@ -30,8 +31,6 @@ #include "string_ids.h" #include "window.h" -const int advertisingCampaignGuestGenerationProbabilities[] = { 400, 300, 200, 200, 250, 200 }; - int park_is_open() { return (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_OPEN) != 0; @@ -370,17 +369,6 @@ static void get_random_peep_spawn(rct2_peep_spawn *spawn) *spawn = peepSpawns[1]; } -static int park_should_generate_new_guest() -{ - if ((scenario_rand() & 0xFFFF) < RCT2_GLOBAL(0x013580EC, uint16)) { - int difficultGeneration = (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_DIFFICULT_GUEST_GENERATION) != 0; - if (!difficultGeneration || RCT2_GLOBAL(0x0135883C, uint16) + 150 < RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16)) - return 1; - } - - return 0; -} - static rct_peep *park_generate_new_guest() { rct_peep *peep; @@ -412,76 +400,26 @@ static rct_peep *park_generate_new_guest() static rct_peep *park_generate_new_guest_due_to_campaign(int campaign) { rct_peep *peep = park_generate_new_guest(); - if (peep != NULL) { - switch (campaign) { - case ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE: - peep->item_standard_flags |= PEEP_ITEM_VOUCHER; - peep->var_F0 = 0; - break; - case ADVERTISING_CAMPAIGN_RIDE_FREE: - peep->item_standard_flags |= PEEP_ITEM_VOUCHER; - peep->var_F0 = 1; - peep->var_F1 = RCT2_ADDRESS(0x01358116, uint8)[campaign]; - peep->var_C5 = RCT2_ADDRESS(0x01358116, uint8)[campaign]; - peep->var_C6 = 240; - break; - case ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE: - peep->item_standard_flags |= PEEP_ITEM_VOUCHER; - peep->var_F0 = 2; - break; - case ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE: - peep->item_standard_flags |= PEEP_ITEM_VOUCHER; - peep->var_F0 = 3; - peep->var_F1 = RCT2_ADDRESS(0x01358116, uint8)[campaign]; - break; - case ADVERTISING_CAMPAIGN_PARK: - break; - case ADVERTISING_CAMPAIGN_RIDE: - peep->var_C5 = RCT2_ADDRESS(0x01358116, uint8)[campaign]; - peep->var_C6 = 240; - break; - } - } + if (peep != NULL) + marketing_set_guest_campaign(peep, campaign); return peep; } -static int park_get_campaign_guest_generation_probability(int campaign) -{ - int probability = advertisingCampaignGuestGenerationProbabilities[campaign]; - rct_ride *ride; - - // Lower probability of guest generation if price was already low - switch (campaign) { - case ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE: - if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) < 4) - probability /= 8; - break; - case ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE: - if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) < 6) - probability /= 8; - break; - case ADVERTISING_CAMPAIGN_RIDE_FREE: - ride = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[RCT2_ADDRESS(0x01358116, uint8)[campaign]]); - if (ride->price < 3) - probability /= 8; - break; - } - - return probability; -} - static void park_generate_new_guests() { - // Check and generate a new guest - if (park_should_generate_new_guest()) - park_generate_new_guest(); + // Generate a new guest for some probability + if ((scenario_rand() & 0xFFFF) < RCT2_GLOBAL(0x013580EC, uint16)) { + int difficultGeneration = (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_DIFFICULT_GUEST_GENERATION) != 0; + if (!difficultGeneration || RCT2_GLOBAL(0x0135883C, uint16) + 150 < RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16)) + park_generate_new_guest(); + } // Extra guests generated by advertising campaigns int campaign; for (campaign = 0; campaign < ADVERTISING_CAMPAIGN_COUNT; campaign++) { if (RCT2_ADDRESS(0x01358102, uint8)[campaign] != 0) { // Random chance of guest generation - if ((scenario_rand() & 0xFFFF) < park_get_campaign_guest_generation_probability(campaign)) + if ((scenario_rand() & 0xFFFF) < marketing_get_campaign_guest_generation_probability(campaign)) park_generate_new_guest_due_to_campaign(campaign); } } diff --git a/src/park.h b/src/park.h index 3d4d778caa..9d3dcc4697 100644 --- a/src/park.h +++ b/src/park.h @@ -51,16 +51,6 @@ enum { PARK_AWARD_BEST_GENTLE_RIDES, }; -enum { - ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE, - ADVERTISING_CAMPAIGN_RIDE_FREE, - ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE, - ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE, - ADVERTISING_CAMPAIGN_PARK, - ADVERTISING_CAMPAIGN_RIDE, - ADVERTISING_CAMPAIGN_COUNT -}; - enum { PARK_FLAGS_PARK_OPEN = (1 << 0), PARK_FLAGS_FORBID_LANDSCAPE_CHANGES = (1 << 2), diff --git a/src/scenario.c b/src/scenario.c index a18407e6f8..9fdd0c0003 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -25,6 +25,7 @@ #include "finance.h" #include "game.h" #include "map.h" +#include "marketing.h" #include "news_item.h" #include "object.h" #include "park.h" @@ -561,49 +562,6 @@ void scenario_entrance_fee_too_high_check() } } - -/* - * Update status of marketing campaigns and send a message when they are done. - * rct2: 0x0069E0C1 - **/ -void scenario_marketing_update() -{ - for (int i = 0; i < 6; ++i) { - uint8 campaign_weeks_left = RCT2_ADDRESS(0x01358102, uint8)[i]; - int campaign_item = 0; - - if (!campaign_weeks_left) - continue; - window_invalidate_by_id(WC_FINANCES, 0); - - // high bit marks the campaign as inactive, on first check the campaign is set actice - // this makes campaigns run a full x weeks even when started in the middle of a week - RCT2_ADDRESS(0x01358102, uint8)[i] &= ~(1 << 7); - if (campaign_weeks_left & (1 << 7)) - continue; - - RCT2_ADDRESS(0x01358102, uint8)[i]--; - if (campaign_weeks_left - 1 != 0) - continue; - - campaign_item = RCT2_ADDRESS(0x01358116, uint8)[i]; - - // this sets the string parameters for the marketing types that have an argument. - if (i == 1 || i == 5) { // free RIDES oh yea - RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(0x01362942 + 304 * campaign_item, uint16);; - RCT2_GLOBAL(0x013CE954, uint32) = RCT2_GLOBAL(0x01362944 + 152 * campaign_item, uint32); - } else if (i == 3) { // free food/merch - campaign_item += 2016; - if (campaign_item >= 2048) - campaign_item += 96; - RCT2_GLOBAL(0x013CE952, uint16) = campaign_item; - } - - news_item_add_to_queue(NEWS_ITEM_MONEY, STR_MARKETING_FINISHED_BASE + i, 0); - } -} - - /* * Scenario and finance related update iteration. * rct2: 0x006C44B1 @@ -639,7 +597,7 @@ void scenario_update() finance_pay_wages(); finance_pay_research(); finance_pay_interest(); - scenario_marketing_update(); + marketing_update(); peep_problem_warnings_update(); RCT2_CALLPROC_EBPSAFE(0x006B7A5E); // check ride reachability ride_update_favourited_stat(); diff --git a/src/window.h b/src/window.h index 25e3478852..6e43bd495c 100644 --- a/src/window.h +++ b/src/window.h @@ -359,6 +359,7 @@ void window_park_entrance_open(); void window_park_guests_open(); void window_park_objective_open(); void window_park_rating_open(); +void window_finances_open(); void window_ride_list_open(); void window_banner_open(); void window_cheats_open(); diff --git a/src/window_finances.c b/src/window_finances.c index a2244518dd..0cf98b5d81 100644 --- a/src/window_finances.c +++ b/src/window_finances.c @@ -18,9 +18,7 @@ * along with this program. If not, see . *****************************************************************************/ -#include #include "addresses.h" -#include "game.h" #include "window.h" enum { @@ -30,4 +28,13 @@ enum { WINDOW_FINANCES_TAB_PROFIT_GRAPH, WINDOW_FINANCES_TAB_MARKETING, WINDOW_FINANCES_TAB_RESEARCH -} WINDOW_FINANCIAL_TAB; \ No newline at end of file +} WINDOW_FINANCIAL_TAB; + +/** + * + * rct2: 0x0069DDF1 + */ +void window_finances_open() +{ + RCT2_CALLPROC_EBPSAFE(0x0069DDF1); +} \ No newline at end of file diff --git a/src/window_game_bottom_toolbar.c b/src/window_game_bottom_toolbar.c index 3966c3904f..efe61f769a 100644 --- a/src/window_game_bottom_toolbar.c +++ b/src/window_game_bottom_toolbar.c @@ -172,7 +172,7 @@ static void window_game_bottom_toolbar_mouseup() case WIDX_LEFT_OUTSET: case WIDX_MONEY: if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & 0x800)) - RCT2_CALLPROC_EBPSAFE(0x0069DDF1); + window_finances_open(); break; case WIDX_GUESTS: window_park_guests_open();