code:
/mob/living/simple_animal/hostile/asteroid/
	vision_range = 2
	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("mining")
	environment_smash = 2
	minbodytemp = 0
	heat_damage_per_tick = 20
	response_help = "pokes"
	response_disarm = "shoves"
	response_harm = "strikes"
	status_flags = 0
	a_intent = "harm"
	var/throw_message = "bounces off of"
	var/icon_aggro = null // for swapping to when we get aggressive
	see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING
	see_in_dark = 14

/mob/living/simple_animal/hostile/asteroid/Aggro()
	..()
	icon_state = icon_aggro

/mob/living/simple_animal/hostile/asteroid/LoseAggro()
	..()
	icon_state = icon_living

/mob/living/simple_animal/hostile/asteroid/bullet_act(var/obj/item/projectile/P)//Reduces damage from most projectiles to curb off-screen kills
	if(!stat)
		Aggro()
	if(P.damage < 30 && P.damage_type != BRUTE)
		P.damage = (P.damage / 3)
		visible_message("[P] has a reduced effect on [src]!")
	..()

/mob/living/simple_animal/hostile/asteroid/hitby(atom/movable/AM)//No floor tiling them to death, wiseguy
	if(istype(AM, /obj/item))
		var/obj/item/T = AM
		if(!stat)
			Aggro()
		if(T.throwforce <= 20)
			visible_message("The [T.name] [src.throw_message] [src.name]!")
			return
	..()

/mob/living/simple_animal/hostile/asteroid/basilisk
	name = "basilisk"
	desc = "A territorial beast, covered in a thick shell that absorbs energy. Its stare causes victims to freeze from the inside."
	icon = 'icons/mob/animal.dmi'
	icon_state = "Basilisk"
	icon_living = "Basilisk"
	icon_aggro = "Basilisk_alert"
	icon_dead = "Basilisk_dead"
	icon_gib = "syndicate_gib"
	move_to_delay = 20
	projectiletype = /obj/item/projectile/temp/basilisk
	projectilesound = 'sound/weapons/pierce.ogg'
	ranged = 1
	ranged_message = "stares"
	ranged_cooldown_cap = 20
	throw_message = "does nothing against the hard shell of"
	vision_range = 2
	speed = 3
	maxHealth = 200
	health = 200
	harm_intent_damage = 5
	melee_damage_lower = 12
	melee_damage_upper = 12
	attacktext = "bites into"
	a_intent = "harm"
	attack_sound = 'sound/weapons/bladeslice.ogg'
	ranged_cooldown_cap = 4
	aggro_vision_range = 9
	idle_vision_range = 2
	turns_per_move = 5

/obj/item/projectile/temp/basilisk
	name = "freezing blast"
	icon_state = "ice_2"
	damage = 0
	damage_type = BURN
	nodamage = 1
	flag = "energy"
	temperature = 50

/mob/living/simple_animal/hostile/asteroid/basilisk/GiveTarget(var/new_target)
	target = new_target
	if(target != null)
		Aggro()
		stance = HOSTILE_STANCE_ATTACK
		if(isliving(target))
			var/mob/living/L = target
			if(L.bodytemperature > 261)
				L.bodytemperature = 261
				visible_message("The [src.name]'s stare chills [L.name] to the bone!")
	return

/mob/living/simple_animal/hostile/asteroid/basilisk/ex_act(severity, target)
	switch(severity)
		if(1.0)
			gib()
		if(2.0)
			adjustBruteLoss(140)
		if(3.0)
			adjustBruteLoss(110)

/mob/living/simple_animal/hostile/asteroid/basilisk/Die()
	var/counter
	for(counter=0, counter<2, counter++)
		var/obj/item/weapon/ore/diamond/D = new /obj/item/weapon/ore/diamond(src.loc)
		D.layer = 4.1
	..()

/mob/living/simple_animal/hostile/asteroid/goldgrub
	name = "goldgrub"
	desc = "A worm that grows fat from eating everything in its sight. Seems to enjoy precious metals and other shiny things, hence the name."
	icon = 'icons/mob/animal.dmi'
	icon_state = "Goldgrub"
	icon_living = "Goldgrub"
	icon_aggro = "Goldgrub_alert"
	icon_dead = "Goldgrub_dead"
	icon_gib = "syndicate_gib"
	vision_range = 2
	aggro_vision_range = 9
	idle_vision_range = 2
	move_to_delay = 5
	friendly = "harmlessly rolls into"
	maxHealth = 45
	health = 45
	harm_intent_damage = 5
	melee_damage_lower = 0
	melee_damage_upper = 0
	attacktext = "barrels into"
	a_intent = "help"
	throw_message = "sinks in slowly, before being pushed out of "
	status_flags = CANPUSH
	search_objects = 1
	wanted_objects = list(/obj/item/weapon/ore/diamond, /obj/item/weapon/ore/gold, /obj/item/weapon/ore/silver,
						  /obj/item/weapon/ore/uranium)

	var/list/ore_types_eaten = list()
	var/alerted = 0
	var/ore_eaten = 1
	var/chase_time = 100

/mob/living/simple_animal/hostile/asteroid/goldgrub/GiveTarget(var/new_target)
	target = new_target
	if(target != null)
		if(istype(target, /obj/item/weapon/ore))
			visible_message("The [src.name] looks at [target.name] with hungry eyes.")
			stance = HOSTILE_STANCE_ATTACK
			return
		if(isliving(target))
			Aggro()
			stance = HOSTILE_STANCE_ATTACK
			visible_message("The [src.name] tries to flee from [target.name]!")
			retreat_distance = 10
			minimum_distance = 10
			Burrow()
			return
	return

/mob/living/simple_animal/hostile/asteroid/goldgrub/AttackingTarget()
	if(istype(target, /obj/item/weapon/ore))
		EatOre(target)
		return
	..()

/mob/living/simple_animal/hostile/asteroid/goldgrub/proc/EatOre(var/atom/targeted_ore)
	for(var/obj/item/weapon/ore/O in targeted_ore.loc)
		ore_eaten++
		if(!(O.type in ore_types_eaten))
			ore_types_eaten += O.type
		qdel(O)
	if(ore_eaten > 5)//Limit the scope of the reward you can get, or else things might get silly
		ore_eaten = 5
	visible_message("The ore was swallowed whole!")

/mob/living/simple_animal/hostile/asteroid/goldgrub/proc/Burrow()//Begin the chase to kill the goldgrub in time
	if(!alerted)
		alerted = 1
		spawn(chase_time)
		if(alerted)
			visible_message("The [src.name] buries into the ground, vanishing from sight!")
			qdel(src)

/mob/living/simple_animal/hostile/asteroid/goldgrub/proc/Reward()
	if(!ore_eaten || ore_types_eaten.len == 0)
		return
	visible_message("[src] spits up the contents of its stomach before dying!")
	var/counter
	for(var/R in ore_types_eaten)
		for(counter=0, counter < ore_eaten, counter++)
			new R(src.loc)
	ore_types_eaten.Cut()
	ore_eaten = 0

/mob/living/simple_animal/hostile/asteroid/goldgrub/bullet_act(var/obj/item/projectile/P)
	visible_message("The [P.name] was repelled by [src.name]'s girth!")
	return

/mob/living/simple_animal/hostile/asteroid/goldgrub/Die()
	alerted = 0
	Reward()
	..()

/mob/living/simple_animal/hostile/asteroid/goldgrub/adjustBruteLoss(var/damage)
	idle_vision_range = 9
	..()

/mob/living/simple_animal/hostile/asteroid/hivelord
	name = "hivelord"
	desc = "A truly alien creature, it is a mass of unknown organic material, constantly fluctuating. When attacking, pieces of it split off and attack in tandem with the original."
	icon = 'icons/mob/animal.dmi'
	icon_state = "Hivelord"
	icon_living = "Hivelord"
	icon_aggro = "Hivelord_alert"
	icon_dead = "Hivelord_dead"
	icon_gib = "syndicate_gib"
	mouse_opacity = 2
	move_to_delay = 14
	ranged = 1
	vision_range = 5
	aggro_vision_range = 9
	idle_vision_range = 5
	speed = 3
	maxHealth = 75
	health = 75
	harm_intent_damage = 5
	melee_damage_lower = 0
	melee_damage_upper = 0
	attacktext = "lashes out at"
	throw_message = "falls right through the strange body of the"
	ranged_cooldown = 0
	ranged_cooldown_cap = 0
	environment_smash = 0
	retreat_distance = 3
	minimum_distance = 3
	pass_flags = PASSTABLE

/mob/living/simple_animal/hostile/asteroid/hivelord/OpenFire(var/the_target)
	var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood(src.loc)
	A.GiveTarget(target)
	A.friends = friends
	A.faction = faction
	return

/mob/living/simple_animal/hostile/asteroid/hivelord/AttackingTarget()
	OpenFire()

/mob/living/simple_animal/hostile/asteroid/hivelord/Die()
	new /obj/item/asteroid/hivelord_core(src.loc)
	mouse_opacity = 1
	..()

/obj/item/asteroid/hivelord_core
	name = "hivelord remains"
	desc = "All that remains of a hivelord, it seems to be what allows it to break pieces of itself off without being hurt... its healing properties will soon become inert if not used quickly. Try not to think about what you're eating."
	icon = 'icons/obj/food/food.dmi'
	icon_state = "boiledrorocore"
	var/inert = 0
	var/life = 120
	var/preserved = 0

/obj/item/asteroid/hivelord_core/New()
//	spawn(1200)
//		inert = 1
//		desc = "The remains of a hivelord that have become useless, having been left alone too long after being harvested."

///replaces 271 and below

/obj/item/asteroid/hivelord_core/New()
	..()
	SSobj.processing += src

/obj/item/asteroid/hivelord_core/Destroy()
	SSobj.processing -= src
	..()

/obj/item/asteroid/hivelord_core/process()
	if(preserved)
		return
	life--
	if(life <= 0)
		SSobj.processing -= src
		inert = 1
		name = "inert [initial(name)]"
		desc = "The remains of a hivelord that have become useless, having been left alone too long after being harvested."

/obj/item/asteroid/hivelord_core/attack(mob/living/M as mob, mob/living/user as mob)
	if(ishuman(M))
		var/mob/living/carbon/human/H = M
		if(inert)
			user << "[src] have become inert, its healing properties are no more."
			return
		else
			if(H.stat == DEAD)
				user << "[src] are useless on the dead."
				return
			if(H != user)
				H.visible_message("[user] forces [H] to eat [src]... they quickly regenerate all injuries!")
			else
				user << "You chomp into [src], barely managing to hold it down, but feel amazingly refreshed in mere moments."
			playsound(src.loc,'sound/items/eatfood.ogg', rand(10,50), 1)
			H.revive()
			H.drop_item()
			qdel(src)
	..()

/mob/living/simple_animal/hostile/asteroid/hivelordbrood
	name = "hivelord brood"
	desc = "A fragment of the original Hivelord, rallying behind its original. One isn't much of a threat, but..."
	icon = 'icons/mob/animal.dmi'
	icon_state = "Hivelordbrood"
	icon_living = "Hivelordbrood"
	icon_aggro = "Hivelordbrood"
	icon_dead = "Hivelordbrood"
	icon_gib = "syndicate_gib"
	mouse_opacity = 2
	move_to_delay = 1
	friendly = "buzzes near"
	vision_range = 10
	speed = 3
	maxHealth = 1
	health = 1
	harm_intent_damage = 5
	melee_damage_lower = 2
	melee_damage_upper = 2
	attacktext = "slashes"
	throw_message = "falls right through the strange body of the"
	environment_smash = 0
	pass_flags = PASSTABLE

/mob/living/simple_animal/hostile/asteroid/hivelordbrood/New()
	..()
	spawn(100)
		qdel(src)

/mob/living/simple_animal/hostile/asteroid/hivelordbrood/Die()
	qdel(src)

