Files
Aurora.3/code/game/objects/items/devices/auto_cpr.dm
2022-06-06 08:10:22 +02:00

490 lines
16 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 = ITEMSIZE_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/breath/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/device(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.add_overlay(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.add_overlay(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.add_overlay(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.add_overlay(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.add_overlay(epp_overlay)
return I
/obj/item/auto_cpr/update_icon()
cut_overlays()
item_state = "[cpr_mode ? "med_harness_cpr" : "[initial(item_state)]"]"
if(breath_mask)
add_overlay("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
add_overlay("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
add_overlay("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"
add_overlay("tank_[tank_type]")
if(epp_active)
add_overlay("epp_active")
if(panel_open)
add_overlay("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/carbon/human/H, mob/living/user, var/target_zone)
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, del_on_fail=0, disable_warning=1, redraw_mob=1))
user.put_in_active_hand(src)
return 1
else
return ..()
/obj/item/auto_cpr/attackby(obj/item/W, mob/user)
if(W.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(W.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(W.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(W, /obj/item/cell))
if(battery)
to_chat(user, "There is already \a [battery] installed.")
return TRUE
user.drop_from_inventory(W, src)
battery = W
user.visible_message(SPAN_NOTICE("[user] places \the [W] in \the [src]."), SPAN_NOTICE("You place \the [W] in \the [src]."))
update_icon()
return TRUE
if(istype(W, /obj/item/clothing/mask/breath))
if(is_type_in_list(W, mask_blacklist))
to_chat(user, "\The [W] 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(W, src)
breath_mask = W
user.visible_message(SPAN_NOTICE("[user] places \the [W] in \the [src]."), SPAN_NOTICE("You place \the [W] in \the [src]."))
update_icon()
return TRUE
if(istype(W, /obj/item/tank/emergency_oxygen))
if(tank)
to_chat(user, "There is already \a [tank] installed!")
return TRUE
user.drop_from_inventory(W, src)
tank = W
user.visible_message(SPAN_NOTICE("[user] places \the [W] in \the [src]."), SPAN_NOTICE("You place \the [W] 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/examine(mob/user)
..(user)
if(!user.Adjacent(src))
return
to_chat(user, SPAN_NOTICE("\The [src]'s [EPP] is currently [epp_mode ? "on" : "off"], while the Auto CPR is [cpr_mode ? "on" : "off"]."))
if(battery)
to_chat(user, SPAN_NOTICE("It currently has a battery with [battery.percent()]% charge."))
if(tank)
to_chat(user, 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)
to_chat(user, SPAN_NOTICE("It has [icon2html(breath_mask, user)] \the [breath_mask] installed."))
#undef EPP