code:
/mob/living/carbon/human/regenerate_icons()
	//invalidate mutant bodypart cache
	mutant_renderkey = null
	return ..()

//used when putting/removing clothes that hide certain mutant body parts to just update those and not update the whole body.
/mob/living/carbon/human/update_mutant_bodyparts(force_update = FALSE)
	dna.species.handle_mutant_bodyparts(src, null, force_update)

/mob/living/carbon/human/update_body_parts()
	//CHECK FOR UPDATE
	for(var/X in bodyparts)
		var/obj/item/bodypart/BP = X
		BP.update_limb()
	var/oldkey = icon_render_key
	icon_render_key = generate_icon_render_key()
	if(oldkey == icon_render_key)
		return

	remove_overlay(BODYPARTS_LAYER)

	//LOAD ICONS
	if(limb_icon_cache[icon_render_key])
		load_limb_from_cache()
		return

	var/is_taur = FALSE
	if(dna?.species.mutant_bodyparts["taur"])
		var/datum/sprite_accessory/taur/S = GLOB.sprite_accessories["taur"][dna.species.mutant_bodyparts["taur"][MUTANT_INDEX_NAME]]
		if(S.hide_legs)
			is_taur = TRUE

	//GENERATE NEW LIMBS
	var/list/new_limbs = list()
	for(var/X in bodyparts)
		var/obj/item/bodypart/BP = X
		if(is_taur && (BP.body_part & LEGS|FEET))
			continue
		var/bp_icon = BP.get_limb_icon()
		if(islist(bp_icon) && length(bp_icon))
			new_limbs |= bp_icon
	if(length(new_limbs))
		overlays_standing[BODYPARTS_LAYER] = new_limbs
		limb_icon_cache[icon_render_key] = new_limbs

	apply_overlay(BODYPARTS_LAYER)

	update_damage_overlays()
	update_medicine_overlays()

//produces a key based on the human's limbs
/mob/living/carbon/human/generate_icon_render_key()
	. = ""
	var/husked = FALSE
	if(dna?.species)
		. += "-markingalpha[dna.species.markings_alpha]"
	if(dna?.species?.mutant_bodyparts["taur"])
		. += "-taur[dna.species.mutant_bodyparts["taur"][MUTANT_INDEX_NAME]]"
	if(HAS_TRAIT(src, TRAIT_HUSK))
		husked = TRUE
		. += "-husk"
	if(dna.check_mutation(HULK))
		. += "-coloured-hulk"
	for(var/X in bodyparts)
		var/obj/item/bodypart/BP = X
		. += "-[BP.body_zone]"
		if(BP.is_stump())
			. += "-stump"
		if(BP.animal_origin)
			. += "-[BP.animal_origin]"
		if(BP.status == BODYPART_ORGANIC)
			. += "-organic"
		else if(BP.status == BODYPART_ROBOTIC)
			. += "-robotic"
		if(BP.body_gender && BP.gender_rendering)
			. += "-gender[BP.body_gender]"
		if(BP.species_id)
			. += "-[BP.species_id]"
		if(BP.skin_tone)
			. += "-skintone[BP.skin_tone]"
		if(BP.species_color)
			. += "-speciescolor[BP.species_color]"
		if(BP.mutation_color)
			. += "-mutationcolor[BP.mutation_color]"
		if(BP.use_digitigrade)
			. += "-digitigrade[BP.use_digitigrade]"
		if(BP.dmg_overlay_type)
			. += "-[BP.dmg_overlay_type]"
		if(HAS_TRAIT(BP, TRAIT_ROTTEN))
			. += "-rotten"
		else if(HAS_TRAIT(BP, TRAIT_PLASMABURNT))
			. += "-plasmaburnt"
		else if(HAS_TRAIT(BP, TRAIT_HUSK))
			. += "-husk"
		if(BP.advanced_rendering)
			. += "-advanced_render"
		for(var/zone in BP.body_markings)
			for(var/key in BP.body_markings[zone])
				var/datum/body_marking/marking = GLOB.body_markings[key]
				var/marking_string = "-marking-[marking.icon_state]"
				if(husked || HAS_TRAIT(BP, TRAIT_HUSK))
					marking_string += "-color888888"
				else
					marking_string += "-color[BP.body_markings[zone][key]]"
				. += marking_string
		if(BP.is_stump())
			. += "-stump"

/mob/living/carbon/human/update_fire(fire_icon = "generic_mob_burning")
	remove_overlay(FIRE_LAYER)

	if(fire_stacks > (HUMAN_FIRE_STACK_ICON_NUM*2))
		fire_icon = "standing_bad"
	else if(fire_stacks > HUMAN_FIRE_STACK_ICON_NUM)
		fire_icon = "standing"
	if(ismonkey(src))
		fire_icon = "standing_monkey"
	if(on_fire || HAS_TRAIT(src, TRAIT_PERMANENTLY_ONFIRE))
		var/mutable_appearance/new_fire_overlay = mutable_appearance('modular_septic/icons/mob/human/overlays/onfire.dmi', fire_icon, -FIRE_LAYER)
		new_fire_overlay.appearance_flags = RESET_COLOR
		overlays_standing[FIRE_LAYER] = new_fire_overlay

	apply_overlay(FIRE_LAYER)

/mob/living/carbon/human/update_inv_ears()
	remove_overlay(EARS_LAYER)

	if(!get_bodypart_nostump(BODY_ZONE_HEAD)) //decapitated
		return

	if(client && hud_used)
		var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_LEAR) + 1]
		inv.update_appearance()
		inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_REAR) + 1]
		inv.update_appearance()

	if(ears_extra)
		ears_extra.screen_loc = ui_ears_extra //move the item to the appropriate screen loc
		if(client && hud_used?.hud_shown)
			if(hud_used.upper_inventory_shown) //if the inventory is open
				client.screen += ears_extra //add it to the client's screen
		update_observer_view(ears_extra,1)
		overlays_standing[EARS_LAYER] = ears_extra.build_worn_icon(default_layer = EARS_LAYER, default_icon_file = 'icons/mob/clothing/ears.dmi')
		var/mutable_appearance/ears_overlay = overlays_standing[EARS_LAYER]
		if(OFFSET_EARS in dna.species.offset_features)
			ears_overlay.pixel_x += dna.species.offset_features[OFFSET_EARS][1]
			ears_overlay.pixel_y += dna.species.offset_features[OFFSET_EARS][2]
		overlays_standing[EARS_LAYER] = ears_overlay
	if(ears)
		ears.screen_loc = ui_ears //move the item to the appropriate screen loc
		if(client && hud_used?.hud_shown)
			if(hud_used.upper_inventory_shown) //if the inventory is open
				client.screen += ears //add it to the client's screen
		update_observer_view(ears,1)
		overlays_standing[EARS_LAYER] = ears.build_worn_icon(default_layer = EARS_LAYER, default_icon_file = 'icons/mob/clothing/ears.dmi')
		var/mutable_appearance/ears_overlay = overlays_standing[EARS_LAYER]
		if(OFFSET_EARS in dna.species.offset_features)
			ears_overlay.pixel_x += dna.species.offset_features[OFFSET_EARS][1]
			ears_overlay.pixel_y += dna.species.offset_features[OFFSET_EARS][2]
		overlays_standing[EARS_LAYER] = ears_overlay
	apply_overlay(EARS_LAYER)

/mob/living/carbon/human/update_inv_wear_suit()
	remove_overlay(SUIT_LAYER)

	if(client && hud_used)
		var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_OCLOTHING) + 1]
		inv.update_icon()

	if(wear_suit)
		wear_suit.screen_loc = ui_oclothing
		if(client && hud_used?.hud_shown)
			if(hud_used.inventory_shown)
				client.screen += wear_suit
		update_observer_view(wear_suit, TRUE)
		var/icon_file = wear_suit.worn_icon
		var/applied_style = NONE
		if(dna.species.mutant_bodyparts["taur"])
			var/datum/sprite_accessory/taur/S = GLOB.sprite_accessories["taur"][dna.species.mutant_bodyparts["taur"][MUTANT_INDEX_NAME]]
			if(wear_suit.mutant_variants & S.taur_mode)
				applied_style = S.taur_mode
			else if(wear_suit.mutant_variants & S.alt_taur_mode)
				applied_style = S.alt_taur_mode
		if(!applied_style)
			if((DIGITIGRADE in dna.species.species_traits) && (wear_suit.mutant_variants & STYLE_DIGITIGRADE))
				applied_style = STYLE_DIGITIGRADE

		var/x_override
		switch(applied_style)
			if(STYLE_DIGITIGRADE)
				icon_file = wear_suit.worn_icon_digi || 'modular_septic/icons/mob/clothing/suit_digi.dmi'
			if(STYLE_TAUR_SNAKE)
				icon_file = wear_suit.worn_icon_taur_snake || 'modular_septic/icons/mob/clothing/suit_taur_snake.dmi'
			if(STYLE_TAUR_HOOF)
				icon_file = wear_suit.worn_icon_taur_hoof || 'modular_septic/icons/mob/clothing/suit_taur_hoof.dmi'
			if(STYLE_TAUR_PAW)
				icon_file = wear_suit.worn_icon_taur_paw || 'modular_septic/icons/mob/clothing/suit_taur_paw.dmi'

		if(applied_style & STYLE_TAUR_ALL)
			x_override = 64

		overlays_standing[SUIT_LAYER] = wear_suit.build_worn_icon(default_layer = SUIT_LAYER, default_icon_file = 'icons/mob/clothing/suit.dmi', override_icon = icon_file, override_x_center = x_override, mutant_styles = applied_style)
		var/mutable_appearance/suit_overlay = overlays_standing[SUIT_LAYER]
		if(OFFSET_SUIT in dna.species.offset_features)
			suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1]
			suit_overlay.pixel_y += dna.species.offset_features[OFFSET_SUIT][2]
		overlays_standing[SUIT_LAYER] = suit_overlay
	update_hair()
	update_mutant_bodyparts()

	apply_overlay(SUIT_LAYER)

/mob/living/carbon/human/update_inv_w_uniform()
	remove_overlay(UNIFORM_LAYER)

	if(client && hud_used)
		var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_ICLOTHING) + 1]
		inv.update_icon()

	if(istype(w_uniform, /obj/item/clothing))
		var/obj/item/clothing/under/U = w_uniform
		U.screen_loc = ui_iclothing
		if(client && hud_used?.hud_shown)
			if(hud_used.inventory_shown)
				client.screen += w_uniform
		update_observer_view(w_uniform,1)

		if(wear_suit && (wear_suit.flags_inv & HIDEJUMPSUIT))
			return

		var/applied_style = NONE
		var/icon_file = w_uniform.worn_icon
		if(dna.species.mutant_bodyparts["taur"])
			var/datum/sprite_accessory/taur/S = GLOB.sprite_accessories["taur"][dna.species.mutant_bodyparts["taur"][MUTANT_INDEX_NAME]]
			if(w_uniform.mutant_variants & S.taur_mode)
				applied_style = S.taur_mode
			else if(w_uniform.mutant_variants & S.alt_taur_mode)
				applied_style = S.alt_taur_mode
		if(!applied_style)
			if((DIGITIGRADE in dna.species.species_traits) && (w_uniform.mutant_variants & STYLE_DIGITIGRADE))
				applied_style = STYLE_DIGITIGRADE

		var/x_override
		switch(applied_style)
			if(STYLE_DIGITIGRADE)
				icon_file = w_uniform.worn_icon_digi || 'modular_septic/icons/mob/clothing/under/uniform_digi.dmi'
			if(STYLE_TAUR_SNAKE)
				icon_file = w_uniform.worn_icon_taur_snake || 'modular_septic/icons/mob/clothing/under/uniform_taur_snake.dmi'
			if(STYLE_TAUR_HOOF)
				icon_file = w_uniform.worn_icon_taur_hoof || 'modular_septic/icons/mob/clothing/under/uniform_taur_hoof.dmi'
			if(STYLE_TAUR_PAW)
				icon_file = w_uniform.worn_icon_taur_paw || 'modular_septic/icons/mob/clothing/under/uniform_taur_paw.dmi'

		if(applied_style & STYLE_TAUR_ALL)
			x_override = 64

		var/target_overlay = U.icon_state
		if(U.adjusted == ALT_STYLE)
			target_overlay = "[target_overlay]_d"

		var/mutable_appearance/uniform_overlay

		if(dna && dna.species.sexes && !applied_style)
			if(body_type == FEMALE && U.fitted != NO_FEMALE_UNIFORM)
				uniform_overlay = U.build_worn_icon(default_layer = UNIFORM_LAYER, default_icon_file = 'icons/mob/clothing/under/default.dmi', isinhands = FALSE, femaleuniform = U.fitted, override_state = target_overlay, override_icon = icon_file, override_x_center = x_override, mutant_styles = applied_style)

		if(!uniform_overlay)
			uniform_overlay = U.build_worn_icon(default_layer = UNIFORM_LAYER, default_icon_file = 'icons/mob/clothing/under/default.dmi', isinhands = FALSE, override_state = target_overlay, override_icon = icon_file, override_x_center = x_override, mutant_styles = applied_style)

		if(OFFSET_UNIFORM in dna.species.offset_features)
			uniform_overlay.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1]
			uniform_overlay.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2]
		overlays_standing[UNIFORM_LAYER] = uniform_overlay

	apply_overlay(UNIFORM_LAYER)
	update_mutant_bodyparts()

