code:
//Creates a throwing star
/obj/item/clothing/suit/space/space_ninja/proc/ninjastar()
	set name = "Create Throwing Stars (1E)"
	set desc = "Creates some throwing stars"
	set category = "Ninja Ability"
	set popup_menu = 0

	if(!ninjacost(10))
		var/mob/living/carbon/human/H = affecting
		var/slot = H.hand ? slot_l_hand : slot_r_hand

		if(H.equip_to_slot_or_del(new /obj/item/weapon/throwing_star/ninja(H), slot))
			H << "A throwing star has been created in your hand!"

		H.throw_mode_on() //So they can quickly throw it.

/obj/item/weapon/throwing_star/ninja
	name = "ninja throwing star"
	throwforce = 30
	embedded_pain_multiplier = 6


code:
/*

Contents:
- Stealth Verbs

*/

/obj/item/clothing/suit/space/space_ninja/proc/toggle_stealth()
	var/mob/living/carbon/human/U = affecting
	if(!U)
		return
	if(s_active)
		cancel_stealth()
	else
		if(cell.charge <= 0)
			U << "You don't have enough power to enable Stealth!"
			return
		s_active=!s_active
		animate(U, alpha = 0,time = 15)
		U.visible_message("[U.name] vanishes into thin air!", \
						"You are now invisible to normal detection.")
	return

/obj/item/clothing/suit/space/space_ninja/proc/cancel_stealth()
	var/mob/living/carbon/human/U = affecting
	if(!U)
		return 0
	if(s_active)
		s_active=!s_active
		animate(U, alpha = 255, time = 15)
		U.visible_message("[U.name] appears from thin air!", \
						"You are now visible.")
		return 1
	return 0

/obj/item/clothing/suit/space/space_ninja/proc/stealth()
	set name = "Toggle Stealth"
	set desc = "Utilize the internal CLOAK-tech device to activate or deactivate stealth-camo."
	set category = "Ninja Equip"

	if(!s_busy)
		toggle_stealth()
	else
		affecting << "Stealth does not appear to work!"

license: mit


code:
/obj/item/clothing/suit/space/space_ninja/proc/ninja_sword_recall()
	set name = "Recall Energy Katana (Variable Cost)"
	set desc = "Teleports the Energy Katana linked to this suit to it's wearer, cost based on distance."
	set category = "Ninja Ability"
	set popup_menu = 0

	var/mob/living/carbon/human/H = affecting

	var/cost = 0
	var/inview = 1

	if(!energyKatana)
		H << "Could not locate Energy Katana!"
		return

	if(energyKatana in H)
		return

	var/distance = get_dist(H,energyKatana)

	if(!(energyKatana in view(H)))
		cost = distance //Actual cost is cost x 10, so 5 turfs is 50 cost.
		inview = 0

	if(!ninjacost(cost))
		if(istype(energyKatana.loc, /mob/living/carbon))
			var/mob/living/carbon/C = energyKatana.loc
			C.unEquip(energyKatana)

			//Somebody swollowed my sword, probably the clown doing a circus act.
			if(energyKatana in C.stomach_contents)
				C.stomach_contents -= energyKatana

			if(energyKatana in C.internal_organs)
				C.internal_organs -= energyKatana

		energyKatana.loc = get_turf(energyKatana)

		if(inview) //If we can see the katana, throw it towards ourselves, damaging people as we go.
			energyKatana.spark_system.start()
			playsound(H, "sparks", 50, 1)
			H.visible_message("\the [energyKatana] flies towards [H]!","You hold out your hand and \the [energyKatana] flies towards you!")
			energyKatana.throw_at(H, distance+1, energyKatana.throw_speed,H)

		else //Else just TP it to us.
			energyKatana.returnToOwner(H,1)


code:
/*

Contents:
- Proc for handling teleporting while grabbing someone
- Telport Ability
- Right-Click Teleport Ability

*/

//Handles elporting while grabbing someone
/obj/item/clothing/suit/space/space_ninja/proc/handle_teleport_grab(turf/T, mob/living/H)
	if(H.pulling && (istype(H.pulling, /mob/living)))
		var/mob/living/victim =	H.pulling
		if(!victim.anchored)
			victim.forceMove(locate(T.x+rand(-1,1),T.y+rand(-1,1),T.z))
	return

//Jaunt
/obj/item/clothing/suit/space/space_ninja/proc/ninjajaunt()
	set name = "Phase Jaunt (10E)"
	set desc = "Utilizes the internal VOID-shift device to rapidly transit in direction facing."
	set category = "Ninja Ability"
	set popup_menu = 0

	if(!ninjacost(100,N_STEALTH_CANCEL))
		var/mob/living/carbon/human/H = affecting
		var/turf/destination = get_teleport_loc(H.loc,H,9,1,3,1,0,1)
		var/turf/mobloc = get_turf(H.loc)//Safety

		if(destination&&istype(mobloc, /turf))//So we don't teleport out of containers
			spawn(0)
				playsound(H.loc, "sparks", 50, 1)
				anim(mobloc,src,'icons/mob/mob.dmi',,"phaseout",,H.dir)

			handle_teleport_grab(destination, H)
			H.loc = destination

			spawn(0)
				spark_system.start()
				playsound(H.loc, 'sound/effects/phasein.ogg', 25, 1)
				playsound(H.loc, "sparks", 50, 1)
				anim(H.loc,H,'icons/mob/mob.dmi',,"phasein",,H.dir)

			spawn(0)
				destination.phase_damage_creatures(20,H)//Paralyse and damage mobs and mechas on the turf
			s_coold = 1
		else
			H << "The VOID-shift device is malfunctioning, teleportation failed."
	return

//Right-Click teleport: It's basically admin "jump to turf"
/obj/item/clothing/suit/space/space_ninja/proc/ninjashift(turf/T in oview())
	set name = "Phase Shift (20E)"
	set desc = "Utilizes the internal VOID-shift device to rapidly transit to a destination in view."
	set category = null//So it does not show up on the panel but can still be right-clicked.
	set src = usr.contents//Fixes verbs not attaching properly for objects. Praise the DM reference guide!

	if(!ninjacost(200,N_STEALTH_CANCEL))
		var/mob/living/carbon/human/H = affecting
		var/turf/mobloc = get_turf(H.loc)//To make sure that certain things work properly below.
		if((!T.density)&&istype(mobloc, /turf))
			spawn(0)
				playsound(H.loc, 'sound/effects/sparks4.ogg', 50, 1)
				anim(mobloc,src,'icons/mob/mob.dmi',,"phaseout",,H.dir)

			handle_teleport_grab(T, H)
			H.loc = T

			spawn(0)
				spark_system.start()
				playsound(H.loc, 'sound/effects/phasein.ogg', 25, 1)
				playsound(H.loc, 'sound/effects/sparks2.ogg', 50, 1)
				anim(H.loc,H,'icons/mob/mob.dmi',,"phasein",,H.dir)

			spawn(0)//Any living mobs in teleport area are gibbed.
				T.phase_damage_creatures(20,H)//Paralyse and damage mobs and mechas on the turf
			s_coold = 1
		else
			H << "You cannot teleport into solid walls or from solid matter"
	return


code:
/*

Contents:
- Assorted ninjadrain_act() procs
- What is Object Oriented Programming

They *could* go in their appropriate files, but this is supposed to be modular

*/

//Needs to return the amount drained from the atom, if no drain on a power object, return 0, otherwise, return a define.
/atom/proc/ninjadrain_act()
	return INVALID_DRAIN

//APC//
/obj/machinery/power/apc/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
	if(!S || !H || !G)
		return INVALID_DRAIN

	var/maxcapacity = 0 //Safety check for batteries
	var/drain = 0 //Drain amount from batteries

	. = 0

	if(cell && cell.charge)
		var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
		spark_system.set_up(5, 0, loc)

		while(G.candrain && cell.charge> 0 && !maxcapacity)
			drain = rand(G.mindrain, G.maxdrain)

			if(cell.charge < drain)
				drain = cell.charge

			if(S.cell.charge + drain > S.cell.maxcharge)
				drain = S.cell.maxcharge - S.cell.charge
				maxcapacity = 1//Reached maximum battery capacity.

			if (do_after(H,10, target = src))
				spark_system.start()
				playsound(loc, "sparks", 50, 1)
				cell.charge -= drain
				S.cell.charge += drain
				. += drain
			else
				break

		if(!emagged)
			flick("apc-spark", G)
			emagged = 1
			locked = 0
			update_icon()

//SMES//
/obj/machinery/power/smes/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
	if(!S || !H || !G)
		return INVALID_DRAIN

	var/maxcapacity = 0 //Safety check for batteries
	var/drain = 0 //Drain amount from batteries

	. = 0

	if(charge)
		var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
		spark_system.set_up(5, 0, loc)

		while(G.candrain && charge > 0 && !maxcapacity)
			drain = rand(G.mindrain, G.maxdrain)

			if(charge < drain)
				drain = charge

			if(S.cell.charge + drain > S.cell.maxcharge)
				drain = S.cell.maxcharge - S.cell.charge
				maxcapacity = 1

			if (do_after(H,10, target = src))
				spark_system.start()
				playsound(loc, "sparks", 50, 1)
				charge -= drain
				S.cell.charge += drain
				. += drain

			else
				break

//CELL//
/obj/item/weapon/stock_parts/cell/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
	if(!S || !H || !G)
		return INVALID_DRAIN

	. = 0

	if(charge)
		if(G.candrain && do_after(H,30, target = src))
			. = charge
			if(S.cell.charge + charge > S.cell.maxcharge)
				S.cell.charge = S.cell.maxcharge
			else
				S.cell.charge += charge
			charge = 0
			corrupt()
			updateicon()

//RDCONSOLE//
/obj/machinery/computer/rdconsole/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
	if(!S || !H || !G)
		return INVALID_DRAIN

	. = DRAIN_RD_HACK_FAILED

	H << "Hacking \the [src]..."
	spawn(0)
		var/turf/location = get_turf(H)
		for(var/mob/living/silicon/ai/AI in player_list)
			AI << "Network Alert: Hacking attempt detected[location?" in [location]":". Unable to pinpoint location"]."

	if(files && files.known_tech.len)
		for(var/datum/tech/current_data in S.stored_research)
			H << "Checking \the [current_data.name] database."
			if(do_after(H, S.s_delay, target = src) && G.candrain && src)
				for(var/datum/tech/analyzing_data in files.known_tech)
					if(current_data.id == analyzing_data.id)
						if(analyzing_data.level > current_data.level)
							H << "Database: UPDATED."
							current_data.level = analyzing_data.level
							. = DRAIN_RD_HACKED
						break//Move on to next.
			else
				break//Otherwise, quit processing.

	H << "Data analyzed. Process finished."

//RD SERVER//
//Shamelessly copypasted from above, since these two used to be the same proc, but with MANY colon operators
/obj/machinery/r_n_d/server/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
	if(!S || !H || !G)
		return INVALID_DRAIN

	. = DRAIN_RD_HACK_FAILED

	H << "Hacking \the [src]..."
	spawn(0)
		var/turf/location = get_turf(H)
		for(var/mob/living/silicon/ai/AI in player_list)
			AI << "Network Alert: Hacking attempt detected[location?" in [location]":". Unable to pinpoint location"]."

	if(files && files.known_tech.len)
		for(var/datum/tech/current_data in S.stored_research)
			H << "Checking \the [current_data.name] database."
			if(do_after(H, S.s_delay, target = src) && G.candrain && src)
				for(var/datum/tech/analyzing_data in files.known_tech)
					if(current_data.id == analyzing_data.id)
						if(analyzing_data.level > current_data.level)
							H << "Database: UPDATED."
							current_data.level = analyzing_data.level
							. = DRAIN_RD_HACKED
						break//Move on to next.
			else
				break//Otherwise, quit processing.

	H << "Data analyzed. Process finished."

//WIRE//
/obj/structure/cable/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
	if(!S || !H || !G)
		return INVALID_DRAIN

	var/maxcapacity = 0 //Safety check
	var/drain = 0 //Drain amount

	. = 0

	var/datum/powernet/PN = powernet
	while(G.candrain && !maxcapacity && src)
		drain = (round((rand(G.mindrain, G.maxdrain))/2))
		var/drained = 0
		if(PN && do_after(H,10, target = src))
			drained = min(drain, PN.avail)
			PN.load += drained
			if(drained < drain)//if no power on net, drain apcs
				for(var/obj/machinery/power/terminal/T in PN.nodes)
					if(istype(T.master, /obj/machinery/power/apc))
						var/obj/machinery/power/apc/AP = T.master
						if(AP.operating && AP.cell && AP.cell.charge > 0)
							AP.cell.charge = max(0, AP.cell.charge - 5)
							drained += 5
		else
			break

		S.cell.charge += drained
		if(S.cell.charge > S.cell.maxcharge)
			. += (drained-(S.cell.charge - S.cell.maxcharge))
			S.cell.charge = S.cell.maxcharge
			maxcapacity = 1
		else
			. += drained
		S.spark_system.start()

//MECH//
/obj/mecha/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
	if(!S || !H || !G)
		return INVALID_DRAIN

	var/maxcapacity = 0 //Safety check
	var/drain = 0 //Drain amount
	. = 0

	occupant_message("Warning: Unauthorized access through sub-route 4, block H, detected.")
	if(get_charge())
		while(G.candrain && cell.charge > 0 && !maxcapacity)
			drain = rand(G.mindrain,G.maxdrain)
			if(cell.charge < drain)
				drain = cell.charge
			if(S.cell.charge + drain > S.cell.maxcharge)
				drain = S.cell.maxcharge - S.cell.charge
				maxcapacity = 1
			if (do_after(H,10, target = src))
				spark_system.start()
				playsound(loc, "sparks", 50, 1)
				cell.use(drain)
				S.cell.charge += drain
				. += drain
			else
				break

