<commit_before>/obj/item/integrated_circuit/reagent
	category_text = "Reagent"
	var/volume = 0
	resistance_flags = UNACIDABLE | FIRE_PROOF
	origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)

/obj/item/integrated_circuit/reagent/New()
	..()
	if(volume)
		create_reagents(volume)

/obj/item/integrated_circuit/reagent/smoke
	name = "smoke generator"
	desc = "Unlike most electronics, creating smoke is completely intentional."
	icon_state = "smoke"
	extended_desc = "This smoke generator creates clouds of smoke on command.  It can also hold liquids inside, which will go \
	into the smoke clouds when activated.  The reagents are consumed when smoke is made."
	container_type = OPENCONTAINER_1
	complexity = 20
	cooldown_per_use = 1 SECONDS
	inputs = list()
	outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF)
	activators = list("create smoke" = IC_PINTYPE_PULSE_IN,"on smoked" = IC_PINTYPE_PULSE_OUT)
	spawn_flags = IC_SPAWN_RESEARCH
	origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 3)
	volume = 100
	power_draw_per_use = 20
	var/smoke_radius = 5
	var/notified = FALSE

/obj/item/integrated_circuit/reagent/smoke/on_reagent_change()
	//reset warning
	notified = FALSE
	set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
	push_data()


/obj/item/integrated_circuit/reagent/smoke/interact(mob/user)
	set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
	push_data()
	..()

/obj/item/integrated_circuit/reagent/smoke/do_work()
	var/location = get_turf(src)
	var/datum/effect_system/smoke_spread/chem/S = new
	S.attach(location)
	playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3)
	if(S)
		S.set_up(reagents, smoke_radius, location, notified)
		if(!notified)
			//we have now notified
			notified = TRUE
		S.start()

	if(reagents)
		reagents.clear_reagents()
	activate_pin(2)


/obj/item/integrated_circuit/reagent/injector
	name = "integrated hypo-injector"
	desc = "This scary looking thing is able to pump liquids into whatever it's pointed at."
	icon_state = "injector"
	extended_desc = "This autoinjector can push reagents into another container or someone else outside of the machine.  The target \
	must be adjacent to the machine, and if it is a person, they cannot be wearing thick clothing. Negative given amount makes injector suck out reagents."
	container_type = OPENCONTAINER_1
	complexity = 20
	cooldown_per_use = 6 SECONDS
	inputs = list("target" = IC_PINTYPE_REF, "injection amount" = IC_PINTYPE_NUMBER)
	inputs_default = list("2" = 5)
	outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF)
	activators = list("inject" = IC_PINTYPE_PULSE_IN, "on injected" = IC_PINTYPE_PULSE_OUT, "on fail" = IC_PINTYPE_PULSE_OUT)
	spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
	volume = 30
	power_draw_per_use = 15
	var/direction_mode = SYRINGE_INJECT
	var/transfer_amount = 10
	var/busy = FALSE

/obj/item/integrated_circuit/reagent/injector/interact(mob/user)
	set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
	push_data()
	..()


/obj/item/integrated_circuit/reagent/injector/on_reagent_change()
	set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
	push_data()

/obj/item/integrated_circuit/reagent/injector/on_data_written()
	var/new_amount = get_pin_data(IC_INPUT, 2)
	if(new_amount < 0)
		new_amount = -new_amount
		direction_mode = SYRINGE_DRAW
	else
		direction_mode = SYRINGE_INJECT
	if(isnum(new_amount))
		new_amount = Clamp(new_amount, 0, volume)
		transfer_amount = new_amount

/obj/item/integrated_circuit/reagent/proc/inject_tray(var/obj/machinery/hydroponics/H,var/atom/movable/SO,var/A)
		var/datum/reagents/S = new /datum/reagents() //This is a strange way, but I don't know of a better one so I can't fix it at the moment...
		S.my_atom = H
		SO.reagents.trans_to(S,A)
		H.applyChemicals(S)
		S.clear_reagents()
		qdel(S)

