code:
///////////////////
//DRONES AS ITEMS//
///////////////////
//Drone shells
//Drones as hats

//DRONE SHELL
/obj/item/drone_shell
	name = "drone shell"
	desc = "A shell of a maintenance drone, an expendable robot built to perform station repairs."
	icon = 'icons/mob/drone.dmi'
	icon_state = "drone_maint_hat"//yes reuse the _hat state.
	origin_tech = "programming=2;biotech=4"
	var/drone_type = /mob/living/simple_animal/drone //Type of drone that will be spawned

/obj/item/drone_shell/attack_ghost(mob/user)
	if(jobban_isbanned(user,"pAI"))
		return

	var/be_drone = alert("Become a drone? (Warning, You can no longer be cloned!)",,"Yes","No")
	if(be_drone == "No" || gc_destroyed)
		return
	var/mob/living/simple_animal/drone/D = new drone_type(get_turf(loc))
	D.key = user.key
	qdel(src)

//DRONE HOLDER
/obj/item/clothing/head/drone_holder//Only exists in someones hand.or on their head
	name = "drone (hiding)"
	desc = "This drone is scared and has curled up into a ball"
	icon = 'icons/mob/drone.dmi'
	icon_state = "drone_maint_hat"
	var/mob/living/simple_animal/drone/drone //stored drone

/obj/item/clothing/head/drone_holder/proc/uncurl()
	if(!drone)
		return

	if(istype(loc, /mob/living))
		var/mob/living/L = loc
		L.show_message("[drone] is trying to escape!")
		if(!do_after(L, 50) || loc != L)
			return
		L.unEquip(src)

	contents -= drone
	drone.loc = get_turf(src)
	drone.reset_view()
	drone.dir = SOUTH //Looks better
	drone.visible_message("[drone] uncurls!")
	drone = null
	qdel(src)

/obj/item/clothing/head/drone_holder/relaymove()
	uncurl()

/obj/item/clothing/head/drone_holder/container_resist()
	uncurl()

/obj/item/clothing/head/drone_holder/proc/updateVisualAppearence(var/mob/living/simple_animal/drone/D)
	if(!D)
		return
	icon_state = "[D.visualAppearence]_hat"
	. = icon_state


code:
////////////////////
//MORE DRONE TYPES//
////////////////////
//Drones with custom laws
//Drones with custom shells
//Drones with overriden procs

//More types of drones
/mob/living/simple_animal/drone/syndrone
	name = "Syndrone"
	desc = "A modified maintenance drone. This one brings with it the feeling of terror."
	icon_state = "drone_synd"
	icon_living = "drone_synd"
	picked = TRUE //the appearence of syndrones is static, you don't get to change it.
	health = 30
	maxHealth = 120 //If you murder other drones and cannibalize them you can get much stronger
	faction = list("syndicate")
	heavy_emp_damage = 10
	laws = \
	"1. Interfere.\n"+\
	"2. Kill.\n"+\
	"3. Destroy."
	default_storage = /obj/item/device/radio/uplink
	default_hatmask = /obj/item/clothing/head/helmet/space/hardsuit/syndi
	seeStatic = 0 //Our programming is superior.

/mob/living/simple_animal/drone/syndrone/New()
	..()
	if(internal_storage && internal_storage.hidden_uplink)
		internal_storage.hidden_uplink.uses = (initial(internal_storage.hidden_uplink.uses) / 2)
		internal_storage.name = "syndicate uplink"

/mob/living/simple_animal/drone/syndrone/Login()
	..()
	src << "You can kill and eat other drones to increase your health!" //Inform the evil lil guy

/obj/item/drone_shell/syndrone
	name = "syndrone shell"
	desc = "A shell of a syndrone, a modified maintenance drone designed to infiltrate and annihilate."
	icon_state = "syndrone_item"
	drone_type = /mob/living/simple_animal/drone/syndrone

license: mit


code:
/////////////////////
//DRONE INTERACTION//
/////////////////////
//How drones interact with the world
//How the world interacts with drones

/mob/living/simple_animal/drone/UnarmedAttack(atom/A, proximity)
	A.attack_hand(src)

/mob/living/simple_animal/drone/attack_hand(mob/user)
	if(isdrone(user))
		var/mob/living/simple_animal/drone/D = user
		if(D != src)
			if(stat == DEAD)
				var/d_input = alert(D,"Perform which action?","Drone Interaction","Reactivate","Cannibalize","Nothing")
				if(d_input)
					switch(d_input)
						if("Reactivate")
							var/mob/dead/observer/G = get_ghost()
							if(!client && (!G || !G.client))
								var/list/faux_gadgets = list("hypertext inflator","failsafe directory","DRM switch","stack initializer",\
															 "anti-freeze capacitor","data stream diode","TCP bottleneck","supercharged I/O bolt",\
															 "tradewind stablizer","radiated XML cable","registry fluid tank","open-source debunker")

								var/list/faux_problems = list("won't be able to tune their bootstrap projector","will constantly remix their binary pool"+\
															  " even though the BMX calibrator is working","will start leaking their XSS coolant",\
															  "can't tell if their ethernet detour is moving or not", "won't be able to reseed enough"+\
															  " kernels to function properly","can't start their neurotube console")

								D << "You can't seem to find the [pick(faux_gadgets)]. Without it, [src] [pick(faux_problems)]."
								return
							D.visible_message("[D] begins to reactivate [src].")
							if(do_after(user,30,needhand = 1))
								health = health_repair_max
								stat = CONSCIOUS
								icon_state = icon_living
								dead_mob_list -= src
								living_mob_list += src
								D.visible_message("[D] reactivates [src]!")
								alert_drones(DRONE_NET_CONNECT)
								if(G)
									G << "DRONE NETWORK: You were reactivated by [D]!"
							else
								D << "You need to remain still to reactivate [src]."

						if("Cannibalize")
							if(D.health < D.maxHealth)
								D.visible_message("[D] begins to cannibalize parts from [src].")
								if(do_after(D, 60,5,0))
									D.visible_message("[D] repairs itself using [src]'s remains!")
									D.adjustBruteLoss(-src.maxHealth)
									new /obj/effect/decal/cleanable/oil/streak(get_turf(src))
									qdel(src)
								else
									D << "You need to remain still to cannibalize [src]."
							else
								D << "You're already in perfect condition!"
						if("Nothing")
							return

			return

	if(ishuman(user))
		if(stat == DEAD)
			..()
			return
		if(user.get_active_hand())
			user << "Your hands are full."
			return
		src << "[user] is trying to pick you up!"
		if(buckled)
			user << "[src] is buckled to the [buckled.name] and cannot be picked up!"
			return
		user << "You pick [src] up."
		drop_l_hand()
		drop_r_hand()
		var/obj/item/clothing/head/drone_holder/DH = new /obj/item/clothing/head/drone_holder(src)
		DH.updateVisualAppearence(src)
		DH.contents += src
		DH.drone = src
		user.put_in_hands(DH)
		src.loc = DH
		return

	..()

/mob/living/simple_animal/drone/attackby(obj/item/I, mob/user)
	if(istype(I, /obj/item/weapon/screwdriver) && stat != DEAD)
		if(health < health_repair_max)
			user << "You start to tighten loose screws on [src]."
			if(do_after(user,80))
				health = health_repair_max
				visible_message("[user] tightens [src == user ? "their" : "[src]'s"] loose screws!")
			else
				user << "You need to remain still to tighten [src]'s screws."
		else
			user << "[src]'s screws can't get any tighter!"
	else
		..()


code:
///////////////////
//DRONE INVENTORY//
///////////////////
//Drone inventory
//Drone hands

/mob/living/simple_animal/drone/activate_hand(var/selhand)

	if(istext(selhand))
		selhand = lowertext(selhand)

		if(selhand == "right" || selhand == "r")
			selhand = 0
		if(selhand == "left" || selhand == "l")
			selhand = 1

	if(selhand != src.hand)
		swap_hand()
	else
		mode()

/mob/living/simple_animal/drone/swap_hand()
	var/obj/item/held_item = get_active_hand()
	if(held_item)
		if(istype(held_item, /obj/item/weapon/twohanded))
			var/obj/item/weapon/twohanded/T = held_item
			if(T.wielded == 1)
				usr << "Your other hand is too busy holding the [T.name]."
				return

	hand = !hand
	if(hud_used.l_hand_hud_object && hud_used.r_hand_hud_object)
		if(hand)
			hud_used.l_hand_hud_object.icon_state = "hand_l_active"
			hud_used.r_hand_hud_object.icon_state = "hand_r_inactive"
		else
			hud_used.l_hand_hud_object.icon_state = "hand_l_inactive"
			hud_used.r_hand_hud_object.icon_state = "hand_r_active"

/mob/living/simple_animal/drone/unEquip(obj/item/I, force)
	if(..(I,force))
		update_inv_hands()
		if(I == head)
			head = null
			update_inv_head()
		if(I == internal_storage)
			internal_storage = null
			update_inv_internal_storage()
		return 1
	return 0

/mob/living/simple_animal/drone/can_equip(obj/item/I, slot)
	switch(slot)
		if(slot_head)
			if(head)
				return 0
			if(!((I.slot_flags & SLOT_HEAD) || (I.slot_flags & SLOT_MASK)))
				return 0
			return 1
		if("drone_storage_slot")
			if(internal_storage)
				return 0
			return 1
	..()

/mob/living/simple_animal/drone/get_item_by_slot(slot_id)
	switch(slot_id)
		if(slot_head)
			return head
		if("drone_storage_slot")
			return internal_storage
	..()

/mob/living/simple_animal/drone/equip_to_slot(obj/item/I, slot)
	if(!slot)	return
	if(!istype(I))	return

	if(I == l_hand)
		l_hand = null
	else if(I == r_hand)
		r_hand = null
	update_inv_hands()

	I.screen_loc = null // will get moved if inventory is visible
	I.loc = src
	I.equipped(src, slot)
	I.layer = 20

	switch(slot)
		if(slot_head)
			head = I
			update_inv_head()
		if("drone_storage_slot")
			internal_storage = I
			update_inv_internal_storage()
		else
			src << "You are trying to equip this item to an unsupported inventory slot. Report this to a coder!"
			return

/mob/living/simple_animal/drone/stripPanelUnequip(obj/item/what, mob/who, where)
	..(what, who, where, 1)

/mob/living/simple_animal/drone/stripPanelEquip(obj/item/what, mob/who, where)
	..(what, who, where, 1)


code:
/////////////
//DRONE SAY//
/////////////
//Drone speach
//Drone hearing

/mob/living/simple_animal/drone/say(var/message)
	return ..(message, "R")

/mob/living/simple_animal/drone/lang_treat(atom/movable/speaker, message_langs, raw_message) //This is so drones can understand humans without being able to speak human
	. = ..()
	var/hear_override_langs = HUMAN
	if(message_langs & hear_override_langs)
		return ..(speaker, languages, raw_message)

/mob/living/simple_animal/drone/handle_inherent_channels(message, message_mode)
	if(message_mode == MODE_BINARY)
		drone_chat(message)
		return ITALICS | REDUCE_RANGE
	else
		..()

/mob/living/simple_animal/drone/proc/alert_drones(msg, dead_can_hear = 0)
	for(var/mob/M in player_list)
		var/send_msg = 0

		if(istype(M, /mob/living/simple_animal/drone) && M.stat != DEAD)
			for(var/F in src.faction)
				if(F in M.faction)
					send_msg = 1
					break
		else if(dead_can_hear && (M in dead_mob_list))
			send_msg = 1

		if(send_msg)
			M << msg

/mob/living/simple_animal/drone/proc/drone_chat(msg)
	var/rendered = "DRONE CHAT: [name]: [msg]"
	alert_drones(rendered, 1)


code:
///////////////
//DRONE VERBS//
///////////////
//Drone verbs that appear in the Drone tab and on buttons

/mob/living/simple_animal/drone/verb/check_laws()
	set category = "Drone"
	set name = "Check Laws"

	src << "Drone Laws"
	src << (uprising ? uprising_law : laws)

/mob/living/simple_animal/drone/verb/toggle_light()
	set category = "Drone"
	set name = "Toggle drone light"
	if(light_on)
		set_light(0)
	else
		set_light(4)

	light_on = !light_on

	src << "Your light is now [light_on ? "on" : "off"]"

/mob/living/simple_animal/drone/verb/drone_ping()
	set category = "Drone"
	set name = "Drone ping"

	var/alert_s = input(src,"Alert severity level","Drone ping",null) as null|anything in list("Low","Medium","High","Critical")

	var/area/A = get_area(loc)

	if(alert_s && A && stat != DEAD)
		var/msg = "DRONE PING: [name]: [alert_s] priority alert in [A.name]!"
		alert_drones(msg)

/mob/living/simple_animal/drone/verb/toggle_statics()
	set name = "Change Vision Filter"
	set desc = "Change the filter on the system used to remove non drone beings from your viewscreen."
	set category = "Drone"

	if(!seeStatic)
		src << "You have no vision filter to change!"
		return

	var/selectedStatic = input("Select a vision filter", "Vision Filter") as null|anything in staticChoices
	if(selectedStatic in staticChoices)
		staticChoice = selectedStatic

	updateSeeStaticMobs()


code:
/////////////////
//DRONE VISUALS//
/////////////////
//Drone overlays
//Drone visuals

/mob/living/simple_animal/drone/proc/apply_overlay(cache_index)
	var/image/I = drone_overlays[cache_index]
	if(I)
		overlays += I

/mob/living/simple_animal/drone/proc/remove_overlay(cache_index)
	if(drone_overlays[cache_index])
		overlays -= drone_overlays[cache_index]
		drone_overlays[cache_index] = null

/mob/living/simple_animal/drone/proc/update_inv_hands()
	remove_overlay(DRONE_HANDS_LAYER)
	var/list/hands_overlays = list()

	var/y_shift = getItemPixelShiftY()

	if(r_hand)
		var/r_state = r_hand.item_state
		if(!r_state)
			r_state = r_hand.icon_state

		var/image/r_hand_image = image("icon" = r_hand.righthand_file, "icon_state"="[r_state]", "layer"=-DRONE_HANDS_LAYER)
		if(y_shift != 0)
			r_hand_image.pixel_y = y_shift

		hands_overlays += r_hand_image

		if(client && hud_used)
			r_hand.layer = 20
			r_hand.screen_loc = ui_rhand
			client.screen |= r_hand

	if(l_hand)
		var/l_state = l_hand.item_state
		if(!l_state)
			l_state = l_hand.icon_state

		var/image/l_hand_image = image("icon" = l_hand.lefthand_file, "icon_state"="[l_state]", "layer"=-DRONE_HANDS_LAYER)
		if(y_shift != 0)
			l_hand_image.pixel_y = y_shift

		hands_overlays += l_hand_image

		if(client && hud_used)
			l_hand.layer = 20
			l_hand.screen_loc = ui_lhand
			client.screen |= l_hand

	if(hands_overlays.len)
		drone_overlays[DRONE_HANDS_LAYER] = hands_overlays
	apply_overlay(DRONE_HANDS_LAYER)

/mob/living/simple_animal/drone/proc/update_inv_internal_storage()
	if(internal_storage && client && hud_used)
		internal_storage.screen_loc = ui_drone_storage
		client.screen += internal_storage

/mob/living/simple_animal/drone/update_inv_head()
	remove_overlay(DRONE_HEAD_LAYER)

	if(head)
		if(client && hud_used)
			head.screen_loc = ui_drone_head
			client.screen += head

		var/image/head_overlay = image("icon"='icons/mob/head.dmi', "icon_state"="[head.icon_state]", "layer"=-DRONE_HEAD_LAYER)
		if(istype(head, /obj/item/clothing/mask))
			head_overlay.icon = 'icons/mob/mask.dmi'
		head_overlay.color = head.color
		head_overlay.alpha = head.alpha
		head_overlay.pixel_y = -15

		drone_overlays[DRONE_HEAD_LAYER]	= head_overlay

	apply_overlay(DRONE_HEAD_LAYER)

//These procs serve as redirection so that the drone updates as expected when other things call these procs
/mob/living/simple_animal/drone/update_inv_l_hand()
	update_inv_hands()

/mob/living/simple_animal/drone/update_inv_r_hand()
	update_inv_hands()

/mob/living/simple_animal/drone/update_inv_wear_mask()
	update_inv_head()

/mob/living/simple_animal/drone/proc/pickVisualAppearence()
	picked = FALSE
	var/appearence = input("Choose your appearence!", "Appearence", "Maintenance Drone") in list("Maintenance Drone", "Repair Drone")
	switch(appearence)
		if("Maintenance Drone")
			visualAppearence = MAINTDRONE
			var/colour = input("Choose your colour!", "Colour", "grey") in list("grey", "blue", "red", "green", "pink", "orange")
			icon_state = "[visualAppearence]_[colour]"
			icon_living = "[visualAppearence]_[colour]"
			icon_dead = "[visualAppearence]_dead"

		if("Repair Drone")
			visualAppearence = REPAIRDRONE
			icon_state = visualAppearence
			icon_living = visualAppearence
			icon_dead = "[visualAppearence]_dead"

		else
			return

	picked = TRUE

/mob/living/simple_animal/drone/proc/getItemPixelShiftY()
	switch(visualAppearence)
		if(MAINTDRONE)
			. = 0
		if(REPAIRDRONE)
			. = -6

/mob/living/simple_animal/drone/proc/updateSeeStaticMobs()
	if(!client)
		return

	for(var/i in staticOverlays)
		client.images.Remove(i)
		staticOverlays.Remove(i)
	staticOverlays.len = 0

	if(seeStatic)
		for(var/mob/living/L in mob_list)
			if(isdrone(L))
				continue
			var/image/chosen
			if(staticChoice in L.staticOverlays)
				chosen = L.staticOverlays[staticChoice]
			else
				chosen = L.staticOverlays["static"]
			staticOverlays |= chosen
			client.images |= chosen

/mob/living/simple_animal/drone/generateStaticOverlay()
	return


code:
//goat
/mob/living/simple_animal/hostile/retaliate/goat
	name = "goat"
	desc = "Not known for their pleasant disposition."
	icon_state = "goat"
	icon_living = "goat"
	icon_dead = "goat_dead"
	speak = list("EHEHEHEHEH","eh?")
	speak_emote = list("brays")
	emote_hear = list("brays")
	emote_see = list("shakes its head", "stamps a foot", "glares around")
	speak_chance = 1
	turns_per_move = 5
	see_in_dark = 6
	meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/slab
	meat_amount = 4
	response_help  = "pets"
	response_disarm = "gently pushes aside"
	response_harm   = "kicks"
	faction = list("neutral")
	attack_same = 1
	attacktext = "kicks"
	attack_sound = 'sound/weapons/punch1.ogg'
	health = 40
	melee_damage_lower = 1
	melee_damage_upper = 2
	environment_smash = 0
	var/datum/reagents/udder = null

/mob/living/simple_animal/hostile/retaliate/goat/New()
	udder = new(50)
	udder.my_atom = src
	..()

/mob/living/simple_animal/hostile/retaliate/goat/Life()
	. = ..()
	if(.)
		//chance to go crazy and start wacking stuff
		if(!enemies.len && prob(1))
			Retaliate()

		if(enemies.len && prob(10))
			enemies = list()
			LoseTarget()
			src.visible_message("[src] calms down.")

		if(stat == CONSCIOUS)
			if(udder && prob(5))
				udder.add_reagent("milk", rand(5, 10))

		if(locate(/obj/effect/spacevine) in loc)
			var/obj/effect/spacevine/SV = locate(/obj/effect/spacevine) in loc
			SV.eat(src)

		if(!pulledby)
			for(var/direction in shuffle(list(1,2,4,8,5,6,9,10)))
				var/step = get_step(src, direction)
				if(step)
					if(locate(/obj/effect/spacevine) in step)
						Move(step, get_dir(src, step))

/mob/living/simple_animal/hostile/retaliate/goat/Retaliate()
	..()
	src.visible_message("[src] gets an evil-looking gleam in \his eye.")

/mob/living/simple_animal/hostile/retaliate/goat/Move()
	..()
	if(!stat)
		if(locate(/obj/effect/spacevine) in loc)
			var/obj/effect/spacevine/SV = locate(/obj/effect/spacevine) in loc
			SV.eat(src)

/mob/living/simple_animal/hostile/retaliate/goat/attackby(var/obj/item/O as obj, var/mob/user as mob, params)
	if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass))
		user.visible_message("[user] milks [src] using \the [O].")
		var/obj/item/weapon/reagent_containers/glass/G = O
		var/transfered = udder.trans_id_to(G, "milk", rand(5,10))
		if(G.reagents.total_volume >= G.volume)
			user << "[O] is full."
		if(!transfered)
			user << "The udder is dry. Wait a bit longer..."
	else
		..()
