Merge pull request #2 from IntelOrca/develop

Fast forward
This commit is contained in:
Michael Steenbeek 2015-03-14 16:48:46 +01:00
commit 3e8067d5ff
63 changed files with 2887 additions and 1005 deletions

View File

@ -2716,8 +2716,8 @@ STR_2714 :-
STR_2715 :.
STR_2716 :/
STR_2717 :'
STR_2718 :???
STR_2719 :???
STR_2718 :(één map omhoog)
STR_2719 :(nieuw bestand)
STR_2720 :{UINT16}s
STR_2721 :{UINT16}s
STR_2722 :{UINT16}m {UINT16}s
@ -2747,7 +2747,7 @@ STR_2745 :\
STR_2746 :]
STR_2747 :{ENDQUOTES}
STR_2748 :Bar
STR_2749 :???
STR_2749 :Mijn nieuwe scenario
STR_2750 :Alles naar boven verplaatsen
STR_2751 :Alles naar beneden verplaatsen
STR_2752 :Onkruid weg

View File

@ -3451,3 +3451,7 @@ STR_3443 :Page 4
STR_3444 :Page 5
STR_3445 :Set Patrol Area
STR_3446 :Cancel Patrol Area
# New strings, cleaner
STR_5120 :Show finances button on toolbar
STR_5121 :Show research button on toolbar

View File

@ -200,6 +200,7 @@
<ClInclude Include="..\src\windows\tooltip.h" />
<ClInclude Include="..\src\world\banner.h" />
<ClInclude Include="..\src\world\climate.h" />
<ClInclude Include="..\src\world\entrance.h" />
<ClInclude Include="..\src\world\footpath.h" />
<ClInclude Include="..\src\world\map.h" />
<ClInclude Include="..\src\world\mapgen.h" />
@ -207,6 +208,7 @@
<ClInclude Include="..\src\world\park.h" />
<ClInclude Include="..\src\world\scenery.h" />
<ClInclude Include="..\src\world\sprite.h" />
<ClInclude Include="..\src\world\water.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libs\libs.vcxproj">

View File

@ -342,7 +342,6 @@
<ClCompile Include="..\src\windows\text_input.c">
<Filter>Source\Windows</Filter>
</ClCompile>
<ClCompile Include="..\lib\lodepng\lodepng.c" />
<ClCompile Include="..\src\windows\map_tooltip.c">
<Filter>Source\Windows</Filter>
</ClCompile>
@ -368,7 +367,7 @@
<ClCompile Include="..\src\interface\viewport_interaction.c">
<Filter>Source\Interface</Filter>
</ClCompile>
<ClCompile Include="..\lib\libspeex\resample.c;..\lib\lodepng\lodepng.c" />
<ClCompile Include="..\lib\lodepng\lodepng.c" />
<ClCompile Include="..\src\world\footpath.c">
<Filter>Source\World</Filter>
</ClCompile>
@ -622,5 +621,11 @@
<ClInclude Include="..\src\ride\track_data.h">
<Filter>Source\Ride</Filter>
</ClInclude>
<ClInclude Include="..\src\world\entrance.h">
<Filter>Source\World</Filter>
</ClInclude>
<ClInclude Include="..\src\world\water.h">
<Filter>Source\World</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -126,12 +126,30 @@
#define RCT2_ADDRESS_RUN_INTRO_TICK_PART 0x009AC319
// 0 = none, 255 = load file, 254 = anything else
#define RCT2_ADDRESS_ERROR_TYPE 0x009AC31B
#define RCT2_ADDRESS_ERROR_STRING_ID 0x009AC31C
#define RCT2_ADDRESS_WINDOW_MAP_FLASHING_FLAGS 0x009AC861
#define RCT2_ADDRESS_RIDE_ENTRIES 0x009ACFA4
#define RCT2_ADDRESS_SMALL_SCENERY_ENTRIES 0x009AD1A4
#define RCT2_ADDRESS_LARGE_SCENERY_ENTRIES 0x009AD594
#define RCT2_ADDRESS_WALL_SCENERY_ENTRIES 0x009AD794
#define RCT2_ADDRESS_BANNER_SCENERY_ENTRIES 0x009AD994
#define RCT2_ADDRESS_PATH_TYPES 0x009ADA14
#define RCT2_ADDRESS_PATH_BIT_SCENERY_ENTRIES 0x009ADA54
#define RCT2_ADDRESS_SCENERY_SET_ENTRIES 0x009ADA90
#define RCT2_ADDRESS_INSTALLED_OBJECT_LIST 0x009ADAE8
#define RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST 0x009ADAEC
#define RCT2_ADDRESS_TOTAL_NO_IMAGES 0x009ADAF0
#define RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK 0x009ADAF8
#define RCT2_ADDRESS_CURRENT_SOUND_DEVICE 0x009AF280
@ -217,15 +235,6 @@
#define RCT2_ADDRESS_G1_ELEMENTS 0x009EBD28
#define RCT2_ADDRESS_PATH_TYPES 0x009ADA14
#define RCT2_ADDRESS_SMALL_SCENERY_ENTRIES 0x009AD1A4
#define RCT2_ADDRESS_LARGE_SCENERY_ENTRIES 0x009AD594
#define RCT2_ADDRESS_WALL_SCENERY_ENTRIES 0x009AD794
#define RCT2_ADDRESS_BANNER_SCENERY_ENTRIES 0x009AD994
#define RCT2_ADDRESS_PATH_BIT_SCENERY_ENTRIES 0x009ADA54
#define RCT2_ADDRESS_SCENERY_SET_ENTRIES 0x009ADA90
//Every pixel changed by rain is stored.
//32bit (pixel_offset 24 bit)(pixel_colour 8 bit)
//Use the rainPixels[] global in drawing.c from now on
@ -258,8 +267,14 @@
#define RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS 0x00F42B6C
#define RCT2_ADDRESS_ORIGINAL_RCT2_OBJECT_COUNT 0x00F42B70
#define RCT2_ADDRESS_CURR_OBJECT_BASE_STRING_ID 0x00F42BBC
#define RCT2_ADDRESS_CURR_OBJECT_CHUNK_POINTER 0x00F42BC0
#define RCT2_ADDRESS_SCENARIO_TEXT_TEMP_OBJECT 0x00F42BC8
// 1 if custom objects installed, 0 otherwise
#define RCT2_ADDRESS_CUSTOM_OBJECTS_INSTALLED 0x00F42BDA
#define RCT2_ADDRESS_VOLUME_ADJUST_ZOOM 0x00F438AC
#define RCT2_ADDRESS_STAFF_HIGHLIGHTED_INDEX 0x00F43908

View File

