code:
/obj/item/device/chameleon
	name = "chameleon-projector"
	icon_state = "shield0"
	flags = CONDUCT
	slot_flags = SLOT_BELT
	item_state = "electronic"
	throwforce = 5
	throw_speed = 3
	throw_range = 5
	w_class = 2
	origin_tech = "syndicate=4;magnets=4"
	var/can_use = 1
	var/obj/effect/dummy/chameleon/active_dummy = null
	var/saved_appearance = null

/obj/item/device/chameleon/New()
	..()
	var/obj/item/weapon/cigbutt/butt = /obj/item/weapon/cigbutt
	saved_appearance = initial(butt.appearance)

/obj/item/device/chameleon/dropped()
	..()
	disrupt()

/obj/item/device/chameleon/equipped()
	disrupt()

/obj/item/device/chameleon/attack_self()
	toggle()

/obj/item/device/chameleon/afterattack(atom/target, mob/user , proximity)
	if(!proximity) return
	if(!active_dummy)
		if(istype(target,/obj/item) && !istype(target, /obj/item/weapon/disk/nuclear))
			playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1, -6)
			user << "Scanned [target]."
			var/obj/temp = new/obj()
			temp.appearance = target.appearance
			temp.layer = initial(target.layer) // scanning things in your inventory
			saved_appearance = temp.appearance

/obj/item/device/chameleon/proc/toggle()
	if(!can_use || !saved_appearance) return
	if(active_dummy)
		eject_all()
		playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6)
		qdel(active_dummy)
		active_dummy = null
		usr << "You deactivate \the [src]."
		PoolOrNew(/obj/effect/overlay/temp/emp/pulse, get_turf(src))
	else
		playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6)
		var/obj/effect/dummy/chameleon/C = new/obj/effect/dummy/chameleon(usr.loc)
		C.activate(usr, saved_appearance, src)
		usr << "You activate \the [src]."
		PoolOrNew(/obj/effect/overlay/temp/emp/pulse, get_turf(src))

/obj/item/device/chameleon/proc/disrupt(delete_dummy = 1)
	if(active_dummy)
		for(var/mob/M in active_dummy)
			M << "Your chameleon-projector deactivates."
		var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread
		spark_system.set_up(5, 0, src)
		spark_system.attach(src)
		spark_system.start()
		eject_all()
		if(delete_dummy)
			qdel(active_dummy)
		active_dummy = null
		can_use = 0
		spawn(50) can_use = 1

/obj/item/device/chameleon/proc/eject_all()
	for(var/atom/movable/A in active_dummy)
		A.loc = active_dummy.loc
		if(ismob(A))
			var/mob/M = A
			M.reset_perspective(null)

/obj/effect/dummy/chameleon
	name = ""
	desc = ""
	density = 0
	var/can_move = 1
	var/obj/item/device/chameleon/master = null

/obj/effect/dummy/chameleon/proc/activate(mob/M, saved_appearance, obj/item/device/chameleon/C)
	appearance = saved_appearance
	M.loc = src
	master = C
	master.active_dummy = src

/obj/effect/dummy/chameleon/attackby()
	master.disrupt()

/obj/effect/dummy/chameleon/attack_hand()
	master.disrupt()

/obj/effect/dummy/chameleon/attack_animal()
	master.disrupt()

/obj/effect/dummy/chameleon/attack_slime()
	master.disrupt()

/obj/effect/dummy/chameleon/attack_alien()
	master.disrupt()

/obj/effect/dummy/chameleon/ex_act() //ok now THATS some serious protection against explosions right here
	master.disrupt()

/obj/effect/dummy/chameleon/bullet_act()
	..()
	master.disrupt()

/obj/effect/dummy/chameleon/relaymove(mob/user, direction)
	if(istype(loc, /turf/open/space) || !direction)
		return //No magical space movement!

	if(can_move)
		can_move = 0
		switch(user.bodytemperature)
			if(300 to INFINITY)
				spawn(10) can_move = 1
			if(295 to 300)
				spawn(13) can_move = 1
			if(280 to 295)
				spawn(16) can_move = 1
			if(260 to 280)
				spawn(20) can_move = 1
			else
				spawn(25) can_move = 1
		step(src, direction)
	return

/obj/effect/dummy/chameleon/Destroy()
	master.disrupt(0)
	return ..()


