Add fast-forward cutscene skip option

This commit is contained in:
dawnDus 2022-08-23 18:27:39 -04:00
parent 670e6891c1
commit 3d86995feb
No known key found for this signature in database
GPG Key ID: 972AABDE81848F21
7 changed files with 92 additions and 20 deletions

View File

@ -126,7 +126,12 @@
"50tps": "50tps (freeware)",
"60tps": "60tps (CS+)"
},
"pause_on_focus_loss": "Pause on focus loss:"
"pause_on_focus_loss": "Pause on focus loss:",
"cutscene_skip_method": {
"entry": "Cutscene Skip:",
"hold": "Hold to Skip",
"fastforward": "Fast-Forward"
}
}
},

View File

@ -118,7 +118,12 @@
"50tps": "50tps (freeware)",
"60tps": "60tps (CS+)"
},
"pause_on_focus_loss": "フォーカスが外れた時のポーズ:"
"pause_on_focus_loss": "フォーカスが外れた時のポーズ:",
"cutscene_skip_method": {
"entry": "カットシーンをスキップ",
"hold": "を押し続け",
"fastforward": "はやおくり"
}
}
},

View File

@ -15,7 +15,7 @@ use super::settings_menu::SettingsMenu;
#[allow(unused)]
enum CurrentMenu {
PauseMenu,
OptionsMenu,
SettingsMenu,
ConfirmMenu,
}
@ -23,7 +23,7 @@ enum CurrentMenu {
enum PauseMenuEntry {
Resume,
Retry,
Options,
Settings,
Title,
Quit,
}
@ -78,7 +78,7 @@ impl PauseMenu {
self.pause_menu.push_entry(PauseMenuEntry::Resume, MenuEntry::Active(state.t("menus.pause_menu.resume")));
self.pause_menu.push_entry(PauseMenuEntry::Retry, MenuEntry::Active(state.t("menus.pause_menu.retry")));
self.pause_menu.push_entry(PauseMenuEntry::Options, MenuEntry::Active(state.t("menus.pause_menu.options")));
self.pause_menu.push_entry(PauseMenuEntry::Settings, MenuEntry::Active(state.t("menus.pause_menu.options")));
self.pause_menu.push_entry(PauseMenuEntry::Title, MenuEntry::Active(state.t("menus.pause_menu.title")));
self.pause_menu.push_entry(PauseMenuEntry::Quit, MenuEntry::Active(state.t("menus.pause_menu.quit")));
@ -148,8 +148,8 @@ impl PauseMenu {
state.sound_manager.play_song(0, &state.constants, &state.settings, ctx)?;
state.load_or_start_game(ctx)?;
}
MenuSelectionResult::Selected(PauseMenuEntry::Options, _) => {
self.current_menu = CurrentMenu::OptionsMenu;
MenuSelectionResult::Selected(PauseMenuEntry::Settings, _) => {
self.current_menu = CurrentMenu::SettingsMenu;
}
MenuSelectionResult::Selected(PauseMenuEntry::Title, _) => {
self.confirm_menu.set_entry(
@ -167,7 +167,7 @@ impl PauseMenu {
}
_ => (),
},
CurrentMenu::OptionsMenu => {
CurrentMenu::SettingsMenu => {
let cm = &mut self.current_menu;
self.settings_menu.tick(
&mut || {
@ -219,7 +219,7 @@ impl PauseMenu {
self.pause_menu.draw(state, ctx)?;
graphics::set_clip_rect(ctx, None)?;
}
CurrentMenu::OptionsMenu => {
CurrentMenu::SettingsMenu => {
self.settings_menu.draw(state, ctx)?;
}
CurrentMenu::ConfirmMenu => {

View File

@ -9,7 +9,9 @@ use crate::input::combined_menu_controller::CombinedMenuController;
use crate::menu::MenuEntry;
use crate::menu::{Menu, MenuSelectionResult};
use crate::scene::title_scene::TitleScene;
use crate::shared_game_state::{Language, ScreenShakeIntensity, SharedGameState, TimingMode, WindowMode};
use crate::shared_game_state::{
CutsceneSkipMode, Language, ScreenShakeIntensity, SharedGameState, TimingMode, WindowMode,
};
use crate::sound::InterpolationMode;
use crate::{graphics, VSyncMode};
@ -110,6 +112,7 @@ impl Default for LanguageMenuEntry {
enum BehaviorMenuEntry {
GameTiming,
PauseOnFocusLoss,
CutsceneSkipMode,
Back,
}
@ -383,6 +386,18 @@ impl SettingsMenu {
),
);
self.behavior.push_entry(
BehaviorMenuEntry::CutsceneSkipMode,
MenuEntry::Options(
state.t("menus.options_menu.behavior_menu.cutscene_skip_method.entry"),
if state.settings.cutscene_skip_mode == CutsceneSkipMode::Hold { 0 } else { 1 },
vec![
state.t("menus.options_menu.behavior_menu.cutscene_skip_method.hold"),
state.t("menus.options_menu.behavior_menu.cutscene_skip_method.fastforward"),
],
),
);
self.behavior.push_entry(BehaviorMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
self.controls_menu.init(state, ctx)?;
@ -739,6 +754,21 @@ impl SettingsMenu {
*value = state.settings.pause_on_focus_loss;
}
}
MenuSelectionResult::Selected(BehaviorMenuEntry::CutsceneSkipMode, toggle) => {
if let MenuEntry::Options(_, value, _) = toggle {
match state.settings.cutscene_skip_mode {
CutsceneSkipMode::Hold => {
state.settings.cutscene_skip_mode = CutsceneSkipMode::FastForward;
*value = 1;
}
CutsceneSkipMode::FastForward => {
state.settings.cutscene_skip_mode = CutsceneSkipMode::Hold;
*value = 0;
}
}
let _ = state.settings.save(ctx);
}
}
MenuSelectionResult::Selected(BehaviorMenuEntry::Back, _) | MenuSelectionResult::Canceled => {
self.current = CurrentMenu::MainMenu;
}

View File

@ -48,7 +48,7 @@ use crate::scene::Scene;
use crate::scripting::tsc::credit_script::CreditScriptVM;
use crate::scripting::tsc::text_script::{ScriptMode, TextScriptExecutionState, TextScriptVM};
use crate::settings::ControllerType;
use crate::shared_game_state::{Language, PlayerCount, ReplayState, SharedGameState, TileSize};
use crate::shared_game_state::{CutsceneSkipMode, Language, PlayerCount, ReplayState, SharedGameState, TileSize};
use crate::stage::{BackgroundType, Stage, StageTexturePaths};
use crate::texture_set::SpriteBatch;
use crate::weapon::bullet::BulletManager;
@ -1782,20 +1782,33 @@ impl Scene for GameScene {
| TextScriptExecutionState::WaitTicks(_, _, _)
| TextScriptExecutionState::WaitInput(_, _, _)
| TextScriptExecutionState::WaitStanding(_, _)
| TextScriptExecutionState::WaitFade(_, _)
| TextScriptExecutionState::Msg(_, _, _, _)
| TextScriptExecutionState::MsgNewLine(_, _, _, _, _)
| TextScriptExecutionState::FallingIsland(_, _, _, _, _, _)
if !state.control_flags.control_enabled() && !state.textscript_vm.flags.cutscene_skip() =>
if !state.control_flags.control_enabled() =>
{
state.touch_controls.control_type = TouchControlType::Dialog;
if self.player1.controller.skip() {
self.skip_counter += 1;
if self.skip_counter >= CUTSCENE_SKIP_WAIT {
state.textscript_vm.flags.set_cutscene_skip(true);
state.tutorial_counter = 0;
match state.settings.cutscene_skip_mode {
CutsceneSkipMode::Hold if !state.textscript_vm.flags.cutscene_skip() => {
if self.player1.controller.skip() {
self.skip_counter += 1;
if self.skip_counter >= CUTSCENE_SKIP_WAIT {
state.textscript_vm.flags.set_cutscene_skip(true);
state.tutorial_counter = 0;
}
} else if self.skip_counter > 0 {
self.skip_counter -= 1;
}
}
} else if self.skip_counter > 0 {
self.skip_counter -= 1;
CutsceneSkipMode::FastForward => {
if self.player1.controller.skip() {
state.textscript_vm.flags.set_cutscene_skip(true);
} else {
state.textscript_vm.flags.set_cutscene_skip(false);
}
}
_ => (),
}
}
_ => {

View File

@ -10,7 +10,7 @@ use crate::input::keyboard_player_controller::KeyboardController;
use crate::input::player_controller::PlayerController;
use crate::input::touch_player_controller::TouchPlayerController;
use crate::player::TargetPlayer;
use crate::shared_game_state::{Language, ScreenShakeIntensity, TimingMode, WindowMode};
use crate::shared_game_state::{CutsceneSkipMode, Language, ScreenShakeIntensity, TimingMode, WindowMode};
use crate::sound::InterpolationMode;
#[derive(serde::Serialize, serde::Deserialize)]
@ -79,6 +79,8 @@ pub struct Settings {
#[serde(skip)]
pub noclip: bool,
pub more_rust: bool,
#[serde(default = "default_cutscene_skip_mode")]
pub cutscene_skip_mode: CutsceneSkipMode,
}
fn default_true() -> bool {
@ -145,6 +147,11 @@ fn default_rumble() -> bool {
false
}
#[inline(always)]
fn default_cutscene_skip_mode() -> CutsceneSkipMode {
CutsceneSkipMode::Hold
}
impl Settings {
pub fn load(ctx: &Context) -> GameResult<Settings> {
if let Ok(file) = user_open(ctx, "/settings.json") {
@ -291,6 +298,11 @@ impl Settings {
self.more_rust = false;
}
if self.version == 19 {
self.version = 20;
self.cutscene_skip_mode = CutsceneSkipMode::Hold;
}
if self.version != initial_version {
log::info!("Upgraded configuration file from version {} to {}.", initial_version, self.version);
}
@ -395,6 +407,7 @@ impl Default for Settings {
debug_mode: false,
noclip: false,
more_rust: false,
cutscene_skip_mode: CutsceneSkipMode::Hold,
}
}
}

View File

@ -106,6 +106,12 @@ pub enum PlayerCount {
Two,
}
#[derive(PartialEq, Eq, Copy, Clone, serde::Serialize, serde::Deserialize)]
pub enum CutsceneSkipMode {
Hold,
FastForward,
}
impl GameDifficulty {
pub fn from_primitive(val: u8) -> GameDifficulty {
return num_traits::FromPrimitive::from_u8(val).unwrap_or(GameDifficulty::Normal);