code:
//Powerful painkiller
/datum/reagent/medicine/morphine
	name = "Morphine"
	description = "A powerful yet highly addictive painkiller. Causes drowsyness. Overdosing causes jitteryness and muscle spasms."
	metabolization_rate = 0.5 * REAGENTS_METABOLISM
	overdose_threshold = OVERDOSE_STANDARD
	addiction_types = list(/datum/addiction/opiods = 15)

/datum/reagent/medicine/morphine/on_mob_metabolize(mob/living/L)
	. = ..()
	L.add_chem_effect(CE_PAINKILLER, 80, "morphine")

/datum/reagent/medicine/morphine/on_mob_end_metabolize(mob/living/L)
	. = ..()
	L.remove_chem_effect(CE_PAINKILLER, "morphine")

/datum/reagent/medicine/morphine/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
	if(current_cycle >= 5)
		SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "numb", /datum/mood_event/narcotic_medium, name)
	switch(current_cycle)
		if(11)
			to_chat(M, span_warning("You start to feel tired...") )
		if(12 to 24)
			M.drowsyness += 1 * REM * delta_time
		if(24 to INFINITY)
			M.Sleeping(4 SECONDS * REM * delta_time)
			. = TRUE
	..()

/datum/reagent/medicine/morphine/overdose_process(mob/living/M, delta_time, times_fired)
	if(DT_PROB(20, delta_time))
		M.drop_all_held_items()
		M.Dizzy(2)
		M.Jitter(2)
	return ..()

//Slight painkiller, stabilizes pulse
/datum/reagent/medicine/inaprovaline
	name = "Inaprovalil"
	description = "Inaprovalil works as a pulse stabilizer and light painkiller. Useful for treating shock. \
				Overdosing causes fatigue and drowsyness."
	metabolization_rate = 0.5 * REAGENTS_METABOLISM
	overdose_threshold = OVERDOSE_STANDARD

/datum/reagent/medicine/inaprovaline/on_mob_metabolize(mob/living/L)
	. = ..()
	L.add_chem_effect(CE_PAINKILLER, 10, "inaprovalil")
	L.add_chem_effect(CE_STABLE, 1, "inaprovalil")

/datum/reagent/medicine/inaprovaline/on_mob_end_metabolize(mob/living/L)
	. = ..()
	L.remove_chem_effect(CE_PAINKILLER, "inaprovalil")
	L.remove_chem_effect(CE_STABLE, "inaprovalil")
	L.remove_chem_effect(CE_SPEED, "inaprovalil")

/datum/reagent/medicine/inaprovaline/overdose_start(mob/living/M)
	. = ..()
	M.add_chem_effect(CE_SPEED, -1, "inaprovalil")

/datum/reagent/medicine/inaprovaline/overdose_process(mob/living/M, delta_time, times_fired)
	. = ..()
	if(DT_PROB(3, delta_time))
		M.slurring = max(M.slurring, 10)
	if(DT_PROB(3, delta_time))
		M.drowsyness = max(M.drowsyness, 5)
	return TRUE

//Pulse increase and painkiller
/datum/reagent/determination
	name = "Adrenaline"
	description = "Adrenaline is a hormone used as a drug to treat cardiac arrest and other cardiac dysrhythmias resulting in diminished or absent cardiac output."
	taste_description = "rush"
	reagent_state = LIQUID
	metabolization_rate = 0.5 * REAGENTS_METABOLISM
	color = "#c8a5dc"

/datum/reagent/determination/on_mob_metabolize(mob/living/L)
	. = ..()
	L.add_chem_effect(CE_STIMULANT, 1, "adrenaline")
	L.add_chem_effect(CE_PULSE, 1, "adrenaline")
	L.add_chem_effect(CE_PAINKILLER, min(5*holder.get_reagent_amount(/datum/reagent/determination), 25), "adrenaline")

/datum/reagent/determination/on_mob_end_metabolize(mob/living/carbon/M)
	. = ..()
	M.remove_chem_effect(CE_STIMULANT, "adrenaline")
	M.remove_chem_effect(CE_PULSE, "adrenaline")
	M.remove_chem_effect(CE_PAINKILLER, "adrenaline")

//Pulse increase and painkilelr
/datum/reagent/medicine/epinephrine
	name = "Epinephrine"
	description = "Epinephrine slowly heals damage if a patient is in critical condition, as well as regulating oxygen loss. Overdose causes weakness and toxin damage."

/datum/reagent/medicine/epinephrine/on_mob_metabolize(mob/living/carbon/M)
	. = ..()
	M.add_chem_effect(CE_STIMULANT, 1, "epinephrine")
	M.add_chem_effect(CE_PULSE, 1, "epinephrine")
	M.add_chem_effect(CE_PAINKILLER, min(5*holder.get_reagent_amount(/datum/reagent/determination), 25), "epinephrine")

/datum/reagent/medicine/epinephrine/on_mob_end_metabolize(mob/living/carbon/M)
	. = ..()
	M.remove_chem_effect(CE_STIMULANT, "epinephrine")
	M.remove_chem_effect(CE_PULSE, "epinephrine")
	M.remove_chem_effect(CE_PAINKILLER, "epinephrine")

/datum/reagent/medicine/epinephrine/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
	if(holder.has_reagent(/datum/reagent/toxin/lexorin))
		holder.remove_reagent(/datum/reagent/toxin/lexorin, 2 * REM * delta_time)
		holder.remove_reagent(/datum/reagent/medicine/epinephrine, 1 * REM * delta_time)
		if(DT_PROB(10, delta_time))
			holder.add_reagent(/datum/reagent/toxin/histamine, 4)
		..()
		return TRUE
	if(M.health <= M.crit_threshold)
		M.adjustToxLoss(-0.5 * REM * delta_time, 0)
		M.adjustBruteLoss(-0.5 * REM * delta_time, 0)
		M.adjustFireLoss(-0.5 * REM * delta_time, 0)
		M.adjustOxyLoss(-0.5 * REM * delta_time, 0)
	if(M.losebreath >= 4)
		M.losebreath -= 2 * REM * delta_time
		M.losebreath = max(0, M.losebreath)
	M.adjustStaminaLoss(-0.5 * REM * delta_time, 0)
	if(DT_PROB(10, delta_time))
		M.AdjustAllImmobility(-20)
	..()
	return TRUE

