diff --git a/code/game/gamemodes/changeling/powers/escape_restraints.dm b/code/game/gamemodes/changeling/powers/escape_restraints.dm index 4e6ed4e5cf..08700b1e04 100644 --- a/code/game/gamemodes/changeling/powers/escape_restraints.dm +++ b/code/game/gamemodes/changeling/powers/escape_restraints.dm @@ -21,7 +21,7 @@ if(world.time < changeling.next_escape) to_chat(src, "We are still recovering from our last escape...") return 0 - if(!(C.handcuffed || C.legcuffed)) // No need to waste chems if there's nothing to break out of + if(!(C.handcuffed || C.legcuffed || istype(C.wear_suit,/obj/item/clothing/suit/straight_jacket))) // No need to waste chems if there's nothing to break out of to_chat(C, "We are are not restrained in a way we can escape...") return 0 @@ -37,22 +37,26 @@ C.update_inv_handcuffed() if (C.client) C.client.screen -= W + W.forceMove(C.loc) + W.dropped(C) if(W) - W.loc = C.loc - W.dropped(C) - if(W) - W.layer = initial(W.layer) + W.layer = initial(W.layer) if(C.legcuffed) var/obj/item/weapon/W = C.legcuffed C.legcuffed = null C.update_inv_legcuffed() if(C.client) C.client.screen -= W + W.forceMove(C.loc) + W.dropped(C) if(W) - W.loc = C.loc - W.dropped(C) - if(W) - W.layer = initial(W.layer) + W.layer = initial(W.layer) + if(istype(C.wear_suit, /obj/item/clothing/suit/straight_jacket)) + var/obj/item/clothing/suit/straight_jacket/SJ = C.wear_suit + SJ.forceMove(C.loc) + SJ.dropped(C) + C.wear_suit = null + escape_cooldown *= 1.5 // Straight jackets are tedious compared to cuffs. if(src.mind.changeling.recursive_enhancement) escape_cooldown *= 0.5 diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm index 0da6c3c3d5..7fe4ab232b 100644 --- a/code/game/gamemodes/changeling/powers/revive.dm +++ b/code/game/gamemodes/changeling/powers/revive.dm @@ -45,6 +45,34 @@ BITSET(H.hud_updateflag, STATUS_HUD) BITSET(H.hud_updateflag, LIFE_HUD) + if(H.handcuffed) + var/obj/item/weapon/W = H.handcuffed + H.handcuffed = null + if(H.buckled && H.buckled.buckle_require_restraints) + H.buckled.unbuckle_mob() + H.update_inv_handcuffed() + if (H.client) + H.client.screen -= W + W.forceMove(H.loc) + W.dropped(H) + if(W) + W.layer = initial(W.layer) + if(H.legcuffed) + var/obj/item/weapon/W = H.legcuffed + H.legcuffed = null + H.update_inv_legcuffed() + if(H.client) + H.client.screen -= W + W.forceMove(H.loc) + W.dropped(H) + if(W) + W.layer = initial(W.layer) + if(istype(H.wear_suit, /obj/item/clothing/suit/straight_jacket)) + var/obj/item/clothing/suit/straight_jacket/SJ = H.wear_suit + SJ.forceMove(H.loc) + SJ.dropped(H) + H.wear_suit = null + C.halloss = 0 C.shock_stage = 0 //Pain C << "We have regenerated." diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 988be655cb..87365674b4 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -224,6 +224,8 @@ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER + var/resist_time = 4800 // Eight minutes. + /obj/item/clothing/suit/straight_jacket/attack_hand(mob/living/user as mob) if(ishuman(user)) var/mob/living/carbon/human/H = user diff --git a/code/modules/mob/living/carbon/human/human_resist.dm b/code/modules/mob/living/carbon/human/human_resist.dm new file mode 100644 index 0000000000..37e20d0d21 --- /dev/null +++ b/code/modules/mob/living/carbon/human/human_resist.dm @@ -0,0 +1,120 @@ +/mob/living/carbon/human/process_resist() + //drop && roll + if(on_fire && !buckled) + adjust_fire_stacks(-1.2) + Weaken(3) + spin(32,2) + visible_message( + "[src] rolls on the floor, trying to put themselves out!", + "You stop, drop, and roll!" + ) + sleep(30) + if(fire_stacks <= 0) + visible_message( + "[src] has successfully extinguished themselves!", + "You extinguish yourself." + ) + ExtinguishMob() + return TRUE + + if(handcuffed) + spawn() escape_handcuffs() + else if(legcuffed) + spawn() escape_legcuffs() + else if(wear_suit && istype(wear_suit, /obj/item/clothing/suit/straight_jacket)) + spawn() escape_straight_jacket() + else + ..() + +#define RESIST_ATTACK_DEFAULT 0 +#define RESIST_ATTACK_CLAWS 1 +#define RESIST_ATTACK_BITE 2 + +/mob/living/carbon/human/proc/escape_straight_jacket() + setClickCooldown(100) + + if(can_break_straight_jacket()) + break_straight_jacket() + return + + var/mob/living/carbon/human/H = src + var/obj/item/clothing/suit/straight_jacket/SJ = H.wear_suit + + var/breakouttime = SJ.resist_time // Configurable per-jacket! + + var/attack_type = RESIST_ATTACK_DEFAULT + + if(H.gloves && istype(H.gloves,/obj/item/clothing/gloves/gauntlets/rig)) + breakouttime /= 2 // Pneumatic force goes a long way. + else if(H.species.unarmed_types) + for(var/datum/unarmed_attack/U in H.species.unarmed_types) + if(istype(U, /datum/unarmed_attack/claws)) + breakouttime /= 1.5 + attack_type = RESIST_ATTACK_CLAWS + break + else if(istype(U, /datum/unarmed_attack/bite/sharp)) + breakouttime /= 1.25 + attack_type = RESIST_ATTACK_BITE + break + + switch(attack_type) + if(RESIST_ATTACK_DEFAULT) + visible_message( + "\The [src] struggles to remove \the [SJ]!", + "You struggle to remove \the [SJ]. (This will take around [round(breakouttime / 600)] minutes and you need to stand still.)" + ) + if(RESIST_ATTACK_CLAWS) + visible_message( + "\The [src] starts clawing at \the [SJ]!", + "You claw at \the [SJ]. (This will take around [round(breakouttime / 600)] minutes and you need to stand still.)" + ) + if(RESIST_ATTACK_BITE) + visible_message( + "\The [src] starts gnawing on \the [SJ]!", + "You gnaw on \the [SJ]. (This will take around [round(breakouttime / 600)] minutes and you need to stand still.)" + ) + + if(do_after(src, breakouttime, incapacitation_flags = INCAPACITATION_DISABLED & INCAPACITATION_KNOCKDOWN)) + if(!wear_suit) + return + visible_message( + "\The [src] manages to remove \the [wear_suit]!", + "You successfully remove \the [wear_suit]." + ) + drop_from_inventory(wear_suit) + +#undef RESIST_ATTACK_DEFAULT +#undef RESIST_ATTACK_CLAWS +#undef RESIST_ATTACK_BITE + +/mob/living/carbon/human/proc/can_break_straight_jacket() + if((HULK in mutations) || species.can_shred(src,1)) + return 1 + return ..() + +/mob/living/carbon/human/proc/break_straight_jacket() + visible_message( + "[src] is trying to rip \the [wear_suit]!", + "You attempt to rip your [wear_suit.name] apart. (This will take around 5 seconds and you need to stand still)" + ) + + if(do_after(src, 20 SECONDS, incapacitation_flags = INCAPACITATION_DEFAULT & ~INCAPACITATION_RESTRAINED)) // Same scaling as breaking cuffs, 5 seconds to 120 seconds, 20 seconds to 480 seconds. + if(!wear_suit || buckled) + return + + visible_message( + "[src] manages to rip \the [wear_suit]!", + "You successfully rip your [wear_suit.name]." + ) + + say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!", "RAAAAAAAARGH!", "HNNNNNNNNNGGGGGGH!", "GWAAAAAAAARRRHHH!", "AAAAAAARRRGH!" )) + + qdel(wear_suit) + wear_suit = null + if(buckled && buckled.buckle_require_restraints) + buckled.unbuckle_mob() + +/mob/living/carbon/human/can_break_cuffs() + if(species.can_shred(src,1)) + return 1 + return ..() diff --git a/code/modules/mob/living/carbon/resist.dm b/code/modules/mob/living/carbon/resist.dm index a86189d5f5..1607559336 100644 --- a/code/modules/mob/living/carbon/resist.dm +++ b/code/modules/mob/living/carbon/resist.dm @@ -153,11 +153,6 @@ legcuffed = null update_inv_legcuffed() -/mob/living/carbon/human/can_break_cuffs() - if(species.can_shred(src,1)) - return 1 - return ..() - /mob/living/carbon/escape_buckle() if(!buckled) return diff --git a/html/changelogs/Mechoid - LingJacket.yml b/html/changelogs/Mechoid - LingJacket.yml new file mode 100644 index 0000000000..5aef776f8e --- /dev/null +++ b/html/changelogs/Mechoid - LingJacket.yml @@ -0,0 +1,37 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Mechoid + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - bugfix: "Oversight regarding Changeling revive not removing restraints fixed." + - tweak: "Straight Jackets can now be resisted out of in 8 minutes, or as low as 5 depending on species attacks. Shredding or hulked humans will break out in 20 seconds, destroying the jacket." diff --git a/polaris.dme b/polaris.dme index 7115b068b0..d6989b142f 100644 --- a/polaris.dme +++ b/polaris.dme @@ -1914,6 +1914,7 @@ #include "code\modules\mob\living\carbon\human\human_movement.dm" #include "code\modules\mob\living\carbon\human\human_organs.dm" #include "code\modules\mob\living\carbon\human\human_powers.dm" +#include "code\modules\mob\living\carbon\human\human_resist.dm" #include "code\modules\mob\living\carbon\human\human_species.dm" #include "code\modules\mob\living\carbon\human\inventory.dm" #include "code\modules\mob\living\carbon\human\life.dm"