Merge remote-tracking branch 'upstream/master'

Conflicts:
	src/config.c
	src/config.h
This commit is contained in:
Jørn Lomax 2014-05-08 11:09:31 +02:00
commit 7d4a80cea2
47 changed files with 2593 additions and 226 deletions

View File

@ -21,6 +21,7 @@
<ClInclude Include="..\src\config.h" />
<ClInclude Include="..\src\date.h" />
<ClInclude Include="..\src\editor.h" />
<ClInclude Include="..\src\finance.h" />
<ClInclude Include="..\src\game.h" />
<ClInclude Include="..\src\gfx.h" />
<ClInclude Include="..\src\intro.h" />
@ -58,6 +59,7 @@
<ClCompile Include="..\src\config.c" />
<ClCompile Include="..\src\date.c" />
<ClCompile Include="..\src\editor.c" />
<ClCompile Include="..\src\finance.c" />
<ClCompile Include="..\src\game.c" />
<ClCompile Include="..\src\gfx.c" />
<ClCompile Include="..\src\intro.c" />
@ -87,7 +89,9 @@
<ClCompile Include="..\src\window_error.c" />
<ClCompile Include="..\src\window_game_bottom_toolbar.c" />
<ClCompile Include="..\src\window_dropdown.c" />
<ClCompile Include="..\src\window_guest_list.c" />
<ClCompile Include="..\src\window_land.c" />
<ClCompile Include="..\src\window_news.c" />
<ClCompile Include="..\src\window_park.c" />
<ClCompile Include="..\src\window_footpath.c" />
<ClCompile Include="..\src\window_ride_list.c" />

View File

@ -123,6 +123,9 @@
<ClInclude Include="..\src\settings.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\finance.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\game.c">
@ -269,6 +272,15 @@
<ClCompile Include="..\src\settings.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\window_news.c">
<Filter>Windows</Filter>
</ClCompile>
<ClCompile Include="..\src\window_guest_list.c">
<Filter>Windows</Filter>
</ClCompile>
<ClCompile Include="..\src\finance.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\openrct2.exe">

View File

@ -141,6 +141,7 @@
#define RCT2_ADDRESS_SPRITES_START_LITTER 0x013573C4
#define RCT2_ADDRESS_CURRENT_LOAN 0x013573E0
#define RCT2_ADDRESS_MAXIMUM_LOAN 0x013580F0
#define RCT2_ADDRESS_PARK_FLAGS 0x013573E4
#define RCT2_ADDRESS_PARK_ENTRANCE_FEE 0x013573E8
#define RCT2_ADDRESS_GUESTS_IN_PARK 0x01357844
@ -160,8 +161,13 @@
#define RCT2_ADDRESS_CURRENT_COMPANY_VALUE 0x0135874C
#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_CURRENT_RESEARCH_LEVEL 0x013573FF
#define RCT2_ADDRESS_CURRENT_INTEREST_RATE 0x0135934A
#define RCT2_ADDRESS_MAP_SIZE 0x01358834
#define RCT2_ADDRESS_PARK_SIZE 0x013580EA
#define RCT2_ADDRESS_SCENARIO_NAME 0x0135920A
#define RCT2_ADDRESS_SCENARIO_DETAILS 0x0135924A
@ -172,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
@ -202,14 +210,28 @@
#define RCT2_ADDRESS_SCENARIO_NAME 0x0141F5B8
#define RCT2_ADDRESS_WATER_RAISE_COST 0x0141F738
#define RCT2_ADDRESS_WATER_LOWER_COST 0x0141F73C
#define RCT2_ADDRESS_WINDOW_LIST 0x01420078
#define RCT2_ADDRESS_NEW_WINDOW_PTR 0x014234B8
#define RCT2_ADDRESS_VIEWPORT_LIST 0x014234BC
#define RCT2_ADDRESS_NEW_VIEWPORT_PTR 0x01423570
#define RCT2_ADDRESS_OS_TIME_MONTH 0x01423A04
#define RCT2_ADDRESS_OS_TOTALPHYS 0x01423B5C
#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
#define RCT2_ADDRESS_OS_TIME_DAY 0x01424304
#define RCT2_ADDRESS_OS_TIME_MONTH 0x01423A04
#define RCT2_ADDRESS_OS_TIME_YEAR 0x01424320
#define RCT2_ADDRESS_OS_TIME_DAYOFWEEK 0x01423B20
@ -298,7 +320,10 @@ static void RCT2_CALLFUNC_X(int address, int *_eax, int *_ebx, int *_ecx, int *_
// Put output ebp into ebp parameter
mov eax, [esp]
mov [_ebp], eax
push ebx
mov ebx, [_ebp]
mov [ebx], eax
pop ebx
add esp, 4
// Get resulting ebx, ecx, edx, esi, edi registers

View File

@ -20,6 +20,7 @@
#include "audio.h"
#include "addresses.h"
#include "rct2.h"
void get_dsound_devices()
{
@ -45,3 +46,24 @@ void sound_stop(rct_sound* sound)
{
RCT2_CALLPROC_1(0x00404DD8, rct_sound*, sound);
}
/**
*
* rct2: 0x006BABB4
*/
void pause_sounds() {
if (++RCT2_GLOBAL(0x009AF59C, uint8) == 1) {
RCT2_CALLPROC_EBPSAFE(0x006BCAE5);
RCT2_CALLPROC_EBPSAFE(0x006BABDF);
RCT2_CALLPROC_EBPSAFE(0x006BCA9F);
RCT2_CALLPROC_EBPSAFE(0x006BD07F);
}
}
/**
*
* rct2: 0x006BABD8
*/
void unpause_sounds() {
RCT2_GLOBAL(0x009AF59C, uint8)--;
}

View File

@ -48,6 +48,8 @@ int sound_prepare(int sound_id, rct_sound *sound, int var_8, int var_c);
void sound_play_panned(int sound_id, int x);
int sound_play(rct_sound* sound, int looping, int volume, int pan, int frequency);
void sound_stop(rct_sound *sound);
void pause_sounds();
void unpause_sounds();
typedef enum {
RCT2_SOUND_SCREAM = 11,

View File

@ -111,9 +111,9 @@ void config_load()
}
RCT2_GLOBAL(0x009AAC77, sint8) = 0;
if (RCT2_GLOBAL(RCT2_ADDRESS_OS_TOTALPHYS, uint32) > 0x4000000) {
if (RCT2_GLOBAL(RCT2_ADDRESS_MEM_TOTAL_PHYSICAL, uint32) > 0x4000000) {
RCT2_GLOBAL(0x009AAC77, sint8) = 1;
if (RCT2_GLOBAL(RCT2_ADDRESS_OS_TOTALPHYS, uint32) > 0x8000000)
if (RCT2_GLOBAL(RCT2_ADDRESS_MEM_TOTAL_PHYSICAL, uint32) > 0x8000000)
RCT2_GLOBAL(0x009AAC77, sint8) = 2;
}
@ -200,6 +200,10 @@ static int config_find_rct2_path(char *resultPath)
const char *searchLocations[] = {
"C:\\Program Files\\Infogrames\\RollerCoaster Tycoon 2",
"C:\\Program Files (x86)\\Infogrames\\RollerCoaster Tycoon 2",
"C:\\Program Files\\Infogrames Interactive\\RollerCoaster Tycoon 2",
"C:\\Program Files (x86)\\Infogrames Interactive\\RollerCoaster Tycoon 2",
"C:\\Program Files\\Atari\\RollerCoaster Tycoon 2",
"C:\\Program Files (x86)\\Atari\\RollerCoaster Tycoon 2",
"C:\\GOG Games\\RollerCoaster Tycoon 2 Triple Thrill Pack"
};
@ -232,7 +236,7 @@ static void config_create_default(char *path)
fprintf(fp, "[general]\n");
fprintf(fp, "game_path = %s\n", gConfig.game_path);
fprintf(fp, "screenshot_format = PNG\n");
fprintf(fp, "temperature_format = C\n");
fprintf(fp, "play_intro = false\n");
fclose(fp);
}
@ -268,6 +272,8 @@ static void config_parse_settings(FILE *fp)
} else {
gConfig.screenshot_format = SCREENSHOT_FORMAT_BMP;
}
} else if (strcmp(setting, "play_intro") == 0) {
gConfig.play_intro = (strcmp(value, "true") == 0);
}
}
free(setting);

View File

@ -86,7 +86,10 @@ void config_save();
// New config format
#define MAX_CONFIG_LENGTH 256
typedef struct general_configuration {
typedef struct configuration {
uint8 play_intro;
uint8 screenshot_format;
char game_path[MAX_PATH];
} configuration_t;

View File

@ -29,6 +29,9 @@
#include "ride.h"
#include "window.h"
#include "viewport.h"
#include "finance.h"
#include "audio.h"
#include "strings.h"
static void set_all_land_owned();
@ -40,33 +43,33 @@ void editor_load()
{
rct_window *mainWindow;
RCT2_CALLPROC_EBPSAFE(0x006BABB4);
RCT2_CALLPROC_EBPSAFE(0x006BABD8);
pause_sounds();
unpause_sounds();
RCT2_CALLPROC_EBPSAFE(0x006A9CE8);
map_init();
RCT2_CALLPROC_EBPSAFE(0x006B9CB0);
RCT2_CALLPROC_EBPSAFE(0x00667104);
RCT2_CALLPROC_EBPSAFE(0x006C4209);
RCT2_CALLPROC_EBPSAFE(0x0069EB13);
reset_park_entrances();
reset_saved_strings();
RCT2_CALLPROC_EBPSAFE(0x0069EB13); // sprites_init
ride_init_all();
RCT2_CALLPROC_EBPSAFE(0x0068F083); // window_guest_list_init_vars_a
RCT2_CALLPROC_EBPSAFE(0x006BD3A4);
window_guest_list_init_vars_a();
sub_6BD3A4();
park_init();
RCT2_CALLPROC_EBPSAFE(0x0069DEFB);
finance_init();
date_reset();
RCT2_CALLPROC_EBPSAFE(0x0068F050); // window_guest_list_init_vars_b
RCT2_CALLPROC_EBPSAFE(0x006BD39C);
window_guest_list_init_vars_b();
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) |= 16;
RCT2_CALLPROC_EBPSAFE(0x006ACA58);
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) |= PARK_FLAGS_SHOW_REAL_GUEST_NAMES;
window_ride_list_init_vars();
RCT2_GLOBAL(0x0141F571, uint8) = 4;
viewport_init_all();
news_item_init_queue();
RCT2_CALLPROC_EBPSAFE(0x0066EF38); // window_main_editor_create
mainWindow = window_get_main();
window_scroll_to_location(mainWindow, 2400, 2400, 112);
mainWindow->flags &= ~0x08;
mainWindow->flags &= ~WF_3;
RCT2_CALLPROC_EBPSAFE(0x006837E3);
gfx_invalidate_screen();
RCT2_GLOBAL(0x009DEA66, sint16) = 0;
@ -94,26 +97,26 @@ void trackdesigner_load()
map_init();
set_all_land_owned();
RCT2_CALLPROC_EBPSAFE(0x006B9CB0);
RCT2_CALLPROC_EBPSAFE(0x00667104);
RCT2_CALLPROC_EBPSAFE(0x006C4209);
RCT2_CALLPROC_EBPSAFE(0x0069EB13);
reset_park_entrances();
reset_saved_strings();
RCT2_CALLPROC_EBPSAFE(0x0069EB13); // reset_sprites
ride_init_all();
RCT2_CALLPROC_EBPSAFE(0x0068F083); // window_guest_list_init_vars_a
RCT2_CALLPROC_EBPSAFE(0x006BD3A4);
window_guest_list_init_vars_a();
sub_6BD3A4();
park_init();
RCT2_CALLPROC_EBPSAFE(0x0069DEFB);
finance_init();
date_reset();
RCT2_CALLPROC_EBPSAFE(0x0068F050); // window_guest_list_init_vars_b
RCT2_CALLPROC_EBPSAFE(0x006BD39C);
window_guest_list_init_vars_b();
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
mainWindow = window_get_main();
window_scroll_to_location(mainWindow, 2400, 2400, 112);
mainWindow->flags &= ~0x08;
mainWindow->flags &= ~WF_3;
RCT2_CALLPROC_EBPSAFE(0x006837E3);
gfx_invalidate_screen();
RCT2_GLOBAL(0x009DEA66, sint16) = 0;
@ -132,26 +135,26 @@ void trackmanager_load()
map_init();
set_all_land_owned();
RCT2_CALLPROC_EBPSAFE(0x006B9CB0);
RCT2_CALLPROC_EBPSAFE(0x00667104);
RCT2_CALLPROC_EBPSAFE(0x006C4209);
RCT2_CALLPROC_EBPSAFE(0x0069EB13);
reset_park_entrances();
reset_saved_strings();
RCT2_CALLPROC_EBPSAFE(0x0069EB13); // reset_sprites
ride_init_all();
RCT2_CALLPROC_EBPSAFE(0x0068F083); // window_guest_list_init_vars_a
RCT2_CALLPROC_EBPSAFE(0x006BD3A4);
window_guest_list_init_vars_a();
sub_6BD3A4();
park_init();
RCT2_CALLPROC_EBPSAFE(0x0069DEFB);
finance_init();
date_reset();
RCT2_CALLPROC_EBPSAFE(0x0068F050); // window_guest_list_init_vars_b
RCT2_CALLPROC_EBPSAFE(0x006BD39C);
window_guest_list_init_vars_b();
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
mainWindow = window_get_main();
window_scroll_to_location(mainWindow, 2400, 2400, 112);
mainWindow->flags &= ~0x08;
mainWindow->flags &= ~WF_3;
RCT2_CALLPROC_EBPSAFE(0x006837E3);
gfx_invalidate_screen();
RCT2_GLOBAL(0x009DEA66, sint16) = 0;
@ -168,3 +171,17 @@ static void set_all_land_owned()
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

140
src/finance.c Normal file
View File

@ -0,0 +1,140 @@
/*****************************************************************************
* Copyright (c) 2014 Matthias Lanzinger
* 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 "finance.h"
#include "sprite.h"
#include "park.h"
#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 };
/**
*
* rct2: 0x069C674
* @param amount (eax)
* @param type passed via global var 0x0141F56C, our type is that var/4.
**/
void finance_payment(int amount, rct_expenditure_type type)
{
int test = RCT2_GLOBAL(0x13CA740, uint32);
sint32 cur_money = DECRYPT_MONEY(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, sint32));
sint32 new_money = cur_money - amount;
//overflow check
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, sint32) = ENCRYPT_MONEY(new_money);
RCT2_ADDRESS(RCT2_ADDRESS_EXPENDITURE_TABLE, sint32)[type] -= amount;
if (RCT2_ADDRESS(0x00988E60, uint32)[type] & 1)
RCT2_GLOBAL(0x0135832C, sint32) -= amount;
RCT2_GLOBAL(0x009A9804, uint32) |= 1; // money diry flag
window_invalidate_by_id(WC_FINANCES, 0);
}
/**
* Pays the wages of all active staff members in the park.
* rct2: 0x006C18A9
**/
void finance_pay_wages()
{
rct_peep* peep;
uint16 sprite_idx;
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & 0x800)
return;
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] / 4, RCT_EXPENDITURE_TYPE_WAGES);
}
}
/**
* Pays the current research level's cost.
* rct2: 0x00684DA5
**/
void finance_pay_research()
{
uint8 level;
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & 0x800)
return;
level = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_RESEARCH_LEVEL, uint8);
finance_payment(research_cost_table[level] / 4, RCT_EXPENDITURE_TYPE_RESEARCH);
}
/**
* Pay interest on current loans.
* rct2: 0x0069E092
**/
void finance_pay_interest()
{
sint32 current_loan = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, sint32);
sint16 current_interest = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, sint16);
sint64 tempcost = (current_loan * 5 * current_interest) >> 14; // (5*interest)/2^14 is pretty close to
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & 0x800)
return;
finance_payment((sint32)tempcost, RCT_EXPENDITURE_TYPE_INTEREST);
}
/**
*
* rct2: 0x0069DEFB
*/
void finance_init() {
for (short i = 0; i < 56; i++) {
RCT2_ADDRESS(RCT2_ADDRESS_EXPENDITURE_TABLE, uint32)[i] = 0;
}
RCT2_GLOBAL(0x0135832C, uint32) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PROFIT, uint32) = 0;
RCT2_GLOBAL(0x01358334, uint32) = 0;
RCT2_GLOBAL(0x01358338, uint16) = 0;
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;
RCT2_GLOBAL(RCT2_ADDRESS_MAXIMUM_LOAN, uint32) = 200000;
RCT2_GLOBAL(0x013587D0, uint32) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, uint8) = 10;
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, sint32) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_COMPANY_VALUE, sint32) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, sint32) = 0x80000000;
RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_ADMISSIONS, uint32) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_INCOME_FROM_ADMISSIONS, uint32) = 0;
RCT2_GLOBAL(0x013587D8, uint16) = 0x3F;
RCT2_CALLPROC_EBPSAFE(0x0069E869);
}

