mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2024-11-24 02:44:17 +00:00
Add Status Only option for input logger (#653)
* Initial attempt, working but menu crashing * Assign raw enum values to fix crash * Merge main into add-status-display --------- Co-authored-by: asimon-1 <40246417+asimon-1@users.noreply.github.com>
This commit is contained in:
parent
65f87df1e0
commit
1475fb2509
2 changed files with 378 additions and 366 deletions
|
@ -1,366 +1,377 @@
|
|||
use itertools::Itertools;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use crate::common::{input::*, menu::QUICK_MENU_ACTIVE, try_get_module_accessor};
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::Mutex;
|
||||
use skyline::nn::ui2d::ResColor;
|
||||
use smash::app::{lua_bind::*, utility};
|
||||
use training_mod_consts::{FighterId, InputDisplay, MENU};
|
||||
|
||||
use super::{frame_counter, input_record::STICK_CLAMP_MULTIPLIER};
|
||||
|
||||
const GREEN: ResColor = ResColor {
|
||||
r: 22,
|
||||
g: 156,
|
||||
b: 0,
|
||||
a: 0,
|
||||
};
|
||||
|
||||
const RED: ResColor = ResColor {
|
||||
r: 153,
|
||||
g: 10,
|
||||
b: 10,
|
||||
a: 0,
|
||||
};
|
||||
|
||||
const CYAN: ResColor = ResColor {
|
||||
r: 0,
|
||||
g: 255,
|
||||
b: 255,
|
||||
a: 0,
|
||||
};
|
||||
|
||||
const BLUE: ResColor = ResColor {
|
||||
r: 0,
|
||||
g: 40,
|
||||
b: 108,
|
||||
a: 0,
|
||||
};
|
||||
|
||||
const PURPLE: ResColor = ResColor {
|
||||
r: 100,
|
||||
g: 66,
|
||||
b: 202,
|
||||
a: 0,
|
||||
};
|
||||
|
||||
pub const YELLOW: ResColor = ResColor {
|
||||
r: 230,
|
||||
g: 180,
|
||||
b: 14,
|
||||
a: 0,
|
||||
};
|
||||
|
||||
pub const WHITE: ResColor = ResColor {
|
||||
r: 255,
|
||||
g: 255,
|
||||
b: 255,
|
||||
a: 0,
|
||||
};
|
||||
|
||||
pub static PER_LOG_FRAME_COUNTER: Lazy<usize> =
|
||||
Lazy::new(|| frame_counter::register_counter(frame_counter::FrameCounterType::InGameNoReset));
|
||||
pub static OVERALL_FRAME_COUNTER: Lazy<usize> =
|
||||
Lazy::new(|| frame_counter::register_counter(frame_counter::FrameCounterType::InGameNoReset));
|
||||
|
||||
pub const NUM_LOGS: usize = 15;
|
||||
pub static mut DRAW_LOG_BASE_IDX: Lazy<Mutex<usize>> = Lazy::new(|| Mutex::new(0));
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
|
||||
pub enum DirectionStrength {
|
||||
None,
|
||||
Weak,
|
||||
// Strong,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default)]
|
||||
pub struct InputLog {
|
||||
pub ttl: u32,
|
||||
pub frames: u32,
|
||||
pub overall_frame: u32,
|
||||
pub raw_inputs: Controller,
|
||||
pub smash_inputs: MappedInputs,
|
||||
pub status: i32,
|
||||
pub fighter_kind: i32,
|
||||
}
|
||||
|
||||
impl PartialEq for InputLog {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.frames == other.frames && !self.is_different(other)
|
||||
}
|
||||
}
|
||||
impl Eq for InputLog {}
|
||||
|
||||
const WALK_THRESHOLD_X: i8 = 20;
|
||||
const _DASH_THRESHOLD_X: i8 = 102;
|
||||
const DEADZONE_THRESHOLD_Y: i8 = 30;
|
||||
const _TAP_JUMP_THRESHOLD_Y: i8 = 90;
|
||||
|
||||
fn bin_stick_values(x: i8, y: i8) -> (DirectionStrength, f32) {
|
||||
(
|
||||
// TODO
|
||||
DirectionStrength::Weak,
|
||||
match (x, y) {
|
||||
// X only
|
||||
(x, y) if y.abs() < DEADZONE_THRESHOLD_Y => match x {
|
||||
x if x > WALK_THRESHOLD_X => 0.0,
|
||||
x if x < -WALK_THRESHOLD_X => 180.0,
|
||||
_ => return (DirectionStrength::None, 0.0),
|
||||
},
|
||||
// Y only
|
||||
(x, y) if x.abs() < WALK_THRESHOLD_X => match y {
|
||||
y if y > DEADZONE_THRESHOLD_Y => 90.0,
|
||||
y if y < -DEADZONE_THRESHOLD_Y => 270.0,
|
||||
_ => return (DirectionStrength::None, 0.0),
|
||||
},
|
||||
// Positive Y
|
||||
(x, y) if y > DEADZONE_THRESHOLD_Y => match x {
|
||||
x if x > WALK_THRESHOLD_X => 45.0,
|
||||
x if x < -WALK_THRESHOLD_X => 135.0,
|
||||
_ => return (DirectionStrength::Weak, 90.0),
|
||||
},
|
||||
// Negative Y
|
||||
(x, y) if y < DEADZONE_THRESHOLD_Y => match x {
|
||||
x if x > WALK_THRESHOLD_X => 315.0,
|
||||
x if x < -WALK_THRESHOLD_X => 225.0,
|
||||
_ => return (DirectionStrength::Weak, 270.0),
|
||||
},
|
||||
_ => return (DirectionStrength::None, 0.0),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
impl InputLog {
|
||||
pub fn is_different(&self, other: &InputLog) -> bool {
|
||||
unsafe {
|
||||
match MENU.input_display {
|
||||
InputDisplay::SMASH => self.is_smash_different(other),
|
||||
InputDisplay::RAW => self.is_raw_different(other),
|
||||
InputDisplay::NONE => false,
|
||||
_ => panic!("Invalid value in is_different: {}", MENU.input_display),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn binned_lstick(&self) -> (DirectionStrength, f32) {
|
||||
unsafe {
|
||||
match MENU.input_display {
|
||||
InputDisplay::SMASH => self.smash_binned_lstick(),
|
||||
InputDisplay::RAW => self.raw_binned_lstick(),
|
||||
InputDisplay::NONE => panic!("Invalid input display to log"),
|
||||
_ => panic!("Invalid value in binned_lstick: {}", MENU.input_display),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn binned_rstick(&self) -> (DirectionStrength, f32) {
|
||||
unsafe {
|
||||
match MENU.input_display {
|
||||
InputDisplay::SMASH => self.smash_binned_rstick(),
|
||||
InputDisplay::RAW => self.raw_binned_rstick(),
|
||||
InputDisplay::NONE => panic!("Invalid input display to log"),
|
||||
_ => panic!("Invalid value in binned_rstick: {}", MENU.input_display),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn button_icons(&self) -> VecDeque<(&str, ResColor)> {
|
||||
unsafe {
|
||||
match MENU.input_display {
|
||||
InputDisplay::SMASH => self.smash_button_icons(),
|
||||
InputDisplay::RAW => self.raw_button_icons(),
|
||||
InputDisplay::NONE => panic!("Invalid input display to log"),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn smash_button_icons(&self) -> VecDeque<(&str, ResColor)> {
|
||||
self.smash_inputs
|
||||
.buttons
|
||||
.to_vec()
|
||||
.iter()
|
||||
.filter_map(|button| {
|
||||
Some(match *button {
|
||||
Buttons::ATTACK | Buttons::ATTACK_RAW => ("a", GREEN),
|
||||
Buttons::SPECIAL | Buttons::SPECIAL_RAW2 => ("b", RED),
|
||||
Buttons::JUMP => ("x", CYAN),
|
||||
Buttons::GUARD | Buttons::GUARD_HOLD => ("lb", BLUE),
|
||||
Buttons::CATCH => ("zr", PURPLE),
|
||||
Buttons::STOCK_SHARE => ("plus", WHITE),
|
||||
Buttons::APPEAL_HI => ("dpad_up", WHITE),
|
||||
Buttons::APPEAL_LW => ("dpad_down", WHITE),
|
||||
Buttons::APPEAL_SL => ("dpad_right", WHITE),
|
||||
Buttons::APPEAL_SR => ("dpad_left", WHITE),
|
||||
_ => return None,
|
||||
})
|
||||
})
|
||||
.unique_by(|(s, _)| *s)
|
||||
.collect::<VecDeque<(&str, ResColor)>>()
|
||||
}
|
||||
|
||||
fn raw_button_icons(&self) -> VecDeque<(&str, ResColor)> {
|
||||
let buttons = self.raw_inputs.current_buttons;
|
||||
let mut icons = VecDeque::new();
|
||||
if buttons.a() {
|
||||
icons.push_front(("a", GREEN));
|
||||
}
|
||||
if buttons.b() {
|
||||
icons.push_front(("b", RED));
|
||||
}
|
||||
if buttons.x() {
|
||||
icons.push_front(("x", CYAN));
|
||||
}
|
||||
if buttons.y() {
|
||||
icons.push_front(("y", CYAN));
|
||||
}
|
||||
if buttons.l() || buttons.real_digital_l() {
|
||||
icons.push_front(("lb", BLUE));
|
||||
}
|
||||
if buttons.r() || buttons.real_digital_r() {
|
||||
icons.push_front(("rb", BLUE));
|
||||
}
|
||||
if buttons.zl() {
|
||||
icons.push_front(("zl", PURPLE));
|
||||
}
|
||||
if buttons.zr() {
|
||||
icons.push_front(("zr", PURPLE));
|
||||
}
|
||||
if buttons.plus() {
|
||||
icons.push_front(("plus", WHITE));
|
||||
}
|
||||
if buttons.minus() {
|
||||
icons.push_front(("minus", WHITE));
|
||||
}
|
||||
if buttons.dpad_up() {
|
||||
icons.push_front(("dpad_up", WHITE));
|
||||
}
|
||||
if buttons.dpad_down() {
|
||||
icons.push_front(("dpad_down", WHITE));
|
||||
}
|
||||
if buttons.dpad_left() {
|
||||
icons.push_front(("dpad_left", WHITE));
|
||||
}
|
||||
if buttons.dpad_right() {
|
||||
icons.push_front(("dpad_right", WHITE));
|
||||
}
|
||||
|
||||
icons
|
||||
}
|
||||
|
||||
fn is_smash_different(&self, other: &InputLog) -> bool {
|
||||
self.smash_inputs.buttons != other.smash_inputs.buttons
|
||||
|| self.smash_binned_lstick() != other.smash_binned_lstick()
|
||||
|| self.smash_binned_rstick() != other.smash_binned_rstick()
|
||||
|| (unsafe { MENU.input_display_status.as_bool() } && self.status != other.status)
|
||||
}
|
||||
|
||||
fn smash_binned_lstick(&self) -> (DirectionStrength, f32) {
|
||||
bin_stick_values(self.smash_inputs.lstick_x, self.smash_inputs.lstick_y)
|
||||
}
|
||||
|
||||
fn smash_binned_rstick(&self) -> (DirectionStrength, f32) {
|
||||
bin_stick_values(self.smash_inputs.rstick_x, self.smash_inputs.rstick_y)
|
||||
}
|
||||
|
||||
fn is_raw_different(&self, other: &InputLog) -> bool {
|
||||
self.raw_inputs.current_buttons != other.raw_inputs.current_buttons
|
||||
|| self.raw_binned_lstick() != other.raw_binned_lstick()
|
||||
|| self.raw_binned_rstick() != other.raw_binned_rstick()
|
||||
|| (unsafe { MENU.input_display_status.as_bool() } && self.status != other.status)
|
||||
}
|
||||
|
||||
fn raw_binned_lstick(&self) -> (DirectionStrength, f32) {
|
||||
let x = (self.raw_inputs.left_stick_x / STICK_CLAMP_MULTIPLIER) as i8;
|
||||
let y = (self.raw_inputs.left_stick_y / STICK_CLAMP_MULTIPLIER) as i8;
|
||||
bin_stick_values(x, y)
|
||||
}
|
||||
|
||||
fn raw_binned_rstick(&self) -> (DirectionStrength, f32) {
|
||||
let x = (self.raw_inputs.right_stick_x / STICK_CLAMP_MULTIPLIER) as i8;
|
||||
let y = (self.raw_inputs.right_stick_y / STICK_CLAMP_MULTIPLIER) as i8;
|
||||
bin_stick_values(x, y)
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_in_place<T>(array: &mut [T], value: T, index: usize) {
|
||||
array[index..].rotate_right(1);
|
||||
array[index] = value;
|
||||
}
|
||||
|
||||
fn insert_in_front<T>(array: &mut [T], value: T) {
|
||||
insert_in_place(array, value, 0);
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref P1_INPUT_LOGS: Mutex<[InputLog; NUM_LOGS]> =
|
||||
Mutex::new([InputLog::default(); NUM_LOGS]);
|
||||
}
|
||||
|
||||
pub fn handle_final_input_mapping(
|
||||
player_idx: i32,
|
||||
controller_struct: &SomeControllerStruct,
|
||||
out: *mut MappedInputs,
|
||||
) {
|
||||
unsafe {
|
||||
if MENU.input_display == InputDisplay::NONE {
|
||||
return;
|
||||
}
|
||||
|
||||
if QUICK_MENU_ACTIVE {
|
||||
return;
|
||||
}
|
||||
|
||||
if player_idx == 0 {
|
||||
let module_accessor = try_get_module_accessor(FighterId::Player);
|
||||
if module_accessor.is_none() {
|
||||
return;
|
||||
}
|
||||
let module_accessor = module_accessor.unwrap();
|
||||
|
||||
let current_frame = frame_counter::get_frame_count(*PER_LOG_FRAME_COUNTER);
|
||||
let current_overall_frame = frame_counter::get_frame_count(*OVERALL_FRAME_COUNTER);
|
||||
// We should always be counting
|
||||
frame_counter::start_counting(*PER_LOG_FRAME_COUNTER);
|
||||
frame_counter::start_counting(*OVERALL_FRAME_COUNTER);
|
||||
|
||||
let potential_input_log = InputLog {
|
||||
ttl: 600,
|
||||
frames: 1,
|
||||
overall_frame: current_overall_frame,
|
||||
raw_inputs: *controller_struct.controller,
|
||||
smash_inputs: *out,
|
||||
status: StatusModule::status_kind(module_accessor),
|
||||
fighter_kind: utility::get_kind(&mut *module_accessor),
|
||||
};
|
||||
|
||||
let input_logs = &mut *P1_INPUT_LOGS.lock();
|
||||
let latest_input_log = input_logs.first_mut().unwrap();
|
||||
let prev_overall_frames = latest_input_log.overall_frame;
|
||||
let prev_ttl = latest_input_log.ttl;
|
||||
// Only update if we are on a new frame according to the latest log
|
||||
let is_new_frame = prev_overall_frames != current_overall_frame;
|
||||
if is_new_frame && latest_input_log.is_different(&potential_input_log) {
|
||||
frame_counter::reset_frame_count(*PER_LOG_FRAME_COUNTER);
|
||||
// We should count this frame already
|
||||
frame_counter::tick_idx(*PER_LOG_FRAME_COUNTER);
|
||||
insert_in_front(input_logs, potential_input_log);
|
||||
let draw_log_base_idx = &mut *DRAW_LOG_BASE_IDX.data_ptr();
|
||||
*draw_log_base_idx = (*draw_log_base_idx + 1) % NUM_LOGS;
|
||||
} else if is_new_frame {
|
||||
*latest_input_log = potential_input_log;
|
||||
latest_input_log.frames = std::cmp::min(current_frame, 99);
|
||||
latest_input_log.ttl = prev_ttl;
|
||||
}
|
||||
|
||||
// Decrease TTL
|
||||
for input_log in input_logs.iter_mut() {
|
||||
if input_log.ttl > 0 && is_new_frame {
|
||||
input_log.ttl -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
use itertools::Itertools;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use crate::common::{input::*, menu::QUICK_MENU_ACTIVE, try_get_module_accessor};
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::Mutex;
|
||||
use skyline::nn::ui2d::ResColor;
|
||||
use smash::app::{lua_bind::*, utility};
|
||||
use training_mod_consts::{FighterId, InputDisplay, MENU};
|
||||
|
||||
use super::{frame_counter, input_record::STICK_CLAMP_MULTIPLIER};
|
||||
|
||||
const GREEN: ResColor = ResColor {
|
||||
r: 22,
|
||||
g: 156,
|
||||
b: 0,
|
||||
a: 0,
|
||||
};
|
||||
|
||||
const RED: ResColor = ResColor {
|
||||
r: 153,
|
||||
g: 10,
|
||||
b: 10,
|
||||
a: 0,
|
||||
};
|
||||
|
||||
const CYAN: ResColor = ResColor {
|
||||
r: 0,
|
||||
g: 255,
|
||||
b: 255,
|
||||
a: 0,
|
||||
};
|
||||
|
||||
const BLUE: ResColor = ResColor {
|
||||
r: 0,
|
||||
g: 40,
|
||||
b: 108,
|
||||
a: 0,
|
||||
};
|
||||
|
||||
const PURPLE: ResColor = ResColor {
|
||||
r: 100,
|
||||
g: 66,
|
||||
b: 202,
|
||||
a: 0,
|
||||
};
|
||||
|
||||
pub const YELLOW: ResColor = ResColor {
|
||||
r: 230,
|
||||
g: 180,
|
||||
b: 14,
|
||||
a: 0,
|
||||
};
|
||||
|
||||
pub const WHITE: ResColor = ResColor {
|
||||
r: 255,
|
||||
g: 255,
|
||||
b: 255,
|
||||
a: 0,
|
||||
};
|
||||
|
||||
pub static PER_LOG_FRAME_COUNTER: Lazy<usize> =
|
||||
Lazy::new(|| frame_counter::register_counter(frame_counter::FrameCounterType::InGameNoReset));
|
||||
pub static OVERALL_FRAME_COUNTER: Lazy<usize> =
|
||||
Lazy::new(|| frame_counter::register_counter(frame_counter::FrameCounterType::InGameNoReset));
|
||||
|
||||
pub const NUM_LOGS: usize = 15;
|
||||
pub static mut DRAW_LOG_BASE_IDX: Lazy<Mutex<usize>> = Lazy::new(|| Mutex::new(0));
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
|
||||
pub enum DirectionStrength {
|
||||
None,
|
||||
Weak,
|
||||
// Strong,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default)]
|
||||
pub struct InputLog {
|
||||
pub ttl: u32,
|
||||
pub frames: u32,
|
||||
pub overall_frame: u32,
|
||||
pub raw_inputs: Controller,
|
||||
pub smash_inputs: MappedInputs,
|
||||
pub status: i32,
|
||||
pub fighter_kind: i32,
|
||||
}
|
||||
|
||||
impl PartialEq for InputLog {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.frames == other.frames && !self.is_different(other)
|
||||
}
|
||||
}
|
||||
impl Eq for InputLog {}
|
||||
|
||||
const WALK_THRESHOLD_X: i8 = 20;
|
||||
const _DASH_THRESHOLD_X: i8 = 102;
|
||||
const DEADZONE_THRESHOLD_Y: i8 = 30;
|
||||
const _TAP_JUMP_THRESHOLD_Y: i8 = 90;
|
||||
|
||||
fn bin_stick_values(x: i8, y: i8) -> (DirectionStrength, f32) {
|
||||
(
|
||||
// TODO
|
||||
DirectionStrength::Weak,
|
||||
match (x, y) {
|
||||
// X only
|
||||
(x, y) if y.abs() < DEADZONE_THRESHOLD_Y => match x {
|
||||
x if x > WALK_THRESHOLD_X => 0.0,
|
||||
x if x < -WALK_THRESHOLD_X => 180.0,
|
||||
_ => return (DirectionStrength::None, 0.0),
|
||||
},
|
||||
// Y only
|
||||
(x, y) if x.abs() < WALK_THRESHOLD_X => match y {
|
||||
y if y > DEADZONE_THRESHOLD_Y => 90.0,
|
||||
y if y < -DEADZONE_THRESHOLD_Y => 270.0,
|
||||
_ => return (DirectionStrength::None, 0.0),
|
||||
},
|
||||
// Positive Y
|
||||
(x, y) if y > DEADZONE_THRESHOLD_Y => match x {
|
||||
x if x > WALK_THRESHOLD_X => 45.0,
|
||||
x if x < -WALK_THRESHOLD_X => 135.0,
|
||||
_ => return (DirectionStrength::Weak, 90.0),
|
||||
},
|
||||
// Negative Y
|
||||
(x, y) if y < DEADZONE_THRESHOLD_Y => match x {
|
||||
x if x > WALK_THRESHOLD_X => 315.0,
|
||||
x if x < -WALK_THRESHOLD_X => 225.0,
|
||||
_ => return (DirectionStrength::Weak, 270.0),
|
||||
},
|
||||
_ => return (DirectionStrength::None, 0.0),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
impl InputLog {
|
||||
pub fn is_different(&self, other: &InputLog) -> bool {
|
||||
unsafe {
|
||||
match MENU.input_display {
|
||||
InputDisplay::SMASH => self.is_smash_different(other),
|
||||
InputDisplay::RAW => self.is_raw_different(other),
|
||||
InputDisplay::STATUS => self.is_status_different(other),
|
||||
InputDisplay::NONE => false,
|
||||
_ => panic!("Invalid value in is_different: {}", MENU.input_display),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn binned_lstick(&self) -> (DirectionStrength, f32) {
|
||||
unsafe {
|
||||
match MENU.input_display {
|
||||
InputDisplay::SMASH => self.smash_binned_lstick(),
|
||||
InputDisplay::RAW => self.raw_binned_lstick(),
|
||||
InputDisplay::STATUS => (DirectionStrength::None, 0.0),
|
||||
InputDisplay::NONE => panic!("Invalid input display to log"),
|
||||
_ => panic!("Invalid value in binned_lstick: {}", MENU.input_display),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn binned_rstick(&self) -> (DirectionStrength, f32) {
|
||||
unsafe {
|
||||
match MENU.input_display {
|
||||
InputDisplay::SMASH => self.smash_binned_rstick(),
|
||||
InputDisplay::RAW => self.raw_binned_rstick(),
|
||||
InputDisplay::STATUS => (DirectionStrength::None, 0.0),
|
||||
InputDisplay::NONE => panic!("Invalid input display to log"),
|
||||
_ => panic!("Invalid value in binned_rstick: {}", MENU.input_display),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn button_icons(&self) -> VecDeque<(&str, ResColor)> {
|
||||
unsafe {
|
||||
match MENU.input_display {
|
||||
InputDisplay::SMASH => self.smash_button_icons(),
|
||||
InputDisplay::RAW => self.raw_button_icons(),
|
||||
InputDisplay::STATUS => VecDeque::new(),
|
||||
InputDisplay::NONE => panic!("Invalid input display to log"),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn smash_button_icons(&self) -> VecDeque<(&str, ResColor)> {
|
||||
self.smash_inputs
|
||||
.buttons
|
||||
.to_vec()
|
||||
.iter()
|
||||
.filter_map(|button| {
|
||||
Some(match *button {
|
||||
Buttons::ATTACK | Buttons::ATTACK_RAW => ("a", GREEN),
|
||||
Buttons::SPECIAL | Buttons::SPECIAL_RAW2 => ("b", RED),
|
||||
Buttons::JUMP => ("x", CYAN),
|
||||
Buttons::GUARD | Buttons::GUARD_HOLD => ("lb", BLUE),
|
||||
Buttons::CATCH => ("zr", PURPLE),
|
||||
Buttons::STOCK_SHARE => ("plus", WHITE),
|
||||
Buttons::APPEAL_HI => ("dpad_up", WHITE),
|
||||
Buttons::APPEAL_LW => ("dpad_down", WHITE),
|
||||
Buttons::APPEAL_SL => ("dpad_right", WHITE),
|
||||
Buttons::APPEAL_SR => ("dpad_left", WHITE),
|
||||
_ => return None,
|
||||
})
|
||||
})
|
||||
.unique_by(|(s, _)| *s)
|
||||
.collect::<VecDeque<(&str, ResColor)>>()
|
||||
}
|
||||
|
||||
fn raw_button_icons(&self) -> VecDeque<(&str, ResColor)> {
|
||||
let buttons = self.raw_inputs.current_buttons;
|
||||
let mut icons = VecDeque::new();
|
||||
if buttons.a() {
|
||||
icons.push_front(("a", GREEN));
|
||||
}
|
||||
if buttons.b() {
|
||||
icons.push_front(("b", RED));
|
||||
}
|
||||
if buttons.x() {
|
||||
icons.push_front(("x", CYAN));
|
||||
}
|
||||
if buttons.y() {
|
||||
icons.push_front(("y", CYAN));
|
||||
}
|
||||
if buttons.l() || buttons.real_digital_l() {
|
||||
icons.push_front(("lb", BLUE));
|
||||
}
|
||||
if buttons.r() || buttons.real_digital_r() {
|
||||
icons.push_front(("rb", BLUE));
|
||||
}
|
||||
if buttons.zl() {
|
||||
icons.push_front(("zl", PURPLE));
|
||||
}
|
||||
if buttons.zr() {
|
||||
icons.push_front(("zr", PURPLE));
|
||||
}
|
||||
if buttons.plus() {
|
||||
icons.push_front(("plus", WHITE));
|
||||
}
|
||||
if buttons.minus() {
|
||||
icons.push_front(("minus", WHITE));
|
||||
}
|
||||
if buttons.dpad_up() {
|
||||
icons.push_front(("dpad_up", WHITE));
|
||||
}
|
||||
if buttons.dpad_down() {
|
||||
icons.push_front(("dpad_down", WHITE));
|
||||
}
|
||||
if buttons.dpad_left() {
|
||||
icons.push_front(("dpad_left", WHITE));
|
||||
}
|
||||
if buttons.dpad_right() {
|
||||
icons.push_front(("dpad_right", WHITE));
|
||||
}
|
||||
|
||||
icons
|
||||
}
|
||||
|
||||
fn is_smash_different(&self, other: &InputLog) -> bool {
|
||||
self.smash_inputs.buttons != other.smash_inputs.buttons
|
||||
|| self.smash_binned_lstick() != other.smash_binned_lstick()
|
||||
|| self.smash_binned_rstick() != other.smash_binned_rstick()
|
||||
|| (unsafe { MENU.input_display_status.as_bool() } && self.status != other.status)
|
||||
}
|
||||
|
||||
fn is_status_different(&self, other: &InputLog) -> bool {
|
||||
unsafe {
|
||||
let input_display_status = MENU.input_display_status.as_bool();
|
||||
input_display_status && (self.status != other.status)
|
||||
}
|
||||
}
|
||||
|
||||
fn smash_binned_lstick(&self) -> (DirectionStrength, f32) {
|
||||
bin_stick_values(self.smash_inputs.lstick_x, self.smash_inputs.lstick_y)
|
||||
}
|
||||
|
||||
fn smash_binned_rstick(&self) -> (DirectionStrength, f32) {
|
||||
bin_stick_values(self.smash_inputs.rstick_x, self.smash_inputs.rstick_y)
|
||||
}
|
||||
|
||||
fn is_raw_different(&self, other: &InputLog) -> bool {
|
||||
self.raw_inputs.current_buttons != other.raw_inputs.current_buttons
|
||||
|| self.raw_binned_lstick() != other.raw_binned_lstick()
|
||||
|| self.raw_binned_rstick() != other.raw_binned_rstick()
|
||||
|| (unsafe { MENU.input_display_status.as_bool() } && self.status != other.status)
|
||||
}
|
||||
|
||||
fn raw_binned_lstick(&self) -> (DirectionStrength, f32) {
|
||||
let x = (self.raw_inputs.left_stick_x / STICK_CLAMP_MULTIPLIER) as i8;
|
||||
let y = (self.raw_inputs.left_stick_y / STICK_CLAMP_MULTIPLIER) as i8;
|
||||
bin_stick_values(x, y)
|
||||
}
|
||||
|
||||
fn raw_binned_rstick(&self) -> (DirectionStrength, f32) {
|
||||
let x = (self.raw_inputs.right_stick_x / STICK_CLAMP_MULTIPLIER) as i8;
|
||||
let y = (self.raw_inputs.right_stick_y / STICK_CLAMP_MULTIPLIER) as i8;
|
||||
bin_stick_values(x, y)
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_in_place<T>(array: &mut [T], value: T, index: usize) {
|
||||
array[index..].rotate_right(1);
|
||||
array[index] = value;
|
||||
}
|
||||
|
||||
fn insert_in_front<T>(array: &mut [T], value: T) {
|
||||
insert_in_place(array, value, 0);
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref P1_INPUT_LOGS: Mutex<[InputLog; NUM_LOGS]> =
|
||||
Mutex::new([InputLog::default(); NUM_LOGS]);
|
||||
}
|
||||
|
||||
pub fn handle_final_input_mapping(
|
||||
player_idx: i32,
|
||||
controller_struct: &SomeControllerStruct,
|
||||
out: *mut MappedInputs,
|
||||
) {
|
||||
unsafe {
|
||||
if MENU.input_display == InputDisplay::NONE {
|
||||
return;
|
||||
}
|
||||
|
||||
if QUICK_MENU_ACTIVE {
|
||||
return;
|
||||
}
|
||||
|
||||
if player_idx == 0 {
|
||||
let module_accessor = try_get_module_accessor(FighterId::Player);
|
||||
if module_accessor.is_none() {
|
||||
return;
|
||||
}
|
||||
let module_accessor = module_accessor.unwrap();
|
||||
|
||||
let current_frame = frame_counter::get_frame_count(*PER_LOG_FRAME_COUNTER);
|
||||
let current_overall_frame = frame_counter::get_frame_count(*OVERALL_FRAME_COUNTER);
|
||||
// We should always be counting
|
||||
frame_counter::start_counting(*PER_LOG_FRAME_COUNTER);
|
||||
frame_counter::start_counting(*OVERALL_FRAME_COUNTER);
|
||||
|
||||
let potential_input_log = InputLog {
|
||||
ttl: 600,
|
||||
frames: 1,
|
||||
overall_frame: current_overall_frame,
|
||||
raw_inputs: *controller_struct.controller,
|
||||
smash_inputs: *out,
|
||||
status: StatusModule::status_kind(module_accessor),
|
||||
fighter_kind: utility::get_kind(&mut *module_accessor),
|
||||
};
|
||||
|
||||
let input_logs = &mut *P1_INPUT_LOGS.lock();
|
||||
let latest_input_log = input_logs.first_mut().unwrap();
|
||||
let prev_overall_frames = latest_input_log.overall_frame;
|
||||
let prev_ttl = latest_input_log.ttl;
|
||||
// Only update if we are on a new frame according to the latest log
|
||||
let is_new_frame = prev_overall_frames != current_overall_frame;
|
||||
if is_new_frame && latest_input_log.is_different(&potential_input_log) {
|
||||
frame_counter::reset_frame_count(*PER_LOG_FRAME_COUNTER);
|
||||
// We should count this frame already
|
||||
frame_counter::tick_idx(*PER_LOG_FRAME_COUNTER);
|
||||
insert_in_front(input_logs, potential_input_log);
|
||||
let draw_log_base_idx = &mut *DRAW_LOG_BASE_IDX.data_ptr();
|
||||
*draw_log_base_idx = (*draw_log_base_idx + 1) % NUM_LOGS;
|
||||
} else if is_new_frame {
|
||||
*latest_input_log = potential_input_log;
|
||||
latest_input_log.frames = std::cmp::min(current_frame, 99);
|
||||
latest_input_log.ttl = prev_ttl;
|
||||
}
|
||||
|
||||
// Decrease TTL
|
||||
for input_log in input_logs.iter_mut() {
|
||||
if input_log.ttl > 0 && is_new_frame {
|
||||
input_log.ttl -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1041,5 +1041,6 @@ byteflags! {
|
|||
pub NONE = "None",
|
||||
pub SMASH = "Smash Inputs",
|
||||
pub RAW = "Raw Inputs",
|
||||
pub STATUS = "Status Only",
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue