diff --git a/citadel.dme b/citadel.dme index ba2f4c655c1..275bc1b82d1 100644 --- a/citadel.dme +++ b/citadel.dme @@ -192,6 +192,7 @@ #include "code\__DEFINES\inventory\procs.dm" #include "code\__DEFINES\inventory\rendering.dm" #include "code\__DEFINES\inventory\slots.dm" +#include "code\__DEFINES\items\hypospray.dm" #include "code\__DEFINES\items\inducer.dm" #include "code\__DEFINES\items\nifs.dm" #include "code\__DEFINES\items\clothing\uniforms.dm" @@ -307,6 +308,7 @@ #include "code\__HELPERS\path.dm" #include "code\__HELPERS\piping_colors_lists.dm" #include "code\__HELPERS\qdel.dm" +#include "code\__HELPERS\reagents.dm" #include "code\__HELPERS\ref.dm" #include "code\__HELPERS\sanitize_values.dm" #include "code\__HELPERS\shell.dm" @@ -1583,7 +1585,6 @@ #include "code\game\objects\items\storage\boxes.dm" #include "code\game\objects\items\storage\briefcase.dm" #include "code\game\objects\items\storage\fancy.dm" -#include "code\game\objects\items\storage\firstaid.dm" #include "code\game\objects\items\storage\internal.dm" #include "code\game\objects\items\storage\laundry_basket.dm" #include "code\game\objects\items\storage\lockbox.dm" @@ -1593,6 +1594,8 @@ #include "code\game\objects\items\storage\toolbox.dm" #include "code\game\objects\items\storage\uplink_kits.dm" #include "code\game\objects\items\storage\wallets.dm" +#include "code\game\objects\items\storage\medical\firstaid.dm" +#include "code\game\objects\items\storage\medical\hypokit.dm" #include "code\game\objects\items\storage\single_use\_single_use.dm" #include "code\game\objects\items\storage\single_use\med_pouch.dm" #include "code\game\objects\items\storage\single_use\mre.dm" @@ -4036,8 +4039,11 @@ #include "code\modules\reagents\chemistry\reagents\Chemistry-Topical.dm" #include "code\modules\reagents\chemistry\reagents\other\cleaner.dm" #include "code\modules\reagents\chemistry\reagents\pyrotechnics\thermite.dm" +#include "code\modules\reagents\chemistry\recipes\medicine.dm" #include "code\modules\reagents\distilling\Distilling-Recipes.dm" #include "code\modules\reagents\distilling\distilling.dm" +#include "code\modules\reagents\items\hypospray.dm" +#include "code\modules\reagents\items\hypovial.dm" #include "code\modules\reagents\machinery\chem_master.dm" #include "code\modules\reagents\machinery\reagent_dispenser.dm" #include "code\modules\reagents\machinery\dispenser\cartridge.dm" diff --git a/code/__DEFINES/_flags/item_flags.dm b/code/__DEFINES/_flags/item_flags.dm index dfebc51bc87..ef8f75fa367 100644 --- a/code/__DEFINES/_flags/item_flags.dm +++ b/code/__DEFINES/_flags/item_flags.dm @@ -31,49 +31,40 @@ DEFINE_BITFIELD(item_flags, list( )) //! Flags for the clothing_flags var on /obj/item -/* -#define LAVAPROTECT (1<<0) -/// SUIT and HEAD items which stop pressure damage. To stop you taking all pressure damage you must have both a suit and head item with this flag. -#define STOPSPRESSUREDAMAGE (1<<1) -*/ /// Blocks the effect that chemical clouds would have on a mob --glasses, mask and helmets ONLY! (NOTE: flag shared with ONESIZEFITSALL) -#define BLOCK_GAS_SMOKE_EFFECT (1<<2) -/// Mask allows internals -#define ALLOWINTERNALS (1<<3) -/// Prevents from slipping on wet floors, in space etc -#define NOSLIP (1<<4) -/* -/// Prevents from slipping on frozen floors -#define NOSLIP_ICE (1<<5) -*/ -/// Prevents syringes, parapens and hyposprays if equipped to slot_suit or SLOT_ID_HEAD. -#define THICKMATERIAL (1<<6) -/* -/// The voicebox in this clothing can be toggled. -#define VOICEBOX_TOGGLABLE (1<<7) -/// The voicebox is currently turned off. -#define VOICEBOX_DISABLED (1<<8) -/// Hats with negative effects when worn (i.e the tinfoil hat). -#define IGNORE_HAT_TOSS (1<<9) -*/ -/// Allows helmets and glasses to scan reagents. -#define SCAN_REAGENTS (1<<10) -/// At the moment, masks with this flag will not prevent eating even if they are covering your face. -#define FLEXIBLEMATERIAL (1<<11) -/// Allows special survival food items to be eaten through it -#define ALLOW_SURVIVALFOOD (1<<12) /// ignores "is this limb here" for equip. -#define CLOTHING_IGNORE_DELIMB (1<<13) +#define CLOTHING_IGNORE_DELIMB (1<<1) /// ignores "do we have a jumpsuit" for belt -#define CLOTHING_IGNORE_BELTLINK (1<<14) +#define CLOTHING_IGNORE_BELTLINK (1<<2) /// for plural limbs, wearable with just one -#define CLOTHING_ALLOW_SINGLE_LIMB (1<<15) +#define CLOTHING_ALLOW_SINGLE_LIMB (1<<3) +/// Prevents syringes, parapens and hyposprays if equipped to slot_suit or SLOT_ID_HEAD. +#define CLOTHING_THICK_MATERIAL (1<<4) +/// Syringes / hyposprays / etc can get through, but need to pass through an injection port. +#define CLOTHING_INJECTION_PORT (1<<5) +// todo: audit +#define BLOCK_GAS_SMOKE_EFFECT (1<<6) +/// Mask allows internals +// todo: audit +#define ALLOWINTERNALS (1<<7) +/// Prevents from slipping on wet floors, in space etc +// todo: audit +#define NOSLIP (1<<8) +/// Allows helmets and glasses to scan reagents. +// todo: audit +#define SCAN_REAGENTS (1<<9) +/// At the moment, masks with this flag will not prevent eating even if they are covering your face. +// todo: audit +#define FLEXIBLEMATERIAL (1<<10) +/// Allows special survival food items to be eaten through it +// todo: audit +#define ALLOW_SURVIVALFOOD (1<<11) DEFINE_BITFIELD(clothing_flags, list( BITFIELD(BLOCK_GAS_SMOKE_EFFECT), BITFIELD(ALLOWINTERNALS), BITFIELD(NOSLIP), - BITFIELD(THICKMATERIAL), + BITFIELD(CLOTHING_THICK_MATERIAL), BITFIELD(SCAN_REAGENTS), BITFIELD(FLEXIBLEMATERIAL), BITFIELD(ALLOW_SURVIVALFOOD), diff --git a/code/__DEFINES/chemistry.dm b/code/__DEFINES/chemistry.dm index e10191ec149..3a6a2341909 100644 --- a/code/__DEFINES/chemistry.dm +++ b/code/__DEFINES/chemistry.dm @@ -1,3 +1,18 @@ +//* Reagent exposure methods. +//* These are flags for combined checks, but are often passed as an one-bit-value enum to procs. + +/// Splashed, touched, sprayed, etc +#define CHEM_TOUCH (1<<0) +/// Eaten, drunk, etc +#define CHEM_INGEST (1<<1) +/// Injected into bloodstream or equivalent +#define CHEM_INJECT (1<<2) +/// Inhaled or immersed in gas +// todo: this is currently unimplemented. +#define CHEM_VAPOR (1<<3) + +//* Unsorted + /// Factor of how fast mob nutrition decreases #define DEFAULT_HUNGER_FACTOR 0.03 /// Factor of how fast mob hydration decreases @@ -5,21 +20,6 @@ /// Means 'Reagent Effect Multiplier'. This is how many units of reagent are consumed per tick #define REM 0.2 -//! Reagent exposure methods. -/// Used for splashing. -#define CHEM_TOUCH (1<<0) -/// Used for ingesting the reagents. Food, drinks, inhaling smoke. -#define CHEM_INGEST (1<<1) -/// Used by foams, sprays, and blob attacks. -#define CHEM_VAPOR (1<<2) -/// Used by medical patches and gels. -#define CHEM_PATCH (1<<3) -/// Used for direct injection of reagents. -#define CHEM_INJECT (1<<4) -/// Used for blood contamination. -#define CHEM_BLOOD (1<<5) - - #define MINIMUM_CHEMICAL_VOLUME 0.01 // states of matter diff --git a/code/__DEFINES/items/hypospray.dm b/code/__DEFINES/items/hypospray.dm new file mode 100644 index 00000000000..36c8c868dfd --- /dev/null +++ b/code/__DEFINES/items/hypospray.dm @@ -0,0 +1,2 @@ +#define HYPOSPRAY_MODE_INJECT 1 +#define HYPOSPRAY_MODE_SPRAY 2 diff --git a/code/__DEFINES/misc/message_ranges.dm b/code/__DEFINES/misc/message_ranges.dm index ac904468230..90fdf16e693 100644 --- a/code/__DEFINES/misc/message_ranges.dm +++ b/code/__DEFINES/misc/message_ranges.dm @@ -1,8 +1,10 @@ -/// message range for silenced combat actions +/// message range for silenced combat actions. for stuff like id swipes, etc #define MESSAGE_RANGE_COMBAT_SILENCED 1 -/// message range for subtle combat actions +/// message range for moderately silenced combat actions. for most things like syringe injections, etc. +#define MESSAGE_RANGE_COMBAT_SUPPRESSED 2 +/// message range for subtle combat actions. for things like subtle hits in melee #define MESSAGE_RANGE_COMBAT_SUBTLE 3 -/// message range for loud combat actions +/// message range for loud combat actions. for things like obvious melee / ranged fire #define MESSAGE_RANGE_COMBAT_LOUD 7 /// message range for most construction / deconstruction actions diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 501ab7a5f42..eec8baaef4d 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -207,6 +207,12 @@ GLOBAL_LIST_INIT(testing_global_profiler, list("_PROFILE_NAME" = "Global")) /proc/log_qdel(text) WRITE_LOG(GLOB.world_qdel_log, "QDEL: [text]") +/proc/log_reagent(text) + WRITE_LOG(GLOB.world_reagent_log, text) + +/proc/log_reagent_transfer(text) + log_reagent("TRANSFER: [text]") + /proc/log_subsystem(subsystem, text) WRITE_LOG(GLOB.subsystem_log, "[subsystem]: [text]") diff --git a/code/__HELPERS/reagents.dm b/code/__HELPERS/reagents.dm new file mode 100644 index 00000000000..3857d459ce9 --- /dev/null +++ b/code/__HELPERS/reagents.dm @@ -0,0 +1,52 @@ +// todo: this doesn't entirely work. see recipe for peridaxon requiring priority. +/proc/chem_recipes_do_conflict(datum/chemical_reaction/r1, datum/chemical_reaction/r2) + // do the non-list tests first, because they are cheaper + if(r1.required_container != r2.required_container) + return FALSE + // if(r1.is_cold_recipe == r2.is_cold_recipe) + // if(r1.required_temp != r2.required_temp) + // //one reaction requires a more extreme temperature than the other, so there is no conflict + // return FALSE + // else + // var/datum/chemical_reaction/cold_one = r1.is_cold_recipe ? r1 : r2 + // var/datum/chemical_reaction/warm_one = r1.is_cold_recipe ? r2 : r1 + // if(cold_one.required_temp < warm_one.required_temp) + // //the range of temperatures does not overlap, so there is no conflict + // return FALSE + + //find the reactions with the shorter and longer required_reagents list + var/datum/chemical_reaction/long_req + var/datum/chemical_reaction/short_req + if(r1.required_reagents.len > r2.required_reagents.len) + long_req = r1 + short_req = r2 + else if(r1.required_reagents.len < r2.required_reagents.len) + long_req = r2 + short_req = r1 + else + //if they are the same length, sort instead by the length of the catalyst list + //this is important if the required_reagents lists are the same + if(r1.catalysts.len > r2.catalysts.len) + long_req = r1 + short_req = r2 + else + long_req = r2 + short_req = r1 + + + //check if the shorter reaction list is a subset of the longer one + var/list/overlap = r1.required_reagents & r2.required_reagents + if(overlap.len != short_req.required_reagents.len) + //there is at least one reagent in the short list that is not in the long list, so there is no conflict + return FALSE + + //check to see if the shorter reaction's catalyst list is also a subset of the longer reaction's catalyst list + //if the longer reaction's catalyst list is a subset of the shorter ones, that is fine + //if the reaction lists are the same, the short reaction will have the shorter required_catalysts list, so it will register as a conflict + var/list/short_minus_long_catalysts = short_req.catalysts - long_req.catalysts + if(short_minus_long_catalysts.len) + //there is at least one unique catalyst for the short reaction, so there is no conflict + return FALSE + + //if we got this far, the longer reaction will be impossible to create if the shorter one is earlier in GLOB.chemical_reactions_list, and will require the reagents to be added in a particular order otherwise + return TRUE diff --git a/code/_globals/logging.dm b/code/_globals/logging.dm index b1f043ed3c8..7758b1c2711 100644 --- a/code/_globals/logging.dm +++ b/code/_globals/logging.dm @@ -30,6 +30,9 @@ GLOBAL_PROTECT(sql_error_log) /// Map error logging GLOBAL_VAR(world_map_error_log) GLOBAL_PROTECT(world_map_error_log) +GLOBAL_VAR(world_reagent_log) +GLOBAL_PROTECT(world_reagent_log) +/// Reagent logging /// datum/controller/subsystem logging in general GLOBAL_VAR(subsystem_log) GLOBAL_PROTECT(subsystem_log) @@ -39,13 +42,6 @@ GLOBAL_PROTECT(tgui_log) SIMPLE_LOG_BOILERPLATE(inventory_log, inventory) SIMPLE_LOG_BOILERPLATE(click_log, click) -/// Picture logging -GLOBAL_VAR(picture_log_directory) -GLOBAL_PROTECT(picture_log_directory) -GLOBAL_VAR_INIT(picture_logging_id, 1) -GLOBAL_PROTECT(picture_logging_id) -GLOBAL_VAR(picture_logging_prefix) -GLOBAL_PROTECT(picture_logging_prefix) /// Log associated with [/proc/log_suspicious_login()] /// Intended to hold all logins that failed due to suspicious circumstances such as ban detection, CID randomisation etc. GLOBAL_VAR(world_suspicious_login_log) diff --git a/code/controllers/subsystem/processing/chemistry.dm b/code/controllers/subsystem/processing/chemistry.dm index d42a5d360a4..60b0d6725df 100644 --- a/code/controllers/subsystem/processing/chemistry.dm +++ b/code/controllers/subsystem/processing/chemistry.dm @@ -30,21 +30,24 @@ PROCESSING_SUBSYSTEM_DEF(chemistry) * - more than one chemical it will still only appear in only one of the sublists. */ /datum/controller/subsystem/processing/chemistry/proc/initialize_chemical_reactions() - var/paths = typesof(/datum/chemical_reaction) - /datum/chemical_reaction + var/paths = subtypesof(/datum/chemical_reaction) chemical_reactions = list() chemical_reactions_by_reagent = list() for(var/path in paths) var/datum/chemical_reaction/D = new path chemical_reactions += D - if(D.required_reagents && D.required_reagents.len) - var/reagent_id = D.required_reagents[1] - LAZYINITLIST(chemical_reactions_by_reagent[reagent_id]) - chemical_reactions_by_reagent[reagent_id] += D + tim_sort(chemical_reactions, /proc/cmp_chemical_reaction_priority) + for(var/datum/chemical_reaction/D as anything in chemical_reactions) + if(!length(D.required_reagents)) + continue + var/reagent_id = D.required_reagents[1] + LAZYINITLIST(chemical_reactions_by_reagent[reagent_id]) + chemical_reactions_by_reagent[reagent_id] += D /// Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id /datum/controller/subsystem/processing/chemistry/proc/initialize_chemical_reagents() - var/paths = typesof(/datum/reagent) - /datum/reagent + var/paths = subtypesof(/datum/reagent) reagent_lookup = list() for(var/datum/reagent/path as anything in paths) if(initial(path.abstract_type) == path) diff --git a/code/datums/autolathe/medical.dm b/code/datums/autolathe/medical.dm index 60c6332c24a..fe7f74203f2 100644 --- a/code/datums/autolathe/medical.dm +++ b/code/datums/autolathe/medical.dm @@ -33,6 +33,13 @@ /datum/category_item/autolathe/medical/vial name = "glass vial" path =/obj/item/reagent_containers/glass/beaker/vial +/datum/category_item/autolathe/medical/hypovial + name = "hypovial" + path =/obj/item/reagent_containers/glass/hypovial + +/datum/category_item/autolathe/medical/hypovial_large + name = "large hypovial" + path =/obj/item/reagent_containers/glass/hypovial/large /datum/category_item/autolathe/medical/syringe name = "syringe" diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index b828d07e91d..6909f279a40 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -47,7 +47,7 @@ if(("name" in vars) && !isatom(src)) . += "[vars["name"]]
" -/datum/proc/on_reagent_change(changetype) +/datum/proc/on_reagent_change() return // todo: proper way to mark things immutable & provide a method to make a mutable clone for editing. diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index 00ce70a3195..2727789cdf6 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -598,7 +598,7 @@ inject_amount = 0 if (inject_amount > 50) inject_amount = 50 - connected.beaker.reagents.trans_to_mob(connected.occupant, inject_amount, CHEM_BLOOD) + connected.beaker.reagents.trans_to_mob(connected.occupant, inject_amount, CHEM_INJECT) return 1 // return 1 forces an update to all Nano uis attached to src //////////////////////////////////////////////////////// diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index 0e6de4e1690..bea8fe774fe 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -248,7 +248,7 @@ var/has_clonexa = occupant.reagents.get_reagent_amount("clonexadone") >= 1 var/has_cryo_medicine = has_cryo || has_clonexa if(beaker && !has_cryo_medicine) - beaker.reagents.trans_to_mob(occupant, 1, CHEM_BLOOD, 10) + beaker.reagents.trans_to_mob(occupant, 1, CHEM_INJECT, 10) /obj/machinery/atmospherics/component/unary/cryo_cell/proc/heat_gas_contents() if(air_contents.total_moles < 1) diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index aa68329b3a8..18aeb9da9c9 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -196,7 +196,7 @@ if(istype(reagent_container, /obj/item/reagent_containers/blood)) // speed up transfer on blood packs real_transfer_amount *= 2 - target_reagents.trans_to_mob(attached_victim, real_transfer_amount * delta_time * 0.5, type = CHEM_BLOOD) + target_reagents.trans_to_mob(attached_victim, real_transfer_amount * delta_time * 0.5, type = CHEM_INJECT) update_appearance() // Take blood diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index a97e406144a..089ff5c0f01 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -968,6 +968,7 @@ /obj/item/storage/single_use/med_pouch/oxyloss = 3, /obj/item/storage/single_use/med_pouch/burn = 3, /obj/item/storage/single_use/med_pouch/trauma = 3, + /obj/item/storage/hypokit = 6, ) contraband = list( /obj/item/reagent_containers/pill/tox = 3, diff --git a/code/game/mecha/equipment/tools/syringe_gun.dm b/code/game/mecha/equipment/tools/syringe_gun.dm index fce149846fd..9c04e46be03 100644 --- a/code/game/mecha/equipment/tools/syringe_gun.dm +++ b/code/game/mecha/equipment/tools/syringe_gun.dm @@ -83,7 +83,7 @@ if(M) S.icon_state = initial(S.icon_state) S.icon = initial(S.icon) - S.reagents.trans_to_mob(M, S.reagents.total_volume, CHEM_BLOOD) + S.reagents.trans_to_mob(M, S.reagents.total_volume, CHEM_INJECT) M.take_organ_damage(2) S.visible_message(" [M] was hit by the syringe!") break diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index bad4a3d29ad..d66f9e2cd3b 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -218,7 +218,7 @@ return if(H.reagents) - syringe.reagents.trans_to_mob(H, 30, CHEM_BLOOD) + syringe.reagents.trans_to_mob(H, 30, CHEM_INJECT) /obj/structure/closet/body_bag/cryobag/examine(mob/user) . = ..() diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm index 49ddd6783db..209782d42fa 100644 --- a/code/game/objects/items/devices/defib.dm +++ b/code/game/objects/items/devices/defib.dm @@ -296,7 +296,7 @@ /obj/item/shockpaddles/proc/check_contact(mob/living/carbon/human/H) if(!combat) for(var/obj/item/clothing/cloth in list(H.wear_suit, H.w_uniform)) - if((cloth.body_cover_flags & UPPER_TORSO) && (cloth.clothing_flags & THICKMATERIAL)) + if((cloth.body_cover_flags & UPPER_TORSO) && (cloth.clothing_flags & CLOTHING_THICK_MATERIAL)) return FALSE return TRUE diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index 47b02eea6c0..c07bde49c14 100644 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -139,6 +139,7 @@ /obj/item/clothing/head/surgery, /obj/item/clothing/gloves, /obj/item/reagent_containers/hypospray, + /obj/item/hypospray, /obj/item/clothing/glasses, /obj/item/tool/crowbar, /obj/item/flashlight, @@ -271,6 +272,7 @@ /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, + /obj/item/hypospray, /obj/item/storage/pill_bottle, /obj/item/stack/medical, /obj/item/stack/marker_beacon, @@ -346,6 +348,7 @@ /obj/item/clothing/head/surgery, /obj/item/clothing/gloves, /obj/item/reagent_containers/hypospray, + /obj/item/hypospray, /obj/item/clothing/glasses, /obj/item/tool/crowbar, /obj/item/flashlight, diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/medical/firstaid.dm similarity index 99% rename from code/game/objects/items/storage/firstaid.dm rename to code/game/objects/items/storage/medical/firstaid.dm index dc01f10598e..e7f2dbb161f 100644 --- a/code/game/objects/items/storage/firstaid.dm +++ b/code/game/objects/items/storage/medical/firstaid.dm @@ -19,9 +19,6 @@ drop_sound = 'sound/items/drop/cardboardbox.ogg' pickup_sound = 'sound/items/pickup/cardboardbox.ogg' -/obj/item/storage/firstaid/Initialize(mapload) - . = ..() - /obj/item/storage/firstaid/fire name = "fire first aid kit" desc = "It's an emergency medical kit, loaded with everything you would need to treat burns of any kind." diff --git a/code/game/objects/items/storage/medical/hypokit.dm b/code/game/objects/items/storage/medical/hypokit.dm new file mode 100644 index 00000000000..84b17b1860b --- /dev/null +++ b/code/game/objects/items/storage/medical/hypokit.dm @@ -0,0 +1,105 @@ +/obj/item/storage/hypokit + name = "hypospray kit" + desc = "A standard issue storage case and assorted vials for a prototype subdermal hypospray." + icon = 'icons/items/storage/firstaid_small.dmi' + inhand_icon = 'icons/items/storage/firstaid.dmi' + icon_state = "normal" + max_storage_space = INVENTORY_BOX_SPACE + can_hold = list( + /obj/item/reagent_containers/glass/hypovial, + /obj/item/hypospray, + ) + + var/hypospray_path = /obj/item/hypospray + var/vial_path = /obj/item/reagent_containers/glass/hypovial + var/vial_amount = 6 + +/obj/item/storage/hypokit/PopulateContents() + . = ..() + new hypospray_path(src) + spawn_hypovials() + +/obj/item/storage/hypokit/proc/spawn_hypovials() + for(var/i in 1 to vial_amount) + new vial_path(src) + +/obj/item/storage/hypokit/combat + name = "combat hypospray kit" + icon_state = "tactical" + hypospray_path = /obj/item/hypospray/combat/loaded + vial_path = /obj/item/reagent_containers/glass/hypovial/large + max_storage_space = INVENTORY_BOX_SPACE * 2 + storage_cost = ITEMSIZE_COST_NORMAL * 1.5 + +/obj/item/storage/hypokit/combat/loaded/spawn_hypovials() + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/large/bicaridine(src) + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/large/dylovene(src) + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/large/kelotane(src) + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/large/dexalin_plus(src) + new /obj/item/reagent_containers/glass/hypovial/large/inaprovaline(src) + new /obj/item/reagent_containers/glass/hypovial/large/peridaxon(src) + new /obj/item/reagent_containers/glass/hypovial/large/tramadol(src) + new /obj/item/reagent_containers/glass/hypovial/large/arithrazine(src) + new /obj/item/reagent_containers/glass/hypovial/large/spaceacillin(src) + +/obj/item/storage/hypokit/advanced + name = "advanced hypospray kit" + icon = 'icons/items/storage/firstaid.dmi' + icon_state = "briefcase" + inhand_state = "normal" + hypospray_path = /obj/item/hypospray/advanced/loaded + vial_path = /obj/item/reagent_containers/glass/hypovial/large + max_storage_space = INVENTORY_BOX_SPACE * 2 + storage_cost = ITEMSIZE_COST_NORMAL * 1.5 + +/obj/item/storage/hypokit/advanced/loaded/spawn_hypovials() + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/large/bicaridine(src) + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/large/dylovene(src) + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/large/kelotane(src) + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/large/dexalin_plus(src) + new /obj/item/reagent_containers/glass/hypovial/large/inaprovaline(src) + new /obj/item/reagent_containers/glass/hypovial/large/peridaxon(src) + new /obj/item/reagent_containers/glass/hypovial/large/tramadol(src) + new /obj/item/reagent_containers/glass/hypovial/large/arithrazine(src) + new /obj/item/reagent_containers/glass/hypovial/large/spaceacillin(src) + +/obj/item/storage/hypokit/advanced/cmo + hypospray_path = /obj/item/hypospray/advanced/cmo/loaded + +/obj/item/storage/hypokit/advanced/cmo/loaded/spawn_hypovials() + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/large/bicaridine(src) + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/large/dylovene(src) + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/large/kelotane(src) + new /obj/item/reagent_containers/glass/hypovial/large/dexalin_plus(src) + new /obj/item/reagent_containers/glass/hypovial/large/inaprovaline(src) + new /obj/item/reagent_containers/glass/hypovial/large/peridaxon(src) + new /obj/item/reagent_containers/glass/hypovial/large/tramadol(src) + new /obj/item/reagent_containers/glass/hypovial/large/arithrazine(src) + new /obj/item/reagent_containers/glass/hypovial/large/spaceacillin(src) + +/obj/item/storage/hypokit/loaded + +/obj/item/storage/hypokit/loaded/spawn_hypovials() + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/bicaridine(src) + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/dylovene(src) + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/kelotane(src) + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/dexalin(src) + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/tricordrazine(src) + for(var/i in 1 to 2) + new /obj/item/reagent_containers/glass/hypovial/inaprovaline(src) diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index 19969897f0b..5418de66bf4 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -376,7 +376,7 @@ the implant may become unstable and either pre-maturely inject the subject or si /obj/item/implant/chem/activate(var/cause) if((!cause) || (!src.imp_in)) return 0 var/mob/living/carbon/R = src.imp_in - src.reagents.trans_to_mob(R, cause, CHEM_BLOOD) + src.reagents.trans_to_mob(R, cause, CHEM_INJECT) to_chat(R, "You hear a faint *beep*.") if(!src.reagents.total_volume) to_chat(R, "You hear a faint click from your chest.") 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 ade6bf960e8..fbd71b7f764 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -169,7 +169,7 @@ /obj/item/radio/headset/heads/cmo, /obj/item/radio/headset/heads/cmo/alt, /obj/item/flash, - /obj/item/reagent_containers/hypospray/vial, + /obj/item/storage/hypokit/advanced/cmo, /obj/item/clothing/suit/storage/hooded/wintercoat/medical/cmo, /obj/item/clothing/shoes/boots/winter/medical, /obj/item/storage/box/freezer, @@ -179,7 +179,6 @@ /obj/item/clothing/head/bio_hood/cmo, /obj/item/gps/medical/cmo, /obj/item/clothing/shoes/white, - /obj/item/reagent_containers/glass/beaker/vial, /obj/item/clothing/under/rank/chief_medical_officer/turtleneck) /obj/structure/closet/secure_closet/CMO/Initialize(mapload) diff --git a/code/game/objects/structures/medical_stand_vr.dm b/code/game/objects/structures/medical_stand_vr.dm index 8e7d87d4180..2fb5f1f0f6e 100644 --- a/code/game/objects/structures/medical_stand_vr.dm +++ b/code/game/objects/structures/medical_stand_vr.dm @@ -400,7 +400,7 @@ if(beaker) if(mode) // Give blood if(beaker.volume > 0) - beaker.reagents.trans_to_mob(attached, transfer_amount, CHEM_BLOOD) + beaker.reagents.trans_to_mob(attached, transfer_amount, CHEM_INJECT) update_icon() else // Take blood var/amount = beaker.reagents.maximum_volume - beaker.reagents.total_volume diff --git a/code/game/world.dm b/code/game/world.dm index dab7c370e12..38b5675d35b 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -141,21 +141,13 @@ GLOBAL_LIST(topic_status_cache) var/realtime = world.realtime var/texttime = time2text(realtime, "YYYY/MM/DD") GLOB.log_directory = "data/logs/[texttime]/round-" - GLOB.picture_logging_prefix = "L_[time2text(realtime, "YYYYMMDD")]_" - GLOB.picture_log_directory = "data/picture_logs/[texttime]/round-" if(GLOB.round_id) GLOB.log_directory += "[GLOB.round_id]" - GLOB.picture_logging_prefix += "R_[GLOB.round_id]_" - GLOB.picture_log_directory += "[GLOB.round_id]" else var/timestamp = replacetext(TIME_STAMP("hh:mm:ss", FALSE), ":", ".") GLOB.log_directory += "[timestamp]" - GLOB.picture_log_directory += "[timestamp]" - GLOB.picture_logging_prefix += "T_[timestamp]_" else GLOB.log_directory = "data/logs/[override_dir]" - GLOB.picture_logging_prefix = "O_[override_dir]_" - GLOB.picture_log_directory = "data/picture_logs/[override_dir]" GLOB.world_game_log = "[GLOB.log_directory]/game.log" GLOB.world_asset_log = "[GLOB.log_directory]/asset.log" @@ -166,6 +158,7 @@ GLOBAL_LIST(topic_status_cache) GLOB.world_map_error_log = "[GLOB.log_directory]/map_errors.log" GLOB.world_runtime_log = "[GLOB.log_directory]/runtime.log" GLOB.tgui_log = "[GLOB.log_directory]/tgui.log" + GLOB.world_reagent_log = "[GLOB.log_directory]/reagents.log" GLOB.subsystem_log = "[GLOB.log_directory]/subsystem.log" #ifdef UNIT_TESTS diff --git a/code/modules/cargo/supplypacks/medical.dm b/code/modules/cargo/supplypacks/medical.dm index 22c5bd8ffe7..c5d1ce98766 100644 --- a/code/modules/cargo/supplypacks/medical.dm +++ b/code/modules/cargo/supplypacks/medical.dm @@ -119,7 +119,7 @@ /obj/item/storage/belt/medical, /obj/item/radio/headset/heads/cmo, /obj/item/clothing/under/rank/chief_medical_officer, - /obj/item/reagent_containers/hypospray/vial, + /obj/item/storage/hypokit/advanced/cmo, /obj/item/clothing/accessory/stethoscope, /obj/item/clothing/glasses/hud/health, /obj/item/clothing/suit/storage/toggle/labcoat/cmo, @@ -176,7 +176,8 @@ /obj/item/reagent_containers/dropper, /obj/item/healthanalyzer, /obj/item/storage/box/pillbottles, - /obj/item/reagent_containers/syringe + /obj/item/storage/box/syringes, + /obj/item/storage/hypokit, ) cost = 20 container_type = /obj/structure/closet/crate/secure/nanomed @@ -203,8 +204,8 @@ /obj/item/healthanalyzer, /obj/item/cartridge/medical, /obj/item/flashlight/pen, - /obj/item/reagent_containers/syringe, - /obj/item/clothing/accessory/storage/white_vest + /obj/item/clothing/accessory/storage/white_vest, + /obj/item/storage/hypokit, ) cost = 20 container_type = /obj/structure/closet/crate/secure/nanomed diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm index fffdb756b30..26a4d44c245 100644 --- a/code/modules/clothing/gloves/_gloves.dm +++ b/code/modules/clothing/gloves/_gloves.dm @@ -68,7 +68,7 @@ if(!istype(I, /obj/item/clothing/gloves)) return FALSE - if(clothing_flags & THICKMATERIAL) + if(clothing_flags & CLOTHING_THICK_MATERIAL) return FALSE var/obj/item/clothing/gloves/G = I @@ -81,7 +81,7 @@ if(!istype(I, /obj/item/clothing/gloves)) return FALSE - if(clothing_flags & THICKMATERIAL) + if(clothing_flags & CLOTHING_THICK_MATERIAL) return FALSE var/obj/item/clothing/gloves/G = I diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm index dbcc462ce53..20feab1a510 100644 --- a/code/modules/clothing/gloves/miscellaneous.dm +++ b/code/modules/clothing/gloves/miscellaneous.dm @@ -133,7 +133,7 @@ icon_state = "knuckledusters" matter = list("brass" = 500) attack_verb = list("punched", "beaten", "struck") - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL siemens_coefficient = 1 fingerprint_chance = 100 overgloves = 1 diff --git a/code/modules/clothing/gloves/rings/rings.dm b/code/modules/clothing/gloves/rings/rings.dm index 99df5ffa840..e56bf23c277 100644 --- a/code/modules/clothing/gloves/rings/rings.dm +++ b/code/modules/clothing/gloves/rings/rings.dm @@ -67,7 +67,7 @@ to_chat(H, "You feel a prick as you slip on \the [src].") if(H.reagents) var/contained = reagents.get_reagents() - var/trans = reagents.trans_to_mob(H, 15, CHEM_BLOOD) + var/trans = reagents.trans_to_mob(H, 15, CHEM_INJECT) add_attack_logs(usr, H, "Injected with [name] containing [contained] transferred [trans] units") return diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 818c695a115..808e94c4bcd 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -2,9 +2,9 @@ name = "helmet" desc = "Standard headgear. Protects well enough against a wide range of attacks." icon_state = "helmet" + clothing_flags = CLOTHING_THICK_MATERIAL valid_accessory_slots = ACCESSORY_SLOT_HELM_C|ACCESSORY_SLOT_HELM_R restricted_accessory_slots = ACCESSORY_SLOT_HELM_C|ACCESSORY_SLOT_HELM_R - clothing_flags = THICKMATERIAL armor_type = /datum/armor/station/medium inv_hide_flags = HIDEEARS|BLOCKHEADHAIR cold_protection = HEAD diff --git a/code/modules/clothing/head/hood.dm b/code/modules/clothing/head/hood.dm index bede9fc90b7..c0bc7cfdf91 100644 --- a/code/modules/clothing/head/hood.dm +++ b/code/modules/clothing/head/hood.dm @@ -130,7 +130,7 @@ name = "explorer hood" desc = "An armoured hood for exploring harsh environments." icon_state = "explorer" - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE siemens_coefficient = 0.9 armor_type = /datum/armor/exploration/soft @@ -140,7 +140,7 @@ desc = "An armoured hood for mining in harsh environments." icon = 'icons/clothing/suit/mining.dmi' icon_state = "minehood" - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL worn_render_flags = WORN_RENDER_SLOT_ONE_FOR_ALL min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE siemens_coefficient = 0.9 @@ -151,7 +151,7 @@ name = "eldritch hood" desc = "A baggy hood smeared with some kind of waxy substance. Up close, what appeared to be burlap is revealed to actually be tanned skin." icon_state = "eldritch" - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL siemens_coefficient = 0.9 armor_type = /datum/armor/lavaland/eldritch @@ -234,7 +234,7 @@ icon = 'icons/obj/clothing/spacesuits.dmi' icon_state = "deathsquad" armor_type = /datum/armor/station/heavy - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL inv_hide_flags = BLOCKHAIR siemens_coefficient = 0.7 @@ -245,7 +245,7 @@ icon_state = "helmet" valid_accessory_slots = (ACCESSORY_SLOT_HELM_C) restricted_accessory_slots = (ACCESSORY_SLOT_HELM_C) - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL armor_type = /datum/armor/station/medium siemens_coefficient = 0.7 @@ -256,7 +256,7 @@ icon_state = "helmet" valid_accessory_slots = (ACCESSORY_SLOT_HELM_C) restricted_accessory_slots = (ACCESSORY_SLOT_HELM_C) - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL armor_type = /datum/armor/station/medium siemens_coefficient = 0.7 starting_accessories = list(/obj/item/clothing/accessory/armor/helmcover/navy) diff --git a/code/modules/clothing/head/pilot_helmet.dm b/code/modules/clothing/head/pilot_helmet.dm index 512676753ac..b2031fb6d58 100644 --- a/code/modules/clothing/head/pilot_helmet.dm +++ b/code/modules/clothing/head/pilot_helmet.dm @@ -5,7 +5,7 @@ desc = "Standard pilot gear. Protects the head from impacts." icon_state = "pilot_helmet1" item_icons = list(SLOT_ID_HEAD = 'icons/mob/clothing/pilot_helmet.dmi') - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL armor_type = /datum/armor/exploration/space/pilot inv_hide_flags = HIDEEARS cold_protection = HEAD diff --git a/code/modules/clothing/spacesuits/alien.dm b/code/modules/clothing/spacesuits/alien.dm index 7689c4b2df4..d5a4de6ec22 100644 --- a/code/modules/clothing/spacesuits/alien.dm +++ b/code/modules/clothing/spacesuits/alien.dm @@ -32,7 +32,7 @@ /obj/item/clothing/suit/space/vox w_class = ITEMSIZE_NORMAL atom_flags = PHORONGUARD - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL allowed = list(/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs,/obj/item/tank) armor_type = /datum/armor/vox/space/armored siemens_coefficient = 0.2 @@ -44,7 +44,7 @@ armor_type = /datum/armor/vox/space/armored siemens_coefficient = 0.2 atom_flags = PHORONGUARD - clothing_flags = THICKMATERIAL | ALLOWINTERNALS + clothing_flags = CLOTHING_THICK_MATERIAL | ALLOWINTERNALS inv_hide_flags = 0 species_restricted = list(SPECIES_VOX) diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index 14b32b2af18..1825aea103b 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -39,7 +39,7 @@ icon_state = "deathsquad" item_state_slots = list(SLOT_ID_RIGHT_HAND = "syndicate-helm-black-red", SLOT_ID_LEFT_HAND = "syndicate-helm-black-red") armor_type = /datum/armor/centcom/deathsquad - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL inv_hide_flags = BLOCKHAIR siemens_coefficient = 0.6 diff --git a/code/modules/clothing/spacesuits/spacesuits.dm b/code/modules/clothing/spacesuits/spacesuits.dm index ec2a0ad00d1..df8a64f17e6 100644 --- a/code/modules/clothing/spacesuits/spacesuits.dm +++ b/code/modules/clothing/spacesuits/spacesuits.dm @@ -7,7 +7,7 @@ icon_state = "space" desc = "A special helmet designed for work in a hazardous, low-pressure environment." atom_flags = PHORONGUARD - clothing_flags = THICKMATERIAL | ALLOWINTERNALS | ALLOW_SURVIVALFOOD + clothing_flags = CLOTHING_THICK_MATERIAL | CLOTHING_INJECTION_PORT | ALLOWINTERNALS | ALLOW_SURVIVALFOOD permeability_coefficient = 0.01 armor_type = /datum/armor/general/space inv_hide_flags = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|BLOCKHAIR @@ -70,7 +70,7 @@ gas_transfer_coefficient = 0.01 permeability_coefficient = 0.02 atom_flags = PHORONGUARD - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL | CLOTHING_INJECTION_PORT body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS allowed = list(/obj/item/flashlight,/obj/item/tank/emergency/oxygen,/obj/item/suit_cooling_unit) slowdown = 1 diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 5d65ac5efcd..dbe25654c5d 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -1,7 +1,7 @@ /obj/item/clothing/suit/armor allowed = list(/obj/item/gun/ballistic/sec/flash, /obj/item/gun/energy,/obj/item/reagent_containers/spray/pepper,/obj/item/gun/ballistic,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/handcuffs,/obj/item/flashlight/maglight,/obj/item/clothing/head/helmet) body_cover_flags = UPPER_TORSO|LOWER_TORSO - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL valid_accessory_slots = (\ ACCESSORY_SLOT_OVER\ |ACCESSORY_SLOT_MEDAL\ @@ -138,7 +138,7 @@ item_state_slots = list(SLOT_ID_RIGHT_HAND = "swat", SLOT_ID_LEFT_HAND = "swat") gas_transfer_coefficient = 0.01 permeability_coefficient = 0.01 - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS allowed = list(/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/handcuffs,/obj/item/tank/emergency/oxygen,/obj/item/clothing/head/helmet) slowdown = 1 @@ -304,7 +304,7 @@ allowed = list(/obj/item/gun,/obj/item/reagent_containers/spray/pepper,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/handcuffs,/obj/item/flashlight/maglight,/obj/item/clothing/head/helmet) body_cover_flags = UPPER_TORSO|LOWER_TORSO - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL cold_protection = UPPER_TORSO|LOWER_TORSO min_cold_protection_temperature = ARMOR_MIN_COLD_PROTECTION_TEMPERATURE diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm index 7a1ada49a0e..58777abcd83 100644 --- a/code/modules/clothing/suits/bio.dm +++ b/code/modules/clothing/suits/bio.dm @@ -9,7 +9,7 @@ body_cover_flags = HEAD|FACE|EYES siemens_coefficient = 0.9 atom_flags = PHORONGUARD - clothing_flags = THICKMATERIAL | ALLOW_SURVIVALFOOD + clothing_flags = CLOTHING_THICK_MATERIAL | ALLOW_SURVIVALFOOD /obj/item/clothing/suit/bio_suit name = "bio suit" @@ -25,7 +25,7 @@ inv_hide_flags = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER siemens_coefficient = 0.9 atom_flags = PHORONGUARD - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL //Standard biosuit, orange stripe /obj/item/clothing/head/bio_hood/general @@ -103,7 +103,7 @@ body_cover_flags = HEAD|FACE|EYES siemens_coefficient = 0.9 atom_flags = PHORONGUARD - clothing_flags = THICKMATERIAL | ALLOW_SURVIVALFOOD + clothing_flags = CLOTHING_THICK_MATERIAL | ALLOW_SURVIVALFOOD /obj/item/clothing/suit/beekeeper name = "beekeeping suit" @@ -119,4 +119,4 @@ inv_hide_flags = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER siemens_coefficient = 0.9 atom_flags = PHORONGUARD - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL diff --git a/code/modules/clothing/suits/hooded.dm b/code/modules/clothing/suits/hooded.dm index fc302235a2f..bde0b3b5f05 100644 --- a/code/modules/clothing/suits/hooded.dm +++ b/code/modules/clothing/suits/hooded.dm @@ -430,7 +430,7 @@ icon_state = "explorer" item_state = "explorer" atom_flags = PHORONGUARD - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS @@ -456,7 +456,7 @@ icon_state = "miner" atom_flags = PHORONGUARD worn_render_flags = WORN_RENDER_SLOT_ONE_FOR_ALL - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS @@ -482,7 +482,7 @@ name = "eldritch garment" desc = "A billowing garment that seeps a thick, waxy substance. Upon closer inspection this outfit is crafted out of tanned skin, the ritual icons and spells drawn onto it having been tattooed before removal." icon_state = "eldritch_armor" - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL inv_hide_flags = HIDEHOLSTER item_state_slots = list(SLOT_ID_RIGHT_HAND = "brown_jacket", SLOT_ID_LEFT_HAND = "brown_jacket") action_button_name = "Toggle Eldritch Hood" diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm index 5bd57769374..fe85ebfac38 100644 --- a/code/modules/clothing/suits/utility.dm +++ b/code/modules/clothing/suits/utility.dm @@ -82,7 +82,7 @@ icon_state = "rad" desc = "A hood with radiation protective properties. Label: Made with lead, do not eat insulation" inv_hide_flags = BLOCKHAIR - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL body_cover_flags = HEAD|FACE|EYES armor_type = /datum/armor/general/radsuit @@ -98,4 +98,4 @@ slowdown = 1.5 armor_type = /datum/armor/general/radsuit inv_hide_flags = HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL diff --git a/code/modules/detectivework/tools/rag.dm b/code/modules/detectivework/tools/rag.dm index 56046b2aeb7..51825b1e590 100644 --- a/code/modules/detectivework/tools/rag.dm +++ b/code/modules/detectivework/tools/rag.dm @@ -135,8 +135,8 @@ SPAN_WARNING("You smother [L] with [src]!"), "You hear some struggling and muffled cries of surprise" ) - //it's inhaled, so... maybe CHEM_BLOOD doesn't make a whole lot of sense but it's the best we can do for now - reagents.trans_to_mob(L, amount_per_transfer_from_this, CHEM_BLOOD) + //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 + reagents.trans_to_mob(L, amount_per_transfer_from_this, CHEM_INJECT) update_name() else to_chat(user, SPAN_WARNING("You can't smother this creature.")) diff --git a/code/modules/examine/descriptions/armor.dm b/code/modules/examine/descriptions/armor.dm index d7434a032fd..304969d7397 100644 --- a/code/modules/examine/descriptions/armor.dm +++ b/code/modules/examine/descriptions/armor.dm @@ -18,7 +18,7 @@ if(max_pressure_protection != null) armor_stats += "Wearing this will protect you from high pressures.
" - if(clothing_flags & THICKMATERIAL) + if(clothing_flags & CLOTHING_THICK_MATERIAL) armor_stats += "The material is exceptionally thick.
" if(max_heat_protection_temperature == FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE) diff --git a/code/modules/food/glass/bottle.dm b/code/modules/food/glass/bottle.dm index 2077cff92c7..76736ada995 100644 --- a/code/modules/food/glass/bottle.dm +++ b/code/modules/food/glass/bottle.dm @@ -7,6 +7,7 @@ icon = 'icons/obj/medical/chemical.dmi' icon_state = null item_state = "atoxinbottle" + w_class = WEIGHT_CLASS_SMALL amount_per_transfer_from_this = 10 possible_transfer_amounts = list(5,10,15,25,30,60) atom_flags = 0 diff --git a/code/modules/hydroponics/seed.dm b/code/modules/hydroponics/seed.dm index b90c5aa4cdc..1553cfa6920 100644 --- a/code/modules/hydroponics/seed.dm +++ b/code/modules/hydroponics/seed.dm @@ -156,7 +156,7 @@ for(var/obj/item/clothing/clothes in target) if(target.is_holding(clothes)) return - if(clothes.clothing_flags & THICKMATERIAL) + if(clothes.clothing_flags & CLOTHING_THICK_MATERIAL) body_coverage &= ~(clothes.body_cover_flags) if(!body_coverage) diff --git a/code/modules/materials/material_sheets.dm b/code/modules/materials/material_sheets.dm index b8c2ee6715c..7cb1ce93b46 100644 --- a/code/modules/materials/material_sheets.dm +++ b/code/modules/materials/material_sheets.dm @@ -297,7 +297,7 @@ if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = user var/obj/item/clothing/gloves/G = H.gloves - if(istype(G) && ((G.clothing_flags & THICKMATERIAL && prob(70)) || istype(G, /obj/item/clothing/gloves/gauntlets))) + if(istype(G) && ((G.clothing_flags & CLOTHING_THICK_MATERIAL && prob(70)) || istype(G, /obj/item/clothing/gloves/gauntlets))) burn_user = FALSE if(burn_user) diff --git a/code/modules/mob/action_feedback.dm b/code/modules/mob/action_feedback.dm index 19d5b55a7f2..92c19d3c0d5 100644 --- a/code/modules/mob/action_feedback.dm +++ b/code/modules/mob/action_feedback.dm @@ -53,11 +53,17 @@ visible_message(others, self, blind, range) /** - * gives feedback for something a mob can innately feel + * gives feedback for something a mob can innately feel, body or not. */ /mob/proc/innate_feedback(msg) to_chat(src, msg) +/** + * gives feedback for something a mob can physically feel on their body. + */ +/mob/proc/tactile_feedback(msg) + to_chat(src, msg) + /** * gives feedback for an ui click */ diff --git a/code/modules/mob/inventory/hands.dm b/code/modules/mob/inventory/hands.dm index c6f1f81b3b3..67c8d278b1d 100644 --- a/code/modules/mob/inventory/hands.dm +++ b/code/modules/mob/inventory/hands.dm @@ -1,3 +1,5 @@ +// todo: we need a set of 'core' procs subtypes need to override, and the rest are composites of those procs. + /mob/proc/put_in_hands(obj/item/I, flags) if(is_holding(I)) return TRUE @@ -169,6 +171,12 @@ /mob/proc/is_holding(obj/item/I) return !!get_held_index(I) +/** + * returns if we're holding something in inactive hand slots + */ +/mob/proc/is_holding_inactive(obj/item/I) + return is_holding(I) && (get_active_held_item() != I) + /** * drops all our held items * diff --git a/code/modules/mob/living/bot/medibot.dm b/code/modules/mob/living/bot/medibot.dm index d57139e2a2a..a3167ab0358 100644 --- a/code/modules/mob/living/bot/medibot.dm +++ b/code/modules/mob/living/bot/medibot.dm @@ -186,7 +186,7 @@ update_appearance() if(do_mob(src, victim, 30)) if(t == 1) - reagent_glass.reagents.trans_to_mob(victim, injection_amount, CHEM_BLOOD) + reagent_glass.reagents.trans_to_mob(victim, injection_amount, CHEM_INJECT) else victim.reagents.add_reagent(t, injection_amount) visible_message(SPAN_WARNING("[src] injects [victim] with the syringe!")) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 53b709f4a28..ef95cf34191 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1285,10 +1285,10 @@ else switch(target_zone) if(BP_HEAD) //If targeting head, check helmets - if(head && (head.clothing_flags & THICKMATERIAL) && !ignore_thickness && !istype(head, /obj/item/clothing/head/helmet/space)) //If they're wearing a head piece, if that head piece is thick, the injector doesn't bypass thickness, and that headpiece isn't a space helmet with an injection port - it fails + if(head && (head.clothing_flags & CLOTHING_THICK_MATERIAL) && !ignore_thickness && !istype(head, /obj/item/clothing/head/helmet/space)) //If they're wearing a head piece, if that head piece is thick, the injector doesn't bypass thickness, and that headpiece isn't a space helmet with an injection port - it fails . = 0 else //Otherwise, if not targeting head, check the suit - if(wear_suit && (wear_suit.clothing_flags & THICKMATERIAL) && !ignore_thickness&& !istype(wear_suit, /obj/item/clothing/suit/space)) //If they're wearing a suit piece, if that suit piece is thick, the injector doesn't bypass thickness, and that suit isn't a space suit with an injection port - it fails + if(wear_suit && (wear_suit.clothing_flags & CLOTHING_THICK_MATERIAL) && !ignore_thickness&& !istype(wear_suit, /obj/item/clothing/suit/space)) //If they're wearing a suit piece, if that suit piece is thick, the injector doesn't bypass thickness, and that suit isn't a space suit with an injection port - it fails . = 0 if(!. && error_msg && user) if(!fail_msg) diff --git a/code/modules/organs/internal/subtypes/brain.dm b/code/modules/organs/internal/subtypes/brain.dm index 7109b0269cd..312f65a176a 100644 --- a/code/modules/organs/internal/subtypes/brain.dm +++ b/code/modules/organs/internal/subtypes/brain.dm @@ -277,13 +277,11 @@ name = "Promethean Revival" id = "prom_revival" result = null - required_reagents = list(MAT_PHORON = 40) + required_reagents = list( + /datum/reagent/toxin/phoron = 40, + ) result_amount = 1 - -/datum/chemical_reaction/promethean_brain_revival/can_happen(datum/reagents/holder) - if(holder.my_atom && istype(holder.my_atom, /obj/item/organ/internal/brain/slime)) - return ..() - return FALSE + required_container = /obj/item/organ/internal/brain/slime /datum/chemical_reaction/promethean_brain_revival/on_reaction(datum/reagents/holder) var/obj/item/organ/internal/brain/slime/brain = holder.my_atom diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index e2a0ba9485b..dc34db77f48 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -125,7 +125,7 @@ if(reagents.total_volume) if(target.reagents) var/contained = reagents.get_reagents() - var/trans = reagents.trans_to_mob(target, 30, CHEM_BLOOD) + var/trans = reagents.trans_to_mob(target, 30, CHEM_INJECT) add_attack_logs(user,target,"Injected with [src.name] containing [contained], trasferred [trans] units") /* diff --git a/code/modules/projectiles/guns/launcher/syringe_gun.dm b/code/modules/projectiles/guns/launcher/syringe_gun.dm index 4c30191b72d..494f5587aa6 100644 --- a/code/modules/projectiles/guns/launcher/syringe_gun.dm +++ b/code/modules/projectiles/guns/launcher/syringe_gun.dm @@ -55,7 +55,7 @@ //unfortuately we don't know where the dart will actually hit, since that's done by the parent. if(L.can_inject() && syringe.reagents) var/contained = syringe.reagents.get_reagents() - var/trans = syringe.reagents.trans_to_mob(L, 15, CHEM_BLOOD) + var/trans = syringe.reagents.trans_to_mob(L, 15, CHEM_INJECT) add_attack_logs(TT.thrower,L,"Shot with [src.name] containing [contained], trasferred [trans] units") syringe.break_syringe(iscarbon(A)? A : null) diff --git a/code/modules/projectiles/guns/projectile/dartgun.dm b/code/modules/projectiles/guns/projectile/dartgun.dm index 04d259c011c..29864fe4560 100644 --- a/code/modules/projectiles/guns/projectile/dartgun.dm +++ b/code/modules/projectiles/guns/projectile/dartgun.dm @@ -15,7 +15,7 @@ if(blocked < 2 && isliving(target)) var/mob/living/L = target if(L.can_inject(target_zone=def_zone)) - reagents.trans_to_mob(L, reagent_amount, CHEM_BLOOD) + reagents.trans_to_mob(L, reagent_amount, CHEM_INJECT) /obj/item/ammo_casing/chemdart name = "chemical dart" diff --git a/code/modules/reagents/chemistry/_readme.dm b/code/modules/reagents/chemistry/_readme.dm index 5d07cb8b43d..5572cce78fe 100644 --- a/code/modules/reagents/chemistry/_readme.dm +++ b/code/modules/reagents/chemistry/_readme.dm @@ -118,7 +118,7 @@ About the Holder: Checks mob's clothing if [clothes] is 1 and transfers [amount] reagents to mob's skin. Don't call this directly. Call apply_to() instead. - trans_to_mob(mob/target, amount = 1, type = CHEM_BLOOD, multiplier = 1, copy = 0) + trans_to_mob(mob/target, amount = 1, type = CHEM_INJECT, multiplier = 1, copy = 0) Transfers [amount] reagents to the mob's appropriate holder, depending on [type]. Ignores protection. trans_to_turf(turf/target, amount = 1, multiplier = 1, copy = 0) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 4e3651a471e..c0f9ad14a0e 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -147,7 +147,7 @@ current.volume += amount if(!isnull(data)) // For all we know, it could be zero or empty string and meaningful - current.mix_data(data, amount) + current.mix_data(src, current.data, current.volume, data, amount) update_total() if(!safety) handle_reactions() @@ -397,12 +397,12 @@ perm = L.reagent_permeability() return trans_to_mob(target, amount, CHEM_TOUCH, perm, copy) -/datum/reagents/proc/trans_to_mob(mob/target, amount = 1, type = CHEM_BLOOD, multiplier = 1, copy = 0) // Transfer after checking into which holder... +/datum/reagents/proc/trans_to_mob(mob/target, amount = 1, type = CHEM_INJECT, multiplier = 1, copy = 0) // Transfer after checking into which holder... if(!target || !istype(target)) return if(iscarbon(target)) var/mob/living/carbon/C = target - if(type == CHEM_BLOOD) + if(type == CHEM_INJECT) var/datum/reagents/R = C.reagents return trans_to_holder(R, amount, multiplier, copy) if(type == CHEM_INGEST) diff --git a/code/modules/reagents/chemistry/metabolism.dm b/code/modules/reagents/chemistry/metabolism.dm index a6878785735..4de7a6acc4b 100644 --- a/code/modules/reagents/chemistry/metabolism.dm +++ b/code/modules/reagents/chemistry/metabolism.dm @@ -1,5 +1,5 @@ /datum/reagents/metabolism - var/metabolism_class //CHEM_TOUCH, CHEM_INGEST, or CHEM_BLOOD + var/metabolism_class //CHEM_TOUCH, CHEM_INGEST, or CHEM_INJECT var/metabolism_speed = 1 // Multiplicative, 1 is full speed, 0.5 is half, etc. var/mob/living/carbon/parent @@ -24,7 +24,7 @@ // "Specialized" metabolism datums /datum/reagents/metabolism/bloodstream - metabolism_class = CHEM_BLOOD + metabolism_class = CHEM_INJECT /datum/reagents/metabolism/ingested metabolism_class = CHEM_INGEST diff --git a/code/modules/reagents/chemistry/reaction.dm b/code/modules/reagents/chemistry/reaction.dm index 29ebc9f5cdb..a5b41f0c714 100644 --- a/code/modules/reagents/chemistry/reaction.dm +++ b/code/modules/reagents/chemistry/reaction.dm @@ -1,17 +1,30 @@ +/proc/cmp_chemical_reaction_priority(datum/chemical_reaction/A, datum/chemical_reaction/B) + return B.priority - A.priority + /datum/chemical_reaction - //? core + abstract_type = /datum/chemical_reaction + //* core *// /// id - must be unique and in CamelCase. var/id /// reagent reaction flags - see [code/__DEFINES/reagents/flags.dm] var/chemical_reaction_flags = NONE + //* reaction *// + /// required reagents as ratios. path or id is supported, prefer paths for compile time checking. + var/list/required_reagents = list() + /// result reagent path or id. prefer path for compile time checking. + var/result + /// how much of the result is made per 1 ratio of required_reagents consumed. + var/result_amount = 0 + /// priority - higher is checked first when reacting. + var/priority = 0 + /// required container typepath of holder my_atom + var/required_container + //? legacy / unsorted var/name = null - var/result = null - var/list/required_reagents = list() var/list/catalysts = list() var/list/inhibitors = list() - var/result_amount = 0 //how far the reaction proceeds each time it is processed. Used with either REACTION_RATE or HALF_LIFE macros. var/reaction_rate = HALF_LIFE(0) @@ -29,7 +42,40 @@ var/log_is_important = 0 // If this reaction should be considered important for logging. Important recipes message admins when mixed, non-important ones just log to file. +/datum/chemical_reaction/New() + for(var/i in 1 to length(required_reagents)) + var/datum/reagent/path = required_reagents[i] + if(!ispath(path)) + continue + var/amt = required_reagents[path] + var/id = initial(path.id) + required_reagents[i] = id + required_reagents[id] = amt + for(var/i in 1 to length(catalysts)) + var/datum/reagent/path = catalysts[i] + if(!ispath(path)) + continue + var/amt = catalysts[path] + var/id = initial(path.id) + catalysts[i] = id + catalysts[id] = amt + for(var/i in 1 to length(inhibitors)) + var/datum/reagent/path = inhibitors[i] + if(!ispath(path)) + continue + var/amt = inhibitors[path] + var/id = initial(path.id) + inhibitors[i] = id + inhibitors[id] = amt + if(ispath(result, /datum/reagent)) + var/datum/reagent/result_initial = result + result = initial(result_initial.id) + /datum/chemical_reaction/proc/can_happen(datum/reagents/holder) + // check container + if(!isnull(required_container) && !istype(holder.my_atom, required_container)) + return FALSE + //check that all the required reagents are present if(!holder.has_all_reagents(required_reagents)) return 0 @@ -124,30 +170,6 @@ //Standard First Aid Medication -/datum/chemical_reaction/inaprovaline - //Helps the patient breath in shock, very weak painkiller, and reduces bleeding - name = "Inaprovaline" - id = "inaprovaline" - result = "inaprovaline" - required_reagents = list("oxygen" = 1, MAT_CARBON = 1, "sugar" = 1) - result_amount = 3 - -/datum/chemical_reaction/tricordrazine - //Heals the four standards slowly - name = "Tricordrazine" - id = "tricordrazine" - result = "tricordrazine" - required_reagents = list("inaprovaline" = 1, "anti_toxin" = 1) - result_amount = 2 - -/datum/chemical_reaction/dylovene - //Heals toxin - name = "Dylovene" - id = "anti_toxin" - result = "anti_toxin" - required_reagents = list("silicon" = 1, "potassium" = 1, "nitrogen" = 1) - result_amount = 3 - /datum/chemical_reaction/carthatoline //heals toxin name = "Carthatoline" @@ -210,8 +232,6 @@ required_reagents = list("dexalin" = 1, MAT_CARBON = 1, MAT_IRON = 1) result_amount = 3 - - //Painkiller /datum/chemical_reaction/paracetamol @@ -256,20 +276,12 @@ //The Daxon Family -/datum/chemical_reaction/peridaxon - //Heals all organs - name = "Peridaxon" - id = "peridaxon" - result = "peridaxon" - required_reagents = list("bicaridine" = 2, "clonexadone" = 2) - catalysts = list(MAT_PHORON = 5) - result_amount = 2 - /datum/chemical_reaction/nanoperidaxon //Heals ALL organs name = "Nano-Peridaxon" id = "nanoperidaxon" result = "nanoperidaxon" + priority = 100 required_reagents = list("peridaxon" = 2, "nifrepairnanites" = 2) result_amount = 2 @@ -278,6 +290,7 @@ name = "Osteodaxon" id = "osteodaxon" result = "osteodaxon" + priority = 100 required_reagents = list("bicaridine" = 2, MAT_PHORON = 0.1, "carpotoxin" = 1) catalysts = list(MAT_PHORON = 5) inhibitors = list("clonexadone" = 1) // Messes with cryox @@ -288,6 +301,7 @@ name = "Respirodaxon" id = "respirodaxon" result = "respirodaxon" + priority = 100 required_reagents = list("dexalinp" = 2, "biomass" = 2, MAT_PHORON = 1) catalysts = list(MAT_PHORON = 5) inhibitors = list("dexalin" = 1) @@ -298,6 +312,7 @@ name = "Gastirodaxon" id = "gastirodaxon" result = "gastirodaxon" + priority = 100 required_reagents = list("carthatoline" = 1, "biomass" = 2, "tungsten" = 2) catalysts = list(MAT_PHORON = 5) inhibitors = list("lithium" = 1) @@ -308,6 +323,7 @@ name = "Hepanephrodaxon" id = "hepanephrodaxon" result = "hepanephrodaxon" + priority = 100 required_reagents = list("carthatoline" = 2, "biomass" = 2, "lithium" = 1) catalysts = list(MAT_PHORON = 5) inhibitors = list("tungsten" = 1) @@ -318,6 +334,7 @@ name = "Cordradaxon" id = "cordradaxon" result = "cordradaxon" + priority = 100 required_reagents = list("potassium_chlorophoride" = 1, "biomass" = 2, "bicaridine" = 2) catalysts = list(MAT_PHORON = 5) inhibitors = list("clonexadone" = 1) diff --git a/code/modules/reagents/chemistry/reagent.dm b/code/modules/reagents/chemistry/reagent.dm index d3ba6810349..ccb2844468f 100644 --- a/code/modules/reagents/chemistry/reagent.dm +++ b/code/modules/reagents/chemistry/reagent.dm @@ -132,7 +132,7 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) if(ishuman(M)) var/mob/living/carbon/human/H = M if(!H.isSynthetic()) - if(H.species.has_organ[O_HEART] && (active_metab.metabolism_class == CHEM_BLOOD)) + if(H.species.has_organ[O_HEART] && (active_metab.metabolism_class == CHEM_INJECT)) var/obj/item/organ/internal/heart/Pump = H.internal_organs_by_name[O_HEART] // todo: completely optimize + refactor metabolism, none of these checks should be in here if(mechanical_circulation) @@ -162,7 +162,7 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) var/obj/item/organ/internal/heart/machine/Pump = H.internal_organs_by_name[O_PUMP] var/obj/item/organ/internal/stomach/machine/Cycler = H.internal_organs_by_name[O_CYCLER] - if(active_metab.metabolism_class == CHEM_BLOOD) + if(active_metab.metabolism_class == CHEM_INJECT) if(Pump) removed *= 1.1 - Pump.damage / Pump.max_damage else @@ -201,7 +201,7 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) dose = min(dose + removed, max_dose) if(removed >= (metabolism * 0.1) || removed >= 0.1) // If there's too little chemical, don't affect the mob, just remove it switch(active_metab.metabolism_class) - if(CHEM_BLOOD) + if(CHEM_INJECT) affect_blood(M, alien, removed) if(CHEM_INGEST) affect_ingest(M, alien, removed * ingest_abs_mult) @@ -212,13 +212,21 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) remove_self(removed) return +// todo: on_mob_life with method of CHEM_INJECT, or tick_mob_blood /datum/reagent/proc/affect_blood(mob/living/carbon/M, alien, removed) return +// todo: on_mob_life with method of CHEM_INGEST, or tick_mob_ingest /datum/reagent/proc/affect_ingest(mob/living/carbon/M, alien, removed) M.bloodstr.add_reagent(id, removed) return +// todo: on_mob_life with method of CHEM_TOUCH, or tick_mob_touch +/datum/reagent/proc/affect_touch(mob/living/carbon/M, alien, removed) + return + +// todo: fourth apply method of CHEM_VAPOR implementation? + /datum/reagent/proc/handle_vampire(var/mob/living/carbon/M, var/alien, var/removed, var/is_vampire) if(blood_content > 0 && is_vampire) #define blud_warn_timer 3000 @@ -230,9 +238,6 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) return M.nutrition += removed * blood_content //We should always be able to process real blood. -/datum/reagent/proc/affect_touch(mob/living/carbon/M, alien, removed) - return - /datum/reagent/proc/overdose(var/mob/living/carbon/M, var/alien, var/removed) // Overdose effect. if(alien == IS_DIONA) return @@ -246,9 +251,6 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) data = newdata return -/datum/reagent/proc/mix_data(var/newdata, var/newamount) // You have a reagent with data, and new reagent with its own data get added, how do you deal with that? - return - /datum/reagent/proc/get_data() // Just in case you have a reagent that handles data differently. if(data && istype(data, /list)) return data.Copy() @@ -276,3 +278,60 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) /datum/reagent/proc/on_update(atom/A) return + +/** + * called when we first get applied to a mob + * + * @params + * * target - target mob + * * holder - the holder on the target mob + * * method - an enum of how we're applied from [code/__DEFINES/chemistry.dm] + * * amount - how much is being applied + * * data - data. not necessarily a list, but casted as one. this is before mix_data is called. + * + * @return amount to inject into the mob side holder. defaults to amount. this can be overriden by the mob / transfer procs. + */ +// todo: implement this proc, replace reaction mob and similar with it. +// /datum/reagent/proc/apply_to_mob(mob/target, datum/reagents/holder, amount, list/data) +// return amount + +/** + * called when we first get sprayed/splashed on a non-mob + * + * not called if we're transferred into a holder on the obj + * + * @params + * * target - the target. + * * amount - how much is being applied + * * data - data. not necessarily a list, but casted as one. this is before mix_data is caled. + */ +// todo: implement this proc, replace touch_obj/reaction_obj and similar with it. +// /datum/reagent/proc/apply_to_obj(obj/target, amount, list/data) + +/** + * called when we first get sprayed/splashed on a turf + * + * not called if we're transferred into a holder on the turf, somehow + * + * @params + * * target - the target. + * * amount - how much is being applied + * * data - data. not necessarily a list, but casted as one. this is before mix_data is caled. + */ +// todo: implement this proc, replace touch_turf/reaction_turf and similar with it. +// /datum/reagent/proc/apply_to_turf(turf/target, amount, list/data) + +/** + * called when a new reagent is being mixed with this one to mix our data lists. + * + * this may not be called if the data is the exact same! + * + * @params + * * holder - (optional) the holder we're mixing in, if any. + * * current_data - our current data. not necessarily a list, only typecasted to one. + * * current_amount - our current amount + * * new_data - new inbound data. not necessarily a list, only typedcasted to one. + * * new_amount - the amount that's coming in, not what we will be at after mixing. + */ +/datum/reagent/proc/mix_data(datum/reagents/holder, list/current_data, current_amount, list/new_data, new_amount) + return diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm new file mode 100644 index 00000000000..e3c8d12e03c --- /dev/null +++ b/code/modules/reagents/chemistry/recipes/medicine.dm @@ -0,0 +1,46 @@ +/datum/chemical_reaction/dylovene + name = "Dylovene" + id = "anti_toxin" + result = /datum/reagent/dylovene + required_reagents = list( + /datum/reagent/silicon = 1, + /datum/reagent/potassium = 1, + /datum/reagent/nitrogen = 1, + ) + result_amount = 3 + +/datum/chemical_reaction/inaprovaline + name = "Inaprovaline" + id = "inaprovaline" + result = /datum/reagent/inaprovaline + required_reagents = list( + /datum/reagent/oxygen = 1, + /datum/reagent/carbon = 1, + /datum/reagent/sugar = 1, + ) + result_amount = 3 + priority = 50 + +/datum/chemical_reaction/tricordrazine + name = "Tricordrazine" + id = "tricordrazine" + result = /datum/reagent/tricordrazine + required_reagents = list( + /datum/reagent/inaprovaline = 1, + /datum/reagent/dylovene = 1, + ) + result_amount = 2 + +/datum/chemical_reaction/peridaxon + name = "Peridaxon" + id = "peridaxon" + result = /datum/reagent/peridaxon + required_reagents = list( + /datum/reagent/bicaridine = 2, + /datum/reagent/clonexadone = 2, + ) + catalysts = list( + /datum/reagent/toxin/phoron = 5, + ) + result_amount = 2 + priority = 100 diff --git a/code/modules/reagents/items/hypospray.dm b/code/modules/reagents/items/hypospray.dm new file mode 100644 index 00000000000..1af01a93897 --- /dev/null +++ b/code/modules/reagents/items/hypospray.dm @@ -0,0 +1,243 @@ +/obj/item/hypospray + name = "hypospray" + desc = "A standard issue prototype hypospray that allows for the quick, sterile application of medications both dermally and directly to the bloodstream." + description_fluff = "While technically still a prototype due to its unique two-mode applicator, this model - and others like it - have been floating around space for almost a century.\n \ + Hardened, low-power electronics allow for it to optimize an injection sequence when the trigger is pulled on the fly, avoiding the need to directly aim for a vein - though a skilled user still tends to have faster operation cycles by far.\n \ + Initially developed in a joint venture between Nanotrasen and Vey-Med, the designs quickly proliferated due to their immense usefulness - and were subsequently leaked. \ + Nowadays, one can expect this model to be on all but the most backwater colonies and installations." + icon = 'icons/modules/reagents/items/hypospray.dmi' + icon_state = "hypo" + inhand_state = "hypo" + w_class = WEIGHT_CLASS_SMALL + drop_sound = 'sound/items/drop/gun.ogg' + pickup_sound = 'sound/items/pickup/gun.ogg' + worn_render_flags = NONE + + /// loaded vial + var/obj/item/reagent_containers/glass/hypovial/loaded + /// allow large vials + var/allow_large = FALSE + /// standard injection delay + var/injection_time = 1 SECONDS + /// delay add if person is resisting. null to disallow inject. + var/resist_add_time = 2 SECONDS + /// delay add to injection port items (like hardsuits). null to disallow inject. overriden by thick_add_time. + var/port_add_time = 1 SECONDS + /// delay add to thickmaterial suits. null to disallow inject. overrides port_add_time. + var/thick_add_time = null + /// injection amount + var/inject_amount = 5 + /// max injection level + var/inject_max = 10 + /// injection mode + var/inject_mode = HYPOSPRAY_MODE_INJECT + /// can people change how much to inject? + var/inject_adjustable = TRUE + +/obj/item/hypospray/Initialize(mapload) + . = ..() + if(ispath(loaded)) + loaded = new loaded(src) + update_icon() + +/obj/item/hypospray/examine(mob/user) + . = ..() + if(get_dist(get_turf(src), user) <= 1) + if(!isnull(loaded)) + . += SPAN_NOTICE("Its vial has [loaded.reagents.total_volume] units remaining.") + else + . += SPAN_NOTICE("It's unloaded.") + +/obj/item/hypospray/update_icon_state() + var/vial_state + if(!isnull(loaded)) + if(istype(loaded, /obj/item/reagent_containers/glass/hypovial/bluespace)) + vial_state = "-l-bs" + else + vial_state = "-l" + icon_state = "[initial(icon_state)][vial_state]" + return ..() + +/obj/item/hypospray/attack_hand(mob/user, list/params) + if(user.is_holding_inactive(src)) + if(isnull(loaded)) + user.action_feedback(SPAN_WARNING("[src] has no vial loaded."), src) + return CLICKCHAIN_DO_NOT_PROPAGATE + user.put_in_hands_or_drop(loaded) + user.action_feedback(SPAN_NOTICE("You remove [loaded] from [src]."), src) + loaded = null + playsound(src, 'sound/weapons/empty.ogg', 50, FALSE) + update_icon() + return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING + return ..() + +/obj/item/hypospray/attackby(obj/item/I, mob/living/user, list/params, clickchain_flags, damage_multiplier) + if(istype(I, /obj/item/reagent_containers/glass/hypovial)) + var/obj/item/reagent_containers/glass/hypovial/vial = I + if(!user.transfer_item_to_loc(vial, src)) + user.action_feedback(SPAN_WARNING("[vial] is stuck to your hand!"), src) + return CLICKCHAIN_DO_NOT_PROPAGATE + var/obj/item/reagent_containers/glass/hypovial/old_vial = loaded + loaded = vial + if(!isnull(old_vial)) + user.action_feedback(SPAN_NOTICE("You quickly swap [old_vial] with [vial]."), src) + user.put_in_hands_or_drop(old_vial) + else + user.action_feedback(SPAN_NOTICE("You insert [vial] into [src]."), src) + playsound(src, 'sound/weapons/autoguninsert.ogg', 50, FALSE) + update_icon() + return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING + return ..() + +// todo: alt click context radials? +/obj/item/hypospray/verb/set_transfer_amount() + set name = "Set Injection Amount" + set category = "Object" + + if(!inject_adjustable) + usr.action_feedback(SPAN_WARNING("[src] can't have its injection thresholds changed."), src) + return + var/amount = input(usr, "Set how much you want to inject per use.", "Injection Amount", inject_amount) as num|null + if(isnull(amount)) + return + amount = round(amount, 1) + amount = clamp(amount, 1, inject_max) + inject_amount = amount + usr.action_feedback(SPAN_NOTICE("[src] is now set to inject [amount] per use."), src) + +/obj/item/hypospray/attack_self(mob/user) + switch(inject_mode) + if(HYPOSPRAY_MODE_INJECT) + inject_mode = HYPOSPRAY_MODE_SPRAY + if(HYPOSPRAY_MODE_SPRAY) + inject_mode = HYPOSPRAY_MODE_INJECT + switch(inject_mode) + if(HYPOSPRAY_MODE_INJECT) + user.action_feedback(SPAN_NOTICE("[src] is now set to subdermal injection."), src) + if(HYPOSPRAY_MODE_SPRAY) + user.action_feedback(SPAN_NOTICE("[src] is now set to surface spray."), src) + playsound(src, 'sound/effects/pop.ogg', 50, 0) + +// todo: alt click context radials? +/obj/item/hypospray/AltClick(mob/user) + if(!inject_adjustable) + user.action_feedback(SPAN_WARNING("[src] can't have its injection thresholds changed."), src) + return + inject_amount = (inject_amount + 5 > inject_max)? min(5, inject_max) : inject_amount + 5 + user.action_feedback(SPAN_NOTICE("[src] is now set to inject [inject_amount] per use."), src) + +/obj/item/hypospray/attack_mob(mob/target, mob/user, clickchain_flags, list/params, mult, target_zone, intent) + if(injection_checks(target, user, target_zone)) + do_inject(target, user) + return CLICKCHAIN_DID_SOMETHING | CLICKCHAIN_DO_NOT_PROPAGATE + return CLICKCHAIN_DO_NOT_PROPAGATE + +/obj/item/hypospray/proc/injection_checks(mob/target, mob/user, target_zone, speed_mult = 1, silent = FALSE) + // todo: legacy cast, get organ/etc should be on mob level maybe. + var/mob/living/L = target + if(!istype(L)) + user.action_feedback(SPAN_WARNING("[target] isn't injectable."), src) + return FALSE + if(!loaded?.reagents?.total_volume) + user.action_feedback(SPAN_WARNING("[src]'s vial is empty."), src) + return FALSE + var/obj/item/organ/external/limb = L.get_organ(target_zone || BP_HEAD) + if(isnull(limb)) + user.action_feedback(SPAN_WARNING("[target] doesn't have that limb."), src) + return FALSE + var/inject_verb + var/inject_message + switch(inject_mode) + if(HYPOSPRAY_MODE_INJECT) + inject_verb = "inject" + if(HYPOSPRAY_MODE_SPRAY) + inject_verb = "spray" + inject_message = "[user] starts to [inject_verb] [target] with \the [src]." + var/block_flags = NONE + for(var/obj/item/I as anything in target.inventory.items_that_cover(limb.body_part_flags)) + block_flags |= (I.clothing_flags & (CLOTHING_THICK_MATERIAL | CLOTHING_INJECTION_PORT)) + // got all coverage, proceed. + var/delay = injection_time + if(block_flags & CLOTHING_THICK_MATERIAL) + if(isnull(thick_add_time)) + user.action_feedback(SPAN_WARNING("[src] can't [inject_verb] through something that thick!"), src) + return FALSE + delay += thick_add_time + // todo: 'friendly name' so limbs can stay concealed of their true names while under clothing? + inject_message = SPAN_WARNING("[user] starts to dig [src] up against [target]'s [limb]!") + else if(block_flags & CLOTHING_INJECTION_PORT) + if(isnull(thick_add_time)) + user.action_feedback(SPAN_WARNING("[src] is not compatible with injection ports!"), src) + return FALSE + delay += port_add_time + // todo: 'friendly name' so limbs can stay concealed of their true names while under clothing? + inject_message = SPAN_NOTICE("[user] starts to search for an injection port on [target]'s [limb].") + if(target.a_intent != INTENT_HELP) + if(isnull(resist_add_time)) + user.action_feedback(SPAN_WARNING("[src] is not capable of aligning while [target] is resisting! (Non-help intent)"), src) + return FALSE + delay += resist_add_time + // todo: 'friendly name' so limbs can stay concealed of their true names while under clothing? + inject_message = SPAN_WARNING("[user] starts to intrusively align [src] up against [target]'s [limb]!") + if(!silent) + user.visible_action_feedback(inject_message, target, MESSAGE_RANGE_COMBAT_SUPPRESSED) + if(!do_after(user, delay, target, mobility_flags = MOBILITY_CAN_USE)) + return FALSE + if(!loaded?.reagents?.total_volume) + return FALSE + return TRUE + +/obj/item/hypospray/proc/do_inject(mob/target, mob/user, mode = inject_mode, silent = FALSE) + if(!loaded.reagents.total_volume) + return + var/logstr = "[inject_amount] of [loaded.reagents.log_list()]" + if(user) + add_attack_logs(user, target, "injected with [logstr]") + log_reagent("hypospray: [user] -> [target] using [mode]: [logstr]") + var/where_str + switch(mode) + if(HYPOSPRAY_MODE_INJECT) + loaded.reagents.trans_to_mob(target, inject_amount, CHEM_INJECT) + where_str = "rushing into your veins" + if(HYPOSPRAY_MODE_SPRAY) + loaded.reagents.trans_to_mob(target, inject_amount, CHEM_TOUCH) + where_str = "on your skin" + playsound(src, 'sound/items/hypospray2.ogg', 50, TRUE, -1) + target.tactile_feedback(SPAN_WARNING("You feel a tiny prick, and a cool sensation [where_str].")) + if(!isnull(user)) + user.action_feedback("You inject [target] with [src]. [loaded.reagents.total_volume] units remaining.", src) + +/obj/item/hypospray/loaded + loaded = /obj/item/reagent_containers/glass/hypovial/tricordrazine + +/obj/item/hypospray/advanced + name = "advanced hypospray" + desc = "An upgraded hypospray with faster injection protocols. Supports large vials." + icon_state = "hypo-cmo" + allow_large = TRUE + injection_time = 0.5 SECONDS + resist_add_time = 1 SECONDS + port_add_time = 0.5 SECONDS + +/obj/item/hypospray/advanced/loaded + loaded = /obj/item/reagent_containers/glass/hypovial/large/tricordrazine + +/obj/item/hypospray/advanced/cmo + port_add_time = 0 SECONDS + +/obj/item/hypospray/advanced/cmo/loaded + loaded = /obj/item/reagent_containers/glass/hypovial/large/tricordrazine + +/obj/item/hypospray/combat + name = "combat hypospray" + desc = "An upgraded variant of the regular hypospray, this one sports quickened injection - allowing for the faster incapacitation of vic- er, medication of allies. Supports large vials." + icon_state = "hypo-combat" + inhand_state = "hypo-combat" + allow_large = TRUE + injection_time = 0.5 SECONDS + resist_add_time = 1 SECONDS + port_add_time = 0.5 SECONDS + thick_add_time = 3 SECONDS + +/obj/item/hypospray/combat/loaded + loaded = /obj/item/reagent_containers/glass/hypovial/large/tricordrazine diff --git a/code/modules/reagents/items/hypovial.dm b/code/modules/reagents/items/hypovial.dm new file mode 100644 index 00000000000..7a2edc1a0d8 --- /dev/null +++ b/code/modules/reagents/items/hypovial.dm @@ -0,0 +1,118 @@ + +/obj/item/reagent_containers/glass/hypovial + name = "hypospray vial" + desc = "A standard issue vial used for hyposprays." + icon = 'icons/modules/reagents/items/hypospray.dmi' + icon_state = "vial" + w_class = WEIGHT_CLASS_TINY // 14 fits in a box, not 7 + volume = 60 + start_rename = TRUE + /// how many [state][#] overlays we have for reagents remaining + var/overlay_count = 3 + +/obj/item/reagent_containers/glass/hypovial/update_icon(updates) + cut_overlays() + . = ..() + if(overlay_count) + var/num = clamp(round((reagents.total_volume / reagents.maximum_volume) * overlay_count, 1), 0, overlay_count) + if(num) + var/mutable_appearance/overlay = mutable_appearance(icon, "[icon_state][num]") + overlay.color = reagents.get_color() + add_overlay(overlay) + +/obj/item/reagent_containers/glass/hypovial/large + name = "large hypospray vial" + desc = "A larger variant of the common hypospray vial. Only compatible with advanced units." + icon_state = "vial-l" + w_class = WEIGHT_CLASS_SMALL + volume = 120 + overlay_count = 4 + +/obj/item/reagent_containers/glass/hypovial/bluespace + name = "bluespace hypospray vial" + desc = "A prototype hypospray vial with the ability to hold reagents in a quasi-compressed state." + icon_state = "vial-bs" + volume = 120 + overlay_count = 0 + +//* subtypes - regular + +/obj/item/reagent_containers/glass/hypovial/bicaridine + start_reagent = /datum/reagent/bicaridine + +/obj/item/reagent_containers/glass/hypovial/kelotane + start_reagent = /datum/reagent/kelotane + +/obj/item/reagent_containers/glass/hypovial/dylovene + start_reagent = /datum/reagent/dylovene + +/obj/item/reagent_containers/glass/hypovial/dexalin + start_reagent = /datum/reagent/dexalin + +/obj/item/reagent_containers/glass/hypovial/tricordrazine + start_reagent = /datum/reagent/tricordrazine + +/obj/item/reagent_containers/glass/hypovial/peridaxon + start_reagent = /datum/reagent/peridaxon + +/obj/item/reagent_containers/glass/hypovial/tramadol + start_reagent = /datum/reagent/tramadol + +/obj/item/reagent_containers/glass/hypovial/inaprovaline + start_reagent = /datum/reagent/inaprovaline + +/obj/item/reagent_containers/glass/hypovial/imidalky + start_with = list( + /datum/reagent/imidazoline = 30, + /datum/reagent/alkysine = 30, + ) + +/obj/item/reagent_containers/glass/hypovial/arithrazine + start_reagent = /datum/reagent/arithrazine + +/obj/item/reagent_containers/glass/hypovial/spaceacillin + start_reagent = /datum/reagent/spaceacillin + +/obj/item/reagent_containers/glass/hypovial/dexalin_plus + start_reagent = /datum/reagent/dexalinp + +//* subtypes - large + +/obj/item/reagent_containers/glass/hypovial/large/bicaridine + start_reagent = /datum/reagent/bicaridine + +/obj/item/reagent_containers/glass/hypovial/large/kelotane + start_reagent = /datum/reagent/kelotane + +/obj/item/reagent_containers/glass/hypovial/large/dylovene + start_reagent = /datum/reagent/dylovene + +/obj/item/reagent_containers/glass/hypovial/large/dexalin + start_reagent = /datum/reagent/dexalin + +/obj/item/reagent_containers/glass/hypovial/large/tricordrazine + start_reagent = /datum/reagent/tricordrazine + +/obj/item/reagent_containers/glass/hypovial/large/peridaxon + start_reagent = /datum/reagent/peridaxon + +/obj/item/reagent_containers/glass/hypovial/large/tramadol + start_reagent = /datum/reagent/tramadol + +/obj/item/reagent_containers/glass/hypovial/large/inaprovaline + start_reagent = /datum/reagent/inaprovaline + +/obj/item/reagent_containers/glass/hypovial/large/imidalky + start_with = list( + /datum/reagent/imidazoline = 30, + /datum/reagent/alkysine = 30, + ) + +/obj/item/reagent_containers/glass/hypovial/large/arithrazine + start_reagent = /datum/reagent/arithrazine + +/obj/item/reagent_containers/glass/hypovial/large/spaceacillin + start_reagent = /datum/reagent/spaceacillin + +/obj/item/reagent_containers/glass/hypovial/large/dexalin_plus + start_reagent = /datum/reagent/dexalinp diff --git a/code/modules/reagents/machinery/chem_master.dm b/code/modules/reagents/machinery/chem_master.dm index ddf1025ed9b..bf6379db1b9 100644 --- a/code/modules/reagents/machinery/chem_master.dm +++ b/code/modules/reagents/machinery/chem_master.dm @@ -1,7 +1,8 @@ //TODO: We don't have check_reactions or something like it, so we can't prevent idiot transfers. @Zandario +// todo: this is horrifying and needs refactored. ESPECIALLY ITS TGUI. ~silicons /obj/machinery/chem_master name = "ChemMaster 3000" - desc = "Used to seperate and package chemicals in to autoinjectors, lollipops, patches, pills, or bottles. Warranty void if used to create Space Drugs." + desc = "Used to seperate and package chemicals in to autoinjectors, patches, pills, or bottles. Warranty void if used to create Space Drugs." density = TRUE anchored = TRUE icon = 'icons/obj/medical/chemical.dmi' @@ -19,10 +20,8 @@ var/obj/item/storage/pill_bottle/pill_bottle = null var/useramount = 15 // Last used amount var/pillamount = 10 - var/lolliamount = 5 var/autoamount = 5 var/max_pill_count = 20 - var/max_lolli_count = 10 var/max_auto_count = 5 var/printing = FALSE var/autosprite = TRUE @@ -361,6 +360,8 @@ else style = styles[chosen_condi_style] vol_each_max = min(50, vol_each_max) + else if(item_type == "hypovial") + vol_each_max = min(vol_each_max, 60) else return FALSE if(vol_each_text == "auto") @@ -393,6 +394,9 @@ return FALSE //! Start filling + var/atom/where = drop_location() + name = trim(name) + if(item_type == "pill") var/obj/item/reagent_containers/pill/P var/target_loc = drop_location() @@ -448,6 +452,15 @@ reagents.trans_to_obj(P, vol_each,/* transfered_by = usr*/) return TRUE + if(item_type == "hypovial") + var/obj/item/reagent_containers/glass/hypovial/P + for(var/i in 1 to amount) + P = new(where) + P.name = "[initial(P.name)] ([name])" + P.renamed_by_player = TRUE + reagents.trans_to_obj(P, vol_each) + return TRUE + // if(item_type == "condiment_pack") // var/obj/item/reagent_containers/condiment/pack/P // for(var/i in 1 to amount) diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 7901aa80a2d..cba898a73b2 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -4,9 +4,34 @@ icon = 'icons/obj/medical/chemical.dmi' icon_state = null w_class = ITEMSIZE_SMALL + + /// start reagent list. overrides reagent/volume. list(id = volume); volume must be specified. + var/list/start_with + /// start reagent id or path + var/start_reagent + /// start reagent amount. null for max. + var/start_volume + /// volume of our default reagents holder + var/volume = 30 + /// automatically rename to [[start_reagent]] + var/start_rename = FALSE + var/amount_per_transfer_from_this = 5 var/possible_transfer_amounts = list(5,10,15,25,30) - var/volume = 30 + +/obj/item/reagent_containers/Initialize(mapload) + . = ..() + if(!possible_transfer_amounts) + remove_obj_verb(src, /obj/item/reagent_containers/verb/set_APTFT) + create_reagents(volume) + if(!isnull(start_with)) + for(var/id in start_with) + reagents.add_reagent(id, start_with[id]) + else if(!isnull(start_reagent)) + reagents.add_reagent(start_reagent, isnull(start_volume)? volume : start_volume) + if(start_rename) + var/datum/reagent/R = start_reagent + name = "[name] ([initial(R.name)])" /obj/item/reagent_containers/verb/set_APTFT() //set amount_per_transfer_from_this set name = "Set transfer amount" @@ -16,12 +41,6 @@ if(N) amount_per_transfer_from_this = N -/obj/item/reagent_containers/Initialize(mapload) - . = ..() - if(!possible_transfer_amounts) - remove_obj_verb(src, /obj/item/reagent_containers/verb/set_APTFT) - create_reagents(volume) - /obj/item/reagent_containers/attack_self(mob/user) . = ..() if(.) diff --git a/code/modules/reagents/reagent_containers/dropper.dm b/code/modules/reagents/reagent_containers/dropper.dm index 491bf949c33..c4b971787a3 100644 --- a/code/modules/reagents/reagent_containers/dropper.dm +++ b/code/modules/reagents/reagent_containers/dropper.dm @@ -68,7 +68,7 @@ add_attack_logs(user,target,"Used [src.name] containing [contained]") trans += reagents.trans_to_mob(target, min(amount_per_transfer_from_this, reagents.total_volume)/2, CHEM_INGEST) //Half injected, half ingested - trans += reagents.trans_to_mob(target, min(amount_per_transfer_from_this, reagents.total_volume), CHEM_BLOOD) //I guess it gets into the bloodstream through the eyes or something + trans += reagents.trans_to_mob(target, min(amount_per_transfer_from_this, reagents.total_volume), CHEM_INJECT) //I guess it gets into the bloodstream through the eyes or something user.visible_message("[user] squirts something into [target]'s eyes!", "You transfer [trans] units of the solution.") return diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index 6a1041b472c..6b410e7b4c2 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -140,6 +140,10 @@ name = "[base_name] ([label_text])" desc = "[base_desc] It is labeled \"[label_text]\"." +/obj/item/reagent_containers/glass/on_reagent_change() + . = ..() + update_icon() + /obj/item/reagent_containers/glass/beaker name = "beaker" desc = "A beaker." @@ -147,6 +151,7 @@ icon_state = "beaker" base_icon_state = "beaker" item_state = "beaker" + w_class = WEIGHT_CLASS_TINY matter = list(MAT_GLASS = 500) drop_sound = 'sound/items/drop/glass.ogg' pickup_sound = 'sound/items/pickup/glass.ogg' @@ -155,9 +160,6 @@ . = ..() desc += " Can hold up to [volume] units." -/obj/item/reagent_containers/glass/beaker/on_reagent_change() - update_icon() - /obj/item/reagent_containers/glass/beaker/pickup(mob/user, flags, atom/oldLoc) . = ..() update_icon() @@ -201,6 +203,7 @@ desc = "A large beaker." icon_state = "beakerlarge" base_icon_state = "beakerlarge" + w_class = WEIGHT_CLASS_SMALL matter = list(MAT_GLASS = 1000) volume = 120 amount_per_transfer_from_this = 10 @@ -212,6 +215,7 @@ desc = "A cryostasis beaker that allows for chemical storage without reactions." icon_state = "beakernoreact" base_icon_state = "beakernoreact" + w_class = WEIGHT_CLASS_SMALL matter = list(MAT_GLASS = 500) volume = 60 amount_per_transfer_from_this = 10 @@ -222,6 +226,7 @@ desc = "A bluespace beaker, powered by experimental bluespace technology." icon_state = "beakerbluespace" base_icon_state = "beakerbluespace" + w_class = WEIGHT_CLASS_SMALL matter = list(MAT_GLASS = 5000) volume = 300 amount_per_transfer_from_this = 10 diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 18c8b6c4167..647017af01f 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -75,7 +75,7 @@ if(H.reagents) var/contained = reagentlist() - var/trans = reagents.trans_to_mob(H, amount_per_transfer_from_this, CHEM_BLOOD) + var/trans = reagents.trans_to_mob(H, amount_per_transfer_from_this, CHEM_INJECT) add_attack_logs(user,H,"Injected with [src.name] containing [contained], trasferred [trans] units") to_chat(user, SPAN_NOTICE("[trans] units injected. [reagents.total_volume] units remaining in \the [src].")) return TRUE diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 61b123d5e02..d68e68da638 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -208,7 +208,7 @@ var/contained = reagentlist() if(ismob(target)) while(reagents.total_volume) - trans += reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_BLOOD) + trans += reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_INJECT) update_icon() if(!reagents.total_volume || !do_after(user,cycle_time,target)) break @@ -267,7 +267,7 @@ var/syringestab_amount_transferred = rand(0, (reagents.total_volume - 5)) //nerfed by popular demand var/contained = reagents.get_reagents() - var/trans = reagents.trans_to_mob(target, syringestab_amount_transferred, CHEM_BLOOD) + var/trans = reagents.trans_to_mob(target, syringestab_amount_transferred, CHEM_INJECT) if(isnull(trans)) trans = 0 add_attack_logs(user,target,"Stabbed with [src.name] containing [contained], trasferred [trans] units") break_syringe(target, user) diff --git a/code/modules/research/designs/medical.dm b/code/modules/research/designs/medical.dm index e744c9f8527..85195c01c45 100644 --- a/code/modules/research/designs/medical.dm +++ b/code/modules/research/designs/medical.dm @@ -148,12 +148,12 @@ // sort_string = "KCAVA" /datum/design/item/medical/protohypospray - name = "prototype hypospray" + name = "advanced hypospray" desc = "This prototype hypospray is a sterile, air-needle autoinjector for rapid administration of drugs to patients." id = "protohypospray" req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3, TECH_POWER = 2, TECH_BIO = 4, TECH_ILLEGAL = 2) materials = list(MAT_STEEL = 500, MAT_GLASS = 1500, MAT_SILVER = 2000, MAT_GOLD = 1500, MAT_URANIUM = 1000) - build_path = /obj/item/reagent_containers/hypospray/science + build_path = /obj/item/hypospray/advanced sort_string = "KCAVB" // ML-3M medigun and cells diff --git a/code/modules/rigsuits/pieces.dm b/code/modules/rigsuits/pieces.dm index 3fd46e6ea65..6615b424065 100644 --- a/code/modules/rigsuits/pieces.dm +++ b/code/modules/rigsuits/pieces.dm @@ -17,7 +17,7 @@ /obj/item/clothing/head/hardsuit name = "helmet" atom_flags = PHORONGUARD - clothing_flags = THICKMATERIAL | ALLOW_SURVIVALFOOD | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB | ALLOWINTERNALS + clothing_flags = CLOTHING_THICK_MATERIAL | CLOTHING_INJECTION_PORT | ALLOW_SURVIVALFOOD | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB | ALLOWINTERNALS inv_hide_flags = HIDEEARS|HIDEEYES|HIDEFACE|BLOCKHAIR body_cover_flags = HEAD|FACE|EYES heat_protection = HEAD|FACE|EYES @@ -52,7 +52,7 @@ //Flags body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - clothing_flags = THICKMATERIAL | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB + clothing_flags = CLOTHING_THICK_MATERIAL | CLOTHING_INJECTION_PORT | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS atom_flags = PHORONGUARD inv_hide_flags = HIDEJUMPSUIT|HIDETAIL @@ -110,7 +110,7 @@ /obj/item/clothing/gloves/hardsuit name = "gauntlets" - clothing_flags = THICKMATERIAL | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB + clothing_flags = CLOTHING_THICK_MATERIAL | CLOTHING_INJECTION_PORT | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB atom_flags = PHORONGUARD body_cover_flags = HANDS heat_protection = HANDS @@ -153,7 +153,7 @@ /obj/item/clothing/shoes/hardsuit name = "boots" atom_flags = PHORONGUARD - clothing_flags = CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB + clothing_flags = CLOTHING_IGNORE_BELTLINK | CLOTHING_INJECTION_PORT | CLOTHING_THICK_MATERIAL | CLOTHING_IGNORE_DELIMB body_cover_flags = FEET cold_protection = FEET heat_protection = FEET diff --git a/code/modules/rigsuits/rig_pieces.dm b/code/modules/rigsuits/rig_pieces.dm index 0ea9613f0f0..f06fd025829 100644 --- a/code/modules/rigsuits/rig_pieces.dm +++ b/code/modules/rigsuits/rig_pieces.dm @@ -5,7 +5,7 @@ /obj/item/clothing/head/helmet/space/hardsuit name = "helmet" atom_flags = PHORONGUARD - clothing_flags = THICKMATERIAL | ALLOW_SURVIVALFOOD | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB | ALLOWINTERNALS + clothing_flags = CLOTHING_THICK_MATERIAL | ALLOW_SURVIVALFOOD | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB | ALLOWINTERNALS inv_hide_flags = HIDEEARS|HIDEEYES|HIDEFACE|BLOCKHAIR body_cover_flags = HEAD|FACE|EYES heat_protection = HEAD|FACE|EYES @@ -44,7 +44,7 @@ /obj/item/clothing/gloves/gauntlets/hardsuit name = "gauntlets" - clothing_flags = THICKMATERIAL | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB + clothing_flags = CLOTHING_THICK_MATERIAL | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB atom_flags = PHORONGUARD body_cover_flags = HANDS heat_protection = HANDS @@ -119,7 +119,7 @@ //Flags body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - clothing_flags = THICKMATERIAL | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB + clothing_flags = CLOTHING_THICK_MATERIAL | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS atom_flags = PHORONGUARD inv_hide_flags = HIDEJUMPSUIT|HIDETAIL @@ -215,7 +215,7 @@ /obj/item/clothing/head/lightrig name = "mask" - clothing_flags = THICKMATERIAL | ALLOWINTERNALS | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB + clothing_flags = CLOTHING_THICK_MATERIAL | ALLOWINTERNALS | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB atom_flags = PHORONGUARD body_cover_flags = HEAD|FACE|EYES heat_protection = HEAD|FACE|EYES @@ -225,7 +225,7 @@ name = "suit" allowed = list(/obj/item/flashlight) inv_hide_flags = HIDEJUMPSUIT - clothing_flags = THICKMATERIAL | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB + clothing_flags = CLOTHING_THICK_MATERIAL | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB atom_flags = PHORONGUARD body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS @@ -242,7 +242,7 @@ /obj/item/clothing/gloves/gauntlets/lightrig name = "gloves" - clothing_flags = THICKMATERIAL | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB + clothing_flags = CLOTHING_THICK_MATERIAL | CLOTHING_IGNORE_BELTLINK | CLOTHING_IGNORE_DELIMB atom_flags = PHORONGUARD species_restricted = null body_cover_flags = HANDS diff --git a/code/modules/rigsuits/suits/light.dm b/code/modules/rigsuits/suits/light.dm index 2ecd0468827..da0613ba826 100644 --- a/code/modules/rigsuits/suits/light.dm +++ b/code/modules/rigsuits/suits/light.dm @@ -15,7 +15,7 @@ armor_type = /datum/armor/hardsuit/light emp_protection = 10 slowdown = 0 - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL offline_slowdown = 0 offline_vision_restriction = 0 diff --git a/code/modules/rigsuits/suits/species/vox.dm b/code/modules/rigsuits/suits/species/vox.dm index 878c7b41d5c..900e92d94fe 100644 --- a/code/modules/rigsuits/suits/species/vox.dm +++ b/code/modules/rigsuits/suits/species/vox.dm @@ -5,7 +5,7 @@ icon_state = "vox_rig" armor_type = /datum/armor/hardsuit/vox atom_flags = PHORONGUARD - clothing_flags = THICKMATERIAL + clothing_flags = CLOTHING_THICK_MATERIAL siemens_coefficient = 0.2 offline_slowdown = 5 allowed = list( diff --git a/code/modules/surgery/other.dm b/code/modules/surgery/other.dm index 93c7b37a29e..97a01af469d 100644 --- a/code/modules/surgery/other.dm +++ b/code/modules/surgery/other.dm @@ -163,7 +163,7 @@ var/obj/item/reagent_containers/container = tool - var/trans = container.reagents.trans_to_mob(target, container.amount_per_transfer_from_this, CHEM_BLOOD) //technically it's contact, but the reagents are being applied to internal tissue + var/trans = container.reagents.trans_to_mob(target, container.amount_per_transfer_from_this, CHEM_INJECT) //technically it's contact, but the reagents are being applied to internal tissue if (trans > 0) affected.status &= ~ORGAN_DEAD affected.owner.update_icons_body() @@ -179,7 +179,7 @@ var/obj/item/reagent_containers/container = tool - var/trans = container.reagents.trans_to_mob(target, container.amount_per_transfer_from_this, CHEM_BLOOD) + var/trans = container.reagents.trans_to_mob(target, container.amount_per_transfer_from_this, CHEM_INJECT) user.visible_message("[user]'s hand slips, applying [trans] units of the solution to the wrong place in [target]'s [affected.name] with the [tool]!" , \ "Your hand slips, applying [trans] units of the solution to the wrong place in [target]'s [affected.name] with the [tool]!") diff --git a/code/modules/unit_tests/reagents/reagent_id_typos.dm b/code/modules/unit_tests/reagents/reagent_id_typos.dm deleted file mode 100644 index d6548852fa5..00000000000 --- a/code/modules/unit_tests/reagents/reagent_id_typos.dm +++ /dev/null @@ -1,14 +0,0 @@ - - -/datum/unit_test/reagent_id_typos - -/datum/unit_test/reagent_id_typos/Run() - build_chemical_reactions_list() - build_chemical_reagent_list() - - for(var/I in GLOB.chemical_reactions_list) - for(var/V in GLOB.chemical_reactions_list[I]) - var/datum/chemical_reaction/R = V - for(var/id in (R.required_reagents + R.required_catalysts)) - if(!GLOB.chemical_reagents_list[id]) - Fail("Unknown chemical id \"[id]\" in recipe [R.type]") diff --git a/code/modules/unit_tests/reagents/reagent_recipe_collisions.dm b/code/modules/unit_tests/reagents/reagent_recipe_collisions.dm index 20e875422f2..fa537ceffa9 100644 --- a/code/modules/unit_tests/reagents/reagent_recipe_collisions.dm +++ b/code/modules/unit_tests/reagents/reagent_recipe_collisions.dm @@ -3,13 +3,18 @@ /datum/unit_test/reagent_recipe_collisions /datum/unit_test/reagent_recipe_collisions/Run() - build_chemical_reactions_list() - var/list/reactions = list() - for(var/V in GLOB.chemical_reactions_list) - reactions += GLOB.chemical_reactions_list[V] + var/list/reactions = SSchemistry.chemical_reactions.Copy() for(var/i in 1 to (reactions.len-1)) + var/datum/chemical_reaction/r1 = reactions[i] + //! LEGACY PATCH - we don't have abstract types / skipovers properly set up. + if(!length(r1.required_reagents)) + continue + //! LEGACY PATCH END for(var/i2 in (i+1) to reactions.len) - var/datum/chemical_reaction/r1 = reactions[i] var/datum/chemical_reaction/r2 = reactions[i2] + //! LEGACY PATCH - we don't have abstract types / skipovers properly set up. + if(!length(r2.required_reagents)) + continue + //! LEGACY PATCH END if(chem_recipes_do_conflict(r1, r2)) Fail("Chemical recipe conflict between [r1.type] and [r2.type]") diff --git a/code/modules/xenobio/items/extracts.dm b/code/modules/xenobio/items/extracts.dm index 6c9b752f87a..cff78d327da 100644 --- a/code/modules/xenobio/items/extracts.dm +++ b/code/modules/xenobio/items/extracts.dm @@ -40,14 +40,15 @@ . += "This extract is inert." /datum/chemical_reaction/slime - var/required = null + abstract_type = /datum/chemical_reaction/slime /datum/chemical_reaction/slime/can_happen(var/datum/reagents/holder) - if(holder.my_atom && istype(holder.my_atom, required)) - var/obj/item/slime_extract/T = holder.my_atom - if(T.uses > 0) - return ..() - return FALSE + if(!istype(holder.my_atom, /obj/item/slime_extract)) + return FALSE + var/obj/item/slime_extract/T = holder.my_atom + if(T.uses <= 0) + return FALSE + return ..() /datum/chemical_reaction/slime/on_reaction(var/datum/reagents/holder) var/obj/item/slime_extract/T = holder.my_atom @@ -56,12 +57,10 @@ T.visible_message("[icon2html(thing = T, target = world)] \The [T] goes inert.") T.name = "inert [initial(T.name)]" - // *************** // * Grey slimes * // *************** - /obj/item/slime_extract/grey name = "grey slime extract" icon_state = "grey slime extract" @@ -73,7 +72,7 @@ result = null required_reagents = list(MAT_PHORON = 5) result_amount = 1 - required = /obj/item/slime_extract/grey + required_container = /obj/item/slime_extract/grey /datum/chemical_reaction/slime/grey_new_slime/on_reaction(var/datum/reagents/holder) holder.my_atom.visible_message("Infused with phoron, the core begins to quiver and grow, and soon a new baby slime emerges from it!") @@ -87,7 +86,7 @@ result = null required_reagents = list("blood" = 5) result_amount = 1 - required = /obj/item/slime_extract/grey + required_container = /obj/item/slime_extract/grey /datum/chemical_reaction/slime/grey_monkey/on_reaction(var/datum/reagents/holder) for(var/i = 1 to 4) @@ -100,7 +99,7 @@ result = "slimejelly" required_reagents = list("peridaxon" = 5) result_amount = 15 - required = /obj/item/slime_extract/grey + required_container = /obj/item/slime_extract/grey // **************** // * Metal slimes * @@ -130,7 +129,7 @@ required_reagents = list(MAT_PHORON = 5) result = "metamorphic" result_amount = REAGENTS_PER_SHEET // Makes enough to make one sheet of any metal. - required = /obj/item/slime_extract/metal + required_container = /obj/item/slime_extract/metal /datum/chemical_reaction/metamorphic @@ -195,7 +194,7 @@ required_reagents = list("water" = 5) result = "binding" result_amount = REAGENTS_PER_SHEET // Makes enough to make one sheet of any metal. - required = /obj/item/slime_extract/metal + required_container = /obj/item/slime_extract/metal /datum/reagent/toxin/binding_metal @@ -265,7 +264,7 @@ result = "frostoil" required_reagents = list(MAT_PHORON = 5) result_amount = 20 - required = /obj/item/slime_extract/blue + required_container = /obj/item/slime_extract/blue /datum/chemical_reaction/slime/blue_stability @@ -273,7 +272,7 @@ id = "m_stability" required_reagents = list("blood" = 5) result_amount = 1 - required = /obj/item/slime_extract/blue + required_container = /obj/item/slime_extract/blue /datum/chemical_reaction/slime/blue_stability/on_reaction(var/datum/reagents/holder) new /obj/item/slimepotion/stabilizer(get_turf(holder.my_atom)) @@ -297,7 +296,7 @@ id = "m_steroid" required_reagents = list(MAT_PHORON = 5) result_amount = 1 - required = /obj/item/slime_extract/purple + required_container = /obj/item/slime_extract/purple /datum/chemical_reaction/slime/purple_steroid/on_reaction(var/datum/reagents/holder) new /obj/item/slimepotion/steroid(get_turf(holder.my_atom)) @@ -319,7 +318,7 @@ id = "m_fire" required_reagents = list(MAT_PHORON = 5) result_amount = 1 - required = /obj/item/slime_extract/orange + required_container = /obj/item/slime_extract/orange /datum/chemical_reaction/slime/orange_fire/on_reaction(var/datum/reagents/holder) log_and_message_admins("Orange extract reaction (fire) has been activated in [get_area(holder.my_atom)]. Last fingerprints: [holder.my_atom.fingerprintslast]") @@ -356,7 +355,7 @@ id = "m_emp" required_reagents = list("water" = 5) result_amount = 1 - required = /obj/item/slime_extract/yellow + required_container = /obj/item/slime_extract/yellow /datum/chemical_reaction/slime/yellow_emp/on_reaction(var/datum/reagents/holder) log_and_message_admins("Yellow extract reaction (emp) has been activated in [get_area(holder.my_atom)]. Last fingerprints: [holder.my_atom.fingerprintslast]") @@ -374,7 +373,7 @@ id = "m_cell" required_reagents = list(MAT_PHORON = 5) result_amount = 1 - required = /obj/item/slime_extract/yellow + required_container = /obj/item/slime_extract/yellow /datum/chemical_reaction/slime/yellow_battery/on_reaction(var/datum/reagents/holder) new /obj/item/cell/slime(get_turf(holder.my_atom)) @@ -386,7 +385,7 @@ id = "m_flashlight" required_reagents = list("blood" = 5) result_amount = 1 - required = /obj/item/slime_extract/yellow + required_container = /obj/item/slime_extract/yellow /datum/chemical_reaction/slime/yellow_flashlight/on_reaction(var/datum/reagents/holder) new /obj/item/flashlight/slime(get_turf(holder.my_atom)) @@ -408,7 +407,7 @@ result = "gold" required_reagents = list(MAT_PHORON = 5) result_amount = 5 - required = /obj/item/slime_extract/gold + required_container = /obj/item/slime_extract/gold // ***************** @@ -427,7 +426,7 @@ result = "silver" required_reagents = list(MAT_PHORON = 5) result_amount = 5 - required = /obj/item/slime_extract/silver + required_container = /obj/item/slime_extract/silver // ********************** @@ -447,7 +446,7 @@ result = "phoron" required_reagents = list("water" = 5) result_amount = REAGENTS_PER_SHEET * 2 - required = /obj/item/slime_extract/dark_purple + required_container = /obj/item/slime_extract/dark_purple // ******************** @@ -468,7 +467,7 @@ id = "m_cold_snap" required_reagents = list(MAT_PHORON = 5) result_amount = 1 - required = /obj/item/slime_extract/dark_blue + required_container = /obj/item/slime_extract/dark_blue // This iterates over a ZAS zone's contents, so that things seperated in other zones aren't subjected to the temperature drop. /datum/chemical_reaction/slime/dark_blue_cold_snap/on_reaction(var/datum/reagents/holder) @@ -550,7 +549,7 @@ id = "m_enrage" required_reagents = list("blood" = 5) result_amount = 1 - required = /obj/item/slime_extract/red + required_container = /obj/item/slime_extract/red /datum/chemical_reaction/slime/red_enrage/on_reaction(var/datum/reagents/holder) for(var/mob/living/simple_mob/slime/S in view(get_turf(holder.my_atom))) @@ -586,7 +585,7 @@ id = "m_mutation" required_reagents = list(MAT_PHORON = 5) result_amount = 1 - required = /obj/item/slime_extract/red + required_container = /obj/item/slime_extract/red /datum/chemical_reaction/slime/red_mutation/on_reaction(var/datum/reagents/holder) new /obj/item/slimepotion/mutator(get_turf(holder.my_atom)) @@ -607,7 +606,7 @@ result = "uranium" required_reagents = list(MAT_PHORON = 5) result_amount = 5 - required = /obj/item/slime_extract/green + required_container = /obj/item/slime_extract/green // *************** @@ -627,7 +626,7 @@ result = "slime_bleed_fixer" required_reagents = list("blood" = 5) result_amount = 30 - required = /obj/item/slime_extract/pink + required_container = /obj/item/slime_extract/pink /datum/chemical_reaction/slime/pink_bone_fix @@ -636,7 +635,7 @@ result = "slime_bone_fixer" required_reagents = list(MAT_PHORON = 5) result_amount = 30 - required = /obj/item/slime_extract/pink + required_container = /obj/item/slime_extract/pink /datum/chemical_reaction/slime/pink_organ_fix @@ -645,7 +644,7 @@ result = "slime_organ_fixer" required_reagents = list("water" = 5) result_amount = 30 - required = /obj/item/slime_extract/pink + required_container = /obj/item/slime_extract/pink /datum/reagent/myelamine/slime @@ -686,7 +685,7 @@ id = "m_boom" required_reagents = list("blood" = 5) result_amount = 1 - required = /obj/item/slime_extract/oil + required_container = /obj/item/slime_extract/oil /datum/chemical_reaction/slime/oil_griff/on_reaction(var/datum/reagents/holder) @@ -724,7 +723,7 @@ id = "m_tele_lesser" required_reagents = list("water" = 5) result_amount = 1 - required = /obj/item/slime_extract/bluespace + required_container = /obj/item/slime_extract/bluespace /datum/chemical_reaction/slime/bluespace_lesser/on_reaction(var/datum/reagents/holder) for(var/i = 1 to 5) @@ -736,7 +735,7 @@ id = "m_tele_lesser" required_reagents = list(MAT_PHORON = 5) result_amount = 1 - required = /obj/item/slime_extract/bluespace + required_container = /obj/item/slime_extract/bluespace /datum/chemical_reaction/slime/bluespace_greater/on_reaction(var/datum/reagents/holder) new /obj/item/disposable_teleporter/slime(get_turf(holder.my_atom)) @@ -747,7 +746,7 @@ id = "bloodcrystal" required_reagents = list("blood" = 5) result_amount = 1 - required = /obj/item/slime_extract/bluespace + required_container = /obj/item/slime_extract/bluespace /datum/chemical_reaction/slime/bloodcrystal/on_reaction(var/datum/reagents/holder) new /obj/item/ore/bluespace_crystal(get_turf(holder.my_atom)) @@ -769,7 +768,7 @@ id = "m_enhancer" required_reagents = list(MAT_PHORON = 5) result_amount = 1 - required = /obj/item/slime_extract/cerulean + required_container = /obj/item/slime_extract/cerulean /datum/chemical_reaction/slime/cerulean_enhancer/on_reaction(var/datum/reagents/holder) new /obj/item/slimepotion/enhancer(get_turf(holder.my_atom)) @@ -791,7 +790,7 @@ id = "m_slime_food" required_reagents = list(MAT_PHORON = 5) result_amount = 1 - required = /obj/item/slime_extract/amber + required_container = /obj/item/slime_extract/amber /datum/chemical_reaction/slime/amber_slimefood/on_reaction(var/datum/reagents/holder) new /obj/item/slimepotion/feeding(get_turf(holder.my_atom)) @@ -803,7 +802,7 @@ id = "m_people_food" required_reagents = list("water" = 5) result_amount = 1 - required = /obj/item/slime_extract/amber + required_container = /obj/item/slime_extract/amber /datum/chemical_reaction/slime/amber_peoplefood/on_reaction(var/datum/reagents/holder) new /obj/item/reagent_containers/food/snacks/slime(get_turf(holder.my_atom)) @@ -826,7 +825,7 @@ id = "m_promethean" required_reagents = list(MAT_PHORON = 5) result_amount = 1 - required = /obj/item/slime_extract/sapphire + required_container = /obj/item/slime_extract/sapphire /datum/chemical_reaction/slime/sapphire_promethean/on_reaction(var/datum/reagents/holder) new /obj/item/slime_cube(get_turf(holder.my_atom)) @@ -847,7 +846,7 @@ id = "m_strength" required_reagents = list(MAT_PHORON = 5) result_amount = 1 - required = /obj/item/slime_extract/ruby + required_container = /obj/item/slime_extract/ruby /datum/chemical_reaction/slime/ruby_swole/on_reaction(var/datum/reagents/holder) for(var/mob/living/L in range(1, holder.my_atom)) @@ -875,7 +874,7 @@ id = "m_strength" required_reagents = list("blood" = 5) result_amount = 1 - required = /obj/item/slime_extract/ruby + required_container = /obj/item/slime_extract/ruby /datum/chemical_reaction/slime/ruby_loyalty/on_reaction(var/datum/reagents/holder) new /obj/item/slimepotion/loyalty(get_turf(holder.my_atom)) @@ -896,7 +895,7 @@ id = "m_agility" required_reagents = list(MAT_PHORON = 5) result_amount = 1 - required = /obj/item/slime_extract/emerald + required_container = /obj/item/slime_extract/emerald /datum/chemical_reaction/slime/emerald_fast/on_reaction(var/datum/reagents/holder) for(var/mob/living/L in range(1, holder.my_atom)) @@ -933,7 +932,7 @@ id = "m_docile" required_reagents = list("water" = 5) result_amount = 1 - required = /obj/item/slime_extract/light_pink + required_container = /obj/item/slime_extract/light_pink /datum/chemical_reaction/slime/light_pink_docility/on_reaction(var/datum/reagents/holder) new /obj/item/slimepotion/docility(get_turf(holder.my_atom)) @@ -945,7 +944,7 @@ id = "m_friendship" required_reagents = list(MAT_PHORON = 5) result_amount = 1 - required = /obj/item/slime_extract/light_pink + required_container = /obj/item/slime_extract/light_pink /datum/chemical_reaction/slime/light_pink_friendship/on_reaction(var/datum/reagents/holder) new /obj/item/slimepotion/friendship(get_turf(holder.my_atom)) @@ -969,7 +968,7 @@ id = "m_rng_slime" required_reagents = list(MAT_PHORON = 5) result_amount = 1 - required = /obj/item/slime_extract/rainbow + required_container = /obj/item/slime_extract/rainbow /datum/chemical_reaction/slime/rainbow_random_slime/on_reaction(var/datum/reagents/holder) @@ -993,7 +992,7 @@ id = "m_unity" required_reagents = list("water" = 5) result_amount = 1 - required = /obj/item/slime_extract/rainbow + required_container = /obj/item/slime_extract/rainbow /datum/chemical_reaction/slime/rainbow_unity/on_reaction(var/datum/reagents/holder) new /obj/item/slimepotion/unity(get_turf(holder.my_atom)) @@ -1005,4 +1004,4 @@ result = "mutationtoxin" required_reagents = list("blood" = 5) result_amount = 30 - required = /obj/item/slime_extract/sapphire + required_container = /obj/item/slime_extract/sapphire diff --git a/code/modules/xenobio2/mob/xeno procs.dm b/code/modules/xenobio2/mob/xeno procs.dm index 9c1e560b30c..167e7046f48 100644 --- a/code/modules/xenobio2/mob/xeno procs.dm +++ b/code/modules/xenobio2/mob/xeno procs.dm @@ -54,7 +54,7 @@ Divergence proc, used in mutation to make unique datums. //Let's handle some chemical smoke, for scientific smoke bomb purposes. for(var/obj/effect/particle_effect/smoke/chem/smoke in view(1, src)) if(smoke.reagents.total_volume) - smoke.reagents.trans_to_mob(src, 10, CHEM_BLOOD, copy = 1) + smoke.reagents.trans_to_mob(src, 10, CHEM_INJECT, copy = 1) reagents.trans_to_obj(temp_chem_holder, min(reagents.total_volume,rand(1,4))) var/reagent_total diff --git a/icons/items/storage/firstaid.dmi b/icons/items/storage/firstaid.dmi new file mode 100644 index 00000000000..6962ec92221 Binary files /dev/null and b/icons/items/storage/firstaid.dmi differ diff --git a/icons/items/storage/firstaid_small.dmi b/icons/items/storage/firstaid_small.dmi new file mode 100644 index 00000000000..a794c09f90f Binary files /dev/null and b/icons/items/storage/firstaid_small.dmi differ diff --git a/icons/modules/reagents/items/hypospray.dmi b/icons/modules/reagents/items/hypospray.dmi new file mode 100644 index 00000000000..3ff6118ef59 Binary files /dev/null and b/icons/modules/reagents/items/hypospray.dmi differ diff --git a/icons/screen/atom_hud/health.dmi b/icons/screen/atom_hud/health.dmi index 752829fba26..152af8331e8 100644 Binary files a/icons/screen/atom_hud/health.dmi and b/icons/screen/atom_hud/health.dmi differ diff --git a/maps/map_files/rift/rift-05-surface2.dmm b/maps/map_files/rift/rift-05-surface2.dmm index 80f4a203839..9f03715c56c 100644 --- a/maps/map_files/rift/rift-05-surface2.dmm +++ b/maps/map_files/rift/rift-05-surface2.dmm @@ -10075,7 +10075,6 @@ /area/rnd/outpost/xenobiology/outpost_slimepens) "gra" = ( /obj/structure/table/standard, -/obj/machinery/recharger, /obj/effect/floor_decal/corner/paleblue{ dir = 10 }, @@ -10086,6 +10085,28 @@ desc = null; pixel_y = 24 }, +/obj/item/storage/hypokit{ + pixel_x = -8; + pixel_y = -8 + }, +/obj/item/storage/hypokit{ + pixel_x = -8 + }, +/obj/item/storage/hypokit{ + pixel_x = -8; + pixel_y = 8 + }, +/obj/item/storage/hypokit{ + pixel_x = 8; + pixel_y = 8 + }, +/obj/item/storage/hypokit{ + pixel_x = 8; + pixel_y = -8 + }, +/obj/item/storage/hypokit{ + pixel_x = 8 + }, /turf/simulated/floor/tiled/white, /area/medical/medbay_primary_storage) "grT" = ( @@ -18859,6 +18880,7 @@ /obj/item/cane, /obj/item/cane/crutch, /obj/item/cane/crutch, +/obj/machinery/recharger, /turf/simulated/floor/tiled/white, /area/medical/medbay_primary_storage) "lLU" = ( diff --git a/sound/items/hypospray.ogg b/sound/items/hypospray.ogg new file mode 100644 index 00000000000..b70d3fd5b58 Binary files /dev/null and b/sound/items/hypospray.ogg differ diff --git a/sound/items/hypospray2.ogg b/sound/items/hypospray2.ogg new file mode 100644 index 00000000000..14835e9bb6a Binary files /dev/null and b/sound/items/hypospray2.ogg differ diff --git a/sound/items/hypospray_long.ogg b/sound/items/hypospray_long.ogg new file mode 100644 index 00000000000..d7da6c839f3 Binary files /dev/null and b/sound/items/hypospray_long.ogg differ diff --git a/sound/weapons/autoguninsert.ogg b/sound/weapons/autoguninsert.ogg new file mode 100644 index 00000000000..f68139968e0 Binary files /dev/null and b/sound/weapons/autoguninsert.ogg differ diff --git a/tgui/packages/tgui/interfaces/ChemMaster.tsx b/tgui/packages/tgui/interfaces/ChemMaster.tsx index 9de38db10b3..7f594ef85a8 100644 --- a/tgui/packages/tgui/interfaces/ChemMaster.tsx +++ b/tgui/packages/tgui/interfaces/ChemMaster.tsx @@ -310,6 +310,7 @@ const PackagingControls = (props, context) => { 'bottleAmount', 1 ); + const [vialAmount, setVialAmount] = useSharedState(context, "vialAmount", 1); const [packAmount, setPackAmount] = useSharedState(context, 'packAmount', 1); const { condi, @@ -417,6 +418,21 @@ const PackagingControls = (props, context) => { })} /> )} + {!condi && ( + setVialAmount(value)} + onCreate={() => + act('create', { + type: 'hypovial', + amount: vialAmount, + volume: 'auto', + })} + /> + )} {!!condi && (