From ebd50a8e00e4d84dbe464f16b60002249e431790 Mon Sep 17 00:00:00 2001 From: MarinaGryphon Date: Mon, 10 Jul 2017 13:32:26 -0500 Subject: [PATCH] Falling In Reverse: Hoists Update (#2573) Adds hoists! Traverse Z-levels in style! Use a hoist kit to deploy it on the same tile as you, in the direction you're facing. Drag an object or mob to the hoist clamp in order to attach them to it. Left click on a hoist to move up or down, depending on its current direction. This will also pull anything attached to the clamp along with it. When the clamp is blocked and can't move up or down further, it will automatically switch direction. To disconnect someone (or something) from a clamp, drag the clamp to the tile you want to put them on. It must be within one tile of both you and whatever is attached to the clamp. When you're done using a hoist, you can collapse it back into a hoist kit with the Collapse Hoist verb, for easy transportation. Hoist kits are not available on the map, so they have to be spawned in. It is preferred to use hoist kits instead of directly spawning a hoist, where possible, when testing. --- baystation12.dme | 1 + code/modules/multiz/hoist.dm | 247 ++++++++++++++++++++++ html/changelogs/MoondancerPony-Hoists.yml | 36 ++++ icons/obj/hoists.dmi | Bin 0 -> 2422 bytes 4 files changed, 284 insertions(+) create mode 100644 code/modules/multiz/hoist.dm create mode 100644 html/changelogs/MoondancerPony-Hoists.yml create mode 100644 icons/obj/hoists.dmi diff --git a/baystation12.dme b/baystation12.dme index 3c5c3915e77..a9e966322aa 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1706,6 +1706,7 @@ #include "code\modules\modular_computers\NTNet\NTNRC\conversation.dm" #include "code\modules\multiz\_stubs.dm" #include "code\modules\multiz\basic.dm" +#include "code\modules\multiz\hoist.dm" #include "code\modules\multiz\mobile_ladders.dm" #include "code\modules\multiz\movement.dm" #include "code\modules\multiz\openspace.dm" diff --git a/code/modules/multiz/hoist.dm b/code/modules/multiz/hoist.dm new file mode 100644 index 00000000000..396f8a5bfa4 --- /dev/null +++ b/code/modules/multiz/hoist.dm @@ -0,0 +1,247 @@ +/////////////////////////// +// Dost thou even hoist? // +/////////////////////////// + +/obj/item/hoist_kit + name = "hoist kit" + desc = "A setup kit for a hoist that can be used to lift things. The hoist will deploy in the direction you're facing." + icon = 'icons/obj/hoists.dmi' + icon_state = "hoist_case" + +/obj/item/hoist_kit/attack_self(mob/user) + new /obj/structure/hoist (get_turf(user), user.dir) + user.visible_message(span("warning", "[user] deploys the hoist kit!"), span("notice", "You deploy the hoist kit!"), span("notice", "You hear the sound of parts snapping into place.")) + qdel(src) + +/obj/effect/hoist_hook + name = "hoist clamp" + desc = "A clamp used to lift people or things." + icon = 'icons/obj/hoists.dmi' + icon_state = "hoist_hook" + var/obj/structure/hoist/source_hoist + can_buckle = 1 + anchored = 1 + +/obj/effect/hoist_hook/MouseDrop_T(atom/movable/AM,mob/user) + var/canuse = use_check(user, USE_DISALLOW_SILICONS) + if(canuse) // to cut it down from 4+ return statements to just 1 + switch(canuse) + if(USE_FAIL_INCAPACITATED) + to_chat(user, span("warning", "You can't do that while incapacitated!")) + if(USE_FAIL_NONLIVING) + to_chat(user, span("warning", "You can't do that while dead.")) + if(USE_FAIL_IS_SILICON) + to_chat(user, span("notice", "You need hands for that.")) + if(USE_FAIL_NON_ADV_TOOL_USR) + to_chat(user, span("warning", "You stare cluelessly at \the [src].")) + return + + if (!AM.simulated || AM.anchored) + to_chat(user, span("notice", "You can't do that.")) + return + if (source_hoist.hoistee) + to_chat(user, span("notice", "\The [source_hoist.hoistee] is already attached to \the [src]!")) + return + source_hoist.attach_hoistee(AM) + user.visible_message(span("danger", "[user] attaches \the [AM] to \the [src]."), span("danger", "You attach \the [AM] to \the [src]."), span("danger", "You hear something clamp into place.")) + +/obj/structure/hoist/proc/attach_hoistee(atom/movable/AM) + if (get_turf(AM) != get_turf(source_hook)) + AM.forceMove(get_turf(source_hook)) + hoistee = AM + if(ismob(AM)) + source_hook.buckle_mob(AM) + else + AM.anchored = 1 + +/obj/effect/hoist_hook/MouseDrop(atom/dest) + ..() + if(!Adjacent(usr) || !dest.Adjacent(usr)) return // carried over from the default proc + + if (!ishuman(usr)) + return + + if (usr.incapacitated()) + to_chat(usr, span("notice", "You can't do that while incapacitated.")) + return + + if (!usr.IsAdvancedToolUser()) + to_chat(usr, span("notice", "You stare cluelessly at \the [src].")) + return + + if (!source_hoist.hoistee) + return + if (!isturf(dest)) + return + if (!dest.Adjacent(source_hoist.hoistee)) + return + + var/turf/desturf = dest + source_hoist.hoistee.forceMove(desturf) + usr.visible_message(span("danger", "[user] detaches \the [source_hoist.hoistee] from the hoist clamp."), span("danger", "You detach \the [source_hoist.hoistee] from the hoist clamp."), span("danger", "You hear something unclamp.")) + source_hoist.release_hoistee() + +/obj/structure/hoist + icon = 'icons/obj/hoists.dmi' + icon_state = "hoist_base" + var/broken = 0 + density = 1 + anchored = 1 + name = "hoist" + desc = "A manual hoist, uses a clamp and pulley to hoist things." + var/atom/movable/hoistee + var/movedir = UP + var/obj/effect/hoist_hook/source_hook + +/obj/structure/hoist/Initialize(mapload, ndir) + . = ..() + dir = ndir + var/turf/newloc = get_step(src, dir) + source_hook = new(newloc) + source_hook.source_hoist = src + +/obj/structure/hoist/Destroy() + if(hoistee) + release_hoistee() + QDEL_NULL(src.source_hook) + return ..() + +/obj/effect/hoist_hook/Destroy() + source_hoist = null + return ..() + +/obj/structure/hoist/proc/release_hoistee() + if(ismob(hoistee)) + source_hook.unbuckle_mob(hoistee) + else + hoistee.anchored = 0 + hoistee = null + +/obj/structure/hoist/proc/break_hoist() + if(broken) + return + broken = 1 + desc += " It looks broken, and the clamp has retracted back into the hoist. Seems like you'd have to re-deploy it to get it to work again." + if(hoistee) + release_hoistee() + QDEL_NULL(source_hook) + +/obj/structure/hoist/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if(prob(50)) + qdel(src) + else + visible_message("\The [src] shakes violently, and neatly collapses as its damage sensors go off.") + collapse_kit() + return + if(3.0) + if(prob(50) && !broken) + break_hoist() + return + +/obj/effect/hoist_hook/ex_act(severity) + switch(severity) + if(1.0) + source_hoist.break_hoist() + return + if(2.0) + if(prob(50)) + source_hoist.break_hoist() + return + if(3.0) + if(prob(25)) + source_hoist.break_hoist() + return + + +/obj/structure/hoist/attack_hand(mob/living/user) + if (!ishuman(user)) + return + + if (user.incapacitated()) + to_chat(user, span("notice", "You can't do that while incapacitated.")) + return + + if (!user.IsAdvancedToolUser()) + to_chat(user, span("notice", "You stare cluelessly at \the [src].")) + return + + if(broken) + to_chat(user, span("warning", "The hoist is broken!")) + return + var/can = can_move_dir(movedir) + var/movtext = movedir == UP ? "raise" : "lower" + if (!can) // If you can't... + movedir = movedir == UP ? DOWN : UP // switch directions! + to_chat(user, span("notice", "You switch the direction of the pulley.")) + return + + if (!hoistee) + user.visible_message(span("notice", "[user] begins to [movtext] the clamp."), span("notice", "You begin to [movtext] the clamp."), span("notice", "You hear the sound of a crank.")) + move_dir(movedir, 0) + return + + var/size + if (ismob(hoistee)) + var/mob/M = hoistee + size = M.mob_size + else if (isobj(hoistee)) + var/obj/O = hoistee + size = O.w_class + + user.visible_message(span("notice", "[user] begins to [movtext] \the [hoistee]!"), span("notice", "You begin to [movtext] \the [hoistee]!"), span("notice", "You hear the sound of a crank.")) + if (do_after(user, (1 SECONDS) * size / 4, act_target = src)) + move_dir(movedir, 1) + +/obj/structure/hoist/proc/collapse_kit() + new /obj/item/hoist_kit(get_turf(src)) + qdel(src) + +/obj/structure/hoist/verb/collapse_hoist() + set name = "Collapse Hoist" + set category = "Object" + set src in range(1) + + if (!ishuman(usr)) + return + + if (isobserver(usr) || usr.incapacitated()) + return + if (!usr.IsAdvancedToolUser()) // thanks nanacode + to_chat(usr, span("notice", "You stare cluelessly at \the [src].")) + return + + if (hoistee) + to_chat(usr, span("notice", "You cannot collapse the hoist with \the [hoistee] attached!")) + return + collapse_kit() + +/obj/structure/hoist/proc/can_move_dir(direction) + var/turf/dest = direction == UP ? GetAbove(source_hook) : GetBelow(source_hook) + switch(direction) + if (UP) + if (!isopenturf(dest)) // can't move into a solid tile + return 0 + if (source_hook in get_step(src, dir)) // you don't get to move above the hoist + return 0 + if (DOWN) + if (!isopenturf(get_turf(source_hook))) // can't move down through a solid tile + return 0 + if (!dest) // can't move if there's nothing to move to + return 0 + return 1 // i thought i could trust myself to write something as simple as this, guess i was wrong + +/obj/structure/hoist/proc/move_dir(direction, ishoisting) + var/can = can_move_dir(direction) + if (!can) + return 0 + var/turf/move_dest = direction == UP ? GetAbove(source_hook) : GetBelow(source_hook) + source_hook.forceMove(move_dest) + if (!ishoisting) + return 1 + hoistee.forceMove(move_dest) + return 1 diff --git a/html/changelogs/MoondancerPony-Hoists.yml b/html/changelogs/MoondancerPony-Hoists.yml new file mode 100644 index 00000000000..b9d99865b93 --- /dev/null +++ b/html/changelogs/MoondancerPony-Hoists.yml @@ -0,0 +1,36 @@ +################################ +# 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: MoondancerPony + +# 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: + - rscadd: "Added a Hoist, deployable via hoist kits. Objects and people can be attached to it and raised/lowered across Z levels without incurring damage." diff --git a/icons/obj/hoists.dmi b/icons/obj/hoists.dmi new file mode 100644 index 0000000000000000000000000000000000000000..1decaff1047761696427ecd5a8284b7dfdd8f5e1 GIT binary patch literal 2422 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 literal 0 HcmV?d00001