diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index 7bcdf63ab5..98ad674378 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3772,6 +3772,9 @@ STR_5435 :Rename save STR_5436 :Edit Title Sequences... STR_5437 :No save selected STR_5438 :Can't make changes while command editor is open -STR_5439 :A wait with at least 4 seconds is required with a restart +STR_5439 :A wait command with at least 4 seconds is required with a restart command STR_5440 :Minimize fullscreen on focus loss STR_5441 :{SMALLFONT}{BLACK}Identifies rides by track type,{NEWLINE}so vehicles can be changed{NEWLINE}afterwards, like in RCT1. Only{NEWLINE}toggleable in the title screen. +STR_5442 :Speed +STR_5443 :Speed{MOVE_X}{87}{STRINGID} +STR_5444 :Speed: diff --git a/src/config.c b/src/config.c index a98127b24e..3fdde76f90 100644 --- a/src/config.c +++ b/src/config.c @@ -1567,6 +1567,9 @@ static void title_sequence_open(const char *path, const char *customName) } else if (_stricmp(token, "ZOOM") == 0) { command.command = TITLE_SCRIPT_ZOOM; command.zoom = atoi(part1) & 0xFF; + } else if (_stricmp(token, "SPEED") == 0) { + command.command = TITLE_SCRIPT_SPEED; + command.speed = max(1, min(4, atoi(part1) & 0xFF)); } else if (_stricmp(token, "WAIT") == 0) { command.command = TITLE_SCRIPT_WAIT; command.seconds = atoi(part1) & 0xFF; @@ -1624,6 +1627,9 @@ void title_sequence_save_preset_script(int preset) case TITLE_SCRIPT_ZOOM: fprintf(file, "ZOOM %i\r\n", command->zoom); break; + case TITLE_SCRIPT_SPEED: + fprintf(file, "SPEED %i\r\n", command->speed); + break; case TITLE_SCRIPT_WAIT: fprintf(file, "WAIT %i\r\n\r\n", command->seconds); break; diff --git a/src/config.h b/src/config.h index 922d0edbf7..6f5a85b991 100644 --- a/src/config.h +++ b/src/config.h @@ -228,6 +228,7 @@ typedef struct { uint8 x; // LOCATION uint8 rotations; // ROTATE (counter-clockwise) uint8 zoom; // ZOOM + uint8 speed; // SPEED uint8 seconds; // WAIT }; uint8 y; // LOCATION diff --git a/src/game.c b/src/game.c index 07cbf76933..2a032562e7 100644 --- a/src/game.c +++ b/src/game.c @@ -731,6 +731,8 @@ int game_load_save(const char *path) load_palette(); gfx_invalidate_screen(); + gGameSpeed = 1; + scenario_set_filename((char*)0x0135936C); return 1; } diff --git a/src/scenario.c b/src/scenario.c index d89609418a..1e486f902a 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -337,6 +337,8 @@ int scenario_load_and_play_from_path(const char *path) gfx_invalidate_screen(); RCT2_GLOBAL(0x009DEA66, uint16) = 0; RCT2_GLOBAL(0x009DEA5C, uint16) = 62000; // (doesn't appear to ever be read) + gGameSpeed = 1; + return 1; } diff --git a/src/title.c b/src/title.c index d7b2a2e321..160de8c665 100644 --- a/src/title.c +++ b/src/title.c @@ -308,6 +308,10 @@ static void title_do_next_script_opcode() if (w != NULL && w->viewport != NULL) window_zoom_set(w, script_operand); break; + case TITLE_SCRIPT_SPEED: + script_operand = (*_currentScript++); + gGameSpeed = max(1, min(4, script_operand)); + break; case TITLE_SCRIPT_RESTART: _scriptNoLoadsSinceRestart = 1; gTitleScriptCommand = -1; @@ -384,6 +388,7 @@ static void title_do_next_script_opcode() */ static void title_update_showcase() { + int i, numUpdates; // Loop used for scene skip functionality // Only loop here when the appropriate save hasn't been loaded yet since no game updates are required do { @@ -401,7 +406,14 @@ static void title_update_showcase() } while (gTitleScriptSkipTo != -1 && gTitleScriptSkipLoad != -1); if (gTitleScriptSkipTo != -1 && gTitleScriptSkipLoad == -1) { - game_logic_update(); + if (gGameSpeed > 1) { + numUpdates = 1 << (gGameSpeed - 1); + } else { + numUpdates = 1; + } + for (i = 0; i < numUpdates; i++) { + game_logic_update(); + } update_palette_effects(); update_rain_animation(); } @@ -435,12 +447,22 @@ static void DrawOpenRCT2(int x, int y) void game_handle_input(); void title_update() { + int i, numUpdates; screenshot_check(); title_handle_keyboard_input(); if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0) { title_update_showcase(); - game_logic_update(); + + if (gGameSpeed > 1) { + numUpdates = 1 << (gGameSpeed - 1); + } else { + numUpdates = 1; + } + + for (i = 0; i < numUpdates; i++) { + game_logic_update(); + } start_title_music(); } @@ -665,6 +687,9 @@ bool title_refresh_sequence() case TITLE_SCRIPT_ZOOM: *scriptPtr++ = title->commands[i].zoom; break; + case TITLE_SCRIPT_SPEED: + *scriptPtr++ = title->commands[i].speed; + break; case TITLE_SCRIPT_WAIT: *scriptPtr++ = title->commands[i].seconds; break; diff --git a/src/title.h b/src/title.h index a174d222f0..b788e9e4aa 100644 --- a/src/title.h +++ b/src/title.h @@ -30,6 +30,7 @@ enum { TITLE_SCRIPT_RESTART, TITLE_SCRIPT_LOAD, TITLE_SCRIPT_END, + TITLE_SCRIPT_SPEED, TITLE_SCRIPT_LOOP, TITLE_SCRIPT_ENDLOOP } TITLE_SCRIPT_COMMANDS; diff --git a/src/windows/title_command_editor.c b/src/windows/title_command_editor.c index 1acbd81f41..61746a6ea9 100644 --- a/src/windows/title_command_editor.c +++ b/src/windows/title_command_editor.c @@ -43,12 +43,13 @@ TITLE_COMMAND_ORDER window_title_command_editor_orders[] = { { TITLE_SCRIPT_LOCATION, 5417, 5427 }, { TITLE_SCRIPT_ROTATE, 5419, 5428 }, { TITLE_SCRIPT_ZOOM, 5421, 5429 }, + { TITLE_SCRIPT_SPEED, 5442, 5444 }, { TITLE_SCRIPT_WAIT, 5423, 5430 }, { TITLE_SCRIPT_RESTART, 5425, STR_NONE }, { TITLE_SCRIPT_END, 5426, STR_NONE }, }; -#define NUM_COMMANDS 7 +#define NUM_COMMANDS 8 enum WINDOW_WATER_WIDGET_IDX { WIDX_BACKGROUND, @@ -59,8 +60,8 @@ enum WINDOW_WATER_WIDGET_IDX { WIDX_TEXTBOX_FULL, WIDX_TEXTBOX_X, WIDX_TEXTBOX_Y, - WIDX_SAVE, - WIDX_SAVE_DROPDOWN, + WIDX_INPUT, + WIDX_INPUT_DROPDOWN, WIDX_OKAY, WIDX_CANCEL }; @@ -203,8 +204,8 @@ void window_title_command_editor_open(int index, bool insert) (1 << WIDX_TEXTBOX_FULL) | (1 << WIDX_TEXTBOX_X) | (1 << WIDX_TEXTBOX_Y) | - (1 << WIDX_SAVE) | - (1 << WIDX_SAVE_DROPDOWN) | + (1 << WIDX_INPUT) | + (1 << WIDX_INPUT_DROPDOWN) | (1 << WIDX_OKAY) | (1 << WIDX_CANCEL); window_init_scroll_widgets(window); @@ -302,24 +303,45 @@ static void window_title_command_editor_mousedown(int widgetIndex, rct_window* w gDropdownItemsChecked = 1 << get_command_info_index(command.command); break; - case WIDX_SAVE_DROPDOWN: - num_items = gConfigTitleSequences.presets[gCurrentTitleSequence].num_saves; - for (i = 0; i < num_items; i++) { - gDropdownItemsFormat[i] = 2777; - gDropdownItemsArgs[i] = (uint64)&gConfigTitleSequences.presets[gCurrentTitleSequence].saves[i]; - } - - window_dropdown_show_text_custom_width( - w->x + widget->left, - w->y + widget->top, - widget->bottom - widget->top + 1, - w->colours[1], - DROPDOWN_FLAG_STAY_OPEN, - num_items, - widget->right - widget->left - 3 - ); + case WIDX_INPUT_DROPDOWN: + if (command.command == TITLE_SCRIPT_SPEED) { + num_items = 4; + for (i = 0; i < num_items; i++) { + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = 5142 + i; + } - gDropdownItemsChecked = 1 << (command.saveIndex); + window_dropdown_show_text_custom_width( + w->x + widget->left, + w->y + widget->top, + widget->bottom - widget->top + 1, + w->colours[1], + DROPDOWN_FLAG_STAY_OPEN, + num_items, + widget->right - widget->left - 3 + ); + + gDropdownItemsChecked = 1 << (command.speed - 1); + } + else if (command.command == TITLE_SCRIPT_LOAD) { + num_items = gConfigTitleSequences.presets[gCurrentTitleSequence].num_saves; + for (i = 0; i < num_items; i++) { + gDropdownItemsFormat[i] = 2777; + gDropdownItemsArgs[i] = (uint64)&gConfigTitleSequences.presets[gCurrentTitleSequence].saves[i]; + } + + window_dropdown_show_text_custom_width( + w->x + widget->left, + w->y + widget->top, + widget->bottom - widget->top + 1, + w->colours[1], + DROPDOWN_FLAG_STAY_OPEN, + num_items, + widget->right - widget->left - 3 + ); + + gDropdownItemsChecked = 1 << (command.saveIndex); + } break; } } @@ -356,6 +378,9 @@ static void window_title_command_editor_dropdown() command.zoom = 0; _itoa(command.zoom, textbox1Buffer, 10); break; + case TITLE_SCRIPT_SPEED: + command.speed = 1; + break; case TITLE_SCRIPT_WAIT: command.seconds = 10; _itoa(command.seconds, textbox1Buffer, 10); @@ -368,10 +393,17 @@ static void window_title_command_editor_dropdown() } window_invalidate(w); break; - case WIDX_SAVE_DROPDOWN: - if (dropdownIndex == command.saveIndex) - break; - command.saveIndex = (uint8)dropdownIndex; + case WIDX_INPUT_DROPDOWN: + if (command.command == TITLE_SCRIPT_SPEED) { + if (dropdownIndex == command.speed - 1) + break; + command.speed = (uint8)(dropdownIndex + 1); + } + else if (command.command == TITLE_SCRIPT_LOAD) { + if (dropdownIndex == command.saveIndex) + break; + command.saveIndex = (uint8)dropdownIndex; + } window_invalidate(w); break; } @@ -453,12 +485,13 @@ static void window_title_command_editor_invalidate() window_title_command_editor_widgets[WIDX_TEXTBOX_FULL].type = WWT_EMPTY; window_title_command_editor_widgets[WIDX_TEXTBOX_X].type = WWT_EMPTY; window_title_command_editor_widgets[WIDX_TEXTBOX_Y].type = WWT_EMPTY; - window_title_command_editor_widgets[WIDX_SAVE].type = WWT_EMPTY; - window_title_command_editor_widgets[WIDX_SAVE_DROPDOWN].type = WWT_EMPTY; + window_title_command_editor_widgets[WIDX_INPUT].type = WWT_EMPTY; + window_title_command_editor_widgets[WIDX_INPUT_DROPDOWN].type = WWT_EMPTY; switch (command.command) { case TITLE_SCRIPT_LOAD: - window_title_command_editor_widgets[WIDX_SAVE].type = WWT_DROPDOWN; - window_title_command_editor_widgets[WIDX_SAVE_DROPDOWN].type = WWT_DROPDOWN_BUTTON; + case TITLE_SCRIPT_SPEED: + 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_LOCATION: window_title_command_editor_widgets[WIDX_TEXTBOX_X].type = WWT_TEXT_BOX; @@ -494,16 +527,27 @@ static void window_title_command_editor_paint() w->widgets[WIDX_COMMAND_DROPDOWN].left - w->widgets[WIDX_COMMAND].left - 4 ); - if (command.command == TITLE_SCRIPT_LOAD) { + if (command.command == TITLE_SCRIPT_SPEED) { + gfx_draw_string_left_clipped( + dpi, + 5142 + command.speed - 1, + NULL, + 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 if (command.command == TITLE_SCRIPT_LOAD) { if (command.saveIndex == 0xFF) { gfx_draw_string_left_clipped( dpi, 5437, NULL, w->colours[1], - w->x + w->widgets[WIDX_SAVE].left + 1, - w->y + w->widgets[WIDX_SAVE].top, - w->widgets[WIDX_SAVE_DROPDOWN].left - w->widgets[WIDX_SAVE].left - 4 + 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 { @@ -513,9 +557,9 @@ static void window_title_command_editor_paint() 1170, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, w->colours[1], - w->x + w->widgets[WIDX_SAVE].left + 1, - w->y + w->widgets[WIDX_SAVE].top, - w->widgets[WIDX_SAVE_DROPDOWN].left - w->widgets[WIDX_SAVE].left - 4 + 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 ); } } diff --git a/src/windows/title_editor.c b/src/windows/title_editor.c index 23274d5924..a62e17a86d 100644 --- a/src/windows/title_editor.c +++ b/src/windows/title_editor.c @@ -160,7 +160,7 @@ static rct_widget window_title_editor_widgets[] = { // Presets Tab { WWT_DROPDOWN, 1, 125, 299, 60, 71, STR_NONE, STR_NONE }, // Preset title sequences { WWT_DROPDOWN_BUTTON, 1, 288, 298, 61, 70, 876, STR_NONE }, - { WWT_DROPDOWN_BUTTON, 1, 10, 100, 82, 93, 5254, 5255 }, // New button + { WWT_DROPDOWN_BUTTON, 1, 10, 100, 82, 93, 5254, 5255 }, // Create button { WWT_DROPDOWN_BUTTON, 1, 10, 100, 82+20, 93+20, 5239, 5383 }, // Duplicate button { WWT_DROPDOWN_BUTTON, 1, 110, 200, 82, 93, 3349, 5384 }, // Delete button { WWT_DROPDOWN_BUTTON, 1, 210, 300, 82, 93, 3348, 5385 }, // Rename button @@ -1011,6 +1011,10 @@ void window_title_editor_scrollpaint() commandName = 5422; RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = command->zoom; break; + case TITLE_SCRIPT_SPEED: + commandName = 5443; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = (uint16)(5142 + command->speed - 1); + break; case TITLE_SCRIPT_WAIT: commandName = 5424; RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = command->seconds;