code:
/datum/organ_process/heart
	slot = ORGAN_SLOT_HEART
	mob_types = list(/mob/living/carbon/human)
	var/static/sound/slowbeat = sound('modular_septic/sound/heart/slowbeat.ogg', channel = CHANNEL_HEARTBEAT, repeat = TRUE)
	var/static/sound/fastbeat = sound('modular_septic/sound/heart/fastbeat.ogg', channel = CHANNEL_HEARTBEAT, repeat = TRUE)

/datum/organ_process/heart/needs_process(mob/living/carbon/owner)
	return (..() && owner.needs_heart())

/datum/organ_process/heart/handle_process(mob/living/carbon/owner, delta_time, times_fired)
	handle_pulse(owner, delta_time, times_fired)
	if(owner.pulse)
		handle_heartbeat(owner, delta_time, times_fired)
		if(owner.pulse == PULSE_FASTER && DT_PROB(0.5, delta_time))
			owner.adjustOrganLoss(ORGAN_SLOT_HEART, 1)
		if(owner.pulse >= PULSE_THREADY && DT_PROB(2.5, delta_time))
			owner.adjustOrganLoss(ORGAN_SLOT_HEART, 1)
	handle_blood(owner, delta_time, times_fired)
	return TRUE

/datum/organ_process/heart/proc/handle_pulse(mob/living/carbon/owner, delta_time, times_fired)
	// Pulse mod starts out as just the chemical effect amount
	var/heart_efficiency = owner.getorganslotefficiency(ORGAN_SLOT_HEART)
	var/is_stable = owner.get_chem_effect(CE_STABLE) || HAS_TRAIT(owner, TRAIT_STABLEHEART)
	var/pulse_mod = (is_stable ? 0 : owner.get_chem_effect(CE_PULSE))

	// If you have enough heart chemicals to be over 2, you're likely to take extra damage.
	if(pulse_mod > 2 && !is_stable)
		var/damage_chance = (pulse_mod - 2) ** 2
		// delta time is fucking WEIRD
		if(DT_PROB(damage_chance/2, delta_time))
			owner.adjustOrganLoss(ORGAN_SLOT_HEART, 1)

	// Now pulse mod is impacted by shock stage and other things too
	var/oxygenation = GET_EFFECTIVE_BLOOD_VOL(owner.get_blood_oxygenation(), owner.total_blood_req)
	if(!is_stable)
		if(owner.shock_stage >= SHOCK_STAGE_2)
			pulse_mod++
		if(owner.shock_stage >= SHOCK_STAGE_5)
			pulse_mod++

	if(oxygenation < BLOOD_VOLUME_OKAY) //Brain wants us to get MOAR OXY
		pulse_mod++
	if(oxygenation < BLOOD_VOLUME_BAD) //MOAR
		pulse_mod++

	if(HAS_TRAIT(owner, TRAIT_FAKEDEATH) || owner.get_chem_effect(CE_NOPULSE))
		owner.pulse = clamp(PULSE_NONE + pulse_mod, PULSE_NONE, PULSE_FASTER) //Pretend that we're dead. unlike actual death, can be infuenced by meds
		return

	// If our heart is stopped, it isn't going to restart itself randomly.
	if(heart_efficiency < failing_threshold)
		owner.set_heartattack(TRUE)
		return
	if(owner.pulse <= PULSE_NONE)
		return

	// Pulse normally shouldn't go above PULSE_FASTER unless you get extremely doped up
	if(pulse_mod < 5)
		owner.pulse = clamp(PULSE_NORM + pulse_mod, PULSE_SLOW, PULSE_FASTER)
	else
		owner.pulse = clamp(PULSE_NORM + pulse_mod, PULSE_SLOW, PULSE_THREADY)

	// If in fibrillation, then it can be PULSE_THREADY
	var/fibrillation = ((oxygenation <= BLOOD_VOLUME_SURVIVE) || (owner.shock_stage >= SHOCK_STAGE_6 && DT_PROB(25, delta_time)))
	if(owner.pulse && fibrillation)
		owner.pulse = PULSE_THREADY

	// Stablising chemicals pull the heartbeat towards the center
	if(owner.pulse != PULSE_NORM && is_stable)
		if(owner.pulse > PULSE_NORM)
			owner.pulse--
		else
			owner.pulse++

	// Thready pulse can damage us
	if(owner.pulse >= PULSE_THREADY)
		if(DT_PROB(2.5, delta_time))
			owner.adjustOrganLoss(ORGAN_SLOT_HEART, 1)
	else if(owner.pulse >= PULSE_FASTER)
		if(DT_PROB(0.5, delta_time))
			owner.adjustOrganLoss(ORGAN_SLOT_HEART, 1)

	// Finally, check if we should go into cardiac arrest
	// cardiovascular shock, not enough liquid to pump
	var/should_stop = (owner.get_blood_circulation() < BLOOD_VOLUME_SURVIVE + DEFAULT_TOTAL_BLOOD_REQ - owner.total_blood_req) && DT_PROB(40, delta_time)
	// brain failing to work heart properly
	should_stop = should_stop || DT_PROB(max(0, GETBRAINLOSS(owner) - owner.maxHealth * 0.75)/2, delta_time)
	// erratic heart patterns, usually caused by oxyloss
	should_stop = should_stop || (owner.pulse >= PULSE_THREADY && DT_PROB(6, delta_time))

	// One heart has stopped due to going into traumatic or cardiovascular shock
	if(should_stop)
		// We don't use the set_heartattack proc here to avoid stopping all hearts instead of one only
		var/list/hearts = owner.getorganslotlist(ORGAN_SLOT_HEART)
		for(var/heartache in shuffle(hearts))
			var/obj/item/organ/heart/heart = heartache
			if(heart.can_stop())
				heart.Stop()
				break
	// No pulse means we are already having a cardiac arrest moment
	if(owner.pulse <= PULSE_NONE)
		owner.set_heartattack(TRUE)

/datum/organ_process/heart/proc/handle_blood(mob/living/carbon/owner, delta_time, times_fired)
	// Dead, pulseless or cryosleep people do not pump blood
	if(!owner.pulse || (owner.bodytemperature <= TCRYO))
		return

	// this is crazy dumbass code but it makes sense if you think enough about it
	var/effective_blood_circulation = GET_EFFECTIVE_BLOOD_VOL(owner.get_blood_circulation(), owner.total_blood_req)
	// keep in mind, get_blood_circulation() already deals with heart efficiency!

	// Effects of blood circulation
	switch(effective_blood_circulation)
		if(BLOOD_VOLUME_EXCESS to BLOOD_VOLUME_MAX_LETHAL)
			owner.status_flags &= ~BLEEDOUT
			if(DT_PROB(7.5, delta_time))
				to_chat(owner, span_userdanger("Blood starts to tear my arteries apart!"))
				var/obj/item/bodypart/artery_popper = pick(owner.bodyparts)
				if(!artery_popper.is_artery_torn())
					artery_popper.force_wound_upwards(/datum/wound/artery)
		if(BLOOD_VOLUME_MAXIMUM to BLOOD_VOLUME_EXCESS)
			owner.status_flags &= ~BLEEDOUT
			if(DT_PROB(5, delta_time))
				to_chat(owner, span_warning("My arteries feel terribly bloated."))
		if(-INFINITY to BLOOD_VOLUME_SURVIVE)
			if(!(owner.status_flags & BLEEDOUT))
				owner.status_flags |= BLEEDOUT
				to_chat(owner, span_userdanger("My organs feel outrageously heavy!"))
			else if(DT_PROB(2.5, delta_time))
				to_chat(owner, span_userdanger("Not... Enough... Blood..."))
		else
			owner.status_flags &= ~BLEEDOUT

	// Bleeding out
	var/temp_bleed = 0
	var/bleed_mod = 1
	if(ishuman(owner))
		var/mob/living/carbon/human/human_owner = owner
		if(human_owner.physiology)
			bleed_mod *= human_owner.physiology.bleed_mod
	for(var/X in owner.bodyparts)
		var/obj/item/bodypart/bleed_part = X
		var/resulting_bleed = bleed_part.get_bleed_rate(TRUE) * 0.5 * delta_time
		bleed_part.generic_bleedstacks = max(0, bleed_part.generic_bleedstacks - 0.5 * delta_time)
		switch(owner.pulse)
			if(PULSE_SLOW)
				resulting_bleed *= 0.8
			if(PULSE_FAST)
				resulting_bleed *= 1.25
			if(PULSE_FASTER, PULSE_THREADY)
				resulting_bleed *= 1.5
		resulting_bleed = CEILING(resulting_bleed * bleed_mod, 0.1)
		if(!resulting_bleed)
			continue
		if(bleed_part.current_gauze)
			bleed_part.seep_gauze(resulting_bleed * bleed_part.current_gauze.absorption_rate)
		else
			temp_bleed += resulting_bleed
	if(temp_bleed)
		owner.bleed(temp_bleed)
	if(CHECK_BITFIELD(owner.status_flags, BLEEDOUT) && DT_PROB(50, delta_time))
		owner.Unconscious(4 SECONDS)

/datum/organ_process/heart/proc/handle_heartbeat(mob/living/carbon/owner, delta_time, times_fired)
	var/turf/T = get_turf(owner)
	var/datum/gas_mixture/environment = (istype(T) ? T.return_air() : null)
	var/pressure = (environment ? environment.return_pressure() : 0)
	if(owner.heartbeat_sound != BEAT_SLOW && (owner.nervous_system_failure() || owner.undergoing_cardiac_arrest() || (pressure < SOUND_MINIMUM_PRESSURE) ))
		owner.heartbeat_sound = BEAT_SLOW
		owner.playsound_local(get_turf(owner), slowbeat, 40, 0, channel = CHANNEL_HEARTBEAT, use_reverb = FALSE)
		if(owner.nervous_system_failure() || owner.undergoing_cardiac_arrest())
			to_chat(owner, span_notice("You feel your heart slow down..."))
		return
	if(owner.heartbeat_sound == BEAT_SLOW && !owner.nervous_system_failure() && !owner.undergoing_cardiac_arrest() && !(pressure < SOUND_MINIMUM_PRESSURE))
		owner.stop_sound_channel(CHANNEL_HEARTBEAT)
		owner.heartbeat_sound = BEAT_NONE
		return
	if((owner.jitteriness || owner.shock_stage >= SHOCK_STAGE_2) && !owner.nervous_system_failure())
		owner.playsound_local(get_turf(owner), fastbeat, 40, 0, channel = CHANNEL_HEARTBEAT, use_reverb = FALSE)
		owner.heartbeat_sound = BEAT_FAST
		return
	if(owner.heartbeat_sound == BEAT_FAST && !owner.jitteriness && owner.shock_stage < SHOCK_STAGE_2)
		owner.stop_sound_channel(CHANNEL_HEARTBEAT)
		owner.heartbeat_sound = BEAT_NONE
		return


code:
/datum/organ_process/intestines
	slot = ORGAN_SLOT_INTESTINES
	mob_types = list(/mob/living/carbon/human)

/datum/organ_process/intestines/needs_process(mob/living/carbon/owner)
	return (..() && !(NOINTESTINES in owner.dna.species.species_traits))

/datum/organ_process/intestines/handle_process(mob/living/carbon/owner, delta_time, times_fired)
	var/list/intestines = owner.getorganslotlist(ORGAN_SLOT_INTESTINES)
	var/needshit_event
	var/collective_shit_amount = 0
	for(var/obj/item/organ/intestines/intestine as anything in intestines)
		collective_shit_amount += (intestine.reagents.get_reagent_amount(/datum/reagent/consumable/shit) - intestine.food_reagents[/datum/reagent/consumable/shit])
	switch(collective_shit_amount)
		if(30 to 60)
			needshit_event = /datum/mood_event/needshit
			if(DT_PROB(5, delta_time))
				to_chat(owner, span_warning(pick("I need to go to the bathroom.", "I need to shit.", "I need to take a dump.")))
		if(60 to INFINITY)
			needshit_event = /datum/mood_event/reallyneedshit
			if(DT_PROB(10, delta_time))
				to_chat(owner, span_warning(pick("I <b>really</b> need to shit!", "My anus is BLEEDING!", "I'm gonna shit myself!")))
	if(needshit_event)
		SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "need_poop", needshit_event)
	else
		SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "need_poop")
	return TRUE

repo_name: AnalWerewolf/sundown

license: mit


code:
#define HAS_SILENT_TOXIN 0 //don't provide a feedback message if this is the only toxin present
#define HAS_NO_TOXIN 1
#define HAS_PAINFUL_TOXIN 2

/datum/organ_process/kidneys
	slot = ORGAN_SLOT_KIDNEYS
	mob_types = list(/mob/living/carbon/human)

/datum/organ_process/kidneys/needs_process(mob/living/carbon/owner)
	return (..() && !HAS_TRAIT(owner, TRAIT_NOMETABOLISM) && !(NOKIDNEYS in owner.dna.species.species_traits))

/datum/organ_process/kidneys/handle_process(mob/living/carbon/owner, delta_time, times_fired)
	if(!HAS_TRAIT(owner, TRAIT_NOMETABOLISM))
		handle_toxins(owner, delta_time, times_fired)
	if(!HAS_TRAIT(owner, TRAIT_NOTHIRST))
		handle_hydration(owner, delta_time, times_fired)
	return TRUE

/datum/organ_process/kidneys/proc/handle_toxins(mob/living/carbon/human/owner, delta_time, times_fired)
	var/list/kidneys = owner.getorganslotlist(ORGAN_SLOT_KIDNEYS)
	var/kidney_efficiency = owner.getorganslotefficiency(ORGAN_SLOT_KIDNEYS)
	var/filter_toxins = FALSE
	var/collective_tox_tolerance = 0
	var/collective_tox_lethality = 0
	for(var/thing in kidneys)
		var/obj/item/organ/kidneys/kidney = thing
		if(kidney.is_failing())
			continue
		if(kidney.filter_toxins)
			filter_toxins = TRUE
		collective_tox_tolerance += kidney.tox_tolerance
		collective_tox_lethality += kidney.tox_lethality
	var/antitoxin_effect = owner.get_chem_effect(CE_ANTITOX)
	if(antitoxin_effect)
		filter_toxins = TRUE
		kidney_efficiency += antitoxin_effect
		collective_tox_tolerance += antitoxin_effect/10
		collective_tox_lethality -= antitoxin_effect/10
	if(filter_toxins && (kidney_efficiency >= failing_threshold))
		if(filter_toxins && !HAS_TRAIT(owner, TRAIT_TOXINLOVER))
			var/list/stomachs = owner.getorganslot(ORGAN_SLOT_STOMACH)
			// handle toxin filtration
			for(var/datum/reagent/toxin/T in owner.reagents.reagent_list)
				var/thisamount = owner.reagents.get_reagent_amount(T.type)
				if(thisamount && thisamount <= collective_tox_tolerance * (kidney_efficiency/optimal_threshold))
					owner.reagents.remove_reagent(T.type, 0.5 * delta_time * (kidney_efficiency/100))
				else if(collective_tox_lethality > 0)
					owner.adjustOrganLoss(ORGAN_SLOT_LIVER, thisamount * collective_tox_lethality * (0.5 * delta_time))
			for(var/thing in stomachs)
				var/obj/belly = thing
				for(var/datum/reagent/toxin/T in belly.reagents.reagent_list)
					var/thisamount = belly.reagents.get_reagent_amount(T.type)
					if(thisamount && thisamount <= collective_tox_tolerance * (kidney_efficiency/optimal_threshold))
						owner.reagents.remove_reagent(T.type, 0.5 * delta_time * (kidney_efficiency/100))
					else if(collective_tox_lethality > 0)
						owner.adjustOrganLoss(ORGAN_SLOT_LIVER, thisamount * collective_tox_lethality * (100/kidney_efficiency) * (0.5 * delta_time))

