From 7ff8185a65e57167fa547a994ed3e6a95f382dc3 Mon Sep 17 00:00:00 2001
From: sidschingis <SijingYou92@gmail.com>
Date: Fri, 14 Aug 2020 21:12:50 +0200
Subject: [PATCH] Apply Bit Flags to Mash/Defensive Options (#136)

* Apply Bit Flag

Defensive Options

* Apply Bit Flag

Followups

* Apply Bit Flag

Mash options

* Update Version String
---
 TrainingModpackOverlay/Makefile               |   4 +-
 .../include/taunt_toggles.hpp                 |  57 +++--
 TrainingModpackOverlay/source/gui_main.cpp    |  53 ++--
 src/common/consts.rs                          | 236 ++++--------------
 src/common/mod.rs                             |   7 +-
 src/training/ledge.rs                         |   2 +-
 src/training/mash.rs                          | 171 ++++---------
 src/training/shield.rs                        |  35 +--
 8 files changed, 175 insertions(+), 390 deletions(-)

diff --git a/TrainingModpackOverlay/Makefile b/TrainingModpackOverlay/Makefile
index 039c7cf..260746f 100644
--- a/TrainingModpackOverlay/Makefile
+++ b/TrainingModpackOverlay/Makefile
@@ -38,7 +38,7 @@ include $(DEVKITPRO)/libnx/switch_rules
 #   NACP building is skipped as well.
 #---------------------------------------------------------------------------------
 APP_TITLE	:=	Training Modpack
-APP_VERSION	:=	2.05
+APP_VERSION	:=	2.1 Beta
 
 TARGET		:=	ovlTrainingModpack
 BUILD		:=	build
@@ -189,7 +189,7 @@ DEPENDS	:=	$(OFILES:.o=.d)
 #---------------------------------------------------------------------------------
 all	:	 $(OUTPUT).ovl
 
-$(OUTPUT).ovl		:	$(OUTPUT).elf $(OUTPUT).nacp 
+$(OUTPUT).ovl		:	$(OUTPUT).elf $(OUTPUT).nacp
 	@elf2nro $< $@ $(NROFLAGS)
 	@echo "built ... $(notdir $(OUTPUT).ovl)"
 
diff --git a/TrainingModpackOverlay/include/taunt_toggles.hpp b/TrainingModpackOverlay/include/taunt_toggles.hpp
index b0de8bc..ff4b40a 100644
--- a/TrainingModpackOverlay/include/taunt_toggles.hpp
+++ b/TrainingModpackOverlay/include/taunt_toggles.hpp
@@ -56,7 +56,7 @@ Currently only used for
 #define MASH_SIDE_B 6
 #define MASH_UP_B 7
 #define MASH_DOWN_B 8
-#define MASH_UP_SMASH 9
+#define MASH_U_SMASH 9
 #define MASH_GRAB 10
 const std::vector<std::string> attack_items{"Neutral Air",
                                             "Forward Air",
@@ -125,6 +125,28 @@ Specific tech options can be chosen and include:
 CPUs will also perform a defensive
 option after getting up.)"""";
 
+// Defensive States
+
+// clang-format off
+#define ENUM_CLASS_DefensiveFlag(type,x) \
+	x(type,SpotDodge,"Spotdodge") \
+	x(type,RollF,"RollF") \
+	x(type,RollB,"RollB") \
+	x(type,Jab,"Jab")\
+	x(type,Shield,"Shield")
+
+// clang-format on
+DEFINE_ENUM_CLASS(DefensiveFlag);
+
+const std::string defensive_help = R""""(
+Choose the defensive option a CPU
+will perform after teching or
+getting up from the ledge.
+
+Specific options include:
+    Flash shield, spotdodge, and jab
+)"""";
+
 // Mash States
 #define MASH_AIRDODGE 1
 #define MASH_JUMP 2
@@ -160,10 +182,19 @@ Random
 - Hitstun, shieldstun, landing.)"""";
 
 // Action items (Follow Up only atm)