/mob/living/simple_animal/hostile/asteroid/goliath
	name = "goliath"
	desc = "A massive beast that uses long tentacles to ensare its prey, threatening them is not advised under any conditions."
	icon = 'icons/mob/animal.dmi'
	icon_state = "Goliath"
	icon_living = "Goliath"
	icon_aggro = "Goliath_alert"
	icon_dead = "Goliath_dead"
	icon_gib = "syndicate_gib"
	attack_sound = 'sound/weapons/punch4.ogg'
	mouse_opacity = 2
	move_to_delay = 40
	ranged = 1
	ranged_cooldown = 2 //By default, start the Goliath with his cooldown off so that people can run away quickly on first sight
	ranged_cooldown_cap = 8
	friendly = "wails at"
	vision_range = 4
	speed = 3
	maxHealth = 300
	health = 300
	harm_intent_damage = 0
	melee_damage_lower = 25
	melee_damage_upper = 25
	attacktext = "pulverizes"
	throw_message = "does nothing to the rocky hide of the"
	aggro_vision_range = 9
	idle_vision_range = 5
	anchored = 1 //Stays anchored until death as to be unpullable
	mob_size = MOB_SIZE_LARGE
	var/pre_attack = 0

/mob/living/simple_animal/hostile/asteroid/goliath/Life()
	..()
	handle_preattack()

/mob/living/simple_animal/hostile/asteroid/goliath/proc/handle_preattack()
	if(ranged_cooldown <= 2 && !pre_attack)
		pre_attack++
	if(!pre_attack || stat || stance == HOSTILE_STANCE_IDLE)
		return
	icon_state = "Goliath_preattack"

/mob/living/simple_animal/hostile/asteroid/goliath/revive()
	anchored = 1
	..()

/mob/living/simple_animal/hostile/asteroid/goliath/Die()
	anchored = 0
	..()

/mob/living/simple_animal/hostile/asteroid/goliath/OpenFire()
	var/tturf = get_turf(target)
	if(get_dist(src, target) <= 7)//Screen range check, so you can't get tentacle'd offscreen
		visible_message("The [src.name] digs its tentacles under [target.name]!")
		new /obj/effect/goliath_tentacle/original(tturf)
		ranged_cooldown = ranged_cooldown_cap
		icon_state = icon_aggro
		pre_attack = 0
	return

/mob/living/simple_animal/hostile/asteroid/goliath/adjustBruteLoss(var/damage)
	ranged_cooldown--
	handle_preattack()
	..()

/mob/living/simple_animal/hostile/asteroid/goliath/Aggro()
	vision_range = aggro_vision_range
	handle_preattack()
	if(icon_state != icon_aggro)
		icon_state = icon_aggro
	return

/obj/effect/goliath_tentacle/
	name = "Goliath tentacle"
	icon = 'icons/mob/animal.dmi'
	icon_state = "Goliath_tentacle"
	var/latched = 0

/obj/effect/goliath_tentacle/New()
	var/turftype = get_turf(src)
	if(istype(turftype, /turf/simulated/mineral))
		var/turf/simulated/mineral/M = turftype
		M.gets_drilled()
	spawn(20)
		Trip()

/obj/effect/goliath_tentacle/original

/obj/effect/goliath_tentacle/original/New()
	for(var/obj/effect/goliath_tentacle/original/O in loc)//No more GG NO RE from 2+ goliaths simultaneously tentacling you
		if(O != src)
			qdel(src)
	var/list/directions = cardinal.Copy()
	var/counter
	for(counter = 1, counter <= 3, counter++)
		var/spawndir = pick(directions)
		directions -= spawndir
		var/turf/T = get_step(src,spawndir)
		new /obj/effect/goliath_tentacle(T)
	..()

/obj/effect/goliath_tentacle/proc/Trip()
	for(var/mob/living/M in src.loc)
		M.Stun(5)
		M.adjustBruteLoss(rand(10,15))
		if(!M)
			continue //If the mob got deleted, we don't want to process it anymore
		latched = 1
		visible_message("The [src.name] grabs hold of [M.name]!")
	if(!latched)
		qdel(src)
	else
		spawn(50)
			qdel(src)

/mob/living/simple_animal/hostile/asteroid/goliath/Die()
	var/obj/item/asteroid/goliath_hide/G = new /obj/item/asteroid/goliath_hide(src.loc)
	G.layer = 4.1
	..()

/obj/item/asteroid/goliath_hide
	name = "goliath hide plates"
	desc = "Pieces of a goliath's rocky hide, these might be able to make your suit a bit more durable to attack from the local fauna."
	icon = 'icons/obj/items.dmi'
	icon_state = "goliath_hide"
	flags = NOBLUDGEON
	w_class = 3
	layer = 4

/obj/item/asteroid/goliath_hide/afterattack(atom/target, mob/user, proximity_flag)
	if(proximity_flag)
		if(istype(target, /obj/item/clothing/suit/space/hardsuit/mining) || istype(target, /obj/item/clothing/head/helmet/space/hardsuit/mining))
			var/obj/item/clothing/C = target
			var/list/current_armor = C.armor
			if(current_armor.["melee"] < 80)
				current_armor.["melee"] = min(current_armor.["melee"] + 10, 80)
				user << "You strengthen [target], improving its resistance against melee attacks."
				qdel(src)
			else
				user << "You can't improve [C] any further."
				return
		if(istype(target, /obj/mecha/working/ripley))
			var/obj/mecha/D = target
			var/list/damage_absorption = D.damage_absorption
			if(damage_absorption.["brute"] > 0.3)
				damage_absorption.["brute"] = max(damage_absorption.["brute"] - 0.1, 0.3)
				user << "You strengthen [target], improving its resistance against melee attacks."
				qdel(src)
				if(D.icon_state == "ripley-open")
					D.overlays += image("icon"="mecha.dmi", "icon_state"="ripley-g-open")
					D.desc = "Autonomous Power Loader Unit. Its armour is enhanced with some goliath hide plates."
				else
					user << "You can't add armour onto the mech while someone is inside!"
				if(damage_absorption.["brute"] == 0.3)
					if(D.icon_state == "ripley-open")
						D.overlays += image("icon"="mecha.dmi", "icon_state"="ripley-g-full-open")
						D.desc = "Autonomous Power Loader Unit. It's wearing a fearsome carapace entirely composed of goliath hide plates - the pilot must be an experienced monster hunter."
					else
						user << "You can't add armour onto the mech while someone is inside!"
			else
				user << "You can't improve [D] any further."
				return


code:
/mob/living/simple_animal/hostile/mushroom
	name = "walking mushroom"
	desc = "It's a massive mushroom... with legs?"
	icon_state = "mushroom_color"
	icon_living = "mushroom_color"
	icon_dead = "mushroom_dead"
	speak_chance = 0
	turns_per_move = 1
	maxHealth = 10
	health = 10
	meat_type = /obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice
	meat_amount = 1
	response_help  = "pets"
	response_disarm = "gently pushes aside"
	response_harm   = "whacks"
	harm_intent_damage = 5
	melee_damage_lower = 1
	melee_damage_upper = 1
	attack_same = 2
	attacktext = "chomps"
	faction = list("mushroom")
	environment_smash = 0
	stat_attack = 2
	mouse_opacity = 1
	speed = 1
	ventcrawler = 2
	robust_searching = 1
	var/powerlevel = 0 //Tracks our general strength level gained from eating other shrooms
	var/bruised = 0 //If someone tries to cheat the system by attacking a shroom to lower its health, punish them so that it wont award levels to shrooms that eat it
	var/recovery_cooldown = 0 //So you can't repeatedly revive it during a fight
	var/faint_ticker = 0 //If we hit three, another mushroom's gonna eat us
	var/image/cap_living = null //Where we store our cap icons so we dont generate them constantly to update our icon
	var/image/cap_dead = null

/mob/living/simple_animal/hostile/mushroom/examine(mob/user)
	..()
	if(health >= maxHealth)
		user << "It looks healthy."
	else
		user << "It looks like it's been roughed up."

/mob/living/simple_animal/hostile/mushroom/Life()
	..()
	if(!stat)//Mushrooms slowly regenerate if conscious, for people who want to save them from being eaten
		health = min(health+2, maxHealth)

/mob/living/simple_animal/hostile/mushroom/New()//Makes every shroom a little unique
	melee_damage_lower += rand(3, 5)
	melee_damage_upper += rand(10,20)
	maxHealth += rand(40,60)
	move_to_delay = rand(3,11)
	var/cap_color = rgb(rand(0, 255), rand(0, 255), rand(0, 255))
	cap_living = image('icons/mob/animal.dmi',icon_state = "mushroom_cap")
	cap_dead = image('icons/mob/animal.dmi',icon_state = "mushroom_cap_dead")
	cap_living.color = cap_color
	cap_dead.color = cap_color
	UpdateMushroomCap()
	health = maxHealth
	..()

/mob/living/simple_animal/hostile/mushroom/adjustBruteLoss(var/damage)//Possibility to flee from a fight just to make it more visually interesting
	if(!retreat_distance && prob(33))
		retreat_distance = 5
		spawn(30)
			retreat_distance = null
	..()

/mob/living/simple_animal/hostile/mushroom/attack_animal(var/mob/living/L)
	if(istype(L, /mob/living/simple_animal/hostile/mushroom) && stat == DEAD)
		var/mob/living/simple_animal/hostile/mushroom/M = L
		if(faint_ticker < 2)
			M.visible_message("[M] chews a bit on [src].")
			faint_ticker++
			return
		M.visible_message("[M] devours [src]!")
		var/level_gain = (powerlevel - M.powerlevel)
		if(level_gain >= -1 && !bruised && !M.ckey)//Player shrooms can't level up to become robust gods.
			if(level_gain < 1)//So we still gain a level if two mushrooms were the same level
				level_gain = 1
			M.LevelUp(level_gain)
		M.health = M.maxHealth
		qdel(src)
	..()

/mob/living/simple_animal/hostile/mushroom/revive()
	..()
	icon_state = "mushroom_color"
	UpdateMushroomCap()

/mob/living/simple_animal/hostile/mushroom/Die()
	visible_message("[src] fainted.")
	..()
	UpdateMushroomCap()

/mob/living/simple_animal/hostile/mushroom/proc/UpdateMushroomCap()
	overlays.Cut()
	if(health == 0)
		overlays += cap_dead
	else
		overlays += cap_living

/mob/living/simple_animal/hostile/mushroom/proc/Recover()
	visible_message("[src] slowly begins to recover.")
	health = 5
	faint_ticker = 0
	icon_state = icon_living
	UpdateMushroomCap()
	recovery_cooldown = 1
	spawn(300)
		recovery_cooldown = 0

/mob/living/simple_animal/hostile/mushroom/proc/LevelUp(var/level_gain)
	if(powerlevel <= 9)
		powerlevel += level_gain
		if(prob(25))
			melee_damage_lower += (level_gain * rand(1,5))
		else
			melee_damage_upper += (level_gain * rand(1,5))
		maxHealth += (level_gain * rand(1,5))
	health = maxHealth //They'll always heal, even if they don't gain a level, in case you want to keep this shroom around instead of harvesting it

/mob/living/simple_animal/hostile/mushroom/proc/Bruise()
	if(!bruised && !stat)
		src.visible_message("The [src.name] was bruised!")
		bruised = 1

/mob/living/simple_animal/hostile/mushroom/attackby(obj/item/I as obj, mob/user as mob, params)
	if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom))
		if(stat == DEAD && !recovery_cooldown)
			Recover()
			qdel(I)
		else
			user << "[src] won't eat it!"
		return
	if(I.force)
		Bruise()
	..()

/mob/living/simple_animal/hostile/mushroom/attack_hand(mob/living/carbon/human/M as mob)
	..()
	if(M.a_intent == "harm")
		Bruise()

