mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2024-11-20 00:46:34 +00:00
huge migration, get menu working, OoS grab
This commit is contained in:
parent
7a57b8e247
commit
548b306645
10 changed files with 248 additions and 208 deletions
|
@ -7,7 +7,7 @@ use smash::app::lua_bind::{self, *};
|
|||
use smash::app::{FighterManager, FighterInformation};
|
||||
use smash::hash40;
|
||||
|
||||
pub static menu : consts::TrainingModpackMenu = consts::TrainingModpackMenu{
|
||||
pub static mut menu_struct : consts::TrainingModpackMenu = consts::TrainingModpackMenu{
|
||||
HITBOX_VIS : true,
|
||||
DI_STATE : NONE,
|
||||
ATTACK_STATE : MASH_NAIR,
|
||||
|
@ -18,6 +18,8 @@ pub static menu : consts::TrainingModpackMenu = consts::TrainingModpackMenu{
|
|||
DEFENSIVE_STATE : RANDOM_DEFENSIVE,
|
||||
};
|
||||
|
||||
pub static mut menu : *mut consts::TrainingModpackMenu = 0 as *mut consts::TrainingModpackMenu;
|
||||
|
||||
pub static mut fighter_manager_addr : usize = 0;
|
||||
|
||||
extern "C" {
|
||||
|
@ -84,7 +86,7 @@ pub unsafe fn perform_defensive_option(
|
|||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
flag: &mut i32)
|
||||
{
|
||||
match menu.DEFENSIVE_STATE {
|
||||
match (*menu).DEFENSIVE_STATE {
|
||||
RANDOM_DEFENSIVE => {
|
||||
let random_cmds = vec![
|
||||
*FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE,
|
||||
|
|
|
@ -130,15 +130,6 @@ pub unsafe fn generate_hitbox_effects(
|
|||
let pos = Vector3f{x : x_curr, y : y_curr, z : z_curr};
|
||||
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,
|
||||
Hash40{hash: hash40("sys_shield")}, Hash40{hash: bone},
|
||||
&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;
|
||||
// if true { // color intensity scales with damage
|
||||
// color_scale = unlerp_bounded(1.0, 18.0, damage.get_num());
|
||||
|
@ -198,6 +189,46 @@ pub unsafe fn generate_hitbox_effects(
|
|||
// 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)]
|
||||
#[skyline::hook(replace = sv_animcmd::CATCH)]
|
||||
unsafe fn handle_catch(lua_state: u64) {
|
||||
|
@ -216,7 +247,7 @@ unsafe fn handle_catch(lua_state: u64) {
|
|||
|
||||
original!()(lua_state);
|
||||
|
||||
if menu.HITBOX_VIS && is_training_mode() {
|
||||
if (*menu).HITBOX_VIS && is_training_mode() {
|
||||
generate_hitbox_effects(
|
||||
sv_system::battle_object_module_accessor(lua_state),
|
||||
joint.get_int(),
|
||||
|
|
156
src/lib.rs
156
src/lib.rs
|
@ -5,6 +5,7 @@
|
|||
#![allow(non_snake_case)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![feature(with_options)]
|
||||
#![feature(asm)]
|
||||
|
||||
mod hitbox_visualizer;
|
||||
mod training;
|
||||
|
@ -17,36 +18,29 @@ use smash::app::{self};
|
|||
use smash::app::lua_bind::{*};
|
||||
use smash::app::sv_animcmd::{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 smash::Result;
|
||||
use skyline::nn;
|
||||
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 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)]
|
||||
#[skyline::hook(replace = status_AttackAirMain_common)]
|
||||
pub unsafe fn handle_AttackAirMain(fighter: *mut L2CAgent) {
|
||||
CancelModule::enable_cancel(sv_system::battle_object_module_accessor((*fighter).lua_state_agent));
|
||||
original!()(fighter);
|
||||
#[skyline::hook(replace = smash::lua2cpp::L2CFighterCommon_sub_guard_cont)]
|
||||
pub unsafe fn handle_sub_guard_cont(fighter: &mut L2CFighterCommon) -> L2CValue {
|
||||
let module_accessor = sv_system::battle_object_module_accessor(fighter.lua_state_agent);
|
||||
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) {
|
||||
|
@ -54,27 +48,8 @@ fn nro_main(nro: &NroInfo) {
|
|||
"common" =>
|
||||
{
|
||||
println!("Loaded common NRO!");
|
||||
unsafe {
|
||||
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!");
|
||||
}
|
||||
skyline::install_hook!(handle_sub_guard_cont);
|
||||
},
|
||||
"item" => println!("Loaded item NRO!"),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
@ -82,14 +57,14 @@ fn nro_main(nro: &NroInfo) {
|
|||
#[skyline::main(name = "test")]
|
||||
pub fn main() {
|
||||
println!("Training modpack initialized.");
|
||||
// hitbox_visualizer::hitbox_visualization();
|
||||
hitbox_visualizer::hitbox_visualization();
|
||||
training::training_mods();
|
||||
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 {
|
||||
// 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());
|
||||
|
||||
println!("File pointer: {:#?}", f);
|
||||
|
@ -98,93 +73,4 @@ pub fn main() {
|
|||
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();
|
||||
// }
|
||||
|
|
|
@ -13,11 +13,11 @@ pub unsafe fn get_float(module_accessor: &mut app::BattleObjectModuleAccessor, v
|
|||
if is_training_mode() &&
|
||||
is_operation_cpu(module_accessor) &&
|
||||
is_in_hitstun(module_accessor) {
|
||||
if menu.DI_STATE != NONE {
|
||||
let mut angle = (menu.DI_STATE - 1) as f64 * PI / 4.0;
|
||||
if (*menu).DI_STATE != NONE {
|
||||
let mut angle = ((*menu).DI_STATE - 1) as f64 * PI / 4.0;
|
||||
|
||||
// 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;
|
||||
}
|
||||
// If facing left, reverse angle
|
||||
|
|
|
@ -21,10 +21,10 @@ pub unsafe fn force_option(
|
|||
let mut status = 0;
|
||||
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;
|
||||
} else {
|
||||
ledge_case = menu.LEDGE_STATE;
|
||||
ledge_case = (*menu).LEDGE_STATE;
|
||||
}
|
||||
|
||||
match ledge_case {
|
||||
|
@ -85,7 +85,7 @@ pub unsafe fn check_button_on(
|
|||
if is_training_mode() && is_operation_cpu(module_accessor) {
|
||||
let prev_status = StatusModule::prev_status_kind(module_accessor, 0) 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) {
|
||||
return Some(true)
|
||||
|
@ -101,7 +101,7 @@ pub unsafe fn get_command_flag_cat(
|
|||
category: 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);
|
||||
defensive_option(module_accessor, category, flag);
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@ pub unsafe fn get_attack_air_kind(
|
|||
module_accessor: &mut app::BattleObjectModuleAccessor) -> Option<i32>
|
||||
{
|
||||
if is_training_mode() && is_operation_cpu(module_accessor) {
|
||||
if menu.MASH_STATE == MASH_ATTACK {
|
||||
match menu.ATTACK_STATE {
|
||||
if (*menu).MASH_STATE == MASH_ATTACK {
|
||||
match (*menu).ATTACK_STATE {
|
||||
MASH_NAIR => return Some(*FIGHTER_COMMAND_ATTACK_AIR_KIND_N),
|
||||
MASH_FAIR => return Some(*FIGHTER_COMMAND_ATTACK_AIR_KIND_F),
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ pub unsafe fn get_command_flag_cat(
|
|||
{
|
||||
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) {
|
||||
match menu.MASH_STATE {
|
||||
match (*menu).MASH_STATE {
|
||||
MASH_AIRDODGE => {
|
||||
if category == FIGHTER_PAD_COMMAND_CATEGORY1 {
|
||||
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE;
|
||||
|
@ -53,7 +53,7 @@ pub unsafe fn get_command_flag_cat(
|
|||
},
|
||||
MASH_ATTACK => {
|
||||
if category == FIGHTER_PAD_COMMAND_CATEGORY1 {
|
||||
match menu.ATTACK_STATE {
|
||||
match (*menu).ATTACK_STATE {
|
||||
MASH_NAIR |
|
||||
MASH_FAIR |
|
||||
MASH_BAIR |
|
||||
|
@ -74,7 +74,7 @@ pub unsafe fn get_command_flag_cat(
|
|||
_ => ()
|
||||
}
|
||||
} 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 => {
|
||||
|
@ -140,7 +140,7 @@ pub unsafe fn check_button_on(
|
|||
{
|
||||
if [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ pub unsafe fn check_button_on(
|
|||
|
||||
if [*CONTROL_PAD_BUTTON_ATTACK, *CONTROL_PAD_BUTTON_CATCH].contains(&button) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
127
src/training/SaveStates.rs
Normal file
127
src/training/SaveStates.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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> {
|
||||
if is_training_mode() {
|
||||
if menu.SHIELD_STATE == SHIELD_INFINITE {
|
||||
if (*menu).SHIELD_STATE == SHIELD_INFINITE {
|
||||
if param_type == hash40("common") {
|
||||
if param_hash == hash40("shield_dec1") {
|
||||
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 {
|
||||
// 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 menu.MASH_STATE == NONE {
|
||||
if (*menu).MASH_STATE == NONE {
|
||||
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
|
||||
if menu.MASH_STATE == MASH_ATTACK {
|
||||
if [MASH_NEUTRAL_B, MASH_SIDE_B, MASH_DOWN_B].contains(&menu.ATTACK_STATE) {
|
||||
if (*menu).MASH_STATE == MASH_ATTACK {
|
||||
if [MASH_NEUTRAL_B, MASH_SIDE_B, MASH_DOWN_B].contains(&(*menu).ATTACK_STATE) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ pub unsafe fn init_settings(
|
|||
{
|
||||
if is_training_mode() && is_operation_cpu(module_accessor) {
|
||||
if status_kind == FIGHTER_STATUS_KIND_DOWN {
|
||||
match menu.TECH_STATE {
|
||||
match (*menu).TECH_STATE {
|
||||
RANDOM_TECH => {
|
||||
let random_statuses = vec![
|
||||
*FIGHTER_STATUS_KIND_DOWN,
|
||||
|
@ -79,7 +79,7 @@ pub unsafe fn get_command_flag_cat(
|
|||
category: 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 status = StatusModule::status_kind(module_accessor) as i32;
|
||||
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) {
|
||||
let prev_status = StatusModule::prev_status_kind(module_accessor, 0) 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) {
|
||||
return Some(true)
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ pub unsafe fn change_motion(
|
|||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
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 app::sv_math::rand(hash40("fighter"), 2) != 0 {
|
||||
return Some(hash40("passive_stand_f"))
|
||||
|
|
|
@ -13,6 +13,7 @@ mod Shield;
|
|||
mod Tech;
|
||||
mod Mash;
|
||||
mod Ledge;
|
||||
mod SaveStates;
|
||||
|
||||
#[allow(unused_unsafe)]
|
||||
#[skyline::hook(replace = WorkModule::get_float)]
|
||||
|
@ -48,42 +49,7 @@ pub unsafe fn handle_get_command_flag_cat(
|
|||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
category: i32) -> i32
|
||||
{
|
||||
//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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SaveStates::save_states(module_accessor);
|
||||
|
||||
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);
|
||||
Ledge::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
|
||||
}
|
||||
|
@ -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() {
|
||||
println!("Applying training mods.");
|
||||
|
@ -216,6 +209,7 @@ pub fn training_mods() {
|
|||
// Hold/Infinite shield
|
||||
skyline::install_hook!(handle_check_button_on);
|
||||
skyline::install_hook!(handle_check_button_off);
|
||||
skyline::install_hook!(handle_attack);
|
||||
|
||||
skyline::install_hook!(handle_get_param_float);
|
||||
|
||||
|
|
Loading…
Reference in a new issue