code:
/obj/item/device/flashlight
	name = "flashlight"
	desc = "A hand-held emergency light."
	icon = 'icons/obj/lighting.dmi'
	icon_state = "flashlight"
	item_state = "flashlight"
	w_class = 2
	flags = CONDUCT
	slot_flags = SLOT_BELT
	m_amt = 50
	g_amt = 20
	action_button_name = "Toggle Light"
	var/on = 0
	var/brightness_on = 6 //luminosity when on
	light_power = 2

/obj/item/device/flashlight/initialize()
	..()
	if(on)
		icon_state = "[initial(icon_state)]-on"
		set_light(brightness_on)
	else
		icon_state = initial(icon_state)
		set_light(0)

/obj/item/device/flashlight/proc/update_brightness(var/mob/user = null)
	if(on)
		icon_state = "[initial(icon_state)]-on"
		set_light(brightness_on)
	else
		icon_state = initial(icon_state)
		set_light(0)

/obj/item/device/flashlight/attack_self(mob/user)
	if(!isturf(user.loc))
		user << "You cannot turn the light on while in this [user.loc]." //To prevent some lighting anomalities.
		return 0
	on = !on
	update_brightness(user)
	return 1

/obj/item/device/flashlight/attack(mob/living/carbon/human/M as mob, mob/living/carbon/human/user as mob)
	add_fingerprint(user)
	if(on && user.zone_sel.selecting == "eyes")

		if((user.disabilities & CLUMSY || user.getBrainLoss() >= 60) && prob(50))	//too dumb to use flashlight properly
			return ..()	//just hit them in the head

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

		var/mob/living/carbon/human/H = M	//mob has protective eyewear
		if(istype(M, /mob/living/carbon/human) && ((H.head && H.head.flags & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES)))
			user << "You're going to need to remove that [(H.head && H.head.flags & HEADCOVERSEYES) ? "helmet" : (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) ? "mask": "glasses"] first."
			return

		if(M == user)	//they're using it on themselves
			if(!M.eye_blind)
				flick("flash", M.flash)
				M.visible_message("[M] directs [src] to \his eyes.", \
									 "You wave the light in front of your eyes! Trippy!")
			else
				M.visible_message("[M] directs [src] to \his eyes.", \
									 "You wave the light in front of your eyes.")
			return

		user.visible_message("[user] directs [src] to [M]'s eyes.", \
							 "You direct [src] to [M]'s eyes.")

		if(istype(M, /mob/living/carbon/human) || istype(M, /mob/living/carbon/monkey))	//robots and aliens are unaffected
			if(M.stat == DEAD || M.disabilities & BLIND)	//mob is dead or fully blind
				user << "[M] pupils does not react to the light!"
			else if(M.dna.check_mutation(XRAY))	//mob has X-RAY vision
				user << "[M] pupils give an eerie glow!"
			else	//they're okay!
				if(!M.eye_blind)
					flick("flash", M.flash)	//flash the affected mob
					user << "[M]'s pupils narrow."
	else
		return ..()

/obj/item/device/flashlight/pen
	name = "penlight"
	desc = "A pen-sized light, used by medical staff. It can also be used to create a hologram to alert people of incoming medical assistance."
	icon_state = "penlight"
	item_state = ""
	flags = CONDUCT
	brightness_on = 2
	var/holo_cooldown = 0

/obj/item/device/flashlight/pen/afterattack(atom/target, mob/user, proximity_flag)
	if(!proximity_flag)
		if(holo_cooldown)
			user << "[src] is not ready yet."
			return
		var/T = get_turf(target)
		if(locate(/mob/living) in T)
			CreateHolo(T, user)
			return
	..()

/obj/item/device/flashlight/pen/proc/CreateHolo(var/tturf,var/creator)
	var/obj/effect/medical_holosign/M = new /obj/effect/medical_holosign(tturf)
	M.visible_message("[creator] created a medical hologram!")
	holo_cooldown = 1
	spawn(100)
		holo_cooldown = 0
	return

/obj/effect/medical_holosign
	name = "medical holosign"
	desc = "A small holographic barrier that indicates a medic is coming to treat a patient."
	icon = 'icons/effects/effects.dmi'
	icon_state = "medi_holo"
	layer = 4.1
	mouse_opacity = 0

/obj/effect/medical_holosign/New()
	playsound(loc, 'sound/machines/ping.ogg', 50, 0)
	spawn(30)
		qdel(src)
	return

/obj/item/device/flashlight/seclite
	name = "seclite"
	desc = "A robust flashlight used by security."
	icon_state = "seclite"
	item_state = "seclite"
	force = 9 // Not as good as a stun baton.
	brightness_on = 5 // A little better than the standard flashlight.
	hitsound = 'sound/weapons/genhit1.ogg'

// the desk lamps are a bit special
/obj/item/device/flashlight/lamp
	name = "desk lamp"
	desc = "A desk lamp with an adjustable mount."
	icon_state = "lamp"
	item_state = "lamp"
	brightness_on = 5
	w_class = 4
	flags = CONDUCT
	m_amt = 0
	g_amt = 0
	on = 1

// green-shaded desk lamp
/obj/item/device/flashlight/lamp/green
	desc = "A classic green-shaded desk lamp."
	icon_state = "lampgreen"
	item_state = "lampgreen"

/obj/item/device/flashlight/lamp/verb/toggle_light()
	set name = "Toggle light"
	set category = "Object"
	set src in oview(1)

	if(!usr.stat)
		attack_self(usr)

//Bananalamp
obj/item/device/flashlight/lamp/bananalamp
	name = "banana lamp"
	desc = "Only a clown would think to make a ghetto banana-shaped lamp. Even has a goofy pullstring."
	icon_state = "bananalamp"
	item_state = "bananalamp"

// FLARES

/obj/item/device/flashlight/flare
	name = "flare"
	desc = "A red Nanotrasen issued flare. There are instructions on the side, it reads 'pull cord, make light'."
	w_class = 2.0
	brightness_on = 8 // Pretty bright.
	light_power = 2.5
	icon_state = "flare"
	item_state = "flare"
	action_button_name = null	//just pull it manually, neckbeard. //You are now pulling manually
	var/fuel = 0
	var/on_damage = 7
	var/produce_heat = 1500

/obj/item/device/flashlight/flare/New()
	fuel = rand(800, 1000) // Sorry for changing this so much but I keep under-estimating how long X number of ticks last in seconds.
	..()

/obj/item/device/flashlight/flare/process()
	var/turf/pos = get_turf(src)
	if(pos)
		pos.hotspot_expose(produce_heat, 5)
	fuel = max(fuel - 1, 0)
	if(!fuel || !on)
		turn_off()
		if(!fuel)
			icon_state = "[initial(icon_state)]-empty"
		SSobj.processing -= src

/obj/item/device/flashlight/flare/proc/turn_off()
	on = 0
	force = initial(src.force)
	damtype = initial(src.damtype)
	if(ismob(loc))
		var/mob/U = loc
		update_brightness(U)
	else
		update_brightness(null)

/obj/item/device/flashlight/flare/update_brightness(var/mob/user = null)
	..()
	if(on)
		item_state = "[initial(item_state)]-on"
	else
		item_state = "[initial(item_state)]"

/obj/item/device/flashlight/flare/attack_self(mob/user)

	// Usual checks
	if(!fuel)
		user << "It's out of fuel."
		return
	if(on)
		return

	. = ..()
	// All good, turn it on.
	if(.)
		user.visible_message("[user] lights \the [src].", "You light \the [src]!")
		force = on_damage
		damtype = "fire"
		SSobj.processing += src

/obj/item/device/flashlight/flare/torch
	name = "torch"
	desc = "A torch fashioned from some leaves and a log."
	w_class = 4
	brightness_on = 7
	icon_state = "torch"
	item_state = "torch"
	on_damage = 10

/obj/item/device/flashlight/lantern
	name = "lantern"
	icon_state = "lantern"
	desc = "A mining lantern."
	brightness_on = 6			// luminosity when on

/obj/item/device/flashlight/slime
	gender = PLURAL
	name = "glowing slime extract"
	desc = "Extract from a yellow slime. It emits a strong light when squeezed."
	icon = 'icons/obj/lighting.dmi'
	icon_state = "slime"
	item_state = "slime"
	w_class = 2
	slot_flags = SLOT_BELT
	m_amt = 0
	g_amt = 0
	brightness_on = 7 //luminosity when on

/obj/item/device/flashlight/emp
	origin_tech = "magnets=4;syndicate=5"

	var/emp_max_charges = 4
	var/emp_cur_charges = 4
	var/charge_tick = 0

/obj/item/device/flashlight/emp/New()
		..()
		SSobj.processing |= src

/obj/item/device/flashlight/emp/Destroy()
		SSobj.processing.Remove(src)
		..()

/obj/item/device/flashlight/emp/process()
		charge_tick++
		if(charge_tick < 10) return 0
		charge_tick = 0
		emp_cur_charges = min(emp_cur_charges+1, emp_max_charges)
		return 1

/obj/item/device/flashlight/emp/attack(mob/living/M as mob, mob/living/user as mob)
	if(on && user.zone_sel.selecting == "eyes") // call original attack proc only if aiming at the eyes
		..()
	return

/obj/item/device/flashlight/emp/afterattack(atom/A as mob|obj, mob/user, proximity)
	if(A.loc == user || !check_allowed_items(A)) //why isn't this the default behaviour
		return
	if(!proximity) return
	if (emp_cur_charges > 0)
		emp_cur_charges -= 1
		A.visible_message("[user] blinks \the [src] at \the [A].", \
											"[user] blinks \the [src] at \the [A].")
		if(ismob(A))
			var/mob/M = A
			add_logs(user, M, "attacked", object="EMP-light")
		user << "\The [src] now has [emp_cur_charges] charge\s."
		A.emp_act(1)
	else
		user << "\The [src] needs time to recharge!"
	return


code:
/obj/item/device/laser_pointer
	name = "laser pointer"
	desc = "Don't shine it in your eyes!"
	icon = 'icons/obj/device.dmi'
	icon_state = "pointer"
	item_state = "pen"
	var/pointer_icon_state
	flags = CONDUCT
	slot_flags = SLOT_BELT
	m_amt = 500
	g_amt = 500
	w_class = 2 //Increased to 2, because diodes are w_class 2. Conservation of matter.
	origin_tech = "combat=1;magnets=2"
	var/turf/pointer_loc
	var/energy = 5
	var/max_energy = 5
	var/effectchance = 33
	var/recharging = 0
	var/recharge_locked = 0
	var/obj/item/weapon/stock_parts/micro_laser/diode //used for upgrading!

/obj/item/device/laser_pointer/red
	pointer_icon_state = "red_laser"
/obj/item/device/laser_pointer/green
	pointer_icon_state = "green_laser"
/obj/item/device/laser_pointer/blue
	pointer_icon_state = "blue_laser"
/obj/item/device/laser_pointer/purple
	pointer_icon_state = "purple_laser"

/obj/item/device/laser_pointer/New()
	..()
	diode = new(src)
	if(!pointer_icon_state)
		pointer_icon_state = pick("red_laser","green_laser","blue_laser","purple_laser")

/obj/item/device/laser_pointer/upgraded/New()
	..()
	diode = new /obj/item/weapon/stock_parts/micro_laser/ultra

/obj/item/device/laser_pointer/attack(mob/living/M, mob/user)
	laser_act(M, user)

/obj/item/device/laser_pointer/attackby(obj/item/W, mob/user, params)
	if(istype(W, /obj/item/weapon/stock_parts/micro_laser))
		if(!diode)
			user.drop_item()
			W.loc = src
			diode = W
			user << "You install a [diode.name] in [src]."
		else
			user << "[src] already has a diode installed."
		return

	else if(istype(W, /obj/item/weapon/screwdriver))
		if(diode)
			user << "You remove the [diode.name] from \the [src]."
			diode.loc = get_turf(src.loc)
			diode = null
		return
	..()
	return

/obj/item/device/laser_pointer/afterattack(var/atom/target, var/mob/living/user, flag, params)
	if(flag)	//we're placing the object on a table or in backpack
		return
	laser_act(target, user)

/obj/item/device/laser_pointer/proc/laser_act(var/atom/target, var/mob/living/user)
	if( !(user in (viewers(7,target))) )
		return
	if (!diode)
		user << "You point [src] at [target], but nothing happens!"
		return
	if (!user.IsAdvancedToolUser())
		user << "You don't have the dexterity to do this!"
		return
	if(ishuman(user))
		var/mob/living/carbon/human/H = user
		if(H.dna && (H.dna.check_mutation(HULK) || NOGUNS in H.dna.species.specflags))
			user << "Your fingers can't press the button!"
			return

	add_fingerprint(user)

	//nothing happens if the battery is drained
	if(recharge_locked)
		user << "You point [src] at [target], but it's still charging."
		return

	var/outmsg
	var/turf/targloc = get_turf(target)

	//human/alien mobs
	if(iscarbon(target))
		var/mob/living/carbon/C = target
		if(user.zone_sel.selecting == "eyes")
			add_logs(user, C, "shone in the eyes", object="laser pointer")

			var/severity = 1
			if(prob(33))
				severity = 2
			else if(prob(50))
				severity = 0

			//20% chance to actually hit the eyes
			if(prob(effectchance * diode.rating) && C.flash_eyes(severity))
				outmsg = "You blind [C] by shining [src] in their eyes."
			else
				outmsg = "You fail to blind [C] by shining [src] at their eyes."

	//robots and AI
	else if(issilicon(target))
		var/mob/living/silicon/S = target
		//20% chance to actually hit the sensors
		if(prob(effectchance * diode.rating))
			flick("e_flash", S.flash)
			S.Weaken(rand(5,10))
			S << "Your sensors were overloaded by a laser!"
			outmsg = "You overload [S] by shining [src] at their sensors."
			add_logs(user, S, "shone in the sensors", object="laser pointer")
		else
			outmsg = "You fail to overload [S] by shining [src] at their sensors."

	//cameras
	else if(istype(target, /obj/machinery/camera))
		var/obj/machinery/camera/C = target
		if(prob(effectchance * diode.rating))
			C.emp_act(1)
			outmsg = "You hit the lens of [C] with [src], temporarily disabling the camera!"
			add_logs(user, C, "EMPed", object="laser pointer")
		else
			outmsg = "You missed the lens of [C] with [src]."

	//laser pointer image
	icon_state = "pointer_[pointer_icon_state]"
	var/list/showto = list()
	for(var/mob/M in range(7,targloc))
		if(M.client)
			showto.Add(M.client)
	var/image/I = image('icons/obj/projectiles.dmi',targloc,pointer_icon_state,10)
	I.pixel_x = target.pixel_x + rand(-5,5)
	I.pixel_y = target.pixel_y + rand(-5,5)

	if(outmsg)
		user << outmsg
	else
		user << "You point [src] at [target]."

	energy -= 1
	if(energy <= max_energy)
		if(!recharging)
			recharging = 1
			SSobj.processing |= src
		if(energy <= 0)
			user << "You've overused the battery of [src], now it needs time to recharge!"
			recharge_locked = 1

	flick_overlay(I, showto, 10)
	icon_state = "pointer"

/obj/item/device/laser_pointer/process()
	if(prob(20 - recharge_locked*5))
		energy += 1
		if(energy >= max_energy)
			energy = max_energy
			recharging = 0
			recharge_locked = 0
			..()

license: mit


code:
// Light Replacer (LR)
//
// ABOUT THE DEVICE
//
// This is a device supposedly to be used by Janitors and Janitor Cyborgs which will
// allow them to easily replace lights. This was mostly designed for Janitor Cyborgs since
// they don't have hands or a way to replace lightbulbs.
//
// HOW IT WORKS
//
// You attack a light fixture with it, if the light fixture is broken it will replace the
// light fixture with a working light; the broken light is then placed on the floor for the
// user to then pickup with a trash bag. If it's empty then it will just place a light in the fixture.
//
// HOW TO REFILL THE DEVICE
//
// It will need to be manually refilled with lights.
// If it's part of a robot module, it will charge when the Robot is inside a Recharge Station.
//
// EMAGGED FEATURES
//
// NOTICE: The Cyborg cannot use the emagged Light Replacer and the light's explosion was nerfed. It cannot create holes in the station anymore.
//
// I'm not sure everyone will react the emag's features so please say what your opinions are of it.
//
// When emagged it will rig every light it replaces, which will explode when the light is on.
// This is VERY noticable, even the device's name changes when you emag it so if anyone
// examines you when you're holding it in your hand, you will be discovered.
// It will also be very obvious who is setting all these lights off, since only Janitor Borgs and Janitors have easy
// access to them, and only one of them can emag their device.
//
// The explosion cannot insta-kill anyone with 30% or more health.

#define LIGHT_OK 0
#define LIGHT_EMPTY 1
#define LIGHT_BROKEN 2
#define LIGHT_BURNED 3

/obj/item/device/lightreplacer

	name = "light replacer"
	desc = "A device to automatically replace lights. Refill with working lightbulbs."

	icon = 'icons/obj/janitor.dmi'
	icon_state = "lightreplacer0"
	item_state = "electronic"

	flags = CONDUCT
	slot_flags = SLOT_BELT
	origin_tech = "magnets=3;materials=2"

	var/max_uses = 20
	var/uses = 0
	var/emagged = 0
	var/failmsg = ""
	// How much to increase per each glass?
	var/increment = 5
	// How much to take from the glass?
	var/decrement = 1
	var/charge = 1

/obj/item/device/lightreplacer/New()
	uses = max_uses / 2
	failmsg = "The [name]'s refill light blinks red."
	..()

/obj/item/device/lightreplacer/examine(mob/user)
	..()
	user << "It has [uses] light\s remaining."

/obj/item/device/lightreplacer/attackby(obj/item/W, mob/user, params)

	if(istype(W, /obj/item/stack/sheet/glass))
		var/obj/item/stack/sheet/glass/G = W
		if(uses >= max_uses)
			user << "[src.name] is full."
			return
		else if(G.use(decrement))
			AddUses(increment)
			user << "You insert a piece of glass into the [src.name]. You have [uses] lights remaining."
			return
		else
			user << "You need one sheet of glass to replace lights."

	if(istype(W, /obj/item/weapon/light))
		var/obj/item/weapon/light/L = W
		if(L.status == 0) // LIGHT OKAY
			if(uses < max_uses)
				AddUses(1)
				user << "You insert the [L.name] into the [src.name]. You have [uses] lights remaining."
				user.drop_item()
				qdel(L)
				return
		else
			user << "You need a working light."
			return

/obj/item/device/lightreplacer/emag_act()
	if(!emagged)
		Emag()

/obj/item/device/lightreplacer/attack_self(mob/user)
	/* // This would probably be a bit OP. If you want it though, uncomment the code.
	if(isrobot(user))
		var/mob/living/silicon/robot/R = user
		if(R.emagged)
			src.Emag()
			usr << "You shortcircuit the [src]."
			return
	*/
	usr << "It has [uses] lights remaining."

/obj/item/device/lightreplacer/update_icon()
	icon_state = "lightreplacer[emagged]"

/obj/item/device/lightreplacer/proc/Use(var/mob/user)

	playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
	AddUses(-1)
	return 1

// Negative numbers will subtract
/obj/item/device/lightreplacer/proc/AddUses(var/amount = 1)
	uses = min(max(uses + amount, 0), max_uses)

/obj/item/device/lightreplacer/proc/Charge(var/mob/user)
	charge += 1
	if(charge > 7)
		AddUses(1)
		charge = 1

/obj/item/device/lightreplacer/proc/ReplaceLight(var/obj/machinery/light/target, var/mob/living/U)

	if(target.status != LIGHT_OK)
		if(CanUse(U))
			if(!Use(U)) return
			U << "You replace the [target.fitting] with \the [src]."

			if(target.status != LIGHT_EMPTY)

				var/obj/item/weapon/light/L1 = new target.light_type(target.loc)
				L1.status = target.status
				L1.rigged = target.rigged
				L1.brightness_range = target.brightness_range
				L1.brightness_power = target.brightness_power
				L1.brightness_color = target.brightness_color
				L1.switchcount = target.switchcount
				target.switchcount = 0
				L1.update()

				target.status = LIGHT_EMPTY
				target.update()

			var/obj/item/weapon/light/L2 = new target.light_type()

			target.status = L2.status
			target.switchcount = L2.switchcount
			target.rigged = emagged
			target.brightness_range = L2.brightness_range
			target.brightness_power = L2.brightness_power
			target.brightness_color = L2.brightness_color
			target.on = target.has_power()
			target.update()
			qdel(L2)

			if(target.on && target.rigged)
				target.explode()
			return

		else
			U << failmsg
			return
	else
		U << "There is a working [target.fitting] already inserted."
		return

/obj/item/device/lightreplacer/proc/Emag()
	emagged = !emagged
	playsound(src.loc, "sparks", 100, 1)
	if(emagged)
		name = "shortcircuited [initial(name)]"
	else
		name = initial(name)
	update_icon()

//Can you use it?

/obj/item/device/lightreplacer/proc/CanUse(var/mob/living/user)
	src.add_fingerprint(user)
	//Not sure what else to check for. Maybe if clumsy?
	if(uses > 0)
		return 1
	else
		return 0

/obj/item/device/lightreplacer/cyborg

/obj/item/device/lightreplacer/proc/janicart_insert(mob/user, obj/structure/janitorialcart/J)
	J.put_in_cart(src, user)
	J.myreplacer = src
	J.update_icon()

/obj/item/device/lightreplacer/cyborg/janicart_insert(mob/user, obj/structure/janitorialcart/J)
	return

#undef LIGHT_OK
#undef LIGHT_EMPTY
#undef LIGHT_BROKEN
#undef LIGHT_BURNED


code:
#define MAX_MATSYNTH_MATTER 60
#define MAT_SYNTH_ROBO 50

#define MAT_COST_COMMON		1
#define MAT_COST_MEDIUM		5
#define MAT_COST_RARE		15

/obj/item/device/material_synth
	name = "material synthesizer"
	desc = "A device capable of producing very little material with a great deal of investment. Use wisely."
	icon = 'icons/obj/device.dmi'
	icon_state = "mat_synthoff"

	flags = FPRINT | CONDUCT
	w_class = 3.0
	origin_tech = "engineering=4;materials=5;power=3"

	var/mode = 1	//0 is material selection, 1 is material production
	var/emagged = 0

	var/obj/item/stack/sheet/active_material = /obj/item/stack/sheet/metal
	var/list/materials_scanned = list(	"metal" = /obj/item/stack/sheet/metal,
										"glass" = /obj/item/stack/sheet/glass,
										"reinforced glass" = /obj/item/stack/sheet/rglass,
										"plasteel" = /obj/item/stack/sheet/plasteel)
	var/matter = 0

/obj/item/device/material_synth/cyborg
	materials_scanned = list(	//"plasma glass" = /obj/item/stack/sheet/glass/plasmaglass, //not in
								//"reinforced plasma glass" = /obj/item/stack/sheet/rglass/plasmarglass,
								"metal" = /obj/item/stack/sheet/metal,
								"glass" = /obj/item/stack/sheet/glass,
								"reinforced glass" = /obj/item/stack/sheet/rglass,
								"plasteel" = /obj/item/stack/sheet/plasteel)

/obj/item/device/material_synth/update_icon()
	icon_state = "mat_synth[mode ? "on" : "off"]"

/obj/item/device/material_synth/afterattack(var/obj/target, mob/user)
	//message_admins("This fired with [target.type]")
	if(istype(target, /obj/item/stack/sheet))
		//message_admins("Yes it is")
		for(var/matID in materials_scanned)
			if(materials_scanned[matID] == target.type)
				//message_admins("WE'RE GETTING KICKED OUT")
				user <<"You've already scanned \the [target]."
				return
		materials_scanned["[initial(target.name)]"] = target.type
		user <<"You successfully scan \the [target] into \the [src]'s material banks."
		return 1
	return ..()

/obj/item/device/material_synth/attackby(var/obj/O, mob/user)
	if(istype(O, /obj/item/weapon/rcd_ammo))
		var/obj/item/weapon/rcd_ammo/RA = O
		if(matter + 10 > MAX_MATSYNTH_MATTER)
			user <<"\The [src] can't take any more material right now."
			return
		else
			matter += 10
			qdel(RA)
	if(istype(O, /obj/item/weapon/card/emag))
		if(!emagged)
			emagged = 1
			var/matter_rng = rand(5, 25)
			if(matter >= matter_rng)
				var/obj/item/device/spawn_item = pick(typesof(/obj/item/device) - /obj/item/device) //we make any kind of device. It's a surprise!
				user.visible_message("\The [src] in [user]'s hands appears to be trying to synthesize... \a [initial(spawn_item.name)]?",
									 "You hear a loud popping noise.")
				user <<"\The [src] pops and fizzles in your hands, before creating... \a [initial(spawn_item.name)]?"
				sleep(10)
				new spawn_item(get_turf(src))
				matter -= matter_rng
				return 1
			else
				user<<"The lack of matter in \the [src] shorts out the device!"
				explosion(src.loc, 0,0,1,2) //traitors - fuck them, am I right?
				qdel(src)
		else
			user<<"You don't think you can do that again..."
			return
	return ..()

/obj/item/device/material_synth/attack_self(mob/user)
	if(materials_scanned.len)
		var/selection = materials_scanned[input("Select the material you'd like to synthesize", "Change Material Type") as null|anything in materials_scanned]
		if(selection)
			active_material = selection
			user << "You switch \the [src] to synthesize [initial(active_material.name)]"
		else
			active_material = null
	else
		user << "ERROR: NO MATERIAL DATA FOUND"
		return 0
	var/mat_name = initial(active_material.name)
	if(isrobot(user))
		var/mob/living/silicon/robot/r_user = user
		if(!r_user.cell)
			return
		if(active_material && r_user.cell.charge)
			var/modifier = MAT_COST_COMMON
			if(initial(active_material.perunit) < 3750)
				modifier = MAT_COST_MEDIUM
			if(initial(active_material.perunit) < 2000)
				modifier = MAT_COST_RARE
			var/tospawn = max(0, round(input("How many sheets of [mat_name] do you want to synthesize?") as num))
			if(tospawn)
				if(TakeCost(tospawn, modifier, r_user))
					if(!active_material)
						return
					var/obj/item/stack/sheet/spawned_sheet = new active_material(get_turf(src))
					spawned_sheet.amount = tospawn
				else
					r_user <<"You can't make that much [mat_name] without shutting down!"
					return
		else if(r_user.cell.charge)
			user <<"You must select a sheet type first!"
			return
	else
		if(active_material && matter)
			var/modifier = MAT_COST_COMMON
			if(initial(active_material.perunit) < 3750) //synthesizing is EXPENSIVE
				modifier = MAT_COST_MEDIUM
			if(initial(active_material.perunit) < 2000)
				modifier = MAT_COST_RARE
			var/tospawn = Clamp(round(input("How many sheets of [mat_name] do you want to synthesize? (0 - [matter / modifier])") as num), 0, round(matter / modifier))
			if(tospawn)
				var/obj/item/stack/sheet/spawned_sheet = new active_material(get_turf(src))
				spawned_sheet.amount = tospawn
				TakeCost(tospawn, modifier, user)
		else if(matter)
			user <<"You must select a sheet type first!"
			return
		else
			user <<"\The [src] is empty!"

/obj/item/device/material_synth/proc/TakeCost(var/spawned, var/modifier, mob/user)
	if(spawned)
		matter -= round(spawned * modifier)
/*
/obj/item/device/material_synth/verb/togglemode()
	set category = "Object"
	set name = "Choose Material Synthesis"
	if(materials_scanned.len)
		var/selection = materials_scanned[input("Select the material you'd like to synthesize", "Change Material Type") in materials_scanned]
		if(selection)
			active_material = selection
			user << "You switch \the [src] to synthesize [initial(active_material.name)]"
	else
		user << "ERROR: NO MATERIAL DATA FOUND"
		return 0
	return 1*/

//mommis matter synth lacks the capability to scan new materials.

obj/item/device/material_synth/cyborg/afterattack(/obj/target, mob/user)
	user << "Your [src.name] does not contain this functionality."
	return 0

/obj/item/device/material_synth/cyborg/TakeCost(var/spawned, var/modifier, mob/user)
	if(isrobot(user))
		var/mob/living/silicon/robot/R = user
		return R.cell.use(spawned*modifier*MAT_SYNTH_ROBO)
	return


code:
/obj/item/device/megaphone
	name = "megaphone"
	desc = "A device used to project your voice. Loudly."
	icon_state = "megaphone"
	item_state = "radio"
	w_class = 2
	flags = FPRINT
	siemens_coefficient = 1

	var/spamcheck = 0
	var/emagged = 0
	var/insults = 0
	var/list/insultmsg = list("FUCK EVERYONE!", "DEATH TO LIZARDS!", "ALL SECURITY TO SHOOT ME ON SIGHT!", "I HAVE A BOMB!", "CAPTAIN IS A COMDOM!", "FOR THE SYNDICATE!", "VIVA!", "HONK!")

/obj/item/device/megaphone/attack_self(mob/living/carbon/human/user as mob)
	if(user.client)
		if(user.client.prefs.muted & MUTE_IC)
			src << "You cannot speak in IC (muted)."
			return
	if(!ishuman(user))
		user << "You don't know how to use this!"
		return
	if(user.can_speak())
		user << "You find yourself unable to speak at all."
		return
	if(spamcheck > world.time)
		user << "\The [src] needs to recharge!"
		return

	var/message = copytext(sanitize(input(user, "Shout a message?", "Megaphone", null)  as text),1,MAX_MESSAGE_LEN)
	if(!message)
		return
	message = capitalize(message)
	if ((src.loc == user && user.stat == 0))
		if(emagged)
			if(insults)
				user.audible_message("[user] broadcasts, \"[pick(insultmsg)]\"", null, 1) // 2 stands for hearable message
				insults--
			else
				user << "*BZZZZzzzzzt*"
		else
			user.audible_message("[user] broadcasts, \"[message]\"", null, 1) // 2 stands for hearable message

		playsound(loc, 'sound/items/megaphone.ogg', 100, 0, 1)
		spamcheck = world.time + 50
		return

/obj/item/device/megaphone/emag_act(mob/user)
	user << "You overload \the [src]'s voice synthesizer."
	emagged = 1
	insults = rand(1, 3)	//to prevent dickflooding

/obj/item/device/megaphone/sec
	name = "security megaphone"
	icon_state = "megaphone-sec"

/obj/item/device/megaphone/command
	name = "command megaphone"
	icon_state = "megaphone-command"

/obj/item/device/megaphone/cargo
	name = "supply megaphone"
	icon_state = "megaphone-cargo"


code:
/**
 * Multitool -- A multitool is used for hacking electronic devices.
 * TO-DO -- Using it as a power measurement tool for cables etc. Nannek.
 *
 */

/obj/item/device/multitool
	name = "multitool"
	desc = "Used for pulsing wires to test which to cut. Not recommended by doctors."
	icon_state = "multitool"
	force = 5.0
	w_class = 2.0
	throwforce = 0
	throw_range = 7
	throw_speed = 3
	m_amt = 50
	g_amt = 20
	origin_tech = "magnets=1;engineering=1"
	var/obj/machinery/telecomms/buffer // simple machine buffer for device linkage
	hitsound = 'sound/weapons/tap.ogg'

// Syndicate device disguised as a multitool; it will turn red when an AI camera is nearby.

/obj/item/device/multitool/ai_detect
	var/track_delay = 0

/obj/item/device/multitool/ai_detect/New()
	..()
	SSobj.processing += src

/obj/item/device/multitool/ai_detect/Destroy()
	SSobj.processing -= src
	..()

/obj/item/device/multitool/ai_detect/process()

	if(track_delay > world.time)
		return

	var/found_eye = 0
	var/turf/our_turf = get_turf(src)

	if(cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z))

		var/datum/camerachunk/chunk = cameranet.getCameraChunk(our_turf.x, our_turf.y, our_turf.z)

		if(chunk)
			if(chunk.seenby.len)
				for(var/mob/camera/aiEye/A in chunk.seenby)
					var/turf/eye_turf = get_turf(A)
					if(get_dist(our_turf, eye_turf) < 8)
						found_eye = 1
						break

	if(found_eye)
		icon_state = "[initial(icon_state)]_red"
	else
		icon_state = initial(icon_state)

	track_delay = world.time + 10 // 1 second
	return


code:
/obj/item/device/paicard
	name = "personal AI device"
	icon = 'icons/obj/aicards.dmi'
	icon_state = "pai"
	item_state = "electronic"
	w_class = 2.0
	slot_flags = SLOT_BELT
	origin_tech = "programming=2"
	var/obj/item/device/radio/radio
	var/looking_for_personality = 0
	var/mob/living/silicon/pai/pai

/obj/item/device/paicard/New()
	..()
	overlays += "pai-off"

/obj/item/device/paicard/Destroy()
	//Will stop people throwing friend pAIs into the singularity so they can respawn
	if(!isnull(pai))
		pai.death(0)
	..()

/obj/item/device/paicard/attack_self(mob/user)
	if (!in_range(src, user))
		return
	user.set_machine(src)
	var/dat = "<TT>Personal AI Device
"
	if(pai && (!pai.master_dna || !pai.master))
		dat += "Imprint Master DNA
"
	if(pai)
		dat += "Installed Personality: [pai.name]
"
		dat += "Prime directive:
[pai.laws.zeroth]
"
		for(var/slaws in pai.laws.supplied)
			dat += "Additional directives:
[slaws]
"
		dat += "Configure Directives
"
		dat += "
"
		dat += "
Device Settings

"
		if(radio)
			dat += "Radio Uplink
"
			dat += "Transmit: [(radio.wires.IsIndexCut(WIRE_TRANSMIT)) ? "Disabled" : "Enabled"]
"
			dat += "Receive: [(radio.wires.IsIndexCut(WIRE_RECEIVE)) ? "Disabled" : "Enabled"]
"
		else
			dat += "Radio Uplink
"
			dat += "Radio firmware not loaded. Please install a pAI personality to load firmware.
"
		dat += "\[Wipe current pAI personality\]
"
	else
		if(looking_for_personality)
			dat += "Searching for a personality..."
			dat += "\[View available personalities\]
"
		else
			dat += "No personality is installed.
"
			dat += "\[Request personal AI personality\]
"
			dat += "Each time this button is pressed, a request will be sent out to any available personalities. Check back often and alot time for personalities to respond. This process could take anywhere from 15 seconds to several minutes, depending on the available personalities' timeliness."
	user << browse(dat, "window=paicard")
	onclose(user, "paicard")
	return

/obj/item/device/paicard/Topic(href, href_list)

	if(!usr || usr.stat)
		return

	if(href_list["request"])
		src.looking_for_personality = 1
		SSpai.findPAI(src, usr)

	if(pai)
		if(href_list["setdna"])
			if(pai.master_dna)
				return
			if(!istype(usr, /mob/living/carbon))
				usr << "You don't have any DNA, or your DNA is incompatible with this device."
			else
				var/mob/living/carbon/M = usr
				pai.master = M.real_name
				pai.master_dna = M.dna.unique_enzymes
				pai << "You have been bound to a new master."
		if(href_list["wipe"])
			var/confirm = input("Are you CERTAIN you wish to delete the current personality? This action cannot be undone.", "Personality Wipe") in list("Yes", "No")
			if(confirm == "Yes")
				if(pai)
					pai << "You feel yourself slipping away from reality."
					pai << "Byte by byte you lose your sense of self."
					pai << "Your mental faculties leave you."
					pai << "oblivion... "
					pai.death(0)
				removePersonality()
		if(href_list["wires"])
			var/t1 = text2num(href_list["wires"])
			if(radio)
				radio.wires.CutWireIndex(t1)
		if(href_list["setlaws"])
			var/newlaws = copytext(sanitize(input("Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", pai.laws.supplied[1]) as message),1,MAX_MESSAGE_LEN)
			if(newlaws && pai)
				pai.add_supplied_law(0,newlaws)
				pai << "Your supplemental directives have been updated. Your new directives are:"
				pai << "Prime Directive :
[pai.laws.zeroth]"
				for(var/slaws in pai.laws.supplied)
					pai << "Supplemental Directives:
[slaws]"
	attack_self(usr)

// 		WIRE_SIGNAL = 1
//		WIRE_RECEIVE = 2
//		WIRE_TRANSMIT = 4

/obj/item/device/paicard/proc/setPersonality(mob/living/silicon/pai/personality)
	src.pai = personality
	src.overlays += "pai-null"

/obj/item/device/paicard/proc/removePersonality()
	src.pai = null
	src.overlays.Cut()
	src.overlays += "pai-off"

/obj/item/device/paicard/proc/setEmotion(var/emotion)
	if(pai)
		src.overlays.Cut()
		switch(emotion)
			if(1) src.overlays += "pai-happy"
			if(2) src.overlays += "pai-cat"
			if(3) src.overlays += "pai-extremely-happy"
			if(4) src.overlays += "pai-face"
			if(5) src.overlays += "pai-laugh"
			if(6) src.overlays += "pai-off"
			if(7) src.overlays += "pai-sad"
			if(8) src.overlays += "pai-angry"
			if(9) src.overlays += "pai-what"
			if(10) src.overlays += "pai-null"

/obj/item/device/paicard/proc/alertUpdate()
	visible_message("[src] flashes a message across its screen, \"Additional personalities available for download.\"", 3, "[src] bleeps electronically.", 2)

/obj/item/device/paicard/emp_act(severity)
	if(pai)
		pai.emp_act(severity)
	..()


code:
/obj/item/device/pipe_painter
	name = "pipe painter"
	icon = 'icons/obj/bureaucracy.dmi'
	icon_state = "labeler1"
	item_state = "flight"
	var/list/modes = list(
		"grey"		= rgb(255,255,255),
		"red"			= rgb(255,0,0),
		"blue"		= rgb(0,0,255),
		"cyan"		= rgb(0,256,249),
		"green"		= rgb(30,255,0),
		"yellow"	= rgb(255,198,0),
		"purple"	= rgb(130,43,255)
	)
	var/mode = "grey"

	m_amt = 5000
	g_amt = 2000

/obj/item/device/pipe_painter/afterattack(atom/A, mob/user as mob, proximity_flag)
	//Make sure we only paint adjacent items
	if(proximity_flag!= 1)
		return

	if(!istype(A,/obj/machinery/atmospherics/pipe/simple) && !istype(A,/obj/machinery/atmospherics/pipe/manifold) && !istype(A,/obj/machinery/atmospherics/pipe/manifold4w))
		return

	var/obj/machinery/atmospherics/pipe/P = A
	P.color = modes[mode]
	P.pipe_color = modes[mode]
	P.stored.color = modes[mode]
	user.visible_message("[user] paints \the [P] [mode].","You paint \the [P] [mode].")
	P.update_node_icon() //updates the neighbors

/obj/item/device/pipe_painter/attack_self(mob/user as mob)
	mode = input("Which colour do you want to use?","Pipe painter") in modes