/datum/reagent/medicine/epinephrine/overdose_process(mob/living/M, delta_time, times_fired)
	if(DT_PROB(18, REM * delta_time))
		M.adjustStaminaLoss(2.5, 0)
		M.adjustToxLoss(1, 0)
		M.losebreath++
		..()
		return TRUE
	..()

//Reduces pulse slightly
/datum/reagent/medicine/lisinopril
	name = "Lisinopril"
	description = "Lisinopril is a drug used to reduce blood pressure. It is not processed by the liver and has a very slow metabolization. \
				Overdosing causes arterial blockage."
	ph = 5.1
	metabolization_rate = 0.2 * REAGENTS_METABOLISM //Lisinopril has a very, very slow metabolism IRL
	self_consuming = TRUE //Does not get processed by the liver
	color = "#dbafc0"
	overdose_threshold = OVERDOSE_STANDARD

/datum/reagent/medicine/lisinopril/on_mob_metabolize(mob/living/L)
	. = ..()
	L.add_chem_effect(CE_PULSE, -2, "lisinopril")

/datum/reagent/medicine/lisinopril/on_mob_end_metabolize(mob/living/L)
	. = ..()
	L.remove_chem_effect(CE_PULSE, "lisinopril")
	L.remove_chem_effect(CE_BLOCKAGE, "lisinopril")

/datum/reagent/medicine/lisinopril/overdose_start(mob/living/M)
	. = ..()
	M.add_chem_effect(CE_BLOCKAGE, 40, "lisinopril")

//Oxygenation
/datum/reagent/medicine/salbutamol
	name = "Salbutamol"
	description = "Rapidly restores blood oxygenation and dilates the lungs."

/datum/reagent/medicine/salbutamol/on_mob_metabolize(mob/living/L)
	. = ..()
	L.add_chem_effect(CE_OXYGENATED, 2, "salbutamol")

/datum/reagent/medicine/salbutamol/on_mob_end_metabolize(mob/living/L)
	. = ..()
	L.remove_chem_effect(CE_OXYGENATED, "salbutamol")

/datum/reagent/medicine/salbutamol/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
	M.adjustOxyLoss(-3 * REM * delta_time, 0)
	..()
	return TRUE

//Antibiotic
/datum/reagent/medicine/spaceacillin
	name = "Spaceacillin"
	description = "Spaceacillin is a broad spectrum antibiotic and immune response booster. \
				Overdosing weakens immune response instead."
	metabolization_rate = 0.2 * REAGENTS_METABOLISM
	overdose_threshold = OVERDOSE_STANDARD

/datum/reagent/medicine/spaceacillin/on_mob_metabolize(mob/living/L)
	. = ..()
	L.add_chem_effect(CE_ANTIBIOTIC, 50, "spaceacillin")
	if(iscarbon(L))
		var/mob/living/carbon/carbon_mob = L
		carbon_mob.immunity += 25

/datum/reagent/medicine/spaceacillin/on_mob_end_metabolize(mob/living/L)
	. = ..()
	L.remove_chem_effect(CE_ANTIBIOTIC, "spaceacillin")
	if(iscarbon(L))
		var/mob/living/carbon/carbon_mob = L
		carbon_mob.immunity -= 25

/datum/reagent/medicine/spaceacillin/overdose_start(mob/living/M)
	. = ..()
	if(iscarbon(M))
		var/mob/living/carbon/carbon_mob = M
		carbon_mob.immunity -= 75
	M.remove_chem_effect(CE_ANTIBIOTIC, "spaceacillin")

//Copium
/datum/reagent/medicine/copium
	name = "Copium"
	description = "The strongest synthetic painkiller. Highly addictive, easily overdoseable at 15u."
	ph = 6.9
	reagent_state = GAS
	metabolization_rate = REAGENTS_METABOLISM
	self_consuming = TRUE //Does not get processed by the liver
	color = "#d364ff"
	overdose_threshold = 15
	addiction_types = list(/datum/addiction/opiods = 30)

/datum/reagent/medicine/copium/overdose_start(mob/living/M)
	. = ..()
	if(iscarbon(M))
		var/mob/living/carbon/C = M
		C.set_heartattack(TRUE)

/datum/reagent/medicine/copium/on_mob_metabolize(mob/living/L)
	. = ..()
	L.add_chem_effect(CE_PULSE, -2, "copium")
	L.add_chem_effect(CE_PAINKILLER, 200, "copium")

/datum/reagent/medicine/copium/on_mob_end_metabolize(mob/living/L)
	. = ..()
	L.remove_chem_effect(CE_PAINKILLER, "copium")
	L.remove_chem_effect(CE_PULSE, "copium")


code:
/datum/reagent/fuel
	//Gasoline evaporates rather fast - 20u every 10 seconds
	liquid_evaporation_rate = 20
	liquid_fire_power = 10
	liquid_fire_burnrate = 0.1
	accelerant_quality = 10

//mmm warter
/datum/reagent/water
	//10u every 10 seconds
	liquid_evaporation_rate = 10

/datum/reagent/water/expose_turf(turf/open/exposed_turf, reac_volume)
	. = ..()
	if(!. && exposed_turf.turf_fire)
		exposed_turf.turf_fire.reduce_power(reac_volume)

/datum/reagent/water/expose_atom(atom/exposed_atom, reac_volume)
	. = ..()
	if(!.)
		exposed_atom.adjust_germ_level(-reac_volume * SANITIZATION_PER_UNIT_WATER)

/datum/reagent/water/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
	if(ishuman(M))
		var/mob/living/carbon/human/H = M
		if(!HAS_TRAIT(H, TRAIT_NOTHIRST))
			var/kidney_efficiency = H.getorganslotefficiency(ORGAN_SLOT_KIDNEYS)
			if(kidney_efficiency > 0)
				H.adjust_hydration(15 * REAGENTS_METABOLISM * REM * (kidney_efficiency/GLOB.organ_processes_by_slot[ORGAN_SLOT_KIDNEYS].optimal_threshold) * delta_time)
	return ..()

//mm tide pods
/datum/reagent/space_cleaner
	var/sanitization = SANITIZATION_PER_UNIT_SPACE_CLEANER

