1
0
Fork 0
mirror of https://github.com/jugeeya/UltimateTrainingModpack.git synced 2024-11-30 22:00:16 +00:00

Add input recording slots as menu options, randomize playback slots (#553)

This commit is contained in:
jugeeya 2023-08-02 10:27:50 -07:00 committed by GitHub
parent ba93011069
commit 3a40d46fca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 67 additions and 73 deletions

View file

@ -59,14 +59,14 @@ pub static mut RECORDED_LR: f32 = 1.0; // The direction the CPU was facing befor
pub static mut CURRENT_LR: f32 = 1.0; // The direction the CPU was facing at the beginning of this playback pub static mut CURRENT_LR: f32 = 1.0; // The direction the CPU was facing at the beginning of this playback
pub static mut STARTING_STATUS: i32 = 0; // The first status entered in the recording outside of waits pub static mut STARTING_STATUS: i32 = 0; // The first status entered in the recording outside of waits
// used to calculate if the input playback should begin before hitstun would normally end (hitstun cancel, monado art?) // used to calculate if the input playback should begin before hitstun would normally end (hitstun cancel, monado art?)
pub static mut _CURRENT_RECORD_SLOT: usize = 0; // Which slot is being used for recording right now? Want to make sure this is synced with menu choices, maybe just use menu instead pub static mut CURRENT_RECORD_SLOT: usize = 0; // Which slot is being used for recording right now? Want to make sure this is synced with menu choices, maybe just use menu instead
pub static mut CURRENT_PLAYBACK_SLOT: usize = 0; // Which slot is being used for playback right now? pub static mut CURRENT_PLAYBACK_SLOT: usize = 0; // Which slot is being used for playback right now?
lazy_static! { lazy_static! {
static ref P1_FINAL_MAPPING: Mutex<[MappedInputs; FINAL_RECORD_MAX]> = static ref P1_FINAL_MAPPING: Mutex<[[MappedInputs; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]> =
Mutex::new([{ Mutex::new([[{
MappedInputs::default() MappedInputs::default()
}; FINAL_RECORD_MAX]); }; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]);
static ref P1_STARTING_STATUSES: Mutex<[StartingStatus; TOTAL_SLOT_COUNT]> = static ref P1_STARTING_STATUSES: Mutex<[StartingStatus; TOTAL_SLOT_COUNT]> =
Mutex::new([{StartingStatus::Other}; TOTAL_SLOT_COUNT]); Mutex::new([{StartingStatus::Other}; TOTAL_SLOT_COUNT]);
} }
@ -105,10 +105,8 @@ unsafe fn should_mash_playback() {
should_playback = true; should_playback = true;
} }
// if we're in hitstun and want to wait till FAF to act, then we want to match our starting status to the correct transition term to see if we can hitstun cancel // if we're in hitstun and want to wait till FAF to act, then we want to match our starting status to the correct transition term to see if we can hitstun cancel
if MENU.hitstun_playback == HitstunPlayback::Hitstun { if MENU.hitstun_playback == HitstunPlayback::Hitstun && can_transition(cpu_module_accessor) {
if can_transition(cpu_module_accessor) { should_playback = true;
should_playback = true;
}
} }
} else if is_in_shieldstun(&mut *cpu_module_accessor) { } else if is_in_shieldstun(&mut *cpu_module_accessor) {
// TODO: Add instant shieldstun toggle for shield art out of electric hitstun? Idk that's so specific // TODO: Add instant shieldstun toggle for shield art out of electric hitstun? Idk that's so specific
@ -171,6 +169,8 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut BattleObjectModuleAcces
let fighter_kind = utility::get_kind(module_accessor); let fighter_kind = utility::get_kind(module_accessor);
let fighter_is_nana = fighter_kind == *FIGHTER_KIND_NANA; let fighter_is_nana = fighter_kind == *FIGHTER_KIND_NANA;
CURRENT_RECORD_SLOT = MENU.recording_slot.into_idx();
if entry_id_int == 0 && !fighter_is_nana { if entry_id_int == 0 && !fighter_is_nana {
// Attack + Dpad Right: Playback // Attack + Dpad Right: Playback
if ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_ATTACK) if ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_ATTACK)
@ -218,7 +218,7 @@ pub unsafe fn lockout_record() {
INPUT_RECORD = Pause; INPUT_RECORD = Pause;
INPUT_RECORD_FRAME = 0; INPUT_RECORD_FRAME = 0;
POSSESSION = Lockout; POSSESSION = Lockout;
P1_FINAL_MAPPING.lock().iter_mut().for_each(|mapped_input| { P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT].iter_mut().for_each(|mapped_input| {
*mapped_input = MappedInputs::default(); *mapped_input = MappedInputs::default();
}); });
LOCKOUT_FRAME = 30; // This needs to be this high or issues occur dropping shield - but does this cause problems when trying to record ledge? LOCKOUT_FRAME = 30; // This needs to be this high or issues occur dropping shield - but does this cause problems when trying to record ledge?
@ -233,7 +233,7 @@ pub unsafe fn _record() {
INPUT_RECORD = Record; INPUT_RECORD = Record;
POSSESSION = Cpu; POSSESSION = Cpu;
// Reset mappings to nothing, and then start recording. Likely want to reset in case we cut off recording early. // Reset mappings to nothing, and then start recording. Likely want to reset in case we cut off recording early.
P1_FINAL_MAPPING.lock().iter_mut().for_each(|mapped_input| { P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT].iter_mut().for_each(|mapped_input| {
*mapped_input = MappedInputs::default(); *mapped_input = MappedInputs::default();
}); });
INPUT_RECORD_FRAME = 0; INPUT_RECORD_FRAME = 0;
@ -246,6 +246,7 @@ pub unsafe fn playback() {
println!("Tried to playback during lockout!"); println!("Tried to playback during lockout!");
return; return;
} }
CURRENT_PLAYBACK_SLOT = MENU.playback_slot.get_random().into_idx().unwrap();
INPUT_RECORD = Playback; INPUT_RECORD = Playback;
POSSESSION = Player; POSSESSION = Player;
INPUT_RECORD_FRAME = 0; INPUT_RECORD_FRAME = 0;
@ -280,7 +281,7 @@ pub unsafe fn stop_playback() {
pub unsafe fn is_end_standby() -> bool { pub unsafe fn is_end_standby() -> bool {
// Returns whether we should be done with standby this frame (if any significant controller input has been made) // Returns whether we should be done with standby this frame (if any significant controller input has been made)
let first_frame_input = P1_FINAL_MAPPING.lock()[0]; let first_frame_input = P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT][0];
let clamped_lstick_x = ((first_frame_input.lstick_x as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0); let clamped_lstick_x = ((first_frame_input.lstick_x as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
let clamped_lstick_y = ((first_frame_input.lstick_y as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0); let clamped_lstick_y = ((first_frame_input.lstick_y as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
@ -322,7 +323,7 @@ unsafe fn handle_final_input_mapping(
STARTING_STATUS = StatusModule::status_kind(cpu_module_accessor); // TODO: Handle this based on slot later instead STARTING_STATUS = StatusModule::status_kind(cpu_module_accessor); // TODO: Handle this based on slot later instead
} }
P1_FINAL_MAPPING.lock()[INPUT_RECORD_FRAME] = *out; P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT][INPUT_RECORD_FRAME] = *out;
*out = MappedInputs::default(); // don't control player while recording *out = MappedInputs::default(); // don't control player while recording
println!("Stored Player Input! Frame: {}",INPUT_RECORD_FRAME); println!("Stored Player Input! Frame: {}",INPUT_RECORD_FRAME);
} }
@ -357,7 +358,12 @@ unsafe fn set_cpu_controls(p_data: *mut *mut u8) {
if INPUT_RECORD == Record || INPUT_RECORD == Playback { if INPUT_RECORD == Record || INPUT_RECORD == Playback {
let x_input_multiplier = RECORDED_LR * CURRENT_LR; // if we aren't facing the way we were when we initially recorded, we reverse horizontal inputs let x_input_multiplier = RECORDED_LR * CURRENT_LR; // if we aren't facing the way we were when we initially recorded, we reverse horizontal inputs
println!("Overriding Cpu Player: {}, Frame: {}, BUFFER_FRAME: {}, STARTING_STATUS: {}, INPUT_RECORD: {:#?}, POSSESSION: {:#?}", controller_no, INPUT_RECORD_FRAME, BUFFER_FRAME, STARTING_STATUS, INPUT_RECORD, POSSESSION); println!("Overriding Cpu Player: {}, Frame: {}, BUFFER_FRAME: {}, STARTING_STATUS: {}, INPUT_RECORD: {:#?}, POSSESSION: {:#?}", controller_no, INPUT_RECORD_FRAME, BUFFER_FRAME, STARTING_STATUS, INPUT_RECORD, POSSESSION);
let mut saved_mapped_inputs = P1_FINAL_MAPPING.lock()[INPUT_RECORD_FRAME];
let mut saved_mapped_inputs = P1_FINAL_MAPPING.lock()[if INPUT_RECORD == Record {
CURRENT_RECORD_SLOT
} else {
CURRENT_PLAYBACK_SLOT
}][INPUT_RECORD_FRAME];
if BUFFER_FRAME <= 3 && BUFFER_FRAME > 0 { if BUFFER_FRAME <= 3 && BUFFER_FRAME > 0 {
// Our option is already buffered, now we need to 0 out inputs to make sure our future controls act like flicks/presses instead of holding the button // Our option is already buffered, now we need to 0 out inputs to make sure our future controls act like flicks/presses instead of holding the button

View file

@ -73,8 +73,8 @@ pub struct TrainingModpackMenu {
pub landing_override: Action, pub landing_override: Action,
pub trump_override: Action, pub trump_override: Action,
pub save_state_playback: OnOff, pub save_state_playback: OnOff,
//pub recording_slot: RecordSlot, pub recording_slot: RecordSlot,
//pub playback_slot: PlaybackSlot, pub playback_slot: PlaybackSlot,
pub playback_mash: OnOff, pub playback_mash: OnOff,
pub record_trigger: RecordTrigger, pub record_trigger: RecordTrigger,
pub hitstun_playback: HitstunPlayback, pub hitstun_playback: HitstunPlayback,
@ -169,8 +169,8 @@ pub static DEFAULTS_MENU: TrainingModpackMenu = TrainingModpackMenu {
landing_override: Action::empty(), landing_override: Action::empty(),
trump_override: Action::empty(), trump_override: Action::empty(),
save_state_playback: OnOff::Off, save_state_playback: OnOff::Off,
//recording_slot: RecordSlot::S1, recording_slot: RecordSlot::S1,
//playback_slot: PlaybackSlot::S1, playback_slot: PlaybackSlot::S1,
playback_mash: OnOff::On, playback_mash: OnOff::On,
record_trigger: RecordTrigger::None, //Command? record_trigger: RecordTrigger::None, //Command?
hitstun_playback: HitstunPlayback::Hitstun, hitstun_playback: HitstunPlayback::Hitstun,
@ -745,33 +745,12 @@ pub unsafe fn ui_menu(menu: TrainingModpackMenu) -> UiMenu<'static> {
tab_title: "Input Recording", tab_title: "Input Recording",
tab_submenus: Vec::new(), tab_submenus: Vec::new(),
}; };
input_tab.add_submenu_with_toggles::<OnOff>( input_tab.add_submenu_with_toggles::<RecordSlot>(
"Save State Playback", "Recording Slot",
"save_state_playback", "recording_slot",
"Save State Playback: Begin recorded input playback upon loading a save state", "Recording Slot: Choose which slot to record into",
true, true,
&(menu.save_state_playback as u32), &(menu.recording_slot as u32),
);
// input_tab.add_submenu_with_toggles::<RecordSlot>(
// "Recording Slot",
// "recording_slot",
// "Recording Slot: Choose which slot to record into",
// true,
// &(menu.recording_slot as u32),
// );
// input_tab.add_submenu_with_toggles::<PlaybackSlot>( // TODO: This menu should really be a submenu inside Action menus, probably want to be able to customize for each action
// "Playback Slots",
// "playback_slot",
// "Playback Slots: Choose which slots to choose between for playback when this action is triggered",
// false,
// &(menu.playback_slot.bits() as u32),
// );
input_tab.add_submenu_with_toggles::<OnOff>(
"Mash Ends Playback",
"playback_mash",
"Mash Ends Playback: End input recording playback when a mash trigger occurs",
true,
&(menu.playback_mash as u32),
); );
input_tab.add_submenu_with_toggles::<RecordTrigger>( input_tab.add_submenu_with_toggles::<RecordTrigger>(
"Recording Trigger", "Recording Trigger",
@ -780,10 +759,31 @@ pub unsafe fn ui_menu(menu: TrainingModpackMenu) -> UiMenu<'static> {
true, true,
&(menu.record_trigger as u32), &(menu.record_trigger as u32),
); );
input_tab.add_submenu_with_toggles::<OnOff>(
"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::<PlaybackSlot>( // TODO: This menu should really be a submenu inside Action menus, probably want to be able to customize for each action
"Playback Slots",
"playback_slot",
"Playback Slots: Choose which slots to choose between for playback when this action is triggered",
false,
&(menu.playback_slot.bits() as u32),
);
input_tab.add_submenu_with_toggles::<OnOff>(
"Mash Ends Playback",
"playback_mash",
"Mash Ends Playback: End input recording playback when a mash trigger occurs",
true,
&(menu.playback_mash as u32),
);
input_tab.add_submenu_with_toggles::<HitstunPlayback>( input_tab.add_submenu_with_toggles::<HitstunPlayback>(
"Hitstun Playback Trigger", "Playback Hitstun Timing",
"hitstun_playback", "hitstun_playback",
"Hitstun Playback Trigger: When to begin playing back inputs on hitstun mash trigger", "Playback Hitstun Timing: When to begin playing back inputs on hitstun mash trigger",
true, true,
&(menu.hitstun_playback as u32), &(menu.hitstun_playback as u32),
); );

View file

@ -1168,20 +1168,14 @@ pub enum RecordSlot {
} }
impl RecordSlot { impl RecordSlot {
pub fn into_int(self) -> Option<u32> { // TODO: Do I need an into_int here? pub fn into_idx(self) -> usize {
#[cfg(feature = "smash")] match self {
{ RecordSlot::S1 => 0,
Some(match self { RecordSlot::S2 => 1,
RecordSlot::S1 => 1, RecordSlot::S3 => 2,
RecordSlot::S2 => 2, RecordSlot::S4 => 3,
RecordSlot::S3 => 3, RecordSlot::S5 => 4,
RecordSlot::S4 => 4,
RecordSlot::S5 => 5,
})
} }
#[cfg(not(feature = "smash"))]
None
} }
pub fn as_str(self) -> Option<&'static str> { pub fn as_str(self) -> Option<&'static str> {
@ -1220,21 +1214,15 @@ bitflags! {
} }
impl PlaybackSlot { impl PlaybackSlot {
pub fn into_int(self) -> Option<u32> { pub fn into_idx(self) -> Option<usize> {
#[cfg(feature = "smash")] Some(match self {
{ PlaybackSlot::S1 => 0,
Some(match self { PlaybackSlot::S2 => 1,
PlaybackSlot::S1 => 1, PlaybackSlot::S3 => 2,
PlaybackSlot::S2 => 2, PlaybackSlot::S4 => 3,
PlaybackSlot::S3 => 3, PlaybackSlot::S5 => 4,
PlaybackSlot::S4 => 4, _ => return None,
PlaybackSlot::S5 => 5, })
_ => return None,
})
}
#[cfg(not(feature = "smash"))]
None
} }
pub fn as_str(self) -> Option<&'static str> { pub fn as_str(self) -> Option<&'static str> {