diff --git a/src/common/mod.rs b/src/common/mod.rs
index b599600..d7394d7 100644
--- a/src/common/mod.rs
+++ b/src/common/mod.rs
@@ -18,35 +18,47 @@ pub static menu : consts::TrainingModpackMenu = consts::TrainingModpackMenu{
     DEFENSIVE_STATE : RANDOM_DEFENSIVE,
 };
 
-static mut fighter_manager: FighterManager = FighterManager{ _address: 0 };
+pub static mut fighter_manager_addr : usize = 0;
 
 extern "C" {
     #[link_name = "\u{1}_ZN3app9smashball16is_training_modeEv"]
     pub fn is_training_mode() -> bool;
 }
 
-pub fn get_category(module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 {
+pub fn get_category(
+    module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 
+{
 	return (module_accessor.info >> 28) as u8 as i32;
 }
 
-pub unsafe fn is_operation_cpu(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
+pub unsafe fn is_operation_cpu(
+    module_accessor: &mut app::BattleObjectModuleAccessor) -> bool 
+{
     if get_category(module_accessor) as i32 != BATTLE_OBJECT_CATEGORY_FIGHTER {
         return false
     }
 
-    let entry_id = app::FighterEntryID(WorkModule::get_int(module_accessor, *FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID) as i32);
-    let fighter_information = lua_bind::FighterManager::get_fighter_information(&mut fighter_manager, entry_id) as *mut FighterInformation;
+    let entry_id_int = WorkModule::get_int(module_accessor, *FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID) as i32;
+    let entry_id = app::FighterEntryID(entry_id_int);
+    // let mut mgr = FighterManager{_address : fighter_manager_addr as u64};
+    // let fighter_information = lua_bind::FighterManager::get_fighter_information(&mut mgr, entry_id) as *mut FighterInformation;
+    // println!("FighterInformation: {:#?}", fighter_information);
 
-    lua_bind::FighterInformation::is_operation_cpu(fighter_information)
+    // lua_bind::FighterInformation::is_operation_cpu(fighter_information)
+    entry_id_int > 0
 }
 
-pub unsafe fn is_in_hitstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
+pub unsafe fn is_in_hitstun(
+    module_accessor: &mut app::BattleObjectModuleAccessor) -> bool 
+{
     let status_kind = StatusModule::status_kind(module_accessor) as i32;
     (FIGHTER_STATUS_KIND_DAMAGE..=FIGHTER_STATUS_KIND_DAMAGE_FALL)
         .contains(&status_kind)
 }
 
-pub unsafe fn is_in_shieldstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
+pub unsafe fn is_in_shieldstun(
+    module_accessor: &mut app::BattleObjectModuleAccessor) -> bool 
+{
     let status_kind = StatusModule::status_kind(module_accessor) as i32;
     let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32;
     // If we are taking shield damage or we are droping shield from taking shield damage we are in hitstun
@@ -59,33 +71,41 @@ pub unsafe fn is_in_shieldstun(module_accessor: &mut app::BattleObjectModuleAcce
 }
 
 
-pub unsafe fn is_in_landing(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
+pub unsafe fn is_in_landing(
+    module_accessor: &mut app::BattleObjectModuleAccessor) -> bool 
+{
     let status_kind = StatusModule::status_kind(module_accessor) as i32;
     (FIGHTER_STATUS_KIND_LANDING..=FIGHTER_STATUS_KIND_LANDING_DAMAGE_LIGHT)
         .contains(&status_kind)
 }
 
 
-pub unsafe fn perform_defensive_option(module_accessor: &mut app::BattleObjectModuleAccessor, flag: &mut i32) {
-    if menu.DEFENSIVE_STATE == RANDOM_DEFENSIVE {
-        let random_cmds = vec![
-            *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE,
-            *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F,
-            *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B,
-            *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N
-        ];
-
-        let random_cmd_index = app::sv_math::rand(hash40("fighter"), random_cmds.len() as i32) as usize;
-        *flag |= random_cmds[random_cmd_index];
-    } else if menu.DEFENSIVE_STATE == DEFENSIVE_ROLL {
-        if app::sv_math::rand(hash40("fighter"), 2) == 0 {
-            *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F;
-        } else {
-            *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B;
-        }
-    } else if menu.DEFENSIVE_STATE == DEFENSIVE_SPOTDODGE {
-        *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE;
-    } else if menu.DEFENSIVE_STATE == DEFENSIVE_JAB {
-        *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N;
+pub unsafe fn perform_defensive_option(
+    module_accessor: &mut app::BattleObjectModuleAccessor, 
+    flag: &mut i32) 
+{
+    match menu.DEFENSIVE_STATE {
+        RANDOM_DEFENSIVE => {
+            let random_cmds = vec![
+                *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE,
+                *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F,
+                *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B,
+                *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N
+            ];
+    
+            let random_cmd_index = app::sv_math::rand(
+                hash40("fighter"), random_cmds.len() as i32) as usize;
+            *flag |= random_cmds[random_cmd_index];
+        },
+        DEFENSIVE_ROLL => {
+            if app::sv_math::rand(hash40("fighter"), 2) == 0 {
+                *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F;
+            } else {
+                *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B;
+            }
+        },
+        DEFENSIVE_SPOTDODGE => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE,
+        DEFENSIVE_JAB => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N,
+        _ => ()
     }
 }
\ No newline at end of file
diff --git a/src/hitbox_visualizer/mod.rs b/src/hitbox_visualizer/mod.rs
index bc0fcbc..bbbdc7f 100644
--- a/src/hitbox_visualizer/mod.rs
+++ b/src/hitbox_visualizer/mod.rs
@@ -1,13 +1,12 @@
 use smash::hash40;
-use smash::app::BattleObjectModuleAccessor;
-use smash::app::sv_animcmd::{self};
-use smash::app::lua_bind::*;
-use smash::lib::{self, L2CAgent, L2CValue};
-use smash::phx::{Hash40, Vector3f};
-use smash::lib::lua_const::{*};
-use smash::app::sv_system::{self};
 use smash::app::{self};
-use skyline::logging::hex_dump_ptr;
+use smash::app::sv_animcmd::{self};
+use smash::app::sv_system::{self};
+use smash::app::lua_bind::*;
+use smash::lib::lua_const::*;
+use smash::lib::{L2CAgent, L2CValue, L2CValueType};
+use smash::phx::{Hash40, Vector3f};
+use skyline::{logging::HexDump};
 use crate::common::*;
 
 /**
@@ -108,7 +107,7 @@ pub unsafe fn generate_hitbox_effects(l2c_agent: &mut L2CAgent, bone: L2CValue,
     let y_dist : f32;
     let z_dist : f32;
     let mut n_effects : i32;
-    if let lib::L2CValueType::Void = x2.val_type{ // && let lib::L2CValueType::Void = y2.val_type && let lib::L2CValueType::Void = z2.val_type {  // extended hitbox
+    if let L2CValueType::Void = x2.val_type { // && let lib::L2CValueType::Void = y2.val_type && let lib::L2CValueType::Void = z2.val_type {  // extended hitbox
         x_dist = 0.0; y_dist = 0.0; z_dist = 0.0;
         n_effects = 1;
     } 
@@ -177,7 +176,7 @@ unsafe fn handle_attack(lua_state: u64) {
 
     if menu.HITBOX_VIS && is_training_mode() {  // generate hitbox effect(s)
         let color_scale: f32;
-        if false {  // color intensity scales with damage
+        if true {  // color intensity scales with damage
             color_scale = unlerp_bounded(1.0, 18.0, damage.get_num());
         } else {  // color intensity scales with total KB
             // calculate the expected KB a character with 95 weight will receive
@@ -232,14 +231,14 @@ unsafe fn handle_catch(lua_state: u64) {
     }
 }
 
-pub unsafe fn is_shielding(module_accessor: *mut BattleObjectModuleAccessor) -> bool {
+pub unsafe fn is_shielding(module_accessor: *mut app::BattleObjectModuleAccessor) -> bool {
     let status_kind = StatusModule::status_kind(module_accessor) as i32;
     (FIGHTER_STATUS_KIND_GUARD_ON..=FIGHTER_STATUS_KIND_GUARD_OFF).contains(&status_kind)
 }
 
 #[allow(unused_unsafe)]
 #[skyline::hook(replace = AttackModule::clear_all)]
-pub unsafe fn handle_clear_all(module_accessor: *mut BattleObjectModuleAccessor) {
+pub unsafe fn handle_clear_all(module_accessor: *mut app::BattleObjectModuleAccessor) {
     if is_training_mode() {
         // only if we're not shielding
         if !is_shielding(module_accessor) {
@@ -252,7 +251,7 @@ pub unsafe fn handle_clear_all(module_accessor: *mut BattleObjectModuleAccessor)
 
 #[allow(unused_unsafe)]
 #[skyline::hook(replace = GrabModule::set_rebound)]
-pub unsafe fn handle_set_rebound(module_accessor: *mut BattleObjectModuleAccessor, rebound: bool) {
+pub unsafe fn handle_set_rebound(module_accessor: *mut app::BattleObjectModuleAccessor, rebound: bool) {
     if is_training_mode() && rebound == false {
         // only if we're not shielding
         if !is_shielding(module_accessor) {
diff --git a/src/lib.rs b/src/lib.rs
index dcca399..000da36 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -21,37 +21,87 @@ use skyline::libc::{size_t, c_int, c_void, strlen};
 use smash::Result;
 use skyline::nn;
 use skyline::patching::patch_data_from_text;
-use skyline::{from_c_str, c_str};
+use skyline::{from_c_str, c_str, hooks::A64HookFunction};
 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 = nn::ro::LoadModule)]
-pub unsafe fn handle_load_module(
-    p_out_module: *mut skyline::nn::ro::Module, 
-    p_image: *const c_void, 
-    buffer: *mut c_void, 
-    buffer_size: size_t, 
-    flag: c_int) -> Result {
+#[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);
+}
 
-    let ret = original!()(p_out_module, p_image, buffer, buffer_size, flag);
+#[allow(unused_unsafe)]
+#[skyline::hook(replace = game_BatSwing4Common1)]
+pub unsafe fn handle_game_BatSwing4Common1(fighter: *mut L2CAgent) {
+    println!("[handle_game_BatSwing4Common1]");
+    original!()(fighter);
+}
 
-    let name = from_c_str(&(*p_out_module).Name as *const u8);
-    println!("[handleLoadModule] NRO name: {}\n", name);
-    let text_start = (*(*p_out_module).ModuleObject).module_base;
-    println!("Module base: {}\n", text_start);
-    if name.starts_with("common") {
-        println!("Is common!");
-        // 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)
-        };
-
-        println!("{}", res);
+#[allow(unused_unsafe)]
+#[skyline::hook(replace = game_BatSwing4Common2)]
+pub unsafe fn handle_game_BatSwing4Common2(fighter: *mut L2CAgent) {
+    println!("[handle_game_BatSwing4Common2]");
+    sv_animcmd::frame((*fighter).lua_state_agent, 0x30 as f32);
+    if sv_animcmd::is_excute((*fighter).lua_state_agent) {
+        hitbox_visualizer::wrap(sv_animcmd::EFFECT_FOLLOW_NO_SCALE,
+            &mut (*fighter), 
+            &mut [
+            L2CValue::new_int(hash40("sys_shield")), L2CValue::new_int(hash40("top")), 
+            L2CValue::new_num(0.0), L2CValue::new_num(0.0), L2CValue::new_num(0.0), L2CValue::new_num(0.0), L2CValue::new_num(0.0), L2CValue::new_num(0.0), 
+            L2CValue::new_num(1.0), L2CValue::new_bool(false)].to_vec());
     }
+    original!()(fighter);
+}
 
-    ret
+fn nro_main(nro: &NroInfo) {
+    match nro.name {
+        "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);
+                        // skyline::install_hook!(handle_game_BatSwing4Common1);
+                        // skyline::install_hook!(handle_game_BatSwing4Common2);
+                        println!("Hooked!");
+                    }
+                },
+        "item" => println!("Loaded item NRO!"),
+        _ => ()
+    }
 }
 
 #[skyline::main(name = "test")]
@@ -59,10 +109,11 @@ pub fn main() {
     println!("Training modpack initialized.");
     hitbox_visualizer::hitbox_visualization();
     training::training_mods();
+    nro::add_hook(nro_main).unwrap();
 
-    println!("OpenMode_Write: {} {}", nn::fs::OpenMode_OpenMode_Write, nn::fs::OpenMode_OpenMode_Write as i32);
-    let buffer = format!("{:x}", &common::menu as *const _ as u64);
-    println!("Writing training_modpack.log with {}...\n", buffer);
+    // println!("OpenMode_Write: {} {}", nn::fs::OpenMode_OpenMode_Write, nn::fs::OpenMode_OpenMode_Write as i32);
+    // let buffer = format!("{:x}", &common::menu as *const _ as u64);
+    // println!("Writing training_modpack.log with {}...\n", buffer);
 
-    // skyline::install_hook!(handle_load_module);
+    // fs::File::create("sd:/test.log").unwrap();
 }
diff --git a/src/training/DirectionalInfluence.rs b/src/training/DirectionalInfluence.rs
new file mode 100644
index 0000000..e0d213d
--- /dev/null
+++ b/src/training/DirectionalInfluence.rs
@@ -0,0 +1,40 @@
+use smash::hash40;
+use smash::app::{self};
+use smash::app::lua_bind::*;
+use smash::lib::lua_const::*;
+use crate::common::*;
+use crate::common::consts::*;
+use core::f64::consts::PI;
+
+
+pub unsafe fn get_float(module_accessor: &mut app::BattleObjectModuleAccessor, var: i32) -> Option<f32> {
+    if var == FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_X ||
+        var == FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_Y {
+        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;
+
+                // Either 0 (right) or PI (left)
+                if menu.DI_STATE == DI_RANDOM_IN_AWAY {
+                    angle = app::sv_math::rand(hash40("fighter"), 2) as f64 * PI;
+                }
+                // If facing left, reverse angle
+                if PostureModule::lr(module_accessor) != -1.0 {
+                    angle -= PI;
+                }
+
+                if var == FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_X {
+                    return Some(angle.cos() as f32)
+                }
+
+                if var == FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_Y {
+                    return Some(angle.sin() as f32)
+                }
+            }
+        }
+    }
+
+    None
+}
\ No newline at end of file
diff --git a/src/training/Ledge.rs b/src/training/Ledge.rs
new file mode 100644
index 0000000..fc53e7d
--- /dev/null
+++ b/src/training/Ledge.rs
@@ -0,0 +1,108 @@
+use smash::{hash40, phx::Hash40};
+use smash::app::{self};
+use smash::app::lua_bind::*;
+use smash::lib::lua_const::*;
+use crate::common::*;
+use crate::common::consts::*;
+
+pub unsafe fn force_option(
+    module_accessor: &mut app::BattleObjectModuleAccessor)
+{
+    if StatusModule::status_kind(module_accessor) as i32 == *FIGHTER_STATUS_KIND_CLIFF_WAIT {
+        if WorkModule::is_enable_transition_term(module_accessor, *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_CLIFF_CLIMB) {
+            
+            let random_frame = app::sv_math::rand(
+                hash40("fighter"), 
+                MotionModule::end_frame(module_accessor) as i32) as f32;
+
+            let frame = MotionModule::frame(module_accessor) as f32;
+                
+            if frame == random_frame || frame > 30.0 {
+                let mut status = 0;
+                let ledge_case : i32;
+
+                if menu.LEDGE_STATE == RANDOM_LEDGE {
+                    ledge_case = app::sv_math::rand(hash40("fighter"), 4) + 2;
+                } else {
+                    ledge_case = menu.LEDGE_STATE;
+                }
+
+                match ledge_case {
+                    NEUTRAL_LEDGE => status = *FIGHTER_STATUS_KIND_CLIFF_CLIMB,
+                    ROLL_LEDGE => status = *FIGHTER_STATUS_KIND_CLIFF_ESCAPE,
+                    JUMP_LEDGE => status = *FIGHTER_STATUS_KIND_CLIFF_JUMP1,
+                    ATTACK_LEDGE => status = *FIGHTER_STATUS_KIND_CLIFF_ATTACK,
+                    _ => ()
+                }
+
+                StatusModule::change_status_request_from_script(module_accessor, status, true);
+            }
+        }
+    }
+}
+
+pub unsafe fn should_perform_defensive_option(
+    module_accessor: &mut app::BattleObjectModuleAccessor,
+    prev_status: i32,
+    status: i32) -> bool
+{
+    ([*FIGHTER_STATUS_KIND_CLIFF_CLIMB,
+      *FIGHTER_STATUS_KIND_CLIFF_ATTACK,
+      *FIGHTER_STATUS_KIND_CLIFF_ESCAPE]
+        .iter()
+        .any(|i| i == &status || i == &prev_status)
+    )
+    && 
+    (
+        WorkModule::is_enable_transition_term(module_accessor, *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE) ||
+        CancelModule::is_enable_cancel(module_accessor)
+    )
+}
+
+pub unsafe fn defensive_option(
+    module_accessor: &mut app::BattleObjectModuleAccessor,
+    category: i32,
+    flag: &mut i32) 
+{
+    let status = StatusModule::status_kind(module_accessor) as i32;
+    let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32;
+    if [*FIGHTER_STATUS_KIND_CLIFF_JUMP3, 
+        *FIGHTER_STATUS_KIND_CLIFF_JUMP2,
+        *FIGHTER_STATUS_KIND_CLIFF_JUMP1].contains(&status) {
+        *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE;
+    }
+
+    if should_perform_defensive_option(module_accessor, prev_status, status) {
+        perform_defensive_option(module_accessor, flag);
+    }
+}
+
+pub unsafe fn check_button_on(
+    module_accessor: &mut app::BattleObjectModuleAccessor,
+    button: i32) -> Option<bool>
+{
+    if [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) {
+        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 && 
+                should_perform_defensive_option(
+                    module_accessor, prev_status, status) {
+                return Some(true)
+            }
+        }
+    }
+
+    None
+}
+
+pub unsafe fn get_command_flag_cat(
+    module_accessor: &mut app::BattleObjectModuleAccessor,
+    category: i32,
+    flag: &mut i32) 
+{
+    if menu.LEDGE_STATE != NONE && is_training_mode() && is_operation_cpu(module_accessor) {
+        force_option(module_accessor);
+        defensive_option(module_accessor, category, flag);
+    }
+}
\ No newline at end of file
diff --git a/src/training/Mash.rs b/src/training/Mash.rs
new file mode 100644
index 0000000..fe86cf5
--- /dev/null
+++ b/src/training/Mash.rs
@@ -0,0 +1,158 @@
+use smash::{hash40, phx::Hash40};
+use smash::app::{self};
+use smash::app::lua_bind::*;
+use smash::lib::lua_const::*;
+use crate::common::*;
+use crate::common::consts::*;
+
+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 {
+                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),
+                MASH_UPAIR => return Some(*FIGHTER_COMMAND_ATTACK_AIR_KIND_HI),
+                MASH_DAIR => return Some(*FIGHTER_COMMAND_ATTACK_AIR_KIND_LW),
+                _ => ()
+            }
+        }
+
+        if menu.MASH_STATE == MASH_RANDOM {
+            return Some(app::sv_math::rand(hash40("fighter"), 5) + 1);
+        }
+    }
+
+    None
+}
+
+pub unsafe fn get_command_flag_cat(
+    module_accessor: &mut app::BattleObjectModuleAccessor,
+    category: i32,
+    flag: &mut i32) 
+{
+    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 {
+                MASH_AIRDODGE => {
+                    if category == FIGHTER_PAD_COMMAND_CATEGORY1 {
+                        *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE;
+                    }
+                },
+                MASH_JUMP => { 
+                    if !is_in_landing(module_accessor) && category == FIGHTER_PAD_COMMAND_CATEGORY1 {
+                        *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_JUMP_BUTTON;
+                    }
+                },
+                MASH_SPOTDODGE => {
+                    if category == FIGHTER_PAD_COMMAND_CATEGORY1 {
+                        *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE;
+                    }
+                },
+                MASH_ATTACK => {
+                    if category == FIGHTER_PAD_COMMAND_CATEGORY1 {
+                        match menu.ATTACK_STATE {
+                            MASH_NAIR |
+                            MASH_FAIR |
+                            MASH_BAIR |
+                            MASH_UPAIR |
+                            MASH_DAIR => {
+                                *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N;
+                                // If we are performing the attack OOS we also need to jump
+                                if is_in_shieldstun(module_accessor) {
+                                    *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_JUMP_BUTTON;
+                                }
+                            },
+                            MASH_NEUTRAL_B => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_N,
+                            MASH_SIDE_B => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_S,
+                            MASH_UP_B => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_HI,
+                            MASH_DOWN_B => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_LW,
+                            MASH_UP_SMASH => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_HI4,
+                            MASH_GRAB => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_CATCH,
+                            _ => ()
+                    }
+                    } else if category == 1 {
+                        if menu.ATTACK_STATE == MASH_GRAB { *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_CATCH; }
+                    }
+                },
+                MASH_RANDOM => {
+                    if category == FIGHTER_PAD_COMMAND_CATEGORY1 {
+                        let situation_kind = StatusModule::situation_kind(module_accessor) as i32;
+
+                        if situation_kind == SITUATION_KIND_AIR {
+                            let random_commands = vec![
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_JUMP_BUTTON,
+                                // one for each aerial
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_N,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_S,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_HI,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_LW,
+                            ];
+
+                            let random_cmd_index = app::sv_math::rand(
+                                hash40("fighter"), random_commands.len() as i32) as usize;
+
+                            *flag |= random_commands[random_cmd_index];
+                        } else if situation_kind == SITUATION_KIND_GROUND {
+                            let random_commands = vec![
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_JUMP_BUTTON,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_S3,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_HI3,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_LW3,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_S4,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_HI4,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_LW4,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_HI,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_S,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_HI,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_LW,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_CATCH,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F,
+                                *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B,
+                            ];
+
+                            let random_cmd_index = app::sv_math::rand(
+                                hash40("fighter"), random_commands.len() as i32) as usize;
+
+                            *flag |= random_commands[random_cmd_index];
+                        }
+                    }
+                },
+                _ => ()
+            }
+        }
+    }
+}
+
+pub unsafe fn check_button_on(
+    module_accessor: &mut app::BattleObjectModuleAccessor,
+    button: i32) -> Option<bool>
+{
+    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)) {
+                return Some(true)
+            }
+        }
+    }
+
+    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) {
+                return Some(true)
+            }
+        }
+    }
+
+    None
+}
\ No newline at end of file
diff --git a/src/training/Shield.rs b/src/training/Shield.rs
new file mode 100644
index 0000000..ec6c50a
--- /dev/null
+++ b/src/training/Shield.rs
@@ -0,0 +1,75 @@
+
+use smash::hash40;
+use smash::app::{self};
+use smash::app::lua_bind::*;
+use smash::lib::lua_const::*;
+use crate::common::*;
+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 param_type == hash40("common") {
+                if param_hash == hash40("shield_dec1") {
+                    return Some(0.0)
+                }
+                if param_hash == hash40("shield_recovery1") {
+                    return Some(999.0)
+                }
+                // doesn't work, somehow. This parameter isn't checked?
+                if param_hash == hash40("shield_damage_mul") {
+                    return Some(0.0)
+                }
+            }
+        }
+    }
+
+    None
+}
+
+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 we are not mashing then we will always hold shield
+        if menu.MASH_STATE == NONE {
+            return true
+        }
+
+        if !is_in_shieldstun(module_accessor) {
+            return true
+        }
+
+        // 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) {
+                return true
+            }
+        }
+    }
+
+    false
+}
+
+pub unsafe fn check_button_on(module_accessor: &mut app::BattleObjectModuleAccessor, button: i32) -> Option<bool> {
+    if [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) {
+        if is_training_mode() && is_operation_cpu(module_accessor) {
+            if should_hold_shield(module_accessor) {
+                return Some(true)
+            }
+        }
+    }
+
+    None
+}
+
+pub unsafe fn check_button_off(module_accessor: &mut app::BattleObjectModuleAccessor, button: i32) -> Option<bool> {
+    if [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button)  {
+        if is_training_mode() && is_operation_cpu(module_accessor) {
+            if should_hold_shield(module_accessor) {
+                return Some(false)
+            }
+        }
+    }
+
+    None
+}
\ No newline at end of file
diff --git a/src/training/Tech.rs b/src/training/Tech.rs
new file mode 100644
index 0000000..bc3309f
--- /dev/null
+++ b/src/training/Tech.rs
@@ -0,0 +1,144 @@
+use smash::{hash40, phx::Hash40};
+use smash::app::{self};
+use smash::app::lua_bind::*;
+use smash::lib::lua_const::*;
+use crate::common::*;
+use crate::common::consts::*;
+
+pub unsafe fn init_settings(
+    module_accessor: &mut app::BattleObjectModuleAccessor,
+    status_kind: i32) -> Option<()> 
+{
+    if is_training_mode() && is_operation_cpu(module_accessor) {
+        if status_kind == FIGHTER_STATUS_KIND_DOWN {
+            match menu.TECH_STATE {
+                RANDOM_TECH => {
+                    let random_statuses = vec![
+                        *FIGHTER_STATUS_KIND_DOWN,
+                        *FIGHTER_STATUS_KIND_PASSIVE,
+                        *FIGHTER_STATUS_KIND_PASSIVE_FB
+                    ];
+
+                    let random_status_index = app::sv_math::rand(hash40("fighter"), random_statuses.len() as i32) as usize;
+                    if random_statuses[random_status_index] != FIGHTER_STATUS_KIND_DOWN {
+                        StatusModule::change_status_request_from_script(
+                            module_accessor, 
+                            random_statuses[random_status_index], 
+                            true);
+                        return Some(())
+                    }
+                },
+                TECH_IN_PLACE => {
+                    StatusModule::change_status_request_from_script(
+                        module_accessor, 
+                        *FIGHTER_STATUS_KIND_PASSIVE, 
+                        true);
+                    return Some(())
+                },
+                TECH_ROLL => {
+                    StatusModule::change_status_request_from_script(
+                        module_accessor, 
+                        *FIGHTER_STATUS_KIND_PASSIVE_FB,
+                        true);
+                    return Some(())
+                },
+                _ => ()
+            }
+        }
+    }
+
+    None
+}
+
+pub unsafe fn should_perform_defensive_option(
+    module_accessor: &mut app::BattleObjectModuleAccessor, 
+    prev_status: i32, 
+    status: i32) -> bool 
+{
+    (
+        [*FIGHTER_STATUS_KIND_PASSIVE, 
+        *FIGHTER_STATUS_KIND_PASSIVE_FB,
+        *FIGHTER_STATUS_KIND_DOWN_STAND,
+        *FIGHTER_STATUS_KIND_DOWN_STAND_FB,
+        *FIGHTER_STATUS_KIND_DOWN_STAND_ATTACK].contains(&prev_status) ||
+
+        [*FIGHTER_STATUS_KIND_DOWN_STAND,
+        *FIGHTER_STATUS_KIND_DOWN_STAND_FB,
+        *FIGHTER_STATUS_KIND_DOWN_STAND_ATTACK].contains(&status)
+    ) 
+    &&
+    (
+        WorkModule::is_enable_transition_term(module_accessor, *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_GUARD_ON) || 
+        CancelModule::is_enable_cancel(module_accessor)
+    )
+}
+
+pub unsafe fn get_command_flag_cat(
+    module_accessor: &mut app::BattleObjectModuleAccessor,
+    category: i32,
+    flag: &mut i32) 
+{
+    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) {
+            let random_statuses = vec![
+                *FIGHTER_STATUS_KIND_DOWN_STAND,
+                *FIGHTER_STATUS_KIND_DOWN_STAND_FB,
+                *FIGHTER_STATUS_KIND_DOWN_STAND_ATTACK
+            ];
+
+            let random_status_index = app::sv_math::rand(hash40("fighter"), random_statuses.len() as i32) as usize;
+            StatusModule::change_status_request_from_script(module_accessor, random_statuses[random_status_index], true);
+        } else if should_perform_defensive_option(module_accessor, prev_status, status) {
+            perform_defensive_option(module_accessor, flag);
+        }
+    }
+}
+
+pub unsafe fn check_button_on(
+    module_accessor: &mut app::BattleObjectModuleAccessor,
+    button: i32) -> Option<bool> 
+{
+    if [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) {
+        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 && 
+                should_perform_defensive_option(module_accessor, prev_status, status) {
+                return Some(true)
+            }
+        }
+    }
+
+    None
+}
+
+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 [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"))
+            } else { 
+                return Some(hash40("passive_stand_b")) 
+            }
+        } else if [hash40("down_forward_u") | hash40("down_back_u")].contains(&motion_kind) {
+            if app::sv_math::rand(hash40("fighter"), 2) != 0 { 
+                return Some(hash40("down_forward_u"))
+            } else { 
+                return Some(hash40("down_back_u")) 
+            }
+        } else if [hash40("down_forward_d") | hash40("down_back_d")].contains(&motion_kind) {
+            if app::sv_math::rand(hash40("fighter"), 2) != 0 { 
+                return Some(hash40("down_forward_d"))
+            } else { 
+                return Some(hash40("down_back_d")) 
+            }
+        }
+    }
+
+    None
+}
\ No newline at end of file
diff --git a/src/training/mod.rs b/src/training/mod.rs
index a362ae8..9314e66 100644
--- a/src/training/mod.rs
+++ b/src/training/mod.rs
@@ -1,78 +1,74 @@
-use smash::hash40;
-use smash::app::BattleObjectModuleAccessor;
-use smash::app::sv_animcmd::{self};
-use smash::app::lua_bind::*;
-use smash::lib::{self, L2CAgent, L2CValue};
+use smash::app::{self, sv_system, sv_animcmd, lua_bind::*, FighterManager};
+use smash::lib::{self, L2CAgent, L2CValue, lua_const::*};
 use smash::phx::{Hash40, Vector3f};
-use smash::lib::lua_const::{*};
-use smash::app::sv_system::{self};
-use smash::app::{self};
-use skyline::logging::hex_dump_ptr;
+use smash::hash40;
+use skyline::{c_str, nn::ro::LookupSymbol, logging::hex_dump_ptr};
+use crate::common::fighter_manager_addr;
 use crate::common::*;
+use crate::common::consts::*;
+
+mod DirectionalInfluence;
+mod Shield;
+mod Tech;
+mod Mash;
+mod Ledge;
 
 #[allow(unused_unsafe)]
 #[skyline::hook(replace = WorkModule::get_float)]
-pub unsafe fn handle_get_float(module_accessor: *mut BattleObjectModuleAccessor, var: i32) -> f32 {
-    let mut replace = false;
-    //float ret = DirectionalInfluence::get_float(module_accessor, var, replace);
-    //if (replace) return ret;
-
-    original!()(module_accessor, var)
+pub unsafe fn handle_get_float(module_accessor: &mut app::BattleObjectModuleAccessor, var: i32) -> f32 {
+    DirectionalInfluence::get_float(module_accessor, var).unwrap_or_else( || {
+        original!()(module_accessor, var)
+    })
 }
 
-// float get_param_float_replace(u64 module_accessor, u64 param_type, u64 param_hash) {
-//     bool replace;
-//     float ret = Shield::get_param_float(module_accessor, param_type, param_hash, replace);
-//     if (replace) return ret;
+#[allow(unused_unsafe)]
+#[skyline::hook(replace = WorkModule::get_param_float)]
+pub unsafe fn handle_get_param_float(module_accessor: &mut app::BattleObjectModuleAccessor, param_type: u64, param_hash: u64) -> f32 {
+    Shield::get_param_float(module_accessor, param_type, param_hash).unwrap_or_else( || {
+        original!()(module_accessor, param_type, param_hash)
+    })
+}
 
-//     u64 work_module = load_module(module_accessor, 0x50);
-//     float (*get_param_float)(u64, u64, u64) = (float (*)(u64, u64, u64)) load_module_impl(work_module, 0x240);
-//     return get_param_float(work_module, param_type, param_hash);
-// }
-// }  // namespace WorkModule
+#[allow(unused_unsafe)]
+#[skyline::hook(replace = ControlModule::get_attack_air_kind)]
+pub unsafe fn handle_get_attack_air_kind(module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 {
+    // bool replace;
+    // int kind = InputRecorder::get_attack_air_kind(module_accessor, replace);
+    // if (replace) return kind;
 
-// namespace ControlModule {
-// int get_attack_air_kind_replace(u64 module_accessor) {
-//     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_else( || {
+        original!()(module_accessor)
+    })
+}
 
-//     kind = Mash::get_attack_air_kind(module_accessor, replace);
-//     if (replace) return kind;
+#[allow(unused_unsafe)]
+#[skyline::hook(replace = ControlModule::get_command_flag_cat)]
+pub unsafe fn handle_get_command_flag_cat(
+    module_accessor: &mut app::BattleObjectModuleAccessor,
+    category: i32) -> i32 
+{
+    //save_states(module_accessor);
 
-//     u64 control_module = load_module(module_accessor, 0x48);
-//     int (*get_attack_air_kind)(u64) = (int (*)(u64)) load_module_impl(control_module, 0x3B0);
-//     return get_attack_air_kind(control_module);
-// }
+    // Pause Effect AnimCMD if hitbox visualization is active
+    let status_kind = StatusModule::status_kind(module_accessor) as i32;
+    MotionAnimcmdModule::set_sleep_effect(module_accessor, 
+        is_training_mode() &&
+        menu.HITBOX_VIS &&
+        !((*FIGHTER_STATUS_KIND_CATCH..=*FIGHTER_STATUS_KIND_TREAD_FALL).contains(&status_kind) ||
+          (*FIGHTER_STATUS_KIND_WAIT..=*FIGHTER_STATUS_KIND_REBOUND_JUMP).contains(&status_kind)));
 
-// int get_command_flag_cat_replace(u64 module_accessor, int category) {
-//     int (*prev_replace)(u64, int) = (int (*)(u64, int)) prev_get_command_flag_cat;
-//     if (prev_replace)
-//         prev_replace(module_accessor, category);
-//     //save_states(module_accessor);
+    let mut flag = original!()(module_accessor, category);
 
-//     // Pause Effect AnimCMD if hitbox visualization is active
-//     int status_kind = StatusModule::status_kind(module_accessor);
-//     MotionAnimcmdModule::set_sleep_effect(module_accessor, 
-//         is_training_mode() &&
-//         menu.HITBOX_VIS &&
-//         !((status_kind >= FIGHTER_STATUS_KIND_CATCH && status_kind <= FIGHTER_STATUS_KIND_TREAD_FALL) ||
-//           (status_kind >= FIGHTER_STATUS_KIND_WAIT && status_kind <= FIGHTER_STATUS_KIND_REBOUND_JUMP)));
+    // bool replace;
+    // int ret = InputRecorder::get_command_flag_cat(module_accessor, category, flag, replace);
+    // if (replace) return ret;
 
-//     u64 control_module = load_module(module_accessor, 0x48);
-//     int (*get_command_flag_cat)(u64, int) = (int (*)(u64, int)) load_module_impl(control_module, 0x350);
-//     int flag = get_command_flag_cat(control_module, category);
+    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);
 
-//     // bool replace;
-//     // int ret = InputRecorder::get_command_flag_cat(module_accessor, category, flag, replace);
-//     // if (replace) return ret;
-
-//     Mash::get_command_flag_cat(module_accessor, category, flag);
-//     Ledge::get_command_flag_cat(module_accessor, category, flag);
-//     Tech::get_command_flag_cat(module_accessor, category, flag);
-
-//     return flag;
-// }
+    flag
+}
 
 // int get_pad_flag(u64 module_accessor) {
 //     u64 control_module = load_module(module_accessor, 0x48);
@@ -110,96 +106,93 @@ pub unsafe fn handle_get_float(module_accessor: *mut BattleObjectModuleAccessor,
 //     return stick_y;
 // }
 
-// bool check_button_on_replace(u64 module_accessor, int button) {
-//     bool replace;
-//     bool ret = Shield::check_button_on(module_accessor, button, replace);
-//     if (replace) return ret;
-//     ret = Mash::check_button_on(module_accessor, button, replace);
-//     if (replace) return ret;
-//     ret = Tech::check_button_on(module_accessor, button, replace);
-//     if (replace) return ret;
-//     ret = Ledge::check_button_on(module_accessor, button, replace);
-//     if (replace) return ret;
+#[allow(unused_unsafe)]
+#[skyline::hook(replace = ControlModule::check_button_on)]
+pub unsafe fn handle_check_button_on(
+    module_accessor: &mut app::BattleObjectModuleAccessor,
+    button: i32) -> bool
+{
+    Shield::check_button_on(module_accessor, button).unwrap_or_else( || {
+        Mash::check_button_on(module_accessor, button).unwrap_or_else( || {
+            Tech::check_button_on(module_accessor, button).unwrap_or_else( || {
+                Ledge::check_button_on(module_accessor, button).unwrap_or_else( || {
+                    original!()(module_accessor, button)
+                })
+            })
+        })
+    })
+}
 
-//     u64 control_module = load_module(module_accessor, 0x48);
-//     bool (*check_button_on)(u64, int) = (bool (*)(u64, int)) load_module_impl(control_module, 0x260);
-//     return check_button_on(control_module, button);
-// }
+#[allow(unused_unsafe)]
+#[skyline::hook(replace = ControlModule::check_button_off)]
+pub unsafe fn handle_check_button_off(
+    module_accessor: &mut app::BattleObjectModuleAccessor,
+    button: i32) -> bool
+{
+    Shield::check_button_off(module_accessor, button).unwrap_or_else( || {
+        original!()(module_accessor, button)
+    })
+}
 
-// bool check_button_off_replace(u64 module_accessor, int button) {
-//     bool replace;
-//     bool ret = Shield::check_button_off(module_accessor, button, replace);
-//     if (replace) return ret;
+#[allow(unused_unsafe)]
+#[skyline::hook(replace = StatusModule::init_settings)]
+pub unsafe fn handle_init_settings(
+    module_accessor: &mut app::BattleObjectModuleAccessor,
+    situationKind: i32, 
+    unk1: i32, 
+    unk2: u32, 
+    groundCliffCheckKind: i32,
+    unk3: bool, 
+    unk4: i32, 
+    unk5: i32, 
+    unk6: i32, 
+    unk7: i32)
+{
+    let status_kind = StatusModule::status_kind(module_accessor) as i32;
+    Tech::init_settings(module_accessor, status_kind).unwrap_or_else( || {
+        original!()(module_accessor, situationKind, unk1, unk2, groundCliffCheckKind, unk3, unk4, unk5, unk6, unk7)
+    })
+}
 
-//     u64 control_module = load_module(module_accessor, 0x48);
-//     bool (*check_button_off)(u64, int) = (bool (*)(u64, int)) load_module_impl(control_module, 0x268);
-//     return check_button_off(control_module, button);
-// }
-// }  // namespace ControlModule
-
-// namespace StatusModule {
-// void init_settings_replace(u64 module_accessor, int situationKind, int unk1, uint unk2, int groundCliffCheckKind, bool unk3, int unk4, int unk5, int unk6, int unk7) {
-//     bool replace;
-//     Tech::init_settings(module_accessor, StatusModule::status_kind(module_accessor), replace);
-//     if (replace) return;
-
-//     u64 status_module = load_module(module_accessor, 0x40);
-//     void (*init_settings)(u64,int,int,uint,int,bool,int,int,int,int) =
-//         (void (*)(u64,int,int,uint,int,bool,int,int,int,int)) load_module_impl(status_module, 0x1C8);
-
-//     init_settings(status_module, situationKind, unk1, unk2, groundCliffCheckKind, unk3, unk4, unk5, unk6, unk7);
-// }
-// }  // namespace StatusModule
-
-// namespace MotionModule {
-// u64 change_motion_replace(u64 module_accessor, u64 motion_kind, float unk1, float unk2, bool unk3, float unk4, bool unk5, bool unk6) {
-//     bool replace;
-//     u64 motion_kind_ret = Tech::change_motion(module_accessor, motion_kind, replace);
-//     if (replace) motion_kind = motion_kind_ret;
-
-//     u64 motion_module = load_module(module_accessor, 0x88);
-//     u64 change_motion_offset = 0;
-//     if (major < 4) change_motion_offset = 0xD8;
-//     else change_motion_offset = 0xE0;
-    
-//     u64 (*change_motion)(u64,u64,float,float,bool,float,bool,bool) = 
-//         (u64 (*)(u64,u64,float,float,bool,float,bool,bool)) load_module_impl(motion_module, change_motion_offset);
-
-//     return change_motion(motion_module, motion_kind, unk1, unk2, unk3, unk4, unk5, unk6);
-// }
-// }  // namespace MotionModule
-// }  // namespace app::lua_bind
+#[allow(unused_unsafe)]
+#[skyline::hook(replace = MotionModule::change_motion)]
+pub unsafe fn handle_change_motion(
+    module_accessor: &mut app::BattleObjectModuleAccessor,
+    motion_kind: u64, 
+    unk1: f32, 
+    unk2: f32, 
+    unk3: bool, 
+    unk4: f32, 
+    unk5: bool, 
+    unk6: bool) -> u64
+{
+    Tech::change_motion(module_accessor, motion_kind).unwrap_or_else( || {
+        original!()(module_accessor, motion_kind, unk1, unk2, unk3, unk4, unk5, unk6)
+    })
+}
 
 
 pub fn training_mods() {
-    println!("Applying hitbox visualization mods.");
-    // fighter_manager_addr = SaltySDCore_FindSymbol(
-    //     "_ZN3lib9SingletonIN3app14FighterManagerEE9instance_E");
+    println!("Applying training mods.");
+    unsafe {
+        LookupSymbol(&mut fighter_manager_addr, c_str("_ZN3lib9SingletonIN3app14FighterManagerEE9instance_E"));
+        println!("Lookup symbol output: {:#?}", fighter_manager_addr);
+    }
 
-    // // Mash airdodge/jump
-    // SaltySD_function_replace_sym_check_prev(
-    //     "_ZN3app8lua_bind40ControlModule__get_command_flag_cat_implEPNS_26BattleObjectModuleAccessorEi",
-    //     (u64)&ControlModule::get_command_flag_cat_replace,
-    //     prev_get_command_flag_cat);
+    // Mash airdodge/jump
+    skyline::install_hook!(handle_get_command_flag_cat);
 
     // Set DI
     skyline::install_hook!(handle_get_float);
 
     // Hold/Infinite shield
-    // SaltySD_function_replace_sym(
-    //     "_ZN3app8lua_bind35ControlModule__check_button_on_implEPNS_26BattleObjectModuleAccessorEi",
-    //     (u64)&ControlModule::check_button_on_replace);
-    // SaltySD_function_replace_sym(
-    //     "_ZN3app8lua_bind36ControlModule__check_button_off_implEPNS_26BattleObjectModuleAccessorEi",
-    //     (u64)&ControlModule::check_button_off_replace);
-    // SaltySD_function_replace_sym(
-    //     "_ZN3app8lua_bind32WorkModule__get_param_float_implEPNS_26BattleObjectModuleAccessorEmm",
-    //     (u64)&WorkModule::get_param_float_replace);
+    skyline::install_hook!(handle_check_button_on);
+    skyline::install_hook!(handle_check_button_off);
 
-    // // Mash attack
-    // SaltySD_function_replace_sym(
-    //     "_ZN3app8lua_bind39ControlModule__get_attack_air_kind_implEPNS_26BattleObjectModuleAccessorE",
-    //     (u64)&ControlModule::get_attack_air_kind_replace);
+    skyline::install_hook!(handle_get_param_float);
+
+    // Mash attack
+    skyline::install_hook!(handle_get_attack_air_kind);
 
     // // Input recorder
     // SaltySD_function_replace_sym(
@@ -209,11 +202,7 @@ pub fn training_mods() {
     //     "_ZN3app8lua_bind31ControlModule__get_stick_y_implEPNS_26BattleObjectModuleAccessorE",
     //     (u64)&ControlModule::get_stick_y_replace);
 
-    // // Tech options
-    // SaltySD_function_replace_sym(
-    //     "_ZN3app8lua_bind32StatusModule__init_settings_implEPNS_26BattleObjectModuleAccessorENS_13SituationKindEijNS_20GroundCliffCheckKindEbiiii",
-    //     (u64)&StatusModule::init_settings_replace);
-    // SaltySD_function_replace_sym(
-    //     "_ZN3app8lua_bind32MotionModule__change_motion_implEPNS_26BattleObjectModuleAccessorEN3phx6Hash40Effbfbb",
-    //     (u64)&MotionModule::change_motion_replace);
+    // Tech options
+    skyline::install_hook!(handle_init_settings);
+    skyline::install_hook!(handle_change_motion);
 }