OpenRCT2/src/windows/title_scenarioselect.c

438 lines
14 KiB
C
Raw Normal View History

/*****************************************************************************
* 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/>.
*****************************************************************************/
2014-10-06 18:36:58 +02:00
#include "../addresses.h"
#include "../config.h"
2014-10-06 18:36:58 +02:00
#include "../audio/audio.h"
#include "../localisation/date.h"
#include "../localisation/localisation.h"
#include "../scenario.h"
#include "../sprites.h"
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../interface/themes.h"
#include "../util/util.h"
2014-04-09 19:38:04 +02:00
enum {
WIDX_BACKGROUND,
WIDX_TITLEBAR,
WIDX_CLOSE,
WIDX_TABCONTENT,
WIDX_TAB1,
WIDX_TAB2,
WIDX_TAB3,
WIDX_TAB4,
WIDX_TAB5,
WIDX_TAB6,
WIDX_TAB7,
WIDX_TAB8,
2014-04-09 19:38:04 +02:00
WIDX_SCENARIOLIST
};
static rct_widget window_scenarioselect_widgets[] = {
{ WWT_FRAME, 0, 0, 733, 0, 333, -1, STR_NONE }, // panel / background
{ WWT_CAPTION, 0, 1, 732, 1, 14, STR_SELECT_SCENARIO, STR_WINDOW_TITLE_TIP }, // title bar
{ WWT_CLOSEBOX, 0, 721, 731, 2, 13, 824, STR_CLOSE_WINDOW_TIP }, // close x button
{ WWT_IMGBTN, 1, 0, 733, 50, 333, -1, STR_NONE }, // tab content panel
{ WWT_TAB, 1, 3, 93, 17, 50, 0x200015BC, STR_NONE }, // tab 1
{ WWT_TAB, 1, 94, 184, 17, 50, 0x200015BC, STR_NONE }, // tab 2
{ WWT_TAB, 1, 185, 275, 17, 50, 0x200015BC, STR_NONE }, // tab 3
{ WWT_TAB, 1, 276, 366, 17, 50, 0x200015BC, STR_NONE }, // tab 4
{ WWT_TAB, 1, 367, 457, 17, 50, 0x200015BC, STR_NONE }, // tab 5
{ WWT_TAB, 1, 458, 593, 17, 50, 0x200015BC, STR_NONE }, // tab 6
{ WWT_TAB, 1, 594, 684, 17, 50, 0x200015BC, STR_NONE }, // tab 7
{ WWT_TAB, 1, 685, 775, 17, 50, 0x200015BC, STR_NONE }, // tab 8
{ WWT_SCROLL, 1, 3, 555, 54, 329, 2, STR_NONE }, // level list
{ WIDGETS_END },
};
2014-04-09 19:38:04 +02:00
static void window_scenarioselect_init_tabs();
static void window_scenarioselect_mouseup(rct_window *w, int widgetIndex);
2014-05-28 23:22:09 +02:00
static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
static void window_scenarioselect_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height);
static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex, int x, int y);
static void window_scenarioselect_scrollmouseover(rct_window *w, int scrollIndex, int x, int y);
static void window_scenarioselect_invalidate(rct_window *w);
static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi);
static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex);
static rct_window_event_list window_scenarioselect_events = {
NULL,
2014-04-09 19:38:04 +02:00
window_scenarioselect_mouseup,
NULL,
2014-04-09 19:38:04 +02:00
window_scenarioselect_mousedown,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
2014-04-09 19:38:04 +02:00
window_scenarioselect_scrollgetsize,
window_scenarioselect_scrollmousedown,
NULL,
2014-04-09 19:38:04 +02:00
window_scenarioselect_scrollmouseover,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
2014-04-09 19:38:04 +02:00
window_scenarioselect_invalidate,
window_scenarioselect_paint,
window_scenarioselect_scrollpaint
};
/**
2015-10-20 20:16:30 +02:00
*
* rct2: 0x006781B5
*/
2014-04-09 19:38:04 +02:00
void window_scenarioselect_open()
{
rct_window* window;
int window_width;
2014-10-16 03:02:43 +02:00
if (window_bring_to_front_by_class(WC_SCENARIO_SELECT) != NULL)
return;
// Load scenario list
2014-04-09 15:43:27 +02:00
scenario_load_list();
// Shrink the window if we're showing scenarios by difficulty level.
if (gConfigGeneral.scenario_select_mode == 2)
{
window_width = 610;
window_scenarioselect_widgets[WIDX_BACKGROUND].right = 609;
window_scenarioselect_widgets[WIDX_TITLEBAR].right = 608;
window_scenarioselect_widgets[WIDX_CLOSE].left = 597;
window_scenarioselect_widgets[WIDX_CLOSE].right = 607;
window_scenarioselect_widgets[WIDX_TABCONTENT].right = 609;
window_scenarioselect_widgets[WIDX_SCENARIOLIST].right = 433;
}
else
window_width = 733;
2015-02-14 19:26:59 +01:00
window = window_create_centred(
window_width,
2014-04-09 15:43:27 +02:00
334,
&window_scenarioselect_events,
2014-04-13 23:23:56 +02:00
WC_SCENARIO_SELECT,
WF_10
2014-04-09 15:43:27 +02:00
);
2014-04-09 19:38:04 +02:00
window->widgets = window_scenarioselect_widgets;
2015-10-20 20:16:30 +02:00
window->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2)
| (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_TAB5)
| (1 << WIDX_TAB6) | (1 << WIDX_TAB7) | (1 << WIDX_TAB8);
window_init_scroll_widgets(window);
2014-08-23 09:30:31 +02:00
window->viewport_focus_coordinates.var_480 = -1;
window->scenario = NULL;
2014-04-09 19:38:04 +02:00
window_scenarioselect_init_tabs();
window->selected_tab = 0;
2014-04-09 19:38:04 +02:00
}
/**
2015-10-20 20:16:30 +02:00
*
2014-04-09 19:38:04 +02:00
* rct2: 0x00677C8A
*/
static void window_scenarioselect_init_tabs()
{
int show_pages = 0;
for (int i = 0; i < gScenarioListCount; i++) {
rct_scenario_basic* scenario = &gScenarioList[i];
2014-04-10 04:23:12 +02:00
if (scenario->flags & SCENARIO_FLAGS_VISIBLE)
{
if (gConfigGeneral.scenario_select_mode == 1)
show_pages |= 1 << scenario->source_game;
else
show_pages |= 1 << scenario->category;
}
2014-04-09 19:38:04 +02:00
}
int x = 3;
for (int i = 0; i < 8; i++) {
rct_widget* widget = &window_scenarioselect_widgets[i + 4];
2014-04-09 19:38:04 +02:00
if (!(show_pages & (1 << i))) {
widget->type = WWT_EMPTY;
continue;
2014-04-09 19:38:04 +02:00
}
widget->type = WWT_TAB;
widget->left = x;
widget->right = x + 90;
x += 91;
}
}
static void window_scenarioselect_mouseup(rct_window *w, int widgetIndex)
2014-04-09 19:38:04 +02:00
{
if (widgetIndex == WIDX_CLOSE)
window_close(w);
}
2014-05-28 23:22:09 +02:00
static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
2014-04-09 19:38:04 +02:00
{
if (widgetIndex >= WIDX_TAB1 && widgetIndex <= WIDX_TAB8) {
w->selected_tab = widgetIndex - 4;
w->scenario = NULL;
2014-04-09 19:38:04 +02:00
window_invalidate(w);
window_event_resize_call(w);
window_event_invalidate_call(w);
2014-04-09 19:38:04 +02:00
window_init_scroll_widgets(w);
window_invalidate(w);
}
}
static void window_scenarioselect_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height)
2014-04-09 19:38:04 +02:00
{
*height = 0;
for (int i = 0; i < gScenarioListCount; i++) {
rct_scenario_basic *scenario = &gScenarioList[i];
if ((gConfigGeneral.scenario_select_mode == 1 && scenario->source_game != w->selected_tab) ||
(gConfigGeneral.scenario_select_mode == 2 && scenario->category != w->selected_tab))
2014-04-09 19:38:04 +02:00
continue;
2014-04-10 04:23:12 +02:00
if (scenario->flags & SCENARIO_FLAGS_VISIBLE)
*height += 24;
2014-04-09 19:38:04 +02:00
}
}
/**
*
* rct2: 0x6780FE
*/
static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex, int x, int y)
2014-04-09 19:38:04 +02:00
{
int num_unlocks = 5;
for (int i = 0; i < gScenarioListCount; i++) {
rct_scenario_basic *scenario = &gScenarioList[i];
if ((gConfigGeneral.scenario_select_mode == 1 && scenario->source_game != w->selected_tab) ||
(gConfigGeneral.scenario_select_mode == 2 && scenario->category != w->selected_tab))
2014-04-09 19:38:04 +02:00
continue;
2014-04-10 04:23:12 +02:00
if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE))
2014-04-09 19:38:04 +02:00
continue;
if (gConfigGeneral.scenario_unlocking_enabled) {
if (num_unlocks <= 0)
break;
bool is_completed = scenario->flags & SCENARIO_FLAGS_COMPLETED;
if (is_completed) {
num_unlocks++;
} else {
num_unlocks--;
}
}
2014-04-09 19:38:04 +02:00
y -= 24;
if (y >= 0)
continue;
2015-11-18 00:05:24 +01:00
audio_play_sound_panned(SOUND_CLICK_1, w->width / 2 + w->x, 0, 0, 0);
2014-04-10 16:14:47 +02:00
scenario_load_and_play(scenario);
2014-04-09 19:38:04 +02:00
break;
}
}
/**
*
* rct2: 0x678162
*/
static void window_scenarioselect_scrollmouseover(rct_window *w, int scrollIndex, int x, int y)
2014-04-09 19:38:04 +02:00
{
rct_scenario_basic *selected = NULL;
int num_unlocks = 5;
for (int i = 0; i < gScenarioListCount; i++) {
rct_scenario_basic *scenario = &gScenarioList[i];
if ((gConfigGeneral.scenario_select_mode == 1 && scenario->source_game != w->selected_tab) ||
(gConfigGeneral.scenario_select_mode == 2 && scenario->category != w->selected_tab))
continue;
if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE))
2014-04-09 19:38:04 +02:00
continue;
if (gConfigGeneral.scenario_unlocking_enabled) {
if (num_unlocks <= 0)
break;
bool is_completed = scenario->flags & SCENARIO_FLAGS_COMPLETED;
num_unlocks += is_completed ? 1 : -1;
}
2014-04-09 19:38:04 +02:00
y -= 24;
if (y >= 0)
continue;
selected = scenario;
break;
}
if (w->scenario != selected) {
w->scenario = selected;
2014-04-09 19:38:04 +02:00
window_invalidate(w);
}
}
static void window_scenarioselect_invalidate(rct_window *w)
2014-04-09 19:38:04 +02:00
{
colour_scheme_update(w);
2014-04-09 19:38:04 +02:00
w->pressed_widgets &= ~( (1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2)
| (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_TAB5)
| (1 << WIDX_TAB6) | (1 << WIDX_TAB7) | (1 << WIDX_TAB8) );
w->pressed_widgets |= 1LL << (w->selected_tab + 4);
2014-04-09 19:38:04 +02:00
}
static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi)
2014-04-09 19:38:04 +02:00
{
int i, x, y, format;
2014-04-09 19:38:04 +02:00
rct_widget *widget;
2014-04-10 04:23:12 +02:00
rct_scenario_basic *scenario;
2014-04-09 19:38:04 +02:00
window_draw_widgets(w, dpi);
2015-10-20 20:16:30 +02:00
format = (theme_get_preset()->features.rct1_scenario_font) ? 5138 : 1193;
2014-04-09 19:38:04 +02:00
// Text for each tab
for (i = 0; i < 8; i++) {
2014-04-09 19:38:04 +02:00
widget = &window_scenarioselect_widgets[WIDX_TAB1 + i];
if (widget->type == WWT_EMPTY)
continue;
x = (widget->left + widget->right) / 2 + w->x;
y = (widget->top + widget->bottom) / 2 + w->y - 3;
if (gConfigGeneral.scenario_select_mode == 1) {
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = STR_SCENARIO_CATEGORY_RCT1 + i;
} else { // old-style
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = STR_BEGINNER_PARKS + i;
}
gfx_draw_string_centred_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 87, format, 10);
2014-04-09 19:38:04 +02:00
}
// Return if no scenario highlighted
scenario = w->scenario;
2014-04-10 04:23:12 +02:00
if (scenario == NULL)
2014-04-09 19:38:04 +02:00
return;
// Scenario name
x = w->x + window_scenarioselect_widgets[WIDX_SCENARIOLIST].right + 4;
y = w->y + window_scenarioselect_widgets[WIDX_TABCONTENT].top + 5;
safe_strncpy((char*)0x009BC677, scenario->name, 64);
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = 3165; // empty string
gfx_draw_string_centred_clipped(dpi, 1193, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x + 85, y, 170);
2014-04-09 19:38:04 +02:00
y += 15;
2014-04-10 04:23:12 +02:00
// Scenario details
safe_strncpy((char*)0x009BC677, scenario->details, 256);
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = 3165; // empty string
y += gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 170, 1191, 0) + 5;
2014-04-09 19:38:04 +02:00
// Scenario objective
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = scenario->objective_type + STR_OBJECTIVE_NONE;
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, short) = scenario->objective_arg_3;
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, short) = date_get_total_months(MONTH_OCTOBER, scenario->objective_arg_1);
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, int) = scenario->objective_arg_2;
y += gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 170, STR_OBJECTIVE, 0) + 5;
2014-04-09 19:38:04 +02:00
// Scenario score
2014-04-10 04:23:12 +02:00
if (scenario->flags & SCENARIO_FLAGS_COMPLETED) {
safe_strncpy((char*)0x009BC677, scenario->completed_by, 64);
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = 3165; // empty string
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, int) = scenario->company_value;
y += gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 170, STR_COMPLETED_BY_WITH_COMPANY_VALUE, 0);
2014-04-10 04:23:12 +02:00
}
2014-04-09 19:38:04 +02:00
}
static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex)
2014-04-09 19:38:04 +02:00
{
int colour = ColourMapA[w->colours[1]].mid_light;
2014-04-09 19:38:04 +02:00
colour = (colour << 24) | (colour << 16) | (colour << 8) | colour;
gfx_clear(dpi, colour);
int highlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1193;
int unhighlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1191;
int disabled_format = 5619;
bool wide = gConfigGeneral.scenario_select_mode == 1;
int y = 0;
int num_unlocks = 5;
for (int i = 0; i < gScenarioListCount; i++) {
rct_scenario_basic *scenario = &gScenarioList[i];
if ((gConfigGeneral.scenario_select_mode == 1 && scenario->source_game != w->selected_tab) ||
(gConfigGeneral.scenario_select_mode == 2 && scenario->category != w->selected_tab))
2014-04-09 19:38:04 +02:00
continue;
2014-04-10 04:23:12 +02:00
if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE))
2014-04-09 19:38:04 +02:00
continue;
if (y > dpi->y + dpi->height)
continue;
// Draw hover highlight
bool is_highlighted = w->highlighted_item == (int)scenario;
if (is_highlighted)
2014-04-09 19:38:04 +02:00
gfx_fill_rect(dpi, 0, y, w->width, y + 23, 0x02000031);
bool is_completed = scenario->flags & SCENARIO_FLAGS_COMPLETED;
bool is_disabled = false;
if (gConfigGeneral.scenario_unlocking_enabled) {
if (num_unlocks <= 0)
is_disabled = true;
num_unlocks += is_completed ? 1 : -1;
}
int format = is_disabled ? 5619 : (is_highlighted ? highlighted_format : unhighlighted_format);
2014-04-09 19:38:04 +02:00
// Draw scenario name
safe_strncpy((char*)0x009BC677, scenario->name, 64);
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 3165;
gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 1, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS);
2014-04-09 19:38:04 +02:00
// Check if scenario is completed
if (is_completed) {
2014-04-09 19:38:04 +02:00
// Draw completion tick
gfx_draw_sprite(dpi, 0x5A9F, wide ? 500 : 395, y + 1, 0);
2014-04-09 19:38:04 +02:00
// Draw completion score
safe_strncpy((char*)0x009BC677, scenario->completed_by, 64);
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 2793;
2014-05-12 22:03:24 +02:00
RCT2_GLOBAL(0x013CE954, short) = 3165;
gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 11, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS);
2014-04-09 19:38:04 +02:00
}
y += 24;
}
}