1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 11:03:00 +01:00

Refactor title sequence player to new class

This commit is contained in:
Ted John
2016-11-21 00:16:47 +00:00
parent ccd8cff296
commit afdd45f3cc
27 changed files with 1154 additions and 74 deletions

View File

@@ -325,8 +325,10 @@
<ClCompile Include="src\ride\water\water_coaster.c" />
<ClCompile Include="src\scenario.c" />
<ClCompile Include="src\ScenarioRepository.cpp" />
<ClCompile Include="src\title\TitleScreen.cpp" />
<ClCompile Include="src\title\TitleSequence.cpp" />
<ClCompile Include="src\title\TitleSequenceManager.cpp" />
<ClCompile Include="src\title\TitleSequencePlayer.cpp" />
<ClCompile Include="src\windows\changelog.c" />
<ClCompile Include="src\windows\multiplayer.c" />
<ClCompile Include="src\windows\network_status.c" />
@@ -342,7 +344,6 @@
<ClCompile Include="src\world\duck.c" />
<ClCompile Include="src\world\money_effect.c" />
<ClCompile Include="src\world\particle.c" />
<ClCompile Include="src\title.c" />
<ClCompile Include="src\util\sawyercoding.c" />
<ClCompile Include="src\util\util.c" />
<ClCompile Include="src\version.c" />
@@ -574,8 +575,9 @@
<ClInclude Include="src\sprites.h" />
<ClInclude Include="src\title\TitleSequence.h" />
<ClInclude Include="src\title\TitleSequenceManager.h" />
<ClInclude Include="src\title\TitleSequencePlayer.h" />
<ClInclude Include="src\version.h" />
<ClInclude Include="src\title.h" />
<ClInclude Include="src\title\TitleScreen.h" />
<ClInclude Include="src\util\sawyercoding.h" />
<ClInclude Include="src\util\util.h" />
<ClInclude Include="src\windows\dropdown.h" />

View File

@@ -39,7 +39,7 @@ extern "C"
#include "object_list.h"
#include "platform/platform.h"
#include "rct2/interop.h"
#include "title.h"
#include "title/TitleScreen.h"
#include "version.h"
}

View File

@@ -83,11 +83,11 @@ public:
zip_file_t * zipFile = zip_fopen(_zip, path, 0);
if (zipFile != nullptr)
{
data = malloc(dataSize);
size_t readBytes = zip_fread(zipFile, data, dataSize);
data = Memory::Allocate<void>((size_t)dataSize);
uint64 readBytes = zip_fread(zipFile, data, dataSize);
if (readBytes != dataSize)
{
free(data);
Memory::Free(data);
data = nullptr;
dataSize = 0;
}
@@ -95,7 +95,7 @@ public:
}
}
if (outSize != nullptr) *outSize = dataSize;
if (outSize != nullptr) *outSize = (size_t)dataSize;
return data;
}

View File

@@ -17,15 +17,14 @@
#include "audio/audio.h"
#include "cheats.h"
#include "config.h"
#include "game.h"
#include "editor.h"
#include "world/footpath.h"
#include "game.h"
#include "input.h"
#include "localisation/localisation.h"
#include "interface/screenshot.h"
#include "interface/viewport.h"
#include "interface/widget.h"
#include "interface/window.h"
#include "localisation/localisation.h"
#include "management/finance.h"
#include "management/marketing.h"
#include "management/news_item.h"
@@ -39,16 +38,17 @@
#include "rct1.h"
#include "ride/ride.h"
#include "ride/ride_ratings.h"
#include "ride/vehicle.h"
#include "ride/track.h"
#include "ride/track_design.h"
#include "ride/vehicle.h"
#include "scenario.h"
#include "title.h"
#include "title/TitleScreen.h"
#include "util/sawyercoding.h"
#include "util/util.h"
#include "windows/error.h"
#include "windows/tooltip.h"
#include "world/climate.h"
#include "world/footpath.h"
#include "world/map_animation.h"
#include "world/park.h"
#include "world/scenery.h"

View File

@@ -170,7 +170,7 @@ void game_reduce_game_speed();
void game_load_or_quit_no_save_prompt();
bool game_load_sv6_path(const char * path);
int game_load_sv6(SDL_RWops* rw);
bool game_load_sv6(SDL_RWops* rw);
int game_load_network(SDL_RWops* rw);
bool game_load_save(const utf8 *path);
void game_load_init();

View File

@@ -16,8 +16,8 @@
#include "../audio/audio.h"
#include "../config.h"
#include "../game.h"
#include "../editor.h"
#include "../game.h"
#include "../input.h"
#include "../interface/chat.h"
#include "../interface/screenshot.h"
@@ -25,7 +25,7 @@
#include "../network/network.h"
#include "../platform/platform.h"
#include "../ride/track_paint.h"
#include "../title.h"
#include "../title/TitleScreen.h"
#include "../util/util.h"
#include "keyboard_shortcut.h"
#include "viewport.h"

View File

@@ -74,7 +74,6 @@ void title_sequence_change_preset(int preset)
gConfigInterface.current_title_sequence_preset = _strdup(configId);
gCurrentPreviewTitleSequence = preset;
title_refresh_sequence();
window_invalidate_all();
}

View File

@@ -18,10 +18,10 @@
#define _TITLE_SEQUENCES_H_
#include "../common.h"
#include "window.h"
#include "../config.h"
#include "../title.h"
#include "../title/TitleScreen.h"
#include "../title/TitleSequence.h"
#include "window.h"
#define TITLE_SEQUENCE_DEFAULT_PRESETS 2

361
src/openrct2.c Normal file
View File

