mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
434 lines
13 KiB
Plaintext
434 lines
13 KiB
Plaintext
/obj/machinery/portable_atmospherics/canister
|
|
name = "canister"
|
|
icon = 'icons/obj/atmos.dmi'
|
|
icon_state = "yellow"
|
|
density = 1
|
|
var/health = 100.0
|
|
flags = CONDUCT
|
|
|
|
var/valve_open = 0
|
|
var/release_pressure = ONE_ATMOSPHERE
|
|
var/release_flow_rate = ATMOS_DEFAULT_VOLUME_PUMP //in L/s
|
|
|
|
var/canister_color = "yellow"
|
|
var/can_label = 1
|
|
start_pressure = 45 * ONE_ATMOSPHERE
|
|
pressure_resistance = 7 * ONE_ATMOSPHERE
|
|
var/temperature_resistance = 1000 + T0C
|
|
volume = 1000
|
|
use_power = 0
|
|
var/release_log = ""
|
|
var/update_flag = 0
|
|
|
|
/obj/machinery/portable_atmospherics/canister/drain_power()
|
|
return -1
|
|
|
|
/obj/machinery/portable_atmospherics/canister/sleeping_agent
|
|
name = "Canister: \[N2O\]"
|
|
icon_state = "redws"
|
|
canister_color = "redws"
|
|
can_label = 0
|
|
|
|
/obj/machinery/portable_atmospherics/canister/nitrogen
|
|
name = "Canister: \[N2\]"
|
|
icon_state = "red"
|
|
canister_color = "red"
|
|
can_label = 0
|
|
|
|
/obj/machinery/portable_atmospherics/canister/oxygen
|
|
name = "Canister: \[O2\]"
|
|
icon_state = "blue"
|
|
canister_color = "blue"
|
|
can_label = 0
|
|
|
|
/obj/machinery/portable_atmospherics/canister/oxygen/prechilled
|
|
name = "Canister: \[O2 (Cryo)\]"
|
|
|
|
/obj/machinery/portable_atmospherics/canister/phoron
|
|
name = "Canister \[Phoron\]"
|
|
icon_state = "orange"
|
|
canister_color = "orange"
|
|
can_label = 0
|
|
|
|
/obj/machinery/portable_atmospherics/canister/carbon_dioxide
|
|
name = "Canister \[CO2\]"
|
|
icon_state = "black"
|
|
canister_color = "black"
|
|
can_label = 0
|
|
|
|
/obj/machinery/portable_atmospherics/canister/air
|
|
name = "Canister \[Air\]"
|
|
icon_state = "grey"
|
|
canister_color = "grey"
|
|
can_label = 0
|
|
|
|
/obj/machinery/portable_atmospherics/canister/air/airlock
|
|
start_pressure = 3 * ONE_ATMOSPHERE
|
|
|
|
/obj/machinery/portable_atmospherics/canister/empty/
|
|
start_pressure = 0
|
|
can_label = 1
|
|
|
|
/obj/machinery/portable_atmospherics/canister/empty/oxygen
|
|
name = "Canister: \[O2\]"
|
|
icon_state = "blue"
|
|
canister_color = "blue"
|
|
/obj/machinery/portable_atmospherics/canister/empty/phoron
|
|
name = "Canister \[Phoron\]"
|
|
icon_state = "orange"
|
|
canister_color = "orange"
|
|
/obj/machinery/portable_atmospherics/canister/empty/nitrogen
|
|
name = "Canister \[N2\]"
|
|
icon_state = "red"
|
|
canister_color = "red"
|
|
/obj/machinery/portable_atmospherics/canister/empty/carbon_dioxide
|
|
name = "Canister \[CO2\]"
|
|
icon_state = "black"
|
|
canister_color = "black"
|
|
/obj/machinery/portable_atmospherics/canister/empty/sleeping_agent
|
|
name = "Canister \[N2O\]"
|
|
icon_state = "redws"
|
|
canister_color = "redws"
|
|
|
|
|
|
|
|
|
|
/obj/machinery/portable_atmospherics/canister/proc/check_change()
|
|
var/old_flag = update_flag
|
|
update_flag = 0
|
|
if(holding)
|
|
update_flag |= 1
|
|
if(connected_port)
|
|
update_flag |= 2
|
|
|
|
var/tank_pressure = air_contents.return_pressure()
|
|
if(tank_pressure < 10)
|
|
update_flag |= 4
|
|
else if(tank_pressure < ONE_ATMOSPHERE)
|
|
update_flag |= 8
|
|
else if(tank_pressure < 15*ONE_ATMOSPHERE)
|
|
update_flag |= 16
|
|
else
|
|
update_flag |= 32
|
|
|
|
if(update_flag == old_flag)
|
|
return 1
|
|
else
|
|
return 0
|
|
|
|
/obj/machinery/portable_atmospherics/canister/update_icon()
|
|
/*
|
|
update_flag
|
|
1 = holding
|
|
2 = connected_port
|
|
4 = tank_pressure < 10
|
|
8 = tank_pressure < ONE_ATMOS
|
|
16 = tank_pressure < 15*ONE_ATMOS
|
|
32 = tank_pressure go boom.
|
|
*/
|
|
|
|
if (src.destroyed)
|
|
src.overlays = 0
|
|
src.icon_state = text("[]-1", src.canister_color)
|
|
return
|
|
|
|
if(icon_state != "[canister_color]")
|
|
icon_state = "[canister_color]"
|
|
|
|
if(check_change()) //Returns 1 if no change needed to icons.
|
|
return
|
|
|
|
src.overlays = 0
|
|
|
|
if(update_flag & 1)
|
|
overlays += "can-open"
|
|
if(update_flag & 2)
|
|
overlays += "can-connector"
|
|
if(update_flag & 4)
|
|
overlays += "can-o0"
|
|
if(update_flag & 8)
|
|
overlays += "can-o1"
|
|
else if(update_flag & 16)
|
|
overlays += "can-o2"
|
|
else if(update_flag & 32)
|
|
overlays += "can-o3"
|
|
return
|
|
|
|
/obj/machinery/portable_atmospherics/canister/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
|
if(exposed_temperature > temperature_resistance)
|
|
health -= 5
|
|
healthcheck()
|
|
|
|
/obj/machinery/portable_atmospherics/canister/proc/healthcheck()
|
|
if(destroyed)
|
|
return 1
|
|
|
|
if (src.health <= 10)
|
|
var/atom/location = src.loc
|
|
location.assume_air(air_contents)
|
|
|
|
src.destroyed = 1
|
|
playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3)
|
|
src.density = 0
|
|
update_icon()
|
|
|
|
if (src.holding)
|
|
src.holding.loc = src.loc
|
|
src.holding = null
|
|
|
|
return 1
|
|
else
|
|
return 1
|
|
|
|
/obj/machinery/portable_atmospherics/canister/process()
|
|
if (destroyed)
|
|
return
|
|
|
|
..()
|
|
|
|
if(valve_open)
|
|
var/datum/gas_mixture/environment
|
|
if(holding)
|
|
environment = holding.air_contents
|
|
else
|
|
environment = loc.return_air()
|
|
|
|
var/env_pressure = environment.return_pressure()
|
|
var/pressure_delta = release_pressure - env_pressure
|
|
|
|
if((air_contents.temperature > 0) && (pressure_delta > 0))
|
|
var/transfer_moles = calculate_transfer_moles(air_contents, environment, pressure_delta)
|
|
transfer_moles = min(transfer_moles, (release_flow_rate/air_contents.volume)*air_contents.total_moles) //flow rate limit
|
|
|
|
var/returnval = pump_gas_passive(src, air_contents, environment, transfer_moles)
|
|
if(returnval >= 0)
|
|
src.update_icon()
|
|
|
|
if(air_contents.return_pressure() < 1)
|
|
can_label = 1
|
|
else
|
|
can_label = 0
|
|
|
|
air_contents.react() //cooking up air cans - add phoron and oxygen, then heat above PHORON_MINIMUM_BURN_TEMPERATURE
|
|
|
|
/obj/machinery/portable_atmospherics/canister/return_air()
|
|
return air_contents
|
|
|
|
/obj/machinery/portable_atmospherics/canister/proc/return_temperature()
|
|
var/datum/gas_mixture/GM = src.return_air()
|
|
if(GM && GM.volume>0)
|
|
return GM.temperature
|
|
return 0
|
|
|
|
/obj/machinery/portable_atmospherics/canister/proc/return_pressure()
|
|
var/datum/gas_mixture/GM = src.return_air()
|
|
if(GM && GM.volume>0)
|
|
return GM.return_pressure()
|
|
return 0
|
|
|
|
/obj/machinery/portable_atmospherics/canister/blob_act()
|
|
src.health -= 200
|
|
healthcheck()
|
|
return
|
|
|
|
/obj/machinery/portable_atmospherics/canister/bullet_act(var/obj/item/projectile/Proj)
|
|
if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
|
|
return
|
|
|
|
if(Proj.damage)
|
|
src.health -= round(Proj.damage / 2)
|
|
healthcheck()
|
|
..()
|
|
|
|
/obj/machinery/portable_atmospherics/canister/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
|
if(!istype(W, /obj/item/weapon/wrench) && !istype(W, /obj/item/weapon/tank) && !istype(W, /obj/item/device/analyzer) && !istype(W, /obj/item/device/pda))
|
|
visible_message("<span class='warning'>\The [user] hits \the [src] with \a [W]!</span>")
|
|
src.health -= W.force
|
|
src.add_fingerprint(user)
|
|
healthcheck()
|
|
|
|
if(istype(user, /mob/living/silicon/robot) && istype(W, /obj/item/weapon/tank/jetpack))
|
|
var/datum/gas_mixture/thejetpack = W:air_contents
|
|
var/env_pressure = thejetpack.return_pressure()
|
|
var/pressure_delta = min(10*ONE_ATMOSPHERE - env_pressure, (air_contents.return_pressure() - env_pressure)/2)
|
|
//Can not have a pressure delta that would cause environment pressure > tank pressure
|
|
var/transfer_moles = 0
|
|
if((air_contents.temperature > 0) && (pressure_delta > 0))
|
|
transfer_moles = pressure_delta*thejetpack.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION)//Actually transfer the gas
|
|
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
|
|
thejetpack.merge(removed)
|
|
user << "You pulse-pressurize your jetpack from the tank."
|
|
return
|
|
|
|
..()
|
|
|
|
nanomanager.update_uis(src) // Update all NanoUIs attached to src
|
|
|
|
/obj/machinery/portable_atmospherics/canister/attack_ai(var/mob/user as mob)
|
|
return src.attack_hand(user)
|
|
|
|
/obj/machinery/portable_atmospherics/canister/attack_hand(var/mob/user as mob)
|
|
return src.ui_interact(user)
|
|
|
|
/obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
|
if (src.destroyed)
|
|
return
|
|
|
|
// this is the data which will be sent to the ui
|
|
var/data[0]
|
|
data["name"] = name
|
|
data["canLabel"] = can_label ? 1 : 0
|
|
data["portConnected"] = connected_port ? 1 : 0
|
|
data["tankPressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0)
|
|
data["releasePressure"] = round(release_pressure ? release_pressure : 0)
|
|
data["minReleasePressure"] = round(ONE_ATMOSPHERE/10)
|
|
data["maxReleasePressure"] = round(10*ONE_ATMOSPHERE)
|
|
data["valveOpen"] = valve_open ? 1 : 0
|
|
|
|
data["hasHoldingTank"] = holding ? 1 : 0
|
|
if (holding)
|
|
data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure()))
|
|
|
|
// update the ui if it exists, returns null if no ui is passed/found
|
|
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
|
if (!ui)
|
|
// the ui does not exist, so we'll create a new() one
|
|
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
|
ui = new(user, src, ui_key, "canister.tmpl", "Canister", 480, 400)
|
|
// when the ui is first opened this is the data it will use
|
|
ui.set_initial_data(data)
|
|
// open the new ui window
|
|
ui.open()
|
|
// auto update every Master Controller tick
|
|
ui.set_auto_update(1)
|
|
|
|
/obj/machinery/portable_atmospherics/canister/Topic(href, href_list)
|
|
|
|
//Do not use "if(..()) return" here, canisters will stop working in unpowered areas like space or on the derelict. // yeah but without SOME sort of Topic check any dick can mess with them via exploits as he pleases -walter0o
|
|
//First comment might be outdated.
|
|
if (!istype(src.loc, /turf))
|
|
return 0
|
|
|
|
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) // exploit protection -walter0o
|
|
usr << browse(null, "window=canister")
|
|
onclose(usr, "canister")
|
|
return
|
|
|
|
if(href_list["toggle"])
|
|
if (valve_open)
|
|
if (holding)
|
|
release_log += "Valve was <b>closed</b> by [usr] ([usr.ckey]), stopping the transfer into the [holding]<br>"
|
|
else
|
|
release_log += "Valve was <b>closed</b> by [usr] ([usr.ckey]), stopping the transfer into the <font color='red'><b>air</b></font><br>"
|
|
else
|
|
if (holding)
|
|
release_log += "Valve was <b>opened</b> by [usr] ([usr.ckey]), starting the transfer into the [holding]<br>"
|
|
else
|
|
release_log += "Valve was <b>opened</b> by [usr] ([usr.ckey]), starting the transfer into the <font color='red'><b>air</b></font><br>"
|
|
log_open()
|
|
valve_open = !valve_open
|
|
|
|
if (href_list["remove_tank"])
|
|
if(holding)
|
|
if (valve_open)
|
|
valve_open = 0
|
|
release_log += "Valve was <b>closed</b> by [usr] ([usr.ckey]), stopping the transfer into the [holding]<br>"
|
|
if(istype(holding, /obj/item/weapon/tank))
|
|
holding.manipulated_by = usr.real_name
|
|
holding.loc = loc
|
|
holding = null
|
|
|
|
if (href_list["pressure_adj"])
|
|
var/diff = text2num(href_list["pressure_adj"])
|
|
if(diff > 0)
|
|
release_pressure = min(10*ONE_ATMOSPHERE, release_pressure+diff)
|
|
else
|
|
release_pressure = max(ONE_ATMOSPHERE/10, release_pressure+diff)
|
|
|
|
if (href_list["relabel"])
|
|
if (can_label)
|
|
var/list/colors = list(\
|
|
"\[N2O\]" = "redws", \
|
|
"\[N2\]" = "red", \
|
|
"\[O2\]" = "blue", \
|
|
"\[Phoron\]" = "orange", \
|
|
"\[CO2\]" = "black", \
|
|
"\[Air\]" = "grey", \
|
|
"\[CAUTION\]" = "yellow", \
|
|
)
|
|
var/label = input("Choose canister label", "Gas canister") as null|anything in colors
|
|
if (label)
|
|
src.canister_color = colors[label]
|
|
src.icon_state = colors[label]
|
|
src.name = "Canister: [label]"
|
|
|
|
src.add_fingerprint(usr)
|
|
update_icon()
|
|
|
|
return 1
|
|
|
|
/obj/machinery/portable_atmospherics/canister/phoron/New()
|
|
..()
|
|
|
|
src.air_contents.adjust_gas("phoron", MolesForPressure())
|
|
src.update_icon()
|
|
return 1
|
|
|
|
/obj/machinery/portable_atmospherics/canister/oxygen/New()
|
|
..()
|
|
|
|
src.air_contents.adjust_gas("oxygen", MolesForPressure())
|
|
src.update_icon()
|
|
return 1
|
|
|
|
/obj/machinery/portable_atmospherics/canister/oxygen/prechilled/New()
|
|
..()
|
|
|
|
src.air_contents.adjust_gas("oxygen", MolesForPressure())
|
|
src.air_contents.temperature = 80
|
|
src.update_icon()
|
|
return 1
|
|
|
|
/obj/machinery/portable_atmospherics/canister/sleeping_agent/New()
|
|
..()
|
|
|
|
air_contents.adjust_gas("sleeping_agent", MolesForPressure())
|
|
src.update_icon()
|
|
return 1
|
|
|
|
//Dirty way to fill room with gas. However it is a bit easier to do than creating some floor/engine/n2o -rastaf0
|
|
/obj/machinery/portable_atmospherics/canister/sleeping_agent/roomfiller/New()
|
|
..()
|
|
air_contents.gas["sleeping_agent"] = 9*4000
|
|
spawn(10)
|
|
var/turf/simulated/location = src.loc
|
|
if (istype(src.loc))
|
|
while (!location.air)
|
|
sleep(10)
|
|
location.assume_air(air_contents)
|
|
air_contents = new
|
|
return 1
|
|
|
|
/obj/machinery/portable_atmospherics/canister/nitrogen/New()
|
|
|
|
..()
|
|
|
|
src.air_contents.adjust_gas("nitrogen", MolesForPressure())
|
|
src.update_icon()
|
|
return 1
|
|
|
|
/obj/machinery/portable_atmospherics/canister/carbon_dioxide/New()
|
|
..()
|
|
src.air_contents.adjust_gas("carbon_dioxide", MolesForPressure())
|
|
src.update_icon()
|
|
return 1
|
|
|
|
|
|
/obj/machinery/portable_atmospherics/canister/air/New()
|
|
..()
|
|
var/list/air_mix = StandardAirMix()
|
|
src.air_contents.adjust_multi("oxygen", air_mix["oxygen"], "nitrogen", air_mix["nitrogen"])
|
|
|
|
src.update_icon()
|
|
return 1
|