code:
/**********************Mineral stacking unit console**************************/

/obj/machinery/mineral/stacking_unit_console
	name = "stacking machine console"
	icon = 'icons/obj/machines/mining_machines.dmi'
	icon_state = "console"
	density = 0
	anchored = 1
	var/obj/machinery/mineral/stacking_machine/machine = null
	var/machinedir = SOUTHEAST

/obj/machinery/mineral/stacking_unit_console/New()
	..()
	spawn(7)
		src.machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir))
		if (machine)
			machine.CONSOLE = src
		else
			qdel(src)

/obj/machinery/mineral/stacking_unit_console/attack_hand(user as mob)

	var/obj/item/stack/sheet/s
	var/dat

	dat += text("Stacking unit console

")

	for(var/O in machine.stack_list)
		s = machine.stack_list[O]
		if(s.amount > 0)
			dat += text("[capitalize(s.name)]: [s.amount] Release
")

	dat += text("
Stacking: [machine.stack_amt]

")

	user << browse("[dat]", "window=console_stacking_machine")

	return

/obj/machinery/mineral/stacking_unit_console/Topic(href, href_list)
	if(..())
		return
	usr.set_machine(src)
	src.add_fingerprint(usr)
	if(href_list["release"])
		if(!(text2path(href_list["release"]) in machine.stack_list)) return //someone tried to spawn materials by spoofing hrefs
		var/obj/item/stack/sheet/inp = machine.stack_list[text2path(href_list["release"])]
		var/obj/item/stack/sheet/out = new inp.type()
		out.amount = inp.amount
		inp.amount = 0
		machine.unload_mineral(out)

	src.updateUsrDialog()
	return

/**********************Mineral stacking unit**************************/

/obj/machinery/mineral/stacking_machine
	name = "stacking machine"
	icon = 'icons/obj/machines/mining_machines.dmi'
	icon_state = "stacker"
	density = 1
	anchored = 1.0
	var/obj/machinery/mineral/stacking_unit_console/CONSOLE
	var/stk_types = list()
	var/stk_amt   = list()
	var/stack_list[0] //Key: Type.  Value: Instance of type.
	var/stack_amt = 50; //ammount to stack before releassing
	input_dir = EAST
	output_dir = WEST

/obj/machinery/mineral/stacking_machine/proc/process_sheet(obj/item/stack/sheet/inp)
	if(!(inp.type in stack_list)) //It's the first of this sheet added
		var/obj/item/stack/sheet/s = new inp.type(src,0)
		s.amount = 0
		stack_list[inp.type] = s
	var/obj/item/stack/sheet/storage = stack_list[inp.type]
	storage.amount += inp.amount //Stack the sheets
	inp.loc = null //Let the old sheet garbage collect
	while(storage.amount > stack_amt) //Get rid of excessive stackage
		var/obj/item/stack/sheet/out = new inp.type()
		out.amount = stack_amt
		unload_mineral(out)
		storage.amount -= stack_amt

/obj/machinery/mineral/stacking_machine/process()
	var/turf/T = get_step(src, input_dir)
	if(T)
		for(var/obj/item/stack/sheet/S in T)
			process_sheet(S)


code:
/**********************Unloading unit**************************/

/obj/machinery/mineral/unloading_machine
	name = "unloading machine"
	icon = 'icons/obj/machines/mining_machines.dmi'
	icon_state = "unloader"
	density = 1
	anchored = 1.0
	input_dir = WEST
	output_dir = EAST

/obj/machinery/mineral/unloading_machine/process()
	var/turf/T = get_step(src,input_dir)
	if(T)
		var/limit
		for(var/obj/structure/ore_box/B in T)
			for (var/obj/item/weapon/ore/O in B)
				B.contents -= O
				unload_mineral(O)
				limit++
				if (limit>=10)
					return
		for(var/obj/item/I in T)
			unload_mineral(I)
			limit++
			if (limit>=10)
				return

license: mit


code:
/**********************Mine areas**************************/

/area/mine
	icon_state = "mining"
	has_gravity = 1

/area/mine/explored
	name = "Mine"
	icon_state = "explored"
	music = null
	always_unpowered = 1
	requires_power = 1
	poweralm = 0
	power_environ = 0
	power_equip = 0
	power_light = 0
	ambientsounds = list('sound/ambience/ambimine.ogg')

/area/mine/unexplored
	name = "Mine"
	icon_state = "unexplored"
	music = null
	always_unpowered = 1
	requires_power = 1
	poweralm = 0
	power_environ = 0
	power_equip = 0
	power_light = 0
	ambientsounds = list('sound/ambience/ambimine.ogg')

/area/mine/lobby
	name = "Mining station"

/area/mine/storage
	name = "Mining station Storage"

/area/mine/production
	name = "Mining Station Starboard Wing"
	icon_state = "mining_production"

/area/mine/abandoned
	name = "Abandoned Mining Station"

/area/mine/living_quarters
	name = "Mining Station Port Wing"
	icon_state = "mining_living"

/area/mine/eva
	name = "Mining Station EVA"
	icon_state = "mining_eva"

/area/mine/maintenance
	name = "Mining Station Communications"

/area/mine/cafeteria
	name = "Mining station Cafeteria"

/area/mine/hydroponics
	name = "Mining station Hydroponics"

/area/mine/sleeper
	name = "Mining station Emergency Sleeper"

/area/mine/north_outpost
	name = "North Mining Outpost"

/area/mine/west_outpost
	name = "Research Outpost"

/area/mine/laborcamp
	name = "Labor Camp"

/area/mine/laborcamp/security
	name = "Labor Camp Security"
	icon_state = "security"


code:
/**********************Light************************/

//this item is intended to give the effect of entering the mine, so that light gradually fades
/obj/effect/light_emitter
	name = "Light-emtter"
	anchored = 1
	unacidable = 1
	light_range = 8

/**********************Miner Lockers**************************/

/obj/structure/closet/secure_closet/miner
	name = "miner's equipment"
	icon_state = "mining"
	req_access = list(access_mining)

/obj/structure/closet/secure_closet/miner/New()
	..()
	if(prob(50))
		new /obj/item/weapon/storage/backpack/industrial(src)
	else
		new /obj/item/weapon/storage/backpack/satchel_eng(src)
	new /obj/item/device/radio/headset/headset_cargo(src)
	new /obj/item/clothing/under/rank/miner(src)
	new /obj/item/clothing/gloves/fingerless(src)
	new /obj/item/clothing/shoes/sneakers/black(src)
	new /obj/item/device/mining_scanner(src)
	new /obj/item/weapon/storage/bag/ore(src)
	new /obj/item/weapon/shovel(src)
	new /obj/item/weapon/pickaxe(src)
	new /obj/item/clothing/glasses/meson(src)

/**********************Shuttle Computer**************************/

/obj/machinery/computer/shuttle/mining
	name = "Mining Shuttle Console"
	desc = "Used to call and send the mining shuttle."
	req_access = list(access_mining)
	circuit = /obj/item/weapon/circuitboard/mining_shuttle
	shuttleId = "mining"
	possible_destinations = "mining_home;mining_away"

/*********************Pickaxe & Drills**************************/

/obj/item/weapon/pickaxe
	name = "pickaxe"
	icon = 'icons/obj/items.dmi'
	icon_state = "pickaxe"
	flags = CONDUCT
	slot_flags = SLOT_BELT
	force = 15
	throwforce = 10.0
	item_state = "pickaxe"
	w_class = 4.0
	m_amt = 3750 //one sheet, but where can you make them?
	var/digspeed = 40
	var/list/digsound = list('sound/effects/picaxe1.ogg','sound/effects/picaxe2.ogg','sound/effects/picaxe3.ogg')
	origin_tech = "materials=1;engineering=1"
	attack_verb = list("hit", "pierced", "sliced", "attacked")
	var/excavation_amount = 100

/obj/item/weapon/pickaxe/proc/playDigSound()
	playsound(src, pick(digsound),50,1)

/obj/item/weapon/pickaxe/diamond
	name = "diamond-tipped pickaxe"
	icon_state = "dpickaxe"
	item_state = "dpickaxe"
	digspeed = 20 //mines twice as fast as a normal pickaxe, bought from mining vendor
	origin_tech = "materials=4;engineering=3"
	desc = "A pickaxe with a diamond pick head. Extremely robust at cracking rock walls and digging up dirt."

/obj/item/weapon/pickaxe/drill
	name = "mining drill"
	icon_state = "handdrill"
	item_state = "jackhammer"
	digspeed = 30 //available from roundstart, faster than a pickaxe but needs recharging or cell replacements
	digsound = list('sound/weapons/drill.ogg')
	hitsound = 'sound/weapons/drill.ogg'
	origin_tech = "materials=2;powerstorage=3;engineering=2"
	desc = "An electric mining drill for the especially scrawny."

/obj/item/weapon/pickaxe/drill/examine(mob/user)
	..()

/obj/item/weapon/pickaxe/drill/cyborg
	name = "cyborg mining drill"
	flags = NODROP

/obj/item/weapon/pickaxe/drill/diamonddrill
	name = "diamond-tipped mining drill"
	icon_state = "diamonddrill"
	digspeed = 10 //It wrecks all walls, but is a bit slower than the jackhammer
	origin_tech = "materials=6;powerstorage=4;engineering=5"
	desc = "Yours is the drill that will pierce the heavens!"

/obj/item/weapon/pickaxe/drill/jackhammer
	name = "sonic jackhammer"
	icon_state = "jackhammer"
	item_state = "jackhammer"
	digspeed = 5 //sanic fast, but only destroys simple walls
	origin_tech = "materials=3;powerstorage=2;engineering=2"
	digsound = list('sound/weapons/sonic_jackhammer.ogg')
	hitsound = 'sound/weapons/sonic_jackhammer.ogg'
	desc = "Cracks rocks with sonic blasts, and doubles as a demolition power tool for smashing walls.."

/obj/item/weapon/pickaxe/plasmacutter
	name = "plasma cutter"
	icon_state = "plasmacutter"
	item_state = "gun"
	w_class = 3 //it is smaller than the pickaxe
	damtype = "fire"
	throwforce = 8
	digspeed = 30 //Mines slightly faster than a normal pickaxe, but doubles as an unlimited-ammo welding tool in some cases such as wall deconstruction
	digsound = list('sound/weapons/plasma_cutter.ogg')
	hitsound = 'sound/weapons/plasma_cutter.ogg'
	origin_tech = "materials=4;plasmatech=3;engineering=3"
	desc = "A rock cutter that uses bursts of hot plasma. You could use it to cut limbs off of xenos! Or, you know, mine stuff."

/*****************************Shovel********************************/

/obj/item/weapon/shovel
	name = "shovel"
	desc = "A large tool for digging and moving dirt."
	icon = 'icons/obj/items.dmi'
	icon_state = "shovel"
	flags = CONDUCT
	slot_flags = SLOT_BELT
	force = 8.0
	throwforce = 4.0
	item_state = "shovel"
	w_class = 3.0
	m_amt = 50
	origin_tech = "materials=1;engineering=1"
	attack_verb = list("bashed", "bludgeoned", "thrashed", "whacked")

/obj/item/weapon/shovel/spade
	name = "spade"
	desc = "A small tool for digging and moving dirt."
	icon_state = "spade"
	item_state = "spade"
	force = 5.0
	throwforce = 7.0
	w_class = 2.0

/**********************Mining car (Crate like thing, not the rail car)**************************/

/obj/structure/closet/crate/miningcar
	desc = "A mining car. This one doesn't work on rails, but has to be dragged."
	name = "Mining car (not for rails)"
	icon_crate = "miningcar"
	icon_state = "miningcar"


code:
/**********************Mineral deposits**************************/
/datum/controller/game_controller
	var/list/artifact_spawning_turfs = list()

/turf/simulated/mineral //wall piece
	name = "rock"
	icon = 'icons/turf/walls.dmi'
	icon_state = "rock_nochance"
	baseturf = /turf/simulated/floor/plating/asteroid
	oxygen = 0
	nitrogen = 0
	opacity = 1
	density = 1
	blocks_air = 1
	temperature = TCMB
	var/mineralName = ""
	var/mineralAmt = 3
	var/spread = 0 //will the seam spread?
	var/spreadChance = 0 //the percentual chance of an ore spreading to the neighbouring tiles
	var/last_act = 0
	var/scan_state = null //Holder for the image we display when we're pinged by a mining scanner
	var/hidden = 1
	var/datum/geosample/geologic_data
	var/excavation_level = 0
	var/list/finds = list()//no longer null to prevent those pesky runtime errors
	var/next_rock = 0
	var/archaeo_overlay = ""
	var/excav_overlay = ""
	var/obj/item/weapon/last_find
	var/datum/artifact_find/artifact_find

/turf/simulated/mineral/ex_act(severity, target)
	..()
	switch(severity)
		if(3.0)
			if (prob(75))
				src.gets_drilled(null, 1)
		if(2.0)
			if (prob(90))
				src.gets_drilled(null, 1)
		if(1.0)
			src.gets_drilled(null, 1)
	return

/turf/simulated/mineral/New()
	..()

	spawn(1)
		var/turf/T
		if((istype(get_step(src, NORTH), /turf/simulated/floor)) || (istype(get_step(src, NORTH), /turf/space)))
			T = get_step(src, NORTH)
			if (T)
				T.overlays += image('icons/turf/walls.dmi', "rock_side_s")
		if((istype(get_step(src, SOUTH), /turf/simulated/floor)) || (istype(get_step(src, SOUTH), /turf/space)))
			T = get_step(src, SOUTH)
			if (T)
				T.overlays += image('icons/turf/walls.dmi', "rock_side_n", layer=6)
		if((istype(get_step(src, EAST), /turf/simulated/floor)) || (istype(get_step(src, EAST), /turf/space)))
			T = get_step(src, EAST)
			if (T)
				T.overlays += image('icons/turf/walls.dmi', "rock_side_w", layer=6)
		if((istype(get_step(src, WEST), /turf/simulated/floor)) || (istype(get_step(src, WEST), /turf/space)))
			T = get_step(src, WEST)
			if (T)
				T.overlays += image('icons/turf/walls.dmi', "rock_side_e", layer=6)

	if (mineralName && mineralAmt && spread && spreadChance)
		for(var/dir in cardinal)
			if(prob(spreadChance))
				var/turf/T = get_step(src, dir)
				if(istype(T, /turf/simulated/mineral/random))
					Spread(T)

	HideRock()
	return

/turf/simulated/mineral/proc/HideRock()
	if(hidden)
		icon_state = "rock"
	return

/turf/simulated/mineral/proc/Spread(var/turf/T)
	new src.type(T)

/turf/simulated/mineral/random
	name = "mineral deposit"
	icon_state = "rock"
	var/mineralSpawnChanceList = list("Uranium" = 5, "Diamond" = 2, "Gold" = 10, "Silver" = 12, "Plasma" = 20, "Iron" = 40, "Gibtonite" = 4/*, "Adamantine" =5*/, "Cave" = 2)//Currently, Adamantine won't spawn as it has no uses. -Durandan
	var/mineralChance = 13

/turf/simulated/mineral/random/New()
	..()
	if (prob(mineralChance))
		var/mName = pickweight(mineralSpawnChanceList) //temp mineral name

		if (mName)
			var/turf/simulated/mineral/M
			switch(mName)
				if("Uranium")
					M = new/turf/simulated/mineral/uranium(src)
				if("Iron")
					M = new/turf/simulated/mineral/iron(src)
				if("Diamond")
					M = new/turf/simulated/mineral/diamond(src)
				if("Gold")
					M = new/turf/simulated/mineral/gold(src)
				if("Silver")
					M = new/turf/simulated/mineral/silver(src)
				if("Plasma")
					M = new/turf/simulated/mineral/plasma(src)
				if("Cave")
					new/turf/simulated/floor/plating/asteroid/airless/cave(src)
				if("Gibtonite")
					M = new/turf/simulated/mineral/gibtonite(src)
				if("Bananium")
					M = new/turf/simulated/mineral/clown(src)
				/*if("Adamantine")
					M = new/turf/simulated/mineral/adamantine(src)*/
			if(M)
				src = M
				M.levelupdate()
	return

/turf/simulated/mineral/random/high_chance
	icon_state = "rock_highchance"
	mineralChance = 25
	mineralSpawnChanceList = list("Uranium" = 35, "Diamond" = 30, "Gold" = 45, "Silver" = 50, "Plasma" = 50)

/turf/simulated/mineral/random/high_chance/New()
	icon_state = "rock"
	..()

/turf/simulated/mineral/random/low_chance
	icon_state = "rock_lowchance"
	mineralChance = 6
	mineralSpawnChanceList = list("Uranium" = 2, "Diamond" = 1, "Gold" = 4, "Silver" = 6, "Plasma" = 15, "Iron" = 40, "Gibtonite" = 2)

/turf/simulated/mineral/random/low_chance/New()
	icon_state = "rock"
	..()

/turf/simulated/mineral/uranium
	name = "uranium deposit"
	mineralName = "Uranium"
	spreadChance = 5
	spread = 1
	hidden = 1
	scan_state = "rock_Uranium"

/turf/simulated/mineral/iron
	name = "iron deposit"
	icon_state = "rock_Iron"
	mineralName = "Iron"
	spreadChance = 20
	spread = 1
	hidden = 0

/turf/simulated/mineral/diamond
	name = "diamond deposit"
	mineralName = "Diamond"
	spreadChance = 0
	spread = 1
	hidden = 1
	scan_state = "rock_Diamond"

/turf/simulated/mineral/gold
	name = "gold deposit"
	mineralName = "Gold"
	spreadChance = 5
	spread = 1
	hidden = 1
	scan_state = "rock_Gold"

/turf/simulated/mineral/silver
	name = "silver deposit"
	mineralName = "Silver"
	spreadChance = 5
	spread = 1
	hidden = 1
	scan_state = "rock_Silver"

/turf/simulated/mineral/plasma
	name = "plasma deposit"
	icon_state = "rock_Plasma"
	mineralName = "Plasma"
	spreadChance = 8
	spread = 1
	hidden = 1
	scan_state = "rock_Plasma"

/turf/simulated/mineral/clown
	name = "bananium deposit"
	icon_state = "rock_Clown"
	mineralName = "Bananium"
	mineralAmt = 3
	spreadChance = 0
	spread = 0
	hidden = 0

////////////////////////////////Gibtonite
/turf/simulated/mineral/gibtonite
	name = "gibtonite deposit"
	icon_state = "rock_Gibtonite"
	mineralName = "Gibtonite"
	mineralAmt = 1
	spreadChance = 0
	spread = 0
	hidden = 1
	scan_state = "rock_Gibtonite"
	var/det_time = 8 //Countdown till explosion, but also rewards the player for how close you were to detonation when you defuse it
	var/stage = 0 //How far into the lifecycle of gibtonite we are, 0 is untouched, 1 is active and attempting to detonate, 2 is benign and ready for extraction
	var/activated_ckey = null //These are to track who triggered the gibtonite deposit for logging purposes
	var/activated_name = null

/turf/simulated/mineral/gibtonite/New()
	det_time = rand(8,10) //So you don't know exactly when the hot potato will explode
	..()

/turf/simulated/mineral/gibtonite/attackby(obj/item/I, mob/user, params)
	if(istype(I, /obj/item/device/mining_scanner) || istype(I, /obj/item/device/t_scanner/adv_mining_scanner) && stage == 1)
		user.visible_message("You use [I] to locate where to cut off the chain reaction and attempt to stop it...")
		defuse()
	if (istype(I, /obj/item/weapon/pickaxe))
		var/obj/item/weapon/pickaxe/P = I
		var/turf/T = user.loc
		if (!( istype(T, /turf) ))
			return

		if(last_act+P.digspeed > world.time)//prevents message spam
			return
		last_act = world.time
		user << "You start picking..."
		P.playDigSound()

		if(do_after(user,P.digspeed))
			if(istype(src, /turf/simulated/mineral)) //sanity check against turf being deleted during digspeed delay
				user << "You finish cutting into the rock."
				P.update_icon()
				gets_drilled(user)
	else
		return attack_hand(user)
	return

/turf/simulated/mineral/gibtonite/proc/explosive_reaction(var/mob/user = null, triggered_by_explosion = 0)
	if(stage == 0)
		icon_state = "rock_Gibtonite_active"
		name = "gibtonite deposit"
		desc = "An active gibtonite reserve. Run!"
		stage = 1
		visible_message("There was gibtonite inside! It's going to explode!")
		var/turf/bombturf = get_turf(src)
		var/area/A = get_area(bombturf)

		if(user)
			activated_ckey = "[user.ckey]"
			activated_name = "[user.name]"
		var/notify_admins = 0
		if(z != 5)
			notify_admins = 1
			if(!triggered_by_explosion)
				message_admins("[src.activated_ckey]/([src.activated_name])? has triggered a gibtonite deposit reaction at [A.name] (JMP).")
			else
				message_admins("An explosion has triggered a gibtonite deposit reaction at [A.name] (JMP).")

		if(!triggered_by_explosion)
			log_game("[src.activated_ckey] ([src.activated_name]) has triggered a gibtonite deposit reaction at [A.name] ([A.x], [A.y], [A.z]).")
		else
			log_game("An explosion has triggered a gibtonite deposit reaction at [A.name]([bombturf.x],[bombturf.y],[bombturf.z])")

		countdown(notify_admins)

/turf/simulated/mineral/gibtonite/proc/countdown(notify_admins = 0)
	spawn(0)
		while(stage == 1 && det_time > 0 && mineralAmt >= 1)
			det_time--
			sleep(5)
		if(stage == 1 && det_time <= 0 && mineralAmt >= 1)
			var/turf/bombturf = get_turf(src)
			mineralAmt = 0
			explosion(bombturf,1,3,5, adminlog = notify_admins)
		if(stage == 0 || stage == 2)
			return

/turf/simulated/mineral/gibtonite/proc/defuse()
	if(stage == 1)
		icon_state = "rock_Gibtonite_inactive"
		desc = "An inactive gibtonite reserve. The ore can be extracted."
		stage = 2
		if(det_time < 0)
			det_time = 0
		visible_message("The chain reaction was stopped! The gibtonite had [src.det_time] reactions left till the explosion!")

/turf/simulated/mineral/gibtonite/gets_drilled(var/mob/user, triggered_by_explosion = 0, artifact_fail)
	if(stage == 0 && mineralAmt >= 1) //Gibtonite deposit is activated
		playsound(src,'sound/effects/hit_on_shattered_glass.ogg',50,1)
		explosive_reaction(user, triggered_by_explosion)
		return
	if(stage == 1 && mineralAmt >= 1) //Gibtonite deposit goes kaboom
		var/turf/bombturf = get_turf(src)
		mineralAmt = 0
		explosion(bombturf,1,2,5, adminlog = 0)
	if(stage == 2) //Gibtonite deposit is now benign and extractable. Depending on how close you were to it blowing up before defusing, you get better quality ore.
		var/obj/item/weapon/twohanded/required/gibtonite/G = new /obj/item/weapon/twohanded/required/gibtonite/(src)
		if(det_time <= 0)
			G.quality = 3
			G.icon_state = "Gibtonite ore 3"
		if(det_time >= 1 && det_time <= 2)
			G.quality = 2
			G.icon_state = "Gibtonite ore 2"
	var/turf/simulated/floor/plating/asteroid/airless/gibtonite_remains/G = ChangeTurf(/turf/simulated/floor/plating/asteroid/airless/gibtonite_remains)
	G.fullUpdateMineralOverlays()

/turf/simulated/floor/plating/asteroid/airless/gibtonite_remains
	var/det_time = 0
	var/stage = 0

////////////////////////////////End Gibtonite

/turf/simulated/floor/plating/asteroid/airless/cave
	var/length = 100
	var/mob_spawn_list = list("Goldgrub" = 1, "Goliath" = 5, "Basilisk" = 4, "Hivelord" = 3)
	var/sanity = 1

/turf/simulated/floor/plating/asteroid/airless/cave/New(loc, var/length, var/go_backwards = 1, var/exclude_dir = -1)

	// If length (arg2) isn't defined, get a random length; otherwise assign our length to the length arg.
	if(!length)
		src.length = rand(25, 50)
	else
		src.length = length

	// Get our directiosn
	var/forward_cave_dir = pick(alldirs - exclude_dir)
	// Get the opposite direction of our facing direction
	var/backward_cave_dir = angle2dir(dir2angle(forward_cave_dir) + 180)

	// Make our tunnels
	make_tunnel(forward_cave_dir)
	if(go_backwards)
		make_tunnel(backward_cave_dir)
	// Kill ourselves by replacing ourselves with a normal floor.
	SpawnFloor(src)
	..()

/turf/simulated/floor/plating/asteroid/airless/cave/proc/make_tunnel(var/dir)

	var/turf/simulated/mineral/tunnel = src
	var/next_angle = pick(45, -45)

	for(var/i = 0; i < length; i++)
		if(!sanity)
			break

		var/list/L = list(45)
		if(IsOdd(dir2angle(dir))) // We're going at an angle and we want thick angled tunnels.
			L += -45

		// Expand the edges of our tunnel
		for(var/edge_angle in L)
			var/turf/simulated/mineral/edge = get_step(tunnel, angle2dir(dir2angle(dir) + edge_angle))
			if(istype(edge))
				SpawnFloor(edge)

		// Move our tunnel forward
		tunnel = get_step(tunnel, dir)

		if(istype(tunnel))
			// Small chance to have forks in our tunnel; otherwise dig our tunnel.
			if(i > 3 && prob(20))
				new src.type(tunnel, rand(10, 15), 0, dir)
			else
				SpawnFloor(tunnel)
		else //if(!istype(tunnel, src.parent)) // We hit space/normal/wall, stop our tunnel.
			break

		// Chance to change our direction left or right.
		if(i > 2 && prob(33))
			// We can't go a full loop though
			next_angle = -next_angle
			dir = angle2dir(dir2angle(dir) + next_angle)

/turf/simulated/floor/plating/asteroid/airless/cave/proc/SpawnFloor(var/turf/T)
	for(var/turf/S in range(2,T))
		if(istype(S, /turf/space) || istype(S.loc, /area/mine/explored))
			sanity = 0
			break
	if(!sanity)
		return

	SpawnMonster(T)
	var/turf/simulated/floor/t = new /turf/simulated/floor/plating/asteroid/airless(T)
	spawn(2)
		t.fullUpdateMineralOverlays()

/turf/simulated/floor/plating/asteroid/airless/cave/proc/SpawnMonster(var/turf/T)
	if(prob(30))
		if(istype(loc, /area/mine/explored))
			return
		for(var/atom/A in range(15,T))//Lowers chance of mob clumps
			if(istype(A, /mob/living/simple_animal/hostile/asteroid))
				return
		var/randumb = pickweight(mob_spawn_list)
		switch(randumb)
			if("Goliath")
				new /mob/living/simple_animal/hostile/asteroid/goliath(T)
			if("Goldgrub")
				new /mob/living/simple_animal/hostile/asteroid/goldgrub(T)
			if("Basilisk")
				new /mob/living/simple_animal/hostile/asteroid/basilisk(T)
			if("Hivelord")
				new /mob/living/simple_animal/hostile/asteroid/hivelord(T)
	return

/turf/simulated/mineral/attackby(var/obj/item/weapon/W as obj, mob/user as mob, params)

	if (!user.IsAdvancedToolUser())
		usr << "You don't have the dexterity to do this!"
		return

	if (istype(W, /obj/item/device/core_sampler))
		if(!geologic_data)
			geologic_data = new/datum/geosample(src)
		geologic_data.UpdateNearbyArtifactInfo(src)
		var/obj/item/device/core_sampler/C = W
		C.sample_item(src, user)
		return

	if (istype(W, /obj/item/device/depth_scanner))
		var/obj/item/device/depth_scanner/C = W
		C.scan_atom(user, src)
		return

	if (istype(W, /obj/item/device/measuring_tape))
		var/obj/item/device/measuring_tape/P = W
		user.visible_message("[user] extends [P] towards [src].","You extend [P] towards [src].")
		if(do_after(user,25))
			user << "\icon[P] [src] has been excavated to a depth of [2*excavation_level]cm."
		return

	if (istype(W, /obj/item/weapon/pickaxe))
		var/obj/item/weapon/pickaxe/P = W
		var/turf/T = user.loc
		if (!( istype(T, /turf) ))
			return

		if(last_act+P.digspeed > world.time)//prevents message spam
			return
		last_act = world.time

		var/fail_message = ""
		if(finds && finds.len)
			var/datum/find/F = finds[1]
			if(excavation_level + P.excavation_amount > F.excavation_required)
				fail_message = ", [pick("there is a crunching noise","[W] collides with some different rock","part of the rock face crumbles away","something breaks under [W]")]"

		user << "You start picking."

		if(fail_message && prob(90))
			if(prob(25))
				excavate_find(5, finds[1])
			else if(prob(50))
				finds.Remove(finds[1])
				if(prob(50))
					artifact_debris()
		P.playDigSound()

		if(do_after(user,P.digspeed))
			if(istype(src, /turf/simulated/mineral)) //sanity check against turf being deleted during digspeed delay
				user << "You finish cutting into the rock."
				if(finds && finds.len)
					var/datum/find/F = finds[1]
					if(round(excavation_level + P.excavation_amount) == F.excavation_required)

						if(excavation_level + P.excavation_amount > F.excavation_required)

							excavate_find(100, F)
						else
							excavate_find(80, F)

					else if(excavation_level + P.excavation_amount > F.excavation_required - F.clearance_range)

						excavate_find(0, F)

				if( excavation_level + P.excavation_amount >= 100 )
					var/obj/structure/boulder/B
					if(artifact_find)
						if( excavation_level > 0 || prob(15) )

							B = new(src)
							if(artifact_find)
								B.artifact_find = artifact_find
						else
							artifact_debris(1)

					else if(prob(15))
						B = new(src)

					if(B)
						gets_drilled(user, artifact_fail = 0)
					else
						gets_drilled(user, artifact_fail = 1)
					return

				excavation_level += P.excavation_amount
			if(istype(src, /turf/simulated/mineral))
				if(!archaeo_overlay && finds && finds.len)
					var/datum/find/F = finds[1]
					if(F.excavation_required <= excavation_level + F.view_range)
						archaeo_overlay = "overlay_archaeo[rand(1,3)]"
						overlays += archaeo_overlay

				var/update_excav_overlay = 0

				var/subtractions = 0
				while(excavation_level - 25*(subtractions + 1) >= 0 && subtractions < 3)
					subtractions++
				if(excavation_level - P.excavation_amount < subtractions * 25)
					update_excav_overlay = 1

				//update overlays displaying excavation level
				if( !(excav_overlay && excavation_level > 0) || update_excav_overlay )
					var/excav_quadrant = round(excavation_level / 25) + 1
					excav_overlay = "overlay_excv[excav_quadrant]_[rand(1,3)]"
					overlays += excav_overlay

			//drop some rocks
				next_rock += P.excavation_amount * 10
				while(next_rock > 100)
					next_rock -= 100
					var/obj/item/weapon/ore/O = new(src)
					if(!geologic_data)
						geologic_data = new/datum/geosample(src)
					geologic_data.UpdateNearbyArtifactInfo(src)
					O.geologic_data = geologic_data
					P.update_icon()
	else
		return attack_hand(user)
	return

/turf/simulated/mineral/proc/gets_drilled(var/mob/user, triggered_by_explosion = 0, var/artifact_fail = 0)
	if(artifact_find && artifact_fail)
		for(var/mob/living/M in range(src, 200))
			M << "[pick("A high pitched [pick("keening","wailing","whistle")]","A rumbling noise like [pick("thunder","heavy machinery")]")] somehow penetrates your mind before fading away!"
			if(prob(50)) //pain
		//		flick("pain",M.pain)
				M.adjustBruteLoss(5)
			else
				flick("flash",M.flash)
				if(prob(50))
					M.Stun(5)
			M.apply_effect(25, IRRADIATE)
	if ((src.mineralName != "") && (src.mineralAmt > 0) && (src.mineralAmt < 11))
		var/i
		for (i=0;i<mineralAmt;i++)
			if (src.mineralName == "Uranium")
				new /obj/item/weapon/ore/uranium(src)
			if (src.mineralName == "Iron")
				new /obj/item/weapon/ore/iron(src)
			if (src.mineralName == "Gold")
				new /obj/item/weapon/ore/gold(src)
			if (src.mineralName == "Silver")
				new /obj/item/weapon/ore/silver(src)
			if (src.mineralName == "Plasma")
				new /obj/item/weapon/ore/plasma(src)
			if (src.mineralName == "Diamond")
				new /obj/item/weapon/ore/diamond(src)
			if (src.mineralName == "Bananium")
				new /obj/item/weapon/ore/bananium(src)
	var/turf/simulated/floor/plating/asteroid/airless/N = ChangeTurf(/turf/simulated/floor/plating/asteroid/airless)
	reconsider_lights()
	playsound(src, 'sound/effects/break_stone.ogg', 50, 1) //beautiful destruction
	N.fullUpdateMineralOverlays()
	return

/turf/simulated/mineral/proc/excavate_find(var/prob_clean = 0, var/datum/find/F)
	//with skill and luck, players can cleanly extract finds
	//otherwise, they come out inside a chunk of rock
	var/obj/item/weapon/X
	if(prob_clean)
		X = new /obj/item/weapon/archaeological_find(src, new_item_type = F.find_type)
	else
		X = new /obj/item/weapon/strangerock(src, inside_item_type = F.find_type)
		if(!geologic_data)
			geologic_data = new/datum/geosample(src)
		geologic_data.UpdateNearbyArtifactInfo(src)
		X:geologic_data = geologic_data

	//some find types delete the /obj/item/weapon/archaeological_find and replace it with something else, this handles when that happens
	//yuck
	var/display_name = "something"
	if(!X)
		X = last_find
	if(X)
		display_name = X.name

	//many finds are ancient and thus very delicate - luckily there is a specialised energy suspension field which protects them when they're being extracted
	if(prob(F.prob_delicate))
		var/obj/effect/suspension_field/S = locate() in src
		if(!S || S.field_type != get_responsive_reagent(F.find_type))
			if(X)
				visible_message("[pick("[display_name] crumbles away into dust","[display_name] breaks apart")].")
				del(X)

	finds.Remove(F)

/turf/simulated/mineral/proc/artifact_debris(var/severity = 0)
	for(var/j in 1 to rand(1, 3 + max(min(severity, 1), 0) * 2))
		switch(rand(1,6))
			if(1)
				var/obj/item/stack/rods/R = new(src)
				R.amount = rand(5,25)

			if(2)
				var/obj/item/stack/tile/R = new(src)
				R.amount = rand(1,5)

			if(3)
				var/obj/item/stack/sheet/metal/M = new/obj/item/stack/sheet/metal(src)
				M.amount = rand(5,25)

			if(4)
				var/obj/item/stack/sheet/plasteel/R = new(src)
				R.amount = rand(5,25)

			if(5)
				var/quantity = rand(1,3)
				for(var/i=0, i<quantity, i++)
					new/obj/item/weapon/shard(loc)

//			if(6)
//				var/quantity = rand(1,3)
//				for(var/i=0, i<quantity, i++)
//					getFromPool(/obj/item/weapon/shard/plasma, loc)

			if(6)
				var/obj/item/stack/sheet/mineral/uranium/R = new(src)
				R.amount = rand(5,25)

/turf/simulated/mineral/attack_animal(mob/living/simple_animal/user as mob)
	if(user.environment_smash >= 2)
		gets_drilled(artifact_fail = 1)
	..()

/*
/turf/simulated/mineral/proc/setRandomMinerals()
	var/s = pickweight(list("uranium" = 5, "iron" = 50, "gold" = 5, "silver" = 5, "plasma" = 50, "diamond" = 1))
	if (s)
		mineralName = s

	var/N = text2path("/turf/simulated/mineral/[s]")
	if (N)
		var/turf/simulated/mineral/M = new N
		src = M
		if (src.mineralName)
			mineralAmt = 5
	return*/

/turf/simulated/mineral/Bumped(AM as mob|obj)
	..()
	if(istype(AM,/mob/living/carbon/human))
		var/mob/living/carbon/human/H = AM
		if((istype(H.l_hand,/obj/item/weapon/pickaxe)) && (!H.hand))
			src.attackby(H.l_hand,H)
		else if((istype(H.r_hand,/obj/item/weapon/pickaxe)) && H.hand)
			src.attackby(H.r_hand,H)
		return
	else if(istype(AM,/mob/living/silicon/robot))
		var/mob/living/silicon/robot/R = AM
		if(istype(R.module_active,/obj/item/weapon/pickaxe))
			src.attackby(R.module_active,R)
			return
/*	else if(istype(AM,/obj/mecha))
		var/obj/mecha/M = AM
		if(istype(M.selected,/obj/item/mecha_parts/mecha_equipment/tool/drill))
			src.attackby(M.selected,M)
			return*/
//Aparantly mechs are just TOO COOL to call Bump(), so fuck em (for now)
	else
		return

/**********************Asteroid**************************/

/turf/simulated/floor/plating/asteroid //floor piece
	name = "Asteroid"
	icon = 'icons/turf/floors.dmi'
	icon_state = "asteroid"
	icon_plating = "asteroid"
	baseturf = /turf/simulated/floor/plating/asteroid
	var/dug = 0       //0 = has not yet been dug, 1 = has already been dug
	var/archaeo_overlay = ""
	ignoredirt = 1

/turf/simulated/floor/plating/asteroid/airless
	oxygen = 0.01
	nitrogen = 0.01
	temperature = TCMB

/turf/simulated/floor/plating/asteroid/New()
	var/proper_name = name
	..()
	name = proper_name
	//if (prob(50))
	//	seedName = pick(list("1","2","3","4"))
	//	seedAmt = rand(1,4)
	if(prob(20))
		icon_state = "asteroid[rand(0,12)]"
//	spawn(2)
//O		updateMineralOverlays()

/turf/simulated/floor/plating/asteroid/burn_tile()
	return

/turf/simulated/floor/plating/asteroid/ex_act(severity, target)
	contents_explosion(severity, target)
	switch(severity)
		if(3.0)
			return
		if(2.0)
			if (prob(20))
				src.gets_dug()
		if(1.0)
			src.gets_dug()
	return

/turf/simulated/floor/plating/asteroid/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
	//note that this proc does not call ..()
	if(!W || !user)
		return 0

	if ((istype(W, /obj/item/weapon/shovel)))
		var/turf/T = user.loc
		if (!( istype(T, /turf) ))
			return

		if (dug)
			user << "This area has already been dug."
			return

		user << "You start digging."
		playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1) //FUCK YO RUSTLE I GOT'S THE DIGS SOUND HERE

		sleep(20)
		if ((user.loc == T && user.get_active_hand() == W))
			user << "You dug a hole."
			gets_dug()
			return

	if ((istype(W, /obj/item/weapon/pickaxe)))
		var/obj/item/weapon/pickaxe/P = W
		var/turf/T = user.loc
		if (!( istype(T, /turf) ))
			return

		if (dug)
			user << "This area has already been dug."
			return

		user << "You start digging."
		playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1) //FUCK YO RUSTLE I GOT'S THE DIGS SOUND HERE

		sleep(P.digspeed)
		if (!user)
			return
		if ((user.loc == T && user.get_active_hand() == W))
			user << "You dug a hole."
			gets_dug()
			return

	if(istype(W,/obj/item/weapon/storage/bag/ore))
		var/obj/item/weapon/storage/bag/ore/S = W
		if(S.collection_mode == 1)
			for(var/obj/item/weapon/ore/O in src.contents)
				O.attackby(W,user)
				return
	if(istype(W, /obj/item/stack/tile))
		var/obj/item/stack/tile/Z = W
		if(!Z.use(1))
			return
		var/turf/simulated/floor/T = ChangeTurf(Z.turf_type)
		if(istype(Z,/obj/item/stack/tile/light)) //TODO: get rid of this ugly check somehow
			var/obj/item/stack/tile/light/L = Z
			var/turf/simulated/floor/light/F = T
			F.state = L.state
		playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)

/turf/simulated/floor/plating/asteroid/proc/gets_dug()
	if(dug)
		return
	new/obj/item/weapon/ore/glass(src)
	new/obj/item/weapon/ore/glass(src)
	new/obj/item/weapon/ore/glass(src)
	new/obj/item/weapon/ore/glass(src)
	new/obj/item/weapon/ore/glass(src)
	dug = 1
	icon_plating = "asteroid_dug"
	icon_state = "asteroid_dug"
	return

/turf/proc/updateMineralOverlays()
	src.overlays.Cut()

	if(istype(get_step(src, NORTH), /turf/simulated/mineral))
		src.overlays += image('icons/turf/walls.dmi', "rock_side_n")
	if(istype(get_step(src, SOUTH), /turf/simulated/mineral))
		src.overlays += image('icons/turf/walls.dmi', "rock_side_s", layer=6)
	if(istype(get_step(src, EAST), /turf/simulated/mineral))
		src.overlays += image('icons/turf/walls.dmi', "rock_side_e", layer=6)
	if(istype(get_step(src, WEST), /turf/simulated/mineral))
		src.overlays += image('icons/turf/walls.dmi', "rock_side_w", layer=6)

/turf/simulated/mineral/updateMineralOverlays()
	return

/turf/proc/fullUpdateMineralOverlays()
	for (var/turf/t in range(1,src))
		t.updateMineralOverlays()


code:
//MINING CHARGE: Slap it in rocks to cause a controlled explosion. Can be emagged to slap on other things.
/obj/item/device/mining_charge
	name = "standard mining charge"
	desc = "A pyrotechnical device used to cause controlled explosions for digging tunnels without manual labor. It can only be attached to rocks and mineral deposits."
	w_class = 2
	icon = 'icons/obj/mining.dmi'
	icon_state = "mining_charge"
	item_state = "electronic"
	var/active_state = "mining_charge_active"
	throw_speed = 3
	throw_range = 5
	slot_flags = SLOT_BELT
	var/detonating = 0 //If the charge is currently primed
	var/safety = 1 //If the charge can be put on things other than rocks
	var/explosionPower = 2 //The power of the explosion; larger powers = bigger boom
	var/atom/movable/putOn = null //The atom the charge is on
	var/primedOverlay = null

/obj/item/device/mining_charge/emag_act(mob/user)
	if(!safety)
		return
	user << "You press the cryptographic sequencer onto [src], disabling its safeties."
	safety = 0

/obj/item/device/mining_charge/New()
	..()
	primedOverlay = image('icons/obj/mining.dmi', "mining_charge_active")

/obj/item/device/mining_charge/examine(mob/user)
	..()
	user << "A small LED is blinking [safety ? "green" : "red"]."
	if(detonating)
		user << "It appears to be primed."

/obj/item/device/mining_charge/attackby(obj/item/weapon/W, mob/user)
	if(istype(W, /obj/item/weapon/screwdriver) && !safety)
		user << "You restore the safeties on [src]."
		safety = 1
		return
	..()

/obj/item/device/mining_charge/attack_hand(mob/user)
	if(detonating)
		return
	..()

/obj/item/device/mining_charge/afterattack(atom/movable/target, mob/user, flag)
	if(!istype(target, /turf/simulated/mineral) && safety)
		return
	if(!in_range(user, target))
		return
	user.visible_message("[user] starts placing [src] onto [target].", \
						 "You start placing the charge.")
	if(do_after(user, 30 && in_range(user, target)))
		user.visible_message("[user] places [src] onto [target].", \
							 "You slap [src] onto [target]!")
		user.drop_item()
		if(ismob(target))
			var/mob/living/M = target
			M << "[src]'s clamps dig into you!" //Fluff
		loc = target
		putOn = target
		anchored = 1
		icon_state = active_state
		target.overlays += primedOverlay
		Detonate()

/obj/item/device/mining_charge/proc/Detonate(var/timer = 5)
	icon_state = active_state
	update_icon()
	detonating = 1
	light_range = 2
	for(var/i = 0, i < timer, i++)
		sleep(10)
		playsound(get_turf(src), 'sound/machines/defib_saftyOff.ogg', 50, 1)
	sleep(10)
	playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 100, 1)
	sleep(20)
	if(putOn)
		loc = get_turf(putOn)
	src.visible_message("[src] explodes!")
	switch(explosionPower)
		if(-INFINITY to 0)
			explosion(src.loc,-1,0,3)
		if(1)
			explosion(src.loc,-1,1,3)
		if(2)
			explosion(src.loc,-1,2,6)
		if(3 to INFINITY)
			explosion(src.loc,-1,4,12)
	if(putOn)
		putOn.overlays -= primedOverlay
		putOn = null
	if(src) //In case it survived
		qdel(src)

/obj/item/device/mining_charge/small
	name = "compact mining charge"
	desc = "A smaller mining charge that weighs less at the cost of a less powerful explosion."
	icon_state = "mining_charges"
	active_state = "mining_charges_active"
	w_class = 1
	explosionPower = 1

/obj/item/weapon/storage/box/mining_charges
	name = "box of mining charges"
	desc = "A box shaped to hold mining charges."
	can_hold = list(/obj/item/device/mining_charge/)

/obj/item/weapon/storage/box/mining_charges/New()
	..()
	contents = list()
	new /obj/item/device/mining_charge(src)
	new /obj/item/device/mining_charge(src)
	new /obj/item/device/mining_charge/small(src)
	new /obj/item/device/mining_charge/small(src)
	new /obj/item/device/mining_charge/small(src)
	new /obj/item/device/mining_charge/small(src)
	new /obj/item/device/mining_charge/small(src)
	return


code:
/**********************Mint**************************/

/obj/machinery/mineral/mint
	name = "Coin press"
	icon = 'icons/obj/economy.dmi'
	icon_state = "coinpress0"
	density = 1
	anchored = 1.0
	var/amt_silver = 0 //amount of silver
	var/amt_gold = 0   //amount of gold
	var/amt_diamond = 0
	var/amt_iron = 0
	var/amt_plasma = 0
	var/amt_uranium = 0
	var/amt_clown = 0
	var/amt_adamantine = 0
	var/amt_mythril = 0
	var/newCoins = 0   //how many coins the machine made in it's last load
	var/processing = 0
	var/chosen = "metal" //which material will be used to make coins
	var/coinsToProduce = 10

/obj/machinery/mineral/mint/process()
	var/turf/T = get_step(src,input_dir)
	if(T)
		for(var/obj/item/stack/sheet/O in T)
			if (istype(O, /obj/item/stack/sheet/mineral/gold))
				amt_gold += 100 * O.amount
				O.loc = null
			if (istype(O, /obj/item/stack/sheet/mineral/silver))
				amt_silver += 100 * O.amount
				O.loc = null
			if (istype(O, /obj/item/stack/sheet/mineral/diamond))
				amt_diamond += 100 * O.amount
				O.loc = null
			if (istype(O, /obj/item/stack/sheet/mineral/plasma))
				amt_plasma += 100 * O.amount
				O.loc = null
			if (istype(O, /obj/item/stack/sheet/mineral/uranium))
				amt_uranium += 100 * O.amount
				O.loc = null
			if (istype(O, /obj/item/stack/sheet/metal))
				amt_iron += 100 * O.amount
				O.loc = null
			if (istype(O, /obj/item/stack/sheet/mineral/bananium))
				amt_clown += 100 * O.amount
				O.loc = null
			if (istype(O, /obj/item/stack/sheet/mineral/adamantine))
				amt_adamantine += 100 * O.amount
				O.loc = null //Commented out for now. -Durandan
			return

/obj/machinery/mineral/mint/attack_hand(user as mob) //TODO: Adamantine coins! -Durandan

	var/dat = "Coin Press
"

	dat += text("
Gold inserted: [amt_gold] ")
	if (chosen == "gold")
		dat += text("chosen")
	else
		dat += text("Choose")
	dat += text("
Silver inserted: [amt_silver] ")
	if (chosen == "silver")
		dat += text("chosen")
	else
		dat += text("Choose")
	dat += text("
Iron inserted: [amt_iron] ")
	if (chosen == "metal")
		dat += text("chosen")
	else
		dat += text("Choose")
	dat += text("
Diamond inserted: [amt_diamond] ")
	if (chosen == "diamond")
		dat += text("chosen")
	else
		dat += text("Choose")
	dat += text("
Plasma inserted: [amt_plasma] ")
	if (chosen == "plasma")
		dat += text("chosen")
	else
		dat += text("Choose")
	dat += text("
uranium inserted: [amt_uranium] ")
	if (chosen == "uranium")
		dat += text("chosen")
	else
		dat += text("Choose")
	if(amt_clown > 0)
		dat += text("
Bananium inserted: [amt_clown] ")
		if (chosen == "clown")
			dat += text("chosen")
		else
			dat += text("Choose")
	dat += text("
Adamantine inserted: [amt_adamantine] ")//I don't even know these color codes, so fuck it.
	if (chosen == "adamantine")
		dat += text("chosen")
	else
		dat += text("Choose")

	dat += text("

Will produce [coinsToProduce] [chosen] coins if enough materials are available.
")
	//dat += text("The dial which controls the number of conins to produce seems to be stuck. A technician has already been dispatched to fix this.")
	dat += text("-10 ")
	dat += text("-5 ")
	dat += text("-1 ")
	dat += text("+1 ")
	dat += text("+5 ")
	dat += text("+10 ")

	dat += text("

In total this machine produced [newCoins] coins.")
	dat += text("
Make coins")
	user << browse("[dat]", "window=mint")

/obj/machinery/mineral/mint/Topic(href, href_list)
	if(..())
		return
	usr.set_machine(src)
	src.add_fingerprint(usr)
	if(processing==1)
		usr << "The machine is processing."
		return
	if(href_list["choose"])
		chosen = href_list["choose"]
	if(href_list["chooseAmt"])
		coinsToProduce = Clamp(coinsToProduce + text2num(href_list["chooseAmt"]), 0, 1000)
	if(href_list["makeCoins"])
		var/temp_coins = coinsToProduce
		processing = 1;
		icon_state = "coinpress1"
		switch(chosen)
			if("metal")
				while(amt_iron > 0 && coinsToProduce > 0)
					create_coins(/obj/item/weapon/coin/iron)
					amt_iron -= 20
					coinsToProduce--
					newCoins++
					src.updateUsrDialog()
					sleep(5);
			if("gold")
				while(amt_gold > 0 && coinsToProduce > 0)
					create_coins(/obj/item/weapon/coin/gold)
					amt_gold -= 20
					coinsToProduce--
					newCoins++
					src.updateUsrDialog()
					sleep(5);
			if("silver")
				while(amt_silver > 0 && coinsToProduce > 0)
					create_coins(/obj/item/weapon/coin/silver)
					amt_silver -= 20
					coinsToProduce--
					newCoins++
					src.updateUsrDialog()
					sleep(5);
			if("diamond")
				while(amt_diamond > 0 && coinsToProduce > 0)
					create_coins(/obj/item/weapon/coin/diamond)
					amt_diamond -= 20
					coinsToProduce--
					newCoins++
					src.updateUsrDialog()
					sleep(5);
			if("plasma")
				while(amt_plasma > 0 && coinsToProduce > 0)
					create_coins(/obj/item/weapon/coin/plasma)
					amt_plasma -= 20
					coinsToProduce--
					newCoins++
					src.updateUsrDialog()
					sleep(5);
			if("uranium")
				while(amt_uranium > 0 && coinsToProduce > 0)
					create_coins(/obj/item/weapon/coin/uranium)
					amt_uranium -= 20
					coinsToProduce--
					newCoins++
					src.updateUsrDialog()
					sleep(5)
			if("clown")
				while(amt_clown > 0 && coinsToProduce > 0)
					create_coins(/obj/item/weapon/coin/clown)
					amt_clown -= 20
					coinsToProduce--
					newCoins++
					src.updateUsrDialog()
					sleep(5);
			if("adamantine")
				while(amt_adamantine > 0 && coinsToProduce > 0)
					create_coins(/obj/item/weapon/coin/adamantine)
					amt_adamantine -= 20
					coinsToProduce--
					newCoins++
					src.updateUsrDialog()
					sleep(5);
			if("mythril")
				while(amt_adamantine > 0 && coinsToProduce > 0)
					create_coins(/obj/item/weapon/coin/mythril)
					amt_mythril -= 20
					coinsToProduce--
					newCoins++
					src.updateUsrDialog()
					sleep(5);
		icon_state = "coinpress0"
		processing = 0;
		coinsToProduce = temp_coins
	src.updateUsrDialog()
	return

/obj/machinery/mineral/mint/proc/create_coins(var/P)
	var/turf/T = get_step(src,output_dir)
	if(T)
		var/obj/item/O = new P(src)
		var/obj/item/weapon/moneybag/M = locate(/obj/item/weapon/moneybag/, T)
		if(!M)
			M = new /obj/item/weapon/moneybag(src)
			unload_mineral(M)
		O.loc = M


code:
/*****************************Money bag********************************/

/obj/item/weapon/moneybag
	icon = 'icons/obj/storage.dmi'
	name = "Money bag"
	icon_state = "moneybag"
	flags = CONDUCT
	force = 10.0
	throwforce = 0
	w_class = 4.0

/obj/item/weapon/moneybag/attack_hand(user as mob)
	var/amt_gold = 0
	var/amt_silver = 0
	var/amt_diamond = 0
	var/amt_iron = 0
	var/amt_plasma = 0
	var/amt_uranium = 0
	var/amt_clown = 0
	var/amt_adamantine = 0

	for (var/obj/item/weapon/coin/C in contents)
		if (istype(C,/obj/item/weapon/coin/diamond))
			amt_diamond++;
		if (istype(C,/obj/item/weapon/coin/plasma))
			amt_plasma++;
		if (istype(C,/obj/item/weapon/coin/iron))
			amt_iron++;
		if (istype(C,/obj/item/weapon/coin/silver))
			amt_silver++;
		if (istype(C,/obj/item/weapon/coin/gold))
			amt_gold++;
		if (istype(C,/obj/item/weapon/coin/uranium))
			amt_uranium++;
		if (istype(C,/obj/item/weapon/coin/clown))
			amt_clown++;
		if (istype(C,/obj/item/weapon/coin/adamantine))
			amt_adamantine++;

	var/dat = text("The contents of the moneybag reveal...
")
	if (amt_gold)
		dat += text("Gold coins: [amt_gold] Remove one
")
	if (amt_silver)
		dat += text("Silver coins: [amt_silver] Remove one
")
	if (amt_iron)
		dat += text("Metal coins: [amt_iron] Remove one
")
	if (amt_diamond)
		dat += text("Diamond coins: [amt_diamond] Remove one
")
	if (amt_plasma)
		dat += text("Plasma coins: [amt_plasma] Remove one
")
	if (amt_uranium)
		dat += text("Uranium coins: [amt_uranium] Remove one
")
	if (amt_clown)
		dat += text("Bananium coins: [amt_clown] Remove one
")
	if (amt_adamantine)
		dat += text("Adamantine coins: [amt_adamantine] Remove one
")
	user << browse("[dat]", "window=moneybag")

/obj/item/weapon/moneybag/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
	..()
	if (istype(W, /obj/item/weapon/coin))
		var/obj/item/weapon/coin/C = W
		user << "You add the [C.name] into the bag."
		usr.drop_item()
		contents += C
	if (istype(W, /obj/item/weapon/moneybag))
		var/obj/item/weapon/moneybag/C = W
		for (var/obj/O in C.contents)
			contents += O;
		user << "You empty the [C.name] into the bag."
	return

/obj/item/weapon/moneybag/Topic(href, href_list)
	if(..())
		return
	usr.set_machine(src)
	src.add_fingerprint(usr)
	if(href_list["remove"])
		var/obj/item/weapon/coin/COIN
		switch(href_list["remove"])
			if("gold")
				COIN = locate(/obj/item/weapon/coin/gold,src.contents)
			if("silver")
				COIN = locate(/obj/item/weapon/coin/silver,src.contents)
			if("iron")
				COIN = locate(/obj/item/weapon/coin/iron,src.contents)
			if("diamond")
				COIN = locate(/obj/item/weapon/coin/diamond,src.contents)
			if("plasma")
				COIN = locate(/obj/item/weapon/coin/plasma,src.contents)
			if("uranium")
				COIN = locate(/obj/item/weapon/coin/uranium,src.contents)
			if("clown")
				COIN = locate(/obj/item/weapon/coin/clown,src.contents)
			if("adamantine")
				COIN = locate(/obj/item/weapon/coin/adamantine,src.contents)
		if(!COIN)
			return
		COIN.loc = src.loc
	return

/obj/item/weapon/moneybag/vault

/obj/item/weapon/moneybag/vault/New()
	..()
	new /obj/item/weapon/coin/silver(src)
	new /obj/item/weapon/coin/silver(src)
	new /obj/item/weapon/coin/silver(src)
	new /obj/item/weapon/coin/silver(src)
	new /obj/item/weapon/coin/gold(src)
	new /obj/item/weapon/coin/gold(src)
	new /obj/item/weapon/coin/adamantine(src)


code:
/**********************Mineral ores**************************/

/obj/item/weapon/ore
	name = "rock"
	icon = 'icons/obj/mining.dmi'
	icon_state = "ore2"
	var/points = 0 //How many points this ore gets you from the ore redemption machine
	var/refined_type = null //What this ore defaults to being refined into
	var/datum/geosample/geologic_data

/obj/item/weapon/ore/attackby(obj/item/I as obj, mob/user as mob, params)
	if(istype(I, /obj/item/weapon/weldingtool))
		var/obj/item/weapon/weldingtool/W = I
		if(W.remove_fuel(15))
			new refined_type(get_turf(src.loc))
			qdel(src)
		else if(W.isOn())
			user << "Not enough fuel to smelt [src]."
	..()

/obj/item/weapon/ore/uranium
	name = "uranium ore"
	icon_state = "Uranium ore"
	origin_tech = "materials=5"
	points = 18
	refined_type = /obj/item/stack/sheet/mineral/uranium

/obj/item/weapon/ore/iron
	name = "iron ore"
	icon_state = "Iron ore"
	origin_tech = "materials=1"
	points = 1
	refined_type = /obj/item/stack/sheet/metal

/obj/item/weapon/ore/glass
	name = "sand pile"
	icon_state = "Glass ore"
	origin_tech = "materials=1"
	points = 1
	refined_type = /obj/item/stack/sheet/glass

/obj/item/weapon/ore/glass/attack_self(mob/living/user as mob)
	user << "You use the sand to make sandstone."
	var/sandAmt = 1
	for(var/obj/item/weapon/ore/glass/G in user.loc) // The sand on the floor
		sandAmt += 1
		qdel(G)
	while(sandAmt > 0)
		var/obj/item/stack/sheet/mineral/sandstone/SS = new /obj/item/stack/sheet/mineral/sandstone(user.loc)
		if(sandAmt >= SS.max_amount)
			SS.amount = SS.max_amount
		else
			SS.amount = sandAmt
			for(var/obj/item/stack/sheet/mineral/sandstone/SA in user.loc)
				if(SA != SS && SA.amount < SA.max_amount)
					SA.attackby(SS, user) //we try to transfer all old unfinished stacks to the new stack we created.
		sandAmt -= SS.max_amount
	qdel(src)
	return

/obj/item/weapon/ore/plasma
	name = "plasma ore"
	icon_state = "Plasma ore"
	origin_tech = "materials=2"
	points = 36
	refined_type = /obj/item/stack/sheet/mineral/plasma

/obj/item/weapon/ore/plasma/attackby(obj/item/I as obj, mob/user as mob, params)
	if(istype(I, /obj/item/weapon/weldingtool))
		var/obj/item/weapon/weldingtool/W = I
		if(W.welding)
			user << "You can't hit a high enough temperature to smelt [src] properly."
	else
		..()

/obj/item/weapon/ore/silver
	name = "silver ore"
	icon_state = "Silver ore"
	origin_tech = "materials=3"
	points = 18
	refined_type = /obj/item/stack/sheet/mineral/silver

/obj/item/weapon/ore/gold
	name = "gold ore"
	icon_state = "Gold ore"
	origin_tech = "materials=4"
	points = 18
	refined_type = /obj/item/stack/sheet/mineral/gold

/obj/item/weapon/ore/diamond
	name = "diamond ore"
	icon_state = "Diamond ore"
	origin_tech = "materials=6"
	points = 36
	refined_type = /obj/item/stack/sheet/mineral/diamond

/obj/item/weapon/ore/bananium
	name = "bananium ore"
	icon_state = "Clown ore"
	origin_tech = "materials=4"
	points = 27
	refined_type = /obj/item/stack/sheet/mineral/bananium

/obj/item/weapon/ore/slag
	name = "slag"
	desc = "Completely useless"
	icon_state = "slag"

/obj/item/weapon/twohanded/required/gibtonite
	name = "gibtonite ore"
	desc = "Extremely explosive if struck with mining equipment, Gibtonite is often used by miners to speed up their work by using it as a mining charge. This material is illegal to possess by unauthorized personnel under space law."
	icon = 'icons/obj/mining.dmi'
	icon_state = "Gibtonite ore"
	item_state = "Gibtonite ore"
	w_class = 4
	throw_range = 0
	anchored = 1 //Forces people to carry it by hand, no pulling!
	var/primed = 0
	var/det_time = 100
	var/quality = 1 //How pure this gibtonite is, determines the explosion produced by it and is derived from the det_time of the rock wall it was taken from, higher value = better

/obj/item/weapon/twohanded/required/gibtonite/attackby(obj/item/I, mob/user, params)
	if(istype(I, /obj/item/weapon/pickaxe) || istype(I, /obj/item/weapon/resonator))
		GibtoniteReaction(user)
		return
	if(istype(I, /obj/item/device/mining_scanner) || istype(I, /obj/item/device/t_scanner/adv_mining_scanner) && primed)
		primed = 0
		user.visible_message("The chain reaction was stopped! ...The ore's quality went down.")
		icon_state = "Gibtonite ore"
		quality = 1
		return
	..()

/obj/item/weapon/twohanded/required/gibtonite/bullet_act(var/obj/item/projectile/P)
	if(istype(P, /obj/item/projectile/kinetic))
		GibtoniteReaction(P.firer)
	..()

/obj/item/weapon/twohanded/required/gibtonite/ex_act()
	GibtoniteReaction(null, 1)

/obj/item/weapon/twohanded/required/gibtonite/proc/GibtoniteReaction(mob/user, triggered_by_explosive = 0)
	if(!primed)
		playsound(src,'sound/effects/hit_on_shattered_glass.ogg',50,1)
		primed = 1
		icon_state = "Gibtonite active"
		var/turf/bombturf = get_turf(src)
		var/area/A = get_area(bombturf)
		var/notify_admins = 0
		if(z != 5)//Only annoy the admins ingame if we're triggered off the mining zlevel
			notify_admins = 1
		if(notify_admins)
			if(triggered_by_explosive)
				message_admins("An explosion has triggered a [name] to detonate at [A.name] (JMP).")
			else
				message_admins("[key_name(user)]? has triggered a [name] to detonate at [A.name] (JMP).")
		if(triggered_by_explosive)
			log_game("An explosion has primed a [name] for detonation at [A.name]([bombturf.x],[bombturf.y],[bombturf.z])")
		else
			user.visible_message("[user] strikes \the [src], causing a chain reaction!")
			log_game("[key_name(user)] has primed a [name] for detonation at [A.name]([bombturf.x],[bombturf.y],[bombturf.z])")
		spawn(det_time)
		if(primed)
			if(quality == 3)
				explosion(src.loc,2,4,9,adminlog = notify_admins)
			if(quality == 2)
				explosion(src.loc,1,2,5,adminlog = notify_admins)
			if(quality == 1)
				explosion(src.loc,-1,1,3,adminlog = notify_admins)
			qdel(src)

/obj/item/weapon/ore/New()
	pixel_x = rand(0,16)-8
	pixel_y = rand(0,8)-8

/obj/item/weapon/ore/ex_act()
	return

/*****************************Coin********************************/

/obj/item/weapon/coin
	icon = 'icons/obj/economy.dmi'
	name = "coin"
	icon_state = "coin__heads"
	flags = CONDUCT
	force = 1
	throwforce = 2
	w_class = 1.0
	var/string_attached
	var/list/sideslist = list("heads","tails")
	var/cmineral = null
	var/cooldown = 0
	var/value = 10

/obj/item/weapon/coin/New()
	pixel_x = rand(0,16)-8
	pixel_y = rand(0,8)-8

	icon_state = "coin_[cmineral]_heads"
	if(cmineral)
		name = "[cmineral] coin"

/obj/item/weapon/coin/gold
	cmineral = "gold"
	icon_state = "coin_gold_heads"
	value = 160

/obj/item/weapon/coin/silver
	cmineral = "silver"
	icon_state = "coin_silver_heads"
	value = 40

/obj/item/weapon/coin/diamond
	cmineral = "diamond"
	icon_state = "coin_diamond_heads"
	value = 120

/obj/item/weapon/coin/iron
	cmineral = "iron"
	icon_state = "coin_iron_heads"
	value = 20

/obj/item/weapon/coin/plasma
	cmineral = "plasma"
	icon_state = "coin_plasma_heads"
	value = 80

/obj/item/weapon/coin/uranium
	cmineral = "uranium"
	icon_state = "coin_uranium_heads"
	value = 160

/obj/item/weapon/coin/clown
	cmineral = "bananium"
	icon_state = "coin_bananium_heads"
	value = 600 //makes the clown cri

/obj/item/weapon/coin/adamantine
	cmineral = "adamantine"
	icon_state = "coin_adamantine_heads"
	value = 400

/obj/item/weapon/coin/mythril
	cmineral = "mythril"
	icon_state = "coin_mythril_heads"
	value = 400

/obj/item/weapon/coin/twoheaded
	cmineral = "iron"
	icon_state = "coin_iron_heads"
	desc = "Hey, this coin's the same on both sides!"
	sideslist = list("heads")
	value = 20

/obj/item/weapon/coin/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
	if(istype(W, /obj/item/stack/cable_coil))
		var/obj/item/stack/cable_coil/CC = W
		if(string_attached)
			user << "There already is a string attached to this coin."
			return

		if (CC.use(1))
			overlays += image('icons/obj/economy.dmi',"coin_string_overlay")
			string_attached = 1
			user << "You attach a string to the coin."
		else
			user << "You need one length of cable to attach a string to the coin."
			return

	else if(istype(W,/obj/item/weapon/wirecutters))
		if(!string_attached)
			..()
			return

		var/obj/item/stack/cable_coil/CC = new/obj/item/stack/cable_coil(user.loc)
		CC.amount = 1
		CC.update_icon()
		overlays = list()
		string_attached = null
		user << "You detach the string from the coin."
	else ..()

/obj/item/weapon/coin/attack_self(mob/user as mob)
	if(cooldown < world.time - 15)
		var/coinflip = pick(sideslist)
		cooldown = world.time
		flick("coin_[cmineral]_flip", src)
		icon_state = "coin_[cmineral]_[coinflip]"
		playsound(user.loc, 'sound/items/coinflip.ogg', 50, 1)
		if(do_after(user, 15))
			user.visible_message("[user] has flipped [src]. It lands on [coinflip].", \
								 "You flip [src]. It lands on [coinflip].", \
								 "You hear the clattering of loose change.")


code:
/**********************Ore box**************************/

/obj/structure/ore_box
	icon = 'icons/obj/mining.dmi'
	icon_state = "orebox"
	name = "ore box"
	desc = "It's heavy"
	density = 1

/obj/structure/ore_box/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
	if (istype(W, /obj/item/weapon/ore))
		user.drop_item()
		W.loc = src
	if (istype(W, /obj/item/weapon/storage))
		var/obj/item/weapon/storage/S = W
		S.hide_from(usr)
		for(var/obj/item/weapon/ore/O in S.contents)
			S.remove_from_storage(O, src) //This will move the item to this item's contents
		user << "You empty the satchel into the box."
	return

/obj/structure/ore_box/attack_hand(mob/user as mob)
	var/amt_gold = 0
	var/amt_silver = 0
	var/amt_diamond = 0
	var/amt_glass = 0
	var/amt_iron = 0
	var/amt_plasma = 0
	var/amt_uranium = 0
	var/amt_clown = 0

	for (var/obj/item/weapon/ore/C in contents)
		if (istype(C,/obj/item/weapon/ore/diamond))
			amt_diamond++;
		if (istype(C,/obj/item/weapon/ore/glass))
			amt_glass++;
		if (istype(C,/obj/item/weapon/ore/plasma))
			amt_plasma++;
		if (istype(C,/obj/item/weapon/ore/iron))
			amt_iron++;
		if (istype(C,/obj/item/weapon/ore/silver))
			amt_silver++;
		if (istype(C,/obj/item/weapon/ore/gold))
			amt_gold++;
		if (istype(C,/obj/item/weapon/ore/uranium))
			amt_uranium++;
		if (istype(C,/obj/item/weapon/ore/bananium))
			amt_clown++;

	var/dat = text("The contents of the ore box reveal...
")
	if (amt_gold)
		dat += text("Gold ore: [amt_gold]
")
	if (amt_silver)
		dat += text("Silver ore: [amt_silver]
")
	if (amt_iron)
		dat += text("Metal ore: [amt_iron]
")
	if (amt_glass)
		dat += text("Sand: [amt_glass]
")
	if (amt_diamond)
		dat += text("Diamond ore: [amt_diamond]
")
	if (amt_plasma)
		dat += text("Plasma ore: [amt_plasma]
")
	if (amt_uranium)
		dat += text("Uranium ore: [amt_uranium]
")
	if (amt_clown)
		dat += text("Bananium ore: [amt_clown]
")

	dat += text("

Empty box")
	user << browse("[dat]", "window=orebox")
	return

/obj/structure/ore_box/Topic(href, href_list)
	if(..())
		return
	usr.set_machine(src)
	src.add_fingerprint(usr)
	if(href_list["removeall"])
		for (var/obj/item/weapon/ore/O in contents)
			contents -= O
			O.loc = src.loc
		usr << "You empty the box."
	src.updateUsrDialog()
	return

obj/structure/ore_box/ex_act(severity, target)
	if(prob(100 / severity) && severity < 3)
		qdel(src) //nothing but ores can get inside unless its a bug and ores just return nothing on ex_act, not point in calling it on them


code:
// Camera mob, used by AI camera and blob.

/mob/camera
	name = "camera mob"
	density = 0
	anchored = 1
	status_flags = GODMODE  // You can't damage it.
	mouse_opacity = 0
	see_in_dark = 7
	invisibility = 101 // No one can see us

	move_on_shuttle = 0

/mob/camera/experience_pressure_difference()
	return

/mob/camera/Destroy()
	..()
	del(src)

/mob/camera/Login()
	..()
	update_interface()


code:
/mob/dead/dust()	//ghosts can't be vaporised.
	return

/mob/dead/gib(var/animation = 1)		//ghosts can't be gibbed.
	return


code:
/mob/dead/observer/Login()
	..()
	if(client.prefs.unlock_content)
		icon_state = client.prefs.ghost_form
		if (ghostimage)
			ghostimage.icon_state = src.icon_state

	updateghostimages()

	update_interface()


code:
/mob/dead/observer/Logout()
	if (client)
		client.images -= ghost_darkness_images
	..()
	spawn(0)
		if(src && !key)	//we've transferred to another mob. This ghost should be deleted.
			qdel(src)


code:
var/list/image/ghost_darkness_images = list() //this is a list of images for things ghosts should still be able to see when they toggle darkness
/mob/dead/observer
	name = "ghost"
	desc = "It's a g-g-g-g-ghooooost!" //jinkies!
	icon = 'icons/mob/mob.dmi'
	icon_state = "ghost"
	layer = MOB_LAYER + 1
	stat = DEAD
	density = 0
	canmove = 0
	anchored = 1	//  don't get pushed around
	invisibility = INVISIBILITY_OBSERVER
	languages = ALL
	hud_possible = list(ANTAG_HUD)
	var/can_reenter_corpse
	var/datum/hud/living/carbon/hud = null // hud
	var/bootime = 0
	var/started_as_observer //This variable is set to 1 when you enter the game as an observer.
							//If you died in the game and are a ghsot - this will remain as null.
							//Note that this is not a reliable way to determine if admins started as observers, since they change mobs a lot.
	var/atom/movable/following = null
	var/fun_verbs = 0
	var/image/ghostimage = null //this mobs ghost image, for deleting and stuff
	var/ghostvision = 1 //is the ghost able to see things humans can't?
	var/seedarkness = 1

/mob/dead/observer/New(mob/body)
	sight |= SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
	see_invisible = SEE_INVISIBLE_OBSERVER
	see_in_dark = 100
	verbs += /mob/dead/observer/proc/dead_tele
	stat = DEAD

	ghostimage = image(src.icon,src,src.icon_state)
	ghost_darkness_images |= ghostimage
	updateallghostimages()
	overlays.len = 0
	var/turf/T
	if(ismob(body))
		T = get_turf(body)				//Where is the body located?
		attack_log = body.attack_log	//preserve our attack logs by copying them to our ghost

		gender = body.gender
		if(body.mind && body.mind.name)
			name = body.mind.name
		else
			if(body.real_name)
				name = body.real_name
			else
				name = random_name(gender)

		mind = body.mind	//we don't transfer the mind but we keep a reference to it.

	if(!T)	T = pick(latejoin)			//Safety in case we cannot find the body's position
	loc = T

	if(!name)							//To prevent nameless ghosts
		name = random_name(gender)
	real_name = name

	if(!fun_verbs)
		verbs -= /mob/dead/observer/verb/possess

	animate(src, pixel_y = 2, time = 10, loop = -1)

	..()
/mob/dead/observer/Destroy()
	if (ghostimage)
		ghost_darkness_images -= ghostimage
		qdel(ghostimage)
		ghostimage = null
		updateallghostimages()
	..()

/mob/dead/CanPass(atom/movable/mover, turf/target, height=0)
	return 1
/*
Transfer_mind is there to check if mob is being deleted/not going to have a body.
Works together with spawning an observer, noted above.
*/

/mob/proc/ghostize(var/can_reenter_corpse = 1)
	if(key)
		if(!cmptext(copytext(key,1,2),"@")) //aghost
			var/mob/dead/observer/ghost = new(src)	//Transfer safety to observer spawning proc.
			ghost.can_reenter_corpse = can_reenter_corpse
			ghost.key = key
			return ghost

/*
This is the proc mobs get to turn into a ghost. Forked from ghostize due to compatibility issues.
*/
/mob/living/verb/ghost()
	set category = "OOC"
	set name = "Ghost"
	set desc = "Relinquish your life and enter the land of the dead."

	if(stat != DEAD)
		succumb()
	if(stat == DEAD)
		ghostize(1)
	else
		var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you may not play again this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
		if(response != "Ghost")	return	//didn't want to ghost after-all
		resting = 1
		ghostize(0)						//0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3
	return

/mob/dead/observer/Move(NewLoc, direct)
	if(NewLoc)
		loc = NewLoc
		for(var/obj/effect/step_trigger/S in NewLoc)
			S.Crossed(src)

		return
	loc = get_turf(src) //Get out of closets and such as a ghost
	if((direct & NORTH) && y < world.maxy)
		y++
	else if((direct & SOUTH) && y > 1)
		y--
	if((direct & EAST) && x < world.maxx)
		x++
	else if((direct & WEST) && x > 1)
		x--

	for(var/obj/effect/step_trigger/S in locate(x, y, z))	//<-- this is dumb
		S.Crossed(src)

/mob/dead/observer/can_use_hands()	return 0
/mob/dead/observer/is_active()		return 0

/mob/dead/observer/Stat()
	..()
	if(statpanel("Status"))
		stat(null, "Station Time: [worldtime2text()]")
		if(ticker)
			if(ticker.mode)
				//world << "DEBUG: ticker not null"
				if(ticker.mode.name == "AI malfunction")
					var/datum/game_mode/malfunction/malf = ticker.mode
					//world << "DEBUG: malf mode ticker test"
					if(malf.malf_mode_declared && (malf.apcs > 0))
						stat(null, "Time left: [max(malf.AI_win_timeleft/malf.apcs, 0)]")

/mob/dead/observer/verb/reenter_corpse()
	set category = "Ghost"
	set name = "Re-enter Corpse"
	if(!client)	return
	if(!(mind && mind.current))
		src << "You have no body."
		return
	if(!can_reenter_corpse)
		src << "You cannot re-enter your body."
		return
	if(mind.current.key && copytext(mind.current.key,1,2)!="@")	//makes sure we don't accidentally kick any clients
		usr << "Another consciousness is in your body...It is resisting you."
		return
	if(mind.current.ajourn && mind.current.stat != DEAD) 	//check if the corpse is astral-journeying (it's client ghosted using a cultist rune).
		var/obj/effect/rune/R = locate() in mind.current.loc	//whilst corpse is alive, we can only reenter the body if it's on the rune
		if(!(R && R.word1 == wordhell && R.word2 == wordtravel && R.word3 == wordself))	//astral journeying rune
			usr << "The astral cord that ties your body and your spirit has been severed. You are likely to wander the realm beyond until your body is finally dead and thus reunited with you."
			return
	mind.current.ajourn=0
	mind.current.key = key
	return 1

/mob/dead/observer/proc/dead_tele()
	set category = "Ghost"
	set name = "Teleport"
	set desc= "Teleport to a location"
	if(!istype(usr, /mob/dead/observer))
		usr << "Not when you're not dead!"
		return
	usr.verbs -= /mob/dead/observer/proc/dead_tele
	spawn(30)
		usr.verbs += /mob/dead/observer/proc/dead_tele
	var/A
	A = input("Area to jump to", "BOOYEA", A) as null|anything in ghostteleportlocs
	var/area/thearea = ghostteleportlocs[A]
	if(!thearea)	return

	var/list/L = list()
	for(var/turf/T in get_area_turfs(thearea.type))
		L+=T

	if(!L || !L.len)
		usr << "No area available."

	usr.loc = pick(L)

/mob/dead/observer/verb/follow()
	set category = "Ghost"
	set name = "Follow" // "Haunt"
	set desc = "Follow and haunt a mob."

	var/list/mobs = getmobs()
	var/input = input("Please, select a mob!", "Haunt", null, null) as null|anything in mobs
	var/mob/target = mobs[input]
	ManualFollow(target)

// This is the ghost's follow verb with an argument
/mob/dead/observer/proc/ManualFollow(var/atom/movable/target)
	if(target && target != src)
		if(following && following == target)
			return
		following = target
		src << "Now following [target]"
		spawn(0)
			var/turf/pos = get_turf(src)
			while(loc == pos && target && following == target && client)
				var/turf/T = get_turf(target)
				if(!T)
					break
				// To stop the ghost flickering.
				if(loc != T)
					loc = T
				pos = loc
				sleep(15)
			if (target == following) following = null

/mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak
	set category = "Ghost"
	set name = "Jump to Mob"
	set desc = "Teleport to a mob"

	if(istype(usr, /mob/dead/observer)) //Make sure they're an observer!

		var/list/dest = list() //List of possible destinations (mobs)
		var/target = null	   //Chosen target.

		dest += getmobs() //Fill list, prompt user with list
		target = input("Please, select a player!", "Jump to Mob", null, null) as null|anything in dest

		if (!target)//Make sure we actually have a target
			return
		else
			var/mob/M = dest[target] //Destination mob
			var/mob/A = src			 //Source mob
			var/turf/T = get_turf(M) //Turf of the destination mob

			if(T && isturf(T))	//Make sure the turf exists, then move the source to that destination.
				A.loc = T
			else
				A << "This mob is not located in the game world."

/mob/dead/observer/verb/boo()
	set category = "Ghost"
	set name = "Boo!"
	set desc= "Scare your crew members because of boredom!"

	if(bootime > world.time) return
	var/obj/machinery/light/L = locate(/obj/machinery/light) in view(1, src)
	if(L)
		L.flicker()
		bootime = world.time + 600
		return
	//Maybe in the future we can add more spooky code here!
	return

/mob/dead/observer/memory()
	set hidden = 1
	src << "You are dead! You have no mind to store memory!"

/mob/dead/observer/add_memory()
	set hidden = 1
	src << "You are dead! You have no mind to store memory!"

/mob/dead/observer/verb/toggle_ghostsee()
	set name = "Toggle Ghost Vision"
	set desc = "Toggles your ability to see things only ghosts can see, like other ghosts"
	set category = "Ghost"
	ghostvision = !(ghostvision)
	updateghostsight()
	usr << "You [(ghostvision?"now":"no longer")] have ghost vision."

/mob/dead/observer/verb/toggle_darkness()
	set name = "Toggle Darkness"
	set category = "Ghost"
	seedarkness = !(seedarkness)
	updateghostsight()

/mob/dead/observer/proc/updateghostsight()
	if (!seedarkness)
		see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING
	else
		see_invisible = SEE_INVISIBLE_OBSERVER
		if (!ghostvision)
			see_invisible = SEE_INVISIBLE_LIVING;
	updateghostimages()

/proc/updateallghostimages()
	for (var/mob/dead/observer/O in player_list)
		O.updateghostimages()

/mob/dead/observer/proc/updateghostimages()
	if (!client)
		return
	if (seedarkness || !ghostvision)
		client.images -= ghost_darkness_images
	else
		//add images for the 60inv things ghosts can normally see when darkness is enabled so they can see them now
		client.images |= ghost_darkness_images
		if (ghostimage)
			client.images -= ghostimage //remove ourself

/mob/dead/observer/verb/possess()
	set category = "Ghost"
	set name = "Possess!"
	set desc= "Take over the body of a mindless creature!"

	var/list/possessible = list()
	for(var/mob/living/L in living_mob_list)
		if(!(L in player_list) && !L.mind)
			possessible += L

	var/mob/living/target = input("Your new life begins today!", "Possess Mob", null, null) as null|anything in possessible

	if(!target)
		return 0
	if(can_reenter_corpse || (mind && mind.current))
		if(alert(src, "Your soul is still tied to your former life as [mind.current.name], if you go foward there is no going back to that life. Are you sure you wish to continue?", "Move On", "Yes", "No") == "No")
			return 0
	if(target.key)
		src << "Someone has taken this body while you were choosing!"
		return 0

	target.key = key
	return 1

/mob/dead/observer/verb/become_mommi()
	set name = "Become MoMMI"
	set category = "Ghost"
/*
	if(!config.respawn_as_mommi)
		src << "Respawning as MoMMI is disabled.."
		return

	var/timedifference = world.time - client.time_died_as_mouse
	if(client.time_died_as_mouse && timedifference <= mouse_respawn_time * 600)
		var/timedifference_text
		timedifference_text = time2text(mouse_respawn_time * 600 - timedifference,"mm:ss")
		src << "You may only spawn again as a mouse or MoMMI more than [mouse_respawn_time] minutes after your death. You have [timedifference_text] left."
		return
*/
	//find a viable mommi candidate
	var/obj/machinery/mommi_spawner/spawner
	var/list/found_spawners = list()
	for(var/obj/machinery/mommi_spawner/s in world)
		if(s.z == src.z && s.canSpawn())
			found_spawners.Add(s)
	if(found_spawners.len)
		spawner = pick(found_spawners)
		spawner.attack_ghost(src)
	else
		src << "Unable to find any powered MoMMI Spawners on this z-level."

//this is a mob verb instead of atom for performance reasons
//see /mob/verb/examinate() in mob.dm for more info
//overriden here and in /mob/living for different point span classes and sanity checks
/mob/dead/observer/pointed(atom/A as mob|obj|turf in view())
	if(!..())
		return 0
	usr.visible_message("[src] points to [A]")
	return 1

/mob/dead/observer/verb/view_manfiest()
	set name = "View Crew Manifest"
	set category = "Ghost"

	var/dat
	dat += "
Crew Manifest
"
	dat += data_core.get_manifest()

	src << browse(dat, "window=manifest;size=387x420;can_close=1")

/mob/dead/observer/Topic(href, href_list)
	if(href_list["follow"])
		var/atom/movable/target = locate(href_list["follow"])
		if((usr == src) && istype(target) && (target != src)) //for safety against href exploits
			ManualFollow(target)


code:
/mob/dead/observer/say(var/message)
	message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))

	if (!message)
		return

	log_say("Ghost/[src.key] : [message]")

	if (src.client)
		if(src.client.prefs.muted & MUTE_DEADCHAT)
			src << "You cannot talk in deadchat (muted)."
			return

		if (src.client.handle_spam_prevention(message,MUTE_DEADCHAT))
			return

	. = src.say_dead(message)

/mob/dead/observer/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq)
	if(radio_freq)
		var/atom/movable/virtualspeaker/V = speaker
		speaker = V.source
	src << "(F) [message]"


code:
//This is the proc for gibbing a mob. Cannot gib ghosts.
//added different sort of gibs and animations. N
/mob/proc/gib()
	return

//This is the proc for turning a mob into ash. Mostly a copy of gib code (above).
//Originally created for wizard disintegrate. I've removed the virus code since it's irrelevant here.
//Dusting robots does not eject the MMI, so it's a bit more powerful than gib() /N
/mob/proc/dust()
	return

/mob/proc/death(gibbed)
	return


code:
#define INTERACTING 2
#define TRAVEL 4
#define FIGHTING 8

//TRAITS

#define TRAIT_ROBUST 2
#define TRAIT_UNROBUST 4
#define TRAIT_SMART 8
#define TRAIT_DUMB 16
#define TRAIT_MEAN 32
#define TRAIT_FRIENDLY 64
#define TRAIT_THIEVING 128

//defines
#define MAX_RANGE_FIND 32
#define MIN_RANGE_FIND 16
#define FUZZY_CHANCE_HIGH 85
#define FUZZY_CHANCE_LOW 50
#define CHANCE_TALK 15

/*
	NPC VAR EXPLANATIONS (for modules and other things)

		doing = their current action, INTERACTING, TRAVEL or FIGHTING
		interest = how interested the NPC is in the situation, if they are idle, this drops
		timeout = this is internal
		TARGET = their current target
		LAST_TARGET = their last target
		nearby = a list of nearby mobs
		best_force = the highest force object, used for checking when to swap items
		retal = this is internal
		retal_target = this is internal
		update_hands = this is a bool (1/0) to determine if the NPC should update what is in his hands

		MYID = their ID card
		MYPDA = their PDA
		main_hand = what is in their "main" hand (chosen from left > right)
		TRAITS = the traits assigned to this npc
		mymjob = the job assigned to the npc

		robustness = the chance for the npc to hit something
		smartness = the inverse chance for an npc to do stupid things
		attitude = the chance for an npc to do rude or mean things
		slyness = the chance for an npc to do naughty things ie thieving

		functions = the list of procs that the npc will use for modules

		graytide = shitmin var to make them go psycho
*/

/mob/living/carbon/human/interactive
	name = "interactive station member"
	var/doing = 0
	var/interest = 100
	var/timeout = 0
	var/inactivity_period = 0
	var/TARGET = null
	var/LAST_TARGET = null
	var/list/nearby = list()
	var/best_force = 0
	var/retal = 0
	var/mob/retal_target = null
	var/update_hands = 0
	//Job and mind data
	var/obj/item/weapon/card/id/MYID
	var/obj/item/device/pda/MYPDA
	var/obj/item/main_hand
	var/obj/item/other_hand
	var/TRAITS = 0
	var/datum/job/myjob
	//trait vars
	var/robustness = 50
	var/smartness = 50
	var/attitude = 50
	var/slyness = 50
	var/graytide = 0
	var/chattyness = CHANCE_TALK
	//modules
	var/list/functions = list("nearbyscan","combat","doorscan","shitcurity","chatter")

/mob/living/carbon/human/interactive/proc/random()
	//this is here because this has no client/prefs/brain whatever.
	underwear = random_underwear(gender)
	skin_tone = random_skin_tone()
	hair_style = random_hair_style(gender)
	facial_hair_style = random_facial_hair_style(gender)
	hair_color = random_short_color()
	facial_hair_color = hair_color
	eye_color = random_eye_color()
	age = rand(AGE_MIN,AGE_MAX)
	ready_dna(src,random_blood_type())
	//job handling
	var/list/jobs = SSjob.occupations
	for(var/datum/job/J in jobs)
		if(J.title == "Cyborg" || J.title == "AI" || J.title == "Chaplain" || J.title == "Mime")
			jobs -= J
	myjob = pick(jobs)
	if(!graytide)
		myjob.equip(src)
	myjob.apply_fingerprints(src)
	src.job = myjob

/mob/living/carbon/human/interactive/attacked_by(var/obj/item/I, var/mob/living/user, var/def_zone)
	..()
	retal = 1
	retal_target = user

/mob/living/carbon/human/interactive/New()
	..()
	gender = pick(MALE,FEMALE)
	if(gender == MALE)
		name = "[pick(first_names_male)] [pick(last_names)]"
		real_name = name
	else
		name = "[pick(first_names_female)] [pick(last_names)]"
		real_name = name
	random()
	MYID = new(src)
	MYID.name = "[src.real_name]'s ID Card ([myjob.title])"
	MYID.assignment = "[myjob.title]"
	MYID.registered_name = src.real_name
	MYID.access = myjob.access
	src.equip_to_slot_or_del(MYID, slot_wear_id)
	MYPDA = new(src)
	MYPDA.owner = src.real_name
	MYPDA.ownjob = "Crew"
	MYPDA.name = "PDA-[src.real_name] ([myjob.title])"
	src.equip_to_slot_or_del(MYPDA, slot_belt)
	zone_sel = new /obj/screen/zone_sel()
	zone_sel.selecting = "chest"
	if(prob(10)) //my x is augmented
		//arms
		if(prob(rand(FUZZY_CHANCE_LOW,FUZZY_CHANCE_HIGH)))
			var/obj/item/organ/limb/r_arm/R = locate(/obj/item/organ/limb/r_arm) in organs
			del(R)
			organs += new /obj/item/organ/limb/robot/r_arm
		else
			var/obj/item/organ/limb/l_arm/L = locate(/obj/item/organ/limb/l_arm) in organs
			del(L)
			organs += new /obj/item/organ/limb/robot/l_arm
		//legs
		if(prob(rand(FUZZY_CHANCE_LOW,FUZZY_CHANCE_HIGH)))
			var/obj/item/organ/limb/r_leg/R = locate(/obj/item/organ/limb/r_leg) in organs
			del(R)
			organs += new /obj/item/organ/limb/robot/r_leg
		else
			var/obj/item/organ/limb/l_leg/L = locate(/obj/item/organ/limb/l_leg) in organs
			del(L)
			organs += new /obj/item/organ/limb/robot/l_leg
		//chest and head
		if(prob(rand(FUZZY_CHANCE_LOW,FUZZY_CHANCE_HIGH)))
			var/obj/item/organ/limb/chest/R = locate(/obj/item/organ/limb/chest) in organs
			del(R)
			organs += new /obj/item/organ/limb/robot/chest
		else
			var/obj/item/organ/limb/head/L = locate(/obj/item/organ/limb/head) in organs
			del(L)
			organs += new /obj/item/organ/limb/robot/head
		for(var/obj/item/organ/limb/LIMB in organs)
			LIMB.owner = src
	update_icons()
	update_damage_overlays(0)
	update_augments()

	hand = 0

	if(TRAITS & TRAIT_ROBUST)
		robustness = 75
	else if(TRAITS & TRAIT_UNROBUST)
		robustness = 25

	//modifiers are prob chances, lower = smarter
	if(TRAITS & TRAIT_SMART)
		smartness = 25
	else if(TRAITS & TRAIT_DUMB)
		mutations |= CLUMSY
		smartness = 75

	if(TRAITS & TRAIT_MEAN)
		attitude = 75
	else if(TRAITS & TRAIT_FRIENDLY)
		attitude = 1

	if(TRAITS & TRAIT_THIEVING)
		slyness = 75

/mob/living/carbon/human/interactive/attack_hand(mob/living/carbon/human/M as mob)
	..()
	if (health > 0)
		if(M.a_intent == "help")
			chatter()
		if(M.a_intent == "harm")
			retal = 1
			retal_target = M

//THESE EXIST FOR DEBUGGING OF THE DOING/INTEREST SYSTEM EASILY
/mob/living/carbon/human/interactive/proc/doing2string(var/doin)
	var/toReturn = ""
	if(!doin)
		toReturn = "not doing anything"
	if(doin & INTERACTING)
		toReturn += "interacting with something, "
	if(doin & FIGHTING)
		toReturn += "engaging in combat, "
	if(doin & TRAVEL)
		toReturn += "and going somewhere"
	return toReturn

/mob/living/carbon/human/interactive/proc/interest2string(var/inter)
	var/toReturn = "Flatlined"
	if(inter >= 0 && inter <= 25)
		toReturn = "Very Bored"
	if(inter >= 26 && inter <= 50)
		toReturn = "Bored"
	if(inter >= 51 && inter <= 75)
		toReturn = "Content"
	if(inter >= 76)
		toReturn = "Excited"
	return toReturn
//END DEBUG
/mob/living/carbon/human/interactive/proc/isnotfunc()
	if(!canmove)
		return 1
	if(health <= 0)
		return 1
	if(restrained())
		return 1
	if(paralysis)
		return 1
	if(stunned)
		return 1
	if(stat)
		return 1
	if(inactivity_period > 0)
		return 1
	return 0

/mob/living/carbon/human/interactive/proc/enforce_hands()
	if(hand)
		if(!l_hand)
			main_hand = null
			if(r_hand)
				swap_hands()
	else
		if(!r_hand)
			main_hand = null
			if(l_hand)
				swap_hands()

/mob/living/carbon/human/interactive/proc/swap_hands()
	hand = !hand
	var/obj/item/T = other_hand
	main_hand = other_hand
	other_hand = T

/mob/living/carbon/human/interactive/proc/take_to_slot(var/obj/item/G)
	var/list/slots = list ("left pocket" = slot_l_store,"right pocket" = slot_r_store,"left hand" = slot_l_hand,"right hand" = slot_r_hand)
	G.loc = src
	if(G.force && G.force > best_force)
		best_force = G.force
	equip_in_one_of_slots(G, slots)
	update_hands = 1

/mob/living/carbon/human/interactive/proc/insert_into_backpack()
	var/list/slots = list ("left pocket" = slot_l_store,"right pocket" = slot_r_store,"left hand" = slot_l_hand,"right hand" = slot_r_hand)
	var/obj/item/I = get_item_by_slot(pick(slots))
	var/obj/item/weapon/storage/BP = get_item_by_slot(slot_back)
	if(back && BP && I)
		if(BP.can_be_inserted(I,0))
			BP.handle_item_insertion(I,0)
	else
		unEquip(I,TRUE)
	update_hands = 1

/mob/living/carbon/human/interactive/Life()
	..()
	if(isnotfunc()) return
	if(a_intent != "disarm")
		a_intent = "disarm"
	//---------------------------
	//---- interest flow control
	if(interest < 0 || inactivity_period < 0)
		if(interest < 0)
			interest = 0
		if(inactivity_period < 0)
			inactivity_period = 0
	if(interest > 100)
		interest = 100
	//---------------------------
	nearby = list()
	//VIEW FUNCTIONS

	if(!l_hand || !r_hand)
		update_hands = 1

	if(update_hands)
		if(l_hand || r_hand)
			if(l_hand)
				hand = 1
				main_hand = l_hand
				if(r_hand)
					other_hand = r_hand
			else if(r_hand)
				hand = 0
				main_hand = r_hand
				if(l_hand) //this technically shouldnt occur, but its a redundancy
					other_hand = l_hand
			update_icons()
		update_hands = 0

	if(grabbed_by.len > 0)
		for(var/obj/item/weapon/grab/G in grabbed_by)
			if(Adjacent(G))
				a_intent = "disarm"
				G.assailant.attack_hand(src)
				inactivity_period = 10

	//proc functions
	for(var/Proc in functions)
		if(!isnotfunc())
			spawn(1)
				call(src,Proc)(src)

	//target interaction stays hardcoded

	if((TARGET && (TARGET in view(1))) || timeout >= 2)
		if((TARGET in view(1,src)))//this is a bit redundant but it saves two if blocks
			doing |= INTERACTING
			//--------DOORS
			if(istype(TARGET, /obj/machinery/door))
				var/obj/machinery/door/D = TARGET
				if(D.check_access(MYID) && !istype(D,/obj/machinery/door/poddoor))
					D.open()
					sleep(15)
					var/turf/T = get_step(get_step(D.loc,dir),dir) //recursion yo
					tryWalk(T)
			//THIEVING SKILLS
			if(prob(slyness))
				//---------TOOLS
				if(istype(TARGET, /obj/item/weapon))
					var/obj/item/weapon/W = TARGET
					if(W.force >= best_force || prob(rand(FUZZY_CHANCE_LOW,FUZZY_CHANCE_HIGH)))
						if(!l_hand || !r_hand)
							take_to_slot(W)
						else
							insert_into_backpack()
				//---------FASHION
				if(istype(TARGET,/obj/item/clothing))
					if(prob(rand(FUZZY_CHANCE_LOW,FUZZY_CHANCE_HIGH)))
						if(!l_hand || !r_hand)
							var/obj/item/clothing/C = TARGET
							take_to_slot(C)
							if(equip_to_appropriate_slot(C))
								C.update_icon()
							else
								var/obj/item/I = get_item_by_slot(C)
								unEquip(I)
								equip_to_appropriate_slot(C)
							update_hands = 1
							drop_item()
							if(MYPDA in src.loc || MYID in src.loc)
								if(MYPDA in src.loc)
									equip_to_appropriate_slot(MYPDA)
								if(MYID in src.loc)
									equip_to_appropriate_slot(MYID)
							update_icons()
			//THIEVING SKILLS END
			//-------------TOUCH ME
			if(istype(TARGET,/obj/structure))
				var/obj/structure/STR = TARGET
				if(main_hand)
					var/obj/item/weapon/W = main_hand
					STR.attackby(W, src)
				else
					STR.attack_hand(src)
		interest = interest + 25
		doing = doing & ~INTERACTING
		timeout = 0
		TARGET = null
	else
		tryWalk(TARGET)
		timeout++
	if(!doing)
		interest--
	else
		interest++
	if(inactivity_period > 0)
		inactivity_period--

	//this is boring, lets move
	if(!doing && !isnotfunc() && !TARGET)
		doing |= TRAVEL
		if(nearby.len > 4)
			//i'm crowded, time to leave
			TARGET = pick(target_filter(orange(MAX_RANGE_FIND,src)))
		else if(prob(rand(FUZZY_CHANCE_LOW,FUZZY_CHANCE_HIGH)))
			//chance to chase an item
			TARGET = locate(/obj/item) in orange(MIN_RANGE_FIND,src)
		else if(prob(rand(FUZZY_CHANCE_LOW,FUZZY_CHANCE_HIGH)))
			//chance to leave
			TARGET = locate(/obj/machinery/door) in orange(MIN_RANGE_FIND,src) // this is a sort of fix for the current pathing.
		else
			//else, target whatever, or go to our department
			if(prob(rand(FUZZY_CHANCE_LOW,FUZZY_CHANCE_HIGH)))
				TARGET = pick(target_filter(orange(MIN_RANGE_FIND,src)))
			else
				TARGET = pick(get_area_turfs(job2area(myjob)))
		tryWalk(TARGET)
	LAST_TARGET = TARGET

/mob/living/carbon/human/interactive/proc/tryWalk(var/turf/TARGET)
	if(!isnotfunc())
		if(!walk2derpless(TARGET))
			timeout++
	else
		timeout++

/mob/living/carbon/human/interactive/proc/walk2derpless(var/target)
	set background = 1
	var/turf/T = get_turf(target)
	var/turf/D = get_step(src,dir)
	if(D)
		if(!D.density)
			walk_to(src,T,0,5)
			doing = doing & ~TRAVEL
			return 1
		else
			sidestep(D)
			doing = doing & ~TRAVEL
			return 0
	else
		doing = doing & ~TRAVEL
		return 0

/mob/living/carbon/human/interactive/proc/job2area(var/target)
	var/datum/job/T = target
	if(T.title == "Assistant")
		return /area/hallway/primary
	if(T.title == "Captain" || T.title == "Head of Personnel")
		return /area/bridge
	if(T.title == "Bartender" || T.title == "Chef")
		return /area/crew_quarters
	if(T.title == "Station Engineer" || T.title == "Chief Engineer" || T.title == "Atmospheric Technician")
		return /area/engine
	if(T.title == "Chief Medical Officer" || T.title == "Medical Doctor" || T.title == "Chemist" || T.title == "Virologist" || T.title == "Geneticist")
		return /area/medical
	if(T.title == "Research Director" || T.title == "Scientist" || T.title == "Roboticist")
		return /area/toxins
	if(T.title == "Head of Security" || T.title == "Warden" || T.title == "Security Officer" || T.title == "Detective")
		return /area/security
	else
		return pick(/area/hallway,/area/crew_quarters)

/mob/living/carbon/human/interactive/proc/target_filter(var/target)
	var/list/L = target
	for(var/atom/A in target)
		if(istype(A,/area) || istype(A,/turf/space))
			L -= A
	return L

/mob/living/carbon/human/interactive/proc/denied_filter(var/target)
	var/list/denied = list(/obj/structure/window,/obj/structure/table) //expand me
	for(var/a in denied)
		if(istype(target,a))
			return 1
	return 0

///BUILT IN MODULES
/mob/living/carbon/human/interactive/proc/chatter(obj)
	var/verbs_use = pick_list("npc_chatter.txt","verbs_use")
	var/verbs_touch = pick_list("npc_chatter.txt","verbs_touch")
	var/verbs_move = pick_list("npc_chatter.txt","verbs_move")
	var/nouns_insult = pick_list("npc_chatter.txt","nouns_insult")
	var/nouns_generic = pick_list("npc_chatter.txt","nouns_generic")
	var/nouns_objects = pick_list("npc_chatter.txt","nouns_objects")
	var/nouns_body = pick_list("npc_chatter.txt","nouns_body")
	var/adjective_insult = pick_list("npc_chatter.txt","adjective_insult")
	var/adjective_objects = pick_list("npc_chatter.txt","adjective_objects")
	var/adjective_generic = pick_list("npc_chatter.txt","adjective_generic")
	var/curse_words = pick_list("npc_chatter.txt","curse_words")

	if(doing & INTERACTING)
		if(prob(chattyness))
			var/chat = pick("This [nouns_objects] is a little [adjective_objects].",
			"Well [verbs_use] my [nouns_body], this [nouns_insult] is pretty [adjective_insult].",
			"[capitalize(curse_words)], what am I meant to do with this [adjective_insult] [nouns_objects].")
			src.say(chat)
	if(doing & TRAVEL)
		if(prob(chattyness))
			var/chat = pick("Oh [curse_words], [verbs_move]!",
			"Time to get my [adjective_generic] [adjective_insult] [nouns_body] elsewhere.",
			"I wonder if there is anything to [verbs_use] and [verbs_touch] somewhere else..")
			src.say(chat)
	if(doing & FIGHTING)
		if(prob(chattyness))
			var/chat = pick("I'm going to [verbs_use] you, you [adjective_insult] [nouns_insult]!",
			"Rend and [verbs_touch], Rend and [verbs_use]!",
			"You [nouns_insult], I'm going to [verbs_use] you right in the [nouns_body]. JUST YOU WAIT!")
			src.say(chat)
	if(prob(chattyness/2))
		var/what = pick(1,2,3,4,5)
		switch(what)
			if(1)
				src.say("Well [curse_words], this is a [adjective_generic] situation.")
			if(2)
				src.say("Oh [curse_words], that [nouns_insult] was one hell of an [adjective_insult] [nouns_body].")
			if(3)
				src.say("I want to [verbs_use] that [nouns_insult] when I find them.")
			if(4)
				src.say("[pick("Innocent","Guilty","Traitorous","Honk")] until proven [adjective_generic]!")
			if(5)
				var/toSay = ""
				for(var/i = 0; i < 5; i++)
					curse_words = pick_list("npc_chatter.txt","curse_words")
					toSay += "[curse_words] "
				src.say("Hey [nouns_generic], why dont you go [toSay], you [nouns_insult]!")

/mob/living/carbon/human/interactive/proc/shitcurity(obj)
	if(retal && TARGET)
		for(var/obj/item/I in src.contents)
			if(istype(I,/obj/item/weapon/restraints/handcuffs))
				take_to_slot(I)
				I.attack(TARGET,src)
				sleep(25)

/mob/living/carbon/human/interactive/proc/sidestep(obj)
	var/shift = 0
	for(var/dir in cardinal)
		var/turf/T = get_step(src,dir)
		if(T)
			for(var/obj/A in T.contents)
				if(denied_filter(A))
					shift = 1
			if(T.density)
				shift = 1
			if(shift)
				if(src.dir == NORTH || SOUTH)
					var/towalk = pick(EAST,WEST)
					walk_to(src,get_step(src,towalk),0,5)
				else
					var/towalk = pick(NORTH,SOUTH)
					walk_to(src,get_step(src,towalk),0,5)

/mob/living/carbon/human/interactive/proc/combat(obj)
	set background = 1
	enforce_hands()
	if(canmove)
		if(prob(attitude) && (graytide || (TRAITS & TRAIT_MEAN)) || retal)
			a_intent = "harm"
			zone_sel.selecting = pick("chest","r_leg","l_leg","r_arm","l_arm","head")
			doing |= FIGHTING
			if(retal)
				TARGET = retal_target
			else
				var/mob/living/M = locate(/mob/living) in oview(7,src)
				if(istype(M,/mob/living/carbon/human/interactive/greytide))
					return
				if(M != src)
					TARGET = M
				if(!M)
					doing = doing & ~FIGHTING

	if((TARGET && (doing & FIGHTING)) || graytide) // this is a redundancy check
		var/mob/living/M = TARGET
		if(istype(M,/mob/living))
			if(M in range(FUZZY_CHANCE_LOW,src))
				if(M.health > 1)
					if(main_hand)
						if(main_hand.force != 0)
							if(istype(main_hand,/obj/item/weapon/gun/projectile))
								var/obj/item/weapon/gun/projectile/P = main_hand
								if(!P.chambered)
									P.chamber_round()
									P.update_icon()
								else if(P.get_ammo(1) == 0)
									P.attack_self(src)
								else
									P.afterattack(TARGET, src)
							else if(istype(main_hand,/obj/item/weapon/gun/energy))
								var/obj/item/weapon/gun/energy/P = main_hand
								if(!P.can_shoot())
									P.update_icon()
									drop_item()
								else
									P.afterattack(TARGET, src)
							else
								if(get_dist(src,TARGET) > 2)
									if(!walk2derpless(TARGET))
										timeout++
								else
									var/obj/item/weapon/W = main_hand
									if(prob(robustness))
										W.attack(TARGET,src)
							sleep(1)
					else
						if(get_dist(src,TARGET) > 2)
							tryWalk(TARGET)
						else
							if(Adjacent(TARGET))
								M.attack_hand(src)
								sleep(1)
				timeout++
			else if(timeout >= 10 || M.health <= 1 || !(M in range(14,src)))
				doing = doing & ~FIGHTING
				timeout = 0
				TARGET = null
				retal = 0
				retal_target = null
		else
			timeout++

/mob/living/carbon/human/interactive/proc/doorscan(obj)
	for(var/dir in cardinal)
		var/turf/T = get_step(src,dir)
		if(T)
			for(var/obj/machinery/door/D in T.contents)
				if(D.check_access(MYID) && !istype(D,/obj/machinery/door/poddoor) && D.density)
					//layer 3.1 is "closed" for most doors, this is just a hacky !open check because i cannot find an open var
					spawn(1)
						D.open()
						sleep(5)
						walk2derpless(get_step(D,dir))

/mob/living/carbon/human/interactive/proc/nearbyscan(obj)
	for(var/mob/living/M in view(4,src))
		if(M != src)
			nearby += M

//END OF MODULES
/mob/living/carbon/human/interactive/angry
	New()
		TRAITS |= TRAIT_ROBUST
		TRAITS |= TRAIT_MEAN
		..()

/mob/living/carbon/human/interactive/friendly
	New()
		TRAITS |= TRAIT_FRIENDLY
		TRAITS |= TRAIT_UNROBUST
		..()

/mob/living/carbon/human/interactive/greytide
	New()
		TRAITS |= TRAIT_ROBUST
		TRAITS |= TRAIT_MEAN
		TRAITS |= TRAIT_THIEVING
		TRAITS |= TRAIT_DUMB
		graytide = 1
		..()

#undef INTERACTING
#undef TRAVEL
#undef FIGHTING
#undef TRAIT_ROBUST
#undef TRAIT_UNROBUST
#undef TRAIT_SMART
#undef TRAIT_DUMB
#undef TRAIT_MEAN
#undef TRAIT_FRIENDLY
#undef TRAIT_THIEVING


code:
//These procs handle putting s tuff in your hand. It's probably best to use these rather than setting l_hand = ...etc
//as they handle all relevant stuff like adding it to the player's screen and updating their overlays.

//Returns the thing in our active hand
/mob/proc/get_active_hand()
	if(hand)	return l_hand
	else		return r_hand

//Returns the thing in our inactive hand
/mob/proc/get_inactive_hand()
	if(hand)	return r_hand
	else		return l_hand

//Returns if a certain item can be equipped to a certain slot.
// Currently invalid for two-handed items - call obj/item/mob_can_equip() instead.
/mob/proc/can_equip(obj/item/I, slot, disable_warning = 0)
	return 0

//Puts the item into your l_hand if possible and calls all necessary triggers/updates. returns 1 on success.
/mob/proc/put_in_l_hand(var/obj/item/W)
	if(!put_in_hand_check(W))
		return 0
	if(!l_hand)
		W.loc = src		//TODO: move to equipped?
		l_hand = W
		W.layer = 20	//TODO: move to equipped?
//		l_hand.screen_loc = ui_lhand
		W.equipped(src,slot_l_hand)
		if(client)	client.screen |= W
		if(pulling == W) stop_pulling()
		update_inv_l_hand(0)
		W.pixel_x = initial(W.pixel_x)
		W.pixel_y = initial(W.pixel_y)
		return 1
	return 0

//Puts the item into your r_hand if possible and calls all necessary triggers/updates. returns 1 on success.
/mob/proc/put_in_r_hand(var/obj/item/W)
	if(!put_in_hand_check(W))
		return 0
	if(!r_hand)
		W.loc = src
		r_hand = W
		W.layer = 20
//		r_hand.screen_loc = ui_rhand
		W.equipped(src,slot_r_hand)
		if(client)	client.screen |= W
		if(pulling == W) stop_pulling()
		update_inv_r_hand(0)
		W.pixel_x = initial(W.pixel_x)
		W.pixel_y = initial(W.pixel_y)
		return 1
	return 0

/mob/proc/put_in_hand_check(var/obj/item/W)
	if(lying && !(W.flags&ABSTRACT))			return 0
	if(!istype(W))		return 0
	return 1

//Puts the item into our active hand if possible. returns 1 on success.
/mob/proc/put_in_active_hand(var/obj/item/W)
	if(hand)	return put_in_l_hand(W)
	else		return put_in_r_hand(W)

//Puts the item into our inactive hand if possible. returns 1 on success.
/mob/proc/put_in_inactive_hand(var/obj/item/W)
	if(hand)	return put_in_r_hand(W)
	else		return put_in_l_hand(W)

//Puts the item our active hand if possible. Failing that it tries our inactive hand. Returns 1 on success.
//If both fail it drops it on the floor and returns 0.
//This is probably the main one you need to know :)
/mob/proc/put_in_hands(var/obj/item/W)
	if(!W)		return 0
	if(put_in_active_hand(W))			return 1
	else if(put_in_inactive_hand(W))	return 1
	else
		W.loc = get_turf(src)
		W.layer = initial(W.layer)
		W.dropped()
		return 0

/mob/proc/drop_item_v()		//this is dumb.
	if(stat == CONSCIOUS && isturf(loc))
		return drop_item()
	return 0

//Drops the item in our left hand
/mob/proc/drop_l_hand() //I really fucking wonder why this proc had an argument holy shit.
	if(!loc.allow_drop())
		return
	return unEquip(l_hand) //All needed checks are in unEquip

//Drops the item in our right hand
/mob/proc/drop_r_hand()
	if(!loc.allow_drop())
		return
	return unEquip(r_hand) //Why was this not calling unEquip in the first place jesus fuck.

//Drops the item in our active hand.
/mob/proc/drop_item() //THIS. DOES. NOT. NEED. AN. ARGUMENT.
	if(hand)	return drop_l_hand()
	else		return drop_r_hand()

//Here lie drop_from_inventory and before_item_take, already forgotten and not missed.

/mob/proc/canUnEquip(obj/item/I, force)
	if(!I)
		return 1
	if((I.flags & NODROP) && !force)
		return 0
	return 1

/mob/proc/unEquip(obj/item/I, force) //Force overrides NODROP for things like wizarditis and admin undress.
	if(!I) //If there's nothing to drop, the drop is automatically succesfull. If(unEquip) should generally be used to check for NODROP.
		return 1

	if((I.flags & NODROP) && !force)
		return 0

	if(I == r_hand)
		r_hand = null
		update_inv_r_hand()
	else if(I == l_hand)
		l_hand = null
		update_inv_l_hand()

	if(I)
		if(client)
			client.screen -= I
		I.loc = loc
		I.dropped(src)
		if(I)
			I.layer = initial(I.layer)
	return 1

//Attemps to remove an object on a mob.  Will not move it to another area or such, just removes from the mob.
/mob/proc/remove_from_mob(var/obj/O)
	unEquip(O)
	O.screen_loc = null
	return 1

//Outdated but still in use apparently. This should at least be a human proc.
/mob/proc/get_equipped_items()
	var/list/items = new/list()

	if(hasvar(src,"back")) if(src:back) items += src:back
	if(hasvar(src,"belt")) if(src:belt) items += src:belt
	if(hasvar(src,"ears")) if(src:ears) items += src:ears
	if(hasvar(src,"glasses")) if(src:glasses) items += src:glasses
	if(hasvar(src,"gloves")) if(src:gloves) items += src:gloves
	if(hasvar(src,"head")) if(src:head) items += src:head
	if(hasvar(src,"shoes")) if(src:shoes) items += src:shoes
	if(hasvar(src,"wear_id")) if(src:wear_id) items += src:wear_id
	if(hasvar(src,"wear_mask")) if(src:wear_mask) items += src:wear_mask
	if(hasvar(src,"wear_suit")) if(src:wear_suit) items += src:wear_suit
//	if(hasvar(src,"w_radio")) if(src:w_radio) items += src:w_radio  commenting this out since headsets go on your ears now PLEASE DON'T BE MAD KEELIN
	if(hasvar(src,"w_uniform")) if(src:w_uniform) items += src:w_uniform

	//if(hasvar(src,"l_hand")) if(src:l_hand) items += src:l_hand
	//if(hasvar(src,"r_hand")) if(src:r_hand) items += src:r_hand

	return items