diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index a6baa4c8cdb..cf997f6f28d 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -518,6 +518,14 @@ var/list/uplink_items = list() /datum/uplink_item/stealthy_weapons category = "Stealthy and Inconspicuous Weapons" +/datum/uplink_item/stealthy_weapons/garrote + name = "Fiber Wire Garrote" + desc = "A length of fiber wire between two wooden handles, perfect for the discrete assassin. This weapon, when used on a target from behind \ + will instantly put them in your grasp and silence them, as well as causing rapid suffocation. Does not work on those who do not need to breathe." + reference = "GAR" + item = /obj/item/weapon/twohanded/garrote + cost = 12 + /datum/uplink_item/stealthy_weapons/martialarts name = "Martial Arts Scroll" desc = "This scroll contains the secrets of an ancient martial arts technique. You will master unarmed combat, \ diff --git a/code/game/objects/items/weapons/garrote.dm b/code/game/objects/items/weapons/garrote.dm new file mode 100644 index 00000000000..80114bd5dd7 --- /dev/null +++ b/code/game/objects/items/weapons/garrote.dm @@ -0,0 +1,162 @@ +/* + * Contains: + * Traitor fiber wire + * Improvised garrotes + */ + +/obj/item/weapon/twohanded/garrote // 12TC traitor item + name = "fiber wire" + desc = "A length of razor-thin wire with an elegant wooden handle on either end.
You suspect you'd have to be behind the target to use this weapon effectively." + icon_state = "garrot_wrap" + w_class = 1 + var/mob/living/carbon/human/strangling + var/improvised = 0 + var/garrote_time + +/obj/item/weapon/twohanded/garrote/update_icon() + if(strangling) // If we're strangling someone we want our icon to stay wielded + icon_state = "garrot_unwrap" + return + + icon_state = "garrot_[wielded ? "un" : ""]wrap" + +/obj/item/weapon/twohanded/garrote/improvised // Made via tablecrafting + name = "garrote" + desc = "A length of cable with a shoddily-carved wooden handle tied to either end.
You suspect you'd have to be behind the target to use this weapon effectively." + icon_state = "garrot_I_wrap" + improvised = 1 + +/obj/item/weapon/twohanded/garrote/improvised/update_icon() + if(strangling) + icon_state = "garrot_I_unwrap" + return + + icon_state = "garrot_I_[wielded ? "un" : ""]wrap" + +/obj/item/weapon/twohanded/garrote/wield(mob/living/carbon/user) + if(strangling) + user.visible_message("[user] removes the [src] from [strangling]'s neck.", \ + "You remove the [src] from [strangling]'s neck.") + + strangling = null + update_icon() + processing_objects.Remove(src) + + else + ..() + +/obj/item/weapon/twohanded/garrote/attack(mob/living/carbon/M as mob, mob/user as mob) + if(garrote_time > world.time) // Cooldown + return + + if(!istype(user, /mob/living/carbon/human)) // spap_hand is a proc of /mob/living, user is simply /mob + return + + var/mob/living/carbon/human/U = user + + if(!wielded) + user << "You must use both hands to garrote [M]!" + return + + if(!istype(M, /mob/living/carbon/human)) + user << "You don't think that garroting [M] would be very effective..." + return + + if(M == U) + U.suicide() // This will display a prompt for confirmation first. + return + + if(M.dir != U.dir) + user << "You cannot use [src] on [M] from that angle!" + return + + if(improvised && ((M.head && (M.head.flags & HEADCOVERSMOUTH)) || (M.wear_mask && (M.wear_mask.flags & MASKCOVERSMOUTH)))) // Improvised garrotes are blocked by mouth-covering items. + user << "[M]'s neck is blocked by something they're wearing!" + + if(strangling) + user << "You cannot use [src] on two people at once!" + return + + unwield(U) + + U.swap_hand() // For whatever reason the grab will not properly work if we don't have the free hand active. + M.grabbedby(U, 1) + var/obj/item/weapon/grab/G = U.get_active_hand() + U.swap_hand() + + if(G && istype(G)) + if(improvised) // Improvised garrotes start you off with a passive grab, but keep you stunned like an agressive grab. + M.Stun(1) + else + G.state = GRAB_NECK + G.hud.icon_state = "kill" + G.hud.name = "kill" + M.silent += 1 + + garrote_time = world.time + 10 + processing_objects.Add(src) + strangling = M + update_icon() + + playsound(src.loc, 'sound/weapons/cablecuff.ogg', 15, 1, -1) + + M.visible_message("[U] comes from behind and begins garroting [M] with the [src]!", \ + "[U]\ begins garroting you with the [src]![improvised ? "" : " You are unable to speak!"]", \ + "You hear struggling and wire strain against flesh!") + + return + +/obj/item/weapon/twohanded/garrote/process() + + if(!istype(loc, /mob/living/carbon/human)) + strangling = null + update_icon() + processing_objects.Remove(src) + return + + var/mob/living/carbon/human/user = loc + var/obj/item/weapon/grab/G + + if(src == user.r_hand && istype(user.l_hand, /obj/item/weapon/grab)) + G = user.l_hand + + else if(src == user.l_hand && istype(user.r_hand, /obj/item/weapon/grab)) + G = user.r_hand + + else + user.visible_message("[user] loses his grip on [strangling]'s neck.", \ + "You lose your grip on [strangling]'s neck.") + + strangling = null + update_icon() + processing_objects.Remove(src) + + return + + if(!G.affecting) + user.visible_message("[user] loses his grip on [strangling]'s neck.", \ + "You lose your grip on [strangling]'s neck.") + + strangling = null + update_icon() + processing_objects.Remove(src) + + return + + if(G.state < GRAB_NECK) // Only possible with improvised garrotes, essentially this will stun people as if they were aggressively grabbed. Allows for resisting out if you're quick, but not running away. + strangling.Stun(3) + + if(improvised) + strangling.stuttering = max(strangling.stuttering, 3) + strangling.apply_damage(2, OXY, "head") + return + + + strangling.silent = max(strangling.silent, 3) // Non-improvised effects + strangling.apply_damage(4, OXY, "head") + + +/obj/item/weapon/twohanded/garrote/suicide_act(mob/user) + user.visible_message("[user] is wrapping the [src] around \his neck and pulling the handles! It looks like \he's trying to commit suicide.") + playsound(src.loc, 'sound/weapons/cablecuff.ogg', 15, 1, -1) + return (OXYLOSS) \ No newline at end of file diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm index fa0a59010d4..db39efa3845 100644 --- a/code/modules/crafting/recipes.dm +++ b/code/modules/crafting/recipes.dm @@ -192,4 +192,12 @@ result = /obj/item/weapon/soap/ducttape time = 100 reqs = list(/obj/item/stack/tape_roll = 1, - /datum/reagent/liquidgibs = 10) \ No newline at end of file + /datum/reagent/liquidgibs = 10) + +/datum/table_recipe/garrote + name = "Makeshift Garrote" + result = /obj/item/weapon/twohanded/garrote/improvised + time = 15 + reqs = list(/obj/item/stack/sheet/wood = 1, + /obj/item/stack/cable_coil = 5) + tools = list(/obj/item/weapon/kitchen/knife) // Gotta carve the wood into handles \ No newline at end of file diff --git a/icons/obj/weapons.dmi b/icons/obj/weapons.dmi index 892dfe2a64e..728bfaba198 100644 Binary files a/icons/obj/weapons.dmi and b/icons/obj/weapons.dmi differ diff --git a/paradise.dme b/paradise.dme index df54965eea9..ef20c2b52e5 100644 --- a/paradise.dme +++ b/paradise.dme @@ -722,6 +722,7 @@ #include "code\game\objects\items\weapons\extinguisher.dm" #include "code\game\objects\items\weapons\fireworks.dm" #include "code\game\objects\items\weapons\flamethrower.dm" +#include "code\game\objects\items\weapons\garrote.dm" #include "code\game\objects\items\weapons\gift_wrappaper.dm" #include "code\game\objects\items\weapons\handcuffs.dm" #include "code\game\objects\items\weapons\holosign.dm"