Skip to content

Commit

Permalink
Cryo tube gib and output fixes (#36374)
Browse files Browse the repository at this point in the history
* Cryo tube gib sanity

* cleaner x axis

* cleaner x axis

* new system for the animation

* now makes it work with gib remains inside

* sanity

* delay for fluff with multiple items

* crank it up

* crank it up

* not much of a difference

* code cleanup

* code cleanup

* code cleanup

* requested change

* FINALLY fixes the lying down issue!

* FINALLY fixes the lying down issue!

* code cutdown

* default

* default

* dir stuff

* dir stuff

* nvm they aint dense

* fixes ITS LOOSE tier issue with locking caused by wrong indentation

* syntax was not the issue

* this will be a lot less annoying if it ignores mobs

* space

* no tab

* moves up

* type fixing

* makes this not do a typecheck if submerging is false first

* scope reduced

* makes dropped limbs only spread if on a turf

* reduces scope to just these for atomicity

* invert logic so it works proper

* stops gibs when in tube

* stops gibs in cryo, makes it only come out on ejection

* keeps the sound

---------

Co-authored-by: SECBATON-GRIFFON <>
  • Loading branch information
SECBATON-GRIFFON authored Jun 20, 2024
1 parent bd6ec20 commit 91d5e85
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 75 deletions.
1 change: 1 addition & 0 deletions __DEFINES/atom_locking_and_control.dm
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#define DENSE_WHEN_LOCKING 2
#define CANT_BE_MOVED_BY_LOCKED_MOBS 4
#define LOCKED_CAN_LIE_AND_STAND 8
#define LOCKED_STAY_INSIDE 16

// Flags for atom.lockflags
#define DENSE_WHEN_LOCKED 1
Expand Down
1 change: 1 addition & 0 deletions code/ATMOSPHERICS/atmospherics.dm
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ Pipelines + Other Objects -> Pipe network
#define VENT_SOUND_DELAY 30

/obj/machinery/atmospherics/Entered(atom/movable/Obj)
. = ..()
if(istype(Obj, /mob/living))
var/mob/living/L = Obj
L.ventcrawl_layer = src.piping_layer
Expand Down
8 changes: 5 additions & 3 deletions code/datums/locking_category.dm
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@

// Updates the position for AM.
/datum/locking_category/proc/update_lock(var/atom/movable/AM)
var/new_loc = owner.loc

if(flags & LOCKED_STAY_INSIDE)
if(owner.loc != AM.loc)
AM.forceMove(owner)
return
var/new_x = x_offset
var/new_y = y_offset

Expand All @@ -70,7 +72,7 @@
new_x = -y_offset
new_y = x_offset


var/new_loc = owner.loc
if ((new_x || new_y) && isturf(new_loc))
var/newer_loc = locate(owner.x + new_x, owner.y + new_y, owner.z)
if (newer_loc) // Edge (no pun intended) case for map borders.
Expand Down
6 changes: 6 additions & 0 deletions code/game/atoms_movable.dm
Original file line number Diff line number Diff line change
Expand Up @@ -306,10 +306,16 @@
M.canmove = 1

category.unlock(AM)
if((category.flags & LOCKED_STAY_INSIDE) && AM.loc == src)
AM.forceMove(src.loc)
//AM.reset_glide_size() // FIXME: Currently broken.

return TRUE

/atom/movable/proc/unlock_atoms(var/category, var/subtypes = FALSE)
for(var/atom/movable/AM in get_locked(category, subtypes))
unlock_atom(AM)

/atom/movable/proc/unlock_from()
if(!locked_to)
return FALSE
Expand Down
156 changes: 98 additions & 58 deletions code/game/machinery/cryo.dm
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
anchored = 1.0
layer = ABOVE_WINDOW_LAYER
plane = OBJ_PLANE
output_dir = SOUTH

var/on = 0
var/ejecting = 0
var/temperature_archived
var/obj/effect/cryo_overlay/glass = null
var/mob/living/occupant = null
var/obj/item/weapon/reagent_containers/glass/beaker = null

Expand All @@ -29,6 +31,25 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
light_power_on = 2
use_auto_lights = 1

/obj/machinery/atmospherics/unary/cryo_cell/Entered(var/atom/movable/Obj, var/atom/OldLoc)
. = ..()

if(OldLoc.type != src.type)
spawn(rand(0,6))
if(OldLoc.type != src.type)
Obj.submerge_anim()

/atom/movable/proc/submerge_anim()
if(loc?.type == /obj/machinery/atmospherics/unary/cryo_cell)
spawn()
animate(src, pixel_y = pixel_y + 2 * PIXEL_MULTIPLIER, time = 7, loop = 1)
spawn(14)
if(loc?.type == /obj/machinery/atmospherics/unary/cryo_cell)
animate(src, pixel_y = pixel_y - 2 * PIXEL_MULTIPLIER, time = 7, loop = 1)
sleep(14)
if(loc?.type == /obj/machinery/atmospherics/unary/cryo_cell)
submerge_anim()

/obj/machinery/atmospherics/unary/cryo_cell/splashable()
return FALSE

Expand Down Expand Up @@ -68,6 +89,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
if(beaker)
detach()
//beaker.loc = get_step(loc, SOUTH) //Beaker is carefully ejected from the wreckage of the cryotube
QDEL_NULL(glass)
..()

/obj/machinery/atmospherics/unary/cryo_cell/MouseDropTo(atom/movable/O as mob|obj, mob/user as mob)
Expand All @@ -84,14 +106,20 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
return
put_mob(L, user)

/obj/machinery/atmospherics/unary/cryo_cell/proc/get_floaters()
var/list/floaters = contents - beaker
if(floaters.len)
return floaters
return 0

/obj/machinery/atmospherics/unary/cryo_cell/MouseDropFrom(over_object, src_location, var/turf/over_location, src_control, over_control, params)
if(!ishigherbeing(usr) && !isrobot(usr) || occupant == usr || usr.incapacitated() || usr.lying)
return
var/mob/user = usr
if(!user.canMouseDrag())
return
if(!occupant)
var/list/floaters = get_floaters()
if(!floaters || !floaters.len)
to_chat(usr, "<span class='warning'>\The [src] is unoccupied!</span>")
return
if(panel_open)
Expand All @@ -112,7 +140,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
if((A == src) || istype(A, /mob))
continue
return
visible_message("[usr] starts to remove [occupant.name] from \the [src].")
visible_message("[usr] starts to remove [counted_english_list(floaters)] from \the [src].")
go_out(over_location, ejector = usr)

/obj/machinery/atmospherics/unary/cryo_cell/process()
Expand Down Expand Up @@ -147,15 +175,15 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
return 0


/obj/machinery/atmospherics/unary/cryo_cell/relaymove(mob/user as mob)
/obj/machinery/atmospherics/unary/cryo_cell/relaymove(mob/user as mob, direction)
// Just gonna assume this guy's vent crawling don't mind me.
if (user != occupant)
return ..()

if(user.stat)
return

go_out(ejector = usr)
go_out(get_step(loc,direction), ejector = usr)


/obj/machinery/atmospherics/unary/cryo_cell/examine(mob/user)
Expand All @@ -164,16 +192,23 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
if(contents.len)
to_chat(user, "You can just about make out some properties of the cryo's murky depths:")
var/count = 0
for(var/atom/movable/floater in (contents - beaker))
var/list/stuff = list()
for(var/atom/movable/floater in ((contents - beaker) - occupant))
if (isobserver(floater))
count++
else
to_chat(user, "A figure floats in the depths, they appear to be [floater.name]")
stuff += floater

if(occupant)
to_chat(user, "A figure floats in the depths, they appear to be [occupant]")

if (count)
// Let's just assume you can only have observers if there's a mob too.
to_chat(user, "<i>...[count] shape\s float behind them...</i>")

if(stuff.len)
to_chat(user, "Miscellaneous contents float in the depths, it appears to be [counted_english_list(stuff)]")

if(beaker)
to_chat(user, "A beaker, releasing the following chemicals into the fluids:")
for(var/datum/reagent/R in beaker.reagents.reagent_list)
Expand Down Expand Up @@ -210,6 +245,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
data["isOperating"] = on
data["ejecting"] = ejecting
data["hasOccupant"] = occupant ? 1 : 0
data["hasContents"] = get_floaters() ? 1 : 0

var/occupantData[0]
if (occupant)
Expand Down Expand Up @@ -295,7 +331,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
detach()

if(href_list["ejectOccupant"])
if(!occupant || isslime(usr) || ispAI(usr))
if(!get_floaters() || isslime(usr) || ispAI(usr))
return 0 // don't update UIs attached to this object
go_out(ejector = usr)

Expand Down Expand Up @@ -353,50 +389,42 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
/obj/machinery/atmospherics/unary/cryo_cell/update_icon()
handle_update_icon()

/obj/effect/cryo_overlay
plane = EFFECTS_PLANE
layer = BELOW_PROJECTILE_LAYER
icon = 'icons/obj/cryogenics.dmi'
icon_state = "lid0"

/obj/machinery/atmospherics/unary/cryo_cell/proc/handle_update_icon() //making another proc to avoid spam in update_icon
overlays.Cut()
vis_contents.Cut()

if(!glass)
glass = new

glass.icon_state = "lid[on]"
vis_contents += glass

if(!panel_open)
icon_state = "pod[on]"

if(!src.occupant)
overlays += "lid[on]" //if no occupant, just put the lid overlay on, and ignore the rest
for(var/atom/movable/floater in get_floaters())
if (!isobserver(floater))
vis_contents += floater
floater.pixel_y = rand(8,32)
floater.pixel_x = rand(-1,1)

if(occupant)
var/image/pickle = image(occupant.icon, occupant.icon_state)
pickle.overlays = occupant.overlays
pickle.pixel_y = 20
vis_contents += occupant
occupant.pixel_y = 20

overlays += pickle
overlays += "lid[on]"
if(src.on && !running_bob_animation) //no bobbing if off
var/up = 0 //used to see if we are going up or down, 1 is down, 2 is up
//var/up = 0 //used to see if we are going up or down, 1 is down, 2 is up
spawn(0) // Without this, the icon update will block. The new thread will die once the occupant leaves.
running_bob_animation = 1
while(src.on && occupant) // Just to make sure bobing stops if cryo goes off with a patient inside.
overlays.len = 0 //have to remove the overlays first

switch(pickle.pixel_y) //this looks messy as fuck but it works, switch won't call itself twice

if(21) //inbetween state, for smoothness
switch(up) //this is set later in the switch, to keep track of where the mob is supposed to go
if(2) //2 is up
pickle.pixel_y = 22 //set to highest

if(1) //1 is down
pickle.pixel_y = 20 //set to lowest

if(20) //mob is at it's lowest
pickle.pixel_y = 21 //set to inbetween
up = 2 //have to go up

if(22) //mob is at it's highest
pickle.pixel_y = 21 //set to inbetween
up = 1 //have to go down

pickle.overlays = occupant.overlays // We sync
overlays += pickle //re-add the mob to the icon
overlays += "lid[on]" //re-add the overlay of the pod, they are inside it, not floating

if(occupant.stat == DEAD || !occupant.has_brain())
overlays += "moverlay_dead"
else
Expand Down Expand Up @@ -426,6 +454,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
overlays += "nomix"

sleep(7) //don't want to jiggle violently, just slowly bob
// now handled in submerge_anim(), just didn't wanna remove this cus it would mess with the update time people are used to
running_bob_animation = 0

if (on && (beaker == null || beaker.reagents.total_volume == 0))
Expand Down Expand Up @@ -507,12 +536,12 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
nanomanager.update_uis(src)
..()

/obj/machinery/atmospherics/unary/cryo_cell/proc/go_out(var/exit, var/ejector)
if(!occupant || ejecting)
/obj/machinery/atmospherics/unary/cryo_cell/proc/go_out(var/turf/exit, var/ejector)
if(!get_floaters() || ejecting)
return 0
if(!exit)
exit = output_turf()
if (occupant.bodytemperature > T0C+31)
exit = get_output()
if (!occupant || occupant.bodytemperature > T0C+31)
boot_contents(exit, FALSE, ejector) //No temperature regulation cycle required
else
ejecting = 1
Expand All @@ -526,16 +555,13 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
boot_contents(exit, TRUE, ejector)
return 1

/obj/machinery/atmospherics/unary/cryo_cell/proc/boot_contents(var/exit = src.loc, var/regulatetemp = TRUE, var/mob/ejector)
for (var/atom/movable/x in src.contents)
if((x in component_parts) || (x == src.beaker))
continue
x.forceMove(get_step(loc, SOUTH))//to avoid PLAAAAANES issues with our cryo cell
/obj/machinery/atmospherics/unary/cryo_cell/proc/boot_contents(var/turf/exit = src.loc, var/regulatetemp = TRUE, var/mob/ejector)
exit = check_output(exit)
for (var/atom/movable/x in get_floaters())
x.forceMove(exit)
x.pixel_y = initial(x.pixel_y)
unlock_atoms() // do this after so mob comes out on right turf with no pixel_y issues
if(occupant)
if(exit == src.loc)
occupant.forceMove(get_step(loc, SOUTH)) //this doesn't account for walls or anything, but i don't forsee that being a problem.
else
occupant.forceMove(exit)
occupant.reset_view()
if (regulatetemp && occupant.bodytemperature < T0C+34.5)
occupant.bodytemperature = T0C+34.5 //just a little bit chilly still
Expand All @@ -549,6 +575,9 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
update_icon()
nanomanager.update_uis(src)

/datum/locking_category/cryo
flags = LOCKED_STAY_INSIDE

/obj/machinery/atmospherics/unary/cryo_cell/proc/put_mob(mob/living/M as mob, mob/living/user)
if (occupant)
if(user)
Expand Down Expand Up @@ -601,7 +630,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
if(user)
add_fingerprint(user)
M.stop_pulling()
M.forceMove(src)
lock_atom(M,/datum/locking_category/cryo) // puts the mob inside with this category
M.reset_view()
if(M.health > -100 && (M.health < 0 || M.sleeping))
to_chat(M, "<span class='bnotice'>You feel a cold liquid surround you. Your skin starts to freeze up.</span>")
Expand Down Expand Up @@ -696,14 +725,25 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
detach()
add_fingerprint(user)

/obj/machinery/atmospherics/unary/cryo_cell/proc/output_turf()
if(!output_dir || !isturf(loc))
return loc
/obj/machinery/atmospherics/unary/cryo_cell/get_output()
return check_output(..())

/obj/machinery/atmospherics/unary/cryo_cell/proc/check_output(var/turf/T)
if(T == src.loc || dense_turf_or_objs(T))
for(var/dirtocheck in list(SOUTH,SOUTHWEST,SOUTHEAST))
T = get_step(src.loc, dirtocheck) //to avoid PLAAAAANES issues with our cryo cell
if(!dense_turf_or_objs(T))
return T
return get_turf(src.loc) // all else fails, do this
return get_turf(T)

var/turf/T = get_step(get_turf(src), output_dir)
if(!T || is_blocked_turf(T))
return loc
return T
/obj/machinery/atmospherics/unary/cryo_cell/proc/dense_turf_or_objs(var/turf/T)
if(T.density)
return 1
for(var/obj/O in T)
if(O.density)
return 1
return 0

/obj/machinery/atmospherics/unary/cryo_cell/conveyor_act(var/atom/movable/AM, var/obj/machinery/conveyor/CB)
if(isliving(AM))
Expand Down
Loading

0 comments on commit 91d5e85

Please sign in to comment.