Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Maciek Baron 2014-05-03 12:07:26 +01:00
commit c355d27459
27 changed files with 1836 additions and 85 deletions

View File

@ -87,7 +87,9 @@
<ClCompile Include="..\src\window_dropdown.c" />
<ClCompile Include="..\src\window_land.c" />
<ClCompile Include="..\src\window_park.c" />
<ClCompile Include="..\src\window_footpath.c" />
<ClCompile Include="..\src\window_ride_list.c" />
<ClCompile Include="..\src\window_save_prompt.c" />
<ClCompile Include="..\src\window_title_exit.c" />
<ClCompile Include="..\src\window_title_logo.c" />
<ClCompile Include="..\src\window_main.c" />

View File

@ -257,6 +257,12 @@
<ClCompile Include="..\lodepng\lodepng.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\window_footpath.c">
<Filter>Windows</Filter>
</ClCompile>
<ClCompile Include="..\src\window_save_prompt.c">
<Filter>Windows</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\openrct2.exe">

View File

@ -98,12 +98,20 @@
#define RCT2_ADDRESS_TOOL_WINDOWNUMBER 0x009DE542
#define RCT2_ADDRESS_TOOL_WINDOWCLASS 0x009DE544
#define RCT2_ADDRESS_CURRENT_TOOL 0x009DE545
#define RCT2_ADDRESS_TOOL_WIDGETINDEX 0x009DE546
#define RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS 0x009DE55C
#define RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER 0x009DE55E
#define RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX 0x009DE560
#define RCT2_ADDRESS_MAP_SELECTION_FLAGS 0x009DE58A
#define RCT2_ADDRESS_MAP_SELECTION_A_X 0x009DE58C
#define RCT2_ADDRESS_MAP_SELECTION_B_X 0x009DE58E
#define RCT2_ADDRESS_MAP_SELECTION_A_Y 0x009DE590
#define RCT2_ADDRESS_MAP_SELECTION_B_Y 0x009DE592
#define RCT2_ADDRESS_MAP_SELECTION_TYPE 0x009DE594
#define RCT2_ADDRESS_SCREEN_FLAGS 0x009DEA68
#define RCT2_ADDRESS_SCREENSHOT_COUNTDOWN 0x009DEA6D
#define RCT2_ADDRESS_PLACE_OBJECT_MODIFIER 0x009DEA70
@ -188,6 +196,7 @@
#define RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT 0x0141E9AC
#define RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE 0x0141E9AE
#define RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID 0x0141E9AE
#define RCT2_ADDRESS_CURRENT_ROTATION 0x0141E9E0
#define RCT2_ADDRESS_SCENARIO_NAME 0x0141F5B8

View File

@ -29,6 +29,7 @@
#include "peep.h"
#include "screenshot.h"
#include "strings.h"
#include "title.h"
#include "tutorial.h"
#include "widget.h"
#include "window.h"
@ -986,6 +987,8 @@ static int game_check_affordability(int cost)
return ebp;
}
static uint32 game_do_command_table[58];
/**
*
* rct2: 0x006677F2
@ -1004,9 +1007,6 @@ int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int eb
original_edi = edi;
original_ebp = ebp;
RCT2_CALLFUNC_X(0x006677F2, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
return ebx;
flags = ebx;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 0xFFFF;
@ -1016,7 +1016,7 @@ int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int eb
ebx &= ~1;
// Primary command
RCT2_CALLFUNC_X(RCT2_ADDRESS(0x0097B9A4, uint32)[esi], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
RCT2_CALLFUNC_X(game_do_command_table[esi], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
cost = ebx;
if (cost != 0x80000000) {
@ -1039,7 +1039,7 @@ int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int eb
}
// Secondary command
RCT2_CALLFUNC_X(RCT2_ADDRESS(0x0097B9A4, uint32)[esi], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
RCT2_CALLFUNC_X(game_do_command_table[esi], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
edx = ebx;
if (edx != 0x80000000 && edx < cost)
@ -1075,4 +1075,257 @@ int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int eb
window_error_open(RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16), RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16));
return 0x80000000;
}
}
/**
*
* rct2: 0x00667C15
*/
static void game_pause_toggle()
{
rct_window *w;
char input_bl, input_dl;
short input_di;
__asm mov input_bl, bl
if (input_bl & 1) {
RCT2_GLOBAL(0x009DEA6E, uint32) ^= 1;
window_invalidate_by_id(WC_TOP_TOOLBAR, 0);
if (RCT2_GLOBAL(0x009DEA6E, uint32) & 1)
RCT2_CALLPROC_EBPSAFE(0x006BABB4); // pause_sounds
else
RCT2_CALLPROC_EBPSAFE(0x006BABD8); // unpause_sounds
}
__asm mov ebx, 0
}
/**
*
* rct2: 0x0066DB5F
*/
static void game_load_or_quit()
{
rct_window *w;
char input_bl, input_dl;
short input_di;
__asm mov input_bl, bl
__asm mov input_dl, dl
__asm mov input_di, di
if (!(input_bl & 1))
return 0;
switch (input_dl) {
case 0:
RCT2_GLOBAL(0x009A9802, uint16) = input_di;
window_save_prompt_open();
break;
case 1:
window_close_by_id(WC_SAVE_PROMPT, 0);
break;
default:
game_load_or_quit_no_save_prompt();
break;
}
__asm mov ebx, 0
}
/**
*
* rct2: 0x00674F40
*/
static int open_landscape_file_dialog()
{
format_string(0x0141ED68, STR_LOAD_LANDSCAPE_DIALOG_TITLE, 0);
strcpy(0x0141EF68, RCT2_ADDRESS_LANDSCAPES_PATH);
format_string(0x0141EE68, STR_RCT2_LANDSCAPE_FILE, 0);
RCT2_CALLPROC_EBPSAFE(0x006BABB4); // pause_sounds
osinterface_open_common_file_dialog(1, 0x0141ED68, 0x0141EF68, "*.SV6;*.SV4;*.SC6", 0x0141EE68);
RCT2_CALLPROC_EBPSAFE(0x006BABD8); // unpause_sounds
// window_proc
}
/**
*
* rct2: 0x00674EB6
*/
static int open_load_game_dialog()
{
format_string(0x0141ED68, STR_LOAD_GAME_DIALOG_TITLE, 0);
strcpy(0x0141EF68, RCT2_ADDRESS_SAVED_GAMES_PATH);
format_string(0x0141EE68, STR_RCT2_SAVED_GAME, 0);
RCT2_CALLPROC_EBPSAFE(0x006BABB4); // pause_sounds
osinterface_open_common_file_dialog(1, 0x0141ED68, 0x0141EF68, "*.SV6", 0x0141EE68);
RCT2_CALLPROC_EBPSAFE(0x006BABD8); // unpause_sounds
// window_proc
}
/**
*
* rct2: 0x0066DC0F
*/
static void load_landscape()
{
if (open_landscape_file_dialog() == 0) {
gfx_invalidate_screen();
} else {
// Set default filename
char *esi = 0x0141EF67;
while (1) {
esi++;
if (*esi == '.')
break;
if (*esi != 0)
continue;
strcpy(esi, ".SC6");
break;
}
strcpy(0x009ABB37, 0x0141EF68);
RCT2_CALLPROC_EBPSAFE(0x006758C0); // landscape_load
if (1) {
gfx_invalidate_screen();
// game_loop_iteration
} else {
RCT2_GLOBAL(0x009DEA66, uint16) = 0;
// game_loop_iteration
}
}
}
/**
*
* rct2: 0x0066DBB7
*/
static void load_game()
{
if (open_load_game_dialog() == 0) {
gfx_invalidate_screen();
} else {
// Set default filename
char *esi = 0x0141EF67;
while (1) {
esi++;
if (*esi == '.')
break;
if (*esi != 0)
continue;
strcpy(esi, ".SV6");
break;
}
strcpy(0x009ABB37, 0x0141EF68);
RCT2_CALLPROC_EBPSAFE(0x00675E1B); // game_load
if (1) {
gfx_invalidate_screen();
// game_loop_iteration
} else {
RCT2_GLOBAL(0x009DEA66, uint16) = 0;
// game_loop_iteration
}
}
}
/**
*
* rct2: 0x006E3879
*/
static void rct2_exit()
{
RCT2_CALLPROC_EBPSAFE(0x006E3879);
}
/**
*
* rct2: 0x0066DB79
*/
void game_load_or_quit_no_save_prompt()
{
if (RCT2_GLOBAL(0x009A9802, uint16) < 1) {
game_do_command(0, 1, 0, 1, 5, 0, 0);
tool_cancel();
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)
load_landscape();
else
load_game();
} else if (RCT2_GLOBAL(0x009A9802, uint16) == 1) {
game_do_command(0, 1, 0, 1, 5, 0, 0);
if (RCT2_GLOBAL(0x009DE518, uint32) & (1 << 5)) {
RCT2_CALLPROC_EBPSAFE(0x0040705E);
RCT2_GLOBAL(0x009DE518, uint32) &= ~(1 << 5);
}
title_load();
// game_loop_iteration
} else {
rct2_exit();
}
}
#pragma region Game command function table
static uint32 game_do_command_table[58] = {
0x006B2FC5,
0x0066397F,
game_pause_toggle,
0x006C511D,
0x006C5B69,
game_load_or_quit,
0x006B3F0F,
0x006B49D9,
0x006B4EA6,
0x006B52D4,
0x006B578B,
0x006B5559,
0x006660A8,
0x0066640B,
0x006E0E01,
0x006E08F4,
0x006E650F,
0x006A61DE,
0x006A68AE,
0x006A67C0,
0x00663CCD,
0x006B53E9,
0x00698D6C,
0x0068C542,
0x0068C6D1,
0x0068BC01,
0x006E66A0,
0x006E6878,
0x006C5AE9,
0x006BEFA1,
0x006C09D1,
0x006C0B83,
0x006C0BB5,
0x00669C6D,
0x00669D4A,
0x006649BD,
0x006666E7,
0x00666A63,
0x006CD8CE,
0x00669E30,
0x00669E55,
0x006E519A,
0x006E5597,
0x006B893C,
0x006B8E1B,
0x0069DFB3,
0x00684A7F,
0x006D13FE,
0x0069E73C,
0x006CDEE4,
0x006B9E6D,
0x006BA058,
0x006E0F26,
0x006E56B5,
0x006B909A,
0x006BA16A,
0x006648E3,
0x0068DF91
};
#pragma endregion

