This commit is contained in:
Duncan Frost 2014-05-08 17:38:57 +01:00
commit 6af1306c23
17 changed files with 502 additions and 89 deletions

View File

@ -178,6 +178,8 @@
#define RCT2_ADDRESS_CURRENT_TICKS 0x013628F4
#define RCT2_ADDRESS_RIDE_LIST 0x013628F8
#define RCT2_ADDRESS_RIDE_COUNT 0x013587C8
#define RCT2_ADDRESS_RIDE_FLAGS 0x0097CF40
#define RCT2_ADDRESS_SAVED_VIEW_X 0x0138869A
#define RCT2_ADDRESS_SAVED_VIEW_Y 0x0138869C
#define RCT2_ADDRESS_RIDE_MEASUREMENTS 0x0138B60C
@ -215,10 +217,16 @@
#define RCT2_ADDRESS_NEW_WINDOW_PTR 0x014234B8
#define RCT2_ADDRESS_VIEWPORT_LIST 0x014234BC
#define RCT2_ADDRESS_NEW_VIEWPORT_PTR 0x01423570
#define RCT2_ADDRESS_WINDOW_GUEST_LIST_SELECTED_FILTER 0x00F1EE06
#define RCT2_ADDRESS_WINDOW_GUEST_LIST_SELECTED_TAB 0x00F1EE12
#define RCT2_ADDRESS_WINDOW_GUEST_LIST_SELECTED_FILTER 0x00F1EE06
#define RCT2_ADDRESS_WINDOW_GUEST_LIST_SELECTED_TAB 0x00F1EE12
#define RCT2_ADDRESS_WINDOW_GUEST_LIST_SELECTED_VIEW 0x00F1EE13
#define RCT2_ADDRESS_WINDOW_RIDE_LIST_INFORMATION_TYPE 0x00F43833
#define RCT2_ADDRESS_WINDOW_RIDE_LIST_SELECTED_TAB 0x00F43824
#define RCT2_ADDRESS_WINDOW_RIDE_LIST_HIGHLIGHTED_ITEM 0x00F43825
#define RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB 0x00F4390A
#define RCT2_ADDRESS_OS_TIME_MINUTE 0x01424654
#define RCT2_ADDRESS_OS_TIME_HOUR 0x01424656

View File