@ -162,6 +162,11 @@ config_property_definition _generalDefinitions[] = {
{ offsetof(general_configuration, window_width), "window_width", CONFIG_VALUE_TYPE_SINT32, -1, NULL },
};
config_property_definition _interfaceDefinitions[] = {
{ offsetof(interface_configuration, toolbar_show_finances), "toolbar_show_finances", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL },
{ offsetof(interface_configuration, toolbar_show_research), "toolbar_show_research", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL },
};
config_property_definition _soundDefinitions[] = {
{ offsetof(sound_configuration, forced_software_buffering), "forced_software_buffering", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL },
{ offsetof(sound_configuration, sound_quality), "sound_quality", CONFIG_VALUE_TYPE_UINT8, 2, NULL },
@ -170,12 +175,14 @@ config_property_definition _soundDefinitions[] = {
config_section_definition _sectionDefinitions[] = {
{ &gConfigGeneral, "general", _generalDefinitions, countof(_generalDefinitions) },
{ &gConfigInterface, "interface", _interfaceDefinitions, countof(_interfaceDefinitions) },
{ &gConfigSound, "sound", _soundDefinitions, countof(_soundDefinitions) }
};
#pragma endregion
general_configuration gConfigGeneral;
interface_configuration gConfigInterface;
sound_configuration gConfigSound;
bool config_open(const utf8string path);
@ -900,4 +907,48 @@ void config_reset_shortcut_keys()
memcpy(gShortcutKeys, _defaultShortcutKeys, sizeof(gShortcutKeys));
}
void config_shortcut_keys_get_path(char *outPath)
{
platform_get_user_directory(outPath, NULL);
strcat(outPath, "hotkeys.cfg");
}
bool config_shortcut_keys_load()
{
char path[MAX_PATH];
FILE *file;
int result;
config_shortcut_keys_get_path(path);
file = fopen(path, "rb");
if (file != NULL) {
result = fread(gShortcutKeys, sizeof(gShortcutKeys), 1, file) == 1;
fclose(file);
} else {
result = false;
}
return result;
}
bool config_shortcut_keys_save()
{
char path[MAX_PATH];
FILE *file;
int result;
config_shortcut_keys_get_path(path);
file = fopen(path, "wb");
if (file != NULL) {
result = fwrite(gShortcutKeys, sizeof(gShortcutKeys), 1, file) == 1;
fclose(file);
} else {
result = false;
}
return result;
}
#pragma endregion

View File

@ -105,7 +105,7 @@ enum {
AUTOSAVE_NEVER
};
typedef struct general_configuration {
typedef struct {
uint8 play_intro;
uint8 confirmation_prompt;
uint8 screenshot_format;
@ -131,18 +131,24 @@ typedef struct general_configuration {
uint8 autosave_frequency;
} general_configuration;
typedef struct sound_configuration {
typedef struct {
uint8 toolbar_show_finances;
uint8 toolbar_show_research;
} interface_configuration;
typedef struct {
sint8 forced_software_buffering;
sint8 sound_quality;
uint8 title_music;
} sound_configuration;
typedef struct shortcut_entry {
typedef struct {
uint8 key;
uint8 modifier;
} shortcut_entry;
extern general_configuration gConfigGeneral;
extern interface_configuration gConfigInterface;
extern sound_configuration gConfigSound;
extern uint16 gShortcutKeys[SHORTCUT_COUNT];
@ -154,6 +160,9 @@ bool config_save_default();
uint16 getLanguage();
void config_reset_shortcut_keys();
bool config_shortcut_keys_load();
bool config_shortcut_keys_save();
bool config_find_or_browse_install_directory();
#endif

View File

@ -24,6 +24,7 @@
#include "../interface/window.h"
#include "../platform/platform.h"
#include "../object.h"
#include "../world/water.h"
#include "drawing.h"
// HACK These were originally passed back through registers
@ -152,12 +153,12 @@ void gfx_transpose_palette(int pal, unsigned char product)
/* rct2: 0x006837E3 */
void load_palette(){
uint8* water_chunk = object_entry_groups[OBJECT_TYPE_WATER].chunks[0];
rct_water_type* water_type = (rct_water_type*)object_entry_groups[OBJECT_TYPE_WATER].chunks[0];
uint32 palette = 0x5FC;
if (water_chunk != (uint8*)-1){
palette = *((uint32*)(water_chunk + 2));
if ((sint32)water_type != -1){
palette = water_type->image_id;
}
rct_g1_element g1 = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[palette];

View File

@ -31,8 +31,7 @@ typedef struct {
short width; // 0x08
short height; // 0x0A
short pitch; // 0x0C note: this is actually (pitch - width)
uint8 zoom_level; // 0x0E
char var_0F; // 0x0F
uint16 zoom_level; // 0x0E
} rct_drawpixelinfo;
// Size: 0x10

View File

@ -80,7 +80,7 @@ int gfx_load_g1()
* rct2: 0x0067A690
*/
void gfx_bmp_sprite_to_buffer(uint8* palette_pointer, uint8* unknown_pointer, uint8* source_pointer, uint8* dest_pointer, rct_g1_element* source_image, rct_drawpixelinfo *dest_dpi, int height, int width, int image_type){
uint8 zoom_level = dest_dpi->zoom_level;
uint16 zoom_level = dest_dpi->zoom_level;
uint8 zoom_amount = 1 << zoom_level;
//Requires use of palette?
if (image_type & IMAGE_TYPE_USE_PALETTE){

View File

@ -152,13 +152,15 @@ void editor_convert_save_to_scenario()
s6Info->objective_arg_3 = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_NUM_GUESTS, sint16);
climate_reset(RCT2_GLOBAL(RCT2_ADDRESS_CLIMATE, uint8));
if (RCT2_GLOBAL(0x009ADAE4, uint32) != 0xFFFFFFFF) {
object_unload(0, (rct_object_entry_extended*)0x00F4287C);
RCT2_CALLPROC_EBPSAFE(0x006A9FC0);
rct_stex_entry* stex = g_stexEntries[0];
if ((int)stex != 0xFFFFFFFF) {
object_unload(0, &object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].entries[0]);
//RCT2_CALLPROC_EBPSAFE(0x006A9FC0);
reset_loaded_objects();
format_string(s6Info->details, STR_NO_DETAILS_YET, NULL);
s6Info->name[0] = 0;
}
}
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_SCENARIO_EDITOR;
s6Info->var_000 = 4;
@ -462,7 +464,7 @@ static void sub_6A2B62()
object_unload_all();
RCT2_CALLPROC_EBPSAFE(0x0069F53D);
RCT2_CALLPROC_EBPSAFE(0x006A9FC0);
reset_loaded_objects();
RCT2_CALLPROC_EBPSAFE(0x006A2730);
RCT2_CALLPROC_EBPSAFE(0x006A2956);
RCT2_CALLPROC_EBPSAFE(0x006A29B9);
@ -505,7 +507,7 @@ static void sub_6A2B62()
RCT2_GLOBAL(RCT2_ADDRESS_INITIAL_CASH, money32)
);
RCT2_CALLPROC_EBPSAFE(0x0069E89B);
RCT2_CALLPROC_EBPSAFE(0x0069E869);
sub_69E869();//RCT2_CALLPROC_EBPSAFE(0x0069E869);
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, money32) = clamp(
MONEY(0,00),
@ -586,8 +588,8 @@ static int editor_load_landscape_from_sv4(const char *path)
// Open file
fp = fopen(path, "rb");
if (fp == NULL) {
RCT2_GLOBAL(0x009AC31B, uint8) = 255;
RCT2_GLOBAL(0x009AC31C, uint16) = 3011;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = 3011;
return 0;
}
@ -613,8 +615,8 @@ static int editor_load_landscape_from_sc4(const char *path)
// Open file
fp = fopen(path, "rb");
if (fp == NULL) {
RCT2_GLOBAL(0x009AC31B, uint8) = 255;
RCT2_GLOBAL(0x009AC31C, uint16) = 3011;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = 3011;
return 0;
}
@ -757,8 +759,8 @@ static int editor_read_s6(const char *path)
if (file != NULL) {
if (!sawyercoding_validate_checksum(file)) {
fclose(file);
RCT2_GLOBAL(0x009AC31B, uint8) = 255;
RCT2_GLOBAL(0x009AC31C, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
log_error("failed to load scenario, invalid checksum");
return 0;
@ -834,7 +836,7 @@ static int editor_read_s6(const char *path)
// Check expansion pack
// RCT2_CALLPROC_EBPSAFE(0x006757E6);
RCT2_CALLPROC_EBPSAFE(0x006A9FC0);
reset_loaded_objects();//RCT2_CALLPROC_EBPSAFE(0x006A9FC0);
map_update_tile_pointers();
map_remove_all_rides();
@ -910,9 +912,10 @@ static int editor_read_s6(const char *path)
climate_reset(RCT2_GLOBAL(RCT2_ADDRESS_CLIMATE, uint8));
if (RCT2_GLOBAL(0x009ADAE4, uint32) != 0xFFFFFFFF) {
object_unload(0, (rct_object_entry_extended*)0x00F4287C);
RCT2_CALLPROC_EBPSAFE(0x006A9FC0);
rct_stex_entry* stex = g_stexEntries[0];
if ((int)stex != 0xFFFFFFFF) {
object_unload(0, &object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].entries[0]);
reset_loaded_objects();//RCT2_CALLPROC_EBPSAFE(0x006A9FC0);
format_string(s6Info->details, STR_NO_DETAILS_YET, NULL);
s6Info->name[0] = 0;
@ -931,18 +934,18 @@ static int editor_read_s6(const char *path)
w->saved_view_x = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_X, sint16);
w->saved_view_y = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_Y, sint16);
int zoom_difference = (RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION, sint16) & 0xFF) - viewport->zoom;
viewport->zoom = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION, uint16) & 0xFF;
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION, uint16) >> 8;
int cx = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION, sint16) - viewport->zoom;
if (cx != 0) {
if (cx >= 0) {
viewport->view_width <<= cx;
viewport->view_height <<= cx;
if (zoom_difference != 0) {
if (zoom_difference >= 0) {
viewport->view_width <<= zoom_difference;
viewport->view_height <<= zoom_difference;
} else {
cx = -cx;
viewport->view_width >>= cx;
viewport->view_height >>= cx;
zoom_difference = -zoom_difference;
viewport->view_width >>= zoom_difference;
viewport->view_height >>= zoom_difference;
}
}
w->saved_view_x -= viewport->view_width >> 1;
@ -960,8 +963,8 @@ static int editor_read_s6(const char *path)
}
log_error("failed to find scenario file.");
RCT2_GLOBAL(0x009AC31B, uint8) = 255;
RCT2_GLOBAL(0x009AC31C, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
return 0;
}

View File

@ -51,6 +51,7 @@
#include "world/climate.h"
#include "world/park.h"
#include "world/sprite.h"
#include "world/water.h"
int gGameSpeed = 1;
@ -82,11 +83,14 @@ void game_create_windows()
*/
void update_palette_effects()
{
rct_water_type* water_type = (rct_water_type*)object_entry_groups[OBJECT_TYPE_WATER].chunks[0];
if (RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint8) == 1) {
// change palette to lighter color during lightning
int palette = 1532;
if (RCT2_GLOBAL(0x009ADAE0, sint32) != -1) {
palette = RCT2_GLOBAL(RCT2_GLOBAL(0x009ADAE0, int) + 2, int);
if ((sint32)water_type != -1) {
palette = water_type->image_id;
}
rct_g1_element g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[palette];
int xoffset = g1_element.x_offset;
@ -104,9 +108,11 @@ void update_palette_effects()
if (RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint8) == 2) {
// change palette back to normal after lightning
int palette = 1532;
if (RCT2_GLOBAL(0x009ADAE0, sint32) != -1) {
palette = RCT2_GLOBAL(RCT2_GLOBAL(0x009ADAE0, int) + 2, int);
if ((sint32)water_type != -1) {
palette = water_type->image_id;
}
rct_g1_element g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[palette];
int xoffset = g1_element.x_offset;
xoffset = xoffset * 4;
@ -129,8 +135,8 @@ void update_palette_effects()
uint32 j = RCT2_GLOBAL(RCT2_ADDRESS_PALETTE_EFFECT_FRAME_NO, uint32);
j = (((uint16)((~j / 2) * 128) * 15) >> 16);
int p = 1533;
if (RCT2_GLOBAL(0x009ADAE0, int) != -1) {
p = RCT2_GLOBAL(RCT2_GLOBAL(0x009ADAE0, int) + 0x6, int);
if ((sint32)water_type != -1) {
p = water_type->var_06;
}
rct_g1_element g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[q + p];
uint8* vs = &g1_element.offset[j * 3];
@ -148,8 +154,8 @@ void update_palette_effects()
}
p = 1536;
if (RCT2_GLOBAL(0x009ADAE0, int) != -1) {
p = RCT2_GLOBAL(RCT2_GLOBAL(0x009ADAE0, int) + 0xA, int);
if ((sint32)water_type != -1) {
p = water_type->var_0A;
}
g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[q + p];
vs = &g1_element.offset[j * 3];
@ -292,8 +298,6 @@ void game_update()
void game_logic_update()
{
short stringId, _dx;
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, sint32)++;
RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, sint32)++;
RCT2_GLOBAL(0x009DEA66, sint16)++;
@ -323,16 +327,16 @@ void game_logic_update()
// Update windows
window_dispatch_update_all();
if (RCT2_GLOBAL(0x009AC31B, uint8) != 0) {
stringId = STR_UNABLE_TO_LOAD_FILE;
_dx = RCT2_GLOBAL(0x009AC31C, uint16);
if (RCT2_GLOBAL(0x009AC31B, uint8) != 254) {
stringId = RCT2_GLOBAL(0x009AC31C, uint16);
_dx = 0xFFFF;
if (RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) != 0) {
rct_string_id title_text = STR_UNABLE_TO_LOAD_FILE;
rct_string_id body_text = RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16);
if (RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) == 254) {
title_text = RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16);
body_text = 0xFFFF;
}
RCT2_GLOBAL(0x009AC31B, uint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 0;
window_error_open(stringId, _dx);
window_error_open(title_text, body_text);
}
}
@ -595,7 +599,7 @@ int game_load_save(const char *path)
if (file == NULL) {
log_error("unable to open %s", path);
RCT2_GLOBAL(0x009AC31B, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
return 0;
}
@ -605,7 +609,7 @@ int game_load_save(const char *path)
log_error("invalid checksum, %s", path);
RCT2_GLOBAL(0x009AC31B, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
return 0;
}
@ -657,7 +661,7 @@ int game_load_save(const char *path)
}
// The rest is the same as in scenario load and play
RCT2_CALLPROC_EBPSAFE(0x006A9FC0);
reset_loaded_objects();
map_update_tile_pointers();
reset_0x69EBE4();// RCT2_CALLPROC_EBPSAFE(0x0069EBE4);
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_PLAYING;
@ -805,6 +809,26 @@ void game_autosave()
scenario_save(path, 0x80000000);
}
/**
*
* rct2: 0x006E3838
*/
void rct2_exit_reason(rct_string_id title, rct_string_id body){
// Before this would set a quit message
char exit_title[255];
format_string(exit_title, title, 0);
char exit_body[255];
format_string(exit_body, body, 0);
log_error(exit_title);
log_error(exit_body);
rct2_exit();
}
/**
*
* rct2: 0x006E3879

View File

@ -21,6 +21,8 @@
#ifndef _GAME_H_
#define _GAME_H_
#include "common.h"
enum GAME_COMMAND {
GAME_COMMAND_0,
GAME_COMMAND_1,
@ -109,6 +111,7 @@ int game_load_save(const char *path);
void game_pause_toggle(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
char save_game();
void rct2_exit();
void rct2_exit_reason(rct_string_id title, rct_string_id body);
void game_autosave();
#endif

View File

@ -97,8 +97,8 @@ void game_handle_input()
if (RCT2_GLOBAL(0x009DEA64, uint16) & 2) {
RCT2_GLOBAL(0x009DEA64, uint16) &= ~2;
game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 2, 0);
}
game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 2, 0);
}
if (RCT2_GLOBAL(0x009ABDF2, uint8) != 0) {
for (w = g_window_list; w < RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); w++)
@ -113,19 +113,20 @@ void game_handle_input()
break;
game_handle_input_mouse(x, y, state & 0xFF);
}
}
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_5) {
game_handle_input_mouse(x, y, state);
} else if (x != 0x80000000) {
}
else if (x != 0x80000000) {
x = clamp(0, x, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) - 1);
y = clamp(0, y, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16) - 1);
game_handle_input_mouse(x, y, state);
process_mouse_over(x, y);
process_mouse_tool(x, y);
}
}
}
}
for (w = g_window_list; w < RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); w++)
RCT2_CALLPROC_X(w->event_handlers[WE_UNKNOWN_08], 0, 0, 0, 0,(int) w, 0, 0);
@ -143,7 +144,7 @@ static void game_get_next_input(int *x, int *y, int *state)
*y = gCursorState.y;
*state = 0;
return;
}
}
*x = eax->x;
*y = eax->y;
@ -186,7 +187,7 @@ static rct_mouse_data* get_mouse_input()
RCT2_GLOBAL(RCT2_ADDRESS_MOUSE_READ_INDEX, uint32) = (read_index + 1) % 64;
return &mouse_buffer[read_index];
}
}
/**
*
@ -217,17 +218,18 @@ static void game_handle_input_mouse(int x, int y, int state)
break;
case 3:
window_close_by_class(WC_TOOLTIP);
if (w != NULL)
w = window_bring_to_front(w);
if (widgetIndex == -1)
break;
if (widget->type == WWT_VIEWPORT) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_TRACK_MANAGER | SCREEN_FLAGS_TITLE_DEMO)))
input_viewport_drag_begin(w, x, y);
} else if (widget->type == WWT_SCROLL) {
}
else if (widget->type == WWT_SCROLL) {
}
break;
@ -241,7 +243,8 @@ static void game_handle_input_mouse(int x, int y, int state)
w = window_find_by_number(_dragWindowClass, _dragWindowNumber);
if (w == NULL) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
} else {
}
else {
input_window_position_continue(w, _dragX, _dragY, x, y);
if (state == 2)
input_window_position_end(w, x, y);
@ -250,12 +253,13 @@ static void game_handle_input_mouse(int x, int y, int state)
case INPUT_STATE_VIEWPORT_RIGHT:
if (state == 0) {
input_viewport_drag_continue();
} else if (state == 4) {
}
else if (state == 4) {
input_viewport_drag_end();
if (RCT2_GLOBAL(0x009DE540, sint16) < 500) {
viewport_interaction_right_click(x, y);
}
}
}
}
break;
case INPUT_STATE_DROPDOWN_ACTIVE:
input_state_widget_pressed(x, y, state, widgetIndex, w, widget);
@ -265,7 +269,7 @@ static void game_handle_input_mouse(int x, int y, int state)
w = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass),
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber)
);
);
if (!w){
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0;
break;
@ -280,25 +284,25 @@ static void game_handle_input_mouse(int x, int y, int state)
if (w->classification != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) ||
w->number != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) ||
!(RCT2_GLOBAL(0x9DE518, uint32)&(1 << 3)))break;
w = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass),
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)
);
);
if (w == NULL)
break;
RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_DRAG], x, y, 0, (int)RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), (int)w, 0, 0);
}
else if (state == 2){
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0;
if (RCT2_GLOBAL(0x9DE52E, rct_windownumber) != w->number)break;
if ((RCT2_GLOBAL(0x9DE518, uint32)&(1 << 3))){
w = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass),
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)
);
);
if (w == NULL)
break;
RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_UP], x, y, 0, (int)RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), (int)w, 0, 0);
@ -306,10 +310,10 @@ static void game_handle_input_mouse(int x, int y, int state)
else{
if ((RCT2_GLOBAL(0x9DE518, uint32) & (1 << 4)))
break;
viewport_interaction_left_click(x, y);
}
}
}
}
break;
case INPUT_STATE_SCROLL_LEFT:
if (state == 0)
@ -321,18 +325,19 @@ static void game_handle_input_mouse(int x, int y, int state)
w = window_find_by_number(_dragWindowClass, _dragWindowNumber);
if (w == NULL) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
} else {
}
else {
if (state == 2)
input_window_resize_end();
if (state == 0 || state == 2)
input_window_resize_continue(w, x, y);
}
}
break;
case 9:
RCT2_CALLPROC_X(0x006E8ACB, x, y, state, widgetIndex, (int)w, (int)widget, 0);
break;
}
}
}
#pragma region Window positioning / resizing
@ -345,7 +350,7 @@ void input_window_position_begin(rct_window *w, int widgetIndex, int x, int y)
_dragWindowClass = w->classification;
_dragWindowNumber = w->number;
_dragWidgetIndex = widgetIndex;
}
}
static void input_window_position_continue(rct_window *w, int wdx, int wdy, int x, int y)
{
@ -353,7 +358,7 @@ static void input_window_position_continue(rct_window *w, int wdx, int wdy, int
snapProximity = w->flags & WF_NO_SNAPPING ? 0 : gConfigGeneral.window_snap_proximity;
window_move_and_snap(w, x - wdx, y - wdy, snapProximity);
}
}
static void input_window_position_end(rct_window *w, int x, int y)
{
@ -363,7 +368,7 @@ static void input_window_position_end(rct_window *w, int x, int y)
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = _dragWindowNumber;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = _dragWidgetIndex;
RCT2_CALLPROC_X(w->event_handlers[WE_MOVED], 0, 0, x, y, (int)w, 0, 0);
}
}
static void input_window_resize_begin(rct_window *w, int widgetIndex, int x, int y)
{
@ -375,7 +380,7 @@ static void input_window_resize_begin(rct_window *w, int widgetIndex, int x, int
_dragWidgetIndex = widgetIndex;
_originalWindowWidth = w->width;
_originalWindowHeight = w->height;
}
}
static void input_window_resize_continue(rct_window *w, int x, int y)
{
@ -391,9 +396,9 @@ static void input_window_resize_continue(rct_window *w, int x, int y)
w,
targetWidth - w->width,
targetHeight - w->height
);
}
}
);
}
}
static void input_window_resize_end()
{
@ -536,77 +541,77 @@ static void input_scroll_continue(rct_window *w, int widgetIndex, int state, int
rct_widget *widget;
widget = &w->widgets[widgetIndex];
if (widgetIndex != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint32)){
invalidate_scroll();
return;
}
if (w->classification != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8)){
invalidate_scroll();
return;
}
if (w->number != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, uint16)){
invalidate_scroll();
return;
}
if (widgetIndex != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint32)){
invalidate_scroll();
return;
}
if (w->classification != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8)){
invalidate_scroll();
return;
}
if (w->number != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, uint16)){
invalidate_scroll();
return;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) == SCROLL_PART_HSCROLLBAR_THUMB){
int temp_x = x;
x -= RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16);
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = temp_x;
RCT2_CALLPROC_X(0x006E98F2, x, temp_x, state, w->number, (int)w, (int)widget, x);
return;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) == SCROLL_PART_HSCROLLBAR_THUMB){
int temp_x = x;
x -= RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16);
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = temp_x;
RCT2_CALLPROC_X(0x006E98F2, x, temp_x, state, w->number, (int)w, (int)widget, x);
return;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) == SCROLL_PART_VSCROLLBAR_THUMB){
int temp_y = y;
y -= RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16);
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = temp_y;
RCT2_CALLPROC_X(0x006E99A9, temp_y, y, state, w->number, (int)w, (int)widget, y);
return;
}
int scroll_part, scroll_id;
widget_scroll_get_part(w, widget, x, y, &x, &y, &scroll_part, &scroll_id);
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) == SCROLL_PART_VSCROLLBAR_THUMB){
int temp_y = y;
y -= RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16);
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = temp_y;
RCT2_CALLPROC_X(0x006E99A9, temp_y, y, state, w->number, (int)w, (int)widget, y);
return;
}
int scroll_part, scroll_id;
widget_scroll_get_part(w, widget, x, y, &x, &y, &scroll_part, &scroll_id);
if (scroll_part != RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16)){
invalidate_scroll();
return;
}
if (scroll_part != RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16)){
invalidate_scroll();
return;
}
switch (scroll_part){
case SCROLL_PART_VIEW:
RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_DRAG], w->number / 18, y, x, y, (int)w, (int)widget, (int)w->event_handlers);
break;
case SCROLL_PART_HSCROLLBAR_LEFT:
RCT2_CALLPROC_X(0x006E9A60, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
break;
case SCROLL_PART_HSCROLLBAR_RIGHT:
RCT2_CALLPROC_X(0x006E9ABF, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
break;
case SCROLL_PART_HSCROLLBAR_LEFT_TROUGH:
case SCROLL_PART_HSCROLLBAR_RIGHT_TROUGH:
return;
break;
case SCROLL_PART_HSCROLLBAR_THUMB:
case SCROLL_PART_VSCROLLBAR_TOP:
RCT2_CALLPROC_X(0x006E9C37, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
break;
case SCROLL_PART_VSCROLLBAR_BOTTOM:
RCT2_CALLPROC_X(0x006E9C96, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
break;
case SCROLL_PART_VSCROLLBAR_TOP_TROUGH:
case SCROLL_PART_VSCROLLBAR_BOTTOM_TROUGH:
return;
break;
default:
return;
}
}
switch (scroll_part){
case SCROLL_PART_VIEW:
RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_DRAG], w->number / 18, y, x, y, (int)w, (int)widget, (int)w->event_handlers);
break;
case SCROLL_PART_HSCROLLBAR_LEFT:
RCT2_CALLPROC_X(0x006E9A60, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
break;
case SCROLL_PART_HSCROLLBAR_RIGHT:
RCT2_CALLPROC_X(0x006E9ABF, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
break;
case SCROLL_PART_HSCROLLBAR_LEFT_TROUGH:
case SCROLL_PART_HSCROLLBAR_RIGHT_TROUGH:
return;
break;
case SCROLL_PART_HSCROLLBAR_THUMB:
case SCROLL_PART_VSCROLLBAR_TOP:
RCT2_CALLPROC_X(0x006E9C37, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
break;
case SCROLL_PART_VSCROLLBAR_BOTTOM:
RCT2_CALLPROC_X(0x006E9C96, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
break;
case SCROLL_PART_VSCROLLBAR_TOP_TROUGH:
case SCROLL_PART_VSCROLLBAR_BOTTOM_TROUGH:
return;
break;
default:
return;
}
}
static void input_scroll_end()
{
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
invalidate_scroll();
}
}
#pragma endregion
@ -633,14 +638,15 @@ static void input_widget_over(int x, int y, rct_window *w, int widgetIndex)
if (w != NULL && widgetIndex != -1 && widget->type == WWT_SCROLL) {
int eax, ebx, ecx, edx;
widget_scroll_get_part(w, widget, x, y, &eax, &ebx, &ecx, &edx);
if (ecx < 0)
input_update_tooltip(w, widgetIndex, x, y);
else if (ecx == 0) {
RCT2_CALLPROC_X(w->event_handlers[WE_SCROLL_MOUSEOVER], edx, 0, eax, ebx, (int)w, 0, 0);
input_update_tooltip(w, widgetIndex, x, y);
}
} else {
}
}
else {
input_update_tooltip(w, widgetIndex, x, y);
}
@ -664,7 +670,7 @@ static void input_widget_over_change_check(rct_windowclass windowClass, rct_wind
windowClass != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) ||
windowNumber != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber) ||
widgetIndex != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, uint16)
) {
) {
// Invalidate last widget cursor was on if widget is a flat button
input_widget_over_flatbutton_invalidate();
@ -688,7 +694,7 @@ static void input_widget_over_flatbutton_invalidate()
rct_window *w = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass),
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber)
);
);
if (w == NULL)
return;
@ -698,7 +704,7 @@ static void input_widget_over_flatbutton_invalidate()
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass),
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber),
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, rct_windownumber)
);
);
}
}
@ -715,7 +721,7 @@ static void input_widget_left(int x, int y, rct_window *w, int widgetIndex)
if (w != NULL) {
windowClass = w->classification;
windowNumber = w->number;
}
}
window_close_by_class(WC_ERROR);
window_close_by_class(WC_TOOLTIP);
@ -747,7 +753,7 @@ static void input_widget_left(int x, int y, rct_window *w, int widgetIndex)
w = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass),
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)
);
);
if (w != NULL) {
RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_DOWN], x, y, 0, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), (int)w, 0, 0);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_4;
@ -774,7 +780,7 @@ static void input_widget_left(int x, int y, rct_window *w, int widgetIndex)
widget_invalidate_by_number(windowClass, windowNumber, widgetIndex);
window_event_mouse_down_call(w, widgetIndex);
}
}
break;
}
}
@ -798,60 +804,58 @@ void process_mouse_over(int x, int y)
RCT2_GLOBAL(0x9A9808, sint16) = -1;
window = window_find_from_point(x, y);
if (window != NULL) {
if (window != NULL) {
widgetId = window_find_widget_from_point(window, x, y);
RCT2_GLOBAL(0x1420046, sint16) = (widgetId & 0xFFFF);
if (widgetId != -1) {
switch (window->widgets[widgetId].type){
case WWT_VIEWPORT:
if ((RCT2_GLOBAL(0x9DE518, int) & 0x8) == 0) {
if (viewport_interaction_left_over(x, y)) {
sub_6ED990(CURSOR_HAND_POINT);
return;
}
break;
}
}
break;
}
cursorId = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8);
subWindow = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass),
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)
);
);
ebp = (int)subWindow;
if (subWindow == NULL)
{
break;
}
break;
ebx = ebx & 0xFFFFFF00;
edi = cursorId;
esi = (int) subWindow;
esi = (int)subWindow;
RCT2_CALLFUNC_X(subWindow->event_handlers[WE_UNKNOWN_0E], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
cursorId = edi;
if ((ebx & 0xFF) != 0)
{
sub_6ED990(cursorId);
return;
}
break;
}
break;
case WWT_FRAME:
case WWT_RESIZE:
if (!(window->flags & 0x100))
{
break;
}
break;
if (window->min_width == window->max_width && window->min_height == window->max_height)
{
break;
}
break;
if (x < window->x + window->width - 0x13)
{
break;
}
break;
if (y < window->y + window->height - 0x13)
{
break;
}
break;
cursorId = CURSOR_DIAGONAL_ARROWS;
break;
break;
case WWT_SCROLL:
RCT2_GLOBAL(0x9DE558, uint16) = x;
RCT2_GLOBAL(0x9DE55A, uint16) = y;
@ -861,8 +865,8 @@ void process_mouse_over(int x, int y)
if (output_scroll_area != SCROLL_PART_VIEW)
{
cursorId = CURSOR_ARROW;
break;
}
break;
}
//Fall through to default
default:
ecx = x;
@ -875,17 +879,17 @@ void process_mouse_over(int x, int y)
RCT2_CALLFUNC_X(window->event_handlers[WE_CURSOR], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
if (ebx == 0xFFFFFFFF) {
cursorId = CURSOR_ARROW;
break;
}
cursorId = ebx;
break;
}
break;
}
cursorId = ebx;
break;
}
}
}
viewport_interaction_right_over(x, y);
sub_6ED990(cursorId);
}
}
/**
*
@ -898,15 +902,15 @@ void process_mouse_tool(int x, int y)
rct_window* w = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8),
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, uint16)
);
);
if (!w)
tool_cancel();
else
RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_UPDATE], x, y, 0, RCT2_GLOBAL(0x9DE546, uint16), (int)w, 0, 0);
}
}
}
}
/**
*
@ -932,7 +936,7 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
switch (state){
case 0:
if (!w || cursor_w_class != w->classification || cursor_w_number != w->number || widgetIndex != cursor_widgetIndex)
break;
break;
if (w->disabled_widgets & (1ULL << widgetIndex))
break;
@ -943,7 +947,7 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
if (w->hold_down_widgets & (1ULL << widgetIndex) &&
RCT2_GLOBAL(0x009DE528, uint16) >= 16 &&
!(RCT2_GLOBAL(0x009DE528, uint16) & 3)
) {
) {
window_event_mouse_down_call(w, widgetIndex);
}
@ -967,7 +971,8 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
// gDropdownItemsFormat[dropdown_index] will not work until all windows that use dropdown decompiled
if (RCT2_ADDRESS(0x9DEBA4, uint16)[dropdown_index] == 0)goto dropdown_cleanup;
} else {
}
else {
if (cursor_w_class != w->classification || cursor_w_number != w->number || widgetIndex != cursor_widgetIndex)
goto dropdown_cleanup;
dropdown_index = -1;
@ -1003,24 +1008,24 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = cursor_widgetIndex;
if (!w)
break;
break;
if (!widget)
break;
break;
int mid_point_x = (widget->left + widget->right) / 2 + w->x;
sound_play_panned(5, mid_point_x, 0, 0, 0);
if (cursor_w_class != w->classification || cursor_w_number != w->number || widgetIndex != cursor_widgetIndex)
break;
break;
if (w->disabled_widgets & (1ULL << widgetIndex))
break;
break;
widget_invalidate_by_number(cursor_w_class, cursor_w_number, widgetIndex);
window_event_mouse_up_call(w, widgetIndex);
default:
return;
}
}
RCT2_GLOBAL(0x9DE528, uint16) = 0;
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) != 5){
@ -1028,9 +1033,9 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
if (RCT2_GLOBAL(0x9DE518, uint32) & 1){
RCT2_GLOBAL(0x9DE518, uint32) &= 0xFFFE;
widget_invalidate_by_number(cursor_w_class, cursor_w_number, cursor_widgetIndex);
}
return;
}
return;
}
if (!w) return;
@ -1057,7 +1062,7 @@ static void input_update_tooltip(rct_window *w, int widgetIndex, int x, int y)
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, uint16) < 500 ||
(RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, sint16) == x &&
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, sint16) == y)
) {
) {
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = RCT2_GLOBAL(0x009DE588, uint16);
int bp = 2000;
@ -1068,12 +1073,13 @@ static void input_update_tooltip(rct_window *w, int widgetIndex, int x, int y)
window_tooltip_open(w, widgetIndex, x, y);
// RCT2_CALLPROC_X(0x006EA10D, x, y, 0, widgetIndex, w, widget, 0); // window_tooltip_open();
}
} else {
}
}
else {
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) != w->classification ||
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) != w->number ||
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) != widgetIndex
) {
) {
window_tooltip_close();
}
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) += RCT2_GLOBAL(0x009DE588, uint16);
@ -1095,6 +1101,7 @@ static void input_update_tooltip(rct_window *w, int widgetIndex, int x, int y)
*/
void title_handle_keyboard_input()
{
rct_window *w;
int key;
// Handle modifier keys and key scrolling
@ -1114,7 +1121,11 @@ void title_handle_keyboard_input()
key |= RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) << 8;
if (key == gShortcutKeys[SHORTCUT_SCREENSHOT]) {
w = window_find_by_class(WC_CHANGE_KEYBOARD_SHORTCUT);
if (w != NULL) {
keyboard_shortcut_set(key);
}
else if (key == gShortcutKeys[SHORTCUT_SCREENSHOT]) {
keyboard_shortcut_handle_command(SHORTCUT_SCREENSHOT);
}
}
@ -1158,16 +1169,18 @@ void game_handle_keyboard_input()
key |= RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) << 8;
w = window_find_by_class(WC_CHANGE_KEYBOARD_SHORTCUT);
if (w != NULL)
if (w != NULL) {
keyboard_shortcut_set(key);
else if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 1)
}
else if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 1) {
tutorial_stop();
else{
}
else {
w = window_find_by_class(WC_TEXTINPUT);
if (w != NULL){
((void(*)(int, rct_window*))w->event_handlers[WE_TEXT_INPUT])(key,w);
((void(*)(int, rct_window*))w->event_handlers[WE_TEXT_INPUT])(key, w);
}
else{
else {
keyboard_shortcut_handle(key);
}
}
@ -1189,7 +1202,8 @@ void game_handle_keyboard_input()
RCT2_GLOBAL(0x009DEA72, uint16)++;
}
}
} else {
}
else {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 4)) {
window_tooltip_close();
if ((w = window_get_main()) != NULL) {
@ -1208,13 +1222,13 @@ void game_handle_keyboard_input()
* rct2: 0x00406CD2
*/
int get_next_key()
{
{
int i;
for (i = 0; i < 221; i++) {
if (gKeysPressed[i]) {
gKeysPressed[i] = 0;
return i;
}
}
}
return 0;
@ -1253,7 +1267,7 @@ void invalidate_scroll()
rct_window* wind = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8),
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, uint16)
);
);
if (wind == NULL) return;
int scroll_id = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
@ -1263,7 +1277,7 @@ void invalidate_scroll()
window_invalidate_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8),
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, uint16)
);
);
}
/**
@ -1299,6 +1313,10 @@ void game_handle_edge_scroll()
if (mainWindow->viewport == NULL)
return;
uint32 window_flags = SDL_GetWindowFlags(gWindow);
if ((window_flags & SDL_WINDOW_INPUT_FOCUS) == 0)
return;
scrollX = 0;
scrollY = 0;

View File

@ -50,7 +50,7 @@ void keyboard_shortcut_set(int key)
gShortcutKeys[RCT2_GLOBAL(0x009DE511, uint8)] = key;
window_close_by_class(WC_CHANGE_KEYBOARD_SHORTCUT);
window_invalidate_by_class(WC_KEYBOARD_SHORTCUT_LIST);
config_save_default();
config_shortcut_keys_save();
}
/**

View File

@ -230,11 +230,17 @@ void sub_689174(sint16* x, sint16* y, sint16 *z, uint8 curr_rotation){
switch (curr_rotation){
case 0:
for (int i = 0; i < 6; ++i){
*x = start_y - start_x / 2 + height;
*y = start_y + start_x / 2 + height;
*y = start_y + start_x / 2 + height;
height = map_element_height((0xFFFF) & *x, (0xFFFF) & *y);
// HACK: This is to prevent the x and y values being set to values outside
// of the map. This can happen when the height is larger than the map size.
if (*x > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16) && *y > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16)){
*x = start_y - start_x / 2;
*y = start_y + start_x / 2;
}
}
break;
case 1:
@ -243,6 +249,13 @@ void sub_689174(sint16* x, sint16* y, sint16 *z, uint8 curr_rotation){
*y = start_y - start_x / 2 + height;
height = map_element_height((0xFFFF) & *x, (0xFFFF) & *y);
// HACK: This is to prevent the x and y values being set to values outside
// of the map. This can happen when the height is larger than the map size.
if (*x > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16) && *y > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16)){
*x = -start_y - start_x / 2;
*y = start_y - start_x / 2;
}
}
break;
case 2:
@ -251,6 +264,13 @@ void sub_689174(sint16* x, sint16* y, sint16 *z, uint8 curr_rotation){
*y = -start_y - start_x / 2 - height;
height = map_element_height((0xFFFF) & *x, (0xFFFF) & *y);
// HACK: This is to prevent the x and y values being set to values outside
// of the map. This can happen when the height is larger than the map size.
if (*x > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16) && *y > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16)){
*x = -start_y + start_x / 2;
*y = -start_y - start_x / 2;
}
}
break;
case 3:
@ -259,6 +279,13 @@ void sub_689174(sint16* x, sint16* y, sint16 *z, uint8 curr_rotation){
*y = start_x / 2 - start_y - height;
height = map_element_height((0xFFFF) & *x, (0xFFFF) & *y);
// HACK: This is to prevent the x and y values being set to values outside
// of the map. This can happen when the height is larger than the map size.
if (*x > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16) && *y > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16)){
*x = start_y + start_x / 2;
*y = -start_y + start_x / 2;
}
}
break;
}
@ -409,6 +436,27 @@ void sub_6E7DE1(sint16 x, sint16 y, rct_window* w, rct_viewport* viewport){
memcpy(viewport, &view_copy, sizeof(rct_viewport));
}
//rct2: 0x006E7A15
void viewport_set_underground_flag(int underground, rct_window* window, rct_viewport* viewport)
{
if (window->classification != WC_MAIN_WINDOW)
{
if (!underground)
{
int bit = viewport->flags & VIEWPORT_FLAG_UNDERGROUND_INSIDE;
viewport->flags &= ~VIEWPORT_FLAG_UNDERGROUND_INSIDE;
if (!bit) return;
}
else
{
int bit = viewport->flags & VIEWPORT_FLAG_UNDERGROUND_INSIDE;
viewport->flags |= VIEWPORT_FLAG_UNDERGROUND_INSIDE;
if (bit) return;
}
window_invalidate(window);
}
}
/**
*
* rct2: 0x006E7A3A
@ -428,7 +476,8 @@ void viewport_update_position(rct_window *window)
int height = map_element_height(0xFFFF & sprite->unknown.x, 0xFFFF & sprite->unknown.y) & 0xFFFF - 16;
int underground = sprite->unknown.z < height;
RCT2_CALLPROC_X(0x6E7A15, sprite->unknown.x, sprite->unknown.y, sprite->unknown.z, underground, (int)window, (int)viewport, 0);
viewport_set_underground_flag(underground, window, viewport);
//RCT2_CALLPROC_X(0x6E7A15, sprite->unknown.x, sprite->unknown.y, sprite->unknown.z, underground, (int)window, (int)viewport, 0);
int center_x, center_y;
center_2d_coordinates(sprite->unknown.x, sprite->unknown.y, sprite->unknown.z, &center_x, &center_y, window->viewport);
@ -446,7 +495,8 @@ void viewport_update_position(rct_window *window)
int curr_rotation = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32);
sub_689174(&x, &y, &z, curr_rotation);
RCT2_CALLPROC_X(0x006E7A15, x, y, z, 0, (int)window, (int)viewport, 0);
viewport_set_underground_flag(0, window, viewport);
//RCT2_CALLPROC_X(0x006E7A15, x, y, z, 0, (int)window, (int)viewport, 0);
//Clamp to the map minimum value
int at_map_edge = 0;

View File

@ -1113,3 +1113,11 @@ void widget_scroll_get_part(rct_window *w, rct_widget* widget, int x, int y, int
}
}
}
void widget_set_checkbox_value(rct_window *w, int widgetIndex, int value)
{
if (value)
w->pressed_widgets |= (1ULL << widgetIndex);
else
w->pressed_widgets &= ~(1ULL << widgetIndex);
}

View File

@ -63,4 +63,7 @@ int widget_is_pressed(rct_window *w, int widgetIndex);
int widget_is_highlighted(rct_window *w, int widgetIndex);
int widget_is_active_tool(rct_window *w, int widgetIndex);
void widget_scroll_get_part(rct_window *w, rct_widget* widget, int x, int y, int *output_x, int *output_y, int *output_scroll_area, int *scroll_id);
void widget_set_checkbox_value(rct_window *w, int widgetIndex, int value);
#endif

View File

@ -1232,6 +1232,9 @@ void window_zoom_in(rct_window *w)
w->saved_view_x += v->view_width >> 1;
w->saved_view_y += v->view_height >> 1;
// HACK: Prevents the redraw from failing when there is
// a window on top of the viewport.
window_bring_to_front(w);
window_invalidate(w);
}
@ -1259,6 +1262,9 @@ void window_zoom_out(rct_window *w)
w->saved_view_x -= width / 2;
w->saved_view_y -= height >> 1;
// HACK: Prevents the redraw from failing when there is
// a window on top of the viewport.
window_bring_to_front(w);
window_invalidate(w);
}

View File

@ -515,6 +515,7 @@ void window_land_open();
void window_water_open();
void window_staff_list_open();
void window_guest_list_open();
void window_guest_list_open_with_filter(int type, int index);
void window_map_open();
void window_options_open();
void window_shortcut_keys_open();

View File

@ -82,10 +82,19 @@ static int utf8_get_next(char *char_ptr, char **nextchar_ptr)
const char *language_get_string(rct_string_id id)
{
const char *rct = RCT2_ADDRESS(0x009BF2D4, const char*)[id];
const char *openrct = language_strings == NULL ? NULL : language_strings[id];
const char *str = (openrct == NULL || strlen(openrct) == 0 ? rct : openrct);
return str == NULL ? "" : str;
if (id >= STR_OPENRCT2_BEGIN_STRING_ID) {
const char *openrct = language_strings == NULL ? NULL : language_strings[id];
if (openrct != NULL)
return openrct;
// TODO Fall back to another language or otherwise English (UK)
return "(undefined string)";
} else {
const char *rct = RCT2_ADDRESS(0x009BF2D4, const char*)[id];
const char *openrct = language_strings == NULL ? NULL : language_strings[id];
const char *str = (openrct == NULL || strlen(openrct) == 0 ? rct : openrct);
return str == NULL ? "" : str;
}
}
int language_open(int id)
@ -128,7 +137,7 @@ static int language_open_file(const char *filename)
return 0;
fseek(f, 0, SEEK_END);
language_buffer_size = ftell(f);
language_buffer_size = ftell(f) + 1;
language_buffer = calloc(1, language_buffer_size);
fseek(f, 0, SEEK_SET);
fread(language_buffer, language_buffer_size, 1, f);
@ -230,59 +239,77 @@ const int OpenRCT2LangIdToObjectLangId[] = {
0, 0, 1, 3, 6, 2, 0, 0, 4, 7
};
//0x006A9E24
/* rct2: 0x0098DA16 */
uint16 ObjectTypeStringTableCount[] = { 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 };
/* rct2: 0x006A9E24*/
rct_string_id object_get_localised_text(uint8_t** pStringTable/*ebp*/, int type/*ecx*/, int index/*ebx*/, int tableindex/*edx*/)
{
char* pString;
char* pString = NULL;
int result = 0;
while (true)
{
uint8_t language_code = ((uint8_t*)*pStringTable)[0];
(*pStringTable)++;
uint8_t language_code = *(*pStringTable)++;
if (language_code == 0xFF) //end of string table
break;
// This is the ideal situation. Language found
if (language_code == OpenRCT2LangIdToObjectLangId[gCurrentLanguage])//1)
{
pString = *pStringTable;
result |= 1;
}
// Just in case always load english into pString
if (language_code == 0 && !(result & 1))
{
pString = *pStringTable;
result |= 2;
}
// Failing that fall back to whatever is first string
if (!(result & 7))
{
pString = *pStringTable;
result |= 4;
}
while (true)
{
uint8_t character = ((uint8_t*)*pStringTable)[0];
(*pStringTable)++;
if (character == 0) break;
}
// Skip over the actual string entry to get to the next
// entry
while (*(*pStringTable)++ != 0);
}
// If not scenario text
if (RCT2_GLOBAL(0x9ADAFC, uint8_t) == 0)
{
int stringid = 0xD87;
int i;
for (i = 0; i < type; i++)
int stringid = 3463;
for (int i = 0; i < type; i++)
{
int nrobjects = object_entry_group_counts[i];
int nrstringtables = RCT2_GLOBAL(0x98DA16 + i * 2, uint16_t);//the number of string tables in a type
int nrstringtables = ObjectTypeStringTableCount[i];
stringid += nrobjects * nrstringtables;
}
stringid += index * RCT2_GLOBAL(0x98DA16 + type * 2, uint16_t);
RCT2_GLOBAL(0x00F42BBC, uint32) = stringid;
stringid += index * ObjectTypeStringTableCount[type];
// Used by the object list to allocate name in plugin.dat
RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_BASE_STRING_ID, uint32) = stringid;
stringid += tableindex;
RCT2_GLOBAL(0x009BF2D4 + stringid * 4, char*) = pString;//put pointer in stringtable
//put pointer in stringtable
language_strings[stringid] = pString;
// Until all string related functions are finished copy
// to old array as well.
RCT2_ADDRESS(0x009BF2D4, char*)[stringid] = pString;
return stringid;
}
else
{
int stringid = 0xD77 + tableindex;
RCT2_GLOBAL(0x009BF2D4 + stringid * 4, char*) = pString;//put pointer in stringtable
int stringid = 3447 + tableindex;
//put pointer in stringtable
language_strings[stringid] = pString;
// Until all string related functions are finished copy
// to old array as well.
RCT2_ADDRESS(0x009BF2D4, char*)[stringid] = pString;
return stringid;
}
}

