diff --git a/code/game/objects/structures/stasis_cage.dm b/code/game/objects/structures/stasis_cage.dm new file mode 100644 index 00000000000..560f64251ee --- /dev/null +++ b/code/game/objects/structures/stasis_cage.dm @@ -0,0 +1,67 @@ +/obj/structure/stasis_cage + name = "stasis cage" + desc = "A high-tech animal cage, designed to keep contained fauna docile and safe." + icon = 'icons/obj/storage.dmi' + icon_state = "critteropen" + density = 1 + + var/mob/living/simple_mob/contained + +/obj/structure/stasis_cage/Initialize() + . = ..() + + var/mob/living/simple_mob/A = locate() in loc + if(A) + contain(A) + +/obj/structure/stasis_cage/attack_hand(var/mob/user) + release() + +/obj/structure/stasis_cage/attack_robot(var/mob/user) + if(Adjacent(user)) + release() + +/obj/structure/stasis_cage/proc/contain(var/mob/living/simple_mob/animal) + if(contained || !istype(animal)) + return + + contained = animal + animal.forceMove(src) + animal.in_stasis = 1 + if(animal.buckled && istype(animal.buckled, /obj/effect/energy_net)) + animal.buckled.forceMove(animal.loc) + icon_state = "critter" + desc = initial(desc) + " \The [contained] is kept inside." + +/obj/structure/stasis_cage/proc/release() + if(!contained) + return + + contained.dropInto(src) + if(contained.buckled && istype(contained.buckled, /obj/effect/energy_net)) + contained.buckled.dropInto(src) + contained.in_stasis = 0 + contained = null + icon_state = "critteropen" + underlays.Cut() + desc = initial(desc) + +/obj/structure/stasis_cage/Destroy() + release() + + return ..() + +/mob/living/simple_mob/MouseDrop(var/obj/structure/stasis_cage/over_object) + if(istype(over_object) && Adjacent(over_object) && CanMouseDrop(over_object, usr)) + + if(!src.buckled || !istype(src.buckled, /obj/effect/energy_net)) + to_chat(usr, "It's going to be difficult to convince \the [src] to move into \the [over_object] without capturing it in a net.") + return + + usr.visible_message("[usr] begins stuffing \the [src] into \the [over_object].", "You begin stuffing \the [src] into \the [over_object].") + Bumped(usr) + if(do_after(usr, 20, over_object)) + usr.visible_message("[usr] has stuffed \the [src] into \the [over_object].", "You have stuffed \the [src] into \the [over_object].") + over_object.contain(src) + else + return ..() \ No newline at end of file diff --git a/code/modules/ai/ai_holder_disabled.dm b/code/modules/ai/ai_holder_disabled.dm index e7cd6aa1f87..8b296b2d106 100644 --- a/code/modules/ai/ai_holder_disabled.dm +++ b/code/modules/ai/ai_holder_disabled.dm @@ -11,6 +11,9 @@ if(holder.incapacitated(INCAPACITATION_DISABLED)) // Stunned in some form. ai_log("can_act() : Incapacited.", AI_LOG_TRACE) return FALSE + if(holder.instasis()) // In a stasis field. + ai_log("can_act() : In a stasis field.", AI_LOG_TRACE) + return FALSE return TRUE // Test if we should switch to STANCE_DISABLE. diff --git a/code/modules/ai/interfaces.dm b/code/modules/ai/interfaces.dm index dbadac87576..59ffbeea722 100644 --- a/code/modules/ai/interfaces.dm +++ b/code/modules/ai/interfaces.dm @@ -60,6 +60,12 @@ if(myid) return myid.GetID() +/mob/living/proc/instasis() + +/mob/living/simple_mob/instasis() + if(in_stasis) + return TRUE + // Respects move cooldowns as if it had a client. // Also tries to avoid being superdumb with moving into certain tiles (unless that's desired). /mob/living/proc/IMove(turf/newloc, safety = TRUE) diff --git a/code/modules/mob/living/simple_mob/life.dm b/code/modules/mob/living/simple_mob/life.dm index bab2aa41293..4c063e4bd93 100644 --- a/code/modules/mob/living/simple_mob/life.dm +++ b/code/modules/mob/living/simple_mob/life.dm @@ -76,6 +76,9 @@ /mob/living/simple_mob/proc/handle_atmos() var/atmos_unsuitable = 0 + if(in_stasis) + return 1 // return early to skip atmos checks + var/atom/A = src.loc if(istype(A,/turf)) diff --git a/code/modules/mob/living/simple_mob/simple_mob.dm b/code/modules/mob/living/simple_mob/simple_mob.dm index ed012264906..f386ab08669 100644 --- a/code/modules/mob/living/simple_mob/simple_mob.dm +++ b/code/modules/mob/living/simple_mob/simple_mob.dm @@ -151,6 +151,8 @@ var/purge = 0 // Cult stuff. var/supernatural = FALSE // Ditto. + // contained in a cage + var/in_stasis = 0 /mob/living/simple_mob/Initialize() verbs -= /mob/verb/observe diff --git a/html/changelogs/Novacat - stasiscages.yml b/html/changelogs/Novacat - stasiscages.yml new file mode 100644 index 00000000000..1e2d52ab4c8 --- /dev/null +++ b/html/changelogs/Novacat - stasiscages.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: Novacat + +# 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: "Stasis Cages which allows safe transport of mobs." diff --git a/vorestation.dme b/vorestation.dme index df3a32044c2..f83aa472300 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -1241,6 +1241,7 @@ #include "code\game\objects\structures\signs.dm" #include "code\game\objects\structures\simple_doors.dm" #include "code\game\objects\structures\snowman.dm" +#include "code\game\objects\structures\stasis_cage.dm" #include "code\game\objects\structures\tank_dispenser.dm" #include "code\game\objects\structures\target_stake.dm" #include "code\game\objects\structures\transit_tubes.dm"