41
src/finance.h Normal file
View File

@ -0,0 +1,41 @@
/*****************************************************************************
* Copyright (c) 2014 Matthias Lanzinger
* 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 _FINANCE_H_
#define _FINANCE_H_
#include "rct2.h"
typedef int rct_expenditure_type;
enum {
RCT_EXPENDITURE_TYPE_WAGES = 10,
RCT_EXPENDITURE_TYPE_RESEARCH = 12,
RCT_EXPENDITURE_TYPE_INTEREST = 13
};
void finance_payment(int amount, rct_expenditure_type type);
void finance_pay_wages();
void finance_pay_research();
void finance_pay_interest();
void finance_init();
#endif

View File

@ -24,14 +24,18 @@
#include "config.h"
#include "rct2.h"
#include "game.h"
#include "finance.h"
#include "news_item.h"
#include "object.h"
#include "osinterface.h"
#include "peep.h"
#include "sawyercoding.h"
#include "scenario.h"
#include "screenshot.h"
#include "strings.h"
#include "title.h"
#include "tutorial.h"
#include "viewport.h"
#include "widget.h"
#include "window.h"
#include "window_error.h"
@ -137,7 +141,7 @@ void game_logic_update()
if (RCT2_GLOBAL(0x009DEA66, sint16) == 0)
RCT2_GLOBAL(0x009DEA66, sint16)--;
RCT2_CALLPROC_EBPSAFE(0x0068B089);
sub_68B089();
scenario_update();
climate_update();
RCT2_CALLPROC_EBPSAFE(0x006646E1);
@ -399,8 +403,8 @@ static void game_handle_input_mouse(int x, int y, int state)
RCT2_GLOBAL(0x009DE540, sint16) = 1000;
dx <<= viewport->zoom + 1;
dy <<= viewport->zoom + 1;
w->var_4B2 += dx;
w->var_4B4 += dy;
w->saved_view_x += dx;
w->saved_view_y += dy;
}
}
} else if (state == 4) {
@ -795,11 +799,11 @@ void game_handle_edge_scroll()
// Scroll viewport
if (scrollX != 0) {
mainWindow->var_4B2 += scrollX * (12 << mainWindow->viewport->zoom);
mainWindow->saved_view_x += scrollX * (12 << mainWindow->viewport->zoom);
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
}
if (scrollY != 0) {
mainWindow->var_4B4 += scrollY * (12 << mainWindow->viewport->zoom);
mainWindow->saved_view_y += scrollY * (12 << mainWindow->viewport->zoom);
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
}
}
@ -836,11 +840,11 @@ void game_handle_key_scroll()
// Scroll viewport
if (scrollX != 0) {
mainWindow->var_4B2 += scrollX * (12 << mainWindow->viewport->zoom);
mainWindow->saved_view_x += scrollX * (12 << mainWindow->viewport->zoom);
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
}
if (scrollY != 0) {
mainWindow->var_4B4 += scrollY * (12 << mainWindow->viewport->zoom);
mainWindow->saved_view_y += scrollY * (12 << mainWindow->viewport->zoom);
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
}
}
@ -930,7 +934,7 @@ void game_handle_keyboard_input()
// Handle key input
while ((key = get_next_key()) != 0) {
if (key == 255 || key == 0x10 || key == 0x11)
if (key == 255)
continue;
key |= RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) << 8;
@ -1054,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
@ -1094,9 +1099,9 @@ static void game_pause_toggle()
RCT2_GLOBAL(0x009DEA6E, uint32) ^= 1;
window_invalidate_by_id(WC_TOP_TOOLBAR, 0);
if (RCT2_GLOBAL(0x009DEA6E, uint32) & 1)
RCT2_CALLPROC_EBPSAFE(0x006BABB4); // pause_sounds
pause_sounds();
else
RCT2_CALLPROC_EBPSAFE(0x006BABD8); // unpause_sounds
unpause_sounds();
}
__asm mov ebx, 0
@ -1144,9 +1149,9 @@ static int open_landscape_file_dialog()
format_string(0x0141ED68, STR_LOAD_LANDSCAPE_DIALOG_TITLE, 0);
strcpy(0x0141EF68, RCT2_ADDRESS_LANDSCAPES_PATH);
format_string(0x0141EE68, STR_RCT2_LANDSCAPE_FILE, 0);
RCT2_CALLPROC_EBPSAFE(0x006BABB4); // pause_sounds
pause_sounds();
osinterface_open_common_file_dialog(1, 0x0141ED68, 0x0141EF68, "*.SV6;*.SV4;*.SC6", 0x0141EE68);
RCT2_CALLPROC_EBPSAFE(0x006BABD8); // unpause_sounds
unpause_sounds();
// window_proc
}
@ -1156,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);
RCT2_CALLPROC_EBPSAFE(0x006BABB4); // pause_sounds
osinterface_open_common_file_dialog(1, 0x0141ED68, 0x0141EF68, "*.SV6", 0x0141EE68);
RCT2_CALLPROC_EBPSAFE(0x006BABD8); // unpause_sounds
pause_sounds();
result = osinterface_open_common_file_dialog(1, 0x0141ED68, 0x0141EF68, "*.SV6", 0x0141EE68);
unpause_sounds();
// window_proc
return result;
}
/**
@ -1198,6 +1205,109 @@ static void load_landscape()
}
}
/**
*
* rct2: 0x00675E1B
*/
int game_load_save()
{
rct_window *mainWindow;
HANDLE hFile;
char *path;
int i, j;
path = (char*)0x0141EF68;
hFile = CreateFile(
path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_NORMAL, NULL
);
if (hFile == NULL) {
RCT2_GLOBAL(0x009AC31B, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
return 0;
}
RCT2_GLOBAL(0x009E382C, HANDLE) = hFile;
if (!sawyercoding_validate_checksum(hFile)) {
CloseHandle(hFile);
RCT2_GLOBAL(0x009AC31B, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
return 0;
}
rct_s6_header *s6Header = 0x009E34E4;
rct_s6_info *s6Info = 0x0141F570;
// Read first chunk
sawyercoding_read_chunk(hFile, s6Header);
if (s6Header->type == S6_TYPE_SAVEDGAME) {
// Read packed objects
if (s6Header->num_packed_objects > 0) {
j = 0;
for (i = 0; i < s6Header->num_packed_objects; i++)
j += object_load_packed();
if (j > 0)
object_load_list();
}
}
object_read_and_load_entries(hFile);
// Read flags (16 bytes)
sawyercoding_read_chunk(hFile, RCT2_ADDRESS_CURRENT_MONTH_YEAR);
// Read map elements
memset(RCT2_ADDRESS_MAP_ELEMENTS, 0, MAX_MAP_ELEMENTS * sizeof(rct_map_element));
sawyercoding_read_chunk(hFile, RCT2_ADDRESS_MAP_ELEMENTS);
// Read game data, including sprites
sawyercoding_read_chunk(hFile, 0x010E63B8);
CloseHandle(hFile);
// Check expansion pack
// RCT2_CALLPROC_EBPSAFE(0x006757E6);
// The rest is the same as in scenario load and play
RCT2_CALLPROC_EBPSAFE(0x006A9FC0);
map_update_tile_pointers();
RCT2_CALLPROC_EBPSAFE(0x0069EBE4);
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_PLAYING;
viewport_init_all();
game_create_windows();
mainWindow = window_get_main();
mainWindow->var_4B0 = -1;
mainWindow->saved_view_x = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_X, sint16);
mainWindow->saved_view_y = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_Y, sint16);
uint8 _cl = (RCT2_GLOBAL(0x0138869E, sint16) & 0xFF) - mainWindow->viewport->zoom;
mainWindow->viewport->zoom = RCT2_GLOBAL(0x0138869E, sint16) & 0xFF;
*((char*)(&RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, sint32))) = RCT2_GLOBAL(0x0138869E, sint16) >> 8;
if (_cl != 0) {
if (_cl < 0) {
_cl = -_cl;
mainWindow->viewport->view_width >>= _cl;
mainWindow->viewport->view_height >>= _cl;
} else {
mainWindow->viewport->view_width <<= _cl;
mainWindow->viewport->view_height <<= _cl;
}
}
mainWindow->saved_view_x -= mainWindow->viewport->view_width >> 1;
mainWindow->saved_view_y -= mainWindow->viewport->view_height >> 1;
window_invalidate(mainWindow);
RCT2_CALLPROC_EBPSAFE(0x0069E9A7);
RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
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);
RCT2_CALLPROC_EBPSAFE(0x006837E3); // (palette related)
gfx_invalidate_screen();
return 1;
}
/**
*
* rct2: 0x0066DBB7
@ -1220,8 +1330,7 @@ static void load_game()
}
strcpy(0x009ABB37, 0x0141EF68);
RCT2_CALLPROC_EBPSAFE(0x00675E1B); // game_load
if (1) {
if (game_load_save()) {
gfx_invalidate_screen();
rct2_endupdate();
} else {

View File

@ -28,5 +28,6 @@ void game_logic_update();
int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp);
void game_load_or_quit_no_save_prompt();
int game_load_save();
#endif

View File

@ -406,6 +406,33 @@ void gfx_draw_string_centred_clipped(rct_drawpixelinfo *dpi, int format, void *a
//gfx_draw_string(dpi, buffer, colour, x, y);
}
/**
* Draws i formatted text string right aligned.
* rct2: 0x006C1BFC
* dpi (edi)
* format (bx)
* args (esi)
* colour (al)
* x (cx)
* y (dx)
*/
void gfx_draw_string_right(rct_drawpixelinfo* dpi, int format, void* args, int colour, int x, int y)
{
char* buffer;
short text_width;
buffer = (char*)0x0141ED68;
format_string(buffer, format, args);
// Measure text width
text_width = gfx_get_string_width(buffer);
// Draw the text right aligned
x -= text_width;
gfx_draw_string(dpi, buffer, colour, x, y);
}
/**
*
* rct2: 0x006C1E53

View File

@ -280,3 +280,53 @@ int map_element_height(int x, int y)
return height;
}
/**
*
* rct2: 0x0068B089
*/
void sub_68B089()
{
int i;
rct_map_element *mapElementFirst, *mapElement;
if (RCT2_GLOBAL(0x009DEA6F, uint8) & 1)
return;
i = RCT2_GLOBAL(0x0010E63B8, uint32);
do {
i++;
if (i >= MAX_TILE_MAP_ELEMENT_POINTERS)
i = 0;
} while (TILE_MAP_ELEMENT_POINTER(i) == 0xFFFFFFFF);
RCT2_GLOBAL(0x0010E63B8, uint32) = i;
mapElementFirst = mapElement = TILE_MAP_ELEMENT_POINTER(i);
do {
mapElement--;
if (mapElement < RCT2_ADDRESS_MAP_ELEMENTS)
break;
} while (mapElement->base_height == 255);
mapElement++;
if (mapElement == mapElementFirst)
return;
//
TILE_MAP_ELEMENT_POINTER(i) = mapElement;
do {
*mapElement = *mapElementFirst;
mapElementFirst->base_height = 255;
mapElement++;
mapElementFirst++;
} while (!((mapElement - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
// Update next free element?
mapElement = RCT2_GLOBAL(0x0140E9A4, rct_map_element*);
do {
mapElement--;
} while (mapElement->base_height == 255);
mapElement++;
RCT2_GLOBAL(0x0140E9A4, rct_map_element*) = mapElement;
}

View File

@ -185,5 +185,6 @@ enum {
void map_init();
void map_update_tile_pointers();
int map_element_height(int x, int y);
void sub_68B089();
#endif

View File

@ -182,12 +182,12 @@ void news_item_get_subject_location(int type, int subject, int *x, int *y, int *
switch (type) {
case NEWS_ITEM_RIDE:
ride = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[subject]);
if (ride->var_050 == 0xFFFF) {
if (ride->overall_view == 0xFFFF) {
*x = SPRITE_LOCATION_NULL;
break;
}
*x = (ride->var_050 & 0xFF) * 32 + 16;
*y = (ride->var_050 >> 8) * 32 + 16;
*x = (ride->overall_view & 0xFF) * 32 + 16;
*y = (ride->overall_view >> 8) * 32 + 16;
*z = map_element_height(*x, *y);
break;
case NEWS_ITEM_PEEP_ON_RIDE:

View File

@ -62,8 +62,8 @@ int park_calculate_size()
}
}
if (tiles != RCT2_GLOBAL(0x013580EA, sint16)) {
RCT2_GLOBAL(0x013580EA, sint16) = tiles;
if (tiles != RCT2_GLOBAL(RCT2_ADDRESS_PARK_SIZE, sint16)) {
RCT2_GLOBAL(RCT2_ADDRESS_PARK_SIZE, sint16) = tiles;
window_invalidate_by_id(WC_PARK_INFORMATION, 0);
}
@ -76,13 +76,6 @@ int park_calculate_size()
*/
int calculate_park_rating()
{
{
int eax, ebx, ecx, edx, esi, edi, ebp;
RCT2_CALLFUNC_X(0x00669EAA, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
return eax & 0xFFFF;
}
int result;
result = 1150;
@ -115,11 +108,12 @@ int calculate_park_rating()
if (peep->var_C6 <= 89)
_bp++;
}
// Peep happiness -500 to +0
result -= 500;
if (num_happy_peeps > 0)
result += 2 * min(250, (RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) * 300) / num_happy_peeps);
if (RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) > 0)
result += 2 * min(250, (num_happy_peeps * 300) / RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16));
// ?
_bp -= 25;
@ -130,8 +124,8 @@ int calculate_park_rating()
// Rides
{
int i;
short _ax, _bx;
int num_rides;
short _ax, total_ride_intensity = 0, total_ride_excitement = 0, average_intensity, average_excitement;
int num_rides, num_exciting_rides = 0;
rct_ride* ride;
//
@ -143,28 +137,42 @@ int calculate_park_rating()
if (ride->type == RIDE_TYPE_NULL)
continue;
_ax += 100 - ride->var_199;
if (ride->excitement != -1){
total_ride_excitement += ride->excitement / 8;
total_ride_intensity += ride->intensity / 8;
num_exciting_rides++;
}
num_rides++;
}
result -= 200;
if (num_rides > 0)
result += (_ax / num_rides) * 2;
//
_ax = 0;
_bx = 0;
for (i = 0; i < 255; i++) {
ride = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[i]);
result -= 100;
if (ride->type == RIDE_TYPE_NULL)
continue;
if (ride->excitement == -1)
continue;
_ax += ride->excitement / 8;
_bx += ride->intensity / 8;
if (num_exciting_rides>0){
average_excitement = total_ride_excitement / num_exciting_rides;
average_intensity = total_ride_intensity / num_exciting_rides;
average_excitement -= 46;
if (average_excitement < 0){
average_excitement = -average_excitement;
}
average_intensity -= 65;
if (average_intensity < 0){
average_intensity = -average_intensity;
}
average_excitement = min(average_excitement / 2, 50);
average_intensity = min(average_intensity / 2, 50);
result += 100 - average_excitement - average_intensity;
}
_ax = min(1000, _ax);
_bx = min(1000, _bx);
result -= 200 - ((_ax + _bx) / 10);
total_ride_excitement = min(1000, total_ride_excitement);
total_ride_intensity = min(1000, total_ride_intensity);
result -= 200 - ((total_ride_excitement + total_ride_intensity) / 10);
}
// Litter
@ -178,54 +186,14 @@ int calculate_park_rating()
litter = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[sprite_idx].litter);
// Guessing this eliminates recently dropped litter
if (litter->var_24 - RCT2_GLOBAL(0x00F663AC, sint32) >= 7680)
if (litter->var_24 - RCT2_GLOBAL(0x00F663AC, uint32) >= 7680)
num_litter++;
}
result -= 600 - (4 * (150 - min(150, num_litter)));
}
// Rides
{
int i, num_rides;
short _ax, _bx;
rct_ride* ride;
num_rides = 0;
_ax = 0;
_bx = 0;
for (i = 0; i < 255; i++) {
ride = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[i]);
if (ride->type == RIDE_TYPE_NULL)
continue;
if (ride->excitement == -1)
continue;
_ax += ride->excitement / 8;
_bx += ride->intensity / 8;
num_rides++;
}
result -= 100;
if (num_rides > 0) {
_bx = _ax / num_rides;
_ax = _bx / num_rides;
_bx -= 46;
if (_bx >= 0)
_bx = -_bx;
_ax -= 65;
if (_ax >= 0)
_ax = -_ax;
_bx /= 2;
_ax /= 2;
_bx = min(50, _bx);
_ax = min(50, _ax);
result += 100 - _ax - _bx;
}
}
result -= RCT2_GLOBAL(0x0135882E, sint16);
result = clamp(0, result, 999);
return result;
}
@ -273,3 +241,18 @@ int calculate_company_value()
return result;
}
/**
*
* rct2: 0x00667104
*/
void reset_park_entrances() {
RCT2_GLOBAL(0x013573D4, uint16) = 0;
for (short i = 0; i < 4; i++) {
RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i] = 0x8000;
}
RCT2_GLOBAL(0x013573F2, uint16) = 0xFFFF;
RCT2_GLOBAL(0x013573F8, uint16) = 0xFFFF;
}