/datum/organ_process/kidneys/proc/handle_hydration(mob/living/carbon/human/owner, delta_time, times_fired)
	var/kidney_efficiency = owner.getorganslotefficiency(ORGAN_SLOT_KIDNEYS)
	// hydration decrease and satiety
	if(owner.hydration > 0)
		var/thirst_rate = owner.total_hydration_req
		thirst_rate *= 100/max(kidney_efficiency, 25)
		// Whether we cap off our satiety or move it towards 0
		if(owner.hydro_satiety > MAX_SATIETY)
			owner.hydro_satiety = MAX_SATIETY
		else if(owner.hydro_satiety > 0)
			owner.hydro_satiety -= (0.5 * delta_time)
		else if(owner.hydro_satiety < -MAX_SATIETY)
			owner.hydro_satiety = -MAX_SATIETY
		else if(owner.hydro_satiety < 0)
			owner.hydro_satiety += (0.5 * delta_time)
			if(DT_PROB(round(-owner.hydro_satiety/75), delta_time))
				owner.Jitter(5)
			thirst_rate *= 2
		thirst_rate *= owner.physiology.thirst_mod
		owner.adjust_hydration(-thirst_rate * (0.5 * delta_time))

	//Thirst slowdown for if mood isn't enabled
	if(CONFIG_GET(flag/disable_human_mood))
		if(!HAS_TRAIT(owner, TRAIT_NOHUNGER))
			var/thirsty = (500 - owner.hydration) / 5
			if(thirsty >= 70)
				owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/thirst, TRUE, multiplicative_slowdown = (thirsty / 50))
			else
				owner.remove_movespeed_modifier(/datum/movespeed_modifier/thirst, TRUE)

	switch(owner.hydration)
		if(HYDRATION_LEVEL_WELL_HYDRATED to INFINITY)
			owner.update_hud_hydration(4)
		if(HYDRATION_LEVEL_HYDRATED to HYDRATION_LEVEL_WELL_HYDRATED)
			owner.update_hud_hydration(3)
		if(HYDRATION_LEVEL_THIRSTY to HYDRATION_LEVEL_HYDRATED)
			owner.update_hud_hydration(2)
		if(HYDRATION_LEVEL_DEHYDRATED to HYDRATION_LEVEL_THIRSTY)
			owner.update_hud_hydration(1)
		if(0 to HYDRATION_LEVEL_DEHYDRATED)
			owner.update_hud_hydration(0)

#undef HAS_SILENT_TOXIN
#undef HAS_NO_TOXIN
#undef HAS_PAINFUL_TOXIN


code:
/datum/organ_process/liver
	slot = ORGAN_SLOT_LIVER
	processes_dead = TRUE

/datum/organ_process/liver/needs_process(mob/living/carbon/owner)
	return (..() && !HAS_TRAIT(owner, TRAIT_NOMETABOLISM) && !(NOLIVER in owner.dna?.species?.species_traits))

/datum/organ_process/liver/handle_process(mob/living/carbon/owner, delta_time, times_fired)
	var/liver_efficiency = owner.getorganslotefficiency(ORGAN_SLOT_LIVER)
	if(liver_efficiency >= failing_threshold)
		if(owner.stat < DEAD)
			// metabolize reagents
			owner.reagents.metabolize(owner, delta_time, times_fired, can_overdose=TRUE)
			return
		else
			for(var/reagent in owner.reagents.reagent_list)
				var/datum/reagent/R = reagent
				R.on_mob_dead(owner, delta_time)
	return TRUE


code:
/datum/organ_process/lungs
	slot = ORGAN_SLOT_LUNGS

/datum/organ_process/lungs/needs_process(mob/living/carbon/owner)
	var/needlung = owner.needs_lungs()
	if(!needlung || owner.stat >= DEAD)
		owner.failed_last_breath = FALSE
		owner.clear_alert("cant_breathe")
		return FALSE
	return ..()

/datum/organ_process/lungs/handle_process(mob/living/carbon/owner, delta_time, times_fired)
	var/next_breath = owner.get_breath_modulo() // Breathe per 4 ticks normally
	if((times_fired % next_breath) == 0 || owner.failed_last_breath)
		owner.breathe(delta_time, times_fired, src)
		if(owner.failed_last_breath)
			SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "suffocation", /datum/mood_event/suffocation)
		else
			SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "suffocation")
	else
		if(istype(owner.loc, /obj/))
			var/obj/location_as_object = owner.loc
			location_as_object.handle_internal_lifeform(owner,0)
	handle_oxygenation(owner, delta_time, times_fired)
	return TRUE

/datum/organ_process/lungs/proc/handle_oxygenation(mob/living/carbon/owner, delta_time, times_fired)
	var/lung_efficiency = owner.getorganslotefficiency(ORGAN_SLOT_LUNGS)
	var/effective_oxygenation = ((100 - owner.getOxyLoss()) * (lung_efficiency/optimal_threshold))
	if(effective_oxygenation < owner.total_oxygen_req)
		if(DT_PROB(0.5, delta_time))
			if(owner.body_position != LYING_DOWN)
				owner.visible_message(span_danger("[owner] falls to the ground and hyperventilates!"), \
								span_userdanger("I need more air!"))
			else
				owner.visible_message(span_danger("[owner] hyperventilates!"), \
					span_userdanger("I need more air!"))
			owner.Knockdown(8 SECONDS)
			INVOKE_ASYNC(src, .proc/gasp_spam, owner)
		if(DT_PROB(2, delta_time))
			owner.blur_eyes(5)
			owner.set_confusion(max(owner.get_confusion(), rand(8, 16)) )
		if(DT_PROB(2, delta_time))
			owner.agony_gasp()
			owner.losebreath = max(owner.losebreath, rand(8, 16))
		if(DT_PROB(4, delta_time))
			owner.emote("cough")
	if(effective_oxygenation < (owner.total_oxygen_req/10))
		if(DT_PROB(20, delta_time))
			ADJUSTBRAINLOSS(owner, pick(BRAIN_DAMAGE_LOWER_OXYGENATION, BRAIN_DAMAGE_LOWEST_OXYGENATION))

/datum/organ_process/lungs/proc/gasp_spam(mob/living/carbon/victim)
	for(var/i in 1 to 3)
		if(prob(80))
			victim.agony_gasp()
		else
			victim.agony_gargle()
		sleep(1 SECONDS)


code:
//The penis process actually handles horniness in general
/datum/organ_process/penis
	slot = ORGAN_SLOT_PENIS
	mob_types = list(/mob/living/carbon/human)

/datum/organ_process/penis/needs_process(mob/living/carbon/owner)
	return (..() && !(NOHORNY in owner.dna.species.species_traits))

/datum/organ_process/penis/handle_process(mob/living/carbon/human/owner, delta_time, times_fired)
	// horny handling
	switch(owner.arousal)
		if(AROUSAL_LEVEL_HORNY to INFINITY)
			SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "horny", /datum/mood_event/reallyneedsex)
		if(AROUSAL_LEVEL_AROUSED to AROUSAL_LEVEL_HORNY)
			SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "horny", /datum/mood_event/needsex)
		else
			SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "horny")
	//lust reduction
	if(owner.lust)
		owner.adjust_lust(-DELUST_FACTOR)
	return TRUE


code:
/datum/organ_process/spleen
	slot = ORGAN_SLOT_SPLEEN
	mob_types = list(/mob/living/carbon/human)

/datum/organ_process/spleen/needs_process(mob/living/carbon/owner)
	return (..() && !HAS_TRAIT(owner, TRAIT_NOHUNGER) && !HAS_TRAIT(owner, TRAIT_NOBLEED) && !(NOSPLEEN in owner.dna.species.species_traits) && !(NOBLOOD in owner.dna.species.species_traits))

/datum/organ_process/spleen/handle_process(mob/living/carbon/owner, delta_time, times_fired)
	if(owner.blood_volume >= BLOOD_VOLUME_NORMAL)
		return
	var/nutrition_ratio = 0
	switch(owner.nutrition)
		if(0 to NUTRITION_LEVEL_STARVING)
			nutrition_ratio = 0.2
		if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
			nutrition_ratio = 0.4
		if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
			nutrition_ratio = 0.6
		if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
			nutrition_ratio = 0.8
		else
			nutrition_ratio = 1
	if(owner.satiety > 80)
		nutrition_ratio *= 1.25

	var/blood_regen = 0
	var/combined_nutrition_requirement = 0
	var/list/spleens = owner.getorganslotlist(ORGAN_SLOT_SPLEEN)
	for(var/thing in spleens)
		var/obj/item/organ/spleen/spleen = thing
		blood_regen += (spleen.get_slot_efficiency(ORGAN_SLOT_SPLEEN) * spleen.blood_regen_factor)
		combined_nutrition_requirement += (spleen.nutriment_req/1000)
	if(!blood_regen)
		return
	owner.adjust_nutrition(-combined_nutrition_requirement * nutrition_ratio * 0.5 * delta_time)
	owner.adjust_bloodvolume(CEILING(blood_regen * nutrition_ratio * 0.5 * delta_time, 0.1))
	return TRUE


code:
/datum/organ_process/stomach
	slot = ORGAN_SLOT_STOMACH
	mob_types = list(/mob/living/carbon/human)

/datum/organ_process/stomach/needs_process(mob/living/carbon/owner)
	return (..() && !(NOSTOMACH in owner.dna.species.species_traits))

/datum/organ_process/stomach/handle_process(mob/living/carbon/owner, delta_time, times_fired)
	// Manage digestion
	if(!HAS_TRAIT(owner, TRAIT_NOHUNGER))
		handle_nutrition(owner, delta_time, times_fired)
	// If we don't feel hunger, we should still try and digest whatever is in the stomachs
	handle_digestion(owner, delta_time, times_fired)
	// Disgust too is important regardless of hunger
	handle_disgust(owner, delta_time, times_fired)
	return TRUE

/datum/organ_process/stomach/proc/handle_nutrition(mob/living/carbon/human/owner, delta_time, times_fired)
	var/stomach_efficiency = owner.getorganslotefficiency(ORGAN_SLOT_STOMACH)
	//The fucking TRAIT_FAT mutation is the dumbest shit ever. It makes the code so difficult to work with
	if(HAS_TRAIT_FROM(owner, TRAIT_FAT, OBESITY))//I share your pain, past coder.
		if(owner.overeatduration < 200 SECONDS)
			to_chat(owner, span_notice("I feel fit again!"))
			REMOVE_TRAIT(owner, TRAIT_FAT, OBESITY)
			owner.remove_movespeed_modifier(/datum/movespeed_modifier/obesity)
			owner.update_inv_w_uniform()
			owner.update_inv_wear_suit()
	else
		if(owner.overeatduration >= 200 SECONDS)
			to_chat(owner, span_danger("I suddenly feel blubbery!"))
			ADD_TRAIT(owner, TRAIT_FAT, OBESITY)
			owner.add_movespeed_modifier(/datum/movespeed_modifier/obesity)
			owner.update_inv_w_uniform()
			owner.update_inv_wear_suit()

	// nutrition decrease and satiety
	if(owner.nutrition > 0)
		// THEY HUNGER
		var/hunger_rate = owner.total_nutriment_req
		hunger_rate *= 100/max(stomach_efficiency, 25)
		// Whether we cap off our satiety or move it towards 0
		if(owner.satiety > MAX_SATIETY)
			owner.satiety = MAX_SATIETY
		else if(owner.satiety > 0)
			owner.satiety -= (0.5 * delta_time)
		else if(owner.satiety < -MAX_SATIETY)
			owner.satiety = -MAX_SATIETY
		else if(owner.satiety < 0)
			owner.satiety += (0.5 * delta_time)
			if(DT_PROB(round(-owner.satiety/75), delta_time))
				owner.Jitter(5)
			hunger_rate *= 2
		hunger_rate *= owner.physiology.hunger_mod
		owner.adjust_nutrition(-hunger_rate * (0.5 * delta_time))

	if(owner.nutrition > NUTRITION_LEVEL_FULL)
		//capped so people don't take forever to unfat
		if(owner.overeatduration < 20 MINUTES)
			owner.overeatduration = min(owner.overeatduration + (1 SECONDS * delta_time), 20 MINUTES)
	else if(owner.overeatduration > 0)
		owner.overeatduration = max(owner.overeatduration - (2 SECONDS * delta_time), 0)

	//metabolism change
	if(owner.nutrition > NUTRITION_LEVEL_FAT)
		owner.metabolism_efficiency = 1
	else if(owner.nutrition > NUTRITION_LEVEL_FED && owner.satiety > 80)
		if(owner.metabolism_efficiency != 1.25)
			to_chat(owner, span_notice("I feel vigorous."))
		owner.metabolism_efficiency = 1.25
	else if(owner.nutrition < (NUTRITION_LEVEL_STARVING + 50))
		if(owner.metabolism_efficiency != 0.8)
			to_chat(owner, span_notice("I feel sluggish."))
		owner.metabolism_efficiency = 0.8
	else
		if(owner.metabolism_efficiency == 1.25)
			to_chat(owner, span_notice("I no longer feel vigorous."))
		owner.metabolism_efficiency = 1

	//Hunger slowdown for if mood isn't enabled
	if(CONFIG_GET(flag/disable_human_mood))
		if(!HAS_TRAIT(owner, TRAIT_NOHUNGER))
			var/hungry = (500 - owner.nutrition) / 5 //So overeat would be 100 and default level would be 80
			if(hungry >= 70)
				owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/hunger, TRUE, multiplicative_slowdown = (hungry / 50))
			else
				owner.remove_movespeed_modifier(/datum/movespeed_modifier/hunger, TRUE)

	switch(owner.nutrition)
		if(NUTRITION_LEVEL_WELL_FED to INFINITY)
			owner.update_hud_nutrition(4)
		if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
			owner.update_hud_nutrition(3)
		if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
			owner.update_hud_nutrition(2)
		if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
			owner.update_hud_nutrition(1)
		if(0 to NUTRITION_LEVEL_STARVING)
			owner.update_hud_nutrition(0)