/datum/reagent/space_cleaner/expose_atom(atom/exposed_atom, reac_volume)
	. = ..()
	if(!.)
		exposed_atom.adjust_germ_level(-reac_volume * sanitization)

/datum/reagent/space_cleaner/sterilizine
	sanitization = SANITIZATION_PER_UNIT_STERILIZINE

//water but evil
/datum/reagent/hellwater
	accelerant_quality = 20

repo_name: AnalWerewolf/sundown

license: mit


code:
/datum/reagent/benzene
	name = "Benzene"
	description = "A very common hydrocarbon, used as a precursor for various chemicals. Reduces presence of red blood cells when metabolized."
	ph = 7
	taste_description = "alcoholic sweetness"
	color = "#aaaaaa55" // rgb: 170, 170, 170, 85 (alpha)
	liquid_fire_power = 10 //benzene is highly flammable
	liquid_fire_burnrate = 0.1
	liquid_evaporation_rate = 20 //like ethanol, evaporates quick

//benzene is very toxic
/datum/reagent/benzene/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
	. = ..()
	M.adjust_bloodvolume(-0.5)

/datum/reagent/toxin/acid
	liquid_evaporation_rate = 1 //slow evaporation

//fluoride stares....
/datum/reagent/fluorine/on_mob_metabolize(mob/living/L)
	. = ..()
	ADD_TRAIT(L, TRAIT_FLUORIDE_STARE, "fluorine")

/datum/reagent/fluorine/on_mob_end_metabolize(mob/living/L)
	. = ..()
	REMOVE_TRAIT(L, TRAIT_FLUORIDE_STARE, "fluorine")


code:
/datum/reagent/thermite
	liquid_evaporation_rate = 10
	liquid_fire_power = 20
	liquid_fire_burnrate = 0.1
	accelerant_quality = 2

/datum/reagent/clf3
	liquid_evaporation_rate = 40
	liquid_fire_power = 30
	liquid_fire_burnrate = 0.1
	accelerant_quality = 20

/datum/reagent/phlogiston
	liquid_evaporation_rate = 10
	liquid_fire_power = 20
	liquid_fire_burnrate = 0.1
	accelerant_quality = 20

/datum/reagent/napalm
	liquid_evaporation_rate = 10
	liquid_fire_power = 30
	liquid_fire_burnrate = 0.1
	accelerant_quality = 20

/datum/reagent/firefighting_foam/expose_turf(turf/open/exposed_turf, reac_volume)
	. = ..()
	if(!. && exposed_turf.turf_fire)
		qdel(exposed_turf.turf_fire)


code:
/datum/reagent/toxin/plasma
	accelerant_quality = 10


code:
/datum/chemical_reaction
	/// If defined, it'll emitt that pollutant on reaction
	var/pollutant_type
	/// How much amount per volume of the pollutant shall we emitt if `pollutant_type` is defined
	var/pollutant_amount = 1


code:
//bicaridine
/datum/chemical_reaction/medicine/helbital
	results = list(/datum/reagent/medicine/c2/helbital = 3)
	required_reagents = list(/datum/reagent/medicine/inaprovaline = 1, \
							/datum/reagent/carbon = 1, \
							/datum/reagent/fluorine = 1)
	required_temp = 150
	optimal_temp = 300
	overheat_temp = 350
	reaction_flags = REACTION_PH_VOL_CONSTANT
	reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_BRUTE

//kelotane
/datum/chemical_reaction/medicine/aiuri
	results = list(/datum/reagent/medicine/c2/aiuri = 3)
	required_reagents = list(/datum/reagent/silicon = 1, \
							/datum/reagent/carbon = 1, \
							/datum/reagent/hydrogen = 1)
	required_temp = 150
	optimal_temp = 300
	overheat_temp = 350
	reaction_flags = REACTION_PH_VOL_CONSTANT
	reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_BURN

//dicorderal
/datum/chemical_reaction/medicine/probital
	results = list(/datum/reagent/medicine/c2/probital = 2)
	required_reagents = list(/datum/reagent/medicine/c2/aiuri = 1, \
							/datum/reagent/medicine/c2/helbital = 1)
	required_temp = 600
	optimal_temp = 750
	overheat_temp = 800
	reaction_flags = REACTION_PH_VOL_CONSTANT
	reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_BRUTE | REACTION_TAG_BURN

//tirimol
/datum/chemical_reaction/medicine/tirimol
	results = list(/datum/reagent/medicine/c2/tirimol = 3)
	required_reagents = list(/datum/reagent/benzene = 2, \
							/datum/reagent/nitrous_oxide = 1)
	required_catalysts = null
	required_temp = 350
	optimal_temp = 350
	overheat_temp = 450
	reaction_flags = REACTION_PH_VOL_CONSTANT
	reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_OXY


code:
//inaprovaline
/datum/chemical_reaction/medicine/inaprovaline
	results = list(/datum/reagent/medicine/inaprovaline = 3)
	required_reagents = list(/datum/reagent/acetone = 1, \
							/datum/reagent/carbon = 1, \
							/datum/reagent/consumable/sugar = 1)
	required_temp = 300
	optimal_temp = 400
	reaction_tags = REACTION_TAG_EASY | REACTION_TAG_CHEMICAL | REACTION_TAG_HEALING

//lisinopril
/datum/chemical_reaction/medicine/lisinopril
	results = list(/datum/reagent/medicine/lisinopril = 2)
	required_reagents = list(/datum/reagent/ammonia = 1, /datum/reagent/water = 1, /datum/reagent/benzene = 2)
	required_temp = 450
	optimal_temp = 450
	reaction_tags = REACTION_TAG_EASY | REACTION_TAG_CHEMICAL | REACTION_TAG_HEALING

//copium
/datum/chemical_reaction/medicine/copium
	results = list(/datum/reagent/medicine/copium = 1)
	required_reagents = list(/datum/reagent/medicine/morphine = 1, /datum/reagent/medicine/lisinopril = 1, \
					/datum/reagent/medicine/inaprovaline = 1, /datum/reagent/medicine/c2/libital = 1)
	required_temp = 600 //needs to be DILATED
	optimal_temp = 600
	reaction_tags = REACTION_TAG_EASY | REACTION_TAG_CHEMICAL | REACTION_TAG_HEALING