View File

@ -74,5 +74,6 @@ int park_calculate_size();
int calculate_park_rating();
int calculate_park_value();
int calculate_company_value();
void reset_park_entrances();
#endif

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
@ -38,6 +49,144 @@ enum STAFF_TYPE {
};
enum PEEP_THOUGHT_TYPE {
PEEP_THOUGHT_TYPE_SPENT_MONEY = 1, // "I've spent all my money"
PEEP_THOUGHT_TYPE_SICK = 2, // "I feel sick"
PEEP_THOUGHT_TYPE_VERY_SICK = 3, // "I feel very sick"
PEEP_THOUGHT_TYPE_MORE_THRILLING = 4, // "I want to go on something more thrilling than X"
PEEP_THOUGHT_TYPE_INTENSE = 5, // "X looks too intense for me"
PEEP_THOUGHT_TYPE_HAVENT_FINISHED = 6, // "I haven't finished my X yet"
PEEP_THOUGHT_TYPE_SICKENING = 7, // "Just looking at X makes me feel sick"
PEEP_THOUGHT_TYPE_BAD_VALUE = 8, // "I'm not paying that much to go on X"
PEEP_THOUGHT_TYPE_GO_HOME = 9, // "I want to go home"
PEEP_THOUGHT_TYPE_GOOD_VALUE = 10, // "X is really good value"
PEEP_THOUGHT_TYPE_ALREADY_GOT = 11, // "I've already got"
PEEP_THOUGHT_TYPE_CANT_AFFORD = 12, // "I can't afford"
PEEP_THOUGHT_TYPE_NOT_HUNGRY = 13, // "I'm not not hungry"
PEEP_THOUGHT_TYPE_NOT_THIRSTY = 14, // "I'm not not thirsty"
PEEP_THOUGHT_TYPE_DROWNING = 15, // "Help! I'm drowning!"
PEEP_THOUGHT_TYPE_LOST = 16, // "I'm lost!"
PEEP_THOUGHT_TYPE_WAS_GREAT = 17, // "X was great"
PEEP_THOUGHT_TYPE_QUEUING_AGES = 18, // "I've been queuing for X for ages"
PEEP_THOUGHT_TYPE_TIRED = 19, // "I'm tired"
PEEP_THOUGHT_TYPE_HUNGRY = 20, // "I'm hungry"
PEEP_THOUGHT_TYPE_THIRSTY = 21, // "I'm thirsty"
PEEP_THOUGHT_TYPE_BATHROOM = 22, // "I need to go to the bathroom"
PEEP_THOUGHT_TYPE_CANT_FIND = 23, // "I can't find X"
PEEP_THOUGHT_TYPE_NOT_PAYING = 24, // "I'm not paying that much to use X"
PEEP_THOUGHT_TYPE_NOT_WHILE_RAINING = 25, // "I'm not going on X while it's raining"
PEEP_THOUGHT_TYPE_BAD_LITTER = 26, // "The litter here is really bad"
PEEP_THOUGHT_TYPE_CANT_FIND_EXIT = 27, // "I can't find the exit"
PEEP_THOUGHT_TYPE_GET_OFF = 28, // "I want to get off X"
PEEP_THOUGHT_TYPE_GET_OUT = 29, // "I want to get out of X"
PEEP_THOUGHT_TYPE_NOT_SAFE = 30, // "I'm not going on X - it isn't safe"
PEEP_THOUGHT_TYPE_PATH_DISGUSTING = 31, // "This path is disgusting"
PEEP_THOUGHT_TYPE_CROWDED = 32, // "It's too crowded here"
PEEP_THOUGHT_TYPE_VANDALISM = 33, // "The vandalism here is really bad"
PEEP_THOUGHT_TYPE_SCENERY = 34, // "Great scenery!"
PEEP_THOUGHT_VERY_CLEAN = 35, // "This park is very clean and tidy"
PEEP_THOUGHT_TYPE_FOUNTAINS = 36, // "The jumping fountains are great"
PEEP_THOUGHT_TYPE_MUSIC = 37, // "The music is nice here"
PEEP_THOUGHT_TYPE_BALLOON = 38, // "This baloon from X is really good value"
PEEP_THOUGHT_TYPE_TOY = 39, // "This cuddly toy from X is really good value"
PEEP_THOUGHT_TYPE_MAP = 40,
PEEP_THOUGHT_TYPE_PHOTO = 41, // "This on ride photo from X is really good value"
PEEP_THOUGHT_TYPE_UMBRELLA = 42,
PEEP_THOUGHT_TYPE_DRINK = 43,
PEEP_THOUGHT_TYPE_BURGER = 44,
PEEP_THOUGHT_TYPE_FRIES = 45,
PEEP_THOUGHT_TYPE_ICE_CREAM = 46,
PEEP_THOUGHT_TYPE_COTTON_CANDY = 47,
PEEP_THOUGHT_TYPE_PIZZA = 51,
PEEP_THOUGHT_TYPE_POPCORN = 53,
PEEP_THOUGHT_TYPE_HOT_DOG = 54,
PEEP_THOUGHT_TYPE_TENTACLE = 55,
PEEP_THOUGHT_TYPE_HAT = 56,
PEEP_THOUGHT_TYPE_CANDY_APPLE = 57,
PEEP_THOUGHT_TYPE_TSHIRT = 58,
PEEP_THOUGHT_TYPE_DONUT = 59,
PEEP_THOUGHT_TYPE_COFFEE = 60,
PEEP_THOUGHT_TYPE_CHICKEN = 62,
PEEP_THOUGHT_TYPE_LEMONADE = 63,
PEEP_THOUGHT_TYPE_WOW = 67, // "Wow!"
PEEP_THOUGHT_TYPE_WOW2 = 70,// "Wow!"
PEEP_THOUGHT_TYPE_WATCHED = 71, // "I have the strangest feeling someone is watching me"
PEEP_THOUGHT_TYPE_BALLOON_MUCH = 72, // "I'm not paying that much to get a balloon from X"
PEEP_THOUGHT_TYPE_TOY_MUCH = 73,
PEEP_THOUGHT_TYPE_MAP_MUCH = 74,
PEEP_THOUGHT_TYPE_PHOTO_MUCH = 75,
PEEP_THOUGHT_TYPE_UMBRELLA_MUCH = 76,
PEEP_THOUGHT_TYPE_DRINK_MUCH = 77,
PEEP_THOUGHT_TYPE_BURGER_MUCH = 78,
PEEP_THOUGHT_TYPE_FRIES_MUCH = 79,
PEEP_THOUGHT_TYPE_ICE_CREAM_MUCH = 80,
PEEP_THOUGHT_TYPE_COTTON_CANDY_MUCH = 81,
PEEP_THOUGHT_TYPE_PIZZA_MUCH = 85,
PEEP_THOUGHT_TYPE_POPCORN_MUCH = 87,
PEEP_THOUGHT_TYPE_HOT_DOG_MUCH = 88,
PEEP_THOUGHT_TYPE_TENTACLE_MUCH = 89,
PEEP_THOUGHT_TYPE_HAT_MUCH = 90,
PEEP_THOUGHT_TYPE_CANDY_APPLE_MUCH = 91,
PEEP_THOUGHT_TYPE_TSHIRT_MUCH = 92,
PEEP_THOUGHT_TYPE_DONUT_MUCH = 93,
PEEP_THOUGHT_TYPE_COFFEE_MUCH = 94,
PEEP_THOUGHT_TYPE_CHICKEN_MUCH = 96,
PEEP_THOUGHT_TYPE_LEMONADE_MUCH = 97,
PEEP_THOUGHT_TYPE_PHOTO2 = 104, // "This on-ride photo from X is really good value"
PEEP_THOUGHT_TYPE_PHOTO3 = 105,
PEEP_THOUGHT_TYPE_PHOTO4 = 106,
PEEP_THOUGHT_TYPE_PRETZEL = 107,
PEEP_THOUGHT_TYPE_HOT_CHOCOLATE = 108,
PEEP_THOUGHT_TYPE_ICED_TEA = 109,
PEEP_THOUGHT_TYPE_FUNNEL_CAKE = 110,
PEEP_THOUGHT_TYPE_SUNGLASSES = 111,
PEEP_THOUGHT_TYPE_BEEF_NOODLES = 112,
PEEP_THOUGHT_TYPE_FRIED_RICE_NOODLES = 113,
PEEP_THOUGHT_TYPE_WONTON_SOUP = 114,
PEEP_THOUGHT_TYPE_MEATBALL_SOUP = 115,
PEEP_THOUGHT_TYPE_FRUIT_JUICE = 116,
PEEP_THOUGHT_TYPE_SOYBEAN_MILK = 117,
PEEP_THOUGHT_TYPE_SU_JONGKWA = 118,
PEEP_THOUGHT_TYPE_SUB_SANDWICH = 119,
PEEP_THOUGHT_TYPE_COOKIE = 120,
PEEP_THOUGH_ROAST_SAUSAGE = 124,
PEEP_THOUGHT_TYPE_PHOTO2_MUCH = 136,
PEEP_THOUGHT_TYPE_PHOTO3_MUCH = 137,
PEEP_THOUGHT_TYPE_PHOTO4_MUCH = 138,
PEEP_THOUGHT_TYPE_PRETZEL_MUCH = 139,
PEEP_THOUGHT_TYPE_HOT_CHOCOLATE_MUCH = 140,
PEEP_THOUGHT_TYPE_ICED_TEA_MUCH = 141,
PEEP_THOUGHT_TYPE_FUNNEL_CAKE_MUCH = 142,
PEEP_THOUGHT_TYPE_SUNGLASSES_MUCH = 143,
PEEP_THOUGHT_TYPE_BEEF_NOODLES_MUCH = 144,
PEEP_THOUGHT_TYPE_FRIED_RICE_NOODLES_MUCH = 145,
PEEP_THOUGHT_TYPE_WONTON_SOUP_MUCH = 146,
PEEP_THOUGHT_TYPE_MEATBALL_SOUP_MUCH = 147,
PEEP_THOUGHT_TYPE_FRUIT_JUICE_MUCH = 148,
PEEP_THOUGHT_TYPE_SOYBEAN_MILK_MUCH = 149,
PEEP_THOUGHT_TYPE_SU_JONGKWA_MUCH = 150,
PEEP_THOUGHT_TYPE_SUB_SANDWICH_MUCH = 151,
PEEP_THOUGHT_TYPE_COOKIE_MUCH = 152,
PEEP_THOUGHT_ROAST_SAUSAGE_MUCH = 156,
PEEP_THOUGHT_HELP = 168, // "Help! Put me down!"
PEEP_THOUGHT_RUNNING_OUT = 169, // I'm running out of cash!"
PEEP_THOUGHT_NEW_RIDE = 170, // "Wow! A new ride being built!"
PEEP_THOUGHT_NICE_RIDE = 171, // "Nice ride! But not as good as the Phoenix..."
PEEP_THOUGHT_EXCITED = 172, // "I'm so excited - It's an Intamin ride!"
PEEP_THOUGHT_HERE_WE_ARE = 173, // "...and here we are on X!"
PEEP_THOUGHT_TYPE_NONE = 255
};
@ -92,6 +241,69 @@ enum PEEP_FLAGS {
PEEP_FLAGS_ICE_CREAM = (1 << 25) // Unconfirmed
};
enum PEEP_NAUSEA_TOLERANCE {
PEEP_NAUSEA_TOLERANCE_NONE,
PEEP_NAUSEA_TOLERANCE_LOW,
PEEP_NAUSEA_TOLERANCE_AVERAGE,
PEEP_NAUSEA_TOLERANCE_HIGH
};
enum PEEP_ITEM {
// item_standard_flags
PEEP_ITEM_BALLOON = (1 << 0),
PEEP_ITEM_TOY = (1 << 1),
PEEP_ITEM_MAP = (1 << 2),
PEEP_ITEM_PHOTO = (1 << 3),
PEEP_ITEM_UMBRELLA = (1 << 4),
PEEP_ITEM_DRINK = (1 << 5),
PEEP_ITEM_BURGER = (1 << 6),
PEEP_ITEM_FRIES = (1 << 7),
PEEP_ITEM_ICE_CREAM = (1 << 8),
PEEP_ITEM_COTTON_CANDY = (1 << 9),
PEEP_ITEM_EMPTY_CAN = (1 << 10),
PEEP_ITEM_RUBBISH = (1 << 11),
PEEP_ITEM_EMPTY_BURGER_BOX = (1 << 12),
PEEP_ITEM_PIZZA = (1 << 13),
PEEP_ITEM_VOUCHER = (1 << 14),
PEEP_ITEM_POPCORN = (1 << 15),
PEEP_ITEM_HOT_DOG = (1 << 16),
PEEP_ITEM_TENTACLE = (1 << 17),
PEEP_ITEM_HAT = (1 << 18),
PEEP_ITEM_CANDY_APPLE = (1 << 19),
PEEP_ITEM_TSHIRT = (1 << 20),
PEEP_ITEM_DONUT = (1 << 21),
PEEP_ITEM_COFFEE = (1 << 22),
PEEP_ITEM_EMPTY_CUP = (1 << 23),
PEEP_ITEM_CHICKEN = (1 << 24),
PEEP_ITEM_LEMONADE = (1 << 25),
PEEP_ITEM_EMPTY_BOX = (1 << 26),
PEEP_ITEM_EMPTY_BOTTLE = (1 << 27),
// item_extra_flags
PEEP_ITEM_PHOTO2 = (1 << 0),
PEEP_ITEM_PHOTO3 = (1 << 1),
PEEP_ITEM_PHOTO4 = (1 << 2),
PEEP_ITEM_PRETZEL = (1 << 3),
PEEP_ITEM_CHOCOLATE = (1 << 4),
PEEP_ITEM_ICED_TEA = (1 << 5),
PEEP_ITEM_FUNNEL_CAKE = (1 << 6),
PEEP_ITEM_SUNGLASSES = (1 << 7),
PEEP_ITEM_BEEF_NOODLES = (1 << 8),
PEEP_ITEM_FRIED_RICE_NOODLES = (1 << 9),
PEEP_ITEM_WONTON_SOUP = (1 << 10),
PEEP_ITEM_MEATBALL_SOUP = (1 << 11),
PEEP_ITEM_FRUIT_JUICE = (1 << 12),
PEEP_ITEM_SOYBEAN_MILK = (1 << 13),
PEEP_ITEM_SU_JONGKWA = (1 << 14),
PEEP_ITEM_SUB_SANDWICH = (1 << 15),
PEEP_ITEM_COOKIE = (1 << 16),
PEEP_ITEM_EMPTY_BOWL_RED = (1 << 17),
PEEP_ITEM_EMPTY_DRINK_CARTON = (1 << 18),
PEEP_ITEM_EMPTY_JUICE_CUP = (1 << 19),
PEEP_ITEM_ROAST_SAUSAGE = (1 << 20),
PEEP_ITEM_EMPTY_BOWL_BLUE = (1 << 21)
};
typedef struct {
uint8 type;
uint8 item;
@ -137,7 +349,17 @@ typedef struct {
uint8 hunger; // 0x3E
uint8 thirst; // 0x3F
uint8 bathroom; // 0x40
uint8 pad_041[0x27];
uint8 pad_41[0x2];
uint8 intensity; // 0x43
uint8 nausea_tolerance; // 0x44
uint8 pad_45;
uint16 paid_on_drink; // 0x46
uint8 pad_48[0x10];
uint32 item_extra_flags; // 0x58
uint8 photo2_ride_ref; // 0x5C
uint8 photo3_ride_ref; // 0x5D
uint8 photo4_ride_ref; // 0x5E
uint8 pad_5F[0x09]; // 0x5C
uint8 current_ride; // 0x68
uint8 pad_69;
uint8 current_train; // 0x6A
@ -148,11 +370,14 @@ typedef struct {
uint32 id; // 0x9C
sint32 cash_in_pocket; // 0xA0
sint32 cash_spent; // 0xA4
uint8 pad_A8[8];
uint8 pad_A8;
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 pad_C7;
uint8 photo1_ride_ref; // 0xC7
uint32 flags; // 0xC8
uint8 var_CC;
uint8 pad_CD[0x17];
@ -168,9 +393,12 @@ typedef struct {
uint8 umbrella_colour; // 0xF7
uint8 hat_colour; // 0xF8
uint8 favourite_ride; // 0xF9
uint16 pad_FA;
uint32 item_standard_flags; // 0xFC
} rct_peep;
int peep_get_staff_count();
void peep_update_all();
void peep_problem_warnings_update();
#endif

View File

@ -122,12 +122,12 @@ void rct2_init()
RCT2_CALLPROC_EBPSAFE(0x006BA8E0); // init_audio();
viewport_init_all();
news_item_init_queue();
RCT2_CALLPROC_EBPSAFE(0x006C45E7); // get local time
RCT2_CALLPROC_EBPSAFE(0x00667104);
RCT2_CALLPROC_EBPSAFE(0x006C4209);
get_local_time();
reset_park_entrances();
reset_saved_strings();
RCT2_CALLPROC_EBPSAFE(0x0069EB13);
ride_init_all();
RCT2_CALLPROC_EBPSAFE(0x0068F083); // window guest list init vars a
window_guest_list_init_vars_a();
RCT2_CALLPROC_EBPSAFE(0x006BD3A4);
map_init();
park_init();
@ -135,15 +135,14 @@ void rct2_init()
date_reset();
climate_reset(CLIMATE_COOL_AND_WET);
RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
RCT2_CALLPROC_EBPSAFE(0x006ACA58);
RCT2_CALLPROC_EBPSAFE(0x0068F050); // window guest list init vars b
RCT2_CALLPROC_EBPSAFE(0x006BD39C);
window_ride_list_init_vars();
window_guest_list_init_vars_b();
RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8) = WINDOW_STAFF_LIST_TAB_HANDYMEN;
title_load();
gfx_clear(RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo), 10);
// RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, int) = 8;
RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, int) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, int) = gConfig.play_intro ? 8 : 0;
}
// rct2: 0x00683499
@ -235,7 +234,7 @@ void check_cmdline_arg()
if(!stricmp(processed_arg + last_period, "sv6"))
{
strcpy(0x00141EF68, processed_arg);
RCT2_CALLPROC_EBPSAFE(0x00675E1B); //load_saved_game
game_load_save();
}
else if(!stricmp(processed_arg + last_period, "sc6"))
{
@ -376,6 +375,19 @@ void get_system_time()
RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_DAYOFWEEK, sint16) = systime.wDayOfWeek;
}
/**
* Obtains os local time (hour and minute)
* rct2: 0x006C45E7;
*/
void get_local_time()
{
SYSTEMTIME systime;
GetLocalTime(&systime);
RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_HOUR, sint16) = systime.wHour;
RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MINUTE, sint16) = systime.wMinute;
}
/**
* RCT2 and this DLL can not free each other's allocated memory blocks. Use this to allocate memory if RCT2 is still able to
* free it.

View File

@ -126,6 +126,7 @@ void rct2_endupdate();
char *get_file_path(int pathId);
void get_system_info();
void get_system_time();
void get_local_time();
void *rct2_malloc(size_t numBytes);
void *rct2_realloc(void *block, size_t numBytes);
void rct2_free(void *block);

View File

@ -113,7 +113,7 @@ int ride_get_total_queue_length(rct_ride *ride)
{
int i, queueLength = 0;
for (i = 0; i < 4; i++)
if (ride->var_06A[i] != 0xFFFF)
if (ride->entrances[i] != 0xFFFF)
queueLength += ride->queue_length[i];
return queueLength;
}
@ -122,7 +122,7 @@ int ride_get_max_queue_time(rct_ride *ride)
{
int i, queueTime = 0;
for (i = 0; i < 4; i++)
if (ride->var_06A[i] != 0xFFFF)
if (ride->entrances[i] != 0xFFFF)
queueTime = max(queueTime, ride->queue_time[i]);
return queueTime;
}

View File

@ -31,16 +31,20 @@ typedef struct {
uint8 type; // 0x000
uint8 subtype; // 0x001
uint16 pad_002;
uint8 var_004;
uint8 pad_005[0x44];
uint8 mode; // 0x004
uint8 colour_scheme_type; // 0x005
uint16 car_colours[32]; // 0x006
uint8 pad_046[0x03];
uint8 status; // 0x049
uint16 var_04A;
uint32 var_04C;
uint16 var_050; // 0x050
uint8 pad_052[0x18];
uint16 var_06A[4]; // probably entrance map coordinates
uint8 pad_072[0x14];
uint16 train_car_map[1]; // 0x86 Points to the first car in the train
uint16 overall_view; // 0x050
uint16 station_starts[4]; // 0x052
uint8 pad_05A[0x10];
uint16 entrances[4]; // 0x06A
uint16 exits[4]; // 0x072
uint8 pad_07A[0x0C];
uint16 train_car_map[1]; // 0x086 Points to the first car in the train
uint8 pad_088[0x68];
sint16 var_0F0;
sint16 var_0F2;
@ -56,7 +60,8 @@ typedef struct {
sint16 running_cost; // 0x132
sint16 var_134;
sint16 var_136;
uint8 pad_138[0x08];
sint16 price; // 0x138
uint8 pad_13A[0x06];
sint16 excitement; // 0x140
sint16 intensity; // 0x142
uint16 nausea; // 0x144
@ -197,6 +202,52 @@ enum {
RIDE_STATUS_TESTING
};
enum {
RIDE_MODE_NORMAL = 0,
RIDE_MODE_CONTINUOUS_CIRCUIT,
RIDE_MODE_REVERSE_INCLINED_SHUTTLE,
RIDE_MODE_POWERED_LAUNCH, // RCT1 style?
RIDE_MODE_SHUTTLE,
RIDE_MODE_BOAT_HIRE,
RIDE_MODE_UPWARD_LAUNCH,
RIDE_MODE_ROTATING_LIFT,
RIDE_MODE_STATION_TO_STATION,
RIDE_MODE_SINGLE_RIDE_PER_ADMISSION,
RIDE_MODE_UNLIMITED_RIDES_PER_ADMISSION,
RIDE_MODE_MAZE,
RIDE_MODE_RACE,
RIDE_MODE_BUMPERCAR,
RIDE_MODE_SWING,
RIDE_MODE_SHOP_STALL,
RIDE_MODE_ROTATION,
RIDE_MODE_FORWARD_ROTATION,
RIDE_MODE_BACKWARD_ROTATION,
RIDE_MODE_FILM_AVENGING_AVIATORS,
RIDE_MODE_3D_FILM_MOUSE_TAILS,
RIDE_MODE_SPACE_RINGS,
RIDE_MODE_BEGINNERS,
RIDE_MODE_LIM_POWERED_LAUNCH,
RIDE_MODE_FILM_THRILL_RIDERS,
RIDE_MODE_3D_FILM_STORM_CHASERS,
RIDE_MODE_3D_FILM_SPACE_RAIDERS,
RIDE_MODE_INTENSE,
RIDE_MODE_BERSERK,
RIDE_MODE_HAUNTED_HOUSE,
RIDE_MODE_CIRCUS_SHOW,
RIDE_MODE_DOWNWARD_LAUNCH,
RIDE_MODE_CROOKED_HOUSE,
RIDE_MODE_FREEFALL_DROP,
RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED,
RIDE_MODE_POWERED_LAUNCH2, // RCT2 style?
RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED
};
enum {
RIDE_COLOUR_SCHEME_ALL_SAME,
RIDE_COLOUR_SCHEME_DIFFERENT_PER_TRAIN,
RIDE_COLOUR_SCHEME_DIFFERENT_PER_CAR
};
#define MAX_RIDES 255
#define MAX_RIDE_MEASUREMENTS 8

View File

@ -27,6 +27,48 @@ static int decode_chunk_rle(char *buffer, int length);
static int decode_chunk_repeat(char *buffer, int length);
static void decode_chunk_rotate(char *buffer, int length);
/**
*
* rct2: 0x00676FD2
*/
int sawyercoding_validate_checksum(HFILE hFile)
{
int i;
uint32 checksum, fileChecksum;
DWORD dataSize, bufferSize, numBytesRead;
uint8 buffer[1024];
// Get data size
if ((dataSize = SetFilePointer(hFile, 0, NULL, FILE_END)) < 8)
return;
dataSize -= 4;
// Calculate checksum
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
checksum = 0;
do {
bufferSize = min(dataSize, 1024);
ReadFile(hFile, buffer, bufferSize, &numBytesRead, NULL);
if (numBytesRead != bufferSize)
return 0;
for (i = 0; i < bufferSize; i++)
checksum += buffer[i];
dataSize -= bufferSize;
} while (dataSize != 0);
// Read file checksum
ReadFile(hFile, &fileChecksum, sizeof(fileChecksum), &numBytesRead, NULL);
if (numBytesRead != sizeof(fileChecksum))
return 0;
// Reset file position
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
// Validate
return checksum == fileChecksum;
}
/**
*
* rct2: 0x0067685F

View File

@ -36,6 +36,7 @@ enum {
CHUNK_ENCODING_ROTATE
};
int sawyercoding_validate_checksum(HFILE hFile);
int sawyercoding_read_chunk(HFILE hFile, uint8 *buffer);
#endif

View File

@ -23,6 +23,7 @@
#include <windows.h>
#include "addresses.h"
#include "date.h"
#include "finance.h"
#include "game.h"
#include "map.h"
#include "news_item.h"
@ -329,6 +330,12 @@ void scenario_load(char *path)
);
if (hFile != INVALID_HANDLE_VALUE) {
RCT2_GLOBAL(0x009E382C, HANDLE*) = hFile;
if (!sawyercoding_validate_checksum(hFile)) {
CloseHandle(hFile);
RCT2_GLOBAL(0x009AC31B, uint8) = 255;
RCT2_GLOBAL(0x009AC31C, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
return;
}
// Read first chunk
sawyercoding_read_chunk(hFile, s6Header);
@ -393,7 +400,7 @@ void scenario_load(char *path)
}
RCT2_GLOBAL(0x009AC31B, uint8) = 255;
RCT2_GLOBAL(0x009AC31C, uint16) = 3011;
RCT2_GLOBAL(0x009AC31C, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
}
/**
@ -422,8 +429,8 @@ void scenario_load_and_play(rct_scenario_basic *scenario)
mainWindow = window_get_main();
mainWindow->var_4B0 = -1;
mainWindow->var_4B2 = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_X, sint16);
mainWindow->var_4B4 = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_Y, sint16);
mainWindow->saved_view_x = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_X, sint16);
mainWindow->saved_view_y = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_Y, sint16);
uint8 _cl = (RCT2_GLOBAL(0x0138869E, sint16) & 0xFF) - mainWindow->viewport->zoom;
mainWindow->viewport->zoom = RCT2_GLOBAL(0x0138869E, sint16) & 0xFF;
@ -438,12 +445,12 @@ void scenario_load_and_play(rct_scenario_basic *scenario)
mainWindow->viewport->view_height <<= _cl;
}
}
mainWindow->var_4B2 -= mainWindow->viewport->view_width >> 1;
mainWindow->var_4B4 -= mainWindow->viewport->view_height >> 1;
mainWindow->saved_view_x -= mainWindow->viewport->view_width >> 1;
mainWindow->saved_view_y -= mainWindow->viewport->view_height >> 1;
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);
@ -848,9 +855,9 @@ void scenario_update()
if ((current_days_in_month * next_month_tick) >> 16 != (current_days_in_month * month_tick) >> 16) {
// daily checks
RCT2_CALLPROC_EBPSAFE(0x0069E79A); // finance update
RCT2_CALLPROC_EBPSAFE(0x0069E79A); // daily profit update
RCT2_CALLPROC_EBPSAFE(0x0069C35E); // some kind of peeps days_visited update loop
RCT2_CALLPROC_EBPSAFE(0x006C45E7); // get local time
get_local_time();
RCT2_CALLPROC_EBPSAFE(0x0066A13C); // objective 6 dragging
if (objective_type == 10 || objective_type == 9 || objective_type == 8 ||
objective_type == 6 || objective_type == 5) {
@ -862,13 +869,13 @@ void scenario_update()
//if ( (unsigned int)((4 * current_day) & 0xFFFF) >= 0xFFEFu) {
if ( next_month_tick % 0x4000 == 0) {
// weekly checks
RCT2_CALLPROC_EBPSAFE(0x006C18A9);
RCT2_CALLPROC_EBPSAFE(0x00684DA5);
RCT2_CALLPROC_EBPSAFE(0x0069E092);
finance_pay_wages();
finance_pay_research();
finance_pay_interest();
scenario_marketing_update();
RCT2_CALLPROC_EBPSAFE(0x0069BF41);
RCT2_CALLPROC_EBPSAFE(0x006B7A5E);
RCT2_CALLPROC_EBPSAFE(0x006AC916);
peep_problem_warnings_update();
RCT2_CALLPROC_EBPSAFE(0x006B7A5E); // check ride reachability
RCT2_CALLPROC_EBPSAFE(0x006AC916); // ride update favourited
if (month <= 1 && RCT2_GLOBAL(0x009ADAE0, sint32) != -1 && RCT2_GLOBAL(0x009ADAE0 + 14, uint16) & 1) {
for (int i = 0; i < 100; ++i) {
@ -880,8 +887,8 @@ void scenario_update()
break;
}
}
RCT2_CALLPROC_EBPSAFE(0x0066A231);
RCT2_CALLPROC_EBPSAFE(0x0066A348);
RCT2_CALLPROC_EBPSAFE(0x0066A231); // update histories (finance, ratings, etc)
park_calculate_size();
}
//if ( (unsigned int)((2 * current_day) & 0xFFFF) >= 0xFFF8) {
@ -891,14 +898,14 @@ 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;
RCT2_CALLPROC_EBPSAFE(0x0069DEAD);
scenario_objectives_check();
scenario_entrance_fee_too_high_check();
RCT2_CALLPROC_EBPSAFE(0x0066A86C);
RCT2_CALLPROC_EBPSAFE(0x0066A86C); // award checks
}
}

View File

@ -43,7 +43,7 @@ typedef struct {
uint32 pad_00;
uint16 next; // 0x04
uint8 pad_06[0x1E];
sint32 var_24;
uint32 var_24;
} rct_litter;
typedef struct {

View File

@ -124,3 +124,13 @@ void generate_string_file()
fclose(f);
}
/**
*
* rct2: 0x006C4209
*/
void reset_saved_strings() {
for (int i = 0; i < 1024; i++) {
RCT2_ADDRESS(0x135A8F4, uint8)[i * 32] = 0;
}
}