View File

@ -1394,6 +1394,8 @@ enum {
STR_SET_PATROL_AREA = 3445,
STR_CLEAR_PATROL_AREA = 3446,
STR_OPENRCT2_BEGIN_STRING_ID = 5120,
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
STR_COUNT = 32768
};

View File

@ -288,7 +288,7 @@ static int award_is_deserved_best_food(int awardType, int activeAwardTypes)
FOR_ALL_RIDES(i, ride) {
if (ride->status != RIDE_STATUS_OPEN)
continue;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x800000))
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_23))
continue;
shops++;
@ -334,7 +334,7 @@ static int award_is_deserved_worst_food(int awardType, int activeAwardTypes)
FOR_ALL_RIDES(i, ride) {
if (ride->status != RIDE_STATUS_OPEN)
continue;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x800000))
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_23))
continue;
shops++;
@ -459,7 +459,7 @@ static int award_is_deserved_best_custom_designed_rides(int awardType, int activ
customDesignedRides = 0;
FOR_ALL_RIDES(i, ride) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x10000000))
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK))
continue;
if (ride->lifecycle_flags & RIDE_LIFECYCLE_18)
continue;
@ -488,7 +488,7 @@ static int award_is_deserved_most_dazzling_ride_colours(int awardType, int activ
countedRides = 0;
colourfulRides = 0;
FOR_ALL_RIDES(i, ride) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x10000000))
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK))
continue;
countedRides++;

View File

@ -333,7 +333,7 @@ void news_item_open_subject(int type, int subject)
break;
case NEWS_ITEM_PEEPS:
// Open guest list to right tab
RCT2_CALLPROC_X(0x006993BA, 3, subject, 0, 0, 0, 0, 0);
window_guest_list_open_with_filter(3, subject);;
break;
case NEWS_ITEM_AWARD:
window_park_awards_open();

File diff suppressed because it is too large Load Diff

View File

@ -86,8 +86,8 @@ int object_entry_compare(const rct_object_entry *a, const rct_object_entry *b);
int object_calculate_checksum(const rct_object_entry *entry, const char *data, int dataLength);
int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp);
rct_object_entry *object_get_next(rct_object_entry *entry);
int sub_6A9F42(FILE *file, rct_object_entry* entry);
void sub_6A9FC0();
int write_object_file(FILE *file, rct_object_entry* entry);
void reset_loaded_objects();
int find_object_in_entry_group(rct_object_entry* entry, uint8* entry_type, uint8* entry_index);
rct_object_entry *object_list_find(rct_object_entry *entry);

View File

@ -24,6 +24,7 @@
#include "platform/platform.h"
#include "ride/track.h"
#include "util/sawyercoding.h"
#include "game.h"
#define OBJECT_ENTRY_GROUP_COUNT 11
#define OBJECT_ENTRY_COUNT 721
@ -69,16 +70,16 @@ int object_entry_group_encoding[] = {
// 0x98D97C chunk address', 0x98D980 object_entries
rct_object_entry_group object_entry_groups[] = {
(uint8**)(0x009ACFA4 ), (rct_object_entry_extended*)(0x00F3F03C ), // rides
(uint8**)(0x009ACFA4 + (128 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (128 * 20)), // small scenery
(uint8**)(0x009ACFA4 + (380 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (380 * 20)), // large scenery
(uint8**)(0x009ACFA4 + (508 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (508 * 20)), // walls
(uint8**)(0x009ACFA4 + (636 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (636 * 20)), // banners
(uint8**)(0x009ACFA4 + (668 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (668 * 20)), // paths
(uint8**)(0x009ACFA4 + (684 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (684 * 20)), // path bits
(uint8**)(0x009ACFA4 + (699 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (699 * 20)), // scenery sets
(uint8**)(0x009ACFA4 + (718 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (718 * 20)), // park entrance
(uint8**)(0x009ACFA4 + (719 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (719 * 20)), // water
(uint8**)(0x009ACFA4 + (720 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (720 * 20)) // scenario text
(uint8**)(0x009ACFA4 + (128 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (128 * 20)), // small scenery 0x009AD1A4, 0xF2FA3C
(uint8**)(0x009ACFA4 + (380 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (380 * 20)), // large scenery 0x009AD594, 0xF40DEC
(uint8**)(0x009ACFA4 + (508 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (508 * 20)), // walls 0x009AD794, 0xF417EC
(uint8**)(0x009ACFA4 + (636 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (636 * 20)), // banners 0x009AD994, 0xF421EC
(uint8**)(0x009ACFA4 + (668 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (668 * 20)), // paths 0x009ADA14, 0xF4246C
(uint8**)(0x009ACFA4 + (684 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (684 * 20)), // path bits 0x009ADA54, 0xF425AC
(uint8**)(0x009ACFA4 + (699 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (699 * 20)), // scenery sets 0x009ADA90, 0xF426D8
(uint8**)(0x009ACFA4 + (718 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (718 * 20)), // park entrance 0x009ADADC, 0xF42854
(uint8**)(0x009ACFA4 + (719 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (719 * 20)), // water 0x009ADAE0, 0xF42868
(uint8**)(0x009ACFA4 + (720 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (720 * 20)) // scenario text 0x009ADAE4, 0xF4287C
};
static int object_list_cache_load(int totalFiles, uint64 totalFileSize, int fileDateModifiedChecksum);
@ -152,10 +153,12 @@ static void object_list_examine()
int i;
rct_object_entry *object;
RCT2_GLOBAL(RCT2_ADDRESS_CUSTOM_OBJECTS_INSTALLED, uint8) = 0;
object = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*);
for (i = 0; i < RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, sint32); i++) {
if (object->flags & 0xF0)
RCT2_GLOBAL(0x00F42BDA, uint8) |= 1;
if (!(object->flags & 0xF0))
RCT2_GLOBAL(RCT2_ADDRESS_CUSTOM_OBJECTS_INSTALLED, uint8) |= 1;
object = object_get_next(object);
}
@ -165,21 +168,12 @@ static void object_list_examine()
object_list_create_hash_table();
}
/**
*
* rct2: 0x006DED68
*/
void reset_9E32F8()
/* rct2: 0x006A9FC0 */
void reset_loaded_objects()
{
uint8* edi = RCT2_ADDRESS(0x009E32F8, uint8);
memset(edi, 0xFF, 90);
}
reset_type_to_ride_entry_index_map();
void sub_6A9FC0()
{
reset_9E32F8();
RCT2_GLOBAL(0x009ADAF0, uint32) = 0xF26E;
RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) = 0xF26E;
for (int type = 0; type < 11; ++type){
for (int j = 0; j < object_entry_group_counts[type]; j++){
@ -248,7 +242,7 @@ void object_list_load()
//if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_OBJECTS, uint8) != 0)
// RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_OBJECTS, uint8) = 0;
sub_6A9FC0();
reset_loaded_objects();
// Dispose installed object list
if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) != -1) {
@ -259,7 +253,8 @@ void object_list_load()
RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_malloc(4096);
if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, int) == -1){
RCT2_CALLPROC_X(0x006E3838, 0x343, 0xC5A, 0, 0, 0, 0, 0);
log_error("Failed to allocate memory for object list");
rct2_exit_reason(835, 3162);
return;
}
@ -280,7 +275,8 @@ void object_list_load()
installed_buffer_size += 0x1000;
RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_realloc(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*), installed_buffer_size);
if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, int) == -1){
RCT2_CALLPROC_X(0x006E3838, 0x343, 0xC5A, 0, 0, 0, 0, 0);
log_error("Failed to allocate memory for object list");
rct2_exit_reason(835, 3162);
return;
}
}
@ -288,22 +284,22 @@ void object_list_load()
char path[MAX_PATH];
subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), enumFileInfo.path);
rct_object_entry* entry = RCT2_ADDRESS(0x00F42B74, rct_object_entry);
if (!object_load_entry(path, entry))
rct_object_entry entry;
if (!object_load_entry(path, &entry))
continue;
rct_object_entry* installed_entry = (rct_object_entry*)(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*) + current_item_offset);
current_item_offset += install_object_entry(entry, installed_entry, enumFileInfo.path);
current_item_offset += install_object_entry(&entry, installed_entry, enumFileInfo.path);
}
platform_enumerate_files_end(enumFileHandle);
}
sub_6A9FC0();
reset_loaded_objects();
object_list_cache_save(fileCount, totalFileSize, fileDateModifiedChecksum, current_item_offset);
//
// Reload track list
ride_list_item ride_list;
ride_list.entry_index = 0xFC;
ride_list.type = 0xFC;
@ -349,7 +345,7 @@ static int object_list_cache_load(int totalFiles, uint64 totalFileSize, int file
log_error("Potential mismatch in file numbers. Possible corrupt file. Consider deleting plugin.dat.");
fclose(file);
sub_6A9FC0();
reset_loaded_objects();
object_list_examine();
return 1;
}
@ -408,15 +404,15 @@ void set_load_objects_fail_reason(){
format_string(string_buffer, 3323, 0); //Missing object data, ID:
RCT2_CALLPROC_X(0x6AB344, 0, 0, 0, 0, 0, (int)string_buffer, 0x13CE952);
RCT2_GLOBAL(0x9AC31B, uint8) = 0xFF;
RCT2_GLOBAL(0x9AC31C, uint16) = 3165;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 0xFF;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = 3165;
return;
}
char* exapansion_name = &RCT2_ADDRESS(RCT2_ADDRESS_EXPANSION_NAMES, char)[128 * expansion];
if (*exapansion_name == '\0'){
RCT2_GLOBAL(0x9AC31B, uint8) = 0xFF;
RCT2_GLOBAL(0x9AC31C, uint16) = 3325;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 0xFF;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = 3325;
return;
}
@ -424,8 +420,8 @@ void set_load_objects_fail_reason(){
format_string(string_buffer, 3324, 0); // Requires expansion pack
strcat(string_buffer, exapansion_name);
RCT2_GLOBAL(0x9AC31B, uint8) = 0xFF;
RCT2_GLOBAL(0x9AC31C, uint16) = 3165;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 0xFF;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = 3165;
}
/**
@ -493,7 +489,7 @@ void object_unload_all()
if (object_entry_groups[i].chunks[j] != (uint8*)0xFFFFFFFF)
object_unload(j, &object_entry_groups[i].entries[j]);
sub_6A9FC0();
reset_loaded_objects();
}
@ -601,12 +597,14 @@ static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* in
// Chunk size is set to unknown
*((sint32*)installed_entry_pointer) = -1;
// No unknown objects set to 0
*(installed_entry_pointer + 4) = 0;
// No theme objects set to 0
*((sint32*)(installed_entry_pointer + 5)) = 0;
*((uint16*)(installed_entry_pointer + 9)) = 0;
*((uint32*)(installed_entry_pointer + 11)) = 0;
RCT2_GLOBAL(0x9ADAF0, uint32) = 0xF26E;
RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) = 0xF26E;
RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)++;
@ -648,28 +646,31 @@ static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* in
uint8* chunk = RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_CHUNK_POINTER, uint8*); // Loaded in object_load
// When made of two parts i.e Wooden Roller Coaster (Dream Woodie Cars);
if (objectType == OBJECT_TYPE_RIDE && !(*((uint32*)(chunk + 8)) & 0x1000)) {
rct_string_id obj_string = chunk[12];
// When made of two parts i.e Wooden Roller Coaster (Dream Woodie Cars)
if ((objectType == OBJECT_TYPE_RIDE) && !((((rct_ride_type*)chunk)->var_008) & 0x1000)) {
rct_ride_type* ride_type = (rct_ride_type*)chunk;
rct_string_id obj_string = ride_type->var_00C;
if (obj_string == 0xFF){
obj_string = chunk[13];
obj_string = ride_type->var_00D;
if (obj_string == 0xFF) {
obj_string = chunk[14];
obj_string = ride_type->var_00E;
}
}
obj_string += 2;
format_string(installed_entry_pointer, obj_string, 0);
format_string(installed_entry_pointer, obj_string + 2, 0);
strcat(installed_entry_pointer, "\t (");
strcat(installed_entry_pointer, language_get_string((rct_string_id)RCT2_GLOBAL(0x00F42BBC, uint32)));
strcat(installed_entry_pointer, language_get_string((rct_string_id)RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_BASE_STRING_ID, uint32)));
strcat(installed_entry_pointer, ")");
while (*installed_entry_pointer++);
}
else{
strcpy(installed_entry_pointer, language_get_string((rct_string_id)RCT2_GLOBAL(0x00F42BBC, uint32)));
strcpy(installed_entry_pointer, language_get_string((rct_string_id)RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_BASE_STRING_ID, uint32)));
while (*installed_entry_pointer++);
}
*((uint32*)installed_entry_pointer) = RCT2_GLOBAL(0x009ADAF0, uint32) - 0xF26E;
// This is deceptive. Due to setting the total no images earlier to 0xF26E
// this is actually the no_images in this entry.
*((uint32*)installed_entry_pointer) = RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) - 0xF26E;
installed_entry_pointer += 4;
uint8* esi = RCT2_ADDRESS(0x00F42BDB, uint8);

View File

@ -1990,7 +1990,7 @@ void peep_problem_warnings_update()
break;
}
ride = &g_ride_list[peep->guest_heading_to_ride_id];
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x80000))
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_SELLS_FOOD))
hunger_counter++;
break;
@ -2000,7 +2000,7 @@ void peep_problem_warnings_update()
break;
}
ride = &g_ride_list[peep->guest_heading_to_ride_id];
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x1000000))
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_SELLS_DRINKS))
thirst_counter++;
break;
@ -2010,7 +2010,7 @@ void peep_problem_warnings_update()
break;
}
ride = &g_ride_list[peep->guest_heading_to_ride_id];
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x2000000))
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_BATHROOM))
bathroom_counter++;
break;
@ -2223,6 +2223,24 @@ void peep_applause()
sound_play_panned(SOUND_APPLAUSE, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2, 0, 0, 0);
}
/**
*
* rct2: 0x0069C35E
*/
void peep_update_days_in_queue()
{
uint16 sprite_index;
rct_peep *peep;
FOR_ALL_GUESTS(sprite_index, peep) {
if (peep->var_2A == 0 && peep->state == PEEP_STATE_QUEUING) {
if (peep->days_in_queue < 255) {
peep->days_in_queue += 1;
}
}
}
}
/**
*
* rct2: 0x0069A05D
@ -2261,9 +2279,8 @@ void get_arguments_from_action(rct_peep* peep, uint32 *argument_1, uint32* argum
case PEEP_STATE_ENTERING_RIDE:
*argument_1 = STR_ON_RIDE;
ride = g_ride_list[peep->current_ride];
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride.type * 8, uint32) & 0x400000){
if (ride_type_has_flag(ride.type, RIDE_TYPE_FLAG_IN_RIDE))
*argument_1 = STR_IN_RIDE;
}
*argument_1 |= (ride.name << 16);
*argument_2 = ride.name_arguments;
break;

View File

@ -485,7 +485,7 @@ typedef struct {
uint8 pad_F2;
uint8 var_F3;
uint8 var_F4;
uint8 pad_F5;
uint8 days_in_queue; // 0xF5
uint8 balloon_colour; // 0xF6
uint8 umbrella_colour; // 0xF7
uint8 hat_colour; // 0xF8
@ -547,6 +547,7 @@ int peep_can_be_picked_up(rct_peep* peep);
void peep_update_all();
void peep_problem_warnings_update();
void peep_update_crowd_noise();
void peep_update_days_in_queue();
void peep_applause();
rct_peep *peep_generate(int x, int y, int z);
void get_arguments_from_action(rct_peep* peep, uint32 *argument_1, uint32* argument_2);

View File

@ -137,6 +137,7 @@ void platform_get_closest_resolution(int inWidth, int inHeight, int *outWidth, i
if (gResolutions[i].width == inWidth && gResolutions[i].height == inHeight) {
closestWidth = gResolutions[i].width;
closestHeight = gResolutions[i].height;
closestAreaDiff = 0;
break;
}

View File

@ -80,6 +80,7 @@ int rct2_init()
return 0;
config_reset_shortcut_keys();
config_shortcut_keys_load();
RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = 0;
// config_load();
// RCT2_CALLPROC_EBPSAFE(0x00674B81); // pointless expansion pack crap

View File

@ -140,6 +140,15 @@ rct_ride_type *ride_get_entry(rct_ride *ride)
return GET_RIDE_ENTRY(ride->subtype);
}
/**
*
* rct2: 0x006DED68
*/
void reset_type_to_ride_entry_index_map(){
uint8* typeToRideEntryIndexMap = RCT2_ADDRESS(0x009E32F8, uint8);
memset(typeToRideEntryIndexMap, 0xFF, 90);
}
uint8 *get_ride_entry_indices_for_ride_type(uint8 rideType)
{
uint8 *typeToRideEntryIndexMap = (uint8*)0x009E32F8;
@ -413,7 +422,7 @@ void ride_get_status(int rideIndex, int *formatSecondary, int *argument)
*formatSecondary = STR_RACE_WON_BY;
}
} else {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x20000)) {
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) {
*argument = ride->num_riders;
*formatSecondary = STR_PERSON_ON_RIDE;
if(*argument != 1)
@ -947,7 +956,7 @@ int ride_modify(rct_xy_element *input)
if (ride->type == RIDE_TYPE_MAZE)
return ride_modify_maze(mapElement.element, mapElement.x, mapElement.y);
if (RCT2_ADDRESS(RCT2_ADDRESS_RIDE_FLAGS,uint64)[ride->type] & 0x100) {
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_8)) {
if (ride_find_track_gap(&mapElement, &endOfTrackElement))
mapElement = endOfTrackElement;
}
@ -971,7 +980,7 @@ int ride_modify(rct_xy_element *input)
RCT2_GLOBAL(0x00F440B0, uint8) = 0;
RCT2_GLOBAL(0x00F440B1, uint8) = 0;
if (RCT2_ADDRESS(RCT2_ADDRESS_RIDE_FLAGS, uint64)[ride->type] & 0x8000) {
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_15)) {
sub_6C84CE();
return 1;
}
@ -2011,7 +2020,7 @@ rct_ride_measurement *ride_get_measurement(int rideIndex, rct_string_id *message
ride = GET_RIDE(rideIndex);
// Check if ride type supports data logging
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x200)) {
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_DATA_LOGGING)) {
if (message != NULL) *message = STR_DATA_LOGGING_NOT_AVAILABLE_FOR_THIS_TYPE_OF_RIDE;
return NULL;
}
@ -2044,7 +2053,7 @@ rct_ride_measurement *ride_get_measurement(int rideIndex, rct_string_id *message
measurement->ride_index = rideIndex;
ride->measurement_index = i;
measurement->flags = 0;
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x80)
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_G_FORCES))
measurement->flags |= RIDE_MEASUREMENT_FLAG_G_FORCES;
measurement->num_items = 0;
measurement->current_item = 0;
@ -2102,8 +2111,8 @@ void ride_check_all_reachable()
if (ride->status != RIDE_STATUS_OPEN || ride->connected_message_throttle != 0)
continue;
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x20000)
ride_shop_connected(ride, i);
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP))
ride_shop_connected(ride, i);
else
ride_entrance_exit_connected(ride, i);
}
@ -2193,7 +2202,7 @@ static void ride_shop_connected(rct_ride* ride, int ride_idx)
uint16 entrance_directions = 0;
uint8 track_type = mapElement->properties.track.type;
ride = &g_ride_list[mapElement->properties.track.ride_index];
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x80000) {
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_SELLS_FOOD)) {
entrance_directions = RCT2_ADDRESS(0x0099CA64, uint8)[track_type * 16];
} else {
entrance_directions = RCT2_ADDRESS(0x0099BA64, uint8)[track_type * 16];
@ -2799,7 +2808,7 @@ int ride_mode_check_station_present(rct_ride* ride){
if (stationIndex == -1) {
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_NOT_YET_CONSTRUCTED;
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x8000)
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_15))
return -1;
if (ride->type == RIDE_TYPE_MAZE)
@ -2820,7 +2829,8 @@ int ride_check_for_entrance_exit(int rideIndex)
{
rct_ride* ride = GET_RIDE(rideIndex);
if (RCT2_ADDRESS(RCT2_ADDRESS_RIDE_FLAGS, uint32)[ride->type * 2] & 0x20000) return 1;
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP))
return 1;
int i;
uint8 entrance = 0;
@ -3285,7 +3295,7 @@ int ride_is_valid_for_open(int rideIndex, int goingToBeOpen, int isApplying)
sub_6B4D26(rideIndex, &trackElement);
if (
!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x2000) &&
!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_13) &&
!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)
) {
if (sub_6DD84C(ride, rideIndex, &trackElement, isApplying))
@ -3444,4 +3454,9 @@ void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi
}
*ebx = 0;
}
bool ride_type_has_flag(int rideType, int flag)
{
return (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (rideType * 8), uint32) & flag) != 0;
}