//BORG//
/mob/living/silicon/robot/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
	if(!S || !H || !G)
		return INVALID_DRAIN

	var/maxcapacity = 0 //Safety check
	var/drain = 0 //Drain amount
	. = 0

	src << "Warning: Unauthorized access through sub-route 12, block C, detected."

	if(cell && cell.charge)
		while(G.candrain && cell.charge > 0 && !maxcapacity)
			drain = rand(G.mindrain,G.maxdrain)
			if(cell.charge < drain)
				drain = cell.charge
			if(S.cell.charge+drain > S.cell.maxcharge)
				drain = S.cell.maxcharge - S.cell.charge
				maxcapacity = 1
			if (do_after(H,10))
				spark_system.start()
				playsound(loc, "sparks", 50, 1)
				cell.charge -= drain
				S.cell.charge += drain
				. += drain
			else
				break

//CARBON MOBS//
/mob/living/carbon/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
	if(!S || !H || !G)
		return INVALID_DRAIN

	. = DRAIN_MOB_SHOCK_FAILED

	//Default cell = 10,000 charge, 10,000/1000 = 10 uses without charging/upgrading
	if(S.cell && S.cell.charge && S.cell.use(1000))
		. = DRAIN_MOB_SHOCK
		//Got that electric touch
		var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
		spark_system.set_up(5, 0, loc)
		playsound(src, "sparks", 50, 1)
		visible_message("[H] electrocutes [src] with their touch!", "[H] electrocutes you with their touch!")
		electrocute_act(25, H)


code:
/obj/item/clothing/shoes/space_ninja
	name = "ninja shoes"
	desc = "A pair of running shoes. Excellent for running and even better for smashing skulls."
	icon_state = "s-ninja"
	item_state = "secshoes"
	permeability_coefficient = 0.01
	flags = NOSLIP
	armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30)
	strip_delay = 120
	cold_protection = FEET
	min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT
	heat_protection = FEET
	max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT


code:
/*

Contents:
- The Ninja Space Suit
- Ninja Space Suit Procs

*/

// /obj/item/clothing/suit/space/space_ninja

/obj/item/clothing/suit/space/space_ninja
	name = "ninja suit"
	desc = "A unique, vaccum-proof suit of nano-enhanced armor designed specifically for Spider Clan assassins."
	icon_state = "s-ninja"
	item_state = "s-ninja_suit"
	allowed = list(/obj/item/weapon/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/tank/internals,/obj/item/weapon/stock_parts/cell)
	slowdown = 0
	unacidable = 1
	armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30)
	strip_delay = 12

		//Important parts of the suit.
	var/mob/living/carbon/human/affecting = null
	var/obj/item/weapon/stock_parts/cell/cell
	var/datum/effect_system/spark_spread/spark_system
	var/list/reagent_list = list("omnizine","salbutamol","spaceacillin","charcoal","nutriment","radium","potass_iodide")//The reagents ids which are added to the suit at New().
	var/list/stored_research = list()//For stealing station research.
	var/obj/item/weapon/disk/tech_disk/t_disk//To copy design onto disk.
	var/obj/item/weapon/katana/energy/energyKatana //For teleporting the katana back to the ninja (It's an ability)

		//Other articles of ninja gear worn together, used to easily reference them after initializing.
	var/obj/item/clothing/head/helmet/space/space_ninja/n_hood
	var/obj/item/clothing/shoes/space_ninja/n_shoes
	var/obj/item/clothing/gloves/space_ninja/n_gloves

		//Main function variables.
	var/s_initialized = 0//Suit starts off.
	var/s_coold = 0//If the suit is on cooldown. Can be used to attach different cooldowns to abilities. Ticks down every second based on suit ntick().
	var/s_cost = 5//Base energy cost each ntick.
	var/s_acost = 25//Additional cost for additional powers active.
	var/s_delay = 40//How fast the suit does certain things, lower is faster. Can be overridden in specific procs. Also determines adverse probability.
	var/a_transfer = 20//How much reagent is transferred when injecting.
	var/r_maxamount = 80//How much reagent in total there is.

		//Support function variables.
	var/spideros = 0//Mode of SpiderOS. This can change so I won't bother listing the modes here (0 is hub). Check ninja_equipment.dm for how it all works.
	var/s_active = 0//Stealth off.
	var/s_busy = 0//Is the suit busy with a process? Like AI hacking. Used for safety functions.

		//Ability function variables.
	var/s_bombs = 10//Number of starting ninja smoke bombs.
	var/a_boost = 3//Number of adrenaline boosters.

/obj/item/clothing/suit/space/space_ninja/New()
	..()
	verbs += /obj/item/clothing/suit/space/space_ninja/proc/init//suit initialize verb

	//Spark Init
	spark_system = new()
	spark_system.set_up(5, 0, src)
	spark_system.attach(src)

	//Research Init
	stored_research = new()
	for(var/T in subtypesof(/datum/tech))//Store up on research.
		stored_research += new T(src)

	//Reagent Init
	var/reagent_amount
	for(var/reagent_id in reagent_list)
		reagent_amount += reagent_id == "radium" ? r_maxamount+(a_boost*a_transfer) : r_maxamount
	reagents = new(reagent_amount)
	reagents.my_atom = src
	for(var/reagent_id in reagent_list)
		reagent_id == "radium" ? reagents.add_reagent(reagent_id, r_maxamount+(a_boost*a_transfer)) : reagents.add_reagent(reagent_id, r_maxamount)//It will take into account radium used for adrenaline boosting.

	//Cell Init
	cell = new/obj/item/weapon/stock_parts/cell/high
	cell.charge = 9000
	cell.name = "black power cell"
	cell.icon_state = "bscell"

/obj/item/clothing/suit/space/space_ninja/Destroy()
	if(affecting)
		affecting << browse(null, "window=hack spideros")
	return ..()

//Simply deletes all the attachments and self, killing all related procs.
/obj/item/clothing/suit/space/space_ninja/proc/terminate()
	qdel(n_hood)
	qdel(n_gloves)
	qdel(n_shoes)
	qdel(src)

//Randomizes suit parameters.
/obj/item/clothing/suit/space/space_ninja/proc/randomize_param()
	s_cost = rand(1,20)
	s_acost = rand(20,100)
	s_delay = rand(10,100)
	s_bombs = rand(5,20)
	a_boost = rand(1,7)

//This proc prevents the suit from being taken off.
/obj/item/clothing/suit/space/space_ninja/proc/lock_suit(mob/living/carbon/human/H, checkIcons = 0)
	if(!istype(H))
		return 0
	if(checkIcons)
		icon_state = H.gender==FEMALE ? "s-ninjanf" : "s-ninjan"
		H.gloves.icon_state = "s-ninjan"
		H.gloves.item_state = "s-ninjan"
	else
		if(H.mind.special_role!="Space Ninja")
			H << "\red fÄTaL ÈÈRRoR: 382200-*#00CÖDE RED\nUNAUHORIZED USÈ DETÈCeD\nCoMMÈNCING SUB-R0UIN3 13...\nTÈRMInATING U-U-USÈR..."
			H.gib()
			return 0
		if(!istype(H.head, /obj/item/clothing/head/helmet/space/space_ninja))
			H << "ERROR: 100113 UNABLE TO LOCATE HEAD GEAR\nABORTING..."
			return 0
		if(!istype(H.shoes, /obj/item/clothing/shoes/space_ninja))
			H << "ERROR: 122011 UNABLE TO LOCATE FOOT GEAR\nABORTING..."
			return 0
		if(!istype(H.gloves, /obj/item/clothing/gloves/space_ninja))
			H << "ERROR: 110223 UNABLE TO LOCATE HAND GEAR\nABORTING..."
			return 0

		affecting = H
		flags |= NODROP //colons make me go all |=
		slowdown = 0
		n_hood = H.head
		n_hood.flags |= NODROP
		n_shoes = H.shoes
		n_shoes.flags |= NODROP
		n_shoes.slowdown--
		n_gloves = H.gloves
		n_gloves.flags |= NODROP

	return 1

//This proc allows the suit to be taken off.
/obj/item/clothing/suit/space/space_ninja/proc/unlock_suit()
	affecting = null
	flags &= ~NODROP
	slowdown = 1
	icon_state = "s-ninja"
	if(n_hood)//Should be attached, might not be attached.
		n_hood.flags &= ~NODROP
	if(n_shoes)
		n_shoes.flags &= ~NODROP
		n_shoes.slowdown++
	if(n_gloves)
		n_gloves.icon_state = "s-ninja"
		n_gloves.item_state = "s-ninja"
		n_gloves.flags &= ~NODROP
		n_gloves.candrain=0
		n_gloves.draining=0

/obj/item/clothing/suit/space/space_ninja/examine(mob/user)
	..()
	if(s_initialized)
		if(user == affecting)
			user << "All systems operational. Current energy capacity: [cell.charge]."
			user << "The CLOAK-tech device is [s_active?"active":"inactive"]."
			user << "There are [s_bombs] smoke bomb\s remaining."
			user << "There are [a_boost] adrenaline booster\s remaining."


code:
/obj/item/clothing/suit/space/space_ninja/attackby(obj/item/I, mob/U, params)
	if(U==affecting)//Safety, in case you try doing this without wearing the suit/being the person with the suit.

		if(istype(I, /obj/item/weapon/reagent_containers/glass))//If it's a glass beaker.
			var/total_reagent_transfer//Keep track of this stuff.
			for(var/reagent_id in reagent_list)
				var/datum/reagent/R = I.reagents.has_reagent(reagent_id)//Mostly to pull up the name of the reagent after calculating. Also easier to use than writing long proc paths.
				if(R&&reagents.get_reagent_amount(reagent_id)<r_maxamount+(reagent_id == "radium"?(a_boost*a_transfer):0)&&R.volume>=a_transfer)//Radium is always special.
					//Here we determine how much reagent will actually transfer if there is enough to transfer or there is a need of transfer. Minimum of max amount available (using a_transfer) or amount needed.
					var/amount_to_transfer = min( (r_maxamount+(reagent_id == "radium"?(a_boost*a_transfer):0)-reagents.get_reagent_amount(reagent_id)) ,(round(R.volume/a_transfer))*a_transfer)//In the end here, we round the amount available, then multiply it again.
					R.volume -= amount_to_transfer//Remove from reagent volume. Don't want to delete the reagent now since we need to perserve the name.
					reagents.add_reagent(reagent_id, amount_to_transfer)//Add to suit. Reactions are not important.
					total_reagent_transfer += amount_to_transfer//Add to total reagent trans.
					U << "Added [amount_to_transfer] units of [R.name]."//Reports on the specific reagent added.
					I.reagents.update_total()//Now we manually update the total to make sure everything is properly shoved under the rug.

			U << "Replenished a total of [total_reagent_transfer ? total_reagent_transfer : "zero"] chemical units."//Let the player know how much total volume was added.
			return

		else if(istype(I, /obj/item/weapon/stock_parts/cell))
			var/obj/item/weapon/stock_parts/cell/CELL = I
			if(CELL.maxcharge > cell.maxcharge && n_gloves && n_gloves.candrain)
				U << "Higher maximum capacity detected.\nUpgrading..."
				if (n_gloves && n_gloves.candrain && do_after(U,s_delay, target = src))
					U.drop_item()
					CELL.loc = src
					CELL.charge = min(CELL.charge+cell.charge, CELL.maxcharge)
					var/obj/item/weapon/stock_parts/cell/old_cell = cell
					old_cell.charge = 0
					U.put_in_hands(old_cell)
					old_cell.add_fingerprint(U)
					old_cell.corrupt()
					old_cell.updateicon()
					cell = CELL
					U << "Upgrade complete. Maximum capacity: [round(cell.maxcharge/100)]%"
				else
					U << "Procedure interrupted. Protocol terminated."
			return

		else if(istype(I, /obj/item/weapon/disk/tech_disk))//If it's a data disk, we want to copy the research on to the suit.
			var/obj/item/weapon/disk/tech_disk/TD = I
			if(TD.stored)//If it has something on it.
				U << "Research information detected, processing..."
				if(do_after(U,s_delay, target = src))
					for(var/datum/tech/current_data in stored_research)
						if(current_data.id==TD.stored.id)
							if(current_data.level<TD.stored.level)
								current_data.level=TD.stored.level
							break
					TD.stored = null
					U << "Data analyzed and updated. Disk erased."
				else
					U << "ERROR: Procedure interrupted. Process terminated."
			else
				I.loc = src
				t_disk = I
				U << "You slot \the [I] into \the [src]."
			return
	..()


code:
//Verbs link to procs because verb-like procs have a bug which prevents their use if the arguments are not readily referenced.
//^ Old coder words may be false these days, Not taking the risk for now.

/obj/item/clothing/suit/space/space_ninja/proc/init()
	set name = "Initialize Suit"
	set desc = "Initializes the suit for field operation."
	set category = "Ninja Equip"

	ninitialize()

/obj/item/clothing/suit/space/space_ninja/proc/deinit()
	set name = "De-Initialize Suit"
	set desc = "Begins procedure to remove the suit."
	set category = "Ninja Equip"

	if(!s_busy)
		deinitialize()
	else
		affecting << "The function did not trigger!"

/obj/item/clothing/suit/space/space_ninja/proc/ninitialize(delay = s_delay, mob/living/carbon/human/U = loc)
	if(U.mind && U.mind.assigned_role==U.mind.special_role && !s_initialized && !s_busy)//Shouldn't be busy... but anything is possible I guess.
		s_busy = 1
		for(var/i,i<7,i++)
			switch(i)
				if(0)
					U << "Now initializing..."
				if(1)
					if(!lock_suit(U))//To lock the suit onto wearer.
						break
					U << "Securing external locking mechanism...\nNeural-net established."
				if(2)
					U << "Extending neural-net interface...\nNow monitoring brain wave pattern..."
				if(3)
					if(U.stat==2||U.health<=0)
						U << "FÄAL ï¿½Rrï¿½R: 344--93#ï¿½&&21 BRï¿½ï¿½N |/|/aVï¿½ PATT$RN RED\nA-A-aBï¿½rTï¿½NG..."
						unlock_suit()
						break
					lock_suit(U,1)//Check for icons.
					U.regenerate_icons()
					U << "Linking neural-net interface...\nPattern\green GREEN, continuing operation."
				if(4)
					U << "VOID-shift device status: ONLINE.\nCLOAK-tech device status: ONLINE."
				if(5)
					U << "Primary system status: ONLINE.\nBackup system status: ONLINE.\nCurrent energy capacity: [cell.charge]."
				if(6)
					U << "All systems operational. Welcome to SpiderOS, [U.real_name]."
					grant_ninja_verbs()
					grant_equip_verbs()
					ntick()
			sleep(delay)
		s_busy = 0
	else
		if(!U.mind||U.mind.assigned_role!=U.mind.special_role)//Your run of the mill persons shouldn't know what it is. Or how to turn it on.
			U << "You do not understand how this suit functions. Where the heck did it even come from?"
		else if(s_initialized)
			U << "The suit is already functioning. Please report this bug."
		else
			U << "ERROR: You cannot use this function at this time."
	return

/obj/item/clothing/suit/space/space_ninja/proc/deinitialize(delay = s_delay)
	if(affecting==loc&&!s_busy)
		var/mob/living/carbon/human/U = affecting
		if(!s_initialized)
			U << "The suit is not initialized. Please report this bug."
			return
		if(alert("Are you certain you wish to remove the suit? This will take time and remove all abilities.",,"Yes","No")=="No")
			return
		if(s_busy)
			U << "ERROR: You cannot use this function at this time."
			return
		s_busy = 1
		for(var/i = 0,i<7,i++)
			switch(i)
				if(0)
					U << "Now de-initializing..."
					spideros = 0//Spideros resets.
				if(1)
					U << "Logging off, [U:real_name]. Shutting down SpiderOS."
					remove_ninja_verbs()
				if(2)
					U << "Primary system status: OFFLINE.\nBackup system status: OFFLINE."
				if(3)
					U << "VOID-shift device status: OFFLINE.\nCLOAK-tech device status: OFFLINE."
					cancel_stealth()//Shutdowns stealth.
				if(4)
					U << "Disconnecting neural-net interface...\greenSuccess."
				if(5)
					U << "Disengaging neural-net interface...\greenSuccess."
				if(6)
					U << "Unsecuring external locking mechanism...\nNeural-net abolished.\nOperation status: FINISHED."
					remove_equip_verbs()
					unlock_suit()
					U.regenerate_icons()
			sleep(delay)
		s_busy = 0
	return


code:
/obj/item/clothing/suit/space/space_ninja/proc/ntick(mob/living/carbon/human/U = affecting)
	set background = BACKGROUND_ENABLED

	//Runs in the background while the suit is initialized.
	//Requires charge or stealth to process.
	spawn while(s_initialized)
		if(!affecting)
			terminate()//Kills the suit and attached objects.

		else if(cell.charge > 0)
			if(s_coold)
				s_coold--//Checks for ability s_cooldown first.

			cell.charge -= s_cost//s_cost is the default energy cost each ntick, usually 5.
			if(s_active)//If stealth is active.
				cell.charge -= s_acost

		else
			cell.charge = 0
			cancel_stealth()

		sleep(10)//Checks every second.


code:
/*

Contents:
- Procs that add ninja verbs to ninjas
- Procs that remove ninja verbs from ninjas
- Procs that add ninjasuit verbs to ninjas
- Procs that remove ninjasuit verbs from ninjas

*/

/obj/item/clothing/suit/space/space_ninja/proc/grant_equip_verbs()
	verbs -= /obj/item/clothing/suit/space/space_ninja/proc/init
	verbs += /obj/item/clothing/suit/space/space_ninja/proc/deinit
	verbs += /obj/item/clothing/suit/space/space_ninja/proc/stealth
	n_gloves.verbs += /obj/item/clothing/gloves/space_ninja/proc/toggled

	s_initialized = 1

/obj/item/clothing/suit/space/space_ninja/proc/remove_equip_verbs()
	verbs += /obj/item/clothing/suit/space/space_ninja/proc/init
	verbs -= /obj/item/clothing/suit/space/space_ninja/proc/deinit
	verbs -= /obj/item/clothing/suit/space/space_ninja/proc/stealth
	if(n_gloves)
		n_gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/toggled

	s_initialized = 0

/obj/item/clothing/suit/space/space_ninja/proc/grant_ninja_verbs()
	verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjashift
	verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjajaunt
	verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjasmoke
	verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjaboost
	verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjapulse
	verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjastar
	verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjanet
	verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninja_sword_recall

	s_initialized=1
	slowdown=0

/obj/item/clothing/suit/space/space_ninja/proc/remove_ninja_verbs()
	verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjashift
	verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjajaunt
	verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjasmoke
	verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjaboost
	verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjapulse
	verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjastar
	verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjanet
	verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninja_sword_recall


code:
/obj/item/weapon/clipboard
	name = "clipboard"
	icon = 'icons/obj/bureaucracy.dmi'
	icon_state = "clipboard"
	item_state = "clipboard"
	throwforce = 0
	w_class = 2
	throw_speed = 3
	throw_range = 7
	var/obj/item/weapon/pen/haspen		//The stored pen.
	var/obj/item/weapon/paper/toppaper	//The topmost piece of paper.
	slot_flags = SLOT_BELT
	burn_state = FLAMMABLE

/obj/item/weapon/clipboard/New()
	update_icon()

/obj/item/weapon/clipboard/update_icon()
	overlays.Cut()
	if(toppaper)
		overlays += toppaper.icon_state
		overlays += toppaper.overlays
	if(haspen)
		overlays += "clipboard_pen"
	overlays += "clipboard_over"

/obj/item/weapon/clipboard/attackby(obj/item/weapon/W, mob/user, params)
	if(istype(W, /obj/item/weapon/paper))
		if(!user.unEquip(W))
			return
		W.loc = src
		toppaper = W
		user << "You clip the paper onto \the [src]."
		update_icon()
	else if(toppaper)
		toppaper.attackby(usr.get_active_hand(), usr)
		update_icon()

/obj/item/weapon/clipboard/attack_self(mob/user)
	var/dat = "<title>Clipboard</title>"
	if(haspen)
		dat += "Remove Pen

"
	else
		dat += "Add Pen

"

	//The topmost paper. You can't organise contents directly in byond, so this is what we're stuck with.	-Pete
	if(toppaper)
		var/obj/item/weapon/paper/P = toppaper
		dat += "Write Remove - [P.name]

"

		for(P in src)
			if(P == toppaper)
				continue
			dat += "Write Remove Move to top - [P.name]
"
	user << browse(dat, "window=clipboard")
	onclose(user, "clipboard")
	add_fingerprint(usr)

/obj/item/weapon/clipboard/Topic(href, href_list)
	..()
	if(usr.stat || usr.restrained())
		return

	if(usr.contents.Find(src))

		if(href_list["pen"])
			if(haspen)
				haspen.loc = usr.loc
				usr.put_in_hands(haspen)
				haspen = null

		if(href_list["addpen"])
			if(!haspen)
				if(istype(usr.get_active_hand(), /obj/item/weapon/pen))
					var/obj/item/weapon/pen/W = usr.get_active_hand()
					if(!usr.unEquip(W))
						return
					W.loc = src
					haspen = W
					usr << "You slot [W] into [src]."

		if(href_list["write"])
			var/obj/item/P = locate(href_list["write"])
			if(istype(P) && P.loc == src)
				if(usr.get_active_hand())
					P.attackby(usr.get_active_hand(), usr)

		if(href_list["remove"])
			var/obj/item/P = locate(href_list["remove"])
			if(istype(P) && P.loc == src)
				P.loc = usr.loc
				usr.put_in_hands(P)
				if(P == toppaper)
					toppaper = null
					var/obj/item/weapon/paper/newtop = locate(/obj/item/weapon/paper) in src
					if(newtop && (newtop != P))
						toppaper = newtop
					else
						toppaper = null

		if(href_list["read"])
			var/obj/item/weapon/paper/P = locate(href_list["read"])
			if(istype(P) && P.loc == src)
				usr.examinate(P)

		if(href_list["top"])
			var/obj/item/P = locate(href_list["top"])
			if(istype(P) && P.loc == src)
				toppaper = P
				usr << "You move [P.name] to the top."

		//Update everything
		attack_self(usr)
		update_icon()


code:
/* Filing cabinets!
 * Contains:
 *		Filing Cabinets
 *		Security Record Cabinets
 *		Medical Record Cabinets
 */

/*
 * Filing Cabinets
 */
/obj/structure/filingcabinet
	name = "filing cabinet"
	desc = "A large cabinet with drawers."
	icon = 'icons/obj/bureaucracy.dmi'
	icon_state = "filingcabinet"
	density = 1
	anchored = 1

/obj/structure/filingcabinet/chestdrawer
	name = "chest drawer"
	icon_state = "chestdrawer"

/obj/structure/filingcabinet/chestdrawer/wheeled
	name = "rolling chest drawer"
	desc = "A small cabinet with drawers. This one has wheels!"
	anchored = 0

/obj/structure/filingcabinet/filingcabinet	//not changing the path to avoid unecessary map issues, but please don't name stuff like this in the future -Pete
	icon_state = "tallcabinet"

/obj/structure/filingcabinet/initialize()
	for(var/obj/item/I in loc)
		if(istype(I, /obj/item/weapon/paper) || istype(I, /obj/item/weapon/folder) || istype(I, /obj/item/weapon/photo))
			I.loc = src

/obj/structure/filingcabinet/ex_act(severity, target)
	for(var/obj/item/I in src)
		I.loc = src.loc
	qdel(src)
	..()

/obj/structure/filingcabinet/attackby(obj/item/P, mob/user, params)
	if(istype(P, /obj/item/weapon/paper) || istype(P, /obj/item/weapon/folder) || istype(P, /obj/item/weapon/photo) || istype(P, /obj/item/documents))
		if(!user.drop_item())
			return
		user << "You put [P] in [src]."
		P.loc = src
		icon_state = "[initial(icon_state)]-open"
		sleep(5)
		icon_state = initial(icon_state)
		updateUsrDialog()
	else if(istype(P, /obj/item/weapon/wrench))
		playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
		anchored = !anchored
		user << "You [anchored ? "wrench" : "unwrench"] [src]."
	else
		user << "You can't put [P] in [src]!"

/obj/structure/filingcabinet/attack_hand(mob/user)
	if(contents.len <= 0)
		user << "[src] is empty."
		return

	user.set_machine(src)
	var/dat = "
"
	var/i
	for(i=contents.len, i>=1, i--)
		var/obj/item/P = contents[i]
		dat += "
[P.name]
"
	dat += "
"
	user << browse("<title>[name]</title>[dat]", "window=filingcabinet;size=350x300")

/obj/structure/filingcabinet/attack_tk(mob/user)
	if(anchored)
		attack_self_tk(user)
	else
		..()

/obj/structure/filingcabinet/attack_self_tk(mob/user)
	if(contents.len)
		if(prob(40 + contents.len * 5))
			var/obj/item/I = pick(contents)
			I.loc = loc
			if(prob(25))
				step_rand(I)
			user << "You pull \a [I] out of [src] at random."
			return
	user << "You find nothing in [src]."

/obj/structure/filingcabinet/Topic(href, href_list)
	if(href_list["retrieve"])
		usr << browse("", "window=filingcabinet") // Close the menu

		//var/retrieveindex = text2num(href_list["retrieve"])
		var/obj/item/P = locate(href_list["retrieve"])//contents[retrieveindex]
		if(istype(P) && P.loc == src && in_range(src, usr))
			usr.put_in_hands(P)
			updateUsrDialog()
			icon_state = "[initial(icon_state)]-open"
			sleep(5)
			icon_state = initial(icon_state)

/*
 * Security Record Cabinets
 */
/obj/structure/filingcabinet/security
	var/virgin = 1

/obj/structure/filingcabinet/security/proc/populate()
	if(virgin)
		for(var/datum/data/record/G in data_core.general)
			var/datum/data/record/S = find_record("name", G.fields["name"], data_core.security)
			if(!S)
				continue
			var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(src)
			P.info = "Security Record
"
			P.info += "Name: [G.fields["name"]] ID: [G.fields["id"]]
\nSex: [G.fields["sex"]]
\nAge: [G.fields["age"]]
\nFingerprint: [G.fields["fingerprint"]]
\nPhysical Status: [G.fields["p_stat"]]
\nMental Status: [G.fields["m_stat"]]
"
			P.info += "
\nSecurity Data
\nCriminal Status: [S.fields["criminal"]]
\n
\nMinor Crimes: [S.fields["mi_crim"]]
\nDetails: [S.fields["mi_crim_d"]]
\n
\nMajor Crimes: [S.fields["ma_crim"]]
\nDetails: [S.fields["ma_crim_d"]]
\n
\nImportant Notes:
\n\t[S.fields["notes"]]
\n
\nComments/Log
"
			var/counter = 1
			while(S.fields["com_[counter]"])
				P.info += "[S.fields["com_[counter]"]]
"
				counter++
			P.info += "</TT>"
			P.name = "paper - '[G.fields["name"]]'"
			virgin = 0	//tabbing here is correct- it's possible for people to try and use it
						//before the records have been generated, so we do this inside the loop.
/obj/structure/filingcabinet/security/attack_hand()
	populate()
	..()
/obj/structure/filingcabinet/security/attack_tk()
	populate()
	..()

/*
 * Medical Record Cabinets
 */
/obj/structure/filingcabinet/medical
	var/virgin = 1

/obj/structure/filingcabinet/medical/proc/populate()
	if(virgin)
		for(var/datum/data/record/G in data_core.general)
			var/datum/data/record/M = find_record("name", G.fields["name"], data_core.medical)
			if(!M)
				continue
			var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(src)
			P.info = "Medical Record
"
			P.info += "Name: [G.fields["name"]] ID: [G.fields["id"]]
\nSex: [G.fields["sex"]]
\nAge: [G.fields["age"]]
\nFingerprint: [G.fields["fingerprint"]]
\nPhysical Status: [G.fields["p_stat"]]
\nMental Status: [G.fields["m_stat"]]
"
			P.info += "
\nMedical Data
\nBlood Type: [M.fields["blood_type"]]
\nDNA: [M.fields["b_dna"]]
\n
\nMinor Disabilities: [M.fields["mi_dis"]]
\nDetails: [M.fields["mi_dis_d"]]
\n
\nMajor Disabilities: [M.fields["ma_dis"]]
\nDetails: [M.fields["ma_dis_d"]]
\n
\nAllergies: [M.fields["alg"]]
\nDetails: [M.fields["alg_d"]]
\n
\nCurrent Diseases: [M.fields["cdi"]] (per disease info placed in log/comment section)
\nDetails: [M.fields["cdi_d"]]
\n
\nImportant Notes:
\n\t[M.fields["notes"]]
\n
\nComments/Log
"
			var/counter = 1
			while(M.fields["com_[counter]"])
				P.info += "[M.fields["com_[counter]"]]
"
				counter++
			P.info += "</TT>"
			P.name = "paper - '[G.fields["name"]]'"
			virgin = 0	//tabbing here is correct- it's possible for people to try and use it
						//before the records have been generated, so we do this inside the loop.
/obj/structure/filingcabinet/medical/attack_hand()
	populate()
	..()
/obj/structure/filingcabinet/medical/attack_tk()
	populate()
	..()


code:
/obj/item/weapon/folder
	name = "folder"
	desc = "A folder."
	icon = 'icons/obj/bureaucracy.dmi'
	icon_state = "folder"
	w_class = 2
	pressure_resistance = 2
	burn_state = FLAMMABLE

/obj/item/weapon/folder/blue
	desc = "A blue folder."
	icon_state = "folder_blue"

/obj/item/weapon/folder/red
	desc = "A red folder."
	icon_state = "folder_red"

/obj/item/weapon/folder/yellow
	desc = "A yellow folder."
	icon_state = "folder_yellow"

/obj/item/weapon/folder/white
	desc = "A white folder."
	icon_state = "folder_white"

/obj/item/weapon/folder/update_icon()
	overlays.Cut()
	if(contents.len)
		overlays += "folder_paper"

/obj/item/weapon/folder/attackby(obj/item/weapon/W, mob/user, params)
	if(istype(W, /obj/item/weapon/paper) || istype(W, /obj/item/weapon/photo) || istype(W, /obj/item/documents))
		if(!user.unEquip(W))
			return
		W.loc = src
		user << "You put [W] into [src]."
		update_icon()
	else if(istype(W, /obj/item/weapon/pen))
		var/n_name = copytext(sanitize(input(user, "What would you like to label the folder?", "Folder Labelling", null) as text), 1, MAX_NAME_LEN)
		if((in_range(src,user) && user.stat == CONSCIOUS))
			name = "folder[(n_name ? "- '[n_name]'" : null)]"

/obj/item/weapon/folder/attack_self(mob/user)
	var/dat = "<title>[name]</title>"

	for(var/obj/item/I in src)
		dat += "Remove - [I.name]
"
	user << browse(dat, "window=folder")
	onclose(user, "folder")
	add_fingerprint(usr)

/obj/item/weapon/folder/Topic(href, href_list)
	..()
	if(usr.stat || usr.restrained())
		return

	if(usr.contents.Find(src))

		if(href_list["remove"])
			var/obj/item/I = locate(href_list["remove"])
			if(istype(I) && I.loc == src)
				I.loc = usr.loc
				usr.put_in_hands(I)

		if(href_list["read"])
			var/obj/item/I = locate(href_list["read"])
			if(istype(I) && I.loc == src)
				usr.examinate(I)

		//Update everything
		attack_self(usr)
		update_icon()

/obj/item/weapon/folder/documents
	name = "folder- 'TOP SECRET'"
	desc = "A folder stamped \"Top Secret - Property of Nanotrasen Corporation. Unauthorized distribution is punishable by death.\""

/obj/item/weapon/folder/documents/New()
	..()
	new /obj/item/documents/nanotrasen(src)
	update_icon()

/obj/item/weapon/folder/syndicate
	name = "folder- 'TOP SECRET'"
	desc = "A folder stamped \"Top Secret - Property of The Syndicate.\""

/obj/item/weapon/folder/syndicate/red
	icon_state = "folder_sred"

/obj/item/weapon/folder/syndicate/red/New()
	..()
	new /obj/item/documents/syndicate/red(src)
	update_icon()

/obj/item/weapon/folder/syndicate/blue
	icon_state = "folder_sblue"

/obj/item/weapon/folder/syndicate/blue/New()
	..()
	new /obj/item/documents/syndicate/blue(src)
	update_icon()


code:
/obj/item/weapon/hand_labeler
	name = "hand labeler"
	icon = 'icons/obj/bureaucracy.dmi'
	icon_state = "labeler0"
	item_state = "flight"
	var/label = null
	var/labels_left = 30
	var/mode = 0

/obj/item/weapon/hand_labeler/afterattack(atom/A, mob/user,proximity)
	if(!proximity) return
	if(!mode)	//if it's off, give up.
		return
	if(A == loc)	// if placing the labeller into something (e.g. backpack)
		return		// don't set a label

	if(!labels_left)
		user << "No labels left!"
		return
	if(!label || !length(label))
		user << "No text set!"
		return
	if(length(A.name) + length(label) > 64)
		user << "Label too big!"
		return
	if(ishuman(A))
		user << "You can't label humans!"
		return
	if(issilicon(A))
		user << "You can't label cyborgs!"
		return

	user.visible_message("[user] labels [A] as [label].", \
						 "You label [A] as [label].")
	A.name = "[A.name] ([label])"
	labels_left--

/obj/item/weapon/hand_labeler/attack_self(mob/user)
	if(!user.IsAdvancedToolUser())
		user << "You don't have the dexterity to use [src]!"
		return
	mode = !mode
	icon_state = "labeler[mode]"
	if(mode)
		user << "You turn on [src]."
		//Now let them chose the text.
		var/str = copytext(reject_bad_text(input(user,"Label text?","Set label","")),1,MAX_NAME_LEN)
		if(!str || !length(str))
			user << "Invalid text!"
			return
		label = str
		user << "You set the text to '[str]'."
	else
		user << "You turn off [src]."

/obj/item/weapon/hand_labeler/attackby(obj/item/I, mob/user, params)
	..()
	if(istype(I, /obj/item/hand_labeler_refill))
		if(!user.unEquip(I))
			return
		user << "You insert [I] into [src]."
		qdel(I)
		labels_left = initial(labels_left)
		return

/obj/item/hand_labeler_refill
	name = "hand labeler paper roll"
	icon = 'icons/obj/bureaucracy.dmi'
	desc = "A roll of paper. Use it on a hand labeler to refill it."
	icon_state = "labeler_refill"
	item_state = "electropack"
	w_class = 1


code:
/obj/item/weapon/papercutter
	name = "paper cutter"
	desc = "Standard office equipment. Precisely cuts paper using a large blade."
	icon = 'icons/obj/bureaucracy.dmi'
	icon_state = "papercutter-cutter"
	force = 5
	throwforce = 5
	w_class = 3
	var/obj/item/weapon/paper/storedpaper = null
	var/obj/item/weapon/hatchet/cutterblade/storedcutter = null
	var/cuttersecured = TRUE
	pass_flags = PASSTABLE

/obj/item/weapon/papercutter/New()
	..()
	storedcutter = new /obj/item/weapon/hatchet/cutterblade(src)

/obj/item/weapon/papercutter/suicide_act(mob/user)
	if(storedcutter)
		user.visible_message("[user] is beheading \himself with [src.name]! It looks like \he's trying to commit suicide.")
		playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1)
		return (BRUTELOSS)
	else
		user.visible_message("[user] repeatedly bashes [src.name] against \his head! It looks like \he's trying to commit suicide.")
		playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
		return (BRUTELOSS)

/obj/item/weapon/papercutter/update_icon()
	..()
	overlays.Cut()
	icon_state = (storedcutter ? "[initial(icon_state)]-cutter" : "[initial(icon_state)]")
	if(storedpaper)
		overlays += "paper"

/obj/item/weapon/papercutter/attackby(obj/item/P, mob/user, params)
	if(istype(P, /obj/item/weapon/paper) && !storedpaper)
		if(!user.drop_item())
			return
		playsound(loc, "pageturn", 60, 1)
		user << "You place \the [P] in [src]."
		P.loc = src
		storedpaper = P
		update_icon()
		return
	if(istype(P, /obj/item/weapon/hatchet/cutterblade) && !storedcutter)
		if(!user.drop_item())
			return
		user << "You replace [src]'s [P]."
		P.loc = src
		storedcutter = P
		update_icon()
		return
	if(istype(P, /obj/item/weapon/screwdriver) && storedcutter)
		playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
		user << "\The [storedcutter] has been [cuttersecured ? "unsecured" : "secured"]."
		cuttersecured = !cuttersecured
		return
	..()

/obj/item/weapon/papercutter/attack_hand(mob/user)
	src.add_fingerprint(user)
	if(!storedcutter)
		user << "The cutting blade is gone! You can't use \the [src] now."
		return

	if(!cuttersecured)
		user << "You remove [src]'s [storedcutter]."
		user.put_in_hands(storedcutter)
		storedcutter = null
		update_icon()

	if(storedpaper)
		playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1)
		user << "You neatly cut \the [storedpaper]."
		storedpaper = null
		qdel(storedpaper)
		new /obj/item/weapon/paperslip(get_turf(src))
		new /obj/item/weapon/paperslip(get_turf(src))
		update_icon()

/obj/item/weapon/papercutter/MouseDrop(atom/over_object)
	var/mob/M = usr
	if(M.incapacitated() || !Adjacent(M))
		return

	if(over_object == M)
		M.put_in_hands(src)

	else if(istype(over_object, /obj/screen/inventory/hand))
		var/obj/screen/inventory/hand/H = over_object
		if(!remove_item_from_storage(M))
			if(!M.unEquip(src))
				return
		switch(H.slot_id)
			if(slot_r_hand)
				M.put_in_r_hand(src)
			if(slot_l_hand)
				M.put_in_l_hand(src)
	add_fingerprint(M)

/obj/item/weapon/paperslip
	name = "paper slip"
	desc = "A little slip of paper left over after a larger piece was cut. Whoa."
	icon_state = "paperslip"
	icon = 'icons/obj/bureaucracy.dmi'
	burn_state = FLAMMABLE
	burntime = 3

/obj/item/weapon/paperslip/New()
	..()
	pixel_x = rand(-5, 5)
	pixel_y = rand(-5, 5)

/obj/item/weapon/hatchet/cutterblade
	name = "paper cutter"
	desc = "The blade of a paper cutter. Most likely removed for polishing or sharpening."
	icon = 'icons/obj/bureaucracy.dmi'
	icon_state = "cutterblade"
	item_state = "knife"


code:
/obj/item/weapon/paper_bin
	name = "paper bin"
	icon = 'icons/obj/bureaucracy.dmi'
	icon_state = "paper_bin1"
	item_state = "sheet-metal"
	throwforce = 0
	w_class = 3
	throw_speed = 3
	throw_range = 7
	pressure_resistance = 8
	burn_state = FLAMMABLE
	var/amount = 30					//How much paper is in the bin.
	var/list/papers = new/list()	//List of papers put in the bin for reference.

/obj/item/weapon/paper_bin/fire_act()
	if(!amount)
		return
	..()

/obj/item/weapon/paper_bin/burn()
	amount = 0
	extinguish()
	update_icon()
	return

/obj/item/weapon/paper_bin/MouseDrop(atom/over_object)
	var/mob/living/M = usr
	if(!istype(M) || M.incapacitated() || !Adjacent(M))
		return

	if(over_object == M)
		M.put_in_hands(src)

	else if(istype(over_object, /obj/screen/inventory/hand))
		var/obj/screen/inventory/hand/H = over_object
		if(!remove_item_from_storage(M))
			if(!M.unEquip(src))
				return
		switch(H.slot_id)
			if(slot_r_hand)
				M.put_in_r_hand(src)
			if(slot_l_hand)
				M.put_in_l_hand(src)

	add_fingerprint(M)

/obj/item/weapon/paper_bin/attack_paw(mob/user)
	return attack_hand(user)

/obj/item/weapon/paper_bin/attack_hand(mob/user)
	if(user.lying)
		return
	user.changeNext_move(CLICK_CD_MELEE)
	if(amount >= 1)
		amount--
		update_icon()

		var/obj/item/weapon/paper/P
		if(papers.len > 0)	//If there's any custom paper on the stack, use that instead of creating a new paper.
			P = papers[papers.len]
			papers.Remove(P)
		else
			P = new /obj/item/weapon/paper
			if(SSevent.holidays && SSevent.holidays[APRIL_FOOLS])
				if(prob(30))
					P.info = "HONK HONK HONK HONK HONK HONK HONK
HOOOOOOOOOOOOOOOOOOOOOONK
APRIL FOOLS"
					P.rigged = 1
					P.updateinfolinks()

		P.loc = user.loc
		user.put_in_hands(P)
		user << "You take [P] out of \the [src]."
	else
		user << "[src] is empty!"

	add_fingerprint(user)

/obj/item/weapon/paper_bin/attackby(obj/item/weapon/paper/i, mob/user, params)
	if(!istype(i))
		return ..()

	if(!user.unEquip(i))
		return
	i.loc = src
	user << "You put [i] in [src]."
	papers.Add(i)
	amount++
	update_icon()

