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:
parent
ba93011069
commit
3a40d46fca
3 changed files with 67 additions and 73 deletions
|
@ -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
|
||||||
|
|
|
@ -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),
|
||||||
);
|
);
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
Loading…
Reference in a new issue