record last challenge attempts
This commit is contained in:
parent
290068dd37
commit
b1d578c0b4
|
@ -55,7 +55,8 @@
|
|||
"start": "Start",
|
||||
"no_replay": "No Replay",
|
||||
"replay_best": "Replay Best",
|
||||
"delete_replay": "Delete Replay"
|
||||
"replay_last": "Replay Last",
|
||||
"delete_replay": "Delete Best Replay"
|
||||
},
|
||||
|
||||
"options_menu": {
|
||||
|
@ -162,6 +163,8 @@
|
|||
"cancel": "(Esc to cancel)"
|
||||
},
|
||||
|
||||
"rumble": "Rumble:",
|
||||
|
||||
"reset_confirm": "Reset...",
|
||||
"reset_confirm_menu_title": "Reset controls?"
|
||||
}
|
||||
|
|
|
@ -49,7 +49,8 @@
|
|||
"start": "スタート",
|
||||
"no_replay": "ノーリプレイ",
|
||||
"replay_best": "ベストプレイを再生",
|
||||
"delete_replay": "リプレイを削除"
|
||||
"replay_last": "最後のプレイを再生",
|
||||
"delete_replay": "ベストリプレイを削除"
|
||||
},
|
||||
"options_menu": {
|
||||
"graphics": "グラフィック",
|
||||
|
@ -154,6 +155,8 @@
|
|||
"cancel": "(Escキーを押してキャンセル)"
|
||||
},
|
||||
|
||||
"rumble": "ランブル",
|
||||
|
||||
"reset_confirm": "リセット",
|
||||
"reset_confirm_menu_title": "ボタンをリセットしますか?"
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use crate::framework::keyboard::ScanCode;
|
|||
use crate::framework::vfs::OpenOptions;
|
||||
use crate::input::replay_player_controller::{KeyState, ReplayController};
|
||||
use crate::player::Player;
|
||||
use crate::shared_game_state::{ReplayState, SharedGameState};
|
||||
use crate::shared_game_state::{ReplayKind, ReplayState, SharedGameState};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Replay {
|
||||
|
@ -46,26 +46,42 @@ impl Replay {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn stop_recording(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
pub fn stop_recording(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
ctx: &mut Context,
|
||||
is_new_record: bool,
|
||||
) -> GameResult {
|
||||
state.replay_state = ReplayState::None;
|
||||
self.write_replay(state, ctx)?;
|
||||
|
||||
self.write_replay(state, ctx, ReplayKind::Last)?;
|
||||
|
||||
if is_new_record {
|
||||
self.write_replay(state, ctx, ReplayKind::Best)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn initialize_playback(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
pub fn initialize_playback(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
ctx: &mut Context,
|
||||
replay_kind: ReplayKind,
|
||||
) -> GameResult {
|
||||
if !self.is_active {
|
||||
state.replay_state = ReplayState::Playback;
|
||||
self.read_replay(state, ctx)?;
|
||||
state.replay_state = ReplayState::Playback(replay_kind);
|
||||
self.read_replay(state, ctx, replay_kind)?;
|
||||
state.game_rng.load_state(self.rng_seed);
|
||||
self.is_active = true;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_replay(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
fn write_replay(&mut self, state: &mut SharedGameState, ctx: &mut Context, replay_kind: ReplayKind) -> GameResult {
|
||||
if let Ok(mut file) = filesystem::open_options(
|
||||
ctx,
|
||||
[state.get_rec_filename(), ".rep".to_string()].join(""),
|
||||
[state.get_rec_filename(), replay_kind.get_suffix()].join(""),
|
||||
OpenOptions::new().write(true).create(true),
|
||||
) {
|
||||
file.write_u16::<LE>(0)?; // Space for versioning replay files
|
||||
|
@ -77,8 +93,9 @@ impl Replay {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn read_replay(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
if let Ok(mut file) = filesystem::user_open(ctx, [state.get_rec_filename(), ".rep".to_string()].join("")) {
|
||||
fn read_replay(&mut self, state: &mut SharedGameState, ctx: &mut Context, replay_kind: ReplayKind) -> GameResult {
|
||||
if let Ok(mut file) = filesystem::user_open(ctx, [state.get_rec_filename(), replay_kind.get_suffix()].join(""))
|
||||
{
|
||||
self.replay_version = file.read_u16::<LE>()?;
|
||||
self.rng_seed = file.read_u64::<LE>()?;
|
||||
|
||||
|
@ -120,7 +137,7 @@ impl GameEntity<(&mut Context, &mut Player)> for Replay {
|
|||
|
||||
self.keylist.push(inputs);
|
||||
}
|
||||
ReplayState::Playback => {
|
||||
ReplayState::Playback(_) => {
|
||||
let pause = ctx.keyboard_context.is_key_pressed(ScanCode::Escape) && (self.tick - self.resume_tick > 3);
|
||||
|
||||
let next_input = if pause { 1 << 10 } else { *self.keylist.get(self.tick).unwrap_or(&0) };
|
||||
|
@ -153,7 +170,7 @@ impl GameEntity<(&mut Context, &mut Player)> for Replay {
|
|||
|
||||
match state.replay_state {
|
||||
ReplayState::None => {}
|
||||
ReplayState::Playback => {
|
||||
ReplayState::Playback(_) => {
|
||||
state.font.draw_text_with_shadow(
|
||||
"PLAY".chars(),
|
||||
x,
|
||||
|
|
|
@ -430,7 +430,8 @@ impl ControlsMenu {
|
|||
self.main.set_entry(MainMenuEntry::Rumble, MenuEntry::Hidden);
|
||||
} else {
|
||||
self.selected_controller = controller_type;
|
||||
self.main.set_entry(MainMenuEntry::Rumble, MenuEntry::Toggle("Rumble".to_string(), rumble));
|
||||
self.main
|
||||
.set_entry(MainMenuEntry::Rumble, MenuEntry::Toggle(state.t("menus.controls_menu.rumble"), rumble));
|
||||
}
|
||||
} else {
|
||||
self.selected_controller = controller_type;
|
||||
|
|
|
@ -78,12 +78,12 @@ impl PlayerCountMenu {
|
|||
fn update_sizes(&mut self, state: &SharedGameState) {
|
||||
self.coop_menu.update_width(state);
|
||||
self.coop_menu.update_height();
|
||||
self.coop_menu.x = ((state.canvas_size.0 - self.coop_menu.width as f32) / 2.3).floor() as isize;
|
||||
self.coop_menu.x = ((state.canvas_size.0 - self.coop_menu.width as f32) / 2.0).floor() as isize;
|
||||
self.coop_menu.y = 30 + ((state.canvas_size.1 - self.coop_menu.height as f32) / 2.0).floor() as isize;
|
||||
|
||||
self.skin_menu.update_width(state);
|
||||
self.skin_menu.update_height();
|
||||
self.skin_menu.x = ((state.canvas_size.0 - self.coop_menu.width as f32) / 2.3).floor() as isize;
|
||||
self.skin_menu.x = ((state.canvas_size.0 - self.coop_menu.width as f32) / 2.0).floor() as isize;
|
||||
self.skin_menu.y = 30 + ((state.canvas_size.1 - self.coop_menu.height as f32) / 2.0).floor() as isize;
|
||||
}
|
||||
|
||||
|
|
|
@ -1633,8 +1633,10 @@ impl Scene for GameScene {
|
|||
self.drop_player2();
|
||||
}
|
||||
|
||||
if state.mod_path.is_some() && state.replay_state == ReplayState::Playback {
|
||||
self.replay.initialize_playback(state, ctx)?;
|
||||
if state.mod_path.is_some() {
|
||||
if let ReplayState::Playback(replay_kind) = state.replay_state {
|
||||
self.replay.initialize_playback(state, ctx, replay_kind)?;
|
||||
}
|
||||
}
|
||||
|
||||
self.npc_list.set_rng_seed(state.game_rng.next());
|
||||
|
@ -1724,8 +1726,10 @@ impl Scene for GameScene {
|
|||
}
|
||||
|
||||
fn tick(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
if !self.pause_menu.is_paused() && state.replay_state == ReplayState::Playback {
|
||||
self.replay.tick(state, (ctx, &mut self.player1))?;
|
||||
if !self.pause_menu.is_paused() {
|
||||
if let ReplayState::Playback(_) = state.replay_state {
|
||||
self.replay.tick(state, (ctx, &mut self.player1))?;
|
||||
}
|
||||
}
|
||||
|
||||
self.player1.controller.update(state, ctx)?;
|
||||
|
|
|
@ -14,7 +14,9 @@ use crate::menu::settings_menu::SettingsMenu;
|
|||
use crate::menu::{Menu, MenuEntry, MenuSelectionResult};
|
||||
use crate::scene::jukebox_scene::JukeboxScene;
|
||||
use crate::scene::Scene;
|
||||
use crate::shared_game_state::{GameDifficulty, MenuCharacter, ReplayState, Season, SharedGameState, TileSize};
|
||||
use crate::shared_game_state::{
|
||||
GameDifficulty, MenuCharacter, ReplayKind, ReplayState, Season, SharedGameState, TileSize,
|
||||
};
|
||||
use crate::stage::{BackgroundType, NpcType, Stage, StageData, StageTexturePaths, Tileset};
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone)]
|
||||
|
@ -61,7 +63,7 @@ impl Default for ChallengesMenuEntry {
|
|||
pub enum ConfirmMenuEntry {
|
||||
Title,
|
||||
StartChallenge,
|
||||
ReplayBest,
|
||||
Replay(ReplayKind),
|
||||
DeleteReplay,
|
||||
Back,
|
||||
}
|
||||
|
@ -248,8 +250,8 @@ impl Scene for TitleScene {
|
|||
self.confirm_menu.push_entry(ConfirmMenuEntry::Title, MenuEntry::Disabled("".to_owned()));
|
||||
self.confirm_menu
|
||||
.push_entry(ConfirmMenuEntry::StartChallenge, MenuEntry::Active(state.t("menus.challenge_menu.start")));
|
||||
self.confirm_menu
|
||||
.push_entry(ConfirmMenuEntry::ReplayBest, MenuEntry::Disabled(state.t("menus.challenge_menu.no_replay")));
|
||||
self.confirm_menu.push_entry(ConfirmMenuEntry::Replay(ReplayKind::Best), MenuEntry::Hidden);
|
||||
self.confirm_menu.push_entry(ConfirmMenuEntry::Replay(ReplayKind::Last), MenuEntry::Hidden);
|
||||
self.confirm_menu.push_entry(ConfirmMenuEntry::DeleteReplay, MenuEntry::Hidden);
|
||||
self.confirm_menu.push_entry(ConfirmMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||
self.confirm_menu.selected = ConfirmMenuEntry::StartChallenge;
|
||||
|
@ -356,9 +358,9 @@ impl Scene for TitleScene {
|
|||
|
||||
self.confirm_menu.set_entry(ConfirmMenuEntry::Title, MenuEntry::Disabled(mod_name));
|
||||
|
||||
if state.has_replay_data(ctx) {
|
||||
if state.has_replay_data(ctx, ReplayKind::Best) {
|
||||
self.confirm_menu.set_entry(
|
||||
ConfirmMenuEntry::ReplayBest,
|
||||
ConfirmMenuEntry::Replay(ReplayKind::Best),
|
||||
MenuEntry::Active(state.t("menus.challenge_menu.replay_best")),
|
||||
);
|
||||
self.confirm_menu.set_entry(
|
||||
|
@ -366,13 +368,21 @@ impl Scene for TitleScene {
|
|||
MenuEntry::Active(state.t("menus.challenge_menu.delete_replay")),
|
||||
);
|
||||
} else {
|
||||
self.confirm_menu.set_entry(
|
||||
ConfirmMenuEntry::ReplayBest,
|
||||
MenuEntry::Disabled(state.t("menus.challenge_menu.no_replay")),
|
||||
);
|
||||
self.confirm_menu
|
||||
.set_entry(ConfirmMenuEntry::Replay(ReplayKind::Best), MenuEntry::Hidden);
|
||||
self.confirm_menu.set_entry(ConfirmMenuEntry::DeleteReplay, MenuEntry::Hidden);
|
||||
}
|
||||
|
||||
if state.has_replay_data(ctx, ReplayKind::Last) {
|
||||
self.confirm_menu.set_entry(
|
||||
ConfirmMenuEntry::Replay(ReplayKind::Last),
|
||||
MenuEntry::Active(state.t("menus.challenge_menu.replay_last")),
|
||||
);
|
||||
} else {
|
||||
self.confirm_menu
|
||||
.set_entry(ConfirmMenuEntry::Replay(ReplayKind::Last), MenuEntry::Hidden);
|
||||
}
|
||||
|
||||
self.nikumaru_rec.load_counter(state, ctx)?;
|
||||
self.current_menu = CurrentMenu::ChallengeConfirmMenu;
|
||||
}
|
||||
|
@ -391,14 +401,14 @@ impl Scene for TitleScene {
|
|||
state.replay_state = ReplayState::Recording;
|
||||
self.current_menu = CurrentMenu::PlayerCountMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(ConfirmMenuEntry::ReplayBest, _) => {
|
||||
MenuSelectionResult::Selected(ConfirmMenuEntry::Replay(kind), _) => {
|
||||
state.difficulty = GameDifficulty::Normal;
|
||||
state.replay_state = ReplayState::Playback;
|
||||
state.replay_state = ReplayState::Playback(kind);
|
||||
state.reload_resources(ctx)?;
|
||||
state.start_new_game(ctx)?;
|
||||
}
|
||||
MenuSelectionResult::Selected(ConfirmMenuEntry::DeleteReplay, _) => {
|
||||
state.delete_replay_data(ctx)?;
|
||||
state.delete_replay_data(ctx, ReplayKind::Best)?;
|
||||
self.current_menu = CurrentMenu::ChallengesMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(ConfirmMenuEntry::Back, _) | MenuSelectionResult::Canceled => {
|
||||
|
|
|
@ -1755,8 +1755,8 @@ impl TextScriptVM {
|
|||
TSCOpCode::STC => {
|
||||
let new_record = game_scene.nikumaru.save_counter(state, ctx)?;
|
||||
|
||||
if new_record && state.replay_state == ReplayState::Recording {
|
||||
game_scene.replay.stop_recording(state, ctx)?;
|
||||
if state.replay_state == ReplayState::Recording {
|
||||
game_scene.replay.stop_recording(state, ctx, new_record)?;
|
||||
}
|
||||
|
||||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||
|
|
|
@ -243,11 +243,26 @@ pub enum MenuCharacter {
|
|||
Sue,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub enum ReplayKind {
|
||||
Best,
|
||||
Last,
|
||||
}
|
||||
|
||||
impl ReplayKind {
|
||||
pub fn get_suffix(&self) -> String {
|
||||
match self {
|
||||
ReplayKind::Best => ".rep".to_string(),
|
||||
ReplayKind::Last => ".last.rep".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone)]
|
||||
pub enum ReplayState {
|
||||
None,
|
||||
Recording,
|
||||
Playback,
|
||||
Playback(ReplayKind),
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone)]
|
||||
|
@ -805,13 +820,13 @@ impl SharedGameState {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn has_replay_data(&self, ctx: &mut Context) -> bool {
|
||||
filesystem::user_exists(ctx, [self.get_rec_filename(), ".rep".to_string()].join(""))
|
||||
pub fn has_replay_data(&self, ctx: &mut Context, replay_kind: ReplayKind) -> bool {
|
||||
filesystem::user_exists(ctx, [self.get_rec_filename(), replay_kind.get_suffix()].join(""))
|
||||
}
|
||||
|
||||
pub fn delete_replay_data(&self, ctx: &mut Context) -> GameResult {
|
||||
if self.has_replay_data(ctx) {
|
||||
filesystem::user_delete(ctx, [self.get_rec_filename(), ".rep".to_string()].join(""))?;
|
||||
pub fn delete_replay_data(&self, ctx: &mut Context, replay_kind: ReplayKind) -> GameResult {
|
||||
if self.has_replay_data(ctx, replay_kind) {
|
||||
filesystem::user_delete(ctx, [self.get_rec_filename(), replay_kind.get_suffix()].join(""))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue