code:
//##############################################
//################### NEWSCASTERS BE HERE! ####
//###-Agouri###################################

/datum/feed_comment
	var/author = ""
	var/body = ""
	var/time_stamp = ""

/datum/feed_message
	var/author =""
	var/body =""
	//var/parent_channel
	var/backup_body =""
	var/backup_author =""
	var/is_admin_message = 0
	var/icon/img = null
	var/time_stamp = ""
	var/list/datum/feed_comment/comments = list()
	var/locked = 0
	var/caption = ""

/datum/feed_channel
	var/channel_name=""
	var/list/datum/feed_message/messages = list()
	//var/message_count = 0
	var/locked=0
	var/author=""
	var/backup_author=""
	var/censored=0
	var/is_admin_channel=0
	//var/page = null //For newspapers

/datum/feed_message/proc/clear()
	src.author = ""
	src.body = ""
	src.backup_body = ""
	src.backup_author = ""
	src.img = null
	src.locked = 0

/datum/feed_channel/proc/clear()
	src.channel_name = ""
	src.messages = list()
	src.locked = 0
	src.author = ""
	src.backup_author = ""
	src.censored = 0
	src.is_admin_channel = 0

/datum/feed_network
	var/list/datum/feed_channel/network_channels = list()
	var/datum/feed_message/wanted_issue

/datum/feed_network/New()
	CreateFeedChannel("Station Announcements", "SS13", 1)

/datum/feed_network/proc/CreateFeedChannel(var/channel_name, var/author, var/locked, var/adminChannel = 0)
	var/datum/feed_channel/newChannel = new /datum/feed_channel
	newChannel.channel_name = channel_name
	newChannel.author = author
	newChannel.locked = locked
	newChannel.is_admin_channel = adminChannel
	network_channels += newChannel

/datum/feed_network/proc/SubmitArticle(var/msg, var/author, var/channel_name, var/obj/item/weapon/photo/photo, var/adminMessage = 0, var/allow_comments = 1)
	var/datum/feed_message/newMsg = new /datum/feed_message
	newMsg.author = author
	newMsg.body = msg
	newMsg.time_stamp = "[worldtime2text()]"
	newMsg.is_admin_message = adminMessage
	newMsg.locked = !allow_comments
	if(photo)
		newMsg.img = photo.img
		newMsg.caption = photo.scribble
	for(var/datum/feed_channel/FC in network_channels)
		if(FC.channel_name == channel_name)
			FC.messages += newMsg                  //Adding message to the network's appropriate feed_channel
			break
	for(var/obj/machinery/newscaster/NEWSCASTER in allCasters)
		NEWSCASTER.newsAlert(channel_name)

var/datum/feed_network/news_network = new /datum/feed_network     //The global news-network, which is coincidentally a global list.

var/list/obj/machinery/newscaster/allCasters = list() //Global list that will contain reference to all newscasters in existence.

/obj/item/newscaster_frame
	name = "newscaster frame"
	desc = "Used to build newscasters, just secure to the wall."
	icon_state = "newscaster"
	item_state = "syringe_kit"
	m_amt = 14000
	g_amt = 8000

/obj/item/newscaster_frame/proc/try_build(turf/on_wall)
	if (get_dist(on_wall,usr)>1)
		return
	var/ndir = get_dir(usr,on_wall)
	if (!(ndir in cardinal))
		return
	var/turf/loc = get_turf(usr)
	var/area/A = loc.loc
	if (!istype(loc, /turf/simulated/floor))
		usr << "Newscaster cannot be placed on this spot."
		return
	if (A.requires_power == 0 || A.name == "Space")
		usr << "Newscaster cannot be placed in this area."
		return
	for(var/obj/machinery/newscaster/T in loc)
		usr << "There is another newscaster here."
		return
	var/obj/machinery/newscaster/N = new(loc)
	N.pixel_y -= (loc.y - on_wall.y) * 32
	N.pixel_x -= (loc.x - on_wall.x) * 32
	qdel(src)

/obj/machinery/newscaster
	name = "newscaster"
	desc = "A standard Nanotrasen-licensed newsfeed handler for use in commercial space stations. All the news you absolutely have no use for, in one place!"
	icon = 'icons/obj/terminals.dmi'
	icon_state = "newscaster_normal"
	var/isbroken = 0  //1 if someone banged it with something heavy
	var/ispowered = 1 //starts powered, changes with power_change()
	//var/list/datum/feed_channel/channel_list = list() //This list will contain the names of the feed channels. Each name will refer to a data region where the messages of the feed channels are stored.
	//OBSOLETE: We're now using a global news network
	var/screen = 0
		// 0 = welcome screen - main menu
		// 1 = view feed channels
		// 2 = create feed channel
		// 3 = create feed story
		// 4 = feed story submited sucessfully
		// 5 = feed channel created successfully
		// 6 = ERROR: Cannot create feed story
		// 7 = ERROR: Cannot create feed channel
		// 8 = print newspaper
		// 9 = viewing channel feeds
		// 10 = censor feed story
		// 11 = censor feed channel
		//Holy shit this is outdated, made this when I was still starting newscasters :3
	var/paper_remaining = 0
	var/securityCaster = 0
		// 0 = Caster cannot be used to issue wanted posters
		// 1 = the opposite
	var/unit_no = 0 //Each newscaster has a unit number
	//var/datum/feed_message/wanted //We're gonna use a feed_message to store data of the wanted person because fields are similar
	//var/wanted_issue = 0          //OBSOLETE
		// 0 = there's no WANTED issued, we don't need a special icon_state
		// 1 = Guess what.
	var/alert_delay = 500
	var/alert = 0
		// 0 = there hasn't been a news/wanted update in the last alert_delay
		// 1 = there has
	var/scanned_user = "Unknown" //Will contain the name of the person who currently uses the newscaster
	var/msg = "";                //Feed message
	var/obj/item/weapon/photo/photo = null
	var/channel_name = ""; //the feed channel which will be receiving the feed, or being created
	var/c_locked=0;        //Will our new channel be locked to public submissions?
	var/hitstaken = 0      //Death at 3 hits from an item with force>=15
	var/datum/feed_channel/viewing_channel = null
	var/allow_comments = 1
	light_range = 0
	anchored = 1

/obj/machinery/newscaster/security_unit                   //Security unit
	name = "security newscaster"
	securityCaster = 1

/obj/machinery/newscaster/New()
	allCasters += src
	src.paper_remaining = 15
	for(var/obj/machinery/newscaster/NEWSCASTER in allCasters)
		src.unit_no++
	src.update_icon() //for any custom ones on the map...
	..()                                //I just realised the newscasters weren't in the global machines list. The superconstructor call will tend to that

/obj/machinery/newscaster/Destroy()
	allCasters -= src
	viewing_channel = null
	photo = null
	..()

/obj/machinery/newscaster/update_icon()
	if(!ispowered || isbroken)
		icon_state = "newscaster_off"
		if(isbroken) //If the thing is smashed, add crack overlay on top of the unpowered sprite.
			src.overlays.Cut()
			src.overlays += image(src.icon, "crack3")
		return

	src.overlays.Cut() //reset overlays

	if(news_network.wanted_issue) //wanted icon state, there can be no overlays on it as it's a priority message
		icon_state = "newscaster_wanted"
		return

	if(alert) //new message alert overlay
		src.overlays += "newscaster_alert"

	if(hitstaken > 0) //Cosmetic damage overlay
		src.overlays += image(src.icon, "crack[hitstaken]")

	icon_state = "newscaster_normal"
	return

/obj/machinery/newscaster/power_change()
	if(isbroken) //Broken shit can't be powered.
		return
	if( src.powered() )
		src.ispowered = 1
		stat &= ~NOPOWER
		src.update_icon()
	else
		spawn(rand(0, 15))
			src.ispowered = 0
			stat |= NOPOWER
			src.update_icon()

/obj/machinery/newscaster/ex_act(severity, target)
	switch(severity)
		if(1.0)
			qdel(src)
			return
		if(2.0)
			src.isbroken=1
			if(prob(50))
				qdel(src)
			else
				src.update_icon() //can't place it above the return and outside the if-else. or we might get runtimes of null.update_icon() if(prob(50)) goes in.
			return
		else
			if(prob(50))
				src.isbroken=1
			src.update_icon()
			return
	return

/obj/machinery/newscaster/attack_ai(mob/user as mob)
	return src.attack_hand(user)

/obj/machinery/newscaster/attack_hand(mob/user as mob)            //########### THE MAIN BEEF IS HERE! And in the proc below this...############
	if(!src.ispowered || src.isbroken)
		return
	if(istype(user, /mob/living/carbon/human) || istype(user,/mob/living/silicon) )
		var/mob/living/human_or_robot_user = user
		var/dat

		src.scan_user(human_or_robot_user) //Newscaster scans you

		switch(screen)
			if(0)
				dat += "Welcome to Newscasting Unit #[src.unit_no].
 Interface & News networks Operational."
				dat += "
Property of Nanotransen Inc"
				if(news_network.wanted_issue)
					dat+= "
Read Wanted Issue"
				dat+= "

Create Feed Channel"
				dat+= "
View Feed Channels"
				dat+= "
Submit new Feed story"
				dat+= "
Print newspaper"
				dat+= "
Re-scan User"
				dat+= "

Exit"
				if(src.securityCaster)
					var/wanted_already = 0
					if(news_network.wanted_issue)
						wanted_already = 1

					dat+="
Feed Security functions:
"
					dat+="
[(wanted_already) ? ("Manage") : ("Publish")] \"Wanted\" Issue"
					dat+="
Censor Feed Stories"
					dat+="
Mark Feed Channel with Nanotrasen D-Notice"
				dat+="

The newscaster recognises you as: [src.scanned_user]"
			if(1)
				dat+= "Station Feed Channels
"
				if( isemptylist(news_network.network_channels) )
					dat+="No active channels found..."
				else
					for(var/datum/feed_channel/CHANNEL in news_network.network_channels)
						if(CHANNEL.is_admin_channel)
							dat+="[CHANNEL.channel_name]
"
						else
							dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
"
					/*for(var/datum/feed_channel/CHANNEL in src.channel_list)
						dat+="[CHANNEL.channel_name]:
\[created by: [CHANNEL.author]\]

"
						if( isemptylist(CHANNEL.messages) )
							dat+="No feed messages found in channel...

"
						else
							for(var/datum/feed_message/MESSAGE in CHANNEL.messages)
								dat+="-[MESSAGE.body]
\[Story by [MESSAGE.author]\]
"*/

				dat+="

Refresh"
				dat+="
Back"
			if(2)
				dat+="Creating new Feed Channel..."
				dat+="
Channel Name: [src.channel_name]
"
				dat+="Channel Author: [src.scanned_user]
"
				dat+="Will Accept Public Feeds: [(src.c_locked) ? ("NO") : ("YES")]

"
				dat+="
Submit

Cancel
"
			if(3)
				dat+="Creating new Feed Message..."
				dat+="
Receiving Channel: [src.channel_name]
" //MARK
				dat+="Message Author: [src.scanned_user]
"
				dat+="Message Body:
[parsepencode(src.msg, user, SIGNFONT)]
"
				dat+="Attach Photo:  [(src.photo ? "Photo Attached" : "No Photo")]
"
				dat+="Comments [allow_comments ? "Enabled" : "Disabled"]
"
				dat+="
Submit

Cancel
"
			if(4)
				dat+="Feed story successfully submitted to [src.channel_name].

"
				dat+="
Return
"
			if(5)
				dat+="Feed Channel [src.channel_name] created successfully.

"
				dat+="
Return
"
			if(6)
				dat+="ERROR: Could not submit Feed story to Network.

"
				if(src.channel_name=="")
					dat+="�Invalid receiving channel name.
"
				if(src.scanned_user=="Unknown")
					dat+="�Channel author unverified.
"
				if(src.msg == "" || src.msg == "\[REDACTED\]")
					dat+="�Invalid message body.
"

				dat+="
Return
"
			if(7)
				dat+="ERROR: Could not submit Feed Channel to Network.

"
				//var/list/existing_channels = list()            //Let's get dem existing channels - OBSOLETE
				var/list/existing_authors = list()
				for(var/datum/feed_channel/FC in news_network.network_channels)
					//existing_channels += FC.channel_name       //OBSOLETE
					if(FC.author == "\[REDACTED\]")
						existing_authors += FC.backup_author
					else
						existing_authors += FC.author
				if(src.scanned_user in existing_authors)
					dat+="�There already exists a Feed channel under your name.
"
				if(src.channel_name=="" || src.channel_name == "\[REDACTED\]")
					dat+="�Invalid channel name.
"
				var/check = 0
				for(var/datum/feed_channel/FC in news_network.network_channels)
					if(FC.channel_name == src.channel_name)
						check = 1
						break
				if(check)
					dat+="�Channel name already in use.
"
				if(src.scanned_user=="Unknown")
					dat+="�Channel author unverified.
"
				dat+="
Return
"
			if(8)
				var/total_num=length(news_network.network_channels)
				var/active_num=total_num
				var/message_num=0
				for(var/datum/feed_channel/FC in news_network.network_channels)
					if(!FC.censored)
						message_num += length(FC.messages)    //Dont forget, datum/feed_channel's var messages is a list of datum/feed_message
					else
						active_num--
				dat+="Network currently serves a total of [total_num] Feed channels, [active_num] of which are active, and a total of [message_num] Feed Stories." //TODO: CONTINUE
				dat+="

Liquid Paper remaining: [(src.paper_remaining) *100 ] cm^3"
				dat+="

Print Paper"
				dat+="
Cancel"
			if(9)
				dat+="[src.viewing_channel.channel_name]: \[created by: [src.viewing_channel.author]\]
"
				if(src.viewing_channel.censored)
					dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
"
					dat+="No further feed story additions are allowed while the D-Notice is in effect.

"
				else
					if( isemptylist(src.viewing_channel.messages) )
						dat+="No feed messages found in channel...
"
					else
						var/i = 0
						for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages)
							i++
							dat+="-[MESSAGE.body]
"
							if(MESSAGE.img)
								usr << browse_rsc(MESSAGE.img, "tmp_photo[i].png")
								dat+="
"
								if(MESSAGE.caption)
									dat+="[MESSAGE.caption]
"
								dat+="
"
							dat+="\[Story by [MESSAGE.author] \] - ([MESSAGE.time_stamp])
"
							dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]
"
							for(var/datum/feed_comment/comment in MESSAGE.comments)
								dat+="[comment.body]
[comment.author] [comment.time_stamp]
"
							if(MESSAGE.locked)
								dat+="Comments locked
"
							else
								dat+="Comment
"
				dat+="

Refresh"
				dat+="
Back"
			if(10)
				dat+="Nanotrasen Feed Censorship Tool
"
				dat+="NOTE: Due to the nature of news Feeds, total deletion of a Feed Story is not possible.
"
				dat+="Keep in mind that users attempting to view a censored feed will instead see the \[REDACTED\] tag above it."
				dat+="
Select Feed channel to get Stories from:
"
				if(isemptylist(news_network.network_channels))
					dat+="No feed channels found active...
"
				else
					for(var/datum/feed_channel/CHANNEL in news_network.network_channels)
						dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
"
				dat+="
Cancel"
			if(11)
				dat+="Nanotrasen D-Notice Handler
"
				dat+="A D-Notice is to be bestowed upon the channel if the handling Authority deems it as harmful for the station's"
				dat+="morale, integrity or disciplinary behaviour. A D-Notice will render a channel unable to be updated by anyone, without deleting any feed"
				dat+="stories it might contain at the time. You can lift a D-Notice if you have the required access at any time.
"
				if(isemptylist(news_network.network_channels))
					dat+="No feed channels found active...
"
				else
					for(var/datum/feed_channel/CHANNEL in news_network.network_channels)
						dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
"

				dat+="
Back"
			if(12)
				dat+="[src.viewing_channel.channel_name]: \[ created by: [src.viewing_channel.author] \]
"
				dat+="[(src.viewing_channel.author=="\[REDACTED\]") ? ("Undo Author censorship") : ("Censor channel Author")]
"

				if( isemptylist(src.viewing_channel.messages) )
					dat+="No feed messages found in channel...
"
				else
					for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages)
						dat+="-[MESSAGE.body]
\[Story by [MESSAGE.author]\]
"
						dat+="[(MESSAGE.body == "\[REDACTED\]") ? ("Undo story censorship") : ("Censor story")]  -  [(MESSAGE.author == "\[REDACTED\]") ? ("Undo Author Censorship") : ("Censor message Author")]
"
						dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]: [MESSAGE.locked ? "Unlock" : "Lock"]
"
						for(var/datum/feed_comment/comment in MESSAGE.comments)
							dat+="[comment.body] X
[comment.author] [comment.time_stamp]
"
				dat+="
Back"
			if(13)
				dat+="[src.viewing_channel.channel_name]: \[ created by: [src.viewing_channel.author] \]
"
				dat+="Channel messages listed below. If you deem them dangerous to the station, you can Bestow a D-Notice upon the channel.
"
				if(src.viewing_channel.censored)
					dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
"
					dat+="No further feed story additions are allowed while the D-Notice is in effect.

"
				else
					if( isemptylist(src.viewing_channel.messages) )
						dat+="No feed messages found in channel...
"
					else
						for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages)
							dat+="-[MESSAGE.body]
\[Story by [MESSAGE.author]\]
"

				dat+="
Back"
			if(14)
				dat+="Wanted Issue Handler:"
				var/wanted_already = 0
				var/end_param = 1
				if(news_network.wanted_issue)
					wanted_already = 1
					end_param = 2

				if(wanted_already)
					dat+="
A wanted issue is already in Feed Circulation. You can edit or cancel it below."
				dat+="
"
				dat+="Criminal Name: [src.channel_name]
"
				dat+="Description: [src.msg]
"
				dat+="Attach Photo: [(src.photo ? "Photo Attached" : "No Photo")]
"
				if(wanted_already)
					dat+="Wanted Issue created by: [news_network.wanted_issue.backup_author]
"
				else
					dat+="Wanted Issue will be created under prosecutor: [src.scanned_user]
"
				dat+="
[(wanted_already) ? ("Edit Issue") : ("Submit")]"
				if(wanted_already)
					dat+="
Take down Issue"
				dat+="
Cancel"
			if(15)
				dat+="Wanted issue for [src.channel_name] is now in Network Circulation.

"
				dat+="
Return
"
			if(16)
				dat+="ERROR: Wanted Issue rejected by Network.

"
				if(src.channel_name=="" || src.channel_name == "\[REDACTED\]")
					dat+="�Invalid name for person wanted.
"
				if(src.scanned_user=="Unknown")
					dat+="�Issue author unverified.
"
				if(src.msg == "" || src.msg == "\[REDACTED\]")
					dat+="�Invalid description.
"
				dat+="
Return
"
			if(17)
				dat+="Wanted Issue successfully deleted from Circulation
"
				dat+="
Return
"
			if(18)
				if(news_network.wanted_issue)
					dat+="-- STATIONWIDE WANTED ISSUE --
\[Submitted by: [news_network.wanted_issue.backup_author]\]
"
					dat+="Criminal: [news_network.wanted_issue.author]
"
					dat+="Description: [news_network.wanted_issue.body]
"
					dat+="Photo:: "
					if(news_network.wanted_issue.img)
						usr << browse_rsc(news_network.wanted_issue.img, "tmp_photow.png")
						dat+="
"
					else
						dat+="None"
				else
					dat+="No current wanted issue found.

"
				dat+="

Back
"
			if(19)
				dat+="Wanted issue for [src.channel_name] successfully edited.

"
				dat+="
Return
"
			if(20)
				dat+="Printing successful. Please receive your newspaper from the bottom of the machine.

"
				dat+="Return"
			if(21)
				dat+="Unable to print newspaper. Insufficient paper. Please notify maintenance personnel to refill machine storage.

"
				dat+="Return"
			else
				dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com"

		//human_or_robot_user << browse(dat, "window=newscaster_main;size=400x600")
		//onclose(human_or_robot_user, "newscaster_main")

		var/datum/browser/popup = new(human_or_robot_user, "newscaster_main", "Newscaster Unit #[src.unit_no]", 400, 600)
		popup.set_content(dat)
		popup.set_title_image(human_or_robot_user.browse_rsc_icon(src.icon, src.icon_state))
		popup.open()

/obj/machinery/newscaster/Topic(href, href_list)
	if(..())
		return
	if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
		usr.set_machine(src)
		scan_user(usr)
		if(href_list["set_channel_name"])
			src.channel_name = stripped_input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "", MAX_NAME_LEN)
			while (findtext(src.channel_name," ") == 1)
				src.channel_name = copytext(src.channel_name,2,lentext(src.channel_name)+1)
			src.updateUsrDialog()
			//src.update_icon()

		else if(href_list["set_channel_lock"])
			src.c_locked = !src.c_locked
			src.updateUsrDialog()
			//src.update_icon()

		else if(href_list["submit_new_channel"])
			var/list/existing_authors = list()
			for(var/datum/feed_channel/FC in news_network.network_channels)
				//existing_channels += FC.channel_name
				if(FC.author == "\[REDACTED\]")
					existing_authors += FC.backup_author
				else
					existing_authors  +=FC.author
			var/check = 0
			for(var/datum/feed_channel/FC in news_network.network_channels)
				if(FC.channel_name == src.channel_name)
					check = 1
					break
			if(src.channel_name == "" || src.channel_name == "\[REDACTED\]" || src.scanned_user == "Unknown" || check || (src.scanned_user in existing_authors) )
				src.screen=7
			else
				var/choice = alert("Please confirm Feed channel creation","Network Channel Handler","Confirm","Cancel")
				if(choice=="Confirm")
					scan_user(usr)
					news_network.CreateFeedChannel(src.channel_name, src.scanned_user, c_locked)
					feedback_inc("newscaster_channels",1)
					src.screen=5
			src.updateUsrDialog()
			//src.update_icon()

		else if(href_list["set_channel_receiving"])
			//var/list/datum/feed_channel/available_channels = list()
			var/list/available_channels = list()
			for(var/datum/feed_channel/F in news_network.network_channels)
				if( (!F.locked || F.author == scanned_user) && !F.censored)
					available_channels += F.channel_name
			src.channel_name = input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels
			src.updateUsrDialog()

		else if(href_list["set_new_message"])
			var/temp_message = trim(stripped_multiline_input(usr, "Write your Feed story", "Network Channel Handler", src.msg))
			if(temp_message)
				src.msg = temp_message
				src.updateUsrDialog()

		else if(href_list["set_attachment"])
			AttachPhoto(usr)
			src.updateUsrDialog()

		else if(href_list["submit_new_message"])
			if(src.msg =="" || src.msg=="\[REDACTED\]" || src.scanned_user == "Unknown" || src.channel_name == "" )
				src.screen=6
			else
				news_network.SubmitArticle("[parsepencode(src.msg, usr, SIGNFONT)]", scanned_user, channel_name, photo, allow_comments)
				feedback_inc("newscaster_stories",1)
				src.screen=4
				src.msg = ""
			src.updateUsrDialog()

		else if(href_list["create_channel"])
			src.screen=2
			src.updateUsrDialog()

		else if(href_list["create_feed_story"])
			src.screen=3
			src.updateUsrDialog()

		else if(href_list["menu_paper"])
			src.screen=8
			src.updateUsrDialog()
		else if(href_list["print_paper"])
			if(!src.paper_remaining)
				src.screen=21
			else
				src.print_paper()
				src.screen = 20
			src.updateUsrDialog()

		else if(href_list["menu_censor_story"])
			src.screen=10
			src.updateUsrDialog()

		else if(href_list["menu_censor_channel"])
			src.screen=11
			src.updateUsrDialog()

		else if(href_list["menu_wanted"])
			var/already_wanted = 0
			if(news_network.wanted_issue)
				already_wanted = 1

			if(already_wanted)
				src.channel_name = news_network.wanted_issue.author
				src.msg = news_network.wanted_issue.body
			src.screen = 14
			src.updateUsrDialog()

		else if(href_list["set_wanted_name"])
			src.channel_name = trim(stripped_input(usr, "Provide the name of the Wanted person", "Network Security Handler"))
			src.updateUsrDialog()

		else if(href_list["set_wanted_desc"])
			src.msg = trim(stripped_input(usr, "Provide the a description of the Wanted person and any other details you deem important", "Network Security Handler"))
			src.updateUsrDialog()

		else if(href_list["submit_wanted"])
			var/input_param = text2num(href_list["submit_wanted"])
			if(src.msg == "" || src.channel_name == "" || src.scanned_user == "Unknown")
				src.screen = 16
			else
				var/choice = alert("Please confirm Wanted Issue [(input_param==1) ? ("creation.") : ("edit.")]","Network Security Handler","Confirm","Cancel")
				if(choice=="Confirm")
					scan_user(usr)
					if(input_param==1)          //If input_param == 1 we're submitting a new wanted issue. At 2 we're just editing an existing one. See the else below
						var/datum/feed_message/WANTED = new /datum/feed_message
						WANTED.author = src.channel_name
						WANTED.body = src.msg
						WANTED.backup_author = src.scanned_user //I know, a bit wacky
						if(photo)
							WANTED.img = photo.img
						news_network.wanted_issue = WANTED
						for(var/obj/machinery/newscaster/NEWSCASTER in allCasters)
							NEWSCASTER.newsAlert()
							NEWSCASTER.update_icon()
						src.screen = 15
					else
						if(news_network.wanted_issue.is_admin_message)
							alert("The wanted issue has been distributed by a Nanotrasen higherup. You cannot edit it.","Ok")
							return
						news_network.wanted_issue.author = src.channel_name
						news_network.wanted_issue.body = src.msg
						news_network.wanted_issue.backup_author = src.scanned_user
						if(photo)
							news_network.wanted_issue.img = photo.img
						src.screen = 19

			src.updateUsrDialog()

		else if(href_list["cancel_wanted"])
			if(news_network.wanted_issue.is_admin_message)
				alert("The wanted issue has been distributed by a Nanotrasen higherup. You cannot take it down.","Ok")
				return
			var/choice = alert("Please confirm Wanted Issue removal","Network Security Handler","Confirm","Cancel")
			if(choice=="Confirm")
				news_network.wanted_issue = null
				for(var/obj/machinery/newscaster/NEWSCASTER in allCasters)
					NEWSCASTER.update_icon()
				src.screen=17
			src.updateUsrDialog()

		else if(href_list["view_wanted"])
			src.screen=18
			src.updateUsrDialog()
		else if(href_list["censor_channel_author"])
			var/datum/feed_channel/FC = locate(href_list["censor_channel_author"])
			if(FC.is_admin_channel)
				alert("This channel was created by a Nanotrasen Officer. You cannot censor it.","Ok")
				return
			if(FC.author != "\[REDACTED\]")
				FC.backup_author = FC.author
				FC.author = "\[REDACTED\]"
			else
				FC.author = FC.backup_author
			src.updateUsrDialog()

		else if(href_list["censor_channel_story_author"])
			var/datum/feed_message/MSG = locate(href_list["censor_channel_story_author"])
			if(MSG.is_admin_message)
				alert("This message was created by a Nanotrasen Officer. You cannot censor its author.","Ok")
				return
			if(MSG.author != "\[REDACTED\]")
				MSG.backup_author = MSG.author
				MSG.author = "\[REDACTED\]"
			else
				MSG.author = MSG.backup_author
			src.updateUsrDialog()

		else if(href_list["censor_channel_story_body"])
			var/datum/feed_message/MSG = locate(href_list["censor_channel_story_body"])
			if(MSG.is_admin_message)
				alert("This channel was created by a Nanotrasen Officer. You cannot censor it.","Ok")
				return
			if(MSG.body != "\[REDACTED\]")
				MSG.backup_body = MSG.body
				MSG.body = "\[REDACTED\]"
			else
				MSG.body = MSG.backup_body
			src.updateUsrDialog()

		else if(href_list["pick_d_notice"])
			var/datum/feed_channel/FC = locate(href_list["pick_d_notice"])
			src.viewing_channel = FC
			src.screen=13
			src.updateUsrDialog()

		else if(href_list["toggle_d_notice"])
			var/datum/feed_channel/FC = locate(href_list["toggle_d_notice"])
			if(FC.is_admin_channel)
				alert("This channel was created by a Nanotrasen Officer. You cannot place a D-Notice upon it.","Ok")
				return
			FC.censored = !FC.censored
			src.updateUsrDialog()

		else if(href_list["view"])
			src.screen=1
			src.updateUsrDialog()

		else if(href_list["setScreen"]) //Brings us to the main menu and resets all fields~
			src.screen = text2num(href_list["setScreen"])
			if (src.screen == 0)
				src.scanned_user = "Unknown";
				msg = "";
				src.c_locked=0;
				channel_name="";
				src.viewing_channel = null
			src.updateUsrDialog()

		else if(href_list["show_channel"])
			var/datum/feed_channel/FC = locate(href_list["show_channel"])
			src.viewing_channel = FC
			src.screen = 9
			src.updateUsrDialog()

		else if(href_list["pick_censor_channel"])
			var/datum/feed_channel/FC = locate(href_list["pick_censor_channel"])
			src.viewing_channel = FC
			src.screen = 12
			src.updateUsrDialog()

		else if(href_list["new_comment"])
			var/datum/feed_message/FM = locate(href_list["new_comment"])
			var/cominput = copytext(stripped_input(usr, "Write your message:", "New comment", null),1,141)
			if(cominput)
				scan_user(usr)
				var/datum/feed_comment/FC = new/datum/feed_comment
				FC.author = scanned_user
				FC.body = cominput
				FC.time_stamp = worldtime2text()
				FM.comments += FC
				log_comment("[usr]/([usr.ckey]) as [scanned_user] commented on message [FM.body] -- [FC.body]")
			updateUsrDialog()

		else if(href_list["del_comment"])
			var/datum/feed_comment/FC = locate(href_list["del_comment"])
			var/datum/feed_message/FM = locate(href_list["del_comment_msg"])
			FM.comments -= FC
			qdel(FC)
			updateUsrDialog()

		else if(href_list["lock_comment"])
			var/datum/feed_message/FM = locate(href_list["lock_comment"])
			FM.locked ^= 1
			updateUsrDialog()

		else if(href_list["set_comment"])
			allow_comments ^= 1
			updateUsrDialog()

		else if(href_list["refresh"])
			src.updateUsrDialog()

/obj/machinery/newscaster/attackby(obj/item/I as obj, mob/living/user as mob, params)

	if(istype(I, /obj/item/weapon/wrench))
		user << "Now [anchored ? "un" : ""]securing [name]"
		playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
		if(do_after(user, 60))
			new /obj/item/newscaster_frame(loc)
			playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
			qdel(src)
		return

	if (isbroken)
		playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 100, 1)
		audible_message("[user.name] further abuses the shattered [src.name].", null, 5 )
	else
		if(istype(I, /obj/item/weapon) )
			user.do_attack_animation(src)
			var/obj/item/weapon/W = I
			if(W.damtype == STAMINA)
				return
			if(W.force <15)
				audible_message("[user.name] hits the [src.name] with the [W.name] with no visible effect.", null , 5 )
				playsound(src.loc, 'sound/effects/Glasshit.ogg', 100, 1)
			else
				hitstaken++
				if(hitstaken==3)
					audible_message("[user.name] smashes the [src.name]!", null, 5 )
					isbroken=1
					playsound(src.loc, 'sound/effects/Glassbr3.ogg', 100, 1)
				else
					audible_message("[user.name] forcefully slams the [src.name] with the [I.name]!", null, 5 )
					playsound(src.loc, 'sound/effects/Glasshit.ogg', 100, 1)
		else
			user << "This does nothing."
	src.update_icon()

/obj/machinery/newscaster/attack_paw(mob/user as mob)
	user << "The newscaster controls are far too complicated for your tiny brain!"
	return

/obj/machinery/newscaster/proc/AttachPhoto(mob/user as mob)
	if(photo)
		if(!photo.sillynewscastervar)
			photo.loc = src.loc
			if(!issilicon(user) || ismommi(user))
				user.put_in_inactive_hand(photo)
		else
			qdel(photo)
		photo = null
	if(istype(user.get_active_hand(), /obj/item/weapon/photo))
		photo = user.get_active_hand()
		user.drop_item()
		photo.loc = src
	if(istype(user,/mob/living/silicon) && !ismommi(user))
		var/list/nametemp = list()
		var/find
		var/datum/picture/selection
		var/obj/item/device/camera/siliconcam/targetcam = null

		if(istype(user,/mob/living/silicon/ai))
			var/mob/living/silicon/ai/R = user
			targetcam = R.aicamera
		else if(istype(user,/mob/living/silicon/robot))
			var/mob/living/silicon/robot/R = user
			if(R.connected_ai)
				targetcam = R.connected_ai.aicamera
			else
				targetcam = R.aicamera
		else
			user << "You cannot interface with silicon photo uploading"	//gtfo pAIs

		if(targetcam.aipictures.len == 0)
			usr << "No images saved"
			return
		for(var/datum/picture/t in targetcam.aipictures)
			nametemp += t.fields["name"]
		find = input("Select image (numbered in order taken)") in nametemp
		var/obj/item/weapon/photo/P = new/obj/item/weapon/photo()
		for(var/datum/picture/q in targetcam.aipictures)
			if(q.fields["name"] == find)
				selection = q
				break
		P.photocreate(selection.fields["icon"], selection.fields["img"], selection.fields["desc"])
		P.sillynewscastervar = 1
		photo = P
		qdel(P)

//########################################################################################################################
//###################################### NEWSPAPER! ######################################################################
//########################################################################################################################

/obj/item/weapon/newspaper
	name = "newspaper"
	desc = "An issue of The Griffon, the newspaper circulating aboard Nanotrasen Space Stations."
	icon = 'icons/obj/bureaucracy.dmi'
	icon_state = "newspaper"
	w_class = 2	//Let's make it fit in trashbags!
	attack_verb = list("bapped")
	var/screen = 0
	var/pages = 0
	var/curr_page = 0
	var/list/datum/feed_channel/news_content = list()
	var/datum/feed_message/important_message = null
	var/scribble=""
	var/scribble_page = null

/*obj/item/weapon/newspaper/attack_hand(mob/user as mob)
	..()
	world << "derp"*/

obj/item/weapon/newspaper/attack_self(mob/user as mob)
	if(ishuman(user))
		var/mob/living/carbon/human/human_user = user
		var/dat
		src.pages = 0
		switch(screen)
			if(0) //Cover
				dat+="
The Griffon
"
				dat+="
Nanotrasen-standard newspaper, for use on Nanotrasen� Space Facilities

"
				if(isemptylist(src.news_content))
					if(src.important_message)
						dat+="Contents:

**Important Security Announcement** \[page [src.pages+2]\]

"
					else
						dat+="Other than the title, the rest of the newspaper is unprinted..."
				else
					dat+="Contents:

"
					for(var/datum/feed_channel/NP in src.news_content)
						src.pages++
					if(src.important_message)
						dat+="**Important Security Announcement** \[page [src.pages+2]\]
"
					var/temp_page=0
					for(var/datum/feed_channel/NP in src.news_content)
						temp_page++
						dat+="[NP.channel_name] \[page [temp_page+1]\]
"
					dat+="
"
				if(scribble_page==curr_page)
					dat+="
There is a small scribble near the end of this page... It reads: \"[src.scribble]\""
				dat+= "

Next Page

Done reading
"
			if(1) // X channel pages inbetween.
				for(var/datum/feed_channel/NP in src.news_content)
					src.pages++ //Let's get it right again.
				var/datum/feed_channel/C = src.news_content[src.curr_page]
				dat+="[C.channel_name] \[created by: [C.author]\]

"
				if(C.censored)
					dat+="This channel was deemed dangerous to the general welfare of the station and therefore marked with a D-Notice. Its contents were not transferred to the newspaper at the time of printing."
				else
					if(isemptylist(C.messages))
						dat+="No Feed stories stem from this channel..."
					else
						dat+="
"
						var/i = 0
						for(var/datum/feed_message/MESSAGE in C.messages)
							i++
							dat+="-[MESSAGE.body]
"
							if(MESSAGE.img)
								user << browse_rsc(MESSAGE.img, "tmp_photo[i].png")
								dat+="
"
							dat+="\[Story by [MESSAGE.author]\]

"
						dat+="
"
				if(scribble_page==curr_page)
					dat+="
There is a small scribble near the end of this page... It reads: \"[src.scribble]\""
				dat+= "

Previous Page

Next Page
"
			if(2) //Last page
				for(var/datum/feed_channel/NP in src.news_content)
					src.pages++
				if(src.important_message!=null)
					dat+="
Wanted Issue:

"
					dat+="Criminal name: [important_message.author]
"
					dat+="Description: [important_message.body]
"
					dat+="Photo:: "
					if(important_message.img)
						user << browse_rsc(important_message.img, "tmp_photow.png")
						dat+="
"
					else
						dat+="None"
				else
					dat+="Apart from some uninteresting Classified ads, there's nothing on this page..."
				if(scribble_page==curr_page)
					dat+="
There is a small scribble near the end of this page... It reads: \"[src.scribble]\""
				dat+= "

Previous Page
"
			else
				dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com"

		dat+="

[src.curr_page+1]
"
		human_user << browse(dat, "window=newspaper_main;size=300x400")
		onclose(human_user, "newspaper_main")
	else
		user << "The paper is full of intelligible symbols!"

obj/item/weapon/newspaper/Topic(href, href_list)
	var/mob/living/U = usr
	..()
	if ((src in U.contents) || ( istype(loc, /turf) && in_range(src, U) ))
		U.set_machine(src)
		if(href_list["next_page"])
			if(curr_page==src.pages+1)
				return //Don't need that at all, but anyway.
			if(src.curr_page == src.pages) //We're at the middle, get to the end
				src.screen = 2
			else
				if(curr_page == 0) //We're at the start, get to the middle
					src.screen=1
			src.curr_page++
			playsound(src.loc, "pageturn", 50, 1)

		else if(href_list["prev_page"])
			if(curr_page == 0)
				return
			if(curr_page == 1)
				src.screen = 0

			else
				if(curr_page == src.pages+1) //we're at the end, let's go back to the middle.
					src.screen = 1
			src.curr_page--
			playsound(src.loc, "pageturn", 50, 1)

		if (istype(src.loc, /mob))
			src.attack_self(src.loc)

obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
	if(istype(W, /obj/item/weapon/pen))
		if(src.scribble_page == src.curr_page)
			user << "There's already a scribble in this page... You wouldn't want to make things too cluttered, would you?"
		else
			var/s = stripped_input(user, "Write something", "Newspaper")
			if (!s)
				return
			if (!in_range(src, usr) && src.loc != usr)
				return
			src.scribble_page = src.curr_page
			src.scribble = s
			src.attack_self(user)
		return

////////////////////////////////////helper procs

/obj/machinery/newscaster/proc/scan_user(mob/living/user as mob)
	if(istype(user,/mob/living/carbon/human))                       //User is a human
		var/mob/living/carbon/human/human_user = user
		if(human_user.wear_id)                                      //Newscaster scans you
			if(istype(human_user.wear_id, /obj/item/device/pda) )	//autorecognition, woo!
				var/obj/item/device/pda/P = human_user.wear_id
				if(P.id)
					src.scanned_user = "[P.id.registered_name] ([P.id.assignment])"
				else
					src.scanned_user = "Unknown"
			else if(istype(human_user.wear_id, /obj/item/weapon/card/id) )
				var/obj/item/weapon/card/id/ID = human_user.wear_id
				src.scanned_user ="[ID.registered_name] ([ID.assignment])"
			else
				src.scanned_user ="Unknown"
		else
			src.scanned_user ="Unknown"
	else if(istype(user,/mob/living/silicon))
		var/mob/living/silicon/ai_user = user
		src.scanned_user = "[ai_user.name] ([ai_user.job])"
	else
		ERROR("Newscaster used by non-human/silicon mob: [user.type]")

/obj/machinery/newscaster/proc/print_paper()
	feedback_inc("newscaster_newspapers_printed",1)
	var/obj/item/weapon/newspaper/NEWSPAPER = new /obj/item/weapon/newspaper
	for(var/datum/feed_channel/FC in news_network.network_channels)
		NEWSPAPER.news_content += FC
	if(news_network.wanted_issue)
		NEWSPAPER.important_message = news_network.wanted_issue
	NEWSPAPER.loc = get_turf(src)
	src.paper_remaining--
	return

//Removed for now so these aren't even checked every tick. Left this here in-case Agouri needs it later.
///obj/machinery/newscaster/process()       //Was thinking of doing the icon update through process, but multiple iterations per second does not
//	return                                  //bode well with a newscaster network of 10+ machines. Let's just return it, as it's added in the machines list.

/obj/machinery/newscaster/proc/newsAlert(channel)   //This isn't Agouri's work, for it is ugly and vile.
	if(channel) 									//Who the fuck uses spawn(600) anyway, jesus christ
		say("Breaking news from [channel]!")
		src.alert = 1
		src.update_icon()
		spawn(300)
			src.alert = 0
			src.update_icon()
		playsound(src.loc, 'sound/machines/twobeep.ogg', 75, 1)
	else
		say("Attention! Wanted issue distributed!")
		playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 75, 1)
	return

/obj/machinery/newscaster/say_quote(text)
	return "beeps, \"[text]\""


