mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-12-01 00:29:58 +00:00
Add fast-forward cutscene skip option
This commit is contained in:
parent
670e6891c1
commit
3d86995feb
|
|
@ -126,7 +126,12 @@
|
||||||
"50tps": "50tps (freeware)",
|
"50tps": "50tps (freeware)",
|
||||||
"60tps": "60tps (CS+)"
|
"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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,12 @@
|
||||||
"50tps": "50tps (freeware)",
|
"50tps": "50tps (freeware)",
|
||||||
"60tps": "60tps (CS+)"
|
"60tps": "60tps (CS+)"
|
||||||
},
|
},
|
||||||
"pause_on_focus_loss": "フォーカスが外れた時のポーズ:"
|
"pause_on_focus_loss": "フォーカスが外れた時のポーズ:",
|
||||||
|
"cutscene_skip_method": {
|
||||||
|
"entry": "カットシーンをスキップ",
|
||||||
|
"hold": "を押し続け",
|
||||||
|
"fastforward": "はやおくり"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ use super::settings_menu::SettingsMenu;
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
enum CurrentMenu {
|
enum CurrentMenu {
|
||||||
PauseMenu,
|
PauseMenu,
|
||||||
OptionsMenu,
|
SettingsMenu,
|
||||||
ConfirmMenu,
|
ConfirmMenu,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -23,7 +23,7 @@ enum CurrentMenu {
|
||||||
enum PauseMenuEntry {
|
enum PauseMenuEntry {
|
||||||
Resume,
|
Resume,
|
||||||
Retry,
|
Retry,
|
||||||
Options,
|
Settings,
|
||||||
Title,
|
Title,
|
||||||
Quit,
|
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::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::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::Title, MenuEntry::Active(state.t("menus.pause_menu.title")));
|
||||||
self.pause_menu.push_entry(PauseMenuEntry::Quit, MenuEntry::Active(state.t("menus.pause_menu.quit")));
|
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.sound_manager.play_song(0, &state.constants, &state.settings, ctx)?;
|
||||||
state.load_or_start_game(ctx)?;
|
state.load_or_start_game(ctx)?;
|
||||||
}
|
}
|
||||||
MenuSelectionResult::Selected(PauseMenuEntry::Options, _) => {
|
MenuSelectionResult::Selected(PauseMenuEntry::Settings, _) => {
|
||||||
self.current_menu = CurrentMenu::OptionsMenu;
|
self.current_menu = CurrentMenu::SettingsMenu;
|
||||||
}
|
}
|
||||||
MenuSelectionResult::Selected(PauseMenuEntry::Title, _) => {
|
MenuSelectionResult::Selected(PauseMenuEntry::Title, _) => {
|
||||||
self.confirm_menu.set_entry(
|
self.confirm_menu.set_entry(
|
||||||
|
|
@ -167,7 +167,7 @@ impl PauseMenu {
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
CurrentMenu::OptionsMenu => {
|
CurrentMenu::SettingsMenu => {
|
||||||
let cm = &mut self.current_menu;
|
let cm = &mut self.current_menu;
|
||||||
self.settings_menu.tick(
|
self.settings_menu.tick(
|
||||||
&mut || {
|
&mut || {
|
||||||
|
|
@ -219,7 +219,7 @@ impl PauseMenu {
|
||||||
self.pause_menu.draw(state, ctx)?;
|
self.pause_menu.draw(state, ctx)?;
|
||||||
graphics::set_clip_rect(ctx, None)?;
|
graphics::set_clip_rect(ctx, None)?;
|
||||||
}
|
}
|
||||||
CurrentMenu::OptionsMenu => {
|
CurrentMenu::SettingsMenu => {
|
||||||
self.settings_menu.draw(state, ctx)?;
|
self.settings_menu.draw(state, ctx)?;
|
||||||
}
|
}
|
||||||
CurrentMenu::ConfirmMenu => {
|
CurrentMenu::ConfirmMenu => {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,9 @@ use crate::input::combined_menu_controller::CombinedMenuController;
|
||||||
use crate::menu::MenuEntry;
|
use crate::menu::MenuEntry;
|
||||||
use crate::menu::{Menu, MenuSelectionResult};
|
use crate::menu::{Menu, MenuSelectionResult};
|
||||||
use crate::scene::title_scene::TitleScene;
|
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::sound::InterpolationMode;
|
||||||
use crate::{graphics, VSyncMode};
|
use crate::{graphics, VSyncMode};
|
||||||
|
|
||||||
|
|
@ -110,6 +112,7 @@ impl Default for LanguageMenuEntry {
|
||||||
enum BehaviorMenuEntry {
|
enum BehaviorMenuEntry {
|
||||||
GameTiming,
|
GameTiming,
|
||||||
PauseOnFocusLoss,
|
PauseOnFocusLoss,
|
||||||
|
CutsceneSkipMode,
|
||||||
Back,
|
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.behavior.push_entry(BehaviorMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||||
|
|
||||||
self.controls_menu.init(state, ctx)?;
|
self.controls_menu.init(state, ctx)?;
|
||||||
|
|
@ -739,6 +754,21 @@ impl SettingsMenu {
|
||||||
*value = state.settings.pause_on_focus_loss;
|
*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 => {
|
MenuSelectionResult::Selected(BehaviorMenuEntry::Back, _) | MenuSelectionResult::Canceled => {
|
||||||
self.current = CurrentMenu::MainMenu;
|
self.current = CurrentMenu::MainMenu;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ use crate::scene::Scene;
|
||||||
use crate::scripting::tsc::credit_script::CreditScriptVM;
|
use crate::scripting::tsc::credit_script::CreditScriptVM;
|
||||||
use crate::scripting::tsc::text_script::{ScriptMode, TextScriptExecutionState, TextScriptVM};
|
use crate::scripting::tsc::text_script::{ScriptMode, TextScriptExecutionState, TextScriptVM};
|
||||||
use crate::settings::ControllerType;
|
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::stage::{BackgroundType, Stage, StageTexturePaths};
|
||||||
use crate::texture_set::SpriteBatch;
|
use crate::texture_set::SpriteBatch;
|
||||||
use crate::weapon::bullet::BulletManager;
|
use crate::weapon::bullet::BulletManager;
|
||||||
|
|
@ -1782,20 +1782,33 @@ impl Scene for GameScene {
|
||||||
| TextScriptExecutionState::WaitTicks(_, _, _)
|
| TextScriptExecutionState::WaitTicks(_, _, _)
|
||||||
| TextScriptExecutionState::WaitInput(_, _, _)
|
| TextScriptExecutionState::WaitInput(_, _, _)
|
||||||
| TextScriptExecutionState::WaitStanding(_, _)
|
| TextScriptExecutionState::WaitStanding(_, _)
|
||||||
|
| TextScriptExecutionState::WaitFade(_, _)
|
||||||
| TextScriptExecutionState::Msg(_, _, _, _)
|
| TextScriptExecutionState::Msg(_, _, _, _)
|
||||||
| TextScriptExecutionState::MsgNewLine(_, _, _, _, _)
|
| TextScriptExecutionState::MsgNewLine(_, _, _, _, _)
|
||||||
| TextScriptExecutionState::FallingIsland(_, _, _, _, _, _)
|
| 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;
|
state.touch_controls.control_type = TouchControlType::Dialog;
|
||||||
if self.player1.controller.skip() {
|
match state.settings.cutscene_skip_mode {
|
||||||
self.skip_counter += 1;
|
CutsceneSkipMode::Hold if !state.textscript_vm.flags.cutscene_skip() => {
|
||||||
if self.skip_counter >= CUTSCENE_SKIP_WAIT {
|
if self.player1.controller.skip() {
|
||||||
state.textscript_vm.flags.set_cutscene_skip(true);
|
self.skip_counter += 1;
|
||||||
state.tutorial_counter = 0;
|
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 {
|
CutsceneSkipMode::FastForward => {
|
||||||
self.skip_counter -= 1;
|
if self.player1.controller.skip() {
|
||||||
|
state.textscript_vm.flags.set_cutscene_skip(true);
|
||||||
|
} else {
|
||||||
|
state.textscript_vm.flags.set_cutscene_skip(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use crate::input::keyboard_player_controller::KeyboardController;
|
||||||
use crate::input::player_controller::PlayerController;
|
use crate::input::player_controller::PlayerController;
|
||||||
use crate::input::touch_player_controller::TouchPlayerController;
|
use crate::input::touch_player_controller::TouchPlayerController;
|
||||||
use crate::player::TargetPlayer;
|
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;
|
use crate::sound::InterpolationMode;
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
|
|
@ -79,6 +79,8 @@ pub struct Settings {
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub noclip: bool,
|
pub noclip: bool,
|
||||||
pub more_rust: bool,
|
pub more_rust: bool,
|
||||||
|
#[serde(default = "default_cutscene_skip_mode")]
|
||||||
|
pub cutscene_skip_mode: CutsceneSkipMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_true() -> bool {
|
fn default_true() -> bool {
|
||||||
|
|
@ -145,6 +147,11 @@ fn default_rumble() -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn default_cutscene_skip_mode() -> CutsceneSkipMode {
|
||||||
|
CutsceneSkipMode::Hold
|
||||||
|
}
|
||||||
|
|
||||||
impl Settings {
|
impl Settings {
|
||||||
pub fn load(ctx: &Context) -> GameResult<Settings> {
|
pub fn load(ctx: &Context) -> GameResult<Settings> {
|
||||||
if let Ok(file) = user_open(ctx, "/settings.json") {
|
if let Ok(file) = user_open(ctx, "/settings.json") {
|
||||||
|
|
@ -291,6 +298,11 @@ impl Settings {
|
||||||
self.more_rust = false;
|
self.more_rust = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.version == 19 {
|
||||||
|
self.version = 20;
|
||||||
|
self.cutscene_skip_mode = CutsceneSkipMode::Hold;
|
||||||
|
}
|
||||||
|
|
||||||
if self.version != initial_version {
|
if self.version != initial_version {
|
||||||
log::info!("Upgraded configuration file from version {} to {}.", initial_version, self.version);
|
log::info!("Upgraded configuration file from version {} to {}.", initial_version, self.version);
|
||||||
}
|
}
|
||||||
|
|
@ -395,6 +407,7 @@ impl Default for Settings {
|
||||||
debug_mode: false,
|
debug_mode: false,
|
||||||
noclip: false,
|
noclip: false,
|
||||||
more_rust: false,
|
more_rust: false,
|
||||||
|
cutscene_skip_mode: CutsceneSkipMode::Hold,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,12 @@ pub enum PlayerCount {
|
||||||
Two,
|
Two,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Copy, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub enum CutsceneSkipMode {
|
||||||
|
Hold,
|
||||||
|
FastForward,
|
||||||
|
}
|
||||||
|
|
||||||
impl GameDifficulty {
|
impl GameDifficulty {
|
||||||
pub fn from_primitive(val: u8) -> GameDifficulty {
|
pub fn from_primitive(val: u8) -> GameDifficulty {
|
||||||
return num_traits::FromPrimitive::from_u8(val).unwrap_or(GameDifficulty::Normal);
|
return num_traits::FromPrimitive::from_u8(val).unwrap_or(GameDifficulty::Normal);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue