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:
parent
fe8ae6f39f
commit
fb9d1648d4
3 changed files with 88 additions and 22 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue