diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm
index f06df9b4f74..30891c98d31 100644
--- a/code/__DEFINES/status_effects.dm
+++ b/code/__DEFINES/status_effects.dm
@@ -210,7 +210,6 @@
/// Status effects for different actions
#define STATUS_EFFECT_REMOVE_CUFFS /datum/status_effect/action_status_effect/remove_handcuffs
-#define STATUS_EFFECT_BREAK_CUFFS /datum/status_effect/action_status_effect/break_handcuffs
#define STATUS_EFFECT_REMOVE_MUZZLE /datum/status_effect/action_status_effect/remove_muzzle
#define STATUS_EFFECT_UNBUCKLE /datum/status_effect/action_status_effect/unbuckle
diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm
index d458a7379ec..d4e6b085276 100644
--- a/code/datums/status_effects/neutral.dm
+++ b/code/datums/status_effects/neutral.dm
@@ -372,9 +372,6 @@
/datum/status_effect/action_status_effect/remove_handcuffs
id = "remove_handcuffs"
-/datum/status_effect/action_status_effect/break_handcuffs
- id = "break_handcuffs"
-
/datum/status_effect/action_status_effect/remove_muzzle
id = "remove_muzzle"
diff --git a/code/game/gamemodes/cult/blood_magic.dm b/code/game/gamemodes/cult/blood_magic.dm
index 86624155772..3b93222e2fd 100644
--- a/code/game/gamemodes/cult/blood_magic.dm
+++ b/code/game/gamemodes/cult/blood_magic.dm
@@ -606,7 +606,7 @@
"[user] begins shaping dark magic shackles around your wrists!")
if(do_mob(user, C, 30))
if(!C.handcuffed)
- C.handcuffed = new /obj/item/restraints/handcuffs/energy/cult/used(C)
+ C.handcuffed = new /obj/item/restraints/handcuffs/cult(C)
C.update_handcuffed()
C.Silence(12 SECONDS)
to_chat(user, "You shackle [C].")
@@ -621,18 +621,20 @@
/// For the shackling spell
-/obj/item/restraints/handcuffs/energy/cult
+/obj/item/restraints/handcuffs/cult
name = "shadow shackles"
desc = "Shackles that bind the wrists with sinister magic."
- trashtype = /obj/item/restraints/handcuffs/energy/used
+ icon_state = "cablecuff"
+ breakouttime = 45 SECONDS
+ origin_tech = "materials=4;magnets=5;abductor=2"
flags = DROPDEL
-/obj/item/restraints/handcuffs/energy/cult/used/dropped(mob/user)
- user.visible_message("[user]'s shackles shatter in a discharge of dark magic!", \
- "Your [name] shatter in a discharge of dark magic!")
+/obj/item/restraints/handcuffs/cult/finish_resist_restraints(mob/living/carbon/user, break_cuffs, silent)
+ user.visible_message("[user]'s shackles shatter in a discharge of dark magic!", "Your [name] shatter in a discharge of dark magic!")
+ break_cuffs = TRUE
+ silent = TRUE
. = ..()
-
//Construction: Converts 50 metal to a construct shell, plasteel to runed metal, or an airlock to brittle runed airlock
/obj/item/melee/blood_magic/construction
name = "Twisting Aura"
diff --git a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
index d4b73934eb1..1827bfb96ec 100644
--- a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
+++ b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
@@ -359,7 +359,7 @@ CONTENTS:
"[user] begins shaping an energy field around your hands!")
if(do_mob(user, C, 30))
if(!C.handcuffed)
- C.handcuffed = new /obj/item/restraints/handcuffs/energy/used(C)
+ C.handcuffed = new /obj/item/restraints/handcuffs/energy(C)
C.update_handcuffed()
to_chat(user, "You handcuff [C].")
add_attack_logs(user, C, "Handcuffed ([src])")
@@ -392,16 +392,13 @@ CONTENTS:
desc = "A hard-light field restraining the hands."
icon_state = "cablecuff" // Needs sprite
breakouttime = 450
- trashtype = /obj/item/restraints/handcuffs/energy/used
origin_tech = "materials=4;magnets=5;abductor=2"
-
-/obj/item/restraints/handcuffs/energy/used
- desc = "energy discharge"
flags = DROPDEL
-/obj/item/restraints/handcuffs/energy/used/dropped(mob/user)
- user.visible_message("[src] restraining [user] breaks in a discharge of energy!", \
- "[src] restraining [user] breaks in a discharge of energy!")
+/obj/item/restraints/handcuffs/energy/finish_resist_restraints(mob/living/carbon/user, break_cuffs, silent)
+ user.visible_message("[src] restraining [user] breaks in a discharge of energy!", "[src] restraining [user] breaks in a discharge of energy!")
+ break_cuffs = TRUE
+ silent = TRUE
do_sparks(4, 0, user.loc)
. = ..()
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 199f7c320cb..71155d47c9f 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -103,8 +103,6 @@ GLOBAL_DATUM_INIT(welding_sparks, /mutable_appearance, mutable_appearance('icons
var/strip_delay = DEFAULT_ITEM_STRIP_DELAY
/// How long it takes to put an item onto somebody. IE. clothing
var/put_on_delay = DEFAULT_ITEM_PUTON_DELAY
- /// How long it takes to resist out of restraints, like cuffs, and whatnot.
- var/breakouttime = 0
/// For flags that define what areas an item cover
var/flags_cover = 0
diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm
index dc1c7b35716..8bb2e5984e3 100644
--- a/code/game/objects/items/weapons/handcuffs.dm
+++ b/code/game/objects/items/weapons/handcuffs.dm
@@ -3,6 +3,34 @@
desc = "Should not exist. Report me to a(n) coder/admin!"
icon = 'icons/obj/restraints.dmi'
var/cuffed_state = "handcuff"
+ ///How long it will take to break out of restraints
+ var/breakouttime
+
+/obj/item/restraints/proc/attempt_resist_restraints(mob/living/carbon/user, break_cuffs, effective_breakout_time, silent)
+ if(effective_breakout_time)
+ if(!silent)
+ user.visible_message("[user] attempts to [break_cuffs ? "break" : "remove"] [src]!", "You attempt to [break_cuffs ? "break" : "remove"] [src]...")
+ to_chat(user, "(This will take around [DisplayTimeText(effective_breakout_time)] and you need to stand still.)")
+
+ if(!do_after(user, effective_breakout_time, FALSE, user))
+ user.remove_status_effect(STATUS_EFFECT_REMOVE_CUFFS)
+ to_chat(user, "You fail to [break_cuffs ? "break" : "remove"] [src]!")
+ return
+
+ user.remove_status_effect(STATUS_EFFECT_REMOVE_CUFFS)
+ if(loc != user || user.buckled)
+ return
+
+ finish_resist_restraints(user, break_cuffs)
+
+/obj/item/restraints/proc/finish_resist_restraints(mob/living/carbon/user, break_cuffs, silent)
+ if(!silent)
+ user.visible_message("[user] manages to [break_cuffs ? "break" : "remove"] [src]!", "You successfully [break_cuffs ? "break" : "remove"] [src].")
+ user.unEquip(src)
+
+ if(break_cuffs)
+ qdel(src)
+ return TRUE
//////////////////////////////
// MARK: HANDCUFFS
@@ -219,6 +247,22 @@
breakouttime = 0
cuffsound = 'sound/weapons/cablecuff.ogg'
+/obj/item/restraints/handcuffs/twimsts/finish_resist_restraints(mob/living/carbon/user, break_cuffs)
+ if(ishuman(user))
+ var/mob/living/carbon/human/human_user = user
+ if(!human_user.check_has_mouth()) // I have no mouth but I must eat twimsts
+ break_cuffs = TRUE
+ return ..()
+
+ visible_message("[user] manages to eat through [src]!", "You successfully eat through [src].")
+
+ playsound(loc, 'sound/items/eatfood.ogg', 50, FALSE)
+ if(reagents && length(reagents.reagent_list))
+ user.taste(reagents)
+ reagents.reaction(user, REAGENT_INGEST)
+ reagents.trans_to(user, reagents.total_volume)
+ qdel(src)
+
//////////////////////////////
// MARK: CRAFTING
//////////////////////////////
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index f8f4a6f346b..0e97cfbc739 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -605,6 +605,8 @@
var/list/hide_tail_by_species = null
/// Maximum weight class of an item in the suit storage slot.
var/max_suit_w = WEIGHT_CLASS_BULKY
+ ///How long to break out of the suits
+ var/breakouttime
/obj/item/clothing/suit/Initialize(mapload)
. = ..()
@@ -709,6 +711,31 @@
/obj/item/clothing/suit/proc/special_overlays() // Does it have special overlays when worn?
return FALSE
+/obj/item/clothing/suit/proc/resist_restraints(mob/living/carbon/user, break_restraints)
+ var/effective_breakout_time = breakouttime
+ if(break_restraints)
+ effective_breakout_time = 5 SECONDS
+
+ if(user.has_status_effect(STATUS_EFFECT_REMOVE_CUFFS))
+ to_chat(user, "You are already trying to [break_restraints ? "break" : "remove"] your restraints.")
+ return
+ user.apply_status_effect(STATUS_EFFECT_REMOVE_CUFFS)
+
+ user.visible_message("[user] attempts to [break_restraints ? "break" : "remove"] [src]!", "You attempt to [break_restraints ? "break" : "remove"] [src]...")
+ to_chat(user, "(This will take around [DisplayTimeText(effective_breakout_time)] and you need to stand still.)")
+
+ if(!do_after(user, effective_breakout_time, FALSE, user))
+ user.remove_status_effect(STATUS_EFFECT_REMOVE_CUFFS)
+ to_chat(user, "You fail to [break_restraints ? "break" : "remove"] [src]!")
+ return
+
+ user.remove_status_effect(STATUS_EFFECT_REMOVE_CUFFS)
+ if(loc != user || user.buckled)
+ return
+
+ user.visible_message("[user] manages to [break_restraints ? "break" : "remove"] [src]!", "You successfully [break_restraints ? "break" : "remove"] [src].")
+ user.unEquip(src)
+
//Spacesuit
//Note: Everything in modules/clothing/spacesuits should have the entire suit grouped together.
// Meaning the the suit is defined directly after the corrisponding helmet. Just like below!
diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
index fa09251977f..f86cc9387d5 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
@@ -76,9 +76,10 @@ GLOBAL_LIST_INIT(strippable_alien_humanoid_items, create_strippable_list(list(
. = ..()
. += alien_movement_delay
-/mob/living/carbon/alien/humanoid/cuff_resist(obj/item/I)
+/mob/living/carbon/alien/humanoid/resist_restraints(attempt_breaking)
playsound(src, 'sound/voice/hiss5.ogg', 40, 1, 1) //Alien roars when starting to break free
- ..(I, cuff_break = 1)
+ attempt_breaking = TRUE
+ return ..()
/mob/living/carbon/alien/humanoid/get_standard_pixel_y_offset()
if(leaping)
diff --git a/code/modules/mob/living/carbon/carbon_procs.dm b/code/modules/mob/living/carbon/carbon_procs.dm
index 7d20aba8935..38d5c7cadaf 100644
--- a/code/modules/mob/living/carbon/carbon_procs.dm
+++ b/code/modules/mob/living/carbon/carbon_procs.dm
@@ -802,15 +802,22 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
/mob/living/carbon/resist_buckle()
INVOKE_ASYNC(src, PROC_REF(resist_muzzle))
- var/obj/item/I = get_restraining_item()
- var/time = 0
- if(istype(I))
- time = I.breakouttime
+ var/breakout_time = 0
+ var/obj/item/restraints = get_restraining_item()
+
+ if(istype(restraints, /obj/item/clothing/suit/straight_jacket))
+ var/obj/item/clothing/suit/straight_jacket/jacket = restraints
+ jacket.breakouttime = breakout_time
+
+ else if(istype(restraints, /obj/item/restraints))
+ var/obj/item/restraints/cuffs = restraints
+ breakout_time = cuffs.breakouttime
+
else if(isstructure(buckled))
var/obj/structure/struct = buckled
- time = struct.unbuckle_time
+ breakout_time = struct.unbuckle_time
- if(time == 0)
+ if(!breakout_time)
buckled.user_unbuckle_mob(src, src)
return
@@ -820,8 +827,8 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
apply_status_effect(STATUS_EFFECT_UNBUCKLE)
visible_message("[src] attempts to unbuckle [p_themselves()]!",
- "You attempt to unbuckle yourself... (This will take around [time / 10] seconds and you need to stay still.)")
- if(!do_after(src, time, FALSE, src, extra_checks = list(CALLBACK(src, PROC_REF(buckle_check)))))
+ "You attempt to unbuckle yourself... (This will take around [breakout_time / 10] seconds and you need to stay still.)")
+ if(!do_after(src, breakout_time, FALSE, src, extra_checks = list(CALLBACK(src, PROC_REF(buckle_check)))))
if(src && buckled)
to_chat(src, "You fail to unbuckle yourself!")
else
@@ -857,15 +864,21 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
visible_message("[src] has successfully extinguished [p_themselves()]!","You extinguish yourself.")
ExtinguishMob()
-/mob/living/carbon/resist_restraints()
+/mob/living/carbon/resist_restraints(attempt_breaking)
INVOKE_ASYNC(src, PROC_REF(resist_muzzle))
- var/obj/item/I = null
+ if(wear_suit && wear_suit.breakouttime)
+ wear_suit.resist_restraints(src, attempt_breaking)
+ return
+
+ var/obj/item/restraints/cuffs
if(handcuffed)
- I = handcuffed
+ cuffs = handcuffed
else if(legcuffed)
- I = legcuffed
- if(I)
- cuff_resist(I)
+ cuffs = legcuffed
+
+ if(!cuffs)
+ return
+ cuff_resist(cuffs, attempt_breaking)
/mob/living/carbon/resist_muzzle()
if(!istype(wear_mask, /obj/item/clothing/mask/muzzle))
@@ -889,89 +902,18 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
unEquip(I)
remove_status_effect(STATUS_EFFECT_REMOVE_MUZZLE)
+/mob/living/carbon/proc/cuff_resist(obj/item/restraints/restraints, break_cuffs)
+ var/effective_breakout_time = restraints.breakouttime
+ if(break_cuffs)
+ effective_breakout_time = 5 SECONDS
-/mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 600, cuff_break = 0)
- breakouttime = I.breakouttime
- if(HAS_TRAIT(src, TRAIT_I_WANT_BRAINS))
- breakouttime /= 2
+ if(has_status_effect(STATUS_EFFECT_REMOVE_CUFFS))
+ to_chat(src, "You are already trying to [break_cuffs ? "break" : "remove"] [restraints].")
+ return
- if(!cuff_break)
- if(has_status_effect(STATUS_EFFECT_REMOVE_CUFFS))
- to_chat(src, "You are already trying to remove [I].")
- return
- apply_status_effect(STATUS_EFFECT_REMOVE_CUFFS)
- visible_message("[src] attempts to remove [I]!")
- var/is_zombie = HAS_TRAIT(src, TRAIT_I_WANT_BRAINS)
- to_chat(src, "You attempt to remove [I]... (This will take around [breakouttime / 10] seconds[is_zombie ? "" : " and you need to stand still"].)")
- if(do_after(src, breakouttime, 0, target = src, allow_moving = is_zombie, allow_moving_target = is_zombie))
- remove_status_effect(STATUS_EFFECT_REMOVE_CUFFS)
- if(I.loc != src || buckled)
- return
- if(istype(I, /obj/item/restraints/handcuffs/twimsts))
- visible_message("[src] manages to eat through [I]!", "You successfully eat through [I].")
- else
- visible_message("[src] manages to remove [I]!", "You successfully remove [I].")
+ apply_status_effect(STATUS_EFFECT_REMOVE_CUFFS)
- if(I == handcuffed)
- if(istype(I, /obj/item/restraints/handcuffs/twimsts))
- playsound(loc, 'sound/items/eatfood.ogg', 50, FALSE)
- if(I.reagents && length(I.reagents.reagent_list))
- taste(I.reagents)
- I.reagents.reaction(src, REAGENT_INGEST)
- I.reagents.trans_to(src, I.reagents.total_volume)
- qdel(handcuffed)
- else
- handcuffed.forceMove(drop_location())
- handcuffed.dropped(src)
- handcuffed = null
- if(buckled && buckled.buckle_requires_restraints)
- buckled.unbuckle_mob(src)
- update_handcuffed()
- return
- if(I == legcuffed)
- legcuffed.forceMove(drop_location())
- legcuffed.dropped()
- legcuffed = null
- toggle_move_intent()
- update_inv_legcuffed()
- return
- else
- unEquip(I)
- I.dropped(src)
- return
- else
- remove_status_effect(STATUS_EFFECT_REMOVE_CUFFS)
- to_chat(src, "You fail to remove [I]!")
-
- else
- breakouttime = 50
- if(has_status_effect(STATUS_EFFECT_BREAK_CUFFS))
- to_chat(src, "You are already trying to break [I].")
- return
- apply_status_effect(STATUS_EFFECT_BREAK_CUFFS)
- visible_message("[src] is trying to break [I]!")
- to_chat(src, "You attempt to break [I]... (This will take around 5 seconds and you need to stand still.)")
- if(do_after(src, breakouttime, 0, target = src))
- remove_status_effect(STATUS_EFFECT_BREAK_CUFFS)
- if(!I.loc || buckled)
- return
- visible_message("[src] manages to break [I]!")
- to_chat(src, "You successfully break [I].")
- qdel(I)
-
- if(I == handcuffed)
- handcuffed = null
- update_handcuffed()
- return
- else if(I == legcuffed)
- legcuffed = null
- toggle_move_intent()
- update_inv_legcuffed()
- return
- return 1
- else
- remove_status_effect(STATUS_EFFECT_BREAK_CUFFS)
- to_chat(src, "You fail to break [I]!")
+ restraints.attempt_resist_restraints(src, break_cuffs, effective_breakout_time)
//called when we get cuffed/uncuffed
/mob/living/carbon/proc/update_handcuffed()
diff --git a/code/modules/mob/living/carbon/human/human_mob.dm b/code/modules/mob/living/carbon/human/human_mob.dm
index 4e44ff47be6..fd601ae0bb3 100644
--- a/code/modules/mob/living/carbon/human/human_mob.dm
+++ b/code/modules/mob/living/carbon/human/human_mob.dm
@@ -991,20 +991,11 @@
affected.custom_pain("You feel a stabbing pain in your chest!")
L.linked_organ.damage = L.linked_organ.min_bruised_damage
-/mob/living/carbon/human/cuff_resist(obj/item/I)
+/mob/living/carbon/human/resist_restraints(attempt_breaking)
if(HAS_TRAIT(src, TRAIT_HULK))
say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
- if(..(I, cuff_break = 1))
- unEquip(I)
- else
- if(..())
- unEquip(I)
-
-/mob/living/carbon/human/resist_restraints()
- if(wear_suit && wear_suit.breakouttime)
- cuff_resist(wear_suit)
- else
- ..()
+ attempt_breaking = TRUE
+ return ..()
/mob/living/carbon/human/generate_name()
name = dna.species.get_random_name(gender)