From 3f59b7ad9e4e5bba7e5eeba25b6dde19f93b687c Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Mon, 14 Apr 2014 21:25:20 +0100 Subject: [PATCH] add park objective window --- projects/openrct2.vcxproj | 1 + projects/openrct2.vcxproj.filters | 3 + src/addresses.h | 8 +- src/scenario.c | 2 +- src/window.c | 5 + src/window.h | 2 + src/window_park.c | 364 ++++++++++++++++++++++++++++++ 7 files changed, 383 insertions(+), 2 deletions(-) create mode 100644 src/window_park.c diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index 175bfdf74d..1310cea835 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -73,6 +73,7 @@ + diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters index ffddfa3167..fd85ac8050 100644 --- a/projects/openrct2.vcxproj.filters +++ b/projects/openrct2.vcxproj.filters @@ -209,6 +209,9 @@ Windows + + Windows + diff --git a/src/addresses.h b/src/addresses.h index 4795d27e45..2089aa5fe8 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -123,13 +123,20 @@ #define RCT2_ADDRESS_GUESTS_IN_PARK 0x01357844 #define RCT2_ADDRESS_CURRENT_PARK_RATING 0x01357CB0 #define RCT2_ADDRESS_PARK_RATING_HISTORY 0x01357CB2 +#define RCT2_ADDRESS_OBJECTIVE_TYPE 0x013580F8 +#define RCT2_ADDRESS_OBJECTIVE_YEAR 0x013580F9 +#define RCT2_ADDRESS_OBJECTIVE_CURRENCY 0x013580FC +#define RCT2_ADDRESS_OBJECTIVE_NUM_GUESTS 0x01358100 #define RCT2_ADDRESS_CURRENT_PROFIT 0x01358330 #define RCT2_ADDRESS_CURRENT_PARK_VALUE 0x0135853C +#define RCT2_ADDRESS_COMPLETED_COMPANY_VALUE 0x01358740 #define RCT2_ADDRESS_CURRENT_COMPANY_VALUE 0x0135874C #define RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED 0x013587F8 #define RCT2_ADDRESS_MAP_SIZE 0x01358834 +#define RCT2_ADDRESS_SCENARIO_DETAILS 0x0135924A + #define RCT2_ADDRESS_CURRENT_TICKS 0x013628F4 #define RCT2_ADDRESS_RIDE_LIST 0x013628F8 #define RCT2_ADDRESS_RIDE_MEASUREMENTS 0x0138B60C @@ -144,7 +151,6 @@ #define RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS 0x013CE9A4 #define RCT2_ADDRESS_SCENARIO_NAME 0x0141F5B8 -#define RCT2_ADDRESS_SCENARIO_DETAILS 0x0141F5F8 #define RCT2_ADDRESS_WINDOW_LIST 0x01420078 #define RCT2_ADDRESS_NEW_WINDOW_PTR 0x014234B8 diff --git a/src/scenario.c b/src/scenario.c index eba29e691a..16cf640e3e 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -451,7 +451,7 @@ void scenario_load_and_play(rct_scenario_basic *scenario) RCT2_CALLPROC_EBPSAFE(0x006DFEE4); news_item_init_queue(); if (RCT2_ADDRESS(0x013580F8, uint8) != OBJECTIVE_NONE) - RCT2_CALLPROC_EBPSAFE(0x00667E57); // window_park_page_6_open(); + window_park_objective_open(); RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_RATING, sint16) = calculate_park_rating(); RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, sint16) = calculate_park_value(); diff --git a/src/window.c b/src/window.c index f7fdaf0055..da6f787de8 100644 --- a/src/window.c +++ b/src/window.c @@ -383,6 +383,11 @@ void window_invalidate_by_id(uint16 cls, rct_windownumber number) } } +void widget_invalidate(rct_windowclass cls, rct_windownumber number, int widgetIndex) +{ + window_invalidate_by_id((widgetIndex << 8) | 0x80 | cls, number); +} + /** * Initialises scroll widgets to their virtual size. * rct2: 0x006EAEB8 diff --git a/src/window.h b/src/window.h index d15c121c32..5986b0c2ca 100644 --- a/src/window.h +++ b/src/window.h @@ -277,6 +277,7 @@ rct_window *window_find_from_point(int x, int y); int window_find_widget_from_point(rct_window *w, int x, int y); void window_invalidate(rct_window *window); void window_invalidate_by_id(uint16 cls, rct_windownumber number); +void widget_invalidate(rct_windowclass cls, rct_windownumber number, int widgetIndex); void window_init_scroll_widgets(rct_window *w); int window_get_scroll_data_index(rct_window *w, int widget_index); @@ -303,5 +304,6 @@ void window_title_logo_open(); void window_scenarioselect_open(); void window_land_open(); void window_water_open(); +void window_park_objective_open(); #endif \ No newline at end of file diff --git a/src/window_park.c b/src/window_park.c new file mode 100644 index 0000000000..d6ef701378 --- /dev/null +++ b/src/window_park.c @@ -0,0 +1,364 @@ +/***************************************************************************** + * 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 . + *****************************************************************************/ + +#include "addresses.h" +#include "date.h" +#include "strings.h" +#include "sprites.h" +#include "widget.h" +#include "window.h" + +enum WINDOW_PARK_PAGE { + WINDOW_PARK_PAGE_ENTRANCE, + WINDOW_PARK_PAGE_RATING_GRAPH, + WINDOW_PARK_PAGE_GUESTS_GRAPH, + WINDOW_PARK_PAGE_PRICE, + WINDOW_PARK_PAGE_STATS, + WINDOW_PARK_PAGE_OBJECTIVE, + WINDOW_PARK_PAGE_AWARDS +}; + +enum WINDOW_PARK_WIDGET_IDX { + WIDX_BACKGROUND, + WIDX_TITLE, + WIDX_CLOSE, + WIDX_PAGE_BACKGROUND, + WIDX_TAB_1, + WIDX_TAB_2, + WIDX_TAB_3, + WIDX_TAB_4, + WIDX_TAB_5, + WIDX_TAB_6, + WIDX_TAB_7, + WIDX_ENTER_NAME +}; + +static rct_widget window_park_objective_widgets[] = { + { WWT_FRAME, 0, 0, 229, 0, 223, 0x0FFFFFFFF, 65535}, // panel / background + { WWT_CAPTION, 0, 1, 228, 1, 14, 0x361, STR_WINDOW_TITLE_TIP}, // title bar + { WWT_CLOSEBOX, 0, 217, 227, 2, 13, 0x338, STR_CLOSE_WINDOW_TIP}, // close x button + { WWT_IMGBTN, 1, 0, 229, 43, 173, 0x0FFFFFFFF, 65535}, // tab content panel + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, 2462}, // tab 1 + { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, 2463}, // tab 2 + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, 2464}, // tab 3 + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, 2465}, // tab 4 + { WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, 2466}, // tab 5 + { WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, 2467}, // tab 6 + { WWT_TAB, 1, 189, 219, 17, 43, 0x2000144E, 2468}, // tab 7 + { WWT_DROPDOWN_BUTTON, 1, 7, 222, 209, 220, 0x0AE6, 65535}, // enter name + { WIDGETS_END }, +}; + +static void window_park_objective_emptysub() { } +static void window_park_objective_mouseup(); +static void window_park_objective_update(); +static void window_park_objective_invalidate(); +static void window_park_objective_paint(); + +static uint32 window_park_objective_events[] = { + window_park_objective_emptysub, + window_park_objective_mouseup, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_update, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_emptysub, + window_park_objective_invalidate, + window_park_objective_paint, + window_park_objective_emptysub +}; + +static void window_park_align_tabs(rct_window *w); +static void window_park_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w); + +/** + * + * rct2: 0x00667F11 + */ +rct_window *window_park_open() +{ + rct_window* w; + + { + int eax, ebx, ecx, edx, esi, edi, ebp; + ebx = 0xAE00E6; + ecx = 0x4001B; + edx = 0x0097BB6C; + RCT2_CALLFUNC_X(0x006EA9B1, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + w = esi; + } + w->widgets = 0x009A8E68; + w->enabled_widgets = 0x0003E7F4; + w->number = 0; + w->var_48A = WINDOW_PARK_PAGE_ENTRANCE; + w->var_482 = 0; + w->var_48E = 0; + w->var_490 = -1; + w->var_48C = -1; + w->var_492 = 0; + RCT2_CALLPROC_X(0x00667F8B, 0, 0, 0, 0, w, 0, 0); + w->colours[0] = 1; + w->colours[1] = 19; + w->colours[2] = 19; + + return w; +} + +/** + * + * rct2: 0x00667E57 + */ +void window_park_objective_open() +{ + rct_window* window; + + window = window_bring_to_front_by_id(WC_PARK_INFORMATION, 0); + if (window == NULL) { + window = window_park_open(); + window->var_482 = -1; + window->var_484 = -1; + } + + if (RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3)) + if (window->classification == RCT2_GLOBAL(0x009DE544, rct_windowclass) && window->number == RCT2_GLOBAL(0x009DE542, rct_windownumber)) + RCT2_CALLPROC_EBPSAFE(0x006EE281); + + window->viewport = NULL; + window->var_48A = WINDOW_PARK_PAGE_OBJECTIVE; + window_invalidate(window); + window->widgets = window_park_objective_widgets; + window->enabled_widgets = + (1 << WIDX_CLOSE) | + (1 << WIDX_TAB_1) | + (1 << WIDX_TAB_2) | + (1 << WIDX_TAB_3) | + (1 << WIDX_TAB_4) | + (1 << WIDX_TAB_5) | + (1 << WIDX_TAB_6) | + (1 << WIDX_TAB_7) | + (1 << WIDX_ENTER_NAME); + window->var_020 = 0; + window->event_handlers = window_park_objective_events; + window_init_scroll_widgets(window); + window->x = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) / 2 - 115; + window->y = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16) / 2 - 87; + window_invalidate(window); +} + +static void window_park_objective_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_TAB_1: + case WIDX_TAB_2: + case WIDX_TAB_3: + case WIDX_TAB_4: + case WIDX_TAB_5: + case WIDX_TAB_6: + case WIDX_TAB_7: + RCT2_CALLPROC_X(0x00668496, 0, 0, 0, widgetIndex, w, 0, 0); + break; + case WIDX_ENTER_NAME: + RCT2_CALLPROC_X(0x006EE308, 2791, 2792, 0, 0, 0, 0, 0); + break; + } +} + +static void window_park_objective_update() +{ + rct_window *w; + + __asm mov w, esi + + w->var_48E++; + widget_invalidate(w->classification, w->number, WIDX_TAB_6); +} + +static void window_park_objective_invalidate() +{ + int i; + rct_window *w; + + __asm mov w, esi + + // Set correct active tab + for (i = 0; i < 7; i++) + w->pressed_widgets &= ~(1 << (WIDX_TAB_1 + i)); + w->pressed_widgets |= 1 << (WIDX_TAB_1 + w->var_48A); + + // Set window title arguments + *((short*)0x013CE952) = RCT2_GLOBAL(0x013573D4, uint16); + *((short*)0x013CE954) = RCT2_GLOBAL(0x013573D8, uint32); + + // + if (RCT2_GLOBAL(0x013573E4, uint32) & 0x02) + window_park_objective_widgets[WIDX_ENTER_NAME].type = WWT_DROPDOWN_BUTTON; + else + window_park_objective_widgets[WIDX_ENTER_NAME].type = WWT_EMPTY; + + // Align the tabs + window_park_align_tabs(w); + + // Set anchored widgets + window_park_objective_widgets[WIDX_BACKGROUND].right = w->width - 1; + window_park_objective_widgets[WIDX_BACKGROUND].bottom = w->height - 1; + window_park_objective_widgets[WIDX_PAGE_BACKGROUND].right = w->width - 1; + window_park_objective_widgets[WIDX_PAGE_BACKGROUND].bottom = w->width - 1; + window_park_objective_widgets[WIDX_TITLE].right = w->width - 2; + window_park_objective_widgets[WIDX_CLOSE].left = w->width - 13; + window_park_objective_widgets[WIDX_CLOSE].right = w->width - 2; +} + +/** + * + * rct2: 0x0066945C + */ +static void window_park_objective_paint() +{ + int i, x, y; + rct_window *w; + rct_drawpixelinfo *dpi; + + __asm mov w, esi + __asm mov dpi, edi + + window_draw_widgets(w, dpi); + window_park_draw_tab_images(dpi, w); + + // Scenario description + x = w->x + window_park_objective_widgets[WIDX_PAGE_BACKGROUND].left + 4; + y = w->y + window_park_objective_widgets[WIDX_PAGE_BACKGROUND].top + 7; + strcpy((char*)0x009BC677, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_DETAILS, char)); + *((short*)0x013CE952) = 3165; + y += gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, 222, 1191, 0); + y += 5; + + // Your objective: + gfx_draw_string_left(dpi, 2384, NULL, 0, x, y); + y += 10; + + // Objective + *((short*)0x013CE952) = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_NUM_GUESTS, uint16); + *((short*)0x013CE954) = date_get_total_months(MONTH_OCTOBER, RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_YEAR, uint8)); + *((int*)0x013CE956) = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_CURRENCY, sint32); + + gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, 221, 2385 + RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8), 0); + y += 5; + + // Objective outcome + if (RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32) != 0x80000000) { + if (RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32) == 0x80000001) { + // Objective failed + gfx_draw_string_left_wrapped(dpi, NULL, x, y, 222, 2789, 0); + } else { + // Objective completed + *((int*)0x013CE952) = RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32); + gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, 222, 2788, 0); + } + } +} + +static void window_park_align_tabs(rct_window *w) +{ + int i, x, tab_width; + + x = w->widgets[WIDX_TAB_1].left; + tab_width = w->widgets[WIDX_TAB_1].right - w->widgets[WIDX_TAB_1].left; + for (i = 0; i < 7; i++) { + if (w->disabled_widgets & (1 << (WIDX_TAB_1 + i))) + continue; + w->widgets[WIDX_TAB_1 + i].left = x; + w->widgets[WIDX_TAB_1 + i].right = x + tab_width; + x += tab_width + 1; + } +} + +static void window_park_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w) +{ + int sprite_idx; + + // Entrance tab + if (!(w->disabled_widgets & (1 << WIDX_TAB_1))) + gfx_draw_sprite(dpi, 5200, w->x + w->widgets[WIDX_TAB_1].left, w->y + w->widgets[WIDX_TAB_1].top); + + // Rating tab + if (!(w->disabled_widgets & (1 << WIDX_TAB_2))) { + sprite_idx = 5245; + if (w->var_48A == WINDOW_PARK_PAGE_RATING_GRAPH) + sprite_idx += (w->var_48E / 8) % 8; + gfx_draw_sprite(dpi, sprite_idx, w->x + w->widgets[WIDX_TAB_2].left, w->y + w->widgets[WIDX_TAB_2].top); + gfx_draw_sprite(dpi, SPR_RATING_HIGH, w->x + w->widgets[WIDX_TAB_2].left + 7, w->y + w->widgets[WIDX_TAB_2].top + 1); + gfx_draw_sprite(dpi, SPR_RATING_LOW, w->x + w->widgets[WIDX_TAB_2].left + 16, w->y + w->widgets[WIDX_TAB_2].top + 12); + } + + // Price tab + if (!(w->disabled_widgets & (1 << WIDX_TAB_4))) { + sprite_idx = 5253; + if (w->var_48A == WINDOW_PARK_PAGE_PRICE) + sprite_idx += (w->var_48E / 2) % 8; + gfx_draw_sprite(dpi, sprite_idx, w->x + w->widgets[WIDX_TAB_4].left, w->y + w->widgets[WIDX_TAB_4].top); + } + + // Statistics tab + if (!(w->disabled_widgets & (1 << WIDX_TAB_5))) { + sprite_idx = 5277; + if (w->var_48A == WINDOW_PARK_PAGE_STATS) + sprite_idx += (w->var_48E / 4) % 7; + gfx_draw_sprite(dpi, sprite_idx, w->x + w->widgets[WIDX_TAB_5].left, w->y + w->widgets[WIDX_TAB_5].top); + } + + // Objective tab + if (!(w->disabled_widgets & (1 << WIDX_TAB_6))) { + sprite_idx = 5511; + if (w->var_48A == WINDOW_PARK_PAGE_OBJECTIVE) + sprite_idx += (w->var_48E / 4) % 16; + gfx_draw_sprite(dpi, sprite_idx, w->x + w->widgets[WIDX_TAB_6].left, w->y + w->widgets[WIDX_TAB_6].top); + } + + // Awards tab + if (!(w->disabled_widgets & (1 << WIDX_TAB_7))) + gfx_draw_sprite(dpi, 5527, w->x + w->widgets[WIDX_TAB_7].left, w->y + w->widgets[WIDX_TAB_7].top); +} \ No newline at end of file