mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-01-16 12:22:42 +00:00
Runtime map now has a bunch of new areas / items with often-tested stuffs, and some hard-to-put-at-runtime stuffs. Runtime map jobs now are positioned to make it faster to reach the aforementioned often-tested stuffs. Runtime map doesn't generate an overmap anymore by default, which speeds up the process. Runtime map now loads in ~11 seconds instead of ~40 seconds as it was before. Updated the maploader to be faster in parsing maps. Bapi is not engaged anymore if we're only measuring the map size, which speeds up the process. In fastboot we do not generate the codexes anymore, which speeds up the process. In fastboot and if exoplanets and away sites are not enabled, we do not parse the map templates anymore, which speeds up the process. Updated the icon smoothing to be faster. Optimized cargo area code. Other optimizations.
635 lines
20 KiB
Plaintext
635 lines
20 KiB
Plaintext
// Regular airbubble - folded
|
|
/obj/item/airbubble
|
|
name = "air bubble"
|
|
desc = "Special air bubble designed to protect people inside of it from decompressed environments. Has an integrated cooling unit to preserve a stable temperature inside. Requires a power cell to operate."
|
|
icon = 'icons/obj/airbubble.dmi'
|
|
icon_state = "airbubble_fact_folded"
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
var/used = FALSE
|
|
var/ripped = FALSE
|
|
var/zipped = FALSE
|
|
var/obj/item/tank/internal_tank
|
|
var/syndie = FALSE
|
|
|
|
/obj/item/airbubble/Destroy()
|
|
qdel(internal_tank)
|
|
return ..()
|
|
|
|
// Deploy the bubble and transfer all properties of it
|
|
/obj/item/airbubble/attack_self(mob/user)
|
|
if (!isturf(user.loc))
|
|
to_chat(user, "You're fucking stupid, the air bubble can't deploy in an enclosed space.")
|
|
return
|
|
|
|
user.visible_message(
|
|
SPAN_WARNING("[user] begins deploying \the [src]."),
|
|
SPAN_NOTICE("You begin deplyoing \the [src].")
|
|
)
|
|
if (!do_after(user, 0.45 SECONDS))
|
|
return
|
|
user.visible_message(
|
|
SPAN_WARNING("[user] deployed \the [src].") ,
|
|
SPAN_NOTICE("You deploy \the [src].")
|
|
)
|
|
var/obj/structure/closet/airbubble/R
|
|
if(syndie)
|
|
R = new /obj/structure/closet/airbubble/syndie(user.loc)
|
|
else
|
|
R = new /obj/structure/closet/airbubble(user.loc)
|
|
if(!used)
|
|
internal_tank = new /obj/item/tank/emergency_oxygen/engi(src)
|
|
internal_tank.air_contents.adjust_gas(GAS_OXYGEN, (42*ONE_ATMOSPHERE)/(R_IDEAL_GAS_EQUATION*T20C))
|
|
R.internal_tank = internal_tank
|
|
if(!isnull(internal_tank))
|
|
internal_tank.forceMove(R)
|
|
internal_tank = null
|
|
R.add_fingerprint(user)
|
|
R.ripped = ripped
|
|
R.zipped = zipped
|
|
R.update_icon()
|
|
R.desc = desc
|
|
user.drop_from_inventory(src)
|
|
qdel(src)
|
|
|
|
// Deployed bubble
|
|
/obj/structure/closet/airbubble
|
|
name = "air bubble"
|
|
desc = "Special air bubble designed to protect people inside of it from decompressed environments. Has an integrated cooling unit to preserve a stable temperature inside. Requires a power cell to operate."
|
|
icon = 'icons/obj/airbubble.dmi'
|
|
icon_state = "airbubble"
|
|
open_sound = 'sound/items/zip.ogg'
|
|
close_sound = 'sound/items/zip.ogg'
|
|
var/item_path = /obj/item/airbubble
|
|
var/zipped = FALSE
|
|
density = 0
|
|
storage_capacity = 20
|
|
var/contains_body = FALSE
|
|
var/used = TRUE // If we have deployed it once
|
|
var/ripped = FALSE // If it has a hole it in, vent all the air outside
|
|
var/breakout_time = 1 // How many minutes it takes to break out of it.
|
|
|
|
var/use_internal_tank = TRUE
|
|
var/datum/gas_mixture/inside_air
|
|
var/internal_tank_valve = 45 // arbitrary for now
|
|
var/obj/item/tank/internal_tank
|
|
var/syndie = FALSE
|
|
var/last_shake = 0
|
|
var/cooling = FALSE
|
|
var/obj/item/cell/cell = null
|
|
var/max_cooling = 12 //in degrees per second - probably don't need to mess with heat capacity here
|
|
var/charge_consumption = 8.3 //charge per second at max_cooling
|
|
var/thermostat = T20C
|
|
slowdown = 0
|
|
|
|
// Examine to see tank pressure
|
|
/obj/structure/closet/airbubble/get_examine_text(mob/user, distance, is_adjacent, infix, suffix)
|
|
. = ..()
|
|
if(!isnull(internal_tank))
|
|
. += SPAN_NOTICE("\The [src] has [internal_tank] attached, that displays [round(internal_tank.air_contents.return_pressure() ? internal_tank.air_contents.return_pressure() : 0)] KPa.")
|
|
else
|
|
. += SPAN_NOTICE("\The [src] has no tank attached.")
|
|
if (cell)
|
|
. += "\The [src] has [cell] attached, the charge meter reads [round(cell.percent())]%."
|
|
else
|
|
. += SPAN_WARNING("[src] has no power cell installed.")
|
|
|
|
/obj/structure/closet/airbubble/can_open()
|
|
if(zipped)
|
|
return 0
|
|
return 1
|
|
|
|
/obj/structure/closet/airbubble/can_close(mob/user as mob)
|
|
if(zipped)
|
|
return 0
|
|
var/turf/T = get_turf(src)
|
|
for (var/obj/O in T)
|
|
if (O.density && O != src)
|
|
return 0
|
|
var/mob_num = 0
|
|
for(var/mob/living/M in T)
|
|
mob_num += 1
|
|
if(mob_num > 1)
|
|
to_chat(user, SPAN_WARNING("[src] can only fit one person."))
|
|
return 0
|
|
return 1
|
|
|
|
/obj/structure/closet/airbubble/dump_contents()
|
|
|
|
for(var/obj/I in src)
|
|
if (I != internal_tank && I != cell)
|
|
I.forceMove(loc)
|
|
|
|
for(var/mob/M in src)
|
|
M.forceMove(loc)
|
|
if(M.client)
|
|
M.client.eye = M.client.mob
|
|
M.client.perspective = MOB_PERSPECTIVE
|
|
|
|
/obj/structure/closet/airbubble/Initialize()
|
|
. = ..()
|
|
add_inside()
|
|
START_PROCESSING(SSfast_process, src)
|
|
|
|
/obj/structure/closet/airbubble/Destroy()
|
|
STOP_PROCESSING(SSfast_process, src)
|
|
qdel(internal_tank)
|
|
if(parts)
|
|
new parts(loc)
|
|
if (smoothing_flags)
|
|
QUEUE_SMOOTH_NEIGHBORS(src)
|
|
return ..()
|
|
|
|
/obj/structure/closet/airbubble/toggle(mob/user as mob)
|
|
if(!(opened ? close(user) : open(user)))
|
|
to_chat(user, SPAN_NOTICE("It won't budge!"))
|
|
return
|
|
update_icon()
|
|
return 1
|
|
|
|
/obj/structure/closet/airbubble/open(mob/user as mob)
|
|
if(opened)
|
|
return 0
|
|
|
|
if(!can_open())
|
|
return 0
|
|
|
|
dump_contents()
|
|
|
|
update_icon()
|
|
opened = 1
|
|
playsound(loc, open_sound, 15, 1, -3)
|
|
density = 0
|
|
return 1
|
|
|
|
/obj/structure/closet/airbubble/close(mob/user as mob)
|
|
if(!opened)
|
|
return 0
|
|
if(!can_close(user))
|
|
return 0
|
|
|
|
var/stored_units = 0
|
|
|
|
if(store_misc)
|
|
stored_units += store_misc(stored_units)
|
|
if(store_items)
|
|
stored_units += store_items(stored_units)
|
|
if(store_mobs)
|
|
stored_units += store_mobs(stored_units)
|
|
|
|
update_icon()
|
|
opened = 0
|
|
|
|
playsound(loc, close_sound, 25, 0, -3)
|
|
density = 1
|
|
add_inside()
|
|
return 1
|
|
|
|
// Fold the bubble, transfering properties.
|
|
/obj/structure/closet/airbubble/MouseDrop(over_object, src_location, over_location)
|
|
if((!zipped || ripped )&& (over_object == usr && (in_range(src, usr) || usr.contents.Find(src))))
|
|
if(!ishuman(usr)) return
|
|
if(opened) return 0
|
|
if(contents.len > 1) return 0
|
|
if(cell)
|
|
to_chat(usr, SPAN_WARNING("[src] can not be folded with [cell] attached to it."))
|
|
return
|
|
usr.visible_message(
|
|
SPAN_WARNING("[usr] begins folding up the [src.name]."),
|
|
SPAN_NOTICE("You begin folding up the [src.name].")
|
|
)
|
|
if (!do_after(usr, 0.45 SECONDS))
|
|
return
|
|
usr.visible_message(
|
|
SPAN_WARNING("[usr] folds up the [src.name].") ,
|
|
SPAN_NOTICE("You fold up the [src.name].")
|
|
)
|
|
var/obj/item/airbubble/bag
|
|
if(syndie)
|
|
bag = new /obj/item/airbubble/syndie(get_turf(src))
|
|
else
|
|
bag = new /obj/item/airbubble(get_turf(src))
|
|
bag.ripped = ripped
|
|
bag.zipped = zipped
|
|
bag.used = TRUE
|
|
bag.internal_tank = internal_tank
|
|
if(!isnull(internal_tank))
|
|
internal_tank.forceMove(bag)
|
|
internal_tank = null
|
|
bag.w_class = WEIGHT_CLASS_BULKY
|
|
|
|
bag.desc = "Special air bubble designed to protect people inside of it from decompressed environments. Has an integrated cooling unit to preserve a stable temperature inside. Requires a power cell to operate."
|
|
if(syndie)
|
|
bag.desc += " This does not seem like a regular color scheme"
|
|
bag.desc += SPAN_NOTICE(" It appears to be poorly hand folded.")
|
|
|
|
if(ripped)
|
|
bag.icon_state = "[icon_state]_man_folded_ripped"
|
|
bag.desc += SPAN_DANGER(" It has hole in it! Maybe you shouldn't use it!")
|
|
else
|
|
bag.icon_state = "[icon_state]_man_folded"
|
|
qdel(src)
|
|
return
|
|
return ..()
|
|
|
|
/obj/structure/closet/airbubble/req_breakout()
|
|
|
|
if(opened)
|
|
return 0 //Door's open... wait, why are you in it's contents then?
|
|
if(zipped)
|
|
return 1 // If it is zipped
|
|
if(breakout)
|
|
return -1 //Already breaking out.
|
|
return 0
|
|
|
|
/obj/structure/closet/airbubble/proc/breakout_callback(var/mob/living/escapee)
|
|
if (QDELETED(escapee))
|
|
return FALSE
|
|
|
|
if ((world.time - last_shake) > 5 SECONDS)
|
|
var/sound_to_play = pick(list('sound/items/rip1.ogg', 'sound/items/rip2.ogg'))
|
|
playsound(loc, sound_to_play, 100, 1)
|
|
shake_animation()
|
|
last_shake = world.time
|
|
|
|
if (!req_breakout())
|
|
return FALSE
|
|
|
|
return TRUE
|
|
|
|
// If we are stuck, and need to get out
|
|
/obj/structure/closet/airbubble/mob_breakout(var/mob/living/escapee)
|
|
if (req_breakout() < 1)
|
|
return
|
|
|
|
escapee.next_move = world.time + 100
|
|
escapee.last_special = world.time + 100
|
|
to_chat(escapee, SPAN_WARNING("You lean on the back of \the [src] and start punching internal wall with your legs. (this will take about [breakout_time] minutes)"))
|
|
visible_message(SPAN_DANGER("\The [src] begins to shake violently! Something is terring it from the inside!"))
|
|
|
|
var/time = 360 * breakout_time * 2
|
|
breakout = TRUE
|
|
|
|
if (!do_after(escapee, time, src, extra_checks = CALLBACK(src, PROC_REF(breakout_callback), escapee)))
|
|
breakout = FALSE
|
|
return
|
|
|
|
breakout = FALSE
|
|
to_chat(escapee, SPAN_WARNING("You successfully break out! Tearing the bubble's walls!")) // holy shit this is hilarious
|
|
visible_message(SPAN_DANGER("\the [escapee] successfully broke out of \the [src]! Tearing the bubble's walls!"))
|
|
var/sound_to_play = pick(list('sound/items/rip1.ogg', 'sound/items/rip2.ogg'))
|
|
playsound(loc, sound_to_play, 100, 1)
|
|
break_open()
|
|
shake_animation()
|
|
desc += SPAN_DANGER(" It has hole in it! Maybe you shouldn't use it!")
|
|
|
|
// We are out finally, the bubble is ripped. So dump everything out from it. Especially air and user.
|
|
/obj/structure/closet/airbubble/break_open()
|
|
ripped = TRUE
|
|
update_icon()
|
|
dump_contents()
|
|
var/datum/gas_mixture/t_air = get_turf_air()
|
|
t_air.merge(inside_air)
|
|
|
|
// When we shoot bubble, make it rip.
|
|
/obj/structure/closet/airbubble/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
|
. = ..()
|
|
if(. != BULLET_ACT_HIT)
|
|
return .
|
|
|
|
ripped = TRUE
|
|
update_icon()
|
|
|
|
// Change valve on internal tank
|
|
/obj/structure/closet/airbubble/verb/set_internals()
|
|
set src in oview(1)
|
|
set category = "Object"
|
|
set name = "Set Internals"
|
|
|
|
if(!usr.canmove || usr.stat || usr.restrained())
|
|
return
|
|
|
|
if(!ishuman(usr))
|
|
to_chat(usr, SPAN_WARNING("This mob type can't use this verb."))
|
|
return
|
|
|
|
if(!isnull(internal_tank))
|
|
usr.visible_message(
|
|
SPAN_WARNING("[usr] is setting [src] internals."),
|
|
SPAN_NOTICE("You are settting [src] internals.")
|
|
)
|
|
if (!do_after(usr, 2 SECONDS, src))
|
|
return
|
|
usr.visible_message(
|
|
SPAN_WARNING("[usr] has set [src] internals.") ,
|
|
SPAN_NOTICE("You set [src] internals.")
|
|
)
|
|
if(use_internal_tank)
|
|
STOP_PROCESSING(SSfast_process, src)
|
|
else
|
|
START_PROCESSING(SSfast_process, src)
|
|
use_internal_tank = !use_internal_tank
|
|
update_icon()
|
|
else
|
|
to_chat(usr, SPAN_NOTICE("[src] has no internal tank."))
|
|
|
|
// Remove tank from bubble
|
|
/obj/structure/closet/airbubble/verb/take_tank()
|
|
set src in oview(1)
|
|
set category = "Object"
|
|
set name = "Remove Air Tank"
|
|
|
|
if(!usr.canmove || usr.stat || usr.restrained())
|
|
return
|
|
|
|
if(!ishuman(usr))
|
|
to_chat(usr, SPAN_WARNING("This mob type can't use this verb."))
|
|
return
|
|
|
|
if(!isnull(internal_tank))
|
|
usr.visible_message(
|
|
SPAN_WARNING("[usr] is removing [internal_tank] from [src]."),
|
|
SPAN_NOTICE("You are removing [internal_tank] from [src].")
|
|
)
|
|
if (!do_after(usr, 2 SECONDS, src))
|
|
return
|
|
usr.visible_message(
|
|
SPAN_WARNING("[usr] has removed [internal_tank] from [src]."),
|
|
SPAN_NOTICE("You removed [internal_tank] from [src].")
|
|
)
|
|
for(var/obj/I in src)
|
|
I.forceMove(usr.loc)
|
|
use_internal_tank = 0
|
|
internal_tank = null
|
|
update_icon()
|
|
STOP_PROCESSING(SSfast_process, src)
|
|
else
|
|
to_chat(usr, SPAN_WARNING("[src] has no tank."))
|
|
|
|
// Remove tank from bubble
|
|
/obj/structure/closet/airbubble/verb/take_cell()
|
|
set src in oview(1)
|
|
set category = "Object"
|
|
set name = "Detach Power Cell"
|
|
|
|
if(!usr.canmove || usr.stat || usr.restrained())
|
|
return
|
|
|
|
if(!ishuman(usr))
|
|
to_chat(usr, SPAN_WARNING("This mob type can't use this verb."))
|
|
return
|
|
|
|
if(!isnull(cell))
|
|
usr.visible_message(
|
|
SPAN_WARNING("[usr] is removing [cell] from [src]."),
|
|
SPAN_NOTICE("You are removing [cell] from [src].")
|
|
)
|
|
if (!do_after(usr, 2 SECONDS, src))
|
|
return
|
|
usr.visible_message(
|
|
SPAN_WARNING("[usr] has removed [cell] from [src]."),
|
|
SPAN_NOTICE("You removed [cell] from [src].")
|
|
)
|
|
cell.forceMove(usr.loc)
|
|
cell = null
|
|
cooling = FALSE
|
|
update_icon()
|
|
else
|
|
to_chat(usr, SPAN_WARNING("[src] has no power cell."))
|
|
|
|
// Handle most of things: restraining, cutting restrains, attaching tank.
|
|
/obj/structure/closet/airbubble/attackby(obj/item/attacking_item, mob/user)
|
|
if(istype(attacking_item, /obj/item/tank))
|
|
if(!isnull(use_internal_tank))
|
|
user.visible_message(
|
|
SPAN_WARNING("[user] is attaching [attacking_item] to [src]."),
|
|
SPAN_NOTICE("You are attaching [attacking_item] to [src].")
|
|
)
|
|
if (!do_after(user, 2 SECONDS, src))
|
|
return
|
|
user.visible_message(
|
|
SPAN_WARNING("[user] has attached [attacking_item] to [src]."),
|
|
SPAN_NOTICE("You attached [attacking_item] to [src].")
|
|
)
|
|
internal_tank = attacking_item
|
|
user.drop_from_inventory(attacking_item, src)
|
|
use_internal_tank = 1
|
|
START_PROCESSING(SSfast_process, src)
|
|
else
|
|
to_chat(user, SPAN_WARNING("[src] already has a tank attached."))
|
|
return TRUE
|
|
if(opened)
|
|
if(istype(attacking_item, /obj/item/grab))
|
|
var/obj/item/grab/G = attacking_item
|
|
MouseDrop_T(G.affecting, user)
|
|
return FALSE
|
|
if(!attacking_item.dropsafety())
|
|
return FALSE
|
|
user.drop_item()
|
|
return TRUE
|
|
else if(istype(attacking_item, /obj/item/handcuffs/cable))
|
|
if(zipped)
|
|
to_chat(user, SPAN_WARNING("[src]'s zipper is already restrained."))
|
|
return TRUE
|
|
user.visible_message(
|
|
SPAN_WARNING("[user] begins putting cable restrains on zipper of [src]."),
|
|
SPAN_NOTICE("You begin putting cable restrains on zipper of [src].")
|
|
)
|
|
playsound(loc, 'sound/weapons/cablecuff.ogg', 50, 1)
|
|
if (!do_after(user, 3 SECONDS, src, extra_checks = CALLBACK(src, PROC_REF(is_closed))))
|
|
return TRUE
|
|
zipped = !zipped
|
|
update_icon()
|
|
user.visible_message(
|
|
SPAN_WARNING("[src]'s zipper have been zipped by [user]."),
|
|
SPAN_NOTICE("You put restrains on [src]'s zipper.")
|
|
)
|
|
|
|
qdel(attacking_item)
|
|
update_icon()
|
|
return TRUE
|
|
else if(attacking_item.iswirecutter())
|
|
if(!zipped)
|
|
to_chat(user, SPAN_WARNING("[src] has no cables to cut."))
|
|
attack_hand(user)
|
|
return TRUE
|
|
user.visible_message(
|
|
SPAN_WARNING("[user] begins cutting cable restrains on zipper of [src]."),
|
|
SPAN_NOTICE("You begin cutting cable restrains on zipper of [src].")
|
|
)
|
|
playsound(loc, 'sound/items/Wirecutter.ogg', 50, 1)
|
|
if (!do_after(user, 3 SECONDS, src, extra_checks = CALLBACK(src, PROC_REF(is_closed))))
|
|
return TRUE
|
|
zipped = !zipped
|
|
update_icon()
|
|
user.visible_message(
|
|
SPAN_WARNING("[src] zipper's cable restrains has been cut by [user]."),
|
|
SPAN_NOTICE("You cut cable restrains on [src]'s zipper.")
|
|
)
|
|
new/obj/item/handcuffs/cable(src.loc)
|
|
update_icon()
|
|
return TRUE
|
|
else if(istype(attacking_item, /obj/item/cell))
|
|
if(!isnull(cell))
|
|
to_chat(user, SPAN_WARNING("[src] already has [cell] attached to it."))
|
|
attack_hand(user)
|
|
return TRUE
|
|
user.visible_message(
|
|
SPAN_WARNING("[user] is attaching [attacking_item] to [src]."),
|
|
SPAN_NOTICE("You are attaching [attacking_item] to [src].")
|
|
)
|
|
if (!do_after(user, 2 SECONDS, src))
|
|
return TRUE
|
|
user.visible_message(
|
|
SPAN_WARNING("[user] has attached [attacking_item] to [src]."),
|
|
SPAN_NOTICE("You attached [attacking_item] to [src].")
|
|
)
|
|
cell = attacking_item
|
|
cooling = TRUE
|
|
user.drop_from_inventory(attacking_item, src)
|
|
return TRUE
|
|
else
|
|
return attack_hand(user)
|
|
|
|
/obj/structure/closet/airbubble/store_mobs(var/stored_units, var/mob_limit)
|
|
contains_body = ..(stored_units, mob_limit = TRUE)
|
|
return contains_body
|
|
|
|
/obj/structure/closet/airbubble/update_icon()
|
|
ClearOverlays()
|
|
if(ripped)
|
|
name = "ripped air bubble"
|
|
icon_state = "[icon_state]_ripped"
|
|
else
|
|
icon_state = "[initial(icon_state)][opened ? "_open" : ""]"
|
|
if(zipped)
|
|
AddOverlays("[icon_state]_restrained")
|
|
AddOverlays("pressure_[(use_internal_tank) ?("on") : ("off") ]")
|
|
|
|
// Process transfer of air from the tank. Handle if it is ripped open.
|
|
/obj/structure/closet/airbubble/proc/process_tank_give_air()
|
|
if(internal_tank)
|
|
var/datum/gas_mixture/tank_air = internal_tank.return_air()
|
|
|
|
var/release_pressure = internal_tank_valve
|
|
// If ripped, we are leaking
|
|
if(ripped)
|
|
// If we has no pressure in the tank, why bother?
|
|
if(tank_air.return_pressure() <= 1)
|
|
STOP_PROCESSING(SSfast_process, src)
|
|
use_internal_tank = !use_internal_tank
|
|
visible_message(SPAN_WARNING("You hear last bits of air coming out from [src]'s hole.Maybe the tank run out of air?"))
|
|
playsound(loc, 'sound/effects/wind/wind_2_1.ogg', 100, 1)
|
|
return
|
|
inside_air = get_turf_air()
|
|
visible_message(SPAN_WARNING("You hear air howling from [src]'s hole. Maybe it is good to shut off valve on the internals tank?"))
|
|
playsound(loc, 'sound/effects/wind/wind_2_2.ogg', 100, 1)
|
|
|
|
var/transfer_moles = inside_air.volume/(inside_air.temperature * R_IDEAL_GAS_EQUATION)
|
|
var/datum/gas_mixture/removed = tank_air.remove(transfer_moles)
|
|
if(inside_air)
|
|
inside_air.merge(removed)
|
|
else
|
|
qdel(removed)
|
|
return
|
|
var/inside_pressure = inside_air.return_pressure()
|
|
var/pressure_delta = min(release_pressure - inside_pressure, (tank_air.return_pressure() - inside_pressure)/2)
|
|
var/transfer_moles = 0
|
|
|
|
if(pressure_delta > 0) //inside pressure lower than release pressure
|
|
if(tank_air.temperature > 0)
|
|
transfer_moles = pressure_delta*inside_air.volume/(inside_air.temperature * R_IDEAL_GAS_EQUATION)
|
|
var/datum/gas_mixture/removed = tank_air.remove(transfer_moles)
|
|
inside_air.merge(removed)
|
|
|
|
else if(pressure_delta < 0) //inside pressure higher than release pressure
|
|
var/datum/gas_mixture/t_air = get_turf_air()
|
|
pressure_delta = inside_pressure - release_pressure
|
|
|
|
if(t_air)
|
|
pressure_delta = min(inside_pressure - t_air.return_pressure(), pressure_delta)
|
|
if(pressure_delta > 0) //if location pressure is lower than inside pressure
|
|
transfer_moles = pressure_delta*inside_air.volume/(inside_air.temperature * R_IDEAL_GAS_EQUATION)
|
|
|
|
var/datum/gas_mixture/removed = inside_air.remove(transfer_moles)
|
|
if(t_air)
|
|
t_air.merge(removed)
|
|
else //just delete the inside gas, we're in space or some shit
|
|
qdel(removed)
|
|
|
|
/obj/structure/closet/airbubble/proc/process_preserve_temp()
|
|
if (!cooling || !cell)
|
|
return
|
|
for(var/mob/living/carbon/human/H in src)
|
|
var/datum/gas_mixture/t_air = get_turf_air()
|
|
if(!t_air)
|
|
return
|
|
var/env_temp = t_air.temperature
|
|
var/temp_adj = min(H.bodytemperature - max(thermostat, env_temp), max_cooling)
|
|
|
|
if (temp_adj < 0.5) //only cools, doesn't heat, also we don't need extreme precision
|
|
return
|
|
|
|
var/charge_usage = (temp_adj/max_cooling)*charge_consumption
|
|
H.bodytemperature -= temp_adj
|
|
|
|
cell.use(charge_usage)
|
|
|
|
if(cell.charge <= 0)
|
|
cooling = FALSE
|
|
|
|
/obj/structure/closet/airbubble/return_air()
|
|
if(use_internal_tank)
|
|
return inside_air
|
|
return ..()
|
|
|
|
/obj/structure/closet/airbubble/proc/get_turf_air()
|
|
var/turf/T = get_turf(src)
|
|
if(T)
|
|
return T.return_air()
|
|
|
|
/obj/structure/closet/airbubble/proc/return_pressure()
|
|
. = 0
|
|
if(use_internal_tank)
|
|
. = inside_air.return_pressure()
|
|
else
|
|
var/datum/gas_mixture/t_air = get_turf_air()
|
|
if(t_air)
|
|
. = t_air.return_pressure()
|
|
return
|
|
|
|
|
|
/obj/structure/closet/airbubble/proc/return_temperature()
|
|
. = 0
|
|
if(use_internal_tank)
|
|
. = inside_air.temperature
|
|
else
|
|
var/datum/gas_mixture/t_air = get_turf_air()
|
|
if(t_air)
|
|
. = t_air.temperature
|
|
return
|
|
|
|
/obj/structure/closet/airbubble/process()
|
|
process_preserve_temp()
|
|
process_tank_give_air()
|
|
|
|
/obj/structure/closet/airbubble/proc/add_inside()
|
|
inside_air = new
|
|
inside_air.temperature = T20C
|
|
inside_air.volume = 2
|
|
inside_air.adjust_multi(GAS_OXYGEN, O2STANDARD*inside_air.volume/(R_IDEAL_GAS_EQUATION*inside_air.temperature), GAS_NITROGEN, N2STANDARD*inside_air.volume/(R_IDEAL_GAS_EQUATION*inside_air.temperature))
|
|
return inside_air
|
|
|
|
// Syndicate airbubble
|
|
/obj/item/airbubble/syndie
|
|
name = "air bubble"
|
|
desc = "Special air bubble designed to protect people inside of it from decompressed environments. Has an integrated cooling unit to preserve a stable temperature inside. Requires a power cell to operate. This does not seem like a regular color scheme."
|
|
icon_state = "airbubble_syndie_fact_folded"
|
|
syndie = TRUE
|
|
|
|
/obj/structure/closet/airbubble/syndie
|
|
name = "air bubble"
|
|
desc = "Special air bubble designed to protect people inside of it from decompressed environments. Has an integrated cooling unit to preserve a stable temperature inside. Requires a power cell to operate. This does not seem like a regular color scheme."
|
|
icon_state = "airbubble_syndie"
|
|
item_path = /obj/item/airbubble/syndie
|
|
syndie = TRUE
|