1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-22 22:34:33 +01:00

add park update and guest generation

This commit is contained in:
IntelOrca
2014-05-25 13:59:31 +01:00
parent ba77a2916b
commit 6d7b4b1808
9 changed files with 245 additions and 14 deletions

View File

@@ -160,6 +160,8 @@
#define RCT2_ADDRESS_CURRENT_MONTH_YEAR 0x00F663A8
#define RCT2_ADDRESS_CURRENT_MONTH_TICKS 0x00F663AA
#define RCT2_ADDRESS_SCENARIO_SRAND_0 0x00F663B0
#define RCT2_ADDRESS_SCENARIO_SRAND_1 0x00F663B4
#define RCT2_ADDRESS_MAP_ELEMENTS 0x00F663B8
#define RCT2_ADDRESS_SPRITE_LIST 0x010E63BC
@@ -178,6 +180,7 @@
#define RCT2_ADDRESS_CURRENT_PARK_RATING 0x01357CB0
#define RCT2_ADDRESS_PARK_RATING_HISTORY 0x01357CB2
#define RCT2_ADDRESS_GUESTS_IN_PARK_HISTORY 0x01357CD2
#define RCT2_ADDRESS_GUEST_GENERATION_PROBABILITY 0x013580EC
#define RCT2_ADDRESS_OBJECTIVE_TYPE 0x013580F8
#define RCT2_ADDRESS_OBJECTIVE_YEAR 0x013580F9
#define RCT2_ADDRESS_OBJECTIVE_CURRENCY 0x013580FC
@@ -194,8 +197,11 @@
#define RCT2_ADDRESS_AWARD_LIST 0x01358760
#define RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED 0x013587F8
#define RCT2_ADDRESS_CURRENT_INTEREST_RATE 0x0135934A
#define RCT2_ADDRESS_EXPENDITURE_TABLE 0x01357848
#define RCT2_ADDRESS_PEEP_SPAWNS 0x013573F2
#define RCT2_ADDRESS_CURRENT_RESEARCH_LEVEL 0x013573FF
#define RCT2_ADDRESS_EXPENDITURE_TABLE 0x01357848
#define RCT2_ADDRESS_HANDYMAN_COLOUR 0x01357BCD
#define RCT2_ADDRESS_MECHANIC_COLOUR 0x01357BCE

View File

@@ -152,7 +152,7 @@ void game_logic_update()
RCT2_CALLPROC_EBPSAFE(0x006D4204); // update vehicles
RCT2_CALLPROC_EBPSAFE(0x00672AA4); // update text effects
RCT2_CALLPROC_EBPSAFE(0x006ABE4C); // update rides
RCT2_CALLPROC_EBPSAFE(0x006674F7); // update park
park_update();
RCT2_CALLPROC_EBPSAFE(0x00684C7A);
RCT2_CALLPROC_EBPSAFE(0x006B5A2A);
RCT2_CALLPROC_EBPSAFE(0x006B6456); // update ride measurements

View File

@@ -182,6 +182,15 @@ enum {
#define TILE_UNDEFINED_MAP_ELEMENT (rct_map_element*)-1
typedef struct {
uint16 x;
uint16 y;
uint8 z;
uint8 direction;
} rct2_peep_spawn;
void map_init();
void map_update_tile_pointers();
int map_element_height(int x, int y);

View File

@@ -30,6 +30,8 @@
#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;
@@ -53,7 +55,7 @@ void park_init()
RCT2_GLOBAL(0x01357846, uint16) = 0;
RCT2_GLOBAL(0x013573FE, uint16) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_RATING, uint16) = 0;
RCT2_GLOBAL(0x013580EC, uint16) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_GUEST_GENERATION_PROBABILITY, uint16) = 0;
RCT2_GLOBAL(0x013580EE, uint16) = 0;
RCT2_GLOBAL(0x01357CF4, sint32) = -1;
@@ -332,9 +334,9 @@ money32 calculate_company_value()
}
/**
*
* rct2: 0x00667104
*/
*
* rct2: 0x00667104
*/
void reset_park_entrances()
{
RCT2_GLOBAL(0x013573D4, uint16) = 0;
@@ -346,3 +348,164 @@ void reset_park_entrances()
RCT2_GLOBAL(0x013573F2, uint16) = 0xFFFF;
RCT2_GLOBAL(0x013573F8, uint16) = 0xFFFF;
}
/**
*
* rct2: 0x0066730A
*/
static int park_calculate_guest_generation_probability()
{
int eax, ebx, ecx, edx, esi, edi, ebp;
RCT2_CALLFUNC_X(0x0066730A, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
return eax & 0xFFFF;
}
static void get_random_peep_spawn(rct2_peep_spawn *spawn)
{
rct2_peep_spawn *peepSpawns = RCT2_ADDRESS(RCT2_ADDRESS_PEEP_SPAWNS, rct2_peep_spawn);
*spawn = peepSpawns[0];
if (peepSpawns[1].x != 0xFFFF)
if (scenario_rand() & 0x80000)
*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;
rct2_peep_spawn spawn;
get_random_peep_spawn(&spawn);
if (spawn.x != 0xFFFF) {
spawn.z *= 16;
spawn.direction ^= 2;
peep = peep_generate(spawn.x, spawn.y, spawn.z);
if (peep != NULL) {
peep->var_1E = spawn.direction << 3;
// Get the centre point of the tile the peep is on
peep->var_32 = (peep->x & 0xFFE0) + 16;
peep->var_34 = (peep->y & 0xFFE0) + 16;
peep->var_36 = 5;
peep->var_76 = 0;
peep->var_78 = spawn.direction;
peep->var_37 = 0;
peep->state = PEEP_STATE_ENTERING_PARK;
}
}
return peep;
}
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;
}
}
}
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();
// 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))
park_generate_new_guest_due_to_campaign(campaign);
}
}
}
/**
*
* rct2: 0x006674F7
*/
void park_update()
{
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)
return;
// Every 5 seconds approximately
if (RCT2_GLOBAL(0x013628F4, uint8) % 512 == 0) {
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_RATING, uint16) = calculate_park_rating();
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, money32) = calculate_park_value();
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_COMPANY_VALUE, money32) = calculate_company_value();
window_invalidate_by_id(WC_FINANCES, 0);
RCT2_GLOBAL(RCT2_ADDRESS_GUEST_GENERATION_PROBABILITY, uint16) = park_calculate_guest_generation_probability();
RCT2_GLOBAL(0x009A9804, uint16) |= 0x10;
window_invalidate_by_id(WC_PARK_INFORMATION, 0);
}
// Generate new guests
park_generate_new_guests();
}