View File

@ -25,6 +25,7 @@ typedef unsigned short rct_string_id;
void format_string(char *dest, rct_string_id format, void *args);
void generate_string_file();
void reset_saved_strings();
enum {
FORMAT_TINYFONT = 7,
@ -334,6 +335,7 @@ enum {
SPR_BUY_CONSTRUCTION_RIGHTS_TIP = 2326,
STR_PARK_INFORMATION_TIP = 2233,
STR_RECENT_MESSAGES = 2234,
STR_MONTH_JANUARY = 2236,
STR_MONTH_FEBRUARY = STR_MONTH_JANUARY + 1,
@ -353,6 +355,17 @@ enum {
STR_CHANGE_BASE_LAND_TIP = 2294,
STR_CHANGE_VERTICAL_LAND_TIP = 2295,
//STR_NONE = 2368,
STR_LOW = 2369,
STR_AVERAGE = 2370,
STR_HIGH = 2371,
//STR_LOW = 2372,
STR_MEDIUM = 2373,
//STR_HIGH = 2374,
STR_VERY_HIGH = 2375,
STR_EXTREME = 2376,
STR_ULTRA_EXTREME = 2377,
STR_ADJUST_SMALLER_LAND_TIP = 2378,
STR_ADJUST_LARGER_LAND_TIP = 2379,
STR_ADJUST_SMALLER_WATER_TIP = 2380,
@ -403,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,
@ -433,10 +454,17 @@ 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,
STR_UNABLE_TO_LOAD_FILE = 3010,
STR_FILE_CONTAINS_INVALID_DATA = 3011,
STR_BEGINNER_PARKS = 3064,
STR_CHALLENGING_PARKS = STR_BEGINNER_PARKS + 1,

View File

@ -34,6 +34,7 @@
#include "scenario.h"
#include "strings.h"
#include "viewport.h"
#include "editor.h"
static const int gOldMusic = 0;
static const int gRandomShowcase = 0;
@ -91,20 +92,20 @@ void title_load()
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_TITLE_DEMO;
RCT2_CALLPROC_EBPSAFE(0x00667104);
RCT2_CALLPROC_EBPSAFE(0x006C4209);
reset_park_entrances();
reset_saved_strings();
RCT2_CALLPROC_EBPSAFE(0x0069EB13);
ride_init_all();
RCT2_CALLPROC_EBPSAFE(0x0068F083); // window_guest_list_init_vars_a
window_guest_list_init_vars_a();
RCT2_CALLPROC_EBPSAFE(0x006BD3A4);
map_init();
park_init();
date_reset();
RCT2_CALLPROC_X(0x006C45ED, 0, 0, 0, 0, 0, 0, 0);
RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
RCT2_CALLPROC_EBPSAFE(0x006ACA58);
RCT2_CALLPROC_EBPSAFE(0x0068F050); // window_guest_list_init_vars_b
RCT2_CALLPROC_EBPSAFE(0x006BD39C);
window_ride_list_init_vars();
window_guest_list_init_vars_b();
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();
@ -167,8 +168,8 @@ static void title_update_showcase()
w = window_get_main();
w->var_4B0 = -1;
w->var_4B2 = RCT2_GLOBAL(0x0138869A, sint16);
w->var_4B4 = RCT2_GLOBAL(0x0138869C, sint16);
w->saved_view_x = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_X, sint16);
w->saved_view_y = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_Y, sint16);
{
char _cl = (RCT2_GLOBAL(0x0138869E, sint16) & 0xFF) - w->viewport->zoom;
@ -184,13 +185,13 @@ static void title_update_showcase()
w->viewport->view_height <<= _cl;
}
}
w->var_4B2 -= w->viewport->view_width >> 1;
w->var_4B4 -= w->viewport->view_height >> 1;
w->saved_view_x -= w->viewport->view_width >> 1;
w->saved_view_y -= w->viewport->view_height >> 1;
}
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

