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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
171
src/park.c
171
src/park.c
@@ -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();
|
||||
}
|
||||
12
src/park.h
12
src/park.h
@@ -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
|
||||
|
||||
14
src/peep.c
14
src/peep.c
@@ -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;
|
||||
}
|
||||
19
src/peep.h
19
src/peep.h
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user