/obj/item/device/pipe_painter/examine()
	..()
	usr << "It is set to [mode]."


code:
// Powersink - used to drain station power

/obj/item/device/powersink
	desc = "A nulling power sink which drains energy from electrical systems."
	name = "power sink"
	icon_state = "powersink0"
	item_state = "electronic"
	w_class = 4.0
	flags = CONDUCT
	throwforce = 5
	throw_speed = 1
	throw_range = 2
	m_amt = 750
	origin_tech = "powerstorage=3;syndicate=5"
	var/drain_rate = 600000		// amount of power to drain per tick
	var/power_drained = 0 		// has drained this much power
	var/max_power = 1e8		// maximum power that can be drained before exploding
	var/mode = 0		// 0 = off, 1=clamped (off), 2=operating
	var/admins_warned = 0 // stop spam, only warn the admins once that we are about to boom

	var/const/DISCONNECTED = 0
	var/const/CLAMPED_OFF = 1
	var/const/OPERATING = 2

	var/obj/structure/cable/attached		// the attached cable

/obj/item/device/powersink/update_icon()
	icon_state = "powersink[mode == OPERATING]"

/obj/item/device/powersink/proc/set_mode(value)
	if(value == mode)
		return
	switch(value)
		if(DISCONNECTED)
			attached = null
			if(mode == OPERATING)
				SSobj.processing.Remove(src)
			anchored = 0

		if(CLAMPED_OFF)
			if(!attached)
				return
			if(mode == OPERATING)
				SSobj.processing.Remove(src)
			anchored = 1

		if(OPERATING)
			if(!attached)
				return
			SSobj.processing |= src
			anchored = 1

	mode = value
	update_icon()
	set_light(0)

/obj/item/device/powersink/attackby(var/obj/item/I, var/mob/user, params)
	if(istype(I, /obj/item/weapon/screwdriver))
		if(mode == DISCONNECTED)
			var/turf/T = loc
			if(isturf(T) && !T.intact)
				attached = locate() in T
				if(!attached)
					user << "No exposed cable here to attach to."
				else
					set_mode(CLAMPED_OFF)
					user.visible_message( \
						"[user] attaches \the [src] to the cable.", \
						"You attach \the [src] to the cable.",
						"You hear some wires being connected to something.")
			else
				user << "Device must be placed over an exposed cable to attach to it."
		else
			set_mode(DISCONNECTED)
			user.visible_message( \
				"[user] detaches \the [src] from the cable.", \
				"You detach \the [src] from the cable.",
				"You hear some wires being disconnected from something.")
	else
		..()

/obj/item/device/powersink/attack_paw()
	return

/obj/item/device/powersink/attack_ai()
	return

/obj/item/device/powersink/attack_hand(var/mob/user)
	switch(mode)
		if(DISCONNECTED)
			..()

		if(CLAMPED_OFF)
			user.visible_message( \
				"[user] activates \the [src]!", \
				"You activate \the [src]!",
				"You hear a click.")
			message_admins("Power sink activated by [key_name(user, user.client)](?) at ([x],[y],[z] - JMP)")
			log_game("Power sink activated by [key_name(user)] at ([x],[y],[z])")
			set_mode(OPERATING)

		if(OPERATING)
			user.visible_message( \
				"[user] deactivates \the [src]!", \
				"You deactivate \the [src]!",
				"You hear a click.")
			set_mode(CLAMPED_OFF)

/obj/item/device/powersink/process()
	if(!attached)
		set_mode(DISCONNECTED)
		return

	var/datum/powernet/PN = attached.powernet
	if(PN)
		set_light(12)

		// found a powernet, so drain up to max power from it

		var/drained = min ( drain_rate, PN.avail )
		PN.load += drained
		power_drained += drained

		// if tried to drain more than available on powernet
		// now look for APCs and drain their cells
		if(drained < drain_rate)
			for(var/obj/machinery/power/terminal/T in PN.nodes)
				if(istype(T.master, /obj/machinery/power/apc))
					var/obj/machinery/power/apc/A = T.master
					if(A.operating && A.cell)
						A.cell.charge = max(0, A.cell.charge - 50)
						power_drained += 50
						if(A.charging == 2) // If the cell was full
							A.charging = 1 // It's no longer full

	if(power_drained > max_power * 0.95)
		if (!admins_warned)
			admins_warned = 1
			message_admins("Power sink at ([x],[y],[z] - JMP) is 95% full. Explosion imminent.")
		playsound(src, 'sound/effects/screech.ogg', 100, 1, 1)

	if(power_drained >= max_power)
		SSobj.processing.Remove(src)
		explosion(src.loc, 3,6,9,12)
		qdel(src)


code:
/obj/item/device/radio/beacon
	name = "tracking beacon"
	desc = "A beacon used by a teleporter."
	icon_state = "beacon"
	item_state = "signaler"
	var/code = "electronic"
	origin_tech = "bluespace=1"

/obj/item/device/radio/beacon/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq)
	return

/obj/item/device/radio/beacon/send_hear()
	return null

/obj/item/device/radio/beacon/verb/alter_signal(t as text)
	set name = "Alter Beacon's Signal"
	set category = "Object"
	set src in usr

	if ((usr.canmove && !( usr.restrained() )))
		src.code = t
	if (!( src.code ))
		src.code = "beacon"
	src.add_fingerprint(usr)
	return

/*
/obj/item/device/radio/beacon/bacon //Probably a better way of doing this, I'm lazy.
	proc/digest_delay()
		spawn(600)
			qdel(src)*/ //Bacon beacons are no more rip in peace


code:
/obj/item/device/electropack
	name = "electropack"
	desc = "Dance my monkeys! DANCE!!!"
	icon = 'icons/obj/radio.dmi'
	icon_state = "electropack0"
	item_state = "electropack"
	flags = CONDUCT
	slot_flags = SLOT_BACK
	w_class = 5.0
	g_amt = 2500
	m_amt = 10000
	var/on = 1
	var/code = 2
	var/frequency = 1449
	var/shock_cooldown = 0

/obj/item/device/electropack/initialize()
	if(radio_controller)
		radio_controller.add_object(src, frequency, RADIO_CHAT)

/obj/item/device/electropack/Destroy()
	if(radio_controller)
		radio_controller.remove_object(src, frequency)
	..()

/obj/item/device/electropack/attack_hand(mob/user)
	if(iscarbon(user))
		var/mob/living/carbon/C = user
		if(src == C.back)
			user << "You need help taking this off!"
			return
	..()

/obj/item/device/electropack/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
	..()
	if(istype(W, /obj/item/clothing/head/helmet))
		var/obj/item/assembly/shock_kit/A = new /obj/item/assembly/shock_kit( user )
		A.icon = 'icons/obj/assemblies.dmi'

		if(!user.unEquip(W))
			user << "\the [W] is stuck to your hand, you cannot attach it to \the [src]!"
			return
		W.loc = A
		W.master = A
		A.part1 = W

		user.unEquip(src)
		loc = A
		master = A
		A.part2 = src

		user.put_in_hands(A)
		A.add_fingerprint(user)
		if(src.flags & NODROP)
			A.flags |= NODROP

/obj/item/device/electropack/Topic(href, href_list)
	//..()
	if(usr.stat || usr.restrained())
		return
	if(((istype(usr, /mob/living/carbon/human) && ((!( ticker ) || (ticker && ticker.mode != "monkey")) && usr.contents.Find(src))) || (usr.contents.Find(master) || (in_range(src, usr) && istype(loc, /turf)))))
		usr.set_machine(src)
		if(href_list["freq"])
			radio_controller.remove_object(src, frequency)
			frequency = sanitize_frequency(frequency + text2num(href_list["freq"]))
			radio_controller.add_object(src, frequency, RADIO_CHAT)
		else
			if(href_list["code"])
				code += text2num(href_list["code"])
				code = round(code)
				code = min(100, code)
				code = max(1, code)
			else
				if(href_list["power"])
					on = !( on )
					icon_state = "electropack[on]"
		if(!( master ))
			if(istype(loc, /mob))
				attack_self(loc)
			else
				for(var/mob/M in viewers(1, src))
					if(M.client)
						attack_self(M)
		else
			if(istype(master.loc, /mob))
				attack_self(master.loc)
			else
				for(var/mob/M in viewers(1, master))
					if(M.client)
						attack_self(M)
	else
		usr << browse(null, "window=radio")
		return
	return

/obj/item/device/electropack/receive_signal(datum/signal/signal)
	if(!signal || signal.encryption != code)
		return

	if(ismob(loc) && on)
		if(shock_cooldown != 0)
			return
		shock_cooldown = 1
		spawn(100)
			shock_cooldown = 0
		var/mob/M = loc
		step(M, pick(cardinal))

		M << "You feel a sharp shock!"
		var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
		s.set_up(3, 1, M)
		s.start()

		M.Weaken(5)

	if(master)
		master.receive_signal()
	return