-const std::vector<std::string> action_items{"None",        "Airdodge",    "Jump",     "Spotdodge", "Roll F",   "Roll B",
-                                            "Neutral Air", "Forward Air", "Back Air", "Up Air",    "Down Air", "Neutral B",
-                                            "Side B",      "Up B",        "Down B",   "Up Smash",  "F Smash",  "D Smash",
-                                            "Grab",        "Jab",         "Filt",     "Utilt",     "Dtilt",    "Dash Attack"};
+
+// clang-format off
+#define ENUM_CLASS_ActionFlag(type,x) \
+	x(type,Airdodge,"Airdodge") x(type,Jump,"Jump") x(type,Shield,"Shield") x(type,Spotdodge,"Spotdodge") x(type,RollF,"Roll F") x(type,RollB,"Roll B")  \
+    x(type,Nair,"Neutral Air") x(type,Fair,"Forward Air") x(type,Bair,"Back Air") x(type,Uair,"Up Air") x(type,Dair,"Down Air")  \
+    x(type,NeutralB,"Neutral B") x(type,SideB,"Side B") x(type,UpB,"Up B") x(type,DownB,"Down B") \
+    x(type,FSmash,"Forward Smash") x(type,USmash,"Up Smash") x(type,DSmash,"Down Smash") \
+    x(type,Jab,"Jab") x(type,FTilt,"Filt") x(type,UTilt,"Utilt") x(type,Dtilt,"Dtilt")  \
+    x(type,DashAttack,"Dash Attack") x(type,Grab,"Grab")
+
+// clang-format on
+DEFINE_ENUM_CLASS(ActionFlag);
+
 const std::string              follow_up_help = R""""(
 Action to buffer
 after the first mash option
@@ -186,22 +217,6 @@ by damage.
 Hold
 CPUs will hold a normal shield.)"""";
 