/datum/organ_process/stomach/proc/handle_digestion(mob/living/carbon/human/owner, delta_time, times_fired)
	var/datum/organ_process/intestine_process = GLOB.organ_processes_by_slot[ORGAN_SLOT_INTESTINES]
	var/datum/organ_process/bladder_process = GLOB.organ_processes_by_slot[ORGAN_SLOT_BLADDER]

	var/intestinal_efficiency = owner.getorganslotefficiency(ORGAN_SLOT_INTESTINES)
	var/list/intestines = owner.getorganslotlist(ORGAN_SLOT_INTESTINES)
	for(var/obj/item/organ/intestine as anything in intestines)
		if(intestine.get_slot_efficiency(ORGAN_SLOT_INTESTINES) < intestine_process.failing_threshold)
			intestines -= intestine

	var/bladderal_efficiency = owner.getorganslotefficiency(ORGAN_SLOT_BLADDER)
	var/list/bladders = owner.getorganslotlist(ORGAN_SLOT_BLADDER)
	for(var/obj/item/organ/bladder as anything in bladders)
		if(bladder.get_slot_efficiency(ORGAN_SLOT_BLADDER) < bladder_process.failing_threshold)
			bladders -= bladder

	var/stomachal_efficiency = owner.getorganslotefficiency(ORGAN_SLOT_STOMACH)
	var/list/stomachs = owner.getorganslotlist(ORGAN_SLOT_STOMACH)
	for(var/obj/item/organ/stomach/stomach as anything in stomachs)
		// digest food, sent all reagents that can metabolize to the body
		for(var/chunk in stomach.reagents.reagent_list)
			var/datum/reagent/bit = chunk

			// If the reagent does not metabolize then it will sit in the stomach
			// This has an effect on items like plastic causing them to take up space in the stomach
			if(bit.metabolization_rate <= 0)
				continue

			// Ensure that the the minimum is equal to the metabolization_rate of the reagent if it is higher then the STOMACH_METABOLISM_CONSTANT
			var/rate_min = max(bit.metabolization_rate, STOMACH_METABOLISM_CONSTANT)
			// Do not transfer over more then we have
			var/amount_max = bit.volume

			// If the reagent is part of the food reagents for the organ
			// prevent all the reagents form being used leaving the food reagents
			var/amount_food = stomach.food_reagents[bit.type]
			if(amount_food)
				amount_max = max(amount_max - amount_food, 0)
			// Each stomach has an efficiency of it's own
			var/this_stomach_efficiency = stomach.get_slot_efficiency(ORGAN_SLOT_STOMACH)
			// Transfer the amount of reagents based on volume with a min amount of 1u
			var/amount = min((round(stomach.metabolism_efficiency * (this_stomach_efficiency/optimal_threshold) * amount_max, 0.05) + rate_min) * delta_time, amount_max)
			if(amount <= 0)
				continue

			// shit and piss will clog up the stomach without being metabolized
			if(istype(bit, /datum/reagent/consumable/shit))
				if(NOINTESTINES in owner.dna.species.species_traits)
					stomach.reagents.remove_all_type(bit.type)
					continue
				if(!length(intestines) || (intestinal_efficiency < intestine_process.failing_threshold))
					continue
				// try to transfer the shit to the intestines
				var/divided_amount = CEILING(amount/(max(1, length(intestines))), 0.1)
				if(divided_amount > 0)
					if(intestinal_efficiency >= intestine_process.failing_threshold)
						for(var/obj/item/organ/intestine as anything in intestines)
							intestines -= intestine
							var/modifier = clamp(FLOOR(intestine.get_slot_efficiency(ORGAN_SLOT_INTESTINES)/intestine_process.optimal_threshold, 0.1), 0.1, 3)
							var/spillover = max(0, intestine.reagents.total_volume + (divided_amount * modifier) - intestine.reagents.maximum_volume)
							intestine.reagents.add_reagent(/datum/reagent/consumable/shit, (divided_amount * modifier) - spillover, data = owner.get_blood_dna_list())
							stomach.reagents.remove_reagent(/datum/reagent/consumable/shit, (divided_amount * modifier) - spillover)
							// this is here to stay
							if(spillover)
								// unless a friend helps out that is
								if(length(intestines))
									divided_amount = CEILING(divided_amount + spillover/length(intestines), 0.1)
				// oh dear, this is here to stay - in the stomach
				continue
			else if(istype(bit, /datum/reagent/consumable/piss))
				if(NOBLADDER in owner.dna.species.species_traits)
					stomach.reagents.remove_all_type(bit.type)
					continue
				if(!length(bladders) || (bladderal_efficiency < bladder_process.failing_threshold))
					continue
				// try to transfer the piss to the bladders
				var/divided_amount = CEILING(amount/(max(1, length(bladders))), 0.1)
				if(divided_amount > 0)
					if(bladderal_efficiency >= bladder_process.failing_threshold)
						for(var/obj/item/organ/bladder as anything in bladders)
							bladders -= bladder
							var/modifier = clamp(FLOOR(bladder.get_slot_efficiency(ORGAN_SLOT_BLADDER)/bladder_process.optimal_threshold, 0.1), 0.1, 3)
							var/spillover = max(0, bladder.reagents.total_volume + (divided_amount * modifier) - bladder.reagents.maximum_volume)
							bladder.reagents.add_reagent(/datum/reagent/consumable/piss, (divided_amount * modifier) - spillover)
							stomach.reagents.remove_reagent(/datum/reagent/consumable/piss, (divided_amount * modifier) - spillover)
							// this is here to stay
							if(spillover)
								// unless a friend helps out that is
								if(length(bladders))
									divided_amount = CEILING(divided_amount + spillover/length(bladders), 0.1)
				// oh dear, this is here to stay - in the stomach
				continue

			// transfer the reagents over to the body at the rate of the stomach metabolim
			// this way the body is where all reagents that are processed and react
			// the stomach manages how fast they are feed in a drip style
			stomach.reagents.trans_id_to(owner, bit.type, amount=amount)

			var/pissable = FALSE
			var/shittable = FALSE
			if(istype(bit, /datum/reagent/consumable))
				var/datum/reagent/consumable/food = bit
				if(food.nutriment_factor)
					shittable = TRUE
				if(food.hydration_factor)
					pissable = TRUE
			else if(istype(bit, /datum/reagent/water))
				pissable = TRUE
			if(shittable && !(NOINTESTINES in owner.dna.species.species_traits))
				// what goes in, must come out (as shit)
				var/divided_amount = CEILING(amount/(max(1, length(intestines))), 0.1)
				if(divided_amount > 0)
					if(intestinal_efficiency >= intestine_process.failing_threshold)
						for(var/obj/item/organ/intestine as anything in intestines)
							intestines -= intestine
							var/modifier = clamp(FLOOR(intestine_process.optimal_threshold/intestine.get_slot_efficiency(ORGAN_SLOT_INTESTINES), 0.1), 0.1, 3)
							var/spillover = max(0, intestine.reagents.total_volume + (divided_amount * modifier) - intestine.reagents.maximum_volume)
							intestine.reagents.add_reagent(/datum/reagent/consumable/shit, (divided_amount * modifier) - spillover, data = owner.get_blood_dna_list())
							// this is here to stay
							if(spillover)
								// unless a friend helps out that is
								if(!length(intestines))
									stomach.reagents.add_reagent(/datum/reagent/consumable/shit, spillover, data = owner.get_blood_dna_list())
								else
									divided_amount = CEILING(divided_amount + spillover/length(intestines), 0.1)
					// oh dear, this is here to stay - in the stomach
					else
						stomach.reagents.add_reagent(/datum/reagent/consumable/shit, divided_amount, data = owner.get_blood_dna_list())
			if(pissable && !(NOBLADDER in owner.dna.species.species_traits))
				// what goes in, must come out (as piss)
				var/divided_amount = CEILING(amount/(max(1, length(bladders))), 0.1)
				if(divided_amount > 0)
					if(bladderal_efficiency >= bladder_process.failing_threshold)
						for(var/obj/item/organ/bladder as anything in bladders)
							bladders -= bladder
							var/modifier = clamp(FLOOR(bladder_process.optimal_threshold/bladder.get_slot_efficiency(ORGAN_SLOT_BLADDER), 0.1), 0.1, 3)
							var/spillover = max(0, bladder.reagents.total_volume + (divided_amount * modifier) - bladder.reagents.maximum_volume)
							bladder.reagents.add_reagent(/datum/reagent/consumable/piss, (divided_amount * modifier) - spillover)
							// this is here to stay
							if(spillover)
								// unless a friend helps out that is
								if(!length(bladders))
									stomach.reagents.add_reagent(/datum/reagent/consumable/piss, spillover)
								else
									divided_amount = CEILING(divided_amount + spillover/length(bladders), 0.1)
					// oh dear, this is here to stay - in the stomach
					else
						stomach.reagents.add_reagent(/datum/reagent/consumable/piss, divided_amount)

	for(var/obj/item/organ/stomach/stomach as anything in stomachs)
		// This stomach is ok
		if(!stomach.is_bruised() && !stomach.is_failing())
			continue

		// We are checking if we have nutriment in a damaged stomach.
		var/datum/reagent/nutri = locate(/datum/reagent/consumable/nutriment) in stomach.reagents.reagent_list

		// No nutriment found lets exit out
		if(!nutri)
			continue

		// remove the food reagent amount
		var/nutri_vol = nutri.volume
		var/amount_food = stomach.food_reagents[nutri.type]
		if(amount_food)
			nutri_vol = max(nutri_vol - amount_food, 0)

		// found nutriment was stomach food reagent
		if(!(nutri_vol > 0))
			continue

		// Each stomach has an efficiency of it's own
		if(stomach.damage < stomach.high_threshold)
			// The stomach is damaged, has nutriment, but low on theshold, low prob of vomit
			if(DT_PROB(0.0125 * (optimal_threshold - stomachal_efficiency) * (nutri_vol ** 2), delta_time))
				owner.vomit(optimal_threshold - stomachal_efficiency)
				to_chat(owner, span_warning("Your [stomach.name] reels in pain as you're incapable of holding down all that food!"))
				return
		else
			// the change of vomit is now high
			if(DT_PROB(0.05 * (optimal_threshold - stomachal_efficiency) * (nutri_vol ** 2), delta_time))
				owner.vomit(optimal_threshold - stomachal_efficiency)
				to_chat(owner, span_warning("Your [stomach.name] reels in pain as you're incapable of holding down all that food!"))
				return

/datum/organ_process/stomach/proc/handle_disgust(mob/living/carbon/human/owner, delta_time, times_fired)
	var/combined_disgust_metabolism = 0
	for(var/thing in owner.getorganslotlist(ORGAN_SLOT_STOMACH))
		var/obj/item/organ/stomach/stomach = thing
		combined_disgust_metabolism += stomach.disgust_metabolism
	if(owner.disgust)
		var/pukeprob = 2.5 + (0.025 * owner.disgust)
		if(owner.disgust >= DISGUST_LEVEL_GROSS)
			if(DT_PROB(5, delta_time))
				owner.stuttering += 1
				owner.add_confusion(2)
			if(DT_PROB(5, delta_time) && !owner.stat)
				to_chat(owner, span_warning("You feel kind of iffy..."))
			owner.jitteriness = max(owner.jitteriness - 3, 0)
		if(owner.disgust >= DISGUST_LEVEL_VERYGROSS)
			if(DT_PROB(pukeprob, delta_time)) //iT hAndLeS mOrE ThaN PukInG
				owner.add_confusion(2.5)
				owner.stuttering += 1
				owner.vomit(10, 0, 1, 0, 1, 0)
			owner.Dizzy(5)
		if(owner.disgust >= DISGUST_LEVEL_DISGUSTED)
			if(DT_PROB(13, delta_time))
				owner.blur_eyes(3) //We need to add more shit down here
		owner.adjust_disgust(-0.25 * combined_disgust_metabolism * delta_time)
	switch(owner.disgust)
		if(0 to DISGUST_LEVEL_GROSS)
			owner.clear_alert("disgust")
			SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "disgust")
		if(DISGUST_LEVEL_GROSS to DISGUST_LEVEL_VERYGROSS)
			owner.throw_alert("disgust", /atom/movable/screen/alert/gross)
			SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "disgust", /datum/mood_event/gross)
		if(DISGUST_LEVEL_VERYGROSS to DISGUST_LEVEL_DISGUSTED)
			owner.throw_alert("disgust", /atom/movable/screen/alert/verygross)
			SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "disgust", /datum/mood_event/verygross)
		if(DISGUST_LEVEL_DISGUSTED to INFINITY)
			owner.throw_alert("disgust", /atom/movable/screen/alert/disgusted)
			SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "disgust", /datum/mood_event/disgusted)


code:
/obj/item/organ/appendix
	name = "appendix"
	icon_state = "appendix"
	base_icon_state = "appendix"
	desc = "The most famous useless organ of the human body!"
	zone = BODY_ZONE_PRECISE_GROIN
	organ_efficiency = list(ORGAN_SLOT_APPENDIX = 100)
	food_reagents = list(/datum/reagent/consumable/nutriment = 5, \
						/datum/reagent/toxin/bad_food = 5)
	grind_results = list(/datum/reagent/toxin/bad_food = 5)

	maxHealth = STANDARD_ORGAN_THRESHOLD * 0.5 // weak to mirror real life
	high_threshold = STANDARD_ORGAN_THRESHOLD * 0.4
	low_threshold =  STANDARD_ORGAN_THRESHOLD * 0.1
	healing_factor = 0 // just cut this nigga out lmao

	w_class = WEIGHT_CLASS_TINY

	now_failing = span_warning("An explosion of pain erupts in your lower right abdomen!")
	now_fixed = span_info("The pain in your abdomen has subsided.")

	// a small resource hog
	organ_volume = 0.5
	max_blood_storage = 2.5
	current_blood = 2.5
	blood_req = 0.5
	oxygen_req = 0.25
	nutriment_req = 0.5
	hydration_req = 0.5

	var/inflamation_stage = 0

/obj/item/organ/appendix/update_name()
	. = ..()
	name = "[inflamation_stage ? "inflamed " : null][initial(name)]"

/obj/item/organ/appendix/update_icon_state()
	icon_state = "[base_icon_state][inflamation_stage ? "inflamed" : ""]"
	return ..()

/obj/item/organ/appendix/organ_failure(delta_time)
	. = ..()
	inflamation_stage = TRUE
	owner.adjustToxLoss(0.5 * delta_time, TRUE, TRUE) //forced to ensure people don't use it to gain tox as slime person

/obj/item/organ/appendix/get_availability(datum/species/S)
	return !(TRAIT_NOHUNGER in S.inherent_traits)


code:
/obj/item/organ/cyberimp
	name = "cybernetic implant"
	desc = "A state-of-the-art implant that improves a baseline's functionality."
	status = ORGAN_ROBOTIC
	organ_flags = ORGAN_SYNTHETIC
	emp_vulnerability = 50
	var/implant_color = "#FFFFFF"
	var/implant_overlay