code:
//#define AMAP

/obj/machinery/computer/security/verb/station_map()
	set name = ".map"
	set category = "Object"
	set src in view(1)
	usr.set_machine(src)
	if(!mapping)	return

	log_game("[usr]([usr.key]) used station map L[z] in [src.loc.loc]")

	src.drawmap(usr)

/obj/machinery/computer/security/proc/drawmap(var/mob/user as mob)

	var/icx = round(world.maxx/16) + 1
	var/icy = round(world.maxy/16) + 1

	var/xoff = round( (icx*16-world.maxx)-2)
	var/yoff = round( (icy*16-world.maxy)-2)

	var/icount = icx * icy

	var/list/imap = list()

#ifdef AMAP

	for(var/i = 0; i<icount; i++)
		imap += icon('icons/misc/imap.dmi', "blank")
		imap += icon('icons/misc/imap.dmi', "blank")

	//world << "[icount] images in list"

	for(var/wx = 1 ; wx <= world.maxx; wx++)

		for(var/wy = 1; wy <= world.maxy; wy++)

			var/turf/T = locate(wx, wy, z)

			var/colour
			var/colour2

			if(!T)
				colour = rgb(0,0,0)

			else
				var/sense = 1
				switch("[T.type]")
					if("/turf/space")
						colour = rgb(10,10,10)
						sense = 0

					if("/turf/simulated/floor")
						colour = rgb(150,150,150)
						var/turf/simulated/floor/TF = T
						if(TF.burnt == 1)
							sense = 0
							colour = rgb(130,130,130)

					if("/turf/simulated/floor/engine")
						colour = rgb(128,128,128)

					if("/turf/simulated/wall")
						colour = rgb(96,96,96)

					if("/turf/simulated/wall/r_wall")
						colour = rgb(128,96,96)

					else
						colour = rgb(0,40,0)

				if(sense)

					for(var/atom/AM in T.contents)

						if(istype(AM, /obj/machinery/door) && !istype(AM, /obj/machinery/door/window))
							if(AM.density)
								colour = rgb(96,96,192)
								colour2 = colour
							else
								colour = rgb(128,192,128)

						if(istype(AM, /obj/machinery/alarm))
							colour = rgb(0,255,0)
							colour2 = colour
							if(AM.icon_state=="alarm:1")
								colour = rgb(255,255,0)
								colour2 = rgb(255,128,0)

						if(istype(AM, /mob))
							if(AM:client)
								colour = rgb(255,0,0)
							else
								colour = rgb(255,128,128)

							colour2 = rgb(192,0,0)

				var/area/A = T.loc

				if(A.fire)

					var/red = getr(colour)
					var/green = getg(colour)
					var/blue = getb(colour)

					green = min(255, green+40)
					blue = min(255, blue+40)

					colour = rgb(red, green, blue)

			if(!colour2 && !T.density)
				var/datum/gas_mixture/environment = T.return_air()
				var/turf_total = environment.total_moles()
				//var/turf_total = T.co2 + T.oxygen + T.poison + T.sl_gas + T.n2

				var/t1 = turf_total / MOLES_CELLSTANDARD * 150

				if(t1<=100)
					colour2 = rgb(t1*2.55,0,0)
				else
					t1 = min(100, t1-100)
					colour2 = rgb(255, t1*2.55, t1*2.55)

			if(!colour2)
				colour2 = colour

			var/ix = round((wx*2+xoff)/32)
			var/iy = round((wy*2+yoff)/32)

			var/rx = ((wx*2+xoff)%32) + 1
			var/ry = ((wy*2+yoff)%32) + 1

			//world << "trying [ix],[iy] : [ix+icx*iy]"
			var/icon/I = imap[1+(ix + icx*iy)*2]
			var/icon/I2 = imap[2+(ix + icx*iy)*2]

			//world << "icon: \icon[I]"

			I.DrawBox(colour, rx, ry, rx+1, ry+1)

			I2.DrawBox(colour2, rx, ry, rx+1, ry+1)

	user.clearmap()

	user.mapobjs = list()

	for(var/i=0; i<icount;i++)
		var/obj/screen/H = new /obj/screen()

		H.screen_loc = "[5 + i%icx],[6+ round(i/icx)]"

		//world<<"\icon[I] at [H.screen_loc]"

		H.name = (i==0)?"maprefresh":"map"

		var/icon/HI = new/icon

		var/icon/I = imap[i*2+1]
		var/icon/J = imap[i*2+2]

		HI.Insert(I, frame=1, delay = 5)
		HI.Insert(J, frame=2, delay = 5)

		del(I)
		del(J)
		H.icon = HI
		H.layer = 25
		usr.mapobjs += H
#else

	for(var/i = 0; i<icount; i++)
		imap += icon('icons/misc/imap.dmi', "blank")

	for(var/wx = 1 ; wx <= world.maxx; wx++)

		for(var/wy = 1; wy <= world.maxy; wy++)

			var/turf/T = locate(wx, wy, z)

			var/colour

			if(!T)
				colour = rgb(0,0,0)

			else
				var/sense = 1
				switch("[T.type]")
					if("/turf/space")
						colour = rgb(10,10,10)
						sense = 0

					if("/turf/simulated/floor", "/turf/simulated/floor/engine")
						var/datum/gas_mixture/environment = T.return_air()
						var/turf_total = environment.total_moles()
						var/t1 = turf_total / MOLES_CELLSTANDARD * 175

						if(t1<=100)
							colour = rgb(0,0,t1*2.55)
						else
							t1 = min(100, t1-100)
							colour = rgb( t1*2.55, t1*2.55, 255)

					if("/turf/simulated/wall")
						colour = rgb(96,96,96)

					if("/turf/simulated/wall/r_wall")
						colour = rgb(128,96,96)

					else
						colour = rgb(0,40,0)

				if(sense)

					for(var/atom/AM in T.contents)

						if(istype(AM, /obj/machinery/door) && !istype(AM, /obj/machinery/door/window))
							if(AM.density)
								colour = rgb(0,96,192)
							else
								colour = rgb(96,192,128)

						if(istype(AM, /obj/machinery/alarm))
							colour = rgb(0,255,0)

							if(AM.icon_state=="alarm:1")
								colour = rgb(255,255,0)

						if(istype(AM, /mob))
							if(AM:client)
								colour = rgb(255,0,0)
							else
								colour = rgb(255,128,128)

						//if(istype(AM, /obj/effect/blob))
						//	colour = rgb(255,0,255)

				var/area/A = T.loc

				if(A.fire)

					var/red = getr(colour)
					var/green = getg(colour)
					var/blue = getb(colour)

					green = min(255, green+40)
					blue = min(255, blue+40)

					colour = rgb(red, green, blue)

			var/ix = round((wx*2+xoff)/32)
			var/iy = round((wy*2+yoff)/32)

			var/rx = ((wx*2+xoff)%32) + 1
			var/ry = ((wy*2+yoff)%32) + 1

			//world << "trying [ix],[iy] : [ix+icx*iy]"
			var/icon/I = imap[1+(ix + icx*iy)]

			//world << "icon: \icon[I]"

			I.DrawBox(colour, rx, ry, rx, ry)

	user.clearmap()

	user.mapobjs = list()

	for(var/i=0; i<icount;i++)
		var/obj/screen/H = new /obj/screen()

		H.screen_loc = "[5 + i%icx],[6+ round(i/icx)]"

		//world<<"\icon[I] at [H.screen_loc]"

		H.name = (i==0)?"maprefresh":"map"

		var/icon/I = imap[i+1]

		H.icon = I
		del(I)
		H.layer = 25
		usr.mapobjs += H

#endif

	user.client.screen += user.mapobjs

	src.close(user)

/*			if(seccomp == src)
				drawmap(user)
			else
				user.clearmap()*/
	return

/obj/machinery/computer/security/proc/close(mob/user)
	spawn(20)
		var/using = null
		if(user.mapobjs)
			for(var/obj/machinery/computer/security/seccomp in oview(1,user))
				if(seccomp == src)
					using = 1
					break
			if(using)
				close(user)
			else
				user.clearmap()

		return

proc/getr(col)
	return hex2num( copytext(col, 2,4))

proc/getg(col)
	return hex2num( copytext(col, 4,6))

proc/getb(col)
	return hex2num( copytext(col, 6))

/mob/proc/clearmap()
	src.client.screen -= src.mapobjs
	for(var/obj/screen/O in mapobjs)
		qdel(O)

	mapobjs = null
	src.unset_machine()

license: mit


code:
/*CONTENTS
Buildable pipes
Buildable meters
*/
#define PIPE_SIMPLE_STRAIGHT	0
#define PIPE_SIMPLE_BENT		1
#define PIPE_HE_STRAIGHT		2
#define PIPE_HE_BENT			3
#define PIPE_CONNECTOR			4
#define PIPE_MANIFOLD			5
#define PIPE_JUNCTION			6
#define PIPE_UVENT				7
#define PIPE_MVALVE				8
#define PIPE_PUMP				9
#define PIPE_SCRUBBER			10
#define PIPE_INSULATED_STRAIGHT	11
#define PIPE_INSULATED_BENT		12
#define PIPE_GAS_FILTER			13
#define PIPE_GAS_MIXER			14
#define PIPE_PASSIVE_GATE       15
#define PIPE_VOLUME_PUMP        16
#define PIPE_HEAT_EXCHANGE      17
#define PIPE_DVALVE             18
#define PIPE_4WAYMANIFOLD       19
//Disposal piping numbers - do NOT hardcode these, use the defines
#define DISP_PIPE_STRAIGHT		0
#define DISP_PIPE_BENT			1
#define DISP_JUNCTION			2
#define DISP_JUNCTION_FLIP		3
#define DISP_YJUNCTION			4
#define DISP_END_TRUNK			5
#define DISP_END_BIN			6
#define DISP_END_OUTLET			7
#define DISP_END_CHUTE			8
#define DISP_SORTJUNCTION		9
#define DISP_SORTJUNCTION_FLIP	10

/obj/item/pipe
	name = "pipe"
	desc = "A pipe"
	var/pipe_type = 0
	var/pipename
	force = 7
	icon = 'icons/obj/pipe-item.dmi'
	icon_state = "simple"
	item_state = "buildpipe"
	w_class = 3
	level = 2
	var/flipped = 0

/obj/item/pipe/New(loc, pipe_type, dir, obj/machinery/atmospherics/make_from)
	..()
	if (make_from)
		src.dir = make_from.dir
		src.pipename = make_from.name
		src.color = make_from.color
		var/is_bent
		if  (make_from.initialize_directions in list(NORTH|SOUTH, WEST|EAST))
			is_bent = 0
		else
			is_bent = 1
		if     (istype(make_from, /obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction))
			src.pipe_type = PIPE_JUNCTION
		else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple/heat_exchanging))
			src.pipe_type = PIPE_HE_STRAIGHT + is_bent
		else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple/insulated))
			src.pipe_type = PIPE_INSULATED_STRAIGHT + is_bent
		else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple))
			src.pipe_type = PIPE_SIMPLE_STRAIGHT + is_bent
		else if(istype(make_from, /obj/machinery/atmospherics/unary/portables_connector))
			src.pipe_type = PIPE_CONNECTOR
		else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold))
			src.pipe_type = PIPE_MANIFOLD
		else if(istype(make_from, /obj/machinery/atmospherics/unary/vent_pump))
			src.pipe_type = PIPE_UVENT
		else if(istype(make_from, /obj/machinery/atmospherics/binary/valve/digital))
			src.pipe_type = PIPE_DVALVE
		else if(istype(make_from, /obj/machinery/atmospherics/binary/valve))
			src.pipe_type = PIPE_MVALVE
		else if(istype(make_from, /obj/machinery/atmospherics/binary/pump))
			src.pipe_type = PIPE_PUMP
		else if(istype(make_from, /obj/machinery/atmospherics/trinary/filter))
			src.pipe_type = PIPE_GAS_FILTER
		else if(istype(make_from, /obj/machinery/atmospherics/trinary/mixer))
			src.pipe_type = PIPE_GAS_MIXER
		else if(istype(make_from, /obj/machinery/atmospherics/unary/vent_scrubber))
			src.pipe_type = PIPE_SCRUBBER
		else if(istype(make_from, /obj/machinery/atmospherics/binary/passive_gate))
			src.pipe_type = PIPE_PASSIVE_GATE
		else if(istype(make_from, /obj/machinery/atmospherics/binary/volume_pump))
			src.pipe_type = PIPE_VOLUME_PUMP
		else if(istype(make_from, /obj/machinery/atmospherics/unary/heat_exchanger))
			src.pipe_type = PIPE_HEAT_EXCHANGE
		else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold4w))
			src.pipe_type = PIPE_4WAYMANIFOLD

		var/obj/machinery/atmospherics/trinary/triP = make_from
		if(istype(triP) && triP.flipped)
			src.flipped = 1
			src.dir = turn(src.dir, -45)

	else
		src.pipe_type = pipe_type
		src.dir = dir
	//src.pipe_dir = get_pipe_dir()
	update()
	src.pixel_x = rand(-5, 5)
	src.pixel_y = rand(-5, 5)

//update the name and icon of the pipe item depending on the type
var/global/list/pipeID2State = list(
	"simple", \
	"simple", \
	"he", \
	"he", \
	"connector", \
	"manifold", \
	"junction", \
	"uvent", \
	"mvalve", \
	"pump", \
	"scrubber", \
	"insulated", \
	"insulated", \
	"filter", \
	"mixer", \
	"passivegate", \
	"volumepump", \
	"heunary", \
	"dvalve", \
	"manifold4w", \
)

/obj/item/pipe/proc/update()
	var/list/nlist = list( \
		"pipe", \
		"bent pipe", \
		"h/e pipe", \
		"bent h/e pipe", \
		"connector", \
		"manifold", \
		"junction", \
		"vent", \
		"manual valve", \
		"pump", \
		"scrubber", \
		"insulated pipe", \
		"bent insulated pipe", \
		"gas filter", \
		"gas mixer", \
		"passive gate", \
		"volume pump", \
		"heat exchanger", \
		"digital valve", \
		"4-way manifold", \
	)
	name = nlist[pipe_type+1] + " fitting"
	icon_state = pipeID2State[pipe_type + 1]