/mob/living/carbon/human/update_inv_shoes()
	remove_overlay(SHOES_LAYER)

	if(dna.species.mutant_bodyparts["taur"])
		var/datum/sprite_accessory/taur/S = GLOB.sprite_accessories["taur"][dna.species.mutant_bodyparts["taur"][MUTANT_INDEX_NAME]]
		if(S.hide_legs)
			return

	if(!istype(src, /mob/living/carbon/human/dummy) && (num_legs < default_num_legs))
		return

	if(client && hud_used)
		var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_FEET) + 1]
		inv.update_icon()

	if(shoes)
		shoes.screen_loc = ui_shoes					//move the item to the appropriate screen loc
		if(client && hud_used?.hud_shown)
			if(hud_used.inventory_shown)			//if the inventory is open
				client.screen += shoes					//add it to client's screen
		update_observer_view(shoes,1)
		var/icon_file = shoes.worn_icon
		var/applied_styles = NONE
		if((DIGITIGRADE in dna.species.species_traits) && (shoes.mutant_variants & STYLE_DIGITIGRADE))
			applied_styles |= STYLE_DIGITIGRADE
			icon_file = shoes.worn_icon_digi || 'modular_septic/icons/mob/clothing/feet_digi.dmi'

		overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(default_layer = SHOES_LAYER, default_icon_file = 'icons/mob/clothing/feet.dmi', override_icon = icon_file, mutant_styles = applied_styles)
		var/mutable_appearance/shoes_overlay = overlays_standing[SHOES_LAYER]
		if(OFFSET_SHOES in dna.species.offset_features)
			shoes_overlay.pixel_x += dna.species.offset_features[OFFSET_SHOES][1]
			shoes_overlay.pixel_y += dna.species.offset_features[OFFSET_SHOES][2]
		overlays_standing[SHOES_LAYER] = shoes_overlay

	apply_overlay(SHOES_LAYER)

/mob/living/carbon/human/update_inv_s_store()
	remove_overlay(SUIT_STORE_LAYER)

	if(client && hud_used)
		var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_SUITSTORE) + 1]
		inv.update_appearance()

	if(s_store)
		s_store.screen_loc = ui_sstore1
		if(client && hud_used?.hud_shown)
			client.screen += s_store
		update_observer_view(s_store)
		if((s_store.worn_icon_state in icon_states(s_store.worn_icon)) || (s_store.worn_icon_state in icon_states('icons/mob/clothing/back.dmi')) || (s_store.worn_icon_state in icon_states('modular_septic/icons/mob/clothing/back.dmi')) )
			if(s_store.worn_icon_state in icon_states(s_store.worn_icon))
				overlays_standing[SUIT_STORE_LAYER] = s_store.build_worn_icon(default_layer = SUIT_STORE_LAYER, default_icon_file = 'icons/mob/clothing/back.dmi')
			else if(s_store.worn_icon_state in icon_states('icons/mob/clothing/back.dmi'))
				overlays_standing[SUIT_STORE_LAYER] = s_store.build_worn_icon(default_layer = SUIT_STORE_LAYER, default_icon_file = 'icons/mob/clothing/back.dmi', override_icon = 'icons/mob/clothing/back.dmi')
			else
				overlays_standing[SUIT_STORE_LAYER] = s_store.build_worn_icon(default_layer = SUIT_STORE_LAYER, default_icon_file = 'modular_septic/icons/mob/clothing/back.dmi', override_icon = 'modular_septic/icons/mob/clothing/back.dmi')
			var/mutable_appearance/s_store_overlay = overlays_standing[SUIT_STORE_LAYER]
			if(OFFSET_S_STORE in dna.species.offset_features)
				s_store_overlay.pixel_x += dna.species.offset_features[OFFSET_S_STORE][1]
				s_store_overlay.pixel_y += dna.species.offset_features[OFFSET_S_STORE][2]
			overlays_standing[SUIT_STORE_LAYER] = s_store_overlay
	apply_overlay(SUIT_STORE_LAYER)

//update whether our head item appears on our hud.
/mob/living/carbon/human/update_hud_head(obj/item/I)
	I.screen_loc = ui_head
	if(client && hud_used?.hud_shown)
		client.screen += I
	update_observer_view(I,1)

//update whether our mask item appears on our hud.
/mob/living/carbon/human/update_hud_wear_mask(obj/item/I)
	I.screen_loc = ui_mask
	if(client && hud_used?.hud_shown)
		client.screen += I
	update_observer_view(I,1)

// Only renders the head of the human
/mob/living/carbon/human/update_body_parts_head_only()
	if (!dna)
		return

	if (!dna.species)
		return

	var/obj/item/bodypart/HD = get_bodypart_nostump(BODY_ZONE_HEAD)
	if(!istype(HD))
		return

	HD.update_limb()

	add_overlay(HD.get_limb_icon())
	update_damage_overlays()
	if(HD && !(HAS_TRAIT(src, TRAIT_HUSK)))
		// lipstick
		if(lip_style && (LIPS in dna.species.species_traits))
			var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/human_face.dmi', "lips_[lip_style]", -BODY_LAYER)
			lip_overlay.color = lip_color
			if(OFFSET_FACE in dna.species.offset_features)
				lip_overlay.pixel_x += dna.species.offset_features[OFFSET_FACE][1]
				lip_overlay.pixel_y += dna.species.offset_features[OFFSET_FACE][2]
			add_overlay(lip_overlay)

		// eyes
		if(!(NOEYESPRITES in dna.species.species_traits))
			var/obj/item/bodypart/left_eyesocket = LAZYACCESS(eye_bodyparts, 1)
			var/obj/item/bodypart/right_eyesocket = LAZYACCESS(eye_bodyparts, 2)
			var/obj/item/organ/eyes/LE
			var/obj/item/organ/eyes/RE
			for(var/obj/item/organ/eyes/eye in left_eyesocket?.get_organs())
				LE = eye
				break
			for(var/obj/item/organ/eyes/eye in right_eyesocket?.get_organs())
				RE = eye
				break
			var/mutable_appearance/eye_overlay = mutable_appearance('modular_septic/icons/mob/human/sprite_accessory/human_face.dmi', "blank", -BODY_LAYER)
			var/obscured = check_obscured_slots(TRUE) //eyes that shine in the dark shouldn't show when you have glasses
			if(RE)
				var/image/right_overlay = image('modular_septic/icons/mob/human/sprite_accessory/human_face.dmi', null, RE.eye_icon_state, -BODY_LAYER)
				if(EYECOLOR in dna.species.species_traits)
					right_overlay.color = sanitize_hexcolor(right_eye_color, 6, TRUE)
				eye_overlay.add_overlay(right_overlay)
				if(RE.overlay_ignore_lighting && !(obscured & ITEM_SLOT_EYES))
					var/image/right_emissive = image('modular_septic/icons/mob/human/sprite_accessory/human_face.dmi', null, RE.eye_icon_state, -BODY_LAYER)
					right_emissive.plane = EMISSIVE_PLANE
					eye_overlay.add_overlay(right_emissive)
			else
				eye_overlay.add_overlay(image('modular_septic/icons/mob/human/sprite_accessory/human_face.dmi', null, "eye-right-missing", -BODY_LAYER))
			if(LE)
				var/image/left_overlay = image('modular_septic/icons/mob/human/sprite_accessory/human_face.dmi', null, LE.eye_icon_state, -BODY_LAYER)
				if(EYECOLOR in dna.species.species_traits)
					left_overlay.color = sanitize_hexcolor(left_eye_color, 6, TRUE)
				eye_overlay.add_overlay(left_overlay)
				if(LE.overlay_ignore_lighting && !(obscured & ITEM_SLOT_EYES))
					var/image/left_emissive = image('modular_septic/icons/mob/human/sprite_accessory/human_face.dmi', null, LE.eye_icon_state, -BODY_LAYER)
					left_emissive.plane = EMISSIVE_PLANE
					eye_overlay.add_overlay(left_emissive)
			else
				eye_overlay.add_overlay(image('modular_septic/icons/mob/human/sprite_accessory/human_face.dmi', null, "eye-left-missing", -BODY_LAYER))
			if(OFFSET_FACE in dna.species.offset_features)
				eye_overlay.pixel_x += dna.species.offset_features[OFFSET_FACE][1]
				eye_overlay.pixel_y += dna.species.offset_features[OFFSET_FACE][2]
			add_overlay(eye_overlay)

	dna.species.handle_hair(src)

	update_inv_head()
	update_inv_wear_mask()

/obj/item/build_worn_icon(default_layer = 0, default_icon_file = null, isinhands = FALSE, femaleuniform = NO_FEMALE_UNIFORM, override_state = null, override_icon = null, override_x_center = null, override_y_center = null, mutant_styles = NONE)
	//Find a valid icon_state from variables+arguments
	var/t_state
	if(override_state)
		t_state = override_state
	else
		t_state = !isinhands ? (worn_icon_state ? worn_icon_state : icon_state) : (inhand_icon_state ? inhand_icon_state : icon_state)

	//Find a valid icon file from variables+arguments
	var/file2use
	if(override_icon)
		file2use = override_icon
	else
		file2use = !isinhands ? (worn_icon ? worn_icon : default_icon_file) : default_icon_file

	//Find a valid layer from variables+arguments
	var/layer2use = alternate_worn_layer ? alternate_worn_layer : default_layer

	var/mutable_appearance/standing
	if(femaleuniform)
		standing = wear_female_version(t_state,file2use,layer2use,femaleuniform) //should layer2use be in sync with the adjusted value below? needs testing - shiz
	if(!standing)
		standing = mutable_appearance(file2use, t_state, -layer2use)

	//Get the overlays for this item when it's being worn
	//eg: ammo counters, primed grenade flashes, etc.
	var/list/worn_overlays = worn_overlays(standing, isinhands, file2use)
	if(LAZYLEN(worn_overlays))
		standing.overlays.Add(worn_overlays)

	var/x_center
	var/y_center
	if(override_x_center)
		x_center = override_x_center
	else
		x_center = isinhands ? inhand_x_dimension : worn_x_dimension
	if(override_y_center)
		y_center = override_y_center
	else
		y_center = isinhands ? inhand_y_dimension : worn_y_dimension
	standing = center_image(standing, x_center, y_center)

	//Worn offsets
	var/list/offsets = get_worn_offsets(isinhands)
	standing.pixel_x += offsets[1]
	standing.pixel_y += offsets[2]

	standing.alpha = alpha
	standing.color = color

	return standing

/mob/living/carbon/human/update_smelly()
	remove_overlay(SMELL_LAYER)

	switch(germ_level)
		if(-INFINITY to GERM_LEVEL_DIRTY)
			SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "smelly", /datum/mood_event/clean)
		if(GERM_LEVEL_DIRTY to GERM_LEVEL_FILTHY)
			SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "smelly")
		if(GERM_LEVEL_FILTHY to GERM_LEVEL_SMASHPLAYER)
			SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "smelly", /datum/mood_event/needshower)
			overlays_standing[SMELL_LAYER] = mutable_appearance('modular_septic/icons/effects/smell.dmi', "smell", -SMELL_LAYER)
		if(GERM_LEVEL_SMASHPLAYER to INFINITY)
			SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "smelly", /datum/mood_event/reallyneedshower)
			overlays_standing[SMELL_LAYER] = mutable_appearance('modular_septic/icons/effects/smell.dmi', "smell", -SMELL_LAYER)

	apply_overlay(SMELL_LAYER)


code:
/// Hide mutant bodyparts
/mob/living/carbon/human/verb/hide_furry_shit()
	set name = "Hide Mutant Bodyparts"
	set category = "IC"

	if(incapacitated())
		to_chat(src, span_warning("I can't do that right now."))
		return
	if(!do_mob(src, src, 3 SECONDS))
		to_chat(src, span_warning(fail_msg()))
		return
	if(HAS_TRAIT_FROM(src, TRAIT_HIDING_MUTANTPARTS, VERB_TRAIT))
		REMOVE_TRAIT(src, TRAIT_HIDING_MUTANTPARTS, VERB_TRAIT)
		to_chat(src, span_notice("I will now show my mutant bodyparts."))
	else
		ADD_TRAIT(src, TRAIT_HIDING_MUTANTPARTS, VERB_TRAIT)
		to_chat(src, span_notice("I will now hide my mutant bodyparts."))
	update_mutant_bodyparts()

repo_name: AnalWerewolf/sundown

license: mit


code:
/mob/living/carbon/human/update_carry_weight()
	. = 0
	var/list/inventory_items = list(back, wear_mask, wear_neck, head, gloves, shoes, glasses, wear_suit, w_uniform, belt, wear_id, r_store, l_store, s_store)
	//we do need a typecheck here to avoid nulls
	for(var/obj/item/thing in inventory_items)
		. += thing.get_carry_weight()
	for(var/obj/item/thing in held_items)
		. += thing.get_carry_weight()
	carry_weight = .
	update_encumbrance()