@ -25,6 +25,7 @@
#include "addresses.h"
#include "config.h"
#include "rct2.h"
#include <tchar.h>
// Current keyboard shortcuts
uint16 gShortcutKeys[SHORTCUT_COUNT];
@ -78,7 +79,7 @@ void config_reset_shortcut_keys()
}
/**
*
* Reads the config file data/config.cfg
* rct2: 0x006752D5
*/
void config_load()
@ -86,6 +87,7 @@ void config_load()
HANDLE hFile;
DWORD bytesRead;
char* path = get_file_path(PATH_ID_GAMECFG);
hFile = CreateFile(get_file_path(PATH_ID_GAMECFG), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
@ -98,14 +100,15 @@ void config_load()
if (RCT2_GLOBAL(0x009AB4C6, sint8) == 1)
return;
RCT2_GLOBAL(0x009AB4C6, sint8) = 1;
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, sint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FAHRENHEIT, sint8) = 1;
RCT2_GLOBAL(0x009AACBB, sint8) = 1;
RCT2_GLOBAL(0x009AACBD, sint16) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, sint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FAHRENHEIT, sint8) = 1;
RCT2_GLOBAL(0x009AACBB, sint8) = 1;
RCT2_GLOBAL(0x009AACBD, sint16) = 0;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS))
RCT2_GLOBAL(0x009AACBD, sint16) = (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, sint8) + 1) * 256;
RCT2_GLOBAL(0x009AA00D, sint8) = 1;
}
}
RCT2_GLOBAL(0x009AAC77, sint8) = 0;
@ -124,7 +127,7 @@ void config_load()
}
/**
*
* Save configuration to the data/config.cfg file
* rct2: 0x00675487
*/
void config_save()
@ -144,9 +147,14 @@ void config_save()
configuration_t gConfig;
static char *config_show_directory_browser();
static void config_parse_settings(FILE *fp);
static int config_get_line(FILE *fp, char *setting, char *value);
static int config_parse_setting(FILE *fp, char *setting);
static int config_parse_value(FILE *fp, char *value);
static int config_parse_section(FILE *fp, char *setting, char *value);
static void config_create_default(char *path);
static void config_error(char *msg);
/**
* Initilise the settings.
@ -163,7 +171,7 @@ void config_init()
DWORD dwAttrib = GetFileAttributes(path);
if (dwAttrib == INVALID_FILE_ATTRIBUTES || !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) { // folder does not exist
if (!CreateDirectory(path, NULL)) {
return NULL; // error creating path
config_error("Could not create config file (do you have write access to your documents folder?)");
}
}
strcat(path, "\\config.ini");
@ -172,10 +180,12 @@ void config_init()
config_create_default(path);
fp = fopen(path, "r");
if (!fp)
return NULL;
config_error("Could not create config file");
}
config_parse_settings(fp);
fclose(fp);
}
}
@ -220,8 +230,9 @@ static void config_create_default(char *path)
FILE* fp;
if (!config_find_rct2_path(gConfig.game_path)) {
MessageBox(NULL, "Unable to find RCT2 installation directory. Please correct in config.ini.", "OpenRCT2", MB_OK);
strcpy(gConfig.game_path, "C:\\");
MessageBox(NULL, "Unable to find RCT2 installation directory. Please select the directoy where you installed RCT2!", "OpenRCT2", MB_OK);
char *res = config_show_directory_browser();
strcpy(gConfig.game_path, res);
}
fp = fopen(path, "w");
@ -232,6 +243,51 @@ static void config_create_default(char *path)
fclose(fp);
}
/**
* A directory browser allowing for semi-automatic config.ini for non standard installs.
*/
static char *config_show_directory_browser()
{
BROWSEINFO bi;
char pszBuffer[MAX_PATH];
LPITEMIDLIST pidl;
LPMALLOC lpMalloc;
// Initialize COM
if (CoInitializeEx(0, COINIT_APARTMENTTHREADED) != S_OK) {
MessageBox(NULL, _T("Error opening browse window"), _T("ERROR"), MB_OK);
CoUninitialize();
return 0;
}
// Get a pointer to the shell memory allocator
if (SHGetMalloc(&lpMalloc) != S_OK) {
MessageBox(NULL, _T("Error opening browse window"), _T("ERROR"), MB_OK);
CoUninitialize();
return 0;
}
bi.hwndOwner = NULL;
bi.pidlRoot = NULL;
bi.pszDisplayName = pszBuffer;
bi.lpszTitle = _T("Select your RCT2 installation directory");
bi.ulFlags = BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS;
bi.lpfn = NULL;
bi.lParam = 0;
char *outPath = "C:\\";
if (pidl = SHBrowseForFolder(&bi)) {
// Copy the path directory to the buffer
if (SHGetPathFromIDList(pidl, pszBuffer)) {
// Store pszBuffer (and the path) in the outPath
outPath = strcat("", pszBuffer);
}
}
CoUninitialize();
return outPath;
}
/**
* Parse settings and set the game veriables
* @param fp file pointer to the settings file
@ -241,18 +297,25 @@ static void config_parse_settings(FILE *fp)
int c = NULL, pos = 0;
char *setting;
char *value;
setting = (char *)malloc(128);
value = (char *)malloc(128);
int size = 256;
char *section;
setting = (char *)malloc(MAX_CONFIG_LENGTH);
value = (char *)malloc(MAX_CONFIG_LENGTH);
section = (char*)malloc(MAX_CONFIG_LENGTH);
while (config_get_line(fp, setting, value) > 0) {
if (strcmp(setting, "game_path") == 0){
strcpy(gConfig.game_path, value); // TODO: change to copy correct amount of bytes
if (strcmp(setting, "section") == 0){
strcpy(section, value);
continue;
}
if (strcmp(setting, "game_path") == 0){
strcpy(gConfig.game_path, value);
} else if(strcmp(setting, "screenshot_format") == 0) {
if (strcmp(value, "png") == 0 || strcmp(value, "PNG") == 0) {
gConfig.screenshot_format = SCREENSHOT_FORMAT_PNG;
} else if (strcmp(value, "1") == 0) { // Maybe remove that? WARNING: Breaks existing config files
} else if (strcmp(value, "1") == 0) { //TODO: REMOVE LINE AT LATER DATE WHEN EVERYONE HAS NEW CONFIG FORMAT
gConfig.screenshot_format = SCREENSHOT_FORMAT_PNG;
} else {
gConfig.screenshot_format = SCREENSHOT_FORMAT_BMP;
@ -261,78 +324,189 @@ static void config_parse_settings(FILE *fp)
gConfig.play_intro = (strcmp(value, "true") == 0);
}
}
free(setting);
free(value);
free(section);
}
/**
* Read one line in the settings file
* @param fp filepointer to the settings file
* @param fp filepointer to the config file
* @param setting pointer where to to store the setting
* @param value pointer to where to store the value
* @return < 0 on error
* @return < 0 if EOF file is reached or other error
*/
static int config_get_line(FILE *fp, char *setting, char *value)
{
long start = ftell(fp);
long end;
int c;
int pos = 0;
long size;
c = fgetc(fp);
if (c == EOF)
return -1;
while (isalpha(c) || c == '_'){
c = fgetc(fp); // find size of setting
if (c == EOF)
return -1;
while (isspace(c)){
c = getc(fp);
}
end = ftell(fp);
size = end - start;
realloc(setting, size);
fseek(fp, start, SEEK_SET);
c = fgetc(fp);
if (c == '[') {
// TODO support categories
setting[0] = '\0';
value[0] = '\0';
while (c != '\n' && c != EOF) {
pos++;
if (c == '['){
return config_parse_section(fp, setting, value);
}
else if(c == '#'){
while (c != '\n'){
c = fgetc(fp);
}
return 1;
}
while (isalpha(c) || c == '_'){
setting[pos] = (char)c;
pos++;
c = fgetc(fp);
}
setting[pos] = '\0';
while (c != '=') {
if (c == EOF || c == '\n') { // this is not a valid setting
return -1;
}
if (c == EOF){
return -1;
}
while (!isalpha(c)){
c = fgetc(fp);
}
//if the first char is not the '[' char, it belongs to the setting name. We want to leave that for the next fn
fseek(fp, -1, SEEK_CUR);
config_parse_setting(fp, setting);
c = fgetc(fp);
while (isspace(c)) {
while (isspace(c)){
c = getc(fp);
}
if (c != '='){
config_error("There is an error in your configuration file");
return -1;
}
config_parse_value(fp, value);
return 1;
}
/**
* Parse the value of a setting
* @param fp a filepointer to the config file
* @param value a pointer to where to store the setting
* @return < 0 if EOF is reached
*/
static int config_parse_setting(FILE *fp, char *setting){
long start, end;
int size, c, pos = 0;
start = ftell(fp);
c = fgetc(fp);
while (isspace(c)){
start = ftell(fp);
c = fgetc(fp);
}
if (c == EOF){
return -1;
}
while (isalpha(c) || c == '_'){
c = fgetc(fp);
}
end = ftell(fp);
size = end - start;
fseek(fp, start, SEEK_SET);
c = fgetc(fp);
while (isalpha(c) || c == '_'){
setting[pos] = (char)c;
c = fgetc(fp);
pos++;
}
setting[pos] = '\0';
return 1;
}
/**
* Parse the value of a setting
* @param fp a filepointer to the config file
* @param value a pointer to where to store the value
* @return < 0 if EOF is reached
*/
static int config_parse_value(FILE *fp, char *value){
long start, end;
int size, c, pos = 0;
start = ftell(fp);
while (c != '\n' && c!= EOF) {
c = fgetc(fp);
while (isspace(c)){
start = ftell(fp);
c = fgetc(fp);
}
while (c != EOF && c != '\n'){
c = fgetc(fp);
}
end = ftell(fp);
size = end - start;
if (size > MAX_CONFIG_LENGTH){
config_error("One of your settings is too long");
}
fseek(fp, start, SEEK_SET);
c = fgetc(fp);
while (c != EOF && c != '\n'){
value[pos] = (char)c;
c = fgetc(fp);
pos++;
}
value[pos] = '\0';
return;
}
/**
* Parse the current section
* @param fp Filepointer to the config file
* @param setting This is set to contain the string "section"
* @param value Pointer to where the section name should be put
* @return < 0 if EOF is reached
*/
static int config_parse_section(FILE *fp, char *setting, char *value){
int size, c, pos = 0;
long start, end;
strcpy(setting, "section\0");
c = fgetc(fp);
start = ftell(fp);
while (c != ']' && c != EOF){
c = fgetc(fp);
}
end = ftell(fp);
size = end - start;
realloc(value, size);
fseek(fp, start - 1, SEEK_SET);
pos = 0;
c = fgetc(fp);
while (c != '\n' && c != EOF) {
while (c != ']' && c != EOF){
value[pos] = (char)c;
pos++;
c = fgetc(fp);
pos++;
}
value[pos] = '\0';
}
if (c != ']'){
config_error("There is an error with the section headers");
}
c = fgetc(fp); //devour ']'
return 1;
}
/**
* Error with config file. Print error message an quit the game
* @param msg Message to print in message box
*/
static void config_error(char *msg){
MessageBox(NULL, msg, "OpenRCT2", MB_OK);
//TODO:SHUT DOWN EVERYTHING!
}

View File

@ -71,6 +71,11 @@ enum {
SCREENSHOT_FORMAT_PNG
};
enum {
TEMPERATURE_FORMAT_C,
TEMPERATURE_FORMAT_F
};
extern uint16 gShortcutKeys[SHORTCUT_COUNT];
void config_reset_shortcut_keys();
@ -79,6 +84,9 @@ void config_save();
// New config format
#define MAX_CONFIG_LENGTH 256
typedef struct configuration {
uint8 play_intro;
@ -86,6 +94,9 @@ typedef struct configuration {
char game_path[MAX_PATH];
} configuration_t;
//typedef struct hotkey_configuration{
//};
extern configuration_t gConfig;
void config_init();

View File

@ -53,16 +53,16 @@ void editor_load()
RCT2_CALLPROC_EBPSAFE(0x0069EB13); // sprites_init
ride_init_all();
window_guest_list_init_vars_a();
RCT2_CALLPROC_EBPSAFE(0x006BD3A4);
sub_6BD3A4();
park_init();
finance_init();
date_reset();
window_guest_list_init_vars_b();
RCT2_CALLPROC_EBPSAFE(0x006BD39C);
RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8) = WINDOW_STAFF_LIST_TAB_HANDYMEN;
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_SCENARIO_EDITOR;
RCT2_GLOBAL(0x0141F570, uint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) |= PARK_FLAGS_SHOW_REAL_GUEST_NAMES;
RCT2_CALLPROC_EBPSAFE(0x006ACA58);
window_ride_list_init_vars();
RCT2_GLOBAL(0x0141F571, uint8) = 4;
viewport_init_all();
news_item_init_queue();
@ -102,15 +102,15 @@ void trackdesigner_load()
RCT2_CALLPROC_EBPSAFE(0x0069EB13); // reset_sprites
ride_init_all();
window_guest_list_init_vars_a();
RCT2_CALLPROC_EBPSAFE(0x006BD3A4);
sub_6BD3A4();
park_init();
finance_init();
date_reset();
window_guest_list_init_vars_b();
RCT2_CALLPROC_EBPSAFE(0x006BD39C);
RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8) = WINDOW_STAFF_LIST_TAB_HANDYMEN;
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_TRACK_DESIGNER;
RCT2_GLOBAL(0x0141F570, uint8) = 0;
RCT2_CALLPROC_EBPSAFE(0x006ACA58);
window_ride_list_init_vars();
viewport_init_all();
news_item_init_queue();
RCT2_CALLPROC_EBPSAFE(0x0066EF38); // window_main_editor_create
@ -140,15 +140,15 @@ void trackmanager_load()
RCT2_CALLPROC_EBPSAFE(0x0069EB13); // reset_sprites
ride_init_all();
window_guest_list_init_vars_a();
RCT2_CALLPROC_EBPSAFE(0x006BD3A4);
sub_6BD3A4();
park_init();
finance_init();
date_reset();
window_guest_list_init_vars_b();
RCT2_CALLPROC_EBPSAFE(0x006BD39C);
RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8) = WINDOW_STAFF_LIST_TAB_HANDYMEN;
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_TRACK_MANAGER;
RCT2_GLOBAL(0x0141F570, uint8) = 0;
RCT2_CALLPROC_EBPSAFE(0x006ACA58);
window_ride_list_init_vars();
viewport_init_all();
news_item_init_queue();
RCT2_CALLPROC_EBPSAFE(0x0066EF38); // window_main_editor_create
@ -170,4 +170,18 @@ static void set_all_land_owned()
int mapSize = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, sint16);
game_do_command(64, 1, 64, 2, 56, (mapSize - 2) * 32, (mapSize - 2) * 32);
}
/**
*
* rct2: 0x006BD3A4
*/
void sub_6BD3A4() {
for (short i = 0; i < 200; i++) {
RCT2_ADDRESS(0x013CA672, uint8)[i] = 0;
}
for (short i = 200; i < 204; i++) {
RCT2_ADDRESS(0x013CA672, uint8)[i] = 1;
}
RCT2_CALLPROC_EBPSAFE(0x006C0C3F);
}

View File

@ -26,4 +26,6 @@ void editor_convert_save_to_scenario();
void trackdesigner_load();
void trackmanager_load();
void sub_6BD3A4();
#endif

View File

@ -25,9 +25,9 @@
#include "peep.h"
#include "window.h"
// monthly cost
const int wage_table[4] = { 500, 800, 600, 550 };
const int research_cost_table[4] = { 0, 1000, 2000, 4000 }; // monthly cost
const int research_cost_table[4] = { 0, 1000, 2000, 4000 };
/**
*
@ -67,7 +67,7 @@ void finance_pay_wages()
for (sprite_idx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); sprite_idx != SPRITE_INDEX_NULL; sprite_idx = peep->next) {
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[sprite_idx].peep);
if (peep->type == PEEP_TYPE_STAFF)
finance_payment(wage_table[peep->staff_type], RCT_EXPENDITURE_TYPE_WAGES);
finance_payment(wage_table[peep->staff_type] / 4, RCT_EXPENDITURE_TYPE_WAGES);
}
}
@ -109,7 +109,7 @@ void finance_pay_interest()
void finance_init() {
for (short i = 0; i < 56; i++) {
RCT2_ADDRESS(0x01357848, uint32)[i] = 0;
RCT2_ADDRESS(RCT2_ADDRESS_EXPENDITURE_TABLE, uint32)[i] = 0;
}
RCT2_GLOBAL(0x0135832C, uint32) = 0;
@ -119,7 +119,7 @@ void finance_init() {
RCT2_GLOBAL(0x01358334, uint32) = 0;
RCT2_GLOBAL(0x01358338, uint16) = 0;
RCT2_GLOBAL(0x013573DC, uint32) = 100000;
RCT2_GLOBAL(0x013573DC, uint32) = 100000; // Cheat detection
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, sint32) = ENCRYPT_MONEY(100000);
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, sint32) = 100000;
@ -137,4 +137,4 @@ void finance_init() {
RCT2_GLOBAL(0x013587D8, uint16) = 0x3F;
RCT2_CALLPROC_EBPSAFE(0x0069E869);
}
}

View File

@ -24,6 +24,7 @@
#include "config.h"
#include "rct2.h"
#include "game.h"
#include "finance.h"
#include "news_item.h"
#include "object.h"
#include "osinterface.h"
@ -1057,6 +1058,7 @@ int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int eb
//
if (!(flags & 0x20)) {
// Update money balance
finance_payment(cost, RCT2_GLOBAL(0x0141F56C, uint8));
RCT2_CALLPROC_X(0x0069C674, 0, cost, 0, 0, 0, 0, 0);
if (RCT2_GLOBAL(0x0141F568, uint8) == RCT2_GLOBAL(0x013CA740, uint8)) {
// Create a +/- money text effect
@ -1159,13 +1161,15 @@ static int open_landscape_file_dialog()
*/
static int open_load_game_dialog()
{
int result;
format_string(0x0141ED68, STR_LOAD_GAME_DIALOG_TITLE, 0);
strcpy(0x0141EF68, RCT2_ADDRESS_SAVED_GAMES_PATH);
format_string(0x0141EE68, STR_RCT2_SAVED_GAME, 0);
pause_sounds();
osinterface_open_common_file_dialog(1, 0x0141ED68, 0x0141EF68, "*.SV6", 0x0141EE68);
result = osinterface_open_common_file_dialog(1, 0x0141ED68, 0x0141EF68, "*.SV6", 0x0141EE68);
unpause_sounds();
// window_proc
return result;
}
/**
@ -1294,7 +1298,7 @@ int game_load_save()
RCT2_CALLPROC_EBPSAFE(0x0069E9A7);
RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
RCT2_CALLPROC_EBPSAFE(0x006ACA58);
window_ride_list_init_vars();
RCT2_GLOBAL(0x009DEB7C, uint16) = 0;
if (RCT2_GLOBAL(0x0013587C4, uint32) == 0) // this check is not in scenario play
RCT2_CALLPROC_EBPSAFE(0x0069E869);

View File

@ -19,8 +19,10 @@
*****************************************************************************/
#include "addresses.h"
#include "news_item.h"
#include "peep.h"
#include "rct2.h"
#include "ride.h"
#include "sprite.h"
int peep_get_staff_count()
@ -71,3 +73,132 @@ void peep_update_all()
i++;
}
}
/**
*
* rct2: 0x0069BF41
**/
void peep_problem_warnings_update()
{
rct_peep* peep;
rct_ride* ride;
uint16 sprite_idx;
uint16 guests_in_park = RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16);
int hunger_counter = 0, lost_counter = 0, noexit_counter = 0, thirst_counter = 0,
litter_counter = 0, disgust_counter = 0, bathroom_counter = 0 ,vandalism_counter = 0;
static int warning_throttle[6] = { 0, 0, 0, 0, 0, 0 };
RCT2_GLOBAL(RCT2_ADDRESS_RIDE_COUNT, sint16) = ride_get_count(); // refactor this to somewhere else
for (sprite_idx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); sprite_idx != SPRITE_INDEX_NULL; sprite_idx = peep->next) {
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[sprite_idx].peep);
if (peep->type != PEEP_TYPE_GUEST || peep->var_2A != 0 || peep->thoughts[0].pad_3 > 5)
continue;
switch (peep->thoughts[0].type) {
case PEEP_THOUGHT_TYPE_LOST: //0x10
lost_counter++;
break;
case PEEP_THOUGHT_TYPE_HUNGRY: // 0x14
if (peep->var_C5 == -1){
hunger_counter++;
break;
}
ride = &RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[peep->var_C5];
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x80000))
hunger_counter++;
break;
case PEEP_THOUGHT_TYPE_THIRSTY:
if (peep->var_C5 == -1){
thirst_counter++;
break;
}
ride = &RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[peep->var_C5];
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x1000000))
thirst_counter++;
break;
case PEEP_THOUGHT_TYPE_BATHROOM:
if (peep->var_C5 == -1){
bathroom_counter++;
break;
}
ride = &RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[peep->var_C5];
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x2000000))
bathroom_counter++;
break;
case PEEP_THOUGHT_TYPE_BAD_LITTER: // 0x1a
litter_counter++;
break;
case PEEP_THOUGHT_TYPE_CANT_FIND_EXIT: // 0x1b
noexit_counter++;
break;
case PEEP_THOUGHT_TYPE_PATH_DISGUSTING: // 0x1f
disgust_counter++;
break;
case PEEP_THOUGHT_TYPE_VANDALISM: //0x21
vandalism_counter++;
break;
default:
break;
}
}
// could maybe be packed into a loop, would lose a lot of clarity though
if (warning_throttle[0])
--warning_throttle[0];
else if ( hunger_counter >= PEEP_HUNGER_WARNING_THRESHOLD && hunger_counter >= guests_in_park / 16) {
warning_throttle[0] = 4;
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_ARE_HUNGRY, 20);
}
if (warning_throttle[1])
--warning_throttle[1];
else if (thirst_counter >= PEEP_THIRST_WARNING_THRESHOLD && thirst_counter >= guests_in_park / 16) {
warning_throttle[1] = 4;
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_ARE_THIRSTY, 21);
}
if (warning_throttle[2])
--warning_throttle[2];
else if (bathroom_counter >= PEEP_BATHROOM_WARNING_THRESHOLD && bathroom_counter >= guests_in_park / 16) {
warning_throttle[2] = 4;
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_CANT_FIND_BATHROOM, 22);
}
if (warning_throttle[3])
--warning_throttle[3];
else if (litter_counter >= PEEP_LITTER_WARNING_THRESHOLD && litter_counter >= guests_in_park / 32) {
warning_throttle[3] = 4;
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_DISLIKE_LITTER, 26);
}
if (warning_throttle[4])
--warning_throttle[4];
else if (disgust_counter >= PEEP_DISGUST_WARNING_THRESHOLD && disgust_counter >= guests_in_park / 32) {
warning_throttle[4] = 4;
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_DISGUSTED_BY_PATHS, 31);
}
if (warning_throttle[5])
--warning_throttle[5];
else if (vandalism_counter >= PEEP_VANDALISM_WARNING_THRESHOLD && vandalism_counter >= guests_in_park / 32) {
warning_throttle[5] = 4;
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_DISLIKE_VANDALISM, 33);
}
if (warning_throttle[6])
--warning_throttle[6];
else if (noexit_counter >= PEEP_NOEXIT_WARNING_THRESHOLD) {
warning_throttle[6] = 4;
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_GETTING_LOST_OR_STUCK, 27);
} else if (lost_counter >= PEEP_LOST_WARNING_THRESHOLD) {
warning_throttle[6] = 4;
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_GETTING_LOST_OR_STUCK, 16);
}
}