//called when a turf is attacked with a pipe item
// place the pipe on the turf, setting pipe level to 1 (underfloor) if the turf is not intact

// rotate the pipe item clockwise

/obj/item/pipe/verb/rotate()
	set category = "Object"
	set name = "Rotate Pipe"
	set src in view(1)

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

	src.dir = turn(src.dir, -90)

	fixdir()

	return

/obj/item/pipe/verb/flip()
	set category = "Object"
	set name = "Flip Pipe"
	set src in view(1)

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

	if (pipe_type in list(PIPE_GAS_FILTER, PIPE_GAS_MIXER))
		src.dir = turn(src.dir, flipped ? 45 : -45)
		flipped = !flipped
		return

	src.dir = turn(src.dir, -180)

	fixdir()

	return

/obj/item/pipe/Move()
	..()
	if ((pipe_type in list (PIPE_SIMPLE_BENT, PIPE_HE_BENT, PIPE_INSULATED_BENT)) \
		&& (src.dir in cardinal))
		src.dir = src.dir|turn(src.dir, 90)
	else if ((pipe_type in list(PIPE_GAS_FILTER, PIPE_GAS_MIXER)) && flipped)
		src.dir = turn(src.dir, 45+90)
	else if (pipe_type in list (PIPE_SIMPLE_STRAIGHT, PIPE_HE_STRAIGHT, PIPE_INSULATED_STRAIGHT, PIPE_MVALVE, PIPE_DVALVE))
		if(dir==2)
			dir = 1
		else if(dir==8)
			dir = 4
	return

// returns all pipe's endpoints

/obj/item/pipe/proc/get_pipe_dir()
	if (!dir)
		return 0

	var/direct = dir
	if(flipped)
		direct = turn(dir, 45)

	var/flip = turn(direct, 180)
	var/cw = turn(direct, -90)
	var/acw = turn(direct, 90)

	switch(pipe_type)
		if(	PIPE_SIMPLE_STRAIGHT, \
			PIPE_INSULATED_STRAIGHT, \
			PIPE_HE_STRAIGHT, \
			PIPE_JUNCTION, \
			PIPE_PUMP, \
			PIPE_VOLUME_PUMP, \
			PIPE_PASSIVE_GATE, \
			PIPE_MVALVE, \
			PIPE_DVALVE \
		)
			return direct|flip
		if(PIPE_SIMPLE_BENT, PIPE_INSULATED_BENT, PIPE_HE_BENT)
			return direct //dir|acw
		if(PIPE_CONNECTOR,PIPE_UVENT,PIPE_SCRUBBER,PIPE_HEAT_EXCHANGE)
			return direct
		if(PIPE_MANIFOLD)
			return flip|cw|acw
		if(PIPE_4WAYMANIFOLD)
			return NORTH|SOUTH|EAST|WEST
		if(PIPE_GAS_FILTER, PIPE_GAS_MIXER)
			return direct|flip|cw
	return 0

/obj/item/pipe/proc/get_pdir() //endpoints for regular pipes

	var/flip = turn(dir, 180)
//	var/cw = turn(dir, -90)
//	var/acw = turn(dir, 90)

	if (!(pipe_type in list(PIPE_HE_STRAIGHT, PIPE_HE_BENT, PIPE_JUNCTION)))
		return get_pipe_dir()
	switch(pipe_type)
		if(PIPE_HE_STRAIGHT,PIPE_HE_BENT)
			return 0
		if(PIPE_JUNCTION)
			return flip
	return 0

// return the h_dir (heat-exchange pipes) from the type and the dir

/obj/item/pipe/proc/get_hdir() //endpoints for h/e pipes

//	var/flip = turn(dir, 180)
//	var/cw = turn(dir, -90)

	switch(pipe_type)
		if(PIPE_HE_STRAIGHT)
			return get_pipe_dir()
		if(PIPE_HE_BENT)
			return get_pipe_dir()
		if(PIPE_JUNCTION)
			return dir
		else
			return 0

/obj/item/pipe/proc/unflip(var/direction)
	if(!(direction in cardinal))
		return turn(direction, 45)

	return direction

//Helper to clean up dir
/obj/item/pipe/proc/fixdir()
	if (pipe_type in list (PIPE_SIMPLE_STRAIGHT, PIPE_HE_STRAIGHT, PIPE_INSULATED_STRAIGHT, PIPE_MVALVE, PIPE_DVALVE))
		if(dir==2)
			dir = 1
		else if(dir==8)
			dir = 4

/obj/item/pipe/attack_self(mob/user as mob)
	return rotate()

/obj/item/pipe/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob, params)

	//*
	if (!istype(W, /obj/item/weapon/wrench))
		return ..()
	if (!isturf(src.loc))
		return 1

	fixdir()

	var/pipe_dir = get_pipe_dir()

	for(var/obj/machinery/atmospherics/M in src.loc)
		if(M.initialize_directions & pipe_dir)	// matches at least one direction on either type of pipe
			user << "There is already a pipe at that location."
			return 1
	// no conflicts found

	switch(pipe_type)
		if(PIPE_SIMPLE_STRAIGHT, PIPE_SIMPLE_BENT)
			var/obj/machinery/atmospherics/pipe/simple/P = new( src.loc )
			P.construction(dir, pipe_dir, pipe_type, color)

		if(PIPE_HE_STRAIGHT, PIPE_HE_BENT)
			var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/P = new ( src.loc )
			P.initialize_directions_he = pipe_dir
			P.construction(dir, pipe_dir, pipe_type, color)

		if(PIPE_CONNECTOR)
			var/obj/machinery/atmospherics/unary/portables_connector/C = new( src.loc )
			if (pipename)
				C.name = pipename
			C.construction(dir, pipe_dir, pipe_type, color)

		if(PIPE_MANIFOLD)
			var/obj/machinery/atmospherics/pipe/manifold/M = new(loc)
			M.construction(dir, pipe_dir, pipe_type, color)

		if(PIPE_4WAYMANIFOLD)
			var/obj/machinery/atmospherics/pipe/manifold4w/M = new( src.loc )
			M.construction(dir, pipe_dir, pipe_type, color)

		if(PIPE_JUNCTION)
			var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/P = new ( src.loc )
			P.initialize_directions_he = src.get_hdir()
			P.construction(dir, get_pdir(), pipe_type, color)

		if(PIPE_UVENT)
			var/obj/machinery/atmospherics/unary/vent_pump/V = new( src.loc )
			V.construction(dir, pipe_dir, pipe_type, color)

		if(PIPE_MVALVE)
			var/obj/machinery/atmospherics/binary/valve/V = new(src.loc)
			if (pipename)
				V.name = pipename
			V.construction(dir, get_pdir(), pipe_type, color)

		if(PIPE_DVALVE)
			var/obj/machinery/atmospherics/binary/valve/digital/V = new(src.loc)
			if (pipename)
				V.name = pipename
			V.construction(dir, get_pdir(), pipe_type, color)

		if(PIPE_PUMP)
			var/obj/machinery/atmospherics/binary/pump/P = new(src.loc)
			P.construction(dir, pipe_dir, pipe_type, color)

		if(PIPE_GAS_FILTER, PIPE_GAS_MIXER)
			var/obj/machinery/atmospherics/trinary/P
			if(pipe_type == PIPE_GAS_FILTER)
				P = new /obj/machinery/atmospherics/trinary/filter(src.loc)
			else if(pipe_type == PIPE_GAS_MIXER)
				P = new /obj/machinery/atmospherics/trinary/mixer(src.loc)
			P.flipped = flipped
			if (pipename)
				P.name = pipename
			P.construction(unflip(dir), pipe_dir, pipe_type, color)

		if(PIPE_SCRUBBER)
			var/obj/machinery/atmospherics/unary/vent_scrubber/S = new(src.loc)
			if (pipename)
				S.name = pipename
			S.construction(dir, pipe_dir, pipe_type, color)

		if(PIPE_INSULATED_STRAIGHT, PIPE_INSULATED_BENT)
			var/obj/machinery/atmospherics/pipe/simple/insulated/P = new( src.loc )
			P.construction(dir, pipe_dir, pipe_type, color)

		if(PIPE_PASSIVE_GATE)
			var/obj/machinery/atmospherics/binary/passive_gate/P = new(src.loc)
			if (pipename)
				P.name = pipename
			P.construction(dir, pipe_dir, pipe_type, color)

		if(PIPE_VOLUME_PUMP)
			var/obj/machinery/atmospherics/binary/volume_pump/P = new(src.loc)
			if (pipename)
				P.name = pipename
			P.construction(dir, pipe_dir, pipe_type, color)

		if(PIPE_HEAT_EXCHANGE)
			var/obj/machinery/atmospherics/unary/heat_exchanger/C = new( src.loc )
			if (pipename)
				C.name = pipename
			C.construction(dir, pipe_dir, pipe_type, color)

	playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
	user.visible_message( \
		"[user] fastens \the [src].", \
		"You have fastened \the [src].", \
		"You hear ratchet.")

	qdel(src)	// remove the pipe item

	return
	 //TODO: DEFERRED

// ensure that setterm() is called for a newly connected pipeline

/obj/item/pipe_meter
	name = "meter"
	desc = "A meter that can be laid on pipes"
	icon = 'icons/obj/pipe-item.dmi'
	icon_state = "meter"
	item_state = "buildpipe"
	w_class = 4

/obj/item/pipe_meter/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob, params)
	..()

	if (!istype(W, /obj/item/weapon/wrench))
		return ..()
	if(!locate(/obj/machinery/atmospherics/pipe, src.loc))
		user << "You need to fasten it to a pipe."
		return 1
	new/obj/machinery/meter( src.loc )
	playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
	user << "You have fastened the meter to the pipe."
	qdel(src)


code:
/obj/machinery/pipedispenser
	name = "pipe dispenser"
	icon = 'icons/obj/stationobjs.dmi'
	icon_state = "pipe_d"
	density = 1
	anchored = 1
	var/wait = 0

/obj/machinery/pipedispenser/attack_paw(user as mob)
	return src.attack_hand(user)