/obj/item/organ/cyberimp/New(mob/M = null)
	if(iscarbon(M))
		src.Insert(M)
	update_appearance()
	return ..()

/obj/item/organ/cyberimp/update_overlays()
	. = ..()
	if(implant_overlay)
		var/image/overlay = image(icon, src, implant_overlay)
		overlay.color = implant_color
		. += implant_overlay

//BOX O' IMPLANTS
/obj/item/storage/box/cyber_implants
	name = "boxed cybernetic implants"
	desc = "A sleek, sturdy box."
	icon_state = "cyber_implants"
	var/list/boxed = list(
		/obj/item/autosurgeon/organ/syndicate/thermal_eyes,
		/obj/item/autosurgeon/organ/syndicate/xray_eyes,
		/obj/item/autosurgeon/organ/syndicate/anti_stun,
		/obj/item/autosurgeon/organ/syndicate/reviver)
	var/amount = 5

/obj/item/storage/box/cyber_implants/PopulateContents()
	var/implant
	while(contents.len <= amount)
		implant = pick(boxed)
		new implant(src)


code:
/obj/item/organ/cyberimp/arm
	name = "arm-mounted implant"
	desc = "You shouldn't see this! Adminhelp and report this as an issue on github!"
	zone = BODY_ZONE_R_ARM
	organ_efficiency = list(ORGAN_SLOT_ARM_AUG = 100)
	icon_state = "implant-toolkit"
	w_class = WEIGHT_CLASS_SMALL
	actions_types = list(/datum/action/item_action/organ_action/toggle)
	emp_vulnerability = 50
	///A ref for the arm we're taking up. Mostly for the unregister signal upon removal
	var/obj/hand
	//A list of typepaths to create and insert into ourself on init
	var/list/items_to_create = list()
	/// Used to store a list of all items inside, for multi-item implants.
	var/list/items_list = list()// I would use contents, but they shuffle on every activation/deactivation leading to interface inconsistencies.
	/// You can use this var for item path, it would be converted into an item on New().
	var/obj/item/active_item
	/// Sound played when extending
	var/extend_sound = 'sound/mecha/mechmove03.ogg'
	/// Sound played when retracting
	var/retract_sound = 'sound/mecha/mechmove03.ogg'

/obj/item/organ/cyberimp/arm/Initialize()
	. = ..()
	if(ispath(active_item))
		active_item = new active_item(src)
		items_list += WEAKREF(active_item)
	for(var/typepath in items_to_create)
		var/atom/new_item = new typepath(src)
		items_list += WEAKREF(new_item)

	SetSlotFromZone()
	update_appearance()

/obj/item/organ/cyberimp/arm/Destroy()
	hand = null
	active_item = null
	for(var/datum/weakref/ref in items_list)
		var/obj/item/to_del = ref.resolve()
		if(!to_del)
			continue
		qdel(to_del)
	items_list.Cut()
	return ..()

/obj/item/organ/cyberimp/arm/proc/SetSlotFromZone(new_zone = zone)
	switch(new_zone)
		if(BODY_ZONE_R_ARM)
			organ_efficiency = list(ORGAN_SLOT_ARM_AUG = 100)
		if(BODY_ZONE_L_ARM)
			organ_efficiency = list(ORGAN_SLOT_ARM_AUG = 100)
		else
			CRASH("Invalid zone set for arm cyberimp.")

/obj/item/organ/cyberimp/arm/update_appearance()
	. = ..()
	transform = (zone == BODY_ZONE_R_ARM) ? null : matrix(-1, 0, 0, 0, 1, 0)

/obj/item/organ/cyberimp/arm/screwdriver_act(mob/living/user, obj/item/I)
	. = ..()
	if(.)
		return TRUE
	I.play_tool_sound(src)
	if(zone == BODY_ZONE_R_ARM)
		zone = BODY_ZONE_L_ARM
	else
		zone = BODY_ZONE_R_ARM
	to_chat(user, span_notice("You modify [src] to be installed on the [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm."))
	SetSlotFromZone()
	update_appearance()

/obj/item/organ/cyberimp/arm/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE)
	. = ..()
	var/side = zone == BODY_ZONE_R_ARM? RIGHT_HANDS : LEFT_HANDS
	hand = owner.hand_bodyparts[side]
	if(hand)
		RegisterSignal(hand, COMSIG_ITEM_ATTACK_SELF, .proc/ui_action_click) //If the limb gets an attack-self, open the menu. Only happens when hand is empty
		RegisterSignal(M, COMSIG_KB_MOB_DROPITEM_DOWN, .proc/dropkey) //We're nodrop, but we'll watch for the drop hotkey anyway and then stow if possible.

/obj/item/organ/cyberimp/arm/Remove(mob/living/carbon/M, special = 0)
	Retract()
	if(hand)
		UnregisterSignal(hand, COMSIG_ITEM_ATTACK_SELF)
		UnregisterSignal(M, COMSIG_KB_MOB_DROPITEM_DOWN)
	return ..()

/obj/item/organ/cyberimp/arm/emp_act(severity)
	. = ..()
	if(!owner || !CHECK_BITFIELD(organ_flags, ORGAN_SYNTHETIC) || . & EMP_PROTECT_SELF)
		return
	if(prob(15/severity * (emp_vulnerability/50)) && owner)
		to_chat(owner, span_warning("The electromagnetic pulse causes [src] to malfunction!"))
		// give the owner an idea about why his implant is glitching
		Retract()

/**
 * Called when the mob uses the "drop item" hotkey
 *
 * Items inside toolset implants have TRAIT_NODROP, but we can still use the drop item hotkey as a
 * quick way to store implant items. In this case, we check to make sure the user has the correct arm
 * selected, and that the item is actually owned by us, and then we'll hand off the rest to Retract()
**/
/obj/item/organ/cyberimp/arm/proc/dropkey(mob/living/carbon/host)
	if(!host)
		return //How did we even get here
	if(hand != host.hand_bodyparts[host.active_hand_index])
		return //wrong hand
	Retract()

/obj/item/organ/cyberimp/arm/proc/Retract()
	if(!active_item || (active_item in src))
		return

	owner.visible_message(span_notice("[owner] retracts [active_item] back into [owner.p_their()] [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm."),
		span_notice("[active_item] snaps back into your [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm."),
		span_hear("You hear a short mechanical noise."))

	owner.transferItemToLoc(active_item, src, TRUE)
	active_item = null
	playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, TRUE)

/obj/item/organ/cyberimp/arm/proc/Extend(obj/item/item)
	if(!(item in src))
		return

	active_item = item

	active_item.resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
	ADD_TRAIT(active_item, TRAIT_NODROP, HAND_REPLACEMENT_TRAIT)
	active_item.slot_flags = null
	active_item.set_custom_materials(null)

	var/side = zone == BODY_ZONE_R_ARM? RIGHT_HANDS : LEFT_HANDS
	var/hand = owner.get_empty_held_index_for_side(side)
	if(hand)
		owner.put_in_hand(active_item, hand)
	else
		var/list/hand_items = owner.get_held_items_for_side(side, all = TRUE)
		var/success = FALSE
		var/list/failure_message = list()
		for(var/i in 1 to hand_items.len) //Can't just use *in* here.
			var/I = hand_items[i]
			if(!owner.dropItemToGround(I))
				failure_message += span_warning("Your [I] interferes with [src]!")
				continue
			to_chat(owner, span_notice("You drop [I] to activate [src]!"))
			success = owner.put_in_hand(active_item, owner.get_empty_held_index_for_side(side))
			break
		if(!success)
			for(var/i in failure_message)
				to_chat(owner, i)
			return
	owner.visible_message(span_notice("[owner] extends [active_item] from [owner.p_their()] [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm."),
		span_notice("You extend [active_item] from your [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm."),
		span_hear("You hear a short mechanical noise."))
	playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, TRUE)

/obj/item/organ/cyberimp/arm/ui_action_click()
	if((organ_flags & ORGAN_FAILING) || (!active_item && !contents.len))
		to_chat(owner, span_warning("The implant doesn't respond. It seems to be broken..."))
		return

	if(!active_item || (active_item in src))
		active_item = null
		if(contents.len == 1)
			Extend(contents[1])
		else
			var/list/choice_list = list()
			for(var/obj/item/I in items_list)
				choice_list[I] = image(I)
			var/obj/item/choice = show_radial_menu(owner, owner, choice_list)
			if(owner && owner == usr && owner.stat != DEAD && (src in owner.internal_organs) && !active_item && (choice in contents))
				// This monster sanity check is a nice example of how bad input is.
				Extend(choice)
	else
		Retract()


code:
/obj/item/organ/cyberimp/arm/baton
	name = "arm electrification implant"
	desc = "An illegal combat implant that allows the user to administer disabling shocks from their arm."
	contents = newlist(/obj/item/borg/stun)


code:
/obj/item/organ/cyberimp/arm/combat
	name = "combat cybernetics implant"
	desc = "A powerful cybernetic implant that contains combat modules built into the user's arm."
	contents = newlist(/obj/item/melee/energy/blade/hardlight, \
					/obj/item/gun/medbeam, \
					/obj/item/borg/stun, \
					/obj/item/assembly/flash/armimplant)


code:
/obj/item/organ/cyberimp/arm/esword
	name = "arm-mounted energy blade"
	desc = "An illegal and highly dangerous cybernetic implant that can project a deadly blade of concentrated energy."
	contents = newlist(/obj/item/melee/energy/blade/hardlight)

/obj/item/organ/cyberimp/arm/esword/l
	zone = BODY_ZONE_L_ARM


code:
/obj/item/organ/cyberimp/arm/flash
	name = "integrated high-intensity photon projector" //Why not
	desc = "An integrated projector mounted onto a user's arm that is able to be used as a powerful flash."
	contents = newlist(/obj/item/assembly/flash/armimplant)

/obj/item/organ/cyberimp/arm/flash/Extend()
	. = ..()
	active_item.set_light_range(7)
	active_item.set_light_on(TRUE)

/obj/item/organ/cyberimp/arm/flash/Retract()
	active_item.set_light_on(FALSE)
	return ..()

/obj/item/organ/cyberimp/arm/flash/l
	zone = BODY_ZONE_L_ARM


code:
/obj/item/organ/cyberimp/arm/gun/emp_act(severity)
	. = ..()
	if(. & EMP_PROTECT_SELF)
		return
	if(prob(30/severity) && owner && !(organ_flags & ORGAN_FAILING))
		Retract()
		owner.visible_message(span_danger("A loud bang comes from [owner]\'s [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm!"))
		playsound(get_turf(owner), 'sound/weapons/flashbang.ogg', 100, 1)
		to_chat(owner, span_userdanger("You feel an explosion erupt inside your [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm as your implant breaks!"))
		owner.adjust_fire_stacks(20)
		owner.IgniteMob()
		owner.adjustFireLoss(25)
		organ_flags |= ORGAN_FAILING


code:
/obj/item/organ/cyberimp/arm/gun/laser
	name = "arm-mounted laser implant"
	desc = "A variant of the arm cannon implant that fires lethal laser beams. The cannon emerges from the subject's arm and remains inside when not in use."
	icon_state = "arm_laser"
	contents = newlist(/obj/item/gun/energy/laser/mounted)

/obj/item/organ/cyberimp/arm/gun/laser/Initialize()
	. = ..()
	var/obj/item/organ/cyberimp/arm/gun/laser/laserphasergun = locate(/obj/item/gun/energy/laser/mounted) in contents
	laserphasergun.icon = icon //No invisible laser guns kthx
	laserphasergun.icon_state = icon_state

/obj/item/organ/cyberimp/arm/gun/laser/l
	zone = BODY_ZONE_L_ARM


code:
/obj/item/organ/cyberimp/arm/medibeam
	name = "integrated medical beamgun"
	desc = "A cybernetic implant that allows the user to project a healing beam from their hand."
	contents = newlist(/obj/item/gun/medbeam)

/obj/item/organ/cyberimp/arm/medibeam/l
	zone = BODY_ZONE_L_ARM


code:
/obj/item/organ/cyberimp/arm/surgery
	name = "surgical toolset implant"
	desc = "A set of surgical tools hidden behind a concealed panel on the user's arm."
	contents = newlist(/obj/item/retractor/augment, \
					/obj/item/hemostat/augment, \
					/obj/item/cautery/augment, \
					/obj/item/surgicaldrill/augment, \
					/obj/item/scalpel/augment, \
					/obj/item/circular_saw/augment, \
					/obj/item/surgical_drapes)


code:
/obj/item/organ/cyberimp/arm/gun/taser
	name = "arm-mounted taser implant"
	desc = "A variant of the arm cannon implant that fires electrodes and disabler shots. The cannon emerges from the subject's arm and remains inside when not in use."
	icon_state = "arm_taser"
	contents = newlist(/obj/item/gun/energy/e_gun/advtaser/mounted)

/obj/item/organ/cyberimp/arm/gun/taser/l
	zone = BODY_ZONE_L_ARM


code:
/obj/item/organ/cyberimp/arm/toolset
	name = "integrated toolset implant"
	desc = "A stripped-down version of the engineering cyborg toolset, designed to be installed on subject's arm. Contain advanced versions of every tool."
	contents = newlist(/obj/item/screwdriver/cyborg, /obj/item/wrench/cyborg, /obj/item/weldingtool/largetank/cyborg,
		/obj/item/crowbar/cyborg, /obj/item/wirecutters/cyborg, /obj/item/multitool/cyborg)

/obj/item/organ/cyberimp/arm/toolset/emag_act(mob/user)
	. = ..()
	if(!(locate(/obj/item/knife/combat/cyborg) in items_list))
		to_chat(user, span_notice("I unlock [src]'s integrated knife!"))
		items_list += new /obj/item/knife/combat/cyborg(src)
		return TRUE
	return FALSE

/obj/item/organ/cyberimp/arm/toolset/l
	zone = BODY_ZONE_L_ARM


code:
/obj/item/organ/cyberimp/brain
	name = "cybernetic brain implant"
	desc = "Injectors of extra sub-routines for the brain."
	icon_state = "brain_implant"
	implant_overlay = "brain_implant_overlay"
	organ_efficiency = list(ORGAN_SLOT_HEAD_AUG = 100)
	zone = BODY_ZONE_HEAD
	w_class = WEIGHT_CLASS_TINY
	emp_vulnerability = 50

/obj/item/organ/cyberimp/brain/emp_act(severity)
	. = ..()
	if(!owner || !CHECK_BITFIELD(organ_flags, ORGAN_SYNTHETIC) || . & EMP_PROTECT_SELF)
		return
	var/stun_amount = 200/severity * emp_vulnerability/50
	owner.Stun(stun_amount)
	to_chat(owner, span_warning("Your body seizes up!"))


