Files
S.P.L.U.R.T-Station-13/code/modules/atmospherics/machinery/portable/canister.dm
2021-02-22 21:05:07 +08:00

484 lines
17 KiB
Plaintext

#define CAN_DEFAULT_RELEASE_PRESSURE (ONE_ATMOSPHERE)
/obj/machinery/portable_atmospherics/canister
name = "canister"
desc = "A canister for the storage of gas."
icon_state = "yellow"
density = TRUE
volume = 1000
armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 100, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 50)
max_integrity = 250
integrity_failure = 0.4
pressure_resistance = 7 * ONE_ATMOSPHERE
var/valve_open = FALSE
var/release_log = ""
var/filled = 0.5
var/gas_type
var/release_pressure = ONE_ATMOSPHERE
var/can_max_release_pressure = (ONE_ATMOSPHERE * 10)
var/can_min_release_pressure = (ONE_ATMOSPHERE / 10)
// this removes atmos fusion cans**
///Max amount of heat allowed inside of the canister before it starts to melt (different tiers have different limits)
// var/heat_limit = 5000
///Max amount of pressure allowed inside of the canister before it starts to break (different tiers have different limits)
// var/pressure_limit = 50000
var/temperature_resistance = 1000 + T0C
var/starter_temp
// Prototype vars
var/prototype = FALSE
var/valve_timer = null
var/timer_set = 30
var/default_timer_set = 30
var/minimum_timer_set = 1
var/maximum_timer_set = 300
var/timing = FALSE
var/restricted = FALSE
///Set the tier of the canister and overlay used
// var/mode = CANISTER_TIER_1
req_access = list()
var/update = 0
var/static/list/label2types = list(
"n2" = /obj/machinery/portable_atmospherics/canister/nitrogen,
"o2" = /obj/machinery/portable_atmospherics/canister/oxygen,
"co2" = /obj/machinery/portable_atmospherics/canister/carbon_dioxide,
"plasma" = /obj/machinery/portable_atmospherics/canister/toxins,
"n2o" = /obj/machinery/portable_atmospherics/canister/nitrous_oxide,
"no2" = /obj/machinery/portable_atmospherics/canister/nitryl,
"bz" = /obj/machinery/portable_atmospherics/canister/bz,
"air" = /obj/machinery/portable_atmospherics/canister/air,
"water vapor" = /obj/machinery/portable_atmospherics/canister/water_vapor,
"tritium" = /obj/machinery/portable_atmospherics/canister/tritium,
"hyper-noblium" = /obj/machinery/portable_atmospherics/canister/nob,
"stimulum" = /obj/machinery/portable_atmospherics/canister/stimulum,
"pluoxium" = /obj/machinery/portable_atmospherics/canister/pluoxium,
"caution" = /obj/machinery/portable_atmospherics/canister,
"miasma" = /obj/machinery/portable_atmospherics/canister/miasma,
"methane" = /obj/machinery/portable_atmospherics/canister/methane,
"methyl bromide" = /obj/machinery/portable_atmospherics/canister/methyl_bromide
)
/obj/machinery/portable_atmospherics/canister/interact(mob/user)
if(!allowed(user))
to_chat(user, "<span class='warning'>Error - Unauthorized User</span>")
playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1)
return
..()
/obj/machinery/portable_atmospherics/canister/nitrogen
name = "n2 canister"
desc = "Nitrogen. Reportedly useful for something."
icon_state = "red"
gas_type = /datum/gas/nitrogen
/obj/machinery/portable_atmospherics/canister/oxygen
name = "o2 canister"
desc = "Oxygen. Necessary for human life."
icon_state = "blue"
gas_type = /datum/gas/oxygen
/obj/machinery/portable_atmospherics/canister/carbon_dioxide
name = "co2 canister"
desc = "Carbon dioxide. What the fuck is carbon dioxide?"
icon_state = "black"
gas_type = /datum/gas/carbon_dioxide
/obj/machinery/portable_atmospherics/canister/toxins
name = "plasma canister"
desc = "Plasma. The reason YOU are here. Highly toxic."
icon_state = "orange"
gas_type = /datum/gas/plasma
/obj/machinery/portable_atmospherics/canister/bz
name = "\improper BZ canister"
desc = "BZ. A powerful hallucinogenic nerve agent."
icon_state = "purple"
gas_type = /datum/gas/bz
/obj/machinery/portable_atmospherics/canister/nitrous_oxide
name = "n2o canister"
desc = "Nitrous oxide. Known to cause drowsiness."
icon_state = "redws"
gas_type = /datum/gas/nitrous_oxide
/obj/machinery/portable_atmospherics/canister/air
name = "air canister"
desc = "Pre-mixed air."
icon_state = "grey"
/obj/machinery/portable_atmospherics/canister/tritium
name = "tritium canister"
desc = "Tritium. Inhalation might cause irradiation."
icon_state = "green"
gas_type = /datum/gas/tritium
/obj/machinery/portable_atmospherics/canister/nob
name = "hyper-noblium canister"
desc = "Hyper-Noblium. More noble than all other gases."
icon_state = "freon"
gas_type = /datum/gas/hypernoblium
/obj/machinery/portable_atmospherics/canister/nitryl
name = "nitryl canister"
desc = "Nitryl. Feels great 'til the acid eats your lungs."
icon_state = "brown"
gas_type = /datum/gas/nitryl
/obj/machinery/portable_atmospherics/canister/stimulum
name = "stimulum canister"
desc = "Stimulum. High energy gas, high energy people."
icon_state = "darkpurple"
gas_type = /datum/gas/stimulum
/obj/machinery/portable_atmospherics/canister/pluoxium
name = "pluoxium canister"
desc = "Pluoxium. Like oxygen, but more bang for your buck."
icon_state = "darkblue"
gas_type = /datum/gas/pluoxium
/obj/machinery/portable_atmospherics/canister/water_vapor
name = "water vapor canister"
desc = "Water vapor. We get it, you vape."
icon_state = "water_vapor"
gas_type = /datum/gas/water_vapor
filled = 1
/obj/machinery/portable_atmospherics/canister/miasma
name = "miasma canister"
desc = "Miasma. Makes you wish your nose were blocked."
icon_state = "miasma"
gas_type = /datum/gas/miasma
filled = 1
/obj/machinery/portable_atmospherics/canister/methane
name = "methane canister"
desc = "Methane. The simplest of hydrocarbons. Non-toxic but highly flammable."
icon_state = "greyblackred"
gas_type = /datum/gas/methane
/obj/machinery/portable_atmospherics/canister/methyl_bromide
name = "methyl bromide canister"
desc = "Methyl bromide. A potent toxin to most, essential for the Kharmaan to live."
icon_state = "purplecyan"
gas_type = /datum/gas/methyl_bromide
/obj/machinery/portable_atmospherics/canister/proc/get_time_left()
if(timing)
. = round(max(0, valve_timer - world.time) / 10, 1)
else
. = timer_set
/obj/machinery/portable_atmospherics/canister/proc/set_active()
timing = !timing
if(timing)
valve_timer = world.time + (timer_set * 10)
update_icon()
/obj/machinery/portable_atmospherics/canister/proto
name = "prototype canister"
/obj/machinery/portable_atmospherics/canister/proto/default
name = "prototype canister"
desc = "The best way to fix an atmospheric emergency... or the best way to introduce one."
icon_state = "proto"
volume = 5000
max_integrity = 300
temperature_resistance = 2000 + T0C
can_max_release_pressure = (ONE_ATMOSPHERE * 30)
can_min_release_pressure = (ONE_ATMOSPHERE / 30)
prototype = TRUE
/obj/machinery/portable_atmospherics/canister/proto/default/oxygen
name = "prototype canister"
desc = "A prototype canister for a prototype bike, what could go wrong?"
icon_state = "proto"
gas_type = /datum/gas/oxygen
filled = 1
release_pressure = ONE_ATMOSPHERE*2
/obj/machinery/portable_atmospherics/canister/Initialize(mapload, datum/gas_mixture/existing_mixture)
. = ..()
if(existing_mixture)
air_contents.copy_from(existing_mixture)
else
create_gas()
update_icon()
/obj/machinery/portable_atmospherics/canister/proc/create_gas()
if(gas_type)
// air_contents.add_gas(gas_type)
if(starter_temp)
air_contents.set_temperature(starter_temp)
air_contents.set_moles(gas_type,(maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
if(starter_temp)
air_contents.set_temperature(starter_temp)
/obj/machinery/portable_atmospherics/canister/air/create_gas()
air_contents.set_moles(/datum/gas/oxygen, (O2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
air_contents.set_moles(/datum/gas/nitrogen, (N2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
/obj/machinery/portable_atmospherics/canister/update_icon_state()
if(stat & BROKEN)
icon_state = "[icon_state]-1"
/obj/machinery/portable_atmospherics/canister/update_overlays()
. = ..()
if(holding)
. += "can-open"
if(connected_port)
. += "can-connector"
var/pressure = air_contents.return_pressure()
if(pressure >= 40 * ONE_ATMOSPHERE)
. += "can-o3"
else if(pressure >= 10 * ONE_ATMOSPHERE)
. += "can-o2"
else if(pressure >= 5 * ONE_ATMOSPHERE)
. += "can-o1"
else if(pressure >= 10)
. += "can-o0"
/obj/machinery/portable_atmospherics/canister/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > temperature_resistance)
take_damage(5, BURN, 0)
/obj/machinery/portable_atmospherics/canister/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
if(!(stat & BROKEN))
canister_break()
if(disassembled)
new /obj/item/stack/sheet/metal (loc, 10)
else
new /obj/item/stack/sheet/metal (loc, 5)
qdel(src)
/obj/machinery/portable_atmospherics/canister/welder_act(mob/living/user, obj/item/I)
..()
if(user.a_intent == INTENT_HARM)
return FALSE
if(!I.tool_start_check(user, amount=0))
return TRUE
var/pressure = air_contents.return_pressure()
if(pressure > 300)
to_chat(user, "<span class='alert'>The pressure gauge on \the [src] indicates a high pressure inside... maybe you want to reconsider?</span>")
message_admins("[src] deconstructed by [ADMIN_LOOKUPFLW(user)]")
log_game("[src] deconstructed by [key_name(user)]")
to_chat(user, "<span class='notice'>You begin cutting \the [src] apart...</span>")
if(I.use_tool(src, user, 3 SECONDS, volume=50))
to_chat(user, "<span class='notice'>You cut \the [src] apart.</span>")
deconstruct(TRUE)
return TRUE
/obj/machinery/portable_atmospherics/canister/obj_break(damage_flag)
if((stat & BROKEN) || (flags_1 & NODECONSTRUCT_1))
return
stat |= BROKEN
canister_break()
/obj/machinery/portable_atmospherics/canister/proc/canister_break()
disconnect()
var/datum/gas_mixture/expelled_gas = air_contents.remove(air_contents.total_moles())
var/turf/T = get_turf(src)
T.assume_air(expelled_gas)
air_update_turf()
obj_break()
density = FALSE
playsound(src.loc, 'sound/effects/spray.ogg', 10, TRUE, -3)
investigate_log("was destroyed.", INVESTIGATE_ATMOS)
if(holding)
holding.forceMove(T)
holding = null
/obj/machinery/portable_atmospherics/canister/replace_tank(mob/living/user, close_valve)
. = ..()
if(.)
if(close_valve)
valve_open = FALSE
update_icon()
investigate_log("Valve was <b>closed</b> by [key_name(user)].<br>", INVESTIGATE_ATMOS)
else if(valve_open && holding)
investigate_log("[key_name(user)] started a transfer into [holding].<br>", INVESTIGATE_ATMOS)
/obj/machinery/portable_atmospherics/canister/process_atmos()
..()
if(stat & BROKEN)
return PROCESS_KILL
if(timing && valve_timer < world.time)
valve_open = !valve_open
timing = FALSE
if(valve_open)
var/turf/T = get_turf(src)
var/datum/gas_mixture/target_air = holding ? holding.air_contents : T.return_air()
if(release_gas_to(air_contents, target_air, release_pressure) && !holding)
air_update_turf()
// var/our_pressure = air_contents.return_pressure()
// var/our_temperature = air_contents.return_temperature()
///function used to check the limit of the canisters and also set the amount of damage that the canister can receive, if the heat and pressure are way higher than the limit the more damage will be done
// currently unused
// if(our_temperature > heat_limit || our_pressure > pressure_limit)
// take_damage(clamp((our_temperature/heat_limit) * (our_pressure/pressure_limit) * delta_time * 2, 5, 50), BURN, 0)
update_icon()
/obj/machinery/portable_atmospherics/canister/ui_state(mob/user)
return GLOB.physical_state
/obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Canister", name)
ui.open()
/obj/machinery/portable_atmospherics/canister/ui_static_data(mob/user)
return list(
"defaultReleasePressure" = round(CAN_DEFAULT_RELEASE_PRESSURE),
"minReleasePressure" = round(can_min_release_pressure),
"maxReleasePressure" = round(can_max_release_pressure),
"pressureLimit" = round(1e14),
"holdingTankLeakPressure" = round(TANK_LEAK_PRESSURE),
"holdingTankFragPressure" = round(TANK_FRAGMENT_PRESSURE)
)
/obj/machinery/portable_atmospherics/canister/ui_data()
. = list(
"portConnected" = !!connected_port,
"tankPressure" = round(air_contents.return_pressure()),
"releasePressure" = round(release_pressure),
"valveOpen" = !!valve_open,
"isPrototype" = !!prototype,
"hasHoldingTank" = !!holding
)
if (prototype)
. += list(
"restricted" = restricted,
"timing" = timing,
"time_left" = get_time_left(),
"timer_set" = timer_set,
"timer_is_not_default" = timer_set != default_timer_set,
"timer_is_not_min" = timer_set != minimum_timer_set,
"timer_is_not_max" = timer_set != maximum_timer_set
)
if (holding)
. += list(
"holdingTank" = list(
"name" = holding.name,
"tankPressure" = round(holding.air_contents.return_pressure())
)
)
/obj/machinery/portable_atmospherics/canister/ui_act(action, params)
. = ..()
if(.)
return
switch(action)
if("relabel")
var/label = input("New canister label:", name) as null|anything in sortList(label2types)
if(label && !..())
var/newtype = label2types[label]
if(newtype)
var/obj/machinery/portable_atmospherics/canister/replacement = newtype
investigate_log("was relabelled to [initial(replacement.name)] by [key_name(usr)].", INVESTIGATE_ATMOS)
name = initial(replacement.name)
desc = initial(replacement.desc)
icon_state = initial(replacement.icon_state)
if("restricted")
restricted = !restricted
if(restricted)
req_access = list(ACCESS_ENGINE)
else
req_access = list()
. = TRUE
if("pressure")
var/pressure = params["pressure"]
if(pressure == "reset")
pressure = CAN_DEFAULT_RELEASE_PRESSURE
. = TRUE
else if(pressure == "min")
pressure = can_min_release_pressure
. = TRUE
else if(pressure == "max")
pressure = can_max_release_pressure
. = TRUE
else if(pressure == "input")
pressure = input("New release pressure ([can_min_release_pressure]-[can_max_release_pressure] kPa):", name, release_pressure) as num|null
if(!isnull(pressure) && !..())
. = TRUE
else if(text2num(pressure) != null)
pressure = text2num(pressure)
. = TRUE
if(.)
release_pressure = clamp(round(pressure), can_min_release_pressure, can_max_release_pressure)
investigate_log("was set to [release_pressure] kPa by [key_name(usr)].", INVESTIGATE_ATMOS)
if("valve")
var/logmsg
valve_open = !valve_open
if(valve_open)
logmsg = "Valve was <b>opened</b> by [key_name(usr)], starting a transfer into \the [holding || "air"].<br>"
if(!holding)
var/list/danger = list()
for(var/id in air_contents.get_gases())
var/gas = air_contents.get_moles(id)
if(!GLOB.meta_gas_dangers[id])
continue
if(gas > (GLOB.meta_gas_visibility[id] || MOLES_GAS_VISIBLE)) //if moles_visible is undefined, default to default visibility
danger[GLOB.meta_gas_names[id]] = gas //ex. "plasma" = 20
if(danger.len)
message_admins("[ADMIN_LOOKUPFLW(usr)] opened a canister that contains the following at [ADMIN_VERBOSEJMP(src)]:")
log_admin("[key_name(usr)] opened a canister that contains the following at [AREACOORD(src)]:")
for(var/name in danger)
var/msg = "[name]: [danger[name]] moles."
log_admin(msg)
message_admins(msg)
else
logmsg = "Valve was <b>closed</b> by [key_name(usr)], stopping the transfer into \the [holding || "air"].<br>"
investigate_log(logmsg, INVESTIGATE_ATMOS)
release_log += logmsg
. = TRUE
if("timer")
var/change = params["change"]
switch(change)
if("reset")
timer_set = default_timer_set
if("decrease")
timer_set = max(minimum_timer_set, timer_set - 10)
if("increase")
timer_set = min(maximum_timer_set, timer_set + 10)
if("input")
var/user_input = input(usr, "Set time to valve toggle.", name) as null|num
if(!user_input)
return
var/N = text2num(user_input)
if(!N)
return
timer_set = clamp(N,minimum_timer_set,maximum_timer_set)
log_admin("[key_name(usr)] has activated a prototype valve timer")
. = TRUE
if("toggle_timer")
set_active()
if("eject")
if(holding)
if(valve_open)
message_admins("[ADMIN_LOOKUPFLW(usr)] removed [holding] from [src] with valve still open at [ADMIN_VERBOSEJMP(src)] releasing contents into the <span class='boldannounce'>air</span>.")
investigate_log("[key_name(usr)] removed the [holding], leaving the valve open and transferring into the <span class='boldannounce'>air</span>.", INVESTIGATE_ATMOS)
replace_tank(usr, FALSE)
. = TRUE
update_icon()