mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-20 03:19:58 +01:00
Refactored the attack proc signature. Added signals and components for the attack proc. Added signals and components for the attackby proc. Adjusted some leftover attackby procs signatures. Added grep test to ensure people don't keep adding attack/attackby procs with the wrong signature.
495 lines
17 KiB
Plaintext
495 lines
17 KiB
Plaintext
#define EPP "Emergency Positive Pressure system"
|
|
|
|
/obj/item/auto_cpr
|
|
name = "stabilizer harness"
|
|
desc = "A specialized medical harness that gives regular compressions to the patient's ribcage for cases of urgent heart issues, and functions as an emergency \
|
|
artificial respirator for cases of urgent lung issues."
|
|
desc_info = "The Stabilizer Harness' CPR mode is capable of restarting the heart much like manual CPR with a chance for rib cracking ONLY IF the patient is flat lining,\
|
|
while the EPP mode can keep the patient breathing during transport for as long as there's appropriate air in the installed tank. Both use power from the battery. \
|
|
<br> Use this item in your hand to toggle the CPR or EPP modes on/off.<br> Use a Screwdriver on it to unscrew the panel to be able to remove/add other items. \
|
|
The tank can be removed with a Wrench. The battery can be removed with a crowbar. Use the item in your hand the panel unscrewed to remove the breath mask."
|
|
|
|
icon = 'icons/obj/med_harness.dmi'
|
|
icon_state = "med_harness"
|
|
item_state = "med_harness"
|
|
contained_sprite = TRUE
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
origin_tech = list(TECH_MAGNET = 5, TECH_BIO = 3)
|
|
slot_flags = SLOT_OCLOTHING
|
|
var/panel_open = FALSE
|
|
var/last_pump
|
|
var/last_bm_check
|
|
|
|
var/obj/item/cell/battery = null
|
|
var/battery_level = 0
|
|
var/charge_cost = 7 // 7 for 1 active function. Total of 14 if both CPR and EPP are doing their thing
|
|
var/cpr_mode = TRUE // Auto-Compressor system. Can be toggled on/off
|
|
|
|
var/mob/living/carbon/human/breather = null
|
|
var/obj/item/clothing/mask/breath/breath_mask = null
|
|
var/obj/item/tank/emergency_oxygen/tank = null
|
|
var/tank_level = 0
|
|
var/tank_type = null
|
|
var/mask_on = FALSE
|
|
var/epp_mode = FALSE // Emergency Positive Pressure system. Can be toggled on/off
|
|
var/epp_active = FALSE
|
|
|
|
var/list/mask_blacklist = list(
|
|
/obj/item/clothing/mask/gas/vaurca,
|
|
/obj/item/clothing/mask/breath/skrell,
|
|
/obj/item/clothing/mask/breath/lyodsuit,
|
|
/obj/item/clothing/mask/breath/infiltrator)
|
|
|
|
/obj/item/auto_cpr/Initialize()
|
|
. = ..()
|
|
battery = new /obj/item/cell(src)
|
|
breath_mask = new /obj/item/clothing/mask/breath/medical(src)
|
|
tank = new /obj/item/tank/emergency_oxygen/engi(src)
|
|
update_icon()
|
|
|
|
/obj/item/auto_cpr/Destroy()
|
|
STOP_PROCESSING(SSprocessing, src)
|
|
QDEL_NULL(battery)
|
|
if(breather)
|
|
breath_mask_off()
|
|
QDEL_NULL(breath_mask)
|
|
QDEL_NULL(tank)
|
|
return ..()
|
|
|
|
/obj/item/auto_cpr/build_additional_parts(H, mob_icon, slot)
|
|
var/image/I = ..()
|
|
if(!I)
|
|
I = image(null)
|
|
var/c_icon = 'icons/obj/med_harness.dmi'
|
|
if(battery)
|
|
var/c_state = "battery[battery_level][contained_sprite ? slot_str_to_contained_flag(slot) : ""]"
|
|
var/image/battery_overlay = image(c_icon, c_state)
|
|
battery_overlay.appearance_flags = RESET_ALPHA
|
|
I.AddOverlays(battery_overlay)
|
|
if(breath_mask)
|
|
var/c_state = "mask_[mask_on ? "worn" : "idle"][contained_sprite ? slot_str_to_contained_flag(slot) : ""]"
|
|
var/image/mask_overlay = image(c_icon, c_state)
|
|
mask_overlay.appearance_flags = RESET_ALPHA
|
|
I.AddOverlays(mask_overlay)
|
|
if(tank)
|
|
if(tank_level)
|
|
var/c_state = "tank_indicator[tank_level][contained_sprite ? slot_str_to_contained_flag(slot) : ""]"
|
|
var/image/tank_level_overlay = image(c_icon, c_state)
|
|
tank_level_overlay.appearance_flags = RESET_ALPHA
|
|
I.AddOverlays(tank_level_overlay)
|
|
var/c_state = "tank_[tank_type][contained_sprite ? slot_str_to_contained_flag(slot) : ""]"
|
|
var/image/tank_overlay = image(c_icon, c_state)
|
|
tank_overlay.appearance_flags = RESET_ALPHA
|
|
I.AddOverlays(tank_overlay)
|
|
if(epp_active)
|
|
var/c_state = "epp_active[cpr_mode ? "_cpr" : ""][contained_sprite ? slot_str_to_contained_flag(slot) : ""]"
|
|
var/image/epp_overlay = image(c_icon, c_state)
|
|
epp_overlay.appearance_flags = RESET_ALPHA
|
|
I.AddOverlays(epp_overlay)
|
|
return I
|
|
|
|
/obj/item/auto_cpr/update_icon()
|
|
ClearOverlays()
|
|
item_state = "[cpr_mode ? "med_harness_cpr" : "[initial(item_state)]"]"
|
|
|
|
if(breath_mask)
|
|
AddOverlays("mask_[mask_on ? "worn" : "idle"]")
|
|
if(battery)
|
|
switch(battery.percent())
|
|
if(90 to INFINITY) battery_level = 6
|
|
if(80 to 90) battery_level = 5
|
|
if(60 to 79) battery_level = 4
|
|
if(40 to 59) battery_level = 3
|
|
if(20 to 39) battery_level = 2
|
|
if(05 to 19) battery_level = 1
|
|
if(-INFINITY to 4) battery_level = 0
|
|
AddOverlays("battery[battery_level]")
|
|
if(tank)
|
|
switch(tank.percent())
|
|
if(90 to INFINITY) tank_level = 6
|
|
if(80 to 90) tank_level = 5
|
|
if(60 to 79) tank_level = 4
|
|
if(40 to 59) tank_level = 3
|
|
if(20 to 39) tank_level = 2
|
|
if(05 to 19) tank_level = 1
|
|
if(-INFINITY to 4) tank_level = 0
|
|
AddOverlays("tank_indicator[tank_level]")
|
|
|
|
if(istype(tank, /obj/item/tank/emergency_oxygen/engi))
|
|
tank_type = "engi"
|
|
else if(istype(tank, /obj/item/tank/emergency_oxygen))
|
|
tank_type = "oxy"
|
|
else
|
|
tank_type = "other"
|
|
AddOverlays("tank_[tank_type]")
|
|
if(epp_active)
|
|
AddOverlays("epp_active")
|
|
if(panel_open)
|
|
AddOverlays("panel_open[battery ? "_battery" : ""]")
|
|
|
|
/obj/item/auto_cpr/mob_can_equip(mob/living/carbon/human/H, slot, disable_warning = 0, force = 0)
|
|
. = ..()
|
|
if(slot == slot_wear_suit)
|
|
if(panel_open)
|
|
return FALSE
|
|
return
|
|
if(force || !istype(H) || slot != slot_wear_suit)
|
|
return
|
|
if(H.species.get_bodytype() in list(BODYTYPE_HUMAN, BODYTYPE_TAJARA, BODYTYPE_SKRELL, BODYTYPE_UNATHI)) //gtfo stinky bugs
|
|
return
|
|
else
|
|
return FALSE
|
|
|
|
/obj/item/auto_cpr/attack(mob/living/target_mob, mob/living/user, target_zone)
|
|
var/mob/living/carbon/human/H = target_mob
|
|
if(istype(H) && user.a_intent == I_HELP)
|
|
if(panel_open)
|
|
to_chat(user, SPAN_WARNING("You must screw \the [src]'s panel closed before fitting it onto anyone!"))
|
|
return 1
|
|
if(H.wear_suit)
|
|
to_chat(user, SPAN_WARNING("Their [H.wear_suit] is in the way, remove it first!"))
|
|
return 1
|
|
user.visible_message(SPAN_NOTICE("[user] starts fitting \the [src] onto [H]'s chest."))
|
|
|
|
if(!do_after(user, 2 SECONDS, H))
|
|
to_chat(user, SPAN_DANGER("Failed fitting \the [src] onto [H]! Both you and [H] must remain still for you to do that!"))
|
|
return
|
|
|
|
if(user.unEquip(src))
|
|
if(!H.equip_to_slot_if_possible(src, slot_wear_suit, delete_on_fail = FALSE, disable_warning = TRUE, redraw_mob = TRUE))
|
|
user.put_in_active_hand(src)
|
|
return 1
|
|
else
|
|
return ..()
|
|
|
|
/obj/item/auto_cpr/attackby(obj/item/attacking_item, mob/user)
|
|
if(attacking_item.isscrewdriver())
|
|
if(ishuman(loc))
|
|
var/mob/living/carbon/human/H = loc
|
|
if(H.get_inventory_slot(src) == slot_wear_suit)
|
|
to_chat(user, SPAN_WARNING("You must unequip \the [src] before doing that!"))
|
|
return TRUE
|
|
panel_open = !panel_open
|
|
user.visible_message(SPAN_NOTICE("[user] screws \the [src]'s panel [panel_open ? "open" : "closed"]."), SPAN_NOTICE("You screw \the [src]'s panel [panel_open ? "open" : "closed"]."))
|
|
update_icon()
|
|
return TRUE
|
|
|
|
if(panel_open)
|
|
if(attacking_item.iswrench())
|
|
if(!tank)
|
|
to_chat(user, "There isn't a tank to remove!")
|
|
return TRUE
|
|
user.visible_message(SPAN_NOTICE("[user] removes \the [tank] from \the [src]."), SPAN_NOTICE("You remove \the [tank] from \the [src]."))
|
|
tank.forceMove(user.loc)
|
|
user.put_in_hands(tank)
|
|
tank = null
|
|
update_icon()
|
|
return TRUE
|
|
if(attacking_item.iscrowbar())
|
|
if(!battery)
|
|
to_chat(user, "There isn't a battery to remove!")
|
|
return TRUE
|
|
user.visible_message(SPAN_NOTICE("[user] removes \the [battery] from \the [src]."), SPAN_NOTICE("You remove \the [battery] from \the [src]."))
|
|
battery.forceMove(user.loc)
|
|
user.put_in_hands(battery)
|
|
battery = null
|
|
update_icon()
|
|
return TRUE
|
|
if(istype(attacking_item, /obj/item/cell))
|
|
if(battery)
|
|
to_chat(user, "There is already \a [battery] installed.")
|
|
return TRUE
|
|
user.drop_from_inventory(attacking_item, src)
|
|
battery = attacking_item
|
|
user.visible_message(SPAN_NOTICE("[user] places \the [attacking_item] in \the [src]."), SPAN_NOTICE("You place \the [attacking_item] in \the [src]."))
|
|
update_icon()
|
|
return TRUE
|
|
if(istype(attacking_item, /obj/item/clothing/mask/breath))
|
|
if(is_type_in_list(attacking_item, mask_blacklist))
|
|
to_chat(user, "\The [attacking_item] is incompatible with \the [src].")
|
|
return TRUE
|
|
if(breath_mask)
|
|
to_chat(user, "There is already \a [breath_mask] installed.")
|
|
return TRUE
|
|
user.drop_from_inventory(attacking_item, src)
|
|
breath_mask = attacking_item
|
|
user.visible_message(SPAN_NOTICE("[user] places \the [attacking_item] in \the [src]."), SPAN_NOTICE("You place \the [attacking_item] in \the [src]."))
|
|
update_icon()
|
|
return TRUE
|
|
if(istype(attacking_item, /obj/item/tank/emergency_oxygen))
|
|
if(tank)
|
|
to_chat(user, "There is already \a [tank] installed!")
|
|
return TRUE
|
|
user.drop_from_inventory(attacking_item, src)
|
|
tank = attacking_item
|
|
user.visible_message(SPAN_NOTICE("[user] places \the [attacking_item] in \the [src]."), SPAN_NOTICE("You place \the [attacking_item] in \the [src]."))
|
|
update_icon()
|
|
return TRUE
|
|
|
|
/obj/item/auto_cpr/attack_self(mob/user)
|
|
if(panel_open)
|
|
if(!breath_mask)
|
|
to_chat(user, "There isn't an installed mask to remove!")
|
|
return
|
|
user.visible_message(SPAN_NOTICE("[user] removes \the [breath_mask] from \the [src]."), SPAN_NOTICE("You remove \the [breath_mask] from \the [src]."))
|
|
breath_mask.forceMove(user.loc)
|
|
user.put_in_hands(breath_mask)
|
|
breath_mask = null
|
|
update_icon()
|
|
return
|
|
var/list/options = list(
|
|
"Toggle CPR" = image('icons/mob/screen/radial.dmi', "cpr_mode"),
|
|
"Toggle EPP" = image('icons/mob/screen/radial.dmi', "iv_epp"))
|
|
var/chosen_action = show_radial_menu(user, src, options, require_near = TRUE, radius = 42, tooltips = TRUE)
|
|
if(!chosen_action)
|
|
return
|
|
switch(chosen_action)
|
|
if("Toggle CPR")
|
|
toggle_cpr()
|
|
if("Toggle EPP")
|
|
toggle_epp()
|
|
|
|
/obj/item/auto_cpr/attack_hand(mob/user)
|
|
..()
|
|
|
|
/obj/item/auto_cpr/emp_act(severity)
|
|
. = ..()
|
|
|
|
epp_off()
|
|
cpr_mode = FALSE
|
|
if(battery)
|
|
battery.emp_act(severity)
|
|
update_icon()
|
|
|
|
/obj/item/auto_cpr/get_cell()
|
|
return battery
|
|
|
|
/obj/item/auto_cpr/equipped(mob/user, slot)
|
|
..()
|
|
START_PROCESSING(SSprocessing,src)
|
|
|
|
/obj/item/auto_cpr/dropped(mob/user)
|
|
STOP_PROCESSING(SSprocessing,src)
|
|
..()
|
|
|
|
/obj/item/auto_cpr/process()
|
|
if(!ishuman(loc))
|
|
return PROCESS_KILL
|
|
|
|
var/mob/living/carbon/human/H = loc
|
|
if(H.get_inventory_slot(src) != slot_wear_suit)
|
|
if(mask_on)
|
|
breath_mask_off()
|
|
update_icon()
|
|
return PROCESS_KILL
|
|
if(!battery)
|
|
return PROCESS_KILL
|
|
if(battery.charge <= 0)
|
|
if(epp_mode)
|
|
epp_off()
|
|
if(cpr_mode)
|
|
cpr_mode = FALSE
|
|
visible_message(SPAN_WARNING("\The [src] sputters as it runs out of charge!"))
|
|
playsound(src, 'sound/machines/synth_no.ogg', 50)
|
|
update_icon()
|
|
return PROCESS_KILL
|
|
|
|
if(cpr_mode)
|
|
cpr_process(H)
|
|
if(epp_mode)
|
|
epp_process(H)
|
|
H.update_inv_wear_suit()
|
|
update_icon()
|
|
|
|
/obj/item/auto_cpr/proc/cpr_process(mob/living/carbon/human/H)
|
|
if(world.time > last_pump + 10 SECONDS)
|
|
last_pump = world.time
|
|
playsound(src, 'sound/machines/pump.ogg', 25)
|
|
var/obj/item/organ/internal/heart/heart = H.internal_organs_by_name[BP_HEART]
|
|
if(heart)
|
|
heart.external_pump = list(world.time, 0.6)
|
|
battery.use(charge_cost)
|
|
|
|
if(H.is_asystole())
|
|
if(H.stat != DEAD && prob(10))
|
|
H.resuscitate()
|
|
if(prob(5 * rand(2, 3)))
|
|
var/obj/item/organ/external/chest = H.get_organ(BP_CHEST)
|
|
if(chest)
|
|
chest.fracture()
|
|
|
|
/obj/item/auto_cpr/proc/epp_process(mob/living/carbon/human/H)
|
|
if(!tank || !breath_mask)
|
|
src.visible_message(SPAN_WARNING("Error! Vital component for \the [src]'s [EPP] missing! Turning function off."))
|
|
epp_off()
|
|
return
|
|
if(H.species.flags & NO_BREATHE)
|
|
epp_off()
|
|
return
|
|
if(!mask_on)
|
|
if(world.time > last_bm_check + 7 SECONDS) // Give it a few seconds before trying again
|
|
last_bm_check = world.time
|
|
breath_mask_on(H)
|
|
return
|
|
|
|
var/mask_check = breath_mask.get_equip_slot()
|
|
if(mask_check != slot_wear_mask)
|
|
breath_mask_off()
|
|
return
|
|
if(breath_mask.hanging)
|
|
breath_mask_off()
|
|
return
|
|
if(breath_mask.loc != breather)
|
|
breath_mask_off()
|
|
return
|
|
|
|
var/obj/item/organ/internal/lungs/lungs = H.internal_organs_by_name[BP_LUNGS]
|
|
var/safe_pressure_min = H.species.breath_pressure + 2
|
|
safe_pressure_min *= 1 + rand(1,4) * lungs.damage/lungs.max_damage
|
|
if(!lungs)
|
|
epp_off()
|
|
return
|
|
if(lungs.checking_rupture == FALSE)
|
|
src.visible_message(SPAN_WARNING("Error! Patient safety check triggered! Turning the [EPP] off."))
|
|
epp_off()
|
|
return
|
|
if(tank.air_contents.return_pressure() <= 10)
|
|
src.visible_message(SPAN_WARNING("Error! Installed [tank] is low or near empty! Turning the [EPP] off."))
|
|
epp_off()
|
|
return
|
|
|
|
if(H.losebreath > 0)
|
|
if(!epp_active)
|
|
src.visible_message(SPAN_WARNING("\The [src] beeps, activating it's [EPP]!"))
|
|
tank.forceMove(H)
|
|
H.internal = tank
|
|
if(H.internals)
|
|
H.internals.icon_state = "internal1"
|
|
playsound(H, 'sound/machines/windowdoor.ogg', 50)
|
|
epp_active = TRUE
|
|
tank.distribute_pressure = safe_pressure_min
|
|
H.losebreath = 0
|
|
to_chat(H, SPAN_NOTICE("You feel fresh air being pushed into your lungs."))
|
|
battery.use(charge_cost)
|
|
|
|
/obj/item/auto_cpr/proc/breath_mask_on(mob/living/carbon/human/H)
|
|
if(!H.organs_by_name[BP_HEAD])
|
|
src.visible_message(SPAN_WARNING("Error! Patient lacks a head!"))
|
|
playsound(src, 'sound/machines/buzz-sigh.ogg', 50)
|
|
return
|
|
if(!H.check_has_mouth())
|
|
src.visible_message(SPAN_WARNING("Error! Patient lacks a mouth!"))
|
|
playsound(src, 'sound/machines/buzz-sigh.ogg', 50)
|
|
return
|
|
if(H.head && (H.head.body_parts_covered & FACE))
|
|
src.visible_message(SPAN_WARNING("Error! Access to patient's head is obstructed!"))
|
|
playsound(src, 'sound/machines/buzz-sigh.ogg', 50)
|
|
return
|
|
if(H.wear_mask)
|
|
src.visible_message(SPAN_WARNING("Error! Access to patient's mouth is obstructed!"))
|
|
playsound(src, 'sound/machines/buzz-sigh.ogg', 50)
|
|
return
|
|
src.visible_message(SPAN_INFO("\The [src] automatically fastens \the [breath_mask] onto \the [H]."))
|
|
playsound(H, 'sound/effects/buckle.ogg', 50)
|
|
breath_mask.forceMove(H.loc)
|
|
H.equip_to_slot(breath_mask, slot_wear_mask)
|
|
H.update_inv_wear_mask()
|
|
breather = H
|
|
mask_on = TRUE
|
|
update_icon()
|
|
|
|
/obj/item/auto_cpr/proc/breath_mask_off()
|
|
src.visible_message(SPAN_WARNING("\The [src] automatically retracts \the [breath_mask]!"))
|
|
if(epp_active)
|
|
tank.forceMove(src)
|
|
if(breather.internals)
|
|
breather.internals.icon_state = "internal0"
|
|
breather.internal = null
|
|
epp_active = FALSE
|
|
if(breath_mask.hanging)
|
|
breath_mask.hanging = FALSE
|
|
breath_mask.adjust_sprites()
|
|
if(breath_mask.loc != breather)
|
|
var/loc_check = breath_mask.loc
|
|
if(ismob(loc_check))
|
|
var/mob/living/carbon/human/holder = loc_check
|
|
holder.remove_from_mob(breath_mask)
|
|
holder.update_inv_wear_mask()
|
|
holder.update_inv_l_hand()
|
|
holder.update_inv_r_hand()
|
|
breath_mask.forceMove(src)
|
|
breather = null
|
|
mask_on = FALSE
|
|
return
|
|
breather.remove_from_mob(breath_mask)
|
|
breather.update_inv_wear_mask()
|
|
breath_mask.forceMove(src)
|
|
breather = null
|
|
mask_on = FALSE
|
|
|
|
/obj/item/auto_cpr/proc/epp_off()
|
|
if(mask_on)
|
|
breath_mask_off()
|
|
playsound(src, 'sound/machines/buzz-two.ogg', 50)
|
|
epp_mode = FALSE
|
|
|
|
/obj/item/auto_cpr/proc/toggle_check(mob/user)
|
|
if(!ishuman(user) && !issilicon(user))
|
|
to_chat(user, SPAN_WARNING("This mob cannot use this!"))
|
|
return
|
|
if(user.stat || user.incapacitated())
|
|
to_chat(user, SPAN_WARNING("You are in no shape to do this."))
|
|
return
|
|
return TRUE
|
|
|
|
/obj/item/auto_cpr/verb/toggle_epp()
|
|
set category = "Object"
|
|
set name = "Toggle EPP"
|
|
set src in usr
|
|
|
|
if(!toggle_check(usr))
|
|
return
|
|
if(battery?.charge <= 0)
|
|
to_chat(usr, SPAN_WARNING("\The [src] doesn't have enough power for you to do that!"))
|
|
playsound(src, 'sound/machines/synth_no.ogg', 50)
|
|
return
|
|
if(epp_mode)
|
|
epp_off()
|
|
to_chat(usr, SPAN_NOTICE("You toggle \the [src]'s [EPP] off."))
|
|
return
|
|
epp_mode = TRUE
|
|
to_chat(usr, SPAN_NOTICE("You toggle \the [src]'s [EPP] on."))
|
|
playsound(usr, 'sound/machines/click.ogg', 50)
|
|
update_icon()
|
|
|
|
/obj/item/auto_cpr/verb/toggle_cpr()
|
|
set category = "Object"
|
|
set name = "Toggle CPR"
|
|
set src in usr
|
|
|
|
if(!toggle_check(usr))
|
|
return
|
|
if(battery?.charge <= 0)
|
|
to_chat(usr, SPAN_WARNING("\The [src] doesn't have enough power for you to do that!"))
|
|
playsound(src, 'sound/machines/synth_no.ogg', 50)
|
|
return
|
|
cpr_mode = !cpr_mode
|
|
to_chat(usr, SPAN_NOTICE("You toggle \the [src]'s Auto CPR system [cpr_mode ? "on" : "off"]."))
|
|
playsound(usr, 'sound/machines/click.ogg', 50)
|
|
update_icon()
|
|
|
|
/obj/item/auto_cpr/get_examine_text(mob/user, distance, is_adjacent, infix, suffix)
|
|
. = ..()
|
|
if(!is_adjacent)
|
|
return
|
|
. += SPAN_NOTICE("\The [src]'s [EPP] is currently [epp_mode ? "on" : "off"], while the Auto CPR is [cpr_mode ? "on" : "off"].")
|
|
if(battery)
|
|
. += SPAN_NOTICE("It currently has a battery with [battery.percent()]% charge.")
|
|
if(tank)
|
|
. += SPAN_NOTICE("It has [icon2html(tank, user)] \the [tank] installed. The meter shows [round(tank.air_contents.return_pressure())]kPa, \
|
|
with the pressure set to [round(tank.distribute_pressure)]kPa.[epp_active ? " The [EPP] is active." : ""]")
|
|
if(breath_mask)
|
|
. += SPAN_NOTICE("It has [icon2html(breath_mask, user)] \the [breath_mask] installed.")
|
|
|
|
#undef EPP
|