View File

@ -25,6 +25,17 @@
#define PEEP_MAX_THOUGHTS 5
#define PEEP_HUNGER_WARNING_THRESHOLD 25
#define PEEP_THIRST_WARNING_THRESHOLD 25
#define PEEP_BATHROOM_WARNING_THRESHOLD 28
#define PEEP_LITTER_WARNING_THRESHOLD 23
#define PEEP_DISGUST_WARNING_THRESHOLD 22
#define PEEP_VANDALISM_WARNING_THRESHOLD 15
#define PEEP_NOEXIT_WARNING_THRESHOLD 8
#define PEEP_LOST_WARNING_THRESHOLD 8
enum PEEP_TYPE {
PEEP_TYPE_GUEST,
PEEP_TYPE_STAFF
@ -363,7 +374,8 @@ typedef struct {
sint32 time_in_park; // 0xA9
uint8 pad_AD[0x3];
rct_peep_thought thoughts[PEEP_MAX_THOUGHTS]; // 0xB0
uint16 pad_C4;
uint8 pad_C4;
uint8 var_C5;
uint8 var_C6;
uint8 photo1_ride_ref; // 0xC7
uint32 flags; // 0xC8
@ -387,5 +399,6 @@ typedef struct {
int peep_get_staff_count();
void peep_update_all();
void peep_problem_warnings_update();
#endif

View File

@ -135,9 +135,9 @@ void rct2_init()
date_reset();
climate_reset(CLIMATE_COOL_AND_WET);
RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
RCT2_CALLPROC_EBPSAFE(0x006ACA58);
window_ride_list_init_vars();
window_guest_list_init_vars_b();
RCT2_CALLPROC_EBPSAFE(0x006BD39C);
RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8) = WINDOW_STAFF_LIST_TAB_HANDYMEN;
title_load();

View File

@ -450,7 +450,7 @@ void scenario_load_and_play(rct_scenario_basic *scenario)
window_invalidate(mainWindow);
RCT2_CALLPROC_EBPSAFE(0x0069E9A7);
RCT2_CALLPROC_EBPSAFE(0x006ACA58);
window_ride_list_init_vars();
RCT2_GLOBAL(0x00F663B0, sint32) = RCT2_GLOBAL(0x009AA0F0, sint32);
RCT2_GLOBAL(0x00F663B4, sint32) = RCT2_GLOBAL(0x009AA0F4, sint32);
@ -873,7 +873,7 @@ void scenario_update()
finance_pay_research();
finance_pay_interest();
scenario_marketing_update();
RCT2_CALLPROC_EBPSAFE(0x0069BF41); // peep needs update and warnings
peep_problem_warnings_update();
RCT2_CALLPROC_EBPSAFE(0x006B7A5E); // check ride reachability
RCT2_CALLPROC_EBPSAFE(0x006AC916); // ride update favourited
@ -898,7 +898,7 @@ void scenario_update()
}
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_TICKS, uint16) = next_month_tick;
if (next_month_tick > 0x10000) {
if (next_month_tick >= 0x10000) {
// month ends actions
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, sint16)++;
RCT2_GLOBAL(0x009A9804, uint32) |= 2;

View File

@ -416,6 +416,14 @@ enum {
STR_SHOW_GUESTS_ON_MAP_TIP = 2803,
STR_SHOW_MAP_TIP = 2805,
STR_PEEPS_DISGUSTED_BY_PATHS = 2806,
STR_PEEPS_DISLIKE_LITTER = 2807,
STR_PEEPS_DISLIKE_VANDALISM = 2808,
STR_PEEPS_ARE_HUNGRY = 2809,
STR_PEEPS_ARE_THIRSTY = 2810,
STR_PEEPS_CANT_FIND_BATHROOM = 2811,
STR_PEEPS_GETTING_LOST_OR_STUCK = 2812,
STR_ENTRANCE_FEE_TOO_HI = 2813,
STR_AWARD_MOST_UNTIDY = 2814,
@ -446,6 +454,12 @@ enum {
STR_MUSIC_ACKNOWLEDGEMENTS_ELLIPSIS = 2862,
STR_MUSIC_ACKNOWLEDGEMENTS = 2863,
STR_CHANGE_BANNER_TEXT_TIP = 2986,
STR_SET_AS_NO_ENTRY_BANNER_TIP = 2987,
STR_DEMOLISH_BANNER_TIP = 2988,
STR_SELECT_MAIN_COLOR_TIP = 2989,
STR_SELECT_TEXT_COLOR_TIP = 2990,
STR_LICENCE_AGREEMENT_NOTICE_1 = 2969,
STR_LICENCE_AGREEMENT_NOTICE_2 = 2970,

View File

@ -103,9 +103,9 @@ void title_load()
date_reset();
RCT2_CALLPROC_X(0x006C45ED, 0, 0, 0, 0, 0, 0, 0);
RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
RCT2_CALLPROC_EBPSAFE(0x006ACA58);
window_ride_list_init_vars();
window_guest_list_init_vars_b();
RCT2_CALLPROC_EBPSAFE(0x006BD39C);
RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8) = WINDOW_STAFF_LIST_TAB_HANDYMEN;
RCT2_CALLPROC_EBPSAFE(0x0068AFFD);
RCT2_CALLPROC_EBPSAFE(0x0069EBE4);
viewport_init_all();
@ -191,7 +191,7 @@ static void title_update_showcase()
window_invalidate(w);
RCT2_CALLPROC_EBPSAFE(0x0069E9A7);
RCT2_CALLPROC_EBPSAFE(0x006ACA58);
window_ride_list_init_vars();
RCT2_CALLPROC_EBPSAFE(0x00684AC3);
RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
news_item_init_queue();

View File

@ -115,7 +115,7 @@ void widget_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex)
widget_button_draw(dpi, w, widgetIndex);
break;
case WWT_5:
case WWT_6:
case WWT_COLORBTN:
case WWT_TRNBTN:
case WWT_TAB:
widget_tab_draw(dpi, w, widgetIndex);
@ -861,7 +861,7 @@ static void widget_draw_image(rct_drawpixelinfo *dpi, rct_window *w, int widgetI
// Get the colour
colour = w->colours[widget->colour];
if (widget->type == WWT_4 || widget->type == WWT_6 || widget->type == WWT_TRNBTN || widget->type == WWT_TAB)
if (widget->type == WWT_4 || widget->type == WWT_COLORBTN || widget->type == WWT_TRNBTN || widget->type == WWT_TAB)
if (widget_is_pressed(w, widgetIndex) || widget_is_active_tool(w, widgetIndex))
image++;

View File

@ -30,7 +30,7 @@ typedef enum {
WWT_IMGBTN = 3,
WWT_4 = 4,
WWT_5 = 5,
WWT_6 = 6,
WWT_COLORBTN = 6,
WWT_TRNBTN = 7,
WWT_TAB = 8,
WWT_FLATBTN = 9,

View File

@ -1203,4 +1203,28 @@ void window_guest_list_init_vars_b() {
RCT2_GLOBAL(0x00F1EE02, uint32) = 0xFFFFFFFF;
RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_GUEST_LIST_SELECTED_FILTER, uint8) = 0xFF;
RCT2_GLOBAL(0x00F1AF20, uint16) = 0;
}
/**
*
* rct2: 0x006ACA58
*/
void window_ride_list_init_vars() {
// If we are in the track designer, default to the Roller Coaster tab
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) {
RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_RIDE_LIST_SELECTED_TAB, uint8) = WINDOW_RIDE_LIST_TAB_ROLLER_COASTER;
}
else {
RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_RIDE_LIST_SELECTED_TAB, uint8) = WINDOW_RIDE_LIST_TAB_TRANSPORT;
}
for (short i = 0; i < 6; i++) {
/*
Reset what is highlighted in each tab.
Each 16bit number represents the item in its respective tab.
*/
RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_RIDE_LIST_HIGHLIGHTED_ITEM, uint16)[i] = 0xFFFF;
}
RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_RIDE_LIST_INFORMATION_TYPE, uint8) = 0;
}