/obj/item/integrated_circuit/reagent/injector/do_work()
	set waitfor = FALSE // Don't sleep in a proc that is called by a processor without this set, otherwise it'll delay the entire thing
	var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
	if(!istype(AM)||!Adjacent(AM)||busy)
		activate_pin(3)
		return
	if(istype(AM,/obj/machinery/hydroponics)&&(direction_mode==SYRINGE_INJECT)&&(reagents.total_volume))//injection into tray.
		inject_tray(AM,src,transfer_amount)
		activate_pin(2)
		return
	if(!AM.reagents)
		activate_pin(3)
		return
	if(direction_mode == SYRINGE_INJECT)
		if(!reagents.total_volume) // Empty
			activate_pin(3)
			return
		if(AM.is_injectable())
			if(AM.reagents.total_volume>=AM.reagents.maximum_volume)
				activate_pin(3)
				return
			if(isliving(AM))
				var/mob/living/L = AM
				if(!L.can_inject(null, 0))
					activate_pin(3)
					return
				//Always log attemped injections for admins
				var/list/rinject = list()
				for(var/datum/reagent/R in reagents.reagent_list)
					rinject += R.name
				var/contained = english_list(rinject)
				add_logs(src, L, "attemped to inject", addition="which had [contained]") //TODO: proper logging (maybe last touched and assembled)
				L.visible_message("<span class='danger'>[src] is trying to inject [L]!</span>", \
										"<span class='userdanger'>[src] is trying to inject you!</span>")
				busy = TRUE
				if(do_atom(src, L, extra_checks=CALLBACK(L, /mob/living/proc/can_inject,null,0)))
					var/fraction = min(transfer_amount/reagents.total_volume, 1)
					reagents.reaction(L, INJECT, fraction)
					reagents.trans_to(L, transfer_amount)
					L.visible_message("<span class='danger'>[src] injects [L] with it's needle!</span>", \
											"<span class='userdanger'>[src] injects you with it's needle!</span>")
				else
					busy = FALSE
					activate_pin(3)
					return
				busy = FALSE
			else
				reagents.trans_to(AM, transfer_amount)
		else
			activate_pin(3)
			return
	else
		if(reagents.total_volume >= reagents.maximum_volume) // Full
			activate_pin(3)
			return
		var/tramount = Clamp(min(transfer_amount, reagents.maximum_volume - reagents.total_volume), 0, reagents.maximum_volume)
		if(isliving(AM))
			var/mob/living/L = AM<commit_msg>Grammar checks circuit hypospray (#32785)<commit_after>/obj/item/integrated_circuit/reagent
	category_text = "Reagent"
	var/volume = 0
	resistance_flags = UNACIDABLE | FIRE_PROOF
	origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)

/obj/item/integrated_circuit/reagent/New()
	..()
	if(volume)
		create_reagents(volume)

/obj/item/integrated_circuit/reagent/smoke
	name = "smoke generator"
	desc = "Unlike most electronics, creating smoke is completely intentional."
	icon_state = "smoke"
	extended_desc = "This smoke generator creates clouds of smoke on command.  It can also hold liquids inside, which will go \
	into the smoke clouds when activated.  The reagents are consumed when smoke is made."
	container_type = OPENCONTAINER_1
	complexity = 20
	cooldown_per_use = 1 SECONDS
	inputs = list()
	outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF)
	activators = list("create smoke" = IC_PINTYPE_PULSE_IN,"on smoked" = IC_PINTYPE_PULSE_OUT)
	spawn_flags = IC_SPAWN_RESEARCH
	origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 3)
	volume = 100
	power_draw_per_use = 20
	var/smoke_radius = 5
	var/notified = FALSE

/obj/item/integrated_circuit/reagent/smoke/on_reagent_change()
	//reset warning
	notified = FALSE
	set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
	push_data()


/obj/item/integrated_circuit/reagent/smoke/interact(mob/user)
	set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
	push_data()
	..()

/obj/item/integrated_circuit/reagent/smoke/do_work()
	var/location = get_turf(src)
	var/datum/effect_system/smoke_spread/chem/S = new
	S.attach(location)
	playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3)
	if(S)
		S.set_up(reagents, smoke_radius, location, notified)
		if(!notified)
			//we have now notified
			notified = TRUE
		S.start()

	if(reagents)
		reagents.clear_reagents()
	activate_pin(2)


