diff --git a/src/static/img/crouch.svg b/src/static/img/crouch.svg
new file mode 100644
index 0000000..362a8d5
--- /dev/null
+++ b/src/static/img/crouch.svg
@@ -0,0 +1,96 @@
+
+
diff --git a/src/training/crouch.rs b/src/training/crouch.rs
new file mode 100644
index 0000000..54f4cac
--- /dev/null
+++ b/src/training/crouch.rs
@@ -0,0 +1,27 @@
+use crate::common::consts::OnOff;
+use crate::common::*;
+use smash::app::{lua_bind::StatusModule, BattleObjectModuleAccessor};
+use smash::lib::lua_const::*;
+
+pub unsafe fn mod_get_stick_y(module_accessor: &mut BattleObjectModuleAccessor) -> Option {
+ if !is_operation_cpu(module_accessor) {
+ return None;
+ }
+ let fighter_status_kind = StatusModule::status_kind(module_accessor);
+
+ if MENU.crouch == OnOff::On
+ && [
+ *FIGHTER_STATUS_KIND_WAIT,
+ *FIGHTER_STATUS_KIND_SQUAT,
+ *FIGHTER_STATUS_KIND_SQUAT_B,
+ *FIGHTER_STATUS_KIND_SQUAT_F,
+ *FIGHTER_STATUS_KIND_SQUAT_RV,
+ *FIGHTER_STATUS_KIND_SQUAT_WAIT,
+ ]
+ .contains(&fighter_status_kind)
+ {
+ Some(-1.0)
+ } else {
+ None
+ }
+}
diff --git a/src/training/mod.rs b/src/training/mod.rs
index c59f01e..2f1217a 100644
--- a/src/training/mod.rs
+++ b/src/training/mod.rs
@@ -15,6 +15,7 @@ pub mod buff;
pub mod charge;
pub mod clatter;
pub mod combo;
+pub mod crouch;
pub mod directional_influence;
pub mod frame_counter;
pub mod ledge;
@@ -189,7 +190,9 @@ pub unsafe fn get_stick_dir(module_accessor: &mut app::BattleObjectModuleAccesso
}
/**
- *
+ * Called when:
+ * Directional airdodge
+ * Crouching
*/
#[skyline::hook(replace = ControlModule::get_stick_y)]
pub unsafe fn get_stick_y(module_accessor: &mut app::BattleObjectModuleAccessor) -> f32 {
@@ -198,7 +201,8 @@ pub unsafe fn get_stick_y(module_accessor: &mut app::BattleObjectModuleAccessor)
return ori;
}
- air_dodge_direction::mod_get_stick_y(module_accessor).unwrap_or(ori)
+ air_dodge_direction::mod_get_stick_y(module_accessor)
+ .unwrap_or_else(|| crouch::mod_get_stick_y(module_accessor).unwrap_or(ori))
}
#[skyline::hook(replace = ControlModule::check_button_on)]
diff --git a/training_mod_consts/src/lib.rs b/training_mod_consts/src/lib.rs
index d7ef0d0..992645c 100644
--- a/training_mod_consts/src/lib.rs
+++ b/training_mod_consts/src/lib.rs
@@ -1049,6 +1049,7 @@ url_params! {
pub falling_aerials: BoolFlag,
pub aerial_delay: Delay,
pub full_hop: BoolFlag,
+ pub crouch: OnOff,
pub input_delay: i32,
pub save_damage: OnOff,
pub save_state_mirroring: SaveStateMirroring,
@@ -1092,6 +1093,7 @@ impl TrainingModpackMenu {
air_dodge_dir = Direction::from_bits(val),
attack_angle = AttackAngle::from_bits(val),
clatter_strength = num::FromPrimitive::from_u32(val),
+ crouch = OnOff::from_val(val),
defensive_state = Defensive::from_bits(val),
di_state = Direction::from_bits(val),
falling_aerials = BoolFlag::from_bits(val),
@@ -1179,6 +1181,7 @@ pub static DEFAULTS_MENU: TrainingModpackMenu = TrainingModpackMenu {
falling_aerials: BoolFlag::empty(),
aerial_delay: Delay::empty(),
full_hop: BoolFlag::empty(),
+ crouch: OnOff::Off,
input_delay: 0,
save_damage: OnOff::On,
save_state_mirroring: SaveStateMirroring::None,
@@ -1507,6 +1510,12 @@ pub unsafe fn get_menu() -> UiMenu<'static> {
"Character Item: CPU/Player item to hold when loading a save state",
true
);
+ defensive_tab.add_submenu_with_toggles::(
+ "Crouch",
+ "crouch",
+ "Crouch: Should the CPU crouch when on the ground",
+ true
+ );
overall_menu.tabs.push(defensive_tab);
let mut misc_tab = Tab {