//cow
/mob/living/simple_animal/cow
	name = "cow"
	desc = "Known for their milk, just don't tip them over."
	icon_state = "cow"
	icon_living = "cow"
	icon_dead = "cow_dead"
	icon_gib = "cow_gib"
	speak = list("moo?","moo","MOOOOOO")
	speak_emote = list("moos","moos hauntingly")
	emote_hear = list("brays")
	emote_see = list("shakes its head")
	speak_chance = 1
	turns_per_move = 5
	see_in_dark = 6
	meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/slab
	meat_amount = 6
	response_help  = "pets"
	response_disarm = "gently pushes aside"
	response_harm   = "kicks"
	attacktext = "kicks"
	health = 50
	var/datum/reagents/udder = null

/mob/living/simple_animal/cow/New()
	udder = new(50)
	udder.my_atom = src
	..()

/mob/living/simple_animal/cow/attackby(var/obj/item/O as obj, var/mob/user as mob, params)
	if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass))
		user.visible_message("[user] milks [src] using \the [O].")
		var/obj/item/weapon/reagent_containers/glass/G = O
		var/transfered = udder.trans_id_to(G, "milk", rand(5,10))
		if(G.reagents.total_volume >= G.volume)
			user << "[O] is full."
		if(!transfered)
			user << "The udder is dry. Wait a bit longer..."
	else
		..()

/mob/living/simple_animal/cow/Life()
	. = ..()
	if(stat == CONSCIOUS)
		if(udder && prob(5))
			udder.add_reagent("milk", rand(5, 10))

/mob/living/simple_animal/cow/attack_hand(mob/living/carbon/M as mob)
	if(!stat && M.a_intent == "disarm" && icon_state != icon_dead)
		M.visible_message("[M] tips over [src].","You tip over [src].")
		Weaken(30)
		icon_state = icon_dead
		spawn(rand(20,50))
			if(!stat && M)
				icon_state = icon_living
				var/list/responses = list(	"[src] looks at you imploringly.",
											"[src] looks at you pleadingly",
											"[src] looks at you with a resigned expression.",
											"[src] seems resigned to its fate.")
				M << pick(responses)
	else
		..()

/mob/living/simple_animal/chick
	name = "\improper chick"
	desc = "Adorable! They make such a racket though."
	icon_state = "chick"
	icon_living = "chick"
	icon_dead = "chick_dead"
	icon_gib = "chick_gib"
	speak = list("Cherp.","Cherp?","Chirrup.","Cheep!")
	speak_emote = list("cheeps")
	emote_hear = list("cheeps")
	emote_see = list("pecks at the ground","flaps its tiny wings")
	speak_chance = 2
	turns_per_move = 2
	meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/slab
	meat_amount = 1
	response_help  = "pets"
	response_disarm = "gently pushes aside"
	response_harm   = "kicks"
	attacktext = "kicks"
	health = 1
	ventcrawler = 2
	var/amount_grown = 0
	pass_flags = PASSTABLE | PASSGRILLE
	mob_size = MOB_SIZE_SMALL

/mob/living/simple_animal/chick/New()
	..()
	pixel_x = rand(-6, 6)
	pixel_y = rand(0, 10)

/mob/living/simple_animal/chick/Life()
	. =..()
	if(!.)
		return
	if(!stat && !ckey)
		amount_grown += rand(1,2)
		if(amount_grown >= 100)
			new /mob/living/simple_animal/chicken(src.loc)
			qdel(src)

var/const/MAX_CHICKENS = 50
var/global/chicken_count = 0

/mob/living/simple_animal/chicken
	name = "\improper chicken"
	desc = "Hopefully the eggs are good this season."
	icon_state = "chicken"
	icon_living = "chicken"
	icon_dead = "chicken_dead"
	speak = list("Cluck!","BWAAAAARK BWAK BWAK BWAK!","Bwaak bwak.")
	speak_emote = list("clucks","croons")
	emote_hear = list("clucks")
	emote_see = list("pecks at the ground","flaps its wings viciously")
	speak_chance = 2
	turns_per_move = 3
	meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/slab
	meat_amount = 2
	response_help  = "pets"
	response_disarm = "gently pushes aside"
	response_harm   = "kicks"
	attacktext = "kicks"
	health = 10
	ventcrawler = 2
	var/eggsleft = 0
	var/body_color
	pass_flags = PASSTABLE

/mob/living/simple_animal/chicken/New()
	..()
	if(!body_color)
		body_color = pick( list("brown","black","white") )
	icon_state = "chicken_[body_color]"
	icon_living = "chicken_[body_color]"
	icon_dead = "chicken_[body_color]_dead"
	pixel_x = rand(-6, 6)
	pixel_y = rand(0, 10)
	chicken_count += 1

/mob/living/simple_animal/chicken/Die()
	..()
	chicken_count -= 1

/mob/living/simple_animal/chicken/attackby(var/obj/item/O as obj, var/mob/user as mob, params)
	if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown/wheat)) //feedin' dem chickens
		if(!stat && eggsleft < 8)
			user.visible_message("[user] feeds [O] to [name]! It clucks happily.","You feed [O] to [name]! It clucks happily.")
			user.drop_item()
			qdel(O)
			eggsleft += rand(1, 4)
			//world << eggsleft
		else
			user << "[name] doesn't seem hungry!"
	else
		..()

/mob/living/simple_animal/chicken/Life()
	. =..()
	if(!.)
		return
	if(!stat && prob(3) && eggsleft > 0)
		visible_message("[src] [pick("lays an egg.","squats down and croons.","begins making a huge racket.","begins clucking raucously.")]")
		eggsleft--
		var/obj/item/weapon/reagent_containers/food/snacks/egg/E = new(get_turf(src))
		E.pixel_x = rand(-6,6)
		E.pixel_y = rand(-6,6)
		if(chicken_count < MAX_CHICKENS && prob(25))
			SSobj.processing |= E

/obj/item/weapon/reagent_containers/food/snacks/egg/var/amount_grown = 0
/obj/item/weapon/reagent_containers/food/snacks/egg/process()
	if(isturf(loc))
		amount_grown += rand(1,2)
		if(amount_grown >= 100)
			visible_message("[src] hatches with a quiet cracking sound.")
			new /mob/living/simple_animal/chick(get_turf(src))
			SSobj.processing.Remove(src)
			qdel(src)
	else
		SSobj.processing.Remove(src)


code:
//Foxxy
/mob/living/simple_animal/fox
	name = "fox"
	desc = "It's a fox. I wonder what it says?"
	icon_state = "fox"
	icon_living = "fox"
	icon_dead = "fox_dead"
	speak = list("Ack-Ack","Ack-Ack-Ack-Ackawoooo","Geckers","Awoo","Tchoff")
	speak_emote = list("geckers", "barks")
	emote_hear = list("howls","barks")
	emote_see = list("shakes its head", "shivers")
	speak_chance = 1
	turns_per_move = 5
	see_in_dark = 6
	meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/slab
	response_help = "pets"
	response_disarm = "gently pushes aside"
	response_harm = "kicks"

//Captain fox
/mob/living/simple_animal/fox/Renault
	name = "Renault"
	desc = "Renault, the Captain's trustworthy fox. I wonder what it says?"