View File

@ -46,6 +46,50 @@ typedef struct {
uint8 entry_index;
} ride_list_item;
/**
* Ride type vehicle structure.
* size: 0x65
*/
typedef struct{
uint16 var_00; // 0x00 , 0x1A
uint8 var_02; // 0x02 , 0x1C
uint8 var_03; // 0x03 , 0x1D
uint32 var_04; // 0x04 , 0x1E
uint16 var_08; // 0x08 , 0x22
sint8 var_0A; // 0x0A , 0x24
uint8 pad_0B;
uint16 var_0C; // 0x0C , 0x26
uint8 var_0E; // 0x0E , 0x28
uint8 var_0F; // 0x0F , 0x29
uint8 var_10; // 0x10 , 0x2A
uint8 var_11; // 0x11 , 0x2B
uint16 var_12; // 0x12 , 0x2C
uint16 var_14; // 0x14 , 0x2E
uint16 var_16; // 0x16 , 0x30
uint32 base_image_id; // 0x18 , 0x32
uint32 var_1C; // 0x1C , 0x36
uint32 var_20; // 0x20 , 0x3A
uint32 var_24; // 0x24 , 0x3E
uint32 var_28; // 0x28 , 0x42
uint32 var_2C; // 0x2C , 0x46
uint32 var_30; // 0x30 , 0x4A
uint32 var_34; // 0x34 , 0x4E
uint32 var_38; // 0x38 , 0x52
uint32 var_3C; // 0x3C , 0x56
uint32 var_40; // 0x40 , 0x5A
uint32 var_44; // 0x44 , 0x5E
uint32 var_48; // 0x48 , 0x62
uint32 var_4C; // 0x4C , 0x66
uint32 no_vehicle_images; // 0x50 , 0x6A
uint8 no_seating_rows; // 0x54 , 0x6E
uint8 pad_55[0x7];
uint8 var_5C; // 0x5C , 0x76
uint8 var_5D; // 0x5D , 0x77
uint8 pad_5E[0x2];
uint8 var_60; // 0x60 , 0x7A
uint32 var_61; // 0x61 , 0x7B
} rct_ride_type_vehicle;
/**
* Ride type structure.
* size: unknown
@ -53,8 +97,9 @@ typedef struct {
typedef struct {
rct_string_id name; // 0x000
rct_string_id description; // 0x002
uint32 var_004;
uint32 images_offset; // 0x004
uint32 var_008;
// 0xC, D, E are related
uint8 var_00C;
uint8 var_00D;
uint8 var_00E;
@ -63,7 +108,9 @@ typedef struct {
uint8 var_011;
uint8 var_012;
uint8 var_013;
uint8 pad_014[0x19E];
uint8 pad_014[0x6];
rct_ride_type_vehicle vehicles[4]; // 0x1A
uint32 var_1AE;
sint8 excitement_multipler; // 0x1B2
sint8 intensity_multipler; // 0x1B3
sint8 nausea_multipler; // 0x1B4
@ -576,6 +623,41 @@ enum {
RIDE_MEASUREMENT_FLAG_G_FORCES = 1 << 2
};
enum {
RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_MAIN = 1 << 0,
RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_ADDITIONAL = 1 << 1,
RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_SUPPORTS = 1 << 2,
RIDE_TYPE_FLAG_3 = 1 << 3,
RIDE_TYPE_FLAG_HAS_LEAVE_WHEN_ANOTHER_VEHICLE_ARRIVES_AT_STATION = 1 << 4,
RIDE_TYPE_FLAG_CAN_SYNCHRONISE_ADJACENT_STATIONS = 1 << 5,
RIDE_TYPE_FLAG_6 = 1 << 6,
RIDE_TYPE_FLAG_HAS_G_FORCES = 1 << 7,
RIDE_TYPE_FLAG_8 = 1 << 8, // something to do with track, maybe whether it can have gaps
RIDE_TYPE_FLAG_HAS_DATA_LOGGING = 1 << 9,
RIDE_TYPE_FLAG_HAS_DROPS = 1 << 10,
RIDE_TYPE_FLAG_NO_TEST_MODE = 1 << 11,
RIDE_TYPE_FLAG_12 = 1 << 12,
RIDE_TYPE_FLAG_13 = 1 << 13, // something to do with stations or vehicles
RIDE_TYPE_FLAG_HAS_LOAD_OPTIONS = 1 << 14,
RIDE_TYPE_FLAG_15 = 1 << 15, // something to do with station, price and viewport zoom
RIDE_TYPE_FLAG_16 = 1 << 16, // something to do with vehicle colour scheme
RIDE_TYPE_FLAG_IS_SHOP = 1 << 17,
RIDE_TYPE_FLAG_18 = 1 << 18,
RIDE_TYPE_FLAG_SELLS_FOOD = 1 << 19,
RIDE_TYPE_FLAG_20 = 1 << 20,
RIDE_TYPE_FLAG_21 = 1 << 21,
RIDE_TYPE_FLAG_IN_RIDE = 1 << 22, // peeps are "IN" (ride) rather than "ON" (ride)
RIDE_TYPE_FLAG_23 = 1 << 23, // sells food?, seems to be used for food awards...
RIDE_TYPE_FLAG_SELLS_DRINKS = 1 << 24,
RIDE_TYPE_FLAG_IS_BATHROOM = 1 << 25,
RIDE_TYPE_FLAG_26 = 1 << 26, // something to do with vehicle colours
RIDE_TYPE_FLAG_27 = 1 << 27,
RIDE_TYPE_FLAG_HAS_TRACK = 1 << 28,
RIDE_TYPE_FLAG_29 = 1 << 29,
RIDE_TYPE_FLAG_30 = 1 << 30,
RIDE_TYPE_FLAG_SUPPORTS_MULTIPLE_TRACK_COLOUR = 1 << 31,
};
#define MAX_RIDES 255
#define MAX_RIDE_MEASUREMENTS 8
@ -627,6 +709,7 @@ track_colour ride_get_track_colour(rct_ride *ride, int colourScheme);
vehicle_colour ride_get_vehicle_colour(rct_ride *ride, int vehicleIndex);
rct_ride_type *ride_get_entry(rct_ride *ride);
uint8 *get_ride_entry_indices_for_ride_type(uint8 rideType);
void reset_type_to_ride_entry_index_map();
void ride_measurement_clear(rct_ride *ride);
void ride_measurements_update();
rct_ride_measurement *ride_get_measurement(int rideIndex, rct_string_id *message);
@ -644,4 +727,6 @@ void game_command_set_ride_status(int *eax, int *ebx, int *ecx, int *edx, int *e
void ride_set_name(int rideIndex, const char *name);
void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
bool ride_type_has_flag(int rideType, int flag);
#endif

View File

@ -228,7 +228,6 @@ static void ride_race_init_vehicle_speeds(rct_ride *ride)
{
rct_ride_type *rideEntry;
rct_vehicle *vehicle;
uint8 *unk;
int i;
for (i = 0; i < ride->num_vehicles; i++) {
@ -236,9 +235,8 @@ static void ride_race_init_vehicle_speeds(rct_ride *ride)
vehicle->var_48 &= ~(1 << 6);
rideEntry = GET_RIDE_ENTRY(vehicle->var_D6);
unk = (uint8*)((int)rideEntry + (vehicle->var_31 * 0x65));
vehicle->speed = (scenario_rand() & 16) - 8 + RCT2_GLOBAL(unk + 0x76, uint8);
vehicle->speed = (scenario_rand() & 16) - 8 + rideEntry->vehicles[vehicle->var_31].var_5C;
if (vehicle->num_peeps != 0) {
rct_peep *peep = &g_sprite_list[vehicle->peep[0]].peep;

View File

@ -19,6 +19,7 @@
*****************************************************************************/
#include "../addresses.h"
#include "../audio/audio.h"
#include "../game.h"
#include "../interface/viewport.h"
#include "../localisation/localisation.h"
@ -27,6 +28,7 @@
#include "../util/sawyercoding.h"
#include "../util/util.h"
#include "../world/park.h"
#include "../windows/error.h"
#include "ride.h"
#include "track.h"
@ -713,12 +715,12 @@ void load_track_scenery_objects(){
if (track_design->type == RIDE_TYPE_MAZE){
// Skip all of the maze track elements
while (*(uint32*)track_elements != 0)track_elements += 4;
track_elements += 4;
while (*(uint32*)track_elements != 0)track_elements += sizeof(rct_maze_element);
track_elements += sizeof(rct_maze_element);
}
else{
// Skip track_elements
while (*track_elements != 255) track_elements += 2;
while (*track_elements != 255) track_elements += sizeof(rct_track_element);
track_elements++;
// Skip entrance exit elements
@ -727,14 +729,16 @@ void load_track_scenery_objects(){
}
while (*track_elements != 255){
if (!find_object_in_entry_group((rct_object_entry*)track_elements, &entry_type, &entry_index)){
object_load(-1, (rct_object_entry*)track_elements, 0);
rct_track_scenery* scenery_entry = (rct_track_scenery*)track_elements;
if (!find_object_in_entry_group(&scenery_entry->scenery_object, &entry_type, &entry_index)){
object_load(-1, &scenery_entry->scenery_object, 0);
}
// Skip object and location/direction/colour
track_elements += sizeof(rct_object_entry) + 6;
scenery_entry += sizeof(rct_track_scenery);
}
sub_6A9FC0();
reset_loaded_objects();
}
/**
@ -1166,3 +1170,182 @@ int track_is_connected_by_shape(rct_map_element *a, rct_map_element *b)
return aBank == bBank && aAngle == bAngle;
}
/* Based on rct2: 0x006D2897 */
int copy_scenery_to_track(uint8** track_pointer){
rct_track_scenery* track_scenery = (rct_track_scenery*)(*track_pointer - 1);
rct_track_scenery* scenery_source = RCT2_ADDRESS(0x009DA193, rct_track_scenery);
while (1){
int ebx = 0;
memcpy(track_scenery, scenery_source, sizeof(rct_track_scenery));
if ((track_scenery->scenery_object.flags & 0xFF) == 0xFF) break;
//0x00F4414D is direction of track?
if ((track_scenery->scenery_object.flags & 0xF) == OBJECT_TYPE_PATHS){
uint8 slope = (track_scenery->flags & 0x60) >> 5;
slope -= RCT2_GLOBAL(0x00F4414D, uint8);
track_scenery->flags &= 0x9F;
track_scenery->flags |= ((slope & 3) << 5);
// Direction of connection on path
uint8 direction = track_scenery->flags & 0xF;
// Rotate the direction by the track direction
direction = ((direction << 4) >> RCT2_GLOBAL(0x00F4414D, uint8));
track_scenery->flags &= 0xF0;
track_scenery->flags |= (direction & 0xF) | (direction >> 4);
}
else if ((track_scenery->scenery_object.flags & 0xF) == OBJECT_TYPE_WALLS){
uint8 direction = track_scenery->flags & 3;
direction -= RCT2_GLOBAL(0x00F4414D, uint8);
track_scenery->flags &= 0xFC;
track_scenery->flags |= (direction & 3);
}
else {
uint8 direction = track_scenery->flags & 3;
uint8 quadrant = (track_scenery->flags & 0xC) >> 2;
direction -= RCT2_GLOBAL(0x00F4414D, uint8);
quadrant -= RCT2_GLOBAL(0x00F4414D, uint8);
track_scenery->flags &= 0xF0;
track_scenery->flags |= (direction & 3) | ((quadrant & 3) << 2);
}
int x = track_scenery->x * 32 - RCT2_GLOBAL(0x00F44142, sint16);
int y = track_scenery->y * 32 - RCT2_GLOBAL(0x00F44144, sint16);
switch (RCT2_GLOBAL(0x00F4414D, uint8)){
case 0:
break;
case 1:
{
int temp_y = y;
y = x;
x = -y;
}
break;
case 2:
x = -x;
y = -y;
break;
case 3:
{
int temp_x = x;
x = y;
y = -x;
}
break;
}
x /= 32;
y /= 32;
if (x > 127 || y > 127 || x < -126 || y < -126){
window_error_open(3346, 3347);
return 0;
}
track_scenery->x = x;
track_scenery->y = y;
int z = track_scenery->z * 8 - RCT2_GLOBAL(0xF44146, sint16);
z /= 8;
if (z > 127 || z < -126){
window_error_open(3346, 3347);
return 0;
}
track_scenery->z = z;
track_scenery++;
scenery_source++;
}
*track_pointer = (uint8*)track_scenery;
//Skip end of scenery elements byte
(*track_pointer)++;
return 1;
}
/* rct2: 0x006D2804 & 0x006D264D */
int save_track_design(uint8 rideIndex){
rct_ride* ride = GET_RIDE(rideIndex);
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)){
window_error_open(3346, RCT2_GLOBAL(0x141E9AC, rct_string_id));
return 0;
}
if (ride->ratings.excitement == 0xFFFF){
window_error_open(3346, RCT2_GLOBAL(0x141E9AC, rct_string_id));
return 0;
}
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK)) {
window_error_open(3346, RCT2_GLOBAL(0x141E9AC, rct_string_id));
return 0;
}
if (RCT2_CALLPROC_X(0x006CE44F, 0, 0, 0, rideIndex, 0, 0, 0) & 0x100){
window_error_open(3346, RCT2_GLOBAL(0x141E9AC, rct_string_id));
return 0;
}
uint8* track_pointer = RCT2_GLOBAL(0x00F44058, uint8*);
if (RCT2_GLOBAL(0x009DEA6F, uint8) & 1){
if (!copy_scenery_to_track(&track_pointer))
return 0;
}
while (track_pointer < RCT2_ADDRESS(0x009DE217, uint8))*track_pointer++ = 0;
char track_name[MAX_PATH];
// Get track name
format_string(track_name, ride->name, &ride->name_arguments);
char path[MAX_PATH];
subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), track_name);
strcat(path, ".TD6");
// Save track design
format_string(RCT2_ADDRESS(0x141ED68, char), 2306, NULL);
// Track design files
format_string(RCT2_ADDRESS(0x141EE68, char), 2305, NULL);
pause_sounds();
int result = platform_open_common_file_dialog(
0,
RCT2_ADDRESS(0x141ED68, char),
path,
"*.TD?",
RCT2_ADDRESS(0x141EE68, char));
unpause_sounds();
if (result == 0){
ride_list_item item = { .type = 0xFD, .entry_index = 0 };
track_load_list(item);
return 1;
}
// Until 0x006771DC is finished we required to copy the path name.
strcpy(RCT2_ADDRESS(0x141EF68, char), path);
// This is the function that actually saves the track to a file
RCT2_CALLPROC_EBPSAFE(0x006771DC);
ride_list_item item = { .type = 0xFC, .entry_index = 0 };
track_load_list(item);
gfx_invalidate_screen();
return 1;
}

View File

