code:
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33

/obj/machinery/power/emitter
	name = "Emitter"
	desc = "A heavy duty industrial laser"
	icon = 'icons/obj/singularity.dmi'
	icon_state = "emitter"
	anchored = 0
	density = 1
	req_access = list(access_engine_equip)

	use_power = 0
	idle_power_usage = 10
	active_power_usage = 300

	var/active = 0
	var/powered = 0
	var/fire_delay = 100
	var/maximum_fire_delay = 100
	var/minimum_fire_delay = 20
	var/last_shot = 0
	var/shot_number = 0
	var/state = 0
	var/locked = 0

/obj/machinery/power/emitter/New()
	..()
	component_parts = list()
	component_parts += new /obj/item/weapon/circuitboard/emitter(null)
	component_parts += new /obj/item/weapon/stock_parts/micro_laser(null)
	component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
	RefreshParts()

/obj/machinery/power/emitter/RefreshParts()
	var/max_firedelay = 120
	var/firedelay = 120
	var/min_firedelay = 24
	var/power_usage = 350
	for(var/obj/item/weapon/stock_parts/micro_laser/L in component_parts)
		max_firedelay -= 20 * L.rating
		min_firedelay -= 4 * L.rating
		firedelay -= 20 * L.rating
	maximum_fire_delay = max_firedelay
	minimum_fire_delay = min_firedelay
	fire_delay = firedelay
	for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
		power_usage -= 50 * M.rating
	active_power_usage = power_usage

/obj/machinery/power/emitter/verb/rotate()
	set name = "Rotate"
	set category = "Object"
	set src in oview(1)

	if(usr.stat || !usr.canmove || usr.restrained())
		return
	if (src.anchored)
		usr << "It is fastened to the floor!"
		return 0
	src.dir = turn(src.dir, 90)
	return 1

/obj/machinery/power/emitter/initialize()
	..()
	if(state == 2 && anchored)
		connect_to_network()

/obj/machinery/power/emitter/Destroy()
	if(ticker && ticker.current_state == GAME_STATE_PLAYING)
		message_admins("Emitter deleted at ([x],[y],[z] - JMP)",0,1)
		log_game("Emitter deleted at ([x],[y],[z])")
		investigate_log("deleted at ([x],[y],[z])","singulo")
	..()

/obj/machinery/power/emitter/update_icon()
	if (active && powernet && avail(active_power_usage))
		icon_state = "emitter_+a"
	else
		icon_state = "emitter"

/obj/machinery/power/emitter/attack_hand(mob/user as mob)
	src.add_fingerprint(user)
	if(state == 2)
		if(!powernet)
			user << "The emitter isn't connected to a wire!"
			return 1
		if(!src.locked)
			if(src.active==1)
				src.active = 0
				user << "You turn off \the [src]."
				message_admins("Emitter turned off by [key_name(user, user.client)](?) in ([x],[y],[z] - JMP)",0,1)
				log_game("Emitter turned off by [user.ckey]([user]) in ([x],[y],[z])")
				investigate_log("turned off by [user.key]","singulo")
			else
				src.active = 1
				user << "You turn on \the [src]."
				src.shot_number = 0
				src.fire_delay = maximum_fire_delay
				investigate_log("turned on by [user.key]","singulo")
			update_icon()
		else
			user << "The controls are locked!"
	else
		user << "The [src] needs to be firmly secured to the floor first!"
		return 1

/obj/machinery/power/emitter/emp_act(var/severity)//Emitters are hardened but still might have issues
//	add_load(1000)
/*	if((severity == 1)&&prob(1)&&prob(1))
		if(src.active)
			src.active = 0
			src.use_power = 1	*/
	return 1

/obj/machinery/power/emitter/process()
	if(stat & (BROKEN))
		return
	if(src.state != 2 || (!powernet && active_power_usage))
		src.active = 0
		update_icon()
		return
	if(((src.last_shot + src.fire_delay) <= world.time) && (src.active == 1))

		if(!active_power_usage || avail(active_power_usage))
			add_load(active_power_usage)
			if(!powered)
				powered = 1
				update_icon()
				investigate_log("regained power and turned on","singulo")
		else
			if(powered)
				powered = 0
				update_icon()
				investigate_log("lost power and turned off","singulo")
				log_game("Emitter lost power in ([x],[y],[z])")
				message_admins("Emitter lost power in ([x],[y],[z] - JMP)",0,1)
			return

		src.last_shot = world.time
		if(src.shot_number < 3)
			src.fire_delay = 2
			src.shot_number ++
		else
			src.fire_delay = rand(minimum_fire_delay,maximum_fire_delay)
			src.shot_number = 0

		var/obj/item/projectile/beam/emitter/A = PoolOrNew(/obj/item/projectile/beam/emitter,src.loc)

		A.dir = src.dir
		playsound(src.loc, 'sound/weapons/emitter.ogg', 25, 1)

		if(prob(35))
			var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
			s.set_up(5, 1, src)
			s.start()

		switch(dir)
			if(NORTH)
				A.yo = 20
				A.xo = 0
			if(EAST)
				A.yo = 0
				A.xo = 20
			if(WEST)
				A.yo = 0
				A.xo = -20
			else // Any other
				A.yo = -20
				A.xo = 0
		A.starting = loc
		A.fire()

/obj/machinery/power/emitter/attackby(obj/item/W, mob/user, params)

	if(istype(W, /obj/item/weapon/wrench))
		if(active)
			user << "Turn off \the [src] first!"
			return
		switch(state)
			if(0 && !isinspace())
				state = 1
				playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
				user.visible_message("[user.name] secures [src.name] to the floor.", \
					"You secure the external reinforcing bolts to the floor.", \
					"You hear a ratchet")
				src.anchored = 1
			if(1)
				state = 0
				playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
				user.visible_message("[user.name] unsecures [src.name] reinforcing bolts from the floor.", \
					"You undo the external reinforcing bolts.", \
					"You hear a ratchet.")
				src.anchored = 0
			if(2)
				user << "The [src.name] needs to be unwelded from the floor!"
		return

	if(istype(W, /obj/item/weapon/weldingtool))
		var/obj/item/weapon/weldingtool/WT = W
		if(active)
			user << "Turn off \the [src] first."
			return
		switch(state)
			if(0)
				user << "The [src.name] needs to be wrenched to the floor!"
			if(1)
				if (WT.remove_fuel(0,user))
					playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
					user.visible_message("[user.name] starts to weld the [src.name] to the floor.", \
						"You start to weld \the [src] to the floor...", \
						"You hear welding.")
					if (do_after(user,20))
						if(!src || !WT.isOn()) return
						state = 2
						user << "You weld \the [src] to the floor."
						connect_to_network()
			if(2)
				if (WT.remove_fuel(0,user))
					playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
					user.visible_message("[user.name] starts to cut the [src.name] free from the floor.", \
						"You start to cut \the [src] free from the floor...", \
						"You hear welding.")
					if (do_after(user,20))
						if(!src || !WT.isOn()) return
						state = 1
						user << "You cut \the [src] free from the floor."
						disconnect_from_network()
		return

	if(istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda))
		if(emagged)
			user << "The lock seems to be broken!"
			return
		if(src.allowed(user))
			if(active)
				src.locked = !src.locked
				user << "You [src.locked ? "lock" : "unlock"] the controls."
			else
				src.locked = 0 //just in case it somehow gets locked
				user << "The controls can only be locked when \the [src] is online!"
		else
			user << "Access denied."
		return

	if(default_deconstruction_screwdriver(user, "emitter_open", "emitter", W))
		return

	if(exchange_parts(user, W))
		return

	if(default_pry_open(W))
		return

	default_deconstruction_crowbar(W)

	..()
	return

/obj/machinery/power/emitter/emag_act(mob/user as mob)
	if(!emagged)
		locked = 0
		emagged = 1
		user.visible_message("[user.name] emags the [src.name].","You short out the lock.")


code:
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33

/*
field_generator power level display
   The icon used for the field_generator need to have 'num_power_levels' number of icon states
   named 'Field_Gen +p[num]' where 'num' ranges from 1 to 'num_power_levels'

   The power level is displayed using overlays. The current displayed power level is stored in 'powerlevel'.
   The overlay in use and the powerlevel variable must be kept in sync.  A powerlevel equal to 0 means that
   no power level overlay is currently in the overlays list.
   -Aygar
*/

#define field_generator_max_power 250
/obj/machinery/field/generator
	name = "Field Generator"
	desc = "A large thermal battery that projects a high amount of energy when powered."
	icon = 'icons/obj/machines/field_generator.dmi'
	icon_state = "Field_Gen"
	anchored = 0
	density = 1
	use_power = 0
	var/const/num_power_levels = 6	// Total number of power level icon has
	var/Varedit_start = 0
	var/Varpower = 0
	var/active = 0
	var/power = 20  // Current amount of power
	var/state = 0
	var/warming_up = 0
	var/list/obj/machinery/field/containment/fields
	var/list/obj/machinery/field/generator/connected_gens
	var/clean_up = 0

/obj/machinery/field/generator/update_icon()
	overlays.Cut()
	if(warming_up)
		overlays += "+a[warming_up]"
	if(fields.len)
		overlays += "+on"
	// Power level indicator
	// Scale % power to % num_power_levels and truncate value
	var/level = round(num_power_levels * power / field_generator_max_power)
	// Clamp between 0 and num_power_levels for out of range power values
	level = Clamp(level, 0, num_power_levels)
	if(level)
		overlays += "+p[level]"

	return

/obj/machinery/field/generator/New()
	..()
	fields = list()
	connected_gens = list()
	return

/obj/machinery/field/generator/process()
	if(Varedit_start == 1)
		if(active == 0)
			active = 1
			state = 2
			power = field_generator_max_power
			anchored = 1
			warming_up = 3
			start_fields()
			update_icon()
		Varedit_start = 0

	if(src.active == 2)
		calc_power()
		update_icon()
	return

/obj/machinery/field/generator/attack_hand(mob/user as mob)
	if(state == 2)
		if(get_dist(src, user) <= 1)//Need to actually touch the thing to turn it on
			if(src.active >= 1)
				user << "You are unable to turn off the [src.name] once it is online."
				return 1
			else
				user.visible_message("[user.name] turns on the [src.name]", \
					"You turn on the [src.name].", \
					"You hear heavy droning")
				turn_on()
				investigate_log("activated by [user.key].","singulo")

				src.add_fingerprint(user)
	else
		user << "The [src] needs to be firmly secured to the floor first."
		return

/obj/machinery/field/generator/attackby(obj/item/W, mob/user, params)
	if(active)
		user << "The [src] needs to be off."
		return
	else if(istype(W, /obj/item/weapon/wrench))
		switch(state)
			if(0 && !isinspace())
				state = 1
				playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
				user.visible_message("[user.name] secures [src.name] to the floor.", \
					"You secure the external reinforcing bolts to the floor.", \
					"You hear ratchet")
				src.anchored = 1
			if(1)
				state = 0
				playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
				user.visible_message("[user.name] unsecures [src.name] reinforcing bolts from the floor.", \
					"You undo the external reinforcing bolts.", \
					"You hear ratchet")
				src.anchored = 0
			if(2)
				user << "The [src.name] needs to be unwelded from the floor."
				return
	else if(istype(W, /obj/item/weapon/weldingtool))
		var/obj/item/weapon/weldingtool/WT = W
		switch(state)
			if(0)
				user << "The [src.name] needs to be wrenched to the floor."
				return
			if(1)
				if (WT.remove_fuel(0,user))
					playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
					user.visible_message("[user.name] starts to weld the [src.name] to the floor.", \
						"You start to weld \the [src] to the floor.", \
						"You hear welding")
					if (do_after(user,20))
						if(!src || !WT.isOn()) return
						state = 2
						user << "You weld the field generator to the floor."
				else
					return
			if(2)
				if (WT.remove_fuel(0,user))
					playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
					user.visible_message("[user.name] starts to cut the [src.name] free from the floor.", \
						"You start to cut \the [src] free from the floor.", \
						"You hear welding")
					if (do_after(user,20))
						if(!src || !WT.isOn()) return
						state = 1
						user << "You cut \the [src] free from the floor."
				else
					return
	else
		..()
		return