/mob/living/simple_animal/hostile/mushroom/hitby(atom/movable/AM)
	..()
	if(istype(AM, /obj/item))
		var/obj/item/T = AM
		if(T.throwforce)
			Bruise()

/mob/living/simple_animal/hostile/mushroom/bullet_act()
	..()
	Bruise()

/mob/living/simple_animal/hostile/mushroom/harvest()
	var/counter
	for(counter=0, counter<=powerlevel, counter++)
		var/obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice/S = new /obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice(src.loc)
		S.reagents.add_reagent("mushroomhallucinogen", powerlevel)
		S.reagents.add_reagent("doctorsdelight", powerlevel)
		S.reagents.add_reagent("synaptizine", powerlevel)
	qdel(src)

license: mit


code:
/mob/living/simple_animal/hostile/pirate
	name = "Pirate"
	desc = "Does what he wants cause a pirate is free."
	icon_state = "piratemelee"
	icon_living = "piratemelee"
	icon_dead = "piratemelee_dead"
	speak_chance = 0
	turns_per_move = 5
	response_help = "pushes"
	response_disarm = "shoves"
	response_harm = "hits"
	speed = 0
	stop_automated_movement_when_pulled = 0
	maxHealth = 100
	health = 100

	harm_intent_damage = 5
	melee_damage_lower = 30
	melee_damage_upper = 30
	attacktext = "slashes"
	attack_sound = 'sound/weapons/bladeslice.ogg'

	min_oxy = 5
	max_oxy = 0
	min_tox = 0
	max_tox = 1
	min_co2 = 0
	max_co2 = 5
	min_n2 = 0
	max_n2 = 0
	unsuitable_atmos_damage = 15
	var/corpse = /obj/effect/landmark/mobcorpse/pirate
	var/weapon1 = /obj/item/weapon/melee/energy/sword/pirate

	faction = list("pirate")

/mob/living/simple_animal/hostile/pirate/ranged
	name = "Pirate Gunner"
	icon_state = "pirateranged"
	icon_living = "pirateranged"
	icon_dead = "piratemelee_dead"
	projectilesound = 'sound/weapons/laser.ogg'
	ranged = 1
	rapid = 1
	retreat_distance = 5
	minimum_distance = 5
	projectiletype = /obj/item/projectile/beam
	corpse = /obj/effect/landmark/mobcorpse/pirate/ranged
	weapon1 = /obj/item/weapon/gun/energy/laser

/mob/living/simple_animal/hostile/pirate/Die()
	..()
	if(corpse)
		new corpse (src.loc)
	if(weapon1)
		new weapon1 (src.loc)
	qdel(src)
	return


code:
/mob/living/simple_animal/hostile/retaliate/bat
	name = "Space Bat"
	desc = "A rare breed of bat which roosts in spaceships, probably not vampiric."
	icon_state = "bat"
	icon_living = "bat"
	icon_dead = "bat_dead"
	icon_gib = "bat_dead"
	turns_per_move = 1
	response_help = "brushes aside"
	response_disarm = "flails at"
	response_harm = "hits"
	speak_chance = 0
	stop_automated_movement_when_pulled = 0
	maxHealth = 15
	health = 15
	see_in_dark = 10
	harm_intent_damage = 6
	melee_damage_lower = 6
	melee_damage_upper = 5
	attacktext = "bites"
	pass_flags = PASSTABLE
	faction = list("hostile")
	attack_sound = 'sound/weapons/bite.ogg'
	environment_smash = 0
	ventcrawler = 2
	mob_size = MOB_SIZE_SMALL

	//Space bats need no air to fly in.
	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


code:
/mob/living/simple_animal/hostile/retaliate/clown
	name = "Clown"
	desc = "A denizen of clown planet"
	icon_state = "clown"
	icon_living = "clown"
	icon_dead = "clown_dead"
	icon_gib = "clown_gib"
	speak_chance = 0
	turns_per_move = 5
	response_help = "pokes"
	response_disarm = "gently pushes aside"
	response_harm = "hits"
	speak = list("HONK", "Honk!", "Welcome to clown planet!")
	emote_see = list("honks")
	speak_chance = 1
	a_intent = "harm"
	stop_automated_movement_when_pulled = 0
	maxHealth = 75
	health = 75
	speed = 0
	harm_intent_damage = 8
	melee_damage_lower = 10
	melee_damage_upper = 10
	attacktext = "attacks"
	attack_sound = 'sound/items/bikehorn.ogg'
	environment_smash = 0

	min_oxy = 5
	max_oxy = 0
	min_tox = 0
	max_tox = 1
	min_co2 = 0
	max_co2 = 5
	min_n2 = 0
	max_n2 = 0
	minbodytemp = 270
	maxbodytemp = 370
	heat_damage_per_tick = 15	//amount of damage applied if animal's body temperature is higher than maxbodytemp
	cold_damage_per_tick = 10	//same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp
	unsuitable_atmos_damage = 10


code:
/mob/living/simple_animal/hostile/retaliate
	var/list/enemies = list()

/mob/living/simple_animal/hostile/retaliate/Found(var/atom/A)
	if(isliving(A))
		var/mob/living/L = A
		if(!L.stat)
//			stance = HOSTILE_STANCE_ATTACK
			return L
		else
			enemies -= L
	else if(istype(A, /obj/mecha))
		var/obj/mecha/M = A
		if(M.occupant)
//			stance = HOSTILE_STANCE_ATTACK
			return A

/mob/living/simple_animal/hostile/retaliate/ListTargets()
	if(!enemies.len)
		return list()
	var/list/see = ..()
	see &= enemies // Remove all entries that aren't in enemies
	return see

/mob/living/simple_animal/hostile/retaliate/proc/Retaliate()
	var/list/around = view(src, vision_range)

	for(var/atom/movable/A in around)
		if(A == src)
			continue
		if(isliving(A))
			var/mob/living/M = A
			var/faction_check = 0
			for(var/F in faction)
				if(F in M.faction)
					faction_check = 1
					break
			if(faction_check && attack_same || !faction_check)
				enemies |= M
		else if(istype(A, /obj/mecha))
			var/obj/mecha/M = A
			if(M.occupant)
				enemies |= M
				enemies |= M.occupant

	for(var/mob/living/simple_animal/hostile/retaliate/H in around)
		var/retaliate_faction_check = 0
		for(var/F in faction)
			if(F in H.faction)
				retaliate_faction_check = 1
				break
		if(retaliate_faction_check && !attack_same && !H.attack_same)
			H.enemies |= enemies
	return 0

/mob/living/simple_animal/hostile/retaliate/adjustBruteLoss(var/damage)
	..(damage)
	if(stat == CONSCIOUS)
		Retaliate()


code:
/mob/living/simple_animal/hostile/russian
	name = "Russian"
	desc = "For the Motherland!"
	icon_state = "russianmelee"
	icon_living = "russianmelee"
	icon_dead = "russianmelee_dead"
	icon_gib = "syndicate_gib"
	speak_chance = 0
	turns_per_move = 5
	response_help = "pokes"
	response_disarm = "shoves"
	response_harm = "hits"
	speed = 0
	stop_automated_movement_when_pulled = 0
	maxHealth = 100
	health = 100
	harm_intent_damage = 5
	melee_damage_lower = 15
	melee_damage_upper = 15
	attacktext = "punches"
	a_intent = "harm"
	var/corpse = /obj/effect/landmark/mobcorpse/russian
	var/weapon1 = /obj/item/weapon/kitchenknife
	min_oxy = 5
	max_oxy = 0
	min_tox = 0
	max_tox = 1
	min_co2 = 0
	max_co2 = 5
	min_n2 = 0
	max_n2 = 0
	unsuitable_atmos_damage = 15
	faction = list("russian")
	status_flags = CANPUSH

/mob/living/simple_animal/hostile/russian/ranged
	icon_state = "russianranged"
	icon_living = "russianranged"
	corpse = /obj/effect/landmark/mobcorpse/russian/ranged
	weapon1 = /obj/item/weapon/gun/projectile/revolver/mateba
	ranged = 1
	retreat_distance = 5
	minimum_distance = 5
	projectiletype = /obj/item/projectile/bullet
	projectilesound = 'sound/weapons/Gunshot.ogg'
	casingtype = /obj/item/ammo_casing/a357

/mob/living/simple_animal/hostile/russian/ranged/New()
	if(prob(50) && ispath(weapon1,/obj/item/weapon/gun/projectile/revolver/mateba)) //to preserve varedits
		weapon1 = /obj/item/weapon/gun/projectile/shotgun/boltaction
		casingtype = /obj/item/ammo_casing/a762
	..()

/mob/living/simple_animal/hostile/russian/Die()
	..()
	if(corpse)
		new corpse (src.loc)
	if(weapon1)
		new weapon1 (src.loc)
	qdel(src)
	return


code:
// A mob which only moves when it isn't being watched by living beings.

/mob/living/simple_animal/hostile/statue
	name = "statue" // matches the name of the statue with the flesh-to-stone spell
	desc = "An incredibly lifelike marble carving. Its eyes seems to follow you.." // same as an ordinary statue with the added "eye following you" description
	icon = 'icons/obj/statue.dmi'
	icon_state = "human_male"
	icon_living = "human_male"
	icon_dead = "human_male"
	gender = NEUTER
	a_intent = "harm"

	response_help = "touches"
	response_disarm = "pushes"

	speed = -1
	maxHealth = 50000
	health = 50000

	harm_intent_damage = 70
	melee_damage_lower = 68
	melee_damage_upper = 83
	attacktext = "claws"
	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("statue")
	move_to_delay = 0 // Very fast

	animate_movement = NO_STEPS // Do not animate movement, you jump around as you're a scary statue.

	see_in_dark = 13
	vision_range = 12
	aggro_vision_range = 12
	idle_vision_range = 12

	search_objects = 1 // So that it can see through walls

	sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS
	anchored = 1
	status_flags = GODMODE // Cannot push also

	var/cannot_be_seen = 1
	var/mob/living/creator = null

// No movement while seen code.

/mob/living/simple_animal/hostile/statue/New(loc, var/mob/living/creator)
	..()
	// Give spells
	mob_spell_list += new /obj/effect/proc_holder/spell/aoe_turf/flicker_lights(src)
	mob_spell_list += new /obj/effect/proc_holder/spell/aoe_turf/blindness(src)
	mob_spell_list += new /obj/effect/proc_holder/spell/targeted/night_vision(src)

	// Give nightvision
	see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING

	// Set creator
	if(creator)
		src.creator = creator

/mob/living/simple_animal/hostile/statue/Move(var/turf/NewLoc)
	if(can_be_seen(NewLoc))
		if(client)
			src << "You cannot move, there are eyes on you!"
		return 0
	return ..()

/mob/living/simple_animal/hostile/statue/Life()
	..()
	if(!client && target) // If we have a target and we're AI controlled
		var/mob/watching = can_be_seen()
		// If they're not our target
		if(watching && watching != target)
			// This one is closer.
			if(get_dist(watching, src) > get_dist(target, src))
				LoseTarget()
				GiveTarget(watching)

/mob/living/simple_animal/hostile/statue/AttackingTarget()
	if(can_be_seen(get_turf(loc)))
		if(client)
			src << "You cannot attack, there are eyes on you!"
			return
	else
		..()

/mob/living/simple_animal/hostile/statue/DestroySurroundings()
	if(!can_be_seen(get_turf(loc)))
		..()

/mob/living/simple_animal/hostile/statue/face_atom()
	if(!can_be_seen(get_turf(loc)))
		..()

