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 00000000000..1decaff1047 Binary files /dev/null and b/icons/obj/hoists.dmi differ