/obj/machinery/field/generator/emp_act()
	return 0

/obj/machinery/field/generator/blob_act()
	if(active)
		return 0
	else
		..()

/obj/machinery/field/generator/bullet_act(var/obj/item/projectile/Proj)
	if(Proj.flag != "bullet")
		power += Proj.damage
		update_icon()
	return 0

/obj/machinery/field/generator/Destroy()
	src.cleanup()
	..()

/obj/machinery/field/generator/proc/turn_off()
	active = 0
	spawn(1)
		src.cleanup()
		while (warming_up>0 && !active)
			sleep(50)
			warming_up--
			update_icon()

/obj/machinery/field/generator/proc/turn_on()
	active = 1
	spawn(1)
		while (warming_up<3 && active)
			sleep(50)
			warming_up++
			update_icon()
			if(warming_up >= 3)
				start_fields()

/obj/machinery/field/generator/proc/calc_power()
	if(Varpower)
		return 1

	update_icon()
	if(src.power > field_generator_max_power)
		src.power = field_generator_max_power

	var/power_draw = 2
	for (var/obj/machinery/field/containment/F in fields)
		if (isnull(F))
			continue
		power_draw++
	if(draw_power(round(power_draw/2,1)))
		return 1
	else
		visible_message("The [src.name] shuts down!", "You hear something shutting down")
		turn_off()
		investigate_log("ran out of power and deactivated","singulo")
		src.power = 0
		return 0

//This could likely be better, it tends to start loopin if you have a complex generator loop setup.  Still works well enough to run the engine fields will likely recode the field gens and fields sometime -Mport
/obj/machinery/field/generator/proc/draw_power(var/draw = 0, var/failsafe = 0, var/obj/machinery/field/generator/G = null, var/obj/machinery/field/generator/last = null)
	if(Varpower)
		return 1
	if((G && G == src) || (failsafe >= 8))//Loopin, set fail
		return 0
	else
		failsafe++
	if(src.power >= draw)//We have enough power
		src.power -= draw
		return 1
	else//Need more power
		draw -= src.power
		src.power = 0
		for(var/obj/machinery/field/generator/FG in connected_gens)
			if(isnull(FG))
				continue
			if(FG == last)//We just asked you
				continue
			if(G)//Another gen is askin for power and we dont have it
				if(FG.draw_power(draw,failsafe,G,src))//Can you take the load
					return 1
				else
					return 0
			else//We are askin another for power
				if(FG.draw_power(draw,failsafe,src,src))
					return 1
				else
					return 0

/obj/machinery/field/generator/proc/start_fields()
	if(!src.state == 2 || !anchored)
		turn_off()
		return
	spawn(1)
		setup_field(1)
	spawn(2)
		setup_field(2)
	spawn(3)
		setup_field(4)
	spawn(4)
		setup_field(8)
	src.active = 2

/obj/machinery/field/generator/proc/setup_field(var/NSEW)
	var/turf/T = src.loc
	var/obj/machinery/field/generator/G
	var/steps = 0
	if(!NSEW)//Make sure its ran right
		return
	for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for another generator
		T = get_step(T, NSEW)
		if(T.density)//We cant shoot a field though this
			return 0
		for(var/atom/A in T.contents)
			if(ismob(A))
				continue
			if(!istype(A,/obj/machinery/field/generator))
				if((istype(A,/obj/machinery/door)||istype(A,/obj/machinery/the_singularitygen))&&(A.density))
					return 0
		steps += 1
		G = locate(/obj/machinery/field/generator) in T
		if(!isnull(G))
			steps -= 1
			if(!G.active)
				return 0
			break
	if(isnull(G))
		return
	T = src.loc
	for(var/dist = 0, dist < steps, dist += 1) // creates each field tile
		var/field_dir = get_dir(T,get_step(G.loc, NSEW))
		T = get_step(T, NSEW)
		if(!locate(/obj/machinery/field/containment) in T)
			var/obj/machinery/field/containment/CF = new/obj/machinery/field/containment()
			CF.set_master(src,G)
			fields += CF
			G.fields += CF
			CF.loc = T
			CF.dir = field_dir
			for(var/mob/living/L in CF.loc)
				CF.Crossed(L)
	var/listcheck = 0
	for(var/obj/machinery/field/generator/FG in connected_gens)
		if (isnull(FG))
			continue
		if(FG == G)
			listcheck = 1
			break
	if(!listcheck)
		connected_gens.Add(G)
	listcheck = 0
	for(var/obj/machinery/field/generator/FG2 in G.connected_gens)
		if (isnull(FG2))
			continue
		if(FG2 == src)
			listcheck = 1
			break
	if(!listcheck)
		G.connected_gens.Add(src)

/obj/machinery/field/generator/proc/cleanup()
	clean_up = 1
	for (var/obj/machinery/field/containment/F in fields)
		if (isnull(F))
			continue
		qdel(F)
	fields = list()
	for(var/obj/machinery/field/generator/FG in connected_gens)
		if (isnull(FG))
			continue
		FG.connected_gens.Remove(src)
		if(!FG.clean_up)//Makes the other gens clean up as well
			FG.cleanup()
		connected_gens.Remove(FG)
	connected_gens = list()
	clean_up = 0
	update_icon()

	//This is here to help fight the "hurr durr, release singulo cos nobody will notice before the
	//singulo eats the evidence". It's not fool-proof but better than nothing.
	//I want to avoid using global variables.
	spawn(1)
		var/temp = 1 //stops spam
		for(var/obj/singularity/O in world)
			if(istype(O, /obj/singularity/narsie))
				return
			if(O.last_warning && temp)
				if((world.time - O.last_warning) > 50) //to stop message-spam
					temp = 0
					message_admins("A singulo exists and a containment field has failed.",1)
					investigate_log("has failed whilst a singulo exists.","singulo")
			O.last_warning = world.time

/obj/machinery/field/generator/shock(mob/living/user as mob)
	if(fields.len)
		..()

/obj/machinery/field/generator/bump(atom/movable/AM as mob|obj)
	if(fields.len)
		..()

license: mit


code:
/////SINGULARITY SPAWNER
/obj/machinery/the_singularitygen/
	name = "Gravitational Singularity Generator"
	desc = "An odd device which produces a gravitational singularity when set up."
	icon = 'icons/obj/singularity.dmi'
	icon_state = "TheSingGen"
	anchored = 0
	density = 1
	use_power = 0
	var/energy = 0

/obj/machinery/the_singularitygen/process()
	var/turf/T = get_turf(src)
	if(src.energy >= 200)
		new /obj/singularity/(T, 50)
		if(src) qdel(src)

/obj/machinery/the_singularitygen/attackby(obj/item/W, mob/user, params)
	if(istype(W, /obj/item/weapon/wrench))

		if(!anchored && !isinspace())
			user.visible_message("[user.name] secures [src.name] to the floor.", \
				"You secure the [src.name] to the floor.", \
				"You hear a ratchet")
			playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
			anchored = 1
		else if(anchored)
			user.visible_message("[user.name] unsecures [src.name] from the floor.", \
				"You unsecure the [src.name] from the floor.", \
				"You hear a ratchet")
			playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
			anchored = 0
		return
	return ..()


code:
/area/engine/engineering/poweralert(var/state, var/source)
	if (state != poweralm)
		investigate_log("has a power alarm!","singulo")
	..()


code:
/obj/singularity/narsie //Moving narsie to a child object of the singularity so it can be made to function differently. --NEO
	name = "Nar-sie's Avatar"
	desc = "Your mind begins to bubble and ooze as it tries to comprehend what it sees."
	icon = 'icons/obj/magic_terror.dmi'
	pixel_x = -89
	pixel_y = -85
	current_size = 9 //It moves/eats like a max-size singulo, aside from range. --NEO
	contained = 0 //Are we going to move around?
	dissipate = 0 //Do we lose energy over time?
	move_self = 1 //Do we move on our own?
	grav_pull = 5 //How many tiles out do we pull?
	consume_range = 6 //How many tiles out do we eat

var/global/narsie_cometh = 0
var/global/list/narsie_list = list()

/obj/singularity/narsie/large
	name = "Nar-Sie"
	icon = 'icons/obj/narsie.dmi'
	// Pixel stuff centers Narsie.
	pixel_x = -236
	pixel_y = -256
	current_size = 12
	move_self = 1 //Do we move on our own?
	grav_pull = 10
	consume_range = 12 //How many tiles out do we eat
	var/announce = 1
	var/narnar = 1

/obj/singularity/narsie/large/New()
	..()
	if(narnar)
		narsie_list.Add(src)
		narsie_spawn_animation()
	if(announce)
		world << "NAR-SIE HAS RISEN"
		world << pick(sound('sound/hallucinations/im_here1.ogg'), sound('sound/hallucinations/im_here2.ogg'))

		var/area/A = get_area(src)
		if(A)
			notify_ghosts("Nar-Sie has risen in \the [A.name]. Reach out to the Geometer to be given a new shell for your soul.")

	if(!narsie_cometh && narnar)
		sleep(70)
		SSshuttle.emergency.request(null, 0.3) // Cannot recall
		if(narnar)
			SetUniversalState(/datum/universal_state/hell)
		narsie_cometh = 1

/obj/singularity/narsie/large/Destroy()
	if(narnar)
		narsie_list.Remove(src)
	..()

/obj/singularity/narsie/large/attack_ghost(mob/dead/observer/user as mob)
	if(narnar)
		if(!(src in view()))
			user << "Your soul is too far away."
			return
		makeNewConstruct(/mob/living/simple_animal/construct/harvester, user, null, 1)
		new /obj/effect/effect/sleep_smoke(user.loc)

/obj/singularity/narsie/process()
	eat()
	if(!target || prob(5))
		pickcultist()
	move()
	if(prob(25))
		mezzer()

/obj/singularity/narsie/Bump(atom/A)//you dare stand before a god?!
	godsmack(A)
	return

/obj/singularity/narsie/Bumped(atom/A)
	godsmack(A)
	return

/obj/singularity/narsie/proc/godsmack(var/atom/A)
	if(istype(A,/obj/))
		var/obj/O = A
		O.ex_act(1.0)
		if(O) qdel(O)

	else if(isturf(A))
		var/turf/T = A
		T.ChangeTurf(/turf/simulated/floor/plasteel/cult)

/obj/singularity/narsie/mezzer()
	for(var/mob/living/carbon/M in oviewers(8, src))
		if(M.stat == CONSCIOUS)
			if(!iscultist(M))
				M << "You feel your sanity crumble away in an instant as you gaze upon [src.name]..."
				M.apply_effect(3, STUN)

/obj/singularity/narsie/consume(var/atom/A)
	A.narsie_act()

/obj/singularity/narsie/ex_act() //No throwing bombs at it either. --NEO
	return

/obj/singularity/narsie/proc/pickcultist() //Narsie rewards his cultists with being devoured first, then picks a ghost to follow. --NEO
	var/list/cultists = list()
	var/list/noncultists = list()
	for(var/mob/living/carbon/food in living_mob_list) //we don't care about constructs or cult-Ians or whatever. cult-monkeys are fair game i guess
		var/turf/pos = get_turf(food)
		if(pos.z != src.z)
			continue

		if(iscultist(food))
			cultists += food
		else
			noncultists += food

		if(cultists.len) //cultists get higher priority
			acquire(pick(cultists))
			return

		if(noncultists.len)
			acquire(pick(noncultists))
			return

	//no living humans, follow a ghost instead.
	for(var/mob/dead/observer/ghost in player_list)
		if(!ghost.client)
			continue
		var/turf/pos = get_turf(ghost)
		if(pos.z != src.z)
			continue
		cultists += ghost
	if(cultists.len)
		acquire(pick(cultists))
		return

/obj/singularity/narsie/proc/acquire(var/mob/food)
	target << "NAR-SIE HAS LOST INTEREST IN YOU"
	target = food
	if(ishuman(target))
		target << "NAR-SIE HUNGERS FOR YOUR SOUL"
	else
		target << "NAR-SIE HAS CHOSEN YOU TO LEAD HIM TO HIS NEXT MEAL"