code:
/obj/item/device/doorCharge
	name = "airlock charge"
	desc = null //Different examine for traitors
	item_state = "electronic"
	icon_state = "doorCharge"
	w_class = 2
	throw_range = 4
	throw_speed = 1
	force = 3
	attack_verb = list("blown up", "exploded", "detonated")
	materials = list(MAT_METAL=50, MAT_GLASS=30)
	origin_tech = "syndicate=3;combat=2"

/obj/item/device/doorCharge/ex_act(severity, target)
	switch(severity)
		if(1)
			visible_message("[src] detonates!")
			explosion(src.loc,0,2,1,flame_range = 4)
			qdel(src)
		if(2)
			if(prob(50))
				ex_act(1)
		if(3)
			if(prob(25))
				ex_act(1)

/obj/item/device/doorCharge/examine(mob/user)
	..()
	if(user.mind in ticker.mode.traitors) //No nuke ops because the device is excluded from nuclear
		user << "A small explosive device that can be used to sabotage airlocks to cause an explosion upon opening. To apply, remove the airlock's maintenance panel and place it within."
	else
		user << "A small, suspicious object that feels lukewarm when held."

license: mit


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
	materials = list(MAT_METAL=50, MAT_GLASS=20)
	actions_types = list(/datum/action/item_action/toggle_light)
	var/on = 0
	var/brightness_on = 4 //luminosity when on

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

/obj/item/device/flashlight/proc/update_brightness(mob/user = null)
	if(on)
		icon_state = "[initial(icon_state)]-on"
		if(loc == user)
			user.AddLuminosity(brightness_on)
		else if(isturf(loc))
			SetLuminosity(brightness_on)
	else
		icon_state = initial(icon_state)
		if(loc == user)
			user.AddLuminosity(-brightness_on)
		else if(isturf(loc))
			SetLuminosity(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)
	for(var/X in actions)
		var/datum/action/A = X
		A.UpdateButtonIcon()
	return 1

/obj/item/device/flashlight/attack(mob/living/carbon/human/M, mob/living/carbon/human/user)
	add_fingerprint(user)
	if(on && user.zone_selected == "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_cover & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) || (H.glasses && H.glasses.flags_cover & GLASSESCOVERSEYES)))
			user << "You're going to need to remove that [(H.head && H.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask": "glasses"] first."
			return

		if(M == user)	//they're using it on themselves
			if(M.flash_eyes(visual = 1))
				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.")
		else
			user.visible_message("[user] directs [src] to [M]'s eyes.", \
								 "You direct [src] to [M]'s eyes.")
			var/mob/living/carbon/C = M
			if(istype(C))
				if(C.stat == DEAD || (C.disabilities & BLIND)) //mob is dead or fully blind
					user << "[C] pupils don't react to the light!"
				else if(C.dna.check_mutation(XRAY))	//mob has X-RAY vision
					user << "[C] pupils give an eerie glow!"
				else //they're okay!
					if(C.flash_eyes(visual = 1))
						user << "[C]'s pupils narrow."
	else
		return ..()

/obj/item/device/flashlight/pickup(mob/user)
	..()
	if(on)
		user.AddLuminosity(brightness_on)
		SetLuminosity(0)

/obj/item/device/flashlight/dropped(mob/user)
	..()
	if(on)
		user.AddLuminosity(-brightness_on)
		SetLuminosity(brightness_on)

