1
0
Fork 0
mirror of https://github.com/jugeeya/UltimateTrainingModpack.git synced 2024-11-20 08:54:15 +00:00

huge migration, get menu working, OoS grab

This commit is contained in:
jugeeya 2020-05-13 12:20:52 -07:00
parent 7a57b8e247
commit 548b306645
10 changed files with 248 additions and 208 deletions

View file

@ -7,7 +7,7 @@ use smash::app::lua_bind::{self, *};
use smash::app::{FighterManager, FighterInformation}; use smash::app::{FighterManager, FighterInformation};
use smash::hash40; use smash::hash40;
pub static menu : consts::TrainingModpackMenu = consts::TrainingModpackMenu{ pub static mut menu_struct : consts::TrainingModpackMenu = consts::TrainingModpackMenu{
HITBOX_VIS : true, HITBOX_VIS : true,
DI_STATE : NONE, DI_STATE : NONE,
ATTACK_STATE : MASH_NAIR, ATTACK_STATE : MASH_NAIR,
@ -18,6 +18,8 @@ pub static menu : consts::TrainingModpackMenu = consts::TrainingModpackMenu{
DEFENSIVE_STATE : RANDOM_DEFENSIVE, DEFENSIVE_STATE : RANDOM_DEFENSIVE,
}; };
pub static mut menu : *mut consts::TrainingModpackMenu = 0 as *mut consts::TrainingModpackMenu;
pub static mut fighter_manager_addr : usize = 0; pub static mut fighter_manager_addr : usize = 0;
extern "C" { extern "C" {
@ -84,7 +86,7 @@ pub unsafe fn perform_defensive_option(
module_accessor: &mut app::BattleObjectModuleAccessor, module_accessor: &mut app::BattleObjectModuleAccessor,
flag: &mut i32) flag: &mut i32)
{ {
match menu.DEFENSIVE_STATE { match (*menu).DEFENSIVE_STATE {
RANDOM_DEFENSIVE => { RANDOM_DEFENSIVE => {
let random_cmds = vec![ let random_cmds = vec![
*FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE, *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE,

View file

@ -130,15 +130,6 @@ pub unsafe fn generate_hitbox_effects(
let pos = Vector3f{x : x_curr, y : y_curr, z : z_curr}; let pos = Vector3f{x : x_curr, y : y_curr, z : z_curr};
let zeros = Vector3f{x : 0.0, y : 0.0, z : 0.0}; let zeros = Vector3f{x : 0.0, y : 0.0, z : 0.0};
// EffectModule::req_follow(module_accessor,
// Hash40{hash: hash40("sys_shield")}, Hash40{hash: bone},
// &pos, &zeros, size * size_mult,
// true,
// *EFFECT_SUB_ATTRIBUTE_NO_JOINT_SCALE as u32 |
// *EFFECT_SUB_ATTRIBUTE_FOLLOW as u32 |
// *EFFECT_SUB_ATTRIBUTE_CONCLUDE_STATUS as u32,
// 0, 0, 0, 0, true, true);
EffectModule::req_on_joint(module_accessor, EffectModule::req_on_joint(module_accessor,
Hash40{hash: hash40("sys_shield")}, Hash40{hash: bone}, Hash40{hash: hash40("sys_shield")}, Hash40{hash: bone},
&pos, &zeros, size * size_mult, &zeros, &zeros, &pos, &zeros, size * size_mult, &zeros, &zeros,
@ -159,7 +150,7 @@ pub unsafe fn generate_hitbox_effects(
} }
} }
// if menu.HITBOX_VIS && is_training_mode() { // generate hitbox effect(s) // if (*menu).HITBOX_VIS && is_training_mode() { // generate hitbox effect(s)
// let color_scale: f32; // let color_scale: f32;
// if true { // color intensity scales with damage // if true { // color intensity scales with damage
// color_scale = unlerp_bounded(1.0, 18.0, damage.get_num()); // color_scale = unlerp_bounded(1.0, 18.0, damage.get_num());
@ -198,6 +189,46 @@ pub unsafe fn generate_hitbox_effects(
// color); // color);
// } // }
pub unsafe fn get_command_flag_cat(
module_accessor: &mut app::BattleObjectModuleAccessor,
category: i32)
{
// apply only once per frame
if category == 0 && is_training_mode() && (*menu).HITBOX_VIS {
// Pause Effect AnimCMD if hitbox visualization is active
let status_kind = StatusModule::status_kind(module_accessor) as i32;
MotionAnimcmdModule::set_sleep_effect(module_accessor,
!((*FIGHTER_STATUS_KIND_CATCH..=*FIGHTER_STATUS_KIND_TREAD_FALL).contains(&status_kind) ||
(*FIGHTER_STATUS_KIND_WAIT..=*FIGHTER_STATUS_KIND_REBOUND_JUMP).contains(&status_kind)));
if !(*FIGHTER_STATUS_KIND_CATCH..=*FIGHTER_STATUS_KIND_CATCH_TURN).contains(&status_kind) {
EffectModule::set_visible_kind(module_accessor, Hash40{hash: hash40("sys_shield")}, false);
EffectModule::kill_kind(module_accessor, Hash40{hash: hash40("sys_shield")}, false, true);
for i in 0..8 {
if AttackModule::is_attack(module_accessor, i, false) {
let attack_data = *AttackModule::attack_data(module_accessor, i, false);
let is_capsule = attack_data.x2 != 0.0 || attack_data.y2 != 0.0 || attack_data.z2 != 0.0;
let mut x2 = None;
let mut y2 = None;
let mut z2 = None;
if is_capsule {
x2 = Some(attack_data.x2);
y2 = Some(attack_data.y2);
z2 = Some(attack_data.z2);
}
generate_hitbox_effects(
module_accessor,
attack_data.node, // joint
attack_data.size,
attack_data.x, attack_data.y, attack_data.z,
x2, y2, z2,
ID_COLORS[(i % 8) as usize]);
}
}
}
}
}
#[allow(unused_unsafe)] #[allow(unused_unsafe)]
#[skyline::hook(replace = sv_animcmd::CATCH)] #[skyline::hook(replace = sv_animcmd::CATCH)]
unsafe fn handle_catch(lua_state: u64) { unsafe fn handle_catch(lua_state: u64) {
@ -216,7 +247,7 @@ unsafe fn handle_catch(lua_state: u64) {
original!()(lua_state); original!()(lua_state);
if menu.HITBOX_VIS && is_training_mode() { if (*menu).HITBOX_VIS && is_training_mode() {
generate_hitbox_effects( generate_hitbox_effects(
sv_system::battle_object_module_accessor(lua_state), sv_system::battle_object_module_accessor(lua_state),
joint.get_int(), joint.get_int(),

View file

@ -5,6 +5,7 @@
#![allow(non_snake_case)] #![allow(non_snake_case)]
#![allow(non_upper_case_globals)] #![allow(non_upper_case_globals)]
#![feature(with_options)] #![feature(with_options)]
#![feature(asm)]
mod hitbox_visualizer; mod hitbox_visualizer;
mod training; mod training;
@ -17,36 +18,29 @@ use smash::app::{self};
use smash::app::lua_bind::{*}; use smash::app::lua_bind::{*};
use smash::app::sv_animcmd::{self}; use smash::app::sv_animcmd::{self};
use smash::app::sv_system::{self}; use smash::app::sv_system::{self};
use smash::lua2cpp::L2CFighterCommon;
use skyline::libc::{size_t, c_int, c_void, strlen, fopen, fwrite, fclose}; use skyline::libc::{size_t, c_int, c_void, strlen, fopen, fwrite, fclose};
use smash::Result; use smash::Result;
use skyline::nn; use skyline::nn;
use skyline::patching::patch_data_from_text; use skyline::patching::patch_data_from_text;
use skyline::{from_c_str, c_str, hooks::A64HookFunction, logging::hex_dump_ptr}; use skyline::{from_c_str, c_str, hooks::A64HookFunction, logging::hex_dump_ptr, logging::HexDump};
use std::fs; use std::fs;
use skyline::nro::{self, NroInfo}; use skyline::nro::{self, NroInfo};
extern "C" {
#[link_name = "\u{1}_ZN7lua2cpp16L2CFighterCommon28status_AttackAir_Main_commonEv"]
pub fn status_AttackAirMain_common(
arg1: *mut L2CAgent
) -> u64;
#[link_name = "\u{1}_ZN7lua2cpp27L2CFighterAnimcmdGameCommon21game_BatSwing4Common1Ev"]
pub fn game_BatSwing4Common1(
arg1: *mut L2CAgent
) -> u64;
#[link_name = "\u{1}_ZN7lua2cpp27L2CFighterAnimcmdGameCommon21game_BatSwing4Common2Ev"]
pub fn game_BatSwing4Common2(
arg1: *mut L2CAgent
) -> u64;
}
#[allow(unused_unsafe)] #[allow(unused_unsafe)]
#[skyline::hook(replace = status_AttackAirMain_common)] #[skyline::hook(replace = smash::lua2cpp::L2CFighterCommon_sub_guard_cont)]
pub unsafe fn handle_AttackAirMain(fighter: *mut L2CAgent) { pub unsafe fn handle_sub_guard_cont(fighter: &mut L2CFighterCommon) -> L2CValue {
CancelModule::enable_cancel(sv_system::battle_object_module_accessor((*fighter).lua_state_agent)); let module_accessor = sv_system::battle_object_module_accessor(fighter.lua_state_agent);
original!()(fighter); if (*menu).MASH_STATE == MASH_ATTACK && (*menu).ATTACK_STATE == MASH_GRAB {
if StatusModule::prev_status_kind(module_accessor, 0) == FIGHTER_STATUS_KIND_GUARD_DAMAGE {
if WorkModule::get_int(module_accessor, *FIGHTER_INSTANCE_WORK_ID_INT_INVALID_CATCH_FRAME) == 0 {
if WorkModule::is_enable_transition_term(module_accessor, *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_CATCH) {
fighter.fighter_base.change_status(L2CValue::new_int(*FIGHTER_STATUS_KIND_CATCH as u64), L2CValue::new_bool(true));
}
}
}
}
original!()(fighter)
} }
fn nro_main(nro: &NroInfo) { fn nro_main(nro: &NroInfo) {
@ -54,27 +48,8 @@ fn nro_main(nro: &NroInfo) {
"common" => "common" =>
{ {
println!("Loaded common NRO!"); println!("Loaded common NRO!");
unsafe { skyline::install_hook!(handle_sub_guard_cont);
let text_start = (*(*nro.module).ModuleObject).module_base;
println!("Common Text Start: {:x}", text_start);
// raw const_value_table is at : 0x635b70
let fighter_status_kind_fall : u64 = 0x8ee6c39e9be4f0b5;
// let res = match patch_data_from_text(text_start as *const u8, 0x6362b8, &fighter_status_kind_fall) {
// Ok(v) => format!("Patched!"),
// Err(e) => format!("Error patching with e: {}", e)
// };
let fighter_kind_popo : u64 = 0x04aa7a0e945950d5;
let res = match patch_data_from_text(text_start as *const u8, 0x638d78, &fighter_kind_popo) {
Ok(v) => format!("Patched!"),
Err(e) => format!("Error patching with e: {}", e)
};
println!("Result: {}", res);
// skyline::install_hook!(handle_AttackAirMain);
println!("Hooked!");
}
}, },
"item" => println!("Loaded item NRO!"),
_ => () _ => ()
} }
} }
@ -82,14 +57,14 @@ fn nro_main(nro: &NroInfo) {
#[skyline::main(name = "test")] #[skyline::main(name = "test")]
pub fn main() { pub fn main() {
println!("Training modpack initialized."); println!("Training modpack initialized.");
// hitbox_visualizer::hitbox_visualization(); hitbox_visualizer::hitbox_visualization();
training::training_mods(); training::training_mods();
nro::add_hook(nro_main).unwrap(); nro::add_hook(nro_main).unwrap();
let buffer = format!("{:x}", &common::menu as *const _ as u64);
println!("Writing training_modpack.log with {}...\n", buffer);
unsafe { unsafe {
// let f = fopen(c_str("sd:/test.log"), c_str("w")); common::menu = &mut common::menu_struct;
let buffer = format!("{:x}", common::menu as u64);
println!("Writing training_modpack.log with {}...\n", buffer);
let f = fopen("sd:/SaltySD/training_modpack.log\u{0}".as_bytes().as_ptr(), "w\u{0}".as_bytes().as_ptr()); let f = fopen("sd:/SaltySD/training_modpack.log\u{0}".as_bytes().as_ptr(), "w\u{0}".as_bytes().as_ptr());
println!("File pointer: {:#?}", f); println!("File pointer: {:#?}", f);
@ -98,93 +73,4 @@ pub fn main() {
fclose(f); fclose(f);
} }
} }
// fs::File::create("sd:/test.log").unwrap();
} }
// #![feature(proc_macro_hygiene)]
// use smash::hash40;
// use smash::lib::lua_const::{*};
// use smash::lib::{self, L2CAgent, L2CValue};
// use smash::app;
// use smash::app::{lua_bind::*, sv_animcmd, sv_system};
// use skyline::libc::{size_t, c_int, c_void, strlen};
// use smash::Result;
// use skyline::nro::{self, NroInfo};
// use skyline::logging::HexDump;
// extern "C" {
// #[link_name = "\u{1}_ZN7lua2cpp16L2CFighterCommon17status_Catch_MainEv"]
// pub fn status_Catch_Main(
// arg1: *mut L2CAgent
// ) -> u64;
// #[link_name = "\u{1}_ZN7lua2cpp16L2CFighterCommon28sub_wait_ground_check_commonEN3lib8L2CValueE"]
// pub fn sub_wait_ground_check_common(
// arg1: *mut L2CAgent,
// arg2: L2CValue
// ) -> L2CValue;
// #[link_name = "\u{1}_ZN7lua2cpp16L2CFighterCommon25sub_air_check_fall_commonEv"]
// pub fn sub_air_check_fall_common(
// arg1: *mut L2CAgent
// ) -> L2CValue;
// #[link_name = "\u{1}_ZN7lua2cpp14L2CFighterBase13change_statusEN3lib8L2CValueES2_"]
// pub fn change_status(
// arg1: *mut L2CAgent,
// arg2: L2CValue,
// arg3: L2CValue
// ) -> u64;
// }
// #[allow(unused_unsafe)]
// #[skyline::hook(replace = status_Catch_Main)]
// pub unsafe fn handle_status_Catch_Main(fighter: *mut L2CAgent) {
// let module_accessor = sv_system::battle_object_module_accessor((*fighter).lua_state_agent);
// // if CancelModule::is_enable_cancel(module_accessor) {
// // let ret = sub_wait_ground_check_common(fighter, L2CValue::new_bool(false));
// // println!("{}", HexDump(&ret));
// // // sub_air_check_fall_common(fighter);
// // }
// let situation_kind = StatusModule::situation_kind(module_accessor) as i32;
// if situation_kind == SITUATION_KIND_AIR {
// // change_status(fighter,L2CValue::new_int(*FIGHTER_STATUS_KIND_FALL as u64), L2CValue::new_bool(false));
// StatusModule::change_status_request(module_accessor, *FIGHTER_STATUS_KIND_FALL, false);
// return;
// }
// if WorkModule::is_enable_transition_term(module_accessor,*FIGHTER_STATUS_TRANSITION_TERM_ID_WAIT) {
// if MotionModule::is_end(module_accessor) {
// if situation_kind != SITUATION_KIND_GROUND {
// return;
// }
// // change_status(fighter,L2CValue::new_int(*FIGHTER_STATUS_KIND_WAIT as u64), L2CValue::new_bool(false));
// StatusModule::change_status_request(module_accessor, *FIGHTER_STATUS_KIND_WAIT, false);
// return;
// }
// }
// // original!()(fighter); // to call original
// }
// fn nro_main(nro: &NroInfo) {
// match nro.name {
// "common" =>
// {
// println!("Loaded common NRO!");
// skyline::install_hook!(handle_status_Catch_Main);
// println!("change_status: {:p}", change_status as *const());
// println!("sub_air_check_fall_common: {:p}", sub_air_check_fall_common as *const());
// println!("sub_wait_ground_check_common: {:p}", sub_wait_ground_check_common as *const());
// },
// _ => ()
// }
// }
// #[skyline::main(name = "test")]
// pub fn main() {
// println!("Hello from Skyline plugin!");
// nro::add_hook(nro_main).unwrap();
// }

View file

@ -13,11 +13,11 @@ pub unsafe fn get_float(module_accessor: &mut app::BattleObjectModuleAccessor, v
if is_training_mode() && if is_training_mode() &&
is_operation_cpu(module_accessor) && is_operation_cpu(module_accessor) &&
is_in_hitstun(module_accessor) { is_in_hitstun(module_accessor) {
if menu.DI_STATE != NONE { if (*menu).DI_STATE != NONE {
let mut angle = (menu.DI_STATE - 1) as f64 * PI / 4.0; let mut angle = ((*menu).DI_STATE - 1) as f64 * PI / 4.0;
// Either 0 (right) or PI (left) // Either 0 (right) or PI (left)
if menu.DI_STATE == DI_RANDOM_IN_AWAY { if (*menu).DI_STATE == DI_RANDOM_IN_AWAY {
angle = app::sv_math::rand(hash40("fighter"), 2) as f64 * PI; angle = app::sv_math::rand(hash40("fighter"), 2) as f64 * PI;
} }
// If facing left, reverse angle // If facing left, reverse angle

View file

@ -21,10 +21,10 @@ pub unsafe fn force_option(
let mut status = 0; let mut status = 0;
let ledge_case : i32; let ledge_case : i32;
if menu.LEDGE_STATE == RANDOM_LEDGE { if (*menu).LEDGE_STATE == RANDOM_LEDGE {
ledge_case = app::sv_math::rand(hash40("fighter"), 4) + 2; ledge_case = app::sv_math::rand(hash40("fighter"), 4) + 2;
} else { } else {
ledge_case = menu.LEDGE_STATE; ledge_case = (*menu).LEDGE_STATE;
} }
match ledge_case { match ledge_case {
@ -85,7 +85,7 @@ pub unsafe fn check_button_on(
if is_training_mode() && is_operation_cpu(module_accessor) { if is_training_mode() && is_operation_cpu(module_accessor) {
let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32; let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32;
let status = StatusModule::status_kind(module_accessor) as i32; let status = StatusModule::status_kind(module_accessor) as i32;
if menu.DEFENSIVE_STATE == DEFENSIVE_SHIELD && if (*menu).DEFENSIVE_STATE == DEFENSIVE_SHIELD &&
should_perform_defensive_option( should_perform_defensive_option(
module_accessor, prev_status, status) { module_accessor, prev_status, status) {
return Some(true) return Some(true)
@ -101,7 +101,7 @@ pub unsafe fn get_command_flag_cat(
category: i32, category: i32,
flag: &mut i32) flag: &mut i32)
{ {
if menu.LEDGE_STATE != NONE && is_training_mode() && is_operation_cpu(module_accessor) { if (*menu).LEDGE_STATE != NONE && is_training_mode() && is_operation_cpu(module_accessor) {
force_option(module_accessor); force_option(module_accessor);
defensive_option(module_accessor, category, flag); defensive_option(module_accessor, category, flag);
} }

View file

@ -9,8 +9,8 @@ pub unsafe fn get_attack_air_kind(
module_accessor: &mut app::BattleObjectModuleAccessor) -> Option<i32> module_accessor: &mut app::BattleObjectModuleAccessor) -> Option<i32>
{ {
if is_training_mode() && is_operation_cpu(module_accessor) { if is_training_mode() && is_operation_cpu(module_accessor) {
if menu.MASH_STATE == MASH_ATTACK { if (*menu).MASH_STATE == MASH_ATTACK {
match menu.ATTACK_STATE { match (*menu).ATTACK_STATE {
MASH_NAIR => return Some(*FIGHTER_COMMAND_ATTACK_AIR_KIND_N), MASH_NAIR => return Some(*FIGHTER_COMMAND_ATTACK_AIR_KIND_N),
MASH_FAIR => return Some(*FIGHTER_COMMAND_ATTACK_AIR_KIND_F), MASH_FAIR => return Some(*FIGHTER_COMMAND_ATTACK_AIR_KIND_F),
MASH_BAIR => return Some(*FIGHTER_COMMAND_ATTACK_AIR_KIND_B), MASH_BAIR => return Some(*FIGHTER_COMMAND_ATTACK_AIR_KIND_B),
@ -20,7 +20,7 @@ pub unsafe fn get_attack_air_kind(
} }
} }
if menu.MASH_STATE == MASH_RANDOM { if (*menu).MASH_STATE == MASH_RANDOM {
return Some(app::sv_math::rand(hash40("fighter"), 5) + 1); return Some(app::sv_math::rand(hash40("fighter"), 5) + 1);
} }
} }
@ -35,7 +35,7 @@ pub unsafe fn get_command_flag_cat(
{ {
if is_training_mode() && is_operation_cpu(module_accessor) { if is_training_mode() && is_operation_cpu(module_accessor) {
if is_in_hitstun(module_accessor) || is_in_landing(module_accessor) || is_in_shieldstun(module_accessor) { if is_in_hitstun(module_accessor) || is_in_landing(module_accessor) || is_in_shieldstun(module_accessor) {
match menu.MASH_STATE { match (*menu).MASH_STATE {
MASH_AIRDODGE => { MASH_AIRDODGE => {
if category == FIGHTER_PAD_COMMAND_CATEGORY1 { if category == FIGHTER_PAD_COMMAND_CATEGORY1 {
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE; *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE;
@ -53,7 +53,7 @@ pub unsafe fn get_command_flag_cat(
}, },
MASH_ATTACK => { MASH_ATTACK => {
if category == FIGHTER_PAD_COMMAND_CATEGORY1 { if category == FIGHTER_PAD_COMMAND_CATEGORY1 {
match menu.ATTACK_STATE { match (*menu).ATTACK_STATE {
MASH_NAIR | MASH_NAIR |
MASH_FAIR | MASH_FAIR |
MASH_BAIR | MASH_BAIR |
@ -74,7 +74,7 @@ pub unsafe fn get_command_flag_cat(
_ => () _ => ()
} }
} else if category == 1 { } else if category == 1 {
if menu.ATTACK_STATE == MASH_GRAB { *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_CATCH; } if (*menu).ATTACK_STATE == MASH_GRAB { *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_CATCH; }
} }
}, },
MASH_RANDOM => { MASH_RANDOM => {
@ -140,7 +140,7 @@ pub unsafe fn check_button_on(
{ {
if [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) { if [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) {
if is_training_mode() && is_operation_cpu(module_accessor) { if is_training_mode() && is_operation_cpu(module_accessor) {
if menu.MASH_STATE == MASH_AIRDODGE && (is_in_hitstun(module_accessor) || is_in_landing(module_accessor)) { if (*menu).MASH_STATE == MASH_AIRDODGE && (is_in_hitstun(module_accessor) || is_in_landing(module_accessor)) {
return Some(true) return Some(true)
} }
} }
@ -148,7 +148,7 @@ pub unsafe fn check_button_on(
if [*CONTROL_PAD_BUTTON_ATTACK, *CONTROL_PAD_BUTTON_CATCH].contains(&button) { if [*CONTROL_PAD_BUTTON_ATTACK, *CONTROL_PAD_BUTTON_CATCH].contains(&button) {
if is_training_mode() && is_operation_cpu(module_accessor) { if is_training_mode() && is_operation_cpu(module_accessor) {
if menu.MASH_STATE == MASH_ATTACK && menu.ATTACK_STATE == MASH_GRAB && is_in_shieldstun(module_accessor) { if (*menu).MASH_STATE == MASH_ATTACK && (*menu).ATTACK_STATE == MASH_GRAB && is_in_shieldstun(module_accessor) {
return Some(true) return Some(true)
} }
} }

127
src/training/SaveStates.rs Normal file
View file

@ -0,0 +1,127 @@
use smash::{hash40, phx::Hash40, phx::Vector3f};
use smash::app::{self};
use smash::app::lua_bind::*;
use smash::lib::lua_const::*;
use crate::common::*;
use crate::common::consts::*;
#[derive(PartialEq)]
enum SaveState {
Save,
NoAction,
CameraMove,
PosMove,
}
use crate::training::SaveStates::SaveState::*;
static mut save_state_player_state : SaveState = NoAction;
static mut save_state_cpu_state : SaveState = NoAction;
static mut save_state_move_alert : bool = false;
static mut save_state_x_player : f32 = 0.0;
static mut save_state_y_player : f32 = 0.0;
static mut save_state_percent_player : f32 = 0.0;
static mut save_state_lr_player : f32 = 1.0;
static mut save_state_situation_kind_player : i32 = 0 as i32;
static mut save_state_x_cpu : f32 = 0.0;
static mut save_state_y_cpu : f32 = 0.0;
static mut save_state_percent_cpu : f32 = 0.0;
static mut save_state_lr_cpu : f32 = 1.0;
static mut save_state_situation_kind_cpu : i32 = 0 as i32;
pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor) {
let status = StatusModule::status_kind(module_accessor) as i32;
if is_training_mode() {
let save_state_x : *mut f32;
let save_state_y : *mut f32;
let save_state_percent : *mut f32;
let save_state_lr : *mut f32;
let save_state_situation_kind : *mut i32;
let save_state : *mut SaveState;
if is_operation_cpu(module_accessor) {
save_state_x = &mut save_state_x_cpu;
save_state_y = &mut save_state_y_cpu;
save_state_percent = &mut save_state_percent_cpu;
save_state_lr = &mut save_state_lr_cpu;
save_state_situation_kind = &mut save_state_situation_kind_cpu;
save_state = &mut save_state_cpu_state;
} else {
save_state_x = &mut save_state_x_player;
save_state_y = &mut save_state_y_player;
save_state_percent = &mut save_state_percent_player;
save_state_lr = &mut save_state_lr_player;
save_state_situation_kind = &mut save_state_situation_kind_player;
save_state = &mut save_state_player_state;
}
// Grab + Dpad up: reset state
if ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_CATCH) != 0 &&
ControlModule::check_button_trigger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_HI) != 0 {
if *save_state == NoAction {
save_state_player_state = CameraMove;
save_state_cpu_state = CameraMove;
}
}
// move to camera bounds
if *save_state == CameraMove {
*save_state = PosMove;
let left_right = (*save_state_x > 0.0) as i32 as f32 - (*save_state_x < 0.0) as i32 as f32;
let mut y_pos = 0.0;
if *save_state_situation_kind == SITUATION_KIND_GROUND {
y_pos = -50.0;
}
let pos = Vector3f{x : left_right * 50.0, y : y_pos, z : 0.0};
PostureModule::set_pos(module_accessor, &pos);
StatusModule::set_situation_kind(module_accessor, app::SituationKind{situation_kind: *SITUATION_KIND_AIR}, false);
}
// move to correct pos
if *save_state == PosMove {
let pos = Vector3f{x : *save_state_x, y : *save_state_y, z : 0.0};
PostureModule::set_pos(module_accessor, &pos);
PostureModule::set_lr(module_accessor, *save_state_lr);
// DamageModule::add_damage(
// module_accessor,
// -1.0 * DamageModule::damage(module_accessor, 0), 0);
DamageModule::heal(module_accessor, -1.0 * DamageModule::damage(module_accessor, 0), 0);
DamageModule::add_damage(module_accessor, *save_state_percent, 0);
StatusModule::set_situation_kind(module_accessor, app::SituationKind{situation_kind: *save_state_situation_kind}, false);
// Doesn't work, and I don't know why yet.
// if *save_state_situation_kind == SITUATION_KIND_GROUND && status != FIGHTER_STATUS_KIND_WAIT {
// StatusModule::change_status_request(module_accessor, *FIGHTER_STATUS_KIND_WAIT, false);
// }
// else if (*save_state_situation_kind == SITUATION_KIND_AIR && status != FIGHTER_STATUS_KIND_FALL)
// StatusModule::change_status_request(module_accessor, FIGHTER_STATUS_KIND_FALL, 0);
if *save_state_situation_kind == SITUATION_KIND_CLIFF && status != FIGHTER_STATUS_KIND_CLIFF_CATCH_MOVE
&& status != FIGHTER_STATUS_KIND_CLIFF_CATCH {
StatusModule::change_status_request(module_accessor, *FIGHTER_STATUS_KIND_CLIFF_CATCH_MOVE, false);
}
*save_state = NoAction;
}
// Grab + Dpad down: Save state
if ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_CATCH) != 0 &&
ControlModule::check_button_trigger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_LW) != 0 {
save_state_player_state = Save;
save_state_cpu_state = Save;
}
if *save_state == Save {
*save_state = NoAction;
*save_state_x = PostureModule::pos_x(module_accessor);
*save_state_y = PostureModule::pos_y(module_accessor);
*save_state_lr = PostureModule::lr(module_accessor);
*save_state_percent = DamageModule::damage(module_accessor, 0);
*save_state_situation_kind = StatusModule::situation_kind(module_accessor);
}
}
}

View file

@ -8,7 +8,7 @@ use crate::common::consts::*;
pub unsafe fn get_param_float(module_accessor: &mut app::BattleObjectModuleAccessor, param_type: u64, param_hash: u64) -> Option<f32> { pub unsafe fn get_param_float(module_accessor: &mut app::BattleObjectModuleAccessor, param_type: u64, param_hash: u64) -> Option<f32> {
if is_training_mode() { if is_training_mode() {
if menu.SHIELD_STATE == SHIELD_INFINITE { if (*menu).SHIELD_STATE == SHIELD_INFINITE {
if param_type == hash40("common") { if param_type == hash40("common") {
if param_hash == hash40("shield_dec1") { if param_hash == hash40("shield_dec1") {
return Some(0.0) return Some(0.0)
@ -29,9 +29,9 @@ pub unsafe fn get_param_float(module_accessor: &mut app::BattleObjectModuleAcces
pub unsafe fn should_hold_shield(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { pub unsafe fn should_hold_shield(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
// We should hold shield if the state requires it // We should hold shield if the state requires it
if [SHIELD_HOLD, SHIELD_INFINITE].contains(&menu.SHIELD_STATE) { if [SHIELD_HOLD, SHIELD_INFINITE].contains(&(*menu).SHIELD_STATE) {
// If we are not mashing then we will always hold shield // If we are not mashing then we will always hold shield
if menu.MASH_STATE == NONE { if (*menu).MASH_STATE == NONE {
return true return true
} }
@ -40,8 +40,8 @@ pub unsafe fn should_hold_shield(module_accessor: &mut app::BattleObjectModuleAc
} }
// We will only drop shield if we are in shieldstun and our attack can be performed OOS // We will only drop shield if we are in shieldstun and our attack can be performed OOS
if menu.MASH_STATE == MASH_ATTACK { if (*menu).MASH_STATE == MASH_ATTACK {
if [MASH_NEUTRAL_B, MASH_SIDE_B, MASH_DOWN_B].contains(&menu.ATTACK_STATE) { if [MASH_NEUTRAL_B, MASH_SIDE_B, MASH_DOWN_B].contains(&(*menu).ATTACK_STATE) {
return true return true
} }
} }

View file

@ -11,7 +11,7 @@ pub unsafe fn init_settings(
{ {
if is_training_mode() && is_operation_cpu(module_accessor) { if is_training_mode() && is_operation_cpu(module_accessor) {
if status_kind == FIGHTER_STATUS_KIND_DOWN { if status_kind == FIGHTER_STATUS_KIND_DOWN {
match menu.TECH_STATE { match (*menu).TECH_STATE {
RANDOM_TECH => { RANDOM_TECH => {
let random_statuses = vec![ let random_statuses = vec![
*FIGHTER_STATUS_KIND_DOWN, *FIGHTER_STATUS_KIND_DOWN,
@ -79,7 +79,7 @@ pub unsafe fn get_command_flag_cat(
category: i32, category: i32,
flag: &mut i32) flag: &mut i32)
{ {
if menu.TECH_STATE != NONE && is_training_mode() && is_operation_cpu(module_accessor) { if (*menu).TECH_STATE != NONE && is_training_mode() && is_operation_cpu(module_accessor) {
let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32; let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32;
let status = StatusModule::status_kind(module_accessor) as i32; let status = StatusModule::status_kind(module_accessor) as i32;
if [*FIGHTER_STATUS_KIND_DOWN_WAIT, *FIGHTER_STATUS_KIND_DOWN_WAIT_CONTINUE].contains(&status) { if [*FIGHTER_STATUS_KIND_DOWN_WAIT, *FIGHTER_STATUS_KIND_DOWN_WAIT_CONTINUE].contains(&status) {
@ -105,7 +105,7 @@ pub unsafe fn check_button_on(
if is_training_mode() && is_operation_cpu(module_accessor) { if is_training_mode() && is_operation_cpu(module_accessor) {
let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32; let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32;
let status = StatusModule::status_kind(module_accessor) as i32; let status = StatusModule::status_kind(module_accessor) as i32;
if menu.DEFENSIVE_STATE == DEFENSIVE_SHIELD && if (*menu).DEFENSIVE_STATE == DEFENSIVE_SHIELD &&
should_perform_defensive_option(module_accessor, prev_status, status) { should_perform_defensive_option(module_accessor, prev_status, status) {
return Some(true) return Some(true)
} }
@ -119,7 +119,7 @@ pub unsafe fn change_motion(
module_accessor: &mut app::BattleObjectModuleAccessor, module_accessor: &mut app::BattleObjectModuleAccessor,
motion_kind: u64) -> Option<u64> motion_kind: u64) -> Option<u64>
{ {
if menu.TECH_STATE != NONE && is_training_mode() && is_operation_cpu(module_accessor) { if (*menu).TECH_STATE != NONE && is_training_mode() && is_operation_cpu(module_accessor) {
if [hash40("passive_stand_f"), hash40("passive_stand_b")].contains(&motion_kind) { if [hash40("passive_stand_f"), hash40("passive_stand_b")].contains(&motion_kind) {
if app::sv_math::rand(hash40("fighter"), 2) != 0 { if app::sv_math::rand(hash40("fighter"), 2) != 0 {
return Some(hash40("passive_stand_f")) return Some(hash40("passive_stand_f"))

View file

@ -13,6 +13,7 @@ mod Shield;
mod Tech; mod Tech;
mod Mash; mod Mash;
mod Ledge; mod Ledge;
mod SaveStates;
#[allow(unused_unsafe)] #[allow(unused_unsafe)]
#[skyline::hook(replace = WorkModule::get_float)] #[skyline::hook(replace = WorkModule::get_float)]
@ -48,42 +49,7 @@ pub unsafe fn handle_get_command_flag_cat(
module_accessor: &mut app::BattleObjectModuleAccessor, module_accessor: &mut app::BattleObjectModuleAccessor,
category: i32) -> i32 category: i32) -> i32
{ {
//save_states(module_accessor); SaveStates::save_states(module_accessor);
// apply only once per frame
if category == 0 && is_training_mode() && menu.HITBOX_VIS {
// Pause Effect AnimCMD if hitbox visualization is active
let status_kind = StatusModule::status_kind(module_accessor) as i32;
MotionAnimcmdModule::set_sleep_effect(module_accessor,
!((*FIGHTER_STATUS_KIND_CATCH..=*FIGHTER_STATUS_KIND_TREAD_FALL).contains(&status_kind) ||
(*FIGHTER_STATUS_KIND_WAIT..=*FIGHTER_STATUS_KIND_REBOUND_JUMP).contains(&status_kind)));
if !(*FIGHTER_STATUS_KIND_CATCH..=*FIGHTER_STATUS_KIND_CATCH_TURN).contains(&status_kind) {
EffectModule::set_visible_kind(module_accessor, Hash40{hash: hash40("sys_shield")}, false);
EffectModule::kill_kind(module_accessor, Hash40{hash: hash40("sys_shield")}, false, true);
for i in 0..8 {
if AttackModule::is_attack(module_accessor, i, false) {
let attack_data = *AttackModule::attack_data(module_accessor, i, false);
let is_capsule = attack_data.x2 != 0.0 || attack_data.y2 != 0.0 || attack_data.z2 != 0.0;
let mut x2 = None;
let mut y2 = None;
let mut z2 = None;
if is_capsule {
x2 = Some(attack_data.x2);
y2 = Some(attack_data.y2);
z2 = Some(attack_data.z2);
}
hitbox_visualizer::generate_hitbox_effects(
module_accessor,
attack_data.node_, // joint
attack_data.size_,
attack_data.x, attack_data.y, attack_data.z,
x2, y2, z2,
hitbox_visualizer::ID_COLORS[(i % 8) as usize]);
}
}
}
}
let mut flag = original!()(module_accessor, category); let mut flag = original!()(module_accessor, category);
@ -94,6 +60,7 @@ pub unsafe fn handle_get_command_flag_cat(
Mash::get_command_flag_cat(module_accessor, category, &mut flag); Mash::get_command_flag_cat(module_accessor, category, &mut flag);
Ledge::get_command_flag_cat(module_accessor, category, &mut flag); Ledge::get_command_flag_cat(module_accessor, category, &mut flag);
Tech::get_command_flag_cat(module_accessor, category, &mut flag); Tech::get_command_flag_cat(module_accessor, category, &mut flag);
hitbox_visualizer::get_command_flag_cat(module_accessor, category);
flag flag
} }
@ -199,6 +166,32 @@ pub unsafe fn handle_change_motion(
}) })
} }
#[allow(unused_unsafe)]
#[skyline::hook(replace = sv_animcmd::ATTACK)]
pub unsafe fn handle_attack(lua_state: u64) {
let mut l2c_agent = L2CAgent::new(lua_state);
// get all necessary grabbox params
let id = l2c_agent.pop_lua_stack(1); // int
// hacky way of forcing no shield damage on all hitboxes
if is_training_mode() && (*menu).SHIELD_STATE == SHIELD_INFINITE {
let hitbox_params : Vec<L2CValue> = (0..36).map(|i| l2c_agent.pop_lua_stack(i+1)).collect();
l2c_agent.clear_lua_stack();
for i in 0..36 {
let mut x = hitbox_params[i];
if i == 20 {
l2c_agent.push_lua_stack(&mut L2CValue::new_num(-999.0));
} else {
l2c_agent.push_lua_stack(&mut x);
}
}
}
original!()(lua_state);
}
pub fn training_mods() { pub fn training_mods() {
println!("Applying training mods."); println!("Applying training mods.");
@ -216,6 +209,7 @@ pub fn training_mods() {
// Hold/Infinite shield // Hold/Infinite shield
skyline::install_hook!(handle_check_button_on); skyline::install_hook!(handle_check_button_on);
skyline::install_hook!(handle_check_button_off); skyline::install_hook!(handle_check_button_off);
skyline::install_hook!(handle_attack);
skyline::install_hook!(handle_get_param_float); skyline::install_hook!(handle_get_param_float);