/obj/item/device/electropack/attack_self(mob/user)

	if(!istype(user, /mob/living/carbon/human))
		return
	user.set_machine(src)
	var/dat = {"<TT>Turned [on ? "On" : "Off"] -
Toggle

Frequency/Code for electropack:

Frequency:
-
- [format_frequency(frequency)]
+
+

Code:
-
- [code]
+
+

</TT>"}
	user << browse(dat, "window=radio")
	onclose(user, "radio")
	return


code:
/obj/item/device/encryptionkey/
	name = "standard encryption key"
	desc = "An encryption key for a radio headset.  Has no special codes in it.  WHY DOES IT EXIST?  ASK NANOTRASEN."
	icon = 'icons/obj/radio.dmi'
	icon_state = "cypherkey"
	w_class = 1
	var/translate_binary = 0
	var/translate_hive = 0
	var/syndie = 0
	var/centcom = 0
	var/list/channels = list()

/obj/item/device/encryptionkey/New()

/obj/item/device/encryptionkey/attackby(obj/item/weapon/W as obj, mob/user as mob, params)

/obj/item/device/encryptionkey/syndicate
	icon_state = "cypherkey"
	channels = list("Syndicate" = 1)
	origin_tech = "syndicate=3"
	syndie = 1//Signifies that it de-crypts Syndicate transmissions

/obj/item/device/encryptionkey/binary
	name = "binary translator key"
	desc = "An encryption key for a radio headset.  To access the binary channel, use :b."
	icon_state = "cypherkey"
	translate_binary = 1
	origin_tech = "syndicate=3"

/obj/item/device/encryptionkey/headset_sec
	name = "security radio encryption key"
	desc = "An encryption key for a radio headset.  To access the security channel, use :s."
	icon_state = "sec_cypherkey"
	channels = list("Security" = 1)

/obj/item/device/encryptionkey/headset_eng
	name = "engineering radio encryption key"
	desc = "An encryption key for a radio headset.  To access the engineering channel, use :e."
	icon_state = "eng_cypherkey"
	channels = list("Engineering" = 1)

/obj/item/device/encryptionkey/headset_rob
	name = "robotics radio encryption key"
	desc = "An encryption key for a radio headset.  To access the engineering channel, use :e. For research, use :n."
	icon_state = "rob_cypherkey"
	channels = list("Science" = 1, "Engineering" = 1)

/obj/item/device/encryptionkey/headset_med
	name = "medical radio encryption key"
	desc = "An encryption key for a radio headset.  To access the medical channel, use :m."
	icon_state = "med_cypherkey"
	channels = list("Medical" = 1)

/obj/item/device/encryptionkey/headset_sci
	name = "science radio encryption key"
	desc = "An encryption key for a radio headset.  To access the science channel, use :n."
	icon_state = "sci_cypherkey"
	channels = list("Science" = 1)

/obj/item/device/encryptionkey/headset_medsci
	name = "medical research radio encryption key"
	desc = "An encryption key for a radio headset.  To access the medical channel, use :m. For science, use :n."
	icon_state = "medsci_cypherkey"
	channels = list("Science" = 1, "Medical" = 1)

/obj/item/device/encryptionkey/headset_com
	name = "command radio encryption key"
	desc = "An encryption key for a radio headset.  To access the command channel, use :c."
	icon_state = "com_cypherkey"
	channels = list("Command" = 1)

/obj/item/device/encryptionkey/heads/captain
	name = "\proper the captain's encryption key"
	desc = "An encryption key for a radio headset.  Channels are as follows: :c - command, :s - security, :e - engineering, :u - supply, :v - service, :m - medical, :n - science."
	icon_state = "cap_cypherkey"
	channels = list("Command" = 1, "Security" = 1, "Engineering" = 0, "Science" = 0, "Medical" = 0, "Supply" = 0, "Service" = 0)

/obj/item/device/encryptionkey/heads/rd
	name = "\proper the research director's encryption key"
	desc = "An encryption key for a radio headset.  To access the science channel, use :n. For command, use :c."
	icon_state = "rd_cypherkey"
	channels = list("Science" = 1, "Command" = 1)

/obj/item/device/encryptionkey/heads/hos
	name = "\proper the head of security's encryption key"
	desc = "An encryption key for a radio headset.  To access the security channel, use :s. For command, use :c."
	icon_state = "hos_cypherkey"
	channels = list("Security" = 1, "Command" = 1)

/obj/item/device/encryptionkey/heads/ce
	name = "\proper the chief engineer's encryption key"
	desc = "An encryption key for a radio headset.  To access the engineering channel, use :e. For command, use :c."
	icon_state = "ce_cypherkey"
	channels = list("Engineering" = 1, "Command" = 1)

/obj/item/device/encryptionkey/heads/cmo
	name = "\proper the chief medical officer's encryption key"
	desc = "An encryption key for a radio headset.  To access the medical channel, use :m. For command, use :c."
	icon_state = "cmo_cypherkey"
	channels = list("Medical" = 1, "Command" = 1)

/obj/item/device/encryptionkey/heads/hop
	name = "\proper the head of personnel's encryption key"
	desc = "An encryption key for a radio headset.  Channels are as follows: :u - supply, :v - service, :c - command."
	icon_state = "hop_cypherkey"
	channels = list("Supply" = 1, "Service" = 1, "Command" = 1)

/obj/item/device/encryptionkey/headset_cargo
	name = "supply radio encryption key"
	desc = "An encryption key for a radio headset.  To access the supply channel, use :u."
	icon_state = "cargo_cypherkey"
	channels = list("Supply" = 1)

/obj/item/device/encryptionkey/headset_service
	name = "service radio encryption key"
	desc = "An encryption key for a radio headset.  To access the service channel, use :v."
	icon_state = "srv_cypherkey"
	channels = list("Service" = 1)

/obj/item/device/encryptionkey/headset_cent
	name = "centcom radio encryption key"
	desc = "An encryption key for a radio headset.  To access the centcom channel, use :x."
	icon_state = "cent_cypherkey"
	centcom = 1
	channels = list("Centcom" = 1)

/obj/item/device/encryptionkey/ai //ported from NT, this goes 'inside' the AI.
	channels = list("Command" = 1, "Security" = 1, "Engineering" = 1, "Science" = 1, "Medical" = 1, "Supply" = 1, "Service" = 1, "AI Private" = 1)


code:
/obj/item/device/radio/headset
	name = "radio headset"
	desc = "An updated, modular intercom that fits over the head. Takes encryption keys. \nTo speak on the general radio frequency, use ; before speaking."
	icon_state = "headset"
	item_state = "headset"
	g_amt = 0
	m_amt = 75
	subspace_transmission = 1
	canhear_range = 0 // can't hear headsets from very far away

	slot_flags = SLOT_EARS
	var/obj/item/device/encryptionkey/keyslot2 = null
	maxf = 1489

/obj/item/device/radio/headset/New()
	..()
	recalculateChannels()

/obj/item/device/radio/headset/Destroy()
	qdel(keyslot)
	qdel(keyslot2)
	keyslot = null
	keyslot2 = null
	..()

/obj/item/device/radio/headset/talk_into(mob/living/M as mob, message, channel)
	if (!listening)
		return
	..()

/obj/item/device/radio/headset/receive_range(freq, level, var/AIuser)
	if(ishuman(src.loc))
		var/mob/living/carbon/human/H = src.loc
		if(H.ears == src)
			return ..(freq, level)
	else if(AIuser)
		return ..(freq, level)
	return -1

/obj/item/device/radio/headset/syndicate //disguised to look like a normal headset for stealth ops
	origin_tech = "syndicate=3"

/obj/item/device/radio/headset/syndicate/alt //undisguised bowman with flash protection
	name = "syndicate headset"
	desc = "A syndicate headset that can be used to hear all radio frequencies. Protects ears from flashbangs. \nTo access the syndicate channel, use ; before speaking."
	flags = EARBANGPROTECT
	origin_tech = "syndicate=3"
	icon_state = "syndie_headset"
	item_state = "syndie_headset"

/obj/item/device/radio/headset/syndicate/New()
	..()
	make_syndie()

/obj/item/device/radio/headset/binary
	origin_tech = "syndicate=3"
/obj/item/device/radio/headset/binary/New()
	..()
	qdel(keyslot)
	keyslot = new /obj/item/device/encryptionkey/binary
	recalculateChannels()

/obj/item/device/radio/headset/headset_sec
	name = "security radio headset"
	desc = "This is used by your elite security force. \nTo access the security channel, use :s."
	icon_state = "sec_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/headset_sec

/obj/item/device/radio/headset/headset_sec/alt
	name = "security bowman headset"
	desc = "This is used by your elite security force. Protects ears from flashbangs. \nTo access the security channel, use :s."
	flags = EARBANGPROTECT
	icon_state = "sec_headset_alt"
	item_state = "sec_headset_alt"

/obj/item/device/radio/headset/headset_eng
	name = "engineering radio headset"
	desc = "When the engineers wish to chat like girls. \nTo access the engineering channel, use :e. "
	icon_state = "eng_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/headset_eng

/obj/item/device/radio/headset/headset_rob
	name = "robotics radio headset"
	desc = "Made specifically for the roboticists, who cannot decide between departments. \nTo access the engineering channel, use :e. For research, use :n."
	icon_state = "rob_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/headset_rob

/obj/item/device/radio/headset/headset_med
	name = "medical radio headset"
	desc = "A headset for the trained staff of the medbay. \nTo access the medical channel, use :m."
	icon_state = "med_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/headset_med

/obj/item/device/radio/headset/headset_sci
	name = "science radio headset"
	desc = "A sciency headset. Like usual. \nTo access the science channel, use :n."
	icon_state = "sci_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/headset_sci

/obj/item/device/radio/headset/headset_medsci
	name = "medical research radio headset"
	desc = "A headset that is a result of the mating between medical and science. \nTo access the medical channel, use :m. For science, use :n."
	icon_state = "medsci_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/headset_medsci

/obj/item/device/radio/headset/headset_com
	name = "command radio headset"
	desc = "A headset with a commanding channel. \nTo access the command channel, use :c."
	icon_state = "com_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/headset_com

/obj/item/device/radio/headset/heads/captain
	name = "\proper the captain's headset"
	desc = "The headset of the king. \nChannels are as follows: :c - command, :s - security, :e - engineering, :u - supply, :v - service, :m - medical, :n - science."
	icon_state = "com_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/heads/captain

/obj/item/device/radio/headset/heads/captain/alt
	name = "\proper the captain's bowman headset"
	desc = "The headset of the boss. Protects ears from flashbangs. \nChannels are as follows: :c - command, :s - security, :e - engineering, :u - supply, :v - service, :m - medical, :n - science."
	flags = EARBANGPROTECT
	icon_state = "com_headset_alt"
	item_state = "com_headset_alt"

/obj/item/device/radio/headset/heads/rd
	name = "\proper the research director's headset"
	desc = "Headset of the fellow who keeps society marching towards technological singularity. \nTo access the science channel, use :n. For command, use :c."
	icon_state = "com_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/heads/rd

/obj/item/device/radio/headset/heads/hos
	name = "\proper the head of security's headset"
	desc = "The headset of the man in charge of keeping order and protecting the station. \nTo access the security channel, use :s. For command, use :c."
	icon_state = "com_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/heads/hos

/obj/item/device/radio/headset/heads/hos/alt
	name = "\proper the head of security's bowman headset"
	desc = "The headset of the man in charge of keeping order and protecting the station. Protects ears from flashbangs. \nTo access the security channel, use :s. For command, use :c."
	flags = EARBANGPROTECT
	icon_state = "com_headset_alt"
	item_state = "com_headset_alt"

/obj/item/device/radio/headset/heads/ce
	name = "\proper the chief engineer's headset"
	desc = "The headset of the guy in charge of keeping the station powered and undamaged. \nTo access the engineering channel, use :e. For command, use :c."
	icon_state = "com_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/heads/ce

/obj/item/device/radio/headset/heads/cmo
	name = "\proper the chief medical officer's headset"
	desc = "The headset of the highly trained medical chief. \nTo access the medical channel, use :m. For command, use :c."
	icon_state = "com_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/heads/cmo

/obj/item/device/radio/headset/heads/hop
	name = "\proper the head of personnel's headset"
	desc = "The headset of the guy who will one day be captain. \nChannels are as follows: :u - supply, :v - service, :c - command."
	icon_state = "com_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/heads/hop

/obj/item/device/radio/headset/headset_cargo
	name = "supply radio headset"
	desc = "A headset used by the QM and his slaves. \nTo access the supply channel, use :u."
	icon_state = "cargo_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/headset_cargo

/obj/item/device/radio/headset/headset_srv
	name = "service radio headset"
	desc = "Headset used by the service staff, tasked with keeping the station full, happy and clean. \nTo access the service channel, use :v."
	icon_state = "srv_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/headset_service

/obj/item/device/radio/headset/headset_cent
	name = "\improper Centcom headset"
	desc = "A headset used by the upper echelons of Nanotrasen. \nTo access the centcom channel, use :y."
	icon_state = "cent_headset"
	item_state = "headset"
	keyslot = new /obj/item/device/encryptionkey/headset_com
	keyslot2 = new /obj/item/device/encryptionkey/headset_cent

/obj/item/device/radio/headset/headset_cent/commander
	keyslot = new /obj/item/device/encryptionkey/heads/captain

/obj/item/device/radio/headset/headset_cent/alt
	name = "\improper Centcom bowman headset"
	desc = "A headset especially for emergency response personnel. Protects ears from flashbangs. \nTo access the centcom channel, use :y."
	flags = EARBANGPROTECT
	icon_state = "cent_headset_alt"
	item_state = "cent_headset_alt"
	keyslot = null

/obj/item/device/radio/headset/ai
	name = "\proper Integrated Subspace Transceiver "
	keyslot2 = new /obj/item/device/encryptionkey/ai

/obj/item/device/radio/headset/ai/receive_range(freq, level)
	return ..(freq, level, 1)

/obj/item/device/radio/headset/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
//	..()
	user.set_machine(src)
	if (!( istype(W, /obj/item/weapon/screwdriver) || (istype(W, /obj/item/device/encryptionkey/ ))))
		return

	if(istype(W, /obj/item/weapon/screwdriver))
		if(keyslot || keyslot2)

			for(var/ch_name in channels)
				radio_controller.remove_object(src, radiochannels[ch_name])
				secure_radio_connections[ch_name] = null

			if(keyslot)
				var/turf/T = get_turf(user)
				if(T)
					keyslot.loc = T
					keyslot = null

			if(keyslot2)
				var/turf/T = get_turf(user)
				if(T)
					keyslot2.loc = T
					keyslot2 = null

			recalculateChannels()
			user << "You pop out the encryption keys in the headset!"

		else
			user << "This headset doesn't have any unique encryption keys!  How useless..."

	if(istype(W, /obj/item/device/encryptionkey/))
		if(keyslot && keyslot2)
			user << "The headset can't hold another key!"
			return

		if(!keyslot)
			user.drop_item()
			W.loc = src
			keyslot = W

		else
			user.drop_item()
			W.loc = src
			keyslot2 = W

		recalculateChannels()

	return

/obj/item/device/radio/headset/recalculateChannels()
	..()
	if(keyslot2)
		for(var/ch_name in keyslot2.channels)
			if(ch_name in src.channels)
				continue
			src.channels += ch_name
			src.channels[ch_name] = keyslot2.channels[ch_name]

		if(keyslot2.translate_binary)
			src.translate_binary = 1

		if(keyslot2.translate_hive)
			src.translate_hive = 1

		if(keyslot2.syndie)
			src.syndie = 1

	for(var/ch_name in channels)
		secure_radio_connections[ch_name] = add_radio(src, radiochannels[ch_name])

	return


code:
/obj/item/device/radio/intercom
	name = "station intercom"
	desc = "Talk through this."
	icon_state = "intercom"
	anchored = 1
	w_class = 4.0
	canhear_range = 2
	var/number = 0
	var/anyai = 1
	var/mob/living/silicon/ai/ai = list()
	var/last_tick //used to delay the powercheck

/obj/item/device/radio/intercom/New()
	..()
	SSobj.processing += src

/obj/item/device/radio/intercom/Destroy()
	SSobj.processing -= src
	..()

/obj/item/device/radio/intercom/attack_ai(mob/user as mob)
	src.add_fingerprint(user)
	spawn (0)
		attack_self(user)

/obj/item/device/radio/intercom/attack_paw(mob/user as mob)
	return src.attack_hand(user)

/obj/item/device/radio/intercom/attack_hand(mob/user as mob)
	src.add_fingerprint(user)
	spawn (0)
		attack_self(user)

/obj/item/device/radio/intercom/receive_range(freq, level)
	if (!on)
		return -1
	if (isWireCut(WIRE_RECEIVE))
		return -1
	if(!(0 in level))
		var/turf/position = get_turf(src)
		if(isnull(position) || !(position.z in level))
			return -1
	if (!src.listening)
		return -1
	if(freq == SYND_FREQ)
		if(!(src.syndie))
			return -1//Prevents broadcast of messages over devices lacking the encryption

	return canhear_range

/obj/item/device/radio/intercom/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq)
	if(!anyai && !(speaker in ai))
		return
	..()