View File

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

View File

@ -27,6 +27,10 @@
#include "strings.h"
#include "window.h"
// HACK These were originally passed back through registers
int gLastDrawStringX;
int gLastDrawStringY;
uint8 _screenDirtyBlocks[5120];
static void gfx_draw_dirty_blocks(int x, int y, int columns, int rows);
@ -486,5 +490,17 @@ void gfx_draw_string_left(rct_drawpixelinfo *dpi, int format, void *args, int co
*/
void gfx_draw_string(rct_drawpixelinfo *dpi, char *format, int colour, int x, int y)
{
RCT2_CALLPROC_X(0x00682702, colour, 0, x, y, format, dpi, 0);
int eax, ebx, ecx, edx, esi, edi, ebp;
eax = colour;
ebx = 0;
ecx = x;
edx = y;
esi = format;
edi = dpi;
ebp = 0;
RCT2_CALLFUNC_X(0x00682702, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
gLastDrawStringX = ecx;
gLastDrawStringY = edx;
}

View File

@ -46,6 +46,9 @@ typedef struct {
sint16 unused; // 0x0E
} rct_g1_element;
extern int gLastDrawStringX;
extern int gLastDrawStringY;
void gfx_load_g1();
void gfx_clear(rct_drawpixelinfo *dpi, int colour);

135
src/map.c
View File

@ -1,5 +1,5 @@
/*****************************************************************************
* Copyright (c) 2014 Ted John
* Copyright (c) 2014 Ted John, Peter Hill
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
@ -123,34 +123,147 @@ void map_update_tile_pointers()
}
/**
*
* Return the absolute height of an element, given its (x,y) coordinates
*
* rct2: 0x00662783
* UNFINISHED
*/
int sub_662783(int x, int y)
int map_element_height(int x, int y)
{
int i;
rct_map_element *mapElement;
// Off the map
if (x >= 8192 || y >= 8192)
return 16;
x &= 0xFFFFFFE0;
y &= 0xFFFFFFE0;
// Find the tile the element is on
int x_tile = x & 0xFFFFFFE0;
int y_tile = y & 0xFFFFFFE0;
i = ((y * 256) + x) / 8;
i = ((y_tile * 256) + x_tile) / 32;
mapElement = TILE_MAP_ELEMENT_POINTER(i);
while (mapElement->type & MAP_ELEMENT_TYPE_MASK) {
mapElement++;
}
uint32 result =
uint32 height =
((mapElement->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK) << 20) |
(mapElement->base_height << 3);
uint32 ebx = (mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK) & ~0x16;
// slope logic
uint32 slope = (mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK);
uint8 extra_height = (slope & 0x10) >> 4; // 0x10 is the 5th bit - sets slope to double height
// Remove the extra height bit
slope &= 0xF;
return result;
uint8 quad, quad_extra; // which quadrant the element is in?
// quad_extra is for extra height tiles
uint8 xl, yl; // coordinates across this tile
uint8 TILE_SIZE = 31;
xl = x & 0x1f;
yl = y & 0x1f;
// Slope logic:
// Each of the four bits in slope represents that corner being raised
// slope == 15 (all four bits) is not used and slope == 0 is flat
// If the extra_height bit is set, then the slope goes up two z-levels
// We arbitrarily take the SW corner to be closest to the viewer
// One corner up
if ((slope == 1) || (slope == 2) || (slope == 4) || (slope == 8)) {
switch (slope) {
case 1: // NE corner up
quad = xl + yl - TILE_SIZE;
break;
case 2: // SE corner up
quad = xl - yl;
break;
case 4: // SW corner up
quad = TILE_SIZE - yl - xl;
break;
case 8: // NW corner up
quad = xl - yl;
break;
}
// If the element is in the quadrant with the slope, raise its height
if (quad > 0) {
height += quad / 2;
}
}
// One side up
switch (slope) {
case 3: // E side up
height += xl / 2;
break;
case 6: // S side up
height += (TILE_SIZE - yl) / 2;
break;
case 9: // N side up
height += yl / 2;
height++;
break;
case 12: // W side up
height += (TILE_SIZE - xl) / 2;
break;
}
// One corner down
if ((slope == 7) || (slope == 11) || (slope == 13) || (slope == 14)) {
switch (slope) {
case 7: // NW corner down
quad_extra = xl + TILE_SIZE - yl;
quad = xl - yl;
break;
case 11: // SW corner down
quad_extra = xl + yl;
quad = xl + yl - TILE_SIZE;
break;
case 13: // SE corner down
quad_extra = TILE_SIZE - xl + yl;
quad = xl - yl;
break;
case 14: // NE corner down
quad_extra = (TILE_SIZE - xl) + (TILE_SIZE - yl);
quad = TILE_SIZE - yl - xl;
break;
}
if (extra_height) {
height += quad_extra / 2;
height++;
return height;
}
// This tile is essentially at the next height level
height += 0x10;
// so we move *down* the slope
if (quad < 0) {
height += quad / 2;
height += 0xFF00;
}
}
// Valleys
if ((slope == 5) || (slope == 10)) {
switch (slope) {
case 5: // NW-SE valley
if (xl + yl <= TILE_SIZE + 1) {
return height;
}
quad = TILE_SIZE - xl - yl;
break;
case 10: // NE-SW valley
quad = xl - yl;
break;
}
if (quad > 0) {
height += quad / 2;
}
}
return height;
}

View File

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

View File

@ -184,17 +184,9 @@ void news_item_get_subject_location(int type, int subject, int *x, int *y, int *
*x = SPRITE_LOCATION_NULL;
break;
}
{
uint32 eax, ebx, ecx, edx, esi, edi, ebp;
eax = (ride->var_050 & 0xFF) * 32 + 16;
ecx = (ride->var_050 >> 8) * 32 + 16;
RCT2_CALLFUNC_X(0x00662783, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
if (edx & 0xFFFF0000)
edx >>= 16;
*x = eax;
*y = ecx;
*z = edx;
}
*x = (ride->var_050 & 0xFF) * 32 + 16;
*y = (ride->var_050 >> 8) * 32 + 16;
*z = map_element_height(*x, *y);
break;
case NEWS_ITEM_PEEP_ON_RIDE:
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[subject]);
@ -233,16 +225,10 @@ void news_item_get_subject_location(int type, int subject, int *x, int *y, int *
*z = peep->z;
break;
case NEWS_ITEM_BLANK:
{
uint32 eax, ebx, ecx, edx, esi, edi, ebp;
eax = subject;
ecx = subject >> 16;
RCT2_CALLFUNC_X(0x00662783, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
*x = eax;
*y = ecx;
*z = edx;
}
break;
*x = subject;
*y = subject >> 16;
*z = map_element_height(*x, *y);
break;
default:
*x = SPRITE_LOCATION_NULL;
break;

View File

@ -22,6 +22,7 @@
#define _NEWS_ITEM_H_
#include "rct2.h"
#include "map.h"
enum {
NEWS_ITEM_NULL,

View File

@ -19,6 +19,7 @@
*****************************************************************************/
#include <stdio.h>
#include <windows.h>
#include <SDL.h>
#include <SDL_syswm.h>
@ -288,3 +289,63 @@ void osinterface_free()
osinterface_close_window();
SDL_Quit();
}
/**
*
* rct2: 0x004080EA
*/
int osinterface_open_common_file_dialog(int type, char *title, char *filename, char *filterPattern, char *filterName)
{
char initialDirectory[MAX_PATH], *dotAddress, *slashAddress;
OPENFILENAME openFileName;
BOOL result;
int tmp;
// Get directory path from given filename
strcpy(initialDirectory, filename);
dotAddress = strrchr(filename, '.');
if (dotAddress != NULL) {
slashAddress = strrchr(filename, '\\');
if (slashAddress < dotAddress)
*(slashAddress + 1) = 0;
}
// Clear filename
*filename = 0;
// Set open file name options
memset(&openFileName, 0, sizeof(OPENFILENAME));
openFileName.lStructSize = sizeof(OPENFILENAME);
openFileName.hwndOwner = RCT2_GLOBAL(0x009E2D70, HWND);
openFileName.lpstrFile = filename;
openFileName.nMaxFile = MAX_PATH;
openFileName.lpstrInitialDir = initialDirectory;
openFileName.lpstrTitle = title;
// Copy filter name
strcpy(0x01423800, filterName);
// Copy filter pattern
strcpy(0x01423800 + strlen(filterName) + 1, filterPattern);
*((char*)(0x01423800 + strlen(filterName) + 1 + strlen(filterPattern) + 1)) = 0;
openFileName.lpstrFilter = 0x01423800;
//
tmp = RCT2_GLOBAL(0x009E2C74, uint32);
if (RCT2_GLOBAL(0x009E2BB8, uint32) == 2 && RCT2_GLOBAL(0x009E1AF8, uint32) == 1)
RCT2_GLOBAL(0x009E2C74, uint32) = 1;
// Open dialog
if (type == 0) {
openFileName.Flags = OFN_EXPLORER | OFN_CREATEPROMPT | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
result = GetSaveFileName(&openFileName);
} else if (type == 1) {
openFileName.Flags = OFN_EXPLORER | OFN_NONETWORKBUTTON | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
result = GetOpenFileName(&openFileName);
}
//
RCT2_GLOBAL(0x009E2C74, uint32) = tmp;
return result;
}

View File

@ -46,4 +46,6 @@ void osinterface_process_messages();
void osinterface_draw();
void osinterface_free();
int osinterface_open_common_file_dialog(int type, char *title, char *filename, char *filterPattern, char *filterName);
#endif

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/>.
*****************************************************************************/
@ -91,7 +91,9 @@ typedef struct {
sint16 x; // 0x0E
sint16 y; // 0x10
sint16 z; // 0x12
uint8 pad_14[0x0E];
uint8 pad_14[0x09];
uint8 direction; // 0x1D
uint32 pad_1E;
uint16 name_string_idx; // 0x22
uint16 next_x; // 0x24
uint16 next_y; // 0x26
@ -102,36 +104,49 @@ typedef struct {
uint8 sprite_type; // 0x2D
uint8 type; // 0x2E
uint8 staff_type; // 0x2F
uint8 var_30;
uint8 var_31;
uint8 tshirt_colour; // 0x30
uint8 trousers_colour; // 0x31
uint8 pad_32[0x06];
uint8 energy; // 0x38
uint8 var_39;
uint8 energy_growth_rate; // 0x39
uint8 happiness; // 0x3A
uint8 var_03B;
uint8 happiness_growth_rate; // 0x3B
uint8 nausea; // 0x3C
uint8 var_03D;
uint8 nausea_growth_rate; // 0x3D
uint8 hunger; // 0x3E
uint8 thirst; // 0x3F
uint8 bathroom; // 0x40
uint8 pad_041[0x27];
uint8 current_ride; // 0x68
uint8 pad_6A; // 0x6A Part of current_ride?
uint8 current_train; // 0x6B
uint8 current_car; // 0x6C
uint8 current_seat; // 0x6D
uint8 pad_6E[0x2E];
uint8 pad_69;
uint8 current_train; // 0x6A
uint8 current_car; // 0x6B
uint8 current_seat; // 0x6C
uint8 pad_6D[0x0F];
uint8 rides_been_on[32]; // 0x7C
uint32 id; // 0x9C
uint8 pad_A0[0x10];
sint32 cash_in_pocket; // 0xA0
sint32 cash_spent; // 0xA4
uint8 pad_A8[8];
rct_peep_thought thoughts[PEEP_MAX_THOUGHTS]; // 0xB0
uint16 pad_C4;
uint8 var_C6;
uint8 pad_C7;
uint32 var_C8;
uint8 pad_CC[0x2A];
uint32 var_C8; // Bit 25 Ice Cream, Bit 24 mad, Bit 3 tracking, Bit 0 leaving the park
uint8 var_CC;
uint8 pad_CD[0x17];
uint16 paid_to_enter; // 0xE4
uint16 paid_on_rides; // 0xE6
uint16 paid_on_food; // 0xE8
uint16 paid_on_souvenirs; // 0xEA
uint8 no_of_food; // 0xEC
uint8 no_of_drinks; // 0xED
uint8 no_of_souvenirs; // 0xEE
uint8 pad_EF[0x07];
uint8 balloon_colour; // 0xF6
uint8 umbrella_colour; // 0xF7
uint8 hat_colour; // 0xF8
uint8 favourite_ride; // 0xF9
} rct_peep;
int peep_get_staff_count();

View File

@ -162,6 +162,8 @@ enum {
STR_CREDIT_SPARE_6 = 863,
STR_CREDIT_SPARE_7 = 864,
STR_QUIT_SCENARIO_EDITOR = 887,
STR_SCR_BMP = 890,
STR_SCREENSHOT = 891,
STR_SCREENSHOT_SAVED_AS = 892,
@ -170,6 +172,19 @@ enum {
STR_VIEW_OPTIONS_TIP = 937,
STR_ADJUST_LAND_TIP = 938,
STR_SAVE_PROMPT_SAVE = 944,
STR_SAVE_PROMPT_DONT_SAVE = 945,
STR_SAVE_PROMPT_CANCEL = 946,
STR_SAVE_BEFORE_LOADING = 947,
STR_SAVE_BEFORE_QUITTING = 948,
STR_SAVE_BEFORE_QUITTING_2 = 949,
STR_LOAD_GAME = 950,
STR_QUIT_GAME = 951,
STR_QUIT_GAME_2 = 952,
STR_LOAD_LANDSCAPE = 953,
STR_CANCEL = 972,
STR_OK = 973,
@ -190,12 +205,31 @@ enum {
STR_LOCATE_SUBJECT_TIP = 1027,
STR_LOAD_GAME_DIALOG_TITLE = 1036,
STR_LOAD_LANDSCAPE_DIALOG_TITLE = 1037,
STR_RCT2_SAVED_GAME = 1043,
STR_RCT2_LANDSCAPE_FILE = 1045,
STR_RIDES_IN_PARK_TIP = 1053,
STR_PLACE_SCENERY_TIP = 1159,
STR_ADJUST_WATER_TIP = 1160,
STR_BUILD_FOOTPATH_TIP = 1173,
STR_CANT_BUILD_FOOTPATH_HERE = 1176,
STR_CANT_REMOVE_FOOTPATH_FROM_HERE = 1177,
STR_FOOTPATHS = 1181,
STR_TYPE = 1182,
STR_DIRECTION = 1183,
STR_SLOPE = 1184,
STR_DIRECTION_TIP = 1185,
STR_SLOPE_DOWN_TIP = 1186,
STR_LEVEL_TIP = 1187,
STR_SLOPE_UP_TIP = 1188,
STR_CONSTRUCT_THE_SELECTED_FOOTPATH_SECTION_TIP = 1189,
STR_REMOVE_PREVIOUS_FOOTPATH_SECTION_TIP = 1190,
STR_CLOSED = 1194,
STR_TEST_RUN = 1195,
@ -212,10 +246,19 @@ enum {
STR_NUMERIC_UP = 1218,
STR_NUMERIC_DOWN = 1219,
STR_BUILD_THIS = 1407,
STR_COST_LABEL = 1408,
STR_QUEUE_LINE_PATH_TIP = 1423,
STR_FOOTPATH_TIP = 1424,
STR_FREE = 1430,
STR_GUESTS = 1463,
STR_CONSTRUCT_FOOTPATH_ON_LAND_TIP = 1655,
STR_CONSTRUCT_BRIDGE_OR_TUNNEL_FOOTPATH_TIP = 1656,
STR_GUESTS_TIP = 1693,
STR_STAFF_TIP = 1694,
@ -227,6 +270,9 @@ enum {
STR_PARK_CLOSED = 1721,
STR_PARK_OPEN = 1722,
STR_CANT_OPEN_PARK = 1723,
STR_CANT_CLOSE_PARK = 1724,
STR_INDIVIDUAL_GUESTS_TIP = 1752,
STR_SUMMARISED_GUESTS_TIP = 1753,
STR_ADMISSION_PRICE = 1756,

View File

@ -152,7 +152,7 @@ static void title_update_showcase()
{
rct_window* w;
uint8 script_opcode, script_operand;
short x, y;
short x, y, z;
int i, _edx;
if (_scriptWaitCounter <= 0) {
@ -201,18 +201,12 @@ static void title_update_showcase()
case TITLE_SCRIPT_LOCATION:
x = (*_currentScript++) * 32 + 16;
y = (*_currentScript++) * 32 + 16;
// Set location
int eax, ebx, ecx, edx, esi, edi, ebp;
eax = x;
ecx = y;
RCT2_CALLFUNC_X(0x00662783, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
_edx = edx;
z = map_element_height(x, y);
// Update viewport
w = window_get_main();
if (w != NULL) {
window_scroll_to_location(w, x, y, _edx);
window_scroll_to_location(w, x, y, z);
w->flags &= ~0x08;
viewport_update_position(w);
}

View File

@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include <memory.h>
#include <stdlib.h>
#include "addresses.h"
#include "sprites.h"
@ -33,6 +34,8 @@ static void widget_text_button(rct_drawpixelinfo *dpi, rct_window *w, int widget
static void widget_text_unknown(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
static void widget_text(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
static void widget_text_inset(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
static void widget_text_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
static void widget_groupbox_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
static void widget_caption_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
static void widget_closebox_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
static void widget_scroll_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
@ -94,6 +97,10 @@ void widget_scroll_update_thumbs(rct_window *w, int widget_index)
}
}
/**
*
* rct2: 0x006EB2A8
*/
void widget_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex)
{
switch (w->widgets[widgetIndex].type) {
@ -134,7 +141,8 @@ void widget_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex)
break;
case WWT_18:
break;
case WWT_19:
case WWT_GROUPBOX:
widget_groupbox_draw(dpi, w, widgetIndex);
break;
case WWT_CAPTION:
widget_caption_draw(dpi, w, widgetIndex);
@ -500,6 +508,99 @@ static void widget_text_inset(rct_drawpixelinfo *dpi, rct_window *w, int widgetI
widget_text(dpi, w, widgetIndex);
}
/**
*
* rct2: 0x006EC1A6
*/
static void widget_text_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex)
{
rct_widget* widget;
int l, t, r, b, press;
uint8 colour;
// Get the widget
widget = &w->widgets[widgetIndex];
// Resolve the absolute ltrb
l = w->x + widget->left + 5;
t = w->y + widget->top;
r = w->x + widget->right;
b = w->y + widget->bottom;
// Get the colour
colour = w->colours[widget->colour];
press = 0;
if (widget_is_pressed(w, widgetIndex) || widget_is_active_tool(w, widgetIndex))
press |= 0x20;
gfx_fill_rect_inset(dpi, l, t, r, b, colour, press);
// TODO
gfx_fill_rect(dpi, l, t, r, b, colour);
}
/**
*
* rct2: 0x006EB535
*/
static void widget_groupbox_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex)
{
rct_widget* widget;
int l, t, r, b, textRight;
uint8 colour;
// Get the widget
widget = &w->widgets[widgetIndex];
// Resolve the absolute ltrb
l = w->x + widget->left + 5;
t = w->y + widget->top;
r = w->x + widget->right;
b = w->y + widget->bottom;
textRight = l;
// Text
if (widget->image != (uint32)-1) {
colour = w->colours[widget->colour] & 0x7F;
if (colour & 1)
colour |= 0x40;
gfx_draw_string_left(dpi, widget->image, 0x013CE952, colour, l, t);
textRight = gLastDrawStringX + 1;
}
// Border
// Resolve the absolute ltrb
l = w->x + widget->left;
t = w->y + widget->top + 4;
r = w->x + widget->right;
b = w->y + widget->bottom;
// Get the colour
colour = w->colours[widget->colour] & 0x7F;
// Border left of text
gfx_fill_rect(dpi, l, t, l + 4, t, RCT2_ADDRESS(0x0141FC47, uint8)[colour * 8]);
gfx_fill_rect(dpi, l + 1, t + 1, l + 4, t + 1, RCT2_ADDRESS(0x0141FC4B, uint8)[colour * 8]);
// Border right of text
gfx_fill_rect(dpi, textRight, t, r - 1, t, RCT2_ADDRESS(0x0141FC47, uint8)[colour * 8]);
gfx_fill_rect(dpi, textRight, t + 1, r - 2, t + 1, RCT2_ADDRESS(0x0141FC4B, uint8)[colour * 8]);
// Border right
gfx_fill_rect(dpi, r - 1, t + 1, r - 1, b - 1, RCT2_ADDRESS(0x0141FC47, uint8)[colour * 8]);
gfx_fill_rect(dpi, r, t, r, b, RCT2_ADDRESS(0x0141FC4B, uint8)[colour * 8]);
// Border bottom
gfx_fill_rect(dpi, l, b - 1, r - 2, b - 1, RCT2_ADDRESS(0x0141FC47, uint8)[colour * 8]);
gfx_fill_rect(dpi, l, b, r - 1, b, RCT2_ADDRESS(0x0141FC4B, uint8)[colour * 8]);
// Border left
gfx_fill_rect(dpi, l, t + 1, l, b - 2, RCT2_ADDRESS(0x0141FC47, uint8)[colour * 8]);
gfx_fill_rect(dpi, l + 1, t + 2, l + 1, b - 2, RCT2_ADDRESS(0x0141FC4B, uint8)[colour * 8]);
}
/**
*
* rct2: 0x006EB2F9
@ -734,6 +835,10 @@ static void widget_vscrollbar_draw(rct_drawpixelinfo *dpi, rct_scroll *scroll, i
gfx_draw_string(dpi, (char*)0x009DED69, 0, l + 1, b - 8);
}
/**
*
* rct2: 0x006EB951
*/
static void widget_draw_image(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex)
{
int l, t, r, b, colour, image;
@ -760,7 +865,26 @@ static void widget_draw_image(rct_drawpixelinfo *dpi, rct_window *w, int widgetI
if (widget_is_pressed(w, widgetIndex) || widget_is_active_tool(w, widgetIndex))
image++;
if (!widget_is_disabled(w, widgetIndex)) {
if (widget_is_disabled(w, widgetIndex)) {
// Draw greyed out (light border bottom right shadow)
colour = w->colours[widget->colour];
colour = RCT2_ADDRESS(0x00141FC4A, uint8)[(colour & 0x7F) * 8] & 0xFF;
RCT2_GLOBAL(0x009ABDA4, uint32) = 0x009DED74;
memset(0x009DED74, colour, 256);
RCT2_GLOBAL(0x009DED74, uint8) = 0;
RCT2_GLOBAL(0x00EDF81C, uint32) = 0x20000000;
image &= 0x7FFFF;
RCT2_CALLPROC_X(0x0067A46E, 0, image, l + 1, t + 1, 0, dpi, 0);
// Draw greyed out (dark)
colour = w->colours[widget->colour];
colour = RCT2_ADDRESS(0x00141FC48, uint8)[(colour & 0x7F) * 8] & 0xFF;
RCT2_GLOBAL(0x009ABDA4, uint32) = 0x009DED74;
memset(0x009DED74, colour, 256);
RCT2_GLOBAL(0x009DED74, uint8) = 0;
RCT2_GLOBAL(0x00EDF81C, uint32) = 0x20000000;
RCT2_CALLPROC_X(0x0067A46E, 0, image, l, t, 0, dpi, 0);
} else {
if (image & 0x80000000) {
// ?
}
@ -771,8 +895,6 @@ static void widget_draw_image(rct_drawpixelinfo *dpi, rct_window *w, int widgetI
image |= colour << 19;
gfx_draw_sprite(dpi, image, l, t);
} else {
// ?
}
}

View File

@ -43,7 +43,7 @@ typedef enum {
WWT_DROPDOWN = 16,
WWT_VIEWPORT = 17,
WWT_18,
WWT_19,
WWT_GROUPBOX = 19,
WWT_CAPTION = 20,
WWT_CLOSEBOX = 21,
WWT_SCROLL = 22,

View File

@ -1105,3 +1105,70 @@ void window_set_resize(rct_window *w, int minWidth, int minHeight, int maxWidth,
window_invalidate(w);
}
}
/**
*
* rct2: 0x006EE212
*
* @param tool (al)
* @param widgetIndex (dx)
* @param w (esi)
*/
int tool_set(rct_window *w, int widgetIndex, int tool)
{
if (RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3)) {
if (
w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) &&
w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) &&
widgetIndex == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16)
) {
tool_cancel();
return 1;
}
}
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 3);
RCT2_GLOBAL(0x009DE518, uint32) &= ~(1 << 6);
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) = tool;
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) = w->classification;
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) = w->number;
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) = widgetIndex;
return 0;
}
/**
*
* rct2: 0x006EE281
*/
void tool_cancel()
{
rct_window *w;
if (RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3)) {
RCT2_GLOBAL(0x009DE518, uint32) &= ~(1 << 3);
//
RCT2_CALLPROC_EBPSAFE(0x0068AAE1);
RCT2_CALLPROC_EBPSAFE(0x0068AB1B);
// Reset map selection
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) = 0;
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, sint16) >= 0) {
// Invalidate tool widget
widget_invalidate(
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass),
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber),
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16)
);
// Abort tool event
w = window_find_by_id(
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_ABORT], 0, 0, 0, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), w, 0, 0);
}
}
}