code:
// Return the item currently in the slot ID
/mob/living/carbon/human/get_item_by_slot(slot_id)
	switch(slot_id)
		if(ITEM_SLOT_BACK)
			return back
		if(ITEM_SLOT_MASK)
			return wear_mask
		if(ITEM_SLOT_NECK)
			return wear_neck
		if(ITEM_SLOT_HANDCUFFED)
			return handcuffed
		if(ITEM_SLOT_LEGCUFFED)
			return legcuffed
		if(ITEM_SLOT_BELT)
			return belt
		if(ITEM_SLOT_ID)
			return wear_id
		if(ITEM_SLOT_EARS, ITEM_SLOT_LEAR)
			return ears
		if(ITEM_SLOT_REAR)
			return ears_extra
		if(ITEM_SLOT_EYES)
			return glasses
		if(ITEM_SLOT_GLOVES)
			return gloves
		if(ITEM_SLOT_HEAD)
			return head
		if(ITEM_SLOT_FEET)
			return shoes
		if(ITEM_SLOT_OCLOTHING)
			return wear_suit
		if(ITEM_SLOT_ICLOTHING)
			return w_uniform
		if(ITEM_SLOT_LPOCKET)
			return l_store
		if(ITEM_SLOT_RPOCKET)
			return r_store
		if(ITEM_SLOT_SUITSTORE)
			return s_store
	return null


code:
/mob/living/carbon/human/Login()
	. = ..()
	if(!LAZYLEN(afk_thefts))
		return

	var/list/print_msg = list()
	print_msg += "
As you snap back to consciousness, you recall people messing with your stuff..."

	afk_thefts = reverse_range(afk_thefts)

	for(var/list/iter_theft as anything in afk_thefts)
		if(!islist(iter_theft) || LAZYLEN(iter_theft) != AFK_THEFT_TIME)
			stack_trace("[src] ([ckey]) returned to their body and had a null/malformed afk_theft entry. Contents: [json_encode(iter_theft)]")
			continue

		var/thief_name = iter_theft[AFK_THEFT_NAME]
		var/theft_message = iter_theft[AFK_THEFT_MESSAGE]
		var/time_since = world.time - iter_theft[AFK_THEFT_TIME]

		if(time_since > AFK_THEFT_FORGET_DETAILS_TIME)
			print_msg += "\n[span_danger("Someone [theft_message], but it was at least [DisplayTimeText(AFK_THEFT_FORGET_DETAILS_TIME)] ago.")]"
		else
			print_msg += "\n[span_danger("[thief_name] [theft_message] roughly [DisplayTimeText(time_since, 10)] ago.")]"

	if(LAZYLEN(afk_thefts) >= AFK_THEFT_MAX_MESSAGES)
		print_msg += span_warning("\nThere may have been more, but that's all you can remember...")
	print_msg += "
" //div infobo

	to_chat(src, jointext(print_msg, ""))
	LAZYNULL(afk_thefts)


code:
/datum/physiology
	var/thirst_mod = 1 //% of thirst rate taken per tick.
	var/arousal_mod = 1 //% of arousal rate taken per tick


code:
/mob/living/carbon/human/shit(intentional = FALSE)
	var/list/intestines = getorganslotlist(ORGAN_SLOT_INTESTINES)
	var/intestinal_efficiency = getorganslotefficiency(ORGAN_SLOT_INTESTINES)
	if(!length(intestines))
		if(intentional)
			to_chat(src, span_warning("I have no bowels."))
		return
	var/obj/item/bodypart/groin = get_bodypart_nostump(BODY_ZONE_PRECISE_GROIN)
	if(!groin)
		if(intentional)
			to_chat(src, span_warning("I have no groin."))
		return
	if(intestinal_efficiency < ORGAN_FAILING_EFFICIENCY)
		if(intentional)
			to_chat(src, span_warning("My bowels dilate in agonizing pain as they try to shit it's contents out!"))
		return
	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)
	if(collective_shit_amount < 10)
		if(intentional)
			to_chat(src, span_warning("I don't need to shit."))
		return
	var/obj/structure/toilet/toiler = locate() in get_turf(src)
	var/shit_pants = LAZYLEN(clothingonpart(groin))
	if(src in toiler?.buckled_mobs)
		shit_pants = FALSE
	if(shit_pants)
		SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "shat_self", /datum/mood_event/shat_self)
		for(var/obj/item/organ/intestines/intestine as anything in intestines)
			var/amount = min(40, intestine.reagents.get_reagent_amount(/datum/reagent/consumable/shit) - intestine.food_reagents[/datum/reagent/consumable/shit])
			intestine.reagents.remove_reagent(/datum/reagent/consumable/shit, amount)
			var/datum/reagents/reactant_holder = new(1000)
			reactant_holder.add_reagent(/datum/reagent/consumable/shit, amount)
			chem_splash(src, 1, list(reactant_holder))
			qdel(reactant_holder)
		playsound(get_turf(src), 'modular_septic/sound/effects/poo.ogg', 75)
		to_chat(src, span_warning("I shit on myself..."))
		return
	//we'll try to shit a maximum of 40u from each bowel
	var/obj/item/shit/stool = new(get_turf(src))
	stool.add_shit_DNA(get_blood_dna_list())
	stool.reagents.remove_all(INFINITY)
	for(var/obj/item/organ/intestines/intestine as anything in intestines)
		var/amount = min(40, intestine.reagents.get_reagent_amount(/datum/reagent/consumable/shit) - intestine.food_reagents[/datum/reagent/consumable/shit])
		intestine.reagents.trans_id_to(stool, /datum/reagent/consumable/shit, amount, preserve_data = TRUE)
	if(toiler)
		//mess gone
		qdel(stool)
		visible_message("[src] shits on [toiler].", \
					"I take a shit on [toiler].")
	else
		visible_message("[src] shits on [loc].", \
					"I take a shit on [loc].")
	playsound(get_turf(src), 'modular_septic/sound/effects/poo.ogg', 75)

/mob/living/carbon/human/piss(intentional = FALSE)
	var/list/bladders = getorganslotlist(ORGAN_SLOT_BLADDER)
	var/bladderal_efficiency = getorganslotefficiency(ORGAN_SLOT_BLADDER)
	if(!length(bladders))
		if(intentional)
			to_chat(src, span_warning("I have no bladders."))
		return
	var/obj/item/bodypart/groin = get_bodypart_nostump(BODY_ZONE_PRECISE_GROIN)
	if(!groin)
		if(intentional)
			to_chat(src, span_warning("I have no groin."))
		return
	if(bladderal_efficiency < ORGAN_FAILING_EFFICIENCY)
		if(intentional)
			to_chat(src, span_warning("My bladder dilates in agonizing pain as it tries to piss it's contents out!"))
		return
	var/collective_piss_amount = 0
	for(var/obj/item/organ/bladder/bladder as anything in bladders)
		collective_piss_amount += bladder.reagents.get_reagent_amount(/datum/reagent/consumable/piss)
	if(collective_piss_amount < 10)
		if(intentional)
			to_chat(src, span_warning("I don't need to piss."))
		return
	var/obj/structure/toilet/toiler = locate() in get_turf(src)
	var/obj/structure/urinal/urinel = locate() in get_turf(src)
	var/piss_pants = LAZYLEN(clothingonpart(groin))
	if((src in toiler?.buckled_mobs) || (urinel && (getorganslotefficiency(ORGAN_SLOT_PENIS) >= ORGAN_FAILING_EFFICIENCY)))
		piss_pants = FALSE
	var/turf/pissed = get_turf(src)
	if(piss_pants)
		SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "pee_self", /datum/mood_event/pissed_self)
		for(var/obj/item/organ/bladder/bladder as anything in bladders)
			var/amount = min(40, bladder.reagents.get_reagent_amount(/datum/reagent/consumable/piss) - bladder.food_reagents[/datum/reagent/consumable/piss])
			bladder.reagents.remove_reagent(/datum/reagent/consumable/piss, amount)
			pissed.add_liquid(/datum/reagent/consumable/piss, amount)
		playsound(get_turf(src), 'modular_septic/sound/effects/pee.ogg', 75)
		to_chat(src, span_warning("I piss on myself..."))
		return
	//try to evacuate 40u out of each bladder
	if(urinel)
		visible_message("[src] pisses on [urinel].", \
					"I take a piss on [urinel].")
		for(var/obj/item/organ/bladder/bladder as anything in bladders)
			var/amount = min(40, bladder.reagents.get_reagent_amount(/datum/reagent/consumable/piss) - bladder.food_reagents[/datum/reagent/consumable/piss])
			bladder.reagents.remove_reagent(/datum/reagent/consumable/piss, amount)
	else if(toiler)
		visible_message("[src] pisses on [toiler].", \
					"I take a piss on [toiler].")
		for(var/obj/item/organ/bladder/bladder as anything in bladders)
			var/amount = min(40, bladder.reagents.get_reagent_amount(/datum/reagent/consumable/piss) - bladder.food_reagents[/datum/reagent/consumable/piss])
			bladder.reagents.remove_reagent(/datum/reagent/consumable/piss, amount)
	else
		for(var/obj/item/organ/bladder/bladder as anything in bladders)
			var/amount = min(40, bladder.reagents.get_reagent_amount(/datum/reagent/consumable/piss) - bladder.food_reagents[/datum/reagent/consumable/piss])
			bladder.reagents.remove_reagent(/datum/reagent/consumable/piss, amount)
			pissed.add_liquid(/datum/reagent/consumable/piss, amount)
		visible_message("[src] pisses on [pissed].", \
					"I take a piss on [pissed].")
	playsound(get_turf(src), 'modular_septic/sound/effects/pee.ogg', 75)


code:
/datum/species
	bodypart_overides = list(
		BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm,\
		BODY_ZONE_PRECISE_L_HAND = /obj/item/bodypart/l_hand,\
		BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm,\
		BODY_ZONE_PRECISE_R_HAND = /obj/item/bodypart/r_hand,\
		BODY_ZONE_PRECISE_L_EYE = /obj/item/bodypart/l_eyesocket,\
		BODY_ZONE_PRECISE_R_EYE = /obj/item/bodypart/r_eyesocket,\
		BODY_ZONE_PRECISE_MOUTH = /obj/item/bodypart/mouth,\
		BODY_ZONE_PRECISE_FACE = /obj/item/bodypart/face,\
		BODY_ZONE_PRECISE_NECK = /obj/item/bodypart/neck,\
		BODY_ZONE_HEAD = /obj/item/bodypart/head,\
		BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg,\
		BODY_ZONE_PRECISE_L_FOOT = /obj/item/bodypart/l_foot,\
		BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg,\
		BODY_ZONE_PRECISE_R_FOOT = /obj/item/bodypart/r_foot,\
		BODY_ZONE_PRECISE_GROIN = /obj/item/bodypart/groin,\
		BODY_ZONE_CHEST = /obj/item/bodypart/chest,\
		)
	var/list/pain_emote_by_power = list(
		"100" = "agonyscream",
		"90" = "whimper",
		"80" = "moan",
		"70" = "cry",
		"60" = "gargle",
		"50" = "moan",
		"40" = "moan",
		"30" = "groan",
		"20" = "groan",
		"10" = "grunt", //Below 10 pain, we shouldn't emote.
		)
	var/reagent_processing = REAGENT_ORGANIC
	var/list/default_genitals_male = list(ORGAN_SLOT_PENIS = /obj/item/organ/genital/penis,
										ORGAN_SLOT_TESTICLES = /obj/item/organ/genital/testicles)
	var/list/default_genitals_female = list(ORGAN_SLOT_VAGINA = /obj/item/organ/genital/vagina,
										ORGAN_SLOT_WOMB = /obj/item/organ/genital/womb,
										ORGAN_SLOT_BREASTS = /obj/item/organ/genital/breasts,
										)
	var/mutantspleen = /obj/item/organ/spleen
	var/mutantkidneys = /obj/item/organ/kidneys
	var/mutantintestines = /obj/item/organ/intestines
	var/mutantbladder = /obj/item/organ/bladder
	var/examine_icon_state = "human"

/datum/species/New()
	. = ..()
	var/list/genitalia = list()
	genitalia |= default_genitals_male
	genitalia |= default_genitals_female
	for(var/thing in genitalia)
		var/obj/item/organ/genital/genital = genitalia[thing]
		if(initial(genital.mutantpart_key))
			default_mutant_bodyparts[initial(genital.mutantpart_key)] = "None"