/obj/item/device/radio/intercom/process()
	if(((world.timeofday - last_tick) > 30) || ((world.timeofday - last_tick) < 0))
		last_tick = world.timeofday

		if(!src.loc)
			on = 0
		else
			var/area/A = src.loc.loc
			if(!A || !isarea(A) || emped)
				on = 0
			else
				on = A.powered(EQUIP) // set "on" to the power status

		if(!on)
			icon_state = "intercom-p"
		else
			icon_state = "intercom"

/obj/item/device/radio/intercom/rejects_blood()
	return 1


code:
/obj/item/device/radio
	icon = 'icons/obj/radio.dmi'
	name = "station bounced radio"
	suffix = "\[3\]"
	icon_state = "walkietalkie"
	item_state = "walkietalkie"
	var/on = 1 // 0 for off
	var/last_transmission
	var/frequency = 1459 //common chat
	var/traitor_frequency = 0 //tune to frequency to unlock traitor supplies
	var/canhear_range = 3 // the range which mobs can hear this radio from
	var/obj/item/device/radio/patch_link = null
	var/datum/wires/radio/wires = null
	var/list/secure_radio_connections
	var/prison_radio = 0
	var/b_stat = 0
	var/broadcasting = 0
	var/listening = 1
	var/translate_binary = 0
	var/translate_hive = 0
	var/freerange = 0 // 0 - Sanitize frequencies, 1 - Full range
	var/list/channels = list() //see communications.dm for full list. First channes is a "default" for :h
	var/obj/item/device/encryptionkey/keyslot //To allow the radio to accept encryption keys.
	var/subspace_transmission = 0
	var/syndie = 0//Holder to see if it's a syndicate encrpyed radio
	var/centcom = 0
	var/maxf = 1499
	var/freqlock = 0 //Frequency lock to stop the user from untuning specialist radios.
	var/emped = 0	//Highjacked to track the number of consecutive EMPs on the radio, allowing consecutive EMP's to stack properly.
//			"Example" = FREQ_LISTENING|FREQ_BROADCASTING
	flags = CONDUCT | HEAR
	slot_flags = SLOT_BELT
	languages = HUMAN | ROBOT
	throw_speed = 3
	throw_range = 7
	w_class = 2
	g_amt = 25
	m_amt = 75

	var/const/TRANSMISSION_DELAY = 5 // only 2/second/radio
	var/const/FREQ_LISTENING = 1
		//FREQ_BROADCASTING = 2

/obj/item/device/radio/proc/set_frequency(new_frequency)
	remove_radio(src, frequency)
	frequency = add_radio(src, new_frequency)

/obj/item/device/radio/New()
	wires = new(src)
	if(prison_radio)
		wires.CutWireIndex(WIRE_TRANSMIT)
	secure_radio_connections = new
	..()
	if(radio_controller)
		initialize()

/obj/item/device/radio/proc/recalculateChannels()
	channels = list()
	translate_binary = 0
	translate_hive = 0
	syndie = 0
	centcom = 0

	if(keyslot)
		for(var/ch_name in keyslot.channels)
			if(ch_name in src.channels)
				continue
			channels += ch_name
			channels[ch_name] = keyslot.channels[ch_name]

		if(keyslot.translate_binary)
			translate_binary = 1

		if(keyslot.translate_hive)
			translate_hive = 1

		if(keyslot.syndie)
			syndie = 1

		if(keyslot.centcom)
			centcom = 1

	for(var/ch_name in channels)
		secure_radio_connections[ch_name] = add_radio(src, radiochannels[ch_name])

/obj/item/device/radio/proc/make_syndie() //Turns normal radios into Syndicate radios!
	qdel(keyslot)
	keyslot = new /obj/item/device/encryptionkey/syndicate
	syndie = 1
	recalculateChannels()

/obj/item/device/radio/Destroy()
	qdel(wires)
	wires = null
	remove_radio_all(src) //Just to be sure
	..()

/obj/item/device/radio/MouseDrop(obj/over_object as obj, src_location, over_location)
	var/mob/M = usr
	if((!istype(over_object, /obj/screen)) && src.loc == M)
		return attack_self(M)
	return

/obj/item/device/radio/initialize()
	if(freerange)
		if(frequency < 1200 || frequency > 1600)
			frequency = sanitize_frequency(frequency, maxf)
	// The max freq is higher than a regular headset to decrease the chance of people listening in, if you use the higher channels.
	else if (frequency < 1441 || frequency > maxf)
		//world.log << "[src] ([type]) has a frequency of [frequency], sanitizing."
		frequency = sanitize_frequency(frequency, maxf)

	set_frequency(frequency)

	for (var/ch_name in channels)
		secure_radio_connections[ch_name] = add_radio(src, radiochannels[ch_name])

/obj/item/device/radio/attack_self(mob/user as mob)
	user.set_machine(src)
	interact(user)

/obj/item/device/radio/interact(mob/user as mob)
	if(!on)
		return

	if(active_uplink_check(user))
		return

	var/dat = ""

	if(!istype(src, /obj/item/device/radio/headset))
		dat += {"
				Microphone: [broadcasting ? "Engaged" : "Disengaged"]

				Speaker: [listening ? "Engaged" : "Disengaged"]

				"}
	else	//Headsets dont get a mic button, speaker controls both
		dat += "Power: [listening ? "Engaged" : "Disengaged"]
"
	if (freqlock)
		dat += "Frequency: LOCKED
"
	dat += {"
				Frequency:
				-
				-
				[format_frequency(frequency)]
				+
				+

				"}

	for (var/ch_name in channels)
		dat+=text_sec_channel(ch_name, channels[ch_name])
	dat+= text_wires()
	//user << browse(dat, "window=radio")
	//onclose(user, "radio")
	var/datum/browser/popup = new(user, "radio", "[src]")
	popup.set_content(dat)
	popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
	popup.open()
	return

/obj/item/device/radio/proc/text_wires()
	if (b_stat)
		return wires.GetInteractWindow()
	return

/obj/item/device/radio/proc/text_sec_channel(var/chan_name, var/chan_stat)
	var/list = !!(chan_stat&FREQ_LISTENING)!=0
	return {"
			[chan_name]: [list ? "Engaged" : "Disengaged"]

			"}

/obj/item/device/radio/Topic(href, href_list)
	//..()
	if (usr.stat || !on)
		return

	if (!(issilicon(usr) || (usr.contents.Find(src) || ( in_range(src, usr) && istype(loc, /turf) ))))
		usr << browse(null, "window=radio")
		return
	usr.set_machine(src)
	if (href_list["freq"])
		if (!freqlock)
			var/new_frequency = (frequency + text2num(href_list["freq"]))
			if (!freerange || (frequency < 1200 || frequency > 1600))
				new_frequency = sanitize_frequency(new_frequency, maxf)
			set_frequency(new_frequency)
			if(hidden_uplink)
				if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency))
					usr << browse(null, "window=radio")
					return

	else if (href_list["talk"])
		broadcasting = text2num(href_list["talk"])
	else if (href_list["listen"])
		var/chan_name = href_list["ch_name"]
		if (!chan_name)
			listening = text2num(href_list["listen"])
		else
			if (channels[chan_name] & FREQ_LISTENING)
				channels[chan_name] &= ~FREQ_LISTENING
			else
				channels[chan_name] |= FREQ_LISTENING
	if (!( master ))
		if (istype(loc, /mob))
			interact(loc)
		else
			updateDialog()
	else
		if (istype(master.loc, /mob))
			interact(master.loc)
		else
			updateDialog()
	add_fingerprint(usr)

/obj/item/device/radio/proc/isWireCut(var/index)
	return wires.IsIndexCut(index)

/obj/item/device/radio/talk_into(atom/movable/M, message, channel)
	if(!on) return // the device has to be on
	//  Fix for permacell radios, but kinda eh about actually fixing them.
	if(!M || !message) return

	//  Uncommenting this. To the above comment:
	// 	The permacell radios aren't suppose to be able to transmit, this isn't a bug and this "fix" is just making radio wires useless. -Giacom
	if(isWireCut(WIRE_TRANSMIT)) // The device has to have all its wires and shit intact
		return

	if(!M.IsVocal())
		return

	/* Quick introduction:
		This new radio system uses a very robust FTL signaling technology unoriginally
		dubbed "subspace" which is somewhat similar to 'blue-space' but can't
		actually transmit large mass. Headsets are the only radio devices capable
		of sending subspace transmissions to the Communications Satellite.

		A headset sends a signal to a subspace listener/reciever elsewhere in space,
		the signal gets processed and logged, and an audible transmission gets sent
		to each individual headset.
	*/

	/*
		be prepared to disregard any comments in all of tcomms code. i tried my best to keep them somewhat up-to-date, but eh
	*/

		//get the frequency you buttface. radios no longer use the radio_controller. confusing for future generations, convenient for me.
	var/freq
	if(channel && channels && channels.len > 0)
		if (channel == "department")
			channel = channels[1]
		freq = secure_radio_connections[channel]
		if (!channels[channel]) // if the channel is turned off, don't broadcast
			return
	else
		freq = frequency
		channel = null

	var/freqnum = text2num(freq) //Why should we call text2num three times when we can just do it here?
	var/turf/position = get_turf(src)

	//#### Tagging the signal with all appropriate identity values ####//

	// ||-- The mob's name identity --||
	var/real_name = M.name // mob's real name
	var/mobkey = "none" // player key associated with mob
	var/voicemask = 0 // the speaker is wearing a voice mask
	var/voice = M.GetVoice() // Why reinvent the wheel when there is a proc that does nice things already
	if(ismob(M))
		var/mob/speaker = M
		real_name = speaker.real_name
		if(speaker.client)
			mobkey = speaker.key // assign the mob's key

	var/jobname // the mob's "job"

	// --- Human: use their job as seen on the crew manifest - makes it unneeded to carry an ID for an AI to see their job
	if (ishuman(M))
		var/datum/data/record/findjob = find_record("name", voice, data_core.general)

		if(voice != real_name)
			voicemask = 1
		if(findjob)
			jobname = findjob.fields["rank"]
		else
			jobname = "Unknown"

	// --- Carbon Nonhuman ---
	else if (iscarbon(M)) // Nonhuman carbon mob
		jobname = "No id"

	// --- AI ---
	else if (isAI(M))
		jobname = "AI"

	// --- Cyborg ---
	else if (isrobot(M) && !ismommi(M))
		var/mob/living/silicon/robot/B = M
		jobname = "[B.designation] Cyborg"
	// --- MoMMI ---
	else if (ismommi(M))
		jobname = "MoMMI"

	// --- Personal AI (pAI) ---
	else if (istype(M, /mob/living/silicon/pai))
		jobname = "Personal AI"

	// --- Cold, emotionless machines. ---
	else if(isobj(M))
		jobname = "Machine"

	// --- Unidentifiable mob ---
	else
		jobname = "Unknown"

	/* ###### Centcom channel bypasses all comms relays. ###### */

	if (freqnum == CENTCOM_FREQ && centcom)
		var/datum/signal/signal = new
		signal.transmission_method = 2
		signal.data = list(
			"mob" = M, 				// store a reference to the mob
			"mobtype" = M.type, 	// the mob's type
			"realname" = real_name, // the mob's real name
			"name" = voice,			// the mob's voice name
			"job" = jobname,		// the mob's job
			"key" = mobkey,			// the mob's key
			"vmask" = voicemask,	// 1 if the mob is using a voice gas mas

			"compression" = 0,		// uncompressed radio signal
			"message" = message, 	// the actual sent message
			"radio" = src, 			// stores the radio used for transmission
			"slow" = 0,
			"traffic" = 0,
			"type" = 0,
			"server" = null,
			"reject" = 0,
			"level" = 0,
			"languages" = languages,
			)
		signal.frequency = freqnum // Quick frequency set
		Broadcast_Message(M, voicemask,
				  src, message, voice, jobname, real_name,
				  5, signal.data["compression"], list(position.z, 0), freq)
		return

	/* ###### Radio headsets can only broadcast through subspace ###### */

	if(subspace_transmission)
		// First, we want to generate a new radio signal
		var/datum/signal/signal = new
		signal.transmission_method = 2 // 2 would be a subspace transmission.
									   // transmission_method could probably be enumerated through #define. Would be neater.
									   // --- Finally, tag the actual signal with the appropriate values ---
		signal.data = list(
			// Identity-associated tags:
			"mob" = M, // store a reference to the mob
			"mobtype" = M.type, 	// the mob's type
			"realname" = real_name, // the mob's real name
			"name" = voice,			// the mob's voice name
			"job" = jobname,		// the mob's job
			"key" = mobkey,			// the mob's key
			"vmask" = voicemask,	// 1 if the mob is using a voice gas mask

			// We store things that would otherwise be kept in the actual mob
			// so that they can be logged even AFTER the mob is deleted or something

			// Other tags:
			"compression" = rand(35,65), // compressed radio signal
			"message" = message, // the actual sent message
			"radio" = src, // stores the radio used for transmission
			"slow" = 0, // how much to sleep() before broadcasting - simulates net lag
			"traffic" = 0, // dictates the total traffic sum that the signal went through
			"type" = 0, // determines what type of radio input it is: normal broadcast
			"server" = null, // the last server to log this signal
			"reject" = 0,	// if nonzero, the signal will not be accepted by any broadcasting machinery
			"level" = position.z, // The source's z level
			"languages" = M.languages //The languages M is talking in.
			)
		signal.frequency = freq

		 //#### Sending the signal to all subspace receivers ####//

		for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
			R.receive_signal(signal)

		// Allinone can act as receivers.
		for(var/obj/machinery/telecomms/allinone/R in telecomms_list)
			R.receive_signal(signal)

		// Receiving code can be located in Telecommunications.dm
		return

	 /* ###### Intercoms and station-bounced radios ###### */

	var/filter_type = 2

	var/datum/signal/signal = new
	signal.transmission_method = 2

	/* --- Try to send a normal subspace broadcast first */

	signal.data = list(
		"mob" = M, 				// store a reference to the mob
		"mobtype" = M.type, 	// the mob's type
		"realname" = real_name, // the mob's real name
		"name" = voice,			// the mob's voice name
		"job" = jobname,		// the mob's job
		"key" = mobkey,			// the mob's key
		"vmask" = voicemask,	// 1 if the mob is using a voice gas mas

		"compression" = 0,		// uncompressed radio signal
		"message" = message, 	// the actual sent message
		"radio" = src, 			// stores the radio used for transmission
		"slow" = 0,
		"traffic" = 0,
		"type" = 0,
		"server" = null,
		"reject" = 0,
		"level" = position.z
		)
	signal.frequency = text2num(freq) // Quick frequency set
	for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
		R.receive_signal(signal)

	spawn(20) // wait a little...

		if(signal.data["done"] && position.z in signal.data["level"])
			// we're done here.
			return

		// Oh my god; the comms are down or something because the signal hasn't been broadcasted yet in our level.
		// Send a mundane broadcast with limited targets:
		Broadcast_Message(M, voicemask,
						  src, message, voice, jobname, real_name,
						  filter_type, signal.data["compression"], list(position.z), freq)

/obj/item/device/radio/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq)
	if(radio_freq)
		return
	if(broadcasting)
		if(get_dist(src, speaker) <= canhear_range)
			talk_into(speaker, raw_message)