/mob/living/simple_animal/hostile/statue/proc/can_be_seen(var/turf/destination)
	if(!cannot_be_seen)
		return null
	// Check for darkness
	var/turf/T = get_turf(loc)
	if(T && destination)
		// Don't check it twice if our destination is the tile we are on or we can't even get to our destination
		if((T.get_lumcount() * 10) < 1 && destination.get_lumcount() * 10 < 1) // No one can see us in the darkness, right?
			return null
		if(T == destination)
			destination = null

	// We aren't in darkness, loop for viewers.
	var/list/check_list = list(src)
	if(destination)
		check_list += destination

	// This loop will, at most, loop twice.
	for(var/atom/check in check_list)
		for(var/mob/living/M in viewers(world.view + 1, check) - src)
			if(M.client && CanAttack(M) && !issilicon(M))
				if(!M.eye_blind)
					return M
		for(var/obj/mecha/M in view(world.view + 1, check)) //assuming if you can see them they can see you
			if(M.occupant && M.occupant.client)
				if(!M.occupant.eye_blind)
					return M.occupant
	return null

// Cannot talk

/mob/living/simple_animal/hostile/statue/say()
	return 0

// Turn to dust when gibbed

/mob/living/simple_animal/hostile/statue/gib(var/animation = 0)
	dust(animation)

// Stop attacking clientless mobs

/mob/living/simple_animal/hostile/statue/CanAttack(var/atom/the_target)
	if(isliving(the_target))
		var/mob/living/L = the_target
		if(!L.client && !L.ckey)
			return 0
	return ..()

// Don't attack your creator if there is one

/mob/living/simple_animal/hostile/statue/ListTargets()
	. = ..()
	return . - creator

// Statue powers

// Flicker lights
/obj/effect/proc_holder/spell/aoe_turf/flicker_lights
	name = "Flicker Lights"
	desc = "You will trigger a large amount of lights around you to flicker."

	charge_max = 300
	clothes_req = 0
	range = 14

/obj/effect/proc_holder/spell/aoe_turf/flicker_lights/cast(list/targets)
	for(var/turf/T in targets)
		for(var/obj/machinery/light/L in T)
			L.flicker()
	return

//Blind AOE
/obj/effect/proc_holder/spell/aoe_turf/blindness
	name = "Blindness"
	desc = "Your prey will be momentarily blind for you to advance on them."

	message = "You glare your eyes."
	charge_max = 600
	clothes_req = 0
	range = 10

/obj/effect/proc_holder/spell/aoe_turf/blindness/cast(list/targets)
	for(var/mob/living/L in living_mob_list)
		var/turf/T = get_turf(L.loc)
		if(T && T in targets)
			L.eye_blind = max(L.eye_blind, 4)
	return

//Toggle Night Vision
/obj/effect/proc_holder/spell/targeted/night_vision
	name = "Toggle Nightvision \[ON\]"
	desc = "Toggle your nightvision mode."

	charge_max = 10
	clothes_req = 0

	message = "You toggle your night vision!"
	range = -1
	include_user = 1

/obj/effect/proc_holder/spell/targeted/night_vision/cast(list/targets)
	for(var/mob/living/target in targets)
		if(target.see_invisible == SEE_INVISIBLE_LIVING)
			target.see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING
			name = "Toggle Nightvision \[ON\]"
		else
			target.see_invisible = SEE_INVISIBLE_LIVING
			name = "Toggle Nightvision \[OFF\]"
	return


code:
/mob/living/simple_animal/hostile/syndicate
	name = "Syndicate Operative"
	desc = "Death to Nanotrasen."
	icon_state = "syndicate"
	icon_living = "syndicate"
	icon_dead = "syndicate_dead"
	icon_gib = "syndicate_gib"
	speak_chance = 0
	turns_per_move = 5
	response_help = "pokes"
	response_disarm = "shoves"
	response_harm = "hits"
	speed = 0
	stop_automated_movement_when_pulled = 0
	maxHealth = 100
	health = 100
	harm_intent_damage = 5
	melee_damage_lower = 10
	melee_damage_upper = 10
	attacktext = "punches"
	a_intent = "harm"
	var/corpse = /obj/effect/landmark/mobcorpse/syndicatesoldier
	var/weapon1
	var/weapon2
	min_oxy = 5
	max_oxy = 0
	min_tox = 0
	max_tox = 1
	min_co2 = 0
	max_co2 = 5
	min_n2 = 0
	max_n2 = 0
	unsuitable_atmos_damage = 15
	faction = list("syndicate")
	status_flags = CANPUSH

/mob/living/simple_animal/hostile/syndicate/Die()
	..()
	if(corpse)
		new corpse (src.loc)
	if(weapon1)
		new weapon1 (src.loc)
	if(weapon2)
		new weapon2 (src.loc)
	qdel(src)
	return

///////////////Sword and shield////////////

/mob/living/simple_animal/hostile/syndicate/melee
	melee_damage_lower = 20
	melee_damage_upper = 25
	icon_state = "syndicatemelee"
	icon_living = "syndicatemelee"
	weapon1 = /obj/item/weapon/melee/energy/sword/saber/red
	weapon2 = /obj/item/weapon/shield/energy
	attacktext = "slashes"
	status_flags = 0

/mob/living/simple_animal/hostile/syndicate/melee/attackby(var/obj/item/O as obj, var/mob/user as mob, params)
	if(O.force)
		if(prob(80))
			var/damage = O.force
			if (O.damtype == STAMINA)
				damage = 0
			health -= damage
			visible_message("[user] has attacked [src] with [O]!")
		else
			visible_message("[src] blocks [O] with its shield!")
		playsound(loc, O.hitsound, 25, 1, -1)
	else
		usr << "This weapon is ineffective, it does no damage."
		visible_message("[user] gently taps [src] with [O].")

/mob/living/simple_animal/hostile/syndicate/melee/bullet_act(var/obj/item/projectile/Proj)
	if(!Proj)	return
	if(prob(65))
		if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
			src.health -= Proj.damage
	else
		visible_message("[src] blocks [Proj] with its shield!")
	return 0

/mob/living/simple_animal/hostile/syndicate/melee/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
	icon_state = "syndicatemeleespace"
	icon_living = "syndicatemeleespace"
	name = "Syndicate Commando"
	corpse = /obj/effect/landmark/mobcorpse/syndicatecommando
	speed = 1

/mob/living/simple_animal/hostile/syndicate/melee/space/Process_Spacemove(var/movement_dir = 0)
	return

/mob/living/simple_animal/hostile/syndicate/ranged
	ranged = 1
	rapid = 1
	retreat_distance = 5
	minimum_distance = 5
	icon_state = "syndicateranged"
	icon_living = "syndicateranged"
	casingtype = /obj/item/ammo_casing/c45
	projectilesound = 'sound/weapons/Gunshot_smg.ogg'
	projectiletype = /obj/item/projectile/bullet/midbullet2

	weapon1 = /obj/item/weapon/gun/projectile/automatic/c20r

/mob/living/simple_animal/hostile/syndicate/ranged/space
	icon_state = "syndicaterangedpsace"
	icon_living = "syndicaterangedpsace"
	name = "Syndicate Commando"
	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
	corpse = /obj/effect/landmark/mobcorpse/syndicatecommando
	speed = 1

/mob/living/simple_animal/hostile/syndicate/ranged/space/Process_Spacemove(var/movement_dir = 0)
	return

/mob/living/simple_animal/hostile/viscerator
	name = "viscerator"
	desc = "A small, twin-bladed machine capable of inflicting very deadly lacerations."
	icon_state = "viscerator_attack"
	icon_living = "viscerator_attack"
	pass_flags = PASSTABLE
	health = 15
	maxHealth = 15
	melee_damage_lower = 15
	melee_damage_upper = 15
	attacktext = "cuts"
	attack_sound = 'sound/weapons/bladeslice.ogg'
	faction = list("syndicate")
	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_size = MOB_SIZE_SMALL

/mob/living/simple_animal/hostile/viscerator/Die()
	..()
	visible_message("[src] is smashed into pieces!")
	qdel(src)
	return


code:
/mob/living/simple_animal/hostile/tree
	name = "pine tree"
	desc = "A pissed off tree-like alien. It seems annoyed with the festivities..."
	icon = 'icons/obj/flora/pinetrees.dmi'
	icon_state = "pine_1"
	icon_living = "pine_1"
	icon_dead = "pine_1"
	icon_gib = "pine_1"
	speak_chance = 0
	turns_per_move = 5
	response_help = "brushes"
	response_disarm = "pushes"
	response_harm = "hits"
	speed = 1
	maxHealth = 250
	health = 250
	mob_size = MOB_SIZE_LARGE

	pixel_x = -16

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

	//Space carp aren't affected by atmos.
	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("hostile")

/mob/living/simple_animal/hostile/tree/FindTarget()
	. = ..()
	if(.)
		emote("me", 1, "growls at [.].")

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

/mob/living/simple_animal/hostile/tree/Die()
	..()
	visible_message("[src] is hacked into pieces!")
	new /obj/item/stack/sheet/mineral/wood(loc)
	qdel(src)

/mob/living/simple_animal/hostile/tree/festivus
	name = "festivus pole"
	desc = "serenity now... SERENITY NOW!"
	icon_state = "festivus_pole"
	icon_living = "festivus_pole"
	icon_dead = "festivus_pole"
	icon_gib = "festivus_pole"

/mob/living/simple_animal/hostile/tree/festivus/Die()
	..()
	visible_message("[src] is hacked into pieces!")
	new /obj/item/stack/rods(loc)
	qdel(src)


code:
/* Parrots!
 * Contains
 * 		Defines
 *		Inventory (headset stuff)
 *		Attack responces
 *		AI
 *		Procs / Verbs (usable by players)
 *		Sub-types
 *		Hear & say (the things we do for gimmicks)
 */

/*
 * Defines
 */

//Only a maximum of one action and one intent should be active at any given time.
//Actions
#define PARROT_PERCH 1		//Sitting/sleeping, not moving
#define PARROT_SWOOP 2		//Moving towards or away from a target
#define PARROT_WANDER 4		//Moving without a specific target in mind

//Intents
#define PARROT_STEAL 8		//Flying towards a target to steal it/from it
#define PARROT_ATTACK 16	//Flying towards a target to attack it
#define PARROT_RETURN 32	//Flying towards its perch
#define PARROT_FLEE 64		//Flying away from its attacker

/mob/living/simple_animal/parrot
	name = "parrot"
	desc = "The parrot squaks, \"It's a Parrot! BAWWK!\"" //'
	icon = 'icons/mob/animal.dmi'
	icon_state = "parrot_fly"
	icon_living = "parrot_fly"
	icon_dead = "parrot_dead"
	pass_flags = PASSTABLE

	speak = list("Hi!","Hello!","Cracker?","BAWWWWK george mellons griffing me!")
	speak_emote = list("squawks","says","yells")
	emote_hear = list("squawks.","bawks!")
	emote_see = list("flutters its wings.")

	speak_chance = 1 //1% (1 in 100) chance every tick; So about once per 150 seconds, assuming an average tick is 1.5s
	turns_per_move = 5
	meat_type = /obj/item/weapon/reagent_containers/food/snacks/cracker/
	meat_amount = 1
	melee_damage_upper = 10
	melee_damage_lower = 5

	response_help  = "pets"
	response_disarm = "gently moves aside"
	response_harm   = "swats"
	stop_automated_movement = 1
	a_intent = "harm" //parrots now start "aggressive" since only player parrots will nuzzle.
	attacktext = "chomps"
	friendly = "grooms"
	mob_size = MOB_SIZE_SMALL

	var/parrot_damage_upper = 10
	var/parrot_state = PARROT_WANDER //Hunt for a perch when created
	var/parrot_sleep_max = 25 //The time the parrot sits while perched before looking around. Mosly a way to avoid the parrot's AI in life() being run every single tick.
	var/parrot_sleep_dur = 25 //Same as above, this is the var that physically counts down
	var/parrot_dam_zone = list("chest", "head", "l_arm", "l_leg", "r_arm", "r_leg") //For humans, select a bodypart to attack

	var/parrot_speed = 5 //"Delay in world ticks between movement." according to byond. Yeah, that's BS but it does directly affect movement. Higher number = slower.
	//var/parrot_been_shot = 0 this wasn't working right, and parrots don't survive bullets.((Parrots get a speed bonus after being shot. This will deincrement every Life() and at 0 the parrot will return to regular speed.))

	var/parrot_lastmove = null //Updates/Stores position of the parrot while it's moving
	var/parrot_stuck = 0	//If parrot_lastmove hasnt changed, this will increment until it reaches parrot_stuck_threshold
	var/parrot_stuck_threshold = 10 //if this == parrot_stuck, it'll force the parrot back to wandering

	var/list/speech_buffer = list()
	var/list/available_channels = list()

	//Headset for Poly to yell at engineers :)
	var/obj/item/device/radio/headset/ears = null

	//The thing the parrot is currently interested in. This gets used for items the parrot wants to pick up, mobs it wants to steal from,
	//mobs it wants to attack or mobs that have attacked it
	var/atom/movable/parrot_interest = null

	//Parrots will generally sit on their perch unless something catches their eye.
	//These vars store their preffered perch and if they dont have one, what they can use as a perch
	var/obj/parrot_perch = null
	var/obj/desired_perches = list(/obj/structure/computerframe, 		/obj/structure/displaycase, \
									/obj/structure/filingcabinet,		/obj/machinery/teleport, \
									/obj/machinery/computer,			/obj/machinery/clonepod, \
									/obj/machinery/dna_scannernew,		/obj/machinery/telecomms, \
									/obj/machinery/nuclearbomb,			/obj/machinery/particle_accelerator, \
									/obj/machinery/recharge_station,	/obj/machinery/smartfridge, \
									/obj/machinery/suit_storage_unit)

	//Parrots are kleptomaniacs. This variable ... stores the item a parrot is holding.
	var/obj/item/held_item = null