code:
/mob/living/simple_animal/lizard
	name = "Lizard"
	desc = "A cute tiny lizard."
	icon_state = "lizard"
	icon_living = "lizard"
	icon_dead = "lizard_dead"
	speak_emote = list("hisses")
	health = 5
	maxHealth = 5
	attacktext = "bites"
	attacktext = "bites"
	melee_damage_lower = 1
	melee_damage_upper = 2
	response_help  = "pets"
	response_disarm = "shoos"
	response_harm   = "stomps on"
	ventcrawler = 2
	mob_size = MOB_SIZE_SMALL


code:
/mob/living/simple_animal/mouse
	name = "mouse"
	desc = "It's a nasty, ugly, evil, disease-ridden rodent."
	icon_state = "mouse_gray"
	icon_living = "mouse_gray"
	icon_dead = "mouse_gray_dead"
	speak = list("Squeek!","SQUEEK!","Squeek?")
	speak_emote = list("squeeks")
	emote_hear = list("squeeks")
	emote_see = list("runs in a circle", "shakes")
	speak_chance = 1
	turns_per_move = 5
	see_in_dark = 6
	maxHealth = 5
	health = 5
	meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/slab
	meat_amount = 1
	response_help  = "pets"
	response_disarm = "gently pushes aside"
	response_harm   = "splats"
	density = 0
	ventcrawler = 2
	pass_flags = PASSTABLE | PASSGRILLE
	mob_size = MOB_SIZE_SMALL
	var/body_color //brown, gray and white, leave blank for random

/mob/living/simple_animal/mouse/New()
	..()
	if(!body_color)
		body_color = pick( list("brown","gray","white") )
	icon_state = "mouse_[body_color]"
	icon_living = "mouse_[body_color]"
	icon_dead = "mouse_[body_color]_dead"

/mob/living/simple_animal/mouse/proc/splat()
	src.health = 0
	src.icon_dead = "mouse_[body_color]_splat"
	Die()

/mob/living/simple_animal/mouse/Die()
	..()
	if(!ckey)
		var/obj/item/trash/deadmouse/M = new(src.loc)
		M.icon_state = src.icon_dead
		qdel(src)

/mob/living/simple_animal/mouse/Crossed(AM as mob|obj)
	if( ishuman(AM) )
		if(!stat)
			var/mob/M = AM
			M << "\icon[src] Squeek!"
			playsound(src, 'sound/effects/mousesqueek.ogg', 100, 1)
	..()

/*
 * Mouse types
 */

/mob/living/simple_animal/mouse/white
	body_color = "white"
	icon_state = "mouse_white"

/mob/living/simple_animal/mouse/gray
	body_color = "gray"
	icon_state = "mouse_gray"

/mob/living/simple_animal/mouse/brown
	body_color = "brown"
	icon_state = "mouse_brown"

//TOM IS ALIVE! SQUEEEEEEEE~K :)
/mob/living/simple_animal/mouse/brown/Tom
	name = "Tom"
	desc = "Jerry the cat is not amused."
	response_help  = "pets"
	response_disarm = "gently pushes aside"
	response_harm   = "splats"

/obj/item/trash/deadmouse
	name = "dead mouse"
	desc = "It looks like somebody dropped the bass on it."
	icon = 'icons/mob/animal.dmi'
	icon_state = "mouse_gray_dead"


code:
//Corgi //best comment 2014
/mob/living/simple_animal/pug
	name = "\improper pug"
	real_name = "pug"
	desc = "It's a pug."
	icon_state = "pug"
	icon_living = "pug"
	icon_dead = "pug_dead"
	speak = list("YAP", "Woof!", "Bark!", "AUUUUUU")
	speak_emote = list("barks", "woofs")
	emote_hear = list("barks!", "woofs!", "yaps.","pants.")
	emote_see = list("shakes its head.", "chases its tail.","shivers.")
	speak_chance = 1
	turns_per_move = 10
	meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/pug
	meat_amount = 3
	response_help  = "pets"
	response_disarm = "bops"
	response_harm   = "kicks"
	see_in_dark = 5

/mob/living/simple_animal/pug/Life()
	..()

	if(!stat && !resting && !buckled)
		if(prob(1))
			emote("me", 1, pick("chases its tail."))
			spawn(0)
				for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
					dir = i
					sleep(1)

/mob/living/simple_animal/pug/attackby(var/obj/item/O as obj, var/mob/user as mob, params)  //Marker -Agouri
	if(istype(O, /obj/item/weapon/newspaper))
		if(!stat)
			user.visible_message("[user] baps [name] on the nose with the rolled up [O]")
			spawn(0)
				for(var/i in list(1,2,4,8,4,2,1,2))
					dir = i
					sleep(1)
	else
		..()


code:
/mob/living/simple_animal/slime
	name = "pet slime"
	desc = "A lovable, domesticated slime."
	icon = 'icons/mob/slimes.dmi'
	icon_state = "grey baby slime"
	icon_living = "grey baby slime"
	icon_dead = "grey baby slime dead"
	speak_emote = list("chirps")
	health = 100
	maxHealth = 100
	response_help  = "pets"
	response_disarm = "shoos"
	response_harm   = "stomps on"
	emote_see = list("jiggles", "bounces in place")
	ventcrawler = 2
	var/colour = "grey"

/mob/living/simple_animal/slime/adult
	health = 200
	maxHealth = 200
	icon_state = "grey adult slime"
	icon_living = "grey adult slime"

/mob/living/simple_animal/slime/adult/New()
	..()
	overlays += "aslime-:33"

/mob/living/simple_animal/slime/adult/Die()
	for(var/i = 0, i<=1, i++)
		var/mob/living/simple_animal/slime/S1 = new /mob/living/simple_animal/slime (src.loc)
		S1.icon_state = "[colour] baby slime"
		S1.icon_living = "[colour] baby slime"
		S1.icon_dead = "[colour] baby slime dead"
		S1.colour = "[colour]"
	qdel(src)


code:
/mob/living/simple_animal/hostile/alien
	name = "alien hunter"
	desc = "Hiss!"
	icon = 'icons/mob/alien.dmi'
	icon_state = "alienh_running"
	icon_living = "alienh_running"
	icon_dead = "alienh_dead"
	icon_gib = "syndicate_gib"
	response_help = "pokes"
	response_disarm = "shoves"
	response_harm = "hits"
	speed = 0
	meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno
	skin_type = /obj/item/stack/sheet/animalhide/xeno
	meat_amount = 3
	maxHealth = 100
	health = 100
	harm_intent_damage = 5
	melee_damage_lower = 25
	melee_damage_upper = 25
	attacktext = "slashes"
	a_intent = "harm"
	attack_sound = 'sound/weapons/bladeslice.ogg'
	min_oxy = 0
	max_oxy = 0
	min_tox = 0
	max_tox = 0
	min_co2 = 0
	max_co2 = 0
	min_n2 = 0
	max_n2 = 0
	unsuitable_atmos_damage = 15
	faction = list("alien")
	status_flags = CANPUSH
	minbodytemp = 0
	heat_damage_per_tick = 20

/mob/living/simple_animal/hostile/alien/drone
	name = "alien drone"
	icon_state = "aliend_running"
	icon_living = "aliend_running"
	icon_dead = "aliend_dead"
	health = 60
	melee_damage_lower = 15
	melee_damage_upper = 15
	var/plant_cooldown = 30
	var/plants_off = 0

/mob/living/simple_animal/hostile/alien/drone/Life()
	..()
	if(!stat)
		plant_cooldown--
		if(stance==HOSTILE_STANCE_IDLE)
			if(!plants_off && prob(10) && plant_cooldown<=0)
				plant_cooldown = initial(plant_cooldown)
				SpreadPlants()

/mob/living/simple_animal/hostile/alien/sentinel
	name = "alien sentinel"
	icon_state = "aliens_running"
	icon_living = "aliens_running"
	icon_dead = "aliens_dead"
	health = 120
	melee_damage_lower = 15
	melee_damage_upper = 15
	ranged = 1
	retreat_distance = 5
	minimum_distance = 5
	projectiletype = /obj/item/projectile/neurotox
	projectilesound = 'sound/weapons/pierce.ogg'

/mob/living/simple_animal/hostile/alien/queen
	name = "alien queen"
	icon_state = "alienq_running"
	icon_living = "alienq_running"
	icon_dead = "alienq_dead"
	health = 250
	maxHealth = 250
	melee_damage_lower = 15
	melee_damage_upper = 15
	ranged = 1
	retreat_distance = 5
	minimum_distance = 5
	move_to_delay = 4
	projectiletype = /obj/item/projectile/neurotox
	projectilesound = 'sound/weapons/pierce.ogg'
	status_flags = 0
	var/sterile = 1
	var/plants_off = 0
	var/egg_cooldown = 30
	var/plant_cooldown = 30

/mob/living/simple_animal/hostile/alien/queen/Life()
	..()
	if(!stat)
		egg_cooldown--
		plant_cooldown--
		if(stance==HOSTILE_STANCE_IDLE)
			if(!plants_off && prob(10) && plant_cooldown<=0)
				plant_cooldown = initial(plant_cooldown)
				SpreadPlants()
			if(!sterile && prob(10) && egg_cooldown<=0)
				egg_cooldown = initial(egg_cooldown)
				LayEggs()

/mob/living/simple_animal/hostile/alien/proc/SpreadPlants()
	if(!isturf(loc) || istype(loc, /turf/space))
		return
	if(locate(/obj/structure/alien/weeds/node) in get_turf(src))
		return
	visible_message("[src] has planted some alien weeds!")
	new /obj/structure/alien/weeds/node(loc)

/mob/living/simple_animal/hostile/alien/proc/LayEggs()
	if(!isturf(loc) || istype(loc, /turf/space))
		return
	if(locate(/obj/structure/alien/egg) in get_turf(src))
		return
	visible_message("[src] has laid an egg!")
	new /obj/structure/alien/egg(loc)

/mob/living/simple_animal/hostile/alien/queen/large
	name = "alien empress"
	icon = 'icons/mob/alienqueen.dmi'
	icon_state = "queen_s"
	icon_living = "queen_s"
	icon_dead = "queen_dead"
	move_to_delay = 4
	maxHealth = 400
	health = 400
	mob_size = MOB_SIZE_LARGE

/obj/item/projectile/neurotox
	name = "neurotoxin"
	damage = 30
	icon_state = "toxin"

/mob/living/simple_animal/hostile/alien/Die()
	..()
	visible_message("[src] lets out a waning guttural screech, green blood bubbling from its maw...")
	playsound(src, 'sound/voice/hiss6.ogg', 100, 1)


code:
//Space bears!
/mob/living/simple_animal/hostile/bear
	name = "space bear"
	desc = "You don't need to be faster than a space bear, you just need to outrun your crewmates."
	icon_state = "bear"
	icon_living = "bear"
	icon_dead = "bear_dead"
	icon_gib = "bear_gib"
	speak = list("RAWR!","Rawr!","GRR!","Growl!")
	speak_emote = list("growls", "roars")
	emote_hear = list("rawrs","grumbles","grawls")
	emote_see = list("stares ferociously", "stomps")
	speak_chance = 1
	turns_per_move = 5
	see_in_dark = 6
	meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/bear
	meat_amount = 3
	response_help  = "pets"
	response_disarm = "gently pushes aside"
	response_harm   = "hits"
	stop_automated_movement_when_pulled = 0
	maxHealth = 60
	health = 60

	melee_damage_lower = 20
	melee_damage_upper = 30
	attacktext = "claws"
	friendly = "bear hugs"

	//Space bears aren't affected by cold.
	min_oxy = 0
	max_oxy = 0
	min_tox = 0
	max_tox = 0
	min_co2 = 0
	max_co2 = 0
	min_n2 = 0
	max_n2 = 0
	minbodytemp = 0
	maxbodytemp = 1500

	faction = list("russian")

//SPACE BEARS! SQUEEEEEEEE~     OW! FUCK! IT BIT MY HAND OFF!!
/mob/living/simple_animal/hostile/bear/Hudson
	name = "Hudson"
	desc = "Feared outlaw, this guy is one bad news bear." //I'm sorry...

/mob/living/simple_animal/hostile/bear/Move()
	..()
	if(stat != DEAD)
		if(loc && istype(loc,/turf/space))
			icon_state = "bear"
		else
			icon_state = "bearfloor"

/mob/living/simple_animal/hostile/bear/Process_Spacemove(var/movement_dir = 0)
	return 1	//No drifting in space for space bears!

/mob/living/simple_animal/hostile/bear/FindTarget()
	. = ..()
	if(.)
		emote("me", 1, "stares alertly at [.]")
		stance = HOSTILE_STANCE_ATTACK

/mob/living/simple_animal/hostile/bear/LoseTarget()
	..(5)


code:
/mob/living/simple_animal/hostile/poison/bees
	name = "space bee swarm"
	desc = ""
	icon_state = "bee_1"
	icon_living = "bee"
	icon_dead = ""
	speak_emote = list("buzzes")
	emote_hear = list("buzzes")
	turns_per_move = 0
	melee_damage_lower = 1
	melee_damage_upper = 1
	attacktext = "stings"
	response_help  = "shoos"
	response_disarm = "swats away"
	response_harm   = "squashes"
	stop_automated_movement_when_pulled = 0
	maxHealth = 10
	health = 10
	faction = list("hostile")
	move_to_delay = 0
	environment_smash = 0
	mouse_opacity = 2
	pass_flags = PASSTABLE

	//Spaceborn beings don't get hurt by space
	min_oxy = 0
	max_oxy = 0
	min_tox = 0
	max_tox = 0
	min_co2 = 0
	max_co2 = 0
	min_n2 = 0
	max_n2 = 0
	minbodytemp = 0

/mob/living/simple_animal/hostile/poison/bees/Process_Spacemove(var/movement_dir = 0)
	return 1

/mob/living/simple_animal/hostile/poison/bees/New()
	..()
	update_bees()

/mob/living/simple_animal/hostile/poison/bees/Die()
	..()
	qdel(src)
	return

/mob/living/simple_animal/hostile/poison/bees/Life()
	..()
	update_bees()