/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(tturf,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
	materials = list()
	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
	brightness_on = 7 // Pretty bright.
	icon_state = "flare"
	item_state = "flare"
	actions_types = list()
	var/fuel = 0
	var/on_damage = 7
	var/produce_heat = 1500
	heat = 1000

/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(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/is_hot()
	return on * heat

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

/obj/item/device/flashlight/lantern
	name = "lantern"
	icon_state = "lantern"
	item_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
	materials = list()
	brightness_on = 6 //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)
		return ..()

/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, mob/living/user)
	if(on && user.zone_selected == "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(!proximity) return
	if(istype(A, /obj/item/weapon/storage/) && A.loc == user)
		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", "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:
#define RAD_LEVEL_NORMAL 10
#define RAD_LEVEL_MODERATE 30
#define RAD_LEVEL_HIGH 75
#define RAD_LEVEL_VERY_HIGH 125
#define RAD_LEVEL_CRITICAL 200

/obj/item/device/geiger_counter //DISCLAIMER: I know nothing about how real-life Geiger counters work. This will not be realistic. ~Xhuis
	name = "geiger counter"
	desc = "A handheld device used for detecting and measuring radiation pulses."
	icon_state = "geiger_off"
	item_state = "multitool"
	w_class = 2
	slot_flags = SLOT_BELT
	materials = list(MAT_METAL = 150, MAT_GLASS = 150)
	var/scanning = 0
	var/radiation_count = 0
	var/emagged = 0

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

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

/obj/item/device/geiger_counter/process()
	if(emagged)
		if(radiation_count < 20)
			radiation_count++
		return 0
	if(radiation_count > 0)
		radiation_count--
		update_icon()

/obj/item/device/geiger_counter/examine(mob/user)
	..()
	if(!scanning)
		return 1
	user << "Alt-click it to clear stored radiation levels."
	if(emagged)
		user << "The display seems to be incomprehensible."
		return 1
	switch(radiation_count)
		if(-INFINITY to RAD_LEVEL_NORMAL)
			user << "Ambient radiation level count reports that all is well."
		if(RAD_LEVEL_NORMAL + 1 to RAD_LEVEL_MODERATE)
			user << "Ambient radiation levels slightly above average."
		if(RAD_LEVEL_MODERATE + 1 to RAD_LEVEL_HIGH)
			user << "Ambient radiation levels above average."
		if(RAD_LEVEL_HIGH + 1 to RAD_LEVEL_VERY_HIGH)
			user << "Ambient radiation levels highly above average."
		if(RAD_LEVEL_VERY_HIGH + 1 to RAD_LEVEL_CRITICAL)
			user << "Ambient radiation levels nearing critical level."
		if(RAD_LEVEL_CRITICAL + 1 to INFINITY)
			user << "Ambient radiation levels above critical level!"

/obj/item/device/geiger_counter/update_icon()
	if(!scanning)
		icon_state = "geiger_off"
		return 1
	if(emagged)
		icon_state = "geiger_on_emag"
		return 1
	switch(radiation_count)
		if(-INFINITY to RAD_LEVEL_NORMAL)
			icon_state = "geiger_on_1"
		if(RAD_LEVEL_NORMAL + 1 to RAD_LEVEL_MODERATE)
			icon_state = "geiger_on_2"
		if(RAD_LEVEL_MODERATE + 1 to RAD_LEVEL_HIGH)
			icon_state = "geiger_on_3"
		if(RAD_LEVEL_HIGH + 1 to RAD_LEVEL_VERY_HIGH)
			icon_state = "geiger_on_4"
		if(RAD_LEVEL_VERY_HIGH + 1 to RAD_LEVEL_CRITICAL)
			icon_state = "geiger_on_4"
		if(RAD_LEVEL_CRITICAL + 1 to INFINITY)
			icon_state = "geiger_on_5"
	..()

/obj/item/device/geiger_counter/rad_act(amount)
	if(!amount && scanning)
		return 0
	if(emagged)
		amount = Clamp(amount, 0, 25) //Emagged geiger counters can only accept 25 radiation at a time
	radiation_count += amount
	if(isliving(loc))
		var/mob/living/M = loc
		if(!emagged)
			M << "\icon[src] RADIATION PULSE DETECTED."
			M << "\icon[src] Severity: [amount]"
		else
			M << "\icon[src] !@%$AT!(N P!LS! D/TEC?ED."
			M << "\icon[src] &!F2rity: <=[amount]#1"
	update_icon()

/obj/item/device/geiger_counter/attack_self(mob/user)
	scanning = !scanning
	update_icon()
	user << "\icon[src] You switch [scanning ? "on" : "off"] [src]."

/obj/item/device/geiger_counter/attack(mob/living/M, mob/user)
	if(user.a_intent == "help")
		if(!emagged)
			user.visible_message("[user] scans [M] with [src].", "You scan [M]'s radiation levels with [src]...")
			if(!M.radiation)
				user << "\icon[src] Radiation levels within normal boundaries."
				return 1
			else
				user << "\icon[src] Subject is irradiated. Radiation levels: [M.radiation]."
				return 1
		else
			user.visible_message("[user] scans [M] with [src].", "You project [src]'s stored radiation into [M]'s body!")
			M.rad_act(radiation_count)
			radiation_count = 0
		return 1
	..()

/obj/item/device/geiger_counter/attackby(obj/item/I, mob/user, params)
	if(istype(I, /obj/item/weapon/screwdriver) && emagged)
		if(scanning)
			user << "Turn off [src] before you perform this action!"
			return 0
		user.visible_message("[user] unscrews [src]'s maintenance panel and begins fiddling with its innards...", "You begin resetting [src]...")
		playsound(user, 'sound/items/Screwdriver.ogg', 50, 1)
		if(!do_after(user, 40/I.toolspeed, target = user))
			return 0
		user.visible_message("[user] refastens [src]'s maintenance panel!", "You reset [src] to its factory settings!")
		playsound(user, 'sound/items/Screwdriver2.ogg', 50, 1)
		emagged = 0
		radiation_count = 0
		update_icon()
		return 1
	..()

/obj/item/device/geiger_counter/AltClick(mob/living/user)
	if(!istype(user) || user.incapacitated())
		return ..()
	if(!scanning)
		usr << "[src] must be on to reset its radiation level!"
		return 0
	radiation_count = 0
	usr << "You flush [src]'s radiation counts, resetting it to normal."
	update_icon()

/obj/item/device/geiger_counter/emag_act(mob/user)
	if(!emagged)
		if(scanning)
			user << "Turn off [src] before you perform this action!"
			return 0
		user << "You override [src]'s radiation storing protocols. It will now generate small doses of radiation, and stored rads are now projected into creatures you scan."
		emagged = 1

#undef RAD_LEVEL_NORMAL
#undef RAD_LEVEL_MODERATE
#undef RAD_LEVEL_HIGH
#undef RAD_LEVEL_VERY_HIGH
#undef RAD_LEVEL_CRITICAL


code:
//copy pasta of the space piano, don't hurt me -Pete
/obj/item/device/instrument
	name = "generic instrument"
	burn_state = FLAMMABLE
	burntime = 20
	var/datum/song/handheld/song
	var/instrumentId = "generic"
	var/instrumentExt = "ogg"

/obj/item/device/instrument/New()
	song = new(instrumentId, src)
	song.instrumentExt = instrumentExt

/obj/item/device/instrument/Destroy()
	qdel(song)
	song = null
	return ..()

/obj/item/device/instrument/suicide_act(mob/user)
	user.visible_message("[user] begins to play 'Gloomy Sunday'! It looks like \he's trying to commit suicide..")
	return (BRUTELOSS)

/obj/item/device/instrument/initialize()
	song.tempo = song.sanitize_tempo(song.tempo) // tick_lag isn't set when the map is loaded
	..()

/obj/item/device/instrument/attack_self(mob/user)
	if(!user.IsAdvancedToolUser())
		user << "You don't have the dexterity to do this!"
		return 1
	interact(user)

/obj/item/device/instrument/interact(mob/user)
	if(!user)
		return

	if(!isliving(user) || user.stat || user.restrained() || user.lying)
		return

	user.set_machine(src)
	song.interact(user)

/obj/item/device/instrument/violin
	name = "space violin"
	desc = "A wooden musical instrument with four strings and a bow. \"The devil went down to space, he was looking for an assistant to grief.\""
	icon = 'icons/obj/musician.dmi'
	icon_state = "violin"
	item_state = "violin"
	force = 10
	hitsound = "swing_hit"
	instrumentId = "violin"

/obj/item/device/instrument/guitar
	name = "guitar"
	desc = "It's made of wood and has bronze strings."
	icon = 'icons/obj/musician.dmi'
	icon_state = "guitar"
	item_state = "guitar"
	force = 10
	attack_verb = list("played metal on", "serenaded", "crashed", "smashed")
	hitsound = 'sound/weapons/stringsmash.ogg'
	instrumentId = "guitar"


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
	materials = list(MAT_METAL=500, MAT_GLASS=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)
			if(!user.unEquip(W))
				return
			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(atom/target, mob/living/user, flag, params)
	if(flag)	//we're placing the object on a table or in backpack
		return
	laser_act(target, user, params)

/obj/item/device/laser_pointer/proc/laser_act(atom/target, mob/living/user, params)
	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.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_selected == "eyes")
			add_logs(user, C, "shone in the eyes", src)

			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."
				if(C.weakeyes)
					C.Stun(1)
			else
				outmsg = "You fail to blind [C] by shining [src] at their eyes!"

	//robots
	else if(isrobot(target))
		var/mob/living/silicon/S = target
		//20% chance to actually hit the sensors
		if(prob(effectchance * diode.rating))
			S.flash_eyes(affect_silicon = 1)
			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", src)
		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", src)
		else
			outmsg = "You miss the lens of [C] with [src]!"

	//laser pointer image
	icon_state = "pointer_[pointer_icon_state]"
	var/list/showto = list()
	for(var/mob/M in viewers(7,targloc))
		if(M.client)
			showto.Add(M.client)
	var/image/I = image('icons/obj/projectiles.dmi',targloc,pointer_icon_state,10)
	var/list/click_params = params2list(params)
	if(click_params)
		if(click_params["icon-x"])
			I.pixel_x = (text2num(click_params["icon-x"]) - 16)
		if(click_params["icon-y"])
			I.pixel_y = (text2num(click_params["icon-y"]) - 16)
	else
		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 << "The [src]'s battery is overused, 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
			..()


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)
				if(!user.unEquip(W))
					return
				AddUses(1)
				user << "You insert the [L.name] into the [src.name]. You have [uses] lights remaining."
				qdel(L)
				return
		else
			user << "You need a working light!"
			return

	if(istype(W, /obj/item/weapon/storage))
		var/obj/item/weapon/storage/S = W
		var/found_good_light = 0
		var/replaced_something = 0

		for(var/obj/item/I in S.contents)
			if(istype(I,/obj/item/weapon/light))
				var/obj/item/weapon/light/L = I
				if(L.status == LIGHT_OK)
					found_good_light = 1
					if(src.uses < max_uses)
						qdel(L)
						AddUses(1)
						replaced_something = 1
					else
						break

		if(!found_good_light)
			user << "\The [S] contains no useable lights!"
			return

		if(!replaced_something && src.uses == max_uses)
			user << "\The [src] is full!"
			return

		user << "You fill \the [src] with lights from \the [S]. You have [uses] lights remaining."

