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

Configurable Recording Frames (#570)

* Playback Slots for Actions and Ledge Options

* Inital attempt

* Fix playback slot

* Fix menu option, probably

* Fix reading from menu option
This commit is contained in:
jugeeya 2023-08-06 17:07:01 -07:00 committed by GitHub
parent fe8ae6f39f
commit fb9d1648d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 88 additions and 22 deletions

View file

@ -48,9 +48,8 @@ use PossessionState::*;
const STICK_NEUTRAL: f32 = 0.2; const STICK_NEUTRAL: f32 = 0.2;
const STICK_CLAMP_MULTIPLIER: f32 = 1.0 / 120.0; // 120.0 = CLAMP_MAX const STICK_CLAMP_MULTIPLIER: f32 = 1.0 / 120.0; // 120.0 = CLAMP_MAX
const FINAL_RECORD_MAX: usize = 150; // Maximum length for input recording sequences (capacity) const FINAL_RECORD_MAX: usize = 600; // Maximum length for input recording sequences (capacity)
const TOTAL_SLOT_COUNT: usize = 5; // Total number of input recording slots const TOTAL_SLOT_COUNT: usize = 5; // Total number of input recording slots
pub static mut FINAL_RECORD_FRAME: usize = FINAL_RECORD_MAX; // The final frame to play back of the currently recorded sequence (size)
pub static mut INPUT_RECORD: InputRecordState = InputRecordState::None; pub static mut INPUT_RECORD: InputRecordState = InputRecordState::None;
pub static mut INPUT_RECORD_FRAME: usize = 0; pub static mut INPUT_RECORD_FRAME: usize = 0;
pub static mut POSSESSION: PossessionState = PossessionState::Player; pub static mut POSSESSION: PossessionState = PossessionState::Player;
@ -62,10 +61,13 @@ pub static mut STARTING_STATUS: i32 = 0; // The first status entered in the reco
// 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?
pub static mut CURRENT_FRAME_LENGTH: usize = 60;
lazy_static! { lazy_static! {
static ref P1_FINAL_MAPPING: Mutex<[[MappedInputs; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]> = static ref P1_FINAL_MAPPING: Mutex<[[MappedInputs; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]> =
Mutex::new([[{ MappedInputs::default() }; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]); Mutex::new([[{ MappedInputs::default() }; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]);
static ref P1_FRAME_LENGTH_MAPPING: Mutex<[usize; TOTAL_SLOT_COUNT]> =
Mutex::new([60usize; 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]);
} }
@ -182,23 +184,19 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut BattleObjectModuleAcces
module_accessor, module_accessor,
button_config::ButtonCombo::InputPlayback, button_config::ButtonCombo::InputPlayback,
) { ) {
//crate::common::raygun_printer::print_string(&mut *module_accessor, "PLAYBACK");
playback(MENU.playback_slot.get_random().into_idx().unwrap_or(0)); playback(MENU.playback_slot.get_random().into_idx().unwrap_or(0));
println!("Playback Command Received!"); //debug
} }
// Attack + Dpad Left: Record // Attack + Dpad Left: Record
else if button_config::combo_passes_exclusive( else if button_config::combo_passes_exclusive(
module_accessor, module_accessor,
button_config::ButtonCombo::InputRecord, button_config::ButtonCombo::InputRecord,
) { ) {
//crate::common::raygun_printer::print_string(&mut *module_accessor, "RECORDING");
lockout_record(); lockout_record();
println!("Record Command Received!"); //debug
} }
// may need to move this to another func // may need to move this to another func
if (INPUT_RECORD == Record || INPUT_RECORD == Playback) if (INPUT_RECORD == Record || INPUT_RECORD == Playback)
&& INPUT_RECORD_FRAME >= FINAL_RECORD_FRAME - 1 && INPUT_RECORD_FRAME >= CURRENT_FRAME_LENGTH - 1
{ {
INPUT_RECORD = None; INPUT_RECORD = None;
POSSESSION = Player; POSSESSION = Player;
@ -282,6 +280,8 @@ pub unsafe fn lockout_record() {
.for_each(|mapped_input| { .for_each(|mapped_input| {
*mapped_input = MappedInputs::default(); *mapped_input = MappedInputs::default();
}); });
CURRENT_FRAME_LENGTH = MENU.recording_frames.into_frames();
P1_FRAME_LENGTH_MAPPING.lock()[CURRENT_RECORD_SLOT] = CURRENT_FRAME_LENGTH;
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?
BUFFER_FRAME = 0; BUFFER_FRAME = 0;
// Store the direction the CPU is facing when we initially record, so we can turn their inputs around if needed // Store the direction the CPU is facing when we initially record, so we can turn their inputs around if needed
@ -290,20 +290,6 @@ pub unsafe fn lockout_record() {
CURRENT_LR = RECORDED_LR; CURRENT_LR = RECORDED_LR;
} }
pub unsafe fn _record() {
INPUT_RECORD = Record;
POSSESSION = Cpu;
// Reset mappings to nothing, and then start recording. Likely want to reset in case we cut off recording early.
P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT]
.iter_mut()
.for_each(|mapped_input| {
*mapped_input = MappedInputs::default();
});
INPUT_RECORD_FRAME = 0;
LOCKOUT_FRAME = 0;
BUFFER_FRAME = 0;
}
pub unsafe fn playback(slot: usize) { pub unsafe fn playback(slot: usize) {
if INPUT_RECORD == Pause { if INPUT_RECORD == Pause {
println!("Tried to playback during lockout!"); println!("Tried to playback during lockout!");
@ -328,6 +314,7 @@ pub unsafe fn playback(slot: usize) {
); );
CURRENT_PLAYBACK_SLOT = slot; CURRENT_PLAYBACK_SLOT = slot;
CURRENT_FRAME_LENGTH = P1_FRAME_LENGTH_MAPPING.lock()[CURRENT_PLAYBACK_SLOT];
INPUT_RECORD = Playback; INPUT_RECORD = Playback;
POSSESSION = Player; POSSESSION = Player;
INPUT_RECORD_FRAME = 0; INPUT_RECORD_FRAME = 0;
@ -360,6 +347,7 @@ pub unsafe fn playback_ledge(slot: usize) {
); );
CURRENT_PLAYBACK_SLOT = slot; CURRENT_PLAYBACK_SLOT = slot;
CURRENT_FRAME_LENGTH = P1_FRAME_LENGTH_MAPPING.lock()[CURRENT_PLAYBACK_SLOT];
INPUT_RECORD = Playback; INPUT_RECORD = Playback;
POSSESSION = Player; POSSESSION = Player;
@ -524,7 +512,7 @@ unsafe fn set_cpu_controls(p_data: *mut *mut u8) {
// When buffering an option, we keep inputting the first frame of input during the buffer window // When buffering an option, we keep inputting the first frame of input during the buffer window
if BUFFER_FRAME > 0 { if BUFFER_FRAME > 0 {
BUFFER_FRAME -= 1; BUFFER_FRAME -= 1;
} else if INPUT_RECORD_FRAME < FINAL_RECORD_FRAME - 1 && POSSESSION != Standby { } else if INPUT_RECORD_FRAME < CURRENT_FRAME_LENGTH - 1 && POSSESSION != Standby {
INPUT_RECORD_FRAME += 1; INPUT_RECORD_FRAME += 1;
} }
} }

View file

@ -77,6 +77,7 @@ pub struct TrainingModpackMenu {
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 recording_frames: RecordingFrames,
pub hitstun_playback: HitstunPlayback, pub hitstun_playback: HitstunPlayback,
} }
@ -173,6 +174,7 @@ pub static DEFAULTS_MENU: TrainingModpackMenu = TrainingModpackMenu {
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?
recording_frames: RecordingFrames::F150,
hitstun_playback: HitstunPlayback::Hitstun, hitstun_playback: HitstunPlayback::Hitstun,
// TODO: alphabetize // TODO: alphabetize
}; };
@ -759,6 +761,13 @@ 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::<RecordingFrames>(
"Recording Frames",
"recording_frames",
"Recording Frames: Number of frames to record for in the current slot",
true,
&(menu.recording_frames as u32),
);
input_tab.add_submenu_with_toggles::<OnOff>( input_tab.add_submenu_with_toggles::<OnOff>(
"Save State Playback", "Save State Playback",
"save_state_playback", "save_state_playback",

View file

@ -1410,3 +1410,72 @@ impl ToggleTrait for HitstunPlayback {
HitstunPlayback::iter().map(|i| i as u32).collect() HitstunPlayback::iter().map(|i| i as u32).collect()
} }
} }
#[repr(u32)]
#[derive(
Debug, Clone, Copy, PartialEq, FromPrimitive, EnumIter, Serialize_repr, Deserialize_repr,
)]
pub enum RecordingFrames {
F60 = 0x1,
F90 = 0x2,
F120 = 0x4,
F150 = 0x8,
F180 = 0x10,
F210 = 0x20,
F240 = 0x40,
F270 = 0x80,
F300 = 0x100,
F330 = 0x200,
F360 = 0x400,
F390 = 0x800,
F420 = 0x1000,
F450 = 0x2000,
F480 = 0x4000,
F510 = 0x8000,
F540 = 0x10000,
F570 = 0x20000,
F600 = 0x40000,
}
impl RecordingFrames {
pub fn as_str(self) -> Option<&'static str> {
use RecordingFrames::*;
Some(match self {
F60 => "60",
F90 => "90",
F120 => "120",
F150 => "150",
F180 => "180",
F210 => "210",
F240 => "240",
F270 => "270",
F300 => "300",
F330 => "330",
F360 => "360",
F390 => "390",
F420 => "420",
F450 => "450",
F480 => "480",
F510 => "510",
F540 => "540",
F570 => "570",
F600 => "600",
})
}
pub fn into_frames(self) -> usize {
(log_2(self as u32) as usize * 30) + 60
}
}
impl ToggleTrait for RecordingFrames {
fn to_toggle_strs() -> Vec<&'static str> {
RecordingFrames::iter()
.map(|i| i.as_str().unwrap_or(""))
.collect()
}
fn to_toggle_vals() -> Vec<u32> {
RecordingFrames::iter().map(|i| i as u32).collect()
}
}