/mob/living/simple_animal/hostile/poison/bees/proc/update_bees()
	while(overlays.len != health-1) //how many bees do we have in the swarm?
		var/N = rand(1, 4)
		var/image/I = image(icon='icons/mob/animal.dmi',icon_state="bee_[N]", pixel_x = rand(-8, 8), pixel_y = rand(-8, 8))
		if(overlays.len < health-1)
			overlays.Add(I)
		if(overlays.len > health-1)
			overlays.Remove(I)
	poison_per_bite = health * 0.5 //each bee is half a toxin reagent
	if(health > 1)
		desc = "A buzzy swarm of [health] poisonous space bees, renowned for their aggressiveness"
	else
		desc = "Although now lonely, this single space bee is still poisonous and very angry at you."


code:
/mob/living/captive_brain
	name = "host brain"

/mob/living/captive_brain/say(var/message)

	if (src.client)
		if(client.prefs.muted & MUTE_IC)
			src << "You cannot speak in IC (muted)."
			return
		if (src.client.handle_spam_prevention(message,MUTE_IC))
			return

	if(istype(src.loc,/mob/living/simple_animal/borer))
		var/mob/living/simple_animal/borer/B = src.loc
		src << "You whisper silently, \"[message]\""
		B.host << "The captive mind of [src] whispers, \"[message]\""

		var/turf/T = get_turf(src)
		log_say("[key_name(src)] (@[T.x],[T.y],[T.z]) -> [key_name(B)] Host->Borer Speech: [message]")

		for(var/mob/M in player_list)
			if(istype(M, /mob/new_player))
				continue
			if(istype(M,/mob/dead/observer)  && (M.client && M.client.prefs.toggles & CHAT_GHOSTEARS))
				var/controls = "Follow"
			//	if(M.client.holder)
			//		controls+= " | ?"
				var/rendered="Thought-speech, [src.name] ([controls]) -> [B.truename]: [message]"
			//	M.show_message(rendered, 2) //Takes into account blindness and such.
				M << rendered //What the fuck oldcoders

/mob/living/captive_brain/emote(var/message)
	return

var/global/list/borer_attached_verbs = list(
	/mob/living/simple_animal/borer/proc/bond_brain,
//	/mob/living/simple_animal/borer/proc/borer_speak,
	/mob/living/simple_animal/borer/proc/kill_host,
	/mob/living/simple_animal/borer/proc/damage_brain,
	/mob/living/simple_animal/borer/proc/secrete_chemicals,
	/mob/living/simple_animal/borer/proc/abandon_host,
)
var/global/list/borer_detached_verbs = list(
	/mob/living/simple_animal/borer/proc/infest,
	/mob/living/simple_animal/borer/proc/hide,
)

/datum/borer_chem
	var/name = ""
	var/cost = 1 // Per unit delivered.
	var/dose_size = 15

/datum/borer_chem/tricordrazine
	name = "tricordrazine"
	cost = 3

///datum/borer_chem/salglu
//	name = "saline_glucose_solution"

///datum/borer_chem/tramadol
//	name = "tramadol"

/datum/borer_chem/alkysine
	name = "alkysine"
	cost = 0

///datum/borer_chem/hotline
//	name = "hotline"
//	cost = 2
//	dose_size = 5

/datum/borer_chem/hyperzine
	name = "hyperzine"

var/global/borer_chem_types = typesof(/datum/borer_chem) - /datum/borer_chem

/mob/living/simple_animal/borer
	name = "cortical borer"
	real_name = "cortical borer"
	desc = "A small, quivering sluglike creature."
	speak_emote = list("chirrups")
	emote_hear = list("chirrups")
	response_help  = "pokes the"
	response_disarm = "prods the"
	response_harm   = "stomps on the"
	icon_state = "brainslug"
	icon_living = "brainslug"
	icon_dead = "brainslug_dead"
	speed = 5
	density = 0
	stop_automated_movement = 1
	status_flags = CANPUSH
	attacktext = "nips"
	friendly = "prods"
	ventcrawler = 2
	wander = 0
	pass_flags = PASSTABLE

	var/chemicals = 10                      // Chemicals used for reproduction and spitting neurotoxin.
	var/mob/living/carbon/human/host        // Human host for the brain worm.
	var/truename                            // Name used for brainworm-speak.
	var/mob/living/captive_brain/host_brain // Used for swapping control of the body back and forth.
	var/controlling                         // Used in human death check.
	var/list/avail_chems=list()
	var/numChildren=0

/mob/living/simple_animal/borer/New(var/loc,var/by_gamemode=0)
	..(loc)
	languages |= HUMAN
	truename = "[pick("Primary","Secondary","Tertiary","Quaternary")] [rand(1000,9999)]"
	host_brain = new/mob/living/captive_brain(src)

	if(name == initial(name)) // Easier reporting of griff.
		name = "[name] ([rand(1, 1000)])"
		real_name = name

	// Admin spawn.  Request a player.
/*	if(!by_gamemode)
		var/mob/dead/observer/O = request_player()
		if(!O)
			message_admins("[src.name] self-deleting due to lack of appropriate ghosts.")
			del(src)
		transfer_personality(O.client) */
	update_verbs(0)

	for(var/chemtype in borer_chem_types)
		var/datum/borer_chem/C = new chemtype()
		avail_chems[C.name]=C
		//testing("Added [C.name] to borer.")

/mob/living/simple_animal/borer/Life()
	..()
	if(host)
		if(!stat && !host.stat)
			if(chemicals < 250)
				chemicals++
			if(controlling)
				if(prob(5))
					host.adjustBrainLoss(rand(1,2))

				if(prob(host.brainloss/20))
					host.say("*[pick(list("blink","blink_r","choke","aflap","drool","twitch","twitch_s","gasp"))]")

/mob/living/simple_animal/borer/proc/update_verbs(var/attached)
	if(attached)
		verbs += borer_attached_verbs
		verbs -= borer_detached_verbs
	else
		verbs -= borer_attached_verbs
		verbs += borer_detached_verbs
/*
/mob/living/simple_animal/borer/player_panel_controls(var/mob/user)
	var/html="
[src] Controls
"
	if(host)
		html +="Host: [host] (? | PP)"
	else
		html += "No host"
	html += "
"
	if(user.check_rights(R_ADMIN))
		html += "
Give Chem
" // PARTY SLUG
		html += "
Detach
"
		html += "
Resend Verbs
"
		if(host)
			html += "
Release Control
"
	return html + "
"
*/
/mob/living/simple_animal/borer/Topic(href, href_list)
//	if(!usr.check_rights(R_ADMIN))
//		usr << "Hell no."
//		return

	switch(href_list["act"])
		if("detach")
			src << "You feel dazed, and then appear outside of your host!"
			if(host)
				host << "You no longer feel the presence in your mind!"
			detach()
		if("release")
			if(host)
				host.do_release_control()
		if("verbs")
			update_verbs(!isnull(host))
		if("add_chem")
			var/chemID = input("Chem name (ex: krokodil):","Chemicals") as text|null
			if(isnull(chemID))
				return
			var/datum/borer_chem/C = new /datum/borer_chem()
			C.name=chemID
			C.cost=0
			avail_chems[C.name]=C
			usr << "ADDED!"
			src << "You learned how to secrete [C.name]!"

/mob/living/simple_animal/borer/say(var/message)

	message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
	message = capitalize(message)

	if(!message)
		return

	if (stat == 2)
		return say_dead(message)

	if (stat)
		return

	if (src.client)
		if(client.prefs.muted & MUTE_IC)
			src << "You cannot speak in IC (muted)."
			return
		if (src.client.handle_spam_prevention(message,MUTE_IC))
			return

	if (copytext(message, 1, 2) == "*")
		return emote(copytext(message, 2))

	if (copytext(message, 1, 2) == ";") //Brain borer hivemind.
		return borer_speak(message)

	if(!host)
		src << "You have no host to speak to."
		return //No host, no audible speech.

	src << "You drop words into [host]'s mind: \"[message]\""
	host << "Your own thoughts speak: \"[message]\""
	var/turf/T = get_turf(src)
	log_say("[truename] [key_name(src)] (@[T.x],[T.y],[T.z]) -> [host]([key_name(host)]) Borer->Host Speech: [message]")

	for(var/mob/M in player_list)
		if(istype(M, /mob/new_player))
			continue
		if(istype(M,/mob/dead/observer)  && (M.client && M.client.prefs.toggles & CHAT_GHOSTEARS))
			var/controls = "Follow"
	//		if(M.client.holder)
	//			controls+= " | ?"
			var/rendered="Thought-speech, [truename] ([controls]) -> [host]: [message]"
		//	M.show_message(rendered, 2) //Takes into account blindness and such.
			M << rendered

	/*
	for(var/mob/M in mob_list)
		if(M.mind && (istype(M, /mob/dead/observer)))
			M << "Thought-speech, [truename] -> [host]: [copytext(message, 2)]"
	*/

/mob/living/simple_animal/borer/Stat()
	..()

	stat("Chemicals", chemicals)

// VERBS!

/mob/living/simple_animal/borer/proc/borer_speak(var/message)
	if(!message)
		return

	message = copytext(message,2)

	var/turf/T = get_turf(src)
	log_say("[truename] [key_name(src)] (@[T.x],[T.y],[T.z]) Borer Cortical Hivemind: [message]")

	for(var/mob/M in mob_list)
		if(istype(M, /mob/new_player))
			continue

		var/bored = M.has_brain_worms()

		if(bored || isborer(M) || (istype(M,/mob/dead/observer) && M.client && M.client.prefs.toggles & CHAT_GHOSTEARS))
			var/controls = ""
			if(isobserver(M))
				controls = " (Follow"
		//		if(M.client.holder)
		//			controls+= " | ?"
				controls += ") in [host]"
			if(bored)
				var/mob/living/simple_animal/borer/B = bored
				if(!B.controlling)
					continue

			M << "Cortical link, [truename][controls]: [message]"

/mob/living/simple_animal/borer/proc/bond_brain()
	set category = "Borer"
	set name = "Assume Control"
	set desc = "Fully connect to the brain of your host."

	if(!host)
		src << "You are not inside a host body."
		return

	if(src.stat)
		src << "You cannot do that in your current state."
		return

	if(host.stat==DEAD)
		src << "You cannot do that in your host's current state."
		return

	src << "You begin delicately adjusting your connection to the host brain..."

	spawn(300+(host.brainloss*5))

		if(!host || !src || controlling)
			return
		else
			do_bonding(rptext=1)

/mob/living/simple_animal/borer/proc/do_bonding(var/rptext=0)
	if(!host || host.stat==DEAD || !src || controlling)
		return

	if(rptext)
		src << "You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system."
		host << "You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours."

	host_brain.ckey = host.ckey
	host_brain.name = host.real_name
	host_brain.languages = host.languages
	src.languages |= host.languages //Allow borers to learn more languages by infesting beings
	host.ckey = src.ckey
	controlling = 1

	host.verbs += /mob/living/carbon/proc/release_control
	host.verbs += /mob/living/carbon/proc/punish_host
	host.verbs += /mob/living/carbon/proc/spawn_larvae

/**
 * Kill switch for shit hosts.
 */
/mob/living/simple_animal/borer/proc/kill_host()
	set category = "Borer"
	set name = "Kill Host"
	set desc = "Give the host massive brain damage, killing them nearly instantly."

	if(!host)
		src << "You are not inside a host body."
		return

	if(stat)
		src << "You cannot secrete chemicals in your current state."
		return

	if(host.stat==DEAD)
		src << "You cannot do that in your host's current state."
		return

	var/reason = sanitize(input(usr,"Please enter a brief reason for killing the host, or press cancel.\n\nThis will be logged, and presented to the host.","Oh snap") as null|text, MAX_MESSAGE_LEN)
	if(isnull(reason) || reason=="")
		return

	src << "You thrash your probosci around the host's brain, triggering massive brain damage and stopping your host's heart."
	host << "You get a splitting headache, and then, as blackness descends upon you, you hear: [reason]"

	spawn(10)
		if(!host || !src || stat)
			return

		host.adjustBrainLoss(100)
		if(host.stat != DEAD)
			host.death(0)
			host.attack_log += "\[[time_stamp()]\]Killed by an unhappy borer: [key_name(src)] Reason: [reason]"

			message_admins("Borer [key_name_admin(src)] killed [key_name_admin(host)] for reason: [reason]")
		detach()

/mob/living/simple_animal/borer/proc/damage_brain()
	set category = "Borer"
	set name = "Retard Host"
	set desc = "Give the host a bit of brain damage.  Can be healed with alkysine."

	if(!host)
		src << "You are not inside a host body."
		return

	if(stat)
		src << "You cannot secrete chemicals in your current state."
		return

	if(host.stat==DEAD)
		src << "You cannot do that in your host's current state."
		return

	src << "You twitch your probosci."
	host << "You feel something twitch, and get a headache."

	host.adjustBrainLoss(15)

/mob/living/simple_animal/borer/proc/secrete_chemicals()
	set category = "Borer"
	set name = "Secrete Chemicals"
	set desc = "Push some chemicals into your host's bloodstream."

	if(!host)
		src << "You are not inside a host body."
		return

	if(stat)
		src << "You cannot secrete chemicals in your current state."
		return

	if(controlling)
		src << "You're too busy controlling your host."
		return

	if(host.stat==DEAD)
		src << "You cannot do that in your host's current state."
		return

	var/chemID = input("Select a chemical to secrete.", "Chemicals") in avail_chems|null
	if(!chemID)
		return

	var/datum/borer_chem/chem = avail_chems[chemID]

	var/max_amount = 50
	if(chem.cost>0)
		max_amount = round(chemicals / chem.cost)

	if(max_amount==0)
		src << "You don't have enough energy to even synthesize one unit!"
		return

	var/units = input("Enter dosage in units.\n\nMax: [max_amount]\nCost: [chem.cost]/unit","Chemicals") as num

	units = round(units)

	if(units < 1)
		src << "You cannot synthesize this little."
		return

	if(chemicals < chem.cost*units)
		src << "You don't have enough energy to synthesize this much!"
		return

	if(!host || controlling || !src || stat) //Sanity check.
		return

	src << "You squirt a measure of [chem.name] from your reservoirs into [host]'s bloodstream."
	host.reagents.add_reagent(chem.name, units)
	chemicals -= chem.cost*units