//Wizard narsie
/obj/singularity/narsie/wizard
	grav_pull = 0

/obj/singularity/narsie/wizard/eat()
	set background = BACKGROUND_ENABLED
//	if(defer_powernet_rebuild != 2)
//		defer_powernet_rebuild = 1
	for(var/atom/X in orange(consume_range,src))
		if(isturf(X) || istype(X, /atom/movable))
			consume(X)
//	if(defer_powernet_rebuild != 2)
//		defer_powernet_rebuild = 0
	return

/obj/singularity/narsie/proc/narsie_spawn_animation()
	icon = 'icons/obj/narsie_spawn_anim.dmi'
	dir = SOUTH
	move_self = 0
	flick("narsie_spawn_anim",src)
	sleep(11)
	move_self = 1
	icon = initial(icon)


code:
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33

/obj/effect/accelerated_particle
	name = "Accelerated Particles"
	desc = "Small things moving very fast."
	icon = 'icons/obj/machines/particle_accelerator.dmi'
	icon_state = "particle"//Need a new icon for this
	anchored = 1
	density = 1
	var/movement_range = 10
	var/energy = 10

/obj/effect/accelerated_particle/weak
	movement_range = 8
	energy = 5

/obj/effect/accelerated_particle/strong
	movement_range = 15
	energy = 15

/obj/effect/accelerated_particle/powerful
	movement_range = 20
	energy = 50

/obj/effect/accelerated_particle/New(loc, dir = 2)
	src.loc = loc
	src.dir = dir

	if(movement_range > 20)
		movement_range = 20
	spawn(0)
		move(1)
	return

/obj/effect/accelerated_particle/Bump(atom/A)
	if (A)
		if(ismob(A))
			toxmob(A)
		if((istype(A,/obj/machinery/the_singularitygen))||(istype(A,/obj/singularity/)))
			A:energy += energy
	return

/obj/effect/accelerated_particle/Bumped(atom/A)
	if(ismob(A))
		Bump(A)
	return

/obj/effect/accelerated_particle/ex_act(severity, target)
	loc = null
	return

/obj/effect/accelerated_particle/proc/toxmob(var/mob/living/M)
/*	var/radiation = (energy*2) //We don't need to do two multiplications and a single goddamn
			if(istype(M,/mob/living/carbon/human))
		if(M:wear_suit) //TODO: check for radiation protection
			radiation = round(radiation/2,1)
	if(istype(M,/mob/living/carbon/monkey))
		if(M:wear_suit) //TODO: check for radiation protection
			radiation = round(radiation/2,1)*/
	M.apply_effect((energy*6),IRRADIATE,0)
	M.updatehealth()
	//M << "\red You feel odd."
	return

/obj/effect/accelerated_particle/proc/move(var/lag)
	if(loc == null)
		return
	if(!step(src,dir))
		src.loc = get_step(src,dir)
	movement_range--
	if(movement_range <= 0)
		loc = null
	else
		sleep(lag)
		move(lag)


code:
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33

/*Composed of 7 parts
3 Particle emitters
proc
emit_particle()

1 power box
the only part of this thing that uses power, can hack to mess with the pa/make it better

1 fuel chamber
contains procs for mixing gas and whatever other fuel it uses
mix_gas()

1 gas holder WIP
acts like a tank valve on the ground that you wrench gas tanks onto
proc
extract_gas()
return_gas()
attach_tank()
remove_tank()
get_available_mix()

1 End Cap

1 Control computer
interface for the pa, acts like a computer with an html menu for diff parts and a status report
all other parts contain only a ref to this
a /machine/, tells the others to do work
contains ref for all parts
proc
process()
check_build()

Setup map
  |EC|
CC|FC|
  |PB|
PE|PE|PE

Icon Addemdum
Icon system is much more robust, and the icons are all variable based.
Each part has a reference string, powered, strength, and contruction values.
Using this the update_icon() proc is simplified a bit (using for absolutely was problematic with naming),
so the icon_state comes out be:
"[reference][strength]", with a switch controlling construction_states and ensuring that it doesn't
power on while being contructed, and all these variables are set by the computer through it's scan list
Essential order of the icons:
Standard - [reference]
Wrenched - [reference]
Wired    - [reference]w
Closed   - [reference]c
Powered  - [reference]p[strength]
Strength being set by the computer and a null strength (Computer is powered off or inactive) returns a 'null', counting as empty
So, hopefully this is helpful if any more icons are to be added/changed/wondering what the hell is going on here

*/

/obj/structure/particle_accelerator
	name = "Particle Accelerator"
	desc = "Part of a Particle Accelerator."
	icon = 'icons/obj/machines/particle_accelerator.dmi'
	icon_state = "none"
	anchored = 0
	density = 1
	var/obj/machinery/particle_accelerator/control_box/master = null
	var/construction_state = 0
	var/reference = null
	var/powered = 0
	var/strength = null
	var/desc_holder = null

/obj/structure/particle_accelerator/Destroy()
	construction_state = 0
	if(master)
		master.part_scan()
	..()

/obj/structure/particle_accelerator/end_cap
	name = "Alpha Particle Generation Array"
	desc_holder = "This is where Alpha particles are generated from \[REDACTED\]"
	icon_state = "end_cap"
	reference = "end_cap"

/obj/structure/particle_accelerator/update_icon()
	..()
	return

/obj/structure/particle_accelerator/verb/rotate()
	set name = "Rotate Clockwise"
	set category = "Object"
	set src in oview(1)

	if(usr.stat || !usr.canmove || usr.restrained())
		return
	if (src.anchored)
		usr << "It is fastened to the floor!"
		return 0
	src.dir = turn(src.dir, 270)
	return 1

/obj/structure/particle_accelerator/verb/rotateccw()
	set name = "Rotate Counter Clockwise"
	set category = "Object"
	set src in oview(1)

	if(usr.stat || !usr.canmove || usr.restrained())
		return
	if (src.anchored)
		usr << "It is fastened to the floor!"
		return 0
	src.dir = turn(src.dir, 90)
	return 1

/obj/structure/particle_accelerator/examine(mob/user)
	switch(src.construction_state)
		if(0)
			src.desc = text("A [name], looks like it's not attached to the flooring")
		if(1)
			src.desc = text("A [name], it is missing some cables")
		if(2)
			src.desc = text("A [name], the panel is open")
		if(3)
			src.desc = text("The [name] is assembled")
			if(powered)
				src.desc = src.desc_holder
	..()

/obj/structure/particle_accelerator/attackby(obj/item/W, mob/user, params)
	if(istool(W))
		if(src.process_tool_hit(W,user))
			return
	..()
	return

/obj/structure/particle_accelerator/Move()
	..()
	if(master && master.active)
		master.toggle_power()
		investigate_log("was moved whilst active; it powered down.","singulo")

/obj/structure/particle_accelerator/blob_act()
	if(prob(50))
		qdel(src)
	return

/obj/structure/particle_accelerator/update_icon()
	switch(construction_state)
		if(0,1)
			icon_state="[reference]"
		if(2)
			icon_state="[reference]w"
		if(3)
			if(powered)
				icon_state="[reference]p[strength]"
			else
				icon_state="[reference]c"
	return

/obj/structure/particle_accelerator/proc/update_state()
	if(master)
		master.update_state()
		return 0

/obj/structure/particle_accelerator/proc/report_ready(var/obj/O)
	if(O && (O == master))
		if(construction_state >= 3)
			return 1
	return 0

/obj/structure/particle_accelerator/proc/report_master()
	if(master)
		return master
	return 0

/obj/structure/particle_accelerator/proc/connect_master(var/obj/O)
	if(O && istype(O,/obj/machinery/particle_accelerator/control_box))
		if(O.dir == src.dir)
			master = O
			return 1
	return 0

/obj/structure/particle_accelerator/proc/process_tool_hit(var/obj/O, var/mob/user)
	if(!(O) || !(user))
		return 0
	if(!ismob(user) || !isobj(O))
		return 0
	var/temp_state = src.construction_state

	switch(src.construction_state)//TODO:Might be more interesting to have it need several parts rather than a single list of steps
		if(0)
			if(istype(O, /obj/item/weapon/wrench) && !isinspace())
				playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
				src.anchored = 1
				user.visible_message("[user.name] secures the [src.name] to the floor.", \
					"You secure the external bolts.")
				temp_state++
		if(1)
			if(istype(O, /obj/item/weapon/wrench))
				playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
				src.anchored = 0
				user.visible_message("[user.name] detaches the [src.name] from the floor.", \
					"You remove the external bolts.")
				temp_state--
			else if(istype(O, /obj/item/stack/cable_coil))
				var/obj/item/stack/cable_coil/C = O
				if(C.use(1))
					user.visible_message("[user.name] adds wires to the [src.name].", \
						"You add some wires.")
					temp_state++
				else
					user << "You need one length of cable to wire the [src.name]."
					return
		if(2)
			if(istype(O, /obj/item/weapon/wirecutters))//TODO:Shock user if its on?
				user.visible_message("[user.name] removes some wires from the [src.name].", \
					"You remove some wires.")
				temp_state--
			else if(istype(O, /obj/item/weapon/screwdriver))
				user.visible_message("[user.name] closes the [src.name]'s access panel.", \
					"You close the access panel.")
				temp_state++
		if(3)
			if(istype(O, /obj/item/weapon/screwdriver))
				user.visible_message("[user.name] opens the [src.name]'s access panel.", \
					"You open the access panel.")
				temp_state--
	if(temp_state == src.construction_state)//Nothing changed
		return 0
	else
		src.construction_state = temp_state
		if(src.construction_state < 3)//Was taken apart, update state
			update_state()
		update_icon()
		return 1
	return 0

/obj/machinery/particle_accelerator
	name = "Particle Accelerator"
	desc = "Part of a Particle Accelerator."
	icon = 'icons/obj/machines/particle_accelerator.dmi'
	icon_state = "none"
	anchored = 0
	density = 1
	use_power = 0
	idle_power_usage = 0
	active_power_usage = 0
	var/construction_state = 0
	var/active = 0
	var/reference = null
	var/powered = null
	var/strength = 0
	var/desc_holder = null

/obj/machinery/particle_accelerator/verb/rotate()
	set name = "Rotate Clockwise"
	set category = "Object"
	set src in oview(1)

	if(usr.stat || !usr.canmove || usr.restrained())
		return
	if (src.anchored)
		usr << "It is fastened to the floor!"
		return 0
	src.dir = turn(src.dir, 270)
	return 1

/obj/machinery/particle_accelerator/verb/rotateccw()
	set name = "Rotate Counter-Clockwise"
	set category = "Object"
	set src in oview(1)

	if(usr.stat || !usr.canmove || usr.restrained())
		return
	if (src.anchored)
		usr << "It is fastened to the floor!"
		return 0
	src.dir = turn(src.dir, 90)
	return 1

/obj/machinery/particle_accelerator/update_icon()
	return

/obj/machinery/particle_accelerator/examine(mob/user)
	switch(src.construction_state)
		if(0)
			src.desc = text("A [name], looks like it's not attached to the flooring")
		if(1)
			src.desc = text("A [name], it is missing some cables")
		if(2)
			src.desc = text("A [name], the panel is open")
		if(3)
			src.desc = text("The [name] is assembled")
			if(powered)
				src.desc = src.desc_holder
	..()

/obj/machinery/particle_accelerator/attackby(obj/item/W, mob/user, params)
	if(istool(W))
		if(src.process_tool_hit(W,user))
			return
	..()
	return

/obj/machinery/particle_accelerator/blob_act()
	if(prob(50))
		qdel(src)
	return

/obj/machinery/particle_accelerator/proc/update_state()
	return 0

