diff --git a/src/engine_constants.rs b/src/engine_constants.rs index 9841d69..8b00cf7 100644 --- a/src/engine_constants.rs +++ b/src/engine_constants.rs @@ -100,6 +100,8 @@ pub struct TextScriptConsts { pub textbox_rect_top: Rect, pub textbox_rect_middle: Rect, pub textbox_rect_bottom: Rect, + pub textbox_rect_yes_no: Rect, + pub textbox_rect_cursor: Rect, } #[derive(Debug)] @@ -337,7 +339,7 @@ impl EngineConstants { n039_save_sign: [ Rect { left: 224, top: 64, right: 240, bottom: 80 }, Rect { left: 240, top: 64, right: 256, bottom: 80 }, - ] + ], }, tex_sizes: hashmap! { str!("ArmsImage") => (256, 16), @@ -460,6 +462,8 @@ impl EngineConstants { textbox_rect_top: Rect { left: 0, top: 0, right: 244, bottom: 8 }, textbox_rect_middle: Rect { left: 0, top: 8, right: 244, bottom: 16 }, textbox_rect_bottom: Rect { left: 0, top: 16, right: 244, bottom: 24 }, + textbox_rect_yes_no: Rect { left: 152, top: 48, right: 244, bottom: 80 }, + textbox_rect_cursor: Rect { left: 112, top: 88, right: 128, bottom: 104 }, }, font_path: str!("builtin/builtin_font.fnt"), font_scale: 1.0, diff --git a/src/scene/game_scene.rs b/src/scene/game_scene.rs index 84ceb84..f516323 100644 --- a/src/scene/game_scene.rs +++ b/src/scene/game_scene.rs @@ -12,7 +12,7 @@ use crate::scene::Scene; use crate::SharedGameState; use crate::stage::{BackgroundType, Stage}; use crate::str; -use crate::text_script::TextScriptVM; +use crate::text_script::{ConfirmSelection, TextScriptExecutionState, TextScriptVM}; use crate::ui::Components; pub struct GameScene { @@ -302,20 +302,41 @@ impl GameScene { let top_pos = if state.textscript_vm.flags.position_top() { 32.0 } else { state.canvas_size.1 as f32 - 66.0 }; let left_pos = (state.canvas_size.0 / 2.0 - 122.0).floor(); - if state.textscript_vm.flags.background_visible() { + { let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "TextBox")?; - - batch.add_rect(left_pos, top_pos, &state.constants.textscript.textbox_rect_top); - for i in 1..7 { - batch.add_rect(left_pos, top_pos + i as f32 * 8.0, &state.constants.textscript.textbox_rect_middle); + if state.textscript_vm.flags.background_visible() { + batch.add_rect(left_pos, top_pos, &state.constants.textscript.textbox_rect_top); + for i in 1..7 { + batch.add_rect(left_pos, top_pos + i as f32 * 8.0, &state.constants.textscript.textbox_rect_middle); + } + batch.add_rect(left_pos, top_pos + 56.0, &state.constants.textscript.textbox_rect_bottom); + } + + if let TextScriptExecutionState::WaitConfirmation(_, _, _, wait, selection) = state.textscript_vm.state { + let pos_y = if wait > 14 { + state.canvas_size.1 - 96.0 - (wait as f32 - 2.0) * 4.0 + } else { + state.canvas_size.1 - 96.0 + }; + + batch.add_rect((state.canvas_size.0 / 2.0 + 56.0).floor(), pos_y, + &state.constants.textscript.textbox_rect_yes_no); + + if wait == 0 { + let pos_x = if selection == ConfirmSelection::No { 41.0 } else { 0.0 }; + + batch.add_rect((state.canvas_size.0 / 2.0 + 51.0).floor() + pos_x, + state.canvas_size.1 - 86.0, + &state.constants.textscript.textbox_rect_cursor); + } } - batch.add_rect(left_pos, top_pos + 56.0, &state.constants.textscript.textbox_rect_bottom); batch.draw(ctx)?; } if state.textscript_vm.face != 0 { let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "Face")?; + batch.add_rect(left_pos + 14.0, top_pos + 8.0, &Rect::::new_size( (state.textscript_vm.face as usize % 6) * 48, (state.textscript_vm.face as usize / 6) * 48, diff --git a/src/text_script.rs b/src/text_script.rs index 00d25d2..8ced689 100644 --- a/src/text_script.rs +++ b/src/text_script.rs @@ -4,6 +4,7 @@ use std::io::Cursor; use std::io::Seek; use std::io::SeekFrom; use std::iter::Peekable; +use std::ops::Not; use std::str::FromStr; use byteorder::ReadBytesExt; @@ -187,6 +188,25 @@ pub enum TextScriptLine { Line3, } +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[repr(u8)] +pub enum ConfirmSelection { + Yes, + No, +} + +impl Not for ConfirmSelection { + type Output = ConfirmSelection; + + fn not(self) -> ConfirmSelection { + if self == ConfirmSelection::Yes { + ConfirmSelection::No + } else { + ConfirmSelection::Yes + } + } +} + #[derive(Debug, PartialEq, Copy, Clone)] #[repr(u8)] pub enum TextScriptExecutionState { @@ -195,6 +215,7 @@ pub enum TextScriptExecutionState { Msg(u16, u32, u32, u8), WaitTicks(u16, u32, u32), WaitInput(u16, u32), + WaitConfirmation(u16, u32, u16, u8, ConfirmSelection), WaitFade(u16, u32), } @@ -208,6 +229,7 @@ pub struct TextScriptVM { pub strict_mode: bool, pub suspend: bool, pub face: u16, + pub item: u16, pub current_line: TextScriptLine, pub line_1: Vec, pub line_2: Vec, @@ -305,6 +327,7 @@ impl TextScriptVM { strict_mode: false, suspend: true, flags: TextScriptFlags(0), + item: 0, face: 0, current_line: TextScriptLine::Line1, line_1: Vec::with_capacity(24), @@ -415,6 +438,30 @@ impl TextScriptVM { break; } } + TextScriptExecutionState::WaitConfirmation(event, ip, no_event, wait, selection) => { + if wait > 0 { + state.textscript_vm.state = TextScriptExecutionState::WaitConfirmation(event, ip, no_event, wait - 1, selection); + break; + } + + if state.key_trigger.left() || state.key_trigger.right() { + state.textscript_vm.state = TextScriptExecutionState::WaitConfirmation(event, ip, no_event, 0, !selection); + break; + } + + if state.key_trigger.jump() { + match selection { + ConfirmSelection::Yes => { + state.textscript_vm.state = TextScriptExecutionState::Running(event, ip); + }, + ConfirmSelection::No => { + state.textscript_vm.state = TextScriptExecutionState::Running(no_event, 0); + }, + } + } + + break; + } TextScriptExecutionState::WaitInput(event, ip) => { if state.key_trigger.jump() || state.key_trigger.fire() { state.textscript_vm.state = TextScriptExecutionState::Running(event, ip); @@ -592,6 +639,11 @@ impl TextScriptVM { exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32); } + OpCode::YNJ => { + let event_no = read_cur_varint(&mut cursor)? as u16; + + exec_state = TextScriptExecutionState::WaitConfirmation(event, cursor.position() as u32, event_no, 16, ConfirmSelection::No); + } OpCode::TRA => { let map_id = read_cur_varint(&mut cursor)? as usize; let event_num = read_cur_varint(&mut cursor)? as u16; @@ -687,7 +739,7 @@ impl TextScriptVM { OpCode::BOA | OpCode::BSL | OpCode::FOB | OpCode::FOM | OpCode::UNI | OpCode::MYB | OpCode::GIT | OpCode::NUM | OpCode::DNA | OpCode::MPp | OpCode::SKm | OpCode::SKp | OpCode::EQp | OpCode::EQm | - OpCode::ITp | OpCode::ITm | OpCode::AMm | OpCode::UNJ | OpCode::MPJ | OpCode::YNJ | + OpCode::ITp | OpCode::ITm | OpCode::AMm | OpCode::UNJ | OpCode::MPJ | OpCode::XX1 | OpCode::SIL | OpCode::LIp | OpCode::SOU | OpCode::SSS | OpCode::ACH => { let par_a = read_cur_varint(&mut cursor)?;