2022-01-23 04:55:50 +00:00
|
|
|
use byteorder::{LE, ReadBytesExt, WriteBytesExt};
|
2022-01-21 16:31:25 +00:00
|
|
|
|
2022-01-08 11:39:17 +00:00
|
|
|
use crate::common::Rect;
|
2022-01-23 04:55:50 +00:00
|
|
|
use crate::components::draw_common::{Alignment, draw_number, draw_number_zeros};
|
2022-01-08 11:39:17 +00:00
|
|
|
use crate::entity::GameEntity;
|
|
|
|
use crate::frame::Frame;
|
|
|
|
use crate::framework::context::Context;
|
|
|
|
use crate::framework::error::GameResult;
|
2022-01-21 16:31:25 +00:00
|
|
|
use crate::framework::filesystem;
|
2022-01-21 21:40:37 +00:00
|
|
|
use crate::framework::vfs::OpenOptions;
|
2022-01-08 11:39:17 +00:00
|
|
|
use crate::player::Player;
|
2022-01-21 21:40:37 +00:00
|
|
|
use crate::rng::RNG;
|
2022-01-23 04:55:50 +00:00
|
|
|
use crate::scripting::tsc::text_script::TextScriptExecutionState;
|
2022-01-08 11:39:17 +00:00
|
|
|
use crate::shared_game_state::{SharedGameState, TimingMode};
|
|
|
|
|
2022-01-09 12:11:25 +00:00
|
|
|
#[derive(Clone, Copy)]
|
2022-01-08 11:39:17 +00:00
|
|
|
pub struct NikumaruCounter {
|
|
|
|
pub tick: usize,
|
|
|
|
pub shown: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl NikumaruCounter {
|
|
|
|
pub fn new() -> NikumaruCounter {
|
|
|
|
NikumaruCounter { tick: 0, shown: false }
|
|
|
|
}
|
2022-01-21 16:31:25 +00:00
|
|
|
|
2022-01-21 21:40:37 +00:00
|
|
|
fn load_time(&mut self, ctx: &mut Context) -> GameResult<u32> {
|
2022-01-21 16:31:25 +00:00
|
|
|
if let Ok(mut data) = filesystem::user_open(ctx, "/290.rec") {
|
2022-01-21 21:40:37 +00:00
|
|
|
let mut ticks: [u32; 4] = [0; 4];
|
2022-01-21 16:31:25 +00:00
|
|
|
|
|
|
|
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([
|
2022-01-21 21:40:37 +00:00
|
|
|
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),
|
2022-01-21 16:31:25 +00:00
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ticks[0] == ticks[1] && ticks[0] == ticks[2] {
|
|
|
|
return Ok(ticks[0]);
|
|
|
|
}
|
|
|
|
} else {
|
2022-01-21 21:40:37 +00:00
|
|
|
log::warn!("Failed to open 290 record.");
|
2022-01-21 16:31:25 +00:00
|
|
|
}
|
|
|
|
Ok(0)
|
|
|
|
}
|
|
|
|
|
2022-01-21 21:40:37 +00:00
|
|
|
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(())
|
|
|
|
}
|
|
|
|
|
2022-01-21 16:31:25 +00:00
|
|
|
pub fn load_counter(&mut self, ctx: &mut Context) -> GameResult {
|
2022-01-21 21:40:37 +00:00
|
|
|
self.tick = self.load_time(ctx)? as usize;
|
2022-01-21 16:31:25 +00:00
|
|
|
if self.tick > 0 {
|
|
|
|
self.shown = true;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
2022-01-21 21:40:37 +00:00
|
|
|
|
|
|
|
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(())
|
|
|
|
}
|
2022-01-08 11:39:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl GameEntity<&Player> for NikumaruCounter {
|
2022-01-09 13:42:47 +00:00
|
|
|
fn tick(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
|
2022-01-08 11:39:17 +00:00
|
|
|
if !player.equip.has_nikumaru() {
|
|
|
|
self.tick = 0;
|
|
|
|
self.shown = false;
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
self.shown = true;
|
2022-01-09 13:42:47 +00:00
|
|
|
|
|
|
|
if state.control_flags.control_enabled() {
|
|
|
|
self.tick += 1;
|
|
|
|
}
|
2022-01-08 11:39:17 +00:00
|
|
|
|
|
|
|
if self.tick >= 300000 {
|
|
|
|
self.tick = 300000;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn draw(&self, state: &mut SharedGameState, ctx: &mut Context, _frame: &Frame) -> GameResult {
|
|
|
|
if !self.shown {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
2022-01-23 04:55:50 +00:00
|
|
|
if state.textscript_vm.state == TextScriptExecutionState::MapSystem {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
2022-01-08 11:39:17 +00:00
|
|
|
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "TextBox")?;
|
|
|
|
|
|
|
|
let x = 16.0;
|
|
|
|
let y = 8.0;
|
|
|
|
|
|
|
|
const CLOCK_RECTS: [Rect<u16>; 2] = [
|
|
|
|
Rect { left: 112, top: 104, right: 120, bottom: 112 },
|
|
|
|
Rect { left: 120, top: 104, right: 128, bottom: 112 },
|
|
|
|
];
|
|
|
|
const PRIME: Rect<u16> = Rect { left: 128, top: 104, right: 160, bottom: 112 };
|
|
|
|
|
|
|
|
let (one_tenth, second, minute) = match state.settings.timing_mode {
|
|
|
|
TimingMode::_60Hz => (6, 60, 3600),
|
|
|
|
_ => (5, 50, 3000),
|
|
|
|
};
|
|
|
|
|
|
|
|
if self.tick % 30 <= 10 {
|
|
|
|
batch.add_rect(x, y, &CLOCK_RECTS[1]);
|
|
|
|
} else {
|
|
|
|
batch.add_rect(x, y, &CLOCK_RECTS[0]);
|
|
|
|
}
|
|
|
|
batch.add_rect(x + 30.0, y, &PRIME);
|
|
|
|
|
|
|
|
batch.draw(ctx)?;
|
|
|
|
|
|
|
|
draw_number(x + 32.0, y, self.tick / minute, Alignment::Right, state, ctx)?;
|
|
|
|
draw_number_zeros(x + 52.0, y, (self.tick / second) % 60, Alignment::Right, 2, state, ctx)?;
|
|
|
|
draw_number(x + 64.0, y, (self.tick / one_tenth) % 10, Alignment::Right, state, ctx)?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|