@ -63,7 +63,7 @@ void viewport_init_all()
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = -1;
RCT2_GLOBAL(0x009DE550, sint32) = -1;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, sint16) = -1;
RCT2_GLOBAL(0x009DE58A, sint16) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, sint16) = 0;
RCT2_GLOBAL(0x009DEA50, sint16) = -1;
RCT2_CALLPROC_EBPSAFE(0x006EE3C3);
format_string((char*)0x0141FA44, STR_CANCEL, NULL);

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

@ -631,6 +631,7 @@ void window_init_scroll_widgets(rct_window *w)
rct_widget* widget;
rct_scroll* scroll;
int widget_index, scroll_index;
int width, height;
widget_index = 0;
scroll_index = 0;
@ -641,16 +642,11 @@ void window_init_scroll_widgets(rct_window *w)
}
scroll = &w->scrolls[scroll_index];
{
int _eax = 0, _ebx = scroll_index * sizeof(rct_scroll), _ecx = 0, _edx = 0, _esi = w, _edi = widget_index * sizeof(rct_widget), _ebp = 0;
RCT2_CALLFUNC_X(w->event_handlers[WE_SCROLL_GETSIZE], & _eax, &_ebx, &_ecx, &_edx, &_esi, &_edi, &_ebp);
scroll->h_left = 0;
scroll->h_right = _ecx + 1;
scroll->v_top = 0;
scroll->v_bottom = _edx + 1;
}
window_get_scroll_size(w, scroll_index, &width, &height);
scroll->h_left = 0;
scroll->h_right = width + 1;
scroll->v_top = 0;
scroll->v_bottom = height + 1;
if (widget->image & 0x01)
scroll->flags |= HSCROLLBAR_VISIBLE;
@ -675,6 +671,18 @@ void window_update_scroll_widgets(rct_window *w)
RCT2_CALLPROC_X(0x006EAE4E, 0, 0, 0, 0, w, 0, 0);
}
int window_get_scroll_size(rct_window *w, int scrollIndex, int *width, int *height)
{
rct_widget *widget = window_get_scroll_widget(w, scrollIndex);
int widgetIndex = window_get_widget_index(w, widget);
int eax = 0, ebx = scrollIndex * sizeof(rct_scroll), ecx = 0, edx = 0, esi = w, edi = widgetIndex * sizeof(rct_widget), ebp = 0;
RCT2_CALLFUNC_X(w->event_handlers[WE_SCROLL_GETSIZE], & eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
*width = ecx;
*height = edx;
return 1;
}
int window_get_scroll_data_index(rct_window *w, int widget_index)
{
int i, result;
@ -1171,4 +1179,52 @@ void tool_cancel()
RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_ABORT], 0, 0, 0, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), w, 0, 0);
}
}
}
/**
*
* rct2: 0x0068F083
*/
void window_guest_list_init_vars_a() {
RCT2_GLOBAL(0x013B0E6C, uint32) = 1;
RCT2_GLOBAL(0x00F1AF1C, uint32) = 0xFFFFFFFF;
RCT2_GLOBAL(0x00F1EE02, uint32) = 0xFFFFFFFF;
RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_GUEST_LIST_SELECTED_FILTER, uint8) = 0xFF;
}
/**
*
* rct2: 0x0068F050
*/
void window_guest_list_init_vars_b() {
RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_GUEST_LIST_SELECTED_TAB, uint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_GUEST_LIST_SELECTED_VIEW, uint8) = 0;
RCT2_GLOBAL(0x00F1AF1C, uint32) = 0xFFFFFFFF;
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

@ -126,7 +126,7 @@ typedef struct rct_window {
sint16 var_484; // viewport target y
sint16 var_486; // viewport target z
sint16 var_488; // viewport rotation << 8
sint16 page;
sint16 page; // 0x49A
sint16 var_48C;
sint16 var_48E;
sint16 var_490;
@ -136,8 +136,8 @@ typedef struct rct_window {
sint16 var_4AC;
sint16 var_4AE;
sint16 var_4B0; // viewport target sprite?
sint16 var_4B2; // viewport target x?
sint16 var_4B4; // viewport target y?
sint16 saved_view_x; // 0x4B2
sint16 saved_view_y; // 0x4B4
rct_windowclass classification; // 0x4B6
uint8 pad_4B7;
sint8 var_4B8;
@ -190,6 +190,7 @@ typedef enum {
WF_STICK_TO_BACK = (1 << 0),
WF_STICK_TO_FRONT = (1 << 1),
WF_2 = (1 << 2),
WF_3 = (1 << 3),
WF_TRANSPARENT = (1 << 4),
WF_5 = (1 << 5),
WF_RESIZABLE = (1 << 8),
@ -283,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);
@ -298,6 +316,7 @@ void widget_invalidate(rct_windowclass cls, rct_windownumber number, int widgetI
void window_init_scroll_widgets(rct_window *w);
void window_update_scroll_widgets(rct_window *w);
int window_get_scroll_data_index(rct_window *w, int widget_index);
int window_get_scroll_size(rct_window *w, int scrollIndex, int *width, int *height);
rct_window *window_bring_to_front_by_id(rct_windowclass cls, rct_windownumber number);
rct_window *window_bring_to_front(rct_window *w);
@ -334,13 +353,19 @@ void window_save_prompt_open();
void window_title_menu_open();
void window_title_exit_open();
void window_title_logo_open();
void window_news_open();
void window_scenarioselect_open();
void window_clear_scenery_open();
void window_land_open();
void window_water_open();
void window_guest_list_open();
void window_park_entrance_open();
void window_park_objective_open();
void window_ride_list_open();
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

View File

@ -56,7 +56,7 @@ static rct_widget window_cheats_money_widgets[] = {
{ WWT_IMGBTN, 1, 0, WW - 1, 43, WH - 1, 0x0FFFFFFFF, 65535}, // tab content panel
{ WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, 2462}, // tab 1
{ WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, 2462}, // tab 2
{ WWT_CLOSEBOX, 1, 4, 74, 47, 63, 2375, 2375 }, // high money
{ WWT_CLOSEBOX, 1, 4, 74, 47, 63, STR_VERY_HIGH, STR_VERY_HIGH}, // high money
{ WIDGETS_END },
};
@ -67,7 +67,7 @@ static rct_widget window_cheats_guests_widgets[] = {
{ WWT_IMGBTN, 1, 0, WW - 1, 43, WH - 1, 0x0FFFFFFFF, 65535 }, // tab content panel
{ WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, 2462 }, // tab 1
{ WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, 2462 }, // tab 2
{ WWT_CLOSEBOX, 1, 4, 74, 47, 63, 2376, 2376 }, // happy guests
{ WWT_CLOSEBOX, 1, 4, 74, 47, 63, STR_EXTREME, STR_EXTREME}, // happy guests
{ WIDGETS_END },
};

View File

@ -223,7 +223,7 @@ static void window_footpath_close()
RCT2_CALLPROC_EBPSAFE(0x006A7831);
RCT2_CALLPROC_X(0x006CB70A, 0, 0, 0, 0, 0, 0, 0);
RCT2_CALLPROC_EBPSAFE(0x0068AB1B);
RCT2_GLOBAL(0x009DE58A, uint16) &= ~2;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~2;
window_invalidate_by_id(WC_TOP_TOOLBAR, 0);
hide_gridlines();
}
@ -258,7 +258,7 @@ static void window_footpath_mouseup()
tool_cancel();
RCT2_CALLPROC_EBPSAFE(0x006A7831);
RCT2_CALLPROC_EBPSAFE(0x0068AB1B);
RCT2_GLOBAL(0x009DE58A, uint16) &= ~2;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~2;
RCT2_GLOBAL(0x00F3EF99, uint8) = PATH_CONSTRUCTION_MODE_LAND;
tool_set(w, WIDX_CONSTRUCT_ON_LAND, 17);
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 6);
@ -273,7 +273,7 @@ static void window_footpath_mouseup()
RCT2_CALLPROC_EBPSAFE(0x006EE281);
RCT2_CALLPROC_EBPSAFE(0x006A7831);
RCT2_CALLPROC_EBPSAFE(0x0068AB1B);
RCT2_GLOBAL(0x009DE58A, uint16) &= ~2;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~2;
RCT2_GLOBAL(0x00F3EF99, uint8) = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL;
tool_set(w, WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL, 12);
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 6);

View File

@ -195,7 +195,7 @@ static void window_game_bottom_toolbar_mouseup()
break;
case WIDX_RIGHT_OUTSET:
case WIDX_DATE:
RCT2_CALLPROC_EBPSAFE(0x0066E464);
window_news_open();
break;
}
}

View File

@ -233,7 +233,7 @@ static void window_game_top_toolbar_mouseup()
RCT2_CALLPROC_EBPSAFE(0x006BD3CC);
break;
case WIDX_GUESTS:
RCT2_CALLPROC_EBPSAFE(0x006992E3);
window_guest_list_open();
break;
}
}

940
src/window_guest_list.c Normal file
View File