/datum/species/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load)
	// Drop the items the new species can't wear
	if((AGENDER in species_traits))
		C.gender = PLURAL
	for(var/slot_id in no_equip)
		var/obj/item/thing = C.get_item_by_slot(slot_id)
		if(thing && (!thing.species_exception || !is_type_in_list(src,thing.species_exception)))
			C.dropItemToGround(thing)
	if(C.hud_used)
		C.hud_used.update_locked_slots()

	fix_non_native_limbs(C)

	// this needs to be FIRST because qdel calls update_body which checks if we have DIGITIGRADE legs or not and if not then removes DIGITIGRADE from species_traits
	if(DIGITIGRADE in species_traits)
		C.Digitigrade_Leg_Swap(FALSE)

	C.mob_biotypes = inherent_biotypes

	regenerate_organs(C, old_species, replace_current = TRUE)

	if(exotic_bloodtype && C.dna.blood_type != exotic_bloodtype)
		C.dna.blood_type = exotic_bloodtype

	if(old_species.mutanthands)
		for(var/obj/item/I in C.held_items)
			if(istype(I, old_species.mutanthands))
				qdel(I)

	if(mutanthands)
		// Drop items in hands
		// If you're lucky enough to have a TRAIT_NODROP item, then it stays.
		for(var/V in C.held_items)
			var/obj/item/I = V
			if(istype(I))
				C.dropItemToGround(I)
			else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand
				C.put_in_hands(new mutanthands())

	for(var/X in inherent_traits)
		ADD_TRAIT(C, X, SPECIES_TRAIT)

	if(TRAIT_VIRUSIMMUNE in inherent_traits)
		for(var/datum/disease/A in C.diseases)
			A.cure(FALSE)

	if(TRAIT_TOXIMMUNE in inherent_traits)
		C.setToxLoss(0, TRUE, TRUE)

	if(TRAIT_NOMETABOLISM in inherent_traits)
		C.reagents.end_metabolization(C, keep_liverless = TRUE)

	if(TRAIT_GENELESS in inherent_traits)
		C.dna.remove_all_mutations() // Radiation immune mobs can't get mutations normally

	if(inherent_factions)
		for(var/i in inherent_factions)
			C.faction += i //Using +=/-= for this in case you also gain the faction from a different source.

	if(flying_species && isnull(fly))
		fly = new
		fly.Grant(C)

	for(var/obj/item/bodypart/bodypart in C.bodyparts)
		bodypart.alpha = bodypart_alpha
		if(ROBOTIC_LIMBS in species_traits)
			bodypart.change_bodypart_status(BODYPART_ROBOTIC, FALSE, TRUE)
			bodypart.limb_flags |= BODYPART_SYNTHETIC
			bodypart.advanced_rendering = TRUE
		else if(bodypart.status == BODYPART_ORGANIC)
			bodypart.advanced_rendering = TRUE

	C.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/species, multiplicative_slowdown=speedmod)

	if(!(C.status_flags & BUILDING_ORGANS))
		C.update_body()

	SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species)

/datum/species/get_biological_state(mob/living/carbon/human/H)
	. = BIO_INORGANIC
	if(HAS_FLESH in species_traits)
		. = BIO_JUST_FLESH
	if(HAS_BONE in species_traits)
		if(. == BIO_JUST_FLESH)
			. = BIO_FLESH_BONE
		else
			. = BIO_JUST_BONE

/datum/species/get_features()
	var/list/features = list()
	for(var/preference_type in GLOB.preference_entries)
		var/datum/preference/preference = GLOB.preference_entries[preference_type]
		if( (preference.relevant_mutant_bodypart in default_mutant_bodyparts) \
			|| (preference.relevant_species_trait in species_traits) )
			features += preference.savefile_key
	GLOB.features_by_species[type] = features
	return features

/datum/species/handle_environment_pressure(mob/living/carbon/human/H, datum/gas_mixture/environment, delta_time, times_fired)
	var/pressure = environment.return_pressure()
	var/adjusted_pressure = H.calculate_affecting_pressure(pressure)

	// Set alerts and apply damage based on the amount of pressure
	switch(adjusted_pressure)
		// Very high pressure, show an alert and take damage
		if(HAZARD_HIGH_PRESSURE to INFINITY)
			if(!HAS_TRAIT(H, TRAIT_RESISTHIGHPRESSURE))
				var/ouchie = min( ((adjusted_pressure/HAZARD_HIGH_PRESSURE) - 1) * PRESSURE_DAMAGE_COEFFICIENT, MAX_HIGH_PRESSURE_DAMAGE) * H.physiology.pressure_mod * delta_time
				H.take_bodypart_damage(ouchie)
				//high pressures will cause ear damage
				for(var/obj/item/organ/ear in H.getorganslotlist(ORGAN_SLOT_EARS))
					ear.applyOrganDamage(ouchie)
				//also pops your lungs
				for(var/obj/item/organ/lung in H.getorganslotlist(ORGAN_SLOT_LUNGS))
					lung.applyOrganDamage(ouchie)
				H.update_hud_pressure(4)
			else
				H.update_hud_pressure(2)

		// High pressure, show an alert
		if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE)
			if(!HAS_TRAIT(H, TRAIT_RESISTHIGHPRESSURE))
				H.update_hud_pressure(3)
			else
				H.update_hud_pressure(2)

		// No pressure issues here clear pressure alerts
		if(WARNING_LOW_PRESSURE to WARNING_HIGH_PRESSURE)
			H.update_hud_pressure(2)

		// Low pressure here, show an alert
		if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE)
			// We have low pressure resit trait, clear alerts
			if(HAS_TRAIT(H, TRAIT_RESISTLOWPRESSURE))
				H.update_hud_pressure(2)
			else
				H.update_hud_pressure(1)

		// Very low pressure, show an alert and take damage
		else
			// We have low pressure resit trait, clear alerts
			if(HAS_TRAIT(H, TRAIT_RESISTLOWPRESSURE))
				H.update_hud_pressure(2)
			else
				var/ouchie = LOW_PRESSURE_DAMAGE * H.physiology.pressure_mod * delta_time
				H.take_bodypart_damage(ouchie)
				//low pressures will cause ear damage
				for(var/obj/item/organ/ear in H.getorganslotlist(ORGAN_SLOT_EARS))
					ear.applyOrganDamage(ouchie)
				//also pops your lungs
				for(var/obj/item/organ/lung in H.getorganslotlist(ORGAN_SLOT_LUNGS))
					lung.applyOrganDamage(ouchie)
				H.update_hud_pressure(0)

/datum/species/body_temperature_damage(mob/living/carbon/human/humi, delta_time, times_fired)
	// Body temperature is too hot, and we do not have resist traits
	var/is_hulk = HAS_TRAIT(humi, TRAIT_HULK)
	var/cold_damage_limit = bodytemp_cold_damage_limit + (is_hulk ? BODYTEMP_HULK_COLD_DAMAGE_LIMIT_MODIFIER : 0)
	// Apply some burn damage to the body
	if(humi.coretemperature > bodytemp_heat_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTHEAT))
		var/damage_mod = coldmod * humi.physiology.burn_mod * (humi.on_fire ? 2 : 1)
		switch(humi.coretemperature - bodytemp_heat_damage_limit)
			if(0 to 50)
				humi.take_bodypart_damage(burn = HEAT_DAMAGE_LEVEL_1 * damage_mod * delta_time)
			if(50 to 90)
				humi.take_bodypart_damage(burn = HEAT_DAMAGE_LEVEL_2 * damage_mod * delta_time)
			if(90 to INFINITY)
				humi.take_bodypart_damage(burn = HEAT_DAMAGE_LEVEL_3 * damage_mod * delta_time)
	// Apply some burn damage to the body
	if(humi.coretemperature < cold_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTCOLD))
		var/damage_mod = coldmod * humi.physiology.cold_mod * (is_hulk ? HULK_COLD_DAMAGE_MOD : 1)
		switch(cold_damage_limit - humi.coretemperature)
			if(0 to 67)
				humi.take_bodypart_damage(burn = COLD_DAMAGE_LEVEL_1 * damage_mod * delta_time)
			if(67 to 110)
				humi.take_bodypart_damage(burn = COLD_DAMAGE_LEVEL_2 * damage_mod * delta_time)
			if(110 to INFINITY)
				humi.take_bodypart_damage(burn = COLD_DAMAGE_LEVEL_3 * damage_mod * delta_time)

/datum/species/body_temperature_alerts(mob/living/carbon/human/humi)
	// Body temperature is too hot, and we do not have resist traits
	if(humi.bodytemperature > bodytemp_heat_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTHEAT))
		// Clear cold mood and apply hot mood
		SEND_SIGNAL(humi, COMSIG_CLEAR_MOOD_EVENT, "cold")
		SEND_SIGNAL(humi, COMSIG_ADD_MOOD_EVENT, "hot", /datum/mood_event/hot)
		// Remove any slowdown from the cold
		humi.remove_movespeed_modifier(/datum/movespeed_modifier/cold)
		// Display alerts based on how hot it is
		switch(humi.bodytemperature)
			if(0 to 460)
				humi.update_hud_bodytemperature(4)
			if(461 to 700)
				humi.update_hud_bodytemperature(5)
			else
				humi.update_hud_bodytemperature(6)
	// Body temperature is too cold, and we do not have resist traits
	else if(humi.bodytemperature < bodytemp_cold_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTCOLD))
		// clear any hot moods and apply cold mood
		SEND_SIGNAL(humi, COMSIG_CLEAR_MOOD_EVENT, "hot")
		SEND_SIGNAL(humi, COMSIG_ADD_MOOD_EVENT, "cold", /datum/mood_event/cold)
		// Apply cold slow down
		humi.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/cold, multiplicative_slowdown = ((bodytemp_cold_damage_limit - humi.bodytemperature) / COLD_SLOWDOWN_FACTOR))
		// Display alerts based how cold it is
		switch(humi.bodytemperature)
			if(201 to bodytemp_cold_damage_limit)
				humi.update_hud_bodytemperature(2)
			if(120 to 200)
				humi.update_hud_bodytemperature(1)
			else
				humi.update_hud_bodytemperature(0)
	// We are not too hot nor cold, remove status and modifiers
	else
		humi.update_hud_bodytemperature(3)
		humi.remove_movespeed_modifier(/datum/movespeed_modifier/cold)
		SEND_SIGNAL(humi, COMSIG_CLEAR_MOOD_EVENT, "cold")
		SEND_SIGNAL(humi, COMSIG_CLEAR_MOOD_EVENT, "hot")
	// Handle updating external temperature alerts
	external_temperature_alerts(humi)

/datum/species/proc/external_temperature_alerts(mob/living/carbon/human/humi)
	// Get the enviroment details of where the mob is standing
	var/datum/gas_mixture/environment = humi.loc.return_air()
	if(!environment) // if there is no environment (nullspace) drop out here.
		return

	// Get the temperature of the environment for area
	var/area_temp = humi.get_temperature(environment)
	// External temperature is too hot, and we do not have resist traits
	if(area_temp > bodytemp_heat_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTHEAT))
		// Display alerts based on how hot it is
		switch(area_temp)
			if(0 to 460)
				humi.update_hud_temperature(4)
			if(461 to 700)
				humi.update_hud_temperature(5)
			else
				humi.update_hud_temperature(6)
	// Body temperature is too cold, and we do not have resist traits
	else if(area_temp < bodytemp_cold_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTCOLD))
		// Display alerts based how cold it is
		switch(area_temp)
			if(201 to bodytemp_cold_damage_limit)
				humi.update_hud_temperature(2)
			if(120 to 200)
				humi.update_hud_temperature(1)
			else
				humi.update_hud_temperature(0)
	// We are not too hot nor cold, remove status and modifiers
	else
		humi.update_hud_temperature(3)