code:
/datum/chemical_reaction/benzene
	results = list(/datum/reagent/benzene = 3)
	required_reagents = list(/datum/reagent/ash = 1, /datum/reagent/water = 2, /datum/reagent/hydrogen = 1, /datum/reagent/carbon = 1)
	required_temp = 620
	reaction_tags = REACTION_TAG_EASY | REACTION_TAG_CHEMICAL


code:
/obj/item/reagent_containers/Initialize(mapload, vol)
	. = ..()
	AddElement(/datum/element/liquids_interaction, on_interaction_callback = /obj/item/reagent_containers/.proc/attack_on_liquids_turf)

/obj/item/reagent_containers/try_splash(mob/user, atom/target)
	if (!spillable)
		return FALSE

	if (!reagents?.total_volume)
		return FALSE

	var/punctuation = ismob(target) ? "!" : "."

	var/reagent_text
	user.visible_message(
		span_danger("[user] splashes the contents of [src] onto [target][punctuation]"), \
		span_danger("You splash the contents of [src] onto [target][punctuation]"), \
		ignored_mobs = target, \
	)

	if (ismob(target))
		var/mob/target_mob = target
		target_mob.show_message(
			span_userdanger("[user] splash the contents of [src] onto you!"), \
			MSG_VISUAL, \
			span_userdanger("You feel drenched!"), \
		)

	for(var/datum/reagent/reagent as anything in reagents.reagent_list)
		reagent_text += "[reagent] ([num2text(reagent.volume)]),"

	if(isturf(target))
		var/turf/turf_target = target
		turf_target.add_liquid_from_reagents(reagents)
		if(length(reagents.reagent_list) && thrownby)
			log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]", "in [AREACOORD(target)]")
			log_game("[key_name(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [AREACOORD(target)].")
			message_admins("[ADMIN_LOOKUPFLW(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] at [ADMIN_VERBOSEJMP(target)].")
	else
		reagents.expose(target, TOUCH)

	log_combat(user, target, "splashed", reagent_text)
	reagents.clear_reagents()

	return TRUE

/obj/item/reagent_containers/proc/attack_on_liquids_turf(obj/item/reagent_containers/my_container, turf/my_turf, mob/living/user, atom/movable/liquid/liquids)
	if(IS_HARM_INTENT(user, null))
		return FALSE
	if(!my_container.spillable)
		return FALSE
	if(!user.Adjacent(my_turf))
		return FALSE
	//Use an extinguisher first
	if(liquids.fire_state)
		to_chat(user, span_warning("I can't scoop it! It's on fire!"))
		return TRUE
	if(liquids.liquid_state <= LIQUID_STATE_PUDDLE)
		to_chat(user, span_warning("The puddle is too shallow to scoop anything up!"))
		return TRUE
	var/free_space = my_container.reagents.maximum_volume - my_container.reagents.total_volume
	if(free_space <= 0)
		to_chat(user, span_warning("I can't fit any more reagents inside [my_container]!"))
		return TRUE
	var/desired_transfer = my_container.amount_per_transfer_from_this
	if(desired_transfer > free_space)
		desired_transfer = free_space
	var/datum/reagents/temporary_holder = liquids.take_reagents_flat(desired_transfer)
	temporary_holder.trans_to(my_container.reagents, temporary_holder.total_volume)
	to_chat(user, span_notice("I scoop up around [my_container.amount_per_transfer_from_this] units of liquids with [my_container]."))
	qdel(temporary_holder)
	user.changeNext_move(my_container.attack_delay)
	return TRUE


code:
/obj/item/reagent_containers/blood
	name = "\improper IV bag"
	desc = "An IV bag. Can be attached to a human to slowly transfer it's reagents to their bloodstream. Can also take blood from a human."
	amount_per_transfer_from_this = 0.1
	possible_transfer_amounts = list(0.1, 0.2, 0.5, 1, 2, 5)
	///Who are we sticking our needle in?
	var/mob/living/carbon/attached
	///Are we injecting or sucking?
	var/injecting = FALSE

/obj/item/reagent_containers/blood/Destroy()
	if(attached)
		detach_iv()
	return ..()

/obj/item/reagent_containers/blood/examine(mob/user)
	. = ..()
	. |= bloodpack_examine()

/obj/item/reagent_containers/blood/AltClick(mob/user)
	. = ..()
	if(attached)
		to_chat(user, span_notice("\The IV bag needle is removed from [attached]."))
		detach_iv()

/obj/item/reagent_containers/blood/attack_self_secondary(mob/user)
	. = ..()
	injecting = !injecting
	to_chat(user, span_notice("\The [src] will now [injecting ? "inject" : "take blood from"] the attached patient."))

/obj/item/reagent_containers/blood/update_name(updates)
	. = ..()
	if(labelled)
		return
	name = "\improper IV bag[blood_type ? " - [blood_type]" : null]"

/obj/item/reagent_containers/blood/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params)
	. = ..()
	if(iscarbon(over) && (loc == usr) && isliving(usr) && distance_check(over))
		attach_iv(over, usr)

/obj/item/reagent_containers/blood/process(delta_time)
	if(!attached)
		return PROCESS_KILL

	if(!distance_check(attached))
		attached.visible_message(span_danger("\The IV bag needle is ripped out of [attached]!"), \
								span_userdanger("Ouch! \The IV bag needle is ripped from me!"))
		attached.apply_damage(3, BRUTE, pick(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM), sharpness = SHARP_POINTY)

		detach_iv()
		return PROCESS_KILL

	return reagent_handling(delta_time)

/obj/item/reagent_containers/blood/proc/reagent_handling(delta_time)
	if(reagents)
		// Inject reagents
		if(injecting)
			if(reagents.total_volume)
				reagents.trans_to(attached, amount_per_transfer_from_this * delta_time * 0.5, methods = INJECT, show_message = FALSE) //make reagents reacts, but don't spam messages
				update_appearance()
		// Take blood
		else
			var/amount = reagents.maximum_volume - reagents.total_volume
			amount = min(amount, amount_per_transfer_from_this) * 0.5 * delta_time

			attached.transfer_blood_to(src, amount_per_transfer_from_this)
			update_appearance()