@ -0,0 +1,940 @@
/*****************************************************************************
* 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 <string.h>
#include "addresses.h"
#include "game.h"
#include "peep.h"
#include "strings.h"
#include "sprite.h"
#include "sprites.h"
#include "widget.h"
#include "window.h"
#include "window_dropdown.h"
enum {
PAGE_INDIVIDUAL,
PAGE_SUMMARISED
};
enum WINDOW_GUEST_LIST_WIDGET_IDX {
WIDX_BACKGROUND,
WIDX_TITLE,
WIDX_CLOSE,
WIDX_TAB_CONTENT_PANEL,
WIDX_PAGE_DROPDOWN,
WIDX_PAGE_DROPDOWN_BUTTON,
WIDX_INFO_TYPE_DROPDOWN,
WIDX_INFO_TYPE_DROPDOWN_BUTTON,
WIDX_MAP,
WIDX_TAB_1,
WIDX_TAB_2,
WIDX_GUEST_LIST
};
enum {
VIEW_ACTIONS,
VIEW_THOUGHTS
};
static rct_widget window_guest_list_widgets[] = {
{ WWT_FRAME, 0, 0, 349, 0, 329, 0x0FFFFFFFF, STR_NONE }, // panel / background
{ WWT_CAPTION, 0, 1, 348, 1, 14, STR_GUESTS, STR_WINDOW_TITLE_TIP }, // title bar
{ WWT_CLOSEBOX, 0, 337, 347, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button
{ WWT_RESIZE, 1, 0, 349, 43, 329, 0x0FFFFFFFF, STR_NONE }, // tab content panel
{ WWT_DROPDOWN, 1, 5, 84, 59, 70, STR_PAGE_1, STR_NONE }, // page dropdown
{ WWT_DROPDOWN_BUTTON, 1, 73, 83, 60, 69, 876, STR_NONE }, // page dropdown button
{ WWT_DROPDOWN, 1, 126, 301, 59, 70, 0x0FFFFFFFF, STR_INFORMATION_TYPE_TIP }, // information type dropdown
{ WWT_DROPDOWN_BUTTON, 1, 290, 300, 60, 69, 876, STR_INFORMATION_TYPE_TIP }, // information type dropdown button
{ WWT_FLATBTN, 1, 321, 344, 46, 69, 5192, STR_SHOW_GUESTS_ON_MAP_TIP }, // map
{ WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_INDIVIDUAL_GUESTS_TIP }, // tab 1
{ WWT_TAB, 1, 34, 64, 17, 43, 0x02000144E, STR_SUMMARISED_GUESTS_TIP }, // tab 2
{ WWT_SCROLL, 1, 3, 346, 72, 326, 3, STR_NONE }, // guest list
{ WIDGETS_END },
};
static void window_guest_list_emptysub() { }
static void window_guest_list_mouseup();
static void window_guest_list_resize();
static void window_guest_list_mousedown();
static void window_guest_list_dropdown();
static void window_guest_list_update();
static void window_guest_list_scrollgetsize();
static void window_guest_list_scrollmousedown();
static void window_guest_list_scrollmouseover();
static void window_guest_list_tooltip();
static void window_guest_list_invalidate();
static void window_guest_list_paint();
static void window_guest_list_scrollpaint();
static uint32 window_guest_list_events[] = {
window_guest_list_emptysub,
window_guest_list_mouseup,
window_guest_list_resize,
window_guest_list_mousedown,
window_guest_list_dropdown,
window_guest_list_emptysub,
window_guest_list_update,
window_guest_list_emptysub,
window_guest_list_emptysub,
window_guest_list_emptysub,
window_guest_list_emptysub,
window_guest_list_emptysub,
window_guest_list_emptysub,
window_guest_list_emptysub,
window_guest_list_emptysub,
window_guest_list_scrollgetsize,
window_guest_list_scrollmousedown,
window_guest_list_emptysub,
window_guest_list_scrollmouseover,
window_guest_list_emptysub,
window_guest_list_emptysub,
window_guest_list_emptysub,
window_guest_list_tooltip,
window_guest_list_emptysub,
window_guest_list_emptysub,
window_guest_list_invalidate,
window_guest_list_paint,
window_guest_list_scrollpaint
};
static int _window_guest_list_highlighted_index;
static int _window_guest_list_selected_tab;
static int _window_guest_list_selected_filter;
static int _window_guest_list_selected_page;
static int _window_guest_list_selected_view;
static int _window_guest_list_num_pages;
static int _window_guest_list_num_groups;
static uint16 _window_guest_list_groups_num_guests[240];
static uint32 _window_guest_list_groups_argument_1[240];
static uint32 _window_guest_list_groups_argument_2[240];
static uint8 _window_guest_list_groups_guest_faces[240 * 58];
static int window_guest_list_is_peep_in_filter(rct_peep* peep);
static void window_guest_list_find_groups();
static int get_guest_face_sprite(rct_peep *peep);
/**
*
* rct2: 0x006992E3
*/
void window_guest_list_open()
{
rct_window* window;
// Check if window is already open
window = window_bring_to_front_by_id(WC_RIDE_LIST, 0);
if (window != NULL)
return;
window = window_create_auto_pos(350, 330, window_guest_list_events, WC_GUEST_LIST, 0x0400);
window->widgets = window_guest_list_widgets;
window->enabled_widgets =
(1 << WIDX_CLOSE) |
(1 << WIDX_PAGE_DROPDOWN) |
(1 << WIDX_PAGE_DROPDOWN_BUTTON) |
(1 << WIDX_INFO_TYPE_DROPDOWN) |
(1 << WIDX_INFO_TYPE_DROPDOWN_BUTTON) |
(1 << WIDX_MAP) |
(1 << WIDX_TAB_1) |
(1 << WIDX_TAB_2);
window_init_scroll_widgets(window);
_window_guest_list_highlighted_index = -1;
window->var_490 = 0;
_window_guest_list_selected_tab = 1;
_window_guest_list_selected_filter = -1;
_window_guest_list_selected_page = 0;
_window_guest_list_num_pages = 1;
window_guest_list_widgets[WIDX_PAGE_DROPDOWN].type = WWT_EMPTY;
window_guest_list_widgets[WIDX_PAGE_DROPDOWN_BUTTON].type = WWT_EMPTY;
window->var_492 = 0;
window->min_width = 350;
window->min_height = 330;
window->max_width = 500;
window->max_height = 450;
window->flags = WF_RESIZABLE;
window->colours[0] = 1;
window->colours[1] = 15;
window->colours[2] = 15;
}
/**
*
* rct2: 0x00699AAF
*/
static void window_guest_list_mouseup()
{
int i;
short widgetIndex;
rct_window *w;
__asm mov widgetIndex, dx
__asm mov w, esi
switch (widgetIndex) {
case WIDX_CLOSE:
window_close(w);
break;
case WIDX_MAP:
RCT2_CALLPROC_EBPSAFE(0x0068C88A);
break;
}
}
/**
*
* rct2: 0x00699EA3
*/
static void window_guest_list_resize()
{
rct_window *w;
__asm mov w, esi
w->min_width = 350;
w->min_height = 330;
if (w->width < w->min_width) {
window_invalidate(w);
w->width = w->min_width;
}
if (w->height < w->min_height) {
window_invalidate(w);
w->height = w->min_height;
}
}
/**
*
* rct2: 0x00699AC4
*/
static void window_guest_list_mousedown()
{
int i;
short widgetIndex;
rct_window *w;
rct_widget *widget;
__asm mov widgetIndex, dx
__asm mov w, esi
__asm mov widget, edi
switch (widgetIndex) {
case WIDX_TAB_1:
case WIDX_TAB_2:
if (_window_guest_list_selected_filter == -1)
if (_window_guest_list_selected_tab == widgetIndex - WIDX_TAB_1)
break;
_window_guest_list_selected_tab = widgetIndex - WIDX_TAB_1;
_window_guest_list_selected_page = 0;
_window_guest_list_num_pages = 1;
window_guest_list_widgets[WIDX_PAGE_DROPDOWN].type = WWT_EMPTY;
window_guest_list_widgets[WIDX_PAGE_DROPDOWN_BUTTON].type = WWT_EMPTY;
w->var_490 = 0;
_window_guest_list_selected_filter = -1;
window_invalidate(w);
w->scrolls[0].v_top = 0;
break;
case WIDX_PAGE_DROPDOWN_BUTTON:
widget = &w->widgets[widgetIndex - 1];
window_dropdown_show_text_custom_width(
w->x + widget->left,
w->y + widget->top,
widget->bottom - widget->top + 1,
w->colours[1],
0x80,
_window_guest_list_num_pages,
widget->right - widget->left - 3
);
for (i = 0; i < 2; i++) {
gDropdownItemsFormat[i] = 1142;
gDropdownItemsArgs[i] = STR_PAGE_1 + i;
}
RCT2_GLOBAL(0x009DED38, uint32) |= (1 << _window_guest_list_selected_view);
break;
case WIDX_INFO_TYPE_DROPDOWN_BUTTON:
widget = &w->widgets[widgetIndex - 1];
window_dropdown_show_text_custom_width(
w->x + widget->left,
w->y + widget->top,
widget->bottom - widget->top + 1,
w->colours[1],
0x80,
2,
widget->right - widget->left - 3
);
for (i = 0; i < 2; i++) {
gDropdownItemsFormat[i] = 1142;
gDropdownItemsArgs[i] = STR_ACTIONS + i;
}
RCT2_GLOBAL(0x009DED38, uint32) |= (1 << _window_guest_list_selected_view);
break;
}
}
/**
*
* rct2: 0x00699AE1
*/
static void window_guest_list_dropdown()
{
short dropdownIndex, widgetIndex;
rct_window *w;
__asm mov dropdownIndex, ax
__asm mov widgetIndex, dx
__asm mov w, esi
switch (widgetIndex) {
case WIDX_PAGE_DROPDOWN_BUTTON:
if (dropdownIndex == -1)
break;
_window_guest_list_selected_page = dropdownIndex;
window_invalidate(w);
break;
case WIDX_INFO_TYPE_DROPDOWN_BUTTON:
if (dropdownIndex == -1)
break;
_window_guest_list_selected_view = dropdownIndex;
window_invalidate(w);
break;
}
}
/**
*
* rct2: 0x00699E54
*/
static void window_guest_list_update()
{
rct_window *w;
__asm mov w, esi
if (RCT2_GLOBAL(0x00F1AF20, uint16) != 0)
RCT2_GLOBAL(0x00F1AF20, uint16)--;
w->var_490++;
if (w->var_490 >= (_window_guest_list_selected_tab == PAGE_INDIVIDUAL ? 24 : 32))
w->var_490 = 0;
widget_invalidate(WC_GUEST_LIST, 0, WIDX_TAB_1 + _window_guest_list_selected_tab);
}
/**
*
* rct2: 0x00699C55
*/
static void window_guest_list_scrollgetsize()
{
int i, y, numGuests, spriteIdx;
rct_window *w;
rct_peep *peep;
__asm mov w, esi
switch (_window_guest_list_selected_tab) {
case PAGE_INDIVIDUAL:
// Count the number of guests
numGuests = 0;
spriteIdx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16);
while (spriteIdx != SPRITE_INDEX_NULL) {
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[spriteIdx].peep);
spriteIdx = peep->next;
if (peep->type != PEEP_TYPE_GUEST)
continue;
if (peep->var_2A != 0)
continue;
if (_window_guest_list_selected_filter != -1)
if (window_guest_list_is_peep_in_filter(peep))
continue;
numGuests++;
}
w->var_492 = numGuests;
y = numGuests * 10;
break;
case PAGE_SUMMARISED:
// Find the groups
window_guest_list_find_groups();
w->var_492 = _window_guest_list_num_groups;
y = _window_guest_list_num_groups * 21;
break;
}
RCT2_GLOBAL(0x00F1EE09, uint32) = numGuests;
i = _window_guest_list_selected_page;
for (i = _window_guest_list_selected_page - 1; i >= 0; i--)
y -= 0x7BF2;
if (y < 0)
y = 0;
if (y > 0x7BF2)
y = 0x7BF2;
if (_window_guest_list_highlighted_index != -1) {
_window_guest_list_highlighted_index = -1;
window_invalidate(w);
}
i = y - window_guest_list_widgets[WIDX_GUEST_LIST].bottom + window_guest_list_widgets[WIDX_GUEST_LIST].top + 21;
if (i < 0)
i = 0;
if (i < w->scrolls[0].v_top) {
w->scrolls[0].v_top = i;
window_invalidate(w);
}
__asm mov ecx, 447
__asm mov edx, y
}
/**
*
* rct2: 0x00699D7D
*/
static void window_guest_list_scrollmousedown()
{
int i, spriteIdx;
short y;
rct_window *w;
rct_peep *peep;
__asm mov y, dx
__asm mov w, esi
switch (_window_guest_list_selected_tab) {
case PAGE_INDIVIDUAL:
i = y / 10;
i += _window_guest_list_selected_page * 3173;
spriteIdx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16);
while (spriteIdx != SPRITE_INDEX_NULL) {
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[spriteIdx].peep);
spriteIdx = peep->next;
if (peep->type != PEEP_TYPE_GUEST)
continue;
if (peep->var_2A != 0)
continue;
if (_window_guest_list_selected_filter != -1)
if (window_guest_list_is_peep_in_filter(peep))
continue;
if (i == 0) {
// Open guest window
RCT2_CALLPROC_X(0x006989E9, 0, 0, 0, peep, 0, 0, 0);
break;
} else {
i--;
}
}
break;
case PAGE_SUMMARISED:
i = y / 21;
if (i < _window_guest_list_num_groups) {
RCT2_GLOBAL(0x00F1EDF6, uint32) = _window_guest_list_groups_argument_1[i];
RCT2_GLOBAL(0x00F1EDFA, uint32) = _window_guest_list_groups_argument_2[i];
_window_guest_list_selected_filter = _window_guest_list_selected_view;
_window_guest_list_selected_tab = PAGE_INDIVIDUAL;
window_invalidate(w);
w->scrolls[0].v_top = 0;
}
break;
}
}
/**
*
* rct2: 0x00699D3B
*/
static void window_guest_list_scrollmouseover()
{
int i;
short y;
rct_window *w;
__asm mov y, dx
__asm mov w, esi
i = y / (_window_guest_list_selected_tab == PAGE_INDIVIDUAL ? 10 : 21);
i += _window_guest_list_selected_page * 3173;
if (i != _window_guest_list_highlighted_index) {
_window_guest_list_highlighted_index = i;
window_invalidate(w);
}
}
/**
*
* rct2: 0x00699E4A
*/
static void window_guest_list_tooltip()
{
RCT2_GLOBAL(0x013CE952, uint16) = STR_LIST;
}
/**
*
* rct2: 0x00699511
*/
static void window_guest_list_invalidate()
{
rct_window *w;
__asm mov w, esi
w->pressed_widgets &= ~(1 << WIDX_TAB_1);
w->pressed_widgets &= ~(1 << WIDX_TAB_2);
w->pressed_widgets |= (1 << (_window_guest_list_selected_tab + WIDX_TAB_1));
window_guest_list_widgets[WIDX_INFO_TYPE_DROPDOWN].image = STR_ACTIONS + _window_guest_list_selected_view;
window_guest_list_widgets[WIDX_MAP].type = WWT_EMPTY;
if (_window_guest_list_selected_tab == PAGE_INDIVIDUAL && _window_guest_list_selected_filter != -1)
window_guest_list_widgets[WIDX_MAP].type = WWT_FLATBTN;
window_guest_list_widgets[WIDX_BACKGROUND].right = w->width - 1;
window_guest_list_widgets[WIDX_BACKGROUND].bottom = w->height - 1;
window_guest_list_widgets[WIDX_TAB_CONTENT_PANEL].right = w->width - 1;
window_guest_list_widgets[WIDX_TAB_CONTENT_PANEL].bottom = w->height - 1;
window_guest_list_widgets[WIDX_TITLE].right = w->width - 2;
window_guest_list_widgets[WIDX_CLOSE].left = w->width - 13;
window_guest_list_widgets[WIDX_CLOSE].right = w->width - 3;
window_guest_list_widgets[WIDX_GUEST_LIST].right = w->width - 4;
window_guest_list_widgets[WIDX_GUEST_LIST].bottom = w->height - 15;
window_guest_list_widgets[WIDX_PAGE_DROPDOWN].image = _window_guest_list_selected_page + 3440;
}
/**
*
* rct2: 0x006995CC
*/
static void window_guest_list_paint()
{
int i, x, y, format;
rct_window *w;
rct_drawpixelinfo *dpi;
__asm mov w, esi
__asm mov dpi, edi
// Widgets
window_draw_widgets(w, dpi);
// Tab 1 image
i = (_window_guest_list_selected_tab == 0 ? w->var_490 & 0x0FFFFFFFC : 0);
i += ((int*)*((int*)0x00982708))[0] + 1;
i |= 0xA1600000;
gfx_draw_sprite(
dpi,
i,
(window_guest_list_widgets[WIDX_TAB_1].left + window_guest_list_widgets[WIDX_TAB_1].right) / 2 + w->x,
window_guest_list_widgets[WIDX_TAB_1].bottom - 6 + w->y
);
// Tab 2 image
i = (_window_guest_list_selected_tab == 1 ? w->var_490 / 4 : 0);
gfx_draw_sprite(
dpi,
5568 + i,
window_guest_list_widgets[WIDX_TAB_2].left + w->x,
window_guest_list_widgets[WIDX_TAB_2].top + w->y
);
// Filter description
x = w->x + 6;
y = w->y + window_guest_list_widgets[WIDX_TAB_CONTENT_PANEL].top + 3;
if (_window_guest_list_selected_tab == PAGE_INDIVIDUAL) {
if (_window_guest_list_selected_filter != -1) {
if (RCT2_GLOBAL(0x00F1EDF6, sint16) != -1)
format = STR_GUESTS_FILTER + _window_guest_list_selected_filter;
else
format = STR_GUESTS_FILTER_THINKING_ABOUT;
} else {
format = STR_ALL_GUESTS;
}
} else {
format = STR_ALL_GUESTS_SUMMARISED;
}
gfx_draw_string_left_clipped(dpi, format, 0x00F1EDF6, 0, x, y, 310);
// Number of guests (list items)
if (_window_guest_list_selected_tab == PAGE_INDIVIDUAL) {
x = w->x + 4;
y = w->y + window_guest_list_widgets[WIDX_GUEST_LIST].bottom + 2;
RCT2_GLOBAL(0x013CE952, sint16) = w->var_492;
gfx_draw_string_left(dpi, (w->var_492 == 1 ? 1755 : 1754), 0x013CE952, 0, x, y);
}
}
/**
*
* rct2: 0x00699701
*/
static void window_guest_list_scrollpaint()
{
int eax, ebx, ecx, edx, esi, edi, ebp;
int spriteIdx, format, numGuests, i, j, x, y;
rct_window *w;
rct_drawpixelinfo *dpi;
rct_peep *peep;
rct_peep_thought *thought;
__asm mov w, esi
__asm mov dpi, edi
// Background fill
gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width - 1, dpi->y + dpi->height - 1, ((char*)0x0141FC48)[w->colours[1] * 8]);
switch (_window_guest_list_selected_tab) {
case PAGE_INDIVIDUAL:
i = 0;
y = _window_guest_list_selected_page * -0x7BF2;
// For each guest
spriteIdx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16);
while (spriteIdx != SPRITE_INDEX_NULL) {
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[spriteIdx].peep);
spriteIdx = peep->next;
if (peep->type != PEEP_TYPE_GUEST)
continue;
peep->var_0C &= ~0x200;
if (peep->var_2A != 0)
continue;
if (_window_guest_list_selected_filter != -1) {
if (window_guest_list_is_peep_in_filter(peep))
continue;
RCT2_GLOBAL(0x009AC861, uint16) |= 1;
peep->var_0C |= 0x200;
}
//
if (y + 11 >= -0x7FFF && y + 11 > dpi->y && y < 0x7FFF) {
// Check if y is beyond the scroll control
if (y > dpi->y + dpi->height)
break;
// Highlight backcolour and text colour (format)
format = 1191;
if (i == _window_guest_list_highlighted_index) {
gfx_fill_rect(dpi, 0, y, 800, y + 9, 0x02000031);
format = 1193;
}
// Guest name
RCT2_GLOBAL(0x013CE952, uint16) = peep->name_string_idx;
RCT2_GLOBAL(0x013CE954, uint32) = peep->id;
gfx_draw_string_left_clipped(dpi, format, 0x013CE952, 0, 0, y - 1, 113);
switch (_window_guest_list_selected_view) {
case VIEW_ACTIONS:
// Guest face
gfx_draw_sprite(dpi, get_guest_face_sprite(peep), 118, y);
// Tracking icon
if (peep->flags & PEEP_FLAGS_TRACKING)
gfx_draw_sprite(dpi, 5129, 112, y);
// Action
eax = peep->var_0A;
RCT2_CALLFUNC_X(0x00698B0D, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
ebx &= 0xFFFF;
ecx &= 0xFFFF;
RCT2_GLOBAL(0x013CE952, uint16) = ebx;
RCT2_GLOBAL(0x013CE952 + 2, uint16) = ecx;
RCT2_GLOBAL(0x013CE952 + 4, uint32) = edx;
gfx_draw_string_left_clipped(dpi, format, 0x013CE952, 0, 133, y - 1, 314);
break;
case VIEW_THOUGHTS:
// For each thought
for (j = 0; j < PEEP_MAX_THOUGHTS; j++) {
thought = &peep->thoughts[j];
if (thought->type == PEEP_THOUGHT_TYPE_NONE)
break;
if (thought->pad_3 == 0)
continue;
if (thought->pad_3 > 5)
break;
ebx = thought->type;
eax = thought->item;
RCT2_CALLFUNC_X(0x00698342, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
ebx &= 0xFFFF;
RCT2_GLOBAL(0x013CE952, uint16) = ebx;
RCT2_GLOBAL(0x013CE952 + 2, uint32) = *((uint32*)esi);
RCT2_GLOBAL(0x013CE952 + 6, uint16) = *((uint16*)(esi + 4));
gfx_draw_string_left_clipped(dpi, format, 0x013CE952, 0, 118, y - 1, 329);
break;
}
break;
}
}
// Increment list item index and y
i++;
y += 10;
}
break;
case PAGE_SUMMARISED:
y = 0;
// For each group of guests
for (i = 0; i < _window_guest_list_num_groups; i++) {
// Check if y is beyond the scroll control
if (y + 22 >= dpi->y) {
// Check if y is beyond the scroll control
if (y >= dpi->y + dpi->height)
break;
// Highlight backcolour and text colour (format)
format = 1191;
if (i == _window_guest_list_highlighted_index) {
gfx_fill_rect(dpi, 0, y, 800, y + 20, 0x02000031);
format = 1193;
}
// Draw guest faces
numGuests = _window_guest_list_groups_num_guests[i];
for (j = 0; j < 56 && j < numGuests; j++)
gfx_draw_sprite(dpi, _window_guest_list_groups_guest_faces[numGuests * 56 + j] + 5486, j * 8, y + 9);
// Draw action
RCT2_GLOBAL(0x013CE952, uint16) = _window_guest_list_groups_argument_1[i] & 0xFFFF;
RCT2_GLOBAL(0x013CE952 + 2, uint16) = _window_guest_list_groups_argument_1[i] >> 16;
RCT2_GLOBAL(0x013CE952 + 4, uint32) = _window_guest_list_groups_argument_2[i];
RCT2_GLOBAL(0x013CE952 + 10, uint32) = numGuests;
gfx_draw_string_left_clipped(dpi, format, 0x013CE952, 0, 0, y - 1, 414);
// Draw guest count
RCT2_GLOBAL(0x013CE95A, uint16) = STR_GUESTS_COUNT_COMMA_SEP;
gfx_draw_string_right(dpi, format, 0x0013CE95A, 0, 326, y - 1);
}
y += 21;
}
break;
}
}
/**
*
* rct2: 0x0069B865
*/
static int window_guest_list_is_peep_in_filter(rct_peep* peep)
{
int eax, ebx, ecx, edx, esi, edi, ebp;
char temp;
temp = _window_guest_list_selected_view;
_window_guest_list_selected_view = _window_guest_list_selected_filter;
esi = peep;
RCT2_CALLFUNC_X(0x0069B7EA, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
ebx &= 0xFFFF;
_window_guest_list_selected_view = temp;
eax = (RCT2_GLOBAL(0x013CE952, uint16) << 16) | ebx;
if (((RCT2_GLOBAL(0x00F1EDF6, uint32) >> 16) & 0xFFFF) == 0xFFFF && _window_guest_list_selected_filter == 1)
eax |= 0xFFFF;
if (eax == RCT2_GLOBAL(0x00F1EDF6, uint32) && RCT2_GLOBAL(0x013CE954, uint32) == RCT2_GLOBAL(0x00F1EDFA, uint32))
return 0;
return 1;
}
static int sub_69B7EA(rct_peep *peep, int *outEAX)
{
int eax, ebx, ecx, edx, esi, edi, ebp;
switch (_window_guest_list_selected_view) {
case VIEW_ACTIONS:
eax = peep->var_0A;
RCT2_CALLFUNC_X(0x00698B0D, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
RCT2_GLOBAL(0x013CE952, uint16) = ecx & 0xFFFF;
RCT2_GLOBAL(0x013CE952 + 2, uint32) = edx;
*outEAX = eax;
return ebx & 0xFFFF;
case VIEW_THOUGHTS:
if (peep->thoughts[0].pad_3 <= 5) {
eax = peep->thoughts[0].item;
ebx = peep->thoughts[0].type;
if (peep->thoughts[0].type != PEEP_THOUGHT_TYPE_NONE) {
RCT2_CALLFUNC_X(0x00698342, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
RCT2_GLOBAL(0x013CE952, uint16) = *((uint16*)esi);
RCT2_GLOBAL(0x013CE952 + 2, uint32) = *((uint32*)(esi + 2));
*outEAX = eax;
return ebx & 0xFFFF;
}
}
RCT2_GLOBAL(0x013CE952, uint16) = 0;
RCT2_GLOBAL(0x013CE952 + 2, uint32) = 0;
*outEAX = 0;
return 0;
}
}
/**
*
* rct2: 0x0069B5AE
*/
static void window_guest_list_find_groups()
{
int spriteIdx, spriteIdx2, groupIndex, faceIndex;
rct_peep *peep, *peep2;
int eax = RCT2_GLOBAL(0x00F663AC, uint32) & 0xFFFFFF00;
if (_window_guest_list_selected_view == RCT2_GLOBAL(0x00F1EE02, uint32))
if (RCT2_GLOBAL(0x00F1AF20, uint16) != 0 || eax == RCT2_GLOBAL(0x00F1AF1C, uint32))
return;
RCT2_GLOBAL(0x00F1AF1C, uint32) = eax;
RCT2_GLOBAL(0x00F1EE02, uint32) = _window_guest_list_selected_view;
RCT2_GLOBAL(0x00F1AF20, uint16) = 320;
_window_guest_list_num_groups = 0;
// Set all guests to unassigned
spriteIdx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16);
while (spriteIdx != SPRITE_INDEX_NULL) {
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[spriteIdx].peep);
spriteIdx = peep->next;
if (peep->type != PEEP_TYPE_GUEST || peep->var_2A != 0)
continue;
peep->var_0C |= (1 << 8);
}
// For each guest / group
spriteIdx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16);
while (spriteIdx != SPRITE_INDEX_NULL) {
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[spriteIdx].peep);
spriteIdx = peep->next;
if (peep->type != PEEP_TYPE_GUEST || peep->var_2A != 0 || !(peep->var_0C & (1 << 8)))
continue;
// New group, cap at 240 though
groupIndex = _window_guest_list_num_groups;
if (groupIndex >= 240)
break;
int ax = peep->var_0A;
_window_guest_list_num_groups++;
_window_guest_list_groups_num_guests[groupIndex] = 1;
peep->var_0C &= ~(1 << 8);
int bx = sub_69B7EA(peep, &eax);
eax = (RCT2_GLOBAL(0x013CE952, uint16) << 16) | bx;
RCT2_GLOBAL(0x00F1EDF6, uint32) = eax;
_window_guest_list_groups_argument_1[groupIndex] = eax;
RCT2_GLOBAL(0x00F1EDFA, uint32) = RCT2_GLOBAL(0x013CE952 + 2, uint32);
_window_guest_list_groups_argument_2[groupIndex] = RCT2_GLOBAL(0x013CE952 + 2, uint32);
RCT2_ADDRESS(0x00F1AF26, uint8)[groupIndex] = groupIndex;
faceIndex = groupIndex * 56;
_window_guest_list_groups_guest_faces[faceIndex++] = get_guest_face_sprite(peep) - 5486;
// Find more peeps that belong to same group
spriteIdx2 = peep->next;
while (spriteIdx2 != SPRITE_INDEX_NULL) {
peep2 = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[spriteIdx2].peep);
spriteIdx2 = peep2->next;
if (peep2->type != PEEP_TYPE_GUEST || peep2->var_2A != 0 || !(peep2->var_0C & (1 << 8)))
continue;
// Get and check if in same group
// BUG this doesn't work!
bx = sub_69B7EA(peep2, &eax);
if (bx != RCT2_GLOBAL(0x00F1EDF6, uint32) || (eax & 0xFFFF) != RCT2_GLOBAL(0x013CE952, uint16) || eax != RCT2_GLOBAL(0x013CE952 + 2, uint32))
continue;
// Assign guest
_window_guest_list_groups_num_guests[groupIndex]++;
peep2->var_0C &= ~(1 << 8);
// Add face sprite, cap at 56 though
if (_window_guest_list_groups_num_guests[groupIndex] < 56)
continue;
_window_guest_list_groups_guest_faces[faceIndex++] = get_guest_face_sprite(peep2) - 5486;
}
if (RCT2_GLOBAL(0x00F1EDF6, uint16) == 0) {
_window_guest_list_num_groups--;
continue;
}
ax = _window_guest_list_groups_num_guests[groupIndex];
int edi = 0;
while (1) {
if (edi >= groupIndex)
goto nextPeep;
if (ax > _window_guest_list_groups_num_guests[edi])
break;
edi++;
}
int ecx = _window_guest_list_groups_argument_1[groupIndex];
int edx = _window_guest_list_groups_argument_2[groupIndex];
int bl = RCT2_ADDRESS(0x00F1AF26, uint8)[groupIndex];
int temp;
do {
temp = ax;
ax = _window_guest_list_groups_num_guests[edi];
_window_guest_list_groups_num_guests[edi] = temp;
temp = ecx;
ecx = _window_guest_list_groups_argument_1[edi];
_window_guest_list_groups_argument_1[edi] = temp;
temp = edx;
edx = _window_guest_list_groups_argument_2[edi];
_window_guest_list_groups_argument_2[edi] = temp;
RCT2_ADDRESS(0x00F1AF26, uint8)[edi] = bl;
bl = RCT2_ADDRESS(0x00F1AF26, uint8)[edi];
} while (++edi <= groupIndex);
nextPeep:
;
}
}
/**
*
* rct2: 0x00698721
*/
static int get_guest_face_sprite(rct_peep *peep)
{
int eax, ebx, ecx, edx, esi, edi, ebp;
esi = peep;
ebp = 999;
RCT2_CALLFUNC_X(0x00698721, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
return ebp;
}

387
src/window_news.c Normal file
View File

@ -0,0 +1,387 @@
/*****************************************************************************
* 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 <string.h>
#include "addresses.h"
#include "audio.h"
#include "news_item.h"
#include "strings.h"
#include "sprite.h"
#include "sprites.h"
#include "widget.h"
#include "window.h"
static enum WINDOW_NEWS_WIDGET_IDX {
WIDX_BACKGROUND,
WIDX_TITLE,
WIDX_CLOSE,
WIDX_SCROLL
};
static rct_widget window_news_widgets[] = {
{ WWT_FRAME, 0, 0, 399, 0, 299, 0x0FFFFFFFF, STR_NONE }, // panel / background
{ WWT_CAPTION, 0, 1, 398, 1, 14, STR_RECENT_MESSAGES, STR_WINDOW_TITLE_TIP }, // title bar
{ WWT_CLOSEBOX, 0, 387, 397, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button
{ WWT_SCROLL, 0, 4, 395, 18, 295, 2, STR_NONE }, // scroll
{ WIDGETS_END },
};
static void window_news_emptysub() { }
static void window_news_mouseup();
static void window_news_update();
static void window_news_scrollgetsize();
static void window_news_scrollmousedown();
static void window_news_tooltip();
static void window_news_paint();
static void window_news_scrollpaint();
static uint32 window_news_events[] = {
window_news_emptysub,
window_news_mouseup,
window_news_emptysub,
window_news_emptysub,
window_news_emptysub,
window_news_emptysub,
window_news_update,
window_news_emptysub,
window_news_emptysub,
window_news_emptysub,
window_news_emptysub,
window_news_emptysub,
window_news_emptysub,
window_news_emptysub,
window_news_emptysub,
window_news_scrollgetsize,
window_news_scrollmousedown,
window_news_emptysub,
window_news_emptysub,
window_news_emptysub,
window_news_emptysub,
window_news_emptysub,
window_news_tooltip,
window_news_emptysub,
window_news_emptysub,
window_news_emptysub,
window_news_paint,
window_news_scrollpaint
};
/**
*
* rct2: 0x0066E464
*/
void window_news_open()
{
int x, y;
rct_window* window;
// Check if window is already open
window = window_bring_to_front_by_id(WC_RECENT_NEWS, 0);
if (window == NULL) {
window = window_create_auto_pos(
400,
300,
window_news_events,
WC_RECENT_NEWS,
0
);
window->widgets = window_news_widgets;
window->enabled_widgets = (1 << WIDX_CLOSE);
window_init_scroll_widgets(window);
window->colours[0] = 1;
window->colours[1] = 1;
window->colours[2] = 0;
window->var_480 = -1;
}
// sub_66E4BA:
int width, height;
rct_widget *widget;
window_get_scroll_size(window, 0, &width, &height);
widget = &window_news_widgets[WIDX_SCROLL];
window->scrolls[0].v_top = max(0, height - (widget->bottom - widget->top - 1));
widget_scroll_update_thumbs(window, WIDX_SCROLL);
}
/**
*
* rct2: 0x0066D4D5
*/
static void window_news_mouseup()
{
int i;
short widgetIndex;
rct_window *w;
__asm mov widgetIndex, dx
__asm mov w, esi
if (widgetIndex == WIDX_CLOSE)
window_close(w);
}
/**
*
* rct2: 0x0066EAB8
*/
static void window_news_update()
{
int i, j, x, y, z;
rct_window *w;
rct_news_item *newsItems;
__asm mov w, esi
if (w->var_480 == -1)
return;
if (--w->var_484 != 0)
return;
window_invalidate(w);
sound_play_panned(5, w->x + (w->width / 2));
newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
j = w->var_480;
w->var_480 = -1;
for (i = 11; i < 61; i++) {
if (newsItems[i].type == NEWS_ITEM_NULL)
return;
if (j == 0) {
if (newsItems[i].flags & 1)
return;
if (w->var_482 == 1) {
RCT2_CALLPROC_X(0x0066EBE6, 0, newsItems[i].type, newsItems[i].assoc, 0, 0, 0, 0);
return;
} else if (w->var_482 > 1) {
news_item_get_subject_location(newsItems[i].type, newsItems[i].assoc, &x, &y, &z);
if (x != SPRITE_LOCATION_NULL)
if ((w = window_get_main()) != NULL)
window_scroll_to_location(w, x, y, z);
return;
}
}
j--;
}
}
/**
*
* rct2: 0x0066EA3C
*/
static void window_news_scrollgetsize()
{
int i, height;
rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
height = 0;
for (i = 11; i < 61; i++) {
if (newsItems[i].type == NEWS_ITEM_NULL)
break;
height += 42;
}
__asm mov edx, height
}
/**
*
* rct2: 0x0066EA5C
*/
static void window_news_scrollmousedown()
{
int i, buttonIndex;
short x, y;
rct_window *w;
rct_news_item *newsItems;
__asm mov x, cx
__asm mov y, dx
__asm mov w, esi
buttonIndex = 0;
newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
for (i = 11; i < 61; i++) {
if (newsItems[i].type == NEWS_ITEM_NULL)
break;
if (y < 42) {
if (newsItems[i].flags & 1) {
buttonIndex = 0;
break;
} else if (y < 14) {
buttonIndex = 0;
break;
} else if (y >= 38) {
buttonIndex = 0;
break;
} else if (x < 328) {
buttonIndex = 0;
break;
} else if (x < 351) {
if (RCT2_ADDRESS(0x0097BE7C, uint8)[newsItems[i].type] & 2) {
buttonIndex = 1;
break;
}
} else if (x < 376) {
if (RCT2_ADDRESS(0x0097BE7C, uint8)[newsItems[i].type] & 1) {
buttonIndex = 2;
break;
}
}
}
y -= 42;
}
if (buttonIndex != 0) {
w->var_480 = i - 11;
w->var_482 = buttonIndex;
w->var_484 = 4;
window_invalidate(w);
sound_play_panned(4, w->x + (w->width / 2));
}
}
/**
*
* rct2: 0x0066EAAE
*/
static void window_news_tooltip()
{
RCT2_GLOBAL(0x013CE952, uint16) = 3159;
}
/**
*
* rct2: 0x0066E4E8
*/
static void window_news_paint()
{
int x, y;
rct_window *w;
rct_drawpixelinfo *dpi;
__asm mov w, esi
__asm mov dpi, edi
window_draw_widgets(w, dpi);
}
/**
*
* rct2: 0x0066E4EE
*/
static void window_news_scrollpaint()
{
int i, x, y, yy, press;
rct_window *w;
rct_drawpixelinfo *dpi;
rct_news_item *newsItems, *newsItem, *newsItem2;
__asm mov w, esi
__asm mov dpi, edi
y = 0;
newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
for (i = 11; i < 61; i++) {
newsItem = &newsItems[i];
if (newsItem->type == NEWS_ITEM_NULL)
break;
if (y >= dpi->y + dpi->height)
break;
if (y + 42 < dpi->y) {
y += 42;
continue;
}
// Background
gfx_fill_rect_inset(dpi, -1, y, 383, y + 41, w->colours[1], 0x24);
// Date text
RCT2_GLOBAL(0x013CE952, uint16) = STR_DATE_DAY_1 + newsItem->day - 1;
RCT2_GLOBAL(0x013CE952 + 2, uint16) = STR_MONTH_MARCH + (newsItem->month % 8);
gfx_draw_string_left(dpi, 2235, 0x013CE952, 2, 4, y);
// Item text
RCT2_GLOBAL(0x009B5F2C, uint8) = newsItem->colour;
strcpy(0x009B5F2D, newsItem->text);
gfx_draw_string_left_wrapped(dpi, 0, 2, y + 10, 325, 1926, 14);
// Subject button
if ((RCT2_ADDRESS(0x0097BE7C, uint8)[newsItem->type] & 2) && !(newsItem->flags & 1)) {
x = 328;
yy = y + 14;
press = 0;
if (w->var_480 != -1) {
newsItem2 = &newsItems[11 + w->var_480];
if (newsItem == newsItem2 && w->var_482 == 1)
press = 0x20;
}
gfx_fill_rect_inset(dpi, x, yy, x + 23, yy + 23, w->colours[2], press);
switch (newsItem->type) {
case NEWS_ITEM_RIDE:
gfx_draw_sprite(dpi, SPR_RIDE, x, yy);
break;
case NEWS_ITEM_PEEP_ON_RIDE:
// TODO
break;
case NEWS_ITEM_PEEP:
// TODO
break;
case NEWS_ITEM_MONEY:
gfx_draw_sprite(dpi, SPR_FINANCE, x, yy);
break;
case NEWS_ITEM_SCENERY:
gfx_draw_sprite(dpi, newsItem->assoc < 0x10000 ? SPR_NEW_RIDE : SPR_SCENERY, x, yy);
break;
case NEWS_ITEM_PEEPS:
gfx_draw_sprite(dpi, SPR_GUESTS, x, yy);
break;
case NEWS_ITEM_AWARD:
gfx_draw_sprite(dpi, SPR_AWARD, x, yy);
break;
case NEWS_ITEM_GRAPH:
gfx_draw_sprite(dpi, SPR_GRAPH, x, yy);
break;
}
}
// Location button
if ((RCT2_ADDRESS(0x0097BE7C, uint8)[newsItem->type] & 1) && !(newsItem->flags & 1)) {
x = 352;
yy = y + 14;
press = 0;
if (w->var_480 != -1) {
newsItem2 = &newsItems[11 + w->var_480];
if (newsItem == newsItem2 && w->var_482 == 2)
press = 0x20;
}
gfx_fill_rect_inset(dpi, x, yy, x + 23, yy + 23, w->colours[2], press);
gfx_draw_sprite(dpi, SPR_LOCATE, x, yy);
}
y += 42;
}
}

View File

@ -800,15 +800,15 @@ static void window_park_entrance_toolupdate()
if (widgetIndex == WIDX_BUY_LAND_RIGHTS) {
RCT2_CALLPROC_X(0x0068AAE1, x, y, 0, 0, w, 0, 0);
RCT2_GLOBAL(0x009DE58A, uint16) &= 0xFFFE;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= 0xFFFE;
screen_pos_to_map_pos(&x, &y);
if (x != SPRITE_LOCATION_NULL) {
RCT2_GLOBAL(0x009DE58A, uint16) |= 1;
RCT2_GLOBAL(0x009DE594, uint16) = 4;
RCT2_GLOBAL(0x009DE58C, uint16) = x;
RCT2_GLOBAL(0x009DE58E, uint16) = x;
RCT2_GLOBAL(0x009DE590, uint16) = y;
RCT2_GLOBAL(0x009DE592, uint16) = y;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= 1;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 4;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16) = y;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16) = y;
RCT2_CALLPROC_X(0x0068AAE1, x, y, 0, 0, w, 0, 0);
}
}

