separate marketing and add finances window

This commit is contained in:
IntelOrca 2014-05-25 23:17:55 +01:00
parent 4b55a116fe
commit 092764ea6b
12 changed files with 200 additions and 133 deletions

View File

@ -26,6 +26,7 @@
<ClInclude Include="..\src\gfx.h" />
<ClInclude Include="..\src\intro.h" />
<ClInclude Include="..\src\map.h" />
<ClInclude Include="..\src\marketing.h" />
<ClInclude Include="..\src\news_item.h" />
<ClInclude Include="..\src\object.h" />
<ClInclude Include="..\src\osinterface.h" />
@ -67,6 +68,7 @@
<ClCompile Include="..\src\gfx.c" />
<ClCompile Include="..\src\intro.c" />
<ClCompile Include="..\src\map.c" />
<ClCompile Include="..\src\marketing.c" />
<ClCompile Include="..\src\news_item.c" />
<ClCompile Include="..\src\object.c" />
<ClCompile Include="..\src\object_list.c" />

View File

@ -135,6 +135,9 @@
<ClInclude Include="..\src\vehicle.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\marketing.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\game.c">
@ -323,6 +326,9 @@
<ClCompile Include="..\src\sprite.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\marketing.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\openrct2.exe">

View File

@ -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)) {

126
src/marketing.c Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*****************************************************************************/
#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;
}
}

40
src/marketing.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*****************************************************************************/
#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

View File

@ -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:

View File

@ -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);
}
}

View File

@ -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),

View File

@ -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();

View File

@ -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();

View File

@ -18,9 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include <string.h>
#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;
} WINDOW_FINANCIAL_TAB;
/**
*
* rct2: 0x0069DDF1
*/
void window_finances_open()
{
RCT2_CALLPROC_EBPSAFE(0x0069DDF1);
}

View File

@ -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();