mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2025-03-26 08:12:42 +00:00
input_record.rs
This commit is contained in:
parent
301916024d
commit
a685a446d7
2 changed files with 143 additions and 114 deletions
src
|
@ -299,7 +299,7 @@ pub struct MappedInputs {
|
|||
}
|
||||
|
||||
impl MappedInputs {
|
||||
pub fn empty() -> MappedInputs {
|
||||
pub const fn empty() -> MappedInputs {
|
||||
MappedInputs {
|
||||
buttons: Buttons::empty(),
|
||||
lstick_x: 0,
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
use std::cmp::Ordering;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::Mutex;
|
||||
use skyline::nn::ui2d::ResColor;
|
||||
use smash::app::{lua_bind::*, utility, BattleObjectModuleAccessor};
|
||||
use smash::lib::lua_const::*;
|
||||
|
@ -22,7 +20,7 @@ use crate::{error, warn};
|
|||
|
||||
use training_mod_sync::*;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum InputRecordState {
|
||||
None,
|
||||
Pause,
|
||||
|
@ -30,7 +28,7 @@ pub enum InputRecordState {
|
|||
Playback,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum PossessionState {
|
||||
Player,
|
||||
Cpu,
|
||||
|
@ -58,30 +56,26 @@ pub const STICK_NEUTRAL: f32 = 0.2;
|
|||
pub const STICK_CLAMP_MULTIPLIER: f32 = 1.0 / 120.0; // 120.0 = CLAMP_MAX
|
||||
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
|
||||
pub static mut INPUT_RECORD: InputRecordState = InputRecordState::None;
|
||||
pub static mut INPUT_RECORD_FRAME: usize = 0;
|
||||
pub static mut POSSESSION: PossessionState = PossessionState::Player;
|
||||
pub static mut LOCKOUT_FRAME: usize = 0;
|
||||
pub static mut BUFFER_FRAME: usize = 0;
|
||||
pub static mut RECORDED_LR: f32 = 1.0; // The direction the CPU was facing before the current recording was recorded
|
||||
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
|
||||
// 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_PLAYBACK_SLOT: usize = 0; // Which slot is being used for playback right now?
|
||||
pub static mut CURRENT_FRAME_LENGTH: usize = 60;
|
||||
|
||||
lazy_static! {
|
||||
static ref P1_FINAL_MAPPING: Mutex<[[MappedInputs; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]> =
|
||||
Mutex::new([[{ MappedInputs::empty() }; 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]> =
|
||||
Mutex::new([{ StartingStatus::Other }; TOTAL_SLOT_COUNT]);
|
||||
}
|
||||
pub static INPUT_RECORD: RwLock<InputRecordState> = RwLock::new(InputRecordState::None);
|
||||
pub static INPUT_RECORD_FRAME: RwLock<usize> = RwLock::new(0);
|
||||
pub static POSSESSION: RwLock<PossessionState> = RwLock::new(PossessionState::Player);
|
||||
pub static LOCKOUT_FRAME: RwLock<usize> = RwLock::new(0);
|
||||
pub static BUFFER_FRAME: RwLock<usize> = RwLock::new(0);
|
||||
pub static RECORDED_LR: RwLock<f32> = RwLock::new(1.0); // The direction the CPU was facing before the current recording was recorded
|
||||
pub static CURRENT_LR: RwLock<f32> = RwLock::new(1.0); // The direction the CPU was facing at the beginning of this playback
|
||||
pub static STARTING_STATUS: RwLock<i32> = RwLock::new(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?)
|
||||
pub static CURRENT_RECORD_SLOT: RwLock<usize> = RwLock::new(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 CURRENT_PLAYBACK_SLOT: RwLock<usize> = RwLock::new(0); // Which slot is being used for playback right now?
|
||||
pub static CURRENT_FRAME_LENGTH: RwLock<usize> = RwLock::new(60);
|
||||
pub static P1_FINAL_MAPPING: RwLock<[[MappedInputs; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]> =
|
||||
RwLock::new([[{ MappedInputs::empty() }; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]);
|
||||
pub static P1_FRAME_LENGTH_MAPPING: RwLock<[usize; TOTAL_SLOT_COUNT]> =
|
||||
RwLock::new([60; TOTAL_SLOT_COUNT]);
|
||||
// pub static P1_STARTING_STATUSES: RwLock<[StartingStatus; TOTAL_SLOT_COUNT]> = RwLock::new([StartingStatus::Other; TOTAL_SLOT_COUNT]); // TODO! Not used currently
|
||||
|
||||
unsafe fn can_transition(module_accessor: *mut BattleObjectModuleAccessor) -> bool {
|
||||
let transition_term = into_transition_term(into_starting_status(STARTING_STATUS));
|
||||
let transition_term = into_transition_term(into_starting_status(read_rwlock(&STARTING_STATUS)));
|
||||
WorkModule::is_enable_transition_term(module_accessor, transition_term)
|
||||
}
|
||||
|
||||
|
@ -196,7 +190,10 @@ unsafe fn handle_recording_for_fighter(module_accessor: &mut BattleObjectModuleA
|
|||
let fighter_kind = utility::get_kind(module_accessor);
|
||||
let fighter_is_nana = fighter_kind == *FIGHTER_KIND_NANA;
|
||||
|
||||
CURRENT_RECORD_SLOT = get(&MENU).recording_slot.into_idx().unwrap_or(0);
|
||||
assign_rwlock(
|
||||
&CURRENT_RECORD_SLOT,
|
||||
get(&MENU).recording_slot.into_idx().unwrap_or(0),
|
||||
);
|
||||
|
||||
if entry_id_int == 0 && !fighter_is_nana {
|
||||
if button_config::combo_passes(button_config::ButtonCombo::InputPlayback) {
|
||||
|
@ -206,44 +203,51 @@ unsafe fn handle_recording_for_fighter(module_accessor: &mut BattleObjectModuleA
|
|||
{
|
||||
lockout_record();
|
||||
}
|
||||
if INPUT_RECORD == None {
|
||||
let input_record = read_rwlock(&INPUT_RECORD);
|
||||
if input_record == None {
|
||||
clear_notifications_except("Input Recording");
|
||||
}
|
||||
// Handle recording end
|
||||
if (INPUT_RECORD == Record || INPUT_RECORD == Playback)
|
||||
&& INPUT_RECORD_FRAME >= CURRENT_FRAME_LENGTH - 1
|
||||
let mut input_record_frame = lock_write_rwlock(&INPUT_RECORD_FRAME);
|
||||
if (input_record == Record || input_record == Playback)
|
||||
&& *input_record_frame >= read_rwlock(&CURRENT_FRAME_LENGTH) - 1
|
||||
{
|
||||
POSSESSION = Player;
|
||||
assign_rwlock(&POSSESSION, Player);
|
||||
if mash::is_playback_queued() {
|
||||
mash::reset();
|
||||
}
|
||||
|
||||
// If we need to crop the recording for neutral input
|
||||
// INPUT_RECORD_FRAME must be > 0 to prevent bounding errors
|
||||
if INPUT_RECORD == Record
|
||||
if input_record == Record
|
||||
&& get(&MENU).recording_crop == OnOff::ON
|
||||
&& INPUT_RECORD_FRAME > 0
|
||||
&& *input_record_frame > 0
|
||||
{
|
||||
while INPUT_RECORD_FRAME > 0 && is_input_neutral(INPUT_RECORD_FRAME - 1) {
|
||||
while *input_record_frame > 0 && is_input_neutral(*input_record_frame - 1) {
|
||||
// Discard frames at the end of the recording until the last frame with input
|
||||
INPUT_RECORD_FRAME -= 1;
|
||||
*input_record_frame -= 1;
|
||||
}
|
||||
CURRENT_FRAME_LENGTH = INPUT_RECORD_FRAME;
|
||||
P1_FRAME_LENGTH_MAPPING.lock()[CURRENT_RECORD_SLOT] = CURRENT_FRAME_LENGTH;
|
||||
assign_rwlock(&CURRENT_FRAME_LENGTH, *input_record_frame);
|
||||
let mut p1_frame_length_mapping = lock_write_rwlock(&P1_FRAME_LENGTH_MAPPING);
|
||||
(*p1_frame_length_mapping)[read_rwlock(&CURRENT_RECORD_SLOT)] = *input_record_frame;
|
||||
drop(p1_frame_length_mapping);
|
||||
}
|
||||
|
||||
INPUT_RECORD_FRAME = 0;
|
||||
*input_record_frame = 0;
|
||||
|
||||
if get(&MENU).playback_loop == OnOff::ON && INPUT_RECORD == Playback {
|
||||
playback(Some(CURRENT_PLAYBACK_SLOT));
|
||||
if get(&MENU).playback_loop == OnOff::ON && input_record == Playback {
|
||||
let playback_slot = read_rwlock(&CURRENT_PLAYBACK_SLOT);
|
||||
playback(Some(playback_slot));
|
||||
} else {
|
||||
INPUT_RECORD = None;
|
||||
assign_rwlock(&INPUT_RECORD, None);
|
||||
}
|
||||
}
|
||||
drop(input_record_frame);
|
||||
}
|
||||
|
||||
// Handle Possession Coloring
|
||||
if entry_id_int == 1 && POSSESSION == Lockout {
|
||||
let possession = read_rwlock(&POSSESSION);
|
||||
if entry_id_int == 1 && possession == Lockout {
|
||||
clear_notifications_except("Input Recording");
|
||||
color_notification(
|
||||
"Input Recording".to_string(),
|
||||
|
@ -263,7 +267,7 @@ unsafe fn handle_recording_for_fighter(module_accessor: &mut BattleObjectModuleA
|
|||
1.0,
|
||||
*MODEL_COLOR_TYPE_COLOR_BLEND,
|
||||
);
|
||||
} else if entry_id_int == 1 && POSSESSION == Standby {
|
||||
} else if entry_id_int == 1 && possession == Standby {
|
||||
clear_notifications_except("Input Recording");
|
||||
color_notification(
|
||||
"Input Recording".to_string(),
|
||||
|
@ -283,7 +287,7 @@ unsafe fn handle_recording_for_fighter(module_accessor: &mut BattleObjectModuleA
|
|||
1.0,
|
||||
*MODEL_COLOR_TYPE_COLOR_BLEND,
|
||||
);
|
||||
} else if entry_id_int == 1 && POSSESSION == Cpu {
|
||||
} else if entry_id_int == 1 && possession == Cpu {
|
||||
clear_notifications_except("Input Recording");
|
||||
color_notification(
|
||||
"Input Recording".to_string(),
|
||||
|
@ -303,15 +307,17 @@ unsafe fn handle_recording_for_fighter(module_accessor: &mut BattleObjectModuleA
|
|||
0.0,
|
||||
*MODEL_COLOR_TYPE_COLOR_BLEND,
|
||||
);
|
||||
} else if entry_id_int == 1 && POSSESSION == Player && INPUT_RECORD == Playback {
|
||||
} else if entry_id_int == 1 && possession == Player && read_rwlock(&INPUT_RECORD) == Playback {
|
||||
// Need to re-read INPUT_RECORD instead of using the local variable because we might have assigned to it early
|
||||
// Displays if the inputs from the current frame were a result of playback
|
||||
if INPUT_RECORD_FRAME == 0 || INPUT_RECORD_FRAME == 1 {
|
||||
let input_record_frame = read_rwlock(&INPUT_RECORD_FRAME);
|
||||
if input_record_frame == 0 || input_record_frame == 1 {
|
||||
// can be either, seems like a thread issue
|
||||
clear_notifications_except("Input Recording");
|
||||
color_notification(
|
||||
"Input Recording".to_string(),
|
||||
"Playback".to_owned(),
|
||||
CURRENT_FRAME_LENGTH as u32,
|
||||
read_rwlock(&CURRENT_FRAME_LENGTH) as u32,
|
||||
ResColor {
|
||||
r: 0,
|
||||
g: 0,
|
||||
|
@ -324,27 +330,29 @@ unsafe fn handle_recording_for_fighter(module_accessor: &mut BattleObjectModuleA
|
|||
}
|
||||
|
||||
pub unsafe fn lockout_record() {
|
||||
INPUT_RECORD = Pause;
|
||||
INPUT_RECORD_FRAME = 0;
|
||||
POSSESSION = Lockout;
|
||||
P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT]
|
||||
.iter_mut()
|
||||
.for_each(|mapped_input| {
|
||||
*mapped_input = MappedInputs::empty();
|
||||
});
|
||||
CURRENT_FRAME_LENGTH = get(&MENU).recording_duration.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?
|
||||
BUFFER_FRAME = 0;
|
||||
// Store the direction the CPU is facing when we initially record, so we can turn their inputs around if needed
|
||||
let cpu_module_accessor = get_module_accessor(FighterId::CPU);
|
||||
RECORDED_LR = PostureModule::lr(cpu_module_accessor);
|
||||
CURRENT_LR = RECORDED_LR;
|
||||
let recording_duration = get(&MENU).recording_duration.into_frames();
|
||||
let current_record_slot = read_rwlock(&CURRENT_RECORD_SLOT);
|
||||
let mut p1_final_mapping = lock_write_rwlock(&P1_FINAL_MAPPING);
|
||||
(*p1_final_mapping)[current_record_slot] = [{ MappedInputs::empty() }; FINAL_RECORD_MAX];
|
||||
drop(p1_final_mapping);
|
||||
let mut p1_frame_length_mapping = lock_write_rwlock(&P1_FRAME_LENGTH_MAPPING);
|
||||
(*p1_frame_length_mapping)[current_record_slot] = recording_duration;
|
||||
drop(p1_frame_length_mapping);
|
||||
assign_rwlock(&CURRENT_FRAME_LENGTH, recording_duration);
|
||||
assign_rwlock(&INPUT_RECORD, Pause);
|
||||
assign_rwlock(&INPUT_RECORD_FRAME, 0);
|
||||
assign_rwlock(&POSSESSION, Lockout);
|
||||
assign_rwlock(&LOCKOUT_FRAME, 30); // This needs to be this high or issues occur dropping shield - but does this cause problems when trying to record ledge?
|
||||
assign_rwlock(&BUFFER_FRAME, 0);
|
||||
// Store the direction the CPU is facing when we initially record, so we can turn their inputs around if needed
|
||||
assign_rwlock(&RECORDED_LR, PostureModule::lr(cpu_module_accessor));
|
||||
assign_rwlock(&CURRENT_LR, PostureModule::lr(cpu_module_accessor));
|
||||
}
|
||||
|
||||
// Returns whether we did playback
|
||||
pub unsafe fn playback(slot: Option<usize>) -> bool {
|
||||
if INPUT_RECORD == Pause {
|
||||
if read_rwlock(&INPUT_RECORD) == Pause {
|
||||
warn!("Tried to playback during lockout!");
|
||||
return false;
|
||||
}
|
||||
|
@ -353,15 +361,15 @@ pub unsafe fn playback(slot: Option<usize>) -> bool {
|
|||
return false;
|
||||
}
|
||||
let slot = slot.unwrap();
|
||||
|
||||
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 = 0;
|
||||
let cpu_module_accessor = get_module_accessor(FighterId::CPU);
|
||||
CURRENT_LR = PostureModule::lr(cpu_module_accessor);
|
||||
let frame_length = read_rwlock(&P1_FRAME_LENGTH_MAPPING)[slot];
|
||||
assign_rwlock(&CURRENT_FRAME_LENGTH, frame_length);
|
||||
assign_rwlock(&CURRENT_PLAYBACK_SLOT, slot);
|
||||
assign_rwlock(&INPUT_RECORD, Playback);
|
||||
assign_rwlock(&POSSESSION, Player);
|
||||
assign_rwlock(&INPUT_RECORD_FRAME, 0);
|
||||
assign_rwlock(&BUFFER_FRAME, 0);
|
||||
assign_rwlock(&CURRENT_LR, PostureModule::lr(cpu_module_accessor));
|
||||
|
||||
true
|
||||
}
|
||||
|
@ -369,26 +377,28 @@ pub unsafe fn playback(slot: Option<usize>) -> bool {
|
|||
pub unsafe fn playback_ledge(slot: Option<usize>) {
|
||||
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 mut buffer_frame = lock_write_rwlock(&BUFFER_FRAME);
|
||||
*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);
|
||||
if status_kind == *FIGHTER_STATUS_KIND_CLIFF_CATCH {
|
||||
BUFFER_FRAME -= 1;
|
||||
*buffer_frame -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn stop_playback() {
|
||||
INPUT_RECORD = None;
|
||||
INPUT_RECORD_FRAME = 0;
|
||||
POSSESSION = Player;
|
||||
assign_rwlock(&INPUT_RECORD, None);
|
||||
assign_rwlock(&INPUT_RECORD_FRAME, 0);
|
||||
assign_rwlock(&POSSESSION, Player);
|
||||
}
|
||||
|
||||
pub unsafe fn is_input_neutral(input_frame: usize) -> bool {
|
||||
// Returns whether we should be done with standby this frame (if any significant controller input has been made)
|
||||
let frame_input = P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT][input_frame];
|
||||
let current_record_slot = read_rwlock(&CURRENT_RECORD_SLOT);
|
||||
let frame_input = read_rwlock(&P1_FINAL_MAPPING)[current_record_slot][input_frame];
|
||||
|
||||
let clamped_lstick_x =
|
||||
((frame_input.lstick_x as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
|
||||
|
@ -410,31 +420,40 @@ pub unsafe fn is_input_neutral(input_frame: usize) -> bool {
|
|||
}
|
||||
|
||||
pub unsafe fn handle_final_input_mapping(player_idx: i32, out: *mut MappedInputs) {
|
||||
let mut possession = lock_write_rwlock(&POSSESSION);
|
||||
if player_idx == 0 {
|
||||
// if player 1
|
||||
if INPUT_RECORD == Record {
|
||||
if read_rwlock(&INPUT_RECORD) == Record {
|
||||
let mut input_record_frame = lock_write_rwlock(&INPUT_RECORD_FRAME);
|
||||
// check for standby before starting action:
|
||||
if POSSESSION == Standby && !is_input_neutral(0) {
|
||||
if *possession == Standby && !is_input_neutral(0) {
|
||||
// last input made us start an action, so start recording and end standby.
|
||||
INPUT_RECORD_FRAME += 1;
|
||||
POSSESSION = Cpu;
|
||||
*input_record_frame += 1;
|
||||
*possession = Cpu;
|
||||
}
|
||||
|
||||
if INPUT_RECORD_FRAME == 1 {
|
||||
if *input_record_frame == 1 {
|
||||
// We're on the second frame of recording, grabbing the status should give us the status that resulted from the first frame of input
|
||||
// We'll want to save this status so that we use the correct TRANSITION TERM for hitstun cancelling out of damage fly
|
||||
let cpu_module_accessor = get_module_accessor(FighterId::CPU);
|
||||
P1_STARTING_STATUSES.lock()[CURRENT_PLAYBACK_SLOT] =
|
||||
into_starting_status(StatusModule::status_kind(cpu_module_accessor));
|
||||
STARTING_STATUS = StatusModule::status_kind(cpu_module_accessor);
|
||||
assign_rwlock(
|
||||
&STARTING_STATUS,
|
||||
StatusModule::status_kind(cpu_module_accessor),
|
||||
);
|
||||
// TODO: Handle this based on slot later instead
|
||||
// let p1_starting_statuses = lock_write_rwlock(&P1_STARTING_STATUSES);
|
||||
// (*p1_starting_statuses)[read_rwlock(&CURRENT_PLAYBACK_SLOT)] =
|
||||
// into_starting_status(StatusModule::status_kind(cpu_module_accessor));
|
||||
// drop(p1_starting_statuses);
|
||||
}
|
||||
|
||||
P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT][INPUT_RECORD_FRAME] = *out;
|
||||
let mut p1_final_mapping = lock_write_rwlock(&P1_FINAL_MAPPING);
|
||||
let current_record_slot = read_rwlock(&CURRENT_RECORD_SLOT);
|
||||
(*p1_final_mapping)[current_record_slot][*input_record_frame] = *out;
|
||||
drop(p1_final_mapping);
|
||||
*out = MappedInputs::empty(); // don't control player while recording
|
||||
}
|
||||
// Don't allow for player input during Lockout
|
||||
if POSSESSION == Lockout {
|
||||
if *possession == Lockout {
|
||||
*out = MappedInputs::empty();
|
||||
}
|
||||
}
|
||||
|
@ -454,7 +473,7 @@ unsafe fn set_cpu_controls(p_data: *mut *mut u8) {
|
|||
// TODO: Setup STARTING_STATUS based on current playback slot here
|
||||
|
||||
// This check prevents out of shield if mash exiting is on
|
||||
if INPUT_RECORD == None {
|
||||
if read_rwlock(&INPUT_RECORD) == None {
|
||||
should_mash_playback();
|
||||
}
|
||||
|
||||
|
@ -466,20 +485,22 @@ unsafe fn set_cpu_controls(p_data: *mut *mut u8) {
|
|||
}
|
||||
let cpu_module_accessor = cpu_module_accessor.unwrap();
|
||||
|
||||
if INPUT_RECORD == Pause {
|
||||
match LOCKOUT_FRAME.cmp(&0) {
|
||||
Ordering::Greater => LOCKOUT_FRAME -= 1,
|
||||
if read_rwlock(&INPUT_RECORD) == Pause {
|
||||
let lockout_frame = read_rwlock(&LOCKOUT_FRAME);
|
||||
match lockout_frame.cmp(&0) {
|
||||
Ordering::Greater => assign_rwlock(&LOCKOUT_FRAME, lockout_frame - 1),
|
||||
Ordering::Equal => {
|
||||
INPUT_RECORD = Record;
|
||||
POSSESSION = Standby;
|
||||
assign_rwlock(&INPUT_RECORD, Record);
|
||||
assign_rwlock(&POSSESSION, Standby);
|
||||
}
|
||||
Ordering::Less => error!("LOCKOUT_FRAME OUT OF BOUNDS"),
|
||||
}
|
||||
}
|
||||
|
||||
if INPUT_RECORD == Record || INPUT_RECORD == Playback {
|
||||
let input_record = read_rwlock(&INPUT_RECORD);
|
||||
if input_record == Record || input_record == Playback {
|
||||
// if we aren't facing the way we were when we initially recorded, we reverse horizontal inputs
|
||||
let mut x_input_multiplier = RECORDED_LR * CURRENT_LR;
|
||||
let mut x_input_multiplier = read_rwlock(&RECORDED_LR) * read_rwlock(&CURRENT_LR);
|
||||
// Don't flip Shulk's dial inputs
|
||||
let fighter_kind = utility::get_kind(&mut *cpu_module_accessor);
|
||||
if fighter_kind == *FIGHTER_KIND_SHULK {
|
||||
|
@ -509,13 +530,17 @@ unsafe fn set_cpu_controls(p_data: *mut *mut u8) {
|
|||
);
|
||||
}
|
||||
|
||||
let mut saved_mapped_inputs = P1_FINAL_MAPPING.lock()[if INPUT_RECORD == Record {
|
||||
CURRENT_RECORD_SLOT
|
||||
let mut input_record_frame = lock_write_rwlock(&INPUT_RECORD_FRAME);
|
||||
let slot = if input_record == Record {
|
||||
read_rwlock(&CURRENT_RECORD_SLOT)
|
||||
} else {
|
||||
CURRENT_PLAYBACK_SLOT
|
||||
}][INPUT_RECORD_FRAME];
|
||||
|
||||
if BUFFER_FRAME <= 3 && BUFFER_FRAME > 0 {
|
||||
read_rwlock(&CURRENT_PLAYBACK_SLOT)
|
||||
};
|
||||
// TODO! I think something is wrong here, clippy says p1_final_mapping doesn't need to be mutable but we're definitely modifying its contents?
|
||||
let mut p1_final_mapping = lock_write_rwlock(&P1_FINAL_MAPPING);
|
||||
let mut saved_mapped_inputs = (*p1_final_mapping)[slot][*input_record_frame];
|
||||
let mut buffer_frame = lock_write_rwlock(&BUFFER_FRAME);
|
||||
if (0 < *buffer_frame) && (*buffer_frame <= 3) {
|
||||
// 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
|
||||
saved_mapped_inputs = MappedInputs::empty();
|
||||
}
|
||||
|
@ -544,24 +569,28 @@ unsafe fn set_cpu_controls(p_data: *mut *mut u8) {
|
|||
|
||||
// Keep counting frames, unless we're in standby waiting for an input, or are buffering an option
|
||||
// When buffering an option, we keep inputting the first frame of input during the buffer window
|
||||
if BUFFER_FRAME > 0 {
|
||||
BUFFER_FRAME -= 1;
|
||||
} else if INPUT_RECORD_FRAME < CURRENT_FRAME_LENGTH - 1 && POSSESSION != Standby {
|
||||
INPUT_RECORD_FRAME += 1;
|
||||
if *buffer_frame > 0 {
|
||||
*buffer_frame -= 1;
|
||||
} else if *input_record_frame < read_rwlock(&CURRENT_FRAME_LENGTH) - 1
|
||||
&& read_rwlock(&POSSESSION) != Standby
|
||||
{
|
||||
*input_record_frame += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn is_playback() -> bool {
|
||||
INPUT_RECORD == Record || INPUT_RECORD == Playback
|
||||
pub fn is_playback() -> bool {
|
||||
let input_record = read_rwlock(&INPUT_RECORD);
|
||||
input_record == Record || input_record == Playback
|
||||
}
|
||||
|
||||
pub unsafe fn is_recording() -> bool {
|
||||
INPUT_RECORD == Record
|
||||
pub fn is_recording() -> bool {
|
||||
read_rwlock(&INPUT_RECORD) == Record
|
||||
}
|
||||
|
||||
pub unsafe fn is_standby() -> bool {
|
||||
POSSESSION == Standby || POSSESSION == Lockout
|
||||
let possession = read_rwlock(&POSSESSION);
|
||||
possession == Standby || possession == Lockout
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
|
Loading…
Add table
Reference in a new issue