/datum/species/regenerate_organs(mob/living/carbon/C, datum/species/old_species, replace_current = FALSE, list/excluded_zones)
	var/list/slot_mutantorgans = list(ORGAN_SLOT_BRAIN = mutantbrain, ORGAN_SLOT_HEART = mutantheart, \
							ORGAN_SLOT_LUNGS = mutantlungs, \
							ORGAN_SLOT_APPENDIX = mutantappendix, ORGAN_SLOT_EARS = mutantears, \
							ORGAN_SLOT_EYES = mutanteyes, ORGAN_SLOT_TONGUE = mutanttongue, \
							ORGAN_SLOT_LIVER = mutantliver, ORGAN_SLOT_STOMACH = mutantstomach, \
							ORGAN_SLOT_SPLEEN = mutantspleen, ORGAN_SLOT_KIDNEYS = mutantkidneys, \
							ORGAN_SLOT_INTESTINES = mutantintestines, ORGAN_SLOT_BLADDER = mutantbladder)
	// this is pure dumb code but just, bear with me
	for(var/slot in slot_mutantorgans)
		var/list/oldorgans = list()
		oldorgans |= C.getorganslotlist(slot)
		var/obj/item/organ/neworgan = slot_mutantorgans[slot]//used in adding
		var/used_neworgan = FALSE
		neworgan = new neworgan()
		var/should_have = neworgan.get_availability(src) //organ proc that points back to a species trait (so if the species is supposed to have this organ)

		var/mutant_part = FALSE
		for(var/thing in oldorgans)
			var/obj/item/organ/oldorgan = thing
			//Motherfucker! Deal with this in the mutant part code block instead
			if(oldorgan.mutantpart_key)
				mutant_part = TRUE
				break
			if((!should_have || replace_current) && !(oldorgan.zone in excluded_zones) && !(oldorgan.organ_flags & ORGAN_UNREMOVABLE))
				if(slot == ORGAN_SLOT_BRAIN)
					var/obj/item/organ/brain/brain = oldorgan
					if(!brain.decoy_override) //"Just keep it if it's fake" - confucius, probably
						brain.before_organ_replacement(neworgan)
						brain.Remove(C, TRUE, TRUE) //brain argument used so it doesn't cause any... sudden death.
						oldorgans -= brain
						qdel(brain)
				else
					oldorgan.before_organ_replacement(neworgan)
					oldorgan.Remove(C, TRUE)
					oldorgans -= oldorgan
					qdel(oldorgan)
		//Again, deal with this in the mutant part code block instead
		if(mutant_part)
			continue

		if(LAZYLEN(oldorgans))
			for(var/thing in oldorgans)
				var/obj/item/organ/oldorgan = thing
				oldorgan.setOrganDamage(0)
			if((slot in PAIRED_ORGAN_SLOTS) && (LAZYLEN(oldorgans) < 2))
				var/side = LEFT_SIDE
				for(var/thinge in oldorgans)
					var/obj/item/organ/oldorgan = thinge
					if(oldorgan.side == LEFT_SIDE)
						side = RIGHT_SIDE
						break
				used_neworgan = TRUE
				neworgan.switch_side(side)
				neworgan.Insert(C, TRUE, FALSE)
		else if(should_have && !(initial(neworgan.zone) in excluded_zones))
			used_neworgan = TRUE
			neworgan.Insert(C, TRUE, FALSE)
			// this is dumb
			if(slot in PAIRED_ORGAN_SLOTS)
				neworgan = new neworgan.type()
				neworgan.switch_side(LEFT_SIDE)
				neworgan.Insert(C, TRUE, FALSE)
		if(!used_neworgan)
			qdel(neworgan)
	if(old_species)
		for(var/mutantorgan in old_species.mutant_organs)
			// Snowflake check - If our species share this mutant organ, let's not remove it
			// just yet as we'll be properly replacing it later
			if(mutantorgan in mutant_organs)
				continue
			for(var/obj/item/organ/killme in C.getorganlist(mutantorgan))
				killme.Remove(C, TRUE)
				qdel(killme)
	for(var/organ_path in mutant_organs)
		var/obj/item/organ/current_organ = C.getorgan(organ_path)
		if(!current_organ || replace_current)
			var/obj/item/organ/replacement = new organ_path()
			// If there's an existing mutant organ, we're technically replacing it.
			// Let's abuse the snowflake proc that skillchips added. Basically retains
			// feature parity with every other organ too.
			if(current_organ)
				current_organ.before_organ_replacement(replacement)
				current_organ.Remove(C, TRUE)
				qdel(current_organ)
			// organ.Insert will qdel any current organs in that slot, so we don't need to.
			replacement.Insert(C, TRUE, FALSE)
	// Handle mutant organ shit
	var/robot_organs = (ROBOTIC_ORGANS in C.dna.species.species_traits)
	for(var/key in C.dna.species.mutant_bodyparts)
		var/datum/sprite_accessory/SA = LAZYACCESSASSOC(GLOB.sprite_accessories, key, LAZYACCESSASSOC(C.dna.species.mutant_bodyparts, key, MUTANT_INDEX_NAME))
		if(SA && SA.factual && SA.organ_type)
			var/obj/item/organ/path = new SA.organ_type()
			//this needs to be done before the other organs are removed due to reasons i guess
			path.build_from_dna(C.dna, key)
			if(robot_organs)
				path.status = ORGAN_ROBOTIC
				path.organ_flags |= ORGAN_SYNTHETIC
			if(replace_current)
				var/list/old_organs = C.getorganslotlist(LAZYACCESS(path.organ_efficiency, 1))
				for(var/thing in old_organs)
					var/obj/item/organ/oldorgan = thing
					oldorgan.Remove(C, TRUE)
					qdel(oldorgan)
			path.Insert(C, TRUE, FALSE)
			if(LAZYACCESS(path.organ_efficiency, 1) in PAIRED_ORGAN_SLOTS)
				path = new SA.organ_type()
				if(robot_organs)
					path.status = ORGAN_ROBOTIC
					path.organ_flags |= ORGAN_SYNTHETIC
				path.build_from_dna(C.dna, key)
				path.Insert(C, TRUE, FALSE)
	//I have NO CLUE what causes this
	//I *shouldn't* have to have a clue what causes this
	//But i have to do this dumb shit to avoid people having "organs"
	for(var/wtf in C.internal_organs)
		var/obj/item/organ/why = wtf
		if(!LAZYLEN(why.organ_efficiency))
			why.Remove(C, FALSE)
			qdel(why)

///Removes any non-native limbs from the mob
/datum/species/fix_non_native_limbs(mob/living/carbon/human/H)
	for(var/X in H.bodyparts)
		var/obj/item/bodypart/current_part = X
		var/obj/item/bodypart/species_part = bodypart_overides[current_part.body_zone]
		if(current_part.type == species_part)
			continue
		current_part.change_bodypart(species_part)
	if(ROBOTIC_LIMBS in species_traits)
		for(var/thing in H.bodyparts)
			var/obj/item/bodypart/bodypart = thing
			bodypart.change_bodypart_status(BODYPART_ORGANIC)
			bodypart.limb_flags |= BODYPART_SYNTHETIC
			bodypart.advanced_rendering = TRUE
	for(var/thing in H.bodyparts)
		var/obj/item/bodypart/bodypart = thing
		bodypart.update_limb()

/datum/species/proc/breathe(mob/living/carbon/human/H, delta_time, times_fired, datum/organ_process/lung_process)
	if(HAS_TRAIT(H, TRAIT_NOBREATH))
		return TRUE

/datum/species/proc/get_pain_emote(power)
	if(NOPAIN in species_traits) // Synthetics don't grunt because of "pain"
		return
	power = FLOOR(min(100, power), 10)
	var/emote_string
	if(power >= PAIN_EMOTE_MINIMUM)
		emote_string = pain_emote_by_power["[power]"]
	return emote_string

/datum/species/proc/spec_revival(mob/living/carbon/human/H)
	return


code:
/datum/species
	punchdamagelow = 6
	punchdamagehigh = 8
	punchstunthreshold = 16
	attack_sound = list('modular_septic/sound/effects/punch1.wav',
						'modular_septic/sound/effects/punch2.wav',
						'modular_septic/sound/effects/punch3.wav')
	miss_sound = list('modular_septic/sound/effects/punchmiss.ogg')
	attack_effect = ATTACK_EFFECT_PUNCH
	attack_verb = "punch"
	var/attack_verb_continuous = "punches"
	var/kick_effect = ATTACK_EFFECT_KICK
	var/kick_verb = "kick"
	var/kick_verb_continuous = "kicks"
	var/bite_effect = ATTACK_EFFECT_BITE
	var/bite_verb = "bite"
	var/bite_verb_continuous = "bites"

/datum/species/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, mob/living/carbon/human/H)
	// Allows you to put in item-specific reactions based on species
	var/damage = I.force
	if(user.attributes)
		damage *= (GET_MOB_ATTRIBUTE_VALUE(user, STAT_STRENGTH)/ATTRIBUTE_MIDDLING)
	var/weakness = check_species_weakness(I, user)
	if(weakness)
		damage *= weakness
	if((user != H) && damage)
		if(H.check_shields(I, damage, "the [I.name]", MELEE_ATTACK, I.armour_penetration))
			return FALSE
	if((user != H) && H.check_block())
		var/attack_message = "attack"
		if(length(I.attack_verb_simple))
			attack_message = pick(I.attack_verb_simple)
		H.visible_message(span_warning("[H] blocks [user]'s [attack_message] with [user.p_their()] [I]!"), \
						span_userdanger("I block [user]'s [attack_message] with [user.p_their()] [I]!"), \
						span_hear("I hear a swoosh!"), \
						COMBAT_MESSAGE_RANGE, \
						user)
		to_chat(user, span_userdanger("[H] blocks my [attack_message] with my [I]!"))
		return FALSE

	var/hit_area = affecting?.name
	var/def_zone = affecting?.body_zone
	var/intended_zone = user.zone_selected

	var/armor_block = H.run_armor_check(affecting, MELEE, span_notice("My armor has protected my [hit_area]!"), span_warning("My armor has softened a hit to my [hit_area]!"), \
					I.armour_penetration, \
					weak_against_armour = I.weak_against_armour)
	armor_block = min(90, armor_block) //cap damage reduction at 90%
	var/Iwound_bonus = I.wound_bonus

	// this way, you can't wound with a surgical tool on help intent if they have a surgery active and are lying down, so a misclick with a circular saw on the wrong limb doesn't bleed them dry (they still get hit tho)
	if((I.item_flags & SURGICAL_TOOL) && IS_HELP_INTENT(user, null))
		Iwound_bonus = CANT_WOUND

	if(damage && !(I.item_flags & NOBLUDGEON))
		apply_damage(damage, I.damtype, def_zone, armor_block, H, wound_bonus = Iwound_bonus, bare_wound_bonus = I.bare_wound_bonus, sharpness = I.get_sharpness())

	H.send_item_attack_message(I, user, hit_area, affecting)

	if(!(I.item_flags & NOBLUDGEON))
		if((I.damtype == BRUTE) && damage && prob(25 + (damage * 2)))
			if(affecting.is_organic_limb())
				I.add_mob_blood(H) //Make the weapon bloody, not the person.
				if(prob(damage * 2)) //blood spatter!
					var/turf/location = H.loc
					if(istype(location))
						H.do_hitsplatter(get_dir(user, H), min_range = 0, max_range = 2, splatter_loc = pick(FALSE, TRUE))
					if(get_dist(user, H) <= 1) //people with TK won't get smeared with blood
						user.add_mob_blood(H)
					switch(def_zone)
						if(BODY_ZONE_HEAD, BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_PRECISE_L_EYE, BODY_ZONE_PRECISE_R_EYE)
							/* TODO: Move this into its own proc and add other stuff
							if(!I.get_sharpness() && armor_block < 50)
								if(prob(damage))
									if(H.stat <= SOFT_CRIT)
										H.visible_message(span_danger("[H] is knocked senseless!"), \
														span_userdanger("I am knocked senseless!"))
										H.set_confusion(max(H.get_confusion(), 20))
										H.adjust_blurriness(10)
									if(prob(25))
										H.gain_trauma(/datum/brain_trauma/mild/concussion)

								//rev deconversion through blunt trauma.
								var/datum/antagonist/rev/rev = H.mind?.has_antag_datum(/datum/antagonist/rev)
								if(rev && H.stat == CONSCIOUS && H != user && prob(I.force + H.getBruteLoss() * 0.5)))
									rev.remove_revolutionary(FALSE, user)
							*/
							//Apply blood
							if(H.head)
								H.head.add_mob_blood(H)
								H.update_inv_head()
							if(H.wear_mask)
								H.wear_mask.add_mob_blood(H)
								H.update_inv_wear_mask()
							if(H.glasses)
								H.glasses.add_mob_blood(H)
								H.update_inv_glasses()
						if(BODY_ZONE_PRECISE_L_FOOT, BODY_ZONE_PRECISE_R_FOOT)
							if(H.shoes)
								H.shoes.add_mob_blood(H)
								H.update_inv_shoes()
						else
							/* TODO: Move this into its own proc and add other stuff
							if(H.stat == CONSCIOUS && !I.get_sharpness() && armor_block < 50)
								if(prob(damage))
									H.visible_message(span_danger("[H] is knocked down!"), \
												span_userdanger("You're knocked down!"))
									H.CombatKnockdown(10, knockdown_duration = 60)
							*/
							if(H.wear_suit)
								H.wear_suit.add_mob_blood(H)
								H.update_inv_wear_suit()
							if(H.w_uniform)
								H.w_uniform.add_mob_blood(H)
								H.update_inv_w_uniform()
		post_hit_effects(H, user, affecting, I, damage, def_zone, intended_zone)
	return TRUE

/datum/species/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, modifiers)
	if(!istype(M))
		return
	CHECK_DNA_AND_SPECIES(M)
	CHECK_DNA_AND_SPECIES(H)

	if(!attacker_style && M.mind)
		attacker_style = M.mind.martial_art

	if((M != H) && !IS_HELP_INTENT(M, modifiers) && H.check_shields(M, 0, M.name, attack_type = UNARMED_ATTACK))
		H.visible_message(span_warning("[M] attempts to touch [H]!"), \
						span_danger("[M] attempts to touch me!"), \
						span_hear("I hear a swoosh!"), \
						COMBAT_MESSAGE_RANGE, \
						M)
		to_chat(M, span_warning("I attempt to touch [H]!"))
		log_combat(M, H, "attempted to touch")
		return

	SEND_SIGNAL(M, COMSIG_MOB_ATTACK_HAND, M, H, attacker_style)

	switch(M.a_intent)
		if(INTENT_HELP)
			help(M, H, attacker_style)
		if(INTENT_DISARM)
			disarm(M, H, attacker_style)
		if(INTENT_GRAB)
			grab(M, H, attacker_style)
		if(INTENT_HARM)
			harm(M, H, attacker_style)
		else
			help(M, H, attacker_style)