/obj/item/weapon/paper_bin/examine(mob/user)
	..()
	if(amount)
		user << "It contains " + (amount > 1 ? "[amount] papers" : " one paper")+"."
	else
		user << "It doesn't contain anything."

/obj/item/weapon/paper_bin/update_icon()
	if(amount < 1)
		icon_state = "paper_bin0"
	else
		icon_state = "paper_bin1"


code:
/*	Pens!
 *	Contains:
 *		Pens
 *		Sleepy Pens
 *		Parapens
 *		Edaggers
 */

/*
 * Pens
 */
/obj/item/weapon/pen
	desc = "It's a normal black ink pen."
	name = "pen"
	icon = 'icons/obj/bureaucracy.dmi'
	icon_state = "pen"
	item_state = "pen"
	slot_flags = SLOT_BELT | SLOT_EARS
	throwforce = 0
	w_class = 1
	throw_speed = 3
	throw_range = 7
	materials = list(MAT_METAL=10)
	pressure_resistance = 2
	var/colour = "black"	//what colour the ink is!

/obj/item/weapon/pen/suicide_act(mob/user)
	user.visible_message("[user] is scribbling numbers all over themself with [src]! It looks like they're trying to commit sudoku!")
	return(BRUTELOSS)

/obj/item/weapon/pen/blue
	desc = "It's a normal blue ink pen."
	icon_state = "pen_blue"
	colour = "blue"

/obj/item/weapon/pen/red
	desc = "It's a normal red ink pen."
	icon_state = "pen_red"
	colour = "red"

/obj/item/weapon/pen/invisible
	desc = "It's an invisble pen marker."
	icon_state = "pen"
	colour = "white"

/obj/item/weapon/pen/fourcolor
	desc = "It's a fancy four-color ink pen, set to black."
	name = "four-color pen"
	colour = "black"

/obj/item/weapon/pen/fourcolor/attack_self(mob/living/carbon/user)
	switch(colour)
		if("black")
			colour = "red"
		if("red")
			colour = "green"
		if("green")
			colour = "blue"
		else
			colour = "black"
	user << "\The [src] will now write in [colour]."
	desc = "It's a fancy four-color ink pen, set to [colour]."

/obj/item/weapon/pen/attack(mob/living/M, mob/user,stealth)
	if(!istype(M))
		return

	if(!force)
		if(M.can_inject(user, 1))
			user << "You stab [M] with the pen."
			if(!stealth)
				M << "You feel a tiny prick!"
			. = 1

		add_logs(user, M, "stabbed", src)

	else
		. = ..()

/*
 * Sleepypens
 */
/obj/item/weapon/pen/sleepy
	origin_tech = "materials=2;syndicate=5"
	flags = OPENCONTAINER

/obj/item/weapon/pen/sleepy/attack(mob/living/M, mob/user)
	if(!istype(M))
		return

	if(..())
		if(reagents.total_volume)
			if(M.reagents)
				reagents.trans_to(M, reagents.total_volume)

/obj/item/weapon/pen/sleepy/New()
	create_reagents(45)
	reagents.add_reagent("morphine", 20)
	reagents.add_reagent("mutetoxin", 15)
	reagents.add_reagent("tirizene", 10)
	..()

/*
 * (Alan) Edaggers
 */
/obj/item/weapon/pen/edagger
	origin_tech = "combat=3;syndicate=5"
	attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") //these wont show up if the pen is off
	var/on = 0

/obj/item/weapon/pen/edagger/attack_self(mob/living/user)
	if(on)
		on = 0
		force = initial(force)
		w_class = initial(w_class)
		name = initial(name)
		hitsound = initial(hitsound)
		embed_chance = initial(embed_chance)
		throwforce = initial(throwforce)
		playsound(user, 'sound/weapons/saberoff.ogg', 5, 1)
		user << "[src] can now be concealed."
	else
		on = 1
		force = 18
		w_class = 3
		name = "energy dagger"
		hitsound = 'sound/weapons/blade1.ogg'
		embed_chance = 100 //rule of cool
		throwforce = 35
		playsound(user, 'sound/weapons/saberon.ogg', 5, 1)
		user << "[src] is now active."
	update_icon()

/obj/item/weapon/pen/edagger/update_icon()
	if(on)
		icon_state = "edagger"
		item_state = "edagger"
	else
		icon_state = initial(icon_state) //looks like a normal pen when off.
		item_state = initial(item_state)


code:
/*	Photocopiers!
 *	Contains:
 *		Photocopier
 *		Toner Cartridge
 */

/*
 * Photocopier
 */
/obj/machinery/photocopier
	name = "photocopier"
	desc = "Used to copy important documents and anatomy studies."
	icon = 'icons/obj/library.dmi'
	icon_state = "photocopier"
	anchored = 1
	density = 1
	use_power = 1
	idle_power_usage = 30
	active_power_usage = 200
	power_channel = EQUIP
	var/obj/item/weapon/paper/copy = null	//what's in the copier!
	var/obj/item/weapon/photo/photocopy = null
	var/obj/item/documents/doccopy = null
	var/copies = 1	//how many copies to print!
	var/toner = 40 //how much toner is left! woooooo~
	var/maxcopies = 10	//how many copies can be copied at once- idea shamelessly stolen from bs12's copier!
	var/greytoggle = "Greyscale"
	var/mob/living/ass //i can't believe i didn't write a stupid-ass comment about this var when i first coded asscopy.
	var/busy = 0

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

/obj/machinery/photocopier/attack_paw(mob/user)
	return attack_hand(user)

/obj/machinery/photocopier/attack_hand(mob/user)
	user.set_machine(src)

	var/dat = "Photocopier

"
	if(copy || photocopy || doccopy || (ass && (ass.loc == src.loc)))
		dat += "Remove Paper
"
		if(toner)
			dat += "Copy
"
			dat += "Printing: [copies] copies."
			dat += "- "
			dat += "+

"
			if(photocopy)
				dat += "Printing in [greytoggle]

"
	else if(toner)
		dat += "Please insert paper to copy.

"
	if(istype(user,/mob/living/silicon/ai))
		dat += "Print photo from database

"
	dat += "Current toner level: [toner]"
	if(!toner)
		dat +="
Please insert a new toner cartridge!"
	user << browse(dat, "window=copier")
	onclose(user, "copier")

/obj/machinery/photocopier/Topic(href, href_list)
	if(..())
		return
	if(href_list["copy"])
		if(copy)
			for(var/i = 0, i < copies, i++)
				if(toner > 0 && !busy && copy)
					var/obj/item/weapon/paper/c = new /obj/item/weapon/paper (loc)
					if(length(copy.info) > 0)	//Only print and add content if the copied doc has words on it
						if(toner > 10)	//lots of toner, make it dark
							c.info = ""
						else			//no toner? shitty copies for you!
							c.info = ""
						var/copied = copy.info
						copied = replacetext(copied, "<font face=\"[PEN_FONT]\" color=", "<font face=\"[PEN_FONT]\" nocolor=")	//state of the art techniques in action
						copied = replacetext(copied, "<font face=\"[CRAYON_FONT]\" color=", "<font face=\"[CRAYON_FONT]\" nocolor=")	//This basically just breaks the existing color tag, which we need to do because the innermost tag takes priority.
						c.info += copied
						c.info += ""
						c.name = copy.name
						c.fields = copy.fields
						c.updateinfolinks()
						toner--
					busy = 1
					sleep(15)
					busy = 0
				else
					break
			updateUsrDialog()
		else if(photocopy)
			for(var/i = 0, i < copies, i++)
				if(toner >= 5 && !busy && photocopy)  //Was set to = 0, but if there was say 3 toner left and this ran, you would get -2 which would be weird for ink
					var/obj/item/weapon/photo/p = new /obj/item/weapon/photo (loc)
					var/icon/I = icon(photocopy.icon, photocopy.icon_state)
					var/icon/img = icon(photocopy.img)
					if(greytoggle == "Greyscale")
						if(toner > 10) //plenty of toner, go straight greyscale
							I.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0)) //I'm not sure how expensive this is, but given the many limitations of photocopying, it shouldn't be an issue.
							img.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0))
						else //not much toner left, lighten the photo
							I.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(100,100,100))
							img.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(100,100,100))
						toner -= 5	//photos use a lot of ink!
					else if(greytoggle == "Color")
						if(toner >= 10)
							toner -= 10 //Color photos use even more ink!
						else
							continue
					p.icon = I
					p.img = img
					p.name = photocopy.name
					p.desc = photocopy.desc
					p.scribble = photocopy.scribble
					p.pixel_x = rand(-10, 10)
					p.pixel_y = rand(-10, 10)
					p.blueprints = photocopy.blueprints //a copy of a picture is still good enough for the syndicate
					busy = 1
					sleep(15)
					busy = 0
				else
					break
		else if(doccopy)
			for(var/i = 0, i < copies, i++)
				if(toner > 5 && !busy && doccopy)
					new /obj/item/documents/photocopy(src)
					toner-= 6 // the sprite shows 6 papers, yes I checked
					busy = 1
					sleep(15)
					busy = 0
				else
					break
			updateUsrDialog()
		else if(ass) //ASS COPY. By Miauw
			for(var/i = 0, i < copies, i++)
				var/icon/temp_img
				if(ishuman(ass) && (ass.get_item_by_slot(slot_w_uniform) || ass.get_item_by_slot(slot_wear_suit)))
					usr << "You feel kind of silly, copying [ass == usr ? "your" : ass][ass == usr ? "" : "\'s"] ass with [ass == usr ? "your" : "their"] clothes on." //'
					break
				else if(toner >= 5 && !busy && check_ass()) //You have to be sitting on the copier and either be a xeno or a human without clothes on.
					if(isalienadult(ass) || istype(ass,/mob/living/simple_animal/hostile/alien)) //Xenos have their own asses, thanks to Pybro.
						temp_img = icon("icons/ass/assalien.png")
					else if(ishuman(ass)) //Suit checks are in check_ass
						if(ass.gender == MALE)
							temp_img = icon("icons/ass/assmale.png")
						else if(ass.gender == FEMALE)
							temp_img = icon("icons/ass/assfemale.png")
						else 									//In case anyone ever makes the generic ass. For now I'll be using male asses.
							temp_img = icon("icons/ass/assmale.png")
					else if(isdrone (ass) || istype(ass,/mob/living/simple_animal/drone)) //Drones are hot
						temp_img = icon("icons/ass/assdrone.png")
					else
						break
					var/obj/item/weapon/photo/p = new /obj/item/weapon/photo (loc)
					p.desc = "You see [ass]'s ass on the photo."
					p.pixel_x = rand(-10, 10)
					p.pixel_y = rand(-10, 10)
					p.img = temp_img
					var/icon/small_img = icon(temp_img) //Icon() is needed or else temp_img will be rescaled too >.>
					var/icon/ic = icon('icons/obj/items.dmi',"photo")
					small_img.Scale(8, 8)
					ic.Blend(small_img,ICON_OVERLAY, 10, 13)
					p.icon = ic
					toner -= 5
					busy = 1
					sleep(15)
					busy = 0
				else
					break
		updateUsrDialog()
	else if(href_list["remove"])
		if(copy)
			if(!istype(usr,/mob/living/silicon/ai)) //surprised this check didn't exist before, putting stuff in AI's hand is bad
				copy.loc = usr.loc
				usr.put_in_hands(copy)
			else
				copy.loc = src.loc
			usr << "You take [copy] out of [src]."
			copy = null
			updateUsrDialog()
		else if(photocopy)
			if(!istype(usr,/mob/living/silicon/ai)) //same with this one, wtf
				photocopy.loc = usr.loc
				usr.put_in_hands(photocopy)
			else
				photocopy.loc = src.loc
			usr << "You take [photocopy] out of [src]."
			photocopy = null
			updateUsrDialog()
		else if(check_ass())
			ass << "You feel a slight pressure on your ass."
	else if(href_list["min"])
		if(copies > 1)
			copies--
			updateUsrDialog()
	else if(href_list["add"])
		if(copies < maxcopies)
			copies++
			updateUsrDialog()
	else if(href_list["aipic"])
		if(!istype(usr,/mob/living/silicon/ai)) return
		if(toner >= 5 && !busy)
			var/list/nametemp = list()
			var/find
			var/datum/picture/selection
			var/mob/living/silicon/ai/tempAI = usr
			if(tempAI.aicamera.aipictures.len == 0)
				usr << "No images saved"
				return
			for(var/datum/picture/t in tempAI.aicamera.aipictures)
				nametemp += t.fields["name"]
			find = input("Select image (numbered in order taken)") in nametemp
			var/obj/item/weapon/photo/p = new /obj/item/weapon/photo (loc)
			for(var/datum/picture/q in tempAI.aicamera.aipictures)
				if(q.fields["name"] == find)
					selection = q
					break
			var/icon/I = selection.fields["icon"]
			var/icon/img = selection.fields["img"]
			p.icon = I
			p.img = img
			p.desc = selection.fields["desc"]
			p.blueprints = selection.fields["blueprints"]
			p.pixel_x = rand(-10, 10)
			p.pixel_y = rand(-10, 10)
			toner -= 5	 //AI prints color pictures only, thus they can do it more efficiently
			busy = 1
			sleep(15)
			busy = 0
		updateUsrDialog()
	else if(href_list["colortoggle"])
		if(greytoggle == "Greyscale")
			greytoggle = "Color"
		else
			greytoggle = "Greyscale"
		updateUsrDialog()

/obj/machinery/photocopier/proc/do_insertion(obj/item/O, mob/user)
		O.loc = src
		user << "You insert [O] into [src]."
		flick("photocopier1", src)
		updateUsrDialog()