View File

@ -250,6 +250,7 @@ enum {
WC_ERROR = 11,
WC_RIDE = 12,
WC_RIDE_CONSTRUCTION = 13,
WC_SAVE_PROMPT = 14,
WC_RIDE_LIST = 15,
WC_CONSTRUCT_RIDE = 16,
WC_SCENERY = 18,
@ -319,11 +320,16 @@ void window_move_position(rct_window *w, int dx, int dy);
void window_resize(rct_window *w, int dw, int dh);
void window_set_resize(rct_window *w, int minWidth, int minHeight, int maxWidth, int maxHeight);
int tool_set(rct_window *w, int widgetIndex, int tool);
void tool_cancel();
// Open window functions
void window_main_open();
void window_game_top_toolbar_open();
void window_game_bottom_toolbar_open();
void window_about_open();
void window_footpath_open();
void window_save_prompt_open();
void window_title_menu_open();
void window_title_exit_open();
void window_title_logo_open();

View File

@ -300,7 +300,7 @@ static void window_cheats_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w)
if (!(w->disabled_widgets & (1 << WIDX_TAB_2))) {
sprite_idx = 5568;
if (w->page == WINDOW_CHEATS_PAGE_GUESTS)
sprite_idx += (w->var_48E / 2) % 8;
sprite_idx += (w->var_48E / 3) % 8;
gfx_draw_sprite(dpi, sprite_idx, w->x + w->widgets[WIDX_TAB_2].left, w->y + w->widgets[WIDX_TAB_2].top);
}
}