/datum/species/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, modifiers)
	if(!istype(M))
		return
	CHECK_DNA_AND_SPECIES(M)
	CHECK_DNA_AND_SPECIES(H)

	if(!attacker_style && M.mind)
		attacker_style = M.mind.martial_art

	if((M != H) && !IS_HELP_INTENT(M, modifiers) && H.check_shields(M, 0, M.name, attack_type = UNARMED_ATTACK))
		H.visible_message(span_warning("[M] attempts to touch [H]!"), \
						span_danger("[M] attempts to touch me!"), \
						span_hear("I hear a swoosh!"), \
						COMBAT_MESSAGE_RANGE, \
						M)
		to_chat(M, span_warning("I attempt to touch [H]!"))
		log_combat(M, H, "attempted to touch")
		return

	SEND_SIGNAL(M, COMSIG_MOB_ATTACK_HAND, M, H, attacker_style)

	switch(M.a_intent)
		if(INTENT_HELP)
			help(M, H, attacker_style)
		if(INTENT_DISARM)
			disarm(M, H, attacker_style)
		if(INTENT_GRAB)
			grab(M, H, attacker_style)
		if(INTENT_HARM)
			harm(M, H, attacker_style, SPECIAL_ATK_NONE)
		else
			help(M, H, attacker_style, SPECIAL_ATK_NONE)

/datum/species/help(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
	if((target.body_position == STANDING_UP) || (user.zone_selected in list(BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)))
		target.help_shake_act(user)
		if(target != user)
			log_combat(user, target, "shaken")
		return TRUE
	else if(user.zone_selected in list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_MOUTH))
		user.do_cpr(target, user.zone_selected == BODY_ZONE_CHEST ? CPR_CHEST : CPR_MOUTH)
		return TRUE

/datum/species/disarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
	if((user != target) && target.check_block())
		target.visible_message(span_warning("[user]'s shove is blocked by [target]!"), \
						span_userdanger("I block [user]'s shove!"), \
						span_hear("I hear a swoosh!"), \
						COMBAT_MESSAGE_RANGE, \
						user)
		to_chat(user, span_userdanger("My shove at [target] was blocked!"))
		log_combat(user, target, "attempted to shove, was blocked by")
		return FALSE
	if(attacker_style?.disarm_act(user,target) == MARTIAL_ATTACK_SUCCESS)
		return TRUE
	if(user == target)
		return FALSE
	user.disarm(target)

/datum/species/harm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style, special_attack = SPECIAL_ATK_NONE)
	if(HAS_TRAIT(user, TRAIT_PACIFISM))
		to_chat(user, span_warning("I don't want to harm [target]!"))
		return FALSE
	if((user != target) && target.check_block())
		target.visible_message(span_warning("[target] blocks [user]'s attack!"), \
						span_userdanger("I block [user]'s attack!"), \
						span_hear("I hear a swoosh!"), \
						COMBAT_MESSAGE_RANGE, \
						user)
		if(user != target)
			to_chat(user, span_userdanger("My attack at [target] was blocked!"))
		log_combat(user, target, "attempted to punch, was blocked by")
		return FALSE
	if(attacker_style?.harm_act(user,target) == MARTIAL_ATTACK_SUCCESS)
		return TRUE

	var/damage = rand(user.dna.species.punchdamagelow, user.dna.species.punchdamagehigh)
	if(user.attributes)
		damage *= (GET_MOB_ATTRIBUTE_VALUE(user, STAT_STRENGTH)/ATTRIBUTE_MIDDLING)

	var/atk_verb
	var/atk_verb_continuous
	var/atk_effect
	var/atk_sharpness = NONE
	var/atk_cost = 4
	switch(special_attack)
		if(SPECIAL_ATK_BITE)
			atk_verb = pick(user.dna.species.bite_verb)
			atk_verb_continuous = pick(user.dna.species.bite_verb_continuous)
			atk_effect = pick(user.dna.species.bite_effect)
			atk_sharpness = SHARP_POINTY
			atk_cost *= 2
		if(SPECIAL_ATK_KICK)
			atk_verb = pick(user.dna.species.kick_verb)
			atk_verb_continuous = pick(user.dna.species.kick_verb_continuous)
			atk_effect = pick(user.dna.species.kick_effect)
			damage *= 2
			atk_cost *= 3
		else
			atk_verb = pick(user.dna.species.attack_verb)
			atk_verb_continuous = pick(user.dna.species.attack_verb_continuous)
			atk_effect = pick(user.dna.species.attack_effect)

	user.do_attack_animation(target, atk_effect)

	var/obj/item/bodypart/attacking_part
	switch(atk_effect)
		if(ATTACK_EFFECT_BITE)
			attacking_part = user.get_bodypart_nostump(BODY_ZONE_PRECISE_MOUTH)
		if(ATTACK_EFFECT_KICK)
			attacking_part = user.get_active_foot()
		else
			attacking_part = user.get_active_hand()
	if(!attacking_part)
		damage = 0
	else
		damage *= (attacking_part.limb_efficiency/LIMB_EFFICIENCY_OPTIMAL)

	var/obj/item/bodypart/affecting = target.get_bodypart(check_zone(user.zone_selected))

	///calculate the odds that a punch misses entirely
	var/hit_modifier = 0
	///chance to hit the wrong zone
	var/hit_zone_modifier = 0
	if(affecting)
		hit_modifier = affecting.hit_modifier
		hit_zone_modifier = affecting.hit_zone_modifier
		//very hard to miss when hidden by fov
		if(!(src in fov_viewers(2, user)))
			hit_modifier += 4
			hit_zone_modifier += 4
		//easy to kick people when they are down
		if(target.body_position == LYING_DOWN)
			hit_modifier += 6
			hit_zone_modifier += 6
		if(HAS_TRAIT(user, TRAIT_PERFECT_ATTACKER))
			hit_modifier = 20
			hit_zone_modifier = 20
		//hitting yourself is easy
		if(user == target)
			hit_modifier = 20
			hit_zone_modifier = 20

	var/hit_area = parse_zone(user.zone_selected)
	var/def_zone = user.zone_selected
	var/intended_zone = user.zone_selected
	if(affecting)
		hit_area = affecting.name
		def_zone = affecting.body_zone

	user.adjustFatigueLoss(atk_cost)
	//future-proofing for species that have 0 damage/weird cases where no zone is targeted
	var/diceroll = user.diceroll(GET_MOB_ATTRIBUTE_VALUE(user, SKILL_MELEE)+hit_modifier)
	if(!damage || !affecting || (diceroll <= DICE_FAILURE))
		playsound(target.loc, user.dna.species.miss_sound, 60, TRUE, -1)
		if(user != target)
			target.visible_message(span_danger("[user] tries to [atk_verb] [target]'s [hit_area], but misses!"), \
							span_userdanger("[user]'s tries to [atk_verb] my [hit_area], but misses!"), \
							span_hear("I hear a swoosh!"), \
							COMBAT_MESSAGE_RANGE, \
							user)
			to_chat(user, span_userdanger("I try to [atk_verb] [target]'s [hit_area], but miss!"))
		else
			target.visible_message(span_danger("[user] tries to [atk_verb] [user.p_themselves()] on \the [hit_area], but misses!"), \
							span_userdanger("I try to [atk_verb] my [hit_area], but miss!"), \
							span_hear("I hear a swoosh!"), \
							COMBAT_MESSAGE_RANGE)
		log_combat(user, target, "attempted to [atk_verb], missed")
		return FALSE

	if(user.diceroll(GET_MOB_ATTRIBUTE_VALUE(user, SKILL_MELEE)+hit_zone_modifier) <= DICE_FAILURE)
		affecting = target.get_bodypart(ran_zone(user.zone_selected, 0))

	var/armor_block = target.run_armor_check(affecting, MELEE)

	playsound(target.loc, user.dna.species.attack_sound, 60, TRUE, -1)

	if(def_zone == intended_zone)
		if(user != target)
			target.visible_message(span_danger("[user] [atk_verb_continuous] [target]'s [hit_area]![target.wound_message]"), \
							span_userdanger("[user] [atk_verb_continuous] my [hit_area]![target.wound_message]"), \
							span_hear("I hear a sickening sound of flesh hitting flesh!"), \
							vision_distance = COMBAT_MESSAGE_RANGE, \
							ignored_mobs = user)
			to_chat(user, span_userdanger("I [atk_verb] [target]'s [hit_area]!"))
		else
			target.visible_message(span_danger("[user] [atk_verb_continuous] [user.p_themselves()] on \the [hit_area]![target.wound_message]"), \
							span_userdanger("I [atk_verb] myself on \the [hit_area]![target.wound_message]"), \
							span_hear("I hear a sickening sound of flesh hitting flesh!"), \
							vision_distance = COMBAT_MESSAGE_RANGE)
	else
		var/parsed_intended_zone = parse_zone(intended_zone)
		if(user != target)
			target.visible_message(span_danger("[user] aims for \the [parsed_intended_zone], but [atk_verb_continuous] [target]'s [hit_area] instead![target.wound_message]"), \
							span_userdanger("[user] aims for my [parsed_intended_zone], but [atk_verb_continuous] my [hit_area] instead![target.wound_message]"), \
							span_hear("I hear a sickening sound of flesh hitting flesh!"), \
							vision_distance = COMBAT_MESSAGE_RANGE, \
							ignored_mobs = user)
			to_chat(user, span_userdanger("I aim for the [parsed_intended_zone], but [atk_verb] [target]'s [hit_area] instead![target.wound_message]"))
		else
			target.visible_message(span_danger("[user] aims for the [parsed_intended_zone], but [atk_verb_continuous] [user.p_themselves()] on \the [hit_area] instead![target.wound_message]"), \
							span_userdanger("I aim for my [parsed_intended_zone], but [atk_verb] myself on \the [hit_area] instead![target.wound_message]"), \
							span_hear("I hear a sickening sound of flesh hitting flesh!"), \
							vision_distance = COMBAT_MESSAGE_RANGE, \
							ignored_mobs = user)
	target.lastattacker = user.real_name
	target.lastattackerckey = user.ckey
	user.dna.species.spec_unarmedattacked(user, target)

	if(user.limb_destroyer)
		target.dismembering_strike(user, def_zone)

	target.apply_damage(damage, user.dna.species.attack_type, affecting, armor_block, sharpness = atk_sharpness)
	target.apply_damage(damage*1.5, STAMINA, affecting)
	log_combat(user, target, "[atk_verb]")

	SEND_SIGNAL(target, COMSIG_CARBON_CLEAR_WOUND_MESSAGE)
	post_hit_effects(target, user, affecting, atk_effect, damage, def_zone, intended_zone)