code:
/obj/item/organ/cyberimp/brain/anti_drop
	name = "anti-drop implant"
	desc = "This cybernetic brain implant will allow you to force your hand muscles to contract, preventing item dropping. Twitch ear to toggle."
	implant_color = "#DE7E00"
	actions_types = list(/datum/action/item_action/organ_action/toggle)
	var/active = 0
	var/list/stored_items = list()

/obj/item/organ/cyberimp/brain/anti_drop/ui_action_click()
	active = !active
	if(active)
		for(var/obj/item/I in owner.held_items)
			stored_items += I

		var/list/L = owner.get_empty_held_indexes()
		if(LAZYLEN(L) == owner.held_items.len)
			to_chat(owner, span_notice("You are not holding any items, your hands relax..."))
			active = 0
			stored_items = list()
		else
			for(var/obj/item/I in stored_items)
				to_chat(owner, span_notice("Your [owner.get_held_index_name(owner.get_held_index_of_item(I))]'s grip tightens."))
				ADD_TRAIT(I, TRAIT_NODROP, IMPLANT_TRAIT)

	else
		release_items()
		to_chat(owner, span_notice("Your hands relax..."))

/obj/item/organ/cyberimp/brain/anti_drop/emp_act(severity)
	. = ..()
	if(!owner || . & EMP_PROTECT_SELF)
		return
	var/range = severity ? 10 : 5
	var/atom/A
	if(active)
		release_items()
	for(var/obj/item/I in stored_items)
		A = pick(oview(range))
		I.throw_at(A, range, 2)
		to_chat(owner, span_warning("Your [owner.get_held_index_name(owner.get_held_index_of_item(I))] spasms and throws the [I.name]!"))
	stored_items = list()

/obj/item/organ/cyberimp/brain/anti_drop/proc/release_items()
	for(var/obj/item/I in stored_items)
		REMOVE_TRAIT(I, TRAIT_NODROP, IMPLANT_TRAIT)
	stored_items = list()

/obj/item/organ/cyberimp/brain/anti_drop/Remove(mob/living/carbon/M, special = 0)
	if(active)
		ui_action_click()
	return ..()


code:
/obj/item/organ/cyberimp/brain/anti_stun
	name = "CNS Rebooter implant"
	desc = "This implant will automatically give you back control over your central nervous system, reducing downtime when stunned."
	implant_color = "#FFFF00"
	var/static/list/signalCache = list(
		COMSIG_LIVING_STATUS_STUN,
		COMSIG_LIVING_STATUS_KNOCKDOWN,
		COMSIG_LIVING_STATUS_IMMOBILIZE,
		COMSIG_LIVING_STATUS_PARALYZE,
	)
	var/stun_cap_amount = 40

/obj/item/organ/cyberimp/brain/anti_stun/Remove(mob/living/carbon/M, special = FALSE)
	. = ..()
	UnregisterSignal(M, signalCache)

/obj/item/organ/cyberimp/brain/anti_stun/Insert()
	. = ..()
	RegisterSignal(owner, signalCache, .proc/on_signal)

/obj/item/organ/cyberimp/brain/anti_stun/proc/on_signal(datum/source, amount)
	if(!(organ_flags & ORGAN_FAILING) && amount > 0)
		addtimer(CALLBACK(src, .proc/clear_stuns), stun_cap_amount, TIMER_UNIQUE|TIMER_OVERRIDE)

/obj/item/organ/cyberimp/brain/anti_stun/proc/clear_stuns()
	if(owner || !(organ_flags & ORGAN_FAILING))
		owner.SetStun(0)
		owner.SetKnockdown(0)
		owner.SetImmobilized(0)
		owner.SetParalyzed(0)

/obj/item/organ/cyberimp/brain/anti_stun/emp_act(severity)
	. = ..()
	if((organ_flags & ORGAN_FAILING) || . & EMP_PROTECT_SELF)
		return
	organ_flags |= ORGAN_FAILING
	addtimer(CALLBACK(src, .proc/reboot), 90 / severity)

/obj/item/organ/cyberimp/brain/anti_stun/proc/reboot()
	organ_flags &= ~ORGAN_FAILING


code:
/obj/item/organ/cyberimp/chest
	name = "cybernetic torso implant"
	desc = "Implants for the organs in your torso."
	icon_state = "chest_implant"
	implant_overlay = "chest_implant_overlay"
	organ_efficiency = list(ORGAN_SLOT_CHEST_AUG = 100)
	zone = BODY_ZONE_CHEST
	emp_vulnerability = 50


code:
/obj/item/organ/cyberimp/chest/nutriment
	name = "Nutriment pump implant"
	desc = "This implant will synthesize and pump into your bloodstream a small amount of nutriment when you are starving."
	icon_state = "chest_implant"
	implant_color = "#00AA00"
	var/hunger_threshold = NUTRITION_LEVEL_STARVING
	var/synthesizing = 0
	var/poison_amount = 5

/obj/item/organ/cyberimp/chest/nutriment/on_life(delta_time, times_fired)
	. = ..()
	if(synthesizing)
		return

	if(owner.nutrition <= hunger_threshold)
		synthesizing = TRUE
		to_chat(owner, span_notice("You feel less hungry..."))
		owner.adjust_nutrition(25 * delta_time)
		addtimer(CALLBACK(src, .proc/synth_cool), 50)

/obj/item/organ/cyberimp/chest/nutriment/proc/synth_cool()
	synthesizing = FALSE

/obj/item/organ/cyberimp/chest/nutriment/emp_act(severity)
	. = ..()
	if(!owner || . & EMP_PROTECT_SELF)
		return
	owner.reagents.add_reagent(/datum/reagent/toxin/bad_food, poison_amount * severity)
	to_chat(owner, span_warning("You feel like your insides are burning."))

/obj/item/organ/cyberimp/chest/nutriment/plus
	name = "Nutriment pump implant PLUS"
	desc = "This implant will synthesize and pump into your bloodstream a small amount of nutriment when you are hungry."
	icon_state = "chest_implant"
	implant_color = "#006607"
	hunger_threshold = NUTRITION_LEVEL_HUNGRY
	poison_amount = 10


code:
/obj/item/organ/cyberimp/chest/reviver
	name = "Reviver implant"
	desc = "This implant will attempt to revive and heal you if you lose consciousness. For the faint of heart!"
	icon_state = "chest_implant"
	implant_color = "#AD0000"
	var/revive_cost = 0
	var/reviving = FALSE
	COOLDOWN_DECLARE(reviver_cooldown)

/obj/item/organ/cyberimp/chest/reviver/on_life(delta_time, times_fired)
	. = ..()
	if(reviving)
		switch(owner.stat)
			if(UNCONSCIOUS, HARD_CRIT)
				addtimer(CALLBACK(src, .proc/heal), 3 SECONDS)
			else
				COOLDOWN_START(src, reviver_cooldown, revive_cost)
				reviving = FALSE
				to_chat(owner, span_notice("Your reviver implant shuts down and starts recharging. It will be ready again in [DisplayTimeText(revive_cost)]."))
		return

	if(!COOLDOWN_FINISHED(src, reviver_cooldown) || owner.suiciding)
		return

	switch(owner.stat)
		if(UNCONSCIOUS, HARD_CRIT)
			revive_cost = 0
			reviving = TRUE
			to_chat(owner, span_notice("You feel a faint buzzing as your reviver implant starts patching your wounds..."))

/obj/item/organ/cyberimp/chest/reviver/proc/heal()
	if(owner.getOxyLoss())
		owner.adjustOxyLoss(-5)
		revive_cost += 5
	if(owner.getBruteLoss())
		owner.adjustBruteLoss(-2)
		revive_cost += 40
	if(owner.getFireLoss())
		owner.adjustFireLoss(-2)
		revive_cost += 40
	if(owner.getToxLoss())
		owner.adjustToxLoss(-1)
		revive_cost += 40

/obj/item/organ/cyberimp/chest/reviver/emp_act(severity)
	. = ..()
	if(!owner || . & EMP_PROTECT_SELF)
		return

	if(reviving)
		revive_cost += 200
	else
		reviver_cooldown += 20 SECONDS

	if(ishuman(owner))
		var/mob/living/carbon/human/H = owner
		if(H.stat != DEAD && prob(50 / severity) && H.can_heartattack())
			H.set_heartattack(TRUE)
			to_chat(H, span_userdanger("You feel a horrible agony in your chest!"))
			addtimer(CALLBACK(src, .proc/undo_heart_attack), 600 / severity)

/obj/item/organ/cyberimp/chest/reviver/proc/undo_heart_attack()
	var/mob/living/carbon/human/H = owner
	if(!istype(H))
		return
	H.set_heartattack(FALSE)
	if(H.stat == CONSCIOUS)
		to_chat(H, span_notice("You feel your heart beating again!"))


code:
/obj/item/organ/cyberimp/chest/thrusters
	name = "implantable thrusters set"
	desc = "An implantable set of thruster ports. They use the gas from environment or subject's internals for propulsion in zero-gravity areas. \
	Unlike regular jetpacks, this device has no stabilization system."
	icon_state = "imp_jetpack"
	base_icon_state = "imp_jetpack"
	implant_overlay = null
	implant_color = null
	actions_types = list(/datum/action/item_action/organ_action/toggle)
	w_class = WEIGHT_CLASS_NORMAL
	var/on = FALSE
	var/datum/effect_system/trail_follow/ion/ion_trail

/obj/item/organ/cyberimp/chest/thrusters/Insert(mob/living/carbon/M, special = 0)
	. = ..()
	if(!ion_trail)
		ion_trail = new
		ion_trail.auto_process = FALSE
	ion_trail.set_up(M)

/obj/item/organ/cyberimp/chest/thrusters/Remove(mob/living/carbon/M, special = 0)
	if(on)
		toggle(silent = TRUE)
	return ..()

/obj/item/organ/cyberimp/chest/thrusters/ui_action_click()
	. = ..()
	toggle()

/obj/item/organ/cyberimp/chest/thrusters/proc/toggle(silent = FALSE)
	if(!on)
		if((organ_flags & ORGAN_FAILING))
			if(!silent)
				to_chat(owner, span_warning("Your thrusters set seems to be broken!"))
			return FALSE
		if(allow_thrust(0.01))
			on = TRUE
			ion_trail.start()
			RegisterSignal(owner, COMSIG_MOVABLE_MOVED, .proc/move_react)
			owner.add_movespeed_modifier(/datum/movespeed_modifier/jetpack/cybernetic)
			RegisterSignal(owner, COMSIG_MOVABLE_PRE_MOVE, .proc/pre_move_react)
			if(!silent)
				to_chat(owner, span_notice("You turn your thrusters set on."))
	else
		ion_trail.stop()
		UnregisterSignal(owner, COMSIG_MOVABLE_MOVED)
		owner.remove_movespeed_modifier(/datum/movespeed_modifier/jetpack/cybernetic)
		UnregisterSignal(owner, COMSIG_MOVABLE_PRE_MOVE)
		if(!silent)
			to_chat(owner, span_notice("You turn your thrusters set off."))
		on = FALSE
	update_appearance()

/obj/item/organ/cyberimp/chest/thrusters/update_icon_state()
	icon_state = "[base_icon_state][on ? "-on" : null]"
	return ..()

/obj/item/organ/cyberimp/chest/thrusters/proc/move_react()
	if(!on)//If jet dont work, it dont work
		return
	if(!owner)//Don't allow jet self using
		return
	if(!isturf(owner.loc))//You can't use jet in nowhere or in mecha/closet
		return
	if(!(owner.movement_type & FLOATING) || owner.buckled)//You don't want use jet in gravity or while buckled.
		return
	if(owner.pulledby)//You don't must use jet if someone pull you
		return
	if(owner.throwing)//You don't must use jet if you thrown
		return
	if(length(owner.client.keys_held & owner.client.movement_keys))//You use jet when press keys. yes.
		allow_thrust(0.01)

/obj/item/organ/cyberimp/chest/thrusters/proc/pre_move_react()
	ion_trail.oldposition = get_turf(owner)

/obj/item/organ/cyberimp/chest/thrusters/proc/allow_thrust(num)
	if(!owner)
		return FALSE

	var/turf/T = get_turf(owner)
	if(!T) // No more runtimes from being stuck in nullspace.
		return FALSE

	// Priority 1: use air from environment.
	var/datum/gas_mixture/environment = T.return_air()
	if(environment && environment.return_pressure() > 30)
		ion_trail.generate_effect()
		return TRUE

	// Priority 2: use plasma from internal plasma storage.
	// (just in case someone would ever use this implant system to make cyber-alien ops with jetpacks and taser arms)
	if(owner.getPlasma() >= num*100)
		owner.adjustPlasma(-num*100)
		ion_trail.generate_effect()
		return TRUE

	// Priority 3: use internals tank.
	var/obj/item/tank/I = owner.internal
	if(I && I.air_contents && I.air_contents.total_moles() > num)
		var/datum/gas_mixture/removed = I.air_contents.remove(num)
		if(removed.total_moles() > 0.005)
			T.assume_air(removed)
			ion_trail.generate_effect()
			return TRUE
		else
			T.assume_air(removed)
			ion_trail.generate_effect()

	toggle(silent = TRUE)
	return FALSE


code:
/obj/item/organ/cyberimp/eyes/hud/diagnostic
	name = "Diagnostic HUD implant"
	desc = "These cybernetic eye implants will display a diagnostic HUD over everything you see."
	HUD_type = DATA_HUD_DIAGNOSTIC_ADVANCED


code:
// HUD implants
/obj/item/organ/cyberimp/eyes/hud
	name = "HUD implant"
	desc = "These cybernetic eyes will display a HUD over everything you see. Maybe."
	organ_efficiency = list(ORGAN_SLOT_HUD = 100)
	var/HUD_type = 0
	var/HUD_trait = null

/obj/item/organ/cyberimp/eyes/hud/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = FALSE)
	. = ..()
	if(HUD_type)
		var/datum/atom_hud/H = GLOB.huds[HUD_type]
		H.add_hud_to(M)
	if(HUD_trait)
		ADD_TRAIT(M, HUD_trait, ORGAN_TRAIT)

/obj/item/organ/cyberimp/eyes/hud/Remove(mob/living/carbon/M, special = 0)
	if(HUD_type)
		var/datum/atom_hud/H = GLOB.huds[HUD_type]
		H.remove_hud_from(M)
	if(HUD_trait)
		REMOVE_TRAIT(M, HUD_trait, ORGAN_TRAIT)
	return ..()


code:
/obj/item/organ/cyberimp/eyes/hud/medical
	name = "Medical HUD implant"
	desc = "These cybernetic eye implants will display a medical HUD over everything you see."
	HUD_type = DATA_HUD_MEDICAL_ADVANCED
	HUD_trait = TRAIT_MEDICAL_HUD


code:
/obj/item/organ/cyberimp/eyes/hud/security
	name = "Security HUD implant"
	desc = "These cybernetic eye implants will display a security HUD over everything you see."
	HUD_type = DATA_HUD_SECURITY_ADVANCED
	HUD_trait = TRAIT_SECURITY_HUD