@ -40,11 +40,12 @@ typedef struct {
*/
typedef struct {
uint8 var_00;
sint16 x;
sint16 y;
uint8 pad_05[3];
sint16 x; // 0x01
sint16 y; // 0x03
uint16 z;
uint8 pad_07;
uint8 var_08;
uint8 unk_09;
uint8 var_09;
} rct_preview_track;
/**
@ -68,6 +69,17 @@ typedef struct{
uint8 flags;
}rct_track_element;
/* Track Scenery entry size: 0x16 */
typedef struct{
rct_object_entry scenery_object; // 0x00
uint8 x; // 0x10
uint8 y; // 0x11
uint8 z; // 0x12
uint8 flags; // 0x13 direction quadrant tertiary colour
uint8 primary_colour; // 0x14
uint8 secondary_colour; // 0x15
}rct_track_scenery;
enum{
TRACK_ELEMENT_FLAG_CHAIN_LIFT = (1<<7),
TRACK_ELEMENT_FLAG_INVERTED = (1<<6),
@ -118,7 +130,7 @@ typedef struct {
uint8 average_speed; // 0x52
uint16 ride_length; // 0x53
uint8 max_positive_vertical_g; // 0x55
uint8 max_negitive_vertical_g; // 0x56
sint8 max_negitive_vertical_g; // 0x56
uint8 max_lateral_g; // 0x57
union {
uint8 inversions; // 0x58
@ -215,5 +227,6 @@ int track_delete();
void reset_track_list_cache();
int track_is_connected_by_shape(rct_map_element *a, rct_map_element *b);
int sub_6D01B3(int bl, int x, int y, int z);
int save_track_design(uint8 rideIndex);
#endif

View File

@ -39,6 +39,7 @@
#include "world/map.h"
#include "world/park.h"
#include "world/sprite.h"
#include "world/water.h"
static char _scenarioPath[MAX_PATH];
static const char *_scenarioFileName;
@ -68,10 +69,10 @@ int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *in
// Checks for a scenario string object (possibly for localisation)
if ((info->entry.flags & 0xFF) != 255) {
if (object_get_scenario_text(&info->entry)) {
int ebp = RCT2_GLOBAL(0x009ADAF8, uint32);
format_string(info->name, RCT2_GLOBAL(ebp, sint16), NULL);
format_string(info->details, RCT2_GLOBAL(ebp + 4, sint16), NULL);
RCT2_GLOBAL(0x009AA00C, uint8) = RCT2_GLOBAL(ebp + 6, uint8);
rct_stex_entry* stex_entry = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, rct_stex_entry*);
format_string(info->name, stex_entry->scenario_name, NULL);
format_string(info->details, stex_entry->details, NULL);
RCT2_GLOBAL(0x009AA00C, uint8) = stex_entry->var_06;
object_free_scenario_text();
}
}
@ -81,8 +82,8 @@ int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *in
}
log_error("invalid scenario, %s", path);
// RCT2_GLOBAL(0x009AC31B, sint8) = -1;
// RCT2_GLOBAL(0x009AC31C, sint16) = 3011;
// RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, sint8) = -1;
// RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, sint16) = 3011;
return 0;
}
@ -104,8 +105,8 @@ int scenario_load(const char *path)
if (file != NULL) {
if (!sawyercoding_validate_checksum(file)) {
fclose(file);
RCT2_GLOBAL(0x009AC31B, uint8) = 255;
RCT2_GLOBAL(0x009AC31C, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
log_error("failed to load scenario, invalid checksum");
return 0;
@ -171,7 +172,7 @@ int scenario_load(const char *path)
// Check expansion pack
// RCT2_CALLPROC_EBPSAFE(0x006757E6);
sub_6A9FC0();
reset_loaded_objects();
map_update_tile_pointers();
reset_0x69EBE4();// RCT2_CALLPROC_EBPSAFE(0x0069EBE4);
return 1;
@ -181,8 +182,8 @@ int scenario_load(const char *path)
}
log_error("failed to find scenario file.");
RCT2_GLOBAL(0x009AC31B, uint8) = 255;
RCT2_GLOBAL(0x009AC31C, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
return 0;
}
@ -273,11 +274,10 @@ int scenario_load_and_play_from_path(const char *path)
strcpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, s6Info->details);
strcpy((char*)RCT2_ADDRESS_SCENARIO_NAME, s6Info->name);
if (RCT2_GLOBAL(0x009ADAE4, sint32) != -1) {
char *ebp = RCT2_GLOBAL(0x009ADAE4, char*);
rct_stex_entry* stex = g_stexEntries[0];
if ((int)stex != -1) {
//
format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, RCT2_GLOBAL(ebp + 2, uint16), 0);
format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, stex->park_name, 0);
// Set park name
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_RENAME_PARK;
@ -292,12 +292,12 @@ int scenario_load_and_play_from_path(const char *path)
*((int*)(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER + 28)));
//
format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, RCT2_GLOBAL(ebp + 0, uint16), 0);
format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, stex->scenario_name, 0);
strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, 31);
((char*)RCT2_ADDRESS_SCENARIO_NAME)[31] = '\0';
// Set scenario details
format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, RCT2_GLOBAL(ebp + 4, uint16), 0);
format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, stex->details, 0);
strncpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, 255);
((char*)RCT2_ADDRESS_SCENARIO_DETAILS)[255] = '\0';
}
@ -674,7 +674,7 @@ void scenario_update()
if ((current_days_in_month * next_month_tick) >> 16 != (current_days_in_month * month_tick) >> 16) {
// daily checks
finance_update_daily_profit();
RCT2_CALLPROC_EBPSAFE(0x0069C35E); // some kind of peeps days_visited update loop
peep_update_days_in_queue();
get_local_time();
RCT2_CALLPROC_EBPSAFE(0x0066A13C); // objective 6 dragging
switch (objective_type) {
@ -700,7 +700,9 @@ void scenario_update()
ride_check_all_reachable();
ride_update_favourited_stat();
if (month <= 1 && RCT2_GLOBAL(0x009ADAE0, sint32) != -1 && RCT2_GLOBAL(0x009ADAE0 + 14, uint16) & 1) {
rct_water_type* water_type = (rct_water_type*)object_entry_groups[OBJECT_TYPE_WATER].chunks[0];
if (month <= 1 && (sint32)water_type != -1 && water_type->var_0E & 1) {
// 100 attempts at finding some water to create a few ducks at
for (int i = 0; i < 100; i++) {
if (scenario_create_ducks())
@ -837,11 +839,12 @@ int scenario_prepare_for_save()
s6Info->entry.flags = 255;
char *stex = RCT2_GLOBAL(0x009ADAE4, char*);
if (stex != (char*)0xFFFFFFFF) {
format_string(buffer, RCT2_GLOBAL(stex, uint16), NULL);
rct_stex_entry* stex = g_stexEntries[0];
if ((int)stex != 0xFFFFFFFF) {
format_string(buffer, stex->scenario_name, NULL);
strncpy(s6Info->name, buffer, sizeof(s6Info->name));
s6Info->entry = *((rct_object_entry*)0x00F4287C);
memcpy(&s6Info->entry, &object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].entries[0], sizeof(rct_object_entry));
}
if (s6Info->name[0] == 0)
@ -891,7 +894,7 @@ int scenario_write_packed_objects(FILE *file)
if (RCT2_ADDRESS(0x009ACFA4, uint32)[i] == 0xFFFFFFFF || (entry->flags & 0xF0))
continue;
if (!sub_6A9F42(file, (rct_object_entry*)entry))
if (!write_object_file(file, (rct_object_entry*)entry))
return 0;
}
@ -1130,7 +1133,7 @@ int scenario_save(char *path, int flags)
fclose(file);
if (!(flags & 0x80000000))
RCT2_CALLPROC_EBPSAFE(0x006A9FC0);
reset_loaded_objects();//RCT2_CALLPROC_EBPSAFE(0x006A9FC0);
gfx_invalidate_screen();
RCT2_GLOBAL(0x009DEA66, uint16) = 0;

View File

@ -84,11 +84,14 @@ typedef struct {
} rct_scenario_basic;
typedef struct {
rct_string_id scenario_name;
rct_string_id park_name;
rct_string_id details;
rct_string_id scenario_name; // 0x00
rct_string_id park_name; // 0x02
rct_string_id details; // 0x04
uint8 var_06;
} rct_stex_entry;
#define g_stexEntries ((rct_stex_entry**)object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].chunks)
/* This will be useful for backwards compatibility
typedef struct {
// SC6[0]

View File

@ -163,10 +163,14 @@ int sawyercoding_write_chunk_buffer(uint8 *dst_file, uint8* buffer, sawyercoding
free(encode_buffer);
break;
case CHUNK_ENCODING_ROTATE:
encode_chunk_rotate(buffer, chunkHeader.length);
encode_buffer = malloc(chunkHeader.length);
memcpy(encode_buffer, buffer, chunkHeader.length);
encode_chunk_rotate(encode_buffer, chunkHeader.length);
memcpy(dst_file, &chunkHeader, sizeof(sawyercoding_chunk_header));
dst_file += sizeof(sawyercoding_chunk_header);
memcpy(dst_file, buffer, chunkHeader.length);
memcpy(dst_file, encode_buffer, chunkHeader.length);
free(encode_buffer);
break;
}

View File

@ -571,12 +571,12 @@ static void window_cheats_paint()
window_cheats_draw_tab_images(dpi, w);
if (w->page == WINDOW_CHEATS_PAGE_MONEY){
gfx_draw_string(dpi, language_get_string(2681), 0, w->x + XPL(0) + TXTO, w->y + YPL(0) + TXTO);
gfx_draw_string(dpi, language_get_string(2682), 0, w->x + XPL(0) + TXTO, w->y + YPL(2) + TXTO);
gfx_draw_string(dpi, (char*)language_get_string(2681), 0, w->x + XPL(0) + TXTO, w->y + YPL(0) + TXTO);
gfx_draw_string(dpi, (char*)language_get_string(2682), 0, w->x + XPL(0) + TXTO, w->y + YPL(2) + TXTO);
}
else if (w->page == WINDOW_CHEATS_PAGE_GUESTS){
gfx_draw_string(dpi, language_get_string(2683), 0, w->x + XPL(0) + TXTO, w->y + YPL(0) + TXTO);
gfx_draw_string(dpi, language_get_string(2684), 0, w->x + XPL(0) + TXTO, w->y + YPL(2) + TXTO);
gfx_draw_string(dpi, (char*)language_get_string(2683), 0, w->x + XPL(0) + TXTO, w->y + YPL(0) + TXTO);
gfx_draw_string(dpi, (char*)language_get_string(2684), 0, w->x + XPL(0) + TXTO, w->y + YPL(2) + TXTO);
}
}

View File

@ -207,11 +207,32 @@ void window_editor_bottom_toolbar_jump_back_to_options_selection() {
}
/**
*
* rct2: 0x0066F6B0
*/
void window_editor_bottom_toolbar_jump_forward_from_object_selection() {
RCT2_CALLPROC_EBPSAFE(0x0066f6b0);
*
* rct2: 0x006AB1CE
*/
int window_editor_bottom_toolbar_check_object_selection()
{
return RCT2_CALLPROC_EBPSAFE(0x006AB1CE) & 0x100;
}
/**
*
* rct2: 0x0066F6B0
*/
void window_editor_bottom_toolbar_jump_forward_from_object_selection()
{
if (window_editor_bottom_toolbar_check_object_selection())
return;
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) {
RCT2_CALLPROC_EBPSAFE(0x0066F6E3);
} else {
RCT2_CALLPROC_EBPSAFE(0x006DFED0);
RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
RCT2_GLOBAL(0x00141F570, uint8) = 1;
window_map_open();
gfx_invalidate_screen();
}
}
/**

View File

@ -26,6 +26,7 @@
#include "../localisation/localisation.h"
#include "../object.h"
#include "../ride/track.h"
#include "../scenario.h"
#include "error.h"
enum {
@ -251,7 +252,7 @@ static void window_editor_object_selection_close()
RCT2_CALLPROC_EBPSAFE(0x6ABB66);
editor_load_selected_objects();
sub_6A9FC0();
reset_loaded_objects();
object_free_scenario_text();
RCT2_CALLPROC_EBPSAFE(0x6AB316);
RCT2_CALLPROC_EBPSAFE(0x685675);
@ -571,7 +572,9 @@ static void window_editor_object_selection_paint()
gfx_draw_string_left(dpi, 3164, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y);
}
if (w->selected_list_item == -1 || RCT2_GLOBAL(0x009ADAF8, sint32) == -1)
rct_stex_entry* stex_entry = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, rct_stex_entry*);
if (w->selected_list_item == -1 || stex_entry == NULL)
return;
highlightedEntry = (rct_object_entry*)w->var_494;
@ -581,7 +584,7 @@ static void window_editor_object_selection_paint()
widget = &w->widgets[WIDX_PREVIEW];
x = w->x + (widget->left + widget->right) / 2 + 1;
y = w->y + (widget->top + widget->bottom) / 2 + 1;
object_paint(type, 3, type, x, y, 0, (int)dpi, RCT2_GLOBAL(0x009ADAF8, sint32));
object_paint(type, 3, type, x, y, 0, (int)dpi, (int)stex_entry);
// Draw name of object
x = w->x + (widget->left + widget->right) / 2 + 1;
@ -629,7 +632,7 @@ static void window_editor_object_selection_paint()
// Draw description of object
x = w->x + w->widgets[WIDX_LIST].right + 4;
y += 15;
object_paint(type, 259, type, x, y, (int)w, (int)dpi, RCT2_GLOBAL(0x009ADAF8, sint32));
object_paint(type, 259, type, x, y, (int)w, (int)dpi, (int)stex_entry);
// Draw object dat name
strcpy(stringBuffer, datName);

View File

@ -835,7 +835,7 @@ static void window_editor_objective_options_main_invalidate()
window_get_register(w);
stex = RCT2_GLOBAL(0x009ADAE4, rct_stex_entry*);
stex = g_stexEntries[0];
if (stex == (rct_stex_entry*)0xFFFFFFFF)
stex = NULL;
@ -920,7 +920,7 @@ static void window_editor_objective_options_main_paint()
window_draw_widgets(w, dpi);
window_editor_objective_options_draw_tab_images(w, dpi);
stex = RCT2_GLOBAL(0x009ADAE4, rct_stex_entry*);
stex = g_stexEntries[0];
if (stex == (rct_stex_entry*)0xFFFFFFFF)
stex = NULL;

View File

@ -354,7 +354,7 @@ static void window_footpath_dropdown()
j = 0;
for (i = 0; i < 16; i++) {
pathType = RCT2_ADDRESS(RCT2_ADDRESS_PATH_TYPES, rct_path_type*)[i];
pathType = g_pathTypeEntries[i];
if (pathType == (rct_path_type*)-1)
continue;
if (pathType->flags & flags)
@ -533,7 +533,7 @@ static void window_footpath_invalidate()
// Set footpath and queue type button images
selectedPath = RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, uint16);
pathType = RCT2_ADDRESS(RCT2_ADDRESS_PATH_TYPES, rct_path_type*)[selectedPath];
pathType = g_pathTypeEntries[selectedPath];
int pathImage = 71 + pathType->image;
window_footpath_widgets[WIDX_FOOTPATH_TYPE].image = pathImage;
@ -570,7 +570,7 @@ static void window_footpath_paint()
image = RCT2_ADDRESS(0x0098D7E0, uint8)[image];
selectedPath = RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, uint16);
pathType = RCT2_ADDRESS(RCT2_ADDRESS_PATH_TYPES, rct_path_type*)[selectedPath];
pathType = g_pathTypeEntries[selectedPath];
image += pathType->image;
if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_TYPE, uint8) != SELECTED_PATH_TYPE_NORMAL)
image += 51;
@ -609,7 +609,7 @@ static void window_footpath_show_footpath_types_dialog(rct_window *w, rct_widget
flags = 0;
for (i = 0; i < 16; i++) {
pathType = RCT2_ADDRESS(RCT2_ADDRESS_PATH_TYPES, rct_path_type*)[i];
pathType = g_pathTypeEntries[i];
if (pathType == (rct_path_type*)-1)
continue;
if (pathType->flags & flags)

View File

@ -115,13 +115,13 @@ static void* window_guest_list_events[] = {
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 int _window_guest_list_highlighted_index; // 0x00F1EE10
static int _window_guest_list_selected_tab; // 0x00F1EE12
static int _window_guest_list_selected_filter; // 0x00F1EE06
static int _window_guest_list_selected_page; // 0x00F1EE07
static int _window_guest_list_selected_view; // 0x00F1EE13
static int _window_guest_list_num_pages; // 0x00F1EE08
static int _window_guest_list_num_groups; // 0x00F1AF22
static uint16 _window_guest_list_groups_num_guests[240];
static uint32 _window_guest_list_groups_argument_1[240];
@ -178,6 +178,93 @@ void window_guest_list_open()
window->colours[2] = 15;
}
/**
* type == 0 -> guests on ride
* type == 1 -> guests in queue
* type == 2 -> guests thinking about ride
* type == 3 -> guests thinking X, opened from news item
* index is number of the ride or index of the thought
* values of eax and edx probably determine the filter name string
*
* rct2: 0x006993BA
*/
void window_guest_list_open_with_filter(int type, int index)
{
//RCT2_CALLPROC_X(0x006993BA, type, ebx, 0, 0, 0, 0, 0);
uint32 eax, edx;
window_guest_list_open();
_window_guest_list_selected_page = 0;
_window_guest_list_num_pages = 1;
RCT2_GLOBAL(0x009AC7E0, uint8) = 0;
RCT2_GLOBAL(0x009AC7F0, uint8) = 0;
rct_ride *ride;
if (type != 3) { // common for cases 0, 1, 2
ride = GET_RIDE(index & 0x000000FF);
eax = ride->name;
edx = ride->name_arguments;
}
switch(type)
{
case 0:
_window_guest_list_selected_filter = 0;
eax = (eax << 16) + 1435;
if ((RCT2_GLOBAL(0x97CF40 + ride->type * 8, uint32) & 0x400000) != 0)
eax++;
RCT2_GLOBAL(0x00F1EDF6, uint32) = eax;
RCT2_GLOBAL(0x00F1EDFA, uint32) = edx;
_window_guest_list_highlighted_index = 0xFFFF;
_window_guest_list_selected_tab = 0;
_window_guest_list_selected_view = 0;
break;
case 1:
_window_guest_list_selected_filter = 0;
eax = (eax << 16) + 1433;
RCT2_GLOBAL(0x00F1EDF6, uint32) = eax;
RCT2_GLOBAL(0x00F1EDFA, uint32) = edx;
_window_guest_list_highlighted_index = 0xFFFF;
_window_guest_list_selected_tab = 0;
_window_guest_list_selected_view = 0;
break;
case 2:
_window_guest_list_selected_filter = 1;
eax = (eax << 16) + 0xFFFF;
RCT2_GLOBAL(0x00F1EDF6, uint32) = eax;
RCT2_GLOBAL(0x00F1EDFA, uint32) = edx;
_window_guest_list_highlighted_index = 0xFFFF;
_window_guest_list_selected_tab = 0;
_window_guest_list_selected_view = 1;
break;
case 3:
_window_guest_list_selected_filter = 1;
index = (index & 0x000000FF) + 1480;
RCT2_GLOBAL(0x00F1EDF6, uint32) = index;
RCT2_GLOBAL(0x00F1EDFA, uint32) = 0;
_window_guest_list_highlighted_index = 0xFFFF;
_window_guest_list_selected_tab = 0;
_window_guest_list_selected_view = 1;
break;
}
}
/**
*
* rct2: 0x00699AAF
@ -719,7 +806,7 @@ static int window_guest_list_is_peep_in_filter(rct_peep* peep)
_window_guest_list_selected_view = temp;
if (((RCT2_GLOBAL(0x00F1EDF6, uint32) >> 16) & 0xFFFF) == 0xFFFF && _window_guest_list_selected_filter == 1)
if (RCT2_GLOBAL(0x00F1EDF6, uint16) == 0xFFFF && _window_guest_list_selected_filter == 1)
argument1 |= 0xFFFF;
if (argument1 == RCT2_GLOBAL(0x00F1EDF6, uint32) && argument2 == RCT2_GLOBAL(0x00F1EDFA, uint32))

View File

@ -203,6 +203,8 @@ static void window_map_close()
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, uint16) == w->number) {
tool_cancel();
}
//Reset land tool size
RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 0;
}
/**
@ -231,9 +233,11 @@ static void window_map_mouseup()
//RCT2_CALLPROC_EBPSAFE(0x0068CFC1);
sint16 var_idx;
rct_window* var_w;
//Maximum land ownership tool size
int land_tool_limit;
window_widget_get_registers(var_w, var_idx);
switch (var_idx)
{
case WIDX_CLOSE:
@ -290,18 +294,20 @@ static void window_map_mouseup()
case WIDX_LAND_TOOL_SMALLER:
--RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16);
land_tool_limit=1;
if (RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) < 1)
RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 1;
if (RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) < land_tool_limit)
RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = land_tool_limit;
window_invalidate(var_w);
break;
case WIDX_LAND_TOOL_LARGER:
++RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16);
land_tool_limit=64;
if (RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) > 7)
RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 7;
if (RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) > land_tool_limit)
RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = land_tool_limit;
window_invalidate(var_w);
break;
@ -538,8 +544,8 @@ static void window_map_invalidate()
w->widgets[WIDX_LAND_TOOL_LARGER].type = WWT_TRNBTN;
for (i = 0; i < 4; i++)
w->widgets[WIDX_LAND_OWNED_CHECKBOX + i].type = WWT_CHECKBOX;
w->widgets[WIDX_LAND_TOOL].image = SPR_LAND_TOOL_SIZE_0 +
RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, uint16);
w->widgets[WIDX_LAND_TOOL].image = RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, uint16) <= 7 ? SPR_LAND_TOOL_SIZE_0 +
RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, uint16) : 0xFFFFFFFF;
}
// if no tool is active: show the default scenario editor buttons
} else {
@ -563,6 +569,20 @@ static void window_map_paint()
window_draw_widgets(w, dpi);
x = w->x + (window_map_widgets[WIDX_LAND_TOOL].left + window_map_widgets[WIDX_LAND_TOOL].right) / 2;
y = w->y + (window_map_widgets[WIDX_LAND_TOOL].top + window_map_widgets[WIDX_LAND_TOOL].bottom) / 2;
// FEATURE larger land tool size support
if ((RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) > 7) &&
(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == WC_MAP)) {
RCT2_GLOBAL(0x009BC677, char) = FORMAT_BLACK;
RCT2_GLOBAL(0x009BC678, char) = FORMAT_COMMA16;
RCT2_GLOBAL(0x009BC679, char) = 0;
RCT2_GLOBAL(0x013CE952, sint16) = RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16);
gfx_draw_string_centred(dpi, 3165, x, y - 2, 0, (void*)0x013CE952);
}
y = w->y + window_map_widgets[WIDX_LAND_TOOL].bottom + 5;
// guest tab image (animated)
image_id = SPR_TAB_GUESTS_0;
if (w->selected_tab == 0)
@ -606,8 +626,8 @@ static void window_map_paint()
}
} else {
if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) &&
(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) != WC_MAP) &&
(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint8) != WIDX_SET_LAND_RIGHTS))
(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == WC_MAP) &&
(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint8) == WIDX_SET_LAND_RIGHTS))
return;
gfx_draw_string_left(dpi, STR_MAP_SIZE, 0, 0, w->x + 4, w->y + w->widgets[WIDX_MAP_SIZE_SPINNER].top + 1);
@ -887,4 +907,4 @@ static void window_map_center_on_view_point()
w_map->scrolls[0].h_left = cx;
w_map->scrolls[0].v_top = dx;
widget_scroll_update_thumbs(w_map, WIDX_MAP);
}
}

View File

@ -173,7 +173,7 @@ void window_new_campaign_open(sint16 campaignType)
numApplicableRides = 0;
window_new_campaign_rides[0] = 255;
FOR_ALL_RIDES(i, ride) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x03820000))
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP | RIDE_TYPE_FLAG_23 | RIDE_TYPE_FLAG_SELLS_DRINKS | RIDE_TYPE_FLAG_IS_BATHROOM))
window_new_campaign_rides[numApplicableRides++] = i;
}

View File

@ -849,13 +849,13 @@ static void window_new_ride_scrollpaint()
// Draw ride image
rideEntry = rideEntries[listItem->entry_index];
int unk = rideEntry->var_004;
int image_id = rideEntry->images_offset;
if (listItem->type != rideEntry->var_00C) {
unk++;
image_id++;
if (listItem->type != rideEntry->var_00D)
unk++;
image_id++;
}
RCT2_CALLPROC_X(0x00681DE2, 0, 29013, x + 2, y + 2, 0xA0, (int)dpi, unk);
RCT2_CALLPROC_X(0x00681DE2, 0, 29013, x + 2, y + 2, 0xA0, (int)dpi, image_id);
// Next position
x += 116;
@ -934,8 +934,7 @@ static void window_new_ride_paint_ride_information(rct_window *w, rct_drawpixeli
gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, width, 1690, 0);
// Number of designs available
uint32 rideTypeFlags = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (item.type * 8), uint32);
if (rideTypeFlags & 0x10000000) {
if (ride_type_has_flag(item.type, RIDE_TYPE_FLAG_HAS_TRACK)) {
if (item.type != _lastTrackDesignCountRideType.type || item.entry_index != _lastTrackDesignCountRideType.entry_index) {
_lastTrackDesignCountRideType = item;
_lastTrackDesignCount = get_num_track_designs(item);
@ -961,7 +960,7 @@ static void window_new_ride_paint_ride_information(rct_window *w, rct_drawpixeli
// Get price of ride
int unk2 = RCT2_GLOBAL(0x0097CC68 + (item.type * 2), uint8);
money32 price = RCT2_GLOBAL(0x0097DD78 + (item.type * 4), uint16);
if (rideTypeFlags & 0x80000) {
if (ride_type_has_flag(item.type, RIDE_TYPE_FLAG_SELLS_FOOD)) {
price *= RCT2_ADDRESS(0x0099DE34, uint32)[unk2];
} else {
price *= RCT2_ADDRESS(0x0099DA34, uint32)[unk2];
@ -970,7 +969,7 @@ static void window_new_ride_paint_ride_information(rct_window *w, rct_drawpixeli
//
rct_string_id stringId = 1691;
if (!(rideTypeFlags & 0x8000))
if (!ride_type_has_flag(item.type, RIDE_TYPE_FLAG_15))
stringId++;
gfx_draw_string_right(dpi, stringId, &price, 0, x + width, y + 40);
@ -989,8 +988,7 @@ static void window_new_ride_select(rct_window *w)
window_close(w);
uint32 rideTypeFlags = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (item.type * 8), uint32);
if (rideTypeFlags & 0x10000000) {
if (ride_type_has_flag(item.type, RIDE_TYPE_FLAG_HAS_TRACK)) {
track_load_list(item);
uint8 *trackDesignList = (uint8*)0x00F441EC;

View File

@ -82,17 +82,15 @@ enum WINDOW_OPTIONS_WIDGET_IDX {
WIDX_SOUND,
WIDX_SOUND_DROPDOWN,
WIDX_MUSIC,
WIDX_MUSIC_DROPDOWN,
WIDX_SOUND_QUALITY,
WIDX_SOUND_QUALITY_DROPDOWN,
WIDX_SOUND_SW_BUFFER_CHECKBOX,
WIDX_SOUND_PAUSED_CHECKBOX,
WIDX_SOUND_CHECKBOX,
WIDX_MUSIC_CHECKBOX,
WIDX_TITLE_MUSIC,
WIDX_TITLE_MUSIC_DROPDOWN,
WIDX_SCREEN_EDGE_SCROLLING,
WIDX_HOTKEY_DROPDOWN,
WIDX_TOOLBAR_SHOW_FINANCES,
WIDX_TOOLBAR_SHOW_RESEARCH,
WIDX_REAL_NAME_CHECKBOX,
WIDX_SAVE_PLUGIN_DATA_CHECKBOX,
@ -139,18 +137,16 @@ static rct_widget window_options_widgets[] = {
// Audio tab
{ WWT_DROPDOWN, 0, 10, 299, 53, 64, 865, STR_NONE }, // sound
{ WWT_DROPDOWN_BUTTON, 0, 288, 298, 54, 63, 876, STR_NONE },
{ WWT_DROPDOWN, 0, 155, 299, 68, 79, 869, STR_NONE }, // music
{ WWT_DROPDOWN_BUTTON, 0, 288, 298, 69, 78, 876, STR_NONE },
{ WWT_DROPDOWN, 0, 155, 299, 83, 94, 870, STR_NONE }, // sound quality
{ WWT_DROPDOWN_BUTTON, 0, 288, 298, 84, 93, 876, STR_NONE },
{ WWT_CHECKBOX, 0, 10, 299, 99, 110, STR_SOUND_FORCED_SOFTWARE_BUFFER_MIXING, STR_SOUND_FORCED_SOFTWARE_BUFFER_MIXING_TIP },
{ WWT_CHECKBOX, 0, 10, 229, 114, 125, STR_SOUND, STR_NONE }, // enable/disable sound
{ WWT_DROPDOWN, 0, 155, 299, 130, 141, STR_NONE, STR_NONE }, // title music
{ WWT_DROPDOWN_BUTTON, 0, 288, 298, 131, 140, 876, STR_NONE },
{ WWT_CHECKBOX, 0, 10, 229, 68, 79, STR_SOUND, STR_NONE }, // enable / disable sound
{ WWT_CHECKBOX, 0, 10, 229, 83, 94, STR_MUSIC, STR_NONE }, // enable / disable music
{ WWT_DROPDOWN, 0, 155, 299, 98, 109, STR_NONE, STR_NONE }, // title music
{ WWT_DROPDOWN_BUTTON, 0, 288, 298, 99, 108, 876, STR_NONE },
// Controls tab
{ WWT_CHECKBOX, 2, 10, 299, 53, 64, STR_SCREEN_EDGE_SCROLLING, STR_SCREEN_EDGE_SCROLLING_TIP },
{ WWT_DROPDOWN_BUTTON, 0, 26, 185, 68, 78, STR_HOTKEY, STR_HOTKEY_TIP },
{ WWT_CHECKBOX, 2, 10, 299, 82, 93, 5120, STR_NONE },
{ WWT_CHECKBOX, 2, 10, 299, 97, 108, 5121, STR_NONE },
// Misc
{ WWT_CHECKBOX, 2, 10, 299, 53, 64, STR_REAL_NAME, STR_REAL_NAME_TIP },
@ -233,10 +229,8 @@ void window_options_open()
(1ULL << WIDX_TAB_5) |
(1ULL << WIDX_SOUND) |
(1ULL << WIDX_SOUND_DROPDOWN) |
(1ULL << WIDX_MUSIC) |
(1ULL << WIDX_MUSIC_DROPDOWN) |
(1ULL << WIDX_SOUND_QUALITY) |
(1ULL << WIDX_SOUND_QUALITY_DROPDOWN) |
(1ULL << WIDX_SOUND_CHECKBOX) |
(1ULL << WIDX_MUSIC_CHECKBOX) |
(1ULL << WIDX_TITLE_MUSIC) |
(1ULL << WIDX_TITLE_MUSIC_DROPDOWN) |
(1ULL << WIDX_LANGUAGE) |
@ -253,6 +247,8 @@ void window_options_open()
(1ULL << WIDX_TEMPERATURE_DROPDOWN) |
(1ULL << WIDX_HOTKEY_DROPDOWN) |
(1ULL << WIDX_SCREEN_EDGE_SCROLLING) |
(1ULL << WIDX_TOOLBAR_SHOW_FINANCES) |
(1ULL << WIDX_TOOLBAR_SHOW_RESEARCH) |
(1ULL << WIDX_REAL_NAME_CHECKBOX) |
(1ULL << WIDX_CONSTRUCTION_MARKER) |
(1ULL << WIDX_CONSTRUCTION_MARKER_DROPDOWN) |
@ -260,8 +256,6 @@ void window_options_open()
(1ULL << WIDX_HEIGHT_LABELS_DROPDOWN) |
(1ULL << WIDX_TILE_SMOOTHING_CHECKBOX) |
(1ULL << WIDX_GRIDLINES_CHECKBOX) |
(1ULL << WIDX_SOUND_SW_BUFFER_CHECKBOX) |
(1ULL << WIDX_SOUND_PAUSED_CHECKBOX) |
(1ULL << WIDX_SAVE_PLUGIN_DATA_CHECKBOX) |
(1ULL << WIDX_AUTOSAVE) |
(1ULL << WIDX_AUTOSAVE_DROPDOWN);
@ -303,6 +297,18 @@ static void window_options_mouseup()
config_save_default();
window_invalidate(w);
break;
case WIDX_TOOLBAR_SHOW_FINANCES:
gConfigInterface.toolbar_show_finances ^= 1;
config_save_default();
window_invalidate(w);
window_invalidate_by_class(WC_TOP_TOOLBAR);
break;
case WIDX_TOOLBAR_SHOW_RESEARCH:
gConfigInterface.toolbar_show_research ^= 1;
config_save_default();
window_invalidate(w);
window_invalidate_by_class(WC_TOP_TOOLBAR);
break;
case WIDX_REAL_NAME_CHECKBOX:
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) ^= PARK_FLAGS_SHOW_REAL_GUEST_NAMES;
RCT2_CALLPROC_X(0x0069C52F, RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_SHOW_REAL_GUEST_NAMES ? 0 : 1, 0, 0, 0, 0, 0, 0);
@ -328,20 +334,17 @@ static void window_options_mouseup()
config_save_default();
window_invalidate(w);
break;
case WIDX_SOUND_SW_BUFFER_CHECKBOX:
pause_sounds();
gConfigSound.forced_software_buffering ^= 1;
config_save_default();
unpause_sounds();
window_invalidate(w);
break;
case WIDX_SOUND_PAUSED_CHECKBOX:
case WIDX_SOUND_CHECKBOX:
if (g_sounds_disabled)
unpause_sounds();
else
pause_sounds();
window_invalidate(w);
break;
case WIDX_MUSIC_CHECKBOX:
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) ^= 1;
window_invalidate(w);
break;
}
}
@ -379,28 +382,6 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
gDropdownItemsChecked = gConfigGeneral.show_height_as_units ? 1 : 2;
break;
case WIDX_MUSIC_DROPDOWN:
gDropdownItemsFormat[0] = 1142;
gDropdownItemsFormat[1] = 1142;
gDropdownItemsArgs[0] = STR_OFF;
gDropdownItemsArgs[1] = STR_ON;
window_options_show_dropdown(w, widget, 2);
gDropdownItemsChecked = 1 << RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8);
break;
case WIDX_SOUND_QUALITY_DROPDOWN:
num_items = 3;
for (i = 0; i < num_items; i++) {
gDropdownItemsFormat[i] = 1142;
gDropdownItemsArgs[i] = STR_SOUND_LOW + i; // low, medium, high
}
window_options_show_dropdown(w, widget, num_items);
gDropdownItemsChecked = 1 << gConfigSound.sound_quality;
break;
case WIDX_TITLE_MUSIC_DROPDOWN:
num_items = 3;
@ -561,19 +542,6 @@ static void window_options_dropdown()
window_options_update_height_markers();
break;
case WIDX_MUSIC_DROPDOWN:
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) = (uint8)dropdownIndex;
config_save_default();
stop_ride_music();//RCT2_CALLPROC_EBPSAFE(0x006BCA9F);
window_invalidate(w);
break;
case WIDX_SOUND_QUALITY_DROPDOWN:
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MAX_VEHICLE_SOUNDS, uint8) = RCT2_GLOBAL(0x009AF601 + dropdownIndex, uint8);
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MAX_NO_SOUNDS, uint8) = RCT2_GLOBAL(0x009AF604 + dropdownIndex, uint8);
gConfigSound.sound_quality = (sint8)dropdownIndex;
config_save_default();
window_invalidate(w);
break;
case WIDX_TITLE_MUSIC_DROPDOWN:
if (dropdownIndex == 1 && !platform_file_exists(get_file_path(PATH_ID_CSS50))) {
window_error_open(2742, 2743);
@ -752,38 +720,25 @@ static void window_options_invalidate()
// sound quality: low/medium/high
RCT2_GLOBAL(0x013CE952 + 10, uint16) = STR_SOUND_LOW + gConfigSound.sound_quality;
//Sound pause checkbox
if (!g_sounds_disabled)
w->pressed_widgets |= (1ULL << WIDX_SOUND_PAUSED_CHECKBOX);
else
w->pressed_widgets &= ~(1ULL << WIDX_SOUND_PAUSED_CHECKBOX);
// sound software mixing buffer checkbox
if (gConfigSound.forced_software_buffering)
w->pressed_widgets |= (1ULL << WIDX_SOUND_SW_BUFFER_CHECKBOX);
else
w->pressed_widgets &= ~(1ULL << WIDX_SOUND_SW_BUFFER_CHECKBOX);
widget_set_checkbox_value(w, WIDX_SOUND_CHECKBOX, !g_sounds_disabled);
widget_set_checkbox_value(w, WIDX_MUSIC_CHECKBOX, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8));
window_options_widgets[WIDX_SOUND].type = WWT_DROPDOWN;
window_options_widgets[WIDX_SOUND_DROPDOWN].type = WWT_DROPDOWN_BUTTON;
window_options_widgets[WIDX_MUSIC].type = WWT_DROPDOWN;
window_options_widgets[WIDX_MUSIC_DROPDOWN].type = WWT_DROPDOWN_BUTTON;
window_options_widgets[WIDX_SOUND_QUALITY].type = WWT_DROPDOWN;
window_options_widgets[WIDX_SOUND_QUALITY_DROPDOWN].type = WWT_DROPDOWN_BUTTON;
window_options_widgets[WIDX_SOUND_SW_BUFFER_CHECKBOX].type = WWT_CHECKBOX;
window_options_widgets[WIDX_SOUND_PAUSED_CHECKBOX].type = WWT_CHECKBOX;
window_options_widgets[WIDX_SOUND_CHECKBOX].type = WWT_CHECKBOX;
window_options_widgets[WIDX_MUSIC_CHECKBOX].type = WWT_CHECKBOX;
window_options_widgets[WIDX_TITLE_MUSIC].type = WWT_DROPDOWN;
window_options_widgets[WIDX_TITLE_MUSIC_DROPDOWN].type = WWT_DROPDOWN_BUTTON;
break;
case WINDOW_OPTIONS_PAGE_INPUT:
// screen edge scrolling checkbox
if (gConfigGeneral.edge_scrolling)
w->pressed_widgets |= (1ULL << WIDX_SCREEN_EDGE_SCROLLING);
else
w->pressed_widgets &= ~(1ULL << WIDX_SCREEN_EDGE_SCROLLING);
widget_set_checkbox_value(w, WIDX_SCREEN_EDGE_SCROLLING, gConfigGeneral.edge_scrolling);
widget_set_checkbox_value(w, WIDX_TOOLBAR_SHOW_FINANCES, gConfigInterface.toolbar_show_finances);
widget_set_checkbox_value(w, WIDX_TOOLBAR_SHOW_RESEARCH, gConfigInterface.toolbar_show_research);
window_options_widgets[WIDX_SCREEN_EDGE_SCROLLING].type = WWT_CHECKBOX;
window_options_widgets[WIDX_HOTKEY_DROPDOWN].type = WWT_DROPDOWN_BUTTON;
window_options_widgets[WIDX_TOOLBAR_SHOW_FINANCES].type = WWT_CHECKBOX;
window_options_widgets[WIDX_TOOLBAR_SHOW_RESEARCH].type = WWT_CHECKBOX;
break;
case WINDOW_OPTIONS_PAGE_MISC:
// real name checkbox
@ -803,7 +758,7 @@ static void window_options_invalidate()
w->disabled_widgets |= (1ULL << WIDX_REAL_NAME_CHECKBOX);
// save plugin data checkbox: visible or not
if (RCT2_GLOBAL(0x00F42BDA, uint8) == 1)
if (RCT2_GLOBAL(RCT2_ADDRESS_CUSTOM_OBJECTS_INSTALLED, uint8) == 1)
window_options_widgets[WIDX_SAVE_PLUGIN_DATA_CHECKBOX].type = WWT_EMPTY;
else
window_options_widgets[WIDX_SAVE_PLUGIN_DATA_CHECKBOX].type = WWT_CHECKBOX;
@ -863,8 +818,6 @@ static void window_options_paint()
gfx_draw_string_left(dpi, STR_HEIGHT_LABELS, w, 0, w->x + 10, w->y + window_options_widgets[WIDX_HEIGHT_LABELS].top + 1);
break;
case WINDOW_OPTIONS_PAGE_AUDIO:
gfx_draw_string_left(dpi, STR_MUSIC, w, 0, w->x + 10, w->y + window_options_widgets[WIDX_MUSIC].top + 1);
gfx_draw_string_left(dpi, STR_SOUND_QUALITY, w, 0, w->x + 10, w->y + window_options_widgets[WIDX_SOUND_QUALITY].top + 1);
gfx_draw_string_left(dpi, 2738, w, 12, w->x + 10, w->y + window_options_widgets[WIDX_TITLE_MUSIC].top + 1);
gfx_draw_string_left(
dpi,

View File

@ -28,10 +28,12 @@
#include "../peep/staff.h"
#include "../ride/ride.h"
#include "../ride/ride_data.h"
#include "../ride/track.h"
#include "../sprites.h"
#include "../windows/error.h"
#include "../world/map.h"
#include "../world/sprite.h"
#include "../audio/audio.h"
#include "dropdown.h"
#define var_496(w) RCT2_GLOBAL((int)w + 0x496, uint16)
@ -994,7 +996,6 @@ static void window_ride_draw_tab_vehicle(rct_drawpixelinfo *dpi, rct_window *w)
rct_ride *ride;
rct_widget *widget;
int widgetIndex, spriteIndex, x, y, width, height;
uint8 *ebp;
rct_ride_type *rideEntry;
vehicle_colour vehicleColour;
@ -1033,18 +1034,18 @@ static void window_ride_draw_tab_vehicle(rct_drawpixelinfo *dpi, rct_window *w)
dpi->y *= 2;
}
ebp = (uint8*)rideEntry + (RCT2_ADDRESS(0x00F64E38, uint8)[rideEntry->var_013] * 101);
height += RCT2_GLOBAL(ebp + 0x24, sint8);
rct_ride_type_vehicle* rideVehicleEntry = &rideEntry->vehicles[RCT2_ADDRESS(0x00F64E38, uint8)[rideEntry->var_013]];
height += rideVehicleEntry->var_0A;
vehicleColour = ride_get_vehicle_colour(ride, 0);
spriteIndex = 32;
if (w->page == WINDOW_RIDE_PAGE_VEHICLE)
spriteIndex += w->frame_no;
spriteIndex /= (RCT2_GLOBAL(ebp + 0x2C, uint16) & 0x800) ? 4 : 2;
spriteIndex &= RCT2_GLOBAL(ebp + 0x1A, uint16);
spriteIndex *= RCT2_GLOBAL(ebp + 0x30, uint16);
spriteIndex += RCT2_GLOBAL(ebp + 0x32, uint32);
spriteIndex /= (rideVehicleEntry->var_12 & 0x800) ? 4 : 2;
spriteIndex &= rideVehicleEntry->var_00;
spriteIndex *= rideVehicleEntry->var_16;
spriteIndex += rideVehicleEntry->base_image_id;
spriteIndex |= (vehicleColour.additional_1 << 24) | (vehicleColour.main << 19);
spriteIndex |= 0x80000000;
@ -1094,6 +1095,54 @@ static void window_ride_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w)
window_ride_draw_tab_image(dpi, w, WINDOW_RIDE_PAGE_MUSIC, 5335);
}
/**
*
* rct2: 0x006AEB9F
*/
void window_ride_disable_tabs(rct_window *w)
{
//RCT2_CALLPROC_X(0x006AEB9F, 0, 0, 0, 0, (int)w, 0, 0);
uint32 disabled_tabs = 0;
rct_ride *ride = GET_RIDE(w->number & 0xFF);
uint8 ride_type = ride->type; // ecx
if ((RCT2_GLOBAL(0x97CF40 + ride_type * 8, uint32) & 0x200) == 0)
disabled_tabs |= (1 << WIDX_TAB_8); // 0x800
if (ride_type == RIDE_TYPE_MINI_GOLF)
disabled_tabs |= (1 << WIDX_TAB_2 | 1 << WIDX_TAB_3 | 1 << WIDX_TAB_4); // 0xE0
if ((RCT2_GLOBAL(0x97CF40 + ride_type * 8, uint32) & 0x2000) != 0)
disabled_tabs |= (1 << WIDX_TAB_2); // 0x20
if ((RCT2_GLOBAL(0x97CF40 + ride_type * 8, uint32) & 0x4000007) == 0 &&
(RCT2_GLOBAL(0x97D4F2 + ride_type * 8, uint16) & 0x20) == 0)
disabled_tabs |= (1 << WIDX_TAB_5); // 0x100
if ((RCT2_GLOBAL(0x97CF40 + ride_type * 8, uint32) & 0x20000) != 0)
disabled_tabs |= (1 << WIDX_TAB_3 | 1 << WIDX_TAB_4 | 1 << WIDX_TAB_7); // 0x4C0
if ((RCT2_GLOBAL(0x97D4F2 + ride_type * 8, uint32) & 0x4) == 0)
disabled_tabs |= (1 << WIDX_TAB_6); // 0x200
if (ride_type == RIDE_TYPE_ATM ||
ride_type == RIDE_TYPE_FIRST_AID ||
(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) != 0)
disabled_tabs |= (1 << WIDX_TAB_9); // 0x1000
if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint32) & SCREEN_FLAGS_TRACK_DESIGNER) != 0)
disabled_tabs |= (1 << WIDX_TAB_4 | 1 << WIDX_TAB_6 | 1 << WIDX_TAB_9 | 1 << WIDX_TAB_10); // 0x3280
rct_ride_type *type = GET_RIDE_ENTRY(ride->subtype);
if ((type->var_008 & 0x80000) != 0)
disabled_tabs |= (1 << WIDX_TAB_5); // 0x100
w->disabled_widgets = disabled_tabs;
}
/**
*
* rct2: 0x006AEAB4
@ -1116,7 +1165,7 @@ rct_window *window_ride_open(int rideIndex)
w->list_information_type = 0;
w->var_492 = 0;
w->var_494 = 0;
RCT2_CALLPROC_X(0x006AEB9F, 0, 0, 0, 0, (int)w, 0, 0);
window_ride_disable_tabs(w);
w->min_width = 316;
w->min_height = 180;
w->max_width = 500;
@ -1172,7 +1221,7 @@ rct_window *window_ride_main_open(int rideIndex)
w->hold_down_widgets = window_ride_page_hold_down_widgets[WINDOW_RIDE_PAGE_MAIN];
w->event_handlers = window_ride_page_events[WINDOW_RIDE_PAGE_MAIN];
w->pressed_widgets = 0;
RCT2_CALLPROC_X(0x006AEB9F, 0, 0, 0, 0, (int)w, 0, 0);
window_ride_disable_tabs(w);
window_init_scroll_widgets(w);
w->ride.view = 0;
window_ride_init_viewport(w);
@ -1192,7 +1241,7 @@ rct_window *window_ride_open_station(int rideIndex, int stationIndex)
ride = GET_RIDE(rideIndex);
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x2000)
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_13))
return window_ride_main_open(rideIndex);
w = window_bring_to_front_by_number(WC_RIDE, rideIndex);
@ -1219,7 +1268,7 @@ rct_window *window_ride_open_station(int rideIndex, int stationIndex)
w->hold_down_widgets = window_ride_page_hold_down_widgets[w->page];
w->event_handlers = window_ride_page_events[w->page];
w->pressed_widgets = 0;
RCT2_CALLPROC_X(0x006AEB9F, 0, 0, 0, 0, (int)w, 0, 0);
window_ride_disable_tabs(w);
window_init_scroll_widgets(w);
// View
@ -1328,7 +1377,7 @@ rct_window *window_ride_open_vehicle(rct_vehicle *vehicle)
w->hold_down_widgets = window_ride_page_hold_down_widgets[w->page];
w->event_handlers = window_ride_page_events[w->page];
w->pressed_widgets = 0;
RCT2_CALLPROC_X(0x006AEB9F, 0, 0, 0, 0, (int)w, 0, 0);
window_ride_disable_tabs(w);
window_init_scroll_widgets(w);
w->ride.view = view;
@ -1368,7 +1417,7 @@ static void window_ride_set_page(rct_window *w, int page)
w->event_handlers = window_ride_page_events[page];
w->pressed_widgets = 0;
w->widgets = window_ride_page_widgets[page];
RCT2_CALLPROC_X(0x006AEB9F, 0, 0, 0, 0, (int)w, 0, 0);
window_ride_disable_tabs(w);
window_invalidate(w);
RCT2_CALLPROC_X(w->event_handlers[WE_RESIZE], 0, 0, 0, 0, (int)w, 0, 0);
@ -1460,9 +1509,8 @@ static void window_ride_init_viewport(rct_window *w)
focus.coordinate.z = map_element_height(focus.coordinate.x, focus.coordinate.y) & 0xFFFF;
focus.sprite.type |= 0x40;
focus.coordinate.zoom = 1;
if (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x8000){
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_15))
focus.coordinate.zoom = 0;
}
}
focus.coordinate.var_480 = w->viewport_focus_coordinates.var_480;
@ -1633,7 +1681,7 @@ static void window_ride_show_view_dropdown(rct_window *w, rct_widget *widget)
ride = GET_RIDE(w->number);
numItems = 1;
if (!(RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x2000)) {
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_13)) {
numItems += ride->num_stations;
numItems += ride->num_vehicles;
}
@ -1698,7 +1746,7 @@ static void window_ride_show_open_dropdown(rct_window *w, rct_widget *widget)
gDropdownItemsArgs[numItems] = STR_CLOSE_RIDE;
numItems++;
if (!(RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x800)) {
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE)) {
gDropdownItemsFormat[numItems] = 1142;
gDropdownItemsArgs[numItems] = STR_TEST_RIDE;
numItems++;
@ -1725,7 +1773,7 @@ static void window_ride_show_open_dropdown(rct_window *w, rct_widget *widget)
break;
highlightedIndex = 2;
if (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x800)
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE))
break;
if (ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)
break;
@ -1747,7 +1795,7 @@ static void window_ride_show_open_dropdown(rct_window *w, rct_widget *widget)
if (checkedIndex != RIDE_STATUS_CLOSED)
checkedIndex = 3 - checkedIndex;
if (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x800) {
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE)) {
if (checkedIndex != 0)
checkedIndex--;
if (highlightedIndex != 0)
@ -1809,7 +1857,7 @@ static void window_ride_main_dropdown()
dropdownIndex = RCT2_GLOBAL(0x009DEBA2, sint16);
ride = GET_RIDE(w->number);
if ((RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x800) && dropdownIndex != 0)
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE) && dropdownIndex != 0)
dropdownIndex++;
switch (dropdownIndex) {
@ -2508,7 +2556,7 @@ static void window_ride_vehicle_scrollpaint()
rct_ride *ride;
rct_ride_type *rideEntry;
rct_widget *widget;
int x, y, startX, startY, i, j, vehicleColourIndex, spriteIndex, ebp;
int x, y, startX, startY, i, j, vehicleColourIndex, spriteIndex;
rct_vehichle_paintinfo *nextSpriteToDraw, *current, tmp;
vehicle_colour vehicleColour;
@ -2526,8 +2574,8 @@ static void window_ride_vehicle_scrollpaint()
startX = max(2, ((widget->right - widget->left) - ((ride->num_vehicles - 1) * 36)) / 2 - 25);
startY = widget->bottom - widget->top - 4;
ebp = (int)rideEntry + (RCT2_ADDRESS(0x00F64E38, uint8)[0] * 101);
startY += RCT2_GLOBAL(ebp + 0x24, sint8);
rct_ride_type_vehicle* rideVehicleEntry = &rideEntry->vehicles[RCT2_ADDRESS(0x00F64E38, uint8)[0]];
startY += rideVehicleEntry->var_0A;
// For each train
for (i = 0; i < ride->num_vehicles; i++) {
@ -2537,9 +2585,9 @@ static void window_ride_vehicle_scrollpaint()
// For each car in train
for (j = 0; j < ride->num_cars_per_train; j++) {
int ebp = (int)rideEntry + (RCT2_ADDRESS(0x00F64E38, uint8)[j] * 101);
x += RCT2_GLOBAL(ebp + 0x1E, uint32) / 17432;
y -= (RCT2_GLOBAL(ebp + 0x1E, uint32) / 2) / 17432;
rct_ride_type_vehicle* rideVehicleEntry = &rideEntry->vehicles[RCT2_ADDRESS(0x00F64E38, uint8)[j]];
x += rideVehicleEntry->var_04 / 17432;
y -= (rideVehicleEntry->var_04 / 2) / 17432;
// Get colour of vehicle
switch (ride->colour_scheme_type & 3) {
@ -2556,12 +2604,12 @@ static void window_ride_vehicle_scrollpaint()
vehicleColour = ride_get_vehicle_colour(ride, vehicleColourIndex);
spriteIndex = 16;
if (RCT2_GLOBAL(ebp + 0x2C, uint16) & 0x800)
if (rideVehicleEntry->var_12 & 0x800)
spriteIndex /= 2;
spriteIndex &= RCT2_GLOBAL(ebp + 0x1A, uint16);
spriteIndex *= RCT2_GLOBAL(ebp + 0x30, uint16);
spriteIndex += RCT2_GLOBAL(ebp + 0x32, uint32);
spriteIndex &= rideVehicleEntry->var_00;
spriteIndex *= rideVehicleEntry->var_16;
spriteIndex += rideVehicleEntry->base_image_id;
spriteIndex |= (vehicleColour.additional_1 << 24) | (vehicleColour.main << 19);
spriteIndex |= 0x80000000;
@ -2571,8 +2619,8 @@ static void window_ride_vehicle_scrollpaint()
nextSpriteToDraw->tertiary_colour = vehicleColour.additional_2;
nextSpriteToDraw++;
x += RCT2_GLOBAL(ebp + 0x1E, uint32) / 17432;
y -= (RCT2_GLOBAL(ebp + 0x1E, uint32) / 2) / 17432;
x += rideVehicleEntry->var_04 / 17432;
y -= (rideVehicleEntry->var_04 / 2) / 17432;
}
if (ride->type == RIDE_TYPE_REVERSER_ROLLER_COASTER) {
@ -2608,7 +2656,7 @@ static void window_ride_mode_tweak_set(rct_window *w, uint8 value)
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1361;
if (ride->mode == RIDE_MODE_RACE)
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1738;
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x2000)
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_13))
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1746;
if (ride->mode == RIDE_MODE_BUMPERCAR)
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1751;
@ -2966,7 +3014,7 @@ static void window_ride_operating_invalidate()
// Leave if another vehicle arrives at station
if (
(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x10) &&
ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_LEAVE_WHEN_ANOTHER_VEHICLE_ARRIVES_AT_STATION) &&
ride->num_vehicles > 1 &&
ride->mode != RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED &&
ride->mode != RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED
@ -2981,7 +3029,7 @@ static void window_ride_operating_invalidate()
}
// Synchronise with adjacent stations
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x20) {
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_CAN_SYNCHRONISE_ADJACENT_STATIONS)) {
window_ride_operating_widgets[WIDX_SYNCHRONISE_WITH_ADJACENT_STATIONS_CHECKBOX].type = WWT_CHECKBOX;
window_ride_operating_widgets[WIDX_SYNCHRONISE_WITH_ADJACENT_STATIONS_CHECKBOX].image = STR_SYNCHRONISE_WITH_ADJACENT_STATIONS;
window_ride_operating_widgets[WIDX_SYNCHRONISE_WITH_ADJACENT_STATIONS_CHECKBOX].tooltip = STR_SYNCHRONISE_WITH_ADJACENT_STATIONS_TIP;
@ -2994,7 +3042,7 @@ static void window_ride_operating_invalidate()
// Waiting
window_ride_operating_widgets[WIDX_LOAD].image = STR_QUARTER_LOAD + (ride->depart_flags & RIDE_DEPART_WAIT_FOR_LOAD_MASK);
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x4000) {
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_LOAD_OPTIONS)) {
window_ride_operating_widgets[WIDX_LOAD_CHECKBOX].type = WWT_CHECKBOX;
window_ride_operating_widgets[WIDX_LOAD].type = WWT_DROPDOWN;
window_ride_operating_widgets[WIDX_LOAD_DROPDOWN].type = WWT_DROPDOWN_BUTTON;
@ -3086,7 +3134,7 @@ static void window_ride_operating_invalidate()
format = 1736;
caption = STR_MAX_PEOPLE_ON_RIDE;
tooltip = STR_MAX_PEOPLE_ON_RIDE_TIP;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x2000))
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_13))
format = 0;
break;
}
@ -3474,12 +3522,11 @@ static uint32 window_ride_get_colour_button_image(int colour)
static int window_ride_has_track_colour(rct_ride *ride, int trackColour)
{
uint16 unk_1 = RCT2_GLOBAL(0x00993E20 + (ride->entrance_style * 8), uint16);
uint32 unk_2 = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32);
switch (trackColour) {
case 0: return ((unk_1 & 1) && !(unk_2 & 0x20000)) || (unk_2 & 1);
case 1: return ((unk_1 & 2) && !(unk_2 & 0x20000)) || (unk_2 & 2);
case 2: return unk_2 & 4;
case 0: return ((unk_1 & 1) && !ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) || ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_MAIN);
case 1: return ((unk_1 & 2) && !ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) || ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_ADDITIONAL);
case 2: return ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_SUPPORTS);
default: return 0;
}
}
@ -3872,7 +3919,7 @@ static void window_ride_colour_invalidate()
}
// Track, multiple colour schemes
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x80000000) {
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_SUPPORTS_MULTIPLE_TRACK_COLOUR)) {
window_ride_colour_widgets[WIDX_TRACK_COLOUR_SCHEME].type = WWT_DROPDOWN;
window_ride_colour_widgets[WIDX_TRACK_COLOUR_SCHEME_DROPDOWN].type = WWT_DROPDOWN_BUTTON;
window_ride_colour_widgets[WIDX_PAINT_INDIVIDUAL_AREA].type = WWT_FLATBTN;
@ -3907,7 +3954,7 @@ static void window_ride_colour_invalidate()
}
// Track preview
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 7)
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_MAIN | RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_ADDITIONAL | RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_SUPPORTS))
window_ride_colour_widgets[WIDX_TRACK_PREVIEW].type = WWT_SPINNER;
else
window_ride_colour_widgets[WIDX_TRACK_PREVIEW].type = WWT_EMPTY;
@ -3926,10 +3973,7 @@ static void window_ride_colour_invalidate()
}
// Vehicle colours
if (
!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x2000) &&
(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x4000000)
) {
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_13) && ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_26)) {
vehicleColourSchemeType = ride->colour_scheme_type & 3;
if (vehicleColourSchemeType == 0)
w->var_48C = 0;
@ -3945,9 +3989,9 @@ static void window_ride_colour_invalidate()
uint8 *unk;
uint32 unk_eax = 0;
for (unk = (uint8*)0x00F64E38; *unk != 0xFF; unk++) {
unk_eax |= RCT2_GLOBAL((int)rideEntry + 0x2E + (*unk * 101), uint16);
unk_eax |= rideEntry->vehicles[*unk].var_14;
unk_eax = ror32(unk_eax, 16);
unk_eax |= RCT2_GLOBAL((int)rideEntry + 0x2C + (*unk * 101), uint16);
unk_eax |= rideEntry->vehicles[*unk].var_12;
unk_eax = ror32(unk_eax, 16);
}
@ -3967,10 +4011,7 @@ static void window_ride_colour_invalidate()
}
// Vehicle colour scheme type
if (
!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x10000) &&
(ride->num_cars_per_train | ride->num_vehicles) > 1
) {
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_16) && (ride->num_cars_per_train | ride->num_vehicles) > 1) {
window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_SCHEME].type = WWT_DROPDOWN;
window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN].type = WWT_DROPDOWN_BUTTON;
} else {
@ -4113,7 +4154,6 @@ static void window_ride_colour_scrollpaint()
rct_ride *ride;
rct_ride_type *rideEntry;
rct_widget *vehiclePreviewWidget;
uint8 *unk;
int colour, x, y, spriteIndex;
vehicle_colour vehicleColour;
@ -4135,16 +4175,16 @@ static void window_ride_colour_scrollpaint()
// ?
colour = (ride->colour_scheme_type & 3) == RIDE_COLOUR_SCHEME_DIFFERENT_PER_CAR ?
w->var_48C : rideEntry->var_013;
colour = RCT2_ADDRESS(0x00F64E38, uint8)[colour];
unk = (uint8*)rideEntry + (colour * 101);
y += RCT2_GLOBAL(unk + 0x24, sint8);
rct_ride_type_vehicle* rideVehicleEntry = &rideEntry->vehicles[RCT2_ADDRESS(0x00F64E38, uint8)[colour]];
y += rideVehicleEntry->var_0A;
// Draw the coloured spinning vehicle
spriteIndex = RCT2_GLOBAL(unk + 0x2C, uint8) & 0x800 ? w->frame_no / 4 : w->frame_no / 2;
spriteIndex &= RCT2_GLOBAL(unk + 0x1A, uint16);
spriteIndex *= RCT2_GLOBAL(unk + 0x30, uint16);
spriteIndex += RCT2_GLOBAL(unk + 0x32, uint32);
spriteIndex = rideVehicleEntry->var_12 & 0x800 ? w->frame_no / 4 : w->frame_no / 2;
spriteIndex &= rideVehicleEntry->var_00;
spriteIndex *= rideVehicleEntry->var_16;
spriteIndex += rideVehicleEntry->base_image_id;
spriteIndex |= (vehicleColour.additional_1 << 24) | (vehicleColour.main << 19);
spriteIndex |= 0x80000000;
gfx_draw_sprite(dpi, spriteIndex, x, y, vehicleColour.additional_2);
@ -4390,6 +4430,50 @@ static void window_ride_music_paint()
#pragma region Measurements
/* rct2: 0x006D2804 when al == 0*/
static void cancel_scenery_selection(){
RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) &= ~(1 << 2);
RCT2_GLOBAL(0x9DEA6F, uint8) &= ~(1 << 0);
unpause_sounds();
rct_window* main_w = window_get_main();
if (main_w){
main_w->viewport->flags &= ~(VIEWPORT_FLAG_HIDE_VERTICAL | VIEWPORT_FLAG_HIDE_BASE);
}
gfx_invalidate_screen();
tool_cancel();
}
/* rct2: 0x006D27A3 */
static void setup_scenery_selection(rct_window* w){
rct_ride* ride = GET_RIDE(w->number);
if (RCT2_GLOBAL(0x009DEA6F, uint8) & 1){
cancel_scenery_selection();
}
while (tool_set(w, 0, 12));
RCT2_GLOBAL(0x00F64DE8, uint8) = (uint8)w->number;
RCT2_GLOBAL(0x009DA193, uint8) = 0xFF;
RCT2_GLOBAL(0x00F63674, sint32) = -1;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) |= (1 << 2);
RCT2_GLOBAL(0x009DEA6F, uint8) |= 1;
pause_sounds();
rct_window* w_main = window_get_main();
if (w_main){
w_main->viewport->flags |= (VIEWPORT_FLAG_HIDE_VERTICAL | VIEWPORT_FLAG_HIDE_BASE);
}
gfx_invalidate_screen();
}
/**
*
* rct2: 0x006D3026
@ -4408,15 +4492,6 @@ static void window_ride_measurements_design_select_nearby_scenery()
RCT2_CALLPROC_EBPSAFE(0x006D303D);
}
/**
*
* rct2: 0x006AD4CD
*/
static void window_ride_measurements_design_save(rct_window *w)
{
RCT2_CALLPROC_X(0x006D2804, 1, 0, 0, 0, (int)w, 0, 0);
}
/**
*
* rct2: 0x006AD4DA
@ -4424,7 +4499,18 @@ static void window_ride_measurements_design_save(rct_window *w)
static void window_ride_measurements_design_cancel()
{
if (RCT2_GLOBAL(0x009DEA6F, uint8) & 1)
RCT2_CALLPROC_X(0x006D2804, 0, 0, 0, 0, 0, 0, 0);
cancel_scenery_selection();
}
/**
*
* rct2: 0x006AD4CD
*/
static void window_ride_measurements_design_save(rct_window *w)
{
if (save_track_design((uint8)w->number) == 0) return;
window_ride_measurements_design_cancel();
}
/**
@ -4536,9 +4622,9 @@ static void window_ride_measurements_dropdown()
dropdownIndex = RCT2_GLOBAL(0x009DEBA2, sint16);
if (dropdownIndex == 0)
RCT2_CALLPROC_X(0x006D264D, 0, 0, 0, 0, (int)w, 0, 0);
save_track_design((uint8)w->number);
else
RCT2_CALLPROC_X(0x006D27A3, 0, 0, 0, 0, (int)w, 0, 0);
setup_scenery_selection(w);
}
/**
@ -4611,7 +4697,7 @@ static void window_ride_measurements_invalidate()
window_ride_measurements_widgets[WIDX_SAVE_DESIGN].type = WWT_EMPTY;
window_ride_measurements_widgets[WIDX_CANCEL_DESIGN].type = WWT_EMPTY;
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_19)) {
if (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x10000000) {
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK)) {
window_ride_measurements_widgets[WIDX_SAVE_TRACK_DESIGN].type = WWT_FLATBTN;
w->disabled_widgets |= (1 << WIDX_SAVE_TRACK_DESIGN);
if (ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED) {
@ -4763,7 +4849,7 @@ static void window_ride_measurements_paint()
gfx_draw_string_left_clipped(dpi, STR_RIDE_LENGTH, (void*)0x013CE952, 0, x, y, 308);
y += 10;
if (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x80) {
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_G_FORCES)) {
// Max. positive vertical G's
maxPositiveVerticalGs = ride->max_positive_vertical_g;
stringId = maxPositiveVerticalGs >= FIXED_2DP(5,00) ?
@ -4791,7 +4877,7 @@ static void window_ride_measurements_paint()
y += 10;
}
if (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x400) {
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_DROPS)) {
// Drops
drops = ride->drops & 0x3F;
gfx_draw_string_left(dpi, STR_DROPS, &drops, 0, x, y);
@ -5057,7 +5143,7 @@ static void window_ride_graphs_invalidate()
w->pressed_widgets |= (1LL << (WIDX_GRAPH_VELOCITY + (w->list_information_type & 0xFF)));
// Hide graph buttons that are not applicable
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x80) {
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_G_FORCES)) {
window_ride_graphs_widgets[WIDX_GRAPH_VERTICAL].type = WWT_DROPDOWN_BUTTON;
window_ride_graphs_widgets[WIDX_GRAPH_LATERAL].type = WWT_DROPDOWN_BUTTON;
} else {
@ -5603,13 +5689,13 @@ static void window_ride_customer_mouseup()
window_ride_set_page(w, widgetIndex - WIDX_TAB_1);
break;
case WIDX_SHOW_GUESTS_THOUGHTS:
RCT2_CALLPROC_X(0x006993BA, 2, w->number, 0, 0, 0, 0, 0);
window_guest_list_open_with_filter(2, w->number);
break;
case WIDX_SHOW_GUESTS_ON_RIDE:
RCT2_CALLPROC_X(0x006993BA, 0, w->number, 0, 0, 0, 0, 0);
window_guest_list_open_with_filter(0, w->number);
break;
case WIDX_SHOW_GUESTS_QUEUING:
RCT2_CALLPROC_X(0x006993BA, 1, w->number, 0, 0, 0, 0, 0);
window_guest_list_open_with_filter(1, w->number);
break;
}
}
@ -5673,13 +5759,13 @@ static void window_ride_customer_invalidate()
RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name;
RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments;
if (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) * 0x20000) {
window_ride_customer_widgets[WIDX_SHOW_GUESTS_THOUGHTS].type = WWT_FLATBTN;
window_ride_customer_widgets[WIDX_SHOW_GUESTS_ON_RIDE].type = WWT_FLATBTN;
window_ride_customer_widgets[WIDX_SHOW_GUESTS_QUEUING].type = WWT_FLATBTN;
} else {
window_ride_customer_widgets[WIDX_SHOW_GUESTS_THOUGHTS].type = WWT_FLATBTN;
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) {
window_ride_customer_widgets[WIDX_SHOW_GUESTS_ON_RIDE].type = WWT_EMPTY;
window_ride_customer_widgets[WIDX_SHOW_GUESTS_QUEUING].type = WWT_EMPTY;
} else {
window_ride_customer_widgets[WIDX_SHOW_GUESTS_ON_RIDE].type = WWT_FLATBTN;
window_ride_customer_widgets[WIDX_SHOW_GUESTS_QUEUING].type = WWT_FLATBTN;
}
window_ride_anchor_border_widgets(w);

View File

@ -8,12 +8,12 @@
* 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/>.
*****************************************************************************/
@ -22,6 +22,8 @@
#include "../interface/window.h"
#include "../interface/viewport.h"
#include "../game.h"
#include "../ride/track.h"
#include "../drawing/drawing.h"
/* move to ride.c */
void sub_6b2fa9(rct_windownumber number){
@ -47,8 +49,11 @@ enum {
void window_construction_emptysub(){}
void window_construction_close();
void window_construction_mouseup();
void window_construction_paint();
void window_construction_maze_close();
void window_construction_maze_invalidate();
void window_construction_maze_paint();
// 0x993F6C
static void* window_construction_maze_events[] = {
@ -77,8 +82,8 @@ static void* window_construction_maze_events[] = {
window_construction_emptysub,
window_construction_emptysub,
window_construction_emptysub,
(void*)0x6CD435,
(void*)0x6CD45B,
window_construction_maze_invalidate,
window_construction_maze_paint,
window_construction_emptysub
};
@ -110,12 +115,12 @@ static void* window_construction_events[] = {
window_construction_emptysub,
window_construction_emptysub,
(void*)0x6C6AD5,
(void*)0x6C6B86,
window_construction_paint,//(void*)0x6C6B86,
window_construction_emptysub
};
/**
*
*
* rct2: 0x006CB481
*/
rct_window *window_construction_open()
@ -177,7 +182,7 @@ rct_window *window_construction_open()
RCT2_GLOBAL(0xF440CE, uint8) = 30;
}
RCT2_GLOBAL(0xF440A0,uint16) = RCT2_ADDRESS(0x0097CC68, uint8)[ride->type * 2] | 0x100;
RCT2_GLOBAL(0xF440A0, uint16) = RCT2_ADDRESS(0x0097CC68, uint8)[ride->type * 2] | 0x100;
RCT2_GLOBAL(0x00F440B2, uint8) = 0;
RCT2_GLOBAL(0x00F440B3, uint8) = 0;
RCT2_GLOBAL(0x00F440B4, uint8) = 0;
@ -240,7 +245,7 @@ void window_construction_maze_close(){
RCT2_GLOBAL(0x9DE58A, uint16) &= 0xFFFD;
hide_gridlines();
uint8 ride_id = RCT2_GLOBAL(0xF440A7, uint8);
rct_ride* ride = GET_RIDE(ride_id);
@ -325,3 +330,125 @@ void window_construction_mouseup_demolish(rct_window* w){
//6c9BFE
}
void window_construction_maze_invalidate()
{
int ride_idx = RCT2_GLOBAL(0x00F440A7, uint8);
RCT2_GLOBAL(0x13CE958, uint32_t) = RCT2_GLOBAL(0x1362944 + ride_idx * 0x260, uint32_t);
RCT2_GLOBAL(0x13CE956, uint16_t) = RCT2_GLOBAL(0x1362942 + ride_idx * 0x260, uint16_t);
}
//0x6C6B86
void window_construction_paint()
{
rct_window *w;
rct_drawpixelinfo *dpi;
window_paint_get_registers(w, dpi);
window_draw_widgets(w, dpi);
if (RCT2_GLOBAL(0x9D7C00, uint8_t) == 0) return;
uint32_t eax = 0, esi = (uint32_t)w, ebp = 0;//nothing
uint32_t ebx = 0, ecx = 0, edx = 0, edi = (uint32_t)dpi;//returns
if (RCT2_CALLFUNC_X(0x6CA2DF, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp) & 0x100) return;
RCT2_GLOBAL(0xF44133, uint8_t) = edx & 0xFF;
RCT2_GLOBAL(0xF44134, uint8_t) = (ebx >> 8) & 0xFF;
RCT2_GLOBAL(0xF44135, uint8_t) = (edx >> 8) & 0xFF;
edx >>= 16;
RCT2_GLOBAL(0xF44136, int16_t) = edx;
rct_ride* ride = GET_RIDE(RCT2_GLOBAL(0xF44133, uint8));
RCT2_GLOBAL(0xF44064, uint32_t) = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32_t);
// 0x009D7C04 is a widget address remember to change when widget implemented
short width = RCT2_GLOBAL(0x9D7C04, int16_t) - RCT2_GLOBAL(0x9D7C02, int16_t) - 1;
short height = RCT2_GLOBAL(0x9D7C08, int16_t) - RCT2_GLOBAL(0x9D7C06, int16_t) - 1;
rct_drawpixelinfo* clip_dpi = clip_drawpixelinfo(
dpi,
// 0x009D7C02 is a widget address remember to change when widget implemented
w->x + RCT2_GLOBAL(0x9D7C02, int16_t) + 1,
width,
w->y + RCT2_GLOBAL(0x9D7C06, int16_t) + 1,
height);
if (clip_dpi != NULL)
{
rct_preview_track *trackBlock;
ecx = RCT2_GLOBAL(0xF44135, uint8_t);
if (RCT2_GLOBAL(0xF44064, uint32_t) & 0x80000) trackBlock = RCT2_ADDRESS(0x994A38, rct_preview_track*)[ecx];//RCT2_GLOBAL(0x994A38 + ecx * 4, rct_preview_track*);
else trackBlock = RCT2_ADDRESS(0x994638, rct_preview_track*)[ecx];//RCT2_GLOBAL(0x994638 + ecx * 4, rct_preview_track*);
while ((trackBlock + 1)->var_00 != 0xFF) trackBlock++;
short x = trackBlock->x;
short z = trackBlock->z;
short y = trackBlock->y;
if (trackBlock->var_09 & 2) x = y = 0;
short tmp;
switch (RCT2_GLOBAL(0xF44134, uint8_t) & 3)
{
case 1:
tmp = x;
x = y;
y = -tmp;
break;
case 2:
x = -x;
y = -y;
break;
case 3:
tmp = x;
x = -y;
y = tmp;
break;
case 0:
break;
}
//this is actually case 0, but the other cases all jump to it
x /= 2;
y /= 2;
x += 4112;
y += 4112;
z += 1024;
ebx = RCT2_GLOBAL(0xF44135, uint8_t);
short bx;
if (RCT2_GLOBAL(0xF44064, uint32_t) & 0x80000) bx = RCT2_GLOBAL(0x9984A2 + ebx * 8, uint8_t);
else bx = RCT2_GLOBAL(0x997CA2 + ebx * 8, uint8_t);
z -= bx;
int start_x = x;
switch (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32_t))
{
case 0:
x = y - x;
y = (y + start_x) / 2 - z;
break;
case 1:
x = -x - y;
y = (y - start_x) / 2 - z;
break;
case 2:
x -= y;
y = (-y - start_x) / 2 - z;
break;
case 3:
x += y;
y = (-y + start_x) / 2 - z;
break;
}
clip_dpi->x += x - width / 2;
clip_dpi->y += y - height / 2 - 16;
RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*) = clip_dpi;
uint32_t d = RCT2_GLOBAL(0xF44136, int16_t) << 16;
d |= RCT2_GLOBAL(0xF44133, uint8_t);// Ride id
d |= RCT2_GLOBAL(0xF44135, uint8_t) << 8;
RCT2_CALLPROC_X(0x6CBCE2, 0x1000, (((uint16_t)bx) & 0xFF) | (RCT2_GLOBAL(0xF44134, uint8_t) << 8), 0x1000, d, width, 0x400, height);
rct2_free(clip_dpi);
}
short string_x = (RCT2_GLOBAL(0x9D7C02, int16_t) + RCT2_GLOBAL(0x9D7C04, int16_t)) / 2 + w->x;
short string_y = RCT2_GLOBAL(0x9D7C08, int16_t) + w->y - 23;
if (RCT2_GLOBAL(0xF440A6, uint8_t) != 4) gfx_draw_string_centred(dpi, 1407, string_x, string_y, 0, w);
string_y += 11;
if (RCT2_GLOBAL(0xF44070, uint32_t) != 0x80000000 && !(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32_t) & 0x800))
gfx_draw_string_centred(dpi, 1408, string_x, string_y, 0, (void*)0xF44070);
}
//0x006CD45B
void window_construction_maze_paint()
{
rct_window *w;
rct_drawpixelinfo *dpi;
window_paint_get_registers(w, dpi);
window_draw_widgets(w, dpi);
}