/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(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(amount = 1)
	uses = min(max(uses + amount, 0), max_uses)

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

/obj/item/device/lightreplacer/proc/ReplaceLight(obj/machinery/light/target, 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 = target.brightness
				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 = L2.brightness
			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(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:
/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/voicespan = "command_headset" // sic
	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)
	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(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(!user.can_speak(message))
		user << "You find yourself unable to speak at all!"
		return

	if ((src.loc == user && user.stat == 0))
		if(emagged)
			if(insults)
				user.audible_message("[user.GetVoice()] broadcasts, \"[pick(insultmsg)]\"")
				insults--
			else
				user << "*BZZZZzzzzzt*"
		else
			user.audible_message("[user.GetVoice()] broadcasts, \"[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"

/obj/item/device/megaphone/clown
	name = "clown's megaphone"
	desc = "Something that should not exist."
	icon_state = "megaphone-clown"
	voicespan = "clown"


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
	w_class = 2
	throwforce = 0
	throw_range = 7
	throw_speed = 3
	materials = list(MAT_METAL=50, MAT_GLASS=20)
	origin_tech = "magnets=1;engineering=1"
	var/obj/machinery/buffer // simple machine buffer for device linkage
	hitsound = 'sound/weapons/tap.ogg'
	toolspeed = 1

// 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
	return ..()

/obj/item/device/multitool/ai_detect/process()
	if(track_delay > world.time)
		return

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

	for(var/mob/living/silicon/ai/AI in ai_list)
		if(AI.cameraFollow == src)
			found_eye = 1
			break

	if(!found_eye && 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

/obj/item/device/multitool/cyborg
	name = "multitool"
	desc = "Optimised and stripped-down version of a regular multitool."
	icon = 'icons/obj/items_cyborg.dmi'
	toolspeed = 2


code:
/obj/item/device/paicard
	name = "personal AI device"
	icon = 'icons/obj/aicards.dmi'
	icon_state = "pai"
	item_state = "electronic"
	w_class = 2
	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)
	return ..()

/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.is_cut(WIRE_TX)) ? "Disabled" : "Enabled"]
"
			dat += "Receive: [(radio.wires.is_cut(WIRE_RX)) ? "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 give a lot of 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/wire = text2num(href_list["wires"])
			if(radio)
				radio.wires.cut(wire)
		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(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.\"", "[src] bleeps electronically.")

/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"

	materials = list(MAT_METAL=5000, MAT_GLASS=2000)

/obj/item/device/pipe_painter/afterattack(atom/A, mob/user, 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)
	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
	flags = CONDUCT
	throwforce = 5
	throw_speed = 1
	throw_range = 2
	materials = list(MAT_METAL=750)
	origin_tech = "powerstorage=3;syndicate=5"
	var/drain_rate = 1600000	// amount of power to drain per tick
	var/power_drained = 0 		// has drained this much power
	var/max_power = 1e10		// 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()
	SetLuminosity(0)

/obj/item/device/powersink/attackby(obj/item/I, 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 << "This device must be placed over an exposed, powered cable node!"
				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 << "This device must be placed over an exposed, powered cable node!"
		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(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_admin(user)](?) (FLW) 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)
		SetLuminosity(5)

		// 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.98)
		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, 4,8,16,32)
		qdel(src)


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

/obj/item/device/radio/beacon/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
	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

/*
//Probably a better way of doing this, I'm lazy.
/obj/item/device/radio/beacon/bacon/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
	materials = list(MAT_METAL=10000, MAT_GLASS=2500)
	var/on = 1
	var/code = 2
	var/frequency = 1449
	var/shock_cooldown = 0

/obj/item/device/electropack/suicide_act(mob/user)
	user.visible_message("[user] hooks \himself to the electropack and spams the trigger! It looks like \he's trying to commit suicide..")
	return (FIRELOSS)

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

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

/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, mob/user, 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)
	//..()
	var/mob/living/carbon/C = usr
	if(usr.stat || usr.restrained() || C.back == src)
		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"])
			SSradio.remove_object(src, frequency)
			frequency = sanitize_frequency(frequency + text2num(href_list["freq"]))
			SSradio.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_system/spark_spread/s = new /datum/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, mob/user, 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 :y."
	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)

/obj/item/device/encryptionkey/secbot
	channels = list("AI Private"=1,"Security"=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"
	materials = list(MAT_METAL=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

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

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

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

/obj/item/device/radio/headset/receive_range(freq, level, 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/alt/leader
	name = "team leader headset"
	command = TRUE

/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
	command = TRUE

/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, mob/user, 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)
				SSradio.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)
			if(!user.unEquip(W))
				return
			W.loc = src
			keyslot = W

		else
			if(!user.unEquip(W))
				return
			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

		if (keyslot2.centcom)
			centcom = 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
	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
	return ..()

/obj/item/device/radio/intercom/attack_ai(mob/user)
	interact(user)

/obj/item/device/radio/intercom/attack_hand(mob/user)
	interact(user)

/obj/item/device/radio/intercom/interact(mob/user)
	..()
	ui_interact(user, state = default_state)

/obj/item/device/radio/intercom/receive_range(freq, level)
	if(!on)
		return -1
	if(wires.is_cut(WIRE_RX))
		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, list/spans)
	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

		var/area/A = get_area_master(src)
		if(!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/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_switchable = 0
	var/subspace_transmission = 0
	var/syndie = 0//Holder to see if it's a syndicate encrpyed radio
	var/centcom = 0//Bleh, more dirty booleans
	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
	materials = list(MAT_METAL=75, MAT_GLASS=25)

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

	var/command = FALSE //If we are speaking into a command headset, our text can be BOLD
	var/use_command = FALSE

/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 /datum/wires/radio(src)
	if(prison_radio)
		wires.cut(WIRE_TX) // OH GOD WHY
	secure_radio_connections = new
	..()
	if(SSradio)
		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
	patch_link = null
	keyslot = null
	return ..()

/obj/item/device/radio/initialize()
	frequency = sanitize_frequency(frequency, freerange)
	set_frequency(frequency)

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

/obj/item/device/radio/interact(mob/user)
	if (..())
		return
	if(b_stat && !istype(user, /mob/living/silicon/ai))
		wires.interact(user)
	else
		ui_interact(user)

/obj/item/device/radio/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
										datum/tgui/master_ui = null, datum/ui_state/state = inventory_state)
	ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
	if(!ui)
		ui = new(user, src, ui_key, "radio", name, 370, 220 + channels.len * 22, master_ui, state)
		ui.open()

/obj/item/device/radio/ui_data(mob/user)
	var/list/data = list()

	data["broadcasting"] = broadcasting
	data["listening"] = listening
	data["frequency"] = frequency
	data["minFrequency"] = freerange ? MIN_FREE_FREQ : MIN_FREQ
	data["maxFrequency"] = freerange ? MAX_FREE_FREQ : MAX_FREQ
	data["freqlock"] = freqlock
	data["channels"] = list()
	for(var/channel in channels)
		data["channels"][channel] = channels[channel] & FREQ_LISTENING
	data["command"] = command
	data["useCommand"] = use_command
	data["subspace"] = subspace_transmission
	data["subspaceSwitchable"] = subspace_switchable
	data["headset"] = istype(src, /obj/item/device/radio/headset)

	return data

/obj/item/device/radio/ui_act(action, params, datum/tgui/ui)
	if(..())
		return
	switch(action)
		if("frequency")
			if(freqlock)
				return
			var/tune = params["tune"]
			var/adjust = text2num(params["adjust"])
			if(tune == "input")
				var/min = format_frequency(freerange ? MIN_FREE_FREQ : MIN_FREQ)
				var/max = format_frequency(freerange ? MAX_FREE_FREQ : MAX_FREQ)
				tune = input("Tune frequency ([min]-[max]):", name, format_frequency(frequency)) as null|num
				if(!isnull(tune) && !..())
					. = TRUE
			else if(adjust)
				tune = frequency + adjust * 10
				. = TRUE
			else if(text2num(tune) != null)
				tune = tune * 10
				. = TRUE
			if(.)
				frequency = sanitize_frequency(tune, freerange)
				set_frequency(frequency)
				if(frequency == traitor_frequency && hidden_uplink)
					hidden_uplink.interact(usr)
					ui.close()
		if("listen")
			listening = !listening
			. = TRUE
		if("broadcast")
			broadcasting = !broadcasting
			. = TRUE
		if("channel")
			var/channel = params["channel"]
			if(!(channel in channels))
				return
			if(channels[channel] & FREQ_LISTENING)
				channels[channel] &= ~FREQ_LISTENING
			else
				channels[channel] |= FREQ_LISTENING
			. = TRUE
		if("command")
			use_command = !use_command
			. = TRUE
		if("subspace")
			if(subspace_switchable)
				subspace_transmission = !subspace_transmission
				if(!subspace_transmission)
					channels = list()
				else
					recalculateChannels()
				. = TRUE

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

	if(wires.is_cut(WIRE_TX))
		return

	if(!M.IsVocal())
		return

	if(use_command)
		spans |= SPAN_COMMAND

	/* 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 SSradio. 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))
		var/mob/living/silicon/robot/B = M
		jobname = "[B.designation] Cyborg"

	// --- 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,
			"spans" = spans,
			"verb_say" = M.verb_say,
			"verb_ask" = M.verb_ask,
			"verb_exclaim" = M.verb_exclaim,
			"verb_yell" = M.verb_yell
			)
		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, spans,
				  verb_say, verb_ask, verb_exclaim, verb_yell)
		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.
			"spans" = spans, //the span classes of this message.
			"verb_say" = M.verb_say, //the verb used when talking normally
			"verb_ask" = M.verb_ask, //the verb used when asking
			"verb_exclaim" = M.verb_exclaim, //the verb used when exclaiming
			"verb_yell" = M.verb_yell //the verb used when yelling
			)
		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,
		"languages" = languages,
		"spans" = spans,
		"verb_say" = M.verb_say,
		"verb_ask" = M.verb_ask,
		"verb_exclaim" = M.verb_exclaim,
		"verb_yell" = M.verb_yell
		)
	signal.frequency = freqnum // 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, spans,
						  verb_say, verb_ask, verb_exclaim, verb_yell)

/obj/item/device/radio/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
	if(radio_freq)
		return
	if(broadcasting)
		if(get_dist(src, speaker) <= canhear_range)
			talk_into(speaker, raw_message, , spans)
/*
/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 (wires.is_cut(WIRE_RX))
		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))
			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, mob/user, params)
	..()
	if(istype(W, /obj/item/weapon/screwdriver))
		b_stat = !b_stat
		if(b_stat)
			user << "The radio can now be attached and modified!"
		else
			user << "The radio can no longer be modified or attached!"
	add_fingerprint(user)

/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
	name = "cyborg radio"
	subspace_switchable = 1

/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, mob/user, params)
	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)
				SSradio.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)
			if(!user.unEquip(W))
				return
			W.loc = src
			keyslot = W

		recalculateChannels()

	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.