View File

@ -116,7 +116,7 @@ static void window_clear_scenery_close()
{
// If the tool wasn't changed, turn tool off
if (!window_clear_scenery_should_close())
RCT2_CALLPROC_EBPSAFE(0x006EE281);
tool_cancel();
}
/**

854
src/window_footpath.c Normal file
View File

@ -0,0 +1,854 @@
/*****************************************************************************
* Copyright (c) 2014 Ted John
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include <string.h>
#include "addresses.h"
#include "audio.h"
#include "game.h"
#include "map.h"
#include "strings.h"
#include "sprites.h"
#include "viewport.h"
#include "widget.h"
#include "window.h"
#include "window_dropdown.h"
enum {
PATH_CONSTRUCTION_MODE_LAND,
PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL,
PATH_CONSTRUCTION_MODE_2
};
typedef struct {
uint16 pad_00;
uint32 image; // 0x02
uint32 pad_06;
uint8 pad_0A;
uint8 flags; // 0x0B
} rct_path_type;
static enum WINDOW_FOOTPATH_WIDGET_IDX {
WIDX_BACKGROUND,
WIDX_TITLE,
WIDX_CLOSE,
WIDX_TYPE_GROUP,
WIDX_FOOTPATH_TYPE,
WIDX_QUEUELINE_TYPE,
WIDX_DIRECTION_GROUP,
WIDX_DIRECTION_NW,
WIDX_DIRECTION_NE,
WIDX_DIRECTION_SW,
WIDX_DIRECTION_SE,
WIDX_SLOPE_GROUP,
WIDX_SLOPEDOWN,
WIDX_LEVEL,
WIDX_SLOPEUP,
WIDX_CONSTRUCT,
WIDX_REMOVE,
WIDX_MODE_GROUP,
WIDX_CONSTRUCT_ON_LAND,
WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL,
};
static rct_widget window_footpath_widgets[] = {
{ WWT_FRAME, 0, 0, 105, 0, 380, 0x0FFFFFFFF, STR_NONE },
{ WWT_CAPTION, 0, 1, 104, 1, 14, STR_FOOTPATHS, STR_WINDOW_TITLE_TIP },
{ WWT_CLOSEBOX, 0, 93, 103, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
// Type group
{ WWT_GROUPBOX, 0, 3, 102, 17, 71, STR_TYPE, STR_NONE },
{ WWT_FLATBTN, 1, 6, 52, 30, 65, 0xFFFFFFFF, STR_FOOTPATH_TIP },
{ WWT_FLATBTN, 1, 53, 99, 30, 65, 0xFFFFFFFF, STR_QUEUE_LINE_PATH_TIP },
// Direction group
{ WWT_GROUPBOX, 0, 3, 102, 75, 151, STR_DIRECTION, STR_NONE },
{ WWT_FLATBTN, 1, 53, 97, 87, 115, 5635, STR_DIRECTION_TIP },
{ WWT_FLATBTN, 1, 53, 97, 116, 144, 5636, STR_DIRECTION_TIP },
{ WWT_FLATBTN, 1, 8, 52, 116, 144, 5637, STR_DIRECTION_TIP },
{ WWT_FLATBTN, 1, 8, 52, 87, 115, 5638, STR_DIRECTION_TIP },
// Slope group
{ WWT_GROUPBOX, 0, 3, 102, 155, 195, STR_SLOPE, STR_NONE },
{ WWT_FLATBTN, 1, 17, 40, 167, 190, 5145, STR_SLOPE_DOWN_TIP },
{ WWT_FLATBTN, 1, 41, 64, 167, 190, 5146, STR_LEVEL_TIP },
{ WWT_FLATBTN, 1, 65, 88, 167, 190, 5147, STR_SLOPE_UP_TIP },
{ WWT_FLATBTN, 1, 8, 97, 202, 291, 0xFFFFFFFF, STR_CONSTRUCT_THE_SELECTED_FOOTPATH_SECTION_TIP },
{ WWT_FLATBTN, 1, 30, 75, 295, 318, 5162, STR_REMOVE_PREVIOUS_FOOTPATH_SECTION_TIP },
// Mode group
{ WWT_GROUPBOX, 0, 3, 102, 321, 374, 0xFFFFFFFF, STR_NONE },
{ WWT_FLATBTN, 1, 13, 48, 332, 367, 5639, STR_CONSTRUCT_FOOTPATH_ON_LAND_TIP },
{ WWT_FLATBTN, 1, 57, 92, 332, 367, 5640, STR_CONSTRUCT_BRIDGE_OR_TUNNEL_FOOTPATH_TIP },
{ WIDGETS_END },
};
static void window_footpath_emptysub() { }
static void window_footpath_close();
static void window_footpath_mouseup();
static void window_footpath_mousedown();
static void window_footpath_dropdown();
static void window_footpath_update();
static void window_footpath_toolupdate();
static void window_footpath_tooldown();
static void window_footpath_tooldrag();
static void window_footpath_toolup();
static void window_footpath_invalidate();
static void window_footpath_paint();
static uint32 window_footpath_events[] = {
window_footpath_close,
window_footpath_mouseup,
window_footpath_emptysub,
window_footpath_mousedown,
window_footpath_dropdown,
window_footpath_emptysub,
window_footpath_update,
window_footpath_emptysub,
window_footpath_emptysub,
window_footpath_toolupdate,
window_footpath_tooldown,
window_footpath_tooldrag,
window_footpath_toolup,
window_footpath_emptysub,
window_footpath_emptysub,
window_footpath_emptysub,
window_footpath_emptysub,
window_footpath_emptysub,
window_footpath_emptysub,
window_footpath_emptysub,
window_footpath_emptysub,
window_footpath_emptysub,
window_footpath_emptysub,
window_footpath_emptysub,
window_footpath_emptysub,
window_footpath_invalidate,
window_footpath_paint,
window_footpath_emptysub
};
sint32 _window_footpath_cost;
static void window_footpath_show_footpath_types_dialog(rct_window *w, rct_widget *widget, int showQueues);
static void window_footpath_set_provisional_path_at_point(int x, int y);
static int window_footpath_set_provisional_path(int type, int x, int y, int z, int slope);
static void window_footpath_place_path_at_point(int x, int y);
static void window_footpath_construct();
static void window_footpath_remove();
/**
*
* rct2: 0x006A7C43
*/
void window_footpath_open()
{
rct_window* window;
// Check if window is already open
window = window_bring_to_front_by_id(WC_FOOTPATH, 0);
if (window != NULL)
return;
window = window_create(
0,
29,
106,
381,
window_footpath_events,
WC_FOOTPATH,
0
);
window->widgets = window_footpath_widgets;
window->enabled_widgets =
(1 << WIDX_CLOSE) |
(1 << WIDX_FOOTPATH_TYPE) |
(1 << WIDX_QUEUELINE_TYPE) |
(1 << WIDX_DIRECTION_NW) |
(1 << WIDX_DIRECTION_NE) |
(1 << WIDX_DIRECTION_SW) |
(1 << WIDX_DIRECTION_SE) |
(1 << WIDX_SLOPEDOWN) |
(1 << WIDX_LEVEL) |
(1 << WIDX_SLOPEUP) |
(1 << WIDX_CONSTRUCT) |
(1 << WIDX_REMOVE) |
(1 << WIDX_CONSTRUCT_ON_LAND) |
(1 << WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL);
window_init_scroll_widgets(window);
RCT2_CALLPROC_EBPSAFE(0x006EE65A);
show_gridlines();
window->colours[0] = 24;
window->colours[1] = 24;
window->colours[2] = 24;
tool_cancel();
RCT2_GLOBAL(0x00F3EF99, uint8) = PATH_CONSTRUCTION_MODE_LAND;
tool_set(window, WIDX_CONSTRUCT_ON_LAND, 17);
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 6);
RCT2_GLOBAL(0x00F3EF9F, uint8) = 0;
RCT2_CALLPROC_EBPSAFE(0x006A855C);
}
/**
*
* rct2: 0x006A852F
*/
static void window_footpath_close()
{
rct_window *w;
__asm mov w, esi
RCT2_CALLPROC_EBPSAFE(0x006A7831);
RCT2_CALLPROC_X(0x006CB70A, 0, 0, 0, 0, 0, 0, 0);
RCT2_CALLPROC_EBPSAFE(0x0068AB1B);
RCT2_GLOBAL(0x009DE58A, uint16) &= ~2;
window_invalidate_by_id(WC_TOP_TOOLBAR, 0);
hide_gridlines();
}
/**
*
* rct2: 0x006A7E92
*/
static void window_footpath_mouseup()
{
short widgetIndex;
rct_window *w;
__asm mov widgetIndex, dx
__asm mov w, esi
switch (widgetIndex) {
case WIDX_CLOSE:
window_close(w);
break;
case WIDX_CONSTRUCT:
window_footpath_construct();
break;
case WIDX_REMOVE:
window_footpath_remove();
break;
case WIDX_CONSTRUCT_ON_LAND:
if (RCT2_GLOBAL(0x00F3EF99, uint8) == PATH_CONSTRUCTION_MODE_LAND)
break;
_window_footpath_cost = 0x80000000;
tool_cancel();
RCT2_CALLPROC_EBPSAFE(0x006A7831);
RCT2_CALLPROC_EBPSAFE(0x0068AB1B);
RCT2_GLOBAL(0x009DE58A, uint16) &= ~2;
RCT2_GLOBAL(0x00F3EF99, uint8) = PATH_CONSTRUCTION_MODE_LAND;
tool_set(w, WIDX_CONSTRUCT_ON_LAND, 17);
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 6);
RCT2_GLOBAL(0x00F3EF9F, uint8) = 0;
RCT2_CALLPROC_EBPSAFE(0x006A855C);
break;
case WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL:
if (RCT2_GLOBAL(0x00F3EF99, uint8) == PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL)
break;
_window_footpath_cost = 0x80000000;
RCT2_CALLPROC_EBPSAFE(0x006EE281);
RCT2_CALLPROC_EBPSAFE(0x006A7831);
RCT2_CALLPROC_EBPSAFE(0x0068AB1B);
RCT2_GLOBAL(0x009DE58A, uint16) &= ~2;
RCT2_GLOBAL(0x00F3EF99, uint8) = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL;
tool_set(w, WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL, 12);
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 6);
RCT2_GLOBAL(0x00F3EF9F, uint8) = 0;
RCT2_CALLPROC_EBPSAFE(0x006A855C);
break;
}
}
/**
*
* rct2: 0x006A7EC5
*/
static void window_footpath_mousedown()
{
short widgetIndex;
rct_window *w;
rct_widget *widget;
__asm mov widgetIndex, dx
__asm mov w, esi
__asm mov widget, edi
switch (widgetIndex) {
case WIDX_FOOTPATH_TYPE:
window_footpath_show_footpath_types_dialog(w, widget, 0);
break;
case WIDX_QUEUELINE_TYPE:
window_footpath_show_footpath_types_dialog(w, widget, 1);
break;
case WIDX_DIRECTION_NW:
RCT2_CALLPROC_X(0x006A8111, 0, 0, 0, 0, w, 0, 0);
break;
case WIDX_DIRECTION_NE:
RCT2_CALLPROC_X(0x006A8135, 0, 0, 0, 0, w, 0, 0);
break;
case WIDX_DIRECTION_SW:
RCT2_CALLPROC_X(0x006A815C, 0, 0, 0, 0, w, 0, 0);
break;
case WIDX_DIRECTION_SE:
RCT2_CALLPROC_X(0x006A8183, 0, 0, 0, 0, w, 0, 0);
break;
case WIDX_SLOPEDOWN:
RCT2_CALLPROC_X(0x006A81AA, 0, 0, 0, 0, w, 0, 0);
break;
case WIDX_LEVEL:
RCT2_CALLPROC_X(0x006A81C5, 0, 0, 0, 0, w, 0, 0);
break;
case WIDX_SLOPEUP:
RCT2_CALLPROC_X(0x006A81E0, 0, 0, 0, 0, w, 0, 0);
break;
}
}
/**
*
* rct2: 0x006A7F18
*/
static void window_footpath_dropdown()
{
int i, j, pathId;
short dropdownIndex;
short widgetIndex;
rct_window *w;
rct_path_type *pathType;
__asm mov dropdownIndex, ax
__asm mov widgetIndex, dx
__asm mov w, esi
if (widgetIndex == WIDX_FOOTPATH_TYPE)
RCT2_GLOBAL(0x00F3EFA2, uint8) = 0;
else if (widgetIndex == WIDX_QUEUELINE_TYPE)
RCT2_GLOBAL(0x00F3EFA2, uint8) = 1;
else
return;
// Get path id
pathId = dropdownIndex;
if (pathId == -1) {
pathId = RCT2_GLOBAL(0x00F3EFA0, sint16);
} else {
int flags = 4;
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)
flags = 0;
j = 0;
for (i = 0; i < 16; i++) {
pathType = RCT2_ADDRESS(0x009ADA14, rct_path_type*)[i];
if (pathType == (rct_path_type*)-1)
continue;
if (pathType->flags & flags)
continue;
if (j == pathId)
break;
j++;
}
pathId = i;
}
// Set selected path id
RCT2_GLOBAL(0x00F3EFA0, sint16) = pathId;
RCT2_CALLPROC_EBPSAFE(0x006A7831);
_window_footpath_cost = 0x80000000;
window_invalidate(w);
}
/**
*
* rct2: 0x006A8032
*/
static void window_footpath_toolupdate()
{
int x, y, z;
short widgetIndex;
rct_window *w;
rct_map_element *mapElement;
__asm mov x, eax
__asm mov y, ebx
__asm mov widgetIndex, dx
__asm mov w, esi
if (widgetIndex == WIDX_CONSTRUCT_ON_LAND) {
window_footpath_set_provisional_path_at_point(x, y);
} else if (widgetIndex == WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL) {
RCT2_CALLPROC_X(0x006A8388, 0, 0, 0, 0, w, 0, 0);
}
}
/**
*
* rct2: 0x006A8047
*/
static void window_footpath_tooldown()
{
int x, y, z;
short widgetIndex;
rct_window *w;
rct_map_element *mapElement;
__asm mov x, eax
__asm mov y, ebx
__asm mov widgetIndex, dx
__asm mov w, esi
if (widgetIndex == WIDX_CONSTRUCT_ON_LAND) {
window_footpath_place_path_at_point(x, y);
} else if (widgetIndex == WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL) {
RCT2_CALLPROC_X(0x006A840F, x, y, 0, 0, w, 0, 0);
}
}
/**
*
* rct2: 0x006A8067
*/
static void window_footpath_tooldrag()
{
int x, y;
short widgetIndex;
rct_window *w;
__asm mov x, eax
__asm mov y, ebx
__asm mov widgetIndex, dx
__asm mov w, esi
if (widgetIndex == WIDX_CONSTRUCT_ON_LAND) {
RCT2_CALLPROC_X(0x006A82C5, x, y, 0, 0, w, 0, 0);
}
}
/**
*
* rct2: 0x006A8066
*/
static void window_footpath_toolup()
{
int x, y;
short widgetIndex;
rct_window *w;
__asm mov x, eax
__asm mov y, ebx
__asm mov widgetIndex, dx
__asm mov w, esi
if (widgetIndex == WIDX_CONSTRUCT_ON_LAND) {
RCT2_CALLPROC_X(0x006A8380, x, y, 0, 0, w, 0, 0);
}
}
/**
*
* rct2: 0x006A84BB
*/
static void window_footpath_update()
{
rct_window *w;
__asm mov w, esi
// Invalidate construct button
widget_invalidate(WC_FOOTPATH, 0, WIDX_CONSTRUCT);
RCT2_CALLPROC_EBPSAFE(0x006A7760);
// Check tool
if (RCT2_GLOBAL(0x00F3EF99, uint8) == PATH_CONSTRUCTION_MODE_LAND) {
if (!(RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3)))
window_close(w);
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_FOOTPATH)
window_close(w);
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) != WIDX_CONSTRUCT_ON_LAND)
window_close(w);
} else if (RCT2_GLOBAL(0x00F3EF99, uint8) == PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL) {
if (!(RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3)))
window_close(w);
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_FOOTPATH)
window_close(w);
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) != WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL)
window_close(w);
}
}
/**
*
* rct2: 0x006A7D1C
*/
static void window_footpath_invalidate()
{
int selectedPath;
rct_path_type *pathType;
rct_window *w;
__asm mov w, esi
// Press / unpress footpath and queue type buttons
w->pressed_widgets &= ~(1 << WIDX_FOOTPATH_TYPE);
w->pressed_widgets &= ~(1 << WIDX_QUEUELINE_TYPE);
w->pressed_widgets |= RCT2_GLOBAL(0x00F3EFA2, uint8) == 0 ?
(1 << WIDX_FOOTPATH_TYPE) :
(1 << WIDX_QUEUELINE_TYPE);
// Enable / disable construct button
window_footpath_widgets[WIDX_CONSTRUCT].type = RCT2_GLOBAL(0x00F3EF99, uint8) == PATH_CONSTRUCTION_MODE_LAND ? WWT_EMPTY : WWT_IMGBTN;
// Set footpath and queue type button images
selectedPath = RCT2_GLOBAL(0x00F3EFA0, uint16);
pathType = RCT2_ADDRESS(0x009ADA14, rct_path_type*)[selectedPath];
int pathImage = 71 + pathType->image;
window_footpath_widgets[WIDX_FOOTPATH_TYPE].image = pathImage;
window_footpath_widgets[WIDX_QUEUELINE_TYPE].image = pathImage + 1;
window_footpath_widgets[WIDX_QUEUELINE_TYPE].type = WWT_FLATBTN;
// Disable queue in if in editor
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)
window_footpath_widgets[WIDX_QUEUELINE_TYPE].type = WWT_EMPTY;
}
/**
*
* rct2: 0x006A7D8B
*/
static void window_footpath_paint()
{
int x, y, image, selectedPath;
rct_path_type *pathType;
rct_window *w;
rct_drawpixelinfo *dpi;
__asm mov w, esi
__asm mov dpi, edi
window_draw_widgets(w, dpi);
if (!(w->disabled_widgets & (1 << WIDX_CONSTRUCT))) {
// Get construction image
image = (RCT2_GLOBAL(0x00F3EF90, uint8) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)) % 4;
if (RCT2_GLOBAL(0x00F3EF91, uint8) == 2)
image += 4;
else if (RCT2_GLOBAL(0x00F3EF91, uint8) == 6)
image += 8;
image = RCT2_ADDRESS(0x0098D7E0, uint8)[image];
selectedPath = RCT2_GLOBAL(0x00F3EFA0, uint16);
pathType = RCT2_ADDRESS(0x009ADA14, rct_path_type*)[selectedPath];
image += pathType->image;
if (RCT2_GLOBAL(0x00F3EFA2, uint8) != 0)
image += 51;
// Draw construction image
x = w->x + (window_footpath_widgets[WIDX_CONSTRUCT].left + window_footpath_widgets[WIDX_CONSTRUCT].right) / 2;
y = w->y + window_footpath_widgets[WIDX_CONSTRUCT].bottom - 60;
gfx_draw_sprite(dpi, image, x, y);
// Draw build this... label
x = w->x + (window_footpath_widgets[WIDX_CONSTRUCT].left + window_footpath_widgets[WIDX_CONSTRUCT].right) / 2;
y = w->y + window_footpath_widgets[WIDX_CONSTRUCT].bottom - 23;
gfx_draw_string_centred(dpi, STR_BUILD_THIS, x, y, 0, 0);
}
// Draw cost
x = w->x + (window_footpath_widgets[WIDX_CONSTRUCT].left + window_footpath_widgets[WIDX_CONSTRUCT].right) / 2;
y = w->y + window_footpath_widgets[WIDX_CONSTRUCT].bottom - 12;
if (_window_footpath_cost != 0x80000000)
if (!(RCT2_GLOBAL(RCT2_ADDRESS_GAME_FLAGS, uint32) & GAME_FLAGS_NO_MONEY))
gfx_draw_string_centred(dpi, STR_COST_LABEL, x, y, 0, &_window_footpath_cost);
}
/**
*
* rct2: 0x006A7F88
*/
static void window_footpath_show_footpath_types_dialog(rct_window *w, rct_widget *widget, int showQueues)
{
int i, flags, numPathTypes, image;
rct_path_type *pathType;
numPathTypes = 0;
flags = 4;
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)
flags = 0;
for (i = 0; i < 16; i++) {
pathType = RCT2_ADDRESS(0x009ADA14, rct_path_type*)[i];
if (pathType == (rct_path_type*)-1)
continue;
if (pathType->flags & flags)
continue;
image = pathType->image + 71;
if (showQueues)
image++;
gDropdownItemsFormat[numPathTypes] = -1;
gDropdownItemsArgs[numPathTypes] = image;
numPathTypes++;
}
window_dropdown_show_image(
w->x + widget->left, w->y + widget->top, widget->bottom - widget->top + 1,
w->colours[1],
0,
numPathTypes,
47,
36,
gAppropriateImageDropdownItemsPerRow[numPathTypes]
);
}
/**
*
* rct2: 0x006A81FB
*/
static void window_footpath_set_provisional_path_at_point(int x, int y)
{
int z, slope, pathType;
rct_map_element *mapElement;
RCT2_CALLPROC_EBPSAFE(0x0068AAE1);
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~4;
// Get map coordinates from point
int eax, ebx, ecx, edx, esi, edi, ebp;
eax = x;
ebx = y;
edx = -34;
RCT2_CALLFUNC_X(0x00685ADC, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
x = eax & 0xFFFF;
z = ebx & 0xFF;
y = ecx & 0xFFFF;
mapElement = edx;
if (z == 0) {
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~1;
RCT2_CALLPROC_EBPSAFE(0x006A7831);
} else {
// Check for change
if ((RCT2_GLOBAL(0x00F3EF92, uint8) & 2) && RCT2_GLOBAL(0x00F3EF94, uint16) == x && RCT2_GLOBAL(0x00F3EF96, uint16) == y && RCT2_GLOBAL(0x00F3EF98, uint8) == mapElement->base_height)
return;
// Set map selection
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= 1;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 4;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16) = y;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16) = y;
RCT2_CALLPROC_EBPSAFE(0x006A7831);
// Set provisional path
slope = RCT2_ADDRESS(0x0098D8B4, uint8)[mapElement->properties.surface.slope & 0x1F];
if (z == 6)
slope = mapElement->properties.surface.slope & 7;
pathType = (RCT2_GLOBAL(0x00F3EFA2, uint8) << 7) + RCT2_GLOBAL(0x00F3EFA0, uint8);
_window_footpath_cost = window_footpath_set_provisional_path(pathType, x, y, mapElement->base_height, slope);
// window_invalidate_by_id(eax, ebx);
}
}
/**
*
* rct2: 0x006A76FF
*/
static int window_footpath_set_provisional_path(int type, int x, int y, int z, int slope)
{
int cost;
int eax, ebx, ecx, edx, esi, edi, ebp;
RCT2_CALLPROC_EBPSAFE(0x006A77FF);
// Try and show provisional path
cost = game_do_command(x, (slope << 8) | 121, y, (type << 8) | z, 17, 0, 0);
if (cost != 0x80000000) {
RCT2_GLOBAL(0x00F3EF94, uint16) = x;
RCT2_GLOBAL(0x00F3EF96, uint16) = y;
RCT2_GLOBAL(0x00F3EF98, uint8) = z & 0xFF;
RCT2_GLOBAL(0x00F3EF92, uint8) |= 2;
eax = 3;
if (RCT2_GLOBAL(0x00F3EFA4, uint8) & 2)
eax = 1;
RCT2_CALLPROC_X(0x006CB70A, eax, 0, 0, 0, 0, 0, 0);
}
return cost;
}
/**
*
* rct2: 0x006A82C5
*/
static void window_footpath_place_path_at_point(int x, int y)
{
int z, presentType, selectedType, cost;
rct_map_element *mapElement;
if (RCT2_GLOBAL(0x00F3EF9F, uint8) != 0)
return;
RCT2_CALLPROC_EBPSAFE(0x006A7831);
// Get map coordinates from point
int eax, ebx, ecx, edx, esi, edi, ebp;
eax = x;
ebx = y;
edx = -34;
RCT2_CALLFUNC_X(0x00685ADC, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
x = eax & 0xFFFF;
z = ebx & 0xFF;
y = ecx & 0xFFFF;
mapElement = edx;
if (z == 0)
return;
// Set path
presentType = RCT2_ADDRESS(0x0098D8B4, uint8)[mapElement->properties.path.type & 0x1F];
if (z == 6)
presentType = mapElement->properties.path.type & 7;
z = mapElement->base_height;
selectedType = (RCT2_GLOBAL(0x00F3EFA2, uint8) << 7) + RCT2_GLOBAL(0x00F3EFA0, uint8);
// Prepare error text
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, uint16) = STR_CANT_BUILD_FOOTPATH_HERE;
// Try and place path
cost = game_do_command(x, (presentType << 8) | 1, y, (selectedType << 8) | z, 17, 0, 0);
if (cost == 0x80000000) {
RCT2_GLOBAL(0x00F3EF9F, uint8) = 1;
} else if (RCT2_GLOBAL(0x00F3EFD9, uint32) != 0) {
// bp = 0x009DEA62
// dx = 0x009DEA60
// cx = 0x009DEA5E
sound_play_panned(6, 0x8001);
}
}
/**
*
* rct2: 0x006A79B7
*/
static void window_footpath_construct()
{
RCT2_CALLPROC_EBPSAFE(0x006A79B7);
}
/**
*
* rct2: 0x006A7863
*/
static void window_footpath_remove()
{
int x, y, z, lastTile;
rct_map_element *mapElement;
// RCT2_CALLPROC_EBPSAFE(0x006A7863);
_window_footpath_cost = 0x80000000;
RCT2_CALLPROC_EBPSAFE(0x006A7831);
x = RCT2_GLOBAL(0x00F3EF8A, uint16) / 32;
y = RCT2_GLOBAL(0x00F3EF8C, uint16) / 32;
int dl = (RCT2_GLOBAL(0x00F3EF8E, uint16) >> 3) & 0xFF;
int dh = dl - 2;
if (x >= 256 || y >= 256)
goto loc_6A79B0;
mapElement = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[y * 256 + x];
do {
if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH) {
if (mapElement->base_height == dl) {
if (mapElement->properties.path.type & 4)
if (((mapElement->properties.path.type & 3) ^ 2) != RCT2_GLOBAL(0x00F3EF90, uint8))
continue;
goto loc_6A78EF;
} else if (mapElement->base_height == dh) {
if (!(mapElement->properties.path.type & 4))
if ((mapElement->properties.path.type & 3) == RCT2_GLOBAL(0x00F3EF90, uint8))
continue;
goto loc_6A78EF;
}
}
lastTile = (mapElement->flags & MAP_ELEMENT_FLAG_LAST_TILE) != 0;
mapElement++;
} while (!lastTile);
goto loc_6A79B0;
loc_6A78EF:
dl = mapElement->base_height;
int pathType = mapElement->properties.path.type;
if (pathType & 4) {
pathType &= 3;
pathType ^= 2;
if (pathType == RCT2_GLOBAL(0x00F3EF90, uint8))
dl += 2;
}
// Find a connected edge
int edge = RCT2_GLOBAL(0x00F3EF90, uint8) ^ 2;
if (!(mapElement->properties.path.edges & (1 << edge))) {
edge = (edge + 1) % 4;
if (!(mapElement->properties.path.edges & (1 << edge))) {
edge = (edge + 2) % 4;
if (!(mapElement->properties.path.edges & (1 << edge))) {
edge = (edge - 1) % 4;
if (!(mapElement->properties.path.edges & (1 << edge)))
edge ^= 2;
}
}
}
// Remove path
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, uint16) = STR_CANT_REMOVE_FOOTPATH_FROM_HERE;
game_do_command(RCT2_GLOBAL(0x00F3EF8A, uint16), 1, RCT2_GLOBAL(0x00F3EF8C, uint16), mapElement->base_height, 19, 0, 0);
// Move selection
edge ^= 2;
x = RCT2_GLOBAL(0x00F3EF8A, uint16) - RCT2_GLOBAL(0x00993CCC + (edge * 4), sint16);
y = RCT2_GLOBAL(0x00F3EF8C, uint16) - RCT2_GLOBAL(0x00993CCE + (edge * 4), sint16);
RCT2_GLOBAL(0x00F3EF8A, uint16) = x;
RCT2_GLOBAL(0x00F3EF8C, uint16) = y;
RCT2_GLOBAL(0x00F3EF8E, uint16) = dl << 3;
RCT2_GLOBAL(0x00F3EF90, uint8) = edge;
RCT2_GLOBAL(0x00F3EF9E, uint8) = 255;
loc_6A79B0:
RCT2_CALLPROC_EBPSAFE(0x006A855C);
}