View File

@ -222,7 +222,7 @@ void init_scenery_entry(rct_scenery_entry *sceneryEntry, int index, uint8 scener
* rct2: 0x006DFA00
*/
void init_scenery() {
bool enabledScenerySets[0x13] = { false };
bool enabledScenerySets[0x14] = { false };
for (int scenerySetIndex = 0; scenerySetIndex < 0x14; scenerySetIndex++) {
window_scenery_tab_entries[scenerySetIndex][0] = -1;
@ -345,7 +345,7 @@ void init_scenery() {
uint32 tabIndex = tabIndexes[i];
rct_widget* tabWidget = &window_scenery_widgets[tabIndex + WIDX_SCENERY_TAB_1];
if (left != 3 || tabIndex == 0x13) {
if (left != 3 || tabIndex != 0x13) {
if (window_scenery_tab_entries[tabIndex][0] == -1)
continue;
@ -570,12 +570,16 @@ static void window_scenery_resize()
if (w->height < w->min_height) {
w->height = w->min_height;
window_invalidate(w);
// HACK: For some reason invalidate has not been called
window_event_invalidate_call(w);
window_scenery_update_scroll(w);
}
if (w->height > w->max_height) {
w->height = w->max_height;
window_invalidate(w);
// HACK: For some reason invalidate has not been called
window_event_invalidate_call(w);
window_scenery_update_scroll(w);
}
}
@ -690,9 +694,11 @@ static void window_scenery_update(rct_window *w)
gfx_invalidate_screen();
if (!window_scenery_is_scenery_tool_active())
if (!window_scenery_is_scenery_tool_active()){
window_close(w);
return;
}
if (window_scenery_is_repaint_scenery_tool_on == 1) { // the repaint scenery tool is active
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) = 0x17;
} else {

View File

@ -128,7 +128,7 @@ static void window_shortcut_mouseup()
break;
case WIDX_RESET:
config_reset_shortcut_keys();
config_save_default();
config_shortcut_keys_save();
window_invalidate(w);
break;
}
@ -163,17 +163,15 @@ static void window_shortcut_tooltip()
*/
static void window_shortcut_scrollgetsize()
{
int y;
rct_window *w;
int width, height;
window_get_register(w);
y = 32 * 10;
width = 0;
height = 32 * 10;
#ifdef _MSC_VER
__asm mov edx, y
#else
__asm__("mov edx, %[y] " : [y] "+m" (y));
#endif
window_scrollsize_set_registers(width, height);
}
/**
@ -188,8 +186,8 @@ static void window_shortcut_scrollmousedown()
window_scrollmouse_get_registers(w, scrollIndex, x, y);
int selected_item = y / 10;
if (selected_item >= w->no_list_items)return;
if (selected_item >= w->no_list_items)
return;
window_shortcut_change_open(selected_item);
}
@ -206,8 +204,8 @@ static void window_shortcut_scrollmouseover()
window_scrollmouse_get_registers(w, scrollIndex, x, y);
int selected_item = y / 10;
if (selected_item >= w->no_list_items)return;
if (selected_item >= w->no_list_items)
return;
w->selected_list_item = selected_item;
@ -227,14 +225,14 @@ static void window_shortcut_scrollpaint()
gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width - 1, dpi->y + dpi->height - 1, RCT2_ADDRESS(0x0141FC48,uint8)[w->colours[1] * 8]);
for (int i = 0; i < w->no_list_items; ++i){
for (int i = 0; i < w->no_list_items; ++i) {
int y = i * 10;
if (y > dpi->y + dpi->height) {
if (y > dpi->y + dpi->height)
break;
}
if (y + 10 < dpi->y)continue;
int format = STR_BLACK_STRING;
if (i == w->selected_list_item){
if (i == w->selected_list_item) {
format = STR_WINDOW_COLOUR_2_STRING;
gfx_fill_rect(dpi, 0, y, 800, y + 9, 0x2000031);
}
@ -243,33 +241,23 @@ static void window_shortcut_scrollpaint()
RCT2_GLOBAL(0x13CE956, uint16) = 0;
RCT2_GLOBAL(0x13CE958, uint16) = 0;
// This is the original version that will not take into account remapped keys.
//shortcut_entry sc_entry = RCT2_ADDRESS(RCT2_ADDRESS_CONFIG_KEYBOARD_SHORTCUTS, shortcut_entry)[i];
//if (sc_entry.key != 255){
// RCT2_GLOBAL(0x13CE958, uint16) = sc_entry.key + 2525;
// if (sc_entry.modifier){
// RCT2_GLOBAL(0x13CE956, uint16) = 2782;
// if (sc_entry.key != 1){
// RCT2_GLOBAL(0x13CE956, uint16) = 2783;
// }
// }
//}
uint16 shortcut_entry = gShortcutKeys[i];
if (shortcut_entry != 0xFFFF){
RCT2_GLOBAL(0x13CE958, uint16) = STR_INDIVIDUAL_KEYS_BASE + platform_scancode_to_rct_keycode(shortcut_entry & 0xFF);
//Display the modifer
if (shortcut_entry & 0x100){
if (shortcut_entry != 0xFFFF) {
rct_string_id templateStringId = 2525;
const char *scanCodeName = SDL_GetScancodeName(shortcut_entry & 0xFF);
char *templateString = (char*)language_get_string(templateStringId);
strcpy(templateString, scanCodeName);
RCT2_GLOBAL(0x13CE958, uint16) = templateStringId;
// Display the modifer
if (shortcut_entry & 0x100)
RCT2_GLOBAL(0x13CE956, uint16) = STR_SHIFT_PLUS;
}
else if (shortcut_entry & 0x200){
else if (shortcut_entry & 0x200)
RCT2_GLOBAL(0x13CE956, uint16) = STR_CTRL_PLUS;
}
}
RCT2_GLOBAL(0x13CE952, uint16) = STR_SHORTCUT_ENTRY_FORMAT;
gfx_draw_string_left(dpi, format, (void*)0x13CE952, 0, 0, y - 1);
}
}

View File

@ -1240,7 +1240,7 @@ void window_staff_overview_viewport_init_wrapper(){
/* rct2: 0x006BEDA3 */
void window_staff_viewport_init(rct_window* w){
RCT2_CALLPROC_X(0x006BEDA3, 0, 0, 0, 0, (int)w, 0, 0);
//RCT2_CALLPROC_X(0x006BEDA3, 0, 0, 0, 0, (int)w, 0, 0);
if (w->page != WINDOW_STAFF_OVERVIEW) return;

View File

@ -19,6 +19,7 @@
*****************************************************************************/
#include "../addresses.h"
#include "../config.h"
#include "../editor.h"
#include "../game.h"
#include "../input.h"
@ -503,8 +504,11 @@ static void window_top_toolbar_invalidate()
window_top_toolbar_widgets[WIDX_VIEW_MENU].type = WWT_EMPTY;
}
} else {
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)
if ((RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) || !gConfigInterface.toolbar_show_finances)
window_top_toolbar_widgets[WIDX_FINANCES].type = WWT_EMPTY;
if (!gConfigInterface.toolbar_show_research)
window_top_toolbar_widgets[WIDX_RESEARCH].type = WWT_EMPTY;
}
enabledWidgets = 0;

View File

@ -520,7 +520,7 @@ static void window_track_list_paint()
y += 10;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (track_td6->type * 8), uint32) & 0x80) {
if (ride_type_has_flag(track_td6->type, RIDE_TYPE_FLAG_HAS_G_FORCES)) {
// Maximum positive vertical Gs
gForces = track_td6->max_positive_vertical_g * 32;
gfx_draw_string_left(dpi, STR_MAX_POSITIVE_VERTICAL_G, &gForces, 0, x, y);
@ -546,7 +546,7 @@ static void window_track_list_paint()
}
}
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (track_td6->type * 8), uint32) & 0x400) {
if (ride_type_has_flag(track_td6->type, RIDE_TYPE_FLAG_HAS_DROPS)) {
// Drops
drops = track_td6->drops & 0x3F;
gfx_draw_string_left(dpi, STR_DROPS, &drops, 0, x, y);

33
src/world/entrance.h Normal file
View File

@ -0,0 +1,33 @@
/*****************************************************************************
* Copyright (c) 2014 Ted John
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#ifndef _ENTRANCE_H_
#define _ENTRANCE_H_
#include "../common.h"
typedef struct {
rct_string_id string_idx; // 0x00
uint32 image_id; // 0x02
uint8 var_06;
uint8 var_07;
} rct_entrance_type;
#endif

View File

@ -23,19 +23,22 @@
#include "../common.h"
#include "../interface/viewport.h"
#include "../object.h"
enum {
PROVISIONAL_PATH_FLAG_SHOW_ARROW = (1 << 0)
};
typedef struct {
uint16 pad_00;
uint32 image; // 0x02
uint32 pad_06;
uint8 pad_0A;
uint8 flags; // 0x0B
rct_string_id string_idx; // 0x00
uint32 image; // 0x02
uint32 bridge_image; // 0x06
uint8 var_0A;
uint8 flags; // 0x0B
} rct_path_type;
#define g_pathTypeEntries ((rct_path_type**)object_entry_groups[OBJECT_TYPE_PATHS].chunks)
void game_command_place_footpath(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void game_command_remove_footpath(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
money32 footpath_place(int type, int x, int y, int z, int slope, int flags);

View File

@ -385,9 +385,9 @@ static int park_calculate_guest_generation_probability()
if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED)
continue;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x10000000))
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK))
continue;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x200))
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_DATA_LOGGING))
continue;
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED))
continue;

View File

@ -22,14 +22,16 @@
#define _SCENERY_H_
#include "../common.h"
#include "../object.h"
typedef struct {
uint32 flags; // 0x06
uint8 height; // 0x0A
uint8 tool_id; // 0x0B
uint16 price; // 0x0C
sint16 price; // 0x0C
sint16 removal_price; // 0x0E
uint8 pad_10[0x0A];
uint32 var_10;
uint8 pad_14[0x06];
uint8 scenery_tab_id; // 0x1A
} rct_small_scenery_entry;
@ -59,10 +61,13 @@ typedef enum {
typedef struct {
uint8 tool_id; // 0x06
uint8 flags; // 0x07
uint16 price; // 0x08
uint8 pad_0A[6];
sint16 price; // 0x08
sint16 removal_price; // 0x0A
uint32 var_0C;
uint8 scenery_tab_id; // 0x10
uint8 var_11;
uint32 var_12;
uint32 var_16;
} rct_large_scenery_entry;
@ -71,7 +76,7 @@ typedef struct {
uint8 flags; // 0x07
uint8 height; // 0x08
uint8 flags2; // 0x09
uint16 price; // 0x0A
sint16 price; // 0x0A
uint8 scenery_tab_id; // 0x0C
uint8 var_0D;
} rct_wall_scenery_entry;
@ -91,14 +96,14 @@ typedef struct {
uint16 var_06;
uint8 pad_08;
uint8 tool_id; // 0x09
uint16 price; // 0x0A
sint16 price; // 0x0A
uint8 scenery_tab_id; // 0x0C
} rct_path_bit_scenery_entry;
typedef struct {
uint8 var_06;
uint8 flags; // 0x07
uint16 price; // 0x08
sint16 price; // 0x08
uint8 scenery_tab_id; // 0x0A
} rct_banner_scenery_entry;
@ -119,18 +124,18 @@ typedef struct {
uint32 image; // 0x02
uint16 scenery_entries[0x80]; // 0x06
uint8 entry_count; // 0x106
uint8 pad_107;
uint8 var_107;
uint8 var_108; // 0x108, order?
uint8 pad_109;
uint32 var_10A;
} rct_scenery_set_entry;
#define g_smallSceneryEntries RCT2_ADDRESS(RCT2_ADDRESS_SMALL_SCENERY_ENTRIES, rct_scenery_entry*)
#define g_largeSceneryEntries RCT2_ADDRESS(RCT2_ADDRESS_LARGE_SCENERY_ENTRIES, rct_scenery_entry*)
#define g_wallSceneryEntries RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_scenery_entry*)
#define g_bannerSceneryEntries RCT2_ADDRESS(RCT2_ADDRESS_BANNER_SCENERY_ENTRIES, rct_scenery_entry*)
#define g_pathBitSceneryEntries RCT2_ADDRESS(RCT2_ADDRESS_PATH_BIT_SCENERY_ENTRIES, rct_scenery_entry*)
#define g_scenerySetEntries RCT2_ADDRESS(RCT2_ADDRESS_SCENERY_SET_ENTRIES, rct_scenery_set_entry*)
#define g_smallSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].chunks)
#define g_largeSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_LARGE_SCENERY].chunks)
#define g_wallSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_WALLS].chunks)
#define g_bannerSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_BANNERS].chunks)
#define g_pathBitSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_PATH_BITS].chunks)
#define g_scenerySetEntries ((rct_scenery_set_entry**)object_entry_groups[OBJECT_TYPE_SCENERY_SETS].chunks)
void init_scenery();

View File

@ -21,6 +21,7 @@
#include "../addresses.h"
#include "../interface/viewport.h"
#include "sprite.h"
#include "../scenario.h"
rct_sprite* g_sprite_list = RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite);
@ -30,7 +31,19 @@ rct_sprite* g_sprite_list = RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite);
*/
void create_balloon(int x, int y, int z, int colour)
{
RCT2_CALLPROC_X(0x006736C7, x, colour << 8, y, z, 0, 0, 0);
rct_sprite* sprite = create_sprite(2);
if (sprite != NULL)
{
sprite->balloon.var_14 = 13;
sprite->balloon.var_09 = 22;
sprite->balloon.var_15 = 11;
sprite->balloon.sprite_identifier = 2;
sprite_move(x, y, z, sprite);
sprite->balloon.var_01 = 7;
sprite->balloon.var_26 = 0;
sprite->balloon.colour = colour;
sprite->balloon.var_24 = 0;
}
}
/**
@ -39,7 +52,40 @@ void create_balloon(int x, int y, int z, int colour)
*/
void create_duck(int targetX, int targetY)
{
RCT2_CALLPROC_X(0x0067440F, targetX, 0, targetY, 0, 0, 0, 0);
rct_sprite* sprite = create_sprite(2);
if (sprite != NULL)
{
sprite->duck.sprite_identifier = 2;
sprite->duck.var_01 = 8;
sprite->duck.var_14 = 9;
sprite->duck.var_09 = 0xC;
sprite->duck.var_15 = 9;
int offset_xy = scenario_rand() & 0x1E;
targetX += offset_xy;
targetY += offset_xy;
sprite->duck.target_x = targetX;
sprite->duck.target_y = targetY;
uint8 direction = scenario_rand() & 3;
switch (direction)
{
case 0:
targetX = 8191 - (scenario_rand() & 0x3F);
break;
case 1:
targetY = scenario_rand() & 0x3F;
break;
case 2:
targetX = scenario_rand() & 0x3F;
break;
case 3:
targetY = 8191 - (scenario_rand() & 0x3F);
break;
}
sprite->duck.sprite_direction = direction << 3;
sprite_move(targetX, targetY, 496, sprite);
sprite->duck.var_48 = 0;
sprite->duck.var_26 = 0;
}
}
/* rct2: 0x006EC473 */

View File

@ -81,6 +81,47 @@ typedef struct {
uint32 var_24;
} rct_litter;
typedef struct {
uint8 sprite_identifier; // 0x00
uint8 var_01; // 0x01
uint16 var_02; // 0x02
uint16 next; // 0x04
uint16 previous; // 0x06
uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
uint8 var_09; // 0x09
uint8 pad_0A[0xA];
uint8 var_14; // 0x14
uint8 var_15; // 0x15
uint8 pad_16[0xE];
uint8 var_24; // 0x24
uint8 pad_25;
uint16 var_26; // 0x26
uint8 pad_28[4];
uint8 colour; // 0x2C
} rct_balloon;
typedef struct {
uint8 sprite_identifier; // 0x00
uint8 var_01; // 0x01
uint16 var_02; // 0x02
uint16 next; // 0x04
uint16 previous; // 0x06
uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
uint8 var_09; // 0x09
uint8 pad_0A[0xA];
uint8 var_14; // 0x14
uint8 var_15; // 0x15
uint8 pad_16[0x8];
uint8 sprite_direction; // 0x1E
uint8 pad_1F[0x7];
uint16 var_26;
uint8 pad_28[0x8];
sint16 target_x; // 0x30
sint16 target_y; // 0x32
uint8 pad_34[0x14];
uint8 var_48; // 0x48
} rct_duck;
/**
* Sprite structure.
* size: 0x0100
@ -91,6 +132,8 @@ typedef union {
rct_peep peep;
rct_litter litter;
rct_vehicle vehicle;
rct_balloon balloon;
rct_duck duck;
} rct_sprite;
// rct2: 0x010E63BC

34
src/world/water.h Normal file
View File

@ -0,0 +1,34 @@
/*****************************************************************************
* Copyright (c) 2014 Ted John
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#ifndef _WATER_H_
#define _WATER_H_
#include "../common.h"
typedef struct {
rct_string_id string_idx; // 0x00
uint32 image_id; // 0x02
uint32 var_06;
uint32 var_0A;
uint16 var_0E;
} rct_water_type;
#endif