From 9b3313ceedd823424b5f0d29edd708139ecf9a39 Mon Sep 17 00:00:00 2001
From: David Soler <dsbartomeu@uoc.edu>
Date: Tue, 19 Nov 2019 23:18:28 +0100
Subject: [PATCH 1/3] Mash now can be performed OOS.

Added Up smash Mash Option.
Added Spot dodge Mash Option.
---
 source/taunt_toggles.h     | 10 ++++++----
 source/training/common.hpp | 36 ++++++++++++++++++++++++++++++++++++
 source/training/mash.hpp   | 13 ++++++++++++-
 source/training/shield.hpp |  4 ++--
 4 files changed, 56 insertions(+), 7 deletions(-)

diff --git a/source/taunt_toggles.h b/source/taunt_toggles.h
index 02215d5..26309e6 100644
--- a/source/taunt_toggles.h
+++ b/source/taunt_toggles.h
@@ -26,7 +26,9 @@ const char* di_items[] = { "None", "Away", "Up Away", "Up", "Up In", "In", "Down
 #define MASH_SIDE_B 6
 #define MASH_UP_B 7
 #define MASH_DOWN_B 8
-const char* attack_items[] = { "Neutral Air", "Forward Air", "Back Air", "Up Air", "Down Air", "Neutral B", "Side B", "Up B", "Down B" };
+#define MASH_UP_SMASH 9
+#define MASH_GRAB 10
+const char* attack_items[] = { "Neutral Air", "Forward Air", "Back Air", "Up Air", "Down Air", "Neutral B", "Side B", "Up B", "Down B", "Up Smash", "Grab" };
 
 // Ledge Option
 #define RANDOM_LEDGE 1
@@ -46,9 +48,9 @@ const char* tech_items[] = { "None", "Random", "In-Place", "Roll", "Miss Tech" }
 // Mash States
 #define MASH_AIRDODGE 1
 #define MASH_JUMP 2
-#define MASH_ATTACK 3
-#define MASH_RANDOM 4
-const char* mash_items[] = { "None", "Airdodge", "Jump", "Attack", "Random" };
+#define MASH_SPOTDODGE 4
+#define MASH_RANDOM 5
+const char* mash_items[] = { "None", "Airdodge", "Jump", "Attack", "Spotdodge", "Random" };
 
 // Shield States
 #define SHIELD_INFINITE 1
diff --git a/source/training/common.hpp b/source/training/common.hpp
index 82f05c1..4995721 100644
--- a/source/training/common.hpp
+++ b/source/training/common.hpp
@@ -30,12 +30,48 @@ bool is_in_hitstun(u64 module_accessor) {
            status_kind <= FIGHTER_STATUS_KIND_DAMAGE_FALL;
 }
 
+bool is_in_shieldstun(u64 module_accessor) {
+    int status_kind = StatusModule::status_kind(module_accessor);
+    int prev_status = StatusModule::prev_status_kind(module_accessor, 0);
+    // If we are taking shield damage or we are droping shield from taking shield damage we are in hitstun
+    if(status_kind == FIGHTER_STATUS_KIND_GUARD_DAMAGE || (prev_status == FIGHTER_STATUS_KIND_GUARD_DAMAGE && status_kind == FIGHTER_STATUS_KIND_GUARD_OFF))
+    {
+        return true
+    }
+
+    return false;
+}
+
+
 bool is_in_landing(u64 module_accessor) {
     int status_kind = StatusModule::status_kind(module_accessor);
     return status_kind >= FIGHTER_STATUS_KIND_LANDING &&
            status_kind <= FIGHTER_STATUS_KIND_LANDING_DAMAGE_LIGHT;
 }
 
+bool should_hold_shield(u64 module_accessor)
+{
+    // We should hold shield if the state requires it
+    if (menu.SHIELD_STATE == SHIELD_HOLD || menu.SHIELD_STATE == SHIELD_INFINITE) {
+        // 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(menu.ATTACK_STATE == MASH_NEUTRAL_B || menu.ATTACK_STATE == MASH_SIDE_B || menu.ATTACK_STATE == MASH_DOWN_B)
+                return true;
+        }
+    }
+
+    return false;
+}
+
+
 void perform_defensive_option(u64 module_accessor) {
     if (menu.DEFENSIVE_STATE == RANDOM_DEFENSIVE) {
         const int NUM_GROUND_STATUSES = 3;
diff --git a/source/training/mash.hpp b/source/training/mash.hpp
index 08fefb1..9f2f363 100644
--- a/source/training/mash.hpp
+++ b/source/training/mash.hpp
@@ -34,7 +34,7 @@ int get_attack_air_kind(u64 module_accessor, bool& replace) {
 void get_command_flag_cat(u64 module_accessor, int category, int& flag) {
 
     if (is_training_mode() && is_operation_cpu(module_accessor)) {
-        if (is_in_hitstun(module_accessor) || is_in_landing(module_accessor)) {
+        if (is_in_hitstun(module_accessor) || is_in_landing(module_accessor) || is_in_shieldstun(module_accessor)) {
             if (menu.MASH_STATE == MASH_AIRDODGE)
                 if (category == FIGHTER_PAD_COMMAND_CATEGORY1)
                     flag |= FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE;
@@ -43,6 +43,10 @@ void get_command_flag_cat(u64 module_accessor, int category, int& flag) {
                 if (category == FIGHTER_PAD_COMMAND_CATEGORY1)
                     flag |= FIGHTER_PAD_CMD_CAT1_FLAG_JUMP_BUTTON;
 
+            if (menu.MASH_STATE == MASH_SPOTDODGE)
+                if (category == FIGHTER_PAD_COMMAND_CATEGORY1)
+                    flag |= FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE;
+
             if (menu.MASH_STATE == MASH_ATTACK)
                 if (category == FIGHTER_PAD_COMMAND_CATEGORY1) {
                     switch (menu.ATTACK_STATE) {
@@ -52,6 +56,9 @@ void get_command_flag_cat(u64 module_accessor, int category, int& flag) {
                         case MASH_UPAIR:
                         case 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;
                             break;
                         case MASH_NEUTRAL_B:
                             flag |= FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_N;
@@ -64,6 +71,10 @@ void get_command_flag_cat(u64 module_accessor, int category, int& flag) {
                             break;
                         case MASH_DOWN_B:
                             flag |= FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_LW;
+                        case MASH_UP_SMASH:
+                            flag |= FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_HI4;
+                        case MASH_GRAB:
+                            flag |= FIGHTER_PAD_CMD_CAT1_FLAG_CATCH;
                             break;
                     }
                 }
diff --git a/source/training/shield.hpp b/source/training/shield.hpp
index 9a81460..55ed7b3 100644
--- a/source/training/shield.hpp
+++ b/source/training/shield.hpp
@@ -30,7 +30,7 @@ float get_param_float(u64 module_accessor, u64 param_type, u64 param_hash, bool&
 bool check_button_on(u64 module_accessor, int button, bool& replace) {
     if (button == CONTROL_PAD_BUTTON_GUARD_HOLD || button == CONTROL_PAD_BUTTON_GUARD) {
         if (is_training_mode() && is_operation_cpu(module_accessor)) {
-            if (menu.SHIELD_STATE == SHIELD_HOLD || menu.SHIELD_STATE == SHIELD_INFINITE) {
+            if (should_hold_shield(module_accessor)) {
                 replace = true;
                 return true;
             }
@@ -44,7 +44,7 @@ bool check_button_on(u64 module_accessor, int button, bool& replace) {
 bool check_button_off(u64 module_accessor, int button, bool& replace) {
     if (button == CONTROL_PAD_BUTTON_GUARD_HOLD || button == CONTROL_PAD_BUTTON_GUARD) {
         if (is_training_mode() && is_operation_cpu(module_accessor)) {
-            if (menu.SHIELD_STATE == SHIELD_HOLD || menu.SHIELD_STATE == SHIELD_INFINITE) {
+            if (should_hold_shield(module_accessor)) {
                 replace = true;
                 return false;
             }

From b9bdef8ca940f782a7a172dfacc54b1292970772 Mon Sep 17 00:00:00 2001
From: David Soler <dsbartomeu@uoc.edu>
Date: Tue, 19 Nov 2019 23:20:24 +0100
Subject: [PATCH 2/3] Fixed some errors.

---
 source/taunt_toggles.h     | 1 +
 source/training/common.hpp | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/source/taunt_toggles.h b/source/taunt_toggles.h
index 26309e6..666443f 100644
--- a/source/taunt_toggles.h
+++ b/source/taunt_toggles.h
@@ -48,6 +48,7 @@ const char* tech_items[] = { "None", "Random", "In-Place", "Roll", "Miss Tech" }
 // Mash States
 #define MASH_AIRDODGE 1
 #define MASH_JUMP 2
+#define MASH_ATTACK 3
 #define MASH_SPOTDODGE 4
 #define MASH_RANDOM 5
 const char* mash_items[] = { "None", "Airdodge", "Jump", "Attack", "Spotdodge", "Random" };
diff --git a/source/training/common.hpp b/source/training/common.hpp
index 4995721..bcb3c08 100644
--- a/source/training/common.hpp
+++ b/source/training/common.hpp
@@ -36,7 +36,7 @@ bool is_in_shieldstun(u64 module_accessor) {
     // If we are taking shield damage or we are droping shield from taking shield damage we are in hitstun
     if(status_kind == FIGHTER_STATUS_KIND_GUARD_DAMAGE || (prev_status == FIGHTER_STATUS_KIND_GUARD_DAMAGE && status_kind == FIGHTER_STATUS_KIND_GUARD_OFF))
     {
-        return true
+        return true;
     }
 
     return false;

From 3413d18bc8c626863e81aafdc3fc5be5f8138d4e Mon Sep 17 00:00:00 2001
From: David Soler <dsbartomeu@uoc.edu>
Date: Tue, 19 Nov 2019 23:47:12 +0100
Subject: [PATCH 3/3] Fixed error on mash switch, break instruction was missing
 for down b and up smash.

---
 source/training/mash.hpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/source/training/mash.hpp b/source/training/mash.hpp
index 9f2f363..ac980c1 100644
--- a/source/training/mash.hpp
+++ b/source/training/mash.hpp
@@ -71,8 +71,10 @@ void get_command_flag_cat(u64 module_accessor, int category, int& flag) {
                             break;
                         case MASH_DOWN_B:
                             flag |= FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_LW;
+                            break;
                         case MASH_UP_SMASH:
                             flag |= FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_HI4;
+                            break;
                         case MASH_GRAB:
                             flag |= FIGHTER_PAD_CMD_CAT1_FLAG_CATCH;
                             break;