@@ -0,0 +1,361 @@
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/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.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#include "audio/audio.h"
#include "audio/mixer.h"
#include "config.h"
#include "editor.h"
#include "game.h"
#include "interface/chat.h"
#include "interface/themes.h"
#include "interface/window.h"
#include "interface/viewport.h"
#include "intro.h"
#include "localisation/localisation.h"
#include "network/http.h"
#include "network/network.h"
#include "object_list.h"
#include "openrct2.h"
#include "platform/crash.h"
#include "platform/platform.h"
#include "rct2/interop.h"
#include "ride/ride.h"
#include "title/TitleScreen.h"
#include "title/TitleSequenceManager.h"
#include "util/util.h"
#include "version.h"
#include "world/mapgen.h"
#define UPDATE_TIME_MS 25 // (1000 / 40fps) = 25ms
int gExitCode;
int gOpenRCT2StartupAction = STARTUP_ACTION_TITLE;
utf8 gOpenRCT2StartupActionPath[512] = { 0 };
utf8 gExePath[MAX_PATH];
utf8 gCustomUserDataPath[MAX_PATH] = { 0 };
utf8 gCustomOpenrctDataPath[MAX_PATH] = { 0 };
utf8 gCustomRCT2DataPath[MAX_PATH] = { 0 };
utf8 gCustomPassword[MAX_PATH] = { 0 };
// This should probably be changed later and allow a custom selection of things to initialise like SDL_INIT
bool gOpenRCT2Headless = false;
bool gOpenRCT2ShowChangelog;
bool gOpenRCT2SilentBreakpad;
#ifndef DISABLE_NETWORK
// OpenSSL's message digest context used for calculating sprite checksums
EVP_MD_CTX *gHashCTX = NULL;
#endif // DISABLE_NETWORK
/** If set, will end the OpenRCT2 game loop. Intentially private to this module so that the flag can not be set back to 0. */
int _finished;
static void openrct2_loop();
void openrct2_write_full_version_info(utf8 *buffer, size_t bufferSize)
{
utf8 *ch = buffer;
// Name and version
safe_strcpy(ch, OPENRCT2_NAME ", v" OPENRCT2_VERSION, bufferSize - (ch - buffer));
ch = strchr(ch, '\0');
// Build information
if (!str_is_null_or_empty(gGitBranch)) {
snprintf(ch, bufferSize - (ch - buffer), "-%s", gGitBranch);
ch = strchr(ch, '\0');
}
if (!str_is_null_or_empty(gCommitSha1Short)) {
snprintf(ch, bufferSize - (ch - buffer), " build %s", gCommitSha1Short);
ch = strchr(ch, '\0');
}
if (!str_is_null_or_empty(gBuildServer)) {
snprintf(ch, bufferSize - (ch - buffer), " provided by %s", gBuildServer);
ch = strchr(ch, '\0');
}
#if DEBUG
snprintf(ch, bufferSize - (ch - buffer), " (DEBUG)");
#endif
}
static void openrct2_set_exe_path()
{
platform_get_exe_path(gExePath, sizeof(gExePath));
log_verbose("Setting exe path to %s", gExePath);
}
bool openrct2_initialise()
{
utf8 userPath[MAX_PATH];
#ifndef DISABLE_NETWORK
gHashCTX = EVP_MD_CTX_create();
assert(gHashCTX != NULL);
#endif // DISABLE_NETWORK
platform_resolve_openrct_data_path();
platform_resolve_user_data_path();
platform_get_user_directory(userPath, NULL, sizeof(userPath));
if (!platform_ensure_directory_exists(userPath)) {
log_fatal("Could not create user directory (do you have write access to your documents folder?)");
return false;
}
crash_init();
if (!rct2_interop_setup_segment()) {
log_fatal("Unable to load RCT2 data sector");
return false;
}
openrct2_set_exe_path();
config_set_defaults();
if (!config_open_default()) {
if (!config_find_or_browse_install_directory()) {
gConfigGeneral.last_run_version = strndup(OPENRCT2_VERSION, strlen(OPENRCT2_VERSION));
config_save_default();
utf8 path[MAX_PATH];
config_get_default_path(path, sizeof(path));
log_fatal("An RCT2 install directory must be specified! Please edit \"game_path\" in %s.", path);
return false;
}
}
gOpenRCT2ShowChangelog = true;
if (gConfigGeneral.last_run_version != NULL && (strcmp(gConfigGeneral.last_run_version, OPENRCT2_VERSION) == 0))
gOpenRCT2ShowChangelog = false;
gConfigGeneral.last_run_version = strndup(OPENRCT2_VERSION, strlen(OPENRCT2_VERSION));
config_save_default();
// TODO add configuration option to allow multiple instances
// if (!gOpenRCT2Headless && !platform_lock_single_instance()) {
// log_fatal("OpenRCT2 is already running.");
// return false;
// }
if (!rct2_init_directories()) {
return false;
}
if (!rct2_startup_checks()) {
return false;
}
if (!gOpenRCT2Headless) {
audio_init();
audio_populate_devices();
}
if (!language_open(gConfigGeneral.language)) {
log_error("Failed to open configured language...");
if (!language_open(LANGUAGE_ENGLISH_UK)) {
log_fatal("Failed to open fallback language...");
return false;
}
}
http_init();
theme_manager_initialise();
title_sequence_manager_scan();
rct2_interop_setup_hooks();
if (!rct2_init())
return false;
chat_init();
rct2_copy_original_user_files_over();
return true;
}
/**
* Launches the game, after command line arguments have been parsed and processed.
*/
void openrct2_launch()
{
if (openrct2_initialise()) {
gIntroState = INTRO_STATE_NONE;
if((gOpenRCT2StartupAction == STARTUP_ACTION_TITLE) && gConfigGeneral.play_intro)
gOpenRCT2StartupAction = STARTUP_ACTION_INTRO;
switch (gOpenRCT2StartupAction) {
case STARTUP_ACTION_INTRO:
gIntroState = INTRO_STATE_PUBLISHER_BEGIN;
title_load();
break;
case STARTUP_ACTION_TITLE:
title_load();
break;
case STARTUP_ACTION_OPEN:
assert(gOpenRCT2StartupActionPath != NULL);
if (!rct2_open_file(gOpenRCT2StartupActionPath)) {
fprintf(stderr, "Failed to load '%s'", gOpenRCT2StartupActionPath);
title_load();
break;
}
gScreenFlags = SCREEN_FLAGS_PLAYING;
#ifndef DISABLE_NETWORK
if (gNetworkStart == NETWORK_MODE_SERVER) {
if (gNetworkStartPort == 0) {
gNetworkStartPort = gConfigNetwork.default_port;
}
if (str_is_null_or_empty(gCustomPassword)) {
network_set_password(gConfigNetwork.default_password);
}
else {
network_set_password(gCustomPassword);
}
network_begin_server(gNetworkStartPort);
}
#endif // DISABLE_NETWORK
break;
case STARTUP_ACTION_EDIT:
if (strlen(gOpenRCT2StartupActionPath) == 0) {
editor_load();
} else {
if (!editor_load_landscape(gOpenRCT2StartupActionPath)) {
title_load();
}
}
break;
}
#ifndef DISABLE_NETWORK
if (gNetworkStart == NETWORK_MODE_CLIENT) {
if (gNetworkStartPort == 0) {
gNetworkStartPort = gConfigNetwork.default_port;
}
network_begin_client(gNetworkStartHost, gNetworkStartPort);
}
#endif // DISABLE_NETWORK
openrct2_loop();
}
openrct2_dispose();
// HACK Some threads are still running which causes the game to not terminate. Investigation required!
exit(gExitCode);
}
void openrct2_dispose()
{
network_close();
http_dispose();
language_close_all();
rct2_dispose();
config_release();
#ifndef DISABLE_NETWORK
EVP_MD_CTX_destroy(gHashCTX);
#endif // DISABLE_NETWORK
rct2_interop_dispose();
platform_free();
}
/**
* Run the main game loop until the finished flag is set at 40fps (25ms interval).
*/
static void openrct2_loop()
{
uint32 currentTick, ticksElapsed, lastTick = 0;
static uint32 uncapTick = 0;
static int fps = 0;
static uint32 secondTick = 0;
log_verbose("begin openrct2 loop");
_finished = 0;
do {
bool is_minimised = (SDL_GetWindowFlags(gWindow) & (SDL_WINDOW_MINIMIZED | SDL_WINDOW_HIDDEN)) != 0;
if (gConfigGeneral.uncap_fps && gGameSpeed <= 4 && !gOpenRCT2Headless && !is_minimised) {
currentTick = SDL_GetTicks();
if (uncapTick == 0) {
// Reset sprite locations
uncapTick = SDL_GetTicks();
sprite_position_tween_reset();
}
// Limit number of updates per loop (any long pauses or debugging can make this update for a very long time)
if (currentTick - uncapTick > UPDATE_TIME_MS * 60) {
uncapTick = currentTick - UPDATE_TIME_MS - 1;
}
platform_process_messages();
while (uncapTick <= currentTick && currentTick - uncapTick > UPDATE_TIME_MS) {
// Get the original position of each sprite
sprite_position_tween_store_a();
// Update the game so the sprite positions update
rct2_update();
// Get the next position of each sprite
sprite_position_tween_store_b();
uncapTick += UPDATE_TIME_MS;
}
// Tween the position of each sprite from the last position to the new position based on the time between the last
// tick and the next tick.
float nudge = 1 - ((float)(currentTick - uncapTick) / UPDATE_TIME_MS);
sprite_position_tween_all(nudge);
platform_draw();
fps++;
if (SDL_GetTicks() - secondTick >= 1000) {
fps = 0;
secondTick = SDL_GetTicks();
}
sprite_position_tween_restore();
} else {
uncapTick = 0;
currentTick = SDL_GetTicks();
ticksElapsed = currentTick - lastTick;
if (ticksElapsed < UPDATE_TIME_MS) {
SDL_Delay(UPDATE_TIME_MS - ticksElapsed);
lastTick += UPDATE_TIME_MS;
} else {
lastTick = currentTick;
}
platform_process_messages();
rct2_update();
if (!is_minimised) {
platform_draw();
}
}
} while (!_finished);
}
/**
* Causes the OpenRCT2 game loop to finish.
*/
void openrct2_finish()
{
_finished = 1;
}

