mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2025-03-16 03:16:12 +00:00
add all controller support for input_delay
This commit is contained in:
parent
6ec375b0ec
commit
c83371d2c4
6 changed files with 162 additions and 98 deletions
|
@ -13,6 +13,8 @@ skyline_smash = { git = "https://github.com/ultimate-research/skyline-smash.git"
|
||||||
bitflags = "1.2.1"
|
bitflags = "1.2.1"
|
||||||
parking_lot = { version = "0.11.0", features = ["nightly"] }
|
parking_lot = { version = "0.11.0", features = ["nightly"] }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
owo-colors = "1.1.3"
|
||||||
|
paste = "1.0"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|
21
src/lib.rs
21
src/lib.rs
|
@ -16,6 +16,8 @@ use training::combo::FRAME_ADVANTAGE;
|
||||||
use skyline::libc::{c_void, fclose, fopen, fwrite, mkdir};
|
use skyline::libc::{c_void, fclose, fopen, fwrite, mkdir};
|
||||||
use skyline::nro::{self, NroInfo};
|
use skyline::nro::{self, NroInfo};
|
||||||
|
|
||||||
|
use owo_colors::OwoColorize;
|
||||||
|
|
||||||
fn nro_main(nro: &NroInfo<'_>) {
|
fn nro_main(nro: &NroInfo<'_>) {
|
||||||
if nro.module.isLoaded {
|
if nro.module.isLoaded {
|
||||||
return;
|
return;
|
||||||
|
@ -42,7 +44,14 @@ macro_rules! c_str {
|
||||||
|
|
||||||
#[skyline::main(name = "training_modpack")]
|
#[skyline::main(name = "training_modpack")]
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
println!("[Training Modpack] Initialized.");
|
macro_rules! log {
|
||||||
|
($($arg:tt)*) => {
|
||||||
|
print!("{}", "[Training Modpack] ".green());
|
||||||
|
println!($($arg)*);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
log!("Initialized.");
|
||||||
hitbox_visualizer::hitbox_visualization();
|
hitbox_visualizer::hitbox_visualization();
|
||||||
hazard_manager::hazard_manager();
|
hazard_manager::hazard_manager();
|
||||||
training::training_mods();
|
training::training_mods();
|
||||||
|
@ -50,14 +59,14 @@ pub fn main() {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut buffer = format!("{:x}", MENU as *const _ as u64);
|
let mut buffer = format!("{:x}", MENU as *const _ as u64);
|
||||||
println!(
|
log!(
|
||||||
"[Training Modpack] Writing training_modpack.log with {}...",
|
"Writing training_modpack.log with {}...",
|
||||||
buffer
|
buffer
|
||||||
);
|
);
|
||||||
mkdir(c_str!("sd:/TrainingModpack/"), 0777);
|
mkdir(c_str!("sd:/TrainingModpack/"), 0777);
|
||||||
|
|
||||||
// Only necessary upon version upgrade.
|
// Only necessary upon version upgrade.
|
||||||
// println!("[Training Modpack] Removing training_modpack_menu.conf...");
|
// log!("[Training Modpack] Removing training_modpack_menu.conf...");
|
||||||
// remove(c_str!("sd:/TrainingModpack/training_modpack_menu.conf"));
|
// remove(c_str!("sd:/TrainingModpack/training_modpack_menu.conf"));
|
||||||
|
|
||||||
let mut f = fopen(
|
let mut f = fopen(
|
||||||
|
@ -71,8 +80,8 @@ pub fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = format!("{:x}", &FRAME_ADVANTAGE as *const _ as u64);
|
buffer = format!("{:x}", &FRAME_ADVANTAGE as *const _ as u64);
|
||||||
println!(
|
log!(
|
||||||
"[Training Modpack] Writing training_modpack_frame_adv.log with {}...",
|
"Writing training_modpack_frame_adv.log with {}...",
|
||||||
buffer
|
buffer
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use skyline::nn::hid::NpadHandheldState;
|
use skyline::nn::hid::{NpadHandheldState, GetNpadStyleSet};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use crate::common::MENU;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref P1_DELAYED_NPAD_STATES: Mutex<VecDeque<NpadHandheldState>> =
|
static ref P1_DELAYED_NPAD_STATES: Mutex<VecDeque<NpadHandheldState>> =
|
||||||
|
@ -9,7 +10,6 @@ lazy_static! {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn p1_controller_id() -> u32 {
|
pub unsafe fn p1_controller_id() -> u32 {
|
||||||
use skyline::nn::hid::*;
|
|
||||||
let min_controller_id = (0..8)
|
let min_controller_id = (0..8)
|
||||||
.filter(|i| GetNpadStyleSet(i as *const _).flags != 0)
|
.filter(|i| GetNpadStyleSet(i as *const _).flags != 0)
|
||||||
.min()
|
.min()
|
||||||
|
@ -24,18 +24,14 @@ pub unsafe fn p1_controller_id() -> u32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn handle_get_npad_state(
|
pub unsafe fn handle_get_npad_state(
|
||||||
state: *mut skyline::nn::hid::NpadHandheldState,
|
state: *mut NpadHandheldState,
|
||||||
controller_id: *const u32,
|
controller_id: *const u32,
|
||||||
) {
|
) {
|
||||||
if *controller_id == p1_controller_id() {
|
if *controller_id == p1_controller_id() {
|
||||||
let mut delayed_states = P1_DELAYED_NPAD_STATES.lock();
|
let mut delayed_states = P1_DELAYED_NPAD_STATES.lock();
|
||||||
let actual_state = *state;
|
let actual_state = *state;
|
||||||
|
|
||||||
// if INPUT_RECORD == 1 {
|
if delayed_states.len() < MENU.input_delay as usize {
|
||||||
// P1_NPAD_STATES[INPUT_RECORD_FRAME] = actual_state;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if delayed_states.len() < crate::common::MENU.input_delay as usize {
|
|
||||||
(*state).Buttons = 0;
|
(*state).Buttons = 0;
|
||||||
(*state).LStickX = 0;
|
(*state).LStickX = 0;
|
||||||
(*state).LStickY = 0;
|
(*state).LStickY = 0;
|
||||||
|
@ -52,15 +48,28 @@ pub unsafe fn handle_get_npad_state(
|
||||||
}
|
}
|
||||||
|
|
||||||
delayed_states.push_front(actual_state);
|
delayed_states.push_front(actual_state);
|
||||||
delayed_states.truncate(crate::common::MENU.input_delay as usize);
|
delayed_states.truncate(MENU.input_delay as usize);
|
||||||
} else {
|
|
||||||
// if INPUT_RECORD == 1 || INPUT_RECORD == 2 {
|
|
||||||
// (*state).Buttons = P1_NPAD_STATES[INPUT_RECORD_FRAME].Buttons;
|
|
||||||
// (*state).LStickX = P1_NPAD_STATES[INPUT_RECORD_FRAME].LStickX;
|
|
||||||
// (*state).LStickY = P1_NPAD_STATES[INPUT_RECORD_FRAME].LStickY;
|
|
||||||
// (*state).RStickX = P1_NPAD_STATES[INPUT_RECORD_FRAME].RStickX;
|
|
||||||
// (*state).RStickY = P1_NPAD_STATES[INPUT_RECORD_FRAME].RStickY;
|
|
||||||
// (*state).Flags = P1_NPAD_STATES[INPUT_RECORD_FRAME].Flags;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! create_nn_hid_hooks {
|
||||||
|
(
|
||||||
|
$(
|
||||||
|
($func:ident, $hook:ident)
|
||||||
|
),*
|
||||||
|
) => {
|
||||||
|
$(
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[skyline::hook(replace = $func)]
|
||||||
|
pub unsafe fn $hook(
|
||||||
|
state: *mut skyline::nn::hid::NpadHandheldState,
|
||||||
|
controller_id: *const u32,
|
||||||
|
) {
|
||||||
|
original!()(state, controller_id);
|
||||||
|
input_delay::handle_get_npad_state(state, controller_id);
|
||||||
|
// input_record::handle_get_npad_state(state, controller_id);
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
87
src/training/input_record.rs
Normal file
87
src/training/input_record.rs
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
use skyline::nn::hid::NpadHandheldState;
|
||||||
|
use smash::app::{BattleObjectModuleAccessor, lua_bind::WorkModule};
|
||||||
|
use smash::lib::lua_const::*;
|
||||||
|
use crate::training::input_delay::p1_controller_id;
|
||||||
|
|
||||||
|
pub static mut P1_NPAD_STATES: &mut [NpadHandheldState; 90] = &mut [{
|
||||||
|
NpadHandheldState {
|
||||||
|
updateCount: 0,
|
||||||
|
Buttons: 0,
|
||||||
|
LStickX: 0,
|
||||||
|
LStickY: 0,
|
||||||
|
RStickX: 0,
|
||||||
|
RStickY: 0,
|
||||||
|
Flags: 0,
|
||||||
|
}
|
||||||
|
}; 90];
|
||||||
|
|
||||||
|
pub static mut INPUT_RECORD: InputRecordState = InputRecordState::None;
|
||||||
|
pub static mut INPUT_RECORD_FRAME: usize = 0;
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub enum InputRecordState {
|
||||||
|
None,
|
||||||
|
Record,
|
||||||
|
Playback,
|
||||||
|
}
|
||||||
|
|
||||||
|
use InputRecordState::*;
|
||||||
|
|
||||||
|
pub unsafe fn get_command_flag_cat(module_accessor: &mut BattleObjectModuleAccessor) {
|
||||||
|
let entry_id_int =
|
||||||
|
WorkModule::get_int(module_accessor, *FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID) as i32;
|
||||||
|
|
||||||
|
if entry_id_int == 0 {
|
||||||
|
if INPUT_RECORD == Record || INPUT_RECORD == Playback {
|
||||||
|
if INPUT_RECORD_FRAME >= P1_NPAD_STATES.len() - 1 {
|
||||||
|
if INPUT_RECORD == Record {
|
||||||
|
INPUT_RECORD = Playback;
|
||||||
|
}
|
||||||
|
INPUT_RECORD_FRAME = 0;
|
||||||
|
} else {
|
||||||
|
INPUT_RECORD_FRAME += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn record() {
|
||||||
|
INPUT_RECORD = Record;
|
||||||
|
P1_NPAD_STATES.iter_mut().for_each(|state| {
|
||||||
|
*state = NpadHandheldState {
|
||||||
|
updateCount: 0,
|
||||||
|
Buttons: 0,
|
||||||
|
LStickX: 0,
|
||||||
|
LStickY: 0,
|
||||||
|
RStickX: 0,
|
||||||
|
RStickY: 0,
|
||||||
|
Flags: 0,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
INPUT_RECORD_FRAME = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn playback() {
|
||||||
|
INPUT_RECORD = Playback;
|
||||||
|
INPUT_RECORD_FRAME = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn handle_get_npad_state(
|
||||||
|
state: *mut NpadHandheldState,
|
||||||
|
controller_id: *const u32,
|
||||||
|
) {
|
||||||
|
if *controller_id == p1_controller_id() {
|
||||||
|
if INPUT_RECORD == Record {
|
||||||
|
P1_NPAD_STATES[INPUT_RECORD_FRAME] = *state;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if INPUT_RECORD == Record || INPUT_RECORD == Playback {
|
||||||
|
(*state).Buttons = P1_NPAD_STATES[INPUT_RECORD_FRAME].Buttons;
|
||||||
|
(*state).LStickX = P1_NPAD_STATES[INPUT_RECORD_FRAME].LStickX;
|
||||||
|
(*state).LStickY = P1_NPAD_STATES[INPUT_RECORD_FRAME].LStickY;
|
||||||
|
(*state).RStickX = P1_NPAD_STATES[INPUT_RECORD_FRAME].RStickX;
|
||||||
|
(*state).RStickY = P1_NPAD_STATES[INPUT_RECORD_FRAME].RStickY;
|
||||||
|
(*state).Flags = P1_NPAD_STATES[INPUT_RECORD_FRAME].Flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,9 @@ mod character_specific;
|
||||||
mod fast_fall;
|
mod fast_fall;
|
||||||
mod frame_counter;
|
mod frame_counter;
|
||||||
mod full_hop;
|
mod full_hop;
|
||||||
|
#[macro_use]
|
||||||
mod input_delay;
|
mod input_delay;
|
||||||
|
mod input_record;
|
||||||
mod ledge;
|
mod ledge;
|
||||||
mod mash;
|
mod mash;
|
||||||
mod reset;
|
mod reset;
|
||||||
|
@ -61,10 +63,6 @@ pub unsafe fn handle_get_attack_air_kind(
|
||||||
return ori;
|
return ori;
|
||||||
}
|
}
|
||||||
|
|
||||||
// bool replace;
|
|
||||||
// int kind = InputRecorder::get_attack_air_kind(module_accessor, replace);
|
|
||||||
// if (replace) return kind;
|
|
||||||
|
|
||||||
mash::get_attack_air_kind(module_accessor).unwrap_or(ori)
|
mash::get_attack_air_kind(module_accessor).unwrap_or(ori)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,10 +81,6 @@ pub unsafe fn handle_get_command_flag_cat(
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
// bool replace;
|
|
||||||
// int ret = InputRecorder::get_command_flag_cat(module_accessor, category, flag, replace);
|
|
||||||
// if (replace) return ret;
|
|
||||||
|
|
||||||
flag |= mash::get_command_flag_cat(module_accessor, category);
|
flag |= mash::get_command_flag_cat(module_accessor, category);
|
||||||
|
|
||||||
once_per_frame_per_fighter(module_accessor, category);
|
once_per_frame_per_fighter(module_accessor, category);
|
||||||
|
@ -103,24 +97,7 @@ fn once_per_frame_per_fighter(
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let entry_id_int =
|
input_record::get_command_flag_cat(module_accessor);
|
||||||
WorkModule::get_int(module_accessor, *FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID) as i32;
|
|
||||||
|
|
||||||
if entry_id_int == 0 {
|
|
||||||
// if INPUT_RECORD == 1 || INPUT_RECORD == 2 {
|
|
||||||
// if INPUT_RECORD_FRAME >= P1_NPAD_STATES.len() - 1 {
|
|
||||||
// if INPUT_RECORD == 1 {
|
|
||||||
// INPUT_RECORD = 2;
|
|
||||||
// }
|
|
||||||
// INPUT_RECORD_FRAME = 0;
|
|
||||||
// } else {
|
|
||||||
// INPUT_RECORD_FRAME += 1;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
combo::get_command_flag_cat(module_accessor);
|
combo::get_command_flag_cat(module_accessor);
|
||||||
hitbox_visualizer::get_command_flag_cat(module_accessor);
|
hitbox_visualizer::get_command_flag_cat(module_accessor);
|
||||||
save_states::save_states(module_accessor);
|
save_states::save_states(module_accessor);
|
||||||
|
@ -296,46 +273,39 @@ extern "C" {
|
||||||
|
|
||||||
#[link_name = "\u{1}_ZN2nn3hid12GetNpadStateEPNS0_16NpadFullKeyStateERKj"]
|
#[link_name = "\u{1}_ZN2nn3hid12GetNpadStateEPNS0_16NpadFullKeyStateERKj"]
|
||||||
pub fn GetNpadFullKeyState(arg1: *mut skyline::nn::hid::NpadHandheldState, arg2: *const u32);
|
pub fn GetNpadFullKeyState(arg1: *mut skyline::nn::hid::NpadHandheldState, arg2: *const u32);
|
||||||
|
|
||||||
|
#[link_name = "\u{1}_ZN2nn3hid12GetNpadStateEPNS0_11NpadGcStateERKj"]
|
||||||
|
pub fn GetNpadGcState(arg1: *mut skyline::nn::hid::NpadHandheldState, arg2: *const u32);
|
||||||
|
|
||||||
|
#[link_name = "\u{1}_ZN2nn3hid12GetNpadStateEPNS0_16NpadJoyDualStateERKj"]
|
||||||
|
pub fn GetNpadJoyDualState(arg1: *mut skyline::nn::hid::NpadHandheldState, arg2: *const u32);
|
||||||
|
|
||||||
|
#[link_name = "\u{1}_ZN2nn3hid12GetNpadStateEPNS0_16NpadJoyLeftStateERKj"]
|
||||||
|
pub fn GetNpadJoyLeftState(arg1: *mut skyline::nn::hid::NpadHandheldState, arg2: *const u32);
|
||||||
|
|
||||||
|
#[link_name = "\u{1}_ZN2nn3hid12GetNpadStateEPNS0_17NpadJoyRightStateERKj"]
|
||||||
|
pub fn GetNpadJoyRightState(arg1: *mut skyline::nn::hid::NpadHandheldState, arg2: *const u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static mut P1_NPAD_STATES: &mut [skyline::nn::hid::NpadHandheldState; 90] = &mut [{
|
create_nn_hid_hooks!(
|
||||||
skyline::nn::hid::NpadHandheldState {
|
(GetNpadHandheldState, handle_get_npad_handheld_state),
|
||||||
updateCount: 0,
|
(GetNpadFullKeyState, handle_get_npad_full_key_state),
|
||||||
Buttons: 0,
|
(GetNpadGcState, handle_get_npad_gc_state),
|
||||||
LStickX: 0,
|
(GetNpadJoyDualState, handle_get_joy_dual_state),
|
||||||
LStickY: 0,
|
(GetNpadJoyLeftState, handle_get_joy_left_state),
|
||||||
RStickX: 0,
|
(GetNpadJoyRightState, handle_get_joy_right_state));
|
||||||
RStickY: 0,
|
|
||||||
Flags: 0,
|
|
||||||
}
|
|
||||||
}; 90];
|
|
||||||
|
|
||||||
pub static mut INPUT_RECORD: u32 = 0;
|
|
||||||
pub static mut INPUT_RECORD_FRAME: usize = 0;
|
|
||||||
|
|
||||||
#[skyline::hook(replace = GetNpadHandheldState)]
|
|
||||||
pub unsafe fn handle_GetNpadHandheldState(
|
|
||||||
state: *mut skyline::nn::hid::NpadHandheldState,
|
|
||||||
controller_id: *const u32,
|
|
||||||
) {
|
|
||||||
original!()(state, controller_id);
|
|
||||||
input_delay::handle_get_npad_state(state, controller_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[skyline::hook(replace = GetNpadFullKeyState)]
|
|
||||||
pub unsafe fn handle_GetNpadFullKeyState(
|
|
||||||
state: *mut skyline::nn::hid::NpadHandheldState,
|
|
||||||
controller_id: *const u32,
|
|
||||||
) {
|
|
||||||
original!()(state, controller_id);
|
|
||||||
input_delay::handle_get_npad_state(state, controller_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn training_mods() {
|
pub fn training_mods() {
|
||||||
println!("[Training Modpack] Applying training mods.");
|
println!("[Training Modpack] Applying training mods.");
|
||||||
|
|
||||||
// Input Recording/Delay
|
// Input Recording/Delay
|
||||||
skyline::install_hooks!(handle_GetNpadHandheldState, handle_GetNpadFullKeyState);
|
skyline::install_hooks!(
|
||||||
|
handle_get_npad_handheld_state,
|
||||||
|
handle_get_npad_full_key_state,
|
||||||
|
handle_get_npad_gc_state,
|
||||||
|
handle_get_joy_dual_state,
|
||||||
|
handle_get_joy_left_state,
|
||||||
|
handle_get_joy_right_state);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
LookupSymbol(
|
LookupSymbol(
|
||||||
|
|
|
@ -86,8 +86,7 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
||||||
SAVE_STATE_CPU.state = KillPlayer;
|
SAVE_STATE_CPU.state = KillPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
super::INPUT_RECORD = 2;
|
// crate::training::input_record::playback();
|
||||||
super::INPUT_RECORD_FRAME = 0;
|
|
||||||
|
|
||||||
reset::on_reset();
|
reset::on_reset();
|
||||||
return;
|
return;
|
||||||
|
@ -196,19 +195,7 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
||||||
SAVE_STATE_PLAYER.state = Save;
|
SAVE_STATE_PLAYER.state = Save;
|
||||||
SAVE_STATE_CPU.state = Save;
|
SAVE_STATE_CPU.state = Save;
|
||||||
|
|
||||||
super::INPUT_RECORD = 1;
|
// crate::training::input_record::record();
|
||||||
super::P1_NPAD_STATES.iter_mut().for_each(|state| {
|
|
||||||
*state = skyline::nn::hid::NpadHandheldState {
|
|
||||||
updateCount: 0,
|
|
||||||
Buttons: 0,
|
|
||||||
LStickX: 0,
|
|
||||||
LStickY: 0,
|
|
||||||
RStickX: 0,
|
|
||||||
RStickY: 0,
|
|
||||||
Flags: 0,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
super::INPUT_RECORD_FRAME = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if save_state.state == Save {
|
if save_state.state == Save {
|
||||||
|
|
Loading…
Add table
Reference in a new issue