/mob/living/simple_animal/parrot/New()
	..()
	if(!ears)
		var/headset = pick(/obj/item/device/radio/headset/headset_sec, \
						/obj/item/device/radio/headset/headset_eng, \
						/obj/item/device/radio/headset/headset_med, \
						/obj/item/device/radio/headset/headset_sci, \
						/obj/item/device/radio/headset/headset_cargo)
		ears = new headset(src)

	parrot_sleep_dur = parrot_sleep_max //In case someone decides to change the max without changing the duration var

	verbs.Add(/mob/living/simple_animal/parrot/proc/steal_from_ground, \
			  /mob/living/simple_animal/parrot/proc/steal_from_mob, \
			  /mob/living/simple_animal/parrot/verb/drop_held_item_player, \
			  /mob/living/simple_animal/parrot/proc/perch_player, \
			  /mob/living/simple_animal/parrot/proc/toggle_mode)

/mob/living/simple_animal/parrot/Die()
	if(held_item)
		held_item.loc = src.loc
		held_item = null
	walk(src,0)
	..()

/mob/living/simple_animal/parrot/Stat()
	..()
	if(statpanel("Status"))
		stat("Held Item", held_item)
		stat("Mode",a_intent)

/mob/living/simple_animal/parrot/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq)
	if(speaker != src && prob(20)) //Dont imitate ourselves
		if(speech_buffer.len >= 20)
			speech_buffer -= pick(speech_buffer)
		speech_buffer |= html_decode(raw_message)
	..()

/mob/living/simple_animal/parrot/radio(message, message_mode) //literally copied from human/radio(), but there's no other way to do this. at least it's better than it used to be.
	. = ..()
	if(. != 0)
		return .

	switch(message_mode)
		if(MODE_HEADSET)
			if (ears)
				ears.talk_into(src, message)
			return ITALICS | REDUCE_RANGE

		if(MODE_SECURE_HEADSET)
			if (ears)
				ears.talk_into(src, message, 1)
			return ITALICS | REDUCE_RANGE

		if(MODE_DEPARTMENT)
			if (ears)
				ears.talk_into(src, message, message_mode)
			return ITALICS | REDUCE_RANGE

	if(message_mode in radiochannels)
		if(ears)
			ears.talk_into(src, message, message_mode)
			return ITALICS | REDUCE_RANGE

	return 0

/*
 * Inventory
 */
/mob/living/simple_animal/parrot/show_inv(mob/user)
	user.set_machine(src)
	var/dat = 	"
Inventory of [name]

"
	if(ears)
		dat +=	"
Headset: [ears] (Remove)"
	else
		dat +=	"
Headset: Nothing"

	user << browse(dat, "window=mob[real_name];size=325x500")
	onclose(user, "mob[real_name]")

/mob/living/simple_animal/parrot/Topic(href, href_list)

	//Can the usr physically do this?
	if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
		return

	//Is the usr's mob type able to do this? (lolaliens)
	if(ishuman(usr) || ismonkey(usr) || isrobot(usr) ||  isalienadult(usr))

		//Removing from inventory
		if(href_list["remove_inv"])
			var/remove_from = href_list["remove_inv"]
			switch(remove_from)
				if("ears")
					if(ears)
						if(!stat)
							if(available_channels.len)
								src.say("[pick(available_channels)] BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
							else
								src.say("BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
						ears.loc = src.loc
						ears = null
						for(var/possible_phrase in speak)
							if(copytext(possible_phrase,1,3) in department_radio_keys)
								possible_phrase = copytext(possible_phrase,3)
					else
						usr << "There is nothing to remove from its [remove_from]."
						return

		//Adding things to inventory
		else if(href_list["add_inv"])
			var/add_to = href_list["add_inv"]
			if(!usr.get_active_hand())
				usr << "You have nothing in your hand to put on its [add_to]."
				return
			switch(add_to)
				if("ears")
					if(ears)
						usr << "It's already wearing something."
						return
					else
						var/obj/item/item_to_add = usr.get_active_hand()
						if(!item_to_add)
							return

						if( !istype(item_to_add,  /obj/item/device/radio/headset) )
							usr << "This object won't fit."
							return

						var/obj/item/device/radio/headset/headset_to_add = item_to_add

						usr.drop_item()
						headset_to_add.loc = src
						src.ears = headset_to_add
						usr << "You fit the headset onto [src]."

						clearlist(available_channels)
						for(var/ch in headset_to_add.channels)
							switch(ch)
								if("Engineering")
									available_channels.Add(":e")
								if("Command")
									available_channels.Add(":c")
								if("Security")
									available_channels.Add(":s")
								if("Science")
									available_channels.Add(":n")
								if("Medical")
									available_channels.Add(":m")
								if("Supply")
									available_channels.Add(":u")
								if("Service")
									available_channels.Add(":v")

						if(headset_to_add.translate_binary)
							available_channels.Add(":b")
		else
			..()

/*
 * Attack responces
 */
//Humans, monkeys, aliens
/mob/living/simple_animal/parrot/attack_hand(mob/living/carbon/M as mob)
	..()
	if(client)
		return
	if(!stat && M.a_intent == "harm")

		icon_state = "parrot_fly" //It is going to be flying regardless of whether it flees or attacks

		if(parrot_state == PARROT_PERCH)
			parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched

		parrot_interest = M
		parrot_state = PARROT_SWOOP //The parrot just got hit, it WILL move, now to pick a direction..

		if(M.health < 50) //Weakened mob? Fight back!
			parrot_state |= PARROT_ATTACK
		else
			parrot_state |= PARROT_FLEE		//Otherwise, fly like a bat out of hell!
			drop_held_item(0)
	return

/mob/living/simple_animal/parrot/attack_paw(mob/living/carbon/monkey/M as mob)
	attack_hand(M)

/mob/living/simple_animal/parrot/attack_alien(mob/living/carbon/alien/M as mob)
	attack_hand(M)

//Simple animals
/mob/living/simple_animal/parrot/attack_animal(mob/living/simple_animal/M as mob)
	..() //goodbye immortal parrots

	if(client)
		return

	if(parrot_state == PARROT_PERCH)
		parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched

	if(M.melee_damage_upper > 0 && !stat)
		parrot_interest = M
		parrot_state = PARROT_SWOOP | PARROT_ATTACK //Attack other animals regardless
		icon_state = "parrot_fly"

//Mobs with objects
/mob/living/simple_animal/parrot/attackby(var/obj/item/O as obj, var/mob/living/user as mob, params)
	if(!stat && !client && !istype(O, /obj/item/stack/medical) && !istype(O,/obj/item/weapon/reagent_containers/food/snacks/cracker))
		if(O.force)
			if(parrot_state == PARROT_PERCH)
				parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched

			parrot_interest = user
			parrot_state = PARROT_SWOOP
			if (user.health < 50)
				parrot_state |= PARROT_ATTACK //weakened mob? fight back!
			else
				parrot_state |= PARROT_FLEE
			icon_state = "parrot_fly"
			drop_held_item(0)
	else if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/cracker)) //Poly wants a cracker.
		qdel(O)
		user.drop_item()
		if(health < maxHealth)
			adjustBruteLoss(-10)
		user << "[src] eagerly devours the cracker."
	..()
	return

//Bullets
/mob/living/simple_animal/parrot/bullet_act(var/obj/item/projectile/Proj)
	..()
	if(!stat && !client)
		if(parrot_state == PARROT_PERCH)
			parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched

		parrot_interest = null
		parrot_state = PARROT_WANDER | PARROT_FLEE //Been shot and survived! RUN LIKE HELL!
		//parrot_been_shot += 5
		icon_state = "parrot_fly"
		drop_held_item(0)
	return

/*
 * AI - Not really intelligent, but I'm calling it AI anyway.
 */
/mob/living/simple_animal/parrot/Life()
	..()

	//Sprite and AI update for when a parrot gets pulled
	if(pulledby && stat == CONSCIOUS)
		icon_state = "parrot_fly"
		if(!client)
			parrot_state = PARROT_WANDER
		return

	if(client || stat)
		return //Lets not force players or dead/incap parrots to move

	if(!isturf(src.loc) || !canmove || buckled)
		return //If it can't move, dont let it move. (The buckled check probably isn't necessary thanks to canmove)

//-----SPEECH
	/* Parrot speech mimickry!
	   Phrases that the parrot Hear()s get added to speach_buffer.
	   Every once in a while, the parrot picks one of the lines from the buffer and replaces an element of the 'speech' list.
	   Then it clears the buffer to make sure they dont magically remember something from hours ago. */
	if(speech_buffer.len && prob(10))
		if(speak.len)
			speak.Remove(pick(speak))

		speak.Add(pick(speech_buffer))
		clearlist(speech_buffer)

//-----SLEEPING
	if(parrot_state == PARROT_PERCH)
		if(parrot_perch && parrot_perch.loc != src.loc) //Make sure someone hasnt moved our perch on us
			if(parrot_perch in view(src))
				parrot_state = PARROT_SWOOP | PARROT_RETURN
				icon_state = "parrot_fly"
				return
			else
				parrot_state = PARROT_WANDER
				icon_state = "parrot_fly"
				return

		if(--parrot_sleep_dur) //Zzz
			return

		else
			//This way we only call the stuff below once every [sleep_max] ticks.
			parrot_sleep_dur = parrot_sleep_max

			//Cycle through message modes for the headset
			if(speak.len)
				var/list/newspeak = list()

				if(available_channels.len && src.ears)
					for(var/possible_phrase in speak)

						//50/50 chance to not use the radio at all
						var/useradio = 0
						if(prob(50))
							useradio = 1

						if(copytext(possible_phrase,1,3) in department_radio_keys)
							possible_phrase = "[useradio?pick(available_channels):""][copytext(possible_phrase,3)]" //crop out the channel prefix
						else
							possible_phrase = "[useradio?pick(available_channels):""][possible_phrase]"

						newspeak.Add(possible_phrase)

				else //If we have no headset or channels to use, dont try to use any!
					for(var/possible_phrase in speak)
						if(copytext(possible_phrase,1,3) in department_radio_keys)
							possible_phrase = "[copytext(possible_phrase,3,length(possible_phrase)+1)]" //crop out the channel prefix
						newspeak.Add(possible_phrase)
				speak = newspeak

			//Search for item to steal
			parrot_interest = search_for_item()
			if(parrot_interest)
				emote("me", 1, "looks in [parrot_interest]'s direction and takes flight.")
				parrot_state = PARROT_SWOOP | PARROT_STEAL
				icon_state = "parrot_fly"
			return