73
src/openrct2.h Normal file
View File

@@ -0,0 +1,73 @@
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/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.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#pragma once
#include "common.h"
#include "core/Guard.hpp"
#include "platform/platform.h"
#ifndef DISABLE_NETWORK
#include <openssl/evp.h>
#endif // DISABLE_NETWORK
enum STARTUP_ACTION
{
STARTUP_ACTION_INTRO,
STARTUP_ACTION_TITLE,
STARTUP_ACTION_OPEN,
STARTUP_ACTION_EDIT
};
#ifdef __cplusplus
extern "C"
{
#endif
/** The exit code for OpenRCT2 when it exits. */
extern int gExitCode;
extern int gOpenRCT2StartupAction;
extern utf8 gOpenRCT2StartupActionPath[512];
extern utf8 gExePath[MAX_PATH];
extern utf8 gCustomUserDataPath[MAX_PATH];
extern utf8 gCustomOpenrctDataPath[MAX_PATH];
extern utf8 gCustomRCT2DataPath[MAX_PATH];
extern utf8 gCustomPassword[MAX_PATH];
extern bool gOpenRCT2Headless;
extern bool gOpenRCT2ShowChangelog;
#ifndef DISABLE_NETWORK
extern EVP_MD_CTX * gHashCTX;
#endif // DISABLE_NETWORK
#ifndef DISABLE_NETWORK
extern int gNetworkStart;
extern char gNetworkStartHost[128];
extern int gNetworkStartPort;
#endif
void openrct2_write_full_version_info(utf8 * buffer, size_t bufferSize);
bool openrct2_initialise();
void openrct2_launch();
void openrct2_dispose();
void openrct2_finish();
int cmdline_run(const char * * argv, int argc);
#ifdef __cplusplus
}
#endif

