Feature: "Load Scenario" title sequence command

New command goes by LOADSC in script files and in the enumeration.
Scenarios are stored using the internal also used for localisation.
Scenarios selected can only be scenarios to originally come with one of
the games or expansions.
Modified Scenario Select window to have a mode just for title editor
scenario selection.
This commit is contained in:
Robert Jordan 2017-12-31 06:42:40 -05:00 committed by Michael Steenbeek
parent ec69af0410
commit 92fc010b9a
17 changed files with 232 additions and 36 deletions

View File

@ -4480,6 +4480,14 @@ STR_6170 :Tweaks
STR_6171 :Search
STR_6172 :{SMALLFONT}{BLACK}Search
STR_6173 :Please provide the name to search:
STR_6174 :Load Save
STR_6175 :Load Scenario
STR_6176 :Scenario to load:
STR_6177 :Load{MOVE_X}{87}No scenario selected
STR_6178 :Load{MOVE_X}{87}{RED}Missing scenario
STR_6179 :Select
STR_6180 :No scenario selected
STR_6181 :{RED}Missing scenario
#############
# Scenarios #

View File

@ -30,6 +30,8 @@
- Feature: Allow using object files from RCT Classic.
- Feature: Title sequences now testable in-game.
- Feature: Vehicles with matching capabilities are now always switchable.
- Feature: Add search box to track design window.
- Feature: Add load scenario command to title sequences.
- Fix: [#816] In the map window, there are more peeps flickering than there are selected (original bug).
- Fix: [#996, #2589, #2875] Viewport scrolling no longer shakes or gets stuck.
- Fix: [#1185] Close button colour of prompt windows does not match.

View File

@ -247,7 +247,7 @@ public:
return window_track_list_open(rideItem);
}
case WC_SCENARIO_SELECT:
return window_scenarioselect_open((scenarioselect_callback) intent->GetPointerExtra(INTENT_EXTRA_CALLBACK));
return window_scenarioselect_open((scenarioselect_callback) intent->GetPointerExtra(INTENT_EXTRA_CALLBACK), false);
case WD_VEHICLE:
return window_ride_open_vehicle((rct_vehicle *) intent->GetPointerExtra(INTENT_EXTRA_VEHICLE));
case WD_TRACK:

View File

@ -221,7 +221,7 @@ static void window_server_start_mouseup(rct_window *w, rct_widgetindex widgetInd
window_invalidate(w);
break;
case WIDX_START_SERVER:
window_scenarioselect_open(window_server_start_scenarioselect_callback);
window_scenarioselect_open(window_server_start_scenarioselect_callback, false);
break;
case WIDX_LOAD_SERVER:
network_set_password(_password);

View File

@ -24,6 +24,8 @@
#include <openrct2/interface/themes.h>
#include <openrct2/interface/viewport.h>
#include <openrct2/interface/widget.h>
#include <openrct2/scenario/ScenarioRepository.h>
#include <openrct2/scenario/ScenarioSources.h>
#include <openrct2/localisation/localisation.h>
#include <openrct2/util/Util.h>
#include <openrct2-ui/interface/Dropdown.h>
@ -36,7 +38,8 @@ typedef struct TITLE_COMMAND_ORDER {
} TITLE_COMMAND_ORDER;
static TITLE_COMMAND_ORDER _window_title_command_editor_orders[] = {
{ TITLE_SCRIPT_LOAD, STR_TITLE_EDITOR_ACTION_LOAD, STR_TITLE_EDITOR_ARGUMENT_SAVEFILE },
{ TITLE_SCRIPT_LOAD, STR_TITLE_EDITOR_ACTION_LOAD_SAVE, STR_TITLE_EDITOR_ARGUMENT_SAVEFILE },
{ TITLE_SCRIPT_LOADSC, STR_TITLE_EDITOR_ACTION_LOAD_SCENARIO, STR_TITLE_EDITOR_ARGUMENT_SCENARIO },
{ TITLE_SCRIPT_LOCATION, STR_TITLE_EDITOR_COMMAND_TYPE_LOCATION, STR_TITLE_EDITOR_ARGUMENT_COORDINATES },
{ TITLE_SCRIPT_ROTATE, STR_TITLE_EDITOR_COMMAND_TYPE_ROTATE, STR_TITLE_EDITOR_ARGUMENT_ROTATIONS },
{ TITLE_SCRIPT_ZOOM, STR_TITLE_EDITOR_COMMAND_TYPE_ZOOM, STR_TITLE_EDITOR_ARGUMENT_ZOOM_LEVEL },
@ -46,7 +49,7 @@ static TITLE_COMMAND_ORDER _window_title_command_editor_orders[] = {
{ TITLE_SCRIPT_END, STR_TITLE_EDITOR_END, STR_NONE },
};
#define NUM_COMMANDS 8
#define NUM_COMMANDS 9
enum WINDOW_WATER_WIDGET_IDX {
WIDX_BACKGROUND,
@ -60,6 +63,7 @@ enum WINDOW_WATER_WIDGET_IDX {
WIDX_INPUT,
WIDX_INPUT_DROPDOWN,
WIDX_GET,
WIDX_SELECT,
WIDX_OKAY,
WIDX_CANCEL
};
@ -94,6 +98,7 @@ static rct_widget window_title_command_editor_widgets[] = {
{ WWT_DROPDOWN_BUTTON, 1, WW-28, WW-18, BY2+1, BY2+10, STR_DROPDOWN_GLYPH, STR_NONE },
{ WWT_DROPDOWN_BUTTON, 1, WS+WHA+3, WW-WS-1, BY2-14, BY2-3, STR_TITLE_COMMAND_EDITOR_ACTION_GET_LOCATION, STR_NONE }, // Get location/zoom/etc
{ WWT_DROPDOWN_BUTTON, 1, WS+WHA+12, WW-WS-1, BY2-14, BY2-3, STR_TITLE_COMMAND_EDITOR_ACTION_SELECT_SCENARIO, STR_NONE }, // Select scenario
{ WWT_DROPDOWN_BUTTON, 1, 10, 80, WH-21, WH-10, STR_OK, STR_NONE }, // OKAY
{ WWT_DROPDOWN_BUTTON, 1, WW-80, WW-10, WH-21, WH-10, STR_CANCEL, STR_NONE }, // Cancel
@ -109,6 +114,7 @@ static void window_title_command_editor_invalidate(rct_window * w);
static void window_title_command_editor_paint(rct_window * w, rct_drawpixelinfo * dpi);
static void window_title_command_editor_textinput(rct_window * w, rct_widgetindex widgetIndex, char * text);
static void window_title_command_editor_inputsize(rct_window * w);
static void scenario_select_callback(const utf8 * path);
static sint32 get_command_info_index(sint32 index);
static TITLE_COMMAND_ORDER get_command_info(sint32 index);
static LocationXY16 get_location();
@ -145,6 +151,16 @@ static rct_window_event_list window_title_command_editor_events = {
nullptr
};
static void scenario_select_callback(const utf8 * path)
{
if (command.Type == TITLE_SCRIPT_LOADSC)
{
const utf8 * fileName = path_get_filename(path);
auto scenario = GetScenarioRepository()->GetByFilename(fileName);
safe_strcpy(command.Scenario, scenario->internal_name, sizeof(command.Scenario));
}
}
static sint32 get_command_info_index(sint32 index)
{
for (sint32 i = 0; i < NUM_COMMANDS; i++)
@ -225,6 +241,7 @@ void window_title_command_editor_open(TitleSequence * sequence, sint32 index, bo
(1 << WIDX_INPUT) |
(1 << WIDX_INPUT_DROPDOWN) |
(1 << WIDX_GET) |
(1 << WIDX_SELECT) |
(1 << WIDX_OKAY) |
(1 << WIDX_CANCEL);
window_init_scroll_widgets(window);
@ -298,6 +315,9 @@ static void window_title_command_editor_mouseup(rct_window * w, rct_widgetindex
}
window_invalidate(w);
break;
case WIDX_SELECT:
window_scenarioselect_open(scenario_select_callback, true);
break;
case WIDX_OKAY:
if (_window_title_command_editor_insert)
{
@ -446,6 +466,8 @@ static void window_title_command_editor_dropdown(rct_window * w, rct_widgetindex
command.SaveIndex = 0xFF;
}
break;
case TITLE_SCRIPT_LOADSC:
command.Scenario[0] = '\0';
}
window_invalidate(w);
break;
@ -561,6 +583,7 @@ static void window_title_command_editor_invalidate(rct_window * w)
window_title_command_editor_widgets[WIDX_INPUT].type = WWT_EMPTY;
window_title_command_editor_widgets[WIDX_INPUT_DROPDOWN].type = WWT_EMPTY;
window_title_command_editor_widgets[WIDX_GET].type = WWT_EMPTY;
window_title_command_editor_widgets[WIDX_SELECT].type = WWT_EMPTY;
switch (command.Type)
{
case TITLE_SCRIPT_LOAD:
@ -568,6 +591,10 @@ static void window_title_command_editor_invalidate(rct_window * w)
window_title_command_editor_widgets[WIDX_INPUT].type = WWT_DROPDOWN;
window_title_command_editor_widgets[WIDX_INPUT_DROPDOWN].type = WWT_DROPDOWN_BUTTON;
break;
case TITLE_SCRIPT_LOADSC:
window_title_command_editor_widgets[WIDX_INPUT].type = WWT_DROPDOWN;
window_title_command_editor_widgets[WIDX_SELECT].type = WWT_DROPDOWN_BUTTON;
break;
case TITLE_SCRIPT_LOCATION:
window_title_command_editor_widgets[WIDX_TEXTBOX_X].type = WWT_TEXT_BOX;
window_title_command_editor_widgets[WIDX_TEXTBOX_Y].type = WWT_TEXT_BOX;
@ -642,4 +669,42 @@ static void window_title_command_editor_paint(rct_window * w, rct_drawpixelinfo
w->widgets[WIDX_INPUT_DROPDOWN].left - w->widgets[WIDX_INPUT].left - 4);
}
}
else if (command.Type == TITLE_SCRIPT_LOADSC)
{
if (command.Scenario[0] == '\0')
{
gfx_draw_string_left_clipped(
dpi,
STR_TITLE_COMMAND_EDITOR_NO_SCENARIO_SELECTED,
nullptr,
w->colours[1],
w->x + w->widgets[WIDX_INPUT].left + 1,
w->y + w->widgets[WIDX_INPUT].top,
w->widgets[WIDX_INPUT_DROPDOWN].left - w->widgets[WIDX_INPUT].left - 4);
}
else
{
const char * name = "";
rct_string_id nameString = STR_STRING;
auto scenario =
GetScenarioRepository()->GetByInternalName(command.Scenario);
if (scenario != nullptr)
{
name = scenario->name;
}
else
{
nameString = STR_TITLE_COMMAND_EDITOR_MISSING_SCENARIO;
}
set_format_arg(0, uintptr_t, name);
gfx_draw_string_left_clipped(
dpi,
nameString,
gCommonFormatArgs,
w->colours[1],
w->x + w->widgets[WIDX_INPUT].left + 1,
w->y + w->widgets[WIDX_INPUT].top,
w->widgets[WIDX_INPUT_DROPDOWN].left - w->widgets[WIDX_INPUT].left - 4);
}
}
}

View File

@ -1002,6 +1002,27 @@ static void window_title_editor_scrollpaint_commands(rct_window * w, rct_drawpix
set_format_arg(0, uintptr_t, name);
break;
}
case TITLE_SCRIPT_LOADSC:
{
commandName = STR_TITLE_EDITOR_COMMAND_LOAD_FILE;
const char * name = "";
auto scenario =
GetScenarioRepository()->GetByInternalName(command->Scenario);
if (command->Scenario[0] == '\0')
{
commandName = STR_TITLE_EDITOR_COMMAND_LOAD_NO_SCENARIO;
}
else if (scenario != nullptr)
{
name = scenario->name;
}
else
{
commandName = STR_TITLE_EDITOR_COMMAND_LOAD_MISSING_SCENARIO;
}
set_format_arg(0, uintptr_t, name);
break;
}
default:
log_warning("Unknown command %d", command->Type);
}

View File

@ -143,7 +143,7 @@ static void window_title_menu_mouseup(rct_window *w, rct_widgetindex widgetIndex
else {
window_close_by_class(WC_LOADSAVE);
window_close_by_class(WC_SERVER_LIST);
window_scenarioselect_open(window_title_menu_scenarioselect_callback);
window_scenarioselect_open(window_title_menu_scenarioselect_callback, false);
}
break;
case WIDX_CONTINUE_SAVED_GAME:

View File

@ -145,12 +145,13 @@ static bool is_locking_enabled(rct_window *w);
static scenarioselect_callback _callback;
static bool _showLockedInformation = false;
static bool _titleEditor = false;
/**
*
* rct2: 0x006781B5
*/
rct_window * window_scenarioselect_open(scenarioselect_callback callback)
rct_window * window_scenarioselect_open(scenarioselect_callback callback, bool titleEditor)
{
rct_window* window;
sint32 windowWidth;
@ -158,6 +159,12 @@ rct_window * window_scenarioselect_open(scenarioselect_callback callback)
_callback = callback;
if (_titleEditor != titleEditor)
{
_titleEditor = titleEditor;
window_close_by_class(WC_SCENARIO_SELECT);
}
window = window_bring_to_front_by_class(WC_SCENARIO_SELECT);
if (window != nullptr)
return window;
@ -166,18 +173,17 @@ rct_window * window_scenarioselect_open(scenarioselect_callback callback)
scenario_repository_scan();
// Shrink the window if we're showing scenarios by difficulty level.
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY) {
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY && !_titleEditor)
windowWidth = 610;
} else {
else
windowWidth = 733;
}
window = window_create_centred(
windowWidth,
windowHeight,
&window_scenarioselect_events,
WC_SCENARIO_SELECT,
WF_10
WF_10 | (titleEditor ? WF_STICK_TO_FRONT : 0)
);
window->widgets = window_scenarioselect_widgets;
window->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2)
@ -202,18 +208,25 @@ static void window_scenarioselect_init_tabs(rct_window *w)
{
sint32 showPages = 0;
size_t numScenarios = scenario_repository_get_count();
for (size_t i = 0; i < numScenarios; i++) {
for (size_t i = 0; i < numScenarios; i++)
{
const scenario_index_entry *scenario = scenario_repository_get_by_index(i);
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) {
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN || _titleEditor)
{
if (_titleEditor && scenario->source_game == SCENARIO_SOURCE_OTHER)
continue;
showPages |= 1 << scenario->source_game;
} else {
}
else
{
sint32 category = scenario->category;
if (category > SCENARIO_CATEGORY_OTHER) {
if (category > SCENARIO_CATEGORY_OTHER)
{
category = SCENARIO_CATEGORY_OTHER;
}
showPages |= 1 << category;
}
}
}
sint32 firstPage = bitscanforward(showPages);
if (firstPage != -1) {
@ -294,6 +307,10 @@ static void window_scenarioselect_scrollmousedown(rct_window *w, sint32 scrollIn
audio_play_sound(SOUND_CLICK_1, 0, w->x + (w->width / 2));
gFirstTimeSaving = true;
_callback(listItem->scenario.scenario->path);
if (_titleEditor)
{
window_close(w);
}
}
break;
}
@ -383,7 +400,7 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi)
sint32 x = (widget->left + widget->right) / 2 + w->x;
sint32 y = (widget->top + widget->bottom) / 2 + w->y - 3;
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) {
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN || _titleEditor) {
set_format_arg(0, rct_string_id, ScenarioOriginStringIds[i]);
} else { // old-style
set_format_arg(0, rct_string_id, ScenarioCategoryStringIds[i]);
@ -460,7 +477,7 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo *
rct_string_id highlighted_format = (theme_get_flags() & UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT) ? STR_WHITE_STRING : STR_WINDOW_COLOUR_2_STRINGID;
rct_string_id unhighlighted_format = (theme_get_flags() & UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT) ? STR_WHITE_STRING : STR_BLACK_STRING;
bool wide = gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN;
bool wide = gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN || _titleEditor;
rct_widget *listWidget = &w->widgets[WIDX_SCENARIOLIST];
sint32 listWidth = listWidget->right - listWidget->left - 12;
@ -573,15 +590,17 @@ static void initialise_list_items(rct_window *w)
uint8 currentHeading = UINT8_MAX;
for (size_t i = 0; i < numScenarios; i++) {
const scenario_index_entry *scenario = scenario_repository_get_by_index(i);
if (!is_scenario_visible(w, scenario)) {
if (!is_scenario_visible(w, scenario))
continue;
if (_titleEditor && scenario->source_game == SCENARIO_SOURCE_OTHER)
continue;
}
sc_list_item *listItem;
// Category heading
rct_string_id headingStringId = STR_NONE;
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) {
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN || _titleEditor) {
if (w->selected_tab != SCENARIO_SOURCE_REAL && currentHeading != scenario->category) {
currentHeading = scenario->category;
headingStringId = ScenarioCategoryStringIds[currentHeading];
@ -676,7 +695,7 @@ static void initialise_list_items(rct_window *w)
static bool is_scenario_visible(rct_window *w, const scenario_index_entry *scenario)
{
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) {
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN || _titleEditor) {
if (scenario->source_game != w->selected_tab) {
return false;
}
@ -694,14 +713,14 @@ static bool is_scenario_visible(rct_window *w, const scenario_index_entry *scena
static bool is_locking_enabled(rct_window *w)
{
if (gConfigGeneral.scenario_select_mode != SCENARIO_SELECT_MODE_ORIGIN) {
if (gConfigGeneral.scenario_select_mode != SCENARIO_SELECT_MODE_ORIGIN)
return false;
}
if (!gConfigGeneral.scenario_unlocking_enabled) {
if (!gConfigGeneral.scenario_unlocking_enabled)
return false;
}
if (w->selected_tab >= 6) {
if (w->selected_tab >= 6)
return false;
}
if (_titleEditor)
return false;
return true;
}

View File

@ -87,7 +87,7 @@ rct_window * window_guest_list_open_with_filter(sint32 type, sint32 index);
rct_window * window_staff_fire_prompt_open(rct_peep* peep);
void window_title_editor_open(sint32 tab);
void window_title_command_editor_open(struct TitleSequence * sequence, sint32 command, bool insert);
rct_window * window_scenarioselect_open(scenarioselect_callback callback);
rct_window * window_scenarioselect_open(scenarioselect_callback callback, bool titleEditor);
rct_window * window_error_open(rct_string_id title, rct_string_id message);

View File

@ -3741,7 +3741,7 @@ enum {
STR_CLASSIC_MINI_COASTER_GROUP_DESC = 6119,
STR_NEWS_ITEM_RESEARCH_NEW_VEHICLE_AVAILABLE = 6120,
STR_CHEAT_OWN_ALL_LAND_TIP = 6121,
STR_NOT_ENOUGH_ROLLER_COASTERS = 6122,
@ -3798,7 +3798,7 @@ enum {
STR_CONSOLE = 6157,
STR_FAILED_TO_LOAD_IMCOMPATIBLE_RCTC_FLAG = 6158,
STR_SCALING_QUALITY_SMOOTH_NN = 6159,
STR_AVAILABLE_VEHICLES = 6160,
@ -3812,7 +3812,7 @@ enum {
STR_USE_VSYNC = 6165,
STR_USE_VSYNC_TIP = 6166,
STR_OPTIONS_ADVANCED = 6167,
STR_OPTIONS_TITLE_SEQUENCE = 6168,
STR_OPTIONS_SCENARIO_SELECTION = 6169,
@ -3822,6 +3822,15 @@ enum {
STR_GUESTS_FILTER_BY_NAME_TIP = 6172,
STR_GUESTS_ENTER_NAME_TO_SEARCH = 6173,
STR_TITLE_EDITOR_ACTION_LOAD_SAVE = 6174,
STR_TITLE_EDITOR_ACTION_LOAD_SCENARIO = 6175,
STR_TITLE_EDITOR_ARGUMENT_SCENARIO = 6176,
STR_TITLE_EDITOR_COMMAND_LOAD_NO_SCENARIO = 6177,
STR_TITLE_EDITOR_COMMAND_LOAD_MISSING_SCENARIO = 6178,
STR_TITLE_COMMAND_EDITOR_ACTION_SELECT_SCENARIO = 6179,
STR_TITLE_COMMAND_EDITOR_NO_SCENARIO_SELECTED = 6180,
STR_TITLE_COMMAND_EDITOR_MISSING_SCENARIO = 6181,
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
STR_COUNT = 32768
};

View File

@ -269,6 +269,8 @@ public:
desc.title = name.c_str();
}
String::Set(dst->internal_name, sizeof(dst->internal_name), desc.title);
rct_string_id localisedStringIds[3];
if (language_get_localised_scenario_strings(desc.title, localisedStringIds))
{

View File

@ -123,7 +123,7 @@ class ScenarioFileIndex final : public FileIndex<scenario_index_entry>
{
private:
static constexpr uint32 MAGIC_NUMBER = 0x58444953; // SIDX
static constexpr uint16 VERSION = 2;
static constexpr uint16 VERSION = 3;
static constexpr auto PATTERN = "*.sc4;*.sc6";
public:
@ -170,6 +170,7 @@ protected:
stream->WriteValue(item.objective_arg_2);
stream->WriteValue(item.objective_arg_3);
stream->Write(item.internal_name, sizeof(item.internal_name));
stream->Write(item.name, sizeof(item.name));
stream->Write(item.details, sizeof(item.details));
}
@ -192,6 +193,7 @@ protected:
item.objective_arg_3 = stream->ReadValue<sint16>();
item.highscore = nullptr;
stream->Read(item.internal_name, sizeof(item.internal_name));
stream->Read(item.name, sizeof(item.name));
stream->Read(item.details, sizeof(item.details));
@ -279,6 +281,9 @@ private:
ScenarioSources::NormaliseName(entry.name, sizeof(entry.name), entry.name);
}
// entry.name will be translated later so keep the untranslated name here
String::Set(entry.internal_name, sizeof(entry.internal_name), entry.name);
String::Set(entry.details, sizeof(entry.details), s6Info->details);
// Look up and store information regarding the origins of this scenario.
@ -380,6 +385,21 @@ public:
return nullptr;
}
const scenario_index_entry * GetByInternalName(const utf8 * name) const override {
for (size_t i = 0; i < _scenarios.size(); i++) {
const scenario_index_entry * scenario = &_scenarios[i];
if (scenario->source_game == SCENARIO_SOURCE_OTHER)
continue;
// Note: this is always case insensitive search for cross platform consistency
if (String::Equals(name, scenario->internal_name, true)) {
return &_scenarios[i];
}
}
return nullptr;
}
const scenario_index_entry * GetByPath(const utf8 * path) const override
{
for (const auto &scenario : _scenarios)

View File

@ -45,8 +45,9 @@ typedef struct scenario_index_entry
sint32 objective_arg_2;
sint16 objective_arg_3;
scenario_highscore_entry * highscore;
utf8 name[64];
utf8 internal_name[64]; // Untranslated name
utf8 name[64]; // Translated name
utf8 details[256];
} scenario_index_entry;
@ -69,6 +70,10 @@ interface IScenarioRepository
virtual size_t GetCount() const abstract;
virtual const scenario_index_entry * GetByIndex(size_t index) const abstract;
virtual const scenario_index_entry * GetByFilename(const utf8 * filename) const abstract;
/**
* Does not return custom scenarios due to the fact that they may have the same name.
*/
virtual const scenario_index_entry * GetByInternalName(const utf8 * name) const abstract;
virtual const scenario_index_entry * GetByPath(const utf8 * path) const abstract;
virtual bool TryRecordHighscore(const utf8 * scenarioFileName, money32 companyValue, const utf8 * name) abstract;

View File

@ -314,7 +314,7 @@ namespace ScenarioSources
}
}
outDesc->title = nullptr;
outDesc->title = "";
outDesc->id = SC_UNIDENTIFIED;
outDesc->source = SCENARIO_SOURCE_OTHER;
outDesc->index = -1;

View File

@ -29,6 +29,9 @@
#include "../core/String.hpp"
#include "../core/StringBuilder.hpp"
#include "../core/Zip.h"
#include "../scenario/ScenarioRepository.h"
#include "../scenario/ScenarioSources.h"
#include "../util/Util.h"
#include "TitleSequence.h"
@ -475,6 +478,16 @@ static std::vector<TitleCommand> LegacyScriptRead(utf8 * script, size_t scriptLe
command.Type = TITLE_SCRIPT_LOADRCT1;
command.SaveIndex = atoi(part1) & 0xFF;
}
else if (_stricmp(token, "LOADSC") == 0)
{
command.Type = TITLE_SCRIPT_LOADSC;
// Confirm the scenario exists
//source_desc desc;
//if (ScenarioSources::TryGetByName(part1, &desc))
//{
safe_strcpy(command.Scenario, part1, sizeof(command.Scenario));
//}
}
}
if (command.Type != TITLE_SCRIPT_UNDEFINED)
{
@ -517,7 +530,8 @@ static void LegacyScriptGetLine(IStream * stream, char * parts)
{
if (!whitespace)
{
if (part == 0 && cindex == 4 && _strnicmp(parts, "LOAD", 4) == 0)
if (part == 0 && ((cindex == 4 && _strnicmp(parts, "LOAD", 4) == 0) ||
(cindex == 6 && _strnicmp(parts, "LOADSC", 6) == 0)))
{
load = true;
}
@ -595,6 +609,17 @@ static utf8 * LegacyScriptWrite(TitleSequence * seq)
sb.Append(seq->Saves[command->SaveIndex]);
}
break;
case TITLE_SCRIPT_LOADSC:
if (command->Scenario[0] == '\0')
{
sb.Append("LOADSC <No scenario name>");
}
else
{
sb.Append("LOADSC ");
sb.Append(command->Scenario);
}
break;
case TITLE_SCRIPT_LOCATION:
String::Format(buffer, sizeof(buffer), "LOCATION %u %u", command->X, command->Y);
sb.Append(buffer);
@ -634,6 +659,7 @@ bool TitleSequenceIsLoadCommand(const TitleCommand * command)
case TITLE_SCRIPT_LOADMM:
case TITLE_SCRIPT_LOAD:
case TITLE_SCRIPT_LOADRCT1:
case TITLE_SCRIPT_LOADSC:
return true;
default:
return false;

View File

@ -18,6 +18,8 @@
#include "../common.h"
#define TITLE_COMMAND_SCENARIO_LENGTH 64
typedef struct TitleCommand
{
uint8 Type;
@ -32,6 +34,7 @@ typedef struct TitleCommand
uint8 Zoom; // ZOOM
uint8 Speed; // SPEED
uint16 Milliseconds; // WAIT
utf8 Scenario[TITLE_COMMAND_SCENARIO_LENGTH]; // LOADSC
};
} TitleCommand;
@ -70,6 +73,7 @@ enum TITLE_SCRIPT
TITLE_SCRIPT_LOOP,
TITLE_SCRIPT_ENDLOOP,
TITLE_SCRIPT_LOADRCT1,
TITLE_SCRIPT_LOADSC,
};
#ifdef __cplusplus

View File

@ -339,6 +339,21 @@ private:
}
break;
}
case TITLE_SCRIPT_LOADSC:
{
bool loadSuccess = false;
auto scenario = GetScenarioRepository()->GetByInternalName(command->Scenario);
if (scenario != nullptr)
{
loadSuccess = LoadParkFromFile(scenario->path);
}
if (!loadSuccess)
{
Console::Error::WriteLine("Failed to load: \"%s\" for the title sequence.", command->Scenario);
return false;
}
break;
}
}
return true;
}