/obj/machinery/particle_accelerator/proc/process_tool_hit(var/obj/O, var/mob/user)
	if(!(O) || !(user))
		return 0
	if(!ismob(user) || !isobj(O))
		return 0
	var/temp_state = src.construction_state
	switch(src.construction_state)//TODO:Might be more interesting to have it need several parts rather than a single list of steps
		if(0)
			if(istype(O, /obj/item/weapon/wrench))
				playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
				src.anchored = 1
				user.visible_message("[user.name] secures the [src.name] to the floor.", \
					"You secure the external bolts.")
				temp_state++
		if(1)
			if(istype(O, /obj/item/weapon/wrench))
				playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
				src.anchored = 0
				user.visible_message("[user.name] detaches the [src.name] from the floor.", \
					"You remove the external bolts.")
				temp_state--
			else if(istype(O, /obj/item/stack/cable_coil))
				if(O:use(1))
					user.visible_message("[user.name] adds wires to the [src.name].", \
						"You add some wires.")
					temp_state++
		if(2)
			if(istype(O, /obj/item/weapon/wirecutters))//TODO:Shock user if its on?
				user.visible_message("[user.name] removes some wires from the [src.name].", \
					"You remove some wires.")
				temp_state--
			else if(istype(O, /obj/item/weapon/screwdriver))
				user.visible_message("[user.name] closes the [src.name]'s access panel.", \
					"You close the access panel.")
				temp_state++
		if(3)
			if(istype(O, /obj/item/weapon/screwdriver))
				user.visible_message("[user.name] opens the [src.name]'s access panel.", \
					"You open the access panel.")
				temp_state--
				active = 0
	if(temp_state == src.construction_state)//Nothing changed
		return 0
	else
		if(src.construction_state < 3)//Was taken apart, update state
			update_state()
			if(use_power)
				use_power = 0
		src.construction_state = temp_state
		if(src.construction_state >= 3)
			use_power = 1
		update_icon()
		return 1
	return 0


code:
/obj/structure/particle_accelerator/fuel_chamber
	name = "EM Acceleration Chamber"
	desc_holder = "This is where the Alpha particles are accelerated to radical speeds."
	icon = 'icons/obj/machines/particle_accelerator.dmi'
	icon_state = "fuel_chamber"
	reference = "fuel_chamber"

/obj/structure/particle_accelerator/fuel_chamber/update_icon()
	..()
	return


code:
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33

/obj/machinery/particle_accelerator/control_box
	name = "Particle Accelerator Control Console"
	desc = "This controls the density of the particles."
	icon = 'icons/obj/machines/particle_accelerator.dmi'
	icon_state = "control_box"
	reference = "control_box"
	anchored = 0
	density = 1
	use_power = 0
	idle_power_usage = 500
	active_power_usage = 10000
	construction_state = 0
	active = 0
	dir = 1
	var/strength_upper_limit = 2
	var/interface_control = 1
	var/list/obj/structure/particle_accelerator/connected_parts
	var/assembled = 0
	var/parts = null
	var/datum/wires/particle_acc/control_box/wires = null

/obj/machinery/particle_accelerator/control_box/New()
	wires = new(src)
	connected_parts = list()
	..()

/obj/machinery/particle_accelerator/control_box/Destroy()
	if(active)
		toggle_power()
	..()

/obj/machinery/particle_accelerator/control_box/attack_hand(mob/user as mob)
	if(construction_state >= 3)
		interact(user)
	else if(construction_state == 2) // Wires exposed
		wires.Interact(user)

/obj/machinery/particle_accelerator/control_box/update_state()
	if(construction_state < 3)
		use_power = 0
		assembled = 0
		active = 0
		for(var/obj/structure/particle_accelerator/part in connected_parts)
			part.strength = null
			part.powered = 0
			part.update_icon()
		connected_parts = list()
		return
	if(!part_scan())
		use_power = 1
		active = 0
		connected_parts = list()

	return

/obj/machinery/particle_accelerator/control_box/update_icon()
	if(active)
		icon_state = "[reference]p1"
	else
		if(use_power)
			if(assembled)
				icon_state = "[reference]p"
			else
				icon_state = "u[reference]p"
		else
			switch(construction_state)
				if(0)
					icon_state = "[reference]"
				if(1)
					icon_state = "[reference]"
				if(2)
					icon_state = "[reference]w"
				else
					icon_state = "[reference]c"
	return

/obj/machinery/particle_accelerator/control_box/Topic(href, href_list)
	if(..())
		return

	if(!interface_control)
		usr << "ERROR: Request timed out. Check wire contacts."
		return

	if( href_list["close"] )
		usr << browse(null, "window=pacontrol")
		usr.unset_machine()
		return
	if(href_list["togglep"])
		if(!wires.IsIndexCut(PARTICLE_TOGGLE_WIRE))
			src.toggle_power()

	else if(href_list["scan"])
		src.part_scan()

	else if(href_list["strengthup"])
		if(!wires.IsIndexCut(PARTICLE_STRENGTH_WIRE))
			add_strength()

	else if(href_list["strengthdown"])
		if(!wires.IsIndexCut(PARTICLE_STRENGTH_WIRE))
			remove_strength()

	src.updateDialog()
	src.update_icon()
	return

/obj/machinery/particle_accelerator/control_box/proc/strength_change()
	for(var/obj/structure/particle_accelerator/part in connected_parts)
		part.strength = strength
		part.update_icon()

/obj/machinery/particle_accelerator/control_box/proc/add_strength(var/s)
	if(assembled)
		strength++
		if(strength > strength_upper_limit)
			strength = strength_upper_limit
		else
			message_admins("PA Control Computer increased to [strength] by [key_name(usr, usr.client)](?) in ([x],[y],[z] - JMP)",0,1)
			log_game("PA Control Computer increased to [strength] by [usr.ckey]([usr]) in ([x],[y],[z])")
			investigate_log("increased to [strength] by [usr.key]","singulo")
		strength_change()

/obj/machinery/particle_accelerator/control_box/proc/remove_strength(var/s)
	if(assembled)
		strength--
		if(strength < 0)
			strength = 0
		else
			message_admins("PA Control Computer decreased to [strength] by [key_name(usr, usr.client)](?) in ([x],[y],[z] - JMP)",0,1)
			log_game("PA Control Computer decreased to [strength] by [usr.ckey]([usr]) in ([x],[y],[z])")
			investigate_log("decreased to [strength] by [usr.key]","singulo")
		strength_change()

/obj/machinery/particle_accelerator/control_box/power_change()
	..()
	if(stat & NOPOWER)
		active = 0
		use_power = 0
	else if(!stat && construction_state <= 3)
		use_power = 1
	return

/obj/machinery/particle_accelerator/control_box/process()
	if(src.active)
		//a part is missing!
		if( length(connected_parts) < 6 )
			investigate_log("lost a connected part; It powered down.","singulo")
			src.toggle_power()
			return
		//emit some particles
		for(var/obj/structure/particle_accelerator/particle_emitter/PE in connected_parts)
			if(PE)
				PE.emit_particle(src.strength)
	return

/obj/machinery/particle_accelerator/control_box/proc/part_scan()
	for(var/obj/structure/particle_accelerator/fuel_chamber/F in orange(1,src))
		src.dir = F.dir
	connected_parts = list()
	var/tally = 0
	var/ldir = turn(dir,-90)
	var/rdir = turn(dir,90)
	var/odir = turn(dir,180)
	var/turf/T = src.loc
	T = get_step(T,rdir)
	if(check_part(T,/obj/structure/particle_accelerator/fuel_chamber))
		tally++
	T = get_step(T,odir)
	if(check_part(T,/obj/structure/particle_accelerator/end_cap))
		tally++
	T = get_step(T,dir)
	T = get_step(T,dir)
	if(check_part(T,/obj/structure/particle_accelerator/power_box))
		tally++
	T = get_step(T,dir)
	if(check_part(T,/obj/structure/particle_accelerator/particle_emitter/center))
		tally++
	T = get_step(T,ldir)
	if(check_part(T,/obj/structure/particle_accelerator/particle_emitter/left))
		tally++
	T = get_step(T,rdir)
	T = get_step(T,rdir)
	if(check_part(T,/obj/structure/particle_accelerator/particle_emitter/right))
		tally++
	if(tally >= 6)
		assembled = 1
		return 1
	else
		assembled = 0
		return 0

/obj/machinery/particle_accelerator/control_box/proc/check_part(var/turf/T, var/type)
	if(!(T)||!(type))
		return 0
	var/obj/structure/particle_accelerator/PA = locate(/obj/structure/particle_accelerator) in T
	if(istype(PA, type))
		if(PA.connect_master(src))
			if(PA.report_ready(src))
				src.connected_parts.Add(PA)
				return 1
	return 0

/obj/machinery/particle_accelerator/control_box/proc/toggle_power()
	src.active = !src.active
	var/mob/M = usr
	if(istype(M)) //only log if shit isn't wiggitywack
		investigate_log("turned [active?"ON":"OFF"] by [usr ? usr.key : "outside forces"]","singulo")
		message_admins("PA Control Computer turned [active ?"ON":"OFF"] by [key_name(usr, usr.client)](?) in ([x],[y],[z] - JMP)",0,1)
		log_game("PA Control Computer turned [active ?"ON":"OFF"] by [usr.ckey]([usr]) in ([x],[y],[z])")
	if(src.active)
		src.use_power = 2
		for(var/obj/structure/particle_accelerator/part in connected_parts)
			part.strength = src.strength
			part.powered = 1
			part.update_icon()
	else
		src.use_power = 1
		for(var/obj/structure/particle_accelerator/part in connected_parts)
			part.strength = null
			part.powered = 0
			part.update_icon()
	return 1

/obj/machinery/particle_accelerator/control_box/interact(mob/user)
	if((get_dist(src, user) > 1) || (stat & (BROKEN|NOPOWER)))
		if(!istype(user, /mob/living/silicon))
			user.unset_machine()
			user << browse(null, "window=pacontrol")
			return
	user.set_machine(src)

	var/dat = ""
	dat += "Close

"
	dat += "
Status
"
	if(!assembled)
		dat += "Unable to detect all parts!
"
		dat += "Run Scan

"
	else
		dat += "All parts in place.

"
		dat += "Power:"
		if(active)
			dat += "On
"
		else
			dat += "Off
"
		dat += "Toggle Power

"
		dat += "Particle Strength: [src.strength] "
		dat += "--|++

"

	//user << browse(dat, "window=pacontrol;size=420x500")
	//onclose(user, "pacontrol")
	var/datum/browser/popup = new(user, "pacontrol", name, 420, 500)
	popup.set_content(dat)
	popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
	popup.open()
	return


code:
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33

/obj/structure/particle_accelerator/particle_emitter
	name = "EM Containment Grid"
	desc_holder = "This launchs the Alpha particles, might not want to stand near this end."
	icon = 'icons/obj/machines/particle_accelerator.dmi'
	icon_state = "none"
	var/fire_delay = 50
	var/last_shot = 0

/obj/structure/particle_accelerator/particle_emitter/center
	icon_state = "emitter_center"
	reference = "emitter_center"

/obj/structure/particle_accelerator/particle_emitter/left
	icon_state = "emitter_left"
	reference = "emitter_left"

/obj/structure/particle_accelerator/particle_emitter/right
	icon_state = "emitter_right"
	reference = "emitter_right"

/obj/structure/particle_accelerator/particle_emitter/update_icon()
	..()
	return

/obj/structure/particle_accelerator/particle_emitter/proc/set_delay(var/delay)
	if(delay && delay >= 0)
		src.fire_delay = delay
		return 1
	return 0

/obj/structure/particle_accelerator/particle_emitter/proc/emit_particle(var/strength = 0)
	if((src.last_shot + src.fire_delay) <= world.time)
		src.last_shot = world.time
		var/obj/effect/accelerated_particle/A = null
		var/turf/T = get_step(src,dir)
		switch(strength)
			if(0)
				A = new/obj/effect/accelerated_particle/weak(T, dir)
			if(1)
				A = new/obj/effect/accelerated_particle(T, dir)
			if(2)
				A = new/obj/effect/accelerated_particle/strong(T, dir)
			if(3)
				A = new/obj/effect/accelerated_particle/powerful(T, dir)
		if(A)
			A.dir = src.dir
			return 1
	return 0


code:
/obj/structure/particle_accelerator/power_box
	name = "Particle Focusing EM Lens"
	desc_holder = "This uses electromagnetic waves to focus the Alpha-Particles."
	icon = 'icons/obj/machines/particle_accelerator.dmi'
	icon_state = "power_box"
	reference = "power_box"

/obj/structure/particle_accelerator/power_box/update_icon()
	..()
	return