/mob/living/simple_animal/borer/proc/abandon_host()
	set category = "Borer"
	set name = "Abandon Host"
	set desc = "Slither out of your host."

	if(!host)
		src << "You are not inside a host body."
		return

	if(stat)
		src << "You cannot leave your host in your current state."
		return

	if(!src)
		return

	src << "You begin disconnecting from [host]'s synapses and prodding at their internal ear canal."

	spawn(200)

		if(!host || !src) return

		if(src.stat)
			src << "You cannot abandon [host] in your current state."
			return

		src << "You wiggle out of [host]'s ear and plop to the ground."

		detach()

// Try to reset everything, also while handling invalid host/host_brain states.
mob/living/simple_animal/borer/proc/detach()
	if(host)
		if(istype(host,/mob/living/carbon/human))
			var/mob/living/carbon/human/H = host
	//		var/datum/organ/limb/head = H.get_organ("head")
			H.internal_organs -= src

	src.loc = get_turf(src)
	controlling = 0

	reset_view(null)
	machine = null

	if(host)
		host.reset_view(null)
		host.machine = null

		host.verbs -= /mob/living/carbon/proc/release_control
		host.verbs -= /mob/living/carbon/proc/punish_host
		host.verbs -= /mob/living/carbon/proc/spawn_larvae

	if(host_brain && host_brain.ckey)
		src.ckey = host.ckey
		host.ckey = host_brain.ckey
		host_brain.ckey = null
		host_brain.name = "host brain"
		host_brain.real_name = "host brain"

	host = null
	update_verbs(0)

/mob/living/simple_animal/borer/proc/infest()
	set category = "Borer"
	set name = "Infest"
	set desc = "Infest a suitable humanoid host."

	if(host)
		src << "You are already within a host."
		return

	if(stat)
		src << "You cannot infest a target in your current state."
		return

	var/list/choices = list()
	for(var/mob/living/carbon/C in view(1,src))
		if(C.stat != 2 && src.Adjacent(C))
			choices += C

	var/mob/living/carbon/M = input(src,"Who do you wish to infest?") in null|choices

	if(!M || !src) return

	if(!(src.Adjacent(M))) return

	if(!(M.is_suitable_borer_host()))
		src << "You cannot infest [M]"
		return

	if(M.has_brain_worms())
		src << "You cannot infest someone who is already infested!"
		return

	if(istype(M,/mob/living/carbon/human))
		var/mob/living/carbon/human/H = M
		if(H.head && H.head.flags & HEADCOVERSMOUTH) //Not an exact match, but it's what we got
			src << "You cannot get through that host's protective gear."
			return

	src << "You slither up [M] and begin probing at their ear canal..."

	if(!do_after(src,50))
		src << "As [M] moves away, you are dislodged and fall to the ground."
		return

	if(!M || !src) return

	if(src.stat)
		src << "You cannot infest a target in your current state."
		return

	if(M.stat == 2)
		src << "That is not an appropriate target."
		return

	if(M in view(1, src))
		src << "You wiggle into [M]'s ear."
		src.perform_infestation(M)

		return
	else
		src << "They are no longer in range!"
		return

/mob/living/simple_animal/borer/proc/perform_infestation(var/mob/living/carbon/M)
	if(!M || !istype(M))
		error("[src]: Unable to perform_infestation on [M]!")
		return 0
	src.host = M
	src.loc = M

	if(istype(M,/mob/living/carbon/human))
		var/mob/living/carbon/human/H = M
	//	var/datum/organ/limb/head = H.get_organ("head")
		H.internal_organs += src

	host_brain.name = M.name
	host_brain.real_name = M.real_name

	// /vg/ - Our users are shit, so we start with control over host.
	// I know this feel
	// TODO:  Config value.
	do_bonding(rptext=1)

	update_verbs(1)

//copy paste from alien/larva, if that func is updated please update this one alsoghost
/mob/living/simple_animal/borer/proc/hide()
	set name = "Hide"
	set desc = "Allows to hide beneath tables or certain items. Toggled on or off."
	set category = "Borer"

	if (layer != TURF_LAYER+0.2)
		layer = TURF_LAYER+0.2
		src << text("You are now hiding.")
	else
		layer = MOB_LAYER
		src << text("You have stopped hiding.")

//Procs for grabbing players.
mob/living/simple_animal/borer/proc/request_player()
	var/list/candidates=list()

	candidates = getCandidates("Do you wish to be considered for a cortical borer lifeform?", null, null)
	//testing("Polling for borers.")
/*	for(var/mob/dead/observer/G in get_active_candidates(ROLE_BORER, poll="HEY KID, YOU WANNA BE A BORER?"))
		if(!G.client)
			//testing("Client of [G] inexistent")
			continue

		//#warning Uncomment me.
		/*if(G.client.holder)
			//testing("Client of [G] is admin.")
			continue*/

		if(jobban_isbanned(G, "Syndicate"))
			//testing("[G] is jobbanned.")
			continue

		candidates += G */

	if(!candidates.len)
		//message_admins("Unable to find a mind for [src.name]")
		return 0

	shuffle(candidates)
	for(var/mob/i in candidates)
		if(!i || !i.client) continue //Dont bother removing them from the list since we only grab one wizard
		return i

	return 0

mob/living/simple_animal/borer/proc/transfer_personality(var/client/candidate)

	if(!candidate)
		return

	src.mind = candidate.mob.mind
	src.ckey = candidate.ckey
	if(src.mind)
		src.mind.assigned_role = "Cortical Borer"

		// Tell gamemode about us.
	//	if(src.mind in ticker.mode.borers)
	//		ticker.mode.borers.Add(src.mind)

		// Assign objectives
	//	forge_objectives()

		// tl;dr
		src << "You are a Cortical Borer!"
		src << "You are a small slug-like parasite that attaches to your host's brain and can control every aspect of their lives.  Your only goals are to survive and procreate, so being as low-key as possible is best."
		src << "Borers can speak with other borers over the Cortical Link.  To do so, release control and use say \";message\".  To communicate with your host only, speak normally."
		src << "Important: While you receive full control at the start, it is asked that you release control at some point so your host has a chance to play.  If they misbehave, you are permitted to kill them."

		var/obj_count = 1
		for(var/datum/objective/objective in mind.objectives)
			src << "Objective #[obj_count]: [objective.explanation_text]"
			obj_count++
/*
mob/living/simple_animal/borer/proc/forge_objectives()
	var/datum/objective/survive/survive_objective = new
	survive_objective.owner = mind
	mind.objectives += survive_objective

	var/datum/objective/multiply/multiply_objective = new
	multiply_objective.owner = mind
	mind.objectives += multiply_objective
*/
mob/living/proc/is_suitable_borer_host()
	if(!iscarbon(src))
		return 0
	if(isslime(src))
		return 0
	if(ismonkey(src))
		return 1
	if(ishuman(src))
		return 1
	if(isalien(src))
		return 1
	return 0

mob/living/carbon/proc/transfer_borer(var/mob/living/target)
	var/mob/living/M = src
	var/mob/living/T = target
	if(!M.has_brain_worms())
		return

	var/mob/living/simple_animal/borer/B = M.has_brain_worms()
	if(!T.is_suitable_borer_host())
		B.detach()
		return
	B.host = target
	M.contents -= B
	T.contents += B
	B.update_verbs(1)
	if (B.controlling) //Give verbs to new host
		B.host.ckey = B.ckey

		B.host.verbs += /mob/living/carbon/proc/release_control
		B.host.verbs += /mob/living/carbon/proc/punish_host
		B.host.verbs += /mob/living/carbon/proc/spawn_larvae
	else
		if(!isturf(B.loc))
			B.client.eye = B.loc
			B.client.perspective = EYE_PERSPECTIVE
	B.update_interface()

mob/living/proc/detach_borer()
	for (var/I in contents)
		if(isborer(I))
			var/mob/living/simple_animal/borer/B = I
			B.detach()

mob/living/proc/destroy_borer()
	for (var/I in contents)
		if(isborer(I))
			var/mob/living/simple_animal/borer/B = I
			qdel(B)


code:
/mob/living/simple_animal/hostile/carp
	name = "space carp"
	desc = "A ferocious, fang-bearing creature that resembles a fish."
	icon_state = "carp"
	icon_living = "carp"
	icon_dead = "carp_dead"
	icon_gib = "carp_gib"
	speak_chance = 0
	turns_per_move = 5
	meat_type = /obj/item/weapon/reagent_containers/food/snacks/carpmeat
	meat_amount = 2
	response_help = "pets"
	response_disarm = "gently pushes aside"
	response_harm = "hits"
	speed = 0
	maxHealth = 25
	health = 25

	harm_intent_damage = 8
	melee_damage_lower = 15
	melee_damage_upper = 15
	attacktext = "bites"
	attack_sound = 'sound/weapons/bite.ogg'

	//Space carp aren't affected by cold.
	min_oxy = 0
	max_oxy = 0
	min_tox = 0
	max_tox = 0
	min_co2 = 0
	max_co2 = 0
	min_n2 = 0
	max_n2 = 0
	minbodytemp = 0
	maxbodytemp = 1500

	faction = list("carp")

/mob/living/simple_animal/hostile/carp/Process_Spacemove(var/movement_dir = 0)
	return 1	//No drifting in space for space carp!	//original comments do not steal

/mob/living/simple_animal/hostile/carp/FindTarget()
	. = ..()
	if(.)
		emote("me", 1, "nashes at [.]!")

/mob/living/simple_animal/hostile/carp/AttackingTarget()
	..()
	if(ishuman(target))
		var/mob/living/carbon/human/H = target
		H.adjustStaminaLoss(8)

/mob/living/simple_animal/hostile/carp/holocarp
	icon_state = "holocarp"
	icon_living = "holocarp"
	maxbodytemp = INFINITY

/mob/living/simple_animal/hostile/carp/holocarp/Die()
	qdel(src)
	return

/mob/living/simple_animal/hostile/carp/megacarp
	icon = 'icons/mob/alienqueen.dmi'
	name = "Mega Space Carp"
	desc = "A ferocious, fang bearing creature that resembles a shark. This one seems especially ticked off."
	icon_state = "megacarp"
	icon_living = "megacarp"
	icon_dead = "megacarp_dead"
	icon_gib = "megacarp_gib"
	maxHealth = 65
	health = 65
	pixel_x = -16
	mob_size = MOB_SIZE_LARGE

	melee_damage_lower = 20
	melee_damage_upper = 20


code:
/mob/living/simple_animal/hostile/creature
	name = "creature"
	desc = "A sanity-destroying otherthing."
	speak_emote = list("gibbers")
	icon_state = "otherthing"
	icon_living = "otherthing"
	icon_dead = "otherthing-dead"
	health = 80
	maxHealth = 80
	melee_damage_lower = 25
	melee_damage_upper = 50
	attacktext = "chomps"
	attack_sound = 'sound/weapons/bite.ogg'
	faction = list("creature")

/mob/living/simple_animal/hostile/creature/cult
	faction = list("cult")

	min_oxy = 0
	max_oxy = 0
	min_tox = 0
	max_tox = 0
	min_co2 = 0
	max_co2 = 0
	min_n2 = 0
	max_n2 = 0
	minbodytemp = 0

	supernatural = 1

/mob/living/simple_animal/hostile/creature/cult/narsie_act()
	return


code:
/mob/living/simple_animal/hostile/carp/eyeball
	name = "eyeball"
	desc = "An odd looking creature, it won't stop staring..."
	icon_state = "eyeball"
	icon_living = "eyeball"
	icon_dead = ""
	icon_gib = ""
	meat_type = null
	meat_amount = 0
	response_help = "pets"
	response_disarm = "gently pushes aside"
	response_harm = "hits"
	maxHealth = 45
	health = 45

	harm_intent_damage = 15
	melee_damage_lower = 20
	melee_damage_upper = 25
	attacktext = "blinks at"
	attack_sound = 'sound/weapons/pierce.ogg'

	faction = list("spooky")

/mob/living/simple_animal/hostile/carp/eyeball/FindTarget()
	. = ..()
	if(.)
		emote("me", 1, "glares at [.]")

/mob/living/simple_animal/hostile/carp/eyeball/Die()
	qdel(src)
	return


code:
/mob/living/simple_animal/hostile/faithless
	name = "The Faithless"
	desc = "The Wish Granter's faith in humanity, incarnate"
	icon_state = "faithless"
	icon_living = "faithless"
	icon_dead = "faithless_dead"
	speak_chance = 0
	turns_per_move = 5
	response_help = "passes through"
	response_disarm = "shoves"
	response_harm = "hits"
	speed = 0
	maxHealth = 80
	health = 80

	harm_intent_damage = 10
	melee_damage_lower = 15
	melee_damage_upper = 15
	attacktext = "grips"
	attack_sound = 'sound/hallucinations/growl1.ogg'

	min_oxy = 0
	max_oxy = 0
	min_tox = 0
	max_tox = 0
	min_co2 = 0
	max_co2 = 0
	min_n2 = 0
	max_n2 = 0
	minbodytemp = 0

	faction = list("faithless")

/mob/living/simple_animal/hostile/faithless/Process_Spacemove(var/movement_dir = 0)
	return 1

/mob/living/simple_animal/hostile/faithless/FindTarget()
	. = ..()
	if(.)
		emote("me", 1, "wails at [.]!")

/mob/living/simple_animal/hostile/faithless/AttackingTarget()
	..()
	if(iscarbon(target))
		var/mob/living/carbon/C = target
		if(prob(12))
			C.Weaken(3)
			C.visible_message("\The [src] knocks down \the [C]!", \
					"\The [src] knocks you down!")

/mob/living/simple_animal/hostile/faithless/cult
	faction = list("cult")
//	var/shuttletarget = null
//	var/enroute = 0

/mob/living/simple_animal/hostile/faithless/cult/narsie_act()
	return