//-----WANDERING - This is basically a 'I dont know what to do yet' state
	else if(parrot_state == PARROT_WANDER)
		//Stop movement, we'll set it later
		walk(src, 0)
		parrot_interest = null

		//Wander around aimlessly. This will help keep the loops from searches down
		//and possibly move the mob into a new are in view of something they can use
		if(prob(90))
			step(src, pick(cardinal))
			return

		if(!held_item && !parrot_perch) //If we've got nothing to do.. look for something to do.
			var/atom/movable/AM = search_for_perch_and_item() //This handles checking through lists so we know it's either a perch or stealable item
			if(AM)
				if(istype(AM, /obj/item) || isliving(AM))	//If stealable item
					parrot_interest = AM
					emote("me", 1, "turns and flies towards [parrot_interest].")
					parrot_state = PARROT_SWOOP | PARROT_STEAL
					return
				else	//Else it's a perch
					parrot_perch = AM
					parrot_state = PARROT_SWOOP | PARROT_RETURN
					return
			return

		if(parrot_interest && parrot_interest in view(src))
			parrot_state = PARROT_SWOOP | PARROT_STEAL
			return

		if(parrot_perch && parrot_perch in view(src))
			parrot_state = PARROT_SWOOP | PARROT_RETURN
			return

		else //Have an item but no perch? Find one!
			parrot_perch = search_for_perch()
			if(parrot_perch)
				parrot_state = PARROT_SWOOP | PARROT_RETURN
				return
//-----STEALING
	else if(parrot_state == (PARROT_SWOOP | PARROT_STEAL))
		walk(src,0)
		if(!parrot_interest || held_item)
			parrot_state = PARROT_SWOOP | PARROT_RETURN
			return

		if(!(parrot_interest in view(src)))
			parrot_state = PARROT_SWOOP | PARROT_RETURN
			return

		if(in_range(src, parrot_interest))

			if(isliving(parrot_interest))
				steal_from_mob()

			else //This should ensure that we only grab the item we want, and make sure it's not already collected on our perch
				if(!parrot_perch || parrot_interest.loc != parrot_perch.loc)
					held_item = parrot_interest
					parrot_interest.loc = src
					visible_message("[src] grabs [held_item]!", "You grab [held_item]!", "You hear the sounds of wings flapping furiously.")

			parrot_interest = null
			parrot_state = PARROT_SWOOP | PARROT_RETURN
			return

		walk_to(src, parrot_interest, 1, parrot_speed)
		if(isStuck()) return

		return

//-----RETURNING TO PERCH
	else if(parrot_state == (PARROT_SWOOP | PARROT_RETURN))
		walk(src, 0)
		if(!parrot_perch || !isturf(parrot_perch.loc)) //Make sure the perch exists and somehow isnt inside of something else.
			parrot_perch = null
			parrot_state = PARROT_WANDER
			return

		if(in_range(src, parrot_perch))
			src.loc = parrot_perch.loc
			drop_held_item()
			parrot_state = PARROT_PERCH
			icon_state = "parrot_sit"
			return

		walk_to(src, parrot_perch, 1, parrot_speed)
		if(isStuck()) return

		return

//-----FLEEING
	else if(parrot_state == (PARROT_SWOOP | PARROT_FLEE))
		walk(src,0)
		if(!parrot_interest || !isliving(parrot_interest)) //Sanity
			parrot_state = PARROT_WANDER

		walk_away(src, parrot_interest, 1, parrot_speed)
		/*if(parrot_been_shot > 0)
			parrot_been_shot--  didn't work anyways, and besides, any bullet poly survives isn't worth the speed boost.*/
		if(isStuck()) return

		return

//-----ATTACKING
	else if(parrot_state == (PARROT_SWOOP | PARROT_ATTACK))

		//If we're attacking a nothing, an object, a turf or a ghost for some stupid reason, switch to wander
		if(!parrot_interest || !isliving(parrot_interest))
			parrot_interest = null
			parrot_state = PARROT_WANDER
			return

		var/mob/living/L = parrot_interest
		if(melee_damage_upper == 0)
			melee_damage_upper = parrot_damage_upper
			a_intent = "harm"

		//If the mob is close enough to interact with
		if(in_range(src, parrot_interest))

			//If the mob we've been chasing/attacking dies or falls into crit, check for loot!
			if(L.stat)
				parrot_interest = null
				if(!held_item)
					held_item = steal_from_ground()
					if(!held_item)
						held_item = steal_from_mob() //Apparently it's possible for dead mobs to hang onto items in certain circumstances.
				if(parrot_perch in view(src)) //If we have a home nearby, go to it, otherwise find a new home
					parrot_state = PARROT_SWOOP | PARROT_RETURN
				else
					parrot_state = PARROT_WANDER
				return

			attacktext = pick("claws at", "chomps")
			L.attack_animal(src)//Time for the hurt to begin!
		//Otherwise, fly towards the mob!
		else
			walk_to(src, parrot_interest, 1, parrot_speed)
			if(isStuck()) return

		return
//-----STATE MISHAP
	else //This should not happen. If it does lets reset everything and try again
		walk(src,0)
		parrot_interest = null
		parrot_perch = null
		drop_held_item()
		parrot_state = PARROT_WANDER
		return

/*
 * Procs
 */

/mob/living/simple_animal/parrot/movement_delay()
	if(client && stat == CONSCIOUS && parrot_state != "parrot_fly")
		icon_state = "parrot_fly"
	..()

/mob/living/simple_animal/parrot/proc/isStuck()
	//Check to see if the parrot is stuck due to things like windows or doors or windowdoors
	if(parrot_lastmove)
		if(parrot_lastmove == src.loc)
			if(parrot_stuck_threshold >= ++parrot_stuck) //If it has been stuck for a while, go back to wander.
				parrot_state = PARROT_WANDER
				parrot_stuck = 0
				parrot_lastmove = null
				return 1
		else
			parrot_lastmove = null
	else
		parrot_lastmove = src.loc
	return 0

/mob/living/simple_animal/parrot/proc/search_for_item()
	var/item
	for(var/atom/movable/AM in view(src))
		//Skip items we already stole or are wearing or are too big
		if(parrot_perch && AM.loc == parrot_perch.loc || AM.loc == src)
			continue

		if(istype(AM, /obj/item))
			var/obj/item/I = AM
			if(I.w_class < 2)
				item = I

		else if(iscarbon(AM))
			var/mob/living/carbon/C = AM
			if((C.l_hand && C.l_hand.w_class <= 2) || (C.r_hand && C.r_hand.w_class <= 2))
				item = C
		if(item)
			if(!AStar(loc, get_turf(item), src, /turf/proc/Distance))
				item = null
				continue
			return item
	return null

/mob/living/simple_animal/parrot/proc/search_for_perch()
	for(var/obj/O in view(src))
		for(var/path in desired_perches)
			if(istype(O, path))
				return O
	return null

//This proc was made to save on doing two 'in view' loops seperatly
/mob/living/simple_animal/parrot/proc/search_for_perch_and_item()
	for(var/atom/movable/AM in view(src))
		for(var/perch_path in desired_perches)
			if(istype(AM, perch_path))
				return AM

		//Skip items we already stole or are wearing or are too big
		if(parrot_perch && AM.loc == parrot_perch.loc || AM.loc == src)
			continue

		if(istype(AM, /obj/item))
			var/obj/item/I = AM
			if(I.w_class <= 2)
				return I

		if(iscarbon(AM))
			var/mob/living/carbon/C = AM
			if(C.l_hand && C.l_hand.w_class <= 2 || C.r_hand && C.r_hand.w_class <= 2)
				return  C
	return null

/*
 * Verbs - These are actually procs, but can be used as verbs by player-controlled parrots.
 */
/mob/living/simple_animal/parrot/proc/steal_from_ground()
	set name = "Steal from ground"
	set category = "Parrot"
	set desc = "Grabs a nearby item."

	if(stat)
		return -1

	if(held_item)
		src << "You are already holding [held_item]"
		return 1

	for(var/obj/item/I in view(1,src))
		//Make sure we're not already holding it and it's small enough
		if(I.loc != src && I.w_class <= 2)

			//If we have a perch and the item is sitting on it, continue
			if(!client && parrot_perch && I.loc == parrot_perch.loc)
				continue

			held_item = I
			I.loc = src
			visible_message("[src] grabs [held_item]!", "You grab [held_item]!", "You hear the sounds of wings flapping furiously.")
			return held_item

	src << "There is nothing of interest to take."
	return 0

/mob/living/simple_animal/parrot/proc/steal_from_mob()
	set name = "Steal from mob"
	set category = "Parrot"
	set desc = "Steals an item right out of a person's hand!"

	if(stat)
		return -1

	if(held_item)
		src << "You are already holding [held_item]"
		return 1

	var/obj/item/stolen_item = null

	for(var/mob/living/carbon/C in view(1,src))
		if(C.l_hand && C.l_hand.w_class <= 2)
			stolen_item = C.l_hand

		if(C.r_hand && C.r_hand.w_class <= 2)
			stolen_item = C.r_hand

		if(stolen_item)
			C.unEquip(stolen_item)
			held_item = stolen_item
			stolen_item.loc = src
			visible_message("[src] grabs [held_item] out of [C]'s hand!", "You snag [held_item] out of [C]'s hand!", "You hear the sounds of wings flapping furiously.")
			return held_item

	src << "There is nothing of interest to take.</spawn>"
	return 0

/mob/living/simple_animal/parrot/verb/drop_held_item_player()
	set name = "Drop held item"
	set category = "Parrot"
	set desc = "Drop the item you're holding."

	if(stat)
		return

	src.drop_held_item()

	return

/mob/living/simple_animal/parrot/proc/drop_held_item(var/drop_gently = 1)
	set name = "Drop held item"
	set category = "Parrot"
	set desc = "Drop the item you're holding."

	if(stat)
		return -1

	if(!held_item)
		if(src == usr) //So that other mobs wont make this message appear when they're bludgeoning you.
			src << "You have nothing to drop!"
		return 0

//parrots will eat crackers instead of dropping them
	if(istype(held_item,/obj/item/weapon/reagent_containers/food/snacks/cracker) && (drop_gently))
		qdel(held_item)
		held_item = null
		if(health < maxHealth)
			adjustBruteLoss(-10)
		emote("me", 1, "[src] eagerly downs the cracker.")
		return 1

	if(!drop_gently)
		if(istype(held_item, /obj/item/weapon/grenade))
			var/obj/item/weapon/grenade/G = held_item
			G.loc = src.loc
			G.prime()
			src << "You let go of [held_item]!"
			held_item = null
			return 1

	src << "You drop [held_item]."

	held_item.loc = src.loc
	held_item = null
	return 1

/mob/living/simple_animal/parrot/proc/perch_player()
	set name = "Sit"
	set category = "Parrot"
	set desc = "Sit on a nice comfy perch."

	if(stat || !client)
		return

	if(icon_state == "parrot_fly")
		for(var/atom/movable/AM in view(src,1))
			for(var/perch_path in desired_perches)
				if(istype(AM, perch_path))
					src.loc = AM.loc
					icon_state = "parrot_sit"
					return
	src << "There is no perch nearby to sit on."
	return

/mob/living/simple_animal/parrot/proc/toggle_mode()
	set name = "Toggle mode"
	set category = "Parrot"
	set desc = "Time to bear those claws!"

	if(stat || !client)
		return

	if(melee_damage_upper)
		melee_damage_upper = 0
		a_intent = "help"
	else
		melee_damage_upper = parrot_damage_upper
		a_intent = "harm"
	return

/*
 * Sub-types
 */
/mob/living/simple_animal/parrot/Poly
	name = "Poly"
	desc = "Poly the Parrot. An expert on quantum cracker theory."
	speak = list("Poly wanna cracker!", ":e Check the singlo, you chucklefucks!",":e Wire the solars, you lazy bums!",":e WHO TOOK THE DAMN HARDSUITS?",":e OH GOD ITS FREE CALL THE SHUTTLE")

/mob/living/simple_animal/parrot/Poly/New()
	ears = new /obj/item/device/radio/headset/headset_eng(src)
	available_channels = list(":e")
	..()


code:
//Revenants: based off of wraiths from Goon
//"Ghosts" that are invisible and move like ghosts, cannot take damage while invsible
//Don't hear deadchat and are NOT normal ghosts
//Admin-spawn or random event

/mob/living/simple_animal/revenant
	name = "revenant"
	desc = "A malevolent spirit."
	icon = 'icons/mob/mob.dmi'
	icon_state = "revenant_idle"
	incorporeal_move = 1
	invisibility = INVISIBILITY_OBSERVER
	health = 25
	maxHealth = 25
	see_in_dark = 255
	see_invisible = SEE_INVISIBLE_OBSERVER
	languages = ALL
	response_help   = "passes through"
	response_disarm = "swings at"
	response_harm   = "punches"
	minbodytemp = 0
	maxbodytemp = INFINITY
	harm_intent_damage = 5
	speak_emote = list("hisses", "spits", "growls")
	friendly = "touches"
	status_flags = 0
	wander = 0
	density = 0

	var/essence = 25 //The resource of revenants. Max health is equal to twice this amount
	var/essence_regen_cap = 25 //The regeneration cap of essence (go figure); regenerates every Life() tick up to this amount.
	var/essence_regen = 1 //If the revenant regenerates essence or not; 1 for yes, 0 for no
	var/essence_min = 1 //The minimum amount of essence a revenant can have; by default, it never drops below one
	var/strikes = 2 //How many times a revenant can die before dying for good
	var/revealed = 0 //If the revenant can take damage from normal sources.
	var/inhibited = 0 //If the revenant's abilities are blocked by a chaplain's power.

/mob/living/simple_animal/revenant/Life()
	..()
	if(essence < essence_min)
		essence = essence_min
		if(strikes > 0)
			strikes--
			src << "Your essence has dropped below critical levels. You barely manage to save yourself - [strikes ? "you can't keep this up!" : "next time, it's death."]"
		else if(strikes <= 0)
			src << "NO! No... it's too late, you can feel yourself fading..."
			src.notransform = 1
			src.revealed = 1
			src.invisibility = 0
			playsound(src, 'sound/effects/screech.ogg', 100, 1)
			src.visible_message("The revenant lets out a waning screech as violet mist swirls around its dissolving body!")
			src.icon_state = "revenant_draining"
			sleep(30)
			src.death()
	maxHealth = essence * 2
	if(!revealed)
		health = maxHealth //Heals to full when not revealed
	if(essence_regen && !inhibited && essence < essence_regen_cap) //While inhibited, essence will not regenerate
		essence++

/mob/living/simple_animal/revenant/Process_Spacemove(var/movement_dir = 0)
	return 1 //Mainly to prevent the no-grav effect

/mob/living/simple_animal/revenant/ClickOn(var/atom/A, var/params) //Copypaste from ghost code - revenants can't interact with the world directly.
	if(client.buildmode)
		build_click(src, client.buildmode, params, A)
		return

	var/list/modifiers = params2list(params)
	if(modifiers["middle"])
		MiddleClickOn(A)
		return
	if(modifiers["shift"])
		ShiftClickOn(A)
		return
	if(modifiers["alt"])
		AltClickOn(A)
		return
	if(modifiers["ctrl"])
		CtrlClickOn(A)
		return

	if(world.time <= next_move)
		return
	A.attack_ghost(src)

/mob/living/simple_animal/revenant/say(message)
	return 0 //Revenants cannot speak out loud.

/mob/living/simple_animal/revenant/Stat()
	..()
	if(statpanel("Status"))
		stat(null, "Current essence: [essence]E")

/mob/living/simple_animal/revenant/New()
	..()
	notransform = 1
	spawn(50)
		if(src.mind)
			src.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/revenant_harvest
			src.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/revenant_transmit
			src.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/revenant_light
			src.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/revenant_life_tap
			src.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/revenant_seed_drain
			src.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/revenant_mindspike
			src.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/revenant_mindblast
			notransform = 0
		else
			qdel(src)

/mob/living/simple_animal/revenant/death()
	..(1)
	src.invisibility = 0
	visible_message("[src] pulses with an eldritch purple light as its form unwinds into smoke.")
	ghostize()
	qdel(src)
	return

/mob/living/simple_animal/revenant/attackby(obj/item/W, mob/living/user, params)
	..()
	if(istype(W, /obj/item/weapon/nullrod))
		src.visible_message("The revenant screeches and flails!", \
							"The null rod invokes agony in you! You feel your essence draining away!")
		src.essence -= 25 //hella effective
		src.inhibited = 1
		spawn(30)
			src.inhibited = 0

/obj/effect/proc_holder/spell/proc/essence_check(var/essence_cost, var/silent = 0)
	var/mob/living/simple_animal/revenant/W = usr
	if(W.essence < essence_cost)
		if(!silent)
			W << "You need [essence_cost]E to use [name] but you only have [W.essence]E available. Harvest some more things."
		return 0
	W.essence -= essence_cost
	return 1

/mob/living/simple_animal/revenant/proc/change_essence_amount(var/essence_amt, var/silent = 0, var/source = null, var/mob/living/simple_animal/revenant/user = usr)
	if(!essence_amt)
		return
	user.essence += essence_amt
	if(!silent)
		if(essence_amt >= 0)
			user << "Gained [essence_amt]E from [source]."
		else
			user << "Lost [essence_amt]E."
	return 1


code:
//Harvest Essence: The bread and butter of the revenant. The basic way of harvesting additional essence.
/obj/effect/proc_holder/spell/targeted/revenant_harvest
	name = "Harvest (0E)"
	desc = "Siphons the lingering spectral essence from a human, empowering yourself."
	panel = "Revenant Abilities"
	charge_max = 100 //Short cooldown
	clothes_req = 0
	range = 5
	var/essence_drained = 0
	var/draining
	var/list/drained_mobs = list() //Cannot harvest the same mob twice

/obj/effect/proc_holder/spell/targeted/revenant_harvest/cast(list/targets, var/mob/living/simple_animal/revenant/user = usr)
	if(user.inhibited)
		user << "Something is blocking the use of [src]!"
		charge_counter = charge_max
		return
	for(var/mob/living/carbon/human/target in targets)
		spawn(0)
			if(draining)
				user << "You are already siphoning the essence of a soul!"
				return
			if(target in drained_mobs)
				user << "[target]'s soul is dead and empty."
				return
			if(!target.stat)
				user << "This being's soul is too strong to harvest."
				if(prob(10))
					target << "You feel as if you are being watched."
				return
			draining = 1
			essence_drained = 1
			user << "You search for the still-living soul of [target]."
			sleep(10)
			if(target.ckey)
				user << "Their soul burns with intelligence."
				essence_drained += 3
			if(target.stat == UNCONSCIOUS)
				user << "They still cling to life, but are not powerful enough to resist. A large amount of essence lies unguarded."
				essence_drained += 5
			else if(target.stat == DEAD)
				user << "They have passed on."
				essence_drained += 1
			sleep(20)
			switch(essence_drained)
				if(1 to 2)
					user << "[target] will not yield much essence. Still, every bit counts."
				if(3 to 4)
					user << "[target] will yield an average amount of essence."
				if(5 to INFINITY)
					user << "Such a feast! [target] will yield much essence to you."
			sleep(30)
			user << "You begin siphoning essence from [target]'s soul. You can not move while this is happening."
			if(target.stat != DEAD)
				target << "You feel a horribly unpleasant draining sensation as your grip on life weakens..."
			user.icon_state = "revenant_draining"
			user.notransform = 1
			user.revealed = 1
			user.invisibility = 0
			target.visible_message("[target] suddenly rises slightly into the air, their skin turning an ashy gray.")
			target.Beam(user,icon_state="drain_life",icon='icons/effects/effects.dmi',time=50)
			target.death(0)
			target.visible_message("[target] gently slumps back onto the ground.")
			user.icon_state = "revenant_idle"
			user.change_essence_amount(essence_drained * 5, 0, target)
			user << "[target]'s soul has been considerably weakened and will yield no more essence for the time being."
			user.revealed = 0
			user.notransform = 0
			user.invisibility = INVISIBILITY_OBSERVER
			drained_mobs.Add(target)
			draining = 0

//Transmit: the revemant's only direct way to communicate. Sends a single message silently to a single mob for 5E.
/obj/effect/proc_holder/spell/targeted/revenant_transmit
	name = "Unlock: Transmit (5E)"
	desc = "Telepathically transmits a message to the target."
	panel = "Revenant Abilities (Locked)"
	charge_max = 50
	clothes_req = 0
	range = -1
	include_user = 1
	var/locked = 1

/obj/effect/proc_holder/spell/targeted/revenant_transmit/cast(list/targets, var/mob/living/simple_animal/revenant/user = usr)
	if(user.inhibited)
		user << "Something is blocking the use of [src]!"
		charge_counter = charge_max
		return
	if(locked && essence_check(5, 1))
		usr << "You have unlocked Transmit!"
		name = "Transmit (5E)"
		locked = 0
		charge_counter = charge_max
		panel = "Revenant Abilities"
		range = 7
		include_user = 0
		return
	if(locked)
		charge_counter = charge_max
		return
	if(!essence_check(5))
		charge_counter = charge_max
		return
	for(var/mob/living/M in targets)
		spawn(0)
			var/msg = stripped_input(usr, "What do you wish to tell [M]?", null, "")
			usr << "You transmit to [M]: [msg]"
			M << "Suddenly a strange voice resonates in your head... [msg]"

//Overload Light: Breaks a light that's online and sends out lightning bolts to all nearby people.
/obj/effect/proc_holder/spell/aoe_turf/revenant_light
	name = "Unlock: Overload Light (25E)"
	desc = "Directs a large amount of essence into an electrical light, causing an impressive light show."
	panel = "Revenant Abilities (Locked)"
	charge_max = 300
	clothes_req = 0
	range = 5
	var/locked = 1

/obj/effect/proc_holder/spell/aoe_turf/revenant_light/cast(list/targets, var/mob/living/simple_animal/revenant/user = usr)
	if(user.inhibited)
		user << "Something is blocking the use of [src]!"
		charge_counter = charge_max
		return
	if(locked && essence_check(25, 1))
		user << "You have unlocked Overload Light!"
		name = "Overload Light (25E)"
		panel = "Revenant Abilities"
		locked = 0
		charge_counter = charge_max
		return
	if(locked)
		charge_counter = charge_max
		return
	if(!essence_check(25))
		charge_counter = charge_max
		return
	for(var/turf/T in targets)
		spawn(0)
			for(var/obj/machinery/light/L in T.contents)
				spawn(0)
					if(!L.on)
						return
					L.visible_message("\The [L] suddenly flares brightly and begins to spark!")
					sleep(20)
					for(var/mob/living/M in orange(4, L))
						if(M == user)
							return
						M.Beam(L,icon_state="lightning",icon='icons/effects/effects.dmi',time=5)
						M.electrocute_act(25, "[L.name]")
						playsound(M, 'sound/machines/defib_zap.ogg', 50, 1, -1)
	user.revealed = 1
	user.invisibility = 0
	spawn(30)
		user.revealed = 0
		user.invisibility = INVISIBILITY_OBSERVER