code:
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33

/obj/singularity
	name = "gravitational singularity"
	desc = "A gravitational singularity."
	icon = 'icons/obj/singularity.dmi'
	icon_state = "singularity_s1"
	anchored = 1
	density = 1
	layer = 6
	light_range = 6
	unacidable = 1 //Don't comment this out.
	var/current_size = 1
	var/allowed_size = 1
	var/contained = 1 //Are we going to move around?
	var/energy = 100 //How strong are we?
	var/dissipate = 1 //Do we lose energy over time?
	var/dissipate_delay = 10
	var/dissipate_track = 0
	var/dissipate_strength = 1 //How much energy do we lose?
	var/move_self = 1 //Do we move on our own?
	var/grav_pull = 4 //How many tiles out do we pull?
	var/consume_range = 0 //How many tiles out do we eat
	var/event_chance = 15 //Prob for event each tick
	var/target = null //its target. moves towards the target if it has one
	var/last_failed_movement = 0//Will not move in the same dir if it couldnt before, will help with the getting stuck on fields thing
	var/last_warning
	allow_spin = 0

/obj/singularity/New(loc, var/starting_energy = 50, var/temp = 0)
	//CARN: admin-alert for chuckle-fuckery.
	admin_investigate_setup()

	src.energy = starting_energy
	..()
	SSobj.processing |= src
	for(var/obj/machinery/power/singularity_beacon/singubeacon in world)
		if(singubeacon.active)
			target = singubeacon
			break
	return

/obj/singularity/Destroy()
	SSobj.processing.Remove(src)
	..()

/obj/singularity/Move(atom/newloc, direct)
	if(current_size >= STAGE_FIVE || check_turfs_in(direct))
		last_failed_movement = 0//Reset this because we moved
		return ..()
	else
		last_failed_movement = direct
		return 0

/obj/singularity/attack_hand(mob/user as mob)
	consume(user)
	return 1

/obj/singularity/Process_Spacemove()
	return 1

/obj/singularity/blob_act(severity)
	return

/obj/singularity/ex_act(severity, target)
	switch(severity)
		if(1.0)
			if(current_size <= STAGE_TWO)
				investigate_log("has been destroyed by a heavy explosion.","singulo")
				qdel(src)
				return
			else
				energy -= round(((energy+1)/2),1)
		if(2.0)
			energy -= round(((energy+1)/3),1)
		if(3.0)
			energy -= round(((energy+1)/4),1)
	return

/obj/singularity/bullet_act(obj/item/projectile/P)
	return 0 //Will there be an impact? Who knows.  Will we see it? No.

/obj/singularity/Bump(atom/A)
	consume(A)
	return

/obj/singularity/Bumped(atom/A)
	consume(A)
	return

/obj/singularity/process()
	if(current_size >= STAGE_TWO)
		move()
		pulse()
		if(prob(event_chance))//Chance for it to run a special event TODO:Come up with one or two more that fit
			event()
	eat()
	dissipate()
	check_energy()

	return

/obj/singularity/attack_ai() //to prevent ais from gibbing themselves when they click on one.
	return

/obj/singularity/proc/admin_investigate_setup()
	last_warning = world.time
	var/count = locate(/obj/machinery/field/containment) in orange(30, src)
	if(!count)	message_admins("A singulo has been created without containment fields active ([x],[y],[z])",1)
	investigate_log("was created. [count?"":"No containment fields were active"]","singulo")

/obj/singularity/proc/dissipate()
	if(!dissipate)
		return
	if(dissipate_track >= dissipate_delay)
		src.energy -= dissipate_strength
		dissipate_track = 0
	else
		dissipate_track++

/obj/singularity/proc/expand(var/force_size = 0)
	var/temp_allowed_size = src.allowed_size
	if(force_size)
		temp_allowed_size = force_size
	switch(temp_allowed_size)
		if(STAGE_ONE)
			current_size = STAGE_ONE
			icon = 'icons/obj/singularity.dmi'
			icon_state = "singularity_s1"
			pixel_x = 0
			pixel_y = 0
			grav_pull = 4
			consume_range = 0
			dissipate_delay = 10
			dissipate_track = 0
			dissipate_strength = 1
		if(STAGE_TWO)//1 to 3 does not check for the turfs if you put the gens right next to a 1x1 then its going to eat them
			current_size = STAGE_TWO
			icon = 'icons/effects/96x96.dmi'
			icon_state = "singularity_s3"
			pixel_x = -32
			pixel_y = -32
			grav_pull = 6
			consume_range = 1
			dissipate_delay = 5
			dissipate_track = 0
			dissipate_strength = 5
		if(STAGE_THREE)
			if((check_turfs_in(1,2))&&(check_turfs_in(2,2))&&(check_turfs_in(4,2))&&(check_turfs_in(8,2)))
				current_size = STAGE_THREE
				icon = 'icons/effects/160x160.dmi'
				icon_state = "singularity_s5"
				pixel_x = -64
				pixel_y = -64
				grav_pull = 8
				consume_range = 2
				dissipate_delay = 4
				dissipate_track = 0
				dissipate_strength = 20
		if(STAGE_FOUR)
			if((check_turfs_in(1,3))&&(check_turfs_in(2,3))&&(check_turfs_in(4,3))&&(check_turfs_in(8,3)))
				current_size = STAGE_FOUR
				icon = 'icons/effects/224x224.dmi'
				icon_state = "singularity_s7"
				pixel_x = -96
				pixel_y = -96
				grav_pull = 10
				consume_range = 3
				dissipate_delay = 10
				dissipate_track = 0
				dissipate_strength = 10
		if(STAGE_FIVE)//this one also lacks a check for gens because it eats everything
			current_size = STAGE_FIVE
			icon = 'icons/effects/288x288.dmi'
			icon_state = "singularity_s9"
			pixel_x = -128
			pixel_y = -128
			grav_pull = 10
			consume_range = 4
			dissipate = 0 //It cant go smaller due to e loss
	if(current_size == allowed_size)
		investigate_log("grew to size [current_size]","singulo")
		return 1
	else if(current_size < (--temp_allowed_size))
		expand(temp_allowed_size)
	else
		return 0

/obj/singularity/proc/check_energy()
	if(energy <= 0)
		investigate_log("collapsed.","singulo")
		qdel(src)
		return 0
	switch(energy)//Some of these numbers might need to be changed up later -Mport
		if(1 to 199)
			allowed_size = STAGE_ONE
		if(200 to 499)
			allowed_size = STAGE_TWO
		if(500 to 999)
			allowed_size = STAGE_THREE
		if(1000 to 1999)
			allowed_size = STAGE_FOUR
		if(2000 to INFINITY)
			allowed_size = STAGE_FIVE
	if(current_size != allowed_size)
		expand()
	return 1

/obj/singularity/proc/eat()
	set background = BACKGROUND_ENABLED
	for(var/atom/X in orange(grav_pull,src))
		if(!X.SinguloCanEat())
			continue
		var/dist = get_dist(X, src)
		var/obj/singularity/S = src
		if(dist > consume_range)
			X.singularity_pull(S, current_size)
		else if(dist <= consume_range)
			consume(X)
	return

/obj/singularity/proc/consume(var/atom/A)
	var/gain = A.singularity_act(current_size)
	src.energy += gain
	return

/obj/singularity/proc/move(var/force_move = 0)
	if(!move_self)
		return 0

	// Don't move every tick because lag
	if(prob(50))
		return 0

	var/movement_dir = pick(alldirs - last_failed_movement)

	if(force_move)
		movement_dir = force_move

	if(target && prob(60))
		movement_dir = get_dir(src,target) //moves to a singulo beacon, if there is one

	step(src, movement_dir)

/obj/singularity/proc/check_turfs_in(var/direction = 0, var/step = 0)
	if(!direction)
		return 0
	var/steps = 0
	if(!step)
		switch(current_size)
			if(STAGE_ONE)
				steps = 1
			if(STAGE_TWO)
				steps = 3//Yes this is right
			if(STAGE_THREE)
				steps = 3
			if(STAGE_FOUR)
				steps = 4
			if(STAGE_FIVE)
				steps = 5
	else
		steps = step
	var/list/turfs = list()
	var/turf/T = src.loc
	for(var/i = 1 to steps)
		T = get_step(T,direction)
	if(!isturf(T))
		return 0
	turfs.Add(T)
	var/dir2 = 0
	var/dir3 = 0
	switch(direction)
		if(NORTH||SOUTH)
			dir2 = 4
			dir3 = 8
		if(EAST||WEST)
			dir2 = 1
			dir3 = 2
	var/turf/T2 = T
	for(var/j = 1 to steps-1)
		T2 = get_step(T2,dir2)
		if(!isturf(T2))
			return 0
		turfs.Add(T2)
	for(var/k = 1 to steps-1)
		T = get_step(T,dir3)
		if(!isturf(T))
			return 0
		turfs.Add(T)
	for(var/turf/T3 in turfs)
		if(isnull(T3))
			continue
		if(!can_move(T3))
			return 0
	return 1

/obj/singularity/proc/can_move(var/turf/T)
	if(!T)
		return 0
	if((locate(/obj/machinery/field/containment) in T)||(locate(/obj/machinery/shieldwall) in T))
		return 0
	else if(locate(/obj/machinery/field/generator) in T)
		var/obj/machinery/field/generator/G = locate(/obj/machinery/field/generator) in T
		if(G && G.active)
			return 0
	else if(locate(/obj/machinery/shieldwallgen) in T)
		var/obj/machinery/shieldwallgen/S = locate(/obj/machinery/shieldwallgen) in T
		if(S && S.active)
			return 0
	return 1

/obj/singularity/proc/event()
	var/numb = pick(1,2,3,4,5,6)
	switch(numb)
		if(1)//EMP
			emp_area()
		if(2,3)//tox damage all carbon mobs in area
			toxmob()
		if(4)//Stun mobs who lack optic scanners
			mezzer()
		else
			return 0
	return 1

/obj/singularity/proc/toxmob()
	var/toxrange = 10
	var/toxdamage = 4
	var/radiation = 15
	var/radiationmin = 3
	if (src.energy>200)
		toxdamage = round(((src.energy-150)/50)*4,1)
		radiation = round(((src.energy-150)/50)*5,1)
		radiationmin = round((radiation/5),1)//
	for(var/mob/living/M in view(toxrange, src.loc))
		M.apply_effect(rand(radiationmin,radiation), IRRADIATE)
		toxdamage = (toxdamage - (toxdamage*M.getarmor(null, "rad")))
		M.apply_effect(toxdamage, TOX)
	return

/obj/singularity/proc/mezzer()
	for(var/mob/living/carbon/M in oviewers(8, src))
		if(istype(M, /mob/living/carbon/brain)) //Ignore brains
			continue

		if(M.stat == CONSCIOUS)
			if (istype(M,/mob/living/carbon/human))
				var/mob/living/carbon/human/H = M
				if(istype(H.glasses, /obj/item/clothing/glasses/meson))
					var/obj/item/clothing/glasses/meson/MS = H.glasses
					if(MS.vision_flags == SEE_TURFS)
						H << "You look directly into the [src.name], good thing you had your protective eyewear on!"
						return

		M.apply_effect(3, STUN)
		M.visible_message("[M] stares blankly at the [src.name]!", \
						"You look directly into the [src.name] and feel weak.")
	return

/obj/singularity/proc/emp_area()
	empulse(src, 8, 10)
	return

/obj/singularity/proc/pulse()

	for(var/obj/machinery/power/rad_collector/R in rad_collectors)
		if(get_dist(R, src) <= 15) // Better than using orange() every process
			R.receive_pulse(energy)
	return

/obj/singularity/singularity_act()
	var/gain = (energy/2)
	var/dist = max((current_size - 2),1)
	explosion(src.loc,(dist),(dist*2),(dist*4))
	qdel(src)
	return(gain)


code:
// the SMES
// stores power

#define SMESRATE 0.05			// rate of internal charge to external power

