diff --git a/code/game/objects/items/weapons/traps.dm b/code/game/objects/items/weapons/traps.dm index 0986abffa8f..57b450ac0e6 100644 --- a/code/game/objects/items/weapons/traps.dm +++ b/code/game/objects/items/weapons/traps.dm @@ -11,36 +11,41 @@ desc = "A mechanically activated leg trap. Low-tech, but reliable. Looks like it could really hurt if you set it off." throwforce = 0 w_class = 3 - origin_tech = list(TECH_MATERIAL = 1) + origin_tech = list(TECH_ENGINEERING = 2) matter = list(DEFAULT_WALL_MATERIAL = 18750) - var/deployed = 0 + var/deployed = FALSE var/time_to_escape = 60 /obj/item/weapon/trap/proc/can_use(mob/user) return (user.IsAdvancedToolUser() && !issilicon(user) && !user.stat && !user.restrained()) -/obj/item/weapon/trap/attack_self(mob/user as mob) +/obj/item/weapon/trap/attack_self(mob/user) ..() if(!deployed && can_use(user)) + if(deploy(user)) + user.drop_from_inventory(src) + anchored = TRUE + +/obj/item/weapon/trap/proc/deploy(mob/user) + user.visible_message( + "[user] starts to deploy \the [src].", + "You begin deploying \the [src]!", + "You hear the slow creaking of a spring." + ) + + if (do_after(user, 5 SECONDS)) user.visible_message( - "[user] starts to deploy \the [src].", - "You begin deploying \the [src]!", - "You hear the slow creaking of a spring." + "[user] deploys \the [src].", + "You deploy \the [src]!", + "You hear a latch click loudly." ) - if (do_after(user, 60)) - user.visible_message( - "[user] has deployed \the [src].", - "You have deployed \the [src]!", - "You hear a latch click loudly." - ) + deployed = TRUE + update_icon() + return TRUE + return FALSE - deployed = 1 - user.drop_from_inventory(src) - update_icon() - anchored = 1 - -/obj/item/weapon/trap/user_unbuckle_mob(mob/user as mob) +/obj/item/weapon/trap/user_unbuckle_mob(mob/user) if(buckled_mob && can_use(user)) user.visible_message( "\The [user] begins freeing \the [buckled_mob] from \the [src].", @@ -48,33 +53,33 @@ "You hear metal creaking." ) if(do_after(user, time_to_escape)) - user.visible_message("\The [buckled_mob] has been freed from \the [src] by \the [user].") + user.visible_message("\The [buckled_mob] is freed from \the [src] by \the [user].") unbuckle_mob() - anchored = 0 + anchored = FALSE -/obj/item/weapon/trap/attack_hand(mob/user as mob) +/obj/item/weapon/trap/attack_hand(mob/user) if(buckled_mob && can_use(user)) user.visible_message( "[user] begins freeing [buckled_mob] from \the [src].", "You carefully begin to free [buckled_mob] from \the [src]." ) if(do_after(user, time_to_escape)) - user.visible_message("[buckled_mob] has been freed from \the [src] by [user].") + user.visible_message("[buckled_mob] is freed from \the [src] by [user].") unbuckle_mob() - anchored = 0 + anchored = FALSE else if(deployed && can_use(user)) user.visible_message( "[user] starts to disarm \the [src].", "You begin disarming \the [src]!", "You hear a latch click followed by the slow creaking of a spring." ) - if(do_after(user, 60)) + if(do_after(user, 6 SECONDS)) user.visible_message( - "[user] has disarmed \the [src].", - "You have disarmed \the [src]!" + "[user] disarms \the [src].", + "You disarm \the [src]!" ) - deployed = 0 - anchored = 0 + deployed = FALSE + anchored = FALSE update_icon() else ..() @@ -98,10 +103,10 @@ //trap the victim in place set_dir(L.dir) - can_buckle = 1 + can_buckle = TRUE buckle_mob(L) to_chat(L, "The steel jaws of \the [src] bite into you, trapping you in place!") - deployed = 0 + deployed = FALSE can_buckle = initial(can_buckle) playsound(src, 'sound/weapons/beartrap_shut.ogg', 100, 1)//Really loud snapping sound @@ -110,7 +115,7 @@ bear.anger += 15//traps make bears really angry bear.instant_aggro() -/obj/item/weapon/trap/Crossed(AM as mob|obj) +/obj/item/weapon/trap/Crossed(atom/movable/AM) if(deployed && isliving(AM)) var/mob/living/L = AM L.visible_message( @@ -120,8 +125,8 @@ ) attack_mob(L) if(!buckled_mob) - anchored = 0 - deployed = 0 + anchored = FALSE + deployed = FALSE update_icon() ..() @@ -137,15 +142,15 @@ icon = 'icons/obj/items.dmi' icon_base = "small" icon_state = "small0" - desc = "A small mechanical trap thas is used to catch small animals like rats, lizards, chick and spiderlings." + desc = "A small mechanical trap that's used to catch small animals like rats, lizards, and chicks." throwforce = 2 force = 1 w_class = 2 - origin_tech = list(TECH_MATERIAL = 1) + origin_tech = list(TECH_ENGINEERING = 1) matter = list(DEFAULT_WALL_MATERIAL = 1750) - deployed = 0 + deployed = FALSE time_to_escape = 3 // Minutes - can_buckle = FALSE + can_buckle = TRUE var/breakout = FALSE var/last_shake = 0 var/list/allowed_mobs = list(/mob/living/simple_animal/rat, /mob/living/simple_animal/chick, /mob/living/simple_animal/lizard) @@ -155,6 +160,17 @@ health = 100 var/datum/weakref/captured = null +/obj/item/weapon/trap/animal/MouseDrop_T(mob/living/M, mob/living/user) + if(!istype(M)) + return + + if(!captured) + if(!is_type_in_list(M, allowed_mobs)) + to_chat(user, span("warning", "[M] won't fit in there!")) + else if(do_after(user, 5 SECONDS)) + capture(M) + else + to_chat(user, "\The [src] is already full!") /obj/item/weapon/trap/animal/update_icon() icon = initial(icon) @@ -164,50 +180,44 @@ ..() if(captured) var/datum/L = captured.resolve() - if (!L) + if (L) + to_chat(user, "[L] is trapped inside!") return - to_chat(user, "\The [src] has [L].") - + else if(deployed) + to_chat(user, span("warning", "It's set up and ready to capture something.")) else - to_chat(user, "\The [src] is empty.") + to_chat(user, "\The [src] is empty and un-deployed.") -/obj/item/weapon/trap/animal/Crossed(AM as mob|obj) - if(world.time - release_time < 50) // If we just released the animal, not to let it get caught again right away +/obj/item/weapon/trap/animal/Crossed(atom/movable/AM) + if(!deployed || !anchored) return - if(captured?.resolve()) // It is full + if(captured) // just in case but this shouldn't happen return + capture(AM) -/obj/item/weapon/trap/animal/proc/capture(var/mob/AM) - if(isliving(AM)) +/obj/item/weapon/trap/animal/proc/capture(var/mob/AM, var/msg = 1) + if(isliving(AM) && is_type_in_list(AM, allowed_mobs)) var/mob/living/L = AM - for(var/f in allowed_mobs) - if(istype(AM, f)) - L.visible_message( - "[L] enters \the [src], and it snaps shut with a clatter!", - "You enter \the [src], and it snaps shut with a clatter!", - "You hear a loud metallic snap!" - ) - can_buckle = TRUE - captured = WEAKREF(L) - playsound(src, 'sound/weapons/beartrap_shut.ogg', 100, 1) - deployed = 1 - buckle_mob(L) - src.animate_shake() - - else if(istype(AM, /obj/effect/spider/spiderling) && spider) // for spiderlings - var/obj/effect/spider/spiderling/S = AM - captured = WEAKREF(S) + if(msg) + L.visible_message( + "[L] enters \the [src], and it snaps shut with a clatter!", + "You enter \the [src], and it snaps shut with a clatter!", + "You hear a loud metallic snap!" + ) + if(AM.loc != loc) + AM.forceMove(loc) + captured = WEAKREF(L) + buckle_mob(L) playsound(src, 'sound/weapons/beartrap_shut.ogg', 100, 1) - deployed = 1 - buckle_mob(S) + deployed = FALSE src.animate_shake() - update_icon() + update_icon() /obj/item/weapon/trap/animal/proc/req_breakout() - if(!deployed) - return 0 // Cage is open... wait, why are you in it's contents then? + if(deployed || !captured) + return 0 // Trap-door is open, no one is captured. if(breakout) return -1 //Already breaking out. return 1 @@ -242,25 +252,19 @@ breakout = FALSE to_chat(escapee, "You successfully break out!") - visible_message("\the [escapee] successfully broke out of \the [src]!") + visible_message("\The [escapee] successfully breaks out of \the [src]!") playsound(loc, "sound/effects/grillehit.ogg", 100, 1) release() -/obj/item/weapon/trap/animal/Collide(AM as mob|obj) - if(isliving(AM)) - Crossed(AM) - else - ..() - /obj/item/weapon/trap/animal/CollidedWith(atom/AM) - if(isliving(AM)) + if(deployed && is_type_in_list(AM, allowed_mobs)) Crossed(AM) else ..() /obj/item/weapon/trap/animal/verb/release_animal() - set src in oview(1) + set src in orange(1) set category = "Object" set name = "Release animal" @@ -273,8 +277,8 @@ var/datum/M = captured ? captured.resolve() : null - if(deployed) - var/open = alert("Do you want to open the cage and free what is inside?",,"No","Yes") + if(M) + var/open = alert("Do you want to open the cage and free \the [M]?",,"No","Yes") if(open == "No") return @@ -284,30 +288,22 @@ return if(usr == M) - to_chat(usr, "You cannot open lock \the [src] from the inside. You would have to forcefully open it.") + to_chat(usr, "You can't open \the [src] from the inside! You'll need to force it open.") return - var/turf/T_cage = get_turf(src) - var/turf/T_user= get_turf(usr) - - if(!T_cage) + var/adj = src.Adjacent(usr) + if(!adj) attack_self(src) return - var/turf/target = get_turf(locate(T_cage.x + (T_cage.x - T_user.x), T_cage.y + (T_cage.y - T_user.y), T_cage.z)) - if(!target) - attack_self(src) - return - - release(usr, target) + release(usr) /obj/item/weapon/trap/animal/crush_act() - for (var/atom/movable/A in src) - if(istype(A, /mob/living)) - var/mob/living/M = A - M.gib() - else if(A.simulated) - A.ex_act(1) + if(captured) + var/datum/L = captured ? captured.resolve() : null + if(L && isliving(L)) + var/mob/living/LL = L + LL.gib() new /obj/item/stack/material/steel(get_turf(src)) qdel(src) @@ -321,8 +317,8 @@ health -= rand(30, 60) if (health <= 0) - for (var/atom/movable/A as mob|obj in src) - A.ex_act(severity + 1) + if(captured) + release() new /obj/item/stack/material/steel(get_turf(src)) qdel(src) @@ -340,7 +336,6 @@ var/datum/L = captured ? captured.resolve() : null if (!L) - deployed = FALSE captured = null release_time = world.time return @@ -349,41 +344,51 @@ if (isliving(L)) var/mob/living/ll = L msg = "[ll] runs out of \the [src]." - else if (istype(L, /obj/effect/spider/spiderling)) - var/obj/effect/spider/spiderling/S = L - msg = "[S] jumps out of \the [src]." unbuckle_mob() captured = null visible_message(msg) animate_shake() - deployed = FALSE update_icon() release_time = world.time - can_buckle = FALSE -/obj/item/weapon/trap/animal/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/reagent_containers) && contents.len) - var/mob/living/L = pick(contents) - W.afterattack(L, user, TRUE) +/obj/item/weapon/trap/animal/attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = W + var/mob/living/M = G.affecting + + if (G.state == GRAB_PASSIVE || G.state == GRAB_UPGRADING) + to_chat(user, span("notice", "You need a better grip on \the [M]!")) + return + + user.visible_message("[user] starts putting [M] into \the [src].", "You start putting [M] into \the [src].") + + if (!is_type_in_list(M, allowed_mobs)) + to_chat(user, span("warning", "[M] won't fit in there!")) + return + + if (do_mob(user, M, 3 SECONDS, needhand = 0)) + if(captured?.resolve()) + return + capture(M) + else if(W.iswelder()) var/obj/item/weapon/weldingtool/WT = W - if (!WT.welding) - to_chat(user, "Your \the [W] is off!") + if(!WT.welding) + to_chat(user, span("warning", "Your \the [W] is off!")) return - user.visible_message("[user] is trying to slice \the [src]!", - "You are trying to slice \the [src]!") + user.visible_message("[user] is trying to slice \the [src] open!", + "You are trying to slice \the [src] open!") - if (!do_after(user, 3 SECONDS, act_target = src)) - return - if(WT.remove_fuel(0, user)) - user.visible_message("[user] is sliced \the [src]!", - "You sliced \the [src]!") - new /obj/item/stack/rods(src.loc, resources["rods"]) - if(resources.len == 2) - new /obj/item/stack/material/steel(src.loc, resources["metal"]) - release(user) - qdel(src) + if (do_after(user, 30/W.toolspeed, act_target = src)) + if(WT.remove_fuel(2, user)) + user.visible_message("[user] slices \the [src] open!", + "You slice \the [src] open!") + new /obj/item/stack/rods(src.loc, resources["rods"]) + if(resources.len == 2) + new /obj/item/stack/material/steel(src.loc, resources["metal"]) + release(user) + qdel(src) else if(W.isscrewdriver()) var/turf/T = get_turf(src) @@ -392,19 +397,14 @@ return user.visible_message("[user] is trying to [anchored ? "un" : "" ]secure \the [src]!", - "You are trying to [anchored ? "un" : "" ]secure \the [src]!") + "You are trying to [anchored ? "un" : "" ]secure \the [src]!") playsound(src.loc, "sound/items/[pick("Screwdriver", "Screwdriver2")].ogg", 50, 1) - if (!do_after(user, 3 SECONDS, act_target = src)) - return - density = !density - anchored = !anchored - user.visible_message("[user] has [anchored ? "" : "un" ]secured \the [src]!", - "You have [anchored ? "" : "un" ]secured \the [src]!") - - else if(istype(W, /obj/item/weapon) && contents.len) - var/mob/living/L = pick(contents) - L.attackby(W, user) + if (do_after(user, 30/W.toolspeed, act_target = src)) + density = !density + anchored = !anchored + user.visible_message("[user] [anchored ? "" : "un" ]secures \the [src]!", + "You [anchored ? "" : "un" ]secure \the [src]!") else ..() @@ -412,169 +412,107 @@ ..() if(captured) var/datum/M = captured.resolve() - if(!M) - captured = null - return if(isliving(M)) var/mob/living/L = M if(L && buckled_mob.buckled == src) - L.forceMove(src.loc) + L.forceMove(loc) else if(L) captured = null + else + captured = null -/obj/item/weapon/trap/animal/attack_hand(mob/user as mob) - - if (!user) return - if(user.loc == src) // not to pick ourselves +/obj/item/weapon/trap/animal/attack_hand(mob/user) + if(user.loc == src || captured) return - if(anchored) - to_chat(user, "\The [src] is achorned to the floor!") - return - - if (hasorgans(user)) - var/mob/living/carbon/human/H = user - var/obj/item/organ/external/temp = H.organs_by_name["r_hand"] - if (user.hand) - temp = H.organs_by_name["l_hand"] - if(temp && !temp.is_usable()) - to_chat(user, "You try to move your [temp.name], but cannot!") - return - if(!temp) - to_chat(user, "You try to use your hand, but realize it is no longer attached!") - return - src.pickup(user) - if (istype(src.loc, /obj/item/weapon/storage)) - var/obj/item/weapon/storage/S = src.loc - S.remove_from_storage(src) - - src.throwing = 0 - if (src.loc == user) - if(!user.prepare_for_slotmove(src)) - return - else if(isliving(src.loc)) - return - - // If equipping onto active hand fails, drop it on the floor. - if (!user.put_in_active_hand(src)) - forceMove(user.loc) - return - -/obj/item/weapon/trap/animal/MouseDrop(over_object, src_location, over_location) - if(isliving(usr)) - if(usr.isMonkey() && (/mob/living/carbon/human/monkey in allowed_mobs)) // Because monkeys can be of type of just human. - usr.visible_message("[usr] is attempting to enter \the [src] without triggering it to pass through.", - "You are attempting to enter \the [src] without triggering it to pass through. " - ) - if (!do_after(usr, 2 SECONDS, act_target = src)) - return - if(prob(50)) // 50% chance to pass by without getting caught. - usr.forceMove(src.loc) - usr.visible_message("[usr] pass through \the [src] without triggering it.", - "You pass through \the [src] without triggering it." - ) - return - usr.forceMove(src) - - usr.visible_message("[usr] accidentally triggered \the [src]", - "You accidentally triggered \the [src]" - ) - playsound(src, 'sound/weapons/beartrap_shut.ogg', 100, 1) - deployed = 1 - update_icon() - src.animate_shake() - return - for(var/f in allowed_mobs) - if(istype(usr, f)) - usr.visible_message("[usr] is attempting to enter \the [src] without triggering it to pass through.", - "You are attempting to enter \the [src] without triggering it to pass through. " - ) - if (!do_after(usr, 2 SECONDS, act_target = src)) - return - if(prob(50)) // 50% chance to pass by without getting caught. - usr.forceMove(src.loc) - usr.visible_message("[usr] pass through \the [src] without triggering it.", - "You pass through \the [src] without triggering it." - ) - return - usr.forceMove(src) - - usr.visible_message("[usr] accidentally triggered \the [src]", - "You accidentally triggered \the [src]" - ) - playsound(src, 'sound/weapons/beartrap_shut.ogg', 100, 1) - deployed = 1 - update_icon() - src.animate_shake() - if(iscarbon(usr)) - usr.visible_message("[usr] is attempting to enter \the [src] without triggering it to pass through.", - "You are attempting to enter \the [src] without triggering it to pass through. " - ) - if (!do_after(usr, 2 SECONDS, act_target = src)) - return - usr.forceMove(src.loc) - usr.visible_message("[usr] pass through \the [src] without triggering it.", - "You pass through \the [src] without triggering it." - ) + if(anchored && deployed) + to_chat(user, span("notice", "\The [src] is already anchored and set!")) + else if(anchored) + deploy(user) else ..() -/obj/item/weapon/trap/animal/attack_self(mob/user as mob) +/obj/item/weapon/trap/animal/proc/pass_without_trace(mob/user, pct = 100) + if(!is_type_in_list(user, allowed_mobs)) + user.forceMove(loc) + user.visible_message("[user] passes over \the [src] without triggering it.", + "You pass over \the [src] without triggering it." + ) + else + user.visible_message("[user] attempts to pass through \the [src] without triggering it.", + "You attempt to pass through \the [src] without triggering it. " + ) + if(do_after(user, 2 SECONDS, act_target = src)) + if(prob(pct)) + user.forceMove(loc) + user.visible_message("[user] passes through \the [src] without triggering it.", + "You pass through \the [src] without triggering it." + ) + else + user.forceMove(loc) + user.visible_message("[user] accidentally triggers \the [src]!", + "You accidentally trigger \the [src]!" + ) + capture(user) + +/obj/item/weapon/trap/animal/MouseDrop(over_object, src_location, over_location) + if(!isliving(usr) || !src.Adjacent(usr)) + return + + if(captured) + pass_without_trace(usr) // It's full + + if((usr.isMonkey() && (/mob/living/carbon/human/monkey in allowed_mobs)) || is_type_in_list(usr, allowed_mobs)) // Because monkeys can be of type of just human. + pass_without_trace(usr, 50) + return + + else if(iscarbon(usr)) + pass_without_trace(usr) + + else + ..() + +/obj/item/weapon/trap/animal/attack_self(mob/user) if(!can_use(user)) to_chat(user, "You cannot use \the [src].") return - if(!contents.len) - return - - release(user, user.loc) + if(captured) + release(user, user.loc) /obj/item/weapon/trap/animal/attack(var/target, mob/living/user) - if(world.time - release_time < 50) // If we just released the animal, not to let it get caught again right away + if(!deployed) return - if(contents.len) // It is full + if(captured) // It is full return if(isliving(target)) var/mob/living/M = target - for(var/f in allowed_mobs) - if(istype(M, f)) - user.visible_message( - "[user] traps [M] inside of \the [src].", - "You trap [M] inside of the \the [src]!", - "You hear a loud metallic snap!" - ) - captured = WEAKREF(M) - M.forceMove(src) - playsound(src, 'sound/weapons/beartrap_shut.ogg', 100, 1) - deployed = TRUE - update_icon() - src.animate_shake() - - else if(istype(target, /obj/effect/spider/spiderling) && spider) // for spiderlings - var/obj/effect/spider/spiderling/S = target - captured = WEAKREF(S) - S.forceMove(src) - STOP_PROCESSING(SSprocessing, S) - playsound(src, 'sound/weapons/beartrap_shut.ogg', 100, 1) - deployed = TRUE - update_icon() - src.animate_shake() + if(is_type_in_list(M, allowed_mobs)) + user.visible_message( + "[user] traps [M] inside of \the [src].", + "You trap [M] inside of the \the [src]!", + "You hear a loud metallic snap!" + ) + capture(M, msg = 0) else ..() +/obj/item/weapon/trap/animal/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + return TRUE + /obj/item/weapon/trap/animal/medium name = "medium trap" - desc = "A medium mechanical trap thas is used to catch medium size animals like cat, corgi, diyaab, monkey, yithian, pengiuns, chicken, nymph. Sometimes even maintainence drones, spiderbots and PAi." + desc = "A medium mechanical trap that is used to catch moderately-sized animals like cats, monkeys, nymphs, and wayward maintenance drones." icon_base = "medium" icon_state = "medium0" throwforce = 4 force = 5 w_class = 4 - origin_tech = list(TECH_MATERIAL = 3) + origin_tech = list(TECH_ENGINEERING = 3) matter = list(DEFAULT_WALL_MATERIAL = 5750) - deployed = 0 + deployed = FALSE resources = list(rods = 12) spider = FALSE @@ -587,16 +525,16 @@ /obj/item/weapon/trap/animal/large name = "large trap" - desc = "A large mechanical trap thas is used to catch medium size animals like dog, spider, carp, goat, cow, shark, fox, bear, cavern dwellers, and other kinds of Xenomorphs." + desc = "A large mechanical trap that is used to catch larger animals, from spiders and dogs to bears and even larger mammals." icon_base = "large" icon_state = "large0" throwforce = 6 force = 10 w_class = 6 density = 1 - origin_tech = list(TECH_MATERIAL = 4) + origin_tech = list(TECH_ENGINEERING = 3) matter = list(DEFAULT_WALL_MATERIAL = 15750) - deployed = 0 + deployed = FALSE resources = list(rods = 12, metal = 4) spider = FALSE @@ -607,55 +545,66 @@ /mob/living/simple_animal/hostile/carp, /mob/living/simple_animal/hostile/bear, /mob/living/simple_animal/hostile/alien, /mob/living/simple_animal/hostile/giant_spider, /mob/living/simple_animal/hostile/commanded/dog, /mob/living/simple_animal/hostile/retaliate/cavern_dweller, /mob/living/carbon/human/) -/obj/item/weapon/trap/animal/large/attack_hand(mob/user as mob) - return +/obj/item/weapon/trap/animal/large/attack_hand(mob/user) + if(user == buckled_mob) + return + else if(!anchored) + to_chat(user, span("warning", "You need to anchor \the [src] first!")) + else if(captured) + to_chat(user, span("warning", "You can't deploy \the [src] with something caught!")) + else + ..() -/obj/item/weapon/trap/animal/large/attackby(obj/item/W as obj, mob/user as mob) - if(iswrench(W)) +/obj/item/weapon/trap/animal/large/attackby(obj/item/W, mob/user) + if(W.iswrench()) var/turf/T = get_turf(src) if(!T) to_chat(user, "There is nothing to secure [src] to!") return - user.visible_message("[user] is trying to [anchored ? "un" : "" ]secure \the [src]!", - "You are trying to [anchored ? "un" : "" ]secure \the [src]!") - playsound(src.loc, W.usesound, 50, 1) - - if (!do_after(user, 3 SECONDS, act_target = src)) + if(anchored && deployed) + to_chat(user, span("warning", "You can't do that while \the [src] is deployed! Undeploy it first.")) return - anchored = !anchored - user.visible_message("[user] has [anchored ? "" : "un" ]secured \the [src]!", - "You have [anchored ? "" : "un" ]secured \the [src]!") - else if(istype(W, /obj/item/weapon/screwdriver)) + user.visible_message("[user] begins [anchored ? "un" : "" ]securing \the [src]!", + "You beign [anchored ? "un" : "" ]securing \the [src]!") + playsound(src.loc, W.usesound, 50, 1) + + if(do_after(user, 30/W.toolspeed, act_target = src)) + anchored = !anchored + user.visible_message("[user] [anchored ? "" : "un" ]secures \the [src]!", + "You [anchored ? "" : "un" ]secure \the [src]!") + + else if(W.isscrewdriver()) + // Unlike smaller traps, screwdriver shouldn't work on this. return else ..() /obj/item/weapon/trap/animal/large/MouseDrop(over_object, src_location, over_location) - if(isliving(usr) && ishuman(usr)) - usr.visible_message("[usr] is attempting to enter \the [src] without triggering it to pass through.", - "You are attempting to enter \the [src] without triggering it to pass through. " - ) - if (!do_after(usr, 2 SECONDS, act_target = src)) - return - if(usr.a_intent == I_HELP || captured?.resolve() || (usr.a_intent != I_HURT && prob(50))) // 50% chance to pass by without getting caught on disarm, drag, 100% on help. Harm will get you caught. - usr.forceMove(src.loc) - usr.visible_message("[usr] pass through \the [src] without triggering it.", - "You pass through \the [src] without triggering it." - ) - return - usr.forceMove(src) + if(captured) + to_chat(usr, span("warning", "The trap door's down, you can't get through there!")) + return - usr.visible_message("[usr] accidentally triggered \the [src]", - "You accidentally triggered \the [src]" - ) - playsound(src, 'sound/weapons/beartrap_shut.ogg', 100, 1) - deployed = 1 - update_icon() - src.animate_shake() - else + if(!src.Adjacent(usr)) + return + + if(!ishuman(usr)) ..() + return + + var/pct = 0 + if(usr.a_intent == I_HELP) + pct = 100 + else if(usr.a_intent != I_HURT) + pct = 50 + + pass_without_trace(usr, pct) + +/obj/item/weapon/trap/animal/large/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(deployed) + return TRUE + return FALSE /obj/item/weapon/large_trap_foundation name = "large trap foundation" @@ -666,7 +615,7 @@ force = 5 w_class = 5 -/obj/item/weapon/large_trap_foundation/attackby(obj/item/W as obj, mob/user as mob) +/obj/item/weapon/large_trap_foundation/attackby(obj/item/W, mob/user) if(istype(W, /obj/item/stack/rods)) var/obj/item/stack/rods/O = W if(O.get_amount() >= 12) diff --git a/html/changelogs/johnwildkins-trapfix.yml b/html/changelogs/johnwildkins-trapfix.yml new file mode 100644 index 00000000000..5f1d3c87a55 --- /dev/null +++ b/html/changelogs/johnwildkins-trapfix.yml @@ -0,0 +1,46 @@ +################################ +# 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 +# balance +# admin +# backend +# security +# refactor +################################# + +# Your name. +author: JohnWildkins + +# 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: + - refactor: "Traps have been overhauled on the back-end, and their interactions simplified to the end-user." + - tweak: "Large traps must now be anchored and then set before use. The process takes three seconds with a wrench and five seconds with an open hand respectively. Large traps can only deploy once anchored." + - tweak: "You can place someone/thing into a large trap (via buckling) regardless of the trap's deployment." + - bugfix: "You can once again anchor large traps to the floor with a wrench." + - bugfix: "Fixed certain parts of the trap capture event not firing depending on the method of capture." + - bugfix: "You can no longer teleport inside of traps by attempting to sneak through them from a long distance away." diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi index 9386cbeca7a..c7feb6943b9 100644 Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