-// Defensive States
-#define RANDOM_DEFENSIVE 1
-#define DEFENSIVE_SPOTDODGE 2
-#define DEFENSIVE_ROLL 3
-#define DEFENSIVE_JAB 4
-#define DEFENSIVE_SHIELD 5
-const std::vector<std::string> defensive_items{"None", "Random", "Spotdodge", "Roll", "Jab", "Flash Shield"};
-const std::string              defensive_help = R""""(
-Choose the defensive option a CPU
-will perform after teching or
-getting up from the ledge.
-
-Specific options include:
-    Flash shield, spotdodge, and jab
-)"""";
-
 // Hitbox visualization
 const std::string hitbox_help = R""""(
 Currently, hitboxes and
diff --git a/TrainingModpackOverlay/source/gui_main.cpp b/TrainingModpackOverlay/source/gui_main.cpp
index 8291f2d..6204cd4 100644
--- a/TrainingModpackOverlay/source/gui_main.cpp
+++ b/TrainingModpackOverlay/source/gui_main.cpp
@@ -7,23 +7,22 @@
 
 static struct TrainingModpackMenu
 {
-	int        HITBOX_VIS      = true;
-	int        DI_STATE        = NONE;
-	int        LEFT_STICK      = NONE;
-	int        ATTACK_STATE    = MASH_NAIR;
-	int        FOLLOW_UP       = 0;
-	LedgeFlags LEDGE_STATE     = LedgeFlags::All;
-	TechFlags  TECH_STATE      = TechFlags::All;
-	int        MASH_STATE      = NONE;
-	int        SHIELD_STATE    = NONE;
-	int        DEFENSIVE_STATE = RANDOM_DEFENSIVE;
-	int        OOS_OFFSET      = 0;
-	int        REACTION_TIME   = 0;
-	int        MASH_IN_NEUTRAL = false;
-	int        FAST_FALL       = false;
-	int        FAST_FALL_DELAY = 0;
-	int        FALLING_AERIALS = false;
-	int        FULL_HOP        = false;
+	int            HITBOX_VIS      = true;
+	int            DI_STATE        = NONE;
+	int            LEFT_STICK      = NONE;
+	ActionFlags    MASH_STATE      = ActionFlags::None;
+	ActionFlags    FOLLOW_UP       = ActionFlags::None;
+	LedgeFlags     LEDGE_STATE     = LedgeFlags::All;
+	TechFlags      TECH_STATE      = TechFlags::All;
+	int            SHIELD_STATE    = NONE;
+	DefensiveFlags DEFENSIVE_STATE = DefensiveFlags::All;
+	int            OOS_OFFSET      = 0;
+	int            REACTION_TIME   = 0;
+	int            MASH_IN_NEUTRAL = false;
+	int            FAST_FALL       = false;
+	int            FAST_FALL_DELAY = 0;
+	int            FALLING_AERIALS = false;
+	int            FULL_HOP        = false;
 } menu;
 
 static int FRAME_ADVANTAGE = 0;
@@ -390,19 +389,9 @@ tsl::elm::Element* GuiMain::createUI()
 			list->addItem(shieldItem);
 			valueListItems.push_back(shieldItem);
 
-			ValueListItem* mashItem = new ValueListItem("Mash Toggles", mash_items, &menu.MASH_STATE, "mash", mash_help);
-			list->addItem(mashItem);
-			valueListItems.push_back(mashItem);
+			list->addItem(createBitFlagOption(&menu.MASH_STATE, "Mash Toggles", mash_help));
 
-			ValueListItem* attackItem =
-			    new ValueListItem("Attack Toggles", attack_items, &menu.ATTACK_STATE, "attack", attack_help);
-			list->addItem(attackItem);
-			valueListItems.push_back(attackItem);
-
-			ValueListItem* followUp =
-			    new ValueListItem("Followup Toggles", action_items, &menu.FOLLOW_UP, "followUp", follow_up_help);
-			list->addItem(followUp);
-			valueListItems.push_back(followUp);
+			list->addItem(createBitFlagOption(&menu.FOLLOW_UP, "Followup Toggles", follow_up_help));
 
 			ValueListItem* mashNeutralItem =
 			    new ValueListItem("Mash In Neutral", on_off, &menu.MASH_IN_NEUTRAL, "mash_neutral", mash_neutral_help);
@@ -410,12 +399,10 @@ tsl::elm::Element* GuiMain::createUI()
 			valueListItems.push_back(mashNeutralItem);
 
 			list->addItem(createBitFlagOption(&menu.LEDGE_STATE, "Ledge Options", ledge_help));
+
 			list->addItem(createBitFlagOption(&menu.TECH_STATE, "Tech Options", tech_help));
 
-			ValueListItem* defensiveItem =
-			    new ValueListItem("Defensive Options", defensive_items, &menu.DEFENSIVE_STATE, "defensive", defensive_help);
-			list->addItem(defensiveItem);
-			valueListItems.push_back(defensiveItem);
+			list->addItem(createBitFlagOption(&menu.DEFENSIVE_STATE, "Defensive Options", defensive_help));
 
 			ValueListItem* diItem = new ValueListItem("Set DI", di_items, &menu.DI_STATE, "di", di_help);
 			list->addItem(diItem);
diff --git a/src/common/consts.rs b/src/common/consts.rs
index fcc9916..9cebf4e 100644
--- a/src/common/consts.rs
+++ b/src/common/consts.rs
@@ -60,59 +60,6 @@ pub fn direction_to_angle(direction: Direction) -> f64 {
     }
 }
 
-/// Mash Attack States
-#[repr(i32)]
-#[derive(PartialEq, Debug, Copy, Clone)]
-pub enum Attack {
-    Nair = 0,
-    Fair = 1,
-    Bair = 2,
-    UpAir = 3,
-    Dair = 4,
-    NeutralB = 5,
-    SideB = 6,
-    UpB = 7,
-    DownB = 8,
-    UpSmash = 9,
-    FSmash = 10,
-    DSmash = 11,
-    Grab = 12,
-    Jab = 13,
-    Ftilt = 14,
-    Utilt = 15,
-    Dtilt = 16,
-    DashAttack = 17,
-    Nothing = 9999,
-}
-
-impl From<i32> for Attack {
-    fn from(x: i32) -> Self {
-        use Attack::*;
-
-        match x {
-            0 => Nair,
-            1 => Fair,
-            2 => Bair,
-            3 => UpAir,
-            4 => Dair,
-            5 => NeutralB,
-            6 => SideB,
-            7 => UpB,
-            8 => DownB,
-            9 => UpSmash,
-            10 => FSmash,
-            11 => DSmash,
-            12 => Grab,
-            13 => Jab,
-            14 => Ftilt,
-            15 => Utilt,
-            16 => Dtilt,
-            17 => DashAttack,
-            _ => Nothing,
-        }
-    }
-}
-
 // bitflag helper function macro
 macro_rules! to_vec_impl {
     ($e:ty) => {
@@ -152,10 +99,10 @@ macro_rules! get_random_impl {
 bitflags! {
     pub struct LedgeOption : u32
     {
-        const NEUTRAL = 0b1;
-        const ROLL = 0b10;
-        const JUMP = 0b100;
-        const ATTACK = 0b1000;
+        const NEUTRAL = 0x1;
+        const ROLL = 0x2;
+        const JUMP = 0x4;
+        const ATTACK = 0x8;
     }
 }
 
@@ -192,37 +139,6 @@ impl TechFlags {
     get_random_impl! {TechFlags}
 }
 
-/// Mash States
-#[repr(i32)]
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub enum Mash {
-    None = 0,
-    Airdodge = 1,
-    Jump = 2,
-    Attack = 3,
-    Spotdodge = 4,
-    RollForward = 5,
-    RollBack = 6,
-    Random = 7,
-    Shield = 99,
-}
-
-impl From<i32> for Mash {
-    fn from(x: i32) -> Self {
-        match x {
-            0 => Mash::None,
-            1 => Mash::Airdodge,
-            2 => Mash::Jump,
-            3 => Mash::Attack,
-            4 => Mash::Spotdodge,
-            5 => Mash::RollForward,
-            6 => Mash::RollBack,
-            7 => Mash::Random,
-            _ => panic!("Invalid mash state {}", x),
-        }
-    }
-}
-
 /// Shield States
 #[repr(i32)]
 #[derive(Debug, Clone, Copy, PartialEq)]
@@ -233,31 +149,19 @@ pub enum Shield {
 }
 
 // Defensive States
-#[repr(i32)]
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub enum Defensive {
-    None = 0,
-    Random = 1,
-    Spotdodge = 2,
-    Roll = 3,
-    Jab = 4,
-    Shield = 5,
+bitflags! {
+    pub struct Defensive : u32 {
+        const SPOT_DODGE = 0x1;
+        const ROLL_F = 0x2;
+        const ROLL_B = 0x4;
+        const JAB = 0x8;
+        const SHIELD = 0x10;
+    }
 }
 
-impl From<i32> for Defensive {
-    fn from(x: i32) -> Self {
-        use Defensive::*;
-
-        match x {
-            0 => None,
-            1 => Random,
-            2 => Spotdodge,
-            3 => Roll,
-            4 => Jab,
-            5 => Shield,
-            _ => panic!("Invalid mash state {}", x),
-        }
-    }
+impl Defensive {
+    to_vec_impl! {Defensive}
+    get_random_impl! {Defensive}
 }
 
 #[repr(i32)]
@@ -267,85 +171,48 @@ pub enum OnOff {
     On = 1,
 }
 
-#[repr(i32)]
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub enum Action {
-    Nothing = 0,
-    Airdodge = 1,
-    Jump = 2,
-    Spotdodge = 3,
-    RollForward = 4,
-    RollBack = 5,
-    Nair = 6,
-    Fair = 7,
-    Bair = 8,
-    UpAir = 9,
-    Dair = 10,
-    NeutralB = 11,
-    SideB = 12,
-    UpB = 13,
-    DownB = 14,
-    UpSmash = 15,
-    FSmash = 16,
-    DSmash = 17,
-    Grab = 18,
-    Jab = 19,
-    Ftilt = 20,
-    Utilt = 21,
-    Dtilt = 22,
-    DashAttack = 23,
-    Shield = 99,
+bitflags! {
+    pub struct Action : u32 {
+        const AIR_DODGE = 0x1;
+        const JUMP = 0x2;
+        const SHIELD = 0x4;
+        const SPOT_DODGE = 0x8;
+        const ROLL_F = 0x10;
+        const ROLL_B = 0x20;
+        const NAIR = 0x40;
+        const FAIR = 0x80;
+        const BAIR = 0x100;
+        const UAIR = 0x200;
+        const DAIR = 0x400;
+        const NEUTRAL_B = 0x800;
+        const SIDE_B = 0x1000;
+        const UP_B = 0x2000;
+        const DOWN_B = 0x4000;
+        const F_SMASH = 0x8000;
+        const U_SMASH = 0x10000;
+        const D_SMASH = 0x20000;
+        const JAB = 0x40000;
+        const F_TILT = 0x80000;
+        const U_TILT  = 0x100000;
+        const D_TILT  = 0x200000;
+        const DASH_ATTACK = 0x400000;
+        const GRAB = 0x800000;
+    }
 }
 
 impl Action {
     pub fn into_attack_air_kind(&self) -> Option<i32> {
-        use Action::*;
-
-        Some(match self {
-            Nair => *FIGHTER_COMMAND_ATTACK_AIR_KIND_N,
-            Fair => *FIGHTER_COMMAND_ATTACK_AIR_KIND_F,
-            Bair => *FIGHTER_COMMAND_ATTACK_AIR_KIND_B,
-            Dair => *FIGHTER_COMMAND_ATTACK_AIR_KIND_LW,
-            UpAir => *FIGHTER_COMMAND_ATTACK_AIR_KIND_HI,
+        Some(match *self {
+            Action::NAIR => *FIGHTER_COMMAND_ATTACK_AIR_KIND_N,
+            Action::FAIR => *FIGHTER_COMMAND_ATTACK_AIR_KIND_F,
+            Action::BAIR => *FIGHTER_COMMAND_ATTACK_AIR_KIND_B,
+            Action::DAIR => *FIGHTER_COMMAND_ATTACK_AIR_KIND_LW,
+            Action::UAIR => *FIGHTER_COMMAND_ATTACK_AIR_KIND_HI,
             _ => return None,
         })
     }
-}
-
-// To satisfy the unused warning
-impl From<i32> for Action {
-    fn from(x: i32) -> Self {
-        use Action::*;
-
-        match x {
-            0 => Nothing,
-            1 => Airdodge,
-            2 => Jump,
-            3 => Spotdodge,
-            4 => RollForward,
-            5 => RollBack,
-            6 => Nair,
-            7 => Fair,
-            8 => Bair,
-            9 => UpAir,
-            10 => Dair,
-            11 => NeutralB,
-            12 => SideB,
-            13 => UpB,
-            14 => DownB,
-            15 => UpSmash,
-            16 => FSmash,
-            17 => DSmash,
-            18 => Grab,
-            19 => Jab,
-            20 => Ftilt,
-            21 => Utilt,
-            22 => Dtilt,
-            23 => DashAttack,
-            99 => Shield,
-            _ => Nothing,
-        }
-    }
+    to_vec_impl! {Action}
+    get_random_impl! {Action}
 }
 
 #[repr(C)]
@@ -353,11 +220,10 @@ pub struct TrainingModpackMenu {
     pub hitbox_vis: HitboxVisualization,
     pub di_state: Direction,
     pub left_stick: Direction, // Currently only used for air dodge direction
-    pub mash_attack_state: Attack,
+    pub mash_state: Action,
     pub follow_up: Action,
     pub ledge_state: LedgeOption,
     pub tech_state: TechFlags,
-    pub mash_state: Mash,
     pub shield_state: Shield,
     pub defensive_state: Defensive,
     pub oos_offset: u32,
diff --git a/src/common/mod.rs b/src/common/mod.rs
index b5260fc..9d60c47 100644
--- a/src/common/mod.rs
+++ b/src/common/mod.rs
@@ -9,13 +9,12 @@ pub static mut MENU_STRUCT: consts::TrainingModpackMenu = consts::TrainingModpac
     hitbox_vis: HitboxVisualization::On,
     di_state: Direction::None,
     left_stick: Direction::None,
-    mash_attack_state: Attack::Nair,
-    follow_up: Action::Nothing,
+    mash_state: Action::empty(),
+    follow_up: Action::empty(),
     ledge_state: LedgeOption::all(),
     tech_state: TechFlags::all(),
-    mash_state: Mash::None,
     shield_state: Shield::None,
-    defensive_state: Defensive::Random,
+    defensive_state: Defensive::all(),
     oos_offset: 0,
     reaction_time: 0,
     mash_in_neutral: OnOff::Off,
diff --git a/src/training/ledge.rs b/src/training/ledge.rs
index f0d37c6..d34db02 100644
--- a/src/training/ledge.rs
+++ b/src/training/ledge.rs
@@ -32,7 +32,7 @@ pub unsafe fn force_option(module_accessor: &mut app::BattleObjectModuleAccessor
 
     match ledge_case {
         LedgeOption::JUMP => {
-            mash::buffer_menu_mash(module_accessor);
+            mash::buffer_menu_mash();
         }
         _ => mash::perform_defensive_option(),
     }
diff --git a/src/training/mash.rs b/src/training/mash.rs
index 94baf5b..fda4fe8 100644
--- a/src/training/mash.rs
+++ b/src/training/mash.rs
@@ -6,7 +6,7 @@ use crate::training::shield;
 use smash::app::{self, lua_bind::*};
 use smash::lib::lua_const::*;
 
-static mut CURRENT_AERIAL: Action = Action::Nair;
+static mut CURRENT_AERIAL: Action = Action::NAIR;
 static mut QUEUE: Vec<Action> = vec![];
 
 pub fn buffer_action(action: Action) {
@@ -29,7 +29,7 @@ pub fn buffer_follow_up() {
         action = MENU.follow_up;
     }
 
-    if action == Action::Nothing {
+    if action == Action::empty() {
         return;
     }
 
@@ -40,8 +40,11 @@ pub fn buffer_follow_up() {
 
 pub fn get_current_buffer() -> Action {
     unsafe {
-        let current = QUEUE.last().unwrap_or(&Action::Nothing);
-        *current
+        if QUEUE.len() == 0 {
+            return Action::empty();
+        }
+
+        return *QUEUE.last().unwrap();
     }
 }
 
@@ -116,7 +119,7 @@ unsafe fn check_buffer(module_accessor: &mut app::BattleObjectModuleAccessor) {
         return;
     }
 
-    buffer_menu_mash(module_accessor);
+    buffer_menu_mash();
 }
 
 fn should_reset(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
@@ -165,83 +168,20 @@ fn should_buffer(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool
 }
 
 // Temp Translation
-pub fn buffer_menu_mash(module_accessor: &mut app::BattleObjectModuleAccessor) -> Action {
+pub fn buffer_menu_mash() -> Action {
     unsafe {
-        let action;
-        if MENU.mash_state == Mash::Random {
-            action = get_random_action(module_accessor);
-        } else {
-            action = mash_to_action(MENU.mash_state);
-        }
+        let action = MENU.mash_state.get_random();
         buffer_action(action);
 
         action
     }
 }
 
-pub fn mash_to_action(mash: Mash) -> Action {
-    use Action::*;
-    match mash {
-        Mash::Airdodge => Airdodge,
-        Mash::Jump => Jump,
-        Mash::Spotdodge => Spotdodge,
-        Mash::RollForward => RollForward,
-        Mash::RollBack => RollBack,
-        Mash::Shield => Shield,
-        Mash::Attack => unsafe { attack_to_action(MENU.mash_attack_state) },
-        _ => Nothing,
-    }
-}
-
-fn get_random_action(module_accessor: &mut app::BattleObjectModuleAccessor) -> Action {
-    let mut random_cmds = vec![Mash::Jump, Mash::Attack];
-    if is_airborne(module_accessor) {
-        random_cmds.push(Mash::Airdodge);
-    }
-
-    if is_grounded(module_accessor) {
-        random_cmds.push(Mash::RollBack);
-        random_cmds.push(Mash::RollForward);
-        random_cmds.push(Mash::Spotdodge);
-    }
-
-    let random_cmd_index = get_random_int(random_cmds.len() as i32) as usize;
-
-    mash_to_action(random_cmds[random_cmd_index])
-}
-
-fn attack_to_action(attack: Attack) -> Action {
-    use Action::*;
-    match attack {
-        Attack::Nair => Nair,
-        Attack::Fair => Fair,
-        Attack::Bair => Bair,
-        Attack::UpAir => UpAir,
-        Attack::Dair => Dair,
-        Attack::NeutralB => NeutralB,
-        Attack::SideB => SideB,
-        Attack::UpB => UpB,
-        Attack::DownB => DownB,
-        Attack::UpSmash => UpSmash,
-        Attack::FSmash => FSmash,
-        Attack::DSmash => DSmash,
-        Attack::Grab => Grab,
-        Attack::Jab => Jab,
-        Attack::Ftilt => Ftilt,
-        Attack::Utilt => Utilt,
-        Attack::Dtilt => Dtilt,
-        Attack::DashAttack => DashAttack,
-        Attack::Nothing => Nothing,
-    }
-}
-
 unsafe fn perform_action(module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 {
-    use Action::*;
-
     let action = get_current_buffer();
 
     match action {
-        Airdodge => {
+        Action::AIR_DODGE => {
             let expected_status;
             let command_flag;
             // Shield if grounded instead
@@ -259,31 +199,31 @@ unsafe fn perform_action(module_accessor: &mut app::BattleObjectModuleAccessor)
 
             return get_flag(module_accessor, expected_status, command_flag);
         }
-        Jump => {
+        Action::JUMP => {
             return update_jump_flag(module_accessor);
         }
-        Spotdodge => {
+        Action::SPOT_DODGE => {
             return get_flag(
                 module_accessor,
                 *FIGHTER_STATUS_KIND_ESCAPE,
                 *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE,
             );
         }
-        RollForward => {
+        Action::ROLL_F => {
             return get_flag(
                 module_accessor,
                 *FIGHTER_STATUS_KIND_ESCAPE_F,
                 *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F,
             );
         }
-        RollBack => {
+        Action::ROLL_B => {
             return get_flag(
                 module_accessor,
                 *FIGHTER_STATUS_KIND_ESCAPE_B,
                 *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B,
             );
         }
-        Shield => {
+        Action::SHIELD => {
             /*
             Doesn't actually cause the shield, but will clear the buffer once shield is possible.
             Shield hold is performed through shield::should_hold_shield and request_shield
@@ -300,8 +240,8 @@ unsafe fn perform_action(module_accessor: &mut app::BattleObjectModuleAccessor)
 
 pub fn request_shield(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
     match get_current_buffer() {
-        Action::Shield => return true,
-        Action::Airdodge => return is_grounded(module_accessor),
+        Action::SHIELD => return true,
+        Action::AIR_DODGE => return is_grounded(module_accessor),
         _ => {}
     }
 
@@ -325,44 +265,42 @@ unsafe fn get_attack_flag(
     module_accessor: &mut app::BattleObjectModuleAccessor,
     action: Action,
 ) -> i32 {
-    use Action::*;
-
     let command_flag: i32;
     let status: i32;
 
     match action {
-        Nair | Fair | Bair | UpAir | Dair => {
+        Action::NAIR | Action::FAIR | Action::BAIR | Action::UAIR | Action::DAIR => {
             return get_aerial_flag(module_accessor, action);
         }
-        NeutralB => {
+        Action::NEUTRAL_B => {
             command_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_N;
             status = *FIGHTER_STATUS_KIND_SPECIAL_N;
         }
-        SideB => {
+        Action::SIDE_B => {
             command_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_S;
             status = *FIGHTER_STATUS_KIND_SPECIAL_S;
         }
-        UpB => {
+        Action::UP_B => {
             command_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_HI;
             status = *FIGHTER_STATUS_KIND_SPECIAL_HI;
         }
-        DownB => {
+        Action::DOWN_B => {
             command_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_LW;
             status = *FIGHTER_STATUS_KIND_SPECIAL_LW;
         }
-        UpSmash => {
+        Action::U_SMASH => {
             command_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_HI4;
             status = *FIGHTER_STATUS_KIND_ATTACK_HI4_START;
         }
-        FSmash => {
+        Action::F_SMASH => {
             command_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_S4;
             status = *FIGHTER_STATUS_KIND_ATTACK_S4_START;
         }
-        DSmash => {
+        Action::D_SMASH => {
             command_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_LW4;
             status = *FIGHTER_STATUS_KIND_ATTACK_LW4_START;
         }
-        Grab => {
+        Action::GRAB => {
             let cannot_grab = WorkModule::get_int(
                 module_accessor,
                 *FIGHTER_INSTANCE_WORK_ID_INT_INVALID_CATCH_FRAME,
@@ -374,7 +312,7 @@ unsafe fn get_attack_flag(
             command_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_CATCH;
             status = *FIGHTER_STATUS_KIND_CATCH;
         }
-        Jab => {
+        Action::JAB => {
             // Prevent nair when airborne
             if !is_grounded(module_accessor) {
                 return 0;
@@ -383,19 +321,19 @@ unsafe fn get_attack_flag(
             command_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N;
             status = *FIGHTER_STATUS_KIND_ATTACK;
         }
-        Ftilt => {
+        Action::F_TILT => {
             command_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_S3;
             status = *FIGHTER_STATUS_KIND_ATTACK_S3;
         }
-        Utilt => {
+        Action::U_TILT => {
             command_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_HI3;
             status = *FIGHTER_STATUS_KIND_ATTACK_HI3;
         }
-        Dtilt => {
+        Action::D_TILT => {
             command_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_LW3;
             status = *FIGHTER_STATUS_KIND_ATTACK_LW3;
         }
-        DashAttack => {
+        Action::DASH_ATTACK => {
             let current_status = StatusModule::status_kind(module_accessor);
             let is_dashing = current_status == *FIGHTER_STATUS_KIND_DASH;
 
@@ -444,14 +382,14 @@ unsafe fn get_aerial_flag(
         return flag;
     }
 
-    use Action::*;
-
     /*
      * We always trigger attack and change it later into the correct aerial
      * @see get_attack_air_kind()
      */
     let command_flag: i32 = match action {
-        Nair | Fair | Bair | UpAir | Dair => *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N,
+        Action::NAIR | Action::FAIR | Action::BAIR | Action::UAIR | Action::DAIR => {
+            *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N
+        }
         _ => 0,
     };
 
@@ -509,37 +447,14 @@ fn try_change_status(
 pub unsafe fn perform_defensive_option() {
     reset();
 
-    let action;
-
-    match MENU.defensive_state {
-        Defensive::Random => {
-            let random_cmds = vec![
-                Mash::Spotdodge,
-                Mash::RollBack,
-                Mash::RollForward,
-                Mash::Attack,
-            ];
-
-            let random_cmd_index = get_random_int(random_cmds.len() as i32) as usize;
-
-            action = mash_to_action(random_cmds[random_cmd_index]);
-        }
-        Defensive::Roll => {
-            if get_random_int(2) == 0 {
-                action = Action::RollForward;
-            } else {
-                action = Action::RollBack;
-            }
-        }
-        Defensive::Spotdodge => action = Action::Spotdodge,
-        Defensive::Jab => {
-            action = Action::Jab;
-        }
-        Defensive::Shield => {
-            action = Action::Shield;
-        }
-        _ => return,
-    }
+    let action = match MENU.defensive_state.get_random() {
+        Defensive::ROLL_F => Action::ROLL_F,
+        Defensive::ROLL_B => Action::ROLL_B,
+        Defensive::SPOT_DODGE => Action::SPOT_DODGE,
+        Defensive::JAB => Action::JAB,
+        Defensive::SHIELD => Action::SHIELD,
+        _ => Action::empty(),
+    };
 
     buffer_action(action);
 
diff --git a/src/training/shield.rs b/src/training/shield.rs
index 59d0e03..0a2ab45 100644
--- a/src/training/shield.rs
+++ b/src/training/shield.rs
@@ -182,7 +182,7 @@ unsafe fn mod_handle_sub_guard_cont(fighter: &mut L2CFighterCommon) {
         return;
     }
 
-    let action = mash::buffer_menu_mash(module_accessor);
+    let action = mash::buffer_menu_mash();
 
     if handle_escape_option(fighter, module_accessor) {
         return;
@@ -239,19 +239,19 @@ unsafe fn handle_escape_option(
     }
 
     match mash::get_current_buffer() {
-        Action::Spotdodge => {
+        Action::SPOT_DODGE => {
             fighter
                 .fighter_base
                 .change_status(FIGHTER_STATUS_KIND_ESCAPE.as_lua_int(), LUA_TRUE);
             return true;
         }
-        Action::RollForward => {
+        Action::ROLL_F => {
             fighter
                 .fighter_base
                 .change_status(FIGHTER_STATUS_KIND_ESCAPE_F.as_lua_int(), LUA_TRUE);
             return true;
         }
-        Action::RollBack => {
+        Action::ROLL_B => {
             fighter
                 .fighter_base
                 .change_status(FIGHTER_STATUS_KIND_ESCAPE_B.as_lua_int(), LUA_TRUE);
@@ -267,7 +267,7 @@ unsafe fn handle_escape_option(
 fn needs_oos_handling_drop_shield() -> bool {
     let action = mash::get_current_buffer();
 
-    if action == Action::Jump {
+    if action == Action::JUMP {
         return true;
     }
 
@@ -275,11 +275,11 @@ fn needs_oos_handling_drop_shield() -> bool {
         return true;
     }
 
-    if action == Action::UpB {
+    if action == Action::UP_B {
         return true;
     }
 
-    if action == Action::UpSmash {
+    if action == Action::U_SMASH {
         return true;
     }
 
@@ -288,11 +288,11 @@ fn needs_oos_handling_drop_shield() -> bool {
 
 pub fn is_aerial(action: Action) -> bool {
     match action {
-        Action::Nair => return true,
-        Action::Fair => return true,
-        Action::Bair => return true,
-        Action::UpAir => return true,
-        Action::Dair => return true,
+        Action::NAIR => return true,
+        Action::FAIR => return true,
+        Action::BAIR => return true,
+        Action::UAIR => return true,
+        Action::DAIR => return true,
         _ => return false,
     }
 }
@@ -305,11 +305,14 @@ pub fn suspend_shield(action: Action) {
 }
 
 fn need_suspend_shield(action: Action) -> bool {
+    if action == Action::empty(){
+        return false;
+    }
+
     match action {
-        Action::UpSmash => false,
-        Action::Grab => false,
-        Action::Shield => false,
-        Action::Nothing => false,
+        Action::U_SMASH => false,
+        Action::GRAB => false,
+        Action::SHIELD => false,
         _ => {
             // Force shield drop
             true