/obj/machinery/power/smes
	name = "power storage unit"
	desc = "A high-capacity superconducting magnetic energy storage (SMES) unit."
	icon_state = "smes"
	density = 1
	anchored = 1
	use_power = 0
	var/capacity = 5e6 // maximum charge
	var/charge = 1e6 // actual charge

	var/input_attempt = 0 // 1 = attempting to charge, 0 = not attempting to charge
	var/inputting = 0 // 1 = actually inputting, 0 = not inputting
	var/input_level = 50000 // amount of power the SMES attempts to charge by
	var/input_level_max = 200000 // cap on input_level
	var/input_available = 0 // amount of charge available from input last tick

	var/output_attempt = 1 // 1 = attempting to output, 0 = not attempting to output
	var/outputting = 1 // 1 = actually outputting, 0 = not outputting
	var/output_level = 50000 // amount of power the SMES attempts to output
	var/output_level_max = 200000 // cap on output_level
	var/output_used = 0 // amount of power actually outputted. may be less than output_level if the powernet returns excess power

	var/obj/machinery/power/terminal/terminal = null

/obj/machinery/power/smes/New()
	..()
	component_parts = list()
	component_parts += new /obj/item/weapon/circuitboard/smes(null)
	component_parts += new /obj/item/weapon/stock_parts/cell/high(null)
	component_parts += new /obj/item/weapon/stock_parts/cell/high(null)
	component_parts += new /obj/item/weapon/stock_parts/cell/high(null)
	component_parts += new /obj/item/weapon/stock_parts/cell/high(null)
	component_parts += new /obj/item/weapon/stock_parts/cell/high(null)
	component_parts += new /obj/item/weapon/stock_parts/capacitor(null)
	component_parts += new /obj/item/stack/cable_coil(null, 5)
	RefreshParts()
	spawn(5)
		dir_loop:
			for(var/d in cardinal)
				var/turf/T = get_step(src, d)
				for(var/obj/machinery/power/terminal/term in T)
					if(term && term.dir == turn(d, 180))
						terminal = term
						break dir_loop

		if(!terminal)
			stat |= BROKEN
			return
		terminal.master = src
		update_icon()
	return

/obj/machinery/power/smes/RefreshParts()
	var/IO = 0
	var/C = 0
	for(var/obj/item/weapon/stock_parts/capacitor/CP in component_parts)
		IO += CP.rating
	input_level_max = 200000 * IO
	output_level_max = 200000 * IO
	for(var/obj/item/weapon/stock_parts/cell/PC in component_parts)
		C += PC.maxcharge
	capacity = C / (15000) * 1e6

/obj/machinery/power/smes/attackby(obj/item/I, mob/user, params)
	if(!user.IsAdvancedToolUser())
		user << "You don't have the dexterity to use [src]!"
		return 0
	//opening using screwdriver
	if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I))
		update_icon()
		return

	//changing direction using wrench
	if(default_change_direction_wrench(user, I))
		terminal = null
		var/turf/T = get_step(src, dir)
		for(var/obj/machinery/power/terminal/term in T)
			if(term && term.dir == turn(dir, 180))
				terminal = term
				terminal.master = src
				user << "Terminal found."
				break
		if(!terminal)
			user << "No power source found."
			return
		stat &= ~BROKEN
		update_icon()
		return

	//exchanging parts using the RPE
	if(exchange_parts(user, I))
		return

	//building and linking a terminal
	if(istype(I, /obj/item/stack/cable_coil))
		var/dir = get_dir(user,src)
		if(dir & (dir-1))//we don't want diagonal click
			return

		if(terminal) //is there already a terminal ?
			user << "This SMES already have a power terminal!"
			return

		if(!panel_open) //is the panel open ?
			user << "You must open the maintenance panel first!"
			return

		var/turf/T = get_turf(user)
		if (T.intact) //is the floor plating removed ?
			user << "You must first remove the floor plating!"
			return

		var/obj/item/stack/cable_coil/C = I
		if(C.amount < 10)
			user << "You need more wires."
			return

		user << "You start building the power terminal..."
		playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)

		if(do_after(user, 20) && C.amount >= 10)
			var/obj/structure/cable/N = T.get_cable_node() //get the connecting node cable, if there's one
			if (prob(50) && electrocute_mob(usr, N, N)) //animate the electrocution if uncautious and unlucky
				var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
				s.set_up(5, 1, src)
				s.start()
				return

			C.use(10)
			user.visible_message(\
				"[user.name] has build a power terminal!",\
				"You build the power terminal.")

			//build the terminal and link it to the network
			make_terminal(T)
			terminal.connect_to_network()
		return

	//disassembling the terminal
	if(istype(I, /obj/item/weapon/wirecutters) && terminal && panel_open)
		terminal.dismantle(user)

	//crowbarring it !
	default_deconstruction_crowbar(I)

/obj/machinery/power/smes/Destroy()
	if(ticker && ticker.current_state == GAME_STATE_PLAYING)
		var/area/area = get_area(src)
		message_admins("SMES deleted at ([area.name])")
		log_game("SMES deleted at ([area.name])")
		investigate_log("deleted at ([area.name])","singulo")
	if(terminal)
		disconnect_terminal()
	..()

// create a terminal object pointing towards the SMES
// wires will attach to this
/obj/machinery/power/smes/proc/make_terminal(var/turf/T)
	terminal = new/obj/machinery/power/terminal(T)
	terminal.dir = get_dir(T,src)
	terminal.master = src

/obj/machinery/power/smes/disconnect_terminal()
	if(terminal)
		terminal.master = null
		terminal = null

/obj/machinery/power/smes/update_icon()
	overlays.Cut()
	if(stat & BROKEN)	return

	if(panel_open)
		return

	overlays += image('icons/obj/power.dmi', "smes-op[outputting]")

	if(inputting)
		overlays += image('icons/obj/power.dmi', "smes-oc1")
	else
		if(input_attempt)
			overlays += image('icons/obj/power.dmi', "smes-oc0")

	var/clevel = chargedisplay()
	if(clevel>0)
		overlays += image('icons/obj/power.dmi', "smes-og[clevel]")
	return

/obj/machinery/power/smes/proc/chargedisplay()
	return round(5.5*charge/capacity)

/obj/machinery/power/smes/process()

	if(stat & BROKEN)	return

	//store machine state to see if we need to update the icon overlays
	var/last_disp = chargedisplay()
	var/last_chrg = inputting
	var/last_onln = outputting

	//inputting
	if(terminal && input_attempt)
		input_available = terminal.surplus()

		if(inputting)
			if(input_available > 0)		// if there's power available, try to charge

				var/load = min(min((capacity-charge)/SMESRATE, input_level),input_available)		// charge at set rate, limited to spare capacity

				charge += load * SMESRATE	// increase the charge

				add_load(load)		// add the load to the terminal side network

			else					// if not enough capcity
				inputting = 0		// stop inputting

		else
			if(input_attempt && input_available > 0)
				inputting = 1

	//outputting
	if(outputting)
		output_used = min( charge/SMESRATE, output_level)		//limit output to that stored

		charge -= output_used*SMESRATE		// reduce the storage (may be recovered in /restore() if excessive)

		add_avail(output_used)				// add output to powernet (smes side)

		if(output_used < 0.0001)			// either from no charge or set to 0
			outputting = 0
			investigate_log("lost power and turned off","singulo")
	else if(output_attempt && charge > output_level && output_level > 0)
		outputting = 1
	else
		output_used = 0

	// only update icon if state changed
	if(last_disp != chargedisplay() || last_chrg != inputting || last_onln != outputting)
		update_icon()

// called after all power processes are finished
// restores charge level to smes if there was excess this ptick
/obj/machinery/power/smes/proc/restore()
	if(stat & BROKEN)
		return

	if(!outputting)
		output_used = 0
		return

	var/excess = powernet.netexcess		// this was how much wasn't used on the network last ptick, minus any removed by other SMESes

	excess = min(output_used, excess)				// clamp it to how much was actually output by this SMES last ptick

	excess = min((capacity-charge)/SMESRATE, excess)	// for safety, also limit recharge by space capacity of SMES (shouldn't happen)

	// now recharge this amount

	var/clev = chargedisplay()

	charge += excess * SMESRATE			// restore unused power
	powernet.netexcess -= excess		// remove the excess from the powernet, so later SMESes don't try to use it

	output_used -= excess

	if(clev != chargedisplay() ) //if needed updates the icons overlay
		update_icon()
	return

/obj/machinery/power/smes/add_load(var/amount)
	if(terminal && terminal.powernet)
		terminal.powernet.load += amount

/obj/machinery/power/smes/attack_ai(mob/user)
	if(stat & BROKEN) return
	ui_interact(user)

/obj/machinery/power/smes/attack_hand(mob/user)
	add_fingerprint(user)
	if(stat & BROKEN) return
	ui_interact(user)

/obj/machinery/power/smes/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
	if(!user)
		return
	if(!user.IsAdvancedToolUser())
		user << "You don't have the dexterity to use [src]!"
		return 0

// update the ui if it exists, create a new one if it doesn't
	ui = SSnano.push_open_or_new_ui(user, src, ui_key, ui, "smes.tmpl", "SMES - [name]", 350, 560, 1)

/obj/machinery/power/smes/get_ui_data()

	var/list/data = list(
		"capacityPercent" = round(100.0*charge/capacity, 0.1),
		"capacity" = capacity,
		"charge" = charge,

		"inputAttempt" = input_attempt,
		"inputting" = inputting,
		"inputLevel" = input_level,
		"inputLevelMax" = input_level_max,
		"inputAvailable" = input_available,

		"outputAttempt" = output_attempt,
		"outputting" = outputting,
		"outputLevel" = output_level,
		"outputLevelMax" = output_level_max,
		"outputUsed" = output_used
	)

	return data

/obj/machinery/power/smes/Topic(href, href_list)
//	world << "[href] ; [href_list[href]]"

	if(..())
		return

	else if( href_list["input_attempt"] )
		input_attempt = text2num(href_list["input_attempt"])
		if(!input_attempt)
			inputting = 0
		log_smes(usr.ckey)
		update_icon()

	else if( href_list["output_attempt"] )
		output_attempt = text2num(href_list["output_attempt"])
		if(!output_attempt)
			outputting = 0
		log_smes(usr.ckey)
		update_icon()

	else if( href_list["set_input_level"] )
		switch(href_list["set_input_level"])
			if("max")
				input_level = input_level_max
			if("custom")
				var/custom = input(usr, "What rate would you like this SMES to attempt to charge at? Max is [input_level_max].") as null|num
				if(isnum(custom))
					href_list["set_input_level"] = custom
					.()
			if("plus")
				input_level += 10000
			if("minus")
				input_level -= 10000
			else
				var/n = text2num(href_list["set_input_level"])
				if(isnum(n))
					input_level = n

		input_level = Clamp(input_level, 0, input_level_max)
		log_smes(usr.ckey)

	else if(href_list["set_output_level"])
		switch(href_list["set_output_level"])
			if("max")
				output_level = output_level_max
			if("custom")
				var/custom = input(usr, "What rate would you like this SMES to attempt to output at? Max is [output_level_max].") as null|num
				if(isnum(custom))
					href_list["set_output_level"] = custom
					.()
			if("plus")
				output_level += 10000
			if("minus")
				output_level -= 10000
			else
				var/n = text2num(href_list["set_output_level"])
				if(isnum(n))
					output_level = n

		output_level = Clamp(output_level, 0, output_level_max)
		log_smes(usr.ckey)

/obj/machinery/power/smes/proc/log_smes(var/user = "")
	investigate_log("input/output; [input_level>output_level?"":""][input_level]/[output_level] | Charge: [charge] | Output-mode: [output_attempt?"on":"off"] | Input-mode: [input_attempt?"auto":"off"] by [user]","singulo")

/obj/machinery/power/smes/emp_act(severity)
	input_attempt = rand(0,1)
	inputting = input_attempt
	output_attempt = rand(0,1)
	outputting = output_attempt
	output_level = rand(0, output_level_max)
	input_level = rand(0, input_level_max)
	charge -= 1e6/severity
	if (charge < 0)
		charge = 0
	update_icon()
	log_smes("an emp")
	..()

/obj/machinery/power/smes/magical
	name = "magical power storage unit"
	desc = "A high-capacity superconducting magnetic energy storage (SMES) unit. Magically produces power."
	process()
		capacity = INFINITY
		charge = INFINITY
		..()