View File

@ -284,6 +284,23 @@ enum {
WC_CHEATS = 110,
} WINDOW_CLASS;
enum {
WINDOW_RIDE_LIST_TAB_TRANSPORT,
WINDOW_RIDE_LIST_TAB_GENTLE,
WINDOW_RIDE_LIST_TAB_ROLLER_COASTER,
WINDOW_RIDE_LIST_TAB_THRILL,
WINDOW_RIDE_LIST_TAB_WATER,
WINDOW_RIDE_LIST_TAB_SHOP,
WINDOW_RIDE_LIST_TAB_RESEARCH
} WINDOW_RIDE_LIST_TAB;
enum {
WINDOW_STAFF_LIST_TAB_HANDYMEN,
WINDOW_STAFF_LIST_TAB_MECHANICS,
WINDOW_STAFF_LIST_TAB_SECURITY,
WINDOW_STAFF_LIST_TAB_ENTERTAINERS
} WINDOW_STAFF_LIST_TAB;
void window_dispatch_update_all();
void window_update_all();
rct_window *window_create(int x, int y, int width, int height, uint32 *event_handlers, rct_windowclass cls, uint16 flags);
@ -349,5 +366,6 @@ void window_cheats_open();
void window_guest_list_init_vars_a();
void window_guest_list_init_vars_b();
void window_ride_list_init_vars();
#endif