1
0
Fork 0
mirror of https://github.com/doukutsu-rs/doukutsu-rs synced 2025-12-01 08:37:23 +00:00

Merge branch 'master' of github.com:alula/doukutsu-rs

This commit is contained in:
Alula 2022-01-22 02:18:26 +01:00
commit d6df4640ab
No known key found for this signature in database
GPG key ID: 3E00485503A1D8BA
4 changed files with 101 additions and 5 deletions

View file

@ -1,10 +1,15 @@
use byteorder::{ReadBytesExt, WriteBytesExt, LE};
use crate::common::Rect; use crate::common::Rect;
use crate::components::draw_common::{Alignment, draw_number, draw_number_zeros}; use crate::components::draw_common::{draw_number, draw_number_zeros, Alignment};
use crate::entity::GameEntity; use crate::entity::GameEntity;
use crate::frame::Frame; use crate::frame::Frame;
use crate::framework::context::Context; use crate::framework::context::Context;
use crate::framework::error::GameResult; use crate::framework::error::GameResult;
use crate::framework::filesystem;
use crate::framework::vfs::OpenOptions;
use crate::player::Player; use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::{SharedGameState, TimingMode}; use crate::shared_game_state::{SharedGameState, TimingMode};
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -17,6 +22,76 @@ impl NikumaruCounter {
pub fn new() -> NikumaruCounter { pub fn new() -> NikumaruCounter {
NikumaruCounter { tick: 0, shown: false } NikumaruCounter { tick: 0, shown: false }
} }
fn load_time(&mut self, ctx: &mut Context) -> GameResult<u32> {
if let Ok(mut data) = filesystem::user_open(ctx, "/290.rec") {
let mut ticks: [u32; 4] = [0; 4];
for iter in 0..=3 {
ticks[iter] = data.read_u32::<LE>()?;
}
let random = data.read_u32::<LE>()?;
let random_list: [u8; 4] = random.to_le_bytes();
for iter in 0..=3 {
ticks[iter] = u32::from_le_bytes([
ticks[iter].to_le_bytes()[0].wrapping_sub(random_list[iter]),
ticks[iter].to_le_bytes()[1].wrapping_sub(random_list[iter]),
ticks[iter].to_le_bytes()[2].wrapping_sub(random_list[iter]),
ticks[iter].to_le_bytes()[3].wrapping_sub(random_list[iter] / 2),
]);
}
if ticks[0] == ticks[1] && ticks[0] == ticks[2] {
return Ok(ticks[0]);
}
} else {
log::warn!("Failed to open 290 record.");
}
Ok(0)
}
fn save_time(&mut self, new_time: u32, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
if let Ok(mut data) = filesystem::open_options(ctx, "/290.rec", OpenOptions::new().write(true).create(true)) {
let mut ticks: [u32; 4] = [new_time; 4];
let mut random_list: [u8; 4] = [0; 4];
for iter in 0..=3 {
random_list[iter] = state.game_rng.range(0..250) as u8 + iter as u8;
ticks[iter] = u32::from_le_bytes([
ticks[iter].to_le_bytes()[0].wrapping_add(random_list[iter]),
ticks[iter].to_le_bytes()[1].wrapping_add(random_list[iter]),
ticks[iter].to_le_bytes()[2].wrapping_add(random_list[iter]),
ticks[iter].to_le_bytes()[3].wrapping_add(random_list[iter] / 2),
]);
data.write_u32::<LE>(ticks[iter])?;
}
data.write_u32::<LE>(u32::from_le_bytes(random_list))?;
} else {
log::warn!("Failed to write 290 record.");
}
Ok(())
}
pub fn load_counter(&mut self, ctx: &mut Context) -> GameResult {
self.tick = self.load_time(ctx)? as usize;
if self.tick > 0 {
self.shown = true;
}
Ok(())
}
pub fn save_counter(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
let old_record = self.load_time(ctx)? as usize;
if self.tick < old_record || old_record == 0 {
self.save_time(self.tick as u32, state, ctx)?;
}
Ok(())
}
} }
impl GameEntity<&Player> for NikumaruCounter { impl GameEntity<&Player> for NikumaruCounter {

View file

@ -103,6 +103,7 @@ impl PauseMenu {
self.current_menu = CurrentMenu::OptionsMenu; self.current_menu = CurrentMenu::OptionsMenu;
} }
MenuSelectionResult::Selected(3, _) => { MenuSelectionResult::Selected(3, _) => {
state.textscript_vm.flags.set_cutscene_skip(false);
state.next_scene = Some(Box::new(TitleScene::new())); state.next_scene = Some(Box::new(TitleScene::new()));
} }
MenuSelectionResult::Selected(5, _) => { MenuSelectionResult::Selected(5, _) => {

View file

@ -1,5 +1,7 @@
use crate::common::{Color, VERSION_BANNER}; use crate::common::{Color, VERSION_BANNER};
use crate::components::background::Background; use crate::components::background::Background;
use crate::components::nikumaru::NikumaruCounter;
use crate::entity::GameEntity;
use crate::frame::Frame; use crate::frame::Frame;
use crate::framework::context::Context; use crate::framework::context::Context;
use crate::framework::error::GameResult; use crate::framework::error::GameResult;
@ -34,6 +36,7 @@ pub struct TitleScene {
save_select_menu: Menu, save_select_menu: Menu,
background: Background, background: Background,
frame: Frame, frame: Frame,
nikumaru_rec: NikumaruCounter,
stage: Stage, stage: Stage,
textures: StageTexturePaths, textures: StageTexturePaths,
} }
@ -67,6 +70,7 @@ impl TitleScene {
save_select_menu: Menu::new(0, 0, 200, 0), save_select_menu: Menu::new(0, 0, 200, 0),
background: Background::new(), background: Background::new(),
frame: Frame::new(), frame: Frame::new(),
nikumaru_rec: NikumaruCounter::new(),
stage: fake_stage, stage: fake_stage,
textures, textures,
} }
@ -117,6 +121,8 @@ impl Scene for TitleScene {
self.controller.update(state, ctx)?; self.controller.update(state, ctx)?;
self.controller.update_trigger(); self.controller.update_trigger();
self.nikumaru_rec.load_counter(ctx)?;
Ok(()) Ok(())
} }
@ -211,6 +217,8 @@ impl Scene for TitleScene {
self.draw_text_centered(&VERSION_BANNER, state.canvas_size.1 - 15.0, state, ctx)?; self.draw_text_centered(&VERSION_BANNER, state.canvas_size.1 - 15.0, state, ctx)?;
self.draw_text_centered(COPYRIGHT_PIXEL, state.canvas_size.1 - 30.0, state, ctx)?; self.draw_text_centered(COPYRIGHT_PIXEL, state.canvas_size.1 - 30.0, state, ctx)?;
self.nikumaru_rec.draw(state, ctx, &self.frame)?;
match self.current_menu { match self.current_menu {
CurrentMenu::MainMenu => self.main_menu.draw(state, ctx)?, CurrentMenu::MainMenu => self.main_menu.draw(state, ctx)?,
CurrentMenu::OptionMenu => self.option_menu.draw(state, ctx)?, CurrentMenu::OptionMenu => self.option_menu.draw(state, ctx)?,

View file

@ -11,8 +11,8 @@ use std::rc::Rc;
use num_traits::{clamp, FromPrimitive}; use num_traits::{clamp, FromPrimitive};
use crate::bitfield; use crate::bitfield;
use crate::common::{Direction, FadeDirection, FadeState, Rect};
use crate::common::Direction::{Left, Right}; use crate::common::Direction::{Left, Right};
use crate::common::{Direction, FadeDirection, FadeState, Rect};
use crate::engine_constants::EngineConstants; use crate::engine_constants::EngineConstants;
use crate::entity::GameEntity; use crate::entity::GameEntity;
use crate::frame::UpdateTarget; use crate::frame::UpdateTarget;
@ -396,7 +396,13 @@ impl TextScriptVM {
state.textscript_vm.state = if !new_line { state.textscript_vm.state = if !new_line {
TextScriptExecutionState::Msg(event, cursor.position() as u32, remaining - 1, ticks) TextScriptExecutionState::Msg(event, cursor.position() as u32, remaining - 1, ticks)
} else { } else {
TextScriptExecutionState::MsgNewLine(event, cursor.position() as u32, remaining - 1, ticks, 4) TextScriptExecutionState::MsgNewLine(
event,
cursor.position() as u32,
remaining - 1,
ticks,
4,
)
}; };
} else { } else {
state.textscript_vm.state = state.textscript_vm.state =
@ -419,7 +425,8 @@ impl TextScriptVM {
state.textscript_vm.line_2.append(&mut state.textscript_vm.line_3); state.textscript_vm.line_2.append(&mut state.textscript_vm.line_3);
state.textscript_vm.state = TextScriptExecutionState::Msg(event, ip, remaining, ticks); state.textscript_vm.state = TextScriptExecutionState::Msg(event, ip, remaining, ticks);
} else { } else {
state.textscript_vm.state = TextScriptExecutionState::MsgNewLine(event, ip, remaining, ticks, counter); state.textscript_vm.state =
TextScriptExecutionState::MsgNewLine(event, ip, remaining, ticks, counter);
} }
break; break;
} }
@ -1650,9 +1657,14 @@ impl TextScriptVM {
mode != 0, mode != 0,
); );
} }
TSCOpCode::STC => {
game_scene.nikumaru.save_counter(state, ctx)?;
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
}
// unimplemented opcodes // unimplemented opcodes
// Zero operands // Zero operands
TSCOpCode::KE2 | TSCOpCode::MLP | TSCOpCode::FR2 | TSCOpCode::STC | TSCOpCode::HM2 => { TSCOpCode::KE2 | TSCOpCode::MLP | TSCOpCode::FR2 | TSCOpCode::HM2 => {
log::warn!("unimplemented opcode: {:?}", op); log::warn!("unimplemented opcode: {:?}", op);
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32); exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);