/obj/item/integrated_circuit/reagent/injector
	name = "integrated hypo-injector"
	desc = "This scary looking thing is able to pump liquids into whatever it's pointed at."
	icon_state = "injector"
	extended_desc = "This autoinjector can push reagents into another container or someone else outside of the machine.  The target \
	must be adjacent to the machine, and if it is a person, they cannot be wearing thick clothing. Negative given amount makes injector suck out reagents."
	container_type = OPENCONTAINER_1
	complexity = 20
	cooldown_per_use = 6 SECONDS
	inputs = list("target" = IC_PINTYPE_REF, "injection amount" = IC_PINTYPE_NUMBER)
	inputs_default = list("2" = 5)
	outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF)
	activators = list("inject" = IC_PINTYPE_PULSE_IN, "on injected" = IC_PINTYPE_PULSE_OUT, "on fail" = IC_PINTYPE_PULSE_OUT)
	spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
	volume = 30
	power_draw_per_use = 15
	var/direction_mode = SYRINGE_INJECT
	var/transfer_amount = 10
	var/busy = FALSE

/obj/item/integrated_circuit/reagent/injector/interact(mob/user)
	set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
	push_data()
	..()


/obj/item/integrated_circuit/reagent/injector/on_reagent_change()
	set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
	push_data()

/obj/item/integrated_circuit/reagent/injector/on_data_written()
	var/new_amount = get_pin_data(IC_INPUT, 2)
	if(new_amount < 0)
		new_amount = -new_amount
		direction_mode = SYRINGE_DRAW
	else
		direction_mode = SYRINGE_INJECT
	if(isnum(new_amount))
		new_amount = Clamp(new_amount, 0, volume)
		transfer_amount = new_amount

/obj/item/integrated_circuit/reagent/proc/inject_tray(var/obj/machinery/hydroponics/H,var/atom/movable/SO,var/A)
		var/datum/reagents/S = new /datum/reagents() //This is a strange way, but I don't know of a better one so I can't fix it at the moment...
		S.my_atom = H
		SO.reagents.trans_to(S,A)
		H.applyChemicals(S)
		S.clear_reagents()
		qdel(S)

/obj/item/integrated_circuit/reagent/injector/do_work()
	set waitfor = FALSE // Don't sleep in a proc that is called by a processor without this set, otherwise it'll delay the entire thing
	var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
	if(!istype(AM)||!Adjacent(AM)||busy)
		activate_pin(3)
		return
	if(istype(AM,/obj/machinery/hydroponics)&&(direction_mode==SYRINGE_INJECT)&&(reagents.total_volume))//injection into tray.
		inject_tray(AM,src,transfer_amount)
		activate_pin(2)
		return
	if(!AM.reagents)
		activate_pin(3)
		return
	if(direction_mode == SYRINGE_INJECT)
		if(!reagents.total_volume) // Empty
			activate_pin(3)
			return
		if(AM.is_injectable())
			if(AM.reagents.total_volume>=AM.reagents.maximum_volume)
				activate_pin(3)
				return
			if(isliving(AM))
				var/mob/living/L = AM
				if(!L.can_inject(null, 0))
					activate_pin(3)
					return
				//Always log attemped injections for admins
				var/list/rinject = list()
				for(var/datum/reagent/R in reagents.reagent_list)
					rinject += R.name
				var/contained = english_list(rinject)
				add_logs(src, L, "attemped to inject", addition="which had [contained]") //TODO: proper logging (maybe last touched and assembled)
				L.visible_message("<span class='danger'>[src] is trying to inject [L]!</span>", \
										"<span class='userdanger'>[src] is trying to inject you!</span>")
				busy = TRUE
				if(do_atom(src, L, extra_checks=CALLBACK(L, /mob/living/proc/can_inject,null,0)))
					var/fraction = min(transfer_amount/reagents.total_volume, 1)
					reagents.reaction(L, INJECT, fraction)
					reagents.trans_to(L, transfer_amount)
					L.visible_message("<span class='danger'>[src] injects [L] with its needle!</span>", \
											"<span class='userdanger'>[src] injects you with its needle!</span>")
				else
					busy = FALSE
					activate_pin(3)
					return
				busy = FALSE
			else
				reagents.trans_to(AM, transfer_amount)
		else
			activate_pin(3)
			return
	else
		if(reagents.total_volume >= reagents.maximum_volume) // Full
			activate_pin(3)
			return
		var/tramount = Clamp(min(transfer_amount, reagents.maximum_volume - reagents.total_volume), 0, reagents.maximum_volume)
		if(isliving(AM))
			var/mob/living/L = AM
{'fraction_non_alphanumeric': 0.11279737489745693, 'fraction_numerical': 0.009433962264150943, 'mean_word_length': 4.6050574712643675, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4040347', 'n_tokens_mistral': 5037, 'n_tokens_neox': 4423, 'n_words': 949}