View File

@ -497,14 +497,14 @@ static void window_ride_list_scrollpaint()
formatSecondary = STR_POPULARITY_UNKNOWN_LABEL;
if ((ride->var_158 & 0xFF) != 255) {
formatSecondary = STR_POPULARITY_LABEL;
RCT2_GLOBAL(0x013CE952 + 2, uint16) = (ride->var_158 * 4) & 0xFF;
}
RCT2_GLOBAL(0x013CE952 + 2, uint16) = (ride->var_158 & 0xFF) * 4;
}
break;
case INFORMATION_TYPE_SATISFACTION:
formatSecondary = STR_SATISFACTION_UNKNOWN_LABEL;
if ((ride->var_14A & 0xFF) != 255) {
formatSecondary = STR_SATISFACTION_LABEL;
RCT2_GLOBAL(0x013CE952 + 2, uint16) = (ride->var_14A * 5) & 0xFF;
RCT2_GLOBAL(0x013CE952 + 2, uint16) = (ride->var_14A & 0xFF) * 5;
}
break;
case INFORMATION_TYPE_PROFIT:
@ -647,7 +647,7 @@ static void window_ride_list_refresh_list(rct_window *w)
case INFORMATION_TYPE_POPULARITY:
while (--k >= 0) {
otherRide = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[w->var_076[k]]);
if ((ride->var_158 * 4) & 0xFF <= (otherRide->var_158 * 4) & 0xFF)
if ((ride->var_158 & 0xFF) * 4 <= (otherRide->var_158 & 0xFF) * 4)
break;
swapper = w->var_076[k];
@ -658,7 +658,7 @@ static void window_ride_list_refresh_list(rct_window *w)
case INFORMATION_TYPE_SATISFACTION:
while (--k >= 0) {
otherRide = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[w->var_076[k]]);
if ((ride->var_14A * 5) & 0xFF <= (otherRide->var_14A * 5) & 0xFF)
if ((ride->var_14A & 0xFF) * 5 <= (otherRide->var_14A & 0xFF) * 5)
break;
swapper = w->var_076[k];

