code:
/*
	New methods:
	pulse - sends a pulse into a wire for hacking purposes
	cut - cuts a wire and makes any necessary state changes
	mend - mends a wire and makes any necessary state changes
	canAIControl - 1 if the AI can control the airlock, 0 if not (then check canAIHack to see if it can hack in)
	canAIHack - 1 if the AI can hack into the airlock to recover control, 0 if not. Also returns 0 if the AI does not *need* to hack it.
	hasPower - 1 if the main or backup power are functioning, 0 if not.
	requiresIDs - 1 if the airlock is requiring IDs, 0 if not
	isAllPowerCut - 1 if the main and backup power both have cut wires.
	regainMainPower - handles the effect of main power coming back on.
	loseMainPower - handles the effect of main power going offline. Usually (if one isn't already running) spawn a thread to count down how long it will be offline - counting down won't happen if main power was completely cut along with backup power, though, the thread will just sleep.
	loseBackupPower - handles the effect of backup power going offline.
	regainBackupPower - handles the effect of main power coming back on.
	shock - has a chance of electrocuting its target.
*/

// Wires for the airlock are located in the datum folder, inside the wires datum folder.

/obj/machinery/door/airlock
	name = "airlock"
	icon = 'icons/obj/doors/Doorint.dmi'
	icon_state = "door_closed"

	var/aiControlDisabled = 0 //If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in.
	var/hackProof = 0 // if 1, this door can't be hacked by the AI
	var/secondsMainPowerLost = 0 //The number of seconds until power is restored.
	var/secondsBackupPowerLost = 0 //The number of seconds until power is restored.
	var/spawnPowerRestoreRunning = 0
	var/welded = null
	var/locked = 0
	var/lights = 1 // bolt lights show by default
	var/datum/wires/airlock/wires = null
	secondsElectrified = 0 //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it.
	var/aiDisabledIdScanner = 0
	var/aiHacking = 0
	var/obj/machinery/door/airlock/closeOther = null
	var/closeOtherId = null
	var/lockdownbyai = 0
	var/doortype = null
	var/justzap = 0
	var/safe = 1
	normalspeed = 1
	var/obj/item/weapon/airlock_electronics/electronics = null
	var/hasShocked = 0 //Prevents multiple shocks from happening
	var/autoclose = 1
	explosion_block = 1

/obj/machinery/door/airlock/command
	icon = 'icons/obj/doors/Doorcom.dmi'
	doortype = /obj/structure/door_assembly/door_assembly_com

/obj/machinery/door/airlock/security
	icon = 'icons/obj/doors/Doorsec.dmi'
	doortype = /obj/structure/door_assembly/door_assembly_sec

/obj/machinery/door/airlock/engineering
	icon = 'icons/obj/doors/Dooreng.dmi'
	doortype = /obj/structure/door_assembly/door_assembly_eng

/obj/machinery/door/airlock/medical
	icon = 'icons/obj/doors/Doormed.dmi'
	doortype = /obj/structure/door_assembly/door_assembly_med

/obj/machinery/door/airlock/maintenance
	name = "maintenance access"
	icon = 'icons/obj/doors/Doormaint.dmi'
	doortype = /obj/structure/door_assembly/door_assembly_mai

/obj/machinery/door/airlock/external
	name = "external airlock"
	icon = 'icons/obj/doors/Doorext.dmi'
	doortype = /obj/structure/door_assembly/door_assembly_ext

/obj/machinery/door/airlock/glass
	name = "glass airlock"
	icon = 'icons/obj/doors/Doorglass.dmi'
	opacity = 0
	doortype = /obj/structure/door_assembly/door_assembly_glass
	glass = 1

/obj/machinery/door/airlock/centcom
	icon = 'icons/obj/doors/Doorele.dmi'
	opacity = 1
	doortype = null //(centcom) there's no door assembly sprites for this one.

/obj/machinery/door/airlock/vault
	name = "vault door"
	icon = 'icons/obj/doors/vault.dmi'
	opacity = 1
	doortype = /obj/structure/door_assembly/door_assembly_vault

/obj/machinery/door/airlock/glass_large
	name = "glass airlock"
	icon = 'icons/obj/doors/Door2x1glassfull.dmi'
	opacity = 0
	doortype = null //(double glass door) there's no door assembly sprites for this one.
	glass = 1
	bound_width = 64 // 2x1

/obj/machinery/door/airlock/freezer
	name = "freezer airlock"
	icon = 'icons/obj/doors/Doorfreezer.dmi'
	opacity = 1
	doortype = /obj/structure/door_assembly/door_assembly_fre

/obj/machinery/door/airlock/hatch
	name = "airtight hatch"
	icon = 'icons/obj/doors/Doorhatchele.dmi'
	opacity = 1
	doortype = /obj/structure/door_assembly/door_assembly_hatch

/obj/machinery/door/airlock/maintenance_hatch
	name = "maintenance hatch"
	icon = 'icons/obj/doors/Doorhatchmaint2.dmi'
	opacity = 1
	doortype = /obj/structure/door_assembly/door_assembly_mhatch

/obj/machinery/door/airlock/glass_command
	name = "maintenance hatch"
	icon = 'icons/obj/doors/Doorcomglass.dmi'
	opacity = 0
	doortype = /obj/structure/door_assembly/door_assembly_com/glass
	glass = 1

/obj/machinery/door/airlock/glass_engineering
	name = "maintenance hatch"
	icon = 'icons/obj/doors/Doorengglass.dmi'
	opacity = 0
	doortype = /obj/structure/door_assembly/door_assembly_eng/glass
	glass = 1

/obj/machinery/door/airlock/glass_security
	name = "maintenance hatch"
	icon = 'icons/obj/doors/Doorsecglass.dmi'
	opacity = 0
	doortype = /obj/structure/door_assembly/door_assembly_sec/glass
	glass = 1

/obj/machinery/door/airlock/glass_medical
	name = "maintenance hatch"
	icon = 'icons/obj/doors/Doormedglass.dmi'
	opacity = 0
	doortype = /obj/structure/door_assembly/door_assembly_med/glass
	glass = 1

/obj/machinery/door/airlock/mining
	name = "mining airlock"
	icon = 'icons/obj/doors/Doormining.dmi'
	doortype = /obj/structure/door_assembly/door_assembly_min

/obj/machinery/door/airlock/atmos
	name = "atmospherics airlock"
	icon = 'icons/obj/doors/Dooratmo.dmi'
	doortype = /obj/structure/door_assembly/door_assembly_atmo

/obj/machinery/door/airlock/research
	icon = 'icons/obj/doors/Doorresearch.dmi'
	doortype = /obj/structure/door_assembly/door_assembly_research

/obj/machinery/door/airlock/glass_research
	name = "maintenance hatch"
	icon = 'icons/obj/doors/Doorresearchglass.dmi'
	opacity = 0
	doortype = /obj/structure/door_assembly/door_assembly_research/glass
	glass = 1
	heat_proof = 1

/obj/machinery/door/airlock/glass_mining
	name = "maintenance hatch"
	icon = 'icons/obj/doors/Doorminingglass.dmi'
	opacity = 0
	doortype = /obj/structure/door_assembly/door_assembly_min/glass
	glass = 1

/obj/machinery/door/airlock/glass_atmos
	name = "maintenance hatch"
	icon = 'icons/obj/doors/Dooratmoglass.dmi'
	opacity = 0
	doortype = /obj/structure/door_assembly/door_assembly_atmo/glass
	glass = 1

/obj/machinery/door/airlock/gold
	name = "gold airlock"
	icon = 'icons/obj/doors/Doorgold.dmi'
	var/mineral = "gold"
	doortype = /obj/structure/door_assembly/door_assembly_gold

/obj/machinery/door/airlock/silver
	name = "silver airlock"
	icon = 'icons/obj/doors/Doorsilver.dmi'
	var/mineral = "silver"
	doortype = /obj/structure/door_assembly/door_assembly_silver

/obj/machinery/door/airlock/diamond
	name = "diamond airlock"
	icon = 'icons/obj/doors/Doordiamond.dmi'
	var/mineral = "diamond"
	doortype = /obj/structure/door_assembly/door_assembly_diamond

/obj/machinery/door/airlock/uranium
	name = "uranium airlock"
	desc = "And they said I was crazy."
	icon = 'icons/obj/doors/Dooruranium.dmi'
	var/mineral = "uranium"
	doortype = /obj/structure/door_assembly/door_assembly_uranium
	var/last_event = 0

/obj/machinery/door/airlock/uranium/process()
	if(world.time > last_event+20)
		if(prob(50))
			radiate()
		last_event = world.time
	..()

/obj/machinery/door/airlock/uranium/proc/radiate()
	for(var/mob/living/L in range (3,src))
		L.apply_effect(15,IRRADIATE,0)
	return

/obj/machinery/door/airlock/plasma
	name = "plasma airlock"
	desc = "No way this can end badly."
	icon = 'icons/obj/doors/Doorplasma.dmi'
	var/mineral = "plasma"
	doortype = /obj/structure/door_assembly/door_assembly_plasma

/obj/machinery/door/airlock/plasma/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
	if(exposed_temperature > 300)
		PlasmaBurn(exposed_temperature)

/obj/machinery/door/airlock/plasma/proc/ignite(exposed_temperature)
	if(exposed_temperature > 300)
		PlasmaBurn(exposed_temperature)

/obj/machinery/door/airlock/plasma/proc/PlasmaBurn(temperature)
	atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, 500)
	new/obj/structure/door_assembly/door_assembly_0( src.loc )
	qdel(src)

/obj/machinery/door/airlock/plasma/BlockSuperconductivity() //we don't stop the heat~
	return 0

/obj/machinery/door/airlock/clown
	name = "bananium airlock"
	desc = "Honkhonkhonk"
	icon = 'icons/obj/doors/Doorbananium.dmi'
	var/mineral = "bananium"
	doortype = /obj/structure/door_assembly/door_assembly_clown

/obj/machinery/door/airlock/sandstone
	name = "sandstone airlock"
	icon = 'icons/obj/doors/Doorsand.dmi'
	var/mineral = "sandstone"
	doortype = /obj/structure/door_assembly/door_assembly_sandstone

/obj/machinery/door/airlock/science
	icon = 'icons/obj/doors/Doorsci.dmi'
	doortype = /obj/structure/door_assembly/door_assembly_science

/obj/machinery/door/airlock/glass_science
	name = "glass airlock"
	icon = 'icons/obj/doors/Doorsciglass.dmi'
	opacity = 0
	doortype = /obj/structure/door_assembly/door_assembly_science/glass
	glass = 1

/obj/machinery/door/airlock/highsecurity
	name = "high tech security airlock"
	explosion_block = 2
	icon = 'icons/obj/doors/hightechsecurity.dmi'
	doortype = /obj/structure/door_assembly/door_assembly_highsecurity

/obj/machinery/door/airlock/shuttle
	name = "shuttle airlock"
	icon = 'icons/obj/doors/doorshuttle.dmi'
	doortype = /obj/structure/door_assembly/door_assembly_shuttle

/obj/machinery/door/airlock/wood
	name = "wooden airlock"
	icon = 'icons/obj/doors/Doorwood.dmi'
	var/mineral = "wood"
	doortype = /obj/structure/door_assembly/door_assembly_wood

/obj/machinery/door/airlock/virology
	icon = 'icons/obj/doors/Doorviro.dmi'
	doortype = /obj/structure/door_assembly/door_assembly_viro

/obj/machinery/door/airlock/glass_virology
	icon = 'icons/obj/doors/Doorviroglass.dmi'
	opacity = 0
	doortype = /obj/structure/door_assembly/door_assembly_viro/glass
	glass = 1

/*
About the new airlock wires panel:
*	An airlock wire dialog can be accessed by the normal way or by using wirecutters or a multitool on the door while the wire-panel is open. This would show the following wires, which you can either wirecut/mend or send a multitool pulse through. There are 9 wires.
*		one wire from the ID scanner. Sending a pulse through this flashes the red light on the door (if the door has power). If you cut this wire, the door will stop recognizing valid IDs. (If the door has 0000 access, it still opens and closes, though)
*		two wires for power. Sending a pulse through either one causes a breaker to trip, disabling the door for 10 seconds if backup power is connected, or 1 minute if not (or until backup power comes back on, whichever is shorter). Cutting either one disables the main door power, but unless backup power is also cut, the backup power re-powers the door in 10 seconds. While unpowered, the door may be \red open, but bolts-raising will not work. Cutting these wires may electrocute the user.
*		one wire for door bolts. Sending a pulse through this drops door bolts (whether the door is powered or not) or raises them (if it is). Cutting this wire also drops the door bolts, and mending it does not raise them. If the wire is cut, trying to raise the door bolts will not work.
*		two wires for backup power. Sending a pulse through either one causes a breaker to trip, but this does not disable it unless main power is down too (in which case it is disabled for 1 minute or however long it takes main power to come back, whichever is shorter). Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user.
*		one wire for opening the door. Sending a pulse through this while the door has power makes it open the door if no access is required.
*		one wire for AI control. Sending a pulse through this blocks AI control for a second or so (which is enough to see the AI control light on the panel dialog go off and back on again). Cutting this prevents the AI from controlling the door unless it has hacked the door through the power connection (which takes about a minute). If both main and backup power are cut, as well as this wire, then the AI cannot operate or hack the door at all.
*		one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. (Currently it is also STAYING electrified until someone mends the wire)
*		one wire for controling door safetys.  When active, door does not close on someone.  When cut, door will ruin someone's shit.  When pulsed, door will immedately ruin someone's shit.
*		one wire for controlling door speed.  When active, dor closes at normal rate.  When cut, door does not close manually.  When pulsed, door attempts to close every tick.
*/
// You can find code for the airlock wires in the wire datum folder.

/obj/machinery/door/airlock/proc/bolt()
	if(locked)
		return
	locked = 1
	update_icon()

/obj/machinery/door/airlock/proc/unbolt()
	if(!locked)
		return
	locked = 0
	update_icon()

/obj/machinery/door/airlock/Destroy()
	if(id_tag)
		for(var/obj/machinery/doorButtons/D in world)
			D.removeMe(src)
	..()

/obj/machinery/door/airlock/bumpopen(mob/living/user as mob) //Airlocks now zap you when you 'bump' them open when they're electrified. --NeoFite
	if(!issilicon(usr))
		if(src.isElectrified())
			if(!src.justzap)
				if(src.shock(user, 100))
					src.justzap = 1
					spawn (10)
						src.justzap = 0
					return
			else /*if(src.justzap)*/
				return
		else if(user.hallucination > 50 && prob(10) && src.operating == 0)
			user << "You feel a powerful shock course through your body!"
			user.staminaloss += 50
			user.stunned += 5
			return
	..(user)

/obj/machinery/door/airlock/bumpopen(mob/living/simple_animal/user as mob)
	..(user)

/obj/machinery/door/airlock/proc/isElectrified()
	if(src.secondsElectrified != 0)
		return 1
	return 0

/obj/machinery/door/airlock/proc/isWireCut(var/wireIndex)
	// You can find the wires in the datum folder.
	return wires.IsIndexCut(wireIndex)

/obj/machinery/door/airlock/proc/canAIControl()
	return ((src.aiControlDisabled!=1) && (!src.isAllPowerCut()));

/obj/machinery/door/airlock/proc/canAIHack()
	return ((src.aiControlDisabled==1) && (!hackProof) && (!src.isAllPowerCut()));

/obj/machinery/door/airlock/hasPower()
	return ((src.secondsMainPowerLost==0 || src.secondsBackupPowerLost==0) && !(stat & NOPOWER))

/obj/machinery/door/airlock/requiresID()
	return !(src.isWireCut(AIRLOCK_WIRE_IDSCAN) || aiDisabledIdScanner)

/obj/machinery/door/airlock/proc/isAllPowerCut()
	var/retval=0
	if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1) || src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))
		if(src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) || src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))
			retval=1
	return retval

/obj/machinery/door/airlock/proc/regainMainPower()
	if(src.secondsMainPowerLost > 0)
		src.secondsMainPowerLost = 0

/obj/machinery/door/airlock/proc/loseMainPower()
	if(src.secondsMainPowerLost <= 0)
		src.secondsMainPowerLost = 60
		if(src.secondsBackupPowerLost < 10)
			src.secondsBackupPowerLost = 10
	if(!src.spawnPowerRestoreRunning)
		src.spawnPowerRestoreRunning = 1
		spawn(0)
			var/cont = 1
			while (cont)
				sleep(10)
				cont = 0
				if(src.secondsMainPowerLost>0)
					if((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)))
						src.secondsMainPowerLost -= 1
						src.updateDialog()
					cont = 1

				if(src.secondsBackupPowerLost>0)
					if((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)))
						src.secondsBackupPowerLost -= 1
						src.updateDialog()
					cont = 1
			src.spawnPowerRestoreRunning = 0
			src.updateDialog()

/obj/machinery/door/airlock/proc/loseBackupPower()
	if(src.secondsBackupPowerLost < 60)
		src.secondsBackupPowerLost = 60

/obj/machinery/door/airlock/proc/regainBackupPower()
	if(src.secondsBackupPowerLost > 0)
		src.secondsBackupPowerLost = 0

// shock user with probability prb (if all connections & power are working)
// returns 1 if shocked, 0 otherwise
// The preceding comment was borrowed from the grille's shock script
/obj/machinery/door/airlock/proc/shock(mob/user, prb)
	if(!hasPower())		// unpowered, no shock
		return 0
	if(hasShocked)
		return 0	//Already shocked someone recently?
	if(!prob(prb))
		return 0 //you lucked out, no shock for you
	var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
	s.set_up(5, 1, src)
	s.start() //sparks always.
	if(electrocute_mob(user, get_area(src), src))
		hasShocked = 1
		spawn(10)
			hasShocked = 0
		return 1
	else
		return 0

/obj/machinery/door/airlock/update_icon()
	if(overlays) overlays.Cut()
	if(density)
		if(locked && lights)
			icon_state = "door_locked"
		else
			icon_state = "door_closed"
		if(p_open || welded || emergency)
			overlays = list()
			if(p_open)
				overlays += image(icon, "panel_open")
			if(welded)
				overlays += image(icon, "welded")
			if(emergency && !locked)
				overlays += image(icon, "elights")
	else
		icon_state = "door_open"

	return

/obj/machinery/door/airlock/do_animate(animation)
	switch(animation)
		if("opening")
			if(overlays) overlays.Cut()
			if(p_open)
				spawn(2) // The only work around that works. Downside is that the door will be gone for a millisecond.
					flick("o_door_opening", src)  //can not use flick due to BYOND bug updating overlays right before flicking
			else
				flick("door_opening", src)
		if("closing")
			if(overlays) overlays.Cut()
			if(p_open)
				flick("o_door_closing", src)
			else
				flick("door_closing", src)
		if("spark")
			flick("door_spark", src)
		if("deny")
			flick("door_deny", src)
	return

/obj/machinery/door/airlock/attack_ai(mob/user as mob)
	if(!src.canAIControl())
		if(src.canAIHack())
			src.hack(user)
			return
		else
			user << "Airlock AI control has been blocked with a firewall. Unable to hack."
	if(emagged)
		user << "Unable to interface: Airlock is unresponsive."
		return

	//Separate interface for the AI.
	user.set_machine(src)
	var/t1 = text("Airlock Control
\n")
	if(src.secondsMainPowerLost > 0)
		if((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)))
			t1 += text("Main power is offline for [] seconds.
\n", src.secondsMainPowerLost)
		else
			t1 += text("Main power is offline indefinitely.
\n")
	else
		t1 += text("Main power is online.")

	if(src.secondsBackupPowerLost > 0)
		if((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)))
			t1 += text("Backup power is offline for [] seconds.
\n", src.secondsBackupPowerLost)
		else
			t1 += text("Backup power is offline indefinitely.
\n")
	else if(src.secondsMainPowerLost > 0)
		t1 += text("Backup power is online.")
	else
		t1 += text("Backup power is offline, but will turn on if main power fails.")
	t1 += "
\n"

	if(src.isWireCut(AIRLOCK_WIRE_IDSCAN))
		t1 += text("IdScan wire is cut.
\n")
	else if(src.aiDisabledIdScanner)
		t1 += text("IdScan disabled. Enable?
\n", src)
	else
		t1 += text("IdScan enabled. Disable?
\n", src)

	if(src.emergency)
		t1 += text("Emergency Access Override is enabled. Disable?
\n", src)
	else
		t1 += text("Emergency Access Override is disabled. Enable?
\n", src)

	if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1))
		t1 += text("Main Power Input wire is cut.
\n")
	if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))
		t1 += text("Main Power Output wire is cut.
\n")
	if(src.secondsMainPowerLost == 0)
		t1 += text("Temporarily disrupt main power?.
\n", src)
	if(src.secondsBackupPowerLost == 0)
		t1 += text("Temporarily disrupt backup power?.
\n", src)

	if(src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1))
		t1 += text("Backup Power Input wire is cut.
\n")
	if(src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))
		t1 += text("Backup Power Output wire is cut.
\n")

	if(src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS))
		t1 += text("Door bolt drop wire is cut.
\n")
	else if(!src.locked)
		t1 += text("Door bolts are up. Drop them?
\n", src)
	else
		t1 += text("Door bolts are down.")
		if(src.hasPower())
			t1 += text(" Raise?
\n", src)
		else
			t1 += text(" Cannot raise door bolts due to power failure.
\n")

	if(src.isWireCut(AIRLOCK_WIRE_LIGHT))
		t1 += text("Door bolt lights wire is cut.
\n")
	else if(!src.lights)
		t1 += text("Door lights are off. Enable?
\n", src)
	else
		t1 += text("Door lights are on. Disable?
\n", src)

	if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY))
		t1 += text("Electrification wire is cut.
\n")
	if(src.secondsElectrified==-1)
		t1 += text("Door is electrified indefinitely. Un-electrify it?
\n", src)
	else if(src.secondsElectrified>0)
		t1 += text("Door is electrified temporarily ([] seconds). Un-electrify it?
\n", src.secondsElectrified, src)
	else
		t1 += text("Door is not electrified. Electrify it for 30 seconds? Or, Electrify it indefinitely until someone cancels the electrification?
\n", src, src)

	if(src.isWireCut(AIRLOCK_WIRE_SAFETY))
		t1 += text("Door force sensors not responding.
\n")
	else if(src.safe)
		t1 += text("Door safeties operating normally.   Override?
\n",src)
	else
		t1 += text("Danger.  Door safeties disabled.   Restore?
\n",src)

	if(src.isWireCut(AIRLOCK_WIRE_SPEED))
		t1 += text("Door timing circuitry not responding.
\n")
	else if(src.normalspeed)
		t1 += text("Door timing circuitry operating normally.   Override?
\n",src)
	else
		t1 += text("Warning.  Door timing circuitry operating abnormally.   Restore?
\n",src)

	if(src.welded)
		t1 += text("Door appears to have been welded shut.
\n")
	else if(!src.locked)
		if(src.density)
			t1 += text("Open door
\n", src)
		else
			t1 += text("Close door
\n", src)

	t1 += text("
Close
\n", src)
	user << browse(t1, "window=airlock")
	onclose(user, "airlock")

//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 11 lift access override
//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door, 11 enable access override

/obj/machinery/door/airlock/proc/hack(mob/user as mob)
	if(src.aiHacking==0)
		src.aiHacking=1
		spawn(20)
			//TODO: Make this take a minute
			user << "Airlock AI control has been blocked. Beginning fault-detection."
			sleep(50)
			if(src.canAIControl())
				user << "Alert cancelled. Airlock control has been restored without our assistance."
				src.aiHacking=0
				return
			else if(!src.canAIHack())
				user << "We've lost our connection! Unable to hack airlock."
				src.aiHacking=0
				return
			user << "Fault confirmed: airlock control wire disabled or cut."
			sleep(20)
			user << "Attempting to hack into airlock. This may take some time."
			sleep(200)
			if(src.canAIControl())
				user << "Alert cancelled. Airlock control has been restored without our assistance."
				src.aiHacking=0
				return
			else if(!src.canAIHack())
				user << "We've lost our connection! Unable to hack airlock."
				src.aiHacking=0
				return
			user << "Upload access confirmed. Loading control program into airlock software."
			sleep(170)
			if(src.canAIControl())
				user << "Alert cancelled. Airlock control has been restored without our assistance."
				src.aiHacking=0
				return
			else if(!src.canAIHack())
				user << "We've lost our connection! Unable to hack airlock."
				src.aiHacking=0
				return
			user << "Transfer complete. Forcing airlock to execute program."
			sleep(50)
			//disable blocked control
			src.aiControlDisabled = 2
			user << "Receiving control information from airlock."
			sleep(10)
			//bring up airlock dialog
			src.aiHacking = 0
			if (user)
				src.attack_ai(user)

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

/obj/machinery/door/airlock/attack_hand(mob/user as mob)
	if(!istype(user, /mob/living/silicon))
		if(src.isElectrified())
			if(src.shock(user, 100))
				return

	if(ishuman(user) && prob(40) && src.density)
		var/mob/living/carbon/human/H = user
		if(H.getBrainLoss() >= 60)
			playsound(src.loc, 'sound/effects/bang.ogg', 25, 1)
			if(!istype(H.head, /obj/item/clothing/head/helmet))
				H.visible_message("[user] headbutts the airlock.", \
									"[user] headbutts the airlock!")
				var/obj/item/organ/limb/affecting = H.get_organ("head")
				H.Stun(5)
				H.Weaken(5)
				if(affecting.take_damage(10, 0))
					H.update_damage_overlays(0)
			else
				visible_message("[user] headbutts the airlock. Good thing they're wearing a helmet.")
			return

	if(src.p_open)
		wires.Interact(user)
	else
		..(user)
	return

/obj/machinery/door/airlock/Topic(href, href_list, var/nowindow = 0)
	// If you add an if(..()) check you must first remove the var/nowindow parameter.
	// Otherwise it will runtime with this kind of error: null.Topic()
	if(!nowindow)
		..()
	if(usr.stat || usr.restrained())
		return
	add_fingerprint(usr)
	if(href_list["close"])
		usr << browse(null, "window=airlock")
		if(usr.machine==src)
			usr.unset_machine()
			return

	if((in_range(src, usr) && istype(src.loc, /turf)) && src.p_open)
		usr.set_machine(src)

	if(istype(usr, /mob/living/silicon) && src.canAIControl())
		//AI
		//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 8 door safties, 9 door speed, 11 emergency access
		//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door,  8 door safties, 9 door speed, 11 emergency access
		if(href_list["aiDisable"])
			var/code = text2num(href_list["aiDisable"])
			switch (code)
				if(1)
					//disable idscan
					if(src.isWireCut(AIRLOCK_WIRE_IDSCAN))
						usr << "The IdScan wire has been cut - So, you can't disable it, but it is already disabled anyways."
					else if(src.aiDisabledIdScanner)
						usr << "You've already disabled the IdScan feature."
					else
						src.aiDisabledIdScanner = 1
				if(2)
					//disrupt main power
					if(src.secondsMainPowerLost == 0)
						src.loseMainPower()
					else
						usr << "Main power is already offline."
				if(3)
					//disrupt backup power
					if(src.secondsBackupPowerLost == 0)
						src.loseBackupPower()
					else
						usr << "Backup power is already offline."
				if(4)
					//drop door bolts
					if(src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS))
						usr << "You can't drop the door bolts - The door bolt dropping wire has been cut."
					else if(src.locked!=1)
						src.locked = 1
						update_icon()
				if(5)
					//un-electrify door
					if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY))
						usr << text("Can't un-electrify the airlock - The electrification wire is cut.")
					else if(src.secondsElectrified==-1)
						src.secondsElectrified = 0
					else if(src.secondsElectrified>0)
						src.secondsElectrified = 0

				if(8)
					// Safeties!  We don't need no stinking safeties!
					if (src.isWireCut(AIRLOCK_WIRE_SAFETY))
						usr << text("Control to door sensors is disabled.")
					else if (src.safe)
						safe = 0
					else
						usr << text("Firmware reports safeties already overriden.")

				if(9)
					// Door speed control
					if(src.isWireCut(AIRLOCK_WIRE_SPEED))
						usr << text("Control to door timing circuitry has been severed.")
					else if (src.normalspeed)
						normalspeed = 0
					else
						usr << text("Door timing circurity already accellerated.")

				if(7)
					//close door
					if(src.welded)
						usr << text("The airlock has been welded shut!")
					else if(src.locked)
						usr << text("The door bolts are down!")
					else if(!src.density)
						close()
					else
						open()

				if(10)
					// Bolt lights
					if(src.isWireCut(AIRLOCK_WIRE_LIGHT))
						usr << text("Control to door bolt lights has been severed.")
					else if (src.lights)
						lights = 0
					else
						usr << text("Door bolt lights are already disabled!")

				if(11)
					// Emergency access
					if (src.emergency)
						emergency = 0
					else
						usr << text("Emergency access is already disabled!")

		else if(href_list["aiEnable"])
			var/code = text2num(href_list["aiEnable"])
			switch (code)
				if(1)
					//enable idscan
					if(src.isWireCut(AIRLOCK_WIRE_IDSCAN))
						usr << "You can't enable IdScan - The IdScan wire has been cut."
					else if(src.aiDisabledIdScanner)
						src.aiDisabledIdScanner = 0
					else
						usr << "The IdScan feature is not disabled."
				if(4)
					//raise door bolts
					if(src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS))
						usr << text("The door bolt drop wire is cut - you can't raise the door bolts.
\n")
					else if(!src.locked)
						usr << text("The door bolts are already up.
\n")
					else
						if(src.hasPower())
							src.locked = 0
							update_icon()
						else
							usr << text("Cannot raise door bolts due to power failure.
\n")

				if(5)
					//electrify door for 30 seconds
					if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY))
						usr << text("The electrification wire has been cut.
\n")
					else if(src.secondsElectrified==-1)
						usr << text("The door is already indefinitely electrified. You'd have to un-electrify it before you can re-electrify it with a non-forever duration.
\n")
					else if(src.secondsElectrified!=0)
						usr << text("The door is already electrified. You can't re-electrify it while it's already electrified.
\n")
					else
						shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
						add_logs(usr, src, "electrified", admin=0, addition="at [x],[y],[z]")
						src.secondsElectrified = 30
						spawn(10)
							while (src.secondsElectrified>0)
								src.secondsElectrified-=1
								if(src.secondsElectrified<0)
									src.secondsElectrified = 0
								src.updateUsrDialog()
								sleep(10)
				if(6)
					//electrify door indefinitely
					if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY))
						usr << text("The electrification wire has been cut.
\n")
					else if(src.secondsElectrified==-1)
						usr << text("The door is already indefinitely electrified.
\n")
					else if(src.secondsElectrified!=0)
						usr << text("The door is already electrified. You can't re-electrify it while it's already electrified.
\n")
					else
						shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
						add_logs(usr, src, "electrified", admin=0, addition="at [x],[y],[z]")
						src.secondsElectrified = -1

				if (8) // Not in order >.>
					// Safeties!  Maybe we do need some stinking safeties!
					if (src.isWireCut(AIRLOCK_WIRE_SAFETY))
						usr << text("Control to door sensors is disabled.")
					else if (!src.safe)
						safe = 1
						src.updateUsrDialog()
					else
						usr << text("Firmware reports safeties already in place.")

				if(9)
					// Door speed control
					if(src.isWireCut(AIRLOCK_WIRE_SPEED))
						usr << text("Control to door timing circuitry has been severed.")
					else if (!src.normalspeed)
						normalspeed = 1
						src.updateUsrDialog()
					else
						usr << text("Door timing circurity currently operating normally.")

				if(7)
					//open door
					if(src.welded)
						usr << text("The airlock has been welded shut!")
					else if(src.locked)
						usr << text("The door bolts are down!")
					else if(src.density)
						open()
					else
						close()

				if(10)
					// Bolt lights
					if(src.isWireCut(AIRLOCK_WIRE_LIGHT))
						usr << text("Control to door bolt lights has been severed.")
					else if (!src.lights)
						lights = 1
						src.updateUsrDialog()
					else
						usr << text("Door bolt lights are already enabled!")

				if(11)
					// Emergency access
					if (!src.emergency)
						emergency = 1
					else
						usr << text("Emergency access is already enabled!")

	add_fingerprint(usr)
	update_icon()
	if(!nowindow)
		updateUsrDialog()
	return

/obj/machinery/door/airlock/attackby(C as obj, mob/user as mob, params)
	if(!istype(usr, /mob/living/silicon))
		if(src.isElectrified())
			if(src.shock(user, 75))
				return
	if(istype(C, /obj/item/device/detective_scanner))
		return

	src.add_fingerprint(user)
	if((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density))
		var/obj/item/weapon/weldingtool/W = C
		if(W.remove_fuel(0,user))
			user.visible_message("[user] is [welded ? "unwelding":"welding"] the airlock.", \
							"You begin [welded ? "unwelding":"welding"] the airlock...", \
							"You hear welding.")
			playsound(loc, 'sound/items/Welder.ogg', 40, 1)
			if(do_after(user,40,5,1))
				if(density && !operating)//Door must be closed to weld.
					if( !istype(src, /obj/machinery/door/airlock) || !user || !W || !W.isOn() || !user.loc )
						return
					playsound(loc, 'sound/items/Welder2.ogg', 50, 1)
					welded = !welded
					user.visible_message("[user.name] has [welded? "welded shut":"unwelded"] [src].", \
										"You've [welded ? "welded the airlock shut":"unwelded the airlock"].")
					update_icon()
		return
	else if(istype(C, /obj/item/weapon/screwdriver))
		src.p_open = !( src.p_open )
		user << "You [p_open ? "open":"close"] the maintenance panel of the airlock."
		src.update_icon()
	else if(istype(C, /obj/item/weapon/wirecutters))
		return src.attack_hand(user)
	else if(istype(C, /obj/item/device/multitool))
		return src.attack_hand(user)
	else if(istype(C, /obj/item/device/assembly/signaler))
		return src.attack_hand(user)
	else if(istype(C, /obj/item/weapon/pai_cable))
		var/obj/item/weapon/pai_cable/cable = C
		cable.plugin(src, user)
	else if(istype(C, /obj/item/weapon/crowbar) || istype(C, /obj/item/weapon/twohanded/fireaxe) )
		var/beingcrowbarred = null
		if(istype(C, /obj/item/weapon/crowbar) )
			beingcrowbarred = 1 //derp, Agouri
		else
			beingcrowbarred = 0
		if( beingcrowbarred && (density && welded && !operating && src.p_open && (!hasPower()) && !src.locked) )
			playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
			user.visible_message("[user] removes the electronics from the airlock assembly.", \
								 "You start to remove electronics from the airlock assembly.")
			if(do_after(user,40))
				if(src.loc)
					if(src.doortype)
						new src.doortype(src.loc)

					if(emagged)
						user << "You discard the damaged electronics."
						qdel(src)
						return
					user << "You removed the airlock electronics!"

					var/obj/item/weapon/airlock_electronics/ae
					if(!electronics)
						ae = new/obj/item/weapon/airlock_electronics( src.loc )
						if(req_one_access)
							ae.use_one_access = 1
							ae.conf_access = src.req_one_access
						else
							ae.conf_access = src.req_access
					else
						ae = electronics
						electronics = null
						ae.loc = src.loc

					qdel(src)
					return
		else if(hasPower())
			user << " The airlock's motors resist your efforts to force it."
		else if(locked)
			user << " The airlock's bolts prevent it from being forced."
		else if( !welded && !operating)
			if(density)
				if(beingcrowbarred == 0) //being fireaxe'd
					var/obj/item/weapon/twohanded/fireaxe/F = C
					if(F:wielded)
						spawn(0)	open(2)
					else
						user << "You need to be wielding the Fire axe to do that."
				else
					spawn(0)	open(2)
			else
				if(beingcrowbarred == 0)
					var/obj/item/weapon/twohanded/fireaxe/F = C
					if(F:wielded)
						spawn(0)	close(2)
					else
						user << "You need to be wielding the Fire axe to do that."
				else
					spawn(0)	close(2)

	else if(istype(C, /obj/item/weapon/airlock_painter))
		change_paintjob(C, user)
	else
		..()
	return

/obj/machinery/door/airlock/plasma/attackby(C as obj, mob/user as mob, params)
	if(is_hot(C) > 300)//If the temperature of the object is over 300, then ignite
		message_admins("Plasma wall ignited by [key_name(user, user.client)](?) in ([x],[y],[z] - JMP)")
		log_game("Plasma wall ignited by [user.ckey]([user]) in ([x],[y],[z])")
		ignite(is_hot(C))
		return
	..()

/obj/machinery/door/airlock/open(var/forced=0)
	if( operating || welded || locked )
		return 0
	if(!forced)
		if( !hasPower() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR) )
			return 0
	if(forced < 2)
		if(emagged)
			return 0
		use_power(50)
		if(istype(src, /obj/machinery/door/airlock/glass))
			playsound(src.loc, 'sound/machines/windowdoor.ogg', 100, 1)
		if(istype(src, /obj/machinery/door/airlock/clown))
			playsound(src.loc, 'sound/items/bikehorn.ogg', 30, 1)
		else
			playsound(src.loc, 'sound/machines/airlock.ogg', 30, 1)
		if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density)
			src.closeOther.close()
	else
		playsound(src.loc, 'sound/machines/airlockforced.ogg', 30, 1)

	if(autoclose  && normalspeed)
		spawn(150)
			autoclose()
	else if(autoclose && !normalspeed)
		spawn(5)
			autoclose()

	return ..()

/obj/machinery/door/airlock/close(var/forced=0)
	if(operating || welded || locked)
		return
	if(!forced)
		if( !hasPower() || isWireCut(AIRLOCK_WIRE_DOOR_BOLTS) )
			return
	if(safe)
		for(var/atom/movable/M in get_turf(src))
			if(M.density && M != src) //something is blocking the door
				spawn (60)
					autoclose()
				return

	if(forced < 2)
		if(emagged)
			return
		use_power(50)
		if(istype(src, /obj/machinery/door/airlock/glass))
			playsound(src.loc, 'sound/machines/windowdoor.ogg', 30, 1)
		if(istype(src, /obj/machinery/door/airlock/clown))
			playsound(src.loc, 'sound/items/bikehorn.ogg', 30, 1)
		else
			playsound(src.loc, 'sound/machines/airlock.ogg', 30, 1)
	else
		playsound(src.loc, 'sound/machines/airlockforced.ogg', 30, 1)

	var/obj/structure/window/killthis = (locate(/obj/structure/window) in get_turf(src))
	if(killthis)
		killthis.ex_act(2)//Smashin windows

	if(density)
		return 1
	operating = 1
	do_animate("closing")
	src.layer = 3.1
	sleep(5)
	src.density = 1
	if(!safe)
		crush()
	sleep(5)
	update_icon()
	if(visible && !glass)
		src.set_opacity(1)
	operating = 0
	air_update_turf(1)
	update_freelook_sight()
	if(locate(/mob/living) in get_turf(src))
		open()
	return 1

/obj/machinery/door/airlock/New()
	..()
	wires = new(src)
	if(src.closeOtherId != null)
		spawn (5)
			for (var/obj/machinery/door/airlock/A in world)
				if(A.closeOtherId == src.closeOtherId && A != src)
					src.closeOther = A
					break

/obj/machinery/door/airlock/proc/prison_open()
	if(emagged)	return
	src.locked = 0
	src.open()
	src.locked = 1
	return

/obj/machinery/door/airlock/proc/autoclose()
	if(!density && !operating && !locked && !welded && autoclose)
		close()

/obj/machinery/door/airlock/proc/change_paintjob(obj/item/C as obj, mob/user as mob)
	var/obj/item/weapon/airlock_painter/W
	if(istype(C, /obj/item/weapon/airlock_painter))
		W = C
	else
		user << "If you see this, it means airlock/change_paintjob() was called with something other than an airlock painter. Check your code!"
		return

	if(!W.can_use(user))
		return

	if(glass == 1)
		//These airlocks have a glass version.
		var optionlist = list("Default", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Mining")
		var paintjob = input(user, "Please select a paintjob for this airlock.") in optionlist
		if((!in_range(src, usr) && src.loc != usr) || !W.use(user))	return
		switch(paintjob)
			if("Default")
				icon = 'icons/obj/doors/Doorglass.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_glass
				heat_proof = 0
			if("Engineering")
				icon = 'icons/obj/doors/Doorengglass.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_eng/glass
				heat_proof = 0
			if("Atmospherics")
				icon = 'icons/obj/doors/Dooratmoglass.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_atmo/glass
				heat_proof = 0
			if("Security")
				icon = 'icons/obj/doors/Doorsecglass.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_sec/glass
				heat_proof = 0
			if("Command")
				icon = 'icons/obj/doors/Doorcomglass.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_com/glass
				heat_proof = 0
			if("Medical")
				icon = 'icons/obj/doors/Doormedglass.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_med/glass
				heat_proof = 0
			if("Research")
				icon = 'icons/obj/doors/Doorresearchglass.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_research/glass
				heat_proof = 1
			if("Mining")
				icon = 'icons/obj/doors/Doorminingglass.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_min/glass
				heat_proof = 0
	else
		//These airlocks have a regular version.
		var optionlist = list("Default", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Mining", "Maintenance", "External", "High Security")
		var paintjob = input(user, "Please select a paintjob for this airlock.") in optionlist
		if((!in_range(src, usr) && src.loc != usr) || !W.use(user))	return
		switch(paintjob)
			if("Default")
				icon = 'icons/obj/doors/Doorint.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_0
				heat_proof = 0
			if("Engineering")
				icon = 'icons/obj/doors/Dooreng.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_eng
				heat_proof = 0
			if("Atmospherics")
				icon = 'icons/obj/doors/Dooratmo.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_atmo
				heat_proof = 0
			if("Security")
				icon = 'icons/obj/doors/Doorsec.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_sec
				heat_proof = 0
			if("Command")
				icon = 'icons/obj/doors/Doorcom.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_com
				heat_proof = 0
			if("Medical")
				icon = 'icons/obj/doors/Doormed.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_med
				heat_proof = 0
			if("Research")
				icon = 'icons/obj/doors/Doorresearch.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_research
				heat_proof = 0
			if("Mining")
				icon = 'icons/obj/doors/Doormining.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_min
				heat_proof = 0
			if("Maintenance")
				icon = 'icons/obj/doors/Doormaint.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_mai
				heat_proof = 0
			if("External")
				icon = 'icons/obj/doors/Doorext.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_ext
				heat_proof = 0
			if("High Security")
				icon = 'icons/obj/doors/hightechsecurity.dmi'
				doortype = /obj/structure/door_assembly/door_assembly_highsecurity
				heat_proof = 0
	update_icon()

/obj/machinery/door/airlock/CanAStarPass(var/obj/item/weapon/card/id/ID)
//Airlock is passable if it is open (!density), bot has access, and is not bolted shut)
	return !density || (check_access(ID) && !locked)

/obj/machinery/door/airlock/HasProximity(atom/movable/AM as mob|obj)
	for (var/obj/A in contents)
		A.HasProximity(AM)
	return


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

/obj/item/weapon/airlock_electronics
	name = "airlock electronics"
	icon = 'icons/obj/doors/door_assembly.dmi'
	icon_state = "door_electronics"
	w_class = 2.0 //It should be tiny! -Agouri
	m_amt = 50
	g_amt = 50

	req_access = list(access_maint_tunnels)

	var/list/conf_access = null
	var/use_one_access = 0 //If the door should require ALL or only ONE of the listed accesses.
	var/last_configurator = null
	var/locked = 1

/obj/item/weapon/airlock_electronics/attack_self(mob/user as mob)
	if (!ishuman(user) && !ismommi(user))
		return ..(user)

	if(ishuman(user))
		var/mob/living/carbon/human/H = user
		if(H.getBrainLoss() >= 60)
			return

	var/t1 = text("")

	if (last_configurator)
		t1 += "Operator: [last_configurator]
"

	if (locked)
		t1 += "Swipe ID
"
	else
		t1 += "Lock Interface
"

		if(use_one_access)
			t1 += "Restriction Type: At least one access required
"
		else
			t1 += "Restriction Type: All accesses required
"

		t1 += "Remove All
"

		var/accesses = ""
		accesses += "
Access
"
		accesses += "
"
		accesses += "
"
		for(var/i = 1; i <= 7; i++)
			accesses += "[get_region_accesses_name(i)]:	"
		accesses += "

"
		for(var/i = 1; i <= 7; i++)
			accesses += ""
			for(var/A in get_region_accesses(i))
				if(A in conf_access)
					accesses += "[replacetext(get_access_desc(A), " ", "&nbsp")] "
				else
					accesses += "[replacetext(get_access_desc(A), " ", "&nbsp")] "
				accesses += "
"
			accesses += "	"
		accesses += "

"
		t1 += "<tt>[accesses]</tt>"

	t1 += text("
Close
\n", src)

	var/datum/browser/popup = new(user, "airlock_electronics", "Access Control", 900, 500)
	popup.set_content(t1)
	popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
	popup.open()
	onclose(user, "airlock")

/obj/item/weapon/airlock_electronics/Topic(href, href_list)
	..()
	if (usr.stat || usr.restrained() || (!ishuman(usr) && !ismommi(usr)))
		return
	if (href_list["close"])
		usr << browse(null, "window=airlock")
		return

	if (href_list["login"])
		var/obj/item/I = usr.get_active_hand()
		if (istype(I, /obj/item/device/pda))
			var/obj/item/device/pda/pda = I
			I = pda.id
		if (I && src.check_access(I))
			src.locked = 0
			src.last_configurator = I:registered_name
		if (ismommi(usr))
			src.locked = 0
			src.last_configurator = usr.name

	if (locked)
		return

	if (href_list["logout"])
		locked = 1

	if (href_list["access"])
		toggle_access(href_list["access"])

	attack_self(usr)

/obj/item/weapon/airlock_electronics/proc/toggle_access(var/acc)
	if (acc == "all")
		conf_access = null
	else if(acc == "one")
		use_one_access = !use_one_access
	else
		var/req = text2num(acc)

		if (conf_access == null)
			conf_access = list()

		if (!(req in conf_access))
			conf_access += req
		else
			conf_access -= req
			if (!conf_access.len)
				conf_access = null

license: mit


code:
/obj/machinery/door/airlock/alarmlock

	name = "glass alarm airlock"
	icon = 'icons/obj/doors/Doorglass.dmi'
	opacity = 0
	doortype = /obj/structure/door_assembly/door_assembly_glass
	glass = 1

	var/datum/radio_frequency/air_connection
	var/air_frequency = 1437
	autoclose = 0

/obj/machinery/door/airlock/alarmlock/New()
	..()
	air_connection = new

/obj/machinery/door/airlock/alarmlock/Destroy()
	if(radio_controller)
		radio_controller.remove_object(src,air_frequency)
	air_connection = null
	..()

/obj/machinery/door/airlock/alarmlock/initialize()
	..()
	radio_controller.remove_object(src, air_frequency)
	air_connection = radio_controller.add_object(src, air_frequency, RADIO_TO_AIRALARM)
	open()

/obj/machinery/door/airlock/alarmlock/receive_signal(datum/signal/signal)
	..()
	if(stat & (NOPOWER|BROKEN))
		return

	var/alarm_area = signal.data["zone"]
	var/alert = signal.data["alert"]

	var/area/our_area = get_area(src)

	if(alarm_area == our_area.name)
		switch(alert)
			if("severe")
				autoclose = 1
				close()
			if("minor", "clear")
				autoclose = 0
				open()


code:
#define CHARS_PER_LINE 5
#define FONT_SIZE "5pt"
#define FONT_COLOR "#09f"
#define FONT_STYLE "Arial Black"

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

///////////////////////////////////////////////////////////////////////////////////////////////
// Brig Door control displays.
//  Description: This is a controls the timer for the brig doors, displays the timer on itself and
//               has a popup window when used, allowing to set the timer.
//  Code Notes: Combination of old brigdoor.dm code from rev4407 and the status_display.dm code
//  Date: 01/September/2010
//  Programmer: Veryinky
/////////////////////////////////////////////////////////////////////////////////////////////////
/obj/machinery/door_timer
	name = "door timer"
	icon = 'icons/obj/status_display.dmi'
	icon_state = "frame"
	desc = "A remote control for a door."
	req_access = list(access_brig)
	anchored = 1.0    		// can't pick it up
	density = 0       		// can walk through it.
	var/id = null     		// id of door it controls.
	var/releasetime = 0		// when world.time reaches it - release the prisoneer
	var/timelength = 0		// the length of time this door will be set for
	var/timing = 0    		// boolean, true/1 timer is on, false/0 means it's not timing
	var/picture_state		// icon_state of alert picture, if not displaying text/numbers
	var/list/obj/machinery/targets = list()
	var/obj/item/device/radio/Radio //needed to send messages to sec radio

	maptext_height = 26
	maptext_width = 32

/obj/machinery/door_timer/New()
	..()

	Radio = new/obj/item/device/radio(src)
	Radio.listening = 0

	pixel_x = ((src.dir & 3)? (0) : (src.dir == 4 ? 32 : -32))
	pixel_y = ((src.dir & 3)? (src.dir ==1 ? 24 : -32) : (0))

	spawn(20)
		for(var/obj/machinery/door/window/brigdoor/M in world)
			if (M.id == src.id)
				targets += M

		for(var/obj/machinery/flasher/F in world)
			if(F.id == src.id)
				targets += F

		for(var/obj/structure/closet/secure_closet/brig/C in world)
			if(C.id == src.id)
				targets += C

		if(targets.len==0)
			stat |= BROKEN
		update_icon()
		return
	return

//Main door timer loop, if it's timing and time is >0 reduce time by 1.
// if it's less than 0, open door, reset timer
// update the door_timer window and the icon
/obj/machinery/door_timer/process()
	if(stat & (NOPOWER|BROKEN))	return
	if(timing)
		if(world.time > src.releasetime)
			Radio.set_frequency(SEC_FREQ)
			Radio.talk_into(src, "Timer has expired. Releasing prisoner.", SEC_FREQ)
			src.timer_end() // open doors, reset timer, clear status screen
			timing = 0
			timeset(0)
		src.updateUsrDialog()
		src.update_icon()
	else
		timer_end()
	return

// has the door power sitatuation changed, if so update icon.
/obj/machinery/door_timer/power_change()
	..()
	update_icon()
	return

// open/closedoor checks if door_timer has power, if so it checks if the
// linked door is open/closed (by density) then opens it/closes it.
/obj/machinery/door_timer/proc/timer_start()
	if(stat & (NOPOWER|BROKEN))	return 0

	for(var/obj/machinery/door/window/brigdoor/door in targets)
		if(door.density)	continue
		spawn(0)
			door.close()

	for(var/obj/structure/closet/secure_closet/brig/C in targets)
		if(C.broken)	continue
		if(C.opened && !C.close())	continue
		C.locked = 1
		C.update_icon()
	return 1

/obj/machinery/door_timer/proc/timer_end()
	if(stat & (NOPOWER|BROKEN))	return 0

	for(var/obj/machinery/door/window/brigdoor/door in targets)
		if(!door.density)	continue
		spawn(0)
			door.open()

	for(var/obj/structure/closet/secure_closet/brig/C in targets)
		if(C.broken)	continue
		if(C.opened)	continue
		C.locked = 0
		C.update_icon()

	return 1

/obj/machinery/door_timer/proc/timeleft()
	. = (timing ? (releasetime-world.time) : timelength)/10
	if(. < 0)
		. = 0

/obj/machinery/door_timer/proc/timeset(var/seconds)
	if(timing)
		releasetime=world.time+seconds*10
	else
		timelength=seconds*10
	return

//Allows AIs to use door_timer, see human attack_hand function below
/obj/machinery/door_timer/attack_ai(var/mob/user as mob)
	return src.attack_hand(user)

//Allows humans to use door_timer
//Opens dialog window when someone clicks on door timer
// Allows altering timer and the timing boolean.
// Flasher activation limited to 150 seconds
/obj/machinery/door_timer/attack_hand(var/mob/user as mob)
	if(..())
		return
	var/second = round(timeleft() % 60)
	var/minute = round((timeleft() - second) / 60)
	user.set_machine(src)
	var/dat = "<TT>"
	dat += "
Timer System:
"
	dat += "Door [src.id] controls
"
	if (timing)
		dat += "Stop Timer and open door
"
	else
		dat += "Activate Timer and close door
"

	dat += "Time Left: [(minute ? text("[minute]:") : null)][second]
"
	dat += "- - + +
"

	for(var/obj/machinery/flasher/F in targets)
		if(F.last_flash && (F.last_flash + 150) > world.time)
			dat += "
Flash Charging"
		else
			dat += "
Activate Flash"

	dat += "

Close"
	dat += "</TT>"
	user << browse(dat, "window=computer;size=400x500")
	onclose(user, "computer")
	return

//Function for using door_timer dialog input, checks if user has permission
// href_list to
//  "timing" turns on timer
//  "tp" value to modify timer
//  "fc" activates flasher
// Also updates dialog window and timer icon
/obj/machinery/door_timer/Topic(href, href_list)
	if(..())
		return
	if(!src.allowed(usr))
		return

	usr.set_machine(src)
	if(href_list["timing"]) //switch between timing and not timing
		var/timeleft = timeleft()
		timeleft = min(max(round(timeleft), 0), 600)
		timing = text2num(href_list["timing"])
		timeset(timeleft)
	else if(href_list["tp"]) //adjust timer
		var/timeleft = timeleft()
		var/tp = text2num(href_list["tp"])
		timeleft += tp
		timeleft = min(max(round(timeleft), 0), 600)
		timeset(timeleft)
		//src.timing = 1
		//src.closedoor()
	else if(href_list["fc"])
		for(var/obj/machinery/flasher/F in targets)
			F.flash()
	src.add_fingerprint(usr)
	src.updateUsrDialog()
	src.update_icon()
	if(timing)
		src.timer_start()
	else
		src.timer_end()
	return

//icon update function
// if NOPOWER, display blank
// if BROKEN, display blue screen of death icon AI uses
// if timing=true, run update display function
/obj/machinery/door_timer/update_icon()
	if(stat & (NOPOWER))
		icon_state = "frame"
		return
	if(stat & (BROKEN))
		set_picture("ai_bsod")
		return
	if(timing)
		var/disp1 = id
		var/timeleft = timeleft()
		var/disp2 = "[add_zero(num2text((timeleft / 60) % 60),2)]~[add_zero(num2text(timeleft % 60), 2)]"
		if(length(disp2) > CHARS_PER_LINE)
			disp2 = "Error"
		update_display(disp1, disp2)
	else
		if(maptext)	maptext = ""
	return

// Adds an icon in case the screen is broken/off, stolen from status_display.dm
/obj/machinery/door_timer/proc/set_picture(var/state)
	if(maptext)	maptext = ""
	picture_state = state
	overlays.Cut()
	overlays += image('icons/obj/status_display.dmi', icon_state=picture_state)

//Checks to see if there's 1 line or 2, adds text-icons-numbers/letters over display
// Stolen from status_display
/obj/machinery/door_timer/proc/update_display(line1, line2)
	var/new_text = {"
[line1]
[line2]
"}
	if(maptext != new_text)
		maptext = new_text

#undef FONT_SIZE
#undef FONT_COLOR
#undef FONT_STYLE
#undef CHARS_PER_LINE


code:
/obj/machinery/door/proc/checkForMultipleDoors()
	if(!src.loc)
		return 0
	for(var/obj/machinery/door/D in src.loc)
		if(!istype(D, /obj/machinery/door/window) && D.density && D != src)
			return 0
	return 1

/turf/simulated/wall/proc/checkForMultipleDoors()
	if(!src.loc)
		return 0
	for(var/obj/machinery/door/D in locate(src.x,src.y,src.z))
		if(!istype(D, /obj/machinery/door/window) && D.density)
			return 0
	//There are no false wall checks because that would be fucking retarded
	return 1


code:
/obj/machinery/door
	name = "door"
	desc = "It opens and closes."
	icon = 'icons/obj/doors/Doorint.dmi'
	icon_state = "door1"
	anchored = 1
	opacity = 1
	density = 1
	layer = 2.7
	power_channel = ENVIRON

	var/secondsElectrified = 0
	var/visible = 1
	var/p_open = 0
	var/operating = 0
	var/glass = 0
	var/normalspeed = 1
	var/heat_proof = 0 // For glass airlocks/opacity firedoors
	var/emergency = 0 // Emergency access override
	var/sub_door = 0 // 1 if it's meant to go under another door.

/obj/machinery/door/New()
	..()
	if(density)
		layer = 3.1 //Above most items if closed
	else
		layer = 2.7 //Under all objects if opened. 2.7 due to tables being at 2.6
	update_freelook_sight()
	air_update_turf(1)
	airlocks += src
	return

/obj/machinery/door/Destroy()
	density = 0
	air_update_turf(1)
	update_freelook_sight()
	airlocks -= src
	..()
	return

//process()
	//return

/obj/machinery/door/Bumped(atom/AM)
	if(operating || emagged) return
	if(ismob(AM))
		var/mob/M = AM
		if(world.time - M.last_bumped <= 10) return	//Can bump-open one airlock per second. This is to prevent shock spam.
		M.last_bumped = world.time
		if(!M.restrained())
			bumpopen(M)
		return

	if(istype(AM, /obj/machinery/bot))
		var/obj/machinery/bot/bot = AM
		if(src.check_access(bot.botcard) || emergency == 1)
			if(density)
				open()
		return

	if(istype(AM, /obj/mecha))
		var/obj/mecha/mecha = AM
		if(density)
			if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access) || emergency == 1))
				open()
			else
				flick("door_deny", src)
		return
	return

/obj/machinery/door/Move()
	var/turf/T = loc
	..()
	move_update_air(T)

/obj/machinery/door/CanPass(atom/movable/mover, turf/target, height=0)
	if(istype(mover) && mover.checkpass(PASSGLASS))
		return !opacity
	return !density

/obj/machinery/door/CanAtmosPass()
	return !density

//used in the AStar algorithm to determinate if the turf the door is on is passable
/obj/machinery/door/proc/CanAStarPass(var/obj/item/weapon/card/id/ID)
	return !density

/obj/machinery/door/proc/bumpopen(mob/user as mob)
	if(operating)
		return
	src.add_fingerprint(user)
	if(!src.requiresID())
		user = null

	if(density && !emagged)
		if(allowed(user) || src.emergency == 1)
			open()
		else
			flick("door_deny", src)
	return

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

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

/obj/machinery/door/attack_hand(mob/user as mob)
	return src.attackby(user, user)

/obj/machinery/door/attack_tk(mob/user as mob)
	if(requiresID() && !allowed(null))
		return
	..()

/obj/machinery/door/narsie_act()
	qdel(src)

/obj/machinery/door/attackby(obj/item/I as obj, mob/user as mob, params)
	if(istype(I, /obj/item/device/detective_scanner))
		return
	if(isrobot(user))	return //borgs can't attack doors open because it conflicts with their AI-like interaction with them.
	src.add_fingerprint(user)
	if(operating || emagged)	return
	if(!Adjacent(user))
		user = null
	if(!src.requiresID())
		user = null
	if(src.allowed(user) || src.emergency == 1)
		if(src.density)
			open()
		else
			close()
		return
	if(src.density)
		flick("door_deny", src)
	return

/obj/machinery/door/emag_act(mob/user as mob)
	if(density && hasPower() && !emagged)
		flick("door_spark", src)
		sleep(6)
		open()
		emagged = 1
		desc = "Its access panel is smoking slightly."
		if(istype(src, /obj/machinery/door/airlock))
			var/obj/machinery/door/airlock/A = src
			A.lights = 0
			A.locked = 1
			A.loseMainPower()
			A.loseBackupPower()
			A.update_icon()

/obj/machinery/door/blob_act()
	if(prob(40))
		qdel(src)
	return

/obj/machinery/door/emp_act(severity)
	if(prob(20/severity) && (istype(src,/obj/machinery/door/airlock) || istype(src,/obj/machinery/door/window)) )
		open()
	if(prob(40/severity))
		if(secondsElectrified == 0)
			secondsElectrified = -1
			spawn(300)
				secondsElectrified = 0
	..()

/obj/machinery/door/ex_act(severity, target)
	if(severity == 3)
		if(prob(80))
			var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
			s.set_up(2, 1, src)
			s.start()
		return
	..()

/obj/machinery/door/update_icon()
	if(density)
		icon_state = "door1"
	else
		icon_state = "door0"
	return

/obj/machinery/door/proc/do_animate(animation)
	switch(animation)
		if("opening")
			if(p_open)
				flick("o_doorc0", src)
			else
				flick("doorc0", src)
		if("closing")
			if(p_open)
				flick("o_doorc1", src)
			else
				flick("doorc1", src)
		if("deny")
			flick("door_deny", src)
	return

/obj/machinery/door/proc/open()
	if(!density)
		return 1
	if(operating)
		return
	if(!ticker)
		return 0
	operating = 1

	do_animate("opening")
	icon_state = "door0"
	src.set_opacity(0)
	sleep(5)
	src.density = 0
	sleep(5)
	src.layer = 2.7
	update_icon()
	src.set_opacity(0)
	operating = 0
	air_update_turf(1)
	update_freelook_sight()
	return 1

/obj/machinery/door/proc/close()
	if(density)
		return 1
	if(operating)
		return
	operating = 1

	do_animate("closing")
	src.layer = 3.1
	sleep(5)
	src.density = 1
	sleep(5)
	update_icon()
	if(visible && !glass)
		src.set_opacity(1)
	operating = 0
	air_update_turf(1)
	update_freelook_sight()
	return

/obj/machinery/door/proc/crush()
	for(var/mob/living/L in get_turf(src))
		if(isalien(L))  //For xenos
			L.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 1.5) //Xenos go into crit after aproximately the same amount of crushes as humans.
			L.emote("roar")
		else if(ishuman(L)) //For humans
			L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
			L.emote("scream")
			L.Weaken(5)
		else if(ismonkey(L)) //For monkeys
			L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
			L.Weaken(5)
		else //for simple_animals & borgs
			L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
		var/turf/location = src.loc
		if(istype(location, /turf/simulated)) //add_blood doesn't work for borgs/xenos, but add_blood_floor does.
			location.add_blood_floor(L)
	for(var/obj/mecha/M in get_turf(src))
		M.take_damage(DOOR_CRUSH_DAMAGE)

/obj/machinery/door/proc/requiresID()
	return 1

/obj/machinery/door/proc/hasPower()
	return !(stat & NOPOWER)

/obj/machinery/door/BlockSuperconductivity()
	if(opacity || heat_proof)
		return 1
	return 0

/obj/machinery/door/morgue
	icon = 'icons/obj/doors/doormorgue.dmi'


code:
/var/const/OPEN = 1
/var/const/CLOSED = 2

/obj/machinery/door/firedoor
	name = "firelock"
	desc = "Apply crowbar."
	icon = 'icons/obj/doors/Doorfireglass.dmi'
	icon_state = "door_open"
	opacity = 0
	density = 0
	heat_proof = 1
	glass = 1
	var/blocked = 0
	var/nextstate = null
	sub_door = 1

/obj/machinery/door/firedoor/Bumped(atom/AM)
	if(p_open || operating)	return
	if(!density)	return ..()
	return 0

/obj/machinery/door/firedoor/power_change()
	if(powered(power_channel))
		stat &= ~NOPOWER
		latetoggle()
	else
		stat |= NOPOWER
	return

/obj/machinery/door/firedoor/attackby(obj/item/weapon/C as obj, mob/user as mob, params)
	add_fingerprint(user)
	if(operating)	return//Already doing something.
	if(istype(C, /obj/item/weapon/weldingtool))
		var/obj/item/weapon/weldingtool/W = C
		if(W.remove_fuel(0, user))
			blocked = !blocked
			user << text("You [blocked?"welded":"unwelded"] \the [src]")
			update_icon()
			return

	if(istype(C, /obj/item/weapon/crowbar) || (istype(C,/obj/item/weapon/twohanded/fireaxe) && C:wielded == 1))
		if(blocked || operating)	return
		if(density)
			open()
			return
		else	//close it up again	//fucking 10/10 commenting here einstein //bravo nolan
			close()
			return
	return

/obj/machinery/door/firedoor/attack_ai(mob/user as mob)
	add_fingerprint(user)
	if(blocked || operating || stat & NOPOWER)
		return
	if(density)
		open()
	else
		close()
	return

/obj/machinery/door/firedoor/do_animate(animation)
	switch(animation)
		if("opening")
			flick("door_opening", src)
		if("closing")
			flick("door_closing", src)
	return

/obj/machinery/door/firedoor/update_icon()
	overlays.Cut()
	if(density)
		icon_state = "door_closed"
		if(blocked)
			overlays += "welded"
	else
		icon_state = "door_open"
		if(blocked)
			overlays += "welded_open"
	return

/obj/machinery/door/firedoor/open()
	..()
	latetoggle()
	return

/obj/machinery/door/firedoor/close()
	..()
	if(locate(/mob/living) in get_turf(src))
		open()
		return
	latetoggle()
	return

/obj/machinery/door/firedoor/proc/latetoggle()
	if(operating || stat & NOPOWER || !nextstate)
		return
	switch(nextstate)
		if(OPEN)
			nextstate = null
			open()
		if(CLOSED)
			nextstate = null
			close()
	return

/obj/machinery/door/firedoor/border_only
	icon = 'icons/obj/doors/edge_Doorfire.dmi'
	flags = ON_BORDER

/obj/machinery/door/firedoor/border_only/CanPass(atom/movable/mover, turf/target, height=0)
	if(istype(mover) && mover.checkpass(PASSGLASS))
		return 1
	if(get_dir(loc, target) == dir) //Make sure looking at appropriate border
		return !density
	else
		return 1

/obj/machinery/door/firedoor/border_only/CheckExit(atom/movable/mover as mob|obj, turf/target as turf)
	if(istype(mover) && mover.checkpass(PASSGLASS))
		return 1
	if(get_dir(loc, target) == dir)
		return !density
	else
		return 1

/obj/machinery/door/firedoor/border_only/CanAtmosPass(var/turf/T)
	if(get_dir(loc, T) == dir)
		return !density
	else
		return 1

/obj/machinery/door/firedoor/heavy
	name = "heavy firelock"
	icon = 'icons/obj/doors/Doorfire.dmi'
	glass = 0


code:
/obj/machinery/door/poddoor
	name = "blast door"
	desc = "A heavy duty blast door that opens mechanically."
	icon = 'icons/obj/doors/blastdoor.dmi'
	icon_state = "closed"
	var/id = 1
	var/auto_close = 0 // Time in seconds to automatically close when opened, 0 if it doesn't.
	sub_door = 1
	explosion_block = 3

/obj/machinery/door/poddoor/preopen
	icon_state = "open"
	density = 0
	opacity = 0

/obj/machinery/door/poddoor/Bumped(atom/AM)
	if(density)
		return 0
	else
		return ..()

/obj/machinery/door/poddoor/attackby(obj/item/I, mob/user, params)
	add_fingerprint(user)

	if(istype(I, /obj/item/weapon/twohanded/fireaxe))
		var/obj/item/weapon/twohanded/fireaxe/F = I
		if(!F.wielded)
			return
	else if(!istype(I, /obj/item/weapon/crowbar))
		return

	if(stat & NOPOWER)
		open(1)	//ignore the usual power requirement.

/obj/machinery/door/poddoor/open(ignorepower = 0)
	if(operating)
		return
	if(!density)
		return
	if(!ignorepower && (stat & NOPOWER))
		return

	operating = 1
	flick("opening", src)
	icon_state = "open"
	src.set_opacity(0)
	sleep(5)
	density = 0
	sleep(5)
	air_update_turf(1)
	update_freelook_sight()
	operating = 0

	if(auto_close)
		spawn(auto_close)
			// Checks for being able to close are in close().
			close()

	return 1

/obj/machinery/door/poddoor/close(ignorepower = 0)
	if(operating)
		return
	if(density)
		return
	if(!ignorepower && (stat & NOPOWER))
		return

	operating = 1
	flick("closing", src)
	icon_state = "closed"
	src.set_opacity(1)
	air_update_turf(1)
	update_freelook_sight()
	sleep(5)
	crush()
	density = 1
	sleep(5)

	operating = 0

/obj/machinery/door/poddoor/ex_act(severity, target)
	switch(severity)
		if(1.0)
			if(prob(80))
				qdel(src)
			else
				var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
				s.set_up(2, 1, src)
				s.start()
		if(2.0)
			if(prob(20))
				qdel(src)
			else
				var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
				s.set_up(2, 1, src)
				s.start()

		if(3.0)
			if(prob(80))
				var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
				s.set_up(2, 1, src)
				s.start()

/*
/obj/machinery/door/poddoor/two_tile_hor/open()
	if (src.operating == 1) //doors can still open when emag-disabled
		return
	if (!ticker)
		return 0
	if(!src.operating) //in case of emag
		src.operating = 1
	flick("pdoorc0", src)
	src.icon_state = "pdoor0"
	src.SetOpacity(0)
	f1.SetOpacity(0)
	f2.SetOpacity(0)

	sleep(10)
	src.density = 0
	f1.density = 0
	f2.density = 0

	update_nearby_tiles()

	if(operating == 1) //emag again
		src.operating = 0
	if(autoclose)
		spawn(150)
			autoclose()
	return 1

/obj/machinery/door/poddoor/two_tile_hor/close()
	if (src.operating)
		return
	src.operating = 1
	flick("pdoorc1", src)
	src.icon_state = "pdoor1"

	src.density = 1
	f1.density = 1
	f2.density = 1

	sleep(10)
	src.SetOpacity(initial(opacity))
	f1.SetOpacity(initial(opacity))
	f2.SetOpacity(initial(opacity))

	update_nearby_tiles()

	src.operating = 0
	return

/obj/machinery/door/poddoor/four_tile_hor/open()
	if (src.operating == 1) //doors can still open when emag-disabled
		return
	if (!ticker)
		return 0
	if(!src.operating) //in case of emag
		src.operating = 1
	flick("pdoorc0", src)
	src.icon_state = "pdoor0"
	sleep(10)
	src.density = 0
	src.sd_SetOpacity(0)

	f1.density = 0
	f1.sd_SetOpacity(0)
	f2.density = 0
	f2.sd_SetOpacity(0)
	f3.density = 0
	f3.sd_SetOpacity(0)
	f4.density = 0
	f4.sd_SetOpacity(0)

	update_nearby_tiles()

	if(operating == 1) //emag again
		src.operating = 0
	if(autoclose)
		spawn(150)
			autoclose()
	return 1

/obj/machinery/door/poddoor/four_tile_hor/close()
	if (src.operating)
		return
	src.operating = 1
	flick("pdoorc1", src)
	src.icon_state = "pdoor1"
	src.density = 1

	f1.density = 1
	f1.sd_SetOpacity(1)
	f2.density = 1
	f2.sd_SetOpacity(1)
	f3.density = 1
	f3.sd_SetOpacity(1)
	f4.density = 1
	f4.sd_SetOpacity(1)

	if (src.visible)
		src.sd_SetOpacity(1)
	update_nearby_tiles()

	sleep(10)
	src.operating = 0
	return

/obj/machinery/door/poddoor/two_tile_ver/open()
	if (src.operating == 1) //doors can still open when emag-disabled
		return
	if (!ticker)
		return 0
	if(!src.operating) //in case of emag
		src.operating = 1
	flick("pdoorc0", src)
	src.icon_state = "pdoor0"
	sleep(10)
	src.density = 0
	src.sd_SetOpacity(0)

	f1.density = 0
	f1.sd_SetOpacity(0)
	f2.density = 0
	f2.sd_SetOpacity(0)

	update_nearby_tiles()

	if(operating == 1) //emag again
		src.operating = 0
	if(autoclose)
		spawn(150)
			autoclose()
	return 1

/obj/machinery/door/poddoor/two_tile_ver/close()
	if (src.operating)
		return
	src.operating = 1
	flick("pdoorc1", src)
	src.icon_state = "pdoor1"
	src.density = 1

	f1.density = 1
	f1.sd_SetOpacity(1)
	f2.density = 1
	f2.sd_SetOpacity(1)

	if (src.visible)
		src.sd_SetOpacity(1)
	update_nearby_tiles()

	sleep(10)
	src.operating = 0
	return

/obj/machinery/door/poddoor/four_tile_ver/open()
	if (src.operating == 1) //doors can still open when emag-disabled
		return
	if (!ticker)
		return 0
	if(!src.operating) //in case of emag
		src.operating = 1
	flick("pdoorc0", src)
	src.icon_state = "pdoor0"
	sleep(10)
	src.density = 0
	src.sd_SetOpacity(0)

	f1.density = 0
	f1.sd_SetOpacity(0)
	f2.density = 0
	f2.sd_SetOpacity(0)
	f3.density = 0
	f3.sd_SetOpacity(0)
	f4.density = 0
	f4.sd_SetOpacity(0)

	update_nearby_tiles()

	if(operating == 1) //emag again
		src.operating = 0
	if(autoclose)
		spawn(150)
			autoclose()
	return 1

/obj/machinery/door/poddoor/four_tile_ver/close()
	if (src.operating)
		return
	src.operating = 1
	flick("pdoorc1", src)
	src.icon_state = "pdoor1"
	src.density = 1

	f1.density = 1
	f1.sd_SetOpacity(1)
	f2.density = 1
	f2.sd_SetOpacity(1)
	f3.density = 1
	f3.sd_SetOpacity(1)
	f4.density = 1
	f4.sd_SetOpacity(1)

	if (src.visible)
		src.sd_SetOpacity(1)
	update_nearby_tiles()

	sleep(10)
	src.operating = 0
	return

/obj/machinery/door/poddoor/two_tile_hor
	var/obj/machinery/door/poddoor/filler_object/f1
	var/obj/machinery/door/poddoor/filler_object/f2
	icon = 'icons/obj/doors/1x2blast_hor.dmi'

	New()
		..()
		f1 = new/obj/machinery/door/poddoor/filler_object (src.loc)
		f2 = new/obj/machinery/door/poddoor/filler_object (get_step(src,EAST))
		f1.density = density
		f2.density = density
		f1.sd_SetOpacity(opacity)
		f2.sd_SetOpacity(opacity)

	Destroy()
		qdel(f1)
		qdel(f2)
		..()

/obj/machinery/door/poddoor/two_tile_ver
	var/obj/machinery/door/poddoor/filler_object/f1
	var/obj/machinery/door/poddoor/filler_object/f2
	icon = 'icons/obj/doors/1x2blast_vert.dmi'

	New()
		..()
		f1 = new/obj/machinery/door/poddoor/filler_object (src.loc)
		f2 = new/obj/machinery/door/poddoor/filler_object (get_step(src,NORTH))
		f1.density = density
		f2.density = density
		f1.sd_SetOpacity(opacity)
		f2.sd_SetOpacity(opacity)

	Destroy()
		qdel(f1)
		qdel(f2)
		..()

/obj/machinery/door/poddoor/four_tile_hor
	var/obj/machinery/door/poddoor/filler_object/f1
	var/obj/machinery/door/poddoor/filler_object/f2
	var/obj/machinery/door/poddoor/filler_object/f3
	var/obj/machinery/door/poddoor/filler_object/f4
	icon = 'icons/obj/doors/1x4blast_hor.dmi'

	New()
		..()
		f1 = new/obj/machinery/door/poddoor/filler_object (src.loc)
		f2 = new/obj/machinery/door/poddoor/filler_object (get_step(f1,EAST))
		f3 = new/obj/machinery/door/poddoor/filler_object (get_step(f2,EAST))
		f4 = new/obj/machinery/door/poddoor/filler_object (get_step(f3,EAST))
		f1.density = density
		f2.density = density
		f3.density = density
		f4.density = density
		f1.sd_SetOpacity(opacity)
		f2.sd_SetOpacity(opacity)
		f4.sd_SetOpacity(opacity)
		f3.sd_SetOpacity(opacity)

	Destroy()
		qdel(f1)
		qdel(f2)
		qdel(f3)
		qdel(f4)
		..()

/obj/machinery/door/poddoor/four_tile_ver
	var/obj/machinery/door/poddoor/filler_object/f1
	var/obj/machinery/door/poddoor/filler_object/f2
	var/obj/machinery/door/poddoor/filler_object/f3
	var/obj/machinery/door/poddoor/filler_object/f4
	icon = 'icons/obj/doors/1x4blast_vert.dmi'

	New()
		..()
		f1 = new/obj/machinery/door/poddoor/filler_object (src.loc)
		f2 = new/obj/machinery/door/poddoor/filler_object (get_step(f1,NORTH))
		f3 = new/obj/machinery/door/poddoor/filler_object (get_step(f2,NORTH))
		f4 = new/obj/machinery/door/poddoor/filler_object (get_step(f3,NORTH))
		f1.density = density
		f2.density = density
		f3.density = density
		f4.density = density
		f1.sd_SetOpacity(opacity)
		f2.sd_SetOpacity(opacity)
		f4.sd_SetOpacity(opacity)
		f3.sd_SetOpacity(opacity)

	Destroy()
		qdel(f1)
		qdel(f2)
		qdel(f3)
		qdel(f4)
		..()

/obj/machinery/door/poddoor/filler_object
	name = ""
	icon_state = ""

*/


code:
/obj/machinery/door/poddoor/shutters
	gender = PLURAL
	name = "shutters"
	desc = "Heavy duty metal shutters that opens mechanically."
	icon = 'icons/obj/doors/shutters.dmi'
	layer = 3.1

/obj/machinery/door/poddoor/shutters/preopen
	icon_state = "open"
	density = 0
	opacity = 0

//shutters look like ass with things on top of them.

/obj/machinery/door/poddoor/shutters/New()
	..()
	layer = 3.1	//to handle /obj/machinery/door/New() resetting the layer.

/obj/machinery/door/poddoor/shutters/open(ignorepower = 0)
	..()
	layer = 3.1

/obj/machinery/door/poddoor/shutters/close(ignorepower = 0)
	..()
	layer = 3.1


code:
/obj/machinery/door/unpowered
	var/locked = 0

/obj/machinery/door/unpowered/Bumped(atom/AM)
	if(src.locked)	return
	..()
	return

/obj/machinery/door/unpowered/attackby(obj/item/I as obj, mob/user as mob, params)
	if(src.locked)	return
	..()
	return

/obj/machinery/door/unpowered/emag_act()
	return

/obj/machinery/door/unpowered/shuttle
	icon = 'icons/turf/shuttle.dmi'
	name = "door"
	icon_state = "door1"
	opacity = 1
	density = 1
	explosion_block = 1


code:
/obj/machinery/door/window
	name = "interior door"
	desc = "A strong door."
	icon = 'icons/obj/doors/windoor.dmi'
	icon_state = "left"
	var/base_state = "left"
	var/health = 150.0 //If you change this, consider changing ../door/window/brigdoor/ health at the bottom of this .dm file
	visible = 0.0
	flags = ON_BORDER
	opacity = 0
	var/obj/item/weapon/airlock_electronics/electronics = null

/obj/machinery/door/window/New()
	..()

	if (src.req_access && src.req_access.len)
		src.icon_state = "[src.icon_state]"
		src.base_state = src.icon_state
	return

/obj/machinery/door/window/Destroy()
	density = 0
	if(health == 0)
		playsound(src, "shatter", 70, 1)
	electronics = null
	..()

/obj/machinery/door/window/proc/open_and_close()
	open()
	if(src.check_access(null))
		sleep(50)
	else //secure doors close faster
		sleep(20)
	close()

/obj/machinery/door/window/Bumped(atom/movable/AM as mob|obj)
	if( operating || !src.density )
		return
	if (!( ismob(AM) ))
		var/obj/machinery/bot/bot = AM
		if(istype(bot))
			if(src.check_access(bot.botcard))
				open_and_close()
			else
				flick("[src.base_state]deny", src)
		else if(istype(AM, /obj/mecha))
			var/obj/mecha/mecha = AM
			if(mecha.occupant && src.allowed(mecha.occupant))
				open_and_close()
			else
				flick("[src.base_state]deny", src)
		return
	if (!( ticker ))
		return
	var/mob/M = AM
	if(!M.restrained())
		bumpopen(M)
	return

/obj/machinery/door/window/bumpopen(mob/user as mob)
	if( operating || !src.density )
		return
	src.add_fingerprint(user)
	if(!src.requiresID())
		user = null

	if(allowed(user))
		open_and_close()
	else
		flick("[src.base_state]deny", src)
	return

/obj/machinery/door/window/CanPass(atom/movable/mover, turf/target, height=0)
	if(istype(mover) && mover.checkpass(PASSGLASS))
		return 1
	if(get_dir(loc, target) == dir) //Make sure looking at appropriate border
		return !density
	else
		return 1

/obj/machinery/door/window/CanAtmosPass(var/turf/T)
	if(get_dir(loc, T) == dir)
		return !density
	else
		return 1

//used in the AStar algorithm to determinate if the turf the door is on is passable
/obj/machinery/door/window/CanAStarPass(var/obj/item/weapon/card/id/ID, var/to_dir)
	return !density || (dir != to_dir) || check_access(ID)

/obj/machinery/door/window/CheckExit(atom/movable/mover as mob|obj, turf/target as turf)
	if(istype(mover) && mover.checkpass(PASSGLASS))
		return 1
	if(get_dir(loc, target) == dir)
		return !density
	else
		return 1

/obj/machinery/door/window/open(var/forced=0)
	if (src.operating == 1) //doors can still open when emag-disabled
		return 0
	if (!ticker)
		return 0
	if(!forced)
		if(!hasPower())
			return 0
	if(forced < 2)
		if(emagged)
			return 0
	if(!src.operating) //in case of emag
		src.operating = 1
	flick("[src.base_state]opening", src)
	playsound(src.loc, 'sound/machines/windowdoor.ogg', 100, 1)
	src.icon_state ="[src.base_state]open"
	sleep(10)

	src.density = 0
//	src.sd_SetOpacity(0)	//TODO: why is this here? Opaque windoors? ~Carn
	air_update_turf(1)
	update_freelook_sight()

	if(operating == 1) //emag again
		src.operating = 0
	return 1

/obj/machinery/door/window/close(var/forced=0)
	if (src.operating)
		return 0
	if(!forced)
		if(!hasPower())
			return 0
	if(forced < 2)
		if(emagged)
			return 0
	src.operating = 1
	flick("[src.base_state]closing", src)
	playsound(src.loc, 'sound/machines/windowdoor.ogg', 100, 1)
	src.icon_state = src.base_state

	src.density = 1
//	if(src.visible)
//		SetOpacity(1)	//TODO: why is this here? Opaque windoors? ~Carn
	air_update_turf(1)
	update_freelook_sight()
	sleep(10)

	src.operating = 0
	return 1

/obj/machinery/door/window/proc/take_damage(var/damage)
	src.health = max(0, src.health - damage)
	if (src.health <= 0)
		var/debris = list(
			new /obj/item/weapon/shard(src.loc),
			new /obj/item/weapon/shard(src.loc),
			new /obj/item/stack/rods(src.loc, 2),
			new /obj/item/stack/cable_coil(src.loc, 2)
			)
		for(var/obj/fragment in debris)
			transfer_fingerprints_to(fragment)
		src.density = 0
		qdel(src)
		return

/obj/machinery/door/window/ex_act(severity, target)
	switch(severity)
		if(1.0)
			qdel(src)
		if(2.0)
			if(prob(25))
				qdel(src)
			else
				take_damage(120)
		if(3.0)
			take_damage(60)

/obj/machinery/door/window/bullet_act(var/obj/item/projectile/Proj)
	if(Proj.damage)
		if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
			take_damage(round(Proj.damage / 2))
	..()

//When an object is thrown at the window
/obj/machinery/door/window/hitby(AM as mob|obj)

	..()
	visible_message("\The [src] was hit by \the [AM].")
	var/tforce = 0
	if(ismob(AM))
		tforce = 40
	else
		tforce = AM:throwforce
	playsound(src.loc, 'sound/effects/Glasshit.ogg', 100, 1)
	take_damage(tforce)
	//..() //Does this really need to be here twice? The parent proc doesn't even do anything yet. - Nodrak
	return

/obj/machinery/door/window/mech_melee_attack(obj/mecha/M)
	if(M.damtype == "brute")
		playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
		visible_message("[M.name] has hit [src].")
		take_damage(M.force)
	return

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

/obj/machinery/door/window/proc/attack_generic(mob/user as mob, damage = 0)
	if(src.operating)
		return
	user.changeNext_move(CLICK_CD_MELEE)
	playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
	user.visible_message("[user] smashes against the [src.name].", \
				"[user] smashes against the [src.name].")
	take_damage(damage)

/obj/machinery/door/window/attack_alien(mob/living/user as mob)
	user.do_attack_animation(src)
	if(islarva(user))
		return
	attack_generic(user, 25)

/obj/machinery/door/window/attack_animal(mob/living/user as mob)
	if(!isanimal(user))
		return
	var/mob/living/simple_animal/M = user
	M.do_attack_animation(src)
	if(M.melee_damage_upper <= 0)
		return
	attack_generic(M, M.melee_damage_upper)

/obj/machinery/door/window/attack_slime(mob/living/carbon/slime/user as mob)
	user.do_attack_animation(src)
	if(!user.is_adult)
		return
	attack_generic(user, 25)

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

/obj/machinery/door/window/attack_hand(mob/user as mob)
	return src.attackby(user, user)

/obj/machinery/door/window/emag_act(mob/user as mob)
	if(density && !emagged)
		operating = 0
		flick("[src.base_state]spark", src)
		sleep(6)
		desc += "
Its access panel is smoking slightly."
		open()
		emagged = 1

/obj/machinery/door/window/attackby(obj/item/weapon/I as obj, mob/living/user as mob, params)

	//If it's in the process of opening/closing, ignore the click
	if (src.operating)
		return

	add_fingerprint(user)

	if(istype(I, /obj/item/weapon/screwdriver))
		if(src.density || src.operating)
			user << "You need to open the door to access the maintenance panel."
			return
		playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
		src.p_open = !( src.p_open )
		user << "You [p_open ? "open":"close"] the maintenance panel of the [src.name]."
		return

	if(istype(I, /obj/item/weapon/crowbar))
		if(p_open && !src.density && !src.operating)
			playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
			user.visible_message("[user] removes the electronics from the [src.name].", \
								 "You start to remove electronics from the [src.name].")
			if(do_after(user,40))
				if(src.p_open && !src.density && !src.operating && src.loc)
					var/obj/structure/windoor_assembly/WA = new /obj/structure/windoor_assembly(src.loc)
					switch(base_state)
						if("left")
							WA.facing = "l"
						if("right")
							WA.facing = "r"
						if("leftsecure")
							WA.facing = "l"
							WA.secure = 1
						if("rightsecure")
							WA.facing = "r"
							WA.secure = 1
					WA.anchored = 1
					WA.state= "02"
					WA.dir = src.dir
					WA.ini_dir = src.dir
					WA.update_icon()
					WA.created_name = src.name

					if(emagged)
						user << "You discard the damaged electronics."
						qdel(src)
						return

					user << "You removed the airlock electronics!"

					var/obj/item/weapon/airlock_electronics/ae
					if(!electronics)
						ae = new/obj/item/weapon/airlock_electronics( src.loc )
						if(req_one_access)
							ae.use_one_access = 1
							ae.conf_access = src.req_one_access
						else
							ae.conf_access = src.req_access
					else
						ae = electronics
						electronics = null
						ae.loc = src.loc

					qdel(src)
			return

	//If windoor is unpowered, crowbar, fireaxe and armblade can force it.
	if(istype(I, /obj/item/weapon/crowbar) || istype(I, /obj/item/weapon/twohanded/fireaxe) || istype(I, /obj/item/weapon/melee/arm_blade) )
		if(!hasPower())
			if(src.density)
				open(2)
			else
				close(2)
			return

	//If it's a weapon, smash windoor. Unless it's an id card, agent card, ect.. then ignore it (Cards really shouldnt damage a door anyway)
	if(src.density && istype(I, /obj/item/weapon) && !istype(I, /obj/item/weapon/card) )
		user.changeNext_move(CLICK_CD_MELEE)
		user.do_attack_animation(src)
		if( (I.flags&NOBLUDGEON) || !I.force )
			return
		var/aforce = I.force
		playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
		visible_message("[user] has hit \the [src] with [I].")
		if(I.damtype == BURN || I.damtype == BRUTE)
			take_damage(aforce)
		return

	if (!src.requiresID())
		//don't care who they are or what they have, act as if they're NOTHING
		user = null

	if (src.allowed(user))
		if (src.density)
			open()
		else
			close()

	else if (src.density)
		flick("[src.base_state]deny", src)

	return

/obj/machinery/door/window/brigdoor
	name = "secure door"
	icon = 'icons/obj/doors/windoor.dmi'
	icon_state = "leftsecure"
	base_state = "leftsecure"
	var/id = null
	health = 300.0 //Stronger doors for prison (regular window door health is 200)

/obj/machinery/door/window/northleft
	dir = NORTH

/obj/machinery/door/window/eastleft
	dir = EAST

/obj/machinery/door/window/westleft
	dir = WEST

/obj/machinery/door/window/southleft
	dir = SOUTH

/obj/machinery/door/window/northright
	dir = NORTH
	icon_state = "right"
	base_state = "right"

/obj/machinery/door/window/eastright
	dir = EAST
	icon_state = "right"
	base_state = "right"

/obj/machinery/door/window/westright
	dir = WEST
	icon_state = "right"
	base_state = "right"

/obj/machinery/door/window/southright
	dir = SOUTH
	icon_state = "right"
	base_state = "right"

/obj/machinery/door/window/brigdoor/northleft
	dir = NORTH

/obj/machinery/door/window/brigdoor/eastleft
	dir = EAST

/obj/machinery/door/window/brigdoor/westleft
	dir = WEST

/obj/machinery/door/window/brigdoor/southleft
	dir = SOUTH

/obj/machinery/door/window/brigdoor/northright
	dir = NORTH
	icon_state = "rightsecure"
	base_state = "rightsecure"

/obj/machinery/door/window/brigdoor/eastright
	dir = EAST
	icon_state = "rightsecure"
	base_state = "rightsecure"

/obj/machinery/door/window/brigdoor/westright
	dir = WEST
	icon_state = "rightsecure"
	base_state = "rightsecure"

/obj/machinery/door/window/brigdoor/southright
	dir = SOUTH
	icon_state = "rightsecure"
	base_state = "rightsecure"


code:
var/list/doppler_arrays = list()

/obj/machinery/doppler_array
	name = "tachyon-doppler array"
	desc = "A highly precise directional sensor array which measures the release of quants from decaying tachyons. The doppler shifting of the mirror-image formed by these quants can reveal the size, location and temporal affects of energetic disturbances within a large radius ahead of the array."
	icon = 'icons/obj/machines/research.dmi'
	icon_state = "tdoppler"
	density = 1
	anchored = 1

/obj/machinery/doppler_array/New()
	..()
	doppler_arrays += src

/obj/machinery/doppler_array/Destroy()
	doppler_arrays -= src
	..()

/obj/machinery/doppler_array/process()
	return PROCESS_KILL

/obj/machinery/doppler_array/attackby(var/obj/item/O as obj, var/mob/user as mob, params)
	if(istype(O, /obj/item/weapon/wrench))
		if(!anchored && !isinspace())
			anchored = 1
			power_change()
			user << "You fasten [src]."
		else if(anchored)
			anchored = 0
			power_change()
			user << "You unfasten [src]."
		playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)

/obj/machinery/doppler_array/verb/rotate()
	set name = "Rotate Tachyon-doppler Dish"
	set category = "Object"
	set src in oview(1)

	if(!usr || !isturf(usr.loc))
		return
	if(usr.stat || usr.restrained() || !usr.canmove)
		return
	src.dir = turn(src.dir, 90)
	return

/obj/machinery/doppler_array/proc/sense_explosion(var/x0,var/y0,var/z0,var/devastation_range,var/heavy_impact_range,var/light_impact_range,
												  var/took,var/orig_dev_range,var/orig_heavy_range,var/orig_light_range)
	if(stat & NOPOWER)	return
	if(z != z0)			return

	var/dx = abs(x0-x)
	var/dy = abs(y0-y)
	var/distance
	var/direct

	if(dx > dy)
		distance = dx
		if(x0 > x)	direct = EAST
		else		direct = WEST
	else
		distance = dy
		if(y0 > y)	direct = NORTH
		else		direct = SOUTH

	if(distance > 100)		return
	if(!(direct & dir))	return

	var/list/messages = list("Explosive disturbance detected.", \
							 "Epicenter at: grid ([x0],[y0]). Temporal displacement of tachyons: [took] seconds.", \
							 "Factual: Epicenter radius: [devastation_range]. Outer radius: [heavy_impact_range]. Shockwave radius: [light_impact_range].")

	// If the bomb was capped, say it's theoretical size.
	if(devastation_range < orig_dev_range || heavy_impact_range < orig_heavy_range || light_impact_range < orig_light_range)
		messages += "Theoretical: Epicenter radius: [orig_dev_range]. Outer radius: [orig_heavy_range]. Shockwave radius: [orig_light_range]."

	for(var/message in messages)
		say(message)

/obj/machinery/doppler_array/say_quote(text)
	return "states coldly, \"[text]\""

/obj/machinery/doppler_array/power_change()
	if(stat & BROKEN)
		icon_state = "[initial(icon_state)]-broken"
	else
		if(powered() && anchored)
			icon_state = initial(icon_state)
			stat &= ~NOPOWER
		else
			icon_state = "[initial(icon_state)]-off"
			stat |= NOPOWER


code:
#define CLOSING			1
#define OPENING			2
#define CYCLE			3
#define CYCLE_EXTERIOR	4
#define CYCLE_INTERIOR	5

/obj/machinery/doorButtons
	power_channel = ENVIRON
	anchored = 1
	use_power = 1
	idle_power_usage = 2
	active_power_usage = 4
	var/idSelf

/obj/machinery/doorButtons/attackby(obj/O, mob/user)
	attack_hand(user)

/obj/machinery/doorButtons/proc/findObjsByTag()
	return

/obj/machinery/doorButtons/initialize()
	findObjsByTag()

/obj/machinery/doorButtons/proc/removeMe()

/obj/machinery/doorButtons/access_button
	icon = 'icons/obj/airlock_machines.dmi'
	icon_state = "access_button_standby"
	name = "access button"
	var/idDoor
	var/obj/machinery/door/airlock/door
	var/obj/machinery/doorButtons/airlock_controller/controller
	var/busy

/obj/machinery/doorButtons/access_button/findObjsByTag()
	for(var/obj/machinery/doorButtons/airlock_controller/A in world)
		if(A.idSelf == idSelf)
			controller = A
			break
	for(var/obj/machinery/door/airlock/I in world)
		if(I.id_tag == idDoor)
			door = I
			break

/obj/machinery/doorButtons/access_button/attack_hand(mob/user)
	if(..())
		return
	if(busy)
		return
	if(controller && !controller.busy && door)
		if(controller.stat & NOPOWER)
			return
		busy = 1
		update_icon()
		if(door.density)
			if(!controller.exteriorAirlock || !controller.interiorAirlock)
				controller.onlyOpen(door)
			else
				if(controller.exteriorAirlock.density && controller.interiorAirlock.density)
					controller.onlyOpen(door)
				else
					controller.cycleClose(door)
		else
			controller.onlyClose(door)
		sleep(20)
		busy = 0
		update_icon()

/obj/machinery/doorButtons/access_button/update_icon()
	if(stat & NOPOWER)
		icon_state = "access_button_off"
	else
		if(busy)
			icon_state = "access_button_cycle"
		else
			icon_state = "access_button_standby"

/obj/machinery/doorButtons/access_button/power_change()
	..()
	update_icon()

/obj/machinery/doorButtons/access_button/removeMe(obj/O)
	if(O == door)
		door = null

/obj/machinery/doorButtons/airlock_controller
	icon = 'icons/obj/airlock_machines.dmi'
	icon_state = "access_control_standby"
	name = "access console"
	var/obj/machinery/door/airlock/interiorAirlock
	var/obj/machinery/door/airlock/exteriorAirlock
	var/idInterior
	var/idExterior
	var/busy
	var/lostPower

/obj/machinery/doorButtons/airlock_controller/removeMe(obj/O)
	if(O == interiorAirlock)
		interiorAirlock = null
	else if(O == exteriorAirlock)
		exteriorAirlock = null

/obj/machinery/doorButtons/airlock_controller/Destroy()
	for(var/obj/machinery/doorButtons/access_button/A in world)
		if(A.controller == src)
			A.controller = null
	..()

/obj/machinery/doorButtons/airlock_controller/Topic(href, href_list)
	if(..())
		return
	if(busy)
		return
	switch(href_list["command"])
		if("close_exterior")
			onlyClose(exteriorAirlock)
		if("close_interior")
			onlyClose(interiorAirlock)
		if("cycle_exterior")
			cycleClose(exteriorAirlock)
		if("cycle_interior")
			cycleClose(interiorAirlock)
		if("open_exterior")
			onlyOpen(exteriorAirlock)
		if("open_interior")
			onlyOpen(interiorAirlock)

/obj/machinery/doorButtons/airlock_controller/proc/onlyOpen(obj/machinery/door/airlock/A)
	if(A)
		busy = CLOSING
		update_icon()
		openDoor(A)

/obj/machinery/doorButtons/airlock_controller/proc/onlyClose(obj/machinery/door/airlock/A)
	if(A)
		busy = CLOSING
		closeDoor(A)

/obj/machinery/doorButtons/airlock_controller/proc/closeDoor(obj/machinery/door/airlock/A)
	if(A.density)
		goIdle()
		return 0
	update_icon()
	A.unbolt()
	spawn()
		if(A && A.close())
			if(stat & NOPOWER || lostPower || !A || A.gc_destroyed)
				goIdle(1)
				return
			A.bolt()
			if(busy == CLOSING)
				goIdle(1)
		else
			goIdle(1)
	return 1

/obj/machinery/doorButtons/airlock_controller/proc/cycleClose(obj/machinery/door/airlock/A)
	if(!A || !exteriorAirlock || !interiorAirlock)
		return
	if(exteriorAirlock.density == interiorAirlock.density || !A.density)
		return
	busy = CYCLE
	update_icon()
	if(A == interiorAirlock)
		if(closeDoor(exteriorAirlock))
			busy = CYCLE_INTERIOR
	else
		if(closeDoor(interiorAirlock))
			busy = CYCLE_EXTERIOR

/obj/machinery/doorButtons/airlock_controller/proc/cycleOpen(obj/machinery/door/airlock/A)
	if(!A)
		goIdle(1)
	if(A == exteriorAirlock)
		if(interiorAirlock)
			if(!interiorAirlock.density || !interiorAirlock.locked)
				return
	else
		if(exteriorAirlock)
			if(!exteriorAirlock.density || !exteriorAirlock.locked)
				return
	if(busy != OPENING)
		busy = OPENING
		openDoor(A)

/obj/machinery/doorButtons/airlock_controller/proc/openDoor(obj/machinery/door/airlock/A)
	if(exteriorAirlock && interiorAirlock && (!exteriorAirlock.density || !interiorAirlock.density))
		goIdle(1)
		return
	A.unbolt()
	spawn()
		if(A && A.open())
			if(stat | (NOPOWER) && !lostPower && A && !A.gc_destroyed)
				A.bolt()
		goIdle(1)

/obj/machinery/doorButtons/airlock_controller/proc/goIdle(var/update)
	lostPower = 0
	busy = 0
	if(update)
		update_icon()
		updateUsrDialog()

/obj/machinery/doorButtons/airlock_controller/process()
	if(stat & NOPOWER)
		return
	if(busy == CYCLE_EXTERIOR)
		cycleOpen(exteriorAirlock)
	else if(busy == CYCLE_INTERIOR)
		cycleOpen(interiorAirlock)

/obj/machinery/doorButtons/airlock_controller/power_change()
	..()
	if(stat & NOPOWER)
		lostPower = 1
	else
		if(!busy)
			lostPower = 0
	update_icon()

/obj/machinery/doorButtons/airlock_controller/findObjsByTag()
	for(var/obj/machinery/door/airlock/A in world)
		if(A.id_tag == idInterior)
			interiorAirlock = A
		else if(A.id_tag == idExterior)
			exteriorAirlock = A

/obj/machinery/doorButtons/airlock_controller/update_icon()
	if(stat & NOPOWER)
		icon_state = "access_control_off"
		return
	if(busy || lostPower)
		icon_state = "access_control_process"
	else
		icon_state = "access_control_standby"

/obj/machinery/doorButtons/airlock_controller/attack_hand(mob/user)
	if(..())
		return
	var/datum/browser/popup = new(user, "computer", name)
	popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
	popup.set_content(returnText())
	popup.open()

/obj/machinery/doorButtons/airlock_controller/proc/returnText()
	var/output
	if(!exteriorAirlock && !interiorAirlock)
		return "ERROR ERROR ERROR ERROR"
	if(lostPower)
		output = "Initializing..."
	else
		if(!exteriorAirlock || !interiorAirlock)
			if(!exteriorAirlock)
				if(interiorAirlock.density)
					output = "Open Interior Airlock
"
				else
					output = "Close Interior Airlock
"
			else
				if(exteriorAirlock.density)
					output = "Open Exterior Airlock
"
				else
					output = "Close Exterior Airlock
"
		else
			if(exteriorAirlock.density)
				if(interiorAirlock.density)
					output = {"Open Exterior Airlock

					Open Interior Airlock
"}
				else
					output = {"Cycle to Exterior Airlock

					Close Interior Airlock
"}
			else
				if(interiorAirlock.density)
					output = {"Close Exterior Airlock

					Cycle to Interior Airlock
"}
				else
					output = {"Close Exterior Airlock

					Close Interior Airlock
"}

	output = {"Access Control Console

				[output]
"}
	if(exteriorAirlock)
		output += "Exterior Door:  [exteriorAirlock.density ? "closed" : "open"]
"
	if(interiorAirlock)
		output += "Interior Door:  [interiorAirlock.density ? "closed" : "open"]
"

	return output

#undef CLOSING
#undef OPENING
#undef CYCLE
#undef CYCLE_EXTERIOR
#undef CYCLE_INTERIOR