diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm
index ef1d0ea8deb..55a83a46ea6 100644
--- a/code/__DEFINES/combat.dm
+++ b/code/__DEFINES/combat.dm
@@ -288,3 +288,12 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
/// Proceed with the attack chain, but don't call the normal methods.
#define SECONDARY_ATTACK_CONTINUE_CHAIN 3
+
+/// Martial arts attack requested but is not available, allow a check for a regular attack.
+#define MARTIAL_ATTACK_INVALID -1
+
+/// Martial arts attack happened but failed, do not allow a check for a regular attack.
+#define MARTIAL_ATTACK_FAIL FALSE
+
+/// Martial arts attack happened and succeeded, do not allow a check for a regular attack.
+#define MARTIAL_ATTACK_SUCCESS TRUE
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 3d5b6ef73df..00707f6357a 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -330,6 +330,14 @@
if(istype(ML))
ML.pulled(src)
+/mob/living/CtrlClick(mob/user)
+ if (isliving(user))
+ var/mob/living/user_living = user
+ if (user_living.apply_martial_art(src, null, is_grab=TRUE) == MARTIAL_ATTACK_SUCCESS)
+ return
+ ..()
+
+
/mob/living/carbon/human/CtrlClick(mob/user)
if(ishuman(user) && Adjacent(user) && !user.incapacitated())
if(world.time < user.next_move)
diff --git a/code/datums/martial/_martial.dm b/code/datums/martial/_martial.dm
index 4e831b6703e..cd9acf617b9 100644
--- a/code/datums/martial/_martial.dm
+++ b/code/datums/martial/_martial.dm
@@ -15,16 +15,16 @@
var/timerid
/datum/martial_art/proc/help_act(mob/living/A, mob/living/D)
- return FALSE
+ return MARTIAL_ATTACK_INVALID
/datum/martial_art/proc/disarm_act(mob/living/A, mob/living/D)
- return FALSE
+ return MARTIAL_ATTACK_INVALID
/datum/martial_art/proc/harm_act(mob/living/A, mob/living/D)
- return FALSE
+ return MARTIAL_ATTACK_INVALID
/datum/martial_art/proc/grab_act(mob/living/A, mob/living/D)
- return FALSE
+ return MARTIAL_ATTACK_INVALID
/datum/martial_art/proc/can_use(mob/living/L)
return TRUE
diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm
index 8af350d66ff..0caf502b23e 100644
--- a/code/modules/mob/living/carbon/alien/alien_defense.dm
+++ b/code/modules/mob/living/carbon/alien/alien_defense.dm
@@ -52,6 +52,10 @@ In all, this is a lot like the monkey code. /N
if(.) //to allow surgery to return properly.
return FALSE
+ var/martial_result = user.apply_martial_art(src, modifiers)
+ if (martial_result != MARTIAL_ATTACK_INVALID)
+ return martial_result
+
if(user.combat_mode)
if(LAZYACCESS(modifiers, RIGHT_CLICK))
user.do_attack_animation(src, ATTACK_EFFECT_DISARM)
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 0766a04ca71..12b93aac83a 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -176,9 +176,6 @@
if(W.try_handling(user))
return TRUE
- if (user.apply_martial_art(src, modifiers))
- return TRUE
-
return FALSE
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 53da1a41f0a..70853818eab 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -219,6 +219,9 @@
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
+ var/martial_result = user.apply_martial_art(src, modifiers)
+ if (martial_result != MARTIAL_ATTACK_INVALID)
+ return martial_result
if(LAZYACCESS(modifiers, RIGHT_CLICK)) //Always drop item in hand, if no item, get stunned instead.
var/obj/item/I = get_active_held_item()
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 3fa6d2328ea..dfc6b0bf268 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -1347,7 +1347,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
"You block [user]'s grab!", "You hear a swoosh!", COMBAT_MESSAGE_RANGE, user)
to_chat(user, "Your grab at [target] was blocked!")
return FALSE
- if(attacker_style?.grab_act(user,target))
+ if(attacker_style?.grab_act(user,target) == MARTIAL_ATTACK_SUCCESS)
return TRUE
else
target.grabbedby(user)
@@ -1363,7 +1363,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
"You block [user]'s attack!", "You hear a swoosh!", COMBAT_MESSAGE_RANGE, user)
to_chat(user, "Your attack at [target] was blocked!")
return FALSE
- if(attacker_style?.harm_act(user,target))
+ if(attacker_style?.harm_act(user,target) == MARTIAL_ATTACK_SUCCESS)
return TRUE
else
@@ -1447,7 +1447,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
"You block [user]'s shove!", "You hear a swoosh!", COMBAT_MESSAGE_RANGE, user)
to_chat(user, "Your shove at [target] was blocked!")
return FALSE
- if(attacker_style?.disarm_act(user,target))
+ if(attacker_style?.disarm_act(user,target) == MARTIAL_ATTACK_SUCCESS)
return TRUE
if(user.body_position != STANDING_UP)
return FALSE
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 4f4e6e23336..d693cebcd01 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -1975,24 +1975,19 @@
* It is also used to process martial art attacks by nonhumans, even against humans
* Human vs human attacks are handled in species code right now.
*/
-/mob/living/proc/apply_martial_art(mob/living/target, modifiers, is_grab)
+/mob/living/proc/apply_martial_art(mob/living/target, modifiers, is_grab = FALSE)
if(HAS_TRAIT(target, TRAIT_MARTIAL_ARTS_IMMUNE))
- return FALSE
- if(ishuman(target) && ishuman(src)) //Human vs human are handled in species code
- return FALSE
+ return MARTIAL_ATTACK_INVALID
var/datum/martial_art/style = mind?.martial_art
- var/attack_result = FALSE
- if (style)
- if (is_grab)
- attack_result = style.grab_act(src, target)
- if(LAZYACCESS(modifiers, RIGHT_CLICK))
- attack_result = style.disarm_act(src, target)
- if(combat_mode)
- if (HAS_TRAIT(src, TRAIT_PACIFISM))
- return FALSE
- attack_result = style.harm_act(src, target)
- else
- attack_result = style.help_act(src, target)
-
-
- return attack_result
+ if (!style)
+ return MARTIAL_ATTACK_INVALID
+ // will return boolean below since it's not invalid
+ if (is_grab)
+ return style.grab_act(src, target)
+ if (LAZYACCESS(modifiers, RIGHT_CLICK))
+ return style.disarm_act(src, target)
+ if(combat_mode)
+ if (HAS_TRAIT(src, TRAIT_PACIFISM))
+ return FALSE
+ return style.harm_act(src, target)
+ return style.help_act(src, target)
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index af46cff49e6..2519ab1ab26 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -254,16 +254,19 @@
/mob/living/attack_hand(mob/living/carbon/human/user, list/modifiers)
. = ..()
- if (user.apply_martial_art(src, modifiers))
- return TRUE
+ var/martial_result = user.apply_martial_art(src, modifiers)
+ if (martial_result != MARTIAL_ATTACK_INVALID)
+ return martial_result
/mob/living/attack_paw(mob/living/carbon/human/user, list/modifiers)
if(isturf(loc) && istype(loc.loc, /area/start))
to_chat(user, "No attacking people at spawn, you jackass.")
return FALSE
- if (user.apply_martial_art(src, modifiers))
- return TRUE
+ var/martial_result = user.apply_martial_art(src, modifiers)
+ if (martial_result != MARTIAL_ATTACK_INVALID)
+ return martial_result
+
if(LAZYACCESS(modifiers, RIGHT_CLICK))
if (user != src)
user.disarm(src)