View File

@@ -191,7 +191,6 @@ static void platform_resize(int width, int height)
window_relocate_windows(dst_w, dst_h);
}
title_fix_location();
gfx_invalidate_screen();
// Check if the window has been resized in windowed mode and update the config file accordingly

View File

@@ -44,11 +44,11 @@
#include "ride/track_design.h"
#include "ride/TrackDesignRepository.h"
#include "ScenarioRepository.h"
#include "title.h"
#include "title/TitleScreen.h"
#include "util/util.h"
#include "world/climate.h"
#include "world/map.h"
#include "world/park.h"
#include "world/climate.h"
#include "world/scenery.h"
#include "world/sprite.h"

View File

@@ -366,7 +366,7 @@ extern "C"
*
* rct2: 0x00675E1B
*/
int game_load_sv6(SDL_RWops * rw)
bool game_load_sv6(SDL_RWops * rw)
{
if (!sawyercoding_validate_checksum(rw))
{

View File

@@ -18,15 +18,14 @@
#include "cheats.h"
#include "config.h"
#include "game.h"
#include "world/climate.h"
#include "interface/viewport.h"
#include "localisation/date.h"
#include "localisation/localisation.h"
#include "management/award.h"
#include "management/finance.h"
#include "management/marketing.h"
#include "management/research.h"
#include "management/news_item.h"
#include "management/research.h"
#include "network/network.h"
#include "object.h"
#include "object_list.h"
@@ -37,9 +36,9 @@
#include "scenario.h"
#include "ScenarioRepository.h"
#include "ScenarioSources.h"
#include "title.h"
#include "util/sawyercoding.h"
#include "util/util.h"
#include "world/climate.h"
#include "world/map.h"
#include "world/park.h"
#include "world/scenery.h"

218
src/title/TitleScreen.cpp Normal file
View File

@@ -0,0 +1,218 @@
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/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.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#include "../network/network.h"
#include "../openrct2.h"
#include "TitleScreen.h"
#include "TitleSequence.h"
#include "TitleSequenceManager.h"
#include "TitleSequencePlayer.h"
extern "C"
{
#include "../audio/audio.h"
#include "../drawing/drawing.h"
#include "../game.h"
#include "../input.h"
#include "../interface/screenshot.h"
#include "../interface/title_sequences.h"
#include "../interface/viewport.h"
#include "../interface/window.h"
#include "../localisation/localisation.h"
#include "../peep/staff.h"
#include "../world/climate.h"
#include "../world/scenery.h"
}
extern "C"
{
bool gTitleHideVersionInfo = false;
}
static sint32 _sequenceAttemptId;
static sint32 _loadedTitleSequenceId = -1;
static ITitleSequencePlayer * _sequencePlayer = nullptr;
static void TitleInitialise();
static void TryLoadSequence();
static void TryNextSequence();
/**
*
* rct2: 0x00678680
*/
static void TitleInitialise()
{
if (_sequencePlayer == nullptr)
{
_sequencePlayer = CreateTitleSequencePlayer();
}
size_t seqId = title_sequence_manager_get_index_for_config_id(gConfigInterface.current_title_sequence_preset);
if (seqId == SIZE_MAX)
{
seqId = title_sequence_manager_get_index_for_config_id("*OPENRCT2");
if (seqId == SIZE_MAX)
{
seqId = 0;
}
}
title_sequence_change_preset((int)seqId);
TryLoadSequence();
}
static void TryLoadSequence()
{
if (_loadedTitleSequenceId != gCurrentPreviewTitleSequence)
{
if (_sequencePlayer->Begin(gCurrentPreviewTitleSequence))
{
_loadedTitleSequenceId = gCurrentPreviewTitleSequence;
gfx_invalidate_screen();
}
}
}
static void TryNextSequence()
{
gCurrentPreviewTitleSequence = _sequenceAttemptId++;
if (_sequenceAttemptId >= (sint32)TitleSequenceManager::GetCount())
{
_sequenceAttemptId = 0;
}
TryLoadSequence();
}
extern "C"
{
/**
*
* rct2: 0x0068E8DA
*/
void title_load()
{
log_verbose("loading title");
if (gGamePaused & GAME_PAUSED_NORMAL)
pause_toggle();
gScreenFlags = SCREEN_FLAGS_TITLE_DEMO;
#ifndef DISABLE_NETWORK
network_close();
#endif
reset_park_entrances();
user_string_clear_all();
reset_sprite_list();
ride_init_all();
window_guest_list_init_vars_a();
staff_reset_modes();
map_init(150);
park_init();
date_reset();
climate_reset(CLIMATE_COOL_AND_WET);
scenery_set_default_placement_configuration();
window_new_ride_init_vars();
window_guest_list_init_vars_b();
window_staff_list_init_vars();
map_update_tile_pointers();
reset_sprite_spatial_index();
audio_stop_all_music_and_sounds();
viewport_init_all();
news_item_init_queue();
window_main_open();
title_create_windows();
TitleInitialise();
gfx_invalidate_screen();
audio_start_title_music();
gScreenAge = 0;
if (gOpenRCT2ShowChangelog) {
gOpenRCT2ShowChangelog = false;
window_changelog_open();
}
log_verbose("loading title finished");
}
/**
* Creates the windows shown on the title screen; New game, load game,
* tutorial, toolbox and exit.
* rct2: 0x0066B5C0 (part of 0x0066B3E8)
*/
void title_create_windows()
{
window_title_menu_open();
window_title_exit_open();
window_title_options_open();
window_title_logo_open();
window_resize_gui(gScreenWidth, gScreenHeight);
gTitleHideVersionInfo = false;
}
void title_update()
{
screenshot_check();
title_handle_keyboard_input();
if (game_is_not_paused())
{
TryLoadSequence();
if (_sequencePlayer != nullptr && !_sequencePlayer->Update())
{
TryNextSequence();
}
sint32 numUpdates = 1;
if (gGameSpeed > 1) {
numUpdates = 1 << (gGameSpeed - 1);
}
for (sint32 i = 0; i < numUpdates; i++)
{
game_logic_update();
}
update_palette_effects();
// update_rain_animation();
}
gInputFlags &= ~INPUT_FLAG_VIEWPORT_SCROLLING;
window_map_tooltip_update_visibility();
window_dispatch_update_all();
gSavedAge++;
game_handle_input();
}
void DrawOpenRCT2(rct_drawpixelinfo * dpi, int x, int y)
{
utf8 buffer[256];
// Write format codes
utf8 *ch = buffer;
ch = utf8_write_codepoint(ch, FORMAT_MEDIUMFONT);
ch = utf8_write_codepoint(ch, FORMAT_OUTLINE);
ch = utf8_write_codepoint(ch, FORMAT_WHITE);
// Write name and version information
openrct2_write_full_version_info(ch, sizeof(buffer) - (ch - buffer));
gfx_draw_string(dpi, buffer, COLOUR_BLACK, x + 5, y + 5 - 13);
// Write platform information
snprintf(ch, 256 - (ch - buffer), "%s (%s)", OPENRCT2_PLATFORM, OPENRCT2_ARCHITECTURE);
gfx_draw_string(dpi, buffer, COLOUR_BLACK, x + 5, y + 5);
}
}

33
src/title/TitleScreen.h Normal file
View File

@@ -0,0 +1,33 @@
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/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.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#pragma once
#include "../drawing/drawing.h"
#ifdef __cplusplus
extern "C"
{
#endif
extern bool gTitleHideVersionInfo;
void title_load();
void title_create_windows();
void title_update();
void DrawOpenRCT2(rct_drawpixelinfo *dpi, int x, int y);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,402 @@
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/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.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#include "../common.h"
#include <SDL.h>
#include "../core/Console.hpp"
#include "../core/Exception.hpp"
#include "../core/Math.hpp"
#include "../core/Path.hpp"
#include "../core/String.hpp"
#include "../ScenarioRepository.h"
#include "../ScenarioSources.h"
#include "TitleSequence.h"
#include "TitleSequenceManager.h"
#include "TitleSequencePlayer.h"
extern "C"
{
#include "../game.h"
#include "../interface/viewport.h"
#include "../interface/window.h"
#include "../world/scenery.h"
}
class TitleSequencePlayer : public ITitleSequencePlayer
{
private:
uint32 _sequenceId = 0;
TitleSequence * _sequence = nullptr;
sint32 _position = 0;
sint32 _waitCounter = 0;
sint32 _lastScreenWidth = 0;
sint32 _lastScreenHeight = 0;
rct_xy32 _viewCentreLocation = { 0 };
public:
~TitleSequencePlayer() override
{
FreeTitleSequence(_sequence);
}
sint32 GetCurrentPosition() const override
{
return _position;
}
bool Begin(uint32 titleSequenceId) override
{
size_t numSequences = TitleSequenceManager::GetCount();
if (titleSequenceId >= numSequences)
{
return false;
}
auto seqItem = TitleSequenceManager::GetItem(titleSequenceId);
auto sequence = LoadTitleSequence(seqItem->Path.c_str());
if (sequence == nullptr)
{
return false;
}
FreeTitleSequence(_sequence);
_sequence = sequence;
_sequenceId = titleSequenceId;
Reset();
return true;
}
bool Update() override
{
FixViewLocation();
sint32 entryPosition = _position;
if (_waitCounter <= 0)
{
do
{
if (_position > (sint32)_sequence->NumCommands)
{
_position = 0;
return false;
}
const TitleCommand * command = &_sequence->Commands[_position];
bool successful = ExecuteCommand(command);
IncrementPosition();
if (!successful)
{
bool isLoadCommand = false;
do
{
const TitleCommand * command = &_sequence->Commands[_position];
switch (command->Type) {
case TITLE_SCRIPT_LOADMM:
case TITLE_SCRIPT_LOAD:
case TITLE_SCRIPT_LOADRCT1:
isLoadCommand = true;
break;
default:
IncrementPosition();
if (_position == entryPosition)
{
// We have got back to where we started so we can't load any of these parks
return false;
}
break;
}
}
while (!isLoadCommand);
}
}
while (_waitCounter == 0);
}
_waitCounter--;
return true;
}
void Reset() override
{
_position = 0;
_waitCounter = 0;
Update();
}
void Seek(sint32 targetPosition) override
{
if (targetPosition < 0 || targetPosition >= (sint32)_sequence->NumCommands)
{
throw Exception("Invalid position.");
}
if (_position >= targetPosition)
{
Reset();
}
// Set position to the last LOAD command before target position
for (sint32 i = targetPosition; i >= 0; i--)
{
uint8 commandType = _sequence->Commands[i].Type;
if (commandType == TITLE_SCRIPT_LOADMM ||
commandType == TITLE_SCRIPT_LOAD ||
commandType == TITLE_SCRIPT_LOADRCT1)
{
_position = i;
}
}
// Keep updating until we reach target position
while (_position < targetPosition)
{
if (Update())
{
game_logic_update();
}
else
{
break;
}
}
}
private:
void IncrementPosition()
{
_position++;
if (_position >= (sint32)_sequence->NumCommands)
{
_position = 0;
}
}
bool ExecuteCommand(const TitleCommand * command)
{
switch (command->Type) {
case TITLE_SCRIPT_END:
_waitCounter = 1;
break;
case TITLE_SCRIPT_WAIT:
_waitCounter = command->Seconds * 32;
break;
case TITLE_SCRIPT_LOADMM:
{
const utf8 * path = get_file_path(PATH_ID_SIXFLAGS_MAGICMOUNTAIN);
if (!LoadParkFromFile(path))
{
Console::Error::WriteLine("Failed to load: \"%s\" for the title sequence.", path);
return false;
}
break;
}
case TITLE_SCRIPT_LOCATION:
{
sint32 x = command->X * 32 + 16;
sint32 y = command->Y * 32 + 16;
SetViewLocation(x, y);
break;
}
case TITLE_SCRIPT_ROTATE:
RotateView(command->Rotations);
break;
case TITLE_SCRIPT_ZOOM:
SetViewZoom(command->Zoom);
break;
case TITLE_SCRIPT_SPEED:
gGameSpeed = Math::Clamp<uint8>(1, command->Speed, 4);
break;
case TITLE_SCRIPT_RESTART:
Reset();
break;
case TITLE_SCRIPT_LOAD:
{
bool loadSuccess = false;
uint8 saveIndex = command->SaveIndex;
TitleSequenceParkHandle * parkHandle = TitleSequenceGetParkHandle(_sequence, saveIndex);
if (parkHandle != nullptr)
{
loadSuccess = LoadParkFromRW(parkHandle->RWOps, parkHandle->IsScenario);
TitleSequenceCloseParkHandle(parkHandle);
}
if (!loadSuccess)
{
if (_sequence->NumSaves > saveIndex)
{
const utf8 * path = _sequence->Saves[saveIndex];
Console::Error::WriteLine("Failed to load: \"%s\" for the title sequence.", path);
}
return false;
}
break;
}
case TITLE_SCRIPT_LOADRCT1:
{
source_desc sourceDesc;
if (!ScenarioSources::TryGetById(command->SaveIndex, &sourceDesc) || sourceDesc.index == -1)
{
Console::Error::WriteLine("Invalid scenario id.");
return false;
}
const utf8 * path = nullptr;
IScenarioRepository * scenarioRepo = GetScenarioRepository();
size_t numScenarios = scenarioRepo->GetCount();
for (size_t i = 0; i < numScenarios; i++)
{
const scenario_index_entry * scenario = scenarioRepo->GetByIndex(i);
if (scenario->source_index == sourceDesc.index)
{
path = scenario->path;
break;
}
}
if (path == nullptr || !LoadParkFromFile(path))
{
return false;
}
break;
}
}
return true;
}
void SetViewZoom(const uint32 &zoom)
{
rct_window * w = window_get_main();
if (w != nullptr && w->viewport != nullptr)
{
window_zoom_set(w, zoom);
}
}
void RotateView(uint32 count)
{
rct_window * w = window_get_main();
if (w != nullptr)
{
for (uint32 i = 0; i < count; i++)
{
window_rotate_camera(w, 1);
}
}
}
bool LoadParkFromFile(const utf8 * path)
{
bool success = false;
bool isScenario = String::Equals(Path::GetExtension(path), ".sc6", true);
SDL_RWops * rw = SDL_RWFromFile(path, "rb");
if (rw != nullptr)
{
success = LoadParkFromRW(rw, isScenario);
SDL_RWclose(rw);
}
return success;
}
bool LoadParkFromRW(SDL_RWops * rw, bool isScenario)
{
bool successfulLoad = isScenario ? scenario_load_rw(rw) :
game_load_sv6(rw);
if (!successfulLoad)
{
return false;
}
rct_window * w = window_get_main();
w->viewport_target_sprite = -1;
w->saved_view_x = gSavedViewX;
w->saved_view_y = gSavedViewY;
char zoomDifference = gSavedViewZoom - w->viewport->zoom;
w->viewport->zoom = gSavedViewZoom;
gCurrentRotation = gSavedViewRotation;
if (zoomDifference != 0)
{
if (zoomDifference < 0)
{
zoomDifference = -zoomDifference;
w->viewport->view_width >>= zoomDifference;
w->viewport->view_height >>= zoomDifference;
}
else
{
w->viewport->view_width <<= zoomDifference;
w->viewport->view_height <<= zoomDifference;
}
}
w->saved_view_x -= w->viewport->view_width >> 1;
w->saved_view_y -= w->viewport->view_height >> 1;
window_invalidate(w);
reset_sprite_spatial_index();
reset_all_sprite_quadrant_placements();
window_new_ride_init_vars();
if (!isScenario)
{
sub_684AC3();
}
scenery_set_default_placement_configuration();
news_item_init_queue();
load_palette();
gfx_invalidate_screen();
gScreenAge = 0;
gGameSpeed = 1;
return true;
}
/**
* Sets the map location to the given tile coordinates. Z is automatic.
* @param x X position in map tiles.
* @param y Y position in map tiles.
*/
void SetViewLocation(sint32 x, sint32 y)
{
// Update viewport
rct_window * w = window_get_main();
if (w != nullptr)
{
sint32 z = map_element_height(x, y);
window_scroll_to_location(w, x, y, z);
w->flags &= ~WF_SCROLLING_TO_LOCATION;
viewport_update_position(w);
}
// Save known tile position in case of window resize
_lastScreenWidth = gScreenWidth;
_lastScreenHeight = gScreenHeight;
_viewCentreLocation.x = x;
_viewCentreLocation.y = y;
}
/**
* Fixes the view location for when the game window has changed size.
*/
void FixViewLocation()
{
if (gScreenWidth != _lastScreenWidth ||
gScreenHeight != _lastScreenHeight)
{
SetViewLocation(_viewCentreLocation.x, _viewCentreLocation.y);
}
}
};
ITitleSequencePlayer * CreateTitleSequencePlayer()
{
return new TitleSequencePlayer();
}

View File

@@ -14,26 +14,25 @@
*****************************************************************************/
#pragma endregion
#ifndef _TITLE_H_
#define _TITLE_H_
#pragma once
#include <SDL.h>
#include "drawing/drawing.h"
extern bool gTitleHideVersionInfo;
#ifdef __cplusplus
extern sint32 gTitleScriptCommand;
extern uint8 gTitleScriptSave;
extern sint32 gTitleScriptSkipTo;
extern sint32 gTitleScriptSkipLoad;
interface ITitleSequencePlayer
{
virtual ~ITitleSequencePlayer() = default;
void title_load();
void title_create_windows();
void title_update();
void title_skip_from_beginning();
void title_script_get_line(SDL_RWops *file, char *parts);
void title_refresh_sequence();
void title_fix_location();
void DrawOpenRCT2(rct_drawpixelinfo *dpi, int x, int y);
virtual sint32 GetCurrentPosition() const abstract;
virtual bool Begin(uint32 titleSequenceId) abstract;
virtual void Reset() abstract;
virtual bool Update() abstract;
virtual void Seek(sint32 position) abstract;
};
ITitleSequencePlayer * CreateTitleSequencePlayer();
#endif

View File

@@ -28,7 +28,6 @@
#include "../interface/window.h"
#include "../platform/platform.h"
#include "../ride/track_data.h"
#include "../title.h"
#include "../util/util.h"
#include "../world/footpath.h"
#include "../world/scenery.h"

View File

@@ -25,7 +25,6 @@
#include "../localisation/localisation.h"
#include "../network/network.h"
#include "../scenario.h"
#include "../title.h"
#include "../util/util.h"
#include "../windows/error.h"

View File

@@ -37,7 +37,6 @@
#include "../platform/platform.h"
#include "../rct2.h"
#include "../sprites.h"
#include "../title.h"
#include "../title/TitleSequence.h"
#include "../title/TitleSequenceManager.h"
#include "dropdown.h"

View File

@@ -21,7 +21,7 @@
#include "../localisation/localisation.h"
#include "../network/network.h"
#include "../sprites.h"
#include "../title.h"
#include "../title/TitleScreen.h"
#include "../util/util.h"
#include "error.h"

View File

@@ -14,20 +14,20 @@
*****************************************************************************/
#pragma endregion
#include "../game.h"
#include "../input.h"
#include "../interface/themes.h"
#include "../interface/title_sequences.h"
#include "../interface/viewport.h"
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../interface/viewport.h"
#include "../localisation/localisation.h"
#include "../rct2.h"
#include "../sprites.h"
#include "../world/map.h"
#include "../game.h"
#include "../interface/themes.h"
#include "../interface/title_sequences.h"
#include "../title.h"
#include "../title/TitleScreen.h"
#include "../title/TitleSequence.h"
#include "../util/util.h"
#include "../world/map.h"
#include "dropdown.h"
#if 0

View File

@@ -29,7 +29,7 @@
#include "../scenario.h"
#include "../ScenarioSources.h"
#include "../sprites.h"
#include "../title.h"
#include "../title/TitleScreen.h"
#include "../title/TitleSequence.h"
#include "../title/TitleSequenceManager.h"
#include "../util/util.h"
@@ -192,6 +192,11 @@ static rct_widget window_title_editor_widgets[] = {
static sint16 _window_title_editor_highlighted_index;
static TitleSequence * _loadedTitleSequence;
int gTitleScriptCommand;
int gTitleScriptSkipLoad;
int gTitleScriptSkipTo;
int gTitleScriptSave;
static int window_title_editor_tab_animation_loops[] = {
64,
1,
@@ -328,7 +333,7 @@ static void window_title_editor_mouseup(rct_window *w, int widgetIndex)
title_sequence_remove_save(gCurrentTitleSequence, w->selected_list_item);
if (w->selected_list_item > 0)
w->selected_list_item--;
else if (w->selected_list_item > _loadedTitleSequence->NumSaves)
else if (w->selected_list_item > (sint16)_loadedTitleSequence->NumSaves)
w->selected_list_item = (sint16)(_loadedTitleSequence->NumSaves - 1);
}
}
@@ -368,18 +373,18 @@ static void window_title_editor_mouseup(rct_window *w, int widgetIndex)
case WIDX_TITLE_EDITOR_EDIT:
defaultPreset *= 2; playing *= 2; commandEditorOpen *= 2;
if (!defaultPreset && !playing && !commandEditorOpen) {
if (w->selected_list_item != -1 && w->selected_list_item < _loadedTitleSequence->NumCommands)
if (w->selected_list_item != -1 && w->selected_list_item < (sint16)_loadedTitleSequence->NumCommands)
window_title_command_editor_open(w->selected_list_item, false);
}
break;
case WIDX_TITLE_EDITOR_DELETE:
defaultPreset *= 2; playing *= 2; commandEditorOpen *= 2;
if (!defaultPreset && !playing && !commandEditorOpen) {
if (w->selected_list_item != -1 && w->selected_list_item < _loadedTitleSequence->NumCommands) {
if (w->selected_list_item != -1 && w->selected_list_item < (sint16)_loadedTitleSequence->NumCommands) {
title_sequence_delete_command(gCurrentTitleSequence, w->selected_list_item);
if (w->selected_list_item > 0)
w->selected_list_item--;
else if (w->selected_list_item >= _loadedTitleSequence->NumCommands)
else if (w->selected_list_item >= (sint16)_loadedTitleSequence->NumCommands)
w->selected_list_item = (sint16)(_loadedTitleSequence->NumCommands - 1);
}
}
@@ -391,12 +396,12 @@ static void window_title_editor_mouseup(rct_window *w, int widgetIndex)
}
break;*/
case WIDX_TITLE_EDITOR_SKIP_TO:
if (playing && w->selected_list_item != -1 && w->selected_list_item < _loadedTitleSequence->NumCommands) {
if (playing && w->selected_list_item != -1 && w->selected_list_item < (sint16)_loadedTitleSequence->NumCommands) {
if (gTitleScriptCommand > w->selected_list_item) {
gTitleScriptCommand = 0;
}
if (gTitleScriptCommand != w->selected_list_item) {
for (i = gTitleScriptCommand + 1; i < _loadedTitleSequence->NumCommands; i++) {
for (i = gTitleScriptCommand + 1; i < (int)_loadedTitleSequence->NumCommands; i++) {
if (_loadedTitleSequence->Commands[i].Type == TITLE_SCRIPT_LOAD ||
_loadedTitleSequence->Commands[i].Type == TITLE_SCRIPT_LOADMM) {
gTitleScriptSkipLoad = i;
@@ -412,7 +417,7 @@ static void window_title_editor_mouseup(rct_window *w, int widgetIndex)
case WIDX_TITLE_EDITOR_MOVE_DOWN:
defaultPreset *= 2; playing *= 2; commandEditorOpen *= 2;
if (!defaultPreset && !playing && !commandEditorOpen) {
if (w->selected_list_item != -1 && w->selected_list_item < _loadedTitleSequence->NumCommands - 1) {
if (w->selected_list_item != -1 && w->selected_list_item < (sint16)_loadedTitleSequence->NumCommands - 1) {
title_sequence_move_down_command(gCurrentTitleSequence, w->selected_list_item);
w->selected_list_item++;
}
@@ -428,25 +433,20 @@ static void window_title_editor_mouseup(rct_window *w, int widgetIndex)
}
break;
case WIDX_TITLE_EDITOR_REPLAY:
if (playing) {
title_refresh_sequence();
}
break;
case WIDX_TITLE_EDITOR_STOP:
if (playing) {
gCurrentPreviewTitleSequence = 0;
title_refresh_sequence();
}
break;
case WIDX_TITLE_EDITOR_PLAY:
if (gCurrentTitleSequence != gCurrentPreviewTitleSequence && inTitle) {
gCurrentPreviewTitleSequence = gCurrentTitleSequence;
title_refresh_sequence();
}
break;
case WIDX_TITLE_EDITOR_SKIP:
if (playing) {
for (i = gTitleScriptCommand; i < _loadedTitleSequence->NumCommands; i++) {
for (i = gTitleScriptCommand; i < (int)_loadedTitleSequence->NumCommands; i++) {
if (_loadedTitleSequence->Commands[i].Type == TITLE_SCRIPT_LOAD ||
_loadedTitleSequence->Commands[i].Type == TITLE_SCRIPT_LOADMM
) {
@@ -459,7 +459,6 @@ static void window_title_editor_mouseup(rct_window *w, int widgetIndex)
} else if (_loadedTitleSequence->Commands[i].Type == TITLE_SCRIPT_RESTART) {
gTitleScriptSkipLoad = -1;
gTitleScriptSkipTo = -1;
title_refresh_sequence();
break;
}
}
@@ -633,13 +632,13 @@ static void window_title_editor_scrollmousedown(rct_window *w, int scrollIndex,
w->selected_list_item = -1;
switch (w->selected_tab) {
case WINDOW_TITLE_EDITOR_TAB_SAVES:
if (index < _loadedTitleSequence->NumSaves) {
if (index < (int)_loadedTitleSequence->NumSaves) {
w->selected_list_item = index;
widget_invalidate(w, WIDX_TITLE_EDITOR_LIST);
}
break;
case WINDOW_TITLE_EDITOR_TAB_SCRIPT:
if (index < _loadedTitleSequence->NumCommands) {
if (index < (int)_loadedTitleSequence->NumCommands) {
w->selected_list_item = index;
widget_invalidate(w, WIDX_TITLE_EDITOR_LIST);
}
@@ -654,11 +653,11 @@ static void window_title_editor_scrollmouseover(rct_window *w, int scrollIndex,
index = y / ROW_HEIGHT;
switch (w->selected_tab) {
case WINDOW_TITLE_EDITOR_TAB_SAVES:
if (index < _loadedTitleSequence->NumSaves)
if (index < (int)_loadedTitleSequence->NumSaves)
_window_title_editor_highlighted_index = (sint16)index;
break;
case WINDOW_TITLE_EDITOR_TAB_SCRIPT:
if (index < _loadedTitleSequence->NumCommands)
if (index < (int)_loadedTitleSequence->NumCommands)
_window_title_editor_highlighted_index = (sint16)index;
break;
}
@@ -877,7 +876,7 @@ static void window_title_editor_scrollpaint_saves(rct_window *w, rct_drawpixelin
int x = 0;
int y = 0;
bool inTitle = ((gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) == SCREEN_FLAGS_TITLE_DEMO);
for (int i = 0; i < _loadedTitleSequence->NumSaves; i++, y += ROW_HEIGHT) {
for (int i = 0; i < (int)_loadedTitleSequence->NumSaves; i++, y += ROW_HEIGHT) {
bool selected = false;
bool hover = false;
if (i == w->selected_list_item) {
@@ -908,7 +907,7 @@ static void window_title_editor_scrollpaint_commands(rct_window *w, rct_drawpixe
int x = 0;
int y = 0;
bool inTitle = ((gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) == SCREEN_FLAGS_TITLE_DEMO);
for (int i = 0; i < _loadedTitleSequence->NumCommands; i++, y += ROW_HEIGHT) {
for (int i = 0; i < (int)_loadedTitleSequence->NumCommands; i++, y += ROW_HEIGHT) {
TitleCommand * command = &_loadedTitleSequence->Commands[i];
bool selected = false;
bool hover = false;

View File

@@ -23,7 +23,7 @@
#include "../interface/window.h"
#include "../localisation/localisation.h"
#include "../sprites.h"
#include "../title.h"
#include "../title/TitleScreen.h"
#include "dropdown.h"
enum {

View File

@@ -24,7 +24,6 @@
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../interface/themes.h"
#include "../title.h"
#include "../util/util.h"
#define INITIAL_NUM_UNLOCKED_SCENARIOS 5

View File

@@ -31,8 +31,8 @@
#include "../network/twitch.h"
#include "../peep/staff.h"
#include "../scenario.h"
#include "../title.h"
#include "../sprites.h"
#include "../title/TitleScreen.h"
#include "../util/util.h"
#include "../world/banner.h"
#include "../world/scenery.h"