Internals Bugfixes & Internals-Compatible Helmets (#70750)

* Core internals refactor. Add open/close_internals procs to /obj/item/tank. Add open/close_internals, can_breathe_internals, and invalid_internals procs to /mob/living/carbon. Fixed bug in human_stripping.dm preventing changing internals for breathing tube users. Fixed bug in /obj/item/tank/toggle_internals that was auto-adjusting non-internals masks. Fixed bug in slements/strippable that caused two mobs to breathe from the same internals.
This commit is contained in:
Dani Glore
2022-10-31 12:04:52 +01:00
committed by GitHub
parent 26c68c31a0
commit 0a81ea5bf9
22 changed files with 336 additions and 127 deletions
+2
View File
@@ -65,6 +65,8 @@
#define CASTING_CLOTHES (1<<19)
///Moths can't eat the clothing that has this flag.
#define INEDIBLE_CLOTHING (1<<20)
/// Headgear/helmet allows internals
#define HEADINTERNALS (1<<21)
/// Integrity defines for clothing (not flags but close enough)
#define CLOTHING_PRISTINE 0 // We have no damage on the clothing
+1 -2
View File
@@ -245,8 +245,7 @@
if(!visualsOnly)
apply_fingerprints(H)
if(internals_slot)
H.internal = H.get_item_by_slot(internals_slot)
H.update_action_buttons_icon()
H.open_internals(H.get_item_by_slot(internals_slot))
if(implants)
for(var/implant_type in implants)
var/obj/item/implant/I = SSwardrobe.provide_type(implant_type, H)
@@ -8,6 +8,16 @@
* Generic
*/
/// Allows carbon to toggle internals via AltClick of the equipped tank.
/obj/item/tank/internals/AltClick(mob/user)
..()
if((loc == user) && user.canUseTopic(src, be_close = TRUE, no_dexterity = FALSE, no_tk = TRUE, need_hands = TRUE))
toggle_internals(user)
/obj/item/tank/internals/examine(mob/user)
. = ..()
. += span_notice("Alt-click the tank to toggle the valve.")
/*
* Oxygen
*/
+45 -41
View File
@@ -44,38 +44,42 @@
var/list/explosion_info
/// List containing reactions happening inside our tank.
var/list/reaction_info
/// Mob that is currently breathing from the tank.
var/mob/living/carbon/breathing_mob = null
/// Closes the tank if dropped while open.
/obj/item/tank/dropped(mob/living/user, silent)
. = ..()
// Close open air tank if its current user got sent to the shadowrealm.
if (QDELETED(breathing_mob))
breathing_mob = null
return
// Close open air tank if it got dropped by it's current user.
if (loc != breathing_mob)
breathing_mob.cutoff_internals()
/// Closes the tank if given to another mob while open.
/obj/item/tank/equipped(mob/living/user, slot, initial)
. = ..()
// Close open air tank if it was equipped by a mob other than the current user.
if (breathing_mob && (user != breathing_mob))
breathing_mob.cutoff_internals()
/// Called by carbons after they connect the tank to their breathing apparatus.
/obj/item/tank/proc/after_internals_opened(mob/living/carbon/carbon_target)
breathing_mob = carbon_target
/// Called by carbons after they disconnect the tank from their breathing apparatus.
/obj/item/tank/proc/after_internals_closed(mob/living/carbon/carbon_target)
breathing_mob = null
/// Attempts to toggle the mob's internals on or off using this tank. Returns TRUE if successful.
/obj/item/tank/proc/toggle_internals(mob/living/carbon/mob_target)
return mob_target.toggle_internals(src)
/obj/item/tank/ui_action_click(mob/user)
toggle_internals(user)
/obj/item/tank/proc/toggle_internals(mob/user)
var/mob/living/carbon/human/H = user
if(!istype(H))
return
if(H.internal == src)
to_chat(H, span_notice("You close [src] valve."))
H.internal = null
else
if(!H.getorganslot(ORGAN_SLOT_BREATHING_TUBE))
if(!H.wear_mask)
to_chat(H, span_warning("You need a mask!"))
return
var/is_clothing = isclothing(H.wear_mask)
if(is_clothing && H.wear_mask.mask_adjusted)
H.wear_mask.adjustmask(H)
if(!is_clothing || !(H.wear_mask.clothing_flags & MASKINTERNALS))
to_chat(H, span_warning("[H.wear_mask] can't use [src]!"))
return
if(H.internal)
to_chat(H, span_notice("You switch your internals to [src]."))
else
to_chat(H, span_notice("You open [src] valve."))
H.internal = src
H.update_action_buttons_icon()
/obj/item/tank/Initialize(mapload)
. = ..()
@@ -110,8 +114,8 @@
/obj/item/tank/examine(mob/user)
var/obj/icon = src
. = ..()
if(istype(src.loc, /obj/item/assembly))
icon = src.loc
if(istype(loc, /obj/item/assembly))
icon = loc
if(!in_range(src, user) && !isobserver(user))
if(icon == src)
. += span_notice("If you want any more information you'll need to get closer.")
@@ -145,21 +149,21 @@
return ..()
/obj/item/tank/suicide_act(mob/user)
var/mob/living/carbon/human/H = user
var/mob/living/carbon/human/human_user = user
user.visible_message(span_suicide("[user] is putting [src]'s valve to [user.p_their()] lips! It looks like [user.p_theyre()] trying to commit suicide!"))
playsound(loc, 'sound/effects/spray.ogg', 10, TRUE, -3)
if(!QDELETED(H) && air_contents && air_contents.return_pressure() >= 1000)
ADD_TRAIT(H, TRAIT_DISFIGURED, TRAIT_GENERIC)
H.inflate_gib()
if(!QDELETED(human_user) && air_contents && air_contents.return_pressure() >= 1000)
ADD_TRAIT(human_user, TRAIT_DISFIGURED, TRAIT_GENERIC)
human_user.inflate_gib()
return MANUAL_SUICIDE
else
to_chat(user, span_warning("There isn't enough pressure in [src] to commit suicide with..."))
return SHAME
/obj/item/tank/attackby(obj/item/W, mob/user, params)
/obj/item/tank/attackby(obj/item/attacking_item, mob/user, params)
add_fingerprint(user)
if(istype(W, /obj/item/assembly_holder))
bomb_assemble(W, user)
if(istype(attacking_item, /obj/item/assembly_holder))
bomb_assemble(attacking_item, user)
return TRUE
return ..()
@@ -187,10 +191,10 @@
"releasePressure" = round(distribute_pressure)
)
var/mob/living/carbon/C = user
if(!istype(C))
C = loc.loc
if(istype(C) && C.internal == src)
var/mob/living/carbon/carbon_user = user
if(!istype(carbon_user))
carbon_user = loc
if(istype(carbon_user) && (carbon_user.external == src || carbon_user.internal == src))
.["connected"] = TRUE
/obj/item/tank/ui_act(action, params)
@@ -507,7 +507,7 @@
inhand_icon_state = null
desc = "A covering of pressure and temperature-resistant organic tissue with a glass-like chitin front."
item_flags = DROPDEL
clothing_flags = STOPSPRESSUREDAMAGE
clothing_flags = STOPSPRESSUREDAMAGE | HEADINTERNALS
armor = list(MELEE = 0, BULLET = 0, LASER = 0,ENERGY = 0, BOMB = 0, BIO = 100, FIRE = 90, ACID = 90)
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
+1 -1
View File
@@ -266,7 +266,7 @@ Striking a noncultist, however, will tear their flesh."}
icon_state = "cult_helmet"
inhand_icon_state = null
armor = list(MELEE = 50, BULLET = 40, LASER = 50, ENERGY = 60, BOMB = 50, BIO = 100, FIRE = 100, ACID = 100)
clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SNUG_FIT | PLASMAMAN_HELMET_EXEMPT
clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SNUG_FIT | PLASMAMAN_HELMET_EXEMPT | HEADINTERNALS
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT
+1 -1
View File
@@ -232,7 +232,7 @@
return
if(isplasmaman(H))
H.equipOutfit(plasmaman_outfit)
H.internal = H.get_item_for_held_index(2)
H.open_internals(H.get_item_for_held_index(2))
H.equipOutfit(outfit)
+1 -1
View File
@@ -102,7 +102,7 @@
dog_fashion = null
name = "atmospheric technician's firefighting helmet"
desc = "A firefighter's helmet, able to keep the user cool in any situation."
clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | PLASMAMAN_HELMET_EXEMPT
clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | PLASMAMAN_HELMET_EXEMPT | HEADINTERNALS
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
heat_protection = HEAD
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
+9 -4
View File
@@ -62,12 +62,12 @@
M.update_worn_mask()
//Proc that moves gas/breath masks out of the way, disabling them and allowing pill/food consumption
/obj/item/clothing/mask/proc/adjustmask(mob/living/user)
/obj/item/clothing/mask/proc/adjustmask(mob/living/carbon/user)
if(user?.incapacitated())
return
mask_adjusted = !mask_adjusted
if(!mask_adjusted)
src.icon_state = initial(icon_state)
icon_state = initial(icon_state)
clothing_flags |= visor_flags
flags_inv |= visor_flags_inv
flags_cover |= visor_flags_cover
@@ -81,9 +81,14 @@
flags_cover &= ~visor_flags_cover
if(adjusted_flags)
slot_flags = adjusted_flags
if(user)
if(!istype(user))
return
// Update the mob if it's wearing the mask.
if(user.wear_mask == src)
user.wear_mask_update(src, toggle_off = mask_adjusted)
user.update_action_buttons_icon() //when mask is adjusted out, we update all buttons icon so the user's potential internal tank correctly shows as off.
if(loc == user)
// Update action button icon for adjusted mask, if someone is holding it.
user.update_action_buttons_icon()
/**
* Proc called in lungs.dm to act if wearing a mask with filters, used to reduce the filters durability, return a changed gas mixture depending on the filter status
+1 -1
View File
@@ -22,7 +22,7 @@
/obj/item/clothing/mask/breath/AltClick(mob/user)
..()
if(!user.canUseTopic(src, be_close = TRUE, no_dexterity = TRUE, no_tk = FALSE, need_hands = !iscyborg(user)))
if(user.canUseTopic(src, be_close = TRUE, no_dexterity = TRUE, no_tk = FALSE, need_hands = !iscyborg(user)))
adjustmask(user)
/obj/item/clothing/mask/breath/examine(mob/user)
@@ -9,7 +9,7 @@
icon_state = "spaceold"
inhand_icon_state = "space_helmet"
desc = "A special helmet with solar UV shielding to protect your eyes from harmful rays."
clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SNUG_FIT | PLASMAMAN_HELMET_EXEMPT
clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SNUG_FIT | PLASMAMAN_HELMET_EXEMPT | HEADINTERNALS
armor = list(MELEE = 0, BULLET = 0, LASER = 0,ENERGY = 0, BOMB = 0, BIO = 100, FIRE = 80, ACID = 70)
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
+1 -1
View File
@@ -6,7 +6,7 @@
worn_icon = 'icons/mob/clothing/head/bio.dmi'
icon_state = "bio"
inhand_icon_state = "bio_hood"
clothing_flags = THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | SNUG_FIT | PLASMAMAN_HELMET_EXEMPT
clothing_flags = THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | SNUG_FIT | PLASMAMAN_HELMET_EXEMPT | HEADINTERNALS
armor = list(MELEE = 0, BULLET = 0, LASER = 0,ENERGY = 0, BOMB = 0, BIO = 100, FIRE = 30, ACID = 100)
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR|HIDEFACE|HIDESNOUT
resistance_flags = ACID_PROOF
@@ -36,7 +36,10 @@
var/obj/item/back = null
var/obj/item/clothing/mask/wear_mask = null
var/obj/item/clothing/neck/wear_neck = null
/// Equipped air tank. Never set this manually.
var/obj/item/tank/internal = null
/// "External" air tank. Never set this manually. Not required to stay directly equipped on the mob (i.e. could be a machine or MOD suit module).
var/obj/item/tank/external = null
var/obj/item/clothing/head = null
///only used by humans
@@ -81,15 +81,13 @@
/mob/living/carbon/human/get_status_tab_items()
. = ..()
if (internal)
var/datum/gas_mixture/internal_air = internal.return_air()
if (!internal_air)
QDEL_NULL(internal)
else
. += ""
. += "Internal Atmosphere Info: [internal.name]"
. += "Tank Pressure: [internal_air.return_pressure()]"
. += "Distribution Pressure: [internal.distribute_pressure]"
var/obj/item/tank/target_tank = internal || external
if(target_tank)
var/datum/gas_mixture/internal_air = target_tank.return_air()
. += ""
. += "Internal Atmosphere Info: [target_tank.name]"
. += "Tank Pressure: [internal_air.return_pressure()]"
. += "Distribution Pressure: [target_tank.distribute_pressure]"
if(istype(wear_suit, /obj/item/clothing/suit/space))
var/obj/item/clothing/suit/space/S = wear_suit
. += "Thermal Regulator: [S.thermal_on ? "on" : "off"]"
@@ -185,13 +185,11 @@ GLOBAL_LIST_INIT(strippable_human_items, create_strippable_list(list(
return
var/mob/living/carbon/carbon_source = source
var/obj/item/clothing/mask = carbon_source.wear_mask
if (!istype(mask))
return
if ((mask.clothing_flags & MASKINTERNALS) && istype(item, /obj/item/tank))
return isnull(carbon_source.internal) ? "enable_internals" : "disable_internals"
if (carbon_source.can_breathe_internals() && istype(item, /obj/item/tank))
if(carbon_source.internal != item)
return "enable_internals"
else
return "disable_internals"
/proc/strippable_alternate_action_internals(obj/item/item, atom/source, mob/user)
var/obj/item/tank/tank = item
@@ -202,28 +200,26 @@ GLOBAL_LIST_INIT(strippable_human_items, create_strippable_list(list(
if (!istype(carbon_source))
return
var/obj/item/clothing/mask = carbon_source.wear_mask
if (!istype(mask) || !(mask.clothing_flags & MASKINTERNALS))
if (!carbon_source.can_breathe_internals())
return
carbon_source.visible_message(
span_danger("[user] tries to [isnull(carbon_source.internal) ? "open": "close"] the valve on [source]'s [item.name]."),
span_userdanger("[user] tries to [isnull(carbon_source.internal) ? "open": "close"] the valve on your [item.name]."),
span_danger("[user] tries to [(carbon_source.internal != item) ? "open" : "close"] the valve on [source]'s [item.name]."),
span_userdanger("[user] tries to [(carbon_source.internal != item) ? "open" : "close"] the valve on your [item.name]."),
ignored_mobs = user,
)
to_chat(user, span_notice("You try to [isnull(carbon_source.internal) ? "open": "close"] the valve on [source]'s [item.name]..."))
to_chat(user, span_notice("You try to [(carbon_source.internal != item) ? "open" : "close"] the valve on [source]'s [item.name]..."))
if(!do_mob(user, carbon_source, INTERNALS_TOGGLE_DELAY))
return
if(carbon_source.internal)
carbon_source.internal = null
// This isn't meant to be FALSE, it correlates to the icon's name.
if (carbon_source.internal == item)
carbon_source.close_internals()
// This isn't meant to be FALSE, it correlates to the item's name.
else if (!QDELETED(item))
if((carbon_source.wear_mask?.clothing_flags & MASKINTERNALS) || carbon_source.getorganslot(ORGAN_SLOT_BREATHING_TUBE))
carbon_source.internal = item
if(!carbon_source.try_open_internals(item))
return
carbon_source.visible_message(
span_danger("[user] [isnull(carbon_source.internal) ? "closes": "opens"] the valve on [source]'s [item.name]."),
@@ -287,11 +287,44 @@
if((I.body_parts_covered & FEET) || (I.flags_inv | I.transparent_protection) & HIDESHOES)
SEND_SIGNAL(src, COMSIG_CARBON_UNEQUIP_SHOECOVER, I, force, newloc, no_move, invdrop, silent)
/mob/living/carbon/human/toggle_internals(obj/item/tank, is_external = FALSE)
// Just close the tank if it's the one the mob already has open.
var/obj/item/existing_tank = is_external ? external : internal
if(tank == existing_tank)
return toggle_close_internals(is_external)
// Use breathing tube regardless of mask.
if(can_breathe_tube())
return toggle_open_internals(tank, is_external)
// Use mask in absence of tube.
if(isclothing(wear_mask) && ((wear_mask.visor_flags & MASKINTERNALS) || (wear_mask.clothing_flags & MASKINTERNALS)))
// Adjust dishevelled breathing mask back onto face.
if (wear_mask.mask_adjusted)
wear_mask.adjustmask(src)
return toggle_open_internals(tank, is_external)
// Use helmet in absence of tube or valid mask.
if(can_breathe_helmet())
return toggle_open_internals(tank, is_external)
// Notify user of missing valid breathing apparatus.
if (wear_mask)
// Invalid mask
to_chat(src, span_warning("[wear_mask] can't use [tank]!"))
else if (head)
// Invalid headgear
to_chat(src, span_warning("[head] isn't airtight! You need a mask!"))
else
// Not wearing any breathing apparatus.
to_chat(src, span_warning("You need a mask!"))
/// Returns TRUE if the tank successfully toggles open/closed. Opens the tank only if a breathing apparatus is found.
/mob/living/carbon/human/toggle_externals(obj/item/tank)
return toggle_internals(tank, TRUE)
/mob/living/carbon/human/wear_mask_update(obj/item/I, toggle_off = 1)
if((I.flags_inv & (HIDEHAIR|HIDEFACIALHAIR)) || (initial(I.flags_inv) & (HIDEHAIR|HIDEFACIALHAIR)))
update_body_parts()
if(toggle_off && internal && !getorganslot(ORGAN_SLOT_BREATHING_TUBE))
internal = null
// Close internal air tank if mask was the only breathing apparatus.
if(invalid_internals())
cutoff_internals()
if(I.flags_inv & HIDEEYES)
update_worn_glasses()
sec_hud_set_security_status()
@@ -300,6 +333,9 @@
/mob/living/carbon/human/head_update(obj/item/I, forced)
if((I.flags_inv & (HIDEHAIR|HIDEFACIALHAIR)) || forced)
update_body_parts()
// Close internal air tank if helmet was the only breathing apparatus.
if (invalid_internals())
cutoff_internals()
if(I.flags_inv & HIDEEYES || forced)
update_worn_glasses()
if(I.flags_inv & HIDEEARS || forced)
@@ -116,7 +116,7 @@
/datum/species/plasmaman/pre_equip_species_outfit(datum/job/job, mob/living/carbon/human/equipping, visuals_only = FALSE)
if(job.plasmaman_outfit)
equipping.equipOutfit(job.plasmaman_outfit, visuals_only)
equipping.internal = equipping.get_item_for_held_index(2)
equipping.open_internals(equipping.get_item_for_held_index(2))
/datum/species/plasmaman/random_name(gender,unique,lastname)
if(unique)
+151 -3
View File
@@ -168,13 +168,161 @@
// Not an else-if because we're probably equipped in another slot
if(I == internal && (QDELETED(src) || QDELETED(I) || I.loc != src))
internal = null
cutoff_internals()
if(!QDELETED(src))
update_action_buttons_icon(status_only = TRUE)
update_equipment_speed_mods()
//handle stuff to update when a mob equips/unequips a mask.
/// Returns TRUE if an air tank compatible helmet is equipped.
/mob/living/carbon/proc/can_breathe_helmet()
if (isclothing(head) && (head.clothing_flags & HEADINTERNALS))
return TRUE
/// Returns TRUE if an air tank compatible mask is equipped.
/mob/living/carbon/proc/can_breathe_mask()
if (isclothing(wear_mask) && (wear_mask.clothing_flags & MASKINTERNALS))
return TRUE
/// Returns TRUE if a breathing tube is equipped.
/mob/living/carbon/proc/can_breathe_tube()
if (getorganslot(ORGAN_SLOT_BREATHING_TUBE))
return TRUE
/// Returns TRUE if an air tank compatible mask or breathing tube is equipped.
/mob/living/carbon/proc/can_breathe_internals()
return can_breathe_tube() || can_breathe_mask() || can_breathe_helmet()
/// Returns truthy if air tank is open and mob lacks apparatus, or if the tank moved away from the mob.
/mob/living/carbon/proc/invalid_internals()
return (internal || external) && (!can_breathe_internals() || (internal && internal.loc != src))
/**
* Open the internal air tank without checking for any breathing apparatus.
* Returns TRUE if the air tank was opened successfully.
* Closes any existing tanks before opening another one.
*
* Arguments:
* * tank - The given tank to open and start breathing from.
* * is_external - A boolean which indicates if the air tank must be equipped, or stored elsewhere.
*/
/mob/living/carbon/proc/open_internals(obj/item/tank/target_tank, is_external = FALSE)
if (!target_tank)
return
close_all_airtanks()
if (is_external)
external = target_tank
else
internal = target_tank
target_tank.after_internals_opened(src)
update_action_buttons_icon()
return TRUE
/**
* Opens the given internal air tank if a breathing apparatus is found. Returns TRUE if successful, FALSE otherwise.
* Returns TRUE if the tank was opened successfully.
*
* Arguments:
* * tank - The given tank we will attempt to toggle open and start breathing from.
* * is_external - A boolean which indicates if the air tank must be equipped, or stored elsewhere.
*/
/mob/living/carbon/proc/try_open_internals(obj/item/tank/target_tank, is_external = FALSE)
if (!can_breathe_internals())
return
return open_internals(target_tank, is_external)
/**
* Actually closes the active internal or external air tank.
* Returns TRUE if the tank was opened successfully.
*
* Arguments:
* * is_external - A boolean which indicates if the air tank must be equipped, or stored elsewhere.
*/
/mob/living/carbon/proc/close_internals(is_external = FALSE)
var/obj/item/tank/target_tank = is_external ? external : internal
if (!target_tank)
return
if (is_external)
external = null
else
internal = null
target_tank.after_internals_closed(src)
update_action_buttons_icon()
return TRUE
/// Close the the currently open external (that's EX-ternal) air tank. Returns TREUE if successful.
/mob/living/carbon/proc/close_externals()
return close_internals(TRUE)
/// Quickly/lazily close all airtanks without any returns or notifications.
/mob/living/carbon/proc/close_all_airtanks()
if (external)
close_externals()
if (internal)
close_internals()
/**
* Prepares to open the internal air tank and notifies the mob in chat.
* Handles displaying messages to the user before doing the actual opening.
* Returns TRUE if the tank was opened/closed successfully.
*
* Arguments:
* * tank - The given tank to toggle open and start breathing from.
* * is_external - A boolean which indicates if the air tank must be equipped, or stored elsewhere.
*/
/mob/living/carbon/proc/toggle_open_internals(obj/item/tank/target_tank, is_external = FALSE)
if (!target_tank)
return
if(internal || (is_external && external))
to_chat(src, span_notice("You switch your internals to [target_tank]."))
else
to_chat(src, span_notice("You open [target_tank] valve."))
return open_internals(target_tank, is_external)
/**
* Prepares to close the currently open internal air tank and notifies in chat.
* Handles displaying messages to the user before doing the actual closing.
* Returns TRUE if
*
* Arguments:
* * is_external - A boolean which indicates if the air tank must be equipped, or stored elsewhere.
*/
/mob/living/carbon/proc/toggle_close_internals(is_external = FALSE)
if (!internal && !external)
return
to_chat(src, span_notice("You close [is_external ? external : internal] valve."))
return close_internals(is_external)
/// Prepares emergency disconnect from open air tanks and notifies in chat. Usually called after mob suddenly unequips breathing apparatus.
/mob/living/carbon/proc/cutoff_internals()
if (!external && !internal)
return
to_chat(src, span_notice("Your internals disconnect from [external || internal] and the valve closes."))
close_all_airtanks()
/**
* Toggles the given internal air tank open, or close the currently open one, if a compatible breathing apparatus is found.
* Returns TRUE if the tank was opened successfully.
*
* Arguments:
* * tank - The given tank to toggle open and start breathing from internally.
*/
/mob/living/carbon/proc/toggle_internals(obj/item/tank)
// Carbons can't open their own internals tanks.
return FALSE
/**
* Toggles the given external (that's EX-ternal) air tank open, or close the currently open one, if a compatible breathing apparatus is found.
* Returns TRUE if the tank was opened successfully.
*
* Arguments:
* * tank - The given tank to toggle open and start breathing from externally.
*/
/mob/living/carbon/proc/toggle_externals(obj/item/tank)
// Carbons can't open their own externals tanks.
return FALSE
/// Handle stuff to update when a mob equips/unequips a mask.
/mob/living/proc/wear_mask_update(obj/item/I, toggle_off = 1)
update_worn_mask()
@@ -184,7 +332,7 @@
update_tint()
update_worn_mask()
//handle stuff to update when a mob equips/unequips a headgear.
/// Handle stuff to update when a mob equips/unequips a headgear.
/mob/living/carbon/proc/head_update(obj/item/I, forced)
if(isclothing(I))
var/obj/item/clothing/C = I
+16 -11
View File
@@ -151,7 +151,7 @@
failed_last_breath = TRUE
throw_alert(ALERT_NOT_ENOUGH_OXYGEN, /atom/movable/screen/alert/not_enough_oxy)
return FALSE
var/safe_oxy_min = 16
var/safe_co2_max = 10
var/safe_plas_max = 0.05
@@ -303,21 +303,26 @@
return TRUE
//Fourth and final link in a breath chain
/// Fourth and final link in a breath chain
/mob/living/carbon/proc/handle_breath_temperature(datum/gas_mixture/breath)
// The air you breathe out should match your body temperature
breath.temperature = bodytemperature
/// Attempts to take a breath from the external or internal air tank.
/mob/living/carbon/proc/get_breath_from_internal(volume_needed)
if(internal)
if(internal.loc != src)
internal = null
else if ((!wear_mask || !(wear_mask.clothing_flags & MASKINTERNALS)) && !getorganslot(ORGAN_SLOT_BREATHING_TUBE))
internal = null
else
. = internal.remove_air_volume(volume_needed)
if(!.)
return FALSE //to differentiate between no internals and active, but empty internals
if(invalid_internals())
// Unexpectely lost breathing apparatus and ability to breathe from the internal air tank.
cutoff_internals()
return
if (external)
. = external.remove_air_volume(volume_needed)
else if (internal)
. = internal.remove_air_volume(volume_needed)
else
// Return without taking a breath if there is no air tank.
return
// To differentiate between no internals and active, but empty internals.
return . || FALSE
/mob/living/carbon/proc/handle_blood(delta_time, times_fired)
return
+3
View File
@@ -220,6 +220,9 @@
wearer.update_worn_mask()
wearer.update_worn_glasses()
wearer.update_body_parts()
// Close internal air tank if MOD helmet is unsealed and was the only breathing apparatus.
if (!seal && wearer?.invalid_internals())
wearer.cutoff_internals()
/// Finishes the suit's activation, starts processing
/obj/item/mod/control/proc/finish_activation(on)
+1 -1
View File
@@ -444,7 +444,7 @@
icon_state = "[skin]-control[active ? "-sealed" : ""]"
return ..()
/obj/item/mod/control/proc/set_wearer(mob/user)
/obj/item/mod/control/proc/set_wearer(mob/living/carbon/human/user)
wearer = user
SEND_SIGNAL(src, COMSIG_MOD_WEARER_SET, wearer)
RegisterSignal(wearer, COMSIG_ATOM_EXITED, .proc/on_exit)
+28 -28
View File
@@ -55,7 +55,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = NECK_LAYER,
UNSEALED_CLOTHING = SNUG_FIT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|HEADINTERNALS,
SEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
),
@@ -79,7 +79,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = null,
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
UNSEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
),
@@ -126,7 +126,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = NECK_LAYER,
UNSEALED_CLOTHING = SNUG_FIT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -174,7 +174,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = NECK_LAYER,
UNSEALED_CLOTHING = SNUG_FIT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDESNOUT,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR,
UNSEALED_COVER = HEADCOVERSMOUTH,
@@ -228,7 +228,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = NECK_LAYER,
UNSEALED_CLOTHING = SNUG_FIT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -293,7 +293,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = null,
UNSEALED_CLOTHING = SNUG_FIT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEEARS|HIDEHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEYES|HIDEFACE|HIDEFACIALHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -318,7 +318,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = null,
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEEARS|HIDEHAIR|HIDESNOUT,
SEALED_INVISIBILITY = HIDEMASK|HIDEEYES|HIDEFACE,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -424,7 +424,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = NECK_LAYER,
UNSEALED_CLOTHING = SNUG_FIT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -449,7 +449,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = NECK_LAYER,
UNSEALED_CLOTHING = SNUG_FIT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -509,7 +509,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = NECK_LAYER,
UNSEALED_CLOTHING = SNUG_FIT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -564,7 +564,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = null,
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
UNSEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
),
@@ -613,7 +613,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = null,
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEEARS|HIDEHAIR|HIDESNOUT,
SEALED_INVISIBILITY = HIDEMASK|HIDEEYES|HIDEFACE,
UNSEALED_COVER = HEADCOVERSMOUTH,
@@ -665,7 +665,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = null,
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
UNSEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
),
@@ -720,7 +720,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = NECK_LAYER,
UNSEALED_CLOTHING = SNUG_FIT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -768,7 +768,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = NECK_LAYER,
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEEARS|HIDEHAIR,
SEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEYES|HIDEFACE|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -824,7 +824,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = NECK_LAYER,
UNSEALED_CLOTHING = SNUG_FIT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -849,7 +849,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = NECK_LAYER,
UNSEALED_CLOTHING = SNUG_FIT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -905,7 +905,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = null,
UNSEALED_CLOTHING = SNUG_FIT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -1014,7 +1014,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = null,
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL|CASTING_CLOTHES,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
UNSEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
),
@@ -1066,7 +1066,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = null,
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEEARS|HIDEHAIR,
SEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEYES|HIDEFACE|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -1120,7 +1120,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = null,
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
UNSEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
),
@@ -1170,7 +1170,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = NECK_LAYER,
UNSEALED_CLOTHING = SNUG_FIT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -1195,7 +1195,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = null,
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
UNSEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
),
@@ -1247,7 +1247,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = null,
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEEARS|HIDEHAIR,
SEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEYES|HIDEFACE|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -1298,7 +1298,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = null,
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEEARS|HIDEHAIR|HIDESNOUT,
SEALED_INVISIBILITY = HIDEMASK|HIDEEYES|HIDEFACE,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -1343,7 +1343,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = NECK_LAYER,
UNSEALED_CLOTHING = SNUG_FIT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -1389,7 +1389,7 @@
HELMET_FLAGS = list(
UNSEALED_LAYER = null,
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEEARS|HIDEHAIR|HIDESNOUT,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE,
UNSEALED_COVER = HEADCOVERSMOUTH,
@@ -1437,7 +1437,7 @@
"debug" = list(
HELMET_FLAGS = list(
UNSEALED_LAYER = null,
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT|HEADINTERNALS,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEEARS|HIDEHAIR|HIDESNOUT,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE,
UNSEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,