/datum/species/grab(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
	if(target.check_block())
		target.visible_message(span_warning("[target] blocks [user]'s grab!"), \
						span_userdanger("I block [user]'s grab!"), \
						span_hear("I hear a swoosh!"), \
						COMBAT_MESSAGE_RANGE, \
						user)
		to_chat(user, span_warning("My grab at [target] was blocked!"))
		log_combat(user, target, "attempted to grab, was blocked by")
		return FALSE
	if(attacker_style?.grab_act(user,target) == MARTIAL_ATTACK_SUCCESS)
		return TRUE
	else
		target.grabbedby(user)
		return TRUE

/datum/species/proc/spec_attack_foot(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, modifiers)
	if(!istype(M))
		return
	CHECK_DNA_AND_SPECIES(M)
	CHECK_DNA_AND_SPECIES(H)

	if(!attacker_style && M.mind)
		attacker_style = M.mind.martial_art

	if(H.check_shields(M, 0, M.name, attack_type = UNARMED_ATTACK))
		H.visible_message(span_warning("[M] attempts to touch [H]!"), \
						span_danger("[M] attempts to touch me!"), \
						span_hear("I hear a swoosh!"), \
						COMBAT_MESSAGE_RANGE, \
						M)
		to_chat(M, span_warning("I attempt to touch [H]!"))
		log_combat(M, H, "attempted to kick")
		return

	SEND_SIGNAL(M, COMSIG_MOB_ATTACK_FOOT, M, H, attacker_style)

	harm(M, H, attacker_style, SPECIAL_ATK_KICK)

/datum/species/proc/spec_attack_jaw(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, modifiers)
	if(!istype(M))
		return
	CHECK_DNA_AND_SPECIES(M)
	CHECK_DNA_AND_SPECIES(H)

	if(!attacker_style && M.mind)
		attacker_style = M.mind.martial_art

	if(H.check_shields(M, 0, M.name, attack_type = UNARMED_ATTACK))
		log_combat(M, H, "attempted to touch")
		H.visible_message(span_warning("[M] attempts to touch [H]!"), \
						span_danger("[M] attempts to touch me!"), \
						span_hear("I hear a swoosh!"), \
						COMBAT_MESSAGE_RANGE, \
						M)
		to_chat(M, span_warning("I attempt to touch [H]!"))
		return

	SEND_SIGNAL(M, COMSIG_MOB_ATTACK_JAW, M, H, attacker_style)

	harm(M, H, attacker_style, SPECIAL_ATK_BITE)

//Weapon can be an attack effect instead
/datum/species/proc/post_hit_effects(mob/living/carbon/human/victim, mob/living/carbon/human/user, obj/item/bodypart/affected, obj/item/weapon, damage, def_zone, intended_zone)
	if(!istype(weapon))
		var/atk_verb
		var/atk_effect = weapon
		switch(atk_effect)
			if(ATTACK_EFFECT_KICK)
				atk_verb = pick(user.dna.species.kick_verb)
			if(ATTACK_EFFECT_BITE)
				atk_verb = pick(user.dna.species.bite_verb)
			else
				atk_verb = pick(user.dna.species.attack_verb)
		if((atk_effect != ATTACK_EFFECT_BITE) && (victim.stat != DEAD) && damage >= user.dna.species.punchstunthreshold)
			victim.visible_message(span_danger("[user] knocks [victim] down!"), \
							span_userdanger("I am knocked down by [user]!"), \
							span_hear("I hear aggressive shuffling followed by a loud thud!"), \
							COMBAT_MESSAGE_RANGE, \
							user)
			if(user != victim)
				to_chat(user, span_userdanger("I knock [victim] down!"))
			var/knockdown_duration = 40 + (victim.getStaminaLoss() + (victim.getBruteLoss()*0.5))*0.8 //50 total damage = 40 base stun + 40 stun modifier = 80 stun duration, which is the old base duration
			victim.CombatKnockdown(knockdown_duration/4, knockdown_duration)
			log_combat(user, victim, "got a stun [atk_verb] with their previous [atk_verb]")

/datum/species/handle_fire(mob/living/carbon/human/H, delta_time, times_fired, no_protection = FALSE)
	if(!CanIgniteMob(H))
		return TRUE
	if(H.on_fire)
		SEND_SIGNAL(H, COMSIG_HUMAN_BURNING)
		//the fire tries to damage the exposed clothes and items
		var/list/burning_items = list()
		var/obscured = H.check_obscured_slots(TRUE)
		//HEAD//
		if(H.glasses && !(obscured & ITEM_SLOT_EYES))
			burning_items += H.glasses
		if(H.wear_mask && !(obscured & ITEM_SLOT_MASK))
			burning_items += H.wear_mask
		if(H.wear_neck && !(obscured & ITEM_SLOT_NECK))
			burning_items += H.wear_neck
		if(H.ears && !(obscured & ITEM_SLOT_LEAR))
			burning_items += H.ears
		if(H.ears_extra && !(obscured & ITEM_SLOT_REAR))
			burning_items += H.ears_extra
		if(H.head)
			burning_items += H.head

		//CHEST//
		if(H.w_uniform && !(obscured & ITEM_SLOT_ICLOTHING))
			burning_items += H.w_uniform
		if(H.wear_suit)
			burning_items += H.wear_suit

		//ARMS & HANDS//
		var/obj/item/clothing/arm_clothes = null
		if(H.gloves && !(obscured & ITEM_SLOT_GLOVES))
			arm_clothes = H.gloves
		else if(H.wear_suit && ((H.wear_suit.body_parts_covered & HANDS) || (H.wear_suit.body_parts_covered & ARMS)))
			arm_clothes = H.wear_suit
		else if(H.w_uniform && ((H.w_uniform.body_parts_covered & HANDS) || (H.w_uniform.body_parts_covered & ARMS)))
			arm_clothes = H.w_uniform
		if(arm_clothes)
			burning_items |= arm_clothes

		//LEGS & FEET//
		var/obj/item/clothing/leg_clothes = null
		if(H.shoes && !(obscured & ITEM_SLOT_FEET))
			leg_clothes = H.shoes
		else if(H.wear_suit && ((H.wear_suit.body_parts_covered & FEET) || (H.wear_suit.body_parts_covered & LEGS)))
			leg_clothes = H.wear_suit
		else if(H.w_uniform && ((H.w_uniform.body_parts_covered & FEET) || (H.w_uniform.body_parts_covered & LEGS)))
			leg_clothes = H.w_uniform
		if(leg_clothes)
			burning_items |= leg_clothes

		for(var/X in burning_items)
			var/obj/item/I = X
			I.fire_act((H.fire_stacks * 50)) //damage taken is reduced to 2% of this value by fire_act()

		var/thermal_protection = H.get_thermal_protection()

		if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT && !no_protection)
			return
		if(thermal_protection >= FIRE_SUIT_MAX_TEMP_PROTECT && !no_protection)
			H.adjust_bodytemperature(5.5 * delta_time)
		else
			H.adjust_bodytemperature((BODYTEMP_HEATING_MAX + (H.fire_stacks * 12)) * 0.5 * delta_time)
			SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "on_fire", /datum/mood_event/on_fire)


code:
/datum/species/proc/agony_scream(mob/living/carbon/human/H)
	if(!istype(H))
		return FALSE
	H.emote("agonyscream")

/datum/species/proc/fall_scream(mob/living/carbon/human/H)
	if(!istype(H))
		return FALSE
	H.emote("fallscream")

/datum/species/proc/death_scream(mob/living/carbon/human/H)
	if(!istype(H))
		return FALSE
	H.emote("deathscream")

/datum/species/proc/agony_gargle(mob/living/carbon/human/H)
	if(!istype(H))
		return FALSE
	H.emote("gargle")

/datum/species/proc/agony_gasp(mob/living/carbon/human/H)
	if(!istype(H))
		return FALSE
	H.emote("gasp")

/datum/species/proc/death_rattle(mob/living/carbon/human/H)
	if(!istype(H))
		return FALSE
	H.emote("deathrattle")

/datum/species/proc/sexy_moan(mob/living/carbon/human/H)
	if(!istype(H))
		return FALSE
	H.emote("sexymoan")

/datum/species/proc/jump_grunt(mob/living/carbon/human/H)
	if(!istype(H))
		return FALSE
	H.emote("jumpgrunt")

/datum/species/proc/fatigue_grunt(mob/living/carbon/human/H)
	if(!istype(H))
		return FALSE
	H.emote("fatiguegrunt")


code:
/datum/species
	/// List of all birthsigns this species can have, defaults to first in list
	var/list/available_birthsigns = list(/datum/cultural_info/birthsign/starless, \
										/datum/cultural_info/birthsign/warrior, \
										/datum/cultural_info/birthsign/mage)
	/// List of all the languages our species can learn NO MATTER their background
	var/list/learnable_languages = list(/datum/language/common = LANGUAGE_SPOKEN, \
										/datum/language/uncommon = LANGUAGE_SPOKEN, \
										/datum/language/newspeak = LANGUAGE_SPOKEN, \
										/datum/language/cyrillic = LANGUAGE_SPOKEN, \
										/datum/language/aphasia = LANGUAGE_SPOKEN)
	/// List of languages our character MUST have in the setup
	var/list/necessary_languages = list(/datum/language/common = LANGUAGE_UNDERSTOOD)
	/// List of languages our character has by default in the setup
	var/list/default_languages = list(/datum/language/common = LANGUAGE_SPOKEN)


code:
/datum/species/can_equip(obj/item/I, slot, disable_warning, mob/living/carbon/human/H, bypass_equip_delay_self = FALSE)
	if(slot in no_equip)
		if(!I.species_exception || !is_type_in_list(src, I.species_exception))
			return FALSE

	// if there's an item in the slot we want, fail
	if(H.get_item_by_slot(slot))
		return FALSE

	// this check prevents us from equipping something to a slot it doesn't support, WITH the exceptions of storage slots (pockets, and backpacks)
	// we don't require having those slots defined in the item's slot_flags, so we'll rely on their own checks further down
	if(!(I.slot_flags & slot))
		var/excused = FALSE
		// Anything that's small or smaller can fit into a pocket by default
		if((slot == ITEM_SLOT_RPOCKET || slot == ITEM_SLOT_LPOCKET) && I.w_class <= WEIGHT_CLASS_SMALL)
			excused = TRUE
		else if(slot == ITEM_SLOT_BACKPACK || slot == ITEM_SLOT_HANDS)
			excused = TRUE
		else if((slot == ITEM_SLOT_SUITSTORE) && (I.slot_flags & ITEM_SLOT_BACK))
			excused = TRUE
		if(!excused)
			return FALSE

	switch(slot)
		if(ITEM_SLOT_HANDS)
			if(H.get_empty_held_indexes())
				return TRUE
			return FALSE
		if(ITEM_SLOT_MASK)
			if(!H.get_bodypart_nostump(check_zone(BODY_ZONE_PRECISE_FACE)))
				return FALSE
			return equip_delay_self_check(I, H, bypass_equip_delay_self)
		if(ITEM_SLOT_NECK)
			if(!H.get_bodypart_nostump(check_zone(BODY_ZONE_PRECISE_NECK)))
				return FALSE
			return equip_delay_self_check(I, H, bypass_equip_delay_self)
		if(ITEM_SLOT_BACK)
			return equip_delay_self_check(I, H, bypass_equip_delay_self)
		if(ITEM_SLOT_OCLOTHING)
			return equip_delay_self_check(I, H, bypass_equip_delay_self)
		if(ITEM_SLOT_GLOVES)
			if(H.num_hands < H.default_num_hands)
				return FALSE
			return equip_delay_self_check(I, H, bypass_equip_delay_self)
		if(ITEM_SLOT_FEET)
			if(H.num_legs < H.default_num_legs)
				return FALSE
			if(DIGITIGRADE in species_traits)
				if(!disable_warning)
					to_chat(H, span_warning("The footwear around here isn't compatible with your feet!"))
				return FALSE
			return equip_delay_self_check(I, H, bypass_equip_delay_self)
		if(ITEM_SLOT_BELT)
			var/obj/item/bodypart/O = H.get_bodypart_nostump(check_zone(BODY_ZONE_PRECISE_GROIN))
			if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
				if(!disable_warning)
					to_chat(H, span_warning("You need a jumpsuit before you can attach this [I.name]!"))
				return FALSE
			return equip_delay_self_check(I, H, bypass_equip_delay_self)
		if(ITEM_SLOT_EYES)
			if(!H.get_bodypart_nostump(check_zone(BODY_ZONE_PRECISE_FACE)))
				return FALSE
			for(var/thing in H.getorganslotlist(ORGAN_SLOT_EYES))
				var/obj/item/organ/eyes/E = thing
				if(E.no_glasses)
					return FALSE
			return equip_delay_self_check(I, H, bypass_equip_delay_self)
		if(ITEM_SLOT_HEAD)
			if(!H.get_bodypart_nostump(check_zone(BODY_ZONE_HEAD)))
				return FALSE
			return equip_delay_self_check(I, H, bypass_equip_delay_self)
		if(ITEM_SLOT_EARS, ITEM_SLOT_LEAR, ITEM_SLOT_REAR)
			if(!H.get_bodypart_nostump(check_zone(BODY_ZONE_PRECISE_FACE)))
				return FALSE
			return equip_delay_self_check(I, H, bypass_equip_delay_self)
		if(ITEM_SLOT_ICLOTHING)
			return equip_delay_self_check(I, H, bypass_equip_delay_self)
		if(ITEM_SLOT_ID)
			var/obj/item/bodypart/O = H.get_bodypart_nostump(check_zone(BODY_ZONE_CHEST))
			if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
				if(!disable_warning)
					to_chat(H, span_warning("You need a jumpsuit before you can attach this [I.name]!"))
				return FALSE
			return equip_delay_self_check(I, H, bypass_equip_delay_self)
		if(ITEM_SLOT_LPOCKET)
			if(HAS_TRAIT(I, TRAIT_NODROP)) //Pockets aren't visible, so you can't move TRAIT_NODROP items into them.
				return FALSE
			if(H.l_store) // no pocket swaps at all
				return FALSE
			var/obj/item/bodypart/O = H.get_bodypart_nostump(check_zone(BODY_ZONE_L_LEG))
			if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
				if(!disable_warning)
					to_chat(H, span_warning("You need a jumpsuit before you can pocket this [I.name]!"))
				return FALSE
			return TRUE
		if(ITEM_SLOT_RPOCKET)
			if(HAS_TRAIT(I, TRAIT_NODROP))
				return FALSE
			if(H.r_store)
				return FALSE
			var/obj/item/bodypart/O = H.get_bodypart_nostump(check_zone(BODY_ZONE_R_LEG))
			if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
				if(!disable_warning)
					to_chat(H, span_warning("You need a jumpsuit before you can pocket this [I.name]!"))
				return FALSE
			return TRUE
		if(ITEM_SLOT_SUITSTORE)
			if(HAS_TRAIT(I, TRAIT_NODROP))
				return FALSE
			if(!H.get_bodypart_nostump(check_zone(BODY_ZONE_CHEST)))
				return FALSE
			return equip_delay_self_check(I, H, bypass_equip_delay_self)
		if(ITEM_SLOT_HANDCUFFED)
			if(!istype(I, /obj/item/restraints/handcuffs))
				return FALSE
			if(H.num_hands < H.default_num_hands)
				return FALSE
			return TRUE
		if(ITEM_SLOT_LEGCUFFED)
			if(!istype(I, /obj/item/restraints/legcuffs))
				return FALSE
			if(H.num_legs < H.default_num_legs)
				return FALSE
			return TRUE
		if(ITEM_SLOT_BACKPACK)
			if(H.back && SEND_SIGNAL(H.back, COMSIG_TRY_STORAGE_CAN_INSERT, I, H, bypass_equip_delay_self, FALSE, bypass_equip_delay_self))
				return TRUE
			return FALSE
	return FALSE //Unsupported slot