/obj/machinery/photocopier/attackby(obj/item/O, mob/user, params)
	if(istype(O, /obj/item/weapon/paper))
		if(copier_empty())
			if(!user.drop_item())
				return
			copy = O
			do_insertion(O)
		else
			user << "There is already something in [src]!"

	else if(istype(O, /obj/item/weapon/photo))
		if(copier_empty())
			if(!user.drop_item())
				return
			photocopy = O
			do_insertion(O)
		else
			user << "There is already something in [src]!"

	else if(istype(O, /obj/item/documents))
		if(copier_empty())
			if(!user.drop_item())
				return
			doccopy = O
			do_insertion(O)
		else
			user << "There is already something in [src]!"

	else if(istype(O, /obj/item/device/toner))
		if(toner <= 0)
			if(!user.drop_item())
				return
			qdel(O)
			toner = 40
			user << "You insert [O] into [src]."
			updateUsrDialog()
		else
			user << "This cartridge is not yet ready for replacement! Use up the rest of the toner."

	else if(istype(O, /obj/item/weapon/wrench))
		if(isinspace())
			user << "There's nothing to fasten [src] to!"
			return
		playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
		user << "You start [anchored ? "unwrenching" : "wrenching"] [src]..."
		if(do_after(user, 20/O.toolspeed, target = src))
			if(qdeleted(src))
				return
			user << "You [anchored ? "unwrench" : "wrench"] [src]."
			anchored = !anchored

/obj/machinery/photocopier/ex_act(severity, target)
	switch(severity)
		if(1)
			qdel(src)
		if(2)
			if(prob(50))
				qdel(src)
			else
				if(toner > 0)
					new /obj/effect/decal/cleanable/oil(get_turf(src))
					toner = 0
		else
			if(prob(50))
				if(toner > 0)
					new /obj/effect/decal/cleanable/oil(get_turf(src))
					toner = 0

/obj/machinery/photocopier/blob_act()
	if(prob(50))
		qdel(src)
	else
		if(toner > 0)
			new /obj/effect/decal/cleanable/oil(get_turf(src))
			toner = 0

/obj/machinery/photocopier/MouseDrop_T(mob/target, mob/user)
	check_ass() //Just to make sure that you can re-drag somebody onto it after they moved off.
	if (!istype(target) || target.anchored || target.buckled || !Adjacent(user) || !Adjacent(target) || !user.canUseTopic(src, 1) || target == ass || copier_blocked())
		return
	src.add_fingerprint(user)
	if(target == user)
		user.visible_message("[user] starts climbing onto the photocopier!", "You start climbing onto the photocopier...")
	else
		user.visible_message("[user] starts putting [target] onto the photocopier!", "You start putting [target] onto the photocopier...")

	if(do_after(user, 20, target = src))
		if(!target || qdeleted(target) || qdeleted(src) || !Adjacent(target)) //check if the photocopier/target still exists.
			return

		if(target == user)
			user.visible_message("[user] climbs onto the photocopier!", "You climb onto the photocopier.")
		else
			user.visible_message("[user] puts [target] onto the photocopier!", "You put [target] onto the photocopier.")

		target.loc = get_turf(src)
		ass = target

		if(photocopy)
			photocopy.loc = src.loc
			visible_message("[photocopy] is shoved out of the way by [ass]!")
			photocopy = null

		else if(copy)
			copy.loc = src.loc
			visible_message("[copy] is shoved out of the way by [ass]!")
			copy = null
	updateUsrDialog()

/obj/machinery/photocopier/proc/check_ass() //I'm not sure wether I made this proc because it's good form or because of the name.
	if(!ass)
		return 0
	if(ass.loc != src.loc)
		ass = null
		updateUsrDialog()
		return 0
	else if(istype(ass,/mob/living/carbon/human))
		if(!ass.get_item_by_slot(slot_w_uniform) && !ass.get_item_by_slot(slot_wear_suit))
			return 1
		else
			return 0
	else
		return 1

/obj/machinery/photocopier/proc/copier_blocked()
	if(qdeleted(src))
		return
	if(loc.density)
		return 1
	for(var/atom/movable/AM in loc)
		if(AM == src)
			continue
		if(AM.density)
			return 1
	return 0

/obj/machinery/photocopier/proc/copier_empty()
	if(copy || photocopy || check_ass())
		return 0
	else
		return 1

/*
 * Toner cartridge
 */
/obj/item/device/toner
	name = "toner cartridge"
	icon_state = "tonercartridge"
	var/charges = 5
	var/max_charges = 5


code:
/*	Photography!
 *	Contains:
 *		Camera
 *		Camera Film
 *		Photos
 *		Photo Albums
 *		AI Photography
 */

/*
 * Film
 */
/obj/item/device/camera_film
	name = "film cartridge"
	icon = 'icons/obj/items.dmi'
	desc = "A camera film cartridge. Insert it into a camera to reload it."
	icon_state = "film"
	item_state = "electropack"
	w_class = 1
	burn_state = FLAMMABLE

/*
 * Photo
 */
/obj/item/weapon/photo
	name = "photo"
	icon = 'icons/obj/items.dmi'
	icon_state = "photo"
	item_state = "paper"
	w_class = 1
	burn_state = FLAMMABLE
	burntime = 5
	var/icon/img		//Big photo image
	var/scribble		//Scribble on the back.
	var/blueprints = 0	//Does it include the blueprints?
	var/sillynewscastervar  //Photo objects with this set to 1 will not be ejected by a newscaster. Only gets set to 1 if a silicon puts one of their images into a newscaster

/obj/item/weapon/photo/attack_self(mob/user)
	user.examinate(src)

/obj/item/weapon/photo/attackby(obj/item/weapon/P, mob/user, params)
	if(istype(P, /obj/item/weapon/pen) || istype(P, /obj/item/toy/crayon))
		var/txt = sanitize(input(user, "What would you like to write on the back?", "Photo Writing", null)  as text)
		txt = copytext(txt, 1, 128)
		if(loc == user && user.stat == 0)
			scribble = txt
	..()

/obj/item/weapon/photo/examine(mob/user)
	..()

	if(in_range(user, src))
		show(user)
	else
		user << "You need to get closer to get a good look at this photo!"

/obj/item/weapon/photo/proc/show(mob/user)
	user << browse_rsc(img, "tmp_photo.png")
	user << browse("<title>[name]</title>" \
		+ "" \
		+ "" \
		+ "[scribble ? "
Written on the back:
[scribble]" : ""]"\
		+ "", "window=book;size=192x[scribble ? 400 : 192]")
	onclose(user, "[name]")

/obj/item/weapon/photo/verb/rename()
	set name = "Rename photo"
	set category = "Object"
	set src in usr

	var/n_name = copytext(sanitize(input(usr, "What would you like to label the photo?", "Photo Labelling", null)  as text), 1, MAX_NAME_LEN)
	//loc.loc check is for making possible renaming photos in clipboards
	if((loc == usr || loc.loc && loc.loc == usr) && usr.stat == 0 && usr.canmove && !usr.restrained())
		name = "photo[(n_name ? text("- '[n_name]'") : null)]"
	add_fingerprint(usr)

/obj/item/weapon/photo/proc/photocreate(inicon, inimg, indesc, inblueprints)
	icon = inicon
	img = inimg
	desc = indesc
	blueprints = inblueprints

/*
 * Photo album
 */
/obj/item/weapon/storage/photo_album
	name = "photo album"
	icon = 'icons/obj/items.dmi'
	icon_state = "album"
	item_state = "briefcase"
	can_hold = list(/obj/item/weapon/photo)
	burn_state = FLAMMABLE

/*
 * Camera
 */
/obj/item/device/camera
	name = "camera"
	icon = 'icons/obj/items.dmi'
	desc = "A polaroid camera."
	icon_state = "camera"
	item_state = "electropack"
	w_class = 2
	flags = CONDUCT
	slot_flags = SLOT_BELT
	materials = list(MAT_METAL=2000)
	var/pictures_max = 10
	var/pictures_left = 10
	var/on = 1
	var/blueprints = 0	//are blueprints visible in the current photo being created?
	var/list/aipictures = list() //Allows for storage of pictures taken by AI, in a similar manner the datacore stores info. Keeping this here allows us to share some procs w/ regualar camera
	var/see_ghosts = 0 //for the spoop of it

/obj/item/device/camera/CheckParts()
	var/obj/item/device/camera/C = locate(/obj/item/device/camera) in contents
	if(C)
		pictures_max = C.pictures_max
		pictures_left = C.pictures_left
		visible_message("[C] has been imbued with godlike power!")
		qdel(C)

/obj/item/device/camera/spooky
	name = "camera obscura"
	desc = "A polaroid camera, some say it can see ghosts!"
	see_ghosts = 1

/obj/item/device/camera/detective
	name = "Detective's camera"
	desc = "A polaroid camera with extra capacity for crime investigations."
	pictures_max = 30
	pictures_left = 30

/obj/item/device/camera/siliconcam //camera AI can take pictures with
	name = "silicon photo camera"
	var/in_camera_mode = 0

/obj/item/device/camera/siliconcam/ai_camera //camera AI can take pictures with
	name = "AI photo camera"

/obj/item/device/camera/siliconcam/robot_camera //camera cyborgs can take pictures with.. needs it's own because of verb CATEGORY >.>
	name = "Cyborg photo camera"

/obj/item/device/camera/siliconcam/robot_camera/verb/borgprinting()
	set category ="Robot Commands"
	set name = "Print Image"
	set src in usr

	if(usr.stat == DEAD)
		return //won't work if dead
	borgprint()

/obj/item/device/camera/attack(mob/living/carbon/human/M, mob/user)
	return

/obj/item/device/camera/attackby(obj/item/I, mob/user, params)
	if(istype(I, /obj/item/device/camera_film))
		if(pictures_left)
			user << "[src] still has some film in it!"
			return
		if(!user.unEquip(I))
			return
		user << "You insert [I] into [src]."
		qdel(I)
		pictures_left = pictures_max
		return
	..()

/obj/item/device/camera/examine(mob/user)
	..()
	user << "It has [pictures_left] photos left."

/obj/item/device/camera/proc/camera_get_icon(list/turfs, turf/center)
	var/atoms[] = list()
	for(var/turf/T in turfs)
		atoms.Add(T)
		for(var/atom/movable/A in T)
			if(A.invisibility)
				if(see_ghosts)
					if(istype(A, /mob/dead/observer))
						var/mob/dead/observer/O = A
						if(O.orbiting) //so you dont see ghosts following people like antags, etc.
							continue
				else
					continue
			atoms.Add(A)

	var/list/sorted = list()
	var/j
	for(var/i = 1 to atoms.len)
		var/atom/c = atoms[i]
		for(j = sorted.len, j > 0, --j)
			var/atom/c2 = sorted[j]
			if(c2.layer <= c.layer)
				break
		sorted.Insert(j+1, c)

	var/icon/res = icon('icons/effects/96x96.dmi', "")

	for(var/atom/A in sorted)
		var/icon/img = getFlatIcon(A)
		if(istype(A, /mob/living) && A:lying)
			img.Turn(A:lying)

		var/offX = 32 * (A.x - center.x) + A.pixel_x + 33
		var/offY = 32 * (A.y - center.y) + A.pixel_y + 33
		if(istype(A, /atom/movable))
			offX += A:step_x
			offY += A:step_y

		res.Blend(img, blendMode2iconMode(A.blend_mode), offX, offY)

		if(istype(A, /obj/item/areaeditor/blueprints))
			blueprints = 1

	for(var/turf/T in turfs)
		res.Blend(getFlatIcon(T.loc), blendMode2iconMode(T.blend_mode), 32 * (T.x - center.x) + 33, 32 * (T.y - center.y) + 33)

	return res

/obj/item/device/camera/proc/camera_get_mobs(turf/the_turf)
	var/mob_detail
	for(var/mob/M in the_turf)
		if(M.invisibility)
			if(see_ghosts && istype(M,/mob/dead/observer))
				var/mob/dead/observer/O = M
				if(O.orbiting)
					continue
				if(!mob_detail)
					mob_detail = "You can see a g-g-g-g-ghooooost! "
				else
					mob_detail += "You can also see a g-g-g-g-ghooooost!"
			else
				continue

		var/holding = null

		if(istype(M, /mob/living))
			var/mob/living/L = M
			if(L.l_hand || L.r_hand)
				if(L.l_hand) holding = "They are holding \a [L.l_hand]"
				if(L.r_hand)
					if(holding)
						holding += " and \a [L.r_hand]"
					else
						holding = "They are holding \a [L.r_hand]"

			if(!mob_detail)
				mob_detail = "You can see [L] on the photo[L.health < 75 ? " - [L] looks hurt":""].[holding ? " [holding]":"."]. "
			else
				mob_detail += "You can also see [L] on the photo[L.health < 75 ? " - [L] looks hurt":""].[holding ? " [holding]":"."]."

	return mob_detail

/obj/item/device/camera/proc/captureimage(atom/target, mob/user, flag)  //Proc for both regular and AI-based camera to take the image
	var/mobs = ""
	var/isAi = istype(user, /mob/living/silicon/ai)
	var/list/seen
	if(!isAi) //crappy check, but without it AI photos would be subject to line of sight from the AI Eye object. Made the best of it by moving the sec camera check inside
		if(user.client)		//To make shooting through security cameras possible
			seen = get_hear(world.view, user.client.eye) //To make shooting through security cameras possible
		else
			seen = get_hear(world.view, user)
	else
		seen = get_hear(world.view, target)

	var/list/turfs = list()
	for(var/turf/T in range(1, target))
		if(T in seen)
			if(isAi && !cameranet.checkTurfVis(T))
				continue
			else
				turfs += T
				mobs += camera_get_mobs(T)

	var/icon/temp = icon('icons/effects/96x96.dmi',"")
	temp.Blend("#000", ICON_OVERLAY)
	temp.Blend(camera_get_icon(turfs, target), ICON_OVERLAY)

	if(!issilicon(user))
		printpicture(user, temp, mobs, flag)
	else
		aipicture(user, temp, mobs, isAi, blueprints)

/obj/item/device/camera/proc/printpicture(mob/user, icon/temp, mobs, flag) //Normal camera proc for creating photos
	var/obj/item/weapon/photo/P = new/obj/item/weapon/photo(get_turf(src))
	if(Adjacent(user)) //needed because of TK
		user.put_in_hands(P)
	var/icon/small_img = icon(temp)
	var/icon/ic = icon('icons/obj/items.dmi',"photo")
	small_img.Scale(8, 8)
	ic.Blend(small_img,ICON_OVERLAY, 10, 13)
	P.icon = ic
	P.img = temp
	P.desc = mobs
	P.pixel_x = rand(-10, 10)
	P.pixel_y = rand(-10, 10)

	if(blueprints)
		P.blueprints = 1
		blueprints = 0

/obj/item/device/camera/proc/aipicture(mob/user, icon/temp, mobs, isAi) //instead of printing a picture like a regular camera would, we do this instead for the AI

	var/icon/small_img = icon(temp)
	var/icon/ic = icon('icons/obj/items.dmi',"photo")
	small_img.Scale(8, 8)
	ic.Blend(small_img,ICON_OVERLAY, 10, 13)
	var/icon = ic
	var/img = temp
	var/desc = mobs
	var/pixel_x = rand(-10, 10)
	var/pixel_y = rand(-10, 10)

	var/injectblueprints = 1
	if(blueprints)
		injectblueprints = 1
		blueprints = 0

	if(isAi)
		injectaialbum(icon, img, desc, pixel_x, pixel_y, injectblueprints)
	else
		injectmasteralbum(icon, img, desc, pixel_x, pixel_y, injectblueprints)

/datum/picture
	var/name = "image"
	var/list/fields = list()

/obj/item/device/camera/proc/injectaialbum(icon, img, desc, pixel_x, pixel_y, blueprintsinject) //stores image information to a list similar to that of the datacore
	var/numberer = 1
	for(var/datum/picture in src.aipictures)
		numberer++
	var/datum/picture/P = new()
	P.fields["name"] = "Image [numberer] (taken by [src.loc.name])"
	P.fields["icon"] = icon
	P.fields["img"] = img
	P.fields["desc"] = desc
	P.fields["pixel_x"] = pixel_x
	P.fields["pixel_y"] = pixel_y
	P.fields["blueprints"] = blueprintsinject

	aipictures += P
	usr << "Image recorded"	//feedback to the AI player that the picture was taken

/obj/item/device/camera/proc/injectmasteralbum(icon, img, desc, pixel_x, pixel_y, blueprintsinject) //stores image information to a list similar to that of the datacore
	var/numberer = 1
	var/mob/living/silicon/robot/C = src.loc
	if(C.connected_ai)
		for(var/datum/picture in C.connected_ai.aicamera.aipictures)
			numberer++
		var/datum/picture/P = new()
		P.fields["name"] = "Image [numberer] (taken by [src.loc.name])"
		P.fields["icon"] = icon
		P.fields["img"] = img
		P.fields["desc"] = desc
		P.fields["pixel_x"] = pixel_x
		P.fields["pixel_y"] = pixel_y
		P.fields["blueprints"] = blueprintsinject

		C.connected_ai.aicamera.aipictures += P
		usr << "Image recorded and saved to remote database"	//feedback to the Cyborg player that the picture was taken
	else
		injectaialbum(icon, img, desc, pixel_x, pixel_y, blueprintsinject)

/obj/item/device/camera/siliconcam/proc/selectpicture(obj/item/device/camera/siliconcam/targetloc)
	var/list/nametemp = list()
	var/find
	if(targetloc.aipictures.len == 0)
		usr << "No images saved"
		return
	for(var/datum/picture/t in targetloc.aipictures)
		nametemp += t.fields["name"]
	find = input("Select image (numbered in order taken)") in nametemp
	for(var/datum/picture/q in targetloc.aipictures)
		if(q.fields["name"] == find)
			return q

/obj/item/device/camera/siliconcam/proc/viewpichelper(obj/item/device/camera/siliconcam/targetloc)
	var/obj/item/weapon/photo/P = new/obj/item/weapon/photo()
	var/datum/picture/selection = selectpicture(targetloc)
	if(selection)
		P.photocreate(selection.fields["icon"], selection.fields["img"], selection.fields["desc"])
		P.pixel_x = selection.fields["pixel_x"]
		P.pixel_y = selection.fields["pixel_y"]

		P.show(usr)
		usr << P.desc
	qdel(P)    //so 10 thousand picture items are not left in memory should an AI take them and then view them all

/obj/item/device/camera/siliconcam/proc/viewpictures(user)
	if(isrobot(user)) // Cyborg
		var/mob/living/silicon/robot/C = src.loc
		var/obj/item/device/camera/siliconcam/Cinfo
		if(C.connected_ai)
			Cinfo = C.connected_ai.aicamera
			viewpichelper(Cinfo)
		else
			Cinfo = C.aicamera
			viewpichelper(Cinfo)
	else // AI
		var/Ainfo = src
		viewpichelper(Ainfo)

/obj/item/device/camera/afterattack(atom/target, mob/user, flag)
	if(!on || !pictures_left || ismob(target.loc) || !isturf(target.loc))
		return
	if(user.Adjacent(target))
		var/list/bad_targets = list(/obj/structure, /obj/item/weapon/storage)
		if(is_type_in_list(target, bad_targets))
			return

	captureimage(target, user, flag)

	playsound(loc, pick('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg'), 75, 1, -3)

	pictures_left--
	user << "[pictures_left] photos left."
	icon_state = "camera_off"
	on = 0
	spawn(64)
		icon_state = "camera"
		on = 1

/obj/item/device/camera/siliconcam/proc/toggle_camera_mode()
	if(in_camera_mode)
		camera_mode_off()
	else
		camera_mode_on()

/obj/item/device/camera/siliconcam/proc/camera_mode_off()
	src.in_camera_mode = 0
	usr << "Camera Mode deactivated"

/obj/item/device/camera/siliconcam/proc/camera_mode_on()
	src.in_camera_mode = 1
	usr << "Camera Mode activated"

/obj/item/device/camera/siliconcam/robot_camera/proc/borgprint()
	var/list/nametemp = list()
	var/find
	var/datum/picture/selection
	var/mob/living/silicon/robot/C = src.loc
	var/obj/item/device/camera/siliconcam/targetcam = null
	if(C.toner < 20)
		usr << "Insufficent toner to print image."
		return
	if(C.connected_ai)
		targetcam = C.connected_ai.aicamera
	else
		targetcam = C.aicamera
	if(targetcam.aipictures.len == 0)
		usr << "No images saved"
		return
	for(var/datum/picture/t in targetcam.aipictures)
		nametemp += t.fields["name"]
	find = input("Select image (numbered in order taken)") in nametemp
	for(var/datum/picture/q in targetcam.aipictures)
		if(q.fields["name"] == find)
			selection = q
			break
	var/obj/item/weapon/photo/p = new /obj/item/weapon/photo(C.loc)
	p.photocreate(selection.fields["icon"], selection.fields["img"], selection.fields["desc"], selection.fields["blueprints"])
	p.pixel_x = rand(-10, 10)
	p.pixel_y = rand(-10, 10)
	C.toner -= 20	 //Cyborgs are very ineffeicient at printing an image
	visible_message("[C.name] spits out a photograph from a narrow slot on it's chassis.")
	usr << "You print a photograph."


code:
/obj/item/weapon/stamp
	name = "\improper GRANTED rubber stamp"
	desc = "A rubber stamp for stamping important documents."
	icon = 'icons/obj/bureaucracy.dmi'
	icon_state = "stamp-ok"
	item_state = "stamp"
	throwforce = 0
	w_class = 1
	throw_speed = 3
	throw_range = 7
	materials = list(MAT_METAL=60)
	item_color = "cargo"
	pressure_resistance = 2
	attack_verb = list("stamped")

/obj/item/weapon/stamp/suicide_act(mob/user)
	user.visible_message("[user] stamps 'VOID' on \his forehead, then promptly falls over, dead.")
	return (OXYLOSS)

/obj/item/weapon/stamp/qm
	name = "quartermaster's rubber stamp"
	icon_state = "stamp-qm"
	item_color = "qm"

/obj/item/weapon/stamp/law
	name = "law office's rubber stamp"
	icon_state = "stamp-law"
	item_color = "cargo"

/obj/item/weapon/stamp/captain
	name = "captain's rubber stamp"
	icon_state = "stamp-cap"
	item_color = "captain"

/obj/item/weapon/stamp/hop
	name = "head of personnel's rubber stamp"
	icon_state = "stamp-hop"
	item_color = "hop"

/obj/item/weapon/stamp/hos
	name = "head of security's rubber stamp"
	icon_state = "stamp-hos"
	item_color = "hosred"

/obj/item/weapon/stamp/ce
	name = "chief engineer's rubber stamp"
	icon_state = "stamp-ce"
	item_color = "chief"

/obj/item/weapon/stamp/rd
	name = "research director's rubber stamp"
	icon_state = "stamp-rd"
	item_color = "director"

/obj/item/weapon/stamp/cmo
	name = "chief medical officer's rubber stamp"
	icon_state = "stamp-cmo"
	item_color = "cmo"

/obj/item/weapon/stamp/denied
	name = "\improper DENIED rubber stamp"
	icon_state = "stamp-deny"
	item_color = "redcoat"

/obj/item/weapon/stamp/clown
	name = "clown's rubber stamp"
	icon_state = "stamp-clown"
	item_color = "clown"

/obj/item/weapon/stamp/attack_paw(mob/user)
	return attack_hand(user)

// Syndicate stamp to forge documents.

/obj/item/weapon/stamp/chameleon/attack_self(mob/user)

	var/list/stamp_types = typesof(/obj/item/weapon/stamp) - src.type // Get all stamp types except our own
	var/list/stamps = list()

	// Generate them into a list
	for(var/stamp_type in stamp_types)
		var/obj/item/weapon/stamp/S = new stamp_type
		stamps[capitalize(S.name)] = S

	var/list/show_stamps = list("EXIT" = null) + sortList(stamps) // the list that will be shown to the user to pick from

	var/input_stamp = input(user, "Choose a stamp to disguise as.", "Choose a stamp.") in show_stamps

	if(user && src in user.contents)

		var/obj/item/weapon/stamp/chosen_stamp = stamps[capitalize(input_stamp)]

		if(chosen_stamp)
			name = chosen_stamp.name
			icon_state = chosen_stamp.icon_state
			item_color = chosen_stamp.item_color


code:
/obj/item/weapon/am_containment
	name = "antimatter containment jar"
	desc = "Holds antimatter."
	icon = 'icons/obj/machines/antimatter.dmi'
	icon_state = "jar"
	density = 0
	anchored = 0
	force = 8
	throwforce = 10
	throw_speed = 1
	throw_range = 2

	var/fuel = 10000
	var/fuel_max = 10000//Lets try this for now
	var/stability = 100//TODO: add all the stability things to this so its not very safe if you keep hitting in on things

/obj/item/weapon/am_containment/ex_act(severity, target)
	switch(severity)
		if(1)
			explosion(get_turf(src), 1, 2, 3, 5)//Should likely be larger but this works fine for now I guess
			if(src)
				qdel(src)
		if(2)
			if(prob((fuel/10)-stability))
				explosion(get_turf(src), 1, 2, 3, 5)
				if(src)
					qdel(src)
				return
			stability -= 40
		if(3)
			stability -= 20
	//check_stability()
	return

/obj/item/weapon/am_containment/proc/usefuel(wanted)
	if(fuel < wanted)
		wanted = fuel
	fuel -= wanted
	return wanted


code:
/obj/machinery/power/am_control_unit
	name = "antimatter control unit"
	desc = "This device injects antimatter into connected shielding units, the more antimatter injected the more power produced.  Wrench the device to set it up."
	icon = 'icons/obj/machines/antimatter.dmi'
	icon_state = "control"
	anchored = 1
	density = 1
	use_power = 1
	idle_power_usage = 100
	active_power_usage = 1000

	var/list/obj/machinery/am_shielding/linked_shielding
	var/list/obj/machinery/am_shielding/linked_cores
	var/obj/item/weapon/am_containment/fueljar
	var/update_shield_icons = 0
	var/stability = 100
	var/exploding = 0

	var/active = 0//On or not
	var/fuel_injection = 2//How much fuel to inject
	var/shield_icon_delay = 0//delays resetting for a short time
	var/reported_core_efficiency = 0

	var/power_cycle = 0
	var/power_cycle_delay = 4//How many ticks till produce_power is called
	var/stored_core_stability = 0
	var/stored_core_stability_delay = 0

	var/stored_power = 0//Power to deploy per tick

/obj/machinery/power/am_control_unit/New()
	..()
	linked_shielding = list()
	linked_cores = list()

/obj/machinery/power/am_control_unit/Destroy()//Perhaps damage and run stability checks rather than just del on the others
	for(var/obj/machinery/am_shielding/AMS in linked_shielding)
		qdel(AMS)
	return ..()

/obj/machinery/power/am_control_unit/process()
	if(exploding)
		explosion(get_turf(src),8,12,18,12)
		if(src)
			qdel(src)

	if(update_shield_icons && !shield_icon_delay)
		check_shield_icons()
		update_shield_icons = 0

	if(stat & (NOPOWER|BROKEN) || !active)//can update the icons even without power
		return

	if(!fueljar)//No fuel but we are on, shutdown
		toggle_power()
		//Angry buzz or such here
		return

	add_avail(stored_power)

	power_cycle++
	if(power_cycle >= power_cycle_delay)
		produce_power()
		power_cycle = 0

	return

