diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index 47036da9cf8..bed8c64b054 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -24,7 +24,7 @@
return FALSE
/obj/attackby(obj/item/I, mob/living/user, params)
- return ..() || (can_be_hit && isitem(I) && I.attack_obj(src, user))
+ return ..() || (can_be_hit && I.attack_obj(src, user))
/mob/living/attackby(obj/item/I, mob/living/user, params)
user.changeNext_move(CLICK_CD_MELEE)
@@ -37,8 +37,6 @@
SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user)
if(flags & (NOBLUDGEON))
return 0
- if(check_martial_counter(M, user))
- return 0
if(can_operate(M)) //Checks if mob is lying down on table for surgery
if(istype(src,/obj/item/robot_parts))//popup override for direct attach
if(!attempt_initiate_surgery(src, M, user,1))
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index e12aa5cd9db..a363c5e17b3 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -813,7 +813,9 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
desc = "A manual that teaches a single user tactical Close-Quarters Combat before self-destructing. Does not restrict weapon usage, but cannot be used alongside Gloves of the North Star."
reference = "CQC"
item = /obj/item/CQC_manual
- cost = 9
+ gamemodes = list(/datum/game_mode/nuclear)
+ cost = 13
+ surplus = 0
/datum/uplink_item/stealthy_weapons/cameraflash
name = "Camera Flash"
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 4860733f4f7..77b263fb8f2 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -578,11 +578,4 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
return TRUE
/obj/item/attack_hulk(mob/living/carbon/human/user)
- return FALSE
-
-/obj/item/proc/check_martial_counter(mob/living/carbon/human/target, mob/living/carbon/human/user) //handles block for CQC
- if(target.check_block())
- target.visible_message("[target.name] blocks [src] and twists [user]'s arm behind [user.p_their()] back!",
- "You block the attack!")
- user.Stun(2)
- return TRUE
+ return FALSE
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/melee/misc.dm b/code/game/objects/items/weapons/melee/misc.dm
index 381f19dc4cf..9dd14046cb9 100644
--- a/code/game/objects/items/weapons/melee/misc.dm
+++ b/code/game/objects/items/weapons/melee/misc.dm
@@ -1,6 +1,13 @@
/obj/item/melee
needs_permit = 1
+/obj/item/melee/proc/check_martial_counter(mob/living/carbon/human/target, mob/living/carbon/human/user)
+ if(target.check_block())
+ target.visible_message("[target.name] blocks [src] and twists [user]'s arm behind [user.p_their()] back!",
+ "You block the attack!")
+ user.Stun(2)
+ return TRUE
+
/obj/item/melee/chainofcommand
name = "chain of command"
desc = "A tool used by great men to placate the frothing masses."
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index b7356a7757b..f128b874eaa 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -141,6 +141,12 @@
if(isrobot(M))
..()
return
+
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ if(check_martial_counter(H, user))
+ return
+
if(!isliving(M))
return
@@ -166,8 +172,6 @@
if(ishuman(L))
var/mob/living/carbon/human/H = L
- if(check_martial_counter(L, user))
- return
if(H.check_shields(0, "[user]'s [name]", src, MELEE_ATTACK)) //No message; check_shields() handles that
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
return
diff --git a/code/game/objects/items/weapons/swords_axes_etc.dm b/code/game/objects/items/weapons/swords_axes_etc.dm
index 3fc4b4b7717..d0526ebbcb8 100644
--- a/code/game/objects/items/weapons/swords_axes_etc.dm
+++ b/code/game/objects/items/weapons/swords_axes_etc.dm
@@ -52,7 +52,9 @@
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(H.check_shields(0, "[user]'s [name]", src, MELEE_ATTACK))
- return 0
+ return
+ if(check_martial_counter(H, user))
+ return
playsound(get_turf(src), 'sound/effects/woodhit.ogg', 75, 1, -1)
target.Weaken(3)
add_attack_logs(user, target, "Stunned with [src]")
diff --git a/code/modules/martial_arts/cqc.dm b/code/modules/martial_arts/cqc.dm
index 54f9ac97cd9..b57e7fc4f98 100644
--- a/code/modules/martial_arts/cqc.dm
+++ b/code/modules/martial_arts/cqc.dm
@@ -1,4 +1,4 @@
-#define SLAM_COMBO "HG"
+#define SLAM_COMBO "GH"
#define KICK_COMBO "HH"
#define RESTRAIN_COMBO "GG"
#define PRESSURE_COMBO "DG"
@@ -8,15 +8,24 @@
name = "CQC"
help_verb = /mob/living/carbon/human/proc/CQC_help
block_chance = 75
+ var/just_a_cook = FALSE
+ var/static/list/areas_under_siege = typecacheof(list(/area/crew_quarters/kitchen,
+ /area/crew_quarters/cafeteria,
+ /area/crew_quarters/bar))
-/datum/martial_art/cqc/can_use(mob/living/carbon/human/H)
- if(istype(H.gloves, /obj/item/clothing/gloves/fingerless/rapid))
- return FALSE
- return ..()
+/datum/martial_art/cqc/under_siege
+ name = "Close Quarters Cooking"
+ just_a_cook = TRUE
/datum/martial_art/cqc/proc/drop_restraining()
restraining = FALSE
+/datum/martial_art/cqc/can_use(mob/living/carbon/human/H)
+ var/area/A = get_area(H)
+ if(just_a_cook && !(is_type_in_typecache(A, areas_under_siege)))
+ return FALSE
+ return ..()
+
/datum/martial_art/cqc/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!can_use(A))
return FALSE
@@ -44,22 +53,23 @@
/datum/martial_art/cqc/proc/Slam(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!can_use(A))
return FALSE
- if(!D.stat || !D.weakened)
+ if(!D.weakened && !D.resting && !D.lying)
D.visible_message("[A] slams [D] into the ground!", \
"[A] slams you into the ground!")
playsound(get_turf(A), 'sound/weapons/slam.ogg', 50, 1, -1)
D.apply_damage(10, BRUTE)
D.Weaken(6)
add_attack_logs(A, D, "Melee attacked with martial-art [src] : Slam", ATKLOG_ALL)
- else //if target can't be slammed, do a regular grab attack then clear the streak
- streak = ""
- grab_act(A, D)
- streak = ""
+ return TRUE
+ streak = ""
+ harm_act(A, D)
+ streak = ""
return TRUE
/datum/martial_art/cqc/proc/Kick(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!can_use(A))
return FALSE
+ var/success = FALSE
if(!D.stat || !D.weakened)
D.visible_message("[A] kicks [D] back!", \
"[A] kicks you back!")
@@ -68,17 +78,20 @@
D.throw_at(throw_target, 1, 14, A)
D.apply_damage(10, BRUTE)
add_attack_logs(A, D, "Melee attacked with martial-art [src] : Kick", ATKLOG_ALL)
- if(D.weakened && !D.stat)
- D.visible_message("[A] kicks [D]'s head, knocking [D.p_them()] out!", \
- "[A] kicks your head, knocking you out!")
- playsound(get_turf(A), 'sound/weapons/genhit1.ogg', 50, 1, -1)
- D.SetSleeping(15)
- D.adjustBrainLoss(15, 150)
- add_attack_logs(A, D, "Knocked out with martial-art [src] : Kick", ATKLOG_ALL)
- else //if target can't be kicked, do a regular harm attack then clear the streak
- streak = ""
- harm_act(A, D)
- streak = ""
+ success = TRUE
+ if(D.weakened && !D.stat)
+ D.visible_message("[A] kicks [D]'s head, knocking [D.p_them()] out!", \
+ "[A] kicks your head, knocking you out!")
+ playsound(get_turf(A), 'sound/weapons/genhit1.ogg', 50, 1, -1)
+ D.SetSleeping(15)
+ D.adjustBrainLoss(15)
+ add_attack_logs(A, D, "Knocked out with martial-art [src] : Kick", ATKLOG_ALL)
+ success = TRUE
+ if(success)
+ return TRUE
+ streak = ""
+ harm_act(A, D)
+ streak = ""
return TRUE
/datum/martial_art/cqc/proc/Pressure(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -103,6 +116,10 @@
restraining = TRUE
addtimer(CALLBACK(src, .proc/drop_restraining), 50, TIMER_UNIQUE)
add_attack_logs(A, D, "Melee attacked with martial-art [src] : Restrain", ATKLOG_ALL)
+ return TRUE
+ streak = ""
+ harm_act(A, D)
+ streak = ""
return TRUE
/datum/martial_art/cqc/proc/Consecutive(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -118,10 +135,10 @@
D.adjustStaminaLoss(50)
D.apply_damage(25, BRUTE)
add_attack_logs(A, D, "Melee attacked with martial-art [src] : Consecutive", ATKLOG_ALL)
- else //if target can't be hit, do a regular harm attack then clear the streak
- streak = ""
- harm_act(A, D)
- streak = ""
+ return TRUE
+ streak = ""
+ harm_act(A, D)
+ streak = ""
return TRUE
/datum/martial_art/cqc/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -133,6 +150,8 @@
var/obj/item/grab/G = D.grabbedby(A, 1)
if(G)
G.state = GRAB_AGGRESSIVE //Instant aggressive grab
+ add_attack_logs(A, D, "Melee attacked with martial-art [src] : aggressively grabbed", ATKLOG_ALL)
+
return TRUE
/datum/martial_art/cqc/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -141,8 +160,9 @@
add_to_streak("H", D)
if(check_streak(A, D))
return TRUE
+ add_attack_logs(A, D, "Melee attacked with martial-art [src]", ATKLOG_ALL)
A.do_attack_animation(D)
- var/picked_hit_type = pick("CQC'd", "neck chopped", "gut punched")
+ var/picked_hit_type = pick("CQC'd", "neck chopped", "gut punched", "Big Bossed")
var/bonus_damage = 13
if(D.weakened || D.resting || D.lying)
bonus_damage += 5
@@ -154,7 +174,7 @@
playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
D.visible_message("[A] [picked_hit_type] [D]!", \
"[A] [picked_hit_type] you!")
- add_attack_logs(A, D, "Melee attacked with martial-art [src]", ATKLOG_ALL)
+ add_attack_logs(A, D, "Melee attacked with martial-art [src] : [picked_hit_type]", ATKLOG_ALL)
if(A.resting && !D.stat && !D.weakened)
D.visible_message("[A] leg sweeps [D]!", \
"[A] leg sweeps you!")
@@ -168,24 +188,36 @@
if(!can_use(A))
return FALSE
add_to_streak("D", D)
+ var/obj/item/I = null
if(check_streak(A, D))
return TRUE
- if(!restraining)
- D.visible_message("[A] strikes [D]'s jaw with their hand!", \
- "[A] strikes your jaw, disorienting you!")
- playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
- D.Jitter(2)
- D.apply_damage(5, BRUTE)
- add_attack_logs(A, D, "Melee attacked with martial-art [src] : Disarm", ATKLOG_ALL)
- if(restraining)
+ var/obj/item/grab/G = A.get_inactive_hand()
+ if(restraining && istype(G) && G.affecting == D)
D.visible_message("[A] puts [D] into a chokehold!", \
"[A] puts you into a chokehold!")
D.SetSleeping(20)
restraining = FALSE
- add_attack_logs(A, D, "Knocked out with martial-art [src] : Choke hold", ATKLOG_ALL)
+ if(G.state < GRAB_NECK)
+ G.state = GRAB_NECK
+ return TRUE
else
restraining = FALSE
- return FALSE
+
+ if(prob(65))
+ if(!D.stat || !D.weakened || !restraining)
+ I = D.get_active_hand()
+ D.visible_message("[A] strikes [D]'s jaw with their hand!", \
+ "[A] strikes your jaw, disorienting you!")
+ playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
+ if(I && D.drop_item())
+ A.put_in_hands(I)
+ D.Jitter(2)
+ D.apply_damage(5, BRUTE)
+ else
+ D.visible_message("[A] attempted to disarm [D]!", "[A] attempted to disarm [D]!")
+ playsound(D, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
+
+ add_attack_logs(A, D, "Melee attacked with martial-art [src] : Disarmed [I ? " grabbing \the [I]" : ""]", ATKLOG_ALL)
return TRUE
/mob/living/carbon/human/proc/CQC_help()
@@ -194,11 +226,10 @@
set category = "CQC"
to_chat(usr, "You try to remember some of the basics of CQC.")
- to_chat(usr, "Slam: Harm Grab. Slam opponent into the ground, knocking them down.")
+ to_chat(usr, "Slam: Grab, switch hands, Harm. Slam opponent into the ground, knocking them down.")
to_chat(usr, "CQC Kick: Harm Harm. Knocks opponent away. Knocks out stunned or knocked down opponents.")
- to_chat(usr, "Restrain: Grab Switch Hand Grab. Locks opponent into a restraining position, stunning them.")
- to_chat(usr, "Choke Hold: Restrain Disarm. Knocks out an opponent you have restrained.")
+ to_chat(usr, "Restrain: Grab, switch hands, Grab. Locks opponents into a restraining position, disarm to knock them out with a choke hold.")
to_chat(usr, "Pressure: Disarm Grab. Decent stamina damage.")
to_chat(usr, "Consecutive CQC: Disarm Disarm Harm. Mainly offensive move, huge damage and decent stamina damage.")
- to_chat(usr, "In addition, by having your throw mode on when being attacked, you enter an active defense mode where you have a chance to block and sometimes even counter melee attacks done to you.")
\ No newline at end of file
+ to_chat(usr, "In addition, by having your throw mode on when being attacked, you enter an active defense mode where you have a chance to block and sometimes even counter attacks done to you.")
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 84764bfddaa..c1d61338dcd 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -157,7 +157,7 @@ emp_act
return 1
return 0
-/mob/living/carbon/human/check_block()
+/mob/living/carbon/human/proc/check_block()
if(martial_art && prob(martial_art.block_chance) && martial_art.can_use(src) && in_throw_mode && !incapacitated(FALSE, TRUE))
return TRUE
@@ -220,6 +220,10 @@ emp_act
if(check_shields(I.force, "the [I.name]", I, MELEE_ATTACK, I.armour_penetration))
return 0
+ if(check_block())
+ visible_message("[src] blocks [I]!")
+ return FALSE
+
if(istype(I,/obj/item/card/emag))
emag_act(user, affecting)
diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm
index e9a88fdb033..72fe54970a1 100644
--- a/code/modules/mob/living/carbon/human/species/_species.dm
+++ b/code/modules/mob/living/carbon/human/species/_species.dm
@@ -319,7 +319,7 @@
user.do_cpr(target)
/datum/species/proc/grab(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
- if(target.check_block()) //cqc
+ if(target.check_block())
target.visible_message("[target] blocks [user]'s grab attempt!")
return FALSE
if(attacker_style && attacker_style.grab_act(user, target))
@@ -348,7 +348,7 @@
add_attack_logs(user, target, "vampirebit")
return
//end vampire codes
- if(target.check_block()) //cqc
+ if(target.check_block())
target.visible_message("[target] blocks [user]'s attack!")
return FALSE
if(attacker_style && attacker_style.harm_act(user, target))
@@ -393,7 +393,7 @@
SEND_SIGNAL(target, COMSIG_PARENT_ATTACKBY)
/datum/species/proc/disarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
- if(target.check_block()) //cqc
+ if(target.check_block())
target.visible_message("[target] blocks [user]'s disarm attempt!")
return FALSE
if(attacker_style && attacker_style.disarm_act(user, target))
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 0641ce380f5..3182c829466 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -337,8 +337,4 @@
return TRUE
if(INTENT_DISARM)
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
- return TRUE
-
-//defined here, overridden for humans in human_defense. By default, living mobs don't get to block anything
-/mob/living/proc/check_block()
- return FALSE
\ No newline at end of file
+ return TRUE
\ No newline at end of file