mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2025-01-20 01:10:13 +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"
|
||||
parking_lot = { version = "0.11.0", features = ["nightly"] }
|
||||
lazy_static = "1.4.0"
|
||||
owo-colors = "1.1.3"
|
||||
paste = "1.0"
|
||||
|
||||
[profile.dev]
|
||||
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::nro::{self, NroInfo};
|
||||
|
||||
use owo_colors::OwoColorize;
|
||||
|
||||
fn nro_main(nro: &NroInfo<'_>) {
|
||||
if nro.module.isLoaded {
|
||||
return;
|
||||
|
@ -42,7 +44,14 @@ macro_rules! c_str {
|
|||
|
||||
#[skyline::main(name = "training_modpack")]
|
||||
pub fn main() {
|
||||
println!("[Training Modpack] Initialized.");
|
||||
macro_rules! log {
|
||||
($($arg:tt)*) => {
|
||||
print!("{}", "[Training Modpack] ".green());
|
||||
println!($($arg)*);
|
||||
};
|
||||
}
|
||||
|
||||
log!("Initialized.");
|
||||
hitbox_visualizer::hitbox_visualization();
|
||||
hazard_manager::hazard_manager();
|
||||
training::training_mods();
|
||||
|
@ -50,14 +59,14 @@ pub fn main() {
|
|||
|
||||
unsafe {
|
||||
let mut buffer = format!("{:x}", MENU as *const _ as u64);
|
||||
println!(
|
||||
"[Training Modpack] Writing training_modpack.log with {}...",
|
||||
log!(
|
||||
"Writing training_modpack.log with {}...",
|
||||
buffer
|
||||
);
|
||||
mkdir(c_str!("sd:/TrainingModpack/"), 0777);
|
||||
|
||||
// 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"));
|
||||
|
||||
let mut f = fopen(
|
||||
|
@ -71,8 +80,8 @@ pub fn main() {
|
|||
}
|
||||
|
||||
buffer = format!("{:x}", &FRAME_ADVANTAGE as *const _ as u64);
|
||||
println!(
|
||||
"[Training Modpack] Writing training_modpack_frame_adv.log with {}...",
|
||||
log!(
|
||||
"Writing training_modpack_frame_adv.log with {}...",
|
||||
buffer
|
||||
);
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use lazy_static::lazy_static;
|
||||
use parking_lot::Mutex;
|
||||
use skyline::nn::hid::NpadHandheldState;
|
||||
use skyline::nn::hid::{NpadHandheldState, GetNpadStyleSet};
|
||||
use std::collections::VecDeque;
|
||||
use crate::common::MENU;
|
||||
|
||||
lazy_static! {
|
||||
static ref P1_DELAYED_NPAD_STATES: Mutex<VecDeque<NpadHandheldState>> =
|
||||
|
@ -9,7 +10,6 @@ lazy_static! {
|
|||
}
|
||||
|
||||
pub unsafe fn p1_controller_id() -> u32 {
|
||||
use skyline::nn::hid::*;
|
||||
let min_controller_id = (0..8)
|
||||
.filter(|i| GetNpadStyleSet(i as *const _).flags != 0)
|
||||
.min()
|
||||
|
@ -24,18 +24,14 @@ pub unsafe fn p1_controller_id() -> u32 {
|
|||
}
|
||||
|
||||
pub unsafe fn handle_get_npad_state(
|
||||
state: *mut skyline::nn::hid::NpadHandheldState,
|
||||
state: *mut NpadHandheldState,
|
||||
controller_id: *const u32,
|
||||
) {
|
||||
if *controller_id == p1_controller_id() {
|
||||
let mut delayed_states = P1_DELAYED_NPAD_STATES.lock();
|
||||
let actual_state = *state;
|
||||
|
||||
// if INPUT_RECORD == 1 {
|
||||
// P1_NPAD_STATES[INPUT_RECORD_FRAME] = actual_state;
|
||||
// }
|
||||
|
||||
if delayed_states.len() < crate::common::MENU.input_delay as usize {
|
||||
if delayed_states.len() < MENU.input_delay as usize {
|
||||
(*state).Buttons = 0;
|
||||
(*state).LStickX = 0;
|
||||
(*state).LStickY = 0;
|
||||
|
@ -52,15 +48,28 @@ pub unsafe fn handle_get_npad_state(
|
|||
}
|
||||
|
||||
delayed_states.push_front(actual_state);
|
||||
delayed_states.truncate(crate::common::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;
|
||||
// }
|
||||
delayed_states.truncate(MENU.input_delay as usize);
|
||||
}
|
||||
}
|
||||
|
||||
#[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 frame_counter;
|
||||
mod full_hop;
|
||||
#[macro_use]
|
||||
mod input_delay;
|
||||
mod input_record;
|
||||
mod ledge;
|
||||
mod mash;
|
||||
mod reset;
|
||||
|
@ -61,10 +63,6 @@ pub unsafe fn handle_get_attack_air_kind(
|
|||
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)
|
||||
}
|
||||
|
||||
|
@ -83,10 +81,6 @@ pub unsafe fn handle_get_command_flag_cat(
|
|||
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);
|
||||
|
||||
once_per_frame_per_fighter(module_accessor, category);
|
||||
|
@ -103,24 +97,7 @@ fn once_per_frame_per_fighter(
|
|||
}
|
||||
|
||||
unsafe {
|
||||
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 == 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 {
|
||||
input_record::get_command_flag_cat(module_accessor);
|
||||
combo::get_command_flag_cat(module_accessor);
|
||||
hitbox_visualizer::get_command_flag_cat(module_accessor);
|
||||
save_states::save_states(module_accessor);
|
||||
|
@ -296,46 +273,39 @@ extern "C" {
|
|||
|
||||
#[link_name = "\u{1}_ZN2nn3hid12GetNpadStateEPNS0_16NpadFullKeyStateERKj"]
|
||||
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 [{
|
||||
skyline::nn::hid::NpadHandheldState {
|
||||
updateCount: 0,
|
||||
Buttons: 0,
|
||||
LStickX: 0,
|
||||
LStickY: 0,
|
||||
RStickX: 0,
|
||||
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);
|
||||
}
|
||||
create_nn_hid_hooks!(
|
||||
(GetNpadHandheldState, handle_get_npad_handheld_state),
|
||||
(GetNpadFullKeyState, handle_get_npad_full_key_state),
|
||||
(GetNpadGcState, handle_get_npad_gc_state),
|
||||
(GetNpadJoyDualState, handle_get_joy_dual_state),
|
||||
(GetNpadJoyLeftState, handle_get_joy_left_state),
|
||||
(GetNpadJoyRightState, handle_get_joy_right_state));
|
||||
|
||||
pub fn training_mods() {
|
||||
println!("[Training Modpack] Applying training mods.");
|
||||
|
||||
// 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 {
|
||||
LookupSymbol(
|
||||
|
|
|
@ -86,8 +86,7 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
|||
SAVE_STATE_CPU.state = KillPlayer;
|
||||
}
|
||||
|
||||
super::INPUT_RECORD = 2;
|
||||
super::INPUT_RECORD_FRAME = 0;
|
||||
// crate::training::input_record::playback();
|
||||
|
||||
reset::on_reset();
|
||||
return;
|
||||
|
@ -196,19 +195,7 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
|||
SAVE_STATE_PLAYER.state = Save;
|
||||
SAVE_STATE_CPU.state = Save;
|
||||
|
||||
super::INPUT_RECORD = 1;
|
||||
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;
|
||||
// crate::training::input_record::record();
|
||||
}
|
||||
|
||||
if save_state.state == Save {
|
||||
|
|
Loading…
Reference in a new issue