/obj/machinery/pipedispenser/attack_hand(user as mob)
	if(..())
		return 1
	var/dat = {"
Regular pipes:

Pipe

Bent Pipe

Manifold

4-Way Manifold

Manual Valve

Digital Valve

Devices:

Connector

Vent

Gas Pump

Passive Gate

Volume Pump

Scrubber

Meter

Gas Filter

Gas Mixer

Heat exchange:

Pipe

Bent Pipe

Junction

Heat Exchanger

Insulated pipes:

Pipe

Bent Pipe

"}

	user << browse("<TITLE>[src]</TITLE><TT>[dat]</TT>", "window=pipedispenser")
	onclose(user, "pipedispenser")
	return

/obj/machinery/pipedispenser/Topic(href, href_list)
	if(..())
		return 1
	if(!anchored|| !usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
		usr << browse(null, "window=pipedispenser")
		return 1
	usr.set_machine(src)
	src.add_fingerprint(usr)
	if(href_list["make"])
		if(!wait)
			var/p_type = text2num(href_list["make"])
			var/p_dir = text2num(href_list["dir"])
			var/obj/item/pipe/P = new (/*usr.loc*/ src.loc, pipe_type=p_type, dir=p_dir)
			P.update()
			P.add_fingerprint(usr)
			wait = 1
			spawn(10)
				wait = 0
	if(href_list["makemeter"])
		if(!wait)
			new /obj/item/pipe_meter(/*usr.loc*/ src.loc)
			wait = 1
			spawn(15)
				wait = 0
	return

/obj/machinery/pipedispenser/attackby(var/obj/item/W as obj, var/mob/user as mob, params)
	add_fingerprint(user)
	if (istype(W, /obj/item/pipe) || istype(W, /obj/item/pipe_meter))
		usr << "You put [W] back into [src]."
		user.drop_item()
		qdel(W)
		return
	else if (istype(W, /obj/item/weapon/wrench))
		if (!anchored && !isinspace())
			playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
			user << "You begin to fasten \the [src] to the floor..."
			if (do_after(user, 40))
				add_fingerprint(user)
				user.visible_message( \
					"[user] fastens \the [src].", \
					"You have fastened \the [src]. Now it can dispense pipes.", \
					"You hear ratchet.")
				anchored = 1
				stat &= MAINT
				if (usr.machine==src)
					usr << browse(null, "window=pipedispenser")
		else if(anchored)
			playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
			user << "You begin to unfasten \the [src] from the floor..."
			if (do_after(user, 20))
				add_fingerprint(user)
				user.visible_message( \
					"[user] unfastens \the [src].", \
					"You have unfastened \the [src]. Now it can be pulled somewhere else.", \
					"You hear ratchet.")
				anchored = 0
				stat |= ~MAINT
				power_change()
	else
		return ..()

/obj/machinery/pipedispenser/disposal
	name = "disposal pipe dispenser"
	icon = 'icons/obj/stationobjs.dmi'
	icon_state = "pipe_d"
	density = 1
	anchored = 1.0

/*
//Allow you to push disposal pipes into it (for those with density 1)
/obj/machinery/pipedispenser/disposal/Crossed(var/obj/structure/disposalconstruct/pipe as obj)
	if(istype(pipe) && !pipe.anchored)
		qdel(pipe)

Nah
*/

//Allow you to drag-drop disposal pipes and transit tubes into it
/obj/machinery/pipedispenser/disposal/MouseDrop_T(var/obj/structure/pipe as obj, mob/usr as mob)
	if(!usr.canmove || usr.stat || usr.restrained())
		return

	if (!istype(pipe, /obj/structure/disposalconstruct) && !istype(pipe, /obj/structure/c_transit_tube) && !istype(pipe, /obj/structure/c_transit_tube_pod))
		return

	if (get_dist(usr, src) > 1 || get_dist(src,pipe) > 1 )
		return

	if (pipe.anchored)
		return

	qdel(pipe)

/obj/machinery/pipedispenser/disposal/attack_hand(user as mob)
	if(..())
		return 1

	var/dat = {"Disposal Pipes

Pipe

Bent Pipe

Junction

Y-Junction

Trunk

Bin

Outlet

Chute

Sort Junction

"}

	user << browse("<TITLE>[src]</TITLE><TT>[dat]</TT>", "window=pipedispenser")
	return

/obj/machinery/pipedispenser/disposal/Topic(href, href_list)
	if(..())
		return 1
	usr.set_machine(src)
	src.add_fingerprint(usr)
	if(href_list["dmake"])
		if(!wait)
			var/p_type = text2num(href_list["dmake"])
			var/obj/structure/disposalconstruct/C = new (src.loc,p_type)

			if(!C.can_place())
				usr << "There's not enough room to build that here!"
				qdel(C)
				return

			C.add_fingerprint(usr)
			C.update()
			wait = 1
			spawn(15)
				wait = 0
	return

//transit tube dispenser
//inherit disposal for the dragging proc
/obj/machinery/pipedispenser/disposal/transit_tube
	name = "transit tube dispenser"
	icon = 'icons/obj/stationobjs.dmi'
	icon_state = "pipe_d"
	density = 1
	anchored = 1.0

/obj/machinery/pipedispenser/disposal/transit_tube/attack_hand(user as mob)
	if(..())
		return 1

	var/dat = {"Transit Tubes:

Straight Tube

Straight Tube with Crossing

Curved Tube

Diagonal Tube

Junction

Station Equipment:

Through Tube Station

Terminus Tube Station

Tube Blocker

Transit Tube Pod

"}

	user << browse("<TITLE>[src]</TITLE><TT>[dat]</TT>", "window=pipedispenser")
	return

/obj/machinery/pipedispenser/disposal/transit_tube/Topic(href, href_list)
	if(..())
		return 1
	usr.set_machine(src)
	src.add_fingerprint(usr)
	if(!wait)
		if(href_list["tube"])
			var/tube_type = text2num(href_list["tube"])
			if(tube_type <= 4)
				var/obj/structure/c_transit_tube/C = new/obj/structure/c_transit_tube(src.loc)
				switch(tube_type)
					if(0)
						C.icon_state = "E-W"
					if(1)
						C.icon_state = "E-W-Pass"
					if(2)
						C.icon_state = "S-NE"
					if(3)
						C.icon_state = "NE-SW"
					if(4)
						C.icon_state = "W-NE-SE"
				C.add_fingerprint(usr)
			else
				switch(tube_type)
					if(5)
						var/obj/structure/c_transit_tube/station/C = new/obj/structure/c_transit_tube/station(src.loc)
						C.add_fingerprint(usr)
					if(6)
						var/obj/structure/c_transit_tube/station/reverse/C = new/obj/structure/c_transit_tube/station/reverse(src.loc)
						C.add_fingerprint(usr)
					if(7)
						var/obj/structure/c_transit_tube/station/block/C = new/obj/structure/c_transit_tube/station/block(src.loc)
						C.add_fingerprint(usr)
					if(8)
						var/obj/structure/c_transit_tube_pod/C = new/obj/structure/c_transit_tube_pod(src.loc)
						C.add_fingerprint(usr)
			wait = 1
			spawn(15)
				wait = 0
	return


code:
/*		Portable Turrets:
		Constructed from metal, a gun of choice, and a prox sensor.
		This code is slightly more documented than normal, as requested by XSI on IRC.
*/

/obj/machinery/porta_turret
	name = "turret"
	icon = 'icons/obj/turrets.dmi'
	icon_state = "grey_target_prism"
	anchored = 1
	layer = 3
	invisibility = INVISIBILITY_LEVEL_TWO	//the turret is invisible if it's inside its cover
	density = 1
	use_power = 1				//this turret uses and requires power
	idle_power_usage = 50		//when inactive, this turret takes up constant 50 Equipment power
	active_power_usage = 300	//when active, this turret takes up constant 300 Equipment power
	req_access = list(access_security)
	power_channel = EQUIP	//drains power from the EQUIPMENT channel

	var/lasercolor = ""		//Something to do with lasertag turrets, blame Sieve for not adding a comment.
	var/raised = 0			//if the turret cover is "open" and the turret is raised
	var/raising= 0			//if the turret is currently opening or closing its cover
	var/health = 80			//the turret's health
	var/locked = 1			//if the turret's behaviour control access is locked
	var/controllock = 0		//if the turret responds to control panels

	var/installation = /obj/item/weapon/gun/energy/gun/turret		//the type of weapon installed
	var/gun_charge = 0		//the charge of the gun inserted
	var/projectile = null	//holder for bullettype
	var/eprojectile = null	//holder for the shot when emagged
	var/reqpower = 500		//holder for power needed
	var/iconholder = null	//holder for the icon_state. 1 for orange sprite, null for blue.
	var/egun = null			//holder to handle certain guns switching bullettypes

	var/obj/machinery/porta_turret_cover/cover = null	//the cover that is covering this turret
	var/last_fired = 0		//1: if the turret is cooling down from a shot, 0: turret is ready to fire
	var/shot_delay = 15		//1.5 seconds between each shot

	var/check_records = 1	//checks if it can use the security records
	var/criminals = 1		//checks if it can shoot people on arrest
	var/auth_weapons = 0	//checks if it can shoot people that have a weapon they aren't authorized to have
	var/stun_all = 0		//if this is active, the turret shoots everything that isn't security or head of staff
	var/check_anomalies = 1	//checks if it can shoot at unidentified lifeforms (ie xenos)
	var/ai		 = 0 		//if active, will shoot at anything not an AI or cyborg

	var/attacked = 0		//if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!)

	var/on = 1				//determines if the turret is on
	var/disabled = 0

	var/shot_sound 			//what sound should play when the turret fires
	var/eshot_sound			//what sound should play when the emagged turret fires

	var/faction = "neutral"

	var/datum/effect/effect/system/spark_spread/spark_system	//the spark system, used for generating... sparks?

/obj/machinery/porta_turret/New()
	..()
	icon_state = "[lasercolor]grey_target_prism"
	//Sets up a spark system
	spark_system = new /datum/effect/effect/system/spark_spread
	spark_system.set_up(5, 0, src)
	spark_system.attach(src)

	cover = new /obj/machinery/porta_turret_cover(loc)
	cover.Parent_Turret = src
	setup()

/obj/machinery/porta_turret/proc/setup()

	var/obj/item/weapon/gun/energy/E=new installation	//All energy-based weapons are applicable
	var/obj/item/ammo_casing/shottype = E.ammo_type[1]

	projectile = shottype.projectile_type
	eprojectile = projectile
	shot_sound = shottype.fire_sound
	eshot_sound = shot_sound

	switch(E.type)
		if(/obj/item/weapon/gun/energy/laser/bluetag)
			eprojectile = /obj/item/projectile/lasertag/bluetag
			lasercolor = "b"
			req_access = list(access_maint_tunnels, access_theatre)
			check_records = 0
			criminals = 0
			auth_weapons = 1
			stun_all = 0
			check_anomalies = 0
			shot_delay = 30

		if(/obj/item/weapon/gun/energy/laser/redtag)
			eprojectile = /obj/item/projectile/lasertag/redtag
			lasercolor = "r"
			req_access = list(access_maint_tunnels, access_theatre)
			check_records = 0
			criminals = 0
			auth_weapons = 1
			stun_all = 0
			check_anomalies = 0
			shot_delay = 30
			iconholder = 1

		if(/obj/item/weapon/gun/energy/laser/practice)
			iconholder = 1
			eprojectile = /obj/item/projectile/beam

//			if(/obj/item/weapon/gun/energy/laser/practice/sc_laser)
//				iconholder = 1
//				eprojectile = /obj/item/projectile/beam

		if(/obj/item/weapon/gun/energy/laser/retro)
			iconholder = 1

//			if(/obj/item/weapon/gun/energy/laser/retro/sc_retro)
//				iconholder = 1

		if(/obj/item/weapon/gun/energy/laser/captain)
			iconholder = 1

		if(/obj/item/weapon/gun/energy/lasercannon)
			iconholder = 1

		if(/obj/item/weapon/gun/energy/gun/advtaser)
			eprojectile = /obj/item/projectile/beam
			eshot_sound = 'sound/weapons/Laser.ogg'

		if(/obj/item/weapon/gun/energy/gun)
			eprojectile = /obj/item/projectile/beam	//If it has, going to kill mode
			eshot_sound = 'sound/weapons/Laser.ogg'
			egun = 1

		if(/obj/item/weapon/gun/energy/gun/nuclear)
			eprojectile = /obj/item/projectile/beam	//If it has, going to kill mode
			eshot_sound = 'sound/weapons/Laser.ogg'
			egun = 1

		if(/obj/item/weapon/gun/energy/gun/turret)
			eprojectile = /obj/item/projectile/beam	//If it has, going to copypaste mode
			eshot_sound = 'sound/weapons/Laser.ogg'
			egun = 1

/obj/machinery/porta_turret/Destroy()
	//deletes its own cover with it
	qdel(cover)
	cover = null
	..()

/obj/machinery/porta_turret/attack_ai(mob/user)
	return attack_hand(user)

/obj/machinery/porta_turret/attack_hand(mob/user)
	. = ..()
	if(.)
		return
	var/dat

	//The browse() text, similar to ED-209s and beepskies.
	if(!lasercolor)	//Lasertag turrets have less options
		dat += text({"
					<TT>Automatic Portable Turret Installation</TT>

					Status: []

					Behaviour controls are [locked ? "locked" : "unlocked"]"},

					"[on ? "On" : "Off"]" )

		if(!locked)
			dat += text({"

						Check for Weapon Authorization: []

						Check Security Records: []

						Neutralize Identified Criminals: []

						Neutralize All Non-Security and Non-Command Personnel: []

						Neutralize All Unidentified Life Signs: []
"},

						"[auth_weapons ? "Yes" : "No"]",
						"[check_records ? "Yes" : "No"]",
						"[criminals ? "Yes" : "No"]",
						"[stun_all ? "Yes" : "No"]",
						"[check_anomalies ? "Yes" : "No"]" )
	else
		if(istype(user,/mob/living/carbon/human))
			var/mob/living/carbon/human/H = user
			if(lasercolor == "b" && istype(H.wear_suit, /obj/item/clothing/suit/redtag))
				return
			if(lasercolor == "r" && istype(H.wear_suit, /obj/item/clothing/suit/bluetag))
				return
		dat += text({"
					<TT>Automatic Portable Turret Installation</TT>

					Status: []
"},

					"[on ? "On" : "Off"]" )

	user << browse("<TITLE>Automatic Portable Turret Installation</TITLE>[dat]", "window=autosec")
	onclose(user, "autosec")
	return

/obj/machinery/porta_turret/Topic(href, href_list)
	if(..())
		return
	usr.set_machine(src)
	add_fingerprint(usr)
	if(href_list["power"] && !locked)
		if(anchored)	//you can't turn a turret on/off if it's not anchored/secured
			on = !on	//toggle on/off
		else
			usr << "It has to be secured first!"

		updateUsrDialog()
		return

	switch(href_list["operation"])	//toggles customizable behavioural protocols
		if("authweapon")
			auth_weapons = !auth_weapons
		if("checkrecords")
			check_records = !check_records
		if("shootcrooks")
			criminals = !criminals
		if("shootall")
			stun_all = !stun_all
	updateUsrDialog()

/obj/machinery/porta_turret/power_change()

	if(!anchored)
		icon_state = "turretCover"
		return
	if(stat & BROKEN)
		icon_state = "[lasercolor]destroyed_target_prism"
	else
		if( powered() )
			if(on)
				if(iconholder)
					//lasers have a orange icon
					icon_state = "[lasercolor]orange_target_prism"
				else
					//almost everything has a blue icon
					icon_state = "[lasercolor]target_prism"
			else
				icon_state = "[lasercolor]grey_target_prism"
			stat &= ~NOPOWER
		else
			spawn(rand(0, 15))
				icon_state = "[lasercolor]grey_target_prism"
				stat |= NOPOWER

/obj/machinery/porta_turret/attackby(obj/item/I, mob/user, params)
	if(stat & BROKEN)
		if(istype(I, /obj/item/weapon/crowbar))
			//If the turret is destroyed, you can remove it with a crowbar to
			//try and salvage its components
			user << "You begin prying the metal coverings off."
			sleep(20)
			if(prob(70))
				user << "You remove the turret and salvage some components."
				if(installation)
					var/obj/item/weapon/gun/energy/Gun = new installation(loc)
					Gun.power_supply.charge = gun_charge
					Gun.update_icon()
					lasercolor = null
				if(prob(50))
					new /obj/item/stack/sheet/metal(loc, rand(1,4))
				if(prob(50))
					new /obj/item/device/assembly/prox_sensor(loc)
			else
				user << "You remove the turret but did not manage to salvage anything."
			qdel(src)

	else if((istype(I, /obj/item/weapon/wrench)) && (!on))
		if(raised) return
		//This code handles moving the turret around. After all, it's a portable turret!
		if(!anchored && !isinspace())
			anchored = 1
			invisibility = INVISIBILITY_LEVEL_TWO
			icon_state = "[lasercolor]grey_target_prism"
			user << "You secure the exterior bolts on the turret."
			cover = new /obj/machinery/porta_turret_cover(loc) //create a new turret. While this is handled in process(), this is to workaround a bug where the turret becomes invisible for a split second
			cover.Parent_Turret = src //make the cover's parent src
		else if(anchored)
			anchored = 0
			user << "You unsecure the exterior bolts on the turret."
			icon_state = "turretCover"
			invisibility = 0
			qdel(cover) //deletes the cover, and the turret instance itself becomes its own cover.

	else if(istype(I, /obj/item/weapon/card/id)||istype(I, /obj/item/device/pda))
		//Behavior lock/unlock mangement
		if(allowed(user))
			locked = !locked
			user << "Controls are now [locked ? "locked" : "unlocked"]."
		else
			user << "Access denied."

	else
		//if the turret was attacked with the intention of harming it:
		user.changeNext_move(CLICK_CD_MELEE)
		health -= I.force * 0.5
		if(health <= 0)
			die()
		if(I.force * 0.5 > 1) //if the force of impact dealt at least 1 damage, the turret gets pissed off
			if(!attacked && !emagged)
				attacked = 1
				spawn()
					sleep(60)
					attacked = 0
		..()

/obj/machinery/porta_turret/emag_act(user as mob)
	if(!emagged)
		user << "You short out [src]'s threat assessment circuits."
		visible_message("[src] hums oddly...")
		emagged = 1
		iconholder = 1
		controllock = 1
		on = 0 //turns off the turret temporarily
		sleep(60) //6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit
		on = 1 //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here

/obj/machinery/porta_turret/bullet_act(obj/item/projectile/Proj)
	if(on)
		if(!attacked && !emagged)
			attacked = 1
			spawn()
				sleep(60)
				attacked = 0

	if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
		health -= Proj.damage

	..()

	if(prob(45) && Proj.damage > 0)
		spark_system.start()
	if(health <= 0)
		die()	//the death process :(

	if(lasercolor == "b" && disabled == 0)
		if(istype(Proj, /obj/item/projectile/lasertag/redtag))
			disabled = 1
			qdel(Proj)
			sleep(100)
			disabled = 0
	if(lasercolor == "r" && disabled == 0)
		if(istype(Proj, /obj/item/projectile/lasertag/bluetag))
			disabled = 1
			qdel(Proj)
			sleep(100)
			disabled = 0

/obj/machinery/porta_turret/emp_act(severity)
	if(on)
		//if the turret is on, the EMP no matter how severe disables the turret for a while
		//and scrambles its settings, with a slight chance of having an emag effect
		check_records = pick(0, 1)
		criminals = pick(0, 1)
		auth_weapons = pick(0, 1)
		stun_all = pick(0, 0, 0, 0, 1)	//stun_all is a pretty big deal, so it's least likely to get turned on
		if(prob(5))
			emagged = 1

		on=0
		spawn(rand(60,600))
			if(!on)
				on=1

	..()

/obj/machinery/porta_turret/ex_act(severity, target)
	if(severity >= 3)	//turret dies if an explosion touches it!
		qdel(src)
	else
		die()

/obj/machinery/porta_turret/proc/die()	//called when the turret dies, ie, health <= 0
	health = 0
	density = 0
	stat |= BROKEN	//enables the BROKEN bit
	icon_state = "[lasercolor]destroyed_target_prism"
	invisibility = 0
	spark_system.start()	//creates some sparks because they look cool
	density = 1
	qdel(cover)	//deletes the cover - no need on keeping it there!

/obj/machinery/porta_turret/process()
	//the main machinery process

	set background = BACKGROUND_ENABLED

	if(cover == null && anchored)	//if it has no cover and is anchored
		if(stat & BROKEN)	//if the turret is borked
			qdel(cover)	//delete its cover, assuming it has one. Workaround for a pesky little bug
		else

			cover = new /obj/machinery/porta_turret_cover(loc)	//if the turret has no cover and is anchored, give it a cover
			cover.Parent_Turret = src	//assign the cover its Parent_Turret, which would be this (src)

	if(stat & (NOPOWER|BROKEN))
		//if the turret has no power or is broken, make the turret pop down if it hasn't already
		popDown()
		return

	if(!on)
		//if the turret is off, make it pop down
		popDown()
		return

	var/list/targets = list()			//list of primary targets
	var/turretview = view(7, src)

	if(check_anomalies)	//if it's set to check for xenos/simpleanimals
		for(var/mob/living/simple_animal/SA in turretview)
			if(!SA.stat && (!SA.has_unlimited_silicon_privilege || !(faction in SA.faction)) ) //don't target dead animals or NT maint drones.
				targets += SA
		for(var/mob/living/carbon/monkey/M in turretview)
			if(!M.stat)
				targets += M

	for(var/mob/living/carbon/C in turretview)	//loops through all carbon-based lifeforms in view(7)
		if(emagged && C.stat != DEAD)	//if emagged, every living carbon is a target.
			targets += C
			continue

		if(C.stat || C.handcuffed || C.lying)	//if the perp is handcuffed or lying or dead/dying, no need to bother really
			continue

		if(ai)	//If it's set to attack all nonsilicons, target them!
			targets += C
			continue

		if(istype(C, /mob/living/carbon/human))	//if the target is a human, analyze threat level
			if(assess_perp(C) >= 4)
				targets += C

		else if(check_anomalies)
			if(!(faction in C.faction))
				for(var/F in C.faction) //We target carbons without the portaturret's faction and who also have alien or slime faction.
					if(F == "alien" || F == "slime")
						targets += C
						break

	for(var/obj/mecha/M in turretview)
		if(M.occupant)
			if(ai || emagged) // we target all occupied mechs if we're emagged or set to attack all non silicons.
				targets += M

	if(!tryToShootAt(targets))
		spawn()
			popDown() // no valid targets, close the cover

/obj/machinery/porta_turret/proc/tryToShootAt(var/list/atom/movable/targets)
	while(targets.len > 0)
		var/atom/movable/M = pick(targets)
		targets -= M
		if(target(M))
			return 1

/obj/machinery/porta_turret/proc/popUp()	//pops the turret up
	if(disabled)
		return
	if(raising || raised)
		return
	if(stat & BROKEN)
		return
	invisibility = 0
	raising = 1
	flick("popup", cover)
	sleep(10)
	raising = 0
	if(cover)
		cover.icon_state = "openTurretCover"
	raised = 1
	layer = 4

/obj/machinery/porta_turret/proc/popDown()	//pops the turret down
	if(disabled)
		return
	if(raising || !raised)
		return
	if(stat & BROKEN)
		return
	layer = 3
	raising = 1
	flick("popdown", cover)
	sleep(10)
	raising = 0
	cover.icon_state = "turretCover"
	raised = 0
	invisibility = 2
	icon_state = "[lasercolor]grey_target_prism"

/obj/machinery/porta_turret/proc/assess_perp(mob/living/carbon/human/perp)
	var/threatcount = 0	//the integer returned

	if(emagged)
		return 10	//if emagged, always return 10.

	if((stun_all || attacked) && !allowed(perp))
		//if the turret has been attacked or is angry, target all non-sec people
		if(!allowed(perp))
			return 10

	if(auth_weapons)	//check for weapon authorization
		if(isnull(perp.wear_id) || istype(perp.wear_id.GetID(), /obj/item/weapon/card/id/syndicate))

			if(allowed(perp) && !lasercolor) //if the perp has security access, return 0
				return 0

			if((istype(perp.l_hand, /obj/item/weapon/gun) && !istype(perp.l_hand, /obj/item/weapon/gun/projectile/revolver/doublebarrel)) || istype(perp.l_hand, /obj/item/weapon/melee/baton))
				threatcount += 4

			if((istype(perp.r_hand, /obj/item/weapon/gun) && !istype(perp.r_hand, /obj/item/weapon/gun/projectile/revolver/doublebarrel)) || istype(perp.r_hand, /obj/item/weapon/melee/baton))
				threatcount += 4

			if(istype(perp.belt, /obj/item/weapon/gun) || istype(perp.belt, /obj/item/weapon/melee/baton))
				threatcount += 2

	if(lasercolor == "b")	//Lasertag turrets target the opposing team, how great is that? -Sieve
		threatcount = 0		//But does not target anyone else
		if(istype(perp.wear_suit, /obj/item/clothing/suit/redtag))
			threatcount += 4
		if(istype(perp.r_hand,/obj/item/weapon/gun/energy/laser/redtag) || istype(perp.l_hand,/obj/item/weapon/gun/energy/laser/redtag))
			threatcount += 4
		if(istype(perp.belt, /obj/item/weapon/gun/energy/laser/redtag))
			threatcount += 2

	if(lasercolor == "r")
		threatcount = 0
		if(istype(perp.wear_suit, /obj/item/clothing/suit/bluetag))
			threatcount += 4
		if((istype(perp.r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(perp.l_hand,/obj/item/weapon/gun/energy/laser/bluetag)))
			threatcount += 4
		if(istype(perp.belt, /obj/item/weapon/gun/energy/laser/bluetag))
			threatcount += 2

	if(check_records)	//if the turret can check the records, check if they are set to *Arrest* on records
		var/perpname = perp.get_face_name(perp.get_id_name())
		var/datum/data/record/R = find_record("name", perpname, data_core.security)
		if(!R || (R.fields["criminal"] == "*Arrest*"))
			threatcount += 4

	return threatcount

/obj/machinery/porta_turret/proc/target(var/atom/movable/target)
	if(disabled)
		return
	if(target)
		spawn()
			popUp()				//pop the turret up if it's not already up.
		dir = get_dir(src, target)	//even if you can't shoot, follow the target
		spawn()
			shootAt(target)
		return 1
	return

/obj/machinery/porta_turret/proc/shootAt(var/atom/movable/target)
	if(!emagged)	//if it hasn't been emagged, it has to obey a cooldown rate
		if(last_fired || !raised)	//prevents rapid-fire shooting, unless it's been emagged
			return
		last_fired = 1
		spawn()
			sleep(shot_delay)
			last_fired = 0

	var/turf/T = get_turf(src)
	var/turf/U = get_turf(target)
	if(!istype(T) || !istype(U))
		return

	if(!raised) //the turret has to be raised in order to fire - makes sense, right?
		return

	//any emagged turrets will shoot extremely fast! This not only is deadly, but drains a lot power!
	if(iconholder)
		icon_state = "[lasercolor]orange_target_prism"
	else
		icon_state = "[lasercolor]target_prism"
	var/obj/item/projectile/A
	if(emagged)
		A = new eprojectile(loc)
		playsound(loc, eshot_sound, 75, 1)
	else
		A = new projectile(loc)
		playsound(loc, shot_sound, 75, 1)
	A.original = target
	if(!emagged)
		use_power(reqpower)
	else
		use_power(reqpower * 2)
		//Shooting Code:
	A.current = T
	A.yo = U.y - T.y
	A.xo = U.x - T.x
	A.fire()

/obj/machinery/porta_turret/proc/setState(var/on, var/emagged)
	if(controllock)
		return
	src.on = on
	src.emagged = emagged
	src.iconholder = emagged
	src.power_change()

/*
		Portable turret constructions
		Known as "turret frame"s
*/

/obj/machinery/porta_turret_construct
	name = "turret frame"
	icon = 'icons/obj/turrets.dmi'
	icon_state = "turret_frame"
	density=1
	var/build_step = 0			//the current step in the building process
	var/finish_name="turret"	//the name applied to the product turret
	var/installation = null		//the gun type installed
	var/gun_charge = 0			//the gun charge of the gun type installed

/obj/machinery/porta_turret_construct/attackby(obj/item/I, mob/user, params)
	//this is a bit unwieldy but self-explanatory
	switch(build_step)
		if(0)	//first step
			if(istype(I, /obj/item/weapon/wrench) && !anchored)
				playsound(loc, 'sound/items/Ratchet.ogg', 100, 1)
				user << "You secure the external bolts."
				anchored = 1
				build_step = 1
				return

			else if(istype(I, /obj/item/weapon/crowbar) && !anchored)
				playsound(loc, 'sound/items/Crowbar.ogg', 75, 1)
				user << "You dismantle the turret construction."
				new /obj/item/stack/sheet/metal( loc, 5)
				qdel(src)
				return

		if(1)
			if(istype(I, /obj/item/stack/sheet/metal))
				var/obj/item/stack/sheet/metal/M = I
				if(M.use(2))
					user << "You add some metal armor to the interior frame."
					build_step = 2
					icon_state = "turret_frame2"
				else
					user << "You need two sheets of metal to continue construction."
				return

			else if(istype(I, /obj/item/weapon/wrench))
				playsound(loc, 'sound/items/Ratchet.ogg', 75, 1)
				user << "You unfasten the external bolts."
				anchored = 0
				build_step = 0
				return

		if(2)
			if(istype(I, /obj/item/weapon/wrench))
				playsound(loc, 'sound/items/Ratchet.ogg', 100, 1)
				user << "You bolt the metal armor into place."
				build_step = 3
				return

			else if(istype(I, /obj/item/weapon/weldingtool))
				var/obj/item/weapon/weldingtool/WT = I
				if(!WT.isOn())
					return
				if(WT.get_fuel() < 5) //uses up 5 fuel.
					user << "You need more fuel to complete this task."
					return

				playsound(loc, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1)
				if(do_after(user, 20))
					if(!src || !WT.remove_fuel(5, user)) return
					build_step = 1
					user << "You remove the turret's interior metal armor."
					new /obj/item/stack/sheet/metal( loc, 2)
					return

		if(3)
			if(istype(I, /obj/item/weapon/gun/energy)) //the gun installation part

				if(isrobot(user) && !ismommi(user))
					return
				var/obj/item/weapon/gun/energy/E = I //typecasts the item to an energy gun
				if(!user.unEquip(I))
					user << "\the [I] is stuck to your hand, you cannot put it in \the [src]"
					return
				installation = I.type //installation becomes I.type
				gun_charge = E.power_supply.charge //the gun's charge is stored in gun_charge
				user << "You add [I] to the turret."
				build_step = 4
				qdel(I) //delete the gun :(
				return

			else if(istype(I, /obj/item/weapon/wrench))
				playsound(loc, 'sound/items/Ratchet.ogg', 100, 1)
				user << "You remove the turret's metal armor bolts."
				build_step = 2
				return

		if(4)
			if(isprox(I))
				build_step = 5
				if(!user.unEquip(I))
					user << "\the [I] is stuck to your hand, you cannot put it in \the [src]"
					return
				user << "You add the prox sensor to the turret."
				qdel(I)
				return

			//attack_hand() removes the gun

		if(5)
			if(istype(I, /obj/item/weapon/screwdriver))
				playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1)
				build_step = 6
				user << "You close the internal access hatch."
				return

			//attack_hand() removes the prox sensor

		if(6)
			if(istype(I, /obj/item/stack/sheet/metal))
				var/obj/item/stack/sheet/metal/M = I
				if(M.use(2))
					user << "You add some metal armor to the exterior frame."
					build_step = 7
				else
					user << "You need two sheets of metal to continue construction."
				return

			else if(istype(I, /obj/item/weapon/screwdriver))
				playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1)
				build_step = 5
				user << "You open the internal access hatch."
				return

		if(7)
			if(istype(I, /obj/item/weapon/weldingtool))
				var/obj/item/weapon/weldingtool/WT = I
				if(!WT.isOn()) return
				if(WT.get_fuel() < 5)
					user << "You need more fuel to complete this task."

				playsound(loc, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1)
				if(do_after(user, 30))
					if(!src || !WT.remove_fuel(5, user))
						return
					build_step = 8
					user << "You weld the turret's armor down."

					//The final step: create a full turret
					var/obj/machinery/porta_turret/Turret = new/obj/machinery/porta_turret(loc)
					Turret.name = finish_name
					Turret.installation = installation
					Turret.gun_charge = gun_charge
					Turret.setup()

//					Turret.cover=new/obj/machinery/porta_turret_cover(loc)
//					Turret.cover.Parent_Turret=Turret
//					Turret.cover.name = finish_name
					qdel(src)

			else if(istype(I, /obj/item/weapon/crowbar))
				playsound(loc, 'sound/items/Crowbar.ogg', 75, 1)
				user << "You pry off the turret's exterior armor."
				new /obj/item/stack/sheet/metal(loc, 2)
				build_step = 6
				return

	if(istype(I, /obj/item/weapon/pen))	//you can rename turrets like bots!
		var/t = stripped_input(user, "Enter new turret name", name, finish_name)
		if(!t)
			return
		if(!in_range(src, usr) && loc != usr)
			return

		finish_name = t
		return
	..()

/obj/machinery/porta_turret_construct/attack_hand(mob/user)
	switch(build_step)
		if(4)
			if(!installation)
				return
			build_step = 3

			var/obj/item/weapon/gun/energy/Gun = new installation(loc)
			Gun.power_supply.charge = gun_charge
			Gun.update_icon()
			installation = null
			gun_charge = 0
			user << "You remove [Gun] from the turret frame."

		if(5)
			user << "You remove the prox sensor from the turret frame."
			new /obj/item/device/assembly/prox_sensor(loc)
			build_step = 4

/obj/machinery/porta_turret_construct/attack_ai()
	return

/************************
* PORTABLE TURRET COVER *
************************/

/obj/machinery/porta_turret_cover
	name = "turret"
	icon = 'icons/obj/turrets.dmi'
	icon_state = "turretCover"
	anchored = 1
	layer = 3.5
	density = 0
	var/obj/machinery/porta_turret/Parent_Turret = null

//The below code is pretty much just recoded from the initial turret object. It's necessary but uncommented because it's exactly the same!
//>necessary
//I'm not fixing it because i'm fucking bored of this code already, but someone should just reroute these to the parent turret's procs.

/obj/machinery/porta_turret_cover/attack_ai(mob/user)
	. = ..()
	if(.)
		return
	var/dat
	if(Parent_Turret)
		if(!(Parent_Turret.lasercolor))
			dat += text({"
<TT>Automatic Portable Turret Installation</TT>

Status: []

Behaviour controls are [Parent_Turret.locked ? "locked" : "unlocked"]"},

"[Parent_Turret.on ? "On" : "Off"]" )

			dat += text({"

Check for Weapon Authorization: []

Check Security Records: []

Neutralize Identified Criminals: []

Neutralize All Non-Security and Non-Command Personnel: []

Neutralize All Unidentified Life Signs: []
"},

"[Parent_Turret.auth_weapons ? "Yes" : "No"]",
"[Parent_Turret.check_records ? "Yes" : "No"]",
"[Parent_Turret.criminals ? "Yes" : "No"]",
"[Parent_Turret.stun_all ? "Yes" : "No"]" ,
"[Parent_Turret.check_anomalies ? "Yes" : "No"]" )
		else
			dat += text({"
<TT>Automatic Portable Turret Installation</TT>

Status: []
"},

"[Parent_Turret.on ? "On" : "Off"]" )

		user << browse("<TITLE>Automatic Portable Turret Installation</TITLE>[dat]", "window=autosec")
		onclose(user, "autosec")
	return

/obj/machinery/porta_turret_cover/attack_hand(mob/user)

	. = ..()
	if(.)
		return
	var/dat
	if(Parent_Turret)
		if(!Parent_Turret.lasercolor)
			dat += text({"
					<TT>Automatic Portable Turret Installation</TT>

					Status: []

					Behaviour controls are [Parent_Turret.locked ? "locked" : "unlocked"]"},

					"[Parent_Turret.on ? "On" : "Off"]" )

			if(!Parent_Turret.locked)
				dat += text({"

							Check for Weapon Authorization: []

							Check Security Records: []

							Neutralize Identified Criminals: []

							Neutralize All Non-Security and Non-Command Personnel: []

							Neutralize All Unidentified Life Signs: []
"},

							"[Parent_Turret.auth_weapons ? "Yes" : "No"]",
							"[Parent_Turret.check_records ? "Yes" : "No"]",
							"[Parent_Turret.criminals ? "Yes" : "No"]",
							"[Parent_Turret.stun_all ? "Yes" : "No"]" ,
							"[Parent_Turret.check_anomalies ? "Yes" : "No"]" )
		else
			if(istype(user,/mob/living/carbon/human))
				var/mob/living/carbon/human/H = user
				if(Parent_Turret.lasercolor == "b" && istype(H.wear_suit, /obj/item/clothing/suit/redtag))
					return
				if(Parent_Turret.lasercolor == "r" && istype(H.wear_suit, /obj/item/clothing/suit/bluetag))
					return
			dat += text({"
						<TT>Automatic Portable Turret Installation</TT>

						Status: []
"},

						"[Parent_Turret.on ? "On" : "Off"]" )

		user << browse("<TITLE>Automatic Portable Turret Installation</TITLE>[dat]", "window=autosec")
		onclose(user, "autosec")
	return

/obj/machinery/porta_turret_cover/Topic(href, href_list)
	if(..())
		return
	usr.set_machine(src)
	Parent_Turret.add_fingerprint(usr)
	add_fingerprint(usr)
	if(href_list["power"] && !Parent_Turret.locked)
		if(Parent_Turret.anchored)
			if(Parent_Turret.on)
				Parent_Turret.on = 0
			else
				Parent_Turret.on = 1
		else
			usr << "It has to be secured first!"

		updateUsrDialog()
		return

	switch(href_list["operation"])
		if("authweapon")
			Parent_Turret.auth_weapons = !Parent_Turret.auth_weapons
		if("checkrecords")
			Parent_Turret.check_records = !Parent_Turret.check_records
		if("shootcrooks")
			Parent_Turret.criminals = !Parent_Turret.criminals
		if("shootall")
			Parent_Turret.stun_all = !Parent_Turret.stun_all
		if("checkxenos")
			Parent_Turret.check_anomalies = !Parent_Turret.check_anomalies

	updateUsrDialog()

/obj/machinery/porta_turret_cover/attackby(obj/item/I, mob/user, params)
	if(!Parent_Turret)
		return
	if(istype(I, /obj/item/weapon/wrench) && !Parent_Turret.on)
		if(Parent_Turret.raised) return

		if(!Parent_Turret.anchored)
			Parent_Turret.anchored = 1
			Parent_Turret.invisibility = INVISIBILITY_LEVEL_TWO
			Parent_Turret.icon_state = "grey_target_prism"
			user << "You secure the exterior bolts on the turret."
		else
			Parent_Turret.anchored = 0
			user << "You unsecure the exterior bolts on the turret."
			Parent_Turret.icon_state = "turretCover"
			Parent_Turret.invisibility = 0
			qdel(src)

	else if(istype(I, /obj/item/weapon/card/id)||istype(I, /obj/item/device/pda))
		if(Parent_Turret.allowed(user))
			Parent_Turret.locked = !Parent_Turret.locked
			user << "Controls are now [Parent_Turret.locked ? "locked" : "unlocked"]."
			updateUsrDialog()
		else
			user << "Access denied."

	else
		user.changeNext_move(CLICK_CD_MELEE)
		Parent_Turret.health -= I.force * 0.5
		if(Parent_Turret.health <= 0)
			Parent_Turret.die()
		if(I.force * 0.5 > 2)
			if(!Parent_Turret.attacked && !Parent_Turret.emagged)
				Parent_Turret.attacked = 1
				spawn()
					sleep(30)
					Parent_Turret.attacked = 0
		..()

/obj/machinery/porta_turret_cover/emag_act(user as mob)
	if(!emagged)
		user << "You short out [Parent_Turret]'s threat assessment circuits."
		visible_message("[Parent_Turret] hums oddly...")
		Parent_Turret.emagged = 1
		Parent_Turret.on = 0
		sleep(40)
		Parent_Turret.on = 1

/obj/machinery/porta_turret/stationary
	emagged = 1

	New()
		installation = new/obj/item/weapon/gun/energy/laser(loc)
		..()

////////////////////////
//Turret Control Panel//
////////////////////////

/obj/machinery/turretid
	name = "turret control panel"
	desc = "Used to control a room's automated defenses."
	icon = 'icons/obj/machines/turret_control.dmi'
	icon_state = "control_standby"
	anchored = 1
	density = 0
	var/enabled = 1
	var/lethal = 0
	var/locked = 1
	var/control_area //can be area name, path or nothing.
	var/ailock = 0 // AI cannot use this
	req_access = list(access_ai_upload)

/obj/machinery/turretid/New()
	..()
	if(!control_area)
		var/area/CA = get_area(src)
		if(CA)
			control_area = CA
	else if(istext(control_area))
		for(var/area/A in world)
			if(A.name && A.name==control_area)
				control_area = A
				break
	power_change() //Checks power and initial settings
	//don't have to check if control_area is path, since get_area_all_atoms can take path.
	return

/obj/machinery/turretid/attackby(obj/item/weapon/W, mob/user, params)
	if(stat & BROKEN) return
	if (istype(user, /mob/living/silicon))
		return src.attack_hand(user)

	else if( get_dist(src, user) == 0 )		// trying to unlock the interface
		if (src.allowed(usr))
			if(emagged)
				user << "The turret control is unresponsive."
				return

			locked = !locked
			user << "You [ locked ? "lock" : "unlock"] the panel."
			if (locked)
				if (user.machine==src)
					user.unset_machine()
					user << browse(null, "window=turretid")
			else
				if (user.machine==src)
					src.attack_hand(user)
		else
			user << "Access denied."

/obj/machinery/turretid/emag_act(mob/user as mob)
	if(!emagged)
		user << "You short out the turret controls' access analysis module."
		emagged = 1
		locked = 0
		if(user.machine==src)
			src.attack_hand(user)

/obj/machinery/turretid/attack_ai(mob/user as mob)
	if(!ailock)
		return attack_hand(user)
	else
		user << "There seems to be a firewall preventing you from accessing this device."

/obj/machinery/turretid/attack_hand(mob/user as mob)
	if ( get_dist(src, user) > 0 )
		if ( !issilicon(user) )
			user << "You are too far away."
			user.unset_machine()
			user << browse(null, "window=turretid")
			return

	user.set_machine(src)
	var/loc = src.loc
	if (istype(loc, /turf))
		loc = loc:loc
	if (!istype(loc, /area))
		user << text("Turret badly positioned - loc.loc is [].", loc)
		return
	var/area/area = loc
	var/t = ""

	if(src.locked && (!istype(user, /mob/living/silicon)))
		t += "
Swipe ID card to unlock interface
"
	else
		if (!istype(user, /mob/living/silicon))
			t += "
Swipe ID card to lock interface
"
		t += text("Turrets [] - []?
\n", src.enabled?"activated":"deactivated", src, src.enabled?"Disable":"Enable")
		t += text("Currently set for [] - Change to []?
\n", src.lethal?"lethal":"stun repeatedly", src,  src.lethal?"Stun repeatedly":"Lethal")

	//user << browse(t, "window=turretid")
	//onclose(user, "turretid")
	var/datum/browser/popup = new(user, "turretid", "Turret Control Panel ([area.name])")
	popup.set_content(t)
	popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
	popup.open()

/obj/machinery/turretid/Topic(href, href_list)
	if(..())
		return
	if (src.locked)
		if (!istype(usr, /mob/living/silicon))
			usr << "Control panel is locked!"
			return
	if (href_list["toggleOn"])
		toggle_on()
	else if (href_list["toggleLethal"])
		toggle_lethal()
	src.attack_hand(usr)

/obj/machinery/turretid/proc/toggle_lethal()
	lethal = !lethal
	updateTurrets()

/obj/machinery/turretid/proc/toggle_on()
	enabled = !enabled
	updateTurrets()

/obj/machinery/turretid/proc/updateTurrets()
	if(control_area)
		for (var/obj/machinery/porta_turret/aTurret in get_area_all_atoms(control_area))
			aTurret.setState(src.enabled, src.lethal)
	src.update_icon()

/obj/machinery/turretid/power_change()
	..()
	update_icon()

/obj/machinery/turretid/update_icon()
	..()
	if(stat & NOPOWER)
		icon_state = "control_off"
	else if (enabled)
		if (lethal)
			icon_state = "control_kill"
		else
			icon_state = "control_stun"
	else
		icon_state = "control_standby"