code:
/obj/item/organ/cyberimp/eyes/hud/security/syndicate
	name = "Contraband Security HUD Implant"
	desc = "A Cybersun Industries brand Security HUD Implant. These illicit cybernetic eye implants will display a security HUD over everything you see."
	scanner_hidden = TRUE


code:
/obj/item/organ/cyberimp/eyes
	name = "cybernetic eye implant"
	desc = "Implants for your eyes."
	icon_state = "eye_implant"
	implant_overlay = "eye_implant_overlay"
	organ_efficiency = list(ORGAN_SLOT_EYES = 50)
	zone = BODY_ZONE_PRECISE_R_EYE
	w_class = WEIGHT_CLASS_TINY

/obj/item/organ/cyberimp/eyes/screwdriver_act(mob/living/user, obj/item/I)
	. = ..()
	zone = (zone == BODY_ZONE_PRECISE_R_EYE ? BODY_ZONE_PRECISE_L_EYE : BODY_ZONE_PRECISE_R_EYE)
	to_chat(user, span_notice("You modify [src] to be installed on the [parse_zone(zone)]."))


code:
/obj/item/organ/cyberimp/mouth
	zone = BODY_ZONE_PRECISE_MOUTH
	organ_efficiency = list(ORGAN_SLOT_MOUTH_AUG = 100)


code:
/obj/item/organ/cyberimp/mouth/breathing_tube
	name = "breathing tube implant"
	desc = "This simple implant adds an internals connector to your back, allowing you to use internals without a mask and protecting you from being choked."
	icon_state = "implant_mask"
	organ_efficiency = list(ORGAN_SLOT_MOUTH_AUG = 100, ORGAN_SLOT_BREATHING_TUBE = 100)
	w_class = WEIGHT_CLASS_TINY
	emp_vulnerability = 60

/obj/item/organ/cyberimp/mouth/breathing_tube/emp_act(severity)
	. = ..()
	if(!owner || !CHECK_BITFIELD(organ_flags, ORGAN_SYNTHETIC) || . & EMP_PROTECT_SELF)
		return
	if(prob(emp_vulnerability/severity))
		to_chat(owner, span_warning("Your breathing tube suddenly closes!"))
		owner.losebreath += 2


code:
#define INFINITE -1

/obj/item/autosurgeon
	name = "autosurgeon"
	desc = "A device that automatically inserts an implant, skillchip or organ into the user without the hassle of extensive surgery. \
		It has a screwdriver slot for removing accidentally added items."
	icon = 'icons/obj/device.dmi'
	icon_state = "autoimplanter"
	inhand_icon_state = "nothing"
	w_class = WEIGHT_CLASS_SMALL

	var/uses = INFINITE

/obj/item/autosurgeon/attack_self_tk(mob/user)
	return //stops TK fuckery

/obj/item/autosurgeon/organ
	name = "implant autosurgeon"
	desc = "A device that automatically inserts an implant or organ into the user without the hassle of extensive surgery. \
		It has a slot to insert implants or organs and a screwdriver slot for removing accidentally added items."

	var/organ_type = /obj/item/organ
	var/starting_organ
	var/obj/item/storedorgan

/obj/item/autosurgeon/organ/syndicate
	name = "suspicious implant autosurgeon"
	icon_state = "syndicate_autoimplanter"

/obj/item/autosurgeon/organ/Initialize(mapload)
	. = ..()
	if(starting_organ)
		insert_organ(new starting_organ(src))

/obj/item/autosurgeon/organ/proc/insert_organ(obj/item/I)
	storedorgan = I
	I.forceMove(src)
	name = "[initial(name)] ([storedorgan.name])"

/obj/item/autosurgeon/organ/attack_self(mob/user)//when the object it used...
	. = ..()
	if(!iscarbon(user))
		to_chat(user, span_alert("[src] will only work on carbon-based lifeforms."))
		return
	else if(!uses)
		to_chat(user, span_alert("[src] has already been used. The tools are dull and won't reactivate."))
		return
	else if(!storedorgan)
		to_chat(user, span_alert("[src] currently has no implant stored."))
		return
	if(isorgan(storedorgan))
		var/obj/item/organ/actual_organ = storedorgan
		actual_organ.Insert(user) //insert stored organ into the user
	else if(isbodypart(storedorgan))
		var/obj/item/bodypart/actual_bodypart = storedorgan
		actual_bodypart.replace_limb(user)
	user.visible_message(span_notice("[user] presses a button on [src], and you hear a short mechanical noise."), span_notice("You feel a sharp sting as [src] plunges into your body."))
	playsound(get_turf(user), 'sound/weapons/circsawhit.ogg', 50, TRUE)
	storedorgan = null
	name = initial(name)
	if(uses != INFINITE)
		uses--
	if(!uses)
		desc = "[initial(desc)] Looks like it's been used up."

/obj/item/autosurgeon/organ/attackby(obj/item/I, mob/user, params)
	if(istype(I, organ_type))
		if(storedorgan)
			to_chat(user, span_alert("[src] already has an implant stored."))
			return
		else if(!uses)
			to_chat(user, span_alert("[src] has already been used up."))
			return
		if(!user.transferItemToLoc(I, src))
			return
		storedorgan = I
		to_chat(user, span_notice("You insert the [I] into [src]."))
	else
		return ..()

/obj/item/autosurgeon/organ/screwdriver_act(mob/living/user, obj/item/I)
	if(..())
		return TRUE
	if(!storedorgan)
		to_chat(user, span_warning("There's no implant in [src] for you to remove!"))
	else
		var/atom/drop_loc = user.drop_location()
		for(var/J in src)
			var/atom/movable/AM = J
			AM.forceMove(drop_loc)

		to_chat(user, span_notice("You remove the [storedorgan] from [src]."))
		I.play_tool_sound(src)
		storedorgan = null
		if(uses != INFINITE)
			uses--
		if(!uses)
			desc = "[initial(desc)] Looks like it's been used up."
	return TRUE

/obj/item/autosurgeon/organ/cmo
	desc = "A single use autosurgeon that contains a medical heads-up display augment. A screwdriver can be used to remove it, but implants can't be placed back in."
	uses = 1
	starting_organ = /obj/item/organ/cyberimp/eyes/hud/medical

/obj/item/autosurgeon/organ/syndicate/laser_arm
	desc = "A single use autosurgeon that contains a combat arms-up laser augment. A screwdriver can be used to remove it, but implants can't be placed back in."
	uses = 1
	starting_organ = /obj/item/organ/cyberimp/arm/gun/laser

/obj/item/autosurgeon/organ/syndicate/anti_stun
	starting_organ = /obj/item/organ/cyberimp/brain/anti_stun

/obj/item/autosurgeon/organ/syndicate/reviver
	starting_organ = /obj/item/organ/cyberimp/chest/reviver

/obj/item/autosurgeon/organ/syndicate/thermal_eyes
	starting_organ = /obj/item/organ/eyes/robotic/thermals

/obj/item/autosurgeon/organ/syndicate/xray_eyes
	starting_organ = /obj/item/organ/eyes/robotic/xray


code:
/obj/item/organ/bladder
	name = "bladder"
	icon_state = "bladder"
	desc = "Where water goes to die."
	w_class = WEIGHT_CLASS_SMALL
	zone = BODY_ZONE_PRECISE_GROIN
	organ_efficiency = list(ORGAN_SLOT_BLADDER = 100)
	attack_verb_continuous = list("gores", "urinates", "pisses", "leaks")
	attack_verb_simple = list("gore", "urinate", "piss", "leak")

	healing_factor = STANDARD_ORGAN_HEALING

	food_reagents = list(/datum/reagent/consumable/nutriment/organ_tissue = 5, \
					/datum/reagent/water = 5, \
					/datum/reagent/consumable/piss = 5)

	//This is a reagent user and needs more then the 10u from edible component
	reagent_vol = 115 //100u of piss will fill us up

	// Bladder is somewhat small
	organ_volume = 0.5
	max_blood_storage = 15
	current_blood = 15
	blood_req = 3
	oxygen_req = 4
	nutriment_req = 3
	hydration_req = 4

/obj/item/organ/bladder/Initialize()
	. = ..()
	//None edible organs do not get a reagent holder by default
	if(!reagents)
		create_reagents(reagent_vol, REAGENT_HOLDER_ALIVE)
	else
		reagents.flags |= REAGENT_HOLDER_ALIVE

/obj/item/organ/bladder/get_availability(datum/species/S)
	return !(NOBLADDER in S.species_traits)


code:
/obj/item/organ/brain
	name = "brain"
	desc = "A piece of juicy meat found in a person's head."
	icon_state = "brain"
	throw_speed = 3
	throw_range = 5
	layer = ABOVE_MOB_LAYER
	zone = BODY_ZONE_HEAD
	organ_efficiency = list(ORGAN_SLOT_BRAIN = 100)
	unique_slot = ORGAN_SLOT_BRAIN
	organ_flags = ORGAN_EDIBLE|ORGAN_VITAL|ORGAN_INDESTRUCTIBLE
	attack_verb_continuous = list("attacks", "slaps", "whacks")
	attack_verb_simple = list("attack", "slap", "whack")

	// The brain's organ variables are significantly more different than the other organs, with half the decay rate for balance reasons, and twice the maxHealth
	maxHealth = BRAIN_DAMAGE_DEATH
	healing_factor = BRAIN_DAMAGE_DEATH/200
	low_threshold = BRAIN_DAMAGE_DEATH * 0.25
	high_threshold = BRAIN_DAMAGE_DEATH * 0.75
	pain_multiplier = 0 // We don't count towards bodypart pain for balance reasons

	// head cavity volume is 6
	organ_volume = 2
	max_blood_storage = 25
	current_blood = 25
	blood_req = 5
	oxygen_req = 10
	nutriment_req = 10
	hydration_req = 10

	/// This is stuff
	var/damage_threshold_value = BRAIN_DAMAGE_DEATH/10
	/// Suicide is fucking retarded
	var/suicided = FALSE
	/// The actual mob, if for some reason the brain got lobbed off
	var/mob/living/brain/brainmob
	/// If it's a fake brain with no brainmob assigned. Feedback messages will be faked as if it does have a brainmob. See changelings & dullahans.
	var/decoy_override = FALSE
	/// Brain traumas
	var/list/datum/brain_trauma/traumas = list()
	/// List of skillchip items, their location should be this brain.
	var/list/obj/item/skillchip/skillchips
	/// Maximum skillchip complexity we can support before they stop working. Do not reference this var directly and instead call get_max_skillchip_complexity()
	var/max_skillchip_complexity = 3
	/// Maximum skillchip slots available. Do not reference this var directly and instead call get_max_skillchip_slots()
	var/max_skillchip_slots = 5

/obj/item/organ/brain/Insert(mob/living/carbon/C, special = 0,no_id_transfer = FALSE)
	. = ..()
	name = "brain"
	if(C.mind && C.mind.has_antag_datum(/datum/antagonist/changeling) && !no_id_transfer) //congrats, you're trapped in a body you don't control
		if(brainmob && !(C.stat == DEAD || (HAS_TRAIT(C, TRAIT_DEATHCOMA))))
			to_chat(brainmob, span_danger("I can't feel my body! I'm still just a brain!"))
		forceMove(C)
		return

	if(brainmob)
		if(C.key)
			C.ghostize()

		if(brainmob.mind)
			brainmob.mind.transfer_to(C)
		else
			C.key = brainmob.key

		QDEL_NULL(brainmob)

	for(var/X in traumas)
		var/datum/brain_trauma/BT = X
		BT.owner = owner
		BT.on_gain()

/obj/item/organ/brain/Remove(mob/living/carbon/C, special = 0, no_id_transfer = FALSE)
	// Delete skillchips first as parent proc sets owner to null, and skillchips need to know the brain's owner.
	if(!QDELETED(C) && length(skillchips))
		to_chat(C, span_notice("I feel my skillchips enable emergency power saving mode, deactivating as my brain leaves my body..."))
		for(var/chip in skillchips)
			var/obj/item/skillchip/skillchip = chip
			// Run the try_ proc with force = TRUE.
			skillchip.try_deactivate_skillchip(FALSE, TRUE)
	. = ..()
	for(var/X in traumas)
		var/datum/brain_trauma/BT = X
		BT.on_lose(TRUE)
		BT.owner = null

	if(!QDELETED(src) && !QDELETED(C) && !no_id_transfer)
		transfer_identity(C)

/obj/item/organ/brain/handle_blood(delta_time, times_fired)
	var/effective_blood_oxygenation = GET_EFFECTIVE_BLOOD_VOL(owner.get_blood_oxygenation(), owner.total_blood_req)
	var/arterial_efficiency = get_slot_efficiency(ORGAN_SLOT_ARTERY)
	var/in_bleedout = owner.in_bleedout()
	if(arterial_efficiency && !is_failing())
		// Arteries get an extra flat 5 blood regen
		current_blood = min(current_blood + 5 * (0.5 * delta_time) * (arterial_efficiency/ORGAN_OPTIMAL_EFFICIENCY), max_blood_storage)
		return
	if(!blood_req)
		return
	if(!in_bleedout && !(effective_blood_oxygenation < BLOOD_VOLUME_SAFE))
		current_blood = min(current_blood + (blood_req * (0.5 * delta_time)), max_blood_storage)
		return
	if(in_bleedout)
		current_blood = max(current_blood - (blood_req * (0.5 * delta_time)), 0)
	else
		current_blood = max(current_blood - (blood_req * ((BLOOD_VOLUME_NORMAL-effective_blood_oxygenation)/BLOOD_VOLUME_NORMAL) * (0.5 * delta_time)), 0)
	// When all blood is lost, take blood from blood vessels
	if(!current_blood)
		var/obj/item/organ/artery
		var/obj/item/bodypart/parent = owner.get_bodypart(current_zone)
		for(var/thing in shuffle(parent?.getorganslotlist(ORGAN_SLOT_ARTERY)))
			var/obj/item/organ/candidate = thing
			if(candidate.current_blood && (candidate.get_slot_efficiency(ORGAN_SLOT_ARTERY) >= ORGAN_FAILING_EFFICIENCY))
				artery = candidate
				break
		if(artery?.current_blood)
			var/prev_blood = artery.current_blood
			artery.current_blood = max(artery.current_blood - (blood_req * 0.5 * delta_time), 0)
			current_blood = max(prev_blood - artery.current_blood, 0)

/obj/item/organ/brain/organ_failure(delta_time)
	if(owner.stat < UNCONSCIOUS)
		owner.visible_message(span_danger("[owner] starts having a seizure!"), \
							span_userdanger("I'm having a seizure!"))
	owner.Jitter(1000)
	owner.Unconscious(4 SECONDS)

/obj/item/organ/brain/on_owner_examine(datum/source, mob/user, list/examine_list)
	if(!ishuman(owner) || !is_failing())
		return
	if(owner.jitteriness >= 300)
		examine_list += span_flashingdanger("[owner] is having a seizure!")