/obj/item/reagent_containers/blood/proc/bloodpack_examine(mob/user)
	. = list()
	. += span_notice("Currently in [injecting ? "injection" : "extraction"] mode.")
	if(attached)
		. += span_notice("Currently [injecting ? "injecting" : "taking blood from"] [attached].")

/obj/item/reagent_containers/blood/proc/distance_check(mob/living/target)
	. = TRUE
	if(!(get_dist(loc, target) <= 1) || !isturf(target.loc) || !isliving(loc))
		return FALSE

/obj/item/reagent_containers/blood/proc/attach_iv(mob/living/target, mob/user)
	SEND_SIGNAL(src, COMSIG_IV_ATTACH, target)
	user.visible_message(span_warning("[user] attaches [src] to [target]."), \
					span_notice("I attach [src] to [target]."))
	log_combat(user, target, "attached", src, "containing: ([reagents.log_list()])")
	add_fingerprint(user)
	attached = target
	START_PROCESSING(SSobj, src)

	update_appearance()

/obj/item/reagent_containers/blood/proc/detach_iv()
	SEND_SIGNAL(src, COMSIG_IV_DETACH, attached)

	attached = null
	STOP_PROCESSING(SSobj, src)
	update_appearance()


code:
/obj/item/reagent_containers/glass/bottle/multiver
	name = "charcoal bottle"
	desc = "A small bottle of charcoal."
	list_reagents = list(/datum/reagent/medicine/c2/multiver = 30)

/obj/item/reagent_containers/glass/bottle/syriniver
	name = "dylovenal bottle"
	desc = "A small bottle of dylovenal."
	list_reagents = list(/datum/reagent/medicine/c2/syriniver = 30)

/obj/item/reagent_containers/glass/bottle/spaceacillin
	name = "spaceacillin bottle"
	desc = "A small bottle of spaceacilin."
	list_reagents = list(/datum/reagent/medicine/spaceacillin = 30)

/obj/item/reagent_containers/glass/bottle/tirimol
	name = "tirimol bottle"
	desc = "A small bottle of tirimol."
	list_reagents = list(/datum/reagent/medicine/c2/tirimol = 30)

/obj/item/reagent_containers/glass/bottle/copium
	name = "copium bottle"
	desc = "A small bottle of copium."
	list_reagents = list(/datum/reagent/medicine/copium = 30)


code:
#define SQUEEZING_DISPERSAL_PERCENT 0.75

/obj/item/reagent_containers/glass/bucket/attackby_secondary(obj/item/weapon, mob/user, params)
	. = ..()
	if(!istype(weapon, /obj/item/mop))
		return
	if(weapon.reagents.total_volume == 0)
		to_chat(user, span_warning("[weapon] is dry, i can't squeeze anything out!"))
		return
	if(reagents.total_volume == reagents.maximum_volume)
		to_chat(user, span_warning("[src] is full!"))
		return
	weapon.reagents.remove_any(weapon.reagents.total_volume*SQUEEZING_DISPERSAL_PERCENT)
	weapon.reagents.trans_to(src, weapon.reagents.total_volume, transfered_by = user)
	to_chat(user, span_notice("I squeeze the liquids from [weapon] to [src]."))

#undef SQUEEZING_DISPERSAL_PERCENT


code:
/obj/item/reagent_containers/medigel/libital
	name = "medical gel (codeine)"
	desc = "A medical gel applicator bottle, designed for precision application, with an unscrewable cap. This one contains codeine, for treating cuts and bruises and relieving pain."
	list_reagents = list(/datum/reagent/medicine/c2/libital = 50)

/obj/item/reagent_containers/medigel/aiuri
	name = "medical gel (naproxane)"
	desc = "A medical gel applicator bottle, designed for precision application, with an unscrewable cap. This one contains naproxane, useful for treating burns."
	list_reagents = list(/datum/reagent/medicine/c2/aiuri = 50)

/obj/item/reagent_containers/medigel/synthflesh
	name = "medical gel (menderal)"
	desc = "A medical gel applicator bottle, designed for precision application, with an unscrewable cap. This one contains menderal, a medicine capable of healing both bruises and burns."


code:
/obj/item/reagent_containers/pill/patch/libital
	name = "codeine patch (brute)"
	desc = "Analgesic and brute damage reliever."
	list_reagents = list(/datum/reagent/medicine/c2/libital = 10)

/obj/item/reagent_containers/pill/patch/aiuri
	name = "naproxane patch (burn)"
	desc = "Analgesic and burn damage reliever."
	list_reagents = list(/datum/reagent/medicine/c2/lenturi = 10)

/obj/item/reagent_containers/pill/patch/synthflesh
	name = "menderal patch (brute / burn)"
	desc = "Helps with brute and burn injuries."
	list_reagents = list(/datum/reagent/medicine/c2/synthflesh = 10)


code:
/obj/item/reagent_containers/pill/multiver
	name = "charcoal pill"
	desc = "Neutralizes many common toxins."
	list_reagents = list(/datum/reagent/medicine/c2/multiver = 10)

/obj/item/reagent_containers/pill/probital
	name = "dicorderal pill"
	desc = "Used to treat brute and burn damage of minor and moderate severity."
	list_reagents = list(/datum/reagent/medicine/c2/probital = 10)


code:
/obj/item/reagent_containers/syringe/multiver
	name = "syringe (charcoal)"
	desc = "Contains charcoal."
	list_reagents = list(/datum/reagent/medicine/c2/multiver = 15)

/obj/item/reagent_containers/syringe/syriniver
	name = "syringe (dylovenal)"
	desc = "Contains dylovenal."
	list_reagents = list(/datum/reagent/medicine/c2/syriniver = 15)

/obj/item/reagent_containers/syringe/minoxidil
	name = "syringe (minoxidil)"
	desc = "Contains minoxidil."
	list_reagents = list(/datum/reagent/medicine/c2/penthrite = 15)

/obj/item/reagent_containers/syringe/convermol
	name = "syringe (formoterol)"
	desc = "Contains formoterol."
	list_reagents = list(/datum/reagent/medicine/c2/convermol = 15)

/obj/item/reagent_containers/syringe/tirimol
	name = "syringe (tirimol)"
	desc = "Contains tirimol."
	list_reagents = list(/datum/reagent/medicine/c2/tirimol = 15)