View File

@ -26,6 +26,7 @@
#include "tutorial.h"
#include "widget.h"
#include "window.h"
#include "audio.h"
static enum WINDOW_SAVE_PROMPT_WIDGET_IDX {
WIDX_BACKGROUND,
@ -118,7 +119,7 @@ void window_save_prompt_open()
// Pause the game
RCT2_GLOBAL(0x009DEA6E, uint8) |= 2;
RCT2_CALLPROC_EBPSAFE(0x006BABB4);
pause_sounds();
window_invalidate_by_id(0x80 | WC_TOP_TOOLBAR, 0);
}
@ -161,7 +162,7 @@ static void window_save_prompt_close()
{
// Unpause the game
RCT2_GLOBAL(0x009DEA6E, uint8) &= ~2;
RCT2_CALLPROC_EBPSAFE(0x006BABD8);
unpause_sounds();
window_invalidate_by_id(0x80 | WC_TOP_TOOLBAR, 0);
}

View File

@ -102,8 +102,8 @@ void window_water_open()
window_init_scroll_widgets(window);
window_push_others_below(window);
RCT2_GLOBAL(0x0141F738, uint32) = 0x80000000;
RCT2_GLOBAL(0x0141F73C, uint32) = 0x80000000;
RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, uint32) = 0x80000000;
RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, uint32) = 0x80000000;
window->colours[0] = 24;
window->colours[1] = 24;
window->colours[2] = 24;
@ -215,12 +215,12 @@ static void window_water_paint()
// Draw raise cost amount
x = (window_water_widgets[WIDX_PREVIEW].left + window_water_widgets[WIDX_PREVIEW].right) / 2 + w->x;
y = window_water_widgets[WIDX_PREVIEW].bottom + w->y + 5;
if (RCT2_GLOBAL(0x0141F738, uint32) != 0x80000000 && RCT2_GLOBAL(0x0141F738, uint32) != 0)
if (RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, uint32) != 0x80000000 && RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, uint32) != 0)
gfx_draw_string_centred(dpi, 984, x, y, 0, (void*)0x0141F738);
y += 10;
// Draw lower cost amount
if (RCT2_GLOBAL(0x0141F73C, uint32) != 0x80000000 && RCT2_GLOBAL(0x0141F73C, uint32) != 0)
if (RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, uint32) != 0x80000000 && RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, uint32) != 0)
gfx_draw_string_centred(dpi, 985, x, y, 0, (void*)0x0141F73C);
}