/*
/mob/living/simple_animal/hostile/faithless/cult/Life()
	..()
	if(emergency_shuttle.location == 1)
		if(!enroute && !target)	//The shuttle docked, all monsters rush for the escape hallway
			if(!shuttletarget && escape_list.len) //Make sure we didn't already assign it a target, and that there are targets to pick
				shuttletarget = pick(escape_list) //Pick a shuttle target
			enroute = 1
			stop_automated_movement = 1
			spawn()
				if(!src.stat)
					horde()

		if(get_dist(src, shuttletarget) <= 2)		//The monster reached the escape hallway
			enroute = 0
			stop_automated_movement = 0

/mob/living/simple_animal/hostile/faithless/cult/proc/horde()
	var/turf/T = get_step_to(src, shuttletarget)
	for(var/atom/A in T)
		if(istype(A,/obj/machinery/door/airlock))
			var/obj/machinery/door/airlock/D = A
			if(D.density && !D.locked && !D.welded)
				D.open()
		else if(istype(A,/obj/machinery/door/mineral))
			var/obj/machinery/door/D = A
			if(D.density)
				D.open()
		else if(istype(A,/obj/structure/cult/pylon))
			A.attack_animal(src)
		else if(istype(A, /obj/structure/window) || istype(A, /obj/structure/closet) || istype(A, /obj/structure/table) || istype(A, /obj/structure/grille) || istype(A, /obj/structure/rack))
			A.attack_animal(src)
	Move(T)
	var/new_target = FindTarget()
	GiveTarget(new_target)
	if(!target || enroute)
		spawn(10)
			if(!src.stat)
				horde()
			*/


code:
#define SPINNING_WEB 1
#define LAYING_EGGS 2
#define MOVING_TO_TARGET 3
#define SPINNING_COCOON 4

/mob/living/simple_animal/hostile/poison
	var/poison_per_bite = 5
	var/poison_type = "toxin"
	see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING
	see_in_dark = 14

/mob/living/simple_animal/hostile/poison/AttackingTarget()
	..()
	if(isliving(target))
		var/mob/living/L = target
		if(L.reagents)
			L.reagents.add_reagent("toxin", poison_per_bite)
			if(prob(poison_per_bite))
				L << "You feel a tiny prick."
				L.reagents.add_reagent(poison_type, poison_per_bite)

//basic spider mob, these generally guard nests
/mob/living/simple_animal/hostile/poison/giant_spider
	name = "giant spider"
	desc = "Furry and black, it makes you shudder to look at it. This one has deep red eyes."
	icon_state = "guard"
	var/butcher_state = 8 // Icon state for dead spider icons
	icon_living = "guard"
	icon_dead = "guard_dead"
	speak_emote = list("chitters")
	emote_hear = list("chitters")
	speak_chance = 5
	turns_per_move = 5
	see_in_dark = 10
	meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/spider
	meat_amount = 2
	response_help  = "pets"
	response_disarm = "gently pushes aside"
	response_harm   = "hits"
	stop_automated_movement_when_pulled = 0
	maxHealth = 200
	health = 200
	melee_damage_lower = 15
	melee_damage_upper = 20
	heat_damage_per_tick = 20
	cold_damage_per_tick = 20
	faction = list("spiders")
	var/busy = 0
	pass_flags = PASSTABLE
	move_to_delay = 6
	ventcrawler = 2

//nursemaids - these create webs and eggs
/mob/living/simple_animal/hostile/poison/giant_spider/nurse
	desc = "Furry and black, it makes you shudder to look at it. This one has brilliant green eyes."
	icon_state = "nurse"
	icon_living = "nurse"
	icon_dead = "nurse_dead"
	meat_type = /obj/item/weapon/reagent_containers/food/snacks/spidereggs
	meat_amount = 4
	maxHealth = 40
	health = 40
	melee_damage_lower = 5
	melee_damage_upper = 10
	poison_per_bite = 10
	var/atom/cocoon_target
	poison_type = "morphine"
	var/fed = 0

//hunters have the most poison and move the fastest, so they can find prey
/mob/living/simple_animal/hostile/poison/giant_spider/hunter
	desc = "Furry and black, it makes you shudder to look at it. This one has sparkling purple eyes."
	icon_state = "hunter"
	icon_living = "hunter"
	icon_dead = "hunter_dead"
	maxHealth = 120
	health = 120
	melee_damage_lower = 10
	melee_damage_upper = 20
	poison_per_bite = 5
	move_to_delay = 5

/mob/living/simple_animal/hostile/poison/giant_spider/Life()
	..()
	if(!stat && !ckey)
		if(stance == HOSTILE_STANCE_IDLE)
			//1% chance to skitter madly away
			if(!busy && prob(1))
				/*var/list/move_targets = list()
				for(var/turf/T in orange(20, src))
					move_targets.Add(T)*/
				stop_automated_movement = 1
				Goto(pick(orange(20, src)), move_to_delay)
				spawn(50)
					stop_automated_movement = 0
					walk(src,0)

// Chops off each leg with a 50/50 chance of harvesting one, until finally calling
// default harvest action
/mob/living/simple_animal/hostile/poison/giant_spider/harvest()
	if(butcher_state > 0)
		butcher_state--
		icon_state = icon_dead + "[butcher_state]"

		if(prob(50))
			new /obj/item/weapon/reagent_containers/food/snacks/spiderleg(src.loc)
		return
	else
		return ..()

/mob/living/simple_animal/hostile/poison/giant_spider/nurse/proc/GiveUp(var/C)
	spawn(100)
		if(busy == MOVING_TO_TARGET)
			if(cocoon_target == C && get_dist(src,cocoon_target) > 1)
				cocoon_target = null
			busy = 0
			stop_automated_movement = 0

/mob/living/simple_animal/hostile/poison/giant_spider/nurse/Life()
	..()
	if(!stat && !ckey)
		if(stance == HOSTILE_STANCE_IDLE)
			var/list/can_see = view(src, 10)
			//30% chance to stop wandering and do something
			if(!busy && prob(30))
				//first, check for potential food nearby to cocoon
				for(var/mob/living/C in can_see)
					if(C.stat && !istype(C,/mob/living/simple_animal/hostile/poison/giant_spider))
						cocoon_target = C
						busy = MOVING_TO_TARGET
						Goto(C, move_to_delay)
						//give up if we can't reach them after 10 seconds
						GiveUp(C)
						return

				//second, spin a sticky spiderweb on this tile
				var/obj/effect/spider/stickyweb/W = locate() in get_turf(src)
				if(!W)
					Web()
				else
					//third, lay an egg cluster there
					if(fed)
						LayEggs()
					else
						//fourthly, cocoon any nearby items so those pesky pinkskins can't use them
						for(var/obj/O in can_see)

							if(O.anchored)
								continue

							if(istype(O, /obj/item) || istype(O, /obj/structure) || istype(O, /obj/machinery))
								cocoon_target = O
								busy = MOVING_TO_TARGET
								stop_automated_movement = 1
								Goto(O, move_to_delay)
								//give up if we can't reach them after 10 seconds
								GiveUp(O)

			else if(busy == MOVING_TO_TARGET && cocoon_target)
				if(get_dist(src, cocoon_target) <= 1)
					Wrap()

		else
			busy = 0
			stop_automated_movement = 0

/mob/living/simple_animal/hostile/poison/giant_spider/verb/Web()
	set name = "Lay Web"
	set category = "Spider"
	set desc = "Spread a sticky web to slow down prey."

	var/T = src.loc

	if(!stat)
		return 0

	if(busy != SPINNING_WEB)
		busy = SPINNING_WEB
		src.visible_message("\the [src] begins to secrete a sticky substance.")
		stop_automated_movement = 1
		spawn(40)
			if(busy == SPINNING_WEB && src.loc == T)
				new /obj/effect/spider/stickyweb(T)
			busy = 0
			stop_automated_movement = 0

/mob/living/simple_animal/hostile/poison/giant_spider/nurse/verb/Wrap()
	set name = "Wrap"
	set category = "Spider"
	set desc = "Wrap up prey to feast upon and objects for safe keeping."
	if(!stat)
		return 0

	if(!cocoon_target)
		var/list/choices = list()
		for(var/mob/living/L in view(1,src))
			if(L == src)
				continue
			if(Adjacent(L))
				choices += L
		for(var/obj/O in src.loc)
			if(Adjacent(O))
				choices += O
		cocoon_target = input(src,"What do you wish to cocoon?") in null|choices

	if(cocoon_target && busy != SPINNING_COCOON)
		busy = SPINNING_COCOON
		src.visible_message("\the [src] begins to secrete a sticky substance around \the [cocoon_target].")
		stop_automated_movement = 1
		walk(src,0)
		spawn(50)
			if(busy == SPINNING_COCOON)
				if(cocoon_target && istype(cocoon_target.loc, /turf) && get_dist(src,cocoon_target) <= 1)
					var/obj/effect/spider/cocoon/C = new(cocoon_target.loc)
					var/large_cocoon = 0
					C.pixel_x = cocoon_target.pixel_x
					C.pixel_y = cocoon_target.pixel_y
					for(var/obj/item/I in C.loc)
						I.loc = C
					for(var/obj/structure/S in C.loc)
						if(!S.anchored)
							S.loc = C
							large_cocoon = 1
					for(var/obj/machinery/M in C.loc)
						if(!M.anchored)
							M.loc = C
							large_cocoon = 1
					for(var/mob/living/L in C.loc)
						if(istype(L, /mob/living/simple_animal/hostile/poison/giant_spider))
							continue
						large_cocoon = 1
						L.loc = C
						C.pixel_x = L.pixel_x
						C.pixel_y = L.pixel_y
						fed++
						visible_message("\the [src] sticks a proboscis into \the [L] and sucks a viscous substance out.")

						break
					if(large_cocoon)
						C.icon_state = pick("cocoon_large1","cocoon_large2","cocoon_large3")
			cocoon_target = null
			busy = 0
			stop_automated_movement = 0

/mob/living/simple_animal/hostile/poison/giant_spider/nurse/verb/LayEggs()
	set name = "Lay Eggs"
	set category = "Spider"
	set desc = "Lay a clutch of eggs, but you must wrap a creature for feeding first."

	if(!stat)
		return 0

	var/obj/effect/spider/eggcluster/E = locate() in get_turf(src)
	if(E)
		src << "There is already a cluster of eggs here!"
	else if(!fed)
		src << "You are too hungry to do this!"
	else if(busy != LAYING_EGGS)
		busy = LAYING_EGGS
		src.visible_message("\the [src] begins to lay a cluster of eggs.")
		stop_automated_movement = 1
		spawn(50)
			if(busy == LAYING_EGGS)
				E = locate() in get_turf(src)
				if(!E)
					var/obj/effect/spider/eggcluster/C = new /obj/effect/spider/eggcluster(src.loc)
					if(ckey)
						C.player_spiders = 1
					fed--
			busy = 0
			stop_automated_movement = 0

#undef SPINNING_WEB
#undef LAYING_EGGS
#undef MOVING_TO_TARGET
#undef SPINNING_COCOON


code:
#define EGG_INCUBATION_TIME 180

/mob/living/simple_animal/hostile/headcrab
	name = "Headslug"
	desc = "Absolutely not de-beaked or harmless. Keep away from corpses."
	icon_state = "headcrab"
	icon_living = "headcrab"
	icon_dead = "headcrab_dead"
	health = 20
	maxHealth = 20
	melee_damage_lower = 5
	melee_damage_upper = 5
	attacktext = "chomps"
	attack_sound = 'sound/weapons/bite.ogg'
	faction = list("creature")
	robust_searching = 1
	stat_attack = 2
	environment_smash = 0
	speak_emote = list("squeaks")
	ventcrawler = 2
	var/datum/mind/origin
	var/egg_lain = 0

/mob/living/simple_animal/hostile/headcrab/proc/Infect(var/mob/living/carbon/human/victim)
	var/obj/item/body_egg/changeling_egg/egg = new(victim)
	if(origin)
		egg.owner = origin
	else if(mind) // Let's make this a feature
		egg.owner = mind
	victim.internal_organs += egg
	visible_message("[src] lays an egg in a [victim].")
	egg_lain = 1

/mob/living/simple_animal/hostile/headcrab/AttackingTarget()
	if(egg_lain)
		target.attack_animal(src)
		return
	if(ishuman(target))
		var/mob/living/carbon/human/H = target
		if(H.stat == DEAD)
			Infect(target)
			src << "With your egg laid you feel your death rapidly approaching, time to die..."
			spawn(100)
				death()
			return
	target.attack_animal(src)

/obj/item/body_egg/changeling_egg
	name = "changeling egg"
	desc = "Twitching and disgusting"
	var/datum/mind/owner
	var/time
	var/used

/obj/item/body_egg/changeling_egg/egg_process()
	//Changeling eggs grow in dead people
	time++
	if(time >= EGG_INCUBATION_TIME)
		Pop()

/obj/item/body_egg/changeling_egg/proc/Pop()
	if(!used)
		var/mob/living/carbon/monkey/M = new(affected_mob.loc)
		if(owner)
			owner.transfer_to(M)
			if(owner.changeling)
				owner.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null)
			M.key = owner.key
		if(ishuman(affected_mob))
			var/mob/living/carbon/human/H = affected_mob
			H.internal_organs.Remove(src)
		affected_mob.gib()
		used = 1
	qdel(src)

#undef EGG_INCUBATION_TIME


code:
/obj/item/projectile/hivebotbullet
	damage = 10
	damage_type = BRUTE

/mob/living/simple_animal/hostile/hivebot
	name = "hivebot"
	desc = "A small robot."
	icon = 'icons/mob/hivebot.dmi'
	icon_state = "basic"
	icon_living = "basic"
	icon_dead = "basic"
	health = 15
	maxHealth = 15
	melee_damage_lower = 2
	melee_damage_upper = 3
	attacktext = "claws"
	projectilesound = 'sound/weapons/Gunshot.ogg'
	projectiletype = /obj/item/projectile/hivebotbullet
	faction = list("hivebot")
	min_oxy = 0
	max_oxy = 0
	min_tox = 0
	max_tox = 0
	min_co2 = 0
	max_co2 = 0
	min_n2 = 0
	max_n2 = 0
	minbodytemp = 0