/*
/obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R as obj, message)

	if ((R.frequency == frequency && message))
		return 1
	else if

	else
		return null
	return
*/

/obj/item/device/radio/proc/receive_range(freq, level)
	// check if this radio can receive on the given frequency, and if so,
	// what the range is in which mobs will hear the radio
	// returns: -1 if can't receive, range otherwise

	if (isWireCut(WIRE_RECEIVE))
		return -1
	if(!listening)
		return -1
	if(!(0 in level))
		var/turf/position = get_turf(src)
		if(!position || !(position.z in level))
			return -1
	if(freq == SYND_FREQ)
		if(!(src.syndie)) //Checks to see if it's allowed on that frequency, based on the encryption keys
			return -1
	if(freq == CENTCOM_FREQ)
		if(!(src.centcom)) //Checks to see if it's allowed on that frequency, based on the encryption keys
			return -1
	if (!on)
		return -1
	if (!freq) //received on main frequency
		if (!listening)
			return -1
	else
		var/accept = (freq==frequency && listening)
		if (!accept)
			for(var/ch_name in channels)
				if(channels[ch_name] & FREQ_LISTENING)
					if(radiochannels[ch_name] == text2num(freq) || syndie) //the radiochannels list is located in communications.dm
						accept = 1
						break
		if (!accept)
			return -1
	return canhear_range

/obj/item/device/radio/proc/send_hear(freq, level)

	var/range = receive_range(freq, level)
	if(range > -1)
		return get_hearers_in_view(canhear_range, src)

/obj/item/device/radio/examine(mob/user)
	..()
	if (b_stat)
		user << "[name] can be attached and modified."
	else
		user << "[name] can not be modified or attached."

/obj/item/device/radio/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
	..()
	user.set_machine(src)
	if (!( istype(W, /obj/item/weapon/screwdriver) ))
		return
	b_stat = !( b_stat )
	if(!istype(src, /obj/item/device/radio/beacon))
		if (b_stat)
			user.show_message("The radio can now be attached and modified!")
		else
			user.show_message("The radio can no longer be modified or attached!")
		updateDialog()
			//Foreach goto(83)
		add_fingerprint(user)
		return
	else return

/obj/item/device/radio/emp_act(severity)
	emped++ //There's been an EMP; better count it
	var/curremp = emped //Remember which EMP this was
	if (listening && ismob(loc))	// if the radio is turned on and on someone's person they notice
		loc << "\The [src] overloads."
	broadcasting = 0
	listening = 0
	for (var/ch_name in channels)
		channels[ch_name] = 0
	on = 0
	spawn(200)
		if(emped == curremp) //Don't fix it if it's been EMP'd again
			emped = 0
			if (!istype(src, /obj/item/device/radio/intercom)) // intercoms will turn back on on their own
				on = 1
	..()

///////////////////////////////
//////////Borg Radios//////////
///////////////////////////////
//Giving borgs their own radio to have some more room to work with -Sieve

/obj/item/device/radio/borg

/obj/item/device/radio/borg/syndicate
	syndie = 1
	keyslot = new /obj/item/device/encryptionkey/syndicate
/obj/item/device/radio/borg/syndicate/New()
	..()
	set_frequency(SYND_FREQ)

/obj/item/device/radio/borg/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
//	..()
	user.set_machine(src)
	if (!( istype(W, /obj/item/weapon/screwdriver) || (istype(W, /obj/item/device/encryptionkey/ ))))
		return

	if(istype(W, /obj/item/weapon/screwdriver))
		if(keyslot)

			for(var/ch_name in channels)
				radio_controller.remove_object(src, radiochannels[ch_name])
				secure_radio_connections[ch_name] = null

			if(keyslot)
				var/turf/T = get_turf(user)
				if(T)
					keyslot.loc = T
					keyslot = null

			recalculateChannels()
			user << "You pop out the encryption key in the radio!"

		else
			user << "This radio doesn't have any encryption keys!"

	if(istype(W, /obj/item/device/encryptionkey/))
		if(keyslot)
			user << "The radio can't hold another key!"
			return

		if(!keyslot)
			user.drop_item()
			W.loc = src
			keyslot = W

		recalculateChannels()

	return

/obj/item/device/radio/borg/Topic(href, href_list)
	if(usr.stat || !on)
		return
	if (href_list["mode"])
		subspace_transmission = !subspace_transmission
		if(!subspace_transmission)//Simple as fuck, clears the channel list to prevent talking/listening over them if subspace transmission is disabled
			channels = list()
		else
			recalculateChannels()
		usr << "Subspace Transmission is [(subspace_transmission) ? "enabled" : "disabled"]"
	..()