#undef SMESRATE


code:
//ayy lmao
#define NITROGEN_RETARDATION_FACTOR 4        //Higher == N2 slows reaction more
#define THERMAL_RELEASE_MODIFIER 40                //Higher == less heat released during reaction
#define PLASMA_RELEASE_MODIFIER 1000                //Higher == less plasma released by reaction
#define OXYGEN_RELEASE_MODIFIER 500        //Higher == less oxygen released at high temperature/power
#define REACTION_POWER_MODIFIER 1.1                //Higher == more overall power

//These would be what you would get at point blank, decreases with distance
#define DETONATION_RADS 200
#define DETONATION_HALLUCINATION 600

#define WARNING_DELAY 30 		//seconds between warnings.
//#define AUDIO_WARNING_DELAY 30

//#define WARNING_DELAY 30 		//seconds between warnings.

/obj/machinery/power/supermatter
	name = "Supermatter Crystal"
	desc = "A strangely translucent and iridescent crystal. You get headaches just from looking at it."
	icon = 'icons/obj/engine.dmi'
	icon_state = "darkmatter"
	density = 1
	anchored = 0
	light_color = LIGHT_COLOR_YELLOW

	var/max_luminosity = 8 // Now varies based on power.

	// What it's referred to in the alerts
	var/short_name = "Crystal"

	var/gasefficency = 0.25

	var/base_icon_state = "darkmatter"

	var/damage = 0
	var/exploding = 0
	var/damage_archived = 0
	var/warning_point = 100
	var/audio_warning_point=500
	var/emergency_point = 700
	var/explosion_point = 1000

	var/emergency_issued = 0

	var/explosion_power = 8

	var/lastwarning = 0                        // Time in 1/10th of seconds since the last sent warning
//	var/lastaudiowarning = 0

	var/power = 0
	var/max_power = 2000 // Used for lighting scaling.

	var/oxygen = 0				  // Moving this up here for easier debugging.

	//Temporary values so that we can optimize this
	//How much the bullets damage should be multiplied by when it is added to the internal variables
	var/config_bullet_energy = 2
	//How much of the power is left after processing is finished?
//        var/config_power_reduction_per_tick = 0.5
	//How much hallucination should it produce per unit of power?
	var/config_hallucination_power = 0.1

	var/obj/item/device/radio/radio

	// Monitoring shit
	var/frequency = 0
	var/id_tag

	//Add types to this list so it doesn't make a message or get desroyed by the Supermatter on touch.
	var/list/message_exclusions = list(/obj/effect/effect/sparks)

/*
	var/gasefficency = 0.125

	var/base_icon_state = "darkmatter_shard"

	var/damage = 0
	var/damage_archived = 0
	var/safe_alert = "Crystalline hyperstructure returning to safe operating levels."
	var/warning_point = 50
	var/warning_alert = "Danger! Crystal hyperstructure instability!"
	var/emergency_point = 500
	var/emergency_alert = "CRYSTAL DELAMINATION IMMINENT."
	var/explosion_point = 900

	var/emergency_issued = 0

	var/explosion_power = 8

	var/lastwarning = 0				// Time in 1/10th of seconds since the last sent warning
	var/power = 0

	var/oxygen = 0					// Moving this up here for easier debugging.

	//Temporary values so that we can optimize this
	//How much the bullets damage should be multiplied by when it is added to the internal variables
	var/config_bullet_energy = 2
	//How much of the power is left after processing is finished?
//	var/config_power_reduction_per_tick = 0.5
	//How much hallucination should it produce per unit of power?
	var/config_hallucination_power = 0.1

	var/obj/item/device/radio/radio
*/
	//for logging
	var/has_been_powered = 0
	var/has_reached_emergency = 0

/obj/machinery/power/supermatter/shard //Small subtype, less efficient and more sensitive, but less boom.
	name = "Supermatter Shard"
	short_name = "Shard"
	desc = "A strangely translucent and iridescent crystal that looks like it used to be part of a larger structure. You get headaches just from looking at it."
	icon_state = "darkmatter_shard"
	base_icon_state = "darkmatter_shard"

	warning_point = 50
	audio_warning_point=400
	emergency_point = 500
	explosion_point = 900

	gasefficency = 0.125

	explosion_power = 8 // WAS 3 - N3X

	max_luminosity = 6
	max_power=3000

/obj/machinery/power/supermatter/New()
	. = ..()
	radio = new (src)

	investigate_log("has been created.", "supermatter")

/obj/machinery/power/supermatter/Destroy()
	investigate_log("has been destroyed.", "supermatter")
	qdel(radio)
	. = ..()

/obj/machinery/power/supermatter/proc/explode()
		exploding = 1
		explosion(get_turf(src), explosion_power, explosion_power * 2, explosion_power * 3, explosion_power * 4, 1)
		new /turf/simulated/supermatter(get_turf(src))
		SetUniversalState(/datum/universal_state/supermatter_cascade)
		qdel(src)

/obj/machinery/power/supermatter/shard/explode()
		explosion(get_turf(src), explosion_power, explosion_power * 2, explosion_power * 3, explosion_power * 4, 1)
		exploding = 1
		qdel(src)
		return

/obj/machinery/power/supermatter/shard/singularity_act()
	var/prints = ""
	if(src.fingerprintshidden)
		prints = ", all touchers : [list2params(src.fingerprintshidden)]"
	log_admin("New super singularity made by eating a SM crystal [prints]. Last touched by [src.fingerprintslast].")
	message_admins("New super singularity made by eating a SM crystal [prints]. Last touched by [src.fingerprintslast].")
	qdel(src)
	return 15000

/obj/machinery/power/supermatter/singularity_act()
	var/prints = ""
	if(src.fingerprintshidden)
		prints = ", all touchers : " + src.fingerprintshidden
	SetUniversalState(/datum/universal_state/supermatter_cascade)
	//S.expand(STAGE_SUPER, 1)
	log_admin("New super singularity made by eating a SM crystal [prints]. Last touched by [src.fingerprintslast].")
	message_admins("New super singularity made by eating a SM crystal [prints]. Last touched by [src.fingerprintslast].")
	qdel(src)
	return 20000

/obj/machinery/power/supermatter/process()
	var/turf/L = loc

	if(isnull(L))		// We have a null turf...something is wrong, stop processing this entity.
		return PROCESS_KILL

	if(!istype(L)) 	//We are in a crate or somewhere that isn't turf, if we return to turf resume processing but for now.
		return  //Yeah just stop.

	if(istype(L, /turf/space))	// Stop processing this stuff if we've been ejected.
		return

	var/stability = round((damage / explosion_point) * 100)

	if(damage > warning_point) // while the core is still damaged and it's still worth noting its status

	//	var/list/audio_sounds = list('sound/AI/supermatter_integrity_before.ogg')
	//	var/play_alert = 0
	//	var/audio_offset = 0
		if((world.timeofday - lastwarning) / 10 >= WARNING_DELAY)
			var/warning=""
			var/offset = 0

//			audio_sounds += vox_num2list(stability)
//			audio_sounds += list('sound/AI/supermatter_integrity_after.ogg')

			// Damage still low.
			if(damage >= damage_archived) // The damage is still going up
				warning = "Danger! [short_name] hyperstructure instability detected, now at [stability]%."
				offset=150

				if(damage > emergency_point)
					warning = "[uppertext(short_name)] INSTABILITY AT [stability]%. DELAMINATION IMMINENT - EVACUATE IMMEDIATELY."
					offset=0
//					audio_sounds += list('sound/AI/supermatter_delam.ogg')
					//audio_offset = 100
					if(!has_reached_emergency)
						investigate_log("has reached the emergency point for the first time.", "supermatter")
						message_admins("[src] has reached the emergency point (JMP).")
						has_reached_emergency = 1
//				play_alert = (damage > audio_warning_point)
			else
				warning = "[short_name] hyperstructure returning to safe operating levels. Instability: [stability]%"
			//radio.say(warning, "Supermatter [short_name] Monitor")
			radio.talk_into(src, "[warning]")

			lastwarning = world.timeofday - offset

	//	if(play_alert && (world.timeofday - lastaudiowarning) / 10 >= AUDIO_WARNING_DELAY)
	//		for(var/sf in audio_sounds)
	//			var/sound/voice = sound(sf, wait = 1, channel = VOX_CHANNEL)
	//			voice.status = SOUND_STREAM
	//			world << voice
	//		lastaudiowarning = world.timeofday - audio_offset

		if(damage > explosion_point)
			for(var/mob/living/mob in living_mob_list)
				if(istype(mob, /mob/living/carbon/human))
					//Hilariously enough, running into a closet should make you get hit the hardest.
					var/mob/living/carbon/human/H = mob
					H.hallucination += max(50, min(300, DETONATION_HALLUCINATION * sqrt(1 / (get_dist(mob, src) + 1)) ) )
				var/rads = DETONATION_RADS * sqrt( 1 / (get_dist(mob, src) + 1) )
				mob.irradiate(rads)

			explode()

	//Ok, get the air from the turf
	var/datum/gas_mixture/env = L.return_air()

	//Remove gas from surrounding area
	var/datum/gas_mixture/removed = env.remove(gasefficency * env.total_moles())

	if(!removed || !removed.total_moles())
		damage += max((power-1600)/10, 0)
		power = min(power, 1600)
		return 1

	damage_archived = damage
	damage = max( damage + ( (removed.temperature - 800) / 150 ) , 0 )
	//Ok, 100% oxygen atmosphere = best reaction
	//Maxes out at 100% oxygen pressure
	oxygen = max(min((removed.oxygen - (removed.nitrogen * NITROGEN_RETARDATION_FACTOR)) / MOLES_CELLSTANDARD, 1), 0)

	var/temp_factor = 100

	if(oxygen > 0.8)
		// with a perfect gas mix, make the power less based on heat
		icon_state = "[base_icon_state]_glow"
	else
		// in normal mode, base the produced energy around the heat
		temp_factor = 60
		icon_state = base_icon_state

	power = max( (removed.temperature * temp_factor / T0C) * oxygen + power, 0) //Total laser power plus an overload

	//We've generated power, now let's transfer it to the collectors for storing/usage
	transfer_energy()

	var/device_energy = power * REACTION_POWER_MODIFIER

	//To figure out how much temperature to add each tick, consider that at one atmosphere's worth
	//of pure oxygen, with all four lasers firing at standard energy and no N2 present, at room temperature
	//that the device energy is around 2140. At that stage, we don't want too much heat to be put out
	//Since the core is effectively "cold"

	//Also keep in mind we are only adding this temperature to (efficiency)% of the one tile the rock
	//is on. An increase of 4*C @ 25% efficiency here results in an increase of 1*C / (#tilesincore) overall.
	removed.temperature += (device_energy / THERMAL_RELEASE_MODIFIER)

	removed.temperature = max(0, min(removed.temperature, 2500))

	//Calculate how much gas to release
	removed.toxins += max(device_energy / PLASMA_RELEASE_MODIFIER, 0)

	removed.oxygen += max((device_energy + removed.temperature - T0C) / OXYGEN_RELEASE_MODIFIER, 0)

//	removed.update_values()

	env.merge(removed)

	for(var/mob/living/carbon/human/l in view(src, min(7, round(power ** 0.25)))) // If they can see it without mesons on.  Bad on them.
		if(!istype(l.glasses, /obj/item/clothing/glasses/meson))
			l.hallucination = max(0, min(200, l.hallucination + power * config_hallucination_power * sqrt( 1 / max(1, get_dist(l, src)) ) ) )

	for(var/mob/living/l in range(src, round((power / 100) ** 0.25)))
		var/rads = (power / 10) * sqrt( 1 / max(get_dist(l, src),1) )
		l.irradiate(rads)

	power -= (power/500)**3

	var/light_value = Clamp(round(Clamp(power / max_power, 0, 1) * max_luminosity), 0, max_luminosity)
	set_light(light_value, light_value)

	update_light()

	air_update_turf(1)

	return 1

