mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-09 16:12:17 +00:00
Co-authored-by: Will <7099514+Willburd@users.noreply.github.com> Co-authored-by: Cameron Lennox <killer65311@gmail.com>
365 lines
12 KiB
Plaintext
365 lines
12 KiB
Plaintext
#define HEAT_CAPACITY_HUMAN 100 //249840 J/K, for a 72 kg person.
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell
|
|
name = "cryo cell"
|
|
desc = "Used to cool people down for medical reasons. Totally."
|
|
icon = 'icons/obj/cryogenics.dmi' // map only
|
|
icon_state = "pod_preview"
|
|
density = TRUE
|
|
anchored = TRUE
|
|
layer = UNDER_JUNK_LAYER
|
|
interact_offline = 1
|
|
|
|
var/on = 0
|
|
use_power = USE_POWER_IDLE
|
|
idle_power_usage = 20
|
|
active_power_usage = 200
|
|
buckle_lying = FALSE
|
|
buckle_dir = SOUTH
|
|
clicksound = 'sound/machines/buttonbeep.ogg'
|
|
clickvol = 30
|
|
|
|
var/temperature_archived
|
|
var/mob/living/carbon/occupant = null
|
|
var/obj/item/reagent_containers/glass/beaker = null
|
|
|
|
var/current_heat_capacity = 50
|
|
|
|
var/image/fluid
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/Initialize(mapload)
|
|
. = ..()
|
|
icon = 'icons/obj/cryogenics_split.dmi'
|
|
icon_state = "base"
|
|
initialize_directions = dir
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/Initialize(mapload)
|
|
. = ..()
|
|
var/image/tank = image(icon,"tank")
|
|
tank.alpha = 200
|
|
tank.pixel_y = 18
|
|
tank.plane = MOB_PLANE
|
|
tank.layer = MOB_LAYER+0.2 //Above fluid
|
|
fluid = image(icon, "tube_filler")
|
|
fluid.pixel_y = 18
|
|
fluid.alpha = 200
|
|
fluid.plane = MOB_PLANE
|
|
fluid.layer = MOB_LAYER+0.1 //Below glass, above mob
|
|
add_overlay(tank)
|
|
update_icon()
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/Destroy()
|
|
var/turf/T = src.loc
|
|
T.contents += contents
|
|
if(beaker)
|
|
beaker.forceMove(get_step(loc, SOUTH)) //Beaker is carefully ejected from the wreckage of the cryotube
|
|
beaker = null
|
|
. = ..()
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/process()
|
|
..()
|
|
if(!node)
|
|
return
|
|
if(!on)
|
|
return
|
|
|
|
if(occupant)
|
|
if(occupant.stat != 2)
|
|
process_occupant()
|
|
|
|
if(air_contents)
|
|
temperature_archived = air_contents.temperature
|
|
heat_gas_contents()
|
|
expel_gas()
|
|
|
|
if(abs(temperature_archived-air_contents.temperature) > 1)
|
|
network.update = 1
|
|
|
|
return 1
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/relaymove(mob/user as mob)
|
|
// note that relaymove will also be called for mobs outside the cell with UI open
|
|
if(occupant == user && !user.stat)
|
|
go_out()
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/attack_ghost(mob/user)
|
|
tgui_interact(user)
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/attack_hand(mob/user)
|
|
if(user == occupant)
|
|
return
|
|
|
|
if(panel_open)
|
|
to_chat(user, span_boldnotice("Close the maintenance panel first."))
|
|
return
|
|
|
|
tgui_interact(user)
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/tgui_interact(mob/user, datum/tgui/ui = null)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "Cryo", "Cryo Cell") // 520, 470
|
|
ui.open()
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/tgui_data(mob/user)
|
|
// this is the data which will be sent to the ui
|
|
var/data[0]
|
|
data["isOperating"] = on
|
|
data["hasOccupant"] = occupant ? TRUE : FALSE
|
|
|
|
var/occupantData[0]
|
|
if(occupant)
|
|
occupantData["name"] = occupant.name
|
|
occupantData["stat"] = occupant.stat
|
|
occupantData["health"] = occupant.health
|
|
occupantData["maxHealth"] = occupant.getMaxHealth()
|
|
occupantData["minHealth"] = -(occupant.getMaxHealth())
|
|
occupantData["bruteLoss"] = occupant.getBruteLoss()
|
|
occupantData["oxyLoss"] = occupant.getOxyLoss()
|
|
occupantData["toxLoss"] = occupant.getToxLoss()
|
|
occupantData["fireLoss"] = occupant.getFireLoss()
|
|
occupantData["bodyTemperature"] = occupant.bodytemperature
|
|
data["occupant"] = occupantData;
|
|
|
|
data["cellTemperature"] = round(air_contents.temperature)
|
|
data["cellTemperatureStatus"] = "good"
|
|
if(air_contents.temperature > T0C) // if greater than 273.15 kelvin (0 celcius)
|
|
data["cellTemperatureStatus"] = "bad"
|
|
else if(air_contents.temperature > 225)
|
|
data["cellTemperatureStatus"] = "average"
|
|
|
|
data["isBeakerLoaded"] = beaker ? TRUE : FALSE
|
|
data["beakerLabel"] = null
|
|
data["beakerVolume"] = 0
|
|
if(beaker)
|
|
data["beakerLabel"] = beaker.label_text ? beaker.label_text : null
|
|
if(beaker.reagents && beaker.reagents.reagent_list.len)
|
|
for(var/datum/reagent/R in beaker.reagents.reagent_list)
|
|
data["beakerVolume"] += R.volume
|
|
|
|
return data
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/tgui_act(action, params, datum/tgui/ui)
|
|
if(..() || ui.user == occupant)
|
|
return TRUE
|
|
|
|
. = TRUE
|
|
switch(action)
|
|
if("switchOn")
|
|
on = 1
|
|
update_icon()
|
|
if("switchOff")
|
|
on = 0
|
|
update_icon()
|
|
if("ejectBeaker")
|
|
if(beaker)
|
|
beaker.forceMove(get_step(src.loc, SOUTH))
|
|
beaker = null
|
|
update_icon()
|
|
if("ejectOccupant")
|
|
if(!occupant || isslime(ui.user) || ispAI(ui.user))
|
|
return 0 // don't update UIs attached to this object
|
|
go_out()
|
|
else
|
|
return FALSE
|
|
|
|
add_fingerprint(ui.user)
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/attackby(var/obj/item/G as obj, var/mob/user as mob)
|
|
if(istype(G, /obj/item/reagent_containers/glass))
|
|
if(beaker)
|
|
to_chat(user, span_warning("A beaker is already loaded into the machine."))
|
|
return
|
|
|
|
beaker = G
|
|
user.drop_item()
|
|
G.forceMove(src)
|
|
user.visible_message("[user] adds \a [G] to \the [src]!", "You add \a [G] to \the [src]!")
|
|
SStgui.update_uis(src)
|
|
update_icon()
|
|
else if(istype(G, /obj/item/grab))
|
|
var/obj/item/grab/grab = G
|
|
if(!ismob(grab.affecting))
|
|
return
|
|
if(occupant)
|
|
to_chat(user,span_warning("\The [src] is already occupied by [occupant]."))
|
|
if(grab.affecting.has_buckled_mobs())
|
|
to_chat(user, span_warning("\The [grab.affecting] has other entities attached to it. Remove them first."))
|
|
return
|
|
var/mob/M = grab.affecting
|
|
qdel(grab)
|
|
put_mob(M)
|
|
|
|
return
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/MouseDrop_T(var/mob/target, var/mob/user) //Allows borgs to put people into cryo without external assistance
|
|
if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user)|| !ishuman(target))
|
|
return
|
|
put_mob(target)
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/update_icon()
|
|
cut_overlay(fluid)
|
|
fluid.color = null
|
|
if(on)
|
|
if(beaker)
|
|
fluid.color = beaker.reagents.get_color()
|
|
add_overlay(fluid)
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/proc/process_occupant()
|
|
if(air_contents.total_moles < 10)
|
|
return
|
|
if(occupant)
|
|
if(occupant.stat >= DEAD)
|
|
return
|
|
occupant.bodytemperature += 2*(air_contents.temperature - occupant.bodytemperature)*current_heat_capacity/(current_heat_capacity + air_contents.heat_capacity())
|
|
occupant.bodytemperature = max(occupant.bodytemperature, air_contents.temperature) // this is so ugly i'm sorry for doing it i'll fix it later i promise
|
|
occupant.set_stat(UNCONSCIOUS)
|
|
occupant.dir = SOUTH
|
|
if(occupant.bodytemperature < T0C)
|
|
occupant.Sleeping(max(5, (1/occupant.bodytemperature)*2000))
|
|
occupant.Paralyse(max(5, (1/occupant.bodytemperature)*3000))
|
|
if(air_contents.gas[GAS_O2] > 2)
|
|
if(occupant.getOxyLoss()) occupant.adjustOxyLoss(-1)
|
|
else
|
|
occupant.adjustOxyLoss(-1)
|
|
//severe damage should heal waaay slower without proper chemicals
|
|
if(occupant.bodytemperature < 225)
|
|
if(occupant.getToxLoss())
|
|
occupant.adjustToxLoss(max(-1, -20/occupant.getToxLoss()))
|
|
if(occupant.radiation || occupant.accumulated_rads)
|
|
occupant.radiation -= 25
|
|
occupant.accumulated_rads -= 25
|
|
var/heal_brute = occupant.getBruteLoss() ? min(1, 20/occupant.getBruteLoss()) : 0
|
|
var/heal_fire = occupant.getFireLoss() ? min(1, 20/occupant.getFireLoss()) : 0
|
|
occupant.heal_organ_damage(heal_brute,heal_fire)
|
|
var/has_cryo = occupant.reagents.get_reagent_amount(REAGENT_ID_CRYOXADONE) >= 1
|
|
var/has_clonexa = occupant.reagents.get_reagent_amount(REAGENT_ID_CLONEXADONE) >= 1
|
|
var/has_cryo_medicine = has_cryo || has_clonexa
|
|
if(beaker && !has_cryo_medicine)
|
|
beaker.reagents.trans_to_mob(occupant, 1, CHEM_BLOOD, 10)
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/proc/heat_gas_contents()
|
|
if(air_contents.total_moles < 1)
|
|
return
|
|
var/air_heat_capacity = air_contents.heat_capacity()
|
|
var/combined_heat_capacity = current_heat_capacity + air_heat_capacity
|
|
if(combined_heat_capacity > 0)
|
|
var/combined_energy = T20C*current_heat_capacity + air_heat_capacity*air_contents.temperature
|
|
air_contents.temperature = combined_energy/combined_heat_capacity
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/proc/expel_gas()
|
|
if(air_contents.total_moles < 1)
|
|
return
|
|
// var/datum/gas_mixture/expel_gas = new
|
|
// var/remove_amount = air_contents.total_moles()/50
|
|
// expel_gas = air_contents.remove(remove_amount)
|
|
|
|
// Just have the gas disappear to nowhere.
|
|
//expel_gas.temperature = T20C // Lets expel hot gas and see if that helps people not die as they are removed
|
|
//loc.assume_air(expel_gas)
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/proc/go_out()
|
|
if(!(occupant))
|
|
return
|
|
vis_contents -= occupant
|
|
occupant.pixel_x = occupant.default_pixel_x
|
|
occupant.pixel_y = occupant.default_pixel_y
|
|
occupant.forceMove(get_step(src.loc, SOUTH)) //this doesn't account for walls or anything, but i don't forsee that being a problem.
|
|
if(occupant.bodytemperature < 261 && occupant.bodytemperature >= 70) //Patch by Aranclanos to stop people from taking burn damage after being ejected
|
|
occupant.bodytemperature = 261 // Changed to 70 from 140 by Zuhayr due to reoccurance of bug.
|
|
unbuckle_mob(occupant, force = TRUE)
|
|
occupant.cozyloop.stop() // CHOMPStation Add: Cozy Music
|
|
occupant = null
|
|
current_heat_capacity = initial(current_heat_capacity)
|
|
update_use_power(USE_POWER_IDLE)
|
|
SStgui.update_uis(src)
|
|
return
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/proc/put_mob(mob/living/carbon/M as mob)
|
|
if(stat & (NOPOWER|BROKEN))
|
|
to_chat(usr, span_warning("The cryo cell is not functioning."))
|
|
return
|
|
if(!istype(M))
|
|
to_chat(usr, span_danger("The cryo cell cannot handle such a lifeform!"))
|
|
return
|
|
if(occupant)
|
|
to_chat(usr, span_danger("The cryo cell is already occupied!"))
|
|
return
|
|
if(M.abiotic())
|
|
to_chat(usr, span_warning("Subject may not have abiotic items on."))
|
|
return
|
|
if(!node)
|
|
to_chat(usr, span_warning("The cell is not correctly connected to its pipe network!"))
|
|
return
|
|
M.stop_pulling()
|
|
M.forceMove(src)
|
|
M.extinguish_mob()
|
|
if(M.health > -100 && (M.health < 0 || M.sleeping))
|
|
to_chat(M, span_boldnotice("You feel a cold liquid surround you. Your skin starts to freeze up."))
|
|
occupant = M
|
|
occupant.cozyloop.start() // CHOMPStation Add: Cozy Music
|
|
buckle_mob(occupant, forced = TRUE, check_loc = FALSE)
|
|
vis_contents |= occupant
|
|
occupant.pixel_y += 19
|
|
current_heat_capacity = HEAT_CAPACITY_HUMAN
|
|
update_use_power(USE_POWER_ACTIVE)
|
|
// M.metabslow = 1
|
|
add_fingerprint(usr)
|
|
update_icon()
|
|
SStgui.update_uis(src)
|
|
return 1
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/verb/move_eject()
|
|
set name = "Eject occupant"
|
|
set category = "Object"
|
|
set src in oview(1)
|
|
if(usr == occupant)//If the user is inside the tube...
|
|
if(usr.stat == 2)//and he's not dead....
|
|
return
|
|
to_chat(usr, span_notice("Release sequence activated. This will take two minutes."))
|
|
sleep(1200)
|
|
if(!src || !usr || !occupant || (occupant != usr)) //Check if someone's released/replaced/bombed him already
|
|
return
|
|
go_out()//and release him from the eternal prison.
|
|
else
|
|
if(usr.stat != 0)
|
|
return
|
|
go_out()
|
|
add_fingerprint(usr)
|
|
return
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/verb/move_inside()
|
|
set name = "Move Inside"
|
|
set category = "Object"
|
|
set src in oview(1)
|
|
if(isliving(usr))
|
|
var/mob/living/L = usr
|
|
if(L.has_buckled_mobs())
|
|
to_chat(L, span_warning("You have other entities attached to yourself. Remove them first."))
|
|
return
|
|
if(L.stat != CONSCIOUS)
|
|
return
|
|
put_mob(L)
|
|
|
|
/atom/proc/return_air_for_internal_lifeform(var/mob/living/lifeform)
|
|
return return_air()
|
|
|
|
/obj/machinery/atmospherics/unary/cryo_cell/return_air_for_internal_lifeform()
|
|
//assume that the cryo cell has some kind of breath mask or something that
|
|
//draws from the cryo tube's environment, instead of the cold internal air.
|
|
if(src.loc)
|
|
return loc.return_air()
|
|
else
|
|
return null
|
|
|
|
/datum/data/function/proc/reset()
|
|
return
|
|
|
|
/datum/data/function/proc/r_input(href, href_list, mob/user)
|
|
return
|
|
|
|
/datum/data/function/proc/display()
|
|
return
|
|
|
|
#undef HEAT_CAPACITY_HUMAN
|