/obj/item/reagent_containers/syringe/antiviral
	name = "syringe (spaceacillin)"
	desc = "Contains antibiotic agents."
	list_reagents = list(/datum/reagent/medicine/spaceacillin = 15)

/obj/item/reagent_containers/syringe/copium
	name = "syringe (copium)"
	desc = "Contains copium. <b>Do not inject more or equal to 15u at once.</b>"
	custom_premium_price = PAYCHECK_HARD * 3
	list_reagents = list(/datum/reagent/medicine/copium = 15)

/obj/item/reagent_containers/syringe/morphine
	name = "syringe (morphine)"
	desc = "Contains morphine."
	list_reagents = list(/datum/reagent/medicine/morphine = 15)


code:
/obj/structure/reagent_dispensers
	max_integrity = 150

/obj/structure/reagent_dispensers/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
	. = ..()
	if(. && atom_integrity <= 0)
		var/violence = (damage_flag == BULLET || damage_flag == LASER)
		boom(damage_type, violence)

/obj/structure/reagent_dispensers/boom(damage_type = BRUTE, violent = FALSE)
	rupture()

/obj/structure/reagent_dispensers/proc/rupture()
	audible_message(span_danger("[src] audibly ruptures!"))
	chem_splash(loc, 3, list(reagents))
	qdel(src)

/obj/structure/reagent_dispensers/fueltank/boom(damage_type = BRUTE, violent = FALSE)
	//change this later
	if(violent)
		explosion(src, heavy_impact_range = 1, light_impact_range = 5, flame_range = 5)
		qdel(src)
	else
		rupture()

/obj/structure/reagent_dispensers/fueltank/large
	max_integrity = 300

/obj/structure/reagent_dispensers/fueltank/large/boom(damage_type = BRUTE, violent = FALSE)
	if(violent)
		explosion(src, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 7, flame_range = 12)
		qdel(src)
	else
		rupture()

/obj/structure/reagent_dispensers/fueltank/blob_act(obj/structure/blob/B)
	boom(violent = TRUE)

/obj/structure/reagent_dispensers/fueltank/ex_act()
	boom(violent = TRUE)

/obj/structure/reagent_dispensers/fueltank/zap_act(power, zap_flags)
	boom(violent = TRUE)


code:
/datum/addiction/opiods
	name = "opioids"


code:
/datum/techweb_node/syndicate_basic
	design_ids = list(
		"advanced_camera",
		"decloner",
		"donksoft_refill",
		"donksofttoyvendor",
		"largecrossbow",
		"rapidsyringe",
		"suppressor",
	)


code:
/obj/machinery/nuclearbomb
	var/auth_code_1 = ""

/obj/machinery/nuclearbomb/Initialize()
	. = ..()
	auth_code_1 = get_authcode()

/proc/get_authcode(fake = FALSE)
	if(GLOB.nuke_authcode && !fake)
		return GLOB.nuke_authcode

	var/raw_code
	for(var/n in 1 to 5)
		raw_code += random_string(4, GLOB.alphabet + GLOB.alphabet_upper + GLOB.numerals)
		raw_code += "-"
	raw_code += random_string(4, GLOB.alphabet + GLOB.alphabet_upper + GLOB.numerals)

	if(!fake) //the nuke code is real, and we don't have one already
		GLOB.nuke_authcode = raw_code
	return raw_code

/obj/machinery/nuclearbomb/proc/disk_check(obj/item/disk/nuclear/D)
	if(D.auth_code != auth_code_1)
		say("Authentication failure; disk not recognised.")
		return FALSE
	else
		return TRUE

/obj/item/disk/nuclear
	var/auth_code

/obj/item/disk/nuclear/Initialize()
	. = ..()
	auth_code = get_authcode(fake)

/obj/item/disk/nuclear/examine(mob/user)
	. = ..()
	if(auth_code)
		. += span_notice("There's a serial number imprinted on the back...\n[auth_code]")

/obj/item/disk/nuclear/fake/obvious/Initialize()
	. = ..()
	auth_code = null


code:
/obj/machinery/computer/emergency_shuttle/Initialize(mapload, obj/item/circuitboard/C)
	. = ..()
	AddElement(/datum/element/multitool_emaggable)


code:
/turf/onShuttleMove(turf/newT, list/movement_force, move_dir)
	if(newT == src) // In case of in place shuttle rotation shenanigans.
		return
	//Destination turf changes
	//Baseturfs is definitely a list or this proc wouldnt be called
	var/shuttle_boundary = baseturfs.Find(/turf/baseturf_skipover/shuttle)
	if(!shuttle_boundary)
		CRASH("A turf queued to move via shuttle somehow had no skipover in baseturfs. [src]([type]):[loc]")
	var/depth = length(baseturfs) - shuttle_boundary + 1

	if(newT.liquids_group)
		newT.liquids_group.remove_from_group(newT)
	if(newT.liquids)
		if(newT.liquids.immutable)
			newT.liquids.remove_turf(src)
		else
			qdel(newT.liquids, TRUE)

	if(liquids_group)
		liquids_group.remove_from_group(src)
	if(liquids)
		liquids.change_to_new_turf(newT)
		newT.reasses_liquids()

	newT.CopyOnTop(src, 1, depth, TRUE)
	newT.blocks_air = TRUE
	newT.air_update_turf(TRUE, FALSE)
	blocks_air = TRUE
	air_update_turf(TRUE, TRUE)
	if(isopenturf(newT))
		var/turf/open/new_open = newT
		new_open.copy_air_with_tile(src)
	SEND_SIGNAL(src, COMSIG_TURF_ON_SHUTTLE_MOVE, newT)

	return TRUE


code:
//Do a little sound hint
/atom/proc/sound_hint(duration = 5, use_icon = 'modular_septic/icons/effects/sound.dmi', use_states = "sound2")
	//this is HORRIBLE but it prevents runtimes
	if(SSticker.current_state < GAME_STATE_PLAYING)
		return
	var/hint_icon = use_icon
	var/hint_state = pick(use_states)
	var/image/I = image(hint_icon, get_turf(src), hint_state)
	I.plane = SOUND_HINT_PLANE
	var/list/clients = list()
	for(var/mob/M in get_hearers_in_view(world.view, src))
		if(M.client)
			clients |= M.client
	flick_overlay(I, clients, duration)