View File

@@ -51,6 +51,16 @@ 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),
@@ -78,4 +88,6 @@ money32 calculate_park_value();
money32 calculate_company_value();
void reset_park_entrances();
void park_update();
#endif

View File

@@ -288,4 +288,18 @@ void peep_update_crowd_noise()
}
}
}
}
/**
*
* rct2: 0x0069A05D
*/
rct_peep *peep_generate(int x, int y, int z)
{
int eax, ebx, ecx, edx, esi, edi, ebp;
eax = x;
ecx = y;
edx = z;
RCT2_CALLFUNC_X(0x0069A05D, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
return (rct_peep*)esi;
}

View File

@@ -329,7 +329,8 @@ typedef struct {
sint16 var_18;
sint16 var_1A;
sint16 var_1C;
uint32 pad_1E;
uint8 var_1E;
uint8 pad_1F[3];
uint16 name_string_idx; // 0x22
uint16 next_x; // 0x24
uint16 next_y; // 0x26
@@ -342,7 +343,10 @@ typedef struct {
uint8 staff_type; // 0x2F
uint8 tshirt_colour; // 0x30
uint8 trousers_colour; // 0x31
uint8 pad_32[0x06];
uint16 var_32;
uint16 var_34;
uint8 var_36;
uint8 var_37;
uint8 energy; // 0x38
uint8 energy_growth_rate; // 0x39
uint8 happiness; // 0x3A
@@ -368,7 +372,10 @@ typedef struct {
uint8 current_train; // 0x6A
uint8 current_car; // 0x6B
uint8 current_seat; // 0x6C
uint8 pad_6D[0x0F];
uint8 pad_6D[0x09];
uint8 var_76;
uint8 var_78;
uint8 pad_79[0x03];
uint8 rides_been_on[32]; // 0x7C
uint32 id; // 0x9C
money32 cash_in_pocket; // 0xA0
@@ -391,7 +398,10 @@ typedef struct {
uint8 no_of_food; // 0xEC
uint8 no_of_drinks; // 0xED
uint8 no_of_souvenirs; // 0xEE
uint8 pad_EF[0x04];
uint8 pad_EF;
uint8 var_F0;
uint8 var_F1;
uint8 pad_F2;
uint8 var_F3;
uint8 pad_F4[0x02];
uint8 balloon_colour; // 0xF6
@@ -406,5 +416,6 @@ int peep_get_staff_count();
void peep_update_all();
void peep_problem_warnings_update();
void peep_update_crowd_noise();
rct_peep *peep_generate(int x, int y, int z);
#endif

View File

@@ -175,8 +175,11 @@ void scenario_load_and_play(const rct_scenario_basic *scenario)
rct_window *mainWindow;
rct_s6_info *s6Info = (rct_s6_info*)0x0141F570;
RCT2_GLOBAL(0x009AA0F0, uint32) = RCT2_GLOBAL(0x00F663B0, uint32) ^ timeGetTime();
RCT2_GLOBAL(0x009AA0F4, uint32) = RCT2_GLOBAL(0x00F663B4, uint32) ^ timeGetTime();
// Create the scenario pseduo-random seeds using the current time
uint32 srand0, srand1;
srand0 = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_0, uint32) ^ timeGetTime();
srand1 = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_1, uint32) ^ timeGetTime();
RCT2_CALLPROC_EBPSAFE(0x006CBCC3);
subsitute_path(
@@ -214,8 +217,10 @@ void scenario_load_and_play(const rct_scenario_basic *scenario)
RCT2_CALLPROC_EBPSAFE(0x0069E9A7);
window_new_ride_init_vars();
RCT2_GLOBAL(0x00F663B0, sint32) = RCT2_GLOBAL(0x009AA0F0, sint32);
RCT2_GLOBAL(0x00F663B4, sint32) = RCT2_GLOBAL(0x009AA0F4, sint32);
// Set the scenario pseduo-random seeds
RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_0, sint32) = srand0;
RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_1, sint32) = srand1;
RCT2_GLOBAL(0x009DEB7C, sint16) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, sint32) &= 0xFFFFF7FF;
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, sint32) & 0x20000)
@@ -678,3 +683,13 @@ void scenario_update()
}
/**
*
* rct2: 0x006E37D2
*/
int scenario_rand()
{
int eax = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_0, uint32);
RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_0, uint32) += ror32(RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_1, uint32) ^ 0x1234567F, 7);
return RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_1, uint32) = ror32(eax, 3);
}

View File

@@ -128,5 +128,6 @@ int scenario_load_basic(const char *path);
void scenario_load(const char *path);
void scenario_load_and_play(const rct_scenario_basic *scenario);
void scenario_update();
int scenario_rand();
#endif