/obj/machinery/power/supermatter/bullet_act(var/obj/item/projectile/Proj)
	var/turf/L = loc
	if(!istype(L))		// We don't run process() when we are in space
		return 0	// This stops people from being able to really power up the supermatter
				// Then bring it inside to explode instantly upon landing on a valid turf.

	if(Proj.flag != "bullet")
		power += Proj.damage * config_bullet_energy
		if(!has_been_powered)
			investigate_log("has been powered for the first time.", "supermatter")
			message_admins("[src] has been powered for the first time (JMP).")
			has_been_powered = 1
	else
		damage += Proj.damage * config_bullet_energy
	return 0

/obj/machinery/power/supermatter/attack_paw(mob/user as mob)
	return attack_hand(user)

/obj/machinery/power/supermatter/attack_robot(mob/user as mob)
	if(Adjacent(user))
		return attack_hand(user)
	else
		return attack_ai(user)
	return

/obj/machinery/power/supermatter/attack_ai(mob/user as mob)
	var/stability = num2text(round((damage / explosion_point) * 100))
	user << "Matrix Instability: [stability]%"
	user << "Damage: [format_num(damage)]" // idfk what units we're using.
	user << "Power: [format_num(power)]J" // Same

/obj/machinery/power/supermatter/attack_hand(mob/living/user as mob)
	if(!istype(user))
		return
	user.visible_message("\The [user] reaches out and touches \the [src], inducing a resonance... \his body starts to glow and bursts into flames before flashing into ash.",\
		"You reach out and touch \the [src]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\"",\
		"You hear an unearthly noise as a wave of heat washes over you.")

	playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1)

	Consume(user)

/obj/machinery/power/supermatter/proc/transfer_energy()
	for(var/obj/machinery/power/rad_collector/R in rad_collectors)
		if(get_dist(R, src) <= 15) // Better than using orange() every process
			R.receive_pulse(power/10)
	return

/obj/machinery/power/supermatter/attackby(obj/item/W as obj, mob/living/user as mob, params)
	if(!istype(W) || (W.flags & ABSTRACT) || !istype(user))
		return
	if(user.drop_item(W))
		Consume(W)
		user.visible_message("As [user] touches \the [src] with \a [W], silence fills the room...",\
			"You touch \the [src] with \the [W], and everything suddenly goes silent.\"\n\The [W] flashes into dust as you flinch away from \the [src].",\
			"Everything suddenly goes silent.")

		playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1)

		user.apply_effect(150, IRRADIATE)

/obj/machinery/power/supermatter/Bumped(atom/AM as mob|obj)
	if(istype(AM, /mob/living))
		AM.visible_message("\The [AM] slams into \the [src] inducing a resonance... \his body starts to glow and catch flame before flashing into ash.",\
		"You slam into \the [src] as your ears are filled with unearthly ringing. Your last thought is \"Oh, fuck.\"",\
		"You hear an unearthly noise as a wave of heat washes over you.")
	else if(isobj(AM) && !istype(AM, /obj/effect))
		AM.visible_message("\The [AM] smacks into \the [src] and rapidly flashes to ash.",\
		"You hear a loud crack as you are washed with a wave of heat.")
	else
		return

	playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1)

	Consume(AM)

/obj/machinery/power/supermatter/proc/Consume(atom/movable/AM)
	if(istype(AM, /mob/living))
		var/mob/living/user = AM
		user.dust()
		power += 200
		message_admins("[src] has consumed [key_name(user)]? (JMP).")
	else if(isobj(AM) && !istype(AM, /obj/effect))
		qdel(AM)

	investigate_log("has consumed [AM].", "supermatter")

	power += 200

	//Some poor sod got eaten, go ahead and irradiate people nearby.
	for(var/mob/living/L in range(10))
		var/rads = 500 * sqrt( 1 / (get_dist(L, src) + 1) )
		L.irradiate(rads)
		investigate_log("has irradiated [L] after consuming [AM].", "supermatter")
		if(L in view())
			L.show_message("As \the [src] slowly stops resonating, you find your skin covered in new radiation burns.", 1,\
				"The unearthly ringing subsides and you notice you have new radiation burns.", 2)
		else
			L.show_message("You hear an uneartly ringing and notice your skin is covered in fresh radiation burns.", 2)

/obj/machinery/power/supermatter/ex_act(severity) //Do not explode the supermatters
	if(!exploding)
		switch(severity)
			if(3.0)
				return //Should be improved
			else
				return explode()


code:
/datum/supply_packs/engineering/engine/supermatter_shard
	name = "Supermatter Shard Crate"
	contains = list(/obj/machinery/power/supermatter/shard)
	cost = 100 //So cargo thinks twice before killing themselves with it
	containertype = /obj/structure/closet/crate/secure
	containername = "supermatter shard crate"
	access = access_ce


code:
//This is a power switch. When turned on it looks at the cables around the tile that it's on and notes which cables are trying to connect to it.
//After it knows this it creates the number of cables from the center to each of the cables attempting to conenct. These cables cannot be removed
//with wirecutters. When the switch is turned off it removes all the cables on the tile it's on.
//The switch uses a 5s delay to prevent powernet change spamming.
/*
/obj/structure/powerswitch
	name = "power switch"
	desc = "A switch that controls power."
	icon = 'icons/obj/power.dmi'
	icon_state = "switch-dbl-up"
	var/icon_state_on = "switch-dbl-down"
	var/icon_state_off = "switch-dbl-up"
	density = 0
	anchored = 1
	var/on = 0  //up is off, down is on
	var/busy = 0 //set to 1 when you start pulling

/obj/structure/powerswitch/simple
	icon_state = "switch-up"
	icon_state_on = "switch-down"
	icon_state_off = "switch-up"

/obj/structure/powerswitch/examine(mob/user)
	..()
	if(on)
		user << "The switch is in the on position"
	else
		user << "The switch is in the off position"

/obj/structure/powerswitch/attack_ai(mob/user)
	user << "\red You're an AI. This is a manual switch. It's not going to work."
	return

/obj/structure/powerswitch/attack_hand(mob/user)

	if(busy)
		user << "\red This switch is already being toggled."
		return

	..()

	busy = 1
	for(var/mob/O in viewers(user))
		O.show_message(text("\red [user] started pulling the [src]."), 1)

	if(do_after(user, 50))
		set_state(!on)
		for(var/mob/O in viewers(user))
			O.show_message(text("\red [user] flipped the [src] into the [on ? "on": "off"] position."), 1)
	busy = 0

/obj/structure/powerswitch/proc/set_state(var/state)
	on = state
	if(on)
		icon_state = icon_state_on
		var/list/connection_dirs = list()
		for(var/direction in list(1,2,4,8,5,6,9,10))
			for(var/obj/structure/cable/C in get_step(src,direction))
				if(C.d1 == turn(direction, 180) || C.d2 == turn(direction, 180))
					connection_dirs += direction
					break

		for(var/direction in connection_dirs)
			var/obj/structure/cable/C = new/obj/structure/cable(src.loc)
			C.d1 = 0
			C.d2 = direction
			C.icon_state = "[C.d1]-[C.d2]"
			C.power_switch = src

			var/datum/powernet/PN = new()
			PN.number = powernets.len + 1
			powernets += PN
			C.netnum = PN.number
			PN.cables += C

			C.mergeConnectedNetworks(C.d2)
			C.mergeConnectedNetworksOnTurf()

	else
		icon_state = icon_state_off
		for(var/obj/structure/cable/C in src.loc)
			qdel(C)
*/


code:
// the underfloor wiring terminal for the APC
// autogenerated when an APC is placed
// all conduit connects go to this object instead of the APC
// using this solves the problem of having the APC in a wall yet also inside an area

/obj/machinery/power/terminal
	name = "terminal"
	icon_state = "term"
	desc = "It's an underfloor wiring terminal for power equipment."
	level = 1
	layer = TURF_LAYER
	var/obj/machinery/power/master = null
	anchored = 1
	layer = 2.6 // a bit above wires

/obj/machinery/power/terminal/New()
	..()
	var/turf/T = src.loc
	if(level==1) hide(T.intact)
	return

/obj/machinery/power/terminal/Destroy()
	if(master)
		master.disconnect_terminal()
	return ..()

/obj/machinery/power/terminal/hide(var/i)
	if(i)
		invisibility = 101
		icon_state = "term-f"
	else
		invisibility = 0
		icon_state = "term"

/obj/machinery/power/proc/can_terminal_dismantle()
	. = 0

/obj/machinery/power/apc/can_terminal_dismantle()
	. = 0
	if(opened && has_electronics != 2)
		. = 1

/obj/machinery/power/smes/can_terminal_dismantle()
	. = 0
	if(panel_open)
		. = 1

/obj/machinery/power/terminal/proc/dismantle(var/mob/living/user)
	if(istype(loc, /turf/simulated))
		var/turf/simulated/T = loc
		if(T.intact)
			user << "You must first expose the power terminal!"
			return

		if(master && master.can_terminal_dismantle())
			user.visible_message("[user.name] dismantles the power terminal from [master].", \
								"You begin to cut the cables...")

			playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
			if(do_after(user, 50))
				if(master && master.can_terminal_dismantle())
					if(prob(50) && electrocute_mob(user, powernet, src))
						var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
						s.set_up(5, 1, master)
						s.start()
						return
					new /obj/item/stack/cable_coil(loc, 10)
					user << "You cut the cables and dismantle the power terminal."
					qdel(src)

/obj/machinery/power/terminal/attackby(obj/item/W, mob/living/user, params)
	if(istype(W, /obj/item/weapon/wirecutters))
		dismantle(user)
		return

	..()


code:
//Solar tracker

//Machine that tracks the sun and reports it's direction to the solar controllers
//As long as this is working, solar panels on same powernet will track automatically

/obj/machinery/power/tracker
	name = "solar tracker"
	desc = "A solar directional tracker."
	icon = 'icons/obj/power.dmi'
	icon_state = "tracker"
	anchored = 1
	density = 1
	use_power = 0

	var/id = 0
	var/sun_angle = 0		// sun angle as set by sun datum
	var/obj/machinery/power/solar_control/control = null

/obj/machinery/power/tracker/New(var/turf/loc, var/obj/item/solar_assembly/S)
	..(loc)
	Make(S)
	connect_to_network()

/obj/machinery/power/tracker/Destroy()
	unset_control() //remove from control computer
	..()

//set the control of the tracker to a given computer if closer than SOLAR_MAX_DIST
/obj/machinery/power/tracker/proc/set_control(var/obj/machinery/power/solar_control/SC)
	if(!SC || (get_dist(src, SC) > SOLAR_MAX_DIST))
		return 0
	control = SC
	SC.connected_tracker = src
	return 1

//set the control of the tracker to null and removes it from the previous control computer if needed
/obj/machinery/power/tracker/proc/unset_control()
	if(control)
		control.connected_tracker = null
	control = null

/obj/machinery/power/tracker/proc/Make(var/obj/item/solar_assembly/S)
	if(!S)
		S = new /obj/item/solar_assembly(src)
		S.glass_type = /obj/item/stack/sheet/glass
		S.tracker = 1
		S.anchored = 1
	S.loc = src
	update_icon()

//updates the tracker icon and the facing angle for the control computer
/obj/machinery/power/tracker/proc/set_angle(var/angle)
	sun_angle = angle

	//set icon dir to show sun illumination
	dir = turn(NORTH, -angle - 22.5)	// 22.5 deg bias ensures, e.g. 67.5-112.5 is EAST

	if(powernet && (powernet == control.powernet)) //update if we're still in the same powernet
		control.cdir = angle

/obj/machinery/power/tracker/attackby(var/obj/item/weapon/W, var/mob/user, params)

	if(istype(W, /obj/item/weapon/crowbar))
		playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
		user.visible_message("[user] begins to take the glass off the solar tracker.")
		if(do_after(user, 50))
			var/obj/item/solar_assembly/S = locate() in src
			if(S)
				S.loc = src.loc
				S.give_glass()
			playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
			user.visible_message("[user] takes the glass off the tracker.")
			qdel(src)
		return
	..()

// Tracker Electronic

/obj/item/weapon/tracker_electronics

	name = "tracker electronics"
	icon = 'icons/obj/doors/door_assembly.dmi'
	icon_state = "door_electronics"
	w_class = 2.0