code:
//I fuck sex
/datum/surgery_step
	var/name = "Code sucks"
	var/list/implements = list()	//format is path = probability of success. alternatively
	var/implement_type = null		//the current type of implement used. This has to be stored, as the actual typepath of the tool may not match the list type.
	var/accept_hand = 0				//does the surgery step require an open hand? If true, this is the hand chance
	var/minimum_time = 10			//best case scenario time for this step
	var/maximum_time = 20			//worst case scenario
	var/repeatable = FALSE			//can this step be repeated?
	var/step_in_progress = FALSE	//are we being done, right now?
	var/list/chems_needed = list()  //list of chems needed to complete the step. Even on success, the step will have no effect if there aren't the chems required in the mob.
	var/require_all_chems = TRUE    //any on the list or all on the list?
	var/silicons_obey_prob = FALSE	//do silicons care about probability of success?
	var/surgery_flags = (STEP_NEEDS_INCISED) //fucking flags
	var/success_multiplier = 1
	var/ignore_clothes = FALSE //Do we check for clothes covering the location?
	var/requires_bodypart = TRUE //Most surgeries need a bodypart to work
	var/requires_missing_bodypart = TRUE //AKA limb attachment
	var/requires_real_bodypart = FALSE	//Some surgeries don't work on limbs that are fake (AKA le item limb)
	var/requires_bodypart_type = BODYPART_ORGANIC //Prevents you from performing an operation on incorrect limbs. 0 for any limb type
	var/lying_required = FALSE	//Does the victim need to be lying down?
	var/list/possible_locs = ALL_BODYPARTS //Where this can be performed on
	var/list/target_mobtypes = list(/mob/living/carbon)	//Acceptable mob types
	var/requires_tech //Tech tree datum required to unlock this dummy, will be implemented later
	var/stat_used = STAT_INTELLIGENCE //Stat used only affects surgery speed, but not chance
	var/skill_used = SKILL_SURGERY //Skill used affects both speed and chance

/datum/surgery_step/proc/validate_user(mob/user)
	. = TRUE
	if(!(user.zone_selected in possible_locs))
		. = FALSE

/datum/surgery_step/proc/validate_target(mob/living/target, mob/user)
	. = TRUE
	if(length(target_mobtypes))
		. = FALSE
		for(var/bingus in target_mobtypes)
			if(istype(target, bingus))
				. = TRUE
	if(lying_required && (target.body_position != LYING_DOWN))
		. = FALSE
	if(iscarbon(target))
		var/mob/living/carbon/C = target
		var/mob/living/carbon/human/H = C
		var/obj/item/bodypart/BP = C.get_bodypart(check_zone(user.zone_selected))
		if(requires_bodypart && !BP)
			return FALSE
		else if(!requires_bodypart)
			if(requires_missing_bodypart && BP)
				return FALSE
			return TRUE
		if(istype(H) && !ignore_clothes && BP && LAZYLEN(H.clothingonpart(BP)) )
			. = FALSE
		if(requires_bodypart_type && !(BP.status == requires_bodypart_type))
			. = FALSE
		if(CHECK_BITFIELD(surgery_flags, STEP_NEEDS_ENCASED) && !BP.is_encased())
			. = FALSE
		var/how_open = BP.how_open()
		if(CHECK_BITFIELD(surgery_flags, STEP_NEEDS_INCISED) && !CHECK_BITFIELD(how_open, SURGERY_INCISED))
			. = FALSE
		if(CHECK_BITFIELD(surgery_flags, STEP_NEEDS_NOT_INCISED) && CHECK_BITFIELD(how_open, SURGERY_INCISED))
			. = FALSE
		if(CHECK_BITFIELD(surgery_flags, STEP_NEEDS_RETRACTED) && !CHECK_BITFIELD(how_open, SURGERY_RETRACTED))
			. = FALSE
		if(CHECK_BITFIELD(surgery_flags, STEP_NEEDS_DRILLED) && !CHECK_BITFIELD(how_open, SURGERY_DRILLED))
			. = FALSE
		if(CHECK_BITFIELD(surgery_flags, STEP_NEEDS_BROKEN) && !CHECK_BITFIELD(how_open, SURGERY_BROKEN))
			. = FALSE
		if(user == target)
			var/obj/item/bodypart/active_hand = user.get_active_hand()
			if((active_hand?.body_zone in list(BODY_ZONE_R_ARM, BODY_ZONE_PRECISE_R_HAND)) && (user.zone_selected in list(BODY_ZONE_R_ARM, BODY_ZONE_PRECISE_R_HAND)))
				return FALSE
			if((active_hand?.body_zone in list(BODY_ZONE_L_ARM, BODY_ZONE_PRECISE_L_HAND)) && (user.zone_selected in list(BODY_ZONE_L_ARM, BODY_ZONE_PRECISE_L_HAND)))
				return FALSE

/datum/surgery_step/proc/try_op(mob/user, mob/living/target, target_zone, obj/item/tool, try_to_fail = FALSE)
	var/success = FALSE
	if(accept_hand && !tool)
		success = TRUE
	else if(tool)
		for(var/key in implements)
			var/match = FALSE
			if(ispath(key) && istype(tool, key))
				match = TRUE
			else if(tool.tool_behaviour == key)
				match = TRUE
			if(match)
				implement_type = key
				if(tool_check(user, tool, target))
					success = TRUE
					break
	if(success)
		if(!validate_user(user))
			success = FALSE
		if(!validate_target(target, user))
			success = FALSE
		if(target.surgeries[target_zone])
			success = FALSE

	if(success)
		if(get_location_accessible(target, target_zone) || ignore_clothes)
			initiate(user, target, target_zone, tool, try_to_fail)
			return TRUE
	return FALSE