/obj/item/device/radio/borg/interact(mob/user as mob)
	if(!on)
		return

	var/dat = "<title>[src]</title><TT>"
	dat += {"
				Speaker: [listening ? "Engaged" : "Disengaged"]

				Frequency:
				-
				-
				[format_frequency(frequency)]
				+
				+

				Toggle Broadcast Mode

				"}

	if(subspace_transmission)//Don't even bother if subspace isn't turned on
		for (var/ch_name in channels)
			dat+=text_sec_channel(ch_name, channels[ch_name])
	dat+={"[text_wires()]</TT>"}
	user << browse(dat, "window=radio")
	onclose(user, "radio")
	return

/obj/item/device/radio/off	// Station bounced radios, their only difference is spawning with the speakers off, this was made to help the lag.
	listening = 0			// And it's nice to have a subtype too for future features.


code:
//Recaller device
//Allows gang leaders to recall the shuttle
/obj/item/device/recaller
	name = "suspicious device"
	desc = "A strange device of sorts. Hard to really make out what it actually does just by looking."
	icon_state = "recaller"
	item_state = "walkietalkie"
	throwforce = 0
	w_class = 1.0
	throw_speed = 3
	throw_range = 7
	flags = CONDUCT
	var/recalling = 0

/obj/item/device/recaller/attack_self(mob/user)
	if(recalling)
		return
	if((user.mind in ticker.mode.A_bosses) || (user.mind in ticker.mode.B_bosses))
		var/turf/userturf = get_turf(user)
		if(userturf.z != 1)
			user << "\icon[src]Error: Device out of range of station communication arrays."
			return

		switch(SSshuttle.emergency.mode)
			if(SHUTTLE_CALL)
				recalling = 1
				loc << "\icon[src]Generating shuttle recall order with codes retrieved from last call signal..."
				sleep(rand(10,30))
				loc << "\icon[src]Shuttle recall order generated. Accessing station long-range communication arrays..."
				sleep(rand(10,30))
				loc << "\icon[src]Comm arrays accessed. Broadcasting recall signal..."
				sleep(rand(10,30))
				recalling = 0
				log_game("[key_name(user)] has recalled the shuttle with a recaller.")
				message_admins("[key_name_admin(user)] has recalled the shuttle with a recaller.", 1)
				if(!SSshuttle.cancelEvac(user))
					loc << "\icon[src]No response recieved. Emergency shuttle cannot be recalled at this time."
				return

		user << "\icon[src]Emergency shuttle cannot be recalled at this time."


code:
/*
CONTAINS:
T-RAY
DETECTIVE SCANNER
HEALTH ANALYZER
GAS ANALYZER
MASS SPECTROMETER

*/
/obj/item/device/t_scanner
	name = "\improper T-ray scanner"
	desc = "A terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
	icon_state = "t-ray0"
	var/on = 0
	slot_flags = SLOT_BELT
	w_class = 2
	item_state = "electronic"
	m_amt = 150
	origin_tech = "magnets=1;engineering=1"

/obj/item/device/t_scanner/attack_self(mob/user)

	on = !on
	icon_state = copytext(icon_state, 1, length(icon_state))+"[on]"

	if(on)
		SSobj.processing |= src

/obj/item/device/t_scanner/process()
	if(!on)
		SSobj.processing.Remove(src)
		return null
	scan()

/obj/item/device/t_scanner/proc/scan()

	for(var/turf/T in range(2, src.loc.loc) )
		if(!T)
			continue

		if(!T.intact)
			continue

		for(var/obj/O in T.contents)

			if(O.level != 1)
				continue

			if(O.invisibility == 101)
				O.invisibility = 0
				spawn(10)
					if(O)
						var/turf/U = O.loc
						if(U.intact)
							O.invisibility = 101

		var/mob/living/M = locate() in T
		if(M && M.invisibility == 2)
			M.invisibility = 0
			spawn(2)
				if(M)
					M.invisibility = INVISIBILITY_LEVEL_TWO

/obj/item/device/healthanalyzer
	name = "health analyzer"
	icon_state = "health"
	item_state = "analyzer"
	desc = "A hand-held body scanner able to distinguish vital signs of the subject."
	flags = CONDUCT
	slot_flags = SLOT_BELT
	throwforce = 3
	w_class = 1.0
	throw_speed = 3
	throw_range = 7
	m_amt = 200
	origin_tech = "magnets=1;biotech=1"
	var/mode = 1
	var/scanchems = 0

/obj/item/device/healthanalyzer/attack_self(mob/user)
	if(!scanchems)
		user << "You switch the health analyzer to scan chemical contents."
		scanchems = 1
	else
		user << "You switch the health analyzer to check physical health."
		scanchems = 0
	return
/obj/item/device/healthanalyzer/attack(mob/living/M as mob, mob/living/carbon/human/user as mob)

	// Clumsiness/brain damage check
	if ((user.disabilities & CLUMSY || user.getBrainLoss() >= 60) && prob(50))
		user << "You stupidly try to analyze the floor's vitals!"
		user.visible_message("[user] has analyzed the floor's vitals!")
		user.show_message("Analyzing Results for The floor:\n\t Overall Status: Healthy", 1)
		user.show_message("\t Damage Specifics: 0-0-0-0", 1)
		user.show_message("Key: Suffocation/Toxin/Burn/Brute", 1)
		user.show_message("Body Temperature: ???", 1)
		return

	user.visible_message("[user] has analyzed [M]'s vitals.")

	if(!scanchems)
		healthscan(user, M, mode)
	else
		chemscan(user, M)

	src.add_fingerprint(user)
	return

// Used by the PDA medical scanner too
/proc/healthscan(var/mob/living/user, var/mob/living/M, var/mode = 1)

	//Damage specifics
	var/oxy_loss = M.getOxyLoss()
	var/tox_loss = M.getToxLoss()
	var/fire_loss = M.getFireLoss()
	var/brute_loss = M.getBruteLoss()
	var/mob_status = (M.stat > 1 ? "Deceased" : "[M.health]% healthy")

	if(M.status_flags & FAKEDEATH)
		mob_status = "Deceased"
		oxy_loss = max(rand(1, 40), oxy_loss, (300 - (tox_loss + fire_loss + brute_loss))) // Random oxygen loss

	if(ishuman(M))
		var/mob/living/carbon/human/H = M
		if(H.heart_attack)
			user.show_message("Subject suffering from heart attack: Apply defibrillator immediately!", 1)

	user.show_message(text("Analyzing Results for []:\n\t Overall Status: []", M, mob_status), 1)
	if(ishuman(M))
		var/mob/living/carbon/human/H = M
		if(H.dna)// Show target's species, if they have one
			user.show_message("Species: [H.dna.species.name]", 1)
		else // Otherwise we can assume that they are a regular human
			user.show_message("Species: Human", 1)
	user.show_message("\t Damage Specifics: [oxy_loss]-[tox_loss]-[fire_loss]-[brute_loss]", 1)
	user.show_message("Key: Suffocation/Toxin/Burn/Brute", 1)
	user.show_message("Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)", 1)

	// Time of death
	if(M.tod && (M.stat == DEAD || (M.status_flags & FAKEDEATH)))
		user.show_message("Time of Death: [M.tod]", 1)

	// Organ damage report
	if(istype(M, /mob/living/carbon/human) && mode == 1)
		var/mob/living/carbon/human/H = M
		var/list/damaged = H.get_damaged_organs(1,1)
		user.show_message("Localized Damage, Burn/Brute:",1)
		if(length(damaged)>0)
			for(var/obj/item/organ/limb/org in damaged)
				user.show_message(text("\t []: []-[]", capitalize(org.getDisplayName()), (org.burn_dam > 0) ? "[org.burn_dam]" : 0, (org.brute_dam > 0) ? "[org.brute_dam]" : 0), 1)
		else
			user.show_message("\t Limbs are OK.",1)

	// Damage descriptions

	user.show_message(text("[] | [] | [] | []", oxy_loss > 50 ? " Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal", tox_loss > 50 ? " Dangerous amount of toxins detected" : "Subject bloodstream toxin level minimal", fire_loss > 50 ? " Severe burn damage detected" : "Subject burn injury status O.K", brute_loss > 50 ? " Severe tissue damage detected" : "Subject brute-force injury status O.K"), 1)

	if(M.getStaminaLoss())
		user.show_message("Subject appears to be suffering from fatigue.", 1)

	if (M.getCloneLoss())
		user.show_message("Subject appears to have [M.getCloneLoss() > 30 ? "severe" : "minor"] cellular damage.", 1)

	for(var/datum/disease/D in M.viruses)
		if(!(D.visibility_flags & HIDDEN_SCANNER))
			user.show_message("Warning: [D.form] Detected\nName: [D.name].\nType: [D.spread_text].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure_text]", 1)

	if (M.reagents && M.reagents.get_reagent_amount("inaprovaline"))
		user.show_message("Bloodstream Analysis located [M.reagents:get_reagent_amount("inaprovaline")] units of rejuvenation chemicals.", 1)
	if (M.has_brain_worms())
		user.show_message("Subject suffering from aberrant brain activity. Recommend further scanning.", 1)
	if (M.getBrainLoss() >= 100 || !M.getorgan(/obj/item/organ/brain))
		user.show_message("Subject brain function is non-existant.", 1)
	else if (M.getBrainLoss() >= 60)
		user.show_message("Severe brain damage detected. Subject likely to have mental retardation.", 1)
	else if (M.getBrainLoss() >= 10)
		user.show_message("Significant brain damage detected. Subject may have had a concussion.", 1)

	// Blood Level
	if(ishuman(M))
		var/mob/living/carbon/human/H = M
		if(H.vessel)
			if(H.blood_max)
				user.show_message("Subject is bleeding!")
			var/blood_volume = round(H.vessel.get_reagent_amount("blood"))
			var/blood_percent =  blood_volume / 560
			var/blood_type = H.dna.blood_type
			blood_percent *= 100
			if(blood_volume <= 500 && blood_volume > 336)
				user.show_message("Warning: Blood Level LOW: [blood_percent]% [blood_volume]cl. Type: [blood_type]")
			else if(blood_volume <= 336)
				user.show_message("Warning: Blood Level CRITICAL: [blood_percent]% [blood_volume]cl. Type: [blood_type]")
			else
				user.show_message("Blood Level Normal: [blood_percent]% [blood_volume]cl. Type: [blood_type]")

/proc/chemscan(var/mob/living/user, var/mob/living/M)
	if(ishuman(M))
		var/mob/living/carbon/human/H = M
		if(H.reagents)
			if(H.reagents.reagent_list.len)
				user.show_message("Subject contains the following reagents:")
				for(var/datum/reagent/R in H.reagents.reagent_list)
					user.show_message("[R.volume]u of [R.name][R.overdosed == 1 ? " - OVERDOSING" : "."]")
			else
				user.show_message("Subject contains no reagents.")
			if(H.reagents.addiction_list.len)
				user.show_message("Subject is addicted to the following reagents:")
				for(var/datum/reagent/R in H.reagents.addiction_list)
					user.show_message("[R.name]")
			else
				user.show_message("Subject is not addicted to any reagents.")

/obj/item/device/healthanalyzer/verb/toggle_mode()
	set name = "Switch Verbosity"
	set category = "Object"

	if(usr.stat || !usr.canmove || usr.restrained())
		return

	mode = !mode
	switch (mode)
		if(1)
			usr << "The scanner now shows specific limb damage."
		if(0)
			usr << "The scanner no longer shows limb damage."

/obj/item/device/analyzer
	desc = "A hand-held environmental scanner which reports current gas levels."
	name = "analyzer"
	icon_state = "atmos"
	item_state = "analyzer"
	w_class = 2.0
	flags = CONDUCT
	slot_flags = SLOT_BELT
	throwforce = 0
	throw_speed = 3
	throw_range = 7
	m_amt = 30
	g_amt = 20
	origin_tech = "magnets=1;engineering=1"

/obj/item/device/analyzer/attack_self(mob/user as mob)

	if (user.stat)
		return

	var/turf/location = user.loc
	if (!( istype(location, /turf) ))
		return

	var/datum/gas_mixture/environment = location.return_air()

	var/pressure = environment.return_pressure()
	var/total_moles = environment.total_moles()

	user.show_message(" Results:", 1)
	if(abs(pressure - ONE_ATMOSPHERE) < 10)
		user.show_message(" Pressure: [round(pressure,0.1)] kPa", 1)
	else
		user.show_message(" Pressure: [round(pressure,0.1)] kPa", 1)
	user.show_message(" Total Moles: [round(total_moles,0.01)] mol", 1)
	if(total_moles)
		var/o2_concentration = environment.oxygen/total_moles
		var/n2_concentration = environment.nitrogen/total_moles
		var/co2_concentration = environment.carbon_dioxide/total_moles
		var/plasma_concentration = environment.toxins/total_moles
		var/o2_moles = environment.oxygen
		var/n2_moles = environment.nitrogen
		var/co2_moles = environment.carbon_dioxide
		var/plasma_moles = environment.toxins

		var/unknown_moles = total_moles-(o2_moles+n2_moles+co2_moles+plasma_moles)
		var/unknown_concentration =  1-(o2_concentration+n2_concentration+co2_concentration+plasma_concentration)
		if(abs(n2_concentration - N2STANDARD) < 20)
			user.show_message(" Nitrogen: [round(n2_concentration*100,0.1)]% [round(n2_moles,0.01)] mol", 1)
		else
			user.show_message(" Nitrogen: [round(n2_concentration*100,0.1)]% [round(n2_moles,0.01)] mol", 1)

		if(abs(o2_concentration - O2STANDARD) < 2)
			user.show_message(" Oxygen: [round(o2_concentration*100,0.1)]% [round(o2_moles,0.01)] mol", 1)
		else
			user.show_message(" Oxygen: [round(o2_concentration*100,0.1)]% [round(o2_moles,0.01)] mol", 1)

		if(co2_concentration > 0.01)
			user.show_message(" CO2: [round(co2_concentration*100,0.1)]% [round(co2_moles,0.01)] mol", 1)
		else
			user.show_message(" CO2: [round(co2_concentration*100,0.1)]% [round(co2_moles,0.01)] mol", 1)

		if(plasma_concentration > 0.01)
			user.show_message(" Plasma: [round(plasma_concentration*100,0.1)]% [round(plasma_moles,0.01)] mol", 1)

		if(unknown_concentration > 0.01)
			user.show_message(" Unknown: [round(unknown_concentration*100,0.1)]% [round(unknown_moles,0.01)] mol", 1)

		user.show_message(" Temperature: [round(environment.temperature-T0C,0.1)]°C", 1)

	src.add_fingerprint(user)
	return

/obj/item/device/mass_spectrometer
	desc = "A hand-held mass spectrometer which identifies trace chemicals in a blood sample."
	name = "mass-spectrometer"
	icon_state = "spectrometer"
	item_state = "analyzer"
	w_class = 2.0
	flags = CONDUCT | OPENCONTAINER
	slot_flags = SLOT_BELT
	throwforce = 0
	throw_speed = 3
	throw_range = 7
	m_amt = 30
	g_amt = 20
	origin_tech = "magnets=2;biotech=2"
	var/details = 0
	var/recent_fail = 0

/obj/item/device/mass_spectrometer/New()
	..()
	create_reagents(5)

/obj/item/device/mass_spectrometer/on_reagent_change()
	if(reagents.total_volume)
		icon_state = initial(icon_state) + "_s"
	else
		icon_state = initial(icon_state)

/obj/item/device/mass_spectrometer/attack_self(mob/user as mob)
	if (user.stat)
		return
	if (crit_fail)
		user << " This device has critically failed and is no longer functional!"
		return
	if (!user.IsAdvancedToolUser())
		user << " You don't have the dexterity to do this!"
		return
	if(reagents.total_volume)
		var/list/blood_traces = list()
		for(var/datum/reagent/R in reagents.reagent_list)
			if(R.id != "blood")
				reagents.clear_reagents()
				user.show_message(" The sample was contaminated! Please insert another sample.", 1)
				return
			else
				blood_traces = params2list(R.data["trace_chem"])
				break
		var/dat = "Trace Chemicals Found:"
		if(!blood_traces.len)
			dat += "
None"
		else
			for(var/R in blood_traces)
				if(prob(reliability))
					dat += "
[chemical_reagents_list[R]]"

					if(details)
						dat += " ([blood_traces[R]] units)"

					recent_fail = 0
				else
					if(recent_fail)
						crit_fail = 1
						reagents.clear_reagents()
						return
					else
						recent_fail = 1
		dat += ""
		user << dat
		reagents.clear_reagents()
	return

/obj/item/device/mass_spectrometer/adv
	name = "advanced mass-spectrometer"
	icon_state = "adv_spectrometer"
	details = 1
	origin_tech = "magnets=4;biotech=2"

/obj/item/device/slime_scanner
	name = "slime scanner"
	icon_state = "adv_spectrometer"
	item_state = "analyzer"
	origin_tech = "biotech=1"
	w_class = 2.0
	flags = CONDUCT
	throwforce = 0
	throw_speed = 3
	throw_range = 7
	m_amt = 30
	g_amt = 20

/obj/item/device/slime_scanner/attack(mob/living/M as mob, mob/living/user as mob)
	if (!isslime(M))
		user.show_message("This device can only scan slimes!", 1)
		return
	var/mob/living/carbon/slime/T = M
	user.show_message("Slime scan results:", 1)
	user.show_message(text("[T.colour] [] slime", T.is_adult ? "adult" : "baby"), 1)
	user.show_message(text("Nutrition: [T.nutrition]/[]", T.get_max_nutrition()), 1)
	if (T.nutrition < T.get_starve_nutrition())
		user.show_message("Warning: slime is starving!", 1)
	else if (T.nutrition < T.get_hunger_nutrition())
		user.show_message("Warning: slime is hungry", 1)
	user.show_message("Electric change strength: [T.powerlevel]", 1)
	user.show_message("Health: [T.health]", 1)
	if (T.slime_mutation[4] == T.colour)
		user.show_message("This slime does not evolve any further.", 1)
	else
		if (T.slime_mutation[3] == T.slime_mutation[4])
			if (T.slime_mutation[2] == T.slime_mutation[1])
				user.show_message("Possible mutation: [T.slime_mutation[3]]", 1)
				user.show_message("Genetic destability: [T.mutation_chance/2]% chance of mutation on splitting", 1)
			else
				user.show_message("Possible mutations: [T.slime_mutation[1]], [T.slime_mutation[2]], [T.slime_mutation[3]] (x2)", 1)
				user.show_message("Genetic destability: [T.mutation_chance]% chance of mutation on splitting", 1)
		else
			user.show_message("Possible mutations: [T.slime_mutation[1]], [T.slime_mutation[2]], [T.slime_mutation[3]], [T.slime_mutation[4]]", 1)
			user.show_message("Genetic destability: [T.mutation_chance]% chance of mutation on splitting", 1)
	if (T.cores > 1)
		user.show_message("Anomalious slime core amount detected", 1)
	user.show_message("Growth progress: [T.amount_grown]/10", 1)


code:
/obj/item/device/sensor_device
	name = "handheld crew monitor" //Thanks to Gun Hog for the name!
	desc = "A miniature machine that tracks suit sensors across the station."
	icon = 'icons/obj/device.dmi'
	icon_state = "scanner"
	w_class = 2.0
	slot_flags = SLOT_BELT
	origin_tech = "programming=3;materials=3;magnets=3"

/obj/item/device/sensor_device/attack_self(mob/user as mob)
	crewmonitor(user,src) //Proc already exists, just had to call it