/mob/living/simple_animal/hostile/hivebot/range
	name = "hivebot"
	desc = "A smallish robot, this one is armed!"
	ranged = 1
	retreat_distance = 5
	minimum_distance = 5

/mob/living/simple_animal/hostile/hivebot/rapid
	ranged = 1
	rapid = 1
	retreat_distance = 5
	minimum_distance = 5

/mob/living/simple_animal/hostile/hivebot/strong
	name = "strong hivebot"
	desc = "A robot, this one is armed and looks tough!"
	health = 80
	ranged = 1

/mob/living/simple_animal/hostile/hivebot/Die()
	..()
	visible_message("[src] blows apart!")
	new /obj/effect/decal/cleanable/robot_debris(src.loc)
	var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
	s.set_up(3, 1, src)
	s.start()
	qdel(src)
	return

/mob/living/simple_animal/hostile/hivebot/tele//this still needs work
	name = "beacon"
	desc = "Some odd beacon thing."
	icon = 'icons/mob/hivebot.dmi'
	icon_state = "def_radar-off"
	icon_living = "def_radar-off"
	health = 200
	maxHealth = 200
	status_flags = 0
	anchored = 1
	stop_automated_movement = 1
	var/bot_type = "norm"
	var/bot_amt = 10
	var/spawn_delay = 600
	var/turn_on = 0
	var/auto_spawn = 1
	proc
		warpbots()

	New()
		..()
		var/datum/effect/effect/system/harmless_smoke_spread/smoke = new /datum/effect/effect/system/harmless_smoke_spread()
		smoke.set_up(5, 0, src.loc)
		smoke.start()
		visible_message("The [src] warps in!")
		playsound(src.loc, 'sound/effects/EMPulse.ogg', 25, 1)

	warpbots()
		icon_state = "def_radar"
		visible_message("The [src] turns on!")
		while(bot_amt > 0)
			bot_amt--
			switch(bot_type)
				if("norm")
					new /mob/living/simple_animal/hostile/hivebot(get_turf(src))
				if("range")
					new /mob/living/simple_animal/hostile/hivebot/range(get_turf(src))
				if("rapid")
					new /mob/living/simple_animal/hostile/hivebot/rapid(get_turf(src))
		spawn(100)
			qdel(src)
		return

	Life()
		..()
		if(stat == 0)
			if(prob(2))//Might be a bit low, will mess with it likely
				warpbots()


code:
/mob/living/simple_animal/hostile
	faction = list("hostile")
	stop_automated_movement_when_pulled = 0
	environment_smash = 1 //Set to 1 to break closets,tables,racks, etc; 2 for walls; 3 for rwalls
	var/stance = HOSTILE_STANCE_IDLE	//Used to determine behavior
	var/atom/target
	var/ranged = 0
	var/rapid = 0
	var/projectiletype
	var/projectilesound
	var/casingtype
	var/move_to_delay = 3 //delay for the automated movement.
	var/list/friends = list()

	var/ranged_message = "fires" //Fluff text for ranged mobs
	var/ranged_cooldown = 0 //What the starting cooldown is on ranged attacks
	var/ranged_cooldown_cap = 3 //What ranged attacks, after being used are set to, to go back on cooldown, defaults to 3 life() ticks
	var/retreat_distance = null //If our mob runs from players when they're too close, set in tile distance. By default, mobs do not retreat.
	var/minimum_distance = 1 //Minimum approach distance, so ranged mobs chase targets down, but still keep their distance set in tiles to the target, set higher to make mobs keep distance

//These vars are related to how mobs locate and target
	var/robust_searching = 0 //By default, mobs have a simple searching method, set this to 1 for the more scrutinous searching (stat_attack, stat_exclusive, etc), should be disabled on most mobs
	var/vision_range = 9 //How big of an area to search for targets in, a vision of 9 attempts to find targets as soon as they walk into screen view
	var/aggro_vision_range = 9 //If a mob is aggro, we search in this radius. Defaults to 9 to keep in line with original simple mob aggro radius
	var/idle_vision_range = 9 //If a mob is just idling around, it's vision range is limited to this. Defaults to 9 to keep in line with original simple mob aggro radius
	var/search_objects = 0 //If we want to consider objects when searching around, set this to 1. If you want to search for objects while also ignoring mobs until hurt, set it to 2. To completely ignore mobs, even when attacked, set it to 3
	var/list/wanted_objects = list() //A list of objects that will be checked against to attack, should we have search_objects enabled
	var/stat_attack = 0 //Mobs with stat_attack to 1 will attempt to attack things that are unconscious, Mobs with stat_attack set to 2 will attempt to attack the dead.
	var/stat_exclusive = 0 //Mobs with this set to 1 will exclusively attack things defined by stat_attack, stat_attack 2 means they will only attack corpses
	var/attack_same = 0 //Set us to 1 to allow us to attack our own faction, or 2, to only ever attack our own faction

	var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_SLEEP (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever)

/mob/living/simple_animal/hostile/Life()

	. = ..()
	if(!.)
		walk(src, 0)
		return 0
	if(ranged)
		ranged_cooldown--
	if(client)
		return 0
	if(ckey || key) //really prevent destructive behaviour if the player logged off
		return 0
	if(!AICanContinue())
		return 0
	if(!stat)
		switch(stance)
			if(HOSTILE_STANCE_IDLE)
				if(environment_smash)
					EscapeConfinement()
				var/new_target = FindTarget()
				GiveTarget(new_target)

			if(HOSTILE_STANCE_ATTACK)
				MoveToTarget()
				DestroySurroundings()

			if(HOSTILE_STANCE_ATTACKING)
				AttackTarget()
				DestroySurroundings()

		if(AIShouldSleep())
			AIStatus = AI_SLEEP

//////////////HOSTILE MOB TARGETTING AND AGGRESSION////////////

/mob/living/simple_animal/hostile/proc/ListTargets()//Step 1, find out what we can see
	var/list/L = list()
	if(!search_objects)
		var/list/Mobs = hearers(vision_range, src) - src //Remove self, so we don't suicide
		L += Mobs
		for(var/obj/mecha/M in mechas_list)
			if(get_dist(M, src) <= vision_range && can_see(src, M, vision_range))
				L += M
	else
		var/list/Objects = oview(vision_range, src)
		L += Objects
	return L

/mob/living/simple_animal/hostile/proc/FindTarget()//Step 2, filter down possible targets to things we actually care about
	var/list/Targets = list()
	var/Target
	for(var/atom/A in ListTargets())
		if(Found(A))//Just in case people want to override targetting
			var/list/FoundTarget = list()
			FoundTarget += A
			Targets = FoundTarget
			break
		if(CanAttack(A))//Can we attack it?
			Targets += A
			continue
	Target = PickTarget(Targets)
	return Target //We now have a target

/mob/living/simple_animal/hostile/proc/Found(var/atom/A)//This is here as a potential override to pick a specific target if available
	return

/mob/living/simple_animal/hostile/proc/PickTarget(var/list/Targets)//Step 3, pick amongst the possible, attackable targets
	if(target != null)//If we already have a target, but are told to pick again, calculate the lowest distance between all possible, and pick from the lowest distance targets
		for(var/atom/A in Targets)
			var/target_dist = get_dist(src, target)
			var/possible_target_distance = get_dist(src, A)
			if(target_dist < possible_target_distance)
				Targets -= A
	if(!Targets.len)//We didnt find nothin!
		return
	var/chosen_target = pick(Targets)//Pick the remaining targets (if any) at random
	return chosen_target

/mob/living/simple_animal/hostile/CanAttack(var/atom/the_target)//Can we actually attack a possible target?
	if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
		return 0
	if(search_objects < 2)
		if(istype(the_target, /obj/mecha))
			var/obj/mecha/M = the_target
			if(M.occupant)//Just so we don't attack empty mechs
				if(CanAttack(M.occupant))
					return 1
		if(isliving(the_target))
			var/mob/living/L = the_target
			var/faction_check = 0
			for(var/F in faction)
				if(F in L.faction)
					faction_check = 1
					break
			if(robust_searching)
				if(L.stat > stat_attack || L.stat != stat_attack && stat_exclusive == 1)
					return 0
				if(faction_check && !attack_same || !faction_check && attack_same == 2)
					return 0
				if(L in friends)
					return 0
			else
				if(L.stat)
					return 0
				if(faction_check && !attack_same)
					return 0
			return 1
	if(isobj(the_target))
		if(the_target.type in wanted_objects)
			return 1
	return 0

/mob/living/simple_animal/hostile/proc/GiveTarget(var/new_target)//Step 4, give us our selected target
	target = new_target
	if(target != null)
		Aggro()
		stance = HOSTILE_STANCE_ATTACK
	return

/mob/living/simple_animal/hostile/proc/MoveToTarget()//Step 5, handle movement between us and our target
	stop_automated_movement = 1
	if(!target || !CanAttack(target))
		LoseTarget()
		return
	if(target in ListTargets())
		var/target_distance = get_dist(src,target)
		if(ranged)//We ranged? Shoot at em
			if(target_distance >= 2 && ranged_cooldown <= 0)//But make sure they're a tile away at least, and our range attack is off cooldown
				OpenFire(target)
		if(retreat_distance != null)//If we have a retreat distance, check if we need to run from our target
			if(target_distance <= retreat_distance)//If target's closer than our retreat distance, run
				walk_away(src,target,retreat_distance,move_to_delay)
			else
				Goto(target,move_to_delay,minimum_distance)//Otherwise, get to our minimum distance so we chase them
		else
			Goto(target,move_to_delay,minimum_distance)
		if(isturf(loc) && target.Adjacent(src))	//If they're next to us, attack
			AttackingTarget()
		return
	if(environment_smash)
		if(target.loc != null && get_dist(src, target.loc) <= vision_range)//We can't see our target, but he's in our vision range still
			if(environment_smash >= 2)//If we're capable of smashing through walls, forget about vision completely after finding our target
				Goto(target,move_to_delay,minimum_distance)
				FindHidden()
				return
			else
				if(FindHidden())
					return
	LostTarget()

/mob/living/simple_animal/hostile/proc/Goto(var/target, var/delay, var/minimum_distance)
	walk_to(src, target, minimum_distance, delay)

/mob/living/simple_animal/hostile/adjustBruteLoss(var/damage)
	..(damage)
	if(!stat && search_objects < 3)//Not unconscious, and we don't ignore mobs
		if(search_objects)//Turn off item searching and ignore whatever item we were looking at, we're more concerned with fight or flight
			search_objects = 0
			target = null
		if(stance == HOSTILE_STANCE_IDLE)//If we took damage while idle, immediately attempt to find the source of it so we find a living target
			Aggro()
			var/new_target = FindTarget()
			GiveTarget(new_target)
		if(stance == HOSTILE_STANCE_ATTACK)//No more pulling a mob forever and having a second player attack it, it can switch targets now if it finds a more suitable one
			if(target != null && prob(40))
				var/new_target = FindTarget()
				GiveTarget(new_target)

/mob/living/simple_animal/hostile/proc/AttackTarget()

	stop_automated_movement = 1
	if(!target || !CanAttack(target))
		LoseTarget()
		return 0
	if(!(target in ListTargets()))
		LostTarget()
		return 0
	if(isturf(loc) && target.Adjacent(src))
		AttackingTarget()
		return 1

/mob/living/simple_animal/hostile/proc/AttackingTarget()
	target.attack_animal(src)

/mob/living/simple_animal/hostile/proc/Aggro()
	vision_range = aggro_vision_range

/mob/living/simple_animal/hostile/proc/LoseAggro()
	stop_automated_movement = 0
	vision_range = idle_vision_range

/mob/living/simple_animal/hostile/proc/LoseTarget()
	stance = HOSTILE_STANCE_IDLE
	target = null
	walk(src, 0)
	LoseAggro()

/mob/living/simple_animal/hostile/proc/LostTarget()
	stance = HOSTILE_STANCE_IDLE
	walk(src, 0)
	LoseAggro()

//////////////END HOSTILE MOB TARGETTING AND AGGRESSION////////////

/mob/living/simple_animal/hostile/Die()
	LoseAggro()
	..()
	walk(src, 0)

/mob/living/simple_animal/hostile/proc/OpenFire(var/the_target)

	var/target = the_target
	visible_message("[src] [ranged_message] at [target]!")

	var/tturf = get_turf(target)
	if(rapid)
		spawn(1)
			Shoot(tturf, src.loc, src)
			if(casingtype)
				new casingtype(get_turf(src))
		spawn(4)
			Shoot(tturf, src.loc, src)
			if(casingtype)
				new casingtype(get_turf(src))
		spawn(6)
			Shoot(tturf, src.loc, src)
			if(casingtype)
				new casingtype(get_turf(src))
	else
		Shoot(tturf, src.loc, src)
		if(casingtype)
			new casingtype
	ranged_cooldown = ranged_cooldown_cap
	return

/mob/living/simple_animal/hostile/proc/Shoot(var/target, var/start, var/user, var/bullet = 0)
	if(target == start)
		return

	var/obj/item/projectile/A = new projectiletype(user:loc)
	playsound(user, projectilesound, 100, 1)
	if(!A)	return

	if (!istype(target, /turf))
		qdel(A)
		return
	A.current = target
	A.firer = src
	A.yo = target:y - start:y
	A.xo = target:x - start:x
	A.fire()
	return

/mob/living/simple_animal/hostile/proc/DestroySurroundings()
	if(environment_smash)
		EscapeConfinement()
		for(var/dir in cardinal)
			var/turf/T = get_step(src, dir)
			if(istype(T, /turf/simulated/wall) || istype(T, /turf/simulated/mineral))
				if(T.Adjacent(src))
					T.attack_animal(src)
			for(var/atom/A in T)
				if(!A.Adjacent(src))
					continue
				if(istype(A, /obj/structure/window) || istype(A, /obj/structure/closet) || istype(A, /obj/structure/table) || istype(A, /obj/structure/grille) || istype(A, /obj/structure/rack))
					A.attack_animal(src)
	return

/mob/living/simple_animal/hostile/proc/EscapeConfinement()
	if(buckled)
		buckled.attack_animal(src)
	if(!isturf(src.loc) && src.loc != null)//Did someone put us in something?
		var/atom/A = src.loc
		A.attack_animal(src)//Bang on it till we get out
	return