/obj/item/organ/brain/can_heal(delta_time, times_fired)
	. = TRUE
	if(!owner)
		return FALSE
	if(healing_factor <= 0)
		return FALSE
	if(is_dead())
		return FALSE
	if(current_blood <= 0)
		return FALSE
	if(owner.undergoing_cardiac_arrest())
		return FALSE
	var/effective_blood_oxygenation = GET_EFFECTIVE_BLOOD_VOL(owner.get_blood_oxygenation(), owner.total_blood_req)
	if(effective_blood_oxygenation < BLOOD_VOLUME_SAFE)
		return FALSE
	// if stable and not too damaged we can heal
	if(!past_damage_threshold(3) && owner.get_chem_effect(CE_STABLE))
		return TRUE
	// else, we only naturally regen to basically get rounded
	if(!(damage % damage_threshold_value) || owner.get_chem_effect(CE_BRAIN_REGEN))
		return FALSE

/obj/item/organ/brain/transfer_to_limb(obj/item/bodypart/new_limb, mob/living/carbon/human/was_owner)
	. = ..()
	new_limb.brain = src
	if(brainmob)
		new_limb.brainmob = brainmob
		brainmob = null
		new_limb.brainmob.forceMove(new_limb)
		new_limb.brainmob.set_stat(DEAD)

/obj/item/organ/brain/handle_organ_attack(obj/item/tool, mob/living/user, params)
	if(owner && DOING_INTERACTION_WITH_TARGET(user, owner))
		return TRUE
	else if(DOING_INTERACTION_WITH_TARGET(user, src))
		return TRUE
	if(owner && CHECK_BITFIELD(organ_flags, ORGAN_CUT_AWAY))
		for(var/thing in attaching_items)
			if(istype(tool, thing))
				handle_attaching_item(tool, user, params)
				return TRUE
	for(var/thing in healing_items)
		if(istype(tool, thing))
			handle_healing_item(tool, user, params)
			return TRUE
	for(var/thing in healing_tools)
		if(tool.tool_behaviour == thing)
			handle_healing_item(tool, user, params)
			return TRUE
	// LOBOTOMITE
	if(owner && (tool.tool_behaviour == TOOL_HEMOSTAT))
		handle_lobotomy(tool, user, params)
		return TRUE
	if(owner && CHECK_BITFIELD(tool.get_sharpness(), SHARP_EDGED) && !CHECK_BITFIELD(organ_flags, ORGAN_CUT_AWAY))
		handle_cutting_away(tool, user, params)
		return TRUE
	// Attempt to heal the brain
	if(is_failing() && tool.is_drainable() && tool.reagents.has_reagent(/datum/reagent/medicine/mannitol))
		if(brainmob?.health <= HEALTH_THRESHOLD_DEAD) //if the brain is fucked anyway, do nothing
			to_chat(user, span_warning("[src] is far too damaged, there's nothing else i can do for it!"))
			return TRUE
		if(!tool.reagents.has_reagent(/datum/reagent/medicine/mannitol, 10))
			to_chat(user, span_warning("There's not enough mannitol in [tool] to restore [src]!"))
			return TRUE
		user.visible_message(span_notice("[user] starts to pour the contents of [tool] onto [src]."),
						span_notice("I start to slowly pour the contents of [tool] onto [src]."))
		if(!do_after(user, 5 SECONDS, src))
			to_chat(user, span_warning("I failed to pour [tool] onto [src]!"))
			return TRUE
		user.visible_message(span_notice("[user] pours the contents of [tool] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink."), \
						span_notice("I pour the contents of [tool] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink."))
		var/healby = tool.reagents.get_reagent_amount(/datum/reagent/medicine/mannitol)
		applyOrganDamage(-healby*2) //heals 2 damage per unit of mannitol
		tool.reagents.clear_reagents()
		return TRUE
	// Cutting out skill chips.
	if(length(skillchips) && (tool.get_sharpness() & SHARP_EDGED))
		to_chat(user,span_notice("I begin to excise skillchips from [src]."))
		if(do_after(user, 10 SECONDS, target = src))
			for(var/chip in skillchips)
				var/obj/item/skillchip/skillchip = chip
				if(!istype(skillchip))
					stack_trace("Item of type [skillchip.type] qdel'd from [src] skillchip list.")
					qdel(skillchip)
					continue
				remove_skillchip(skillchip)
				if(skillchip.removable)
					skillchip.forceMove(drop_location())
					continue
				qdel(skillchip)
			skillchips = null
		return TRUE

/obj/item/organ/brain/handle_healing_item(obj/item/tool, mob/living/user, params)
	var/obj/item/stack/stack = tool
	if(organ_flags & (ORGAN_DESTROYED|ORGAN_DEAD))
		to_chat(user, span_warning("\The [src] is damaged beyond the point of no return."))
		return
	if(!damage && !length(traumas))
		to_chat(user, span_notice("\The [src] is in pristine quality already."))
		return
	user.visible_message(span_notice("[user] starts healing \the [src]..."), \
					span_notice("I start healing \the [src]..."), \
					vision_distance = COMBAT_MESSAGE_RANGE)
	if(owner)
		owner.custom_pain("OH GOD! There are needles inside my [src]!", 30, FALSE, owner.get_bodypart(current_zone))
		if(!do_mob(user, owner, 5 SECONDS))
			to_chat(user, span_warning("I must stand still!"))
			return
	else
		if(!do_after(user, 5 SECONDS, src))
			to_chat(user, span_warning("I must stand still!"))
			return
	if(istype(stack))
		if(!stack.use(2))
			to_chat(user, span_warning("I don't have enough to heal \the [src]!"))
			return
	user.visible_message(span_notice("[user] healing \the [src]."), \
						span_notice("I heal \the [src]."))
	applyOrganDamage(-min(maxHealth/2, 50))
	cure_all_traumas(TRAUMA_RESILIENCE_SURGERY)

/obj/item/organ/brain/surgical_examine(mob/user)
	. = ..()
	if(length(skillchips) >= 2)
		. += span_info("It has some skillchips embedded in it.")
	else if(length(skillchips))
		. += span_info("It has a skillchip embedded in it.")
	if((brainmob && (brainmob.client || brainmob.get_ghost())) || decoy_override)
		if(is_failing())
			. += span_info("It seems to still have a bit of energy within it, but it's rather damaged...")
		else if(damage >= BRAIN_DAMAGE_DEATH*0.5)
			. += span_info("I can feel the small spark of life still left in this one, but it's got some bruises.")
		else
			. += span_info("I can feel the small spark of life still left in this one.")
	else
		. += span_info("This one is completely devoid of life.")

/obj/item/organ/brain/Destroy() //copypasted from MMIs.
	if(brainmob)
		QDEL_NULL(brainmob)
	QDEL_LIST(traumas)
	destroy_all_skillchips()
	if(owner?.mind) //You aren't allowed to return to brains that don't exist
		owner.mind.current = null
	return ..()

/obj/item/organ/brain/applyOrganDamage(amount, maximum, silent)
	. = ..()
	if(owner && (amount >= 10))
		var/damage_side_effect = CEILING(amount/2, 1)
		if(damage_side_effect >= 1)
			owner.flash_pain(damage_side_effect*4)
			owner.blur_eyes(damage_side_effect)
			owner.add_confusion(damage_side_effect)
			switch(rand(0,3))
				if(1)
					owner.stuttering += damage_side_effect
				if(2)
					owner.slurring += damage_side_effect
				if(3)
					owner.cultslurring += damage_side_effect
			if(damage_side_effect >= 5)
				if(prob(50))
					owner.shit(FALSE)
				else
					owner.piss(FALSE)
			owner.CombatKnockdown(damage_side_effect*2, damage_side_effect, (damage_side_effect >= 5 ? damage_side_effect : null), damage_side_effect >= 5)

/obj/item/organ/brain/check_damage_thresholds(mob/M)
	. = ..()
	// if we're not more injured than before, return without gambling for a trauma
	if(damage <= prev_damage)
		return
	var/damage_delta = damage - prev_damage
	// Safeguard to prevent traumas from low damage
	if((damage_delta >= TRAUMA_ROLL_THRESHOLD) && (damage >= BRAIN_DAMAGE_MILD))
		var/is_boosted = (owner && HAS_TRAIT(owner, TRAIT_SPECIAL_TRAUMA_BOOST))
		var/intelligence_modifier = (owner ? -(GET_MOB_ATTRIBUTE_VALUE(owner, STAT_INTELLIGENCE)-ATTRIBUTE_MIDDLING) : 0)
		if(damage >= BRAIN_DAMAGE_SEVERE)
			// Base chance is the hit damage, plus intelligence mod; for every point of damage past the threshold the chance is increased by 1%
			if(prob((damage_delta+intelligence_modifier) * (1 + max(0, (damage - BRAIN_DAMAGE_SEVERE)/100))))
				if(prob(20 + (is_boosted * 30) - (intelligence_modifier * 2)))
					gain_trauma_type(BRAIN_TRAUMA_SPECIAL, is_boosted ? TRAUMA_RESILIENCE_SURGERY : null, natural_gain = TRUE)
				else
					gain_trauma_type(BRAIN_TRAUMA_SEVERE, natural_gain = TRUE)
		else
			// Base chance is the hit damage, plus intelligence mod; for every point of damage past the threshold the chance is increased by 1%
			if(prob((damage_delta+intelligence_modifier) * (1 + max(0, (damage - BRAIN_DAMAGE_MILD)/100))))
				gain_trauma_type(BRAIN_TRAUMA_MILD, natural_gain = TRUE)
	if(owner)
		if(damage >= BRAIN_DAMAGE_DEATH && prev_damage < BRAIN_DAMAGE_DEATH && (organ_flags & ORGAN_VITAL))
			owner.death()
			return
		var/brain_message
		if(prev_damage < BRAIN_DAMAGE_MILD && damage >= BRAIN_DAMAGE_MILD)
			brain_message = span_warning("I feel lightheaded.")
		else if(prev_damage < BRAIN_DAMAGE_SEVERE && damage >= BRAIN_DAMAGE_SEVERE)
			brain_message = span_warning("I feel less in control of my thoughts.")
		else if(prev_damage < (BRAIN_DAMAGE_DEATH - 20) && damage >= (BRAIN_DAMAGE_DEATH - 20) && damage < BRAIN_DAMAGE_DEATH)
			brain_message = span_warning("I can feel my mind flickering on and off...")
		if(.)
			. += "\n[brain_message]"
		else
			return brain_message

/obj/item/organ/brain/before_organ_replacement(obj/item/organ/replacement)
	. = ..()
	var/obj/item/organ/brain/replacement_brain = replacement
	if(!istype(replacement_brain))
		return

	// If we have some sort of brain type or subtype change and have skillchips, engage the failsafe procedure!
	if(owner && length(skillchips) && (replacement_brain.type != type))
		activate_skillchip_failsafe(FALSE)

	// Check through all our skillchips, remove them from this brain, add them to the replacement brain.
	for(var/chip in skillchips)
		var/obj/item/skillchip/skillchip = chip

		// We're technically doing a little hackery here by bypassing the procs, but I'm the one who wrote them
		// and when you know the rules, you can break the rules.

		// Technically the owning mob is the same. We don't need to activate or deactivate the skillchips.
		// All the skillchips themselves care about is what brain they're in.
		// Because the new brain will ultimately be owned by the same body, we can safely leave skillchip logic alone.

		// Directly change the new holding_brain.
		skillchip.holding_brain = replacement_brain
		//And move the actual obj into the new brain (contents)
		skillchip.forceMove(replacement_brain)

		// Directly add them to the skillchip list in the new brain.
		LAZYADD(replacement_brain.skillchips, skillchip)

	// Any skillchips has been transferred over, time to empty the list.
	LAZYCLEARLIST(skillchips)

/obj/item/organ/brain/proc/handle_lobotomy(obj/item/tool, mob/living/user, params)
	user.visible_message(span_notice("[user] starts lobotomizing \the [src]..."), \
					span_notice("I start lobotomizing \the [src]..."), \
					vision_distance = COMBAT_MESSAGE_RANGE)
	owner.custom_pain("OH GOD! My [src] is being SLASHED IN TWAIN!", 30, FALSE, owner.get_bodypart(current_zone))
	if(!do_mob(user, owner, 10 SECONDS))
		to_chat(user, span_warning("I must stand still!"))
		return TRUE
	user.visible_message(span_notice("[user] lobotomizes \the [src]."), \
					span_notice("I lobotomize \the [src]."), \
					vision_distance = COMBAT_MESSAGE_RANGE)
	switch(owner.diceroll(GET_MOB_ATTRIBUTE_VALUE(owner, STAT_ENDURANCE)))
		// Cure all traumas, no penalties
		if(DICE_CRIT_SUCCESS)
			cure_all_traumas(TRAUMA_RESILIENCE_LOBOTOMY)
		// Cure all traumas, but gain a mild one
		if(DICE_SUCCESS)
			cure_all_traumas(TRAUMA_RESILIENCE_LOBOTOMY)
			gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_SURGERY)
		// Cure nothing, lose intelligence, go fuck yourself
		if(DICE_FAILURE)
			owner.attributes.add_attribute_modifier(/datum/attribute_modifier/lobotomy, TRUE)
		// Cure nothing, lose intelligence, gain another brain trauma, go fuck yourself
		if(DICE_CRIT_FAILURE)
			owner.attributes.add_attribute_modifier(/datum/attribute_modifier/lobotomite, TRUE)
			gain_trauma_type(BRAIN_TRAUMA_SEVERE, TRAUMA_RESILIENCE_LOBOTOMY)
	//no matter how shitty the lobotomy, always cure brainwashing
	if(owner.mind?.has_antag_datum(/datum/antagonist/brainwashed))
		owner.mind.remove_antag_datum(/datum/antagonist/brainwashed)
	return TRUE

/obj/item/organ/brain/proc/get_current_damage_threshold()
	return FLOOR(damage / damage_threshold_value, 1)

/obj/item/organ/brain/proc/past_damage_threshold(threshold)
	return (get_current_damage_threshold() > threshold)

/obj/item/organ/brain/proc/transfer_identity(mob/living/transferer)
	if(brainmob || decoy_override)
		return
	if(!transferer.mind)
		return
	brainmob = new(src)
	brainmob.name = transferer.real_name
	brainmob.real_name = transferer.real_name
	brainmob.timeofhostdeath = transferer.timeofdeath
	brainmob.suiciding = suicided
	if(transferer.has_dna())
		var/mob/living/carbon/carbon_transferer = transferer
		if(!brainmob.stored_dna)
			brainmob.stored_dna = new /datum/dna/stored(brainmob)
		carbon_transferer.dna.copy_dna(brainmob.stored_dna)
		if(HAS_TRAIT(carbon_transferer, TRAIT_BADDNA))
			LAZYSET(brainmob.status_traits, TRAIT_BADDNA, carbon_transferer.status_traits[TRAIT_BADDNA])
	if(transferer.mind && transferer.mind.current)
		transferer.mind.transfer_to(brainmob)
	to_chat(brainmob, span_notice("I feel slightly disoriented. That's normal since i'm just a brain."))

