diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm index 86b875b0fce..721851ffaf3 100644 --- a/code/__defines/chemistry.dm +++ b/code/__defines/chemistry.dm @@ -6,6 +6,7 @@ #define CHEM_TOUCH 1 #define CHEM_INGEST 2 #define CHEM_INJECT 3 +#define CHEM_INHALE 4 #define MINIMUM_CHEMICAL_VOLUME 0.01 diff --git a/code/datums/supplypacks/medical.dm b/code/datums/supplypacks/medical.dm index 0aeab28bf68..1312d297ad6 100644 --- a/code/datums/supplypacks/medical.dm +++ b/code/datums/supplypacks/medical.dm @@ -106,6 +106,7 @@ /obj/item/clothing/shoes/color/white, /obj/item/clothing/gloves/latex, /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/flashlight/pen, /obj/item/chems/syringe) containertype = /obj/structure/closet/crate/secure @@ -125,6 +126,7 @@ /obj/item/clothing/shoes/color/white, /obj/item/clothing/gloves/latex, /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/flashlight/pen, /obj/item/chems/syringe) containertype = /obj/structure/closet/crate/secure @@ -144,6 +146,7 @@ /obj/item/clothing/gloves/latex, /obj/item/chems/dropper, /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/storage/box/pillbottles, /obj/item/chems/syringe) containertype = /obj/structure/closet/crate/secure @@ -167,6 +170,7 @@ /obj/item/clothing/shoes/jackboots, /obj/item/clothing/gloves/latex, /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/flashlight/pen, /obj/item/chems/syringe, /obj/item/clothing/accessory/storage/vest) diff --git a/code/datums/trading/traders/goods.dm b/code/datums/trading/traders/goods.dm index 19a8d5d05f5..95131be8f22 100644 --- a/code/datums/trading/traders/goods.dm +++ b/code/datums/trading/traders/goods.dm @@ -194,6 +194,7 @@ Sells devices, odds and ends, and medical stuff /obj/item/megaphone = TRADER_THIS_TYPE, /obj/item/paicard = TRADER_THIS_TYPE, /obj/item/scanner/health = TRADER_THIS_TYPE, + /obj/item/scanner/breath = TRADER_THIS_TYPE, /obj/item/scanner/gas = TRADER_ALL, /obj/item/scanner/spectrometer = TRADER_ALL, /obj/item/scanner/reagent = TRADER_ALL, diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index b7c3f581f02..76e01d982e5 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -19,6 +19,7 @@ var/obj/item/chems/glass/beaker = null var/filtering = 0 var/pump + var/lavage = FALSE // Are we rinsing reagents from the lungs? var/list/stasis_settings = list(1, 2, 5, 10) var/stasis = 1 var/pump_speed @@ -123,6 +124,16 @@ ingested.trans_to_obj(beaker, pump_speed * trans_amt) else toggle_pump() + if(lavage > 0) + if (beaker) + if (beaker.reagents.total_volume < beaker.reagents.maximum_volume) + var/datum/reagents/inhaled = occupant.get_inhaled_reagents() + var/trans_volume = LAZYLEN(inhaled?.reagent_volumes) + if(inhaled && trans_volume) + inhaled.trans_to_obj(beaker, pump_speed * trans_volume) + else + toggle_lavage() + if(iscarbon(occupant) && stasis > 1) occupant.SetStasis(stasis) @@ -189,6 +200,7 @@ data["beaker"] = -1 data["filtering"] = filtering data["pump"] = pump + data["lavage"] = lavage data["stasis"] = stasis data["skill_check"] = user.skill_check(SKILL_MEDICAL, SKILL_BASIC) ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open) @@ -225,6 +237,10 @@ if(filtering != text2num(href_list["pump"])) toggle_pump() return TOPIC_REFRESH + if(href_list["lavage"]) + if(lavage != text2num(href_list["lavage"])) + toggle_lavage() + return TOPIC_REFRESH if(href_list["chemical"]) var/obj/canister = locate(href_list["chemical"]) if(istype(canister)) @@ -305,6 +321,16 @@ to_chat(occupant, SPAN_WARNING("You feel a tube jammed down your throat.")) pump = !pump +/obj/machinery/sleeper/proc/toggle_lavage() + if(!occupant || !beaker) + lavage = 0 + return + lavage = !lavage + if (lavage) + to_chat(occupant, SPAN_WARNING("You feel a tube jammed down your throat.")) + else + to_chat(occupant, SPAN_NOTICE("You feel a tube retract from your throat.")) + /obj/machinery/sleeper/proc/go_in(var/mob/M, var/mob/user) if(!M || M.anchored) return @@ -364,6 +390,7 @@ beaker = null toggle_filter() toggle_pump() + toggle_lavage() /obj/machinery/sleeper/proc/inject_chemical(var/mob/living/user, var/obj/canister, var/amount, var/target_transfer_type = CHEM_INJECT) if(stat & (BROKEN|NOPOWER)) diff --git a/code/game/machinery/vending/medical.dm b/code/game/machinery/vending/medical.dm index 7b278bad927..e1e2c3afafa 100644 --- a/code/game/machinery/vending/medical.dm +++ b/code/game/machinery/vending/medical.dm @@ -18,10 +18,11 @@ /obj/item/chems/syringe/antibiotic = 4, /obj/item/chems/syringe = 12, /obj/item/scanner/health = 5, - /obj/item/chems/glass/beaker = 4, + /obj/item/scanner/breath = 5, + /obj/item/chems/glass/beaker = 4, /obj/item/chems/dropper = 2, - /obj/item/stack/medical/advanced/bruise_pack = 3, - /obj/item/stack/medical/advanced/ointment = 3, + /obj/item/stack/medical/advanced/bruise_pack = 3, + /obj/item/stack/medical/advanced/ointment = 3, /obj/item/stack/medical/splint = 2, /obj/item/chems/hypospray/autoinjector/pain = 4 ) diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index 1f01b9fd1f0..b48e787dba5 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -236,7 +236,7 @@ steam.start() -- spawns the effect M.adjustOxyLoss(1) if (M.coughedtime != 1) M.coughedtime = 1 - M.emote("cough") + M.cough() spawn ( 20 ) M.coughedtime = 0 @@ -265,7 +265,7 @@ steam.start() -- spawns the effect ADJ_STATUS(M, STAT_ASLEEP, 1) if (M.coughedtime != 1) M.coughedtime = 1 - M.emote("cough") + M.cough() spawn ( 20 ) M.coughedtime = 0 ///////////////////////////////////////////// diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 9aa97fac7e2..63ce53768a3 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -149,9 +149,9 @@ var/list/pinpoint = list(/decl/material/liquid/painkillers=5,/decl/material/liquid/amphetamines=1) var/list/dilating = list(/decl/material/liquid/psychoactives=5,/decl/material/liquid/hallucinogenics=1,/decl/material/liquid/adrenaline=1) var/datum/reagents/ingested = H.get_ingested_reagents() - if(H.reagents.has_any_reagent(pinpoint) || ingested.has_any_reagent(pinpoint)) + if(H.reagents.has_any_reagent(pinpoint) || ingested?.has_any_reagent(pinpoint)) to_chat(user, "\The [H]'s pupils are already pinpoint and cannot narrow any more.") - else if(H.shock_stage >= 30 || H.reagents.has_any_reagent(dilating) || ingested.has_any_reagent(dilating)) + else if(H.shock_stage >= 30 || H.reagents.has_any_reagent(dilating) || ingested?.has_any_reagent(dilating)) to_chat(user, "\The [H]'s pupils narrow slightly, but are still very dilated.") else to_chat(user, "\The [H]'s pupils narrow.") diff --git a/code/game/objects/items/devices/scanners/breath.dm b/code/game/objects/items/devices/scanners/breath.dm new file mode 100644 index 00000000000..2b201add809 --- /dev/null +++ b/code/game/objects/items/devices/scanners/breath.dm @@ -0,0 +1,118 @@ +/obj/item/scanner/breath + name = "breath analyzer" + desc = "A two-in-one breathalyzer and respirometer, measuring intoxication, breath contents, and respiratory health." + icon = 'icons/obj/items/device/scanner/breath_scanner.dmi' + icon_state = "breath_analyzer" + item_state = "analyzer" + item_flags = ITEM_FLAG_NO_BLUDGEON + material = /decl/material/solid/metal/aluminium + origin_tech = "{'biotech':1}" + printout_color = "#deebff" + var/mode = 1 + +/obj/item/scanner/breath/is_valid_scan_target(atom/O) + return istype(O, /mob/living/carbon) + +/obj/item/scanner/breath/scan(atom/A, mob/user) + scan_data = breath_scan_action(A, user, src, mode) + playsound(src, 'sound/effects/fastbeep.ogg', 20) + +/proc/breath_scan_action(mob/living/carbon/target, mob/living/user, obj/scanner, var/verbose) + if (!user.check_dexterity(DEXTERITY_COMPLEX_TOOLS) || !istype(target)) + return + + . = breath_scan_results(target, verbose, user.get_skill_value(SKILL_MEDICAL)) + to_chat(user, "
") + to_chat(user, .) + to_chat(user, "
") + +/proc/breath_scan_results(var/mob/living/carbon/C, var/verbose, var/skill_level = SKILL_DEFAULT) + . = list() + var/header = list() + var/b + var/endb + var/dat = list() + + if(skill_level >= SKILL_BASIC) + header += "" + header += "" + header += "" + header += "" + header += "" + header += "" + header += "" + b = "" + endb = "" + + . += "[b]Breath sample results for \the [C]:[endb]" + + var/obj/item/organ/internal/lungs/lungs = C.get_organ(BP_LUNGS) + var/breathing = "none" + if(istype(lungs) && !(C.status_flags & FAKEDEATH)) + if(lungs.breath_fail_ratio < 0.3) + breathing = "normal" + else if(lungs.breath_fail_ratio < 1) + breathing = "shallow" + + switch(breathing) + if("none") + . += "Alert: No breathing detected." + return + if("shallow") + . += "Subject's breathing is abnormally shallow." + if("normal") + . += "Subject's breathing is normal." + + // Other general warnings. + if(skill_level >= SKILL_BASIC) + switch(C.getOxyLoss()) + if(0 to 25) + dat += "Subject oxygen levels nominal." + if(25 to 50) + dat += "Subject oxygen levels abnormal." + if(50 to INFINITY) + dat += "[b]Severe oxygen deprivation detected.[endb]" + + if(istype(lungs)) + if(lungs.is_broken()) + dat += "[b]Tension pneumothorax detected.[endb]" + else if(lungs.is_bruised()) + dat += "Collapsed lung detected." + else + dat += "Subject lung health nominal." + else + dat += "Subject lung health unknown." + + . += (skill_level < SKILL_BASIC) ? shuffle(dat) : dat + + // Reagent data. + . += "[b]Reagent scan:[endb]" + + var/print_reagent_default_message = TRUE + if (C.has_chemical_effect(CE_ALCOHOL)) + . += "Alcohol detected in subject's breath." + print_reagent_default_message = FALSE + if (C.has_chemical_effect(CE_ALCOHOL_TOXIC)) + . += "Subject is suffering from alcohol poisoning." + print_reagent_default_message = FALSE + + var/datum/reagents/inhaled = C.get_inhaled_reagents() + if(inhaled && inhaled.total_volume) + var/unknown = 0 + for(var/rtype in inhaled.reagent_volumes) + var/decl/material/R = GET_DECL(rtype) + if(R.scannable) + print_reagent_default_message = FALSE + . += "[R.name] found in subject's breath." + else + ++unknown + if(unknown) + print_reagent_default_message = FALSE + . += "Non-medical reagent[(unknown > 1)?"s":""] found in subject's breath." + + if(print_reagent_default_message) + . += "No results." + + header = jointext(header, null) + . = jointext(.,"
") + . = jointext(list(header,.),null) \ No newline at end of file diff --git a/code/game/objects/items/devices/scanners/health.dm b/code/game/objects/items/devices/scanners/health.dm index 8837a258951..7c151143881 100644 --- a/code/game/objects/items/devices/scanners/health.dm +++ b/code/game/objects/items/devices/scanners/health.dm @@ -296,6 +296,20 @@ print_reagent_default_message = FALSE . += "Non-medical reagent[(unknown > 1)?"s":""] found in subject's stomach." + var/datum/reagents/inhaled = H.get_inhaled_reagents() + if(inhaled && inhaled.total_volume) + var/unknown = 0 + for(var/rtype in inhaled.reagent_volumes) + var/decl/material/R = GET_DECL(rtype) + if(R.scannable) + print_reagent_default_message = FALSE + . += "[R.name] found in subject's lungs." + else + ++unknown + if(unknown) + print_reagent_default_message = FALSE + . += "Non-medical reagent[(unknown > 1)?"s":""] found in subject's lungs." + if(length(H.chem_doses)) var/list/chemtraces = list() for(var/T in H.chem_doses) diff --git a/code/game/objects/items/weapons/ecigs.dm b/code/game/objects/items/weapons/ecigs.dm index 084e04365a1..6376f551264 100644 --- a/code/game/objects/items/weapons/ecigs.dm +++ b/code/game/objects/items/weapons/ecigs.dm @@ -115,7 +115,7 @@ Deactivate() to_chat(C,"\The [src]'s power meter flashes a low battery warning and shuts down.") return - ec_cartridge.reagents.trans_to_mob(C, REM, CHEM_INGEST, 0.4) // Most of it is not inhaled... balance reasons. + ec_cartridge.reagents.trans_to_mob(C, REM, CHEM_INHALE, 0.4) // Most of it is not inhaled... balance reasons. /obj/item/clothing/mask/smokable/ecig/on_update_icon() ..() diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 7b1daf03593..3d9cc02ad7a 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -152,6 +152,7 @@ icon = 'icons/clothing/belt/medical.dmi' can_hold = list( /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/chems/dropper, /obj/item/chems/glass/beaker, /obj/item/chems/glass/bottle, @@ -166,6 +167,7 @@ /obj/item/clothing/head/surgery, /obj/item/clothing/gloves/latex, /obj/item/chems/hypospray, + /obj/item/chems/inhaler, /obj/item/clothing/glasses/hud/health, /obj/item/crowbar, /obj/item/flashlight, diff --git a/code/game/objects/items/weapons/storage/med_pouch.dm b/code/game/objects/items/weapons/storage/med_pouch.dm index fd48e10d392..2e96d802dc7 100644 --- a/code/game/objects/items/weapons/storage/med_pouch.dm +++ b/code/game/objects/items/weapons/storage/med_pouch.dm @@ -33,6 +33,9 @@ Single Use Emergency Pouches for(var/obj/item/chems/hypospray/autoinjector/A in contents) A.band_color = color A.update_icon() + for(var/obj/item/chems/inhaler/I in contents) + I.band_color = color + I.update_icon() /obj/item/storage/med_pouch/on_update_icon() overlays.Cut() @@ -113,7 +116,7 @@ Single Use Emergency Pouches startswith = list( /obj/item/chems/hypospray/autoinjector/pouch_auto/stabilizer, - /obj/item/chems/hypospray/autoinjector/pouch_auto/oxy_meds, + /obj/item/chems/inhaler/pouch_auto/oxy_meds, /obj/item/chems/hypospray/autoinjector/pouch_auto/adrenaline, /obj/item/chems/pill/pouch_pill/stabilizer, /obj/item/chems/pill/pouch_pill/oxy_meds @@ -165,9 +168,32 @@ Single Use Emergency Pouches 6) Stay in place once they respond.\ "} +/obj/item/storage/med_pouch/overdose + name = "overdose treatment pouch" + injury_type = "overdose" + color = COLOR_PALE_BLUE_GRAY + + startswith = list( + /obj/item/chems/hypospray/autoinjector/pouch_auto/stabilizer, + /obj/item/chems/inhaler/pouch_auto/oxy_meds, + /obj/item/chems/inhaler/pouch_auto/detoxifier, + /obj/item/chems/hypospray/autoinjector/pouch_auto/adrenaline + ) + instructions = {" + 1) Tear open the emergency medical pack using the easy open tab at the top.\n\ + \t2) Carefully remove all items from the pouch and discard the pouch.\n\ + \t3) Apply all autoinjectors and autoinhalers to the injured party. DO NOT give the injured party any pills, foods, or liquids.\n\ + \t5) Contact the medical team with your location.\n\ + \t6) Find a source of oxygen if possible.\n\ + \t7) Update the medical team with your new location.\n\ + 8) Stay in place once they respond.\ + "} + +// Pills + /obj/item/chems/pill/pouch_pill name = "emergency pill" - desc = "An emergency pill from an emergency medical pouch" + desc = "An emergency pill from an emergency medical pouch." icon_state = "pill2" var/decl/material/chem_type var/chem_amount = 15 @@ -195,9 +221,11 @@ Single Use Emergency Pouches var/decl/material/reagent = GET_DECL(chem_type) SetName("emergency [reagent.liquid_name] pill ([reagents.total_volume]u)") +// Injectors + /obj/item/chems/hypospray/autoinjector/pouch_auto name = "emergency autoinjector" - desc = "An emergency autoinjector from an emergency medical pouch" + desc = "An emergency autoinjector from an emergency medical pouch." /obj/item/chems/hypospray/autoinjector/pouch_auto/stabilizer name = "emergency stabilizer autoinjector" @@ -223,3 +251,17 @@ Single Use Emergency Pouches /obj/item/chems/hypospray/autoinjector/pouch_auto/nanoblood name = "emergency nanoblood autoinjector" starts_with = list(/decl/material/liquid/nanoblood = 5) + +// Inhalers + +/obj/item/chems/inhaler/pouch_auto + name = "emergency autoinhaler" + desc = "An emergency autoinhaler from an emergency medical pouch." + +/obj/item/chems/inhaler/pouch_auto/oxy_meds + name = "emergency oxygel autoinjector" + starts_with = list(/decl/material/liquid/oxy_meds = 5) + +/obj/item/chems/inhaler/pouch_auto/detoxifier + name = "emergency detoxifier autoinjector" + starts_with = list(/decl/material/liquid/detoxifier = 5) diff --git a/code/game/objects/random/random.dm b/code/game/objects/random/random.dm index 67eb6906c95..c6f4e8812d8 100644 --- a/code/game/objects/random/random.dm +++ b/code/game/objects/random/random.dm @@ -172,13 +172,15 @@ /obj/item/stack/medical/advanced/ointment = 2, /obj/item/stack/medical/splint = 1, /obj/item/chems/hypospray/autoinjector = 3, + /obj/item/chems/inhaler = 3, /obj/item/storage/pill_bottle/burn_meds = 2, /obj/item/storage/pill_bottle/antitox = 2, /obj/item/storage/med_pouch/trauma = 2, /obj/item/storage/med_pouch/burn = 2, /obj/item/storage/med_pouch/toxin = 2, /obj/item/storage/med_pouch/radiation = 2, - /obj/item/storage/med_pouch/oxyloss = 2) + /obj/item/storage/med_pouch/oxyloss = 2, + /obj/item/storage/med_pouch/overdose = 2) /obj/random/firstaid name = "Random First Aid Kit" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm index 2ec2efb2655..9818876085b 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -75,6 +75,7 @@ /obj/item/tank/emergency/oxygen/engi, /obj/item/clothing/glasses/hud/health, /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/radio/off, /obj/random/medical, /obj/item/crowbar, @@ -127,7 +128,7 @@ wall_mounted = 1 storage_types = CLOSET_STORAGE_ITEMS req_access = list(access_medical_equip) - + /obj/structure/closet/secure_closet/medical_wall/Initialize() . = ..() tool_interaction_flags &= ~TOOL_INTERACTION_ANCHOR @@ -179,6 +180,7 @@ /obj/item/clothing/suit/storage/toggle/labcoat/virologist, /obj/item/clothing/mask/surgical, /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/clothing/glasses/hud/health ) diff --git a/code/game/objects/structures/crates_lockers/med_crate.dm b/code/game/objects/structures/crates_lockers/med_crate.dm index 1012321c1e3..02f9a8fe2c4 100644 --- a/code/game/objects/structures/crates_lockers/med_crate.dm +++ b/code/game/objects/structures/crates_lockers/med_crate.dm @@ -33,7 +33,7 @@ /obj/structure/closet/crate/med_crate/oxyloss/WillContain() return list( - /obj/item/scanner/health = 2, + /obj/item/scanner/breath = 2, /obj/item/storage/pill_bottle/oxygen = 2, /obj/item/storage/pill_bottle/adrenaline ) diff --git a/code/modules/clothing/masks/smokable.dm b/code/modules/clothing/masks/smokable.dm index 252abdb5ed8..5dbac1dda59 100644 --- a/code/modules/clothing/masks/smokable.dm +++ b/code/modules/clothing/masks/smokable.dm @@ -57,7 +57,7 @@ var/mob/living/carbon/human/C = loc smoke_loc = C.loc if ((src == C.wear_mask || manual) && C.check_has_mouth()) // if it's in the human/monkey mouth, transfer reagents to the mob - reagents.trans_to_mob(C, smoke_amount * amount, CHEM_INGEST, 0.2) + reagents.trans_to_mob(C, smoke_amount * amount, CHEM_INHALE, 0.2) add_trace_DNA(C) else // else just remove some of the reagents reagents.remove_any(smoke_amount * amount) diff --git a/code/modules/clothing/spacesuits/rig/suits/combat.dm b/code/modules/clothing/spacesuits/rig/suits/combat.dm index b2a5bf12b5a..5b34663debc 100644 --- a/code/modules/clothing/spacesuits/rig/suits/combat.dm +++ b/code/modules/clothing/spacesuits/rig/suits/combat.dm @@ -36,6 +36,7 @@ /obj/item/gun, /obj/item/storage/firstaid, /obj/item/chems/hypospray, + /obj/item/chems/inhaler, /obj/item/roller, /obj/item/suit_cooling_unit ) @@ -108,6 +109,7 @@ /obj/item/gun, /obj/item/storage/firstaid, /obj/item/chems/hypospray, + /obj/item/chems/inhaler, /obj/item/roller, /obj/item/suit_cooling_unit ) diff --git a/code/modules/clothing/spacesuits/rig/suits/station.dm b/code/modules/clothing/spacesuits/rig/suits/station.dm index 696efd244fc..830be840623 100644 --- a/code/modules/clothing/spacesuits/rig/suits/station.dm +++ b/code/modules/clothing/spacesuits/rig/suits/station.dm @@ -206,7 +206,7 @@ boots = /obj/item/clothing/shoes/magboots/rig/hazmat gloves = /obj/item/clothing/gloves/rig/hazmat - allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/stack/flag,/obj/item/storage/excavation,/obj/item/pickaxe,/obj/item/scanner/health,/obj/item/measuring_tape,/obj/item/ano_scanner,/obj/item/depth_scanner,/obj/item/core_sampler,/obj/item/gps,/obj/item/pinpointer/radio,/obj/item/radio/beacon,/obj/item/pickaxe/xeno,/obj/item/storage/bag/fossils) + allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/stack/flag,/obj/item/storage/excavation,/obj/item/pickaxe,/obj/item/scanner/health,/obj/item/scanner/breath,/obj/item/measuring_tape,/obj/item/ano_scanner,/obj/item/depth_scanner,/obj/item/core_sampler,/obj/item/gps,/obj/item/pinpointer/radio,/obj/item/radio/beacon,/obj/item/pickaxe/xeno,/obj/item/storage/bag/fossils) anomaly_shielding = 1 req_access = list(access_tox) @@ -252,7 +252,7 @@ boots = /obj/item/clothing/shoes/magboots/rig/medical gloves = /obj/item/clothing/gloves/rig/medical - allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/storage/firstaid,/obj/item/scanner/health,/obj/item/stack/medical,/obj/item/roller,/obj/item/auto_cpr,/obj/item/inflatable_dispenser) + allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/storage/firstaid,/obj/item/scanner/health,/obj/item/scanner/breath,/obj/item/stack/medical,/obj/item/roller,/obj/item/auto_cpr,/obj/item/inflatable_dispenser) req_access = list(access_medical_equip) diff --git a/code/modules/clothing/spacesuits/void/station.dm b/code/modules/clothing/spacesuits/void/station.dm index 99d7fd41fe7..c9c4df89264 100644 --- a/code/modules/clothing/spacesuits/void/station.dm +++ b/code/modules/clothing/spacesuits/void/station.dm @@ -90,7 +90,7 @@ name = "medical voidsuit" desc = "A sterile voidsuit with minor radiation shielding and a suite of self-cleaning technology. Standard issue in most orbital medical facilities." icon = 'icons/clothing/spacesuit/void/medical/suit.dmi' - allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/storage/firstaid,/obj/item/scanner/health,/obj/item/stack/medical) + allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/storage/firstaid,/obj/item/scanner/health,/obj/item/scanner/breath,/obj/item/stack/medical) armor = list( melee = ARMOR_MELEE_KNIVES, laser = ARMOR_LASER_MINOR, @@ -265,7 +265,7 @@ name = "streamlined medical voidsuit" desc = "A more recent and stylish model of Vey-Med voidsuit, with a minor upgrade to radiation shielding." icon = 'icons/clothing/spacesuit/void/medical_alt/suit.dmi' - allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/storage/firstaid,/obj/item/scanner/health,/obj/item/stack/medical) + allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/storage/firstaid,/obj/item/scanner/health,/obj/item/scanner/breath,/obj/item/stack/medical) armor = list( melee = ARMOR_MELEE_KNIVES, laser = ARMOR_LASER_MINOR, diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm index 7674b586f4b..c81e6de31c2 100644 --- a/code/modules/clothing/suits/bio.dm +++ b/code/modules/clothing/suits/bio.dm @@ -5,7 +5,7 @@ desc = "A hood that protects the head and face from biological comtaminants." permeability_coefficient = 0 armor = list( - bio = ARMOR_BIO_SHIELDED, + bio = ARMOR_BIO_SHIELDED, rad = ARMOR_RAD_MINOR ) flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|BLOCKHAIR @@ -26,9 +26,9 @@ gas_transfer_coefficient = 0 permeability_coefficient = 0 body_parts_covered = SLOT_UPPER_BODY|SLOT_LOWER_BODY|SLOT_LEGS|SLOT_FEET|SLOT_ARMS|SLOT_HANDS - allowed = list(/obj/item/tank/emergency,/obj/item/pen,/obj/item/flashlight/pen,/obj/item/scanner/health,/obj/item/ano_scanner,/obj/item/clothing/head/bio_hood,/obj/item/clothing/mask/gas) + allowed = list(/obj/item/tank/emergency,/obj/item/pen,/obj/item/flashlight/pen,/obj/item/scanner/health,/obj/item/scanner/breath,/obj/item/ano_scanner,/obj/item/clothing/head/bio_hood,/obj/item/clothing/mask/gas) armor = list( - bio = ARMOR_BIO_SHIELDED, + bio = ARMOR_BIO_SHIELDED, rad = ARMOR_RAD_MINOR ) flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm index 5bff1d39d43..80e0f40e62b 100644 --- a/code/modules/clothing/suits/jobs.dm +++ b/code/modules/clothing/suits/jobs.dm @@ -172,8 +172,10 @@ /obj/item/stack/medical, /obj/item/chems/dropper, /obj/item/chems/hypospray, + /obj/item/chems/inhaler, /obj/item/chems/syringe, /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/flashlight, /obj/item/radio, /obj/item/tank/emergency, @@ -195,8 +197,10 @@ /obj/item/stack/medical, /obj/item/chems/dropper, /obj/item/chems/hypospray, + /obj/item/chems/inhaler, /obj/item/chems/syringe, - /obj/item/scanner/health, + /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/flashlight, /obj/item/radio, /obj/item/tank/emergency, @@ -215,8 +219,10 @@ /obj/item/stack/medical, /obj/item/chems/dropper, /obj/item/chems/hypospray, + /obj/item/chems/inhaler, /obj/item/chems/syringe, /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/flashlight, /obj/item/radio, /obj/item/tank/emergency, diff --git a/code/modules/clothing/suits/labcoat.dm b/code/modules/clothing/suits/labcoat.dm index d7b0bca94c3..6467b1f587d 100644 --- a/code/modules/clothing/suits/labcoat.dm +++ b/code/modules/clothing/suits/labcoat.dm @@ -4,7 +4,21 @@ icon = 'icons/clothing/suit/labcoat/default.dmi' blood_overlay_type = "coat" body_parts_covered = SLOT_UPPER_BODY|SLOT_ARMS - allowed = list(/obj/item/scanner/gas,/obj/item/stack/medical,/obj/item/chems/dropper,/obj/item/chems/syringe,/obj/item/chems/hypospray,/obj/item/scanner/health,/obj/item/flashlight/pen,/obj/item/chems/glass/bottle,/obj/item/chems/glass/beaker,/obj/item/chems/pill,/obj/item/storage/pill_bottle,/obj/item/paper) + allowed = list( + /obj/item/scanner/gas, + /obj/item/stack/medical, + /obj/item/chems/dropper, + /obj/item/chems/syringe, + /obj/item/chems/hypospray, + /obj/item/chems/inhaler, + /obj/item/scanner/health, + /obj/item/scanner/breath, + /obj/item/flashlight/pen, + /obj/item/chems/glass/bottle, + /obj/item/chems/glass/beaker, + /obj/item/chems/pill, + /obj/item/storage/pill_bottle, + /obj/item/paper) armor = list( bio = ARMOR_BIO_RESISTANT ) @@ -60,4 +74,3 @@ body_parts_covered = SLOT_UPPER_BODY|SLOT_LOWER_BODY|SLOT_LEGS|SLOT_ARMS markings_color = COLOR_BOTTLE_GREEN markings_icon = "_marking" - \ No newline at end of file diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm index ba568a06069..874c943ca23 100644 --- a/code/modules/clothing/suits/utility.dm +++ b/code/modules/clothing/suits/utility.dm @@ -19,7 +19,7 @@ body_parts_covered = SLOT_UPPER_BODY | SLOT_LOWER_BODY| SLOT_ARMS armor = list(laser = ARMOR_LASER_MINOR, energy = ARMOR_ENERGY_MINOR, bomb = ARMOR_BOMB_MINOR) allowed = list(/obj/item/flashlight,/obj/item/tank/emergency,/obj/item/extinguisher,/obj/item/clothing/head/hardhat) - + gas_transfer_coefficient = 0.90 permeability_coefficient = 0.50 @@ -45,10 +45,10 @@ desc = "Use in case of bomb." icon = 'icons/clothing/head/bombsuit.dmi' armor = list( - melee = ARMOR_MELEE_VERY_HIGH, - bullet = ARMOR_BALLISTIC_MINOR, - laser = ARMOR_LASER_SMALL, - energy = ARMOR_ENERGY_RESISTANT, + melee = ARMOR_MELEE_VERY_HIGH, + bullet = ARMOR_BALLISTIC_MINOR, + laser = ARMOR_LASER_SMALL, + energy = ARMOR_ENERGY_RESISTANT, bomb = ARMOR_BOMB_SHIELDED ) flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|BLOCKHAIR @@ -63,10 +63,10 @@ gas_transfer_coefficient = 0.01 permeability_coefficient = 0.01 armor = list( - melee = ARMOR_MELEE_VERY_HIGH, - bullet = ARMOR_BALLISTIC_MINOR, - laser = ARMOR_LASER_SMALL, - energy = ARMOR_ENERGY_RESISTANT, + melee = ARMOR_MELEE_VERY_HIGH, + bullet = ARMOR_BALLISTIC_MINOR, + laser = ARMOR_LASER_SMALL, + energy = ARMOR_ENERGY_RESISTANT, bomb = ARMOR_BOMB_SHIELDED ) flags_inv = HIDEJUMPSUIT|HIDETAIL @@ -97,7 +97,7 @@ flags_inv = BLOCKHAIR body_parts_covered = SLOT_HEAD|SLOT_FACE|SLOT_EYES armor = list( - bio = ARMOR_BIO_RESISTANT, + bio = ARMOR_BIO_RESISTANT, rad = ARMOR_RAD_SHIELDED ) matter = list( @@ -117,7 +117,7 @@ body_parts_covered = SLOT_UPPER_BODY|SLOT_LOWER_BODY|SLOT_LEGS|SLOT_ARMS|SLOT_HANDS|SLOT_FEET allowed = list(/obj/item/flashlight,/obj/item/tank/emergency,/obj/item/clothing/head/radiation,/obj/item/clothing/mask/gas,/obj/item/geiger) armor = list( - bio = ARMOR_BIO_RESISTANT, + bio = ARMOR_BIO_RESISTANT, rad = ARMOR_RAD_SHIELDED ) flags_inv = HIDEJUMPSUIT|HIDETAIL|HIDEGLOVES|HIDESHOES @@ -141,7 +141,7 @@ icon = 'icons/clothing/head/chem_hood.dmi' permeability_coefficient = 0 armor = list( - bio = ARMOR_BIO_RESISTANT, + bio = ARMOR_BIO_RESISTANT, rad = ARMOR_RAD_MINOR ) flags_inv = HIDEEARS|HIDEEYES|BLOCKHAIR @@ -162,9 +162,9 @@ gas_transfer_coefficient = 0 permeability_coefficient = 0 body_parts_covered = SLOT_UPPER_BODY|SLOT_LOWER_BODY|SLOT_LEGS|SLOT_FEET|SLOT_ARMS|SLOT_HANDS - allowed = list(/obj/item/tank/emergency,/obj/item/pen,/obj/item/flashlight/pen,/obj/item/scanner/health,/obj/item/ano_scanner,/obj/item/clothing/head/chem_hood,/obj/item/clothing/mask/gas,/obj/item/geiger) + allowed = list(/obj/item/tank/emergency,/obj/item/pen,/obj/item/flashlight/pen,/obj/item/scanner/health,/obj/item/scanner/breath,/obj/item/ano_scanner,/obj/item/clothing/head/chem_hood,/obj/item/clothing/mask/gas,/obj/item/geiger) armor = list( - bio = ARMOR_BIO_RESISTANT, + bio = ARMOR_BIO_RESISTANT, rad = ARMOR_RAD_MINOR ) flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL diff --git a/code/modules/clothing/under/accessories/storage.dm b/code/modules/clothing/under/accessories/storage.dm index 25177457d7e..7a2c021a1f7 100644 --- a/code/modules/clothing/under/accessories/storage.dm +++ b/code/modules/clothing/under/accessories/storage.dm @@ -140,6 +140,7 @@ /obj/item/chems/syringe, /obj/item/chems/hypospray, /obj/item/chems/hypospray/autoinjector, + /obj/item/chems/inhaler, /obj/item/syringe_cartridge, /obj/item/plastique, /obj/item/clothing/mask/smokable, diff --git a/code/modules/detectivework/tools/rag.dm b/code/modules/detectivework/tools/rag.dm index 81afb62c415..68436d10dd6 100644 --- a/code/modules/detectivework/tools/rag.dm +++ b/code/modules/detectivework/tools/rag.dm @@ -126,7 +126,8 @@ SPAN_DANGER("You smother \the [target] with \the [src]!") ) //it's inhaled, so... maybe CHEM_INJECT doesn't make a whole lot of sense but it's the best we can do for now - var/trans_amt = reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_INJECT) + // ^ HA HA HA + var/trans_amt = reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_INHALE) var/contained_reagents = reagents.get_reagents() admin_inject_log(user, M, src, contained_reagents, trans_amt) update_name() diff --git a/code/modules/emotes/definitions/audible.dm b/code/modules/emotes/definitions/audible.dm index c69bfb83dec..3a168083087 100644 --- a/code/modules/emotes/definitions/audible.dm +++ b/code/modules/emotes/definitions/audible.dm @@ -96,8 +96,19 @@ /decl/emote/audible/cough key = "cough" - emote_message_3p = "USER coughs!" - conscious = 0 + +/decl/emote/audible/cough/check_user(var/mob/living/carbon/user) + . = ..() + if(!.) + return . + var/obj/item/organ/internal/lungs/lung = user.get_organ(BP_LUNGS) + . = lung?.active_breathing && !user.isSynthetic() + +/decl/emote/audible/cough/do_emote(var/mob/living/carbon/user, var/extra_params) + if(!istype(user)) + to_chat(user, SPAN_WARNING("You are unable to vomit.")) + return + user.cough(deliberate = TRUE) /decl/emote/audible/cry key = "cry" diff --git a/code/modules/materials/_materials.dm b/code/modules/materials/_materials.dm index 80ad930d04f..35e32760888 100644 --- a/code/modules/materials/_materials.dm +++ b/code/modules/materials/_materials.dm @@ -83,6 +83,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/gas_overlay) var/default_solid_form = /obj/item/stack/material/sheet var/affect_blood_on_ingest = TRUE + var/affect_blood_on_inhale = TRUE var/narcosis = 0 // Not a great word for it. Constant for causing mild confusion when ingested. var/toxicity = 0 // Organ damage from ingestion. @@ -209,6 +210,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/gas_overlay) var/metabolism = REM // This would be 0.2 normally var/ingest_met = 0 var/touch_met = 0 + var/inhale_met = 0 var/overdose = 0 var/scannable = 0 // Shows up on health analyzers. var/color = COLOR_BEIGE @@ -522,6 +524,8 @@ INITIALIZE_IMMEDIATE(/obj/effect/gas_overlay) removed = ingest_met if(touch_met && (location == CHEM_TOUCH)) removed = touch_met + if(inhale_met && (location == CHEM_INHALE)) + removed = inhale_met removed = M.get_adjusted_metabolism(removed) //adjust effective amounts - removed, dose, and max_dose - for mob size @@ -539,6 +543,8 @@ INITIALIZE_IMMEDIATE(/obj/effect/gas_overlay) affect_ingest(M, alien, effective, holder) if(CHEM_TOUCH) affect_touch(M, alien, effective, holder) + if(CHEM_INHALE) + affect_inhale(M, alien, effective, holder) holder.remove_reagent(type, removed) /decl/material/proc/affect_blood(var/mob/living/M, var/alien, var/removed, var/datum/reagents/holder) @@ -579,6 +585,10 @@ INITIALIZE_IMMEDIATE(/obj/effect/gas_overlay) if(affect_blood_on_ingest) affect_blood(M, alien, removed * 0.5, holder) +/decl/material/proc/affect_inhale(var/mob/living/M, var/alien, var/removed, var/datum/reagents/holder) + if(affect_blood_on_inhale) + affect_blood(M, alien, removed * 0.5, holder) + /decl/material/proc/affect_touch(var/mob/living/M, var/alien, var/removed, var/datum/reagents/holder) if(!istype(M)) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 0b9e25b1955..7de32809f69 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -42,18 +42,18 @@ . = ..() /mob/living/carbon/human/get_ingested_reagents() - if(should_have_organ(BP_STOMACH)) - var/obj/item/organ/internal/stomach/stomach = get_organ(BP_STOMACH) - if(stomach) - return stomach.ingested - return get_contact_reagents() // Kind of a shitty hack, but makes more sense to me than digesting them. + if(!should_have_organ(BP_STOMACH)) + return + var/obj/item/organ/internal/stomach/stomach = get_organ(BP_STOMACH) + return stomach?.ingested /mob/living/carbon/human/metabolize_ingested_reagents() - if(should_have_organ(BP_STOMACH)) - var/obj/item/organ/internal/stomach/stomach = get_organ(BP_STOMACH) - if(stomach) - stomach.metabolize() - return stomach?.ingested + if(!should_have_organ(BP_STOMACH)) + return + var/obj/item/organ/internal/stomach/stomach = get_organ(BP_STOMACH) + if(stomach) + stomach.metabolize() + return stomach.ingested /mob/living/carbon/human/get_fullness() if(!should_have_organ(BP_STOMACH)) @@ -63,6 +63,20 @@ return nutrition + (stomach.ingested?.total_volume * 10) return 0 //Always hungry, but you can't actually eat. :( +/mob/living/carbon/human/get_inhaled_reagents() + if(!should_have_organ(BP_LUNGS)) + return + var/obj/item/organ/internal/lungs/lungs = get_organ(BP_LUNGS) + return lungs?.inhaled + +/mob/living/carbon/human/metabolize_inhaled_reagents() + if(!should_have_organ(BP_LUNGS)) + return + var/obj/item/organ/internal/lungs/lungs = get_organ(BP_LUNGS) + if(lungs) + lungs.metabolize() + return lungs.inhaled + /mob/living/carbon/human/Stat() . = ..() if(statpanel("Status")) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 90b05d0b315..68f11b302c1 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -202,8 +202,7 @@ if(stat != DEAD) if ((disabilities & COUGHING) && prob(5) && GET_STATUS(src, STAT_PARA) <= 1) drop_held_items() - spawn(0) - emote("cough") + cough() /mob/living/carbon/human/handle_mutations_and_radiation() if(getFireLoss()) @@ -267,7 +266,7 @@ var/list/limbs = get_external_organs() if(!isSynthetic() && LAZYLEN(limbs)) var/obj/item/organ/external/O = pick(limbs) - if(istype(O)) + if(istype(O)) O.add_autopsy_data("Radiation Poisoning", damage) /** breathing **/ diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 2c69eaebb8b..f0e4bc8186f 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -56,15 +56,16 @@ var/datum/reagents/metabolism/touching_reagents = metabolize_touching_reagents() var/datum/reagents/metabolism/bloodstr_reagents = metabolize_injected_reagents() var/datum/reagents/metabolism/ingested_reagents = metabolize_ingested_reagents() + var/datum/reagents/metabolism/inhaled_reagents = metabolize_inhaled_reagents() // Update chem dosage. // TODO: refactor chem dosage above isSynthetic() and GODMODE checks. if(length(chem_doses)) for(var/T in chem_doses) - if(bloodstr_reagents?.has_reagent(T) || ingested_reagents?.has_reagent(T) || touching_reagents?.has_reagent(T)) + if(bloodstr_reagents?.has_reagent(T) || ingested_reagents?.has_reagent(T) || touching_reagents?.has_reagent(T) || inhaled_reagents?.has_reagent(T)) continue - var/decl/material/R = T - var/dose = LAZYACCESS(chem_doses, T) - initial(R.metabolism)*2 + var/decl/material/R = GET_DECL(T) + var/dose = LAZYACCESS(chem_doses, T) - R.metabolism*2 LAZYSET(chem_doses, T, dose) if(LAZYACCESS(chem_doses, T) <= 0) LAZYREMOVE(chem_doses, T) @@ -86,19 +87,25 @@ if(istype(touching_reagents)) touching_reagents.metabolize() return touching_reagents - + /mob/living/proc/metabolize_injected_reagents() var/datum/reagents/metabolism/injected_reagents = get_injected_reagents() if(istype(injected_reagents)) injected_reagents.metabolize() return injected_reagents - + /mob/living/proc/metabolize_ingested_reagents() var/datum/reagents/metabolism/ingested_reagents = get_ingested_reagents() if(istype(ingested_reagents)) ingested_reagents.metabolize() return ingested_reagents +/mob/living/proc/metabolize_inhaled_reagents() + var/datum/reagents/metabolism/inhaled_reagents = get_inhaled_reagents() + if(istype(inhaled_reagents)) + inhaled_reagents.metabolize() + return inhaled_reagents + /mob/living/proc/handle_random_events() return @@ -213,7 +220,7 @@ else if(eyeobj) if(eyeobj.owner != src) reset_view(null) - else if(z_eye) + else if(z_eye) return else if(client && !client.adminobs) reset_view(null) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 845a45ab0e3..f411d82d5aa 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -412,6 +412,9 @@ default behaviour is: var/datum/reagents/ingested_reagents = get_ingested_reagents() if(ingested_reagents) ingested_reagents.clear_reagents() + var/datum/reagents/inhaled_reagents = get_inhaled_reagents() + if(inhaled_reagents) + inhaled_reagents.clear_reagents() if(reagents) reagents.clear_reagents() @@ -804,9 +807,17 @@ default behaviour is: if(!lying && T.above && !T.above.is_flooded() && T.above.CanZPass(src, UP) && can_overcome_gravity()) return FALSE if(prob(5)) + var/datum/reagents/metabolism/inhaled = get_inhaled_reagents() + var/datum/reagents/metabolism/ingested = get_ingested_reagents() var/obj/effect/fluid/F = locate() in loc to_chat(src, SPAN_DANGER("You choke and splutter as you inhale [(F?.reagents && F.reagents.get_primary_reagent_name()) || "liquid"]!")) - F?.reagents?.trans_to_holder(get_ingested_reagents(), min(F.reagents.total_volume, rand(2,5))) + var/inhale_amount = 0 + if(inhaled) + inhale_amount = rand(2,5) + F?.reagents?.trans_to_holder(inhaled, min(F.reagents.total_volume, inhale_amount)) + if(ingested) + var/ingest_amount = 5 - inhale_amount + F?.reagents?.trans_to_holder(ingested, min(F.reagents.total_volume, ingest_amount)) T.show_bubbles() return TRUE // Presumably chemical smoke can't be breathed while you're underwater. @@ -937,6 +948,9 @@ default behaviour is: /mob/living/proc/get_injected_reagents() return reagents +/mob/living/proc/get_inhaled_reagents() + return reagents + /mob/living/proc/get_adjusted_metabolism(metabolism) return metabolism diff --git a/code/modules/mob/living/silicon/robot/flying/module_flying_emergency.dm b/code/modules/mob/living/silicon/robot/flying/module_flying_emergency.dm index 79905caa915..0690509ec54 100644 --- a/code/modules/mob/living/silicon/robot/flying/module_flying_emergency.dm +++ b/code/modules/mob/living/silicon/robot/flying/module_flying_emergency.dm @@ -14,6 +14,7 @@ /obj/item/flash, /obj/item/borg/sight/hud/med, /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/scanner/reagent/adv, /obj/item/chems/borghypo/crisis, /obj/item/extinguisher/mini, diff --git a/code/modules/mob/living/silicon/robot/modules/module_medical.dm b/code/modules/mob/living/silicon/robot/modules/module_medical.dm index 8301a2f3561..ab8af1208a8 100644 --- a/code/modules/mob/living/silicon/robot/modules/module_medical.dm +++ b/code/modules/mob/living/silicon/robot/modules/module_medical.dm @@ -28,6 +28,7 @@ /obj/item/flash, /obj/item/borg/sight/hud/med, /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/chems/borghypo/surgeon, /obj/item/incision_manager, /obj/item/hemostat, @@ -102,6 +103,7 @@ /obj/item/flash, /obj/item/borg/sight/hud/med, /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/scanner/reagent/adv, /obj/item/robot_rack/body_bag, /obj/item/chems/borghypo/crisis, diff --git a/code/modules/organs/ailments/ailments_medical.dm b/code/modules/organs/ailments/ailments_medical.dm index 16571b88324..cca4bfcb13f 100644 --- a/code/modules/organs/ailments/ailments_medical.dm +++ b/code/modules/organs/ailments/ailments_medical.dm @@ -91,8 +91,7 @@ return FALSE /datum/ailment/coughing/on_ailment_event() - if(organ.owner.usable_emotes["cough"]) - organ.owner.emote("cough") + organ.owner.cough() organ.owner.setClickCooldown(3) /datum/ailment/sore_joint diff --git a/code/modules/organs/internal/lungs.dm b/code/modules/organs/internal/lungs.dm index 5d034c441ec..2d37cd64c0c 100644 --- a/code/modules/organs/internal/lungs.dm +++ b/code/modules/organs/internal/lungs.dm @@ -31,8 +31,33 @@ var/last_successful_breath var/breath_fail_ratio // How badly they failed a breath. Higher is worse. + var/datum/reagents/metabolism/inhaled + +/obj/item/organ/internal/lungs/Destroy() + QDEL_NULL(inhaled) + . = ..() + +/obj/item/organ/internal/lungs/setup_reagents() + . = ..() + if(!inhaled) + inhaled = new/datum/reagents/metabolism(240, (owner || src), CHEM_INHALE) + if(!inhaled.my_atom) + inhaled.my_atom = src + +/obj/item/organ/internal/lungs/do_install(mob/living/carbon/human/target, obj/item/organ/external/affected, in_place) + if(!(. = ..())) + return + inhaled.my_atom = owner + inhaled.parent = owner + +/obj/item/organ/internal/lungs/do_uninstall(in_place, detach, ignore_children) + . = ..() + if(inhaled) + inhaled.my_atom = src + inhaled.parent = null + /obj/item/organ/internal/lungs/proc/can_drown() - return (is_broken() || !has_gills) + return !has_gills || !is_usable() /obj/item/organ/internal/lungs/proc/remove_oxygen_deprivation(var/amount) var/last_suffocation = oxygen_deprivation @@ -54,6 +79,12 @@ . = ..() sync_breath_types() +// This call needs to be split out to make sure that all the ingested things are metabolised +// before the process call is made on any of the other organs +/obj/item/organ/internal/lungs/proc/metabolize() + if(is_usable()) + inhaled.metabolize() + /** * Set these lungs' breath types based on the lungs' species */ @@ -71,6 +102,7 @@ poison_types = list(/decl/material/gas/chlorine = TRUE) exhale_type = /decl/material/gas/carbon_dioxide + /obj/item/organ/internal/lungs/Process() ..() if(!owner) @@ -78,7 +110,7 @@ if (germ_level > INFECTION_LEVEL_ONE && active_breathing) if(prob(5)) - owner.emote("cough") //respitory tract infection + owner.cough() //respitory tract infection if(is_bruised() && !owner.is_asystole()) if(prob(2)) @@ -155,7 +187,7 @@ var/breatheffect = GET_CHEMICAL_EFFECT(owner, CE_BREATHLOSS) if(!forced && breatheffect && !GET_CHEMICAL_EFFECT(owner, CE_STABLE)) //opiates are bad mmkay safe_pressure_min *= 1 + breatheffect - + if(owner.lying) safe_pressure_min *= 0.8 @@ -204,9 +236,9 @@ continue // Little bit of sanity so we aren't trying to add 0.0000000001 units of CO2, and so we don't end up with 99999 units of CO2. var/reagent_amount = breath.gas[gasname] * REAGENT_UNITS_PER_GAS_MOLE * ratio - if(reagent_amount < 0.05) + if(reagent_amount < MINIMUM_CHEMICAL_VOLUME) continue - owner.reagents.add_reagent(gasname, reagent_amount) + inhaled.add_reagent(gasname, reagent_amount) breath.adjust_gas(gasname, -breath.gas[gasname], update = 0) //update after // Moved after reagent injection so we don't instantly poison ourselves with CO2 or whatever. @@ -335,3 +367,26 @@ /obj/item/organ/internal/lungs/gills name = "lungs and gills" has_gills = TRUE + +/mob/living/carbon/var/lastcough +/mob/living/carbon/proc/cough(var/deliberate = FALSE) + var/obj/item/organ/internal/lungs/lung = get_organ(BP_LUNGS) + if(!lung || !lung.active_breathing || isSynthetic() || stat == DEAD || (deliberate && lastcough + 3 SECONDS > world.time)) + return + + if(lung.breath_fail_ratio > 0.9 && world.time > lung.last_successful_breath + 2 MINUTES) + if(deliberate) + to_chat(src, SPAN_WARNING("You try to cough, but no air comes out!")) + return + + if(deliberate && incapacitated()) + to_chat(src, SPAN_WARNING("You cannot do that right now.")) + return + + audible_message("[src] coughs!", "You cough!", radio_message = "coughs!") // styled like an emote + + lastcough = world.time + + // Coughing clears out 1-2 reagents from the lungs. + if(lung.inhaled.total_volume > 0 && loc) + lung.inhaled.splash(loc, rand(1, 2)) \ No newline at end of file diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 076243b47a2..37da2a27fd5 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -201,7 +201,7 @@ /obj/item/organ/proc/handle_ailment(var/datum/ailment/ailment) if(ailment.treated_by_reagent_type) - for(var/datum/reagents/source in list(owner.get_injected_reagents(), owner.reagents, owner.get_ingested_reagents())) + for(var/datum/reagents/source in list(owner.get_injected_reagents(), owner.reagents, owner.get_ingested_reagents(), owner.get_inhaled_reagents())) for(var/reagent_type in source.reagent_volumes) if(ailment.treated_by_medication(source.reagent_volumes[reagent_type])) ailment.was_treated_by_medication(source, reagent_type) diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm index d605125acd5..f437b9b2dd6 100644 --- a/code/modules/reagents/Chemistry-Holder.dm +++ b/code/modules/reagents/Chemistry-Holder.dm @@ -517,6 +517,10 @@ var/global/obj/temp_reagents_holder = new var/datum/reagents/R = L.get_contact_reagents() if(R) return trans_to_holder(R, amount, multiplier, copy, defer_update = defer_update) + if(type == CHEM_INHALE) + var/datum/reagents/R = L.get_inhaled_reagents() + if(R) + return trans_to_holder(R, amount, multiplier, copy, defer_update = defer_update) var/datum/reagents/R = new /datum/reagents(amount, global.temp_reagents_holder) . = trans_to_holder(R, amount, multiplier, copy, TRUE, defer_update = defer_update) R.touch_mob(target) diff --git a/code/modules/reagents/chems/chems_medicines.dm b/code/modules/reagents/chems/chems_medicines.dm index c15b35c2609..2b96ccc530c 100644 --- a/code/modules/reagents/chems/chems_medicines.dm +++ b/code/modules/reagents/chems/chems_medicines.dm @@ -14,7 +14,7 @@ var/mob/living/carbon/human/H = M var/obj/item/organ/internal/eyes/E = H.get_organ(BP_EYES) if(E && istype(E) && !E.is_broken()) - ADJ_STATUS(M, STAT_BLURRY, -5) + ADJ_STATUS(M, STAT_BLURRY, -5) ADJ_STATUS(M, STAT_BLIND, -5) E.damage = max(E.damage - 5 * removed, 0) @@ -122,10 +122,10 @@ var/removing = (4 * removed) var/datum/reagents/ingested = M.get_ingested_reagents() - for(var/R in ingested.reagent_volumes) + for(var/R in ingested?.reagent_volumes) var/decl/material/chem = GET_DECL(R) if((remove_generic && chem.toxicity) || (R in remove_toxins)) - M.reagents.remove_reagent(R, removing) + ingested.remove_reagent(R, removing) return for(var/R in M.reagents?.reagent_volumes) @@ -253,7 +253,7 @@ if(!BP_IS_PROSTHETIC(E) && prob(25) && !(E.status & ORGAN_MUTATED)) E.mutate() E.limb_flags |= ORGAN_FLAG_DEFORMED - + /decl/material/liquid/retrovirals/affect_blood(var/mob/living/M, var/alien, var/removed, var/datum/reagents/holder) M.adjustCloneLoss(-20 * removed) if(LAZYACCESS(M.chem_doses, type) > 10) @@ -359,3 +359,43 @@ /decl/material/liquid/oxy_meds/affect_blood(var/mob/living/M, var/alien, var/removed, var/datum/reagents/holder) M.add_chemical_effect(CE_OXYGENATED, 1) holder.remove_reagent(/decl/material/gas/carbon_monoxide, 2 * removed) + +#define DETOXIFIER_EFFECTIVENESS 6 // 6u of opiates removed per 1u of detoxifier; 5u is enough to remove 30u, i.e. an overdose +#define DETOXIFIER_DOSE_EFFECTIVENESS 2 // 2u of metabolised opiates removed per 1u of detoxifier; will leave you vulnerable to another OD if you use more +/decl/material/liquid/detoxifier + name = "detoxifier" + lore_text = "A compound designed to purge opiates and narcotics from the body when inhaled or injected." + taste_description = "bitterness" + color = "#6666ff" + metabolism = REM + scannable = TRUE + affect_blood_on_inhale = TRUE + affect_blood_on_ingest = FALSE + value = 1.5 + uid = "chem_detoxifier" + +/decl/material/liquid/detoxifier/affect_blood(var/mob/living/M, var/alien, var/removed, var/datum/reagents/holder) + var/charges = removed * DETOXIFIER_EFFECTIVENESS + var/dosecharges = LAZYACCESS(M.chem_doses, type) * DETOXIFIER_DOSE_EFFECTIVENESS + for(var/datum/reagents/container in list(M.get_ingested_reagents(), M.get_inhaled_reagents(), M.get_injected_reagents())) + for(var/reagent_type in container.reagent_volumes) + var/decl/material/liquid/painkillers/painkiller = GET_DECL(reagent_type) + if(!istype(painkiller) || !painkiller.narcotic) + continue + var/amount = min(charges, REAGENT_VOLUME(container, reagent_type)) + if(amount) + charges -= amount + container.remove_reagent(reagent_type, amount) + var/dose_amount = min(dosecharges, LAZYACCESS(M.chem_doses, reagent_type)) + if(dose_amount) + var/dose = LAZYACCESS(M.chem_doses, reagent_type) - dose_amount + LAZYSET(M.chem_doses, reagent_type, dose) + if(M.chem_doses[reagent_type] <= 0) + LAZYREMOVE(M.chem_doses, reagent_type) + dosecharges -= dose_amount + if(charges <= 0 && dosecharges <= 0) + break + if(charges <= 0 && dosecharges <= 0) + break +#undef DETOXIFIER_EFFECTIVENESS +#undef DETOXIFIER_DOSE_EFFECTIVENESS \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 3ee9da59832..20b55e0e1cc 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -153,6 +153,10 @@ origin_tech = "{'materials':2,'biotech':2}" slot_flags = SLOT_LOWER_BODY | SLOT_EARS w_class = ITEM_SIZE_TINY + matter = list( + /decl/material/solid/fiberglass = MATTER_AMOUNT_REINFORCEMENT, + /decl/material/solid/metal/aluminium = MATTER_AMOUNT_TRACE + ) var/list/starts_with = list(/decl/material/liquid/adrenaline = 5) var/band_color = COLOR_CYAN @@ -167,12 +171,12 @@ update_icon() /obj/item/chems/hypospray/autoinjector/on_update_icon() - overlays.Cut() + cut_overlays() if(reagents.total_volume > 0) icon_state = "[initial(icon_state)]1" else icon_state = "[initial(icon_state)]0" - overlays+= overlay_image(icon,"injector_band",band_color,RESET_COLOR) + add_overlay(overlay_image(icon,"injector_band",band_color,RESET_COLOR)) /obj/item/chems/hypospray/autoinjector/examine(mob/user) . = ..(user) diff --git a/code/modules/reagents/reagent_containers/inhaler.dm b/code/modules/reagents/reagent_containers/inhaler.dm new file mode 100644 index 00000000000..f4ceb610ae0 --- /dev/null +++ b/code/modules/reagents/reagent_containers/inhaler.dm @@ -0,0 +1,115 @@ +//Inhalers +//Just like hypopsray code +/obj/item/chems/inhaler + name = "autoinhaler" + desc = "A rapid and safe way to administer small amounts of drugs into the lungs by untrained or trained personnel." + icon = 'icons/obj/syringe.dmi' + item_state = "autoinjector" + icon_state = "autoinhaler" + center_of_mass = @"{'x':16,'y':11}" + unacidable = TRUE + amount_per_transfer_from_this = 5 + volume = 5 + w_class = ITEM_SIZE_SMALL + possible_transfer_amounts = null + atom_flags = ATOM_FLAG_OPEN_CONTAINER + slot_flags = SLOT_LOWER_BODY + origin_tech = "{'materials':2,'biotech':2}" + var/used = FALSE + matter = list( + /decl/material/solid/fiberglass = MATTER_AMOUNT_REINFORCEMENT, + /decl/material/solid/metal/aluminium = MATTER_AMOUNT_TRACE + ) + var/list/starts_with = null /// A lazylist of starting reagents. Example: list(/decl/material/liquid/adrenaline = 5) + var/band_color = COLOR_GREEN + +/obj/item/chems/inhaler/Initialize() + . = ..() + for(var/T in starts_with) + reagents.add_reagent(T, starts_with[T]) + update_icon() + +/obj/item/chems/inhaler/on_update_icon() + cut_overlays() + if(ATOM_IS_OPEN_CONTAINER(src)) + add_overlay("[icon_state]_loaded") + if(reagents.total_volume > 0) + add_overlay("[icon_state]_reagents") + add_overlay(overlay_image(icon,"[icon_state]_band",band_color,RESET_COLOR)) + +/obj/item/chems/inhaler/attack(var/mob/living/carbon/human/target, var/mob/user, var/proximity) + if (!istype(target)) + return ..() + + if(!proximity) + return TRUE + + if(!reagents.total_volume) + to_chat(user, SPAN_WARNING("\The [src] is empty.")) + return TRUE + + // This properly handles mouth coverage/presence, but should probably be replaced later. + if(user == target) + if(!target.can_eat(src)) + return TRUE + else + if(!target.can_force_feed(user, src)) + return TRUE + + user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) + user.do_attack_animation(target) + + if(user == target) + user.visible_message(SPAN_NOTICE("\The [user] inhales from \the [src]."), SPAN_NOTICE("You stick the \the [src] in your mouth and press the injection button.")) + else + user.visible_message(SPAN_WARNING("\The [user] attempts to administer \the [src] to \the [target]..."), SPAN_NOTICE("You attempt to administer \the [src] to \the [target]...")) + if (!do_after(user, 1 SECONDS, target)) + to_chat(user, SPAN_NOTICE("You and the target need to be standing still in order to inject \the [src].")) + return TRUE + + user.visible_message(SPAN_NOTICE("\The [user] administers \the [src] to \the [target]."), SPAN_NOTICE("You stick \the [src] in \the [target]'s mouth and press the injection button.")) + + var/contained = REAGENT_LIST(src) + var/trans = reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_INHALE) + if(trans) + admin_inject_log(user, target, src, contained, trans) + playsound(src.loc, 'sound/effects/hypospray.ogg', 50, 1) + to_chat(user, SPAN_NOTICE("[trans] units administered. [reagents.total_volume] units remaining in \the [src].")) + used = TRUE + + update_icon() + + return TRUE + +/obj/item/chems/inhaler/attack(mob/M as mob, mob/user as mob) + if(ATOM_IS_OPEN_CONTAINER(src)) + to_chat(user, SPAN_NOTICE("You must secure the reagents inside \the [src] before using it!")) + return FALSE + . = ..() + +/obj/item/chems/inhaler/attack_self(mob/user as mob) + if(ATOM_IS_OPEN_CONTAINER(src)) + if(reagents.total_volume > 0) + to_chat(user, SPAN_NOTICE("With a quick twist of \the [src]'s lid, you secure the reagents inside.")) + atom_flags &= ~ATOM_FLAG_OPEN_CONTAINER + update_icon() + else + to_chat(user, SPAN_NOTICE("You can't secure \the [src] without putting reagents in!")) + else + to_chat(user, SPAN_NOTICE("The reagents inside \the [src] are already secured.")) + return TRUE + +/obj/item/chems/inhaler/attackby(obj/item/tool, mob/user) + if(isScrewdriver(tool) && !ATOM_IS_OPEN_CONTAINER(src)) + to_chat(user, SPAN_NOTICE("Using \the [tool], you unsecure the inhaler's lid.")) // it locks shut after being secured + atom_flags |= ATOM_FLAG_OPEN_CONTAINER + update_icon() + return TRUE + . = ..() + +/obj/item/chems/inhaler/examine(mob/user) + . = ..(user) + if(reagents.total_volume > 0) + to_chat(user, SPAN_NOTICE("It is currently loaded.")) + else + to_chat(user, SPAN_NOTICE("It is spent.")) diff --git a/code/modules/spells/spellbook/cleric.dm b/code/modules/spells/spellbook/cleric.dm index e639f192943..8775b80375e 100644 --- a/code/modules/spells/spellbook/cleric.dm +++ b/code/modules/spells/spellbook/cleric.dm @@ -42,6 +42,7 @@ sacrifice_objects = list( /obj/item/stack/nanopaste, /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/stack/medical/advanced/bruise_pack, /obj/item/stack/medical/advanced/ointment, /obj/item/bodybag/rescue, diff --git a/code/modules/surgery/_surgery.dm b/code/modules/surgery/_surgery.dm index 1ade04bdf37..50a96bd9a9d 100644 --- a/code/modules/surgery/_surgery.dm +++ b/code/modules/surgery/_surgery.dm @@ -4,8 +4,10 @@ var/global/list/surgeries_in_progress = list() var/global/list/surgery_tool_exceptions = list( /obj/item/auto_cpr, /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/shockpaddles, /obj/item/chems/hypospray, + /obj/item/chems/inhaler, /obj/item/modular_computer, /obj/item/chems/syringe, /obj/item/chems/borghypo diff --git a/code/modules/xenoarcheaology/artifacts/standalone/replicator.dm b/code/modules/xenoarcheaology/artifacts/standalone/replicator.dm index ab359d5b9cb..828289b20b2 100644 --- a/code/modules/xenoarcheaology/artifacts/standalone/replicator.dm +++ b/code/modules/xenoarcheaology/artifacts/standalone/replicator.dm @@ -34,6 +34,7 @@ /obj/item/flash, /obj/item/flashlight, /obj/item/scanner/health, + /obj/item/scanner/breath, /obj/item/multitool, /obj/item/paicard, /obj/item/radio, diff --git a/code/modules/xenoarcheaology/tools/equipment.dm b/code/modules/xenoarcheaology/tools/equipment.dm index c49948b3171..50406fdba94 100644 --- a/code/modules/xenoarcheaology/tools/equipment.dm +++ b/code/modules/xenoarcheaology/tools/equipment.dm @@ -22,7 +22,7 @@ rad = ARMOR_RAD_SHIELDED ) anomaly_shielding = 0.6 - allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/stack/flag,/obj/item/storage/excavation,/obj/item/pickaxe,/obj/item/scanner/health,/obj/item/measuring_tape,/obj/item/ano_scanner,/obj/item/depth_scanner,/obj/item/core_sampler,/obj/item/gps,/obj/item/pinpointer/radio,/obj/item/radio/beacon,/obj/item/pickaxe/xeno,/obj/item/storage/bag/fossils) + allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/stack/flag,/obj/item/storage/excavation,/obj/item/pickaxe,/obj/item/scanner/health,/obj/item/scanner/breath,/obj/item/measuring_tape,/obj/item/ano_scanner,/obj/item/depth_scanner,/obj/item/core_sampler,/obj/item/gps,/obj/item/pinpointer/radio,/obj/item/radio/beacon,/obj/item/pickaxe/xeno,/obj/item/storage/bag/fossils) /obj/item/clothing/head/helmet/space/void/excavation name = "excavation voidsuit helmet" diff --git a/icons/obj/items/device/scanner/breath_scanner.dmi b/icons/obj/items/device/scanner/breath_scanner.dmi new file mode 100644 index 00000000000..648bf78f29f Binary files /dev/null and b/icons/obj/items/device/scanner/breath_scanner.dmi differ diff --git a/icons/obj/syringe.dmi b/icons/obj/syringe.dmi index dfcccbd5de1..41e04593521 100644 Binary files a/icons/obj/syringe.dmi and b/icons/obj/syringe.dmi differ diff --git a/nano/templates/sleeper.tmpl b/nano/templates/sleeper.tmpl index 122ca1a3521..0c9ab51c289 100644 --- a/nano/templates/sleeper.tmpl +++ b/nano/templates/sleeper.tmpl @@ -22,6 +22,9 @@
{{:helper.link(data.pump ? "Stomach pump active" : "Stomach pump inactive", null, {'pump' : !data.pump})}}
+
+ {{:helper.link(data.lavage ? "Lung lavage active" : "Lung lavage inactive", null, {'lavage' : !data.lavage})}} +
{{else}} There are a few buttons here, but the labels don't make any sense to you. {{/if}} diff --git a/nebula.dme b/nebula.dme index aed9a1fe2c2..a2a174a85e9 100644 --- a/nebula.dme +++ b/nebula.dme @@ -987,6 +987,7 @@ #include "code\game\objects\items\devices\radio\intercom.dm" #include "code\game\objects\items\devices\radio\radio.dm" #include "code\game\objects\items\devices\scanners\_scanner.dm" +#include "code\game\objects\items\devices\scanners\breath.dm" #include "code\game\objects\items\devices\scanners\gas.dm" #include "code\game\objects\items\devices\scanners\health.dm" #include "code\game\objects\items\devices\scanners\mass_spectrometer.dm" @@ -3004,6 +3005,7 @@ #include "code\modules\reagents\reagent_containers\food.dm" #include "code\modules\reagents\reagent_containers\glass.dm" #include "code\modules\reagents\reagent_containers\hypospray.dm" +#include "code\modules\reagents\reagent_containers\inhaler.dm" #include "code\modules\reagents\reagent_containers\pill.dm" #include "code\modules\reagents\reagent_containers\spray.dm" #include "code\modules\reagents\reagent_containers\syringes.dm"