//Overrides the surgery step to require anasthetics for a smooth surgery
//also lets you do self-surgery again bottom text
/datum/surgery_step/proc/initiate(mob/user, mob/living/target, target_zone, obj/item/tool, try_to_fail = FALSE)
	target.surgeries[target_zone] = src
	var/advance = FALSE
	var/obj/item/bodypart/affecting = target.get_bodypart(target_zone)
	if(preop(user, target, target_zone, tool) == SURGERY_CANCEL)
		target.surgeries -= target_zone
		return FALSE

	var/time = minimum_time
	var/maximum_time_increase = (maximum_time - minimum_time)
	if(skill_used && stat_used)
		time += (maximum_time_increase * ((1 - GET_MOB_ATTRIBUTE_VALUE(user, skill_used)/SKILL_MASTER) + (1 - GET_MOB_ATTRIBUTE_VALUE(user, stat_used)/ATTRIBUTE_MASTER))/2)
	else if(skill_used)
		time += (maximum_time_increase * (1 - GET_MOB_ATTRIBUTE_VALUE(user, skill_used)/SKILL_MASTER))
	else if(stat_used)
		time += (maximum_time_increase * (1 - GET_MOB_ATTRIBUTE_VALUE(user, stat_used)/ATTRIBUTE_MASTER))
	time = clamp(CEILING(time, 1), minimum_time, maximum_time)
	var/speed_mod = (user == target ? 1.5 : 1)
	if(tool)
		speed_mod *= tool.toolspeed

	if(do_after(user, time * speed_mod, target = target))
		var/prob_chance = 100
		if(implement_type)	//this means it isn't a require hand or any item step.
			prob_chance = implements[implement_type]
		else if(!tool)
			prob_chance = accept_hand

		prob_chance *= get_surgery_probability_multiplier(src, target, user)

		var/mob/living/carbon/C = target
		if(istype(C) && affecting.can_feel_pain() && (C.stat <= UNCONSCIOUS) && (C.mob_biotypes & MOB_ORGANIC) && !C.InFullShock() && (C.get_chem_effect(CE_PAINKILLER) < 50))
			prob_chance *= 0.5
			C.visible_message(span_warning("<b>[C]</b> [pick("writhes in pain", "squirms and kicks in agony", "cries in pain as [target.p_their()] body violently jerks")], impeding the surgery!"), \
						span_warning("I[pick(" writhe as agonizing pain surges throught my entire body", " feel burning pain sending my body into a convulsion", " squirm as sickening pain fills every part of me")]!"))
			C.agony_scream()
			var/obj/item/bodypart/affected = C.get_bodypart(check_zone(target_zone))
			var/damage = 7.5 * (ATTRIBUTE_MIDDLING/GET_MOB_ATTRIBUTE_VALUE(C, STAT_ENDURANCE))
			if(affected?.get_incision())
				var/datum/injury/incision = affected.get_incision()
				incision.open_injury(damage)
			else
				C.apply_damage(damage, damagetype = BRUTE, def_zone = target_zone, blocked = FALSE, forced = FALSE, wound_bonus = CANT_WOUND)

		//Dice roll
		var/real_chance = prob_chance
		if(skill_used)
			real_chance = user.attribute_probability(GET_MOB_ATTRIBUTE_VALUE(user, skill_used), prob_chance, SKILL_MIDDLING, 5)
		var/didntfuckup = TRUE
		if(!prob(real_chance))
			didntfuckup = FALSE
		if(didntfuckup || (iscyborg(user) && !silicons_obey_prob && chem_check(target) && !try_to_fail))
			if(success(user, target, target_zone, tool))
				advance = SURGERY_ADVANCE
		else
			if(failure(user, target, target_zone, tool))
				advance = SURGERY_ADVANCE
		spread_germs_to_bodypart(affecting, user, tool)
	target.surgeries -= target_zone
	return advance

/datum/surgery_step/proc/preop(mob/user, mob/living/target, target_zone, obj/item/tool)
	display_results(user, target, \
		span_notice("I begin to perform surgery on [target]..."), \
		span_notice("[user] begins to perform surgery on [target]."), \
		span_notice("[user] begins to perform surgery on [target]."))

/datum/surgery_step/proc/success(mob/user, mob/living/target, target_zone, obj/item/tool)
	display_results(user, target, \
		span_notice("I succeed."), \
		span_notice("[user] succeeds!"), \
		span_notice("[user] finishes."))
	return SURGERY_ADVANCE

/datum/surgery_step/proc/failure(mob/user, mob/living/target, target_zone, obj/item/tool)
	display_results(user, target, span_warning("I screw up!"), \
		span_warning("[user] screws up!"), \
		span_warning("[user] finishes."), \
		TRUE) //By default the patient will notice if the wrong thing has been cut
	var/obj/item/bodypart/limb = target.get_bodypart(check_zone(target_zone))
	limb.receive_damage(brute = 15, sharpness = tool?.get_sharpness())
	return SURGERY_DONT_ADVANCE

/datum/surgery_step/proc/tool_check(mob/user, obj/item/tool, mob/living/carbon/target)
	return TRUE

/datum/surgery_step/proc/chem_check(mob/living/target)
	if(!LAZYLEN(chems_needed))
		return TRUE
	if(require_all_chems)
		. = TRUE
		for(var/R in chems_needed)
			if(!target.reagents.has_reagent(R))
				return FALSE
	else
		. = FALSE
		for(var/R in chems_needed)
			if(target.reagents.has_reagent(R))
				return TRUE

/datum/surgery_step/proc/get_chem_list()
	if(!LAZYLEN(chems_needed))
		return
	var/list/chems = list()
	for(var/R in chems_needed)
		var/datum/reagent/temp = GLOB.chemical_reagents_list[R]
		if(temp)
			var/chemname = temp.name
			chems += chemname
	return english_list(chems, and_text = require_all_chems ? " and " : " or ")

//Replaces visible_message during operations so only people looking over the surgeon can tell what they're doing, allowing for shenanigans.
/datum/surgery_step/proc/display_results(mob/user, mob/living/carbon/target, self_message, detailed_message, vague_message, target_detailed = FALSE)
	var/list/detailed_mobs = get_hearers_in_view(1, user) //Only the surgeon and people looking over his shoulder can see the operation clearly
	if(!target_detailed)
		detailed_mobs -= target //The patient can't see well what's going on, unless it's something like getting cut
	user.visible_message(detailed_message, self_message, vision_distance = 1, ignored_mobs = target_detailed ? null : target)
	user.visible_message(vague_message, ignored_mobs = detailed_mobs)