From 85815f87ff263799e0fd65108ee4ecf1dedec2e4 Mon Sep 17 00:00:00 2001 From: jugeeya Date: Mon, 7 Aug 2023 11:59:47 -0700 Subject: [PATCH] Input Recording Menu Refactor (#579) * Initial * Formatting * Slight name changes --- src/training/input_record.rs | 69 +++++++++++------------------- src/training/save_states.rs | 4 +- training_mod_consts/src/lib.rs | 62 +++++++++++++++------------ training_mod_consts/src/options.rs | 11 ++--- 4 files changed, 66 insertions(+), 80 deletions(-) diff --git a/src/training/input_record.rs b/src/training/input_record.rs index ecccf36..7790079 100644 --- a/src/training/input_record.rs +++ b/src/training/input_record.rs @@ -1,5 +1,5 @@ use crate::common::button_config; -use crate::common::consts::{FighterId, HitstunPlayback}; +use crate::common::consts::{FighterId, HitstunPlayback, OnOff}; use crate::common::{get_module_accessor, is_in_hitstun, is_in_shieldstun, MENU}; use crate::training::input_recording::structures::*; use crate::training::mash; @@ -125,7 +125,7 @@ unsafe fn should_mash_playback() { // probably need a separate standby setting for grounded, aerial, shield, where shield starts once you let go of shield, and aerial keeps you in the air? if should_playback { - playback(mash::queued_playback_slot()); + playback(Some(mash::queued_playback_slot())); } } @@ -184,7 +184,7 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut BattleObjectModuleAcces module_accessor, button_config::ButtonCombo::InputPlayback, ) { - playback(MENU.playback_slot.get_random().into_idx().unwrap_or(0)); + playback(MENU.playback_button_combination.get_random().into_idx()); } // Attack + Dpad Left: Record else if button_config::combo_passes_exclusive( @@ -204,6 +204,9 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut BattleObjectModuleAcces if mash::is_playback_queued() { mash::reset(); } + if MENU.playback_loop == OnOff::On { + playback(Some(CURRENT_PLAYBACK_SLOT)); + } } } @@ -290,15 +293,17 @@ pub unsafe fn lockout_record() { CURRENT_LR = RECORDED_LR; } -pub unsafe fn playback(slot: usize) { +// Returns whether we did playback +pub unsafe fn playback(slot: Option) -> bool { if INPUT_RECORD == Pause { println!("Tried to playback during lockout!"); - return; + return false; } - if MENU.playback_slot.is_empty() { + if slot.is_none() { println!("Tried to playback without a slot selected!"); - return; + return false; } + let slot = slot.unwrap(); clear_notifications("Input Recording"); color_notification( @@ -321,46 +326,22 @@ pub unsafe fn playback(slot: usize) { BUFFER_FRAME = 0; let cpu_module_accessor = get_module_accessor(FighterId::CPU); CURRENT_LR = PostureModule::lr(cpu_module_accessor); + + true } -pub unsafe fn playback_ledge(slot: usize) { - if INPUT_RECORD == Pause { - println!("Tried to playback during lockout!"); - return; +pub unsafe fn playback_ledge(slot: Option) { + let did_playback = playback(slot); + if did_playback { + BUFFER_FRAME = 5; // So we can make sure the option is buffered and won't get ledge trumped if delay is 0 + // drop down from ledge can't be buffered on the same frame as jump/attack/roll/ngu so we have to do this + // Need to buffer 1 less frame for non-lassos + let cpu_module_accessor = get_module_accessor(FighterId::CPU); + let status_kind = StatusModule::status_kind(cpu_module_accessor) as i32; + if status_kind == *FIGHTER_STATUS_KIND_CLIFF_CATCH { + BUFFER_FRAME -= 1; + } } - if MENU.playback_slot.is_empty() { - println!("Tried to playback without a slot selected!"); - return; - } - - clear_notifications("Input Recording"); - color_notification( - "Input Recording".to_string(), - "Playback".to_owned(), - 60, - ResColor { - r: 0, - g: 0, - b: 0, - a: 255, - }, - ); - - CURRENT_PLAYBACK_SLOT = slot; - CURRENT_FRAME_LENGTH = P1_FRAME_LENGTH_MAPPING.lock()[CURRENT_PLAYBACK_SLOT]; - - INPUT_RECORD = Playback; - POSSESSION = Player; - INPUT_RECORD_FRAME = 0; - BUFFER_FRAME = 5; // So we can make sure the option is buffered and won't get ledge trumped if delay is 0 - // drop down from ledge can't be buffered on the same frame as jump/attack/roll/ngu so we have to do this - // Need to buffer 1 less frame for non-lassos - let cpu_module_accessor = get_module_accessor(FighterId::CPU); - let status_kind = StatusModule::status_kind(cpu_module_accessor) as i32; - if status_kind == *FIGHTER_STATUS_KIND_CLIFF_CATCH { - BUFFER_FRAME -= 1; - } - CURRENT_LR = PostureModule::lr(cpu_module_accessor); } pub unsafe fn stop_playback() { diff --git a/src/training/save_states.rs b/src/training/save_states.rs index 2dab66e..2ca2e20 100644 --- a/src/training/save_states.rs +++ b/src/training/save_states.rs @@ -614,8 +614,8 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor) input_record::lockout_record(); } // otherwise, begin input recording playback if selected - else if MENU.save_state_playback == OnOff::On { - input_record::playback(MENU.playback_slot.get_random().into_idx().unwrap_or(0)); + else if !MENU.save_state_playback.is_empty() { + input_record::playback(MENU.save_state_playback.get_random().into_idx()); } return; diff --git a/training_mod_consts/src/lib.rs b/training_mod_consts/src/lib.rs index 00b6b47..accbcbb 100644 --- a/training_mod_consts/src/lib.rs +++ b/training_mod_consts/src/lib.rs @@ -51,6 +51,7 @@ pub struct TrainingModpackMenu { pub save_state_slot: SaveStateSlot, pub randomize_slots: OnOff, pub save_state_mirroring: SaveStateMirroring, + pub save_state_playback: PlaybackSlot, pub sdi_state: Direction, pub sdi_strength: SdiFrequency, pub shield_state: Shield, @@ -72,13 +73,13 @@ pub struct TrainingModpackMenu { pub footstool_override: Action, pub landing_override: Action, pub trump_override: Action, - pub save_state_playback: OnOff, pub recording_slot: RecordSlot, - pub playback_slot: PlaybackSlot, - pub playback_mash: OnOff, pub record_trigger: RecordTrigger, pub recording_frames: RecordingFrames, + pub playback_button_combination: PlaybackSlot, pub hitstun_playback: HitstunPlayback, + pub playback_mash: OnOff, + pub playback_loop: OnOff, } #[repr(C)] @@ -148,6 +149,7 @@ pub static DEFAULTS_MENU: TrainingModpackMenu = TrainingModpackMenu { save_state_slot: SaveStateSlot::One, randomize_slots: OnOff::Off, save_state_mirroring: SaveStateMirroring::None, + save_state_playback: PlaybackSlot::S1, sdi_state: Direction::empty(), sdi_strength: SdiFrequency::None, shield_state: Shield::None, @@ -169,14 +171,13 @@ pub static DEFAULTS_MENU: TrainingModpackMenu = TrainingModpackMenu { footstool_override: Action::empty(), landing_override: Action::empty(), trump_override: Action::empty(), - save_state_playback: OnOff::Off, recording_slot: RecordSlot::S1, - playback_slot: PlaybackSlot::S1, - playback_mash: OnOff::On, - record_trigger: RecordTrigger::None, //Command? recording_frames: RecordingFrames::F150, + record_trigger: RecordTrigger::None, + playback_button_combination: PlaybackSlot::S1, hitstun_playback: HitstunPlayback::Hitstun, - // TODO: alphabetize + playback_mash: OnOff::On, + playback_loop: OnOff::Off, }; pub static mut MENU: TrainingModpackMenu = DEFAULTS_MENU; @@ -698,6 +699,13 @@ pub unsafe fn ui_menu(menu: TrainingModpackMenu) -> UiMenu<'static> { false, &(menu.buff_state.bits()), ); + save_state_tab.add_submenu_with_toggles::( + "Save State Playback", + "save_state_playback", + "Save State Playback: Choose which slots to playback input recording upon loading a save state", + false, + &(menu.save_state_playback.bits() as u32), + ); overall_menu.tabs.push(save_state_tab); let mut misc_tab = Tab { @@ -768,34 +776,34 @@ pub unsafe fn ui_menu(menu: TrainingModpackMenu) -> UiMenu<'static> { true, &(menu.recording_frames as u32), ); - input_tab.add_submenu_with_toggles::( - "Save State Playback", - "save_state_playback", - "Save State Playback: Begin recorded input playback upon loading a save state", - true, - &(menu.save_state_playback as u32), - ); input_tab.add_submenu_with_toggles::( - "Playback Slots", - "playback_slot", - "Playback Slots: Choose which slots to choose between for playback when this action is triggered", + "Playback Button Combination", + "playback_button_combination", + "Playback Button Combination: Choose which slots to playback input recording upon pressing button combination (Default: Attack+Right Taunt)", false, - &(menu.playback_slot.bits() as u32), - ); - input_tab.add_submenu_with_toggles::( - "Mash Ends Playback", - "playback_mash", - "Mash Ends Playback: End input recording playback when a mash trigger occurs", - true, - &(menu.playback_mash as u32), + &(menu.playback_button_combination.bits() as u32), ); input_tab.add_submenu_with_toggles::( "Playback Hitstun Timing", "hitstun_playback", - "Playback Hitstun Timing: When to begin playing back inputs on hitstun mash trigger", + "Playback Hitstun Timing: When to begin playing back inputs when a hitstun mash trigger occurs", true, &(menu.hitstun_playback as u32), ); + input_tab.add_submenu_with_toggles::( + "Playback Mash Interrupt", + "playback_mash", + "Playback Mash Interrupt: End input playback when a mash trigger occurs", + true, + &(menu.playback_mash as u32), + ); + input_tab.add_submenu_with_toggles::( + "Playback Loop", + "playback_loop", + "Playback Loop: Repeat triggered input playbacks indefinitely", + true, + &(menu.playback_loop as u32), + ); overall_menu.tabs.push(input_tab); overall_menu diff --git a/training_mod_consts/src/options.rs b/training_mod_consts/src/options.rs index 1d3fa42..a47e0af 100644 --- a/training_mod_consts/src/options.rs +++ b/training_mod_consts/src/options.rs @@ -250,18 +250,15 @@ impl LedgeOption { } } - pub fn playback_slot(self) -> usize { - match self { + pub fn playback_slot(self) -> Option { + Some(match self { LedgeOption::PLAYBACK_1 => 0, LedgeOption::PLAYBACK_2 => 1, LedgeOption::PLAYBACK_3 => 2, LedgeOption::PLAYBACK_4 => 3, LedgeOption::PLAYBACK_5 => 4, - _ => panic!( - "Invalid LedgeOption playback slot: {}", - self.as_str().unwrap() - ), - } + _ => return None, + }) } pub const fn default() -> LedgeOption {