////////////////////////////////////TRAUMAS////////////////////////////////////////
/obj/item/organ/brain/proc/has_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience = TRAUMA_RESILIENCE_ABSOLUTE)
	for(var/X in traumas)
		var/datum/brain_trauma/BT = X
		if(istype(BT, brain_trauma_type) && (BT.resilience <= resilience))
			return BT

/obj/item/organ/brain/proc/get_traumas_type(brain_trauma_type = /datum/brain_trauma, resilience = TRAUMA_RESILIENCE_ABSOLUTE)
	. = list()
	for(var/trauma_type in traumas)
		var/datum/brain_trauma/brain_trauma = trauma_type
		if(istype(brain_trauma, brain_trauma_type) && (brain_trauma.resilience <= resilience))
			. += brain_trauma

/obj/item/organ/brain/proc/can_gain_trauma(datum/brain_trauma/trauma, resilience, natural_gain = FALSE)
	if(!ispath(trauma))
		trauma = trauma.type
	if(!initial(trauma.can_gain))
		return FALSE
	if(!resilience)
		resilience = initial(trauma.resilience)

	var/resilience_tier_count = 0
	for(var/X in traumas)
		if(istype(X, trauma))
			return FALSE
		var/datum/brain_trauma/existing_trauma = X
		if(resilience == existing_trauma.resilience)
			resilience_tier_count++

	var/max_traumas
	switch(resilience)
		if(TRAUMA_RESILIENCE_BASIC)
			max_traumas = TRAUMA_LIMIT_BASIC
		if(TRAUMA_RESILIENCE_SURGERY)
			max_traumas = TRAUMA_LIMIT_SURGERY
		if(TRAUMA_RESILIENCE_WOUND)
			max_traumas = TRAUMA_LIMIT_WOUND
		if(TRAUMA_RESILIENCE_LOBOTOMY)
			max_traumas = TRAUMA_LIMIT_LOBOTOMY
		if(TRAUMA_RESILIENCE_MAGIC)
			max_traumas = TRAUMA_LIMIT_MAGIC
		if(TRAUMA_RESILIENCE_ABSOLUTE)
			max_traumas = TRAUMA_LIMIT_ABSOLUTE

	if(natural_gain && resilience_tier_count >= max_traumas)
		return FALSE
	return TRUE

//Proc to use when directly adding a trauma to the brain, so extra args can be given
/obj/item/organ/brain/proc/gain_trauma(datum/brain_trauma/trauma, resilience, ...)
	var/list/arguments = list()
	if(args.len > 2)
		arguments = args.Copy(3)
	. = brain_gain_trauma(trauma, resilience, arguments)

//Direct trauma gaining proc. Necessary to assign a trauma to its brain. Avoid using directly.
/obj/item/organ/brain/proc/brain_gain_trauma(datum/brain_trauma/trauma, resilience, list/arguments)
	if(!can_gain_trauma(trauma, resilience))
		return FALSE

	var/datum/brain_trauma/actual_trauma
	if(ispath(trauma))
		if(!LAZYLEN(arguments))
			actual_trauma = new trauma() //arglist with an empty list runtimes for some reason
		else
			actual_trauma = new trauma(arglist(arguments))
	else
		actual_trauma = trauma

	if(actual_trauma.brain) //we don't accept used traumas here
		WARNING("gain_trauma was given an already active trauma.")
		return FALSE

	traumas += actual_trauma
	actual_trauma.brain = src
	if(owner)
		actual_trauma.owner = owner
		SEND_SIGNAL(owner, COMSIG_CARBON_GAIN_TRAUMA, trauma)
		actual_trauma.on_gain()
	if(resilience)
		actual_trauma.resilience = resilience
	SSblackbox.record_feedback("tally", "traumas", 1, actual_trauma.type)
	return actual_trauma

/// Add a random trauma of a certain subtype
/obj/item/organ/brain/proc/gain_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience, natural_gain = FALSE)
	var/list/datum/brain_trauma/possible_traumas = list()
	for(var/trauma_type in subtypesof(brain_trauma_type))
		var/datum/brain_trauma/brain_trauma = trauma_type
		if(can_gain_trauma(brain_trauma, resilience, natural_gain) && initial(brain_trauma.random_gain))
			possible_traumas += brain_trauma

	if(!LAZYLEN(possible_traumas))
		return

	var/trauma_type = pick(possible_traumas)
	return gain_trauma(trauma_type, resilience)

/// Cure a random trauma of a certain resilience level
/obj/item/organ/brain/proc/cure_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience = TRAUMA_RESILIENCE_BASIC)
	var/list/traumas = get_traumas_type(brain_trauma_type, resilience)
	if(LAZYLEN(traumas))
		qdel(pick(traumas))

/obj/item/organ/brain/proc/cure_all_traumas(resilience = TRAUMA_RESILIENCE_BASIC)
	var/amount_cured = 0
	var/list/traumas = get_traumas_type(resilience = resilience)
	for(var/X in traumas)
		qdel(X)
		amount_cured++
	return amount_cured


code:
/obj/item/organ/brain/alien
	name = "alien brain"
	desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?"
	icon_state = "brain-x"


code:
/obj/item/organ/ears
	name = "ear"
	icon_state = "ears"
	desc = "There are three parts to the ear. Inner, middle and outer. Only one of these parts should be normally visible."

	dna_block = DNA_EARS_BLOCK
	mutantpart_key = "ears"
	mutantpart_info = list(MUTANT_INDEX_NAME = "None", MUTANT_INDEX_COLOR = list("FFFFFF"))

	zone = BODY_ZONE_HEAD
	side = RIGHT_SIDE
	organ_efficiency = list(ORGAN_SLOT_EARS = 50) // normal people have two ears you dolt

	maxHealth = STANDARD_ORGAN_THRESHOLD * 0.5 // weaker because we have 2
	high_threshold = STANDARD_ORGAN_THRESHOLD * 0.4
	low_threshold = STANDARD_ORGAN_THRESHOLD * 0.1

	low_threshold_passed = span_info("Your ear begin to resonate with an internal ring sometimes.")
	low_threshold_cleared = span_info("The ringing in your ear has died down.")
	now_failing = span_warning("You are unable to hear at all!")
	now_fixed = span_info("Noise slowly begins filling your ear once more.")

	// remember that this is normally DOUBLED (2 ears)
	organ_volume = 0.5
	max_blood_storage = 2.5
	current_blood = 2.5
	blood_req = 0.5
	oxygen_req = 0.5
	nutriment_req = 0.25
	hydration_req = 0.25

	// `deaf` measures "ticks" of deafness. While > 0, the person is unable
	// to hear anything.
	var/deaf = 0

	// `damage` in this case measures long term damage to the ears, if too high,
	// the person will not have either `deaf` or `ear_damage` decrease
	// without external aid (earmuffs, drugs)

	// Resistance against loud noises
	var/bang_protect = 0
	// Multiplier for both long term and short term ear damage
	var/ear_damage_multiplier = 1

/obj/item/organ/ears/on_life(delta_time, times_fired)
	. = ..()
	// if we have non-damage related deafness like mutations, quirks or clothing (earmuffs), don't bother processing here - Ear healing from earmuffs or chems happen elsewhere
	if(HAS_TRAIT_NOT_FROM(owner, TRAIT_DEAF, EAR_DAMAGE))
		return

	if(is_failing())
		deaf = max(deaf, 1) // if we're failing we always have at least 1 deaf stack (and thus deafness)
	else // only clear deaf stacks if we're not failing
		applyDeaf(-(0.5 * delta_time))

/obj/item/organ/ears/get_slot_efficiency(slot)
	if((slot == ORGAN_SLOT_EARS) && deaf)
		return 0
	return ..()

/obj/item/organ/ears/proc/adjustEarDamage(ddmg, ddeaf)
	applyOrganDamage(ddmg * ear_damage_multiplier, silent = TRUE)
	applyDeaf(ddeaf * ear_damage_multiplier)

/obj/item/organ/ears/proc/applyDeaf(d, maximum = maxHealth)
	if(!d) //Micro-optimization.
		return
	deaf = clamp(deaf + d, 0, maximum)


code:
/obj/item/organ/ears/bronze
	name = "tin ears"
	desc = "The robust ears of a bronze golem."
	icon_state = "ears-c"
	color = COLOR_BROWN
	ear_damage_multiplier = 0.1 //STRONK
	bang_protect = 1 //Fear me weaklings.


code:
/obj/item/organ/ears/cat
	name = "cat ears"
	icon_state = "ears-fluffy"
	ear_damage_multiplier = 2
	dna_block = DNA_EARS_BLOCK
	mutantpart_key = "ears"
	mutantpart_info = list(MUTANT_INDEX_NAME = "Cat", MUTANT_INDEX_COLOR = list("FFAA00"))


code:
/obj/item/organ/ears/cybernetic
	name = "cybernetic ears"
	icon_state = "ears-c"
	desc = "A basic cybernetic organ designed to mimic the operation of ears."
	ear_damage_multiplier = 0.9
	emp_vulnerability = 80
	status = ORGAN_ROBOTIC
	organ_flags = ORGAN_SYNTHETIC

/obj/item/organ/ears/cybernetic/upgraded
	name = "upgraded cybernetic ears"
	icon_state = "ear-c-u"
	base_icon_state = "ears-c-u"
	desc = "An advanced cybernetic ear, surpassing the performance of organic ears."
	ear_damage_multiplier = 0.5

/obj/item/organ/ears/emp_act(severity)
	. = ..()
	if(!owner || !CHECK_BITFIELD(organ_flags, ORGAN_SYNTHETIC) || . & EMP_PROTECT_SELF)
		return
	adjustEarDamage(2*(emp_vulnerability/(100/severity)), (emp_vulnerability/(100/severity)))


code:
/obj/item/organ/ears/fluffy
	name = "fluffy ears"
	icon_state = "ears-fluffy"
	dna_block = DNA_EARS_BLOCK
	mutantpart_key = "ears"
	mutantpart_info = list(MUTANT_INDEX_NAME = "Cat", MUTANT_INDEX_COLOR = list("FFAA00"))

/obj/item/organ/ears/fluffy/update_overlays()
	. = ..()
	var/image/overlay = image(icon, src, "ears-fluffy-detail")
	if(length(mutantpart_info))
		overlay.color = mutantpart_info[MUTANT_INDEX_COLOR]
	. += overlay


code:
/obj/item/organ/ears/invincible
	ear_damage_multiplier = 0


code:
/obj/item/organ/ears/penguin
	name = "penguin ears"
	desc = "The source of a penguin's happy feet."

/obj/item/organ/ears/penguin/Insert(mob/living/carbon/human/H, special = 0, drop_if_replaced = TRUE)
	. = ..()
	if(istype(H))
		to_chat(H, span_notice("I suddenly feel like i've lost my balance."))
		H.AddElement(/datum/element/waddling)

/obj/item/organ/ears/penguin/Remove(mob/living/carbon/human/H,  special = 0)
	. = ..()
	if(istype(H))
		to_chat(H, span_notice("My sense of balance comes back to me."))
		H.RemoveElement(/datum/element/waddling)


code:
//tg compatibility use only
/obj/item/organ/external
	name = "external organ"
	desc = "An external organ that is too external."


code:
/obj/item/organ/external/antennae
	name = "antennae"
	desc = "Severed antennae. Too large to have come from an average insect..."
	icon_state = "antennae"
	zone = BODY_ZONE_HEAD
	organ_efficiency = list(ORGAN_SLOT_EXTERNAL_ANTENNAE = 100)
	dna_block = DNA_MOTH_ANTENNAE_BLOCK
	mutantpart_key = "moth_antennae"
	mutantpart_colored = TRUE
	mutantpart_info = list(MUTANT_INDEX_NAME = "Plain", MUTANT_INDEX_COLOR = list("FFFFFF"))


code:
/obj/item/organ/external/frills
	name = "frills"
	desc = "Severed frills. These probably didn't come from a fish."
	icon_state = "frills"
	zone = BODY_ZONE_HEAD
	organ_efficiency = list(ORGAN_SLOT_EXTERNAL_FRILLS = 100)
	dna_block = DNA_FRILLS_BLOCK
	mutantpart_key = "frills"
	mutantpart_colored = TRUE
	mutantpart_info = list(MUTANT_INDEX_NAME = "Divinity", MUTANT_INDEX_COLOR = list("FFFFFF"))


code:
/obj/item/organ/external/horns
	name = "horns"
	desc = "Whoever had this was certainly very horny."
	icon_state = "horns"
	zone = BODY_ZONE_HEAD
	organ_efficiency = list(ORGAN_SLOT_EXTERNAL_HORNS = 100)
	dna_block = DNA_FRILLS_BLOCK
	mutantpart_key = "horns"
	mutantpart_colored = FALSE
	mutantpart_info = list(MUTANT_INDEX_NAME = "Simple", MUTANT_INDEX_COLOR = list("FFFFFF"))


code:
/obj/item/organ/external/snout
	name = "snout"
	desc = "A severed snout. This probably didn't come from a normal dog."
	icon_state = "snout"
	zone = BODY_ZONE_PRECISE_MOUTH
	organ_efficiency = list(ORGAN_SLOT_EXTERNAL_SNOUT = 100)
	dna_block = DNA_SNOUT_BLOCK
	mutantpart_key = "snout"
	mutantpart_colored = FALSE
	mutantpart_info = list(MUTANT_INDEX_NAME = "Mammal, Short", MUTANT_INDEX_COLOR = list("FFFFFF"))


code:
// Note: tails only work in humans. They use human-specific parameters and rely on human code for displaying.
/obj/item/organ/tail
	name = "tail"
	desc = "A severed tail. What did you cut this off of?"
	icon_state = "tail"
	zone = BODY_ZONE_PRECISE_GROIN
	organ_efficiency = list(ORGAN_SLOT_TAIL = 100)
	dna_block = DNA_HUMAN_TAIL_BLOCK
	mutantpart_key = "tail"
	mutantpart_colored = TRUE
	mutantpart_info = list(MUTANT_INDEX_NAME = "Smooth", MUTANT_INDEX_COLOR = list("FFFFFF"))
	/// The sprite accessory this tail gives to the human it's attached to. If null, it will inherit its value from the human's DNA once attached.
	var/tail_type = "None"
	var/can_wag = TRUE
	var/wagging = FALSE

/obj/item/organ/tail/Insert(mob/living/carbon/human/tail_owner, special = FALSE, drop_if_replaced = TRUE)
	. = ..()
	tail_owner?.dna?.species?.on_tail_regain(tail_owner, src, special)

/obj/item/organ/tail/Remove(mob/living/carbon/human/tail_owner, special = FALSE)
	. = ..()
	tail_owner?.dna?.species?.on_tail_lost(tail_owner, src, special)