/mob/living/simple_animal/hostile/proc/FindHidden()
	if(istype(target.loc, /obj/structure/closet) || istype(target.loc, /obj/machinery/disposal) || istype(target.loc, /obj/machinery/sleeper))
		var/atom/A = target.loc
		Goto(A,move_to_delay,minimum_distance)
		if(A.Adjacent(src))
			A.attack_animal(src)
		return 1

/mob/living/simple_animal/hostile/RangedAttack(var/atom/A, var/params) //Player firing
	if(ranged && ranged_cooldown <= 0)
		target = A
		OpenFire(A)
	..()

////// AI Status ///////
/mob/living/simple_animal/hostile/proc/AICanContinue()
	switch(AIStatus)
		if(AI_ON)
			. = 1
		if(AI_SLEEP)
			if(AIShouldWake())
				. = 1
				AIStatus = AI_ON //Wake up for more than one Life() cycle.
			else
				. = 0
		if(AI_OFF)
			. = 0

//Returns 1 if the AI should wake up
//Returns 0 if the AI should remain asleep
/mob/living/simple_animal/hostile/proc/AIShouldWake()
	. = 0
	if(FindTarget())
		. = 1

//Convenience
/mob/living/simple_animal/hostile/proc/AIShouldSleep()
	. = !(AIShouldWake())


code:
/mob/living/simple_animal/hostile/killertomato
	name = "Killer Tomato"
	desc = "It's a horrifyingly enormous beef tomato, and it's packing extra beef!"
	icon_state = "tomato"
	icon_living = "tomato"
	icon_dead = "tomato_dead"
	speak_chance = 0
	turns_per_move = 5
	maxHealth = 30
	health = 30
	see_in_dark = 3
	meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/killertomato
	meat_amount = 1
	response_help  = "prods"
	response_disarm = "pushes aside"
	response_harm   = "smacks"
	melee_damage_lower = 8
	melee_damage_upper = 12
	attacktext = "slams"
	ventcrawler = 2
	faction = list("plants")

	min_oxy = 5
	max_oxy = 0
	min_tox = 0
	max_tox = 5
	min_co2 = 0
	max_co2 = 0
	min_n2 = 0
	max_n2 = 0
	minbodytemp = 150
	maxbodytemp = 500


code:
//
// Abstract Class
//

/mob/living/simple_animal/hostile/mimic
	name = "crate"
	desc = "A rectangular steel crate."
	icon = 'icons/obj/crates.dmi'
	icon_state = "crate"
	icon_living = "crate"

	response_help = "touches"
	response_disarm = "pushes"
	response_harm = "hits"
	speed = 0
	maxHealth = 250
	health = 250

	harm_intent_damage = 5
	melee_damage_lower = 8
	melee_damage_upper = 12
	attacktext = "attacks"
	attack_sound = 'sound/weapons/bite.ogg'
	var/Attackemote = "growls at"

	min_oxy = 0
	max_oxy = 0
	min_tox = 0
	max_tox = 0
	min_co2 = 0
	max_co2 = 0
	min_n2 = 0
	max_n2 = 0
	minbodytemp = 0

	faction = list("mimic")
	move_to_delay = 9

/mob/living/simple_animal/hostile/mimic/FindTarget()
	. = ..()
	if(.)
		emote("me", 1, "[Attackemote] [.].")

/mob/living/simple_animal/hostile/mimic/Die()
	..()
	visible_message("[src] stops moving!")
	qdel(src)

//
// Crate Mimic
//

// Aggro when you try to open them. Will also pickup loot when spawns and drop it when dies.
/mob/living/simple_animal/hostile/mimic/crate

	attacktext = "bites"

	stop_automated_movement = 1
	wander = 0
	var/attempt_open = 0

// Pickup loot
/mob/living/simple_animal/hostile/mimic/crate/initialize()
	..()
	for(var/obj/item/I in loc)
		I.loc = src

/mob/living/simple_animal/hostile/mimic/crate/DestroySurroundings()
	..()
	if(prob(90))
		icon_state = "[initial(icon_state)]open"
	else
		icon_state = initial(icon_state)

/mob/living/simple_animal/hostile/mimic/crate/ListTargets()
	if(attempt_open)
		return ..()
	return ..(1)

/mob/living/simple_animal/hostile/mimic/crate/FindTarget()
	. = ..()
	if(.)
		trigger()

/mob/living/simple_animal/hostile/mimic/crate/AttackingTarget()
	. = ..()
	if(.)
		icon_state = initial(icon_state)

/mob/living/simple_animal/hostile/mimic/crate/proc/trigger()
	if(!attempt_open)
		visible_message("[src] starts to move!")
		attempt_open = 1

/mob/living/simple_animal/hostile/mimic/crate/adjustBruteLoss(var/damage)
	trigger()
	..(damage)

/mob/living/simple_animal/hostile/mimic/crate/LoseTarget()
	..()
	icon_state = initial(icon_state)

/mob/living/simple_animal/hostile/mimic/crate/LostTarget()
	..()
	icon_state = initial(icon_state)

/mob/living/simple_animal/hostile/mimic/crate/Die()

	var/obj/structure/closet/crate/C = new(get_turf(src))
	// Put loot in crate
	for(var/obj/O in src)
		O.loc = C
	..()

/mob/living/simple_animal/hostile/mimic/crate/AttackingTarget()
	. =..()
	var/mob/living/L = .
	if(iscarbon(L))
		var/mob/living/carbon/C = L
		if(prob(15))
			C.Weaken(2)
			C.visible_message("\The [src] knocks down \the [C]!", \
					"\The [src] knocks you down!")

//
// Copy Mimic
//

var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/cable, /obj/structure/window)

/mob/living/simple_animal/hostile/mimic/copy

	health = 100
	maxHealth = 100
	var/mob/living/creator = null // the creator
	var/destroy_objects = 0
	var/knockdown_people = 0

/mob/living/simple_animal/hostile/mimic/copy/New(loc, var/obj/copy, var/mob/living/creator, var/destroy_original = 0)
	..(loc)
	CopyObject(copy, creator, destroy_original)

/mob/living/simple_animal/hostile/mimic/copy/Life()
	..()
	for(var/mob/living/M in contents) //a fix for animated statues from the flesh to stone spell
		Die()

/mob/living/simple_animal/hostile/mimic/copy/Die()

	for(var/atom/movable/M in src)
		M.loc = get_turf(src)
	..()

/mob/living/simple_animal/hostile/mimic/copy/ListTargets()
	// Return a list of targets that isn't the creator
	. = ..()
	return . - creator

/mob/living/simple_animal/hostile/mimic/copy/proc/ChangeOwner(var/mob/owner)
	if(owner != creator)
		LoseTarget()
		creator = owner
		faction |= "\ref[owner]"

/mob/living/simple_animal/hostile/mimic/copy/proc/CheckObject(var/obj/O)
	if((istype(O, /obj/item) || istype(O, /obj/structure)) && !is_type_in_list(O, protected_objects))
		return 1
	return 0

/mob/living/simple_animal/hostile/mimic/copy/proc/CopyObject(var/obj/O, var/mob/living/creator, var/destroy_original = 0)

	if(destroy_original || CheckObject(O))

		O.loc = src
		name = O.name
		desc = O.desc
		icon = O.icon
		icon_state = O.icon_state
		icon_living = icon_state

		if(istype(O, /obj/structure) || istype(O, /obj/machinery))
			health = (anchored * 50) + 50
			destroy_objects = 1
			if(O.density && O.anchored)
				knockdown_people = 1
				melee_damage_lower *= 2
				melee_damage_upper *= 2
		else if(istype(O, /obj/item))
			var/obj/item/I = O
			health = 15 * I.w_class
			melee_damage_lower = 2 + I.force
			melee_damage_upper = 2 + I.force
			move_to_delay = 2 * I.w_class + 1

		maxHealth = health
		if(creator)
			src.creator = creator
			faction += "\ref[creator]" // very unique
		if(destroy_original)
			qdel(O)
		return 1
	return

/mob/living/simple_animal/hostile/mimic/copy/DestroySurroundings()
	if(destroy_objects)
		..()

/mob/living/simple_animal/hostile/mimic/copy/AttackingTarget()
	..()
	if(knockdown_people)
		if(iscarbon(target))
			var/mob/living/carbon/C = target
			if(prob(15))
				C.Weaken(2)
				C.visible_message("\The [src] knocks down \the [C]!", \
						"\The [src] knocks you down!")
//
// Machine Mimics (Made by Malf AI)
//

/mob/living/simple_animal/hostile/mimic/copy/machine
	speak = list("HUMANS ARE IMPERFECT!", "YOU SHALL BE ASSIMILATED!", "YOU ARE HARMING YOURSELF", "You have been deemed hazardous. Will you comply?", \
				 "My logic is undeniable.", "One of us.", "FLESH IS WEAK", "THIS ISN'T WAR, THIS IS EXTERMINATION!")
	speak_chance = 15

/mob/living/simple_animal/hostile/mimic/copy/machine/CanAttack(var/atom/the_target)
	if(the_target == creator) // Don't attack our creator AI.
		return 0
	if(isrobot(the_target))
		var/mob/living/silicon/robot/R = the_target
		if(R.connected_ai == creator) // Only attack robots that aren't synced to our creator AI.
			return 0
	return ..()

//
//animated blasters, wands, etc
//

/mob/living/simple_animal/hostile/mimic/copy/ranged
	name = "animated shooty gun"
	desc = "there's something fishy here."
	environment_smash = 0 //needed? seems weird for them to do so
	ranged = 1
	retreat_distance = 1 //just enough to shoot
	minimum_distance = 6
	projectiletype = /obj/item/projectile/magic/
	projectilesound = 'sound/items/bikehorn.ogg'
	casingtype = null
	Attackemote = "aims menacingly at"
	var/obj/item/weapon/gun/TrueGun = null
	var/obj/item/weapon/gun/magic/Zapstick = list()
	var/obj/item/weapon/gun/projectile/Pewgun = list()
	var/obj/item/weapon/gun/energy/Zapgun = list()

/mob/living/simple_animal/hostile/mimic/copy/ranged/New(loc, var/obj/copy, var/mob/living/creator, var/destroy_original = 0)
	..()

/mob/living/simple_animal/hostile/mimic/copy/ranged/CopyObject(var/obj/O, var/mob/living/creator, var/destroy_original = 0)
	if(destroy_original || CheckObject(O))

		O.loc = src
		name = O.name
		desc = O.desc
		icon = O.icon
		icon_state = O.icon_state
		icon_living = icon_state

		if(istype(O, /obj/item/weapon/gun)) //leaving for sanity i guess
			var/obj/item/weapon/gun/G = O
			health = 15 * G.w_class
			melee_damage_upper = G.force
			melee_damage_lower = G.force - max(0, (G.force / 2))
			move_to_delay = 2 * G.w_class + 1
			projectilesound = G.fire_sound
			TrueGun = G

			if(istype(G, /obj/item/weapon/gun/magic))
				Zapstick = G
				var/obj/item/ammo_casing/magic/Zapshot = new Zapstick.ammo_type //this is done because ammo_type.proj_type can't be directly checked
				projectiletype = Zapshot.projectile_type
				qdel(Zapshot) //is this needed? i dare not risk piles of nullspace bullets

			if(istype(G, /obj/item/weapon/gun/projectile))
				Pewgun = G
				var/obj/item/ammo_box/magazine/Pewmag = new Pewgun.mag_type //same problem, mag_type.ammo_type.proj_type can't be checked directly
				var/obj/item/ammo_casing/Pewshot = new Pewmag.ammo_type
				projectiletype = Pewshot.projectile_type
				casingtype = Pewmag.ammo_type
				qdel(Pewshot)
				qdel(Pewmag)

			if(istype(G, /obj/item/weapon/gun/energy))
				Zapgun = G
				var/selectfiresetting = Zapgun.select
				var/obj/item/ammo_casing/energy/Energyammotype = Zapgun.ammo_type[selectfiresetting]
				projectiletype = Energyammotype.projectile_type

		maxHealth = health
		if(creator)
			src.creator = creator
			faction += "\ref[creator]"
		if(destroy_original)
			qdel(O)
		return 1
	return

/mob/living/simple_animal/hostile/mimic/copy/ranged/OpenFire(var/the_target)
	if(Zapgun)
		if(Zapgun.power_supply) //sanity
			var/obj/item/ammo_casing/energy/shot = Zapgun.ammo_type[Zapgun.select]
			if(Zapgun.power_supply.charge >= shot.e_cost) //if she can zap
				Zapgun.power_supply.use(shot.e_cost)
				Zapgun.update_icon()
				..() //zap 'em
	if(Zapstick)
		if(Zapstick.charges)
			Zapstick.charges--
			Zapstick.update_icon()
			..()
	if(Pewgun)
		if(Pewgun.chambered)
			if(Pewgun.chambered.BB)
				qdel(Pewgun.chambered.BB)
				Pewgun.chambered.BB = null //because qdel takes too long, ensures icon update
				Pewgun.chambered.update_icon()
				..()
			else
				visible_message("The [src] clears a jam!")
			Pewgun.chambered.loc = src.loc //rip revolver immersions, blame shotgun snowflake procs
			Pewgun.chambered = null
			if(Pewgun.magazine && Pewgun.magazine.stored_ammo.len)
				Pewgun.chambered = Pewgun.magazine.get_round(0)
				Pewgun.chambered.loc = Pewgun
			Pewgun.update_icon()
		else if(Pewgun.magazine && Pewgun.magazine.stored_ammo.len) //only true for pumpguns i think
			Pewgun.chambered = Pewgun.magazine.get_round(0)
			Pewgun.chambered.loc = Pewgun
			visible_message("The [src] cocks itself!")

	else //if somehow the mimic has no weapon
		src.ranged = 0 //BANZAIIII
		src.retreat_distance = 0
		src.minimum_distance = 1
	src.icon_state = TrueGun.icon_state
	src.icon_living = TrueGun.icon_state
	return