View File

@ -176,10 +176,10 @@ static void window_game_top_toolbar_mouseup()
case WIDX_CLEAR_SCENERY:
if ((RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3)) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == 1 && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 16) {
RCT2_CALLPROC_EBPSAFE(0x006EE281);
tool_cancel();
} else {
show_gridlines();
RCT2_CALLPROC_X(0x006EE212, 12, 0, 0, WIDX_CLEAR_SCENERY, w, 0, 0);
tool_set(w, WIDX_CLEAR_SCENERY, 12);
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 6);
RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 2;
window_clear_scenery_open();
@ -187,10 +187,10 @@ static void window_game_top_toolbar_mouseup()
break;
case WIDX_LAND:
if ((RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3)) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == 1 && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 7) {
RCT2_CALLPROC_EBPSAFE(0x006EE281);
tool_cancel();
} else {
show_gridlines();
RCT2_CALLPROC_X(0x006EE212, 18, 0, 0, WIDX_LAND, w, 0, 0);
tool_set(w, WIDX_LAND, 18);
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 6);
RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 1;
window_land_open();
@ -198,26 +198,26 @@ static void window_game_top_toolbar_mouseup()
break;
case WIDX_WATER:
if ((RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3)) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == 1 && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 8) {
RCT2_CALLPROC_EBPSAFE(0x006EE281);
tool_cancel();
} else {
show_gridlines();
RCT2_CALLPROC_X(0x006EE212, 19, 0, 0, WIDX_WATER, w, 0, 0);
tool_set(w, WIDX_WATER, 19);
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 6);
RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 1;
window_water_open();
}
break;
case WIDX_SCENERY:
RCT2_CALLPROC_X(0x006EE212, 0, 0, 0, WIDX_SCENERY, w, 0, 0);
tool_set(w, WIDX_SCENERY, 0);
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 6);
RCT2_CALLPROC_EBPSAFE(0x006E0FEF);
break;
case WIDX_PATH:
if (window_find_by_id(20, 0) == NULL) {
RCT2_CALLPROC_EBPSAFE(0x00006A7C43);
if (window_find_by_id(WC_FOOTPATH, 0) == NULL) {
window_footpath_open();
} else {
RCT2_CALLPROC_EBPSAFE(0x006EE281);
window_close_by_id(0x80 | 20, 0);
tool_cancel();
window_close_by_id(0x80 | WC_FOOTPATH, 0);
}
break;
case WIDX_CONSTRUCT_RIDE:
@ -346,7 +346,7 @@ static void window_game_top_toolbar_dropdown()
game_do_command(0, 1, 0, 0, 5, 0, 0);
break;
case 1: // save game
RCT2_CALLPROC_EBPSAFE(0x006EE281);
tool_cancel();
{
int eax, ebx, ecx, edx, esi, edi, ebp;
RCT2_CALLFUNC_X(0x006750E9, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);

View File

@ -152,7 +152,7 @@ static void window_land_close()
{
// If the tool wasn't changed, turn tool off
if (!window_land_should_close())
RCT2_CALLPROC_EBPSAFE(0x006EE281);
tool_cancel();
}
/**

192
src/window_save_prompt.c Normal file
View File

@ -0,0 +1,192 @@
/*****************************************************************************
* Copyright (c) 2014 Ted John
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include "addresses.h"
#include "game.h"
#include "rct2.h"
#include "strings.h"
#include "sprites.h"
#include "tutorial.h"
#include "widget.h"
#include "window.h"
static enum WINDOW_SAVE_PROMPT_WIDGET_IDX {
WIDX_BACKGROUND,
WIDX_TITLE,
WIDX_CLOSE,
WIDX_3,
WIDX_SAVE,
WIDX_DONT_SAVE,
WIDX_CANCEL
};
static rct_widget window_save_prompt_widgets[] = {
{ WWT_FRAME, 0, 0, 259, 0, 49, -1, STR_NONE }, // panel / background
{ WWT_CAPTION, 0, 1, 258, 1, 14, 0, STR_WINDOW_TITLE_TIP }, // title bar
{ WWT_CLOSEBOX, 0, 247, 257, 2, 13, 824, STR_CLOSE_WINDOW_TIP }, // close x button
{ WWT_12, 0, 2, 257, 19, 30, 0, STR_NONE }, //
{ WWT_DROPDOWN_BUTTON, 0, 8, 85, 35, 46, STR_SAVE_PROMPT_SAVE, STR_NONE }, // save
{ WWT_DROPDOWN_BUTTON, 0, 91, 168, 35, 46, STR_SAVE_PROMPT_DONT_SAVE, STR_NONE }, // don't save
{ WWT_DROPDOWN_BUTTON, 0, 174, 251, 35, 46, STR_SAVE_PROMPT_CANCEL, STR_NONE }, // cancel
{ WIDGETS_END },
};
static void window_save_prompt_emptysub() { }
static void window_save_prompt_close();
static void window_save_prompt_mouseup();
static void window_save_prompt_paint();
static uint32 window_save_prompt_events[] = {
window_save_prompt_close,
window_save_prompt_mouseup,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_emptysub,
window_save_prompt_paint,
window_save_prompt_emptysub
};
/**
*
* rct2: 0x0066DCBE
*/
void window_save_prompt_open()
{
int stringId;
rct_window* window;
// Check if window is already open
window = window_bring_to_front_by_id(WC_SAVE_PROMPT, 0);
if (window == NULL) {
window = window_create(
(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) / 2) - 130,
max(28, (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16) / 2) - 25),
260,
50,
window_save_prompt_events,
WC_SAVE_PROMPT,
0
);
window->widgets = window_save_prompt_widgets;
window->enabled_widgets =
(1 << WIDX_CLOSE) |
(1 << WIDX_SAVE) |
(1 << WIDX_DONT_SAVE) |
(1 << WIDX_CANCEL);
window_init_scroll_widgets(window);
window->colours[0] = 154;
window->flags |= WF_TRANSPARENT;
// Pause the game
RCT2_GLOBAL(0x009DEA6E, uint8) |= 2;
RCT2_CALLPROC_EBPSAFE(0x006BABB4);
window_invalidate_by_id(0x80 | WC_TOP_TOOLBAR, 0);
}
stringId = RCT2_GLOBAL(0x009A9802, uint16) + STR_LOAD_GAME;
if (stringId == STR_LOAD_GAME && RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)
stringId = STR_LOAD_LANDSCAPE;
if (stringId == STR_QUIT_GAME && RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)
stringId = STR_QUIT_SCENARIO_EDITOR;
window_save_prompt_widgets[WIDX_TITLE].image = stringId;
window_save_prompt_widgets[WIDX_3].image = RCT2_GLOBAL(0x009A9802, uint16) + STR_SAVE_BEFORE_LOADING;
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0D) {
game_load_or_quit_no_save_prompt();
return;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 0) {
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 1) {
RCT2_CALLPROC_EBPSAFE(0x0066EE54);
game_load_or_quit_no_save_prompt();
return;
} else {
tutorial_stop();
game_load_or_quit_no_save_prompt();
return;
}
}
if (RCT2_GLOBAL(0x009DEA66, uint16) < 3840) {
game_load_or_quit_no_save_prompt();
return;
}
}
/**
*
* rct2: 0x0066DF17
*/
static void window_save_prompt_close()
{
// Unpause the game
RCT2_GLOBAL(0x009DEA6E, uint8) &= ~2;
RCT2_CALLPROC_EBPSAFE(0x006BABD8);
window_invalidate_by_id(0x80 | WC_TOP_TOOLBAR, 0);
}
/**
*
* rct2: 0x0066DDF2
*/
static void window_save_prompt_mouseup()
{
short widgetIndex;
rct_window *w;
__asm mov widgetIndex, dx
__asm mov w, esi
// TODO
}
static void window_save_prompt_paint()
{
rct_window *w;
rct_drawpixelinfo *dpi;
__asm mov w, esi
__asm mov dpi, edi
window_draw_widgets(w, dpi);
}

View File

@ -117,7 +117,7 @@ static void window_water_close()
{
// If the tool wasn't changed, turn tool off
if (!window_water_should_close())
RCT2_CALLPROC_EBPSAFE(0x006EE281);
tool_cancel();
}
/**