/obj/machinery/power/am_control_unit/proc/produce_power()
	playsound(src.loc, 'sound/effects/bang.ogg', 25, 1)
	var/core_power = reported_core_efficiency//Effectively how much fuel we can safely deal with
	if(core_power <= 0)
		return 0//Something is wrong
	var/core_damage = 0
	var/fuel = fueljar.usefuel(fuel_injection)

	stored_power = (fuel/core_power)*fuel*200000
	//Now check if the cores could deal with it safely, this is done after so you can overload for more power if needed, still a bad idea
	if(fuel > (2*core_power))//More fuel has been put in than the current cores can deal with
		if(prob(50))
			core_damage = 1//Small chance of damage
		if((fuel-core_power) > 5)
			core_damage = 5//Now its really starting to overload the cores
		if((fuel-core_power) > 10)
			core_damage = 20//Welp now you did it, they wont stand much of this
		if(core_damage == 0)
			return
		for(var/obj/machinery/am_shielding/AMS in linked_cores)
			AMS.stability -= core_damage
			AMS.check_stability(1)
		playsound(src.loc, 'sound/effects/bang.ogg', 50, 1)
	return

/obj/machinery/power/am_control_unit/emp_act(severity)
	switch(severity)
		if(1)
			if(active)
				toggle_power()
			stability -= rand(15,30)
		if(2)
			if(active)
				toggle_power()
			stability -= rand(10,20)
	..()
	return 0

/obj/machinery/power/am_control_unit/blob_act()
	stability -= 20
	if(prob(100-stability))//Might infect the rest of the machine
		for(var/obj/machinery/am_shielding/AMS in linked_shielding)
			AMS.blob_act()
		qdel(src)
		return
	check_stability()
	return

/obj/machinery/power/am_control_unit/ex_act(severity, target)
	stability -= (80 - (severity * 20))
	check_stability()
	return

/obj/machinery/power/am_control_unit/bullet_act(obj/item/projectile/Proj)
	if(Proj.flag != "bullet")
		stability -= Proj.force
	return 0

/obj/machinery/power/am_control_unit/power_change()
	..()
	if(stat & NOPOWER && active)
		toggle_power()
	return

/obj/machinery/power/am_control_unit/update_icon()
	if(active)
		icon_state = "control_on"
	else icon_state = "control"
	//No other icons for it atm

/obj/machinery/power/am_control_unit/attackby(obj/item/W, mob/user, params)
	if(istype(W, /obj/item/weapon/wrench))
		if(!anchored)
			playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
			user.visible_message("[user.name] secures the [src.name] to the floor.", \
				"You secure the anchor bolts to the floor.", \
				"You hear a ratchet.")
			src.anchored = 1
			connect_to_network()
		else if(!linked_shielding.len > 0)
			playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
			user.visible_message("[user.name] unsecures the [src.name].", \
				"YYou remove the anchor bolts.", \
				"You hear a ratchet.")
			src.anchored = 0
			disconnect_from_network()
		else
			user << "Once bolted and linked to a shielding unit it the [src.name] is unable to be moved!"
		return

	if(istype(W, /obj/item/weapon/am_containment))
		if(fueljar)
			user << "There is already a [fueljar] inside!"
			return
		fueljar = W
		W.loc = src
		if(user.client)
			user.client.screen -= W
		user.unEquip(W)
		user.update_icons()
		user.visible_message("[user.name] loads an [W.name] into the [src.name].", \
				"You load an [W.name].", \
				"You hear a thunk.")
		return

	if(W.force >= 20)
		stability -= W.force/2
		check_stability()
	..()

/obj/machinery/power/am_control_unit/attack_hand(mob/user)
	if(anchored)
		interact(user)
	return

/obj/machinery/power/am_control_unit/proc/add_shielding(obj/machinery/am_shielding/AMS, AMS_linking = 0)
	if(!istype(AMS))
		return 0
	if(!anchored)
		return 0
	if(!AMS_linking && !AMS.link_control(src))
		return 0
	linked_shielding.Add(AMS)
	update_shield_icons = 1
	return 1

/obj/machinery/power/am_control_unit/proc/remove_shielding(obj/machinery/am_shielding/AMS)
	if(!istype(AMS))
		return 0
	linked_shielding.Remove(AMS)
	update_shield_icons = 2
	if(active)
		toggle_power()
	return 1

/obj/machinery/power/am_control_unit/proc/check_stability()//TODO: make it break when low also might want to add a way to fix it like a part or such that can be replaced
	if(stability <= 0)
		qdel(src)
	return

/obj/machinery/power/am_control_unit/proc/toggle_power()
	active = !active
	if(active)
		use_power = 2
		visible_message("The [src.name] starts up.")
	else
		use_power = 1
		visible_message("The [src.name] shuts down.")
	update_icon()
	return

/obj/machinery/power/am_control_unit/proc/check_shield_icons()//Forces icon_update for all shields
	if(shield_icon_delay)
		return
	shield_icon_delay = 1
	if(update_shield_icons == 2)//2 means to clear everything and rebuild
		for(var/obj/machinery/am_shielding/AMS in linked_shielding)
			if(AMS.processing)
				AMS.shutdown_core()
			AMS.control_unit = null
			spawn(10)
				AMS.controllerscan()
		linked_shielding = list()

	else
		for(var/obj/machinery/am_shielding/AMS in linked_shielding)
			AMS.update_icon()
	spawn(20)
		shield_icon_delay = 0
	return

/obj/machinery/power/am_control_unit/proc/check_core_stability()
	if(stored_core_stability_delay || linked_cores.len <= 0)
		return
	stored_core_stability_delay = 1
	stored_core_stability = 0
	for(var/obj/machinery/am_shielding/AMS in linked_cores)
		stored_core_stability += AMS.stability
	stored_core_stability/=linked_cores.len
	spawn(40)
		stored_core_stability_delay = 0
	return

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

	var/dat = ""
	dat += "AntiMatter Control Panel
"
	dat += "Close
"
	dat += "Refresh
"
	dat += "Force Shielding Update

"
	dat += "Status: [(active?"Injecting":"Standby")]
"
	dat += "Toggle Status
"

	dat += "Stability: [stability]%
"
	dat += "Reactor parts: [linked_shielding.len]
"//TODO: perhaps add some sort of stability check
	dat += "Cores: [linked_cores.len]

"
	dat += "-Current Efficiency: [reported_core_efficiency]
"
	dat += "-Average Stability: [stored_core_stability] (update)
"
	dat += "Last Produced: [stored_power]
"

	dat += "Fuel: "
	if(!fueljar)
		dat += "
No fuel receptacle detected."
	else
		dat += "Eject
"
		dat += "- [fueljar.fuel]/[fueljar.fuel_max] Units
"

		dat += "- Injecting: [fuel_injection] units
"
		dat += "- --|++

"

	user << browse(dat, "window=AMcontrol;size=420x500")
	onclose(user, "AMcontrol")
	return

/obj/machinery/power/am_control_unit/Topic(href, href_list)
	if(..())
		return

	if(href_list["close"])
		usr << browse(null, "window=AMcontrol")
		usr.unset_machine()
		return

	if(href_list["togglestatus"])
		toggle_power()

	if(href_list["refreshicons"])
		update_shield_icons = 1

	if(href_list["ejectjar"])
		if(fueljar)
			fueljar.loc = src.loc
			fueljar = null
			//fueljar.control_unit = null currently it does not care where it is
			//update_icon() when we have the icon for it

	if(href_list["strengthup"])
		fuel_injection++

	if(href_list["strengthdown"])
		fuel_injection--
		if(fuel_injection < 0)
			fuel_injection = 0

	if(href_list["refreshstability"])
		check_core_stability()

	updateDialog()
	return


code:
//like orange but only checks north/south/east/west for one step
/proc/cardinalrange(var/center)
	var/list/things = list()
	for(var/direction in cardinal)
		var/turf/T = get_step(center, direction)
		if(!T) continue
		things += T.contents
	return things

/obj/machinery/am_shielding
	name = "antimatter reactor section"
	desc = "This device was built using a plasma life-form that seems to increase plasma's natural ability to react with neutrinos while reducing the combustibility."

	icon = 'icons/obj/machines/antimatter.dmi'
	icon_state = "shield"
	anchored = 1
	density = 1
	dir = 1
	use_power = 0//Living things generally dont use power
	idle_power_usage = 0
	active_power_usage = 0

	var/obj/machinery/power/am_control_unit/control_unit = null
	var/processing = 0//To track if we are in the update list or not, we need to be when we are damaged and if we ever
	var/stability = 100//If this gets low bad things tend to happen
	var/efficiency = 1//How many cores this core counts for when doing power processing, plasma in the air and stability could affect this

/obj/machinery/am_shielding/New(loc)
	..(loc)
	spawn(10)
		controllerscan()
	return

/obj/machinery/am_shielding/proc/controllerscan(priorscan = 0)
	//Make sure we are the only one here
	if(!istype(src.loc, /turf))
		qdel(src)
		return
	for(var/obj/machinery/am_shielding/AMS in loc.contents)
		if(AMS == src)
			continue
		qdel(src)
		return

	//Search for shielding first
	for(var/obj/machinery/am_shielding/AMS in cardinalrange(src))
		if(AMS && AMS.control_unit && link_control(AMS.control_unit))
			break

	if(!control_unit)//No other guys nearby look for a control unit
		for(var/direction in cardinal)
		for(var/obj/machinery/power/am_control_unit/AMC in cardinalrange(src))
			if(AMC.add_shielding(src))
				break

	if(!control_unit)
		if(!priorscan)
			spawn(20)
				controllerscan(1)//Last chance
			return
		qdel(src)
	return

/obj/machinery/am_shielding/Destroy()
	if(control_unit)
		control_unit.remove_shielding(src)
	if(processing)
		shutdown_core()
	visible_message("The [src.name] melts!")
	//Might want to have it leave a mess on the floor but no sprites for now
	return ..()

/obj/machinery/am_shielding/CanPass(atom/movable/mover, turf/target, height=0)
	if(height==0)
		return 1
	return 0

/obj/machinery/am_shielding/process()
	if(!processing)
		. = PROCESS_KILL
	//TODO: core functions and stability
	//TODO: think about checking the airmix for plasma and increasing power output
	return

/obj/machinery/am_shielding/emp_act()//Immune due to not really much in the way of electronics.
	return 0

/obj/machinery/am_shielding/blob_act()
	stability -= 20
	if(prob(100-stability))
		if(prob(10))//Might create a node
			new /obj/effect/blob/node(src.loc,150)
		else
			new /obj/effect/blob(src.loc,60)
		qdel(src)
		return
	check_stability()
	return

/obj/machinery/am_shielding/ex_act(severity, target)
	stability -= (80 - (severity * 20))
	check_stability()
	return

/obj/machinery/am_shielding/bullet_act(obj/item/projectile/Proj)
	if(Proj.flag != "bullet")
		stability -= Proj.force/2
	return 0

/obj/machinery/am_shielding/update_icon()
	overlays.Cut()
	for(var/direction in alldirs)
		var/machine = locate(/obj/machinery, get_step(loc, direction))
		if((istype(machine, /obj/machinery/am_shielding) && machine:control_unit == control_unit)||(istype(machine, /obj/machinery/power/am_control_unit) && machine == control_unit))
			overlays += "shield_[direction]"

	if(core_check())
		overlays += "core"
		if(!processing)
			setup_core()
	else if(processing)
		shutdown_core()

/obj/machinery/am_shielding/attackby(obj/item/W, mob/user, params)
	if(W.force > 10)
		stability -= W.force/2
		check_stability()
	..()

//Call this to link a detected shilding unit to the controller
/obj/machinery/am_shielding/proc/link_control(obj/machinery/power/am_control_unit/AMC)
	if(!istype(AMC))
		return 0
	if(control_unit && control_unit != AMC)
		return 0//Already have one
	control_unit = AMC
	control_unit.add_shielding(src,1)
	return 1

//Scans cards for shields or the control unit and if all there it
/obj/machinery/am_shielding/proc/core_check()
	for(var/direction in alldirs)
		var/machine = locate(/obj/machinery, get_step(loc, direction))
		if(!machine)
			return 0//Need all for a core
		if(!istype(machine, /obj/machinery/am_shielding) && !istype(machine, /obj/machinery/power/am_control_unit))
			return 0
	return 1

/obj/machinery/am_shielding/proc/setup_core()
	processing = 1
	machines |= src
	SSmachine.processing |= src
	if(!control_unit)
		return
	control_unit.linked_cores.Add(src)
	control_unit.reported_core_efficiency += efficiency
	return

/obj/machinery/am_shielding/proc/shutdown_core()
	processing = 0
	if(!control_unit)
		return
	control_unit.linked_cores.Remove(src)
	control_unit.reported_core_efficiency -= efficiency
	return

/obj/machinery/am_shielding/proc/check_stability(injecting_fuel = 0)
	if(stability > 0)
		return
	if(injecting_fuel && control_unit)
		control_unit.exploding = 1
	if(src)
		qdel(src)
	return

/obj/machinery/am_shielding/proc/recalc_efficiency(new_efficiency)//tbh still not 100% sure how I want to deal with efficiency so this is likely temp
	if(!control_unit || !processing)
		return
	if(stability < 50)
		new_efficiency /= 2
	control_unit.reported_core_efficiency += (new_efficiency - efficiency)
	efficiency = new_efficiency
	return

/obj/item/device/am_shielding_container
	name = "packaged antimatter reactor section"
	desc = "A small storage unit containing an antimatter reactor section.  To use place near an antimatter control unit or deployed antimatter reactor section and use a multitool to activate this package."
	icon = 'icons/obj/machines/antimatter.dmi'
	icon_state = "box"
	item_state = "electronic"
	w_class = 4
	flags = CONDUCT
	throwforce = 5
	throw_speed = 1
	throw_range = 2
	materials = list(MAT_METAL=100)

/obj/item/device/am_shielding_container/attackby(obj/item/I, mob/user, params)
	if(istype(I, /obj/item/device/multitool) && istype(src.loc,/turf))
		new/obj/machinery/am_shielding(src.loc)
		qdel(src)
		return
	..()
	return