//Life Tap: Drains one 'strike' to gain 50E
/obj/effect/proc_holder/spell/targeted/revenant_life_tap
	name = "Unlock: Life Tap (25E)"
	desc = "Draws from your own life pool to gain more essence. Can only be cast three times."
	panel = "Revenant Abilities (Locked)"
	charge_max = 600
	clothes_req = 0
	range = -1
	include_user = 1
	var/locked = 1

/obj/effect/proc_holder/spell/targeted/revenant_life_tap/cast(list/targets, var/mob/living/simple_animal/revenant/user = usr)
	if(user.inhibited)
		user << "Something is blocking the use of [src]!"
		charge_counter = charge_max
		return
	if(locked && essence_check(25, 1))
		user << "You have unlocked Life Tap!"
		name = "Life Tap (0E)"
		panel = "Revenant Abilities"
		locked = 0
		charge_counter = charge_max
		return
	if(locked)
		charge_counter = charge_max
		return
	for(var/mob/living/simple_animal/revenant/target in targets)
		if(!target.strikes)
			target << "Your life force has grown too weak to life tap again."
		target.strikes--
		target << "You convert your own life into energy.[target.strikes ? "" : " This is the last time you can do this."]"
		target.change_essence_amount(50, 0, "your life pool")

//Seed of Draining: Plants a 'seed' in the target that will slowly siphon essence silently from them.
/obj/effect/proc_holder/spell/targeted/revenant_seed_drain
	name = "Unlock: Seed of Draining (20E)"
	desc = "Corrupts a target with dark energies. Their essence will slowly drain for some time."
	panel = "Revenant Abilities (Locked)"
	charge_max = 1200
	clothes_req = 0
	range = 1 //Adjacent
	include_user = 1
	var/locked = 1
	var/planted = 0

/obj/effect/proc_holder/spell/targeted/revenant_seed_drain/cast(list/targets, var/mob/living/simple_animal/revenant/user = usr)
	if(user.inhibited)
		user << "Something is blocking the use of [src]!"
		charge_counter = charge_max
		return
	if(locked && essence_check(20, 1))
		user << "You have unlocked Seed of Draining!"
		charge_counter = charge_max
		name = "Seed of Draining (20E)"
		locked = 0
		panel = "Revenant Abilities"
		include_user = 0
		return
	if(locked)
		charge_counter = charge_max
		return
	if(!essence_check(20))
		charge_counter = charge_max
		return
	if(planted)
		user << "You are already passively draining essence."
		charge_counter = charge_max
		return
	for(var/mob/living/carbon/human/target in targets)
		if(target.stat == DEAD)
			user << "[target] is dead and will not yield essence."
			charge_counter = charge_max
		user << "You plant a draining seed on [target]."
		planted = 1
		for(var/i = 0, i < 120, i++)
			sleep(10)
			var/mob/living/carbon/human/M = target
			user.essence += rand(0.3, 0.5) //Not a huge amount of essence; at the least it's 36 and at the most it's 60
			M.adjustStaminaLoss(1)
			if(prob(3))
				target << "You feel sapped." //Letting the target know that they're not bugged and losing stamina 4nr
		planted = 0
		user << "The energies siphoning [target] have fallen dormant. You will need to plant a new seed."

//Mind Spike: The typical straight damage ability. Does a decent amount of brute damage and small brain damage.
/obj/effect/proc_holder/spell/targeted/revenant_mindspike
	name = "Unlock: Mind Spike (5E)"
	desc = "Drives a spike of dark energy into the target's mind. Cheap but effective and doesn't take long to cool down."
	panel = "Revenant Abilities (Locked)"
	charge_max = 15
	clothes_req = 0
	range = 3
	include_user = 1
	var/locked = 1

/obj/effect/proc_holder/spell/targeted/revenant_mindspike/cast(list/targets, var/mob/living/simple_animal/revenant/user = usr)
	if(user.inhibited)
		user << "Something is blocking the use of [src]!"
		charge_counter = charge_max
		return
	if(locked && essence_check(5, 1))
		user << "You have unlocked Mind Spike!"
		charge_counter = charge_max
		name = "Mind Spike (5E)"
		locked = 0
		panel = "Revenant Abilities"
		include_user = 0
		return
	if(locked)
		charge_counter = charge_max
		return
	if(!essence_check(5))
		charge_counter = charge_max
		return
	for(var/mob/living/carbon/human/M in targets)
		user << "You drive a spike of energy into [M]'s mind!"
		M << "You feel a spike of pain in your head!"
		M.apply_damage(12, BRUTE, "head")
		M.adjustBrainLoss(3)
		//M << 'sound/effects/mind_blast.ogg'
		if(prob(20) && !M.stat)
			M.Weaken(2)
			M.visible_message("[M] clutches at their head!")
		user.revealed = 1
		user.invisibility = 0
		spawn(10)
			user.revealed = 0
			user.invisibility = INVISIBILITY_OBSERVER

//Mind Blast: A big-hitting damage ability.
/obj/effect/proc_holder/spell/targeted/revenant_mindblast
	name = "Unlock: Mind Blast (25E)"
	desc = "Blasts the target's mind with dark energy, doing a hefty amount of damage."
	panel = "Revenant Abilities (Locked)"
	charge_max = 250
	clothes_req = 0
	range = 3
	include_user = 1
	var/locked = 1

/obj/effect/proc_holder/spell/targeted/revenant_mindblast/cast(list/targets, var/mob/living/simple_animal/revenant/user = usr)
	if(user.inhibited)
		user << "Something is blocking the use of [src]!"
		charge_counter = charge_max
		return
	if(locked && essence_check(25, 1))
		user << "You have unlocked Mind Blast!"
		charge_counter = charge_max
		name = "Mind Blast (25E)"
		locked = 0
		panel = "Revenant Abilities"
		include_user = 0
		return
	if(locked)
		charge_counter = charge_max
		return
	if(!essence_check(25))
		charge_counter = charge_max
		return
	for(var/mob/living/carbon/human/M in targets)
		user << "You blast [M]'s mind with energy!"
		M << "You feel a sudden explosion of agony in your head!"
		M.apply_damage(40, BRUTE, "head")
		M.adjustBrainLoss(20)
		M.emote("scream")
		M.Weaken(4)
		//M << 'sound/effects/mind_blast.ogg'
		user.revealed = 1
		user.invisibility = 0
		spawn(30)
			user.revealed = 0
			user.invisibility = INVISIBILITY_OBSERVER

//Hypnotize: Makes the target fall asleep, make them vulnerable to draining.
/obj/effect/proc_holder/spell/targeted/revenant_hypnotize
	name = "Unlock: Hypnotize (15E)"
	desc = "Causes a target to fall asleep."
	panel = "Revenant Abilities (Locked)"
	charge_max = 900
	clothes_req = 0
	range = 3
	include_user = 1
	var/locked = 1

/obj/effect/proc_holder/spell/targeted/revenant_hypnotize/cast(list/targets, var/mob/living/simple_animal/revenant/user = usr)
	if(user.inhibited)
		user << "Something is blocking the use of [src]!"
		charge_counter = charge_max
		return
	if(locked && essence_check(15, 1))
		user << "You have unlocked Hypnotize!"
		charge_counter = charge_max
		name = "Hypnotize (15E)"
		locked = 0
		panel = "Revenant Abilities"
		include_user = 0
		return
	if(locked)
		charge_counter = charge_max
		return
	if(!essence_check(15))
		charge_counter = charge_max
		return
	for(var/mob/living/carbon/human/M in targets)
		user << "You gently influence [M]'s mind toward deep sleep."
		M << "Tired...  so tired..."
		M.drowsyness += 7
		spawn(70)
			M.sleeping += 12


code:
/datum/round_event_control/revenant
	name = "Spawn Revenant"
	typepath = /datum/round_event/revenant
	max_occurrences = 1
	earliest_start = 18000
	weight = 10

/datum/round_event/revenant
	var/key_of_revenant

/datum/round_event/revenant/proc/get_revenant(var/end_if_fail = 0)
	key_of_revenant = null
	if(!key_of_revenant)
		var/list/candidates = get_candidates(BE_REVENANT)
		if(!candidates.len)
			if(end_if_fail)
				return 0
			return find_revenant()
		var/client/C = pick(candidates)
		key_of_revenant = C.key
	if(!key_of_revenant)
		if(end_if_fail)
			return 0
		return find_revenant()
	var/datum/mind/player_mind = new /datum/mind(key_of_revenant)
	player_mind.active = 1
	var/list/spawn_locs = list()
	for(var/obj/effect/landmark/L in landmarks_list)
		if(isturf(L.loc))
			switch(L.name)
				if("carpspawn")
					spawn_locs += L.loc
	if(!spawn_locs)
		return find_revenant()
	var/mob/living/simple_animal/revenant/revvie = new /mob/living/simple_animal/revenant/(pick(spawn_locs))
	player_mind.transfer_to(revvie)
	player_mind.assigned_role = "MODE"
	player_mind.special_role = "Revenant"
	ticker.mode.traitors |= player_mind
	revvie << 'sound/effects/ghost.ogg'
	message_admins("[key_of_revenant] has been made into a Revenant by an event.")
	log_game("[key_of_revenant] was spawned as a Revenant by an event.")
	player_mind.store_memory("I am a revenant. My spectral form has been empowered. My only goal is to gather essence from the humans of [world.name].")
	revvie << "
"
	revvie << "You are a revenant!"
	revvie << "Your formerly mundane spirit has been infused with alien energies and empowered into a revenant."
	revvie << "You are not dead, not alive, but somewhere in between. You are capable of very limited interaction with both worlds."
	revvie << "You are invincible and invisible to everyone but other ghosts. Some abilities may change this."
	revvie << "Your goal is to gather essence from humans. Your essence passively regenerates up to 25E over time. You can use the Harvest abilities to gather more from corpses."
	//revvie << "Be sure to read the wiki page at https://tgstation13.org/wiki/Revenant !" //Not added yet.
	revvie << "
"
	return 1

/datum/round_event/revenant/start()
	get_revenant()

/datum/round_event/revenant/proc/find_revenant()
	message_admins("Attempted to spawn a Revenant but there was no players available. Will try again momentarily, bear with me...")
	spawn(50)
		if(get_revenant(1))
			message_admins("Hooray! Situation has been resolved, [key_of_revenant] has been spawned as a Revenant.")
			log_game("[key_of_revenant] was spawned as a Revenant by an event.")
			return 0
		message_admins("Unfortunately, no candidates were available for becoming a Revenant. Shutting down. :(")
	return kill()


code:
/mob/living/simple_animal/shade
	name = "Shade"
	real_name = "Shade"
	desc = "A bound spirit"
	icon = 'icons/mob/mob.dmi'
	icon_state = "shade"
	icon_living = "shade"
	icon_dead = "shade_dead"
	maxHealth = 50
	health = 50
	speak_emote = list("hisses")
	emote_hear = list("wails","screeches")
	response_help  = "puts their hand through"
	response_disarm = "flails at"
	response_harm   = "punches"
	melee_damage_lower = 5
	melee_damage_upper = 15
	attacktext = "drains the life from"
	minbodytemp = 0
	maxbodytemp = 4000
	min_oxy = 0
	max_co2 = 0
	max_tox = 0
	speed = -1
	stop_automated_movement = 1
	status_flags = 0
	faction = list("cult")
	status_flags = CANPUSH

/mob/living/simple_animal/shade/Life()
	..()
	if(stat == 2)
		new /obj/item/weapon/ectoplasm (src.loc)
		visible_message("[src] lets out a contented sigh as their form unwinds.")
		ghostize()
		qdel(src)
		return

/mob/living/simple_animal/shade/attackby(var/obj/item/O as obj, var/mob/user as mob, params)  //Marker -Agouri
	if(istype(O, /obj/item/device/soulstone))
		var/obj/item/device/soulstone/SS = O
		SS.transfer_soul("SHADE", src, user)
	else
		..()
	return