code:
/datum/species/abductor
	limbs_icon = 'modular_septic/icons/mob/human/species/alien/abductor_parts.dmi'
	limbs_id = "abductor"


code:
/datum/species/android
	limbs_icon = 'modular_septic/icons/mob/human/species/synthetic/synth_parts.dmi'
	limbs_id = "synth"


code:
/datum/species/dullahan
	mutant_bodyparts = list()
	limbs_id = "human"


code:
/datum/species/ethereal
	limbs_icon = 'modular_septic/icons/mob/human/species/ethereal/ethereal_parts_greyscale.dmi'
	limbs_id = "ethereal"


code:
/datum/species/human/felinid
	mutant_bodyparts = list()


code:
/datum/species/fly
	limbs_icon = 'modular_septic/icons/mob/human/species/insect/fly_parts.dmi'
	limbs_id = "fly"


code:
/datum/species/golem
	limbs_icon = 'modular_septic/icons/mob/human/species/golem/golem_parts_greyscale.dmi'
	limbs_id = "golem"

/datum/species/golem/bone
	limbs_icon = 'modular_septic/icons/mob/human/species/golem/bonegolem_parts.dmi'
	limbs_id = "b_golem"

/datum/species/golem/cardboard
	limbs_icon = 'modular_septic/icons/mob/human/species/golem/cardboardgolem_parts.dmi'
	limbs_id = "c_golem"

/datum/species/golem/bronze
	limbs_icon = 'modular_septic/icons/mob/human/species/golem/clockgolem_parts.dmi'
	limbs_id = "clockgolem"

/datum/species/golem/cloth
	limbs_icon = 'modular_septic/icons/mob/human/species/golem/clothgolem_parts.dmi'
	limbs_id = "clothgolem"

/datum/species/golem/runic
	limbs_icon = 'modular_septic/icons/mob/human/species/golem/cultgolem_parts.dmi'
	limbs_id = "cultgolem"

/datum/species/golem/durathread
	limbs_icon = 'modular_septic/icons/mob/human/species/golem/durathreadgolem_parts.dmi'
	limbs_id = "d_golem"

/datum/species/golem/snow
	limbs_icon = 'modular_septic/icons/mob/human/species/golem/snowgolem_parts.dmi'
	limbs_id = "sn_golem"


code:
/datum/species/human
	mutant_bodyparts = list()
	default_mutant_bodyparts = list(
		"ears" = "None",
		"tail" = "None",
		"horns" = "None",
		"wings" = "None",
	)
	limbs_id = "human"
	limbs_icon = DEFAULT_BODYPART_ICON_ORGANIC


code:
/datum/species/jelly
	limbs_icon = 'modular_septic/icons/mob/human/species/slime/jelly_parts_greyscale.dmi'
	limbs_id = "jelly"

/datum/species/jelly/slime
	limbs_icon = 'modular_septic/icons/mob/human/species/slime/slime_parts_greyscale.dmi'
	limbs_id = "slime"

/datum/species/jelly/stargazer
	limbs_icon = 'modular_septic/icons/mob/human/species/slime/stargazer_parts_greyscale.dmi'
	limbs_id = "stargazer"


code:
/datum/species/monkey
	bodypart_overides = list(
		BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/monkey,\
		BODY_ZONE_PRECISE_L_HAND = /obj/item/bodypart/l_hand/monkey,\
		BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/monkey,\
		BODY_ZONE_PRECISE_R_HAND = /obj/item/bodypart/r_hand/monkey,\
		BODY_ZONE_PRECISE_L_EYE = /obj/item/bodypart/l_eyesocket/monkey,\
		BODY_ZONE_PRECISE_R_EYE = /obj/item/bodypart/r_eyesocket/monkey,\
		BODY_ZONE_PRECISE_FACE = /obj/item/bodypart/face/monkey,\
		BODY_ZONE_PRECISE_MOUTH = /obj/item/bodypart/mouth/monkey,\
		BODY_ZONE_PRECISE_NECK = /obj/item/bodypart/neck/monkey,\
		BODY_ZONE_HEAD = /obj/item/bodypart/head/monkey,\
		BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/monkey,\
		BODY_ZONE_PRECISE_L_FOOT = /obj/item/bodypart/l_foot/monkey,\
		BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/monkey,\
		BODY_ZONE_PRECISE_R_FOOT = /obj/item/bodypart/r_foot/monkey,\
		BODY_ZONE_PRECISE_GROIN = /obj/item/bodypart/groin/monkey,\
		BODY_ZONE_CHEST = /obj/item/bodypart/chest/monkey,\
		)
	no_equip = list(ITEM_SLOT_LEAR, ITEM_SLOT_REAR, ITEM_SLOT_EYES, ITEM_SLOT_OCLOTHING, ITEM_SLOT_GLOVES, ITEM_SLOT_FEET, ITEM_SLOT_ICLOTHING, ITEM_SLOT_SUITSTORE)
	limbs_icon = 'modular_septic/icons/mob/human/species/monkey/monkey_parts.dmi'
	limbs_id = "monkey"
	examine_icon_state = "monkey"


code:
/datum/species/mush
	limbs_icon = 'modular_septic/icons/mob/human/species/mushroom/mush_parts_greyscale.dmi'
	limbs_id = "mush"


code:
/datum/species/plasmaman
	limbs_icon = 'modular_septic/icons/mob/human/species/skeleton/plasmaman_parts.dmi'
	limbs_id = "plasmaman"


code:
/datum/species/pod
	limbs_icon = 'modular_septic/icons/mob/human/species/plant/plant_parts_greyscale.dmi'
	limbs_id = "plant"


code:
/datum/species/shadow
	limbs_icon = 'modular_septic/icons/mob/human/species/shadow/shadow_parts.dmi'
	limbs_id = "shadow"


code:
/datum/species/skeleton
	limbs_icon = 'modular_septic/icons/mob/human/species/skeleton/skeleton_parts.dmi'
	limbs_id = "skeleton"


code:
/datum/species/snail
	limbs_icon = 'modular_septic/icons/mob/human/species/slime/snail_parts_greyscale.dmi'
	limbs_id = "snail"


code:
/datum/species/synth
	limbs_icon = 'modular_septic/icons/mob/human/species/synthetic/synth_parts.dmi'
	limbs_id = "synth"


code:
/datum/species/vampire
	mutant_bodyparts = list()


code:
/datum/species/werecat
	name = "Ailuranthrope"
	id = SPECIES_WERECAT
	default_color = "4B4B4B"
	species_traits = list(
		MUTCOLORS,
		EYECOLOR,
		LIPS,
		HAS_FLESH,
		HAS_BONE,
		HAIR,
	)
	inherent_traits = list(
		TRAIT_ADVANCEDTOOLUSER,
		TRAIT_CAN_STRIP,
	)
	inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BEAST
	mutant_bodyparts = list()
	default_mutant_bodyparts = list(
		"tail" = ACC_RANDOM,
		"snout" = ACC_RANDOM,
		"ears" = ACC_RANDOM,
		"horns" = "None",
		"wings" = "None",
	)
	liked_food = GROSS|MEAT|FRIED
	changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT
	limbs_icon = 'modular_septic/icons/mob/human/species/mammal/mammal_parts_greyscale.dmi'
	limbs_id = "mammal"
	examine_icon_state = "werecat"

/datum/species/werecat/get_random_features()
	var/list/returned = MANDATORY_FEATURE_LIST
	var/main_color
	var/second_color
	var/random = rand(1,5)
	//Choose from a variety of mostly coldish, animal, matching colors
	switch(random)
		if(1)
			main_color = "BBAA88"
			second_color = "AAAA99"
		if(2)
			main_color = "777766"
			second_color = "888877"
		if(3)
			main_color = "AA9988"
			second_color = "AAAA99"
		if(4)
			main_color = "EEEEDD"
			second_color = "FFEEEE"
		if(5)
			main_color = "DDCC99"
			second_color = "DDCCAA"
	returned["mcolor"] = main_color
	returned["mcolor2"] = second_color
	returned["mcolor3"] = second_color
	return returned

/datum/species/werecat/get_random_body_markings(list/passed_features)
	var/name = pick("Werecat", "Floof", "Floofer")
	var/datum/body_marking_set/BMS = GLOB.body_marking_sets[name]
	var/list/markings = list()
	if(BMS)
		markings = assemble_body_markings_from_set(BMS, passed_features, src)
	return markings

/datum/species/werecat/random_name(gender,unique,lastname)
	var/randname
	if(gender == MALE)
		randname = pick(GLOB.first_names_male_werecat)
	else
		randname = pick(GLOB.first_names_female_werecat)

	if(lastname)
		randname += " [lastname]"
	else
		randname += " [pick(GLOB.last_names_werecat)]"

	return randname


code:
/datum/species/lizard
	name = "Saurothrope"
	limbs_icon = 'modular_septic/icons/mob/human/species/lizard/lizard_parts_greyscale.dmi'
	limbs_id = "lizard"
	default_color = "D8FFCE"
	species_traits = list(
		MUTCOLORS,
		EYECOLOR,
		LIPS,
		HAS_FLESH,
		HAS_BONE,
		HAIR,
	)
	inherent_traits = list(
		TRAIT_ADVANCEDTOOLUSER,
		TRAIT_CAN_STRIP,
	)
	inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE
	mutant_bodyparts = list()
	mutant_organs = list()
	default_mutant_bodyparts = list(
		"tail" = ACC_RANDOM,
		"snout" = ACC_RANDOM,
		"spines" = ACC_RANDOM,
		"frills" = ACC_RANDOM,
		"horns" = ACC_RANDOM,
		"wings" = "None",
	)
	examine_icon_state = "werelizard"


code:
/datum/species/moth
	name = "Lepidopterathrope"
	mutant_bodyparts = list()
	default_mutant_bodyparts = list(
		"wings" = ACC_RANDOM,
		"moth_antennae" = ACC_RANDOM,
		"moth_markings" = ACC_RANDOM,
	)
	inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG|MOB_BEAST
	limbs_icon = 'modular_septic/icons/mob/human/species/insect/moth_parts_greyscale.dmi'
	limbs_id = "moth"
	attack_verb = "punch"
	attack_effect = ATTACK_EFFECT_PUNCH
	examine_icon_state = "weremoth"


code:
/datum/species/werewolf
	name = "Lycanthrope"
	id = SPECIES_WEREWOLF
	default_color = "4B4B4B"
	species_traits = list(
		MUTCOLORS,
		EYECOLOR,
		LIPS,
		HAS_FLESH,
		HAS_BONE,
		HAIR,
	)
	inherent_traits = list(
		TRAIT_ADVANCEDTOOLUSER,
		TRAIT_CAN_STRIP,
	)
	inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BEAST
	mutant_bodyparts = list()
	default_mutant_bodyparts = list(
		"tail" = ACC_RANDOM,
		"snout" = ACC_RANDOM,
		"ears" = ACC_RANDOM,
		"horns" = "None",
		"wings" = "None",
	)
	liked_food = GROSS|MEAT|FRIED
	changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT
	limbs_icon = 'modular_septic/icons/mob/human/species/mammal/mammal_parts_greyscale.dmi'
	limbs_id = "mammal"
	examine_icon_state = "werewolf"
	default_genitals_male = list(ORGAN_SLOT_PENIS = /obj/item/organ/genital/penis/knotted,
								ORGAN_SLOT_TESTICLES = /obj/item/organ/genital/testicles)

/datum/species/werewolf/get_random_features()
	var/list/returned = MANDATORY_FEATURE_LIST
	var/main_color
	var/second_color
	var/random = rand(1,5)
	//Choose from a variety of mostly brightish, animal, matching colors
	switch(random)
		if(1)
			main_color = "FFAA00"
			second_color = "FFDD44"
		if(2)
			main_color = "FF8833"
			second_color = "FFAA33"
		if(3)
			main_color = "FFCC22"
			second_color = "FFDD88"
		if(4)
			main_color = "FF8800"
			second_color = "FFFFFF"
		if(5)
			main_color = "999999"
			second_color = "EEEEEE"
	returned["mcolor"] = main_color
	returned["mcolor2"] = second_color
	returned["mcolor3"] = second_color
	return returned

/datum/species/werewolf/get_random_body_markings(list/passed_features)
	var/name = pick("Wolf", "Fox", "Floof", "Floofer")
	var/datum/body_marking_set/BMS = GLOB.body_marking_sets[name]
	var/list/markings = list()
	if(BMS)
		markings = assemble_body_markings_from_set(BMS, passed_features, src)
	return markings

/datum/species/werewolf/random_name(gender,unique,lastname)
	var/randname
	if(gender == MALE)
		randname = pick(GLOB.first_names_male_werewolf)
	else
		randname = pick(GLOB.first_names_female_werewolf)

	if(lastname)
		randname += " [lastname]"
	else
		randname += " [pick(GLOB.last_names_werewolf)]"

	return randname


code:
/datum/species/zombie
	limbs_icon = 'modular_septic/icons/mob/human/species/undead/zombie_parts.dmi'
	limbs_id = "zombie"