code:
/datum/surgery/core_removal
	name = "core removal"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/incise, /datum/surgery_step/extract_core)
	species = list(/mob/living/carbon/slime)
	target_must_be_dead = 1

//extract brain
/datum/surgery_step/extract_core
	implements = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/crowbar = 100)
	time = 16

/datum/surgery_step/extract_core/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to extract a core from [target].")

/datum/surgery_step/extract_core/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	var/mob/living/carbon/slime/slime = target
	if(slime.cores > 0)
		slime.cores--
		user.visible_message("[user] successfully extracts a core from [target]!")
		user << "[slime.cores] core\s remaining."

		new slime.coretype(slime.loc)

		if(slime.cores <= 0)
			slime.icon_state = "[slime.colour] baby slime dead-nocore"
			return 1
		else
			return 0
	else
		user.visible_message("There aren't any cores left in [target].")
		return 1


code:
#define MAX_BRAIN_IMPLANT	2
#define MAX_CHEST_IMPLANT	3

/datum/surgery_step/cybernetic_implant/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/cybernetic_implant/implant, datum/surgery/surgery)
	user.visible_message("[user] begins to implant [target] with [implant].")

//[[[[EYES]]]]
/datum/surgery/eye_cybernetic_implant/eyes
	name = "eye cybernetic implant"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/cybernetic_implant/eyes, /datum/surgery_step/fix_eyes, /datum/surgery_step/close)
	location = "eyes"

/datum/surgery_step/cybernetic_implant/eyes
	implements = list(/obj/item/cybernetic_implant/eyes = 100)
	time = 32

/datum/surgery_step/cybernetic_implant/eyes/success(mob/user, mob/living/carbon/target, target_zone, obj/item/cybernetic_implant/eyes/implant, datum/surgery/surgery)
	if(implant)
		var/full = 0
		if(locate(/obj/item/cybernetic_implant/eyes,target.internal_organs))
			full = 1
		insert(user,target,implant,target_zone,full)
		return 1

//[[[[BRAIN]]]]
/datum/surgery/eye_cybernetic_implant/brain
	name = "brain cybernetic implant"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/cybernetic_implant/brain, /datum/surgery_step/close)
	location = "head"

/datum/surgery_step/cybernetic_implant/brain
	implements = list(/obj/item/cybernetic_implant/brain = 100)
	time = 32

/datum/surgery_step/cybernetic_implant/brain/success(mob/user, mob/living/carbon/target, target_zone, obj/item/cybernetic_implant/brain/implant, datum/surgery/surgery)
	if(implant)
		var/full = 0
		for(var/obj/item/I in target.internal_organs)
			if(istype(I,/obj/item/cybernetic_implant/brain))
				full++

		if(full < MAX_BRAIN_IMPLANT)
			full = 0
		insert(user,target,implant,target_zone,full)
		return 1

//[[[[CHEST]]]]

/datum/surgery/eye_cybernetic_implant/chest
	name = "torso cybernetic implant"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/cybernetic_implant/chest, /datum/surgery_step/close)
	location = "chest"

/datum/surgery_step/cybernetic_implant/chest
	implements = list(/obj/item/cybernetic_implant/chest = 100)
	time = 32

/datum/surgery_step/cybernetic_implant/chest/success(mob/user, mob/living/carbon/target, target_zone, obj/item/cybernetic_implant/chest/implant, datum/surgery/surgery)
	if(implant)
		var/full = 0
		for(var/obj/item/I in target.internal_organs)
			if(istype(I,/obj/item/cybernetic_implant/chest))
				full++
		if(full < MAX_CHEST_IMPLANT)
			full = 0

		if(istype(implant,/obj/item/cybernetic_implant/chest/heart))
			if(locate(/obj/item/cybernetic_implant/chest/heart) in target.internal_organs)
				full = 1

		insert(user,target,implant,target_zone,full)
		return 1

/datum/surgery_step/cybernetic_implant/proc/insert(mob/user, mob/living/carbon/target, obj/item/cybernetic_implant/implant,target_zone,full)
	if(full)
		user.visible_message("[user] can't seem to implant anything else into the [target]'s [target_zone].")
	else
		user.visible_message("[user] inserts [implant] into the [target]'s [target_zone == "head" ? "brain" : target_zone]!")
		implant.owner = target
		implant.function()
		user.drop_item()
		target.internal_organs |= implant
		implant.loc = target

license: mit


code:
/datum/surgery/eye_surgery
	name = "eye surgery"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/fix_eyes, /datum/surgery_step/close)
	species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
	location = "eyes"

//fix eyes
/datum/surgery_step/fix_eyes
	implements = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/screwdriver = 45, /obj/item/weapon/pen = 25)
	time = 64

/datum/surgery_step/fix_eyes/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to fix [target]'s eyes.")

/datum/surgery_step/fix_eyes/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] successfully fixes [target]'s eyes!")
	target.disabilities &= ~BLIND
	target.disabilities &= ~NEARSIGHT
	target.eye_blurry = 35	//this will fix itself slowly.
	target.eye_stat = 0
	return 1

/datum/surgery_step/fix_eyes/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(target.getorgan(/obj/item/organ/brain))
		user.visible_message("[user] accidentally stabs [target] right in the brain!")
		target.adjustBrainLoss(100)
	else
		user.visible_message("[user] accidentally stabs [target] right in the brain! Or would have, if [target] had a brain.")
	return 0


code:
/datum/surgery/gender_reassignment
	name = "gender reassignment"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/reshape_genitals, /datum/surgery_step/close)
	species = list(/mob/living/carbon/human)
	location = "groin"
	requires_organic_chest = 1

//reshape_genitals
/datum/surgery_step/reshape_genitals
	implements = list(/obj/item/weapon/scalpel = 100, /obj/item/weapon/hatchet = 50, /obj/item/weapon/wirecutters = 35)
	time = 64

/datum/surgery_step/reshape_genitals/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(target.gender == FEMALE)
		user.visible_message("[user] begins to reshape [target]'s genitals to look more masculine.")
	else
		user.visible_message("[user] begins to reshape [target]'s genitals to look more feminine.")

/datum/surgery_step/reshape_genitals/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	var/mob/living/carbon/human/H = target	//no type check, as that should be handled by the surgery
	H.gender_ambiguous = 0
	if(target.gender == FEMALE)
		user.visible_message("[user] has made a man of [target]!")
		target.gender = MALE
	else
		user.visible_message("[user] has made a woman of [target]!")
		target.gender = FEMALE
	target.regenerate_icons()
	return 1

/datum/surgery_step/reshape_genitals/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	var/mob/living/carbon/human/H = target
	H.gender_ambiguous = 1
	user.visible_message("[user] mutilates [target]'s genitals beyond the point of recognition!")
	target.gender = pick(MALE, FEMALE)
	target.regenerate_icons()
	return 1


code:
//make incision
/datum/surgery_step/incise
	implements = list(/obj/item/weapon/scalpel = 100, /obj/item/weapon/kitchenknife = 65, /obj/item/weapon/shard = 45)
	time = 24

/datum/surgery_step/incise/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to make an incision in [target]'s [parse_zone(target_zone)].")

//clamp bleeders
/datum/surgery_step/clamp_bleeders
	implements = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/wirecutters = 60, /obj/item/stack/cable_coil = 15)
	time = 48

/datum/surgery_step/clamp_bleeders/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to clamp bleeders in [target]'s [parse_zone(target_zone)].")

//retract skin
/datum/surgery_step/retract_skin
	implements = list(/obj/item/weapon/retractor = 100, /obj/item/weapon/screwdriver = 45, /obj/item/weapon/wirecutters = 35)
	time = 32

/datum/surgery_step/retract_skin/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to retract the skin in [target]'s [parse_zone(target_zone)].")

//close incision
/datum/surgery_step/close
	implements = list(/obj/item/weapon/cautery = 100, /obj/item/weapon/weldingtool = 70, /obj/item/weapon/lighter = 45, /obj/item/weapon/match = 20)
	time = 32

/datum/surgery_step/close/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to mend the incision in [target]'s [parse_zone(target_zone)].")

/datum/surgery_step/close/tool_check(mob/user, obj/item/tool)
	if(istype(tool, /obj/item/weapon/cautery))
		return 1

	if(istype(tool, /obj/item/weapon/weldingtool))
		var/obj/item/weapon/weldingtool/WT = tool
		if(WT.isOn())	return 1

	else if(istype(tool, /obj/item/weapon/lighter))
		var/obj/item/weapon/lighter/L = tool
		if(L.lit)	return 1

	else if(istype(tool, /obj/item/weapon/match))
		var/obj/item/weapon/match/M = tool
		if(M.lit)	return 1

	return 0

//saw bone
/datum/surgery_step/saw
	implements = list(/obj/item/weapon/circular_saw = 100, /obj/item/weapon/melee/arm_blade = 75, /obj/item/weapon/hatchet = 35, /obj/item/weapon/kitchenknife/butcher = 25)
	time = 64

/datum/surgery_step/saw/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to saw through the bone in [target]'s [parse_zone(target_zone)].")


code:
/proc/attempt_initiate_surgery(obj/item/I, mob/living/M, mob/user)
	if(istype(M))
		if(M.lying || isslime(M))	//if they're prone or a slime
			var/list/all_surgeries = surgeries_list.Copy()
			var/list/available_surgeries = list()
			for(var/i in all_surgeries)
				var/datum/surgery/S = all_surgeries[i]

				if(locate(S.type) in M.surgeries)
					continue
				if(S.user_species_restricted)
					if(!istype(user, /mob/living/carbon/human))
						continue
					var/mob/living/carbon/human/doc = user
					if(!(doc.dna.species.id in S.user_species_ids))
						continue
				if(S.target_must_be_dead && M.stat != DEAD)
					continue
				if(S.target_must_be_fat && !(M.disabilities & FAT))
					continue

				if(istype(M, /mob/living/carbon/human))
					var/mob/living/carbon/human/H = M //So we can use get_organ and not some terriblly long Switch or something worse - RR

					if(S.requires_organic_chest && H.getlimb(/obj/item/organ/limb/robot/chest)) //This a seperate case to below, see "***" in surgery.dm - RR
						continue

					var/obj/item/organ/limb/affecting = H.get_organ(check_zone(user.zone_sel.selecting))

					if(affecting.status == ORGAN_ROBOTIC && affecting.body_part != HEAD) //Cannot operate on Robotic organs except for the head. - RR
						continue

				for(var/path in S.species)
					if(istype(M, path))
						available_surgeries[S.name] = S
						break

			var/P = input("Begin which procedure?", "Surgery", null, null) as null|anything in available_surgeries
			if(P)
				var/datum/surgery/S = available_surgeries[P]
				var/datum/surgery/procedure = new S.type
				if(procedure)
					if(get_location_accessible(M, procedure.location) || procedure.ignore_clothes)
						if(procedure.location == "anywhere") // if location == "anywhere" change location to the surgeon's target, otherwise leave location as is.
							procedure.location = user.zone_sel.selecting
						M.surgeries += procedure
						user.visible_message("[user] drapes [I] over [M]'s [parse_zone(procedure.location)] to prepare for \an [procedure.name].")

						add_logs(user, M, "operated", addition="Operation type: [procedure.name]")
						return 1
					else
						user << "You need to expose [M]'s [procedure.location] first."
						return 1	//return 1 so we don't slap the guy in the dick with the drapes.
			else
				return 1	//once the input menu comes up, cancelling it shouldn't hit the guy with the drapes either.
	return 0

proc/get_location_modifier(mob/M)
	var/turf/T = get_turf(M)
	if(locate(/obj/structure/optable, T))
		return 1
	else if(locate(/obj/structure/table, T))
		return 0.8
	else if(locate(/obj/structure/stool/bed, T))
		return 0.7
	else
		return 0.5

/proc/get_location_accessible(mob/M, location)
	var/covered_locations	= 0	//based on body_parts_covered
	var/face_covered		= 0	//based on flags_inv
	var/eyesmouth_covered	= 0	//based on flags
	if(iscarbon(M))
		var/mob/living/carbon/C = M
		for(var/obj/item/clothing/I in list(C.back, C.wear_mask))
			covered_locations |= I.body_parts_covered
			face_covered |= I.flags_inv
			eyesmouth_covered |= I.flags
		if(ishuman(C))
			var/mob/living/carbon/human/H = C
			for(var/obj/item/I in list(H.wear_suit, H.w_uniform, H.shoes, H.belt, H.gloves, H.glasses, H.head, H.ears))
				covered_locations |= I.body_parts_covered
				face_covered |= I.flags_inv
				eyesmouth_covered |= I.flags

	switch(location)
		if("head")
			if(covered_locations & HEAD)
				return 0
		if("eyes")
			if(covered_locations & HEAD || face_covered & HIDEEYES || eyesmouth_covered & GLASSESCOVERSEYES)
				return 0
		if("mouth")
			if(covered_locations & HEAD || face_covered & HIDEFACE || eyesmouth_covered & MASKCOVERSMOUTH)
				return 0
		if("chest")
			if(covered_locations & CHEST)
				return 0
		if("groin")
			if(covered_locations & GROIN)
				return 0
		if("l_arm")
			if(covered_locations & ARM_LEFT)
				return 0
		if("r_arm")
			if(covered_locations & ARM_RIGHT)
				return 0
		if("l_leg")
			if(covered_locations & LEG_LEFT)
				return 0
		if("r_leg")
			if(covered_locations & LEG_RIGHT)
				return 0
		if("l_hand")
			if(covered_locations & HAND_LEFT)
				return 0
		if("r_hand")
			if(covered_locations & HAND_RIGHT)
				return 0
		if("l_foot")
			if(covered_locations & FOOT_LEFT)
				return 0
		if("r_foot")
			if(covered_locations & FOOT_RIGHT)
				return 0

	return 1


code:
/datum/surgery/implant_removal
	name = "implant removal"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/extract_implant, /datum/surgery_step/close)
	species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
	location = "chest"
	requires_organic_chest = 1

//extract implant
/datum/surgery_step/extract_implant
	implements = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/crowbar = 65)
	time = 64
	var/obj/item/weapon/implant/I = null

/datum/surgery_step/extract_implant/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	for(var/obj/item/weapon/implant/W in target)
		if(W.imp_in == target)	//Checking that it's actually implanted, not just in his pocket
			I = W
			break
	if(I)
		user.visible_message("[user] begins to extract [I] from [target]'s [target_zone].")
	else
		user.visible_message("[user] looks for an implant in [target]'s [target_zone].")

/datum/surgery_step/extract_implant/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(I)
		user.visible_message("[user] successfully removes [I] from [target]'s [target_zone]!")
		if(istype(I, /obj/item/weapon/implant/loyalty))
			target << "You feel a sense of liberation as Nanotrasen's grip on your mind fades away."
		qdel(I)
		if(istype(target, /mob/living/carbon/human))
			var/mob/living/carbon/human/H = target
			H.sec_hud_set_implants()
	else
		user.visible_message("[user] can't find anything in [target]'s [target_zone].")
	return 1


code:
/////AUGMENTATION SURGERIES//////

//SURGERY STEPS

/datum/surgery_step/replace
	implements = list(/obj/item/weapon/scalpel = 100, /obj/item/weapon/wirecutters = 55)
	time = 32

/datum/surgery_step/replace/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to sever the muscles on [target]'s [parse_zone(user.zone_sel.selecting)]!")

/datum/surgery_step/add_limb
	implements = list(/obj/item/robot_parts = 100)
	time = 32
	var/obj/item/organ/limb/L = null // L because "limb"
	allowed_organs = list("r_arm","l_arm","r_leg","l_leg","chest","head")

/datum/surgery_step/add_limb/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	L = new_organ
	if(L)
		user.visible_message("[user] begins to augment [target]'s [parse_zone(user.zone_sel.selecting)].")
	else
		user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_sel.selecting)].")

//ACTUAL SURGERIES

/datum/surgery/augmentation
	name = "augmentation"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/replace, /datum/surgery_step/saw, /datum/surgery_step/add_limb)
	species = list(/mob/living/carbon/human)
	location = "anywhere" //Check attempt_initate_surgery() (in code/modules/surgery/helpers) to see what this does if you can't tell
	has_multi_loc = 1 //Multi location stuff, See multiple_location_example.dm

//SURGERY STEP SUCCESSES

/datum/surgery_step/add_limb/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(L)
		if(ishuman(target))
			switch(L.body_part)
				if(CHEST)
					if(!istype(tool,/obj/item/robot_parts/chest))
						user << "That is the wrong robotic limb for this body part."
						return 0
				if(HEAD)
					if(!istype(tool,/obj/item/robot_parts/head))
						user << "That is the wrong robotic limb for this body part."
						return 0
				if(ARM_LEFT)
					if(!istype(tool,/obj/item/robot_parts/l_arm))
						user << "That is the wrong robotic limb for this body part."
						return 0
				if(ARM_RIGHT)
					if(!istype(tool,/obj/item/robot_parts/r_arm))
						user << "That is the wrong robotic limb for this body part."
						return 0
				if(LEG_LEFT)
					if(!istype(tool,/obj/item/robot_parts/l_leg))
						user << "That is the wrong robotic limb for this body part."
						return 0
				if(LEG_RIGHT)
					if(!istype(tool,/obj/item/robot_parts/r_leg))
						user << "That is the wrong robotic limb for this body part."
						return 0
			var/mob/living/carbon/human/H = target
			user.visible_message("[user] successfully augments [target]'s [parse_zone(target_zone)]!")
			L.loc = get_turf(target)
			H.organs -= L
			switch(target_zone)
				if("r_leg")
					H.organs += new /obj/item/organ/limb/robot/r_leg(src)
				if("l_leg")
					H.organs += new /obj/item/organ/limb/robot/l_leg(src)
				if("r_arm")
					H.organs += new /obj/item/organ/limb/robot/r_arm(src)
				if("l_arm")
					H.organs += new /obj/item/organ/limb/robot/l_arm(src)
				if("head")
					H.organs += new /obj/item/organ/limb/robot/head(src)
				if("chest")
					var/datum/surgery_step/xenomorph_removal/xeno_removal = new
					xeno_removal.remove_xeno(user, target) // remove an alien if there is one
					H.organs += new /obj/item/organ/limb/robot/chest(src)
					for(var/datum/disease/appendicitis/A in H.viruses) //If they already have Appendicitis, Remove it
						A.cure(1)
			user.drop_item()
			qdel(tool)
			H.update_damage_overlays(0)
			H.update_augments() //Gives them the Cyber limb overlay
			add_logs(user, target, "augmented", addition="by giving him new [parse_zone(target_zone)] INTENT: [uppertext(user.a_intent)]")
	else
		user.visible_message("[user] [target] has no organic [parse_zone(target_zone)] there!")
	return 1


code:
/datum/surgery/lipoplasty
	name = "lipoplasty"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/cut_fat, /datum/surgery_step/remove_fat, /datum/surgery_step/close)
	species = list(/mob/living/carbon/human)
	target_must_be_fat = 1
	location = "chest"
	requires_organic_chest = 1

//cut fat
/datum/surgery_step/cut_fat
	implements = list(/obj/item/weapon/circular_saw = 100, /obj/item/weapon/hatchet = 35, /obj/item/weapon/kitchenknife/butcher = 25)
	time = 64

/datum/surgery_step/cut_fat/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to cut away [target]'s excess fat!")

/datum/surgery_step/cut_fat/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] cuts [target]'s excess fat loose!")
	return 1

//remove fat
/datum/surgery_step/remove_fat
	implements = list(/obj/item/weapon/retractor = 100, /obj/item/weapon/screwdriver = 45, /obj/item/weapon/wirecutters = 35)
	time = 32

/datum/surgery_step/remove_fat/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to extract [target]'s loose fat!")

/datum/surgery_step/remove_fat/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] extracts [target]'s fat!")
	target.overeatduration = 0 //patient is unfatted
	var/removednutriment = target.nutrition
	target.nutrition = NUTRITION_LEVEL_WELL_FED
	removednutriment -= 450 //whatever was removed goes into the meat
	var/obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/newmeat = new
	newmeat.name = "fatty meat"
	newmeat.desc = "Extremely fatty tissue taken from a patient."
	newmeat.reagents.add_reagent ("nutriment", (removednutriment / 15)) //To balance with nutriment_factor of nutriment
	var/obj/item/meatslab = newmeat
	meatslab.loc = target.loc
	return 1


code:
/*
//CONTENTS//
Multiple location example surgery

//THE SURGERY//
it is very similar to a normal surgery.
Location = "anywhere" is the unique difference.

/datum/surgery/multiLocExample
	name = "Multiple Location Surgery Example"
	steps = list(/datum/surgery_step/multiLocExampleStep)
	species = list(/mob/living/carbon)
	location = "anywhere" //A Location "Anywhere" is handled in /code/modules/surgery/helpers attempt_initiate_surgery(), it is converted into a User.zone_sel.selecting.
	has_multi_loc = 1 //Needed to handle Multilocation

//THE STEPS//
The block of "If's" is necessary, add or remove so you have just the areas you want, and set them to convert L(or your subsitute) to what you want it to be
EG: a zone on a mob (where user is targetting) to the limb thats actually there.

/datum/surgery_step/multiLocExampleStep
	implements = list()
	time = 9001
	allowed_organs = list("r_arm","l_arm","r_leg","l_leg","chest","head", "etc")
	// allowed_organs is a list of organs this operation works with, it is defined in the earliest instance of the surgery_step (Eg, datum/surgery_step/multiLocExampleStep)
	// allowed_organs is handled in Handle_Multi_Loc() in surgery_step.dm

/datum/surgery_step/multiLocExampleStep/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	L = new_organ //new_organ is a variable in /datum/surgery_step, it is null by default, and is given a value in Handle_Multi_Loc()
	//Although Handle_Multi_Loc() is /datum/surgery_step/SURGERYNAME/Handle_Multi_Loc() you do not need to rewrite it in the surgery
	if(L)
		user.visible_message("Generic Statement.")
	else
		user.visible_message("Generic Statement 2.")

/datum/surgery_step/multiLocExampleStep/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
You can use whatever you substituted "L" for here for useful things, swapping limbs for other limbs, etc.
if the surgery is intended to be MultiLoc but should only be performable once per limb, add this
"surgery.invalid_locations += user.zone_sel.selecting"
Just after you have swapped limbs around, see limb augmentation for an example of this

*/

//This file is commented out as to avoid:
// a snowflakey removal of it 100% of the time
// it's an example, it doesn't work perfectly due to just being the multiple locations section.
// It is also not set to compile, due to being Empty (according to the compiler)

//Enjoy making Multi-location operations! (if you understood my Rambling)
//If you didn't understand this, Ask for RobRichards in Coderbus


code:
/////AUGMENTATION\\\\\
//See code/modules/surgery/organs/organ.dm for the parent "limb"

/obj/item/organ/limb/robot
	name = "cyberlimb"
	desc = "You should never be seeing this!"
	status = ORGAN_ROBOTIC

/obj/item/organ/limb/robot/chest
	name = "chest"
	desc = "A Robotic chest"
	icon_state = "chest"
	max_damage = 200
	body_part = CHEST

/obj/item/organ/limb/robot/head
	name = "head"
	desc = "A Robotic head"
	icon_state = "head"
	max_damage = 200
	body_part = HEAD

/obj/item/organ/limb/robot/l_arm
	name = "l_arm"
	desc = "A Robotic arm"
	icon_state = "l_arm"
	max_damage = 75
	body_part = ARM_LEFT

/obj/item/organ/limb/robot/l_leg
	name = "l_leg"
	desc = "A Robotic leg"
	icon_state = "l_leg"
	max_damage = 75
	body_part = LEG_LEFT

/obj/item/organ/limb/robot/r_arm
	name = "r_arm"
	desc = "A Robotic arm"
	icon_state = "r_arm"
	max_damage = 75
	body_part = ARM_RIGHT

/obj/item/organ/limb/robot/r_leg
	name = "r_leg"
	desc = "A Robotic leg"
	icon_state = "r_leg"
	max_damage = 75
	body_part = LEG_RIGHT


code:
#define STUN_SET_AMOUNT	2

/obj/item/cybernetic_implant
	name = "cybernetic implant"
	desc = "a state-of-the-art implant that improves a baseline's functionality"
	icon = 'icons/obj/surgery.dmi'
	var/mob/living/carbon/owner = null
	var/implant_color = "#FFFFFF"

/obj/item/cybernetic_implant/New(var/mob/M = null)
	owner = M
	return ..()

/obj/item/cybernetic_implant/proc/function()
	return

//[[[[EYES]]]]

/obj/item/cybernetic_implant/eyes
	name = "cybernetic eyes"
	desc = "artificial photoreceptors with specialized functionality"
	icon_state = "eye_implant"
	var/eye_color = "fff"
	var/flash_protect = 0

/obj/item/cybernetic_implant/eyes/New()
	var/icon/overlay = new /icon('icons/obj/surgery.dmi',"eye_implant_overlay")
	overlay.ColorTone(implant_color)
	overlays |= overlay
	..()

/obj/item/cybernetic_implant/eyes/proc/update_eye_color(fluff_message)
	if(istype(owner,/mob/living/carbon/human))
		var/mob/living/carbon/human/HMN = owner
		HMN.eye_color = eye_color
		HMN.regenerate_icons()
	if(fluff_message)
		owner << "[fluff_message]"

/obj/item/cybernetic_implant/eyes/hud/medical
	name = "Medical HUD implant"
	desc = "These cybernetic eyes will display a medical HUD over everything you see. Wiggle eyes to control."
	eye_color = "0ff"
	implant_color = "#00FFFF"
	origin_tech = "materials=4;programming=3;biotech=4"

/obj/item/cybernetic_implant/eyes/hud/medical/function()
	if(!owner)
		return

	var/datum/atom_hud/H = huds[DATA_HUD_MEDICAL_ADVANCED]
	H.add_hud_to(owner)
	owner.permanent_huds |= H
	update_eye_color("You suddenly see health bars floating above people's heads...")

/obj/item/cybernetic_implant/eyes/hud/security
	name = "Security HUD implant"
	desc = "These cybernetic eyes will display a security HUD over everything you see. Wiggle eyes to control."
	eye_color = "d00"
	implant_color = "#CC0000"
	origin_tech = "materials=4;programming=4;biotech=3;combat=1"

/obj/item/cybernetic_implant/eyes/hud/security/function()
	if(!owner)
		return

	var/datum/atom_hud/H = huds[DATA_HUD_SECURITY_ADVANCED]
	H.add_hud_to(owner)
	owner.permanent_huds |= H
	update_eye_color("Job indicator icons pop up in your vision. That is not a certified surgeon...")

/obj/item/cybernetic_implant/eyes/xray
	name = "X-ray implant"
	desc = "These cybernetic eyes will give you X-ray vision. Blinking is futile."
	eye_color = "000"
	implant_color = "#000000"
	origin_tech = "materials=6;programming=4;biotech=5;magnets=5;plasmatech=2"

/obj/item/cybernetic_implant/eyes/xray/function()
	if(!owner)
		return

	owner.sight |= SEE_MOBS
	owner.sight |= SEE_OBJS
	owner.sight |= SEE_TURFS
	owner.permanent_sight_flags |= SEE_MOBS
	owner.permanent_sight_flags |= SEE_OBJS
	owner.permanent_sight_flags |= SEE_TURFS
	update_eye_color("Your vision is augmented!")

/obj/item/cybernetic_implant/eyes/thermals
	name = "Thermals implant"
	desc = "These cybernetic eyes will give you Thermal vision. Vertical slit pupil included."
	eye_color = "FC0"
	implant_color = "#FFCC00"
	flash_protect = -1
	origin_tech = "materials=6;programming=4;biotech=5;magnets=5;plasmatech=2;syndicate=4"

/obj/item/cybernetic_implant/eyes/thermals/function()
	if(!owner)
		return

	owner.sight |= SEE_MOBS
	owner.permanent_sight_flags |= SEE_MOBS
	update_eye_color("You see prey everywhere you look...")

/obj/item/cybernetic_implant/eyes/emp_act(severity)
	if(!istype(owner))
		return
	if(!owner)
		return
	if(severity > 1)
		if(prob(5))
			return
	var/save_sight = owner.sight
	owner.sight &= 0
	owner.disabilities |= BLIND
	owner << "Static obfuscates your vision!"
	spawn(50)
	owner.sight |= save_sight
	owner.disabilities ^= BLIND

//[[[[BRAIN]]]]

/obj/item/cybernetic_implant/brain
	name = "cybernetic brain implant"
	desc = "injectors of extra sub-routines for the brain"
	icon_state = "brain_implant"

/obj/item/cybernetic_implant/brain/New()
	var/icon/overlay = new /icon('icons/obj/surgery.dmi',"brain_implant_overlay")
	overlay.ColorTone(implant_color)
	overlays |= overlay
	..()

/obj/item/cybernetic_implant/brain/emp_act(severity)
	if(!owner)
		return
	if(!istype(owner))
		return
	var/stun_amount = 5 + (severity-1 ? 0 : 5)
	owner.Stun(stun_amount)
	owner << "Your body seizes up!"
	return stun_amount

/obj/item/cybernetic_implant/brain/anti_drop
	name = "Anti-drop implant"
	desc = "This cybernetic brain implant will allow you to force your hand muscles to contract, preventing item dropping. Twitch ear to toggle."
	var/active = 0
	var/l_hand_ignore = 0
	var/r_hand_ignore = 0
	var/obj/item/l_hand_obj = null
	var/obj/item/r_hand_obj = null
	implant_color = "#DE7E00"
	origin_tech = "materials=5;programming=4;biotech=4"

/obj/item/cybernetic_implant/brain/anti_drop/function()
	action_button_name = "Toggle Anti-Drop"

/obj/item/cybernetic_implant/brain/anti_drop/ui_action_click()
	active = !active
	if(active)
		l_hand_obj = owner.l_hand
		r_hand_obj = owner.r_hand
		if(l_hand_obj)
			if(owner.l_hand.flags & NODROP)
				l_hand_ignore = 1
			else
				owner.l_hand.flags |= NODROP
				l_hand_ignore = 0

		if(r_hand_obj)
			if(owner.r_hand.flags & NODROP)
				r_hand_ignore = 1
			else
				owner.r_hand.flags |= NODROP
				r_hand_ignore = 0

		if(!l_hand_obj && !r_hand_obj)
			owner << "You are not holding any items, your hands relax..."
			active = 0
		else
			var/msg = 0
			msg += !l_hand_ignore && l_hand_obj ? 1 : 0
			msg += !r_hand_ignore && r_hand_obj ? 2 : 0
			switch(msg)
				if(1)
					owner << "Your left hand's grip tightens."
				if(2)
					owner << "Your right hand's grip tightens."
				if(3)
					owner << "Both of your hand's grips tighten."
	else
		release_items()
		owner << "Your hands relax..."
		l_hand_obj = null
		r_hand_obj = null

/obj/item/cybernetic_implant/brain/anti_drop/emp_act(severity)
	if(!owner)
		return
	var/range = severity ? 10 : 5
	var/atom/A
	var/obj/item/L_item = owner.l_hand
	var/obj/item/R_item = owner.r_hand

	release_items()
	..()
	if(L_item)
		A = pick(oview(range))
		L_item.throw_at(A, range, 2)
		owner << "Your left arm spasms and throws the [L_item.name]!"
	if(R_item)
		A = pick(oview(range))
		R_item.throw_at(A, range, 2)
		owner << "Your right arm spasms and throws the [R_item.name]!"

/obj/item/cybernetic_implant/brain/anti_drop/proc/release_items()
	if(!l_hand_ignore && l_hand_obj in owner.contents)
		l_hand_obj.flags ^= NODROP
	if(!r_hand_ignore && r_hand_obj in owner.contents)
		r_hand_obj.flags ^= NODROP

/obj/item/cybernetic_implant/brain/anti_stun
	name = "CNS Rebooter implant"
	desc = "This implant will automatically give you back control over your central nervous system, reducing downtime when stunned."
	implant_color = "#FFFF00"
	origin_tech = "materials=6;programming=4;biotech=5"

/obj/item/cybernetic_implant/brain/anti_stun/function()
	SSobj.processing |= src

/obj/item/cybernetic_implant/brain/anti_stun/process()
	if(!owner)
		SSobj.processing.Remove(src)
		qdel(src)
		return
	if(owner.stat == DEAD)
		return

	if(owner.stunned > STUN_SET_AMOUNT)
		owner.stunned = STUN_SET_AMOUNT
	if(owner.weakened > STUN_SET_AMOUNT)
		owner.weakened = STUN_SET_AMOUNT

/obj/item/cybernetic_implant/brain/anti_stun/emp_act(severity)
	if(!owner)
		return
	if(!istype(owner))
		return
	SSobj.processing.Remove(src)
	spawn(..() * 10)
		SSobj.processing |= src

//[[[[CHEST]]]]

/obj/item/cybernetic_implant/chest
	name = "cybernetic torso implant"
	desc = "implants for the organs in your torso"
	icon_state = "chest_implant"

/obj/item/cybernetic_implant/chest/New()
	var/icon/overlay = new /icon('icons/obj/surgery.dmi',"chest_implant_overlay")
	overlay.ColorTone(implant_color)
	overlays |= overlay
	..()

/obj/item/cybernetic_implant/chest/nutriment
	name = "Nutriment pump implant"
	desc = "This implant with synthesize and pump into your bloodstream a small amount of nutriment when you are starving."
	icon_state = "chest_implant"
	implant_color = "#00AA00"
	var/hunger_threshold = NUTRITION_LEVEL_STARVING
	var/synthesizing = 0
	var/nutriment_amount = 30
	var/poison_amount = 5
	origin_tech = "materials=5;programming=3;biotech=4"

/obj/item/cybernetic_implant/chest/nutriment/function()
	SSobj.processing |= src

/obj/item/cybernetic_implant/chest/nutriment/process()
	if(synthesizing)
		return
	if(!owner)
		SSobj.processing.Remove(src)
		qdel(src)
		return
	if(owner.stat == DEAD)
		return

	if(owner.nutrition <= hunger_threshold)
		synthesizing = 1
		spawn(50)
			owner << "You feel less hungry..."
			owner.nutrition += nutriment_amount
			synthesizing = 0

/obj/item/cybernetic_implant/chest/nutriment/plus
	name = "Nutriment pump implant PLUS"
	desc = "This implant with synthesize and pump into your bloodstream a small amount of nutriment when you are hungry."
	icon_state = "chest_implant"
	implant_color = "#006607"
	hunger_threshold = NUTRITION_LEVEL_HUNGRY
	nutriment_amount = 50
	poison_amount = 10
	origin_tech = "materials=5;programming=3;biotech=5"

/obj/item/cybernetic_implant/chest/nutriment/emp_act(severity)
	if(!owner)
		return
	if(!istype(owner))
		return
	owner.reagents.add_reagent("????",poison_amount / severity) //food poisoning
	owner << "You feel like your insides are burning."

/obj/item/cybernetic_implant/chest/heart/reviver
	name = "Reviver implant"
	desc = "This implant will automatically deliver a therapeutic dose of electrical energy to your heart if it ever stops beating, and inject nanites into your bloodstream. A second chance!"
	icon_state = "chest_implant"
	implant_color = "#AD0000"
	var/defibrillating = 0
	var/recharge_time = 0
	origin_tech = "materials=7;programming=3;biotech=4"

/obj/item/cybernetic_implant/chest/heart/reviver/function()
	if(istype(owner,/mob/living/carbon/human))
		recharge_time = world.time + 2000
		SSobj.processing |= src

/obj/item/cybernetic_implant/chest/heart/reviver/process()
	if(defibrillating)
		return
	if(!owner)
		SSobj.processing.Remove(src)
		qdel(src)
		return
	if(world.time < recharge_time)
		return
	if(owner.stat != DEAD)
		return

	defibrillating = 1
	spawn(600)
		if(owner.stat == DEAD)
			owner.visible_message("[owner]'s body convulses by itself.")
			playsound(owner, "bodyfall", 50, 1)
			playsound(owner, 'sound/machines/defib_zap.ogg', 50, 1, -1)
			dead_mob_list -= owner
			living_mob_list |= list(owner)
			owner.stat = UNCONSCIOUS
			owner.reagents.add_reagent("nanites",10)
			var/mob/living/carbon/human/H = owner
			var/amount = BLOOD_VOLUME_OKAY - H.vessel.total_volume
			H.vessel.add_reagent("blood", amount)
			H.vessel.update_total()
			owner.emote("gasp")
			add_logs(owner, owner, "revived", object="defibrillator implant")
			recharge_time = world.time + 20000
		defibrillating = 0

/obj/item/cybernetic_implant/chest/heart/reviver/emp_act(severity)
	if(!owner)
		return
	if(recharge_time < world.time)
		recharge_time = world.time + (2000 / severity)
	else
		recharge_time += 2000 / severity

	if(prob(60/severity))
		playsound(owner, 'sound/machines/defib_saftyOff.ogg', 50, 1, -1)
		spawn(30)
			playsound(owner, 'sound/machines/defib_zap.ogg', 50, 1, -1)
			if(owner.stat == CONSCIOUS)
				owner.Weaken(5)
				owner.visible_message("[owner] clutches at their chest as if their heart stopped!")


code:
mob/proc/getorgan()
	return
mob/living/carbon/getorgan(typepath)
	return (locate(typepath) in internal_organs)

mob/proc/getlimb()
	return

mob/living/carbon/human/getlimb(typepath)
	return (locate(typepath) in organs)


code:
/obj/item/organ
	name = "organ"
	icon = 'icons/obj/surgery.dmi'

/obj/item/organ/heart
	name = "heart"
	icon_state = "heart-on"
	var/beating = 1

/obj/item/organ/heart/update_icon()
	if(beating)
		icon_state = "heart-on"
	else
		icon_state = "heart-off"

/obj/item/organ/appendix
	name = "appendix"
	icon_state = "appendix"
	var/inflamed = 1

/obj/item/organ/appendix/update_icon()
	if(inflamed)
		icon_state = "appendixinflamed"
	else
		icon_state = "appendix"

//Looking for brains?
//Try code/modules/mob/living/carbon/brain/brain_item.dm

//Old Datum Limbs:
// code/modules/unused/limbs.dm

/obj/item/organ/limb
	name = "limb"
	var/mob/owner = null
	var/body_part = null
	var/brutestate = 0
	var/burnstate = 0
	var/brute_dam = 0
	var/burn_dam = 0
	var/max_damage = 0
	var/status = ORGAN_ORGANIC
	var/list/embedded_objects = list()

/obj/item/organ/limb/chest
	name = "chest"
	desc = "why is it detached..."
	icon_state = "chest"
	max_damage = 200
	body_part = CHEST

/obj/item/organ/limb/head
	name = "head"
	desc = "what a way to get a head in life..."
	icon_state = "head"
	max_damage = 200
	body_part = HEAD

/obj/item/organ/limb/l_arm
	name = "l_arm"
	desc = "why is it detached..."
	icon_state = "l_arm"
	max_damage = 75
	body_part = ARM_LEFT

/obj/item/organ/limb/l_leg
	name = "l_leg"
	desc = "why is it detached..."
	icon_state = "l_leg"
	max_damage = 75
	body_part = LEG_LEFT

/obj/item/organ/limb/r_arm
	name = "r_arm"
	desc = "why is it detached..."
	icon_state = "r_arm"
	max_damage = 75
	body_part = ARM_RIGHT

/obj/item/organ/limb/r_leg
	name = "r_leg"
	desc = "why is it detached..."
	icon_state = "r_leg"
	max_damage = 75
	body_part = LEG_RIGHT

//Applies brute and burn damage to the organ. Returns 1 if the damage-icon states changed at all.
//Damage will not exceed max_damage using this proc
//Cannot apply negative damage
/obj/item/organ/limb/proc/take_damage(brute, burn)
	if(owner && (owner.status_flags & GODMODE))	return 0	//godmode
	brute	= max(brute,0)
	burn	= max(burn,0)

	if(status == ORGAN_ROBOTIC) //This makes robolimbs not damageable by chems and makes it stronger
		brute = max(0, brute - 5)
		burn = max(0, burn - 4)

	var/can_inflict = max_damage - (brute_dam + burn_dam)
	if(!can_inflict)	return 0

	if((brute + burn) < can_inflict)
		brute_dam	+= brute
		burn_dam	+= burn
	else
		if(brute > 0)
			if(burn > 0)
				brute	= round( (brute/(brute+burn)) * can_inflict, 1 )
				burn	= can_inflict - brute	//gets whatever damage is left over
				brute_dam	+= brute
				burn_dam	+= burn
			else
				brute_dam	+= can_inflict
		else
			if(burn > 0)
				burn_dam	+= can_inflict
			else
				return 0
	return update_organ_icon()

//Heals brute and burn damage for the organ. Returns 1 if the damage-icon states changed at all.
//Damage cannot go below zero.
//Cannot remove negative damage (i.e. apply damage)
/obj/item/organ/limb/proc/heal_damage(brute, burn, var/robotic)

	if(robotic && status != ORGAN_ROBOTIC) // This makes organic limbs not heal when the proc is in Robotic mode.
		brute = max(0, brute - 3)
		burn = max(0, burn - 3)

	if(!robotic && status == ORGAN_ROBOTIC) // This makes robolimbs not healable by chems.
		brute = max(0, brute - 3)
		burn = max(0, burn - 3)

	brute_dam	= max(brute_dam - brute, 0)
	burn_dam	= max(burn_dam - burn, 0)
	return update_organ_icon()

//Returns total damage...kinda pointless really
/obj/item/organ/limb/proc/get_damage()
	return brute_dam + burn_dam

//Updates an organ's brute/burn states for use by update_damage_overlays()
//Returns 1 if we need to update overlays. 0 otherwise.
/obj/item/organ/limb/proc/update_organ_icon()
	if(status == ORGAN_ORGANIC) //Robotic limbs show no damage - RR
		var/tbrute	= round( (brute_dam/max_damage)*3, 1 )
		var/tburn	= round( (burn_dam/max_damage)*3, 1 )
		if((tbrute != brutestate) || (tburn != burnstate))
			brutestate = tbrute
			burnstate = tburn
			return 1
		return 0

//Returns a display name for the organ
/obj/item/organ/limb/proc/getDisplayName() //Added "Chest" and "Head" just in case, this may not be needed
	switch(name)
		if("l_leg")		return "left leg"
		if("r_leg")		return "right leg"
		if("l_arm")		return "left arm"
		if("r_arm")		return "right arm"
		if("chest")     return "chest"
		if("head")		return "head"
		else			return name

//Remove all embedded objects from all limbs on the human mob
/mob/living/carbon/human/proc/remove_all_embedded_objects()
	var/turf/T = get_turf(src)

	for(var/obj/item/organ/limb/L in organs)
		for(var/obj/item/I in L.embedded_objects)
			L.embedded_objects -= I
			I.loc = T


code:
/datum/surgery/plastic_surgery
	name = "plastic surgery"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/reshape_face, /datum/surgery_step/close)
	species = list(/mob/living/carbon/human)
	location = "head"

//reshape_face
/datum/surgery_step/reshape_face
	implements = list(/obj/item/weapon/scalpel = 100, /obj/item/weapon/kitchenknife = 50, /obj/item/weapon/wirecutters = 35)
	time = 64

/datum/surgery_step/reshape_face/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to alter [target]'s appearance.")

/datum/surgery_step/reshape_face/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(target.status_flags & DISFIGURED)
		target.status_flags &= ~DISFIGURED
		user.visible_message("[user] successfully restores [target]'s appearance!")
	else
		var/oldname = target.real_name
		target.real_name = random_name(target.gender)
		var/newname = target.real_name	//something about how the code handles names required that I use this instead of target.real_name
		user.visible_message("[user] alters [oldname]'s appearance completely, they are now [newname]!")
	return 1


code:
/datum/surgery/embedded_removal
	name = "removal of embedded objects"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/remove_object)
	species = list(/mob/living/carbon/human)
	location = "anywhere"
	has_multi_loc = 1

/datum/surgery_step/remove_object
	time = 32
	allowed_organs = list("r_arm","l_arm","r_leg","l_leg","chest","head")
	accept_hand = 1
	var/obj/item/organ/limb/L = null

/datum/surgery_step/remove_object/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	L = new_organ
	if(L)
		user.visible_message("[user] looks for objects embedded in [target]'s [parse_zone(user.zone_sel.selecting)].")
	else
		user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_sel.selecting)].")

/datum/surgery_step/remove_object/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(L)
		if(ishuman(target))
			var/mob/living/carbon/human/H = target
			var/objects = 0
			for(var/obj/item/I in L.embedded_objects)
				objects++
				I.loc = get_turf(H)
				L.embedded_objects -= I

			if(objects > 0)
				user.visible_message("[user] sucessfully removes [objects] objects from [H]'s [L.getDisplayName()]!")
			else
				user.visible_message("[user] finds no objects embedded in [H]'s [L.getDisplayName()].")

	else
		user.visible_message("[user] can't find [target]'s [parse_zone(user.zone_sel.selecting)], let alone any objects embedded in it!")

	return 1


code:
/datum/surgery
	var/name = null
	var/status = 1
	var/list/steps = list()										//Steps in a surgery
	var/step_in_progress = 0									//Actively performing a Surgery
	var/list/species = list(/mob/living/carbon/human)			//Acceptable Species
	var/location = "chest"										//Surgery location
	var/target_must_be_dead = 0									//Needs to be dead
	var/target_must_be_fat = 0									//Needs to be fat
	var/requires_organic_chest = 0								//Prevents you from performing an operation on Robotic chests***
	var/has_multi_loc = 0 										//Multiple locations - RR
	var/user_species_restricted = 0 							//Surgery only performable BY species
	var/list/user_species_ids
	var/ignore_clothes = 0

/datum/surgery/proc/next_step(mob/user, mob/living/carbon/target)
	if(step_in_progress)	return

	var/datum/surgery_step/S = get_surgery_step()
	if(S)
		if(S.try_op(user, target, user.zone_sel.selecting, user.get_active_hand(), src))
			return 1
	return 0

/datum/surgery/proc/get_surgery_step()
	var/step_type = steps[status]
	return new step_type

/datum/surgery/proc/complete(mob/living/carbon/human/target)
	target.surgeries -= src
	src = null

/datum/surgery/proc/cancel(var/mob/user, var/mob/living/carbon/human/target)
	if(src.can_cancel())
		target.surgeries -= src
		user << "You cancel the [src]."
		src = null

	else
		user << "You can't cancel the [src]." //Maybe add a explaination that the procedure has already started?

/datum/surgery/proc/can_cancel() //Can be overriden on specific surgeries so you could cancel them at a later step (like augging etc,)
	if(status < 2) //If the procedure hasn't been started
		return 1
	return 0

//INFO
//Check /mob/living/carbon/attackby for how surgery progresses, and also /mob/living/carbon/attack_hand.
//As of Feb 21 2013 they are in code/modules/mob/living/carbon/carbon.dm, lines 459 and 51 respectively.
//Other important variables are var/list/surgeries (/mob/living) and var/list/internal_organs (/mob/living/carbon)
// var/list/organs (/mob/living/carbon/human) is the LIMBS of a Mob.
//Surgical procedures are initiated by attempt_initiate_surgery(), which is called by surgical drapes and bedsheets.
// /code/modules/surgery/multiple_location_example.dm contains steps to setup a multiple location operation.

//TODO
//specific steps for some surgeries (fluff text)
//R&D researching new surgeries (especially for non-humans)
//more interesting failure options
//randomised complications
//more surgeries!
//add a probability modifier for the state of the surgeon- health, twitching, etc. blindness, god forbid.
//helper for converting a zone_sel.selecting to body part (for damage)

//RESOLVED ISSUES //"Todo" jobs that have been completed
//combine hands/feet into the arms - Hands/feet were removed - RR
//surgeries (not steps) that can be initiated on any body part (corresponding with damage locations) - Call this one done, see multiple_location_example.dm - RR

//*** This may seem entirely redundant because of Organic organs only having operations but you CAN circumvent that due to
//all surgeries (except augmentation) not checking where the surgeon aims so this is just a double check, it IS needed - RR


code:
/datum/surgery_step
	var/list/implements = list()	//format is path = probability of success. alternatively
	var/implement_type = null		//the current type of implement used. This has to be stored, as the actual typepath of the tool may not match the list type.
	var/accept_hand = 0				//does the surgery step require an open hand? If true, ignores implements. Compatible with accept_any_item.
	var/accept_any_item = 0			//does the surgery step accept any item? If true, ignores implements. Compatible with require_hand.
	var/time = 10					//how long does the step take?
	var/new_organ = null 			//Used for multilocation operations
	var/list/allowed_organs = list()//Allowed organs, see Handle_Multi_Loc below - RR

/datum/surgery_step/proc/try_op(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	var/success = 0
	if(accept_hand)
		if(!tool)
			success = 1
	if(accept_any_item)
		if(tool && tool_check(user, tool))
			success = 1
	else
		for(var/path in implements)
			if(istype(tool, path))
				implement_type = path
				if(tool_check(user, tool))
					success = 1

	if(success)
		if(target_zone == surgery.location)
			if(get_location_accessible(target, target_zone) || surgery.ignore_clothes)
				initiate(user, target, target_zone, tool, surgery)
				return 1
			else
				user << "You need to expose [target]'s [parse_zone(target_zone)] to perform surgery on it!"
				return 1	//returns 1 so we don't stab the guy in the dick or wherever.
	if(isrobot(user) && user.a_intent != "harm") //to save asimov borgs a LOT of heartache
		return 1
	return 0

/datum/surgery_step/proc/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	surgery.step_in_progress = 1

	if(surgery.has_multi_loc) //if it is multi-location, handle that
		Handle_Multi_Loc(user, target)

	preop(user, target, target_zone, tool)
	if(do_after(user, time))

		var/advance = 0
		var/prob_chance = 100

		if(implement_type)	//this means it isn't a require hand or any item step.
			prob_chance = implements[implement_type]
		prob_chance *= get_location_modifier(target)

		if(prob(prob_chance) || isrobot(user))
			if(success(user, target, target_zone, tool, surgery))
				advance = 1
		else
			if(failure(user, target, target_zone, tool, surgery))
				advance = 1

		if(advance)
			surgery.status++
			if(surgery.status > surgery.steps.len)
				surgery.complete(target)

	surgery.step_in_progress = 0

/datum/surgery_step/proc/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to perform surgery on [target].")

/datum/surgery_step/proc/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] succeeds!")
	return 1

/datum/surgery_step/saw/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(ishuman(target))
		var/mob/living/carbon/human/H = target
		H.apply_damage(75,"brute","[target_zone]")
		user.visible_message("[user] saws [target]'s [parse_zone(target_zone)] open!")
	return 1

/datum/surgery_step/proc/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] screws up!")
	return 0

/datum/surgery_step/close/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(locate(/datum/surgery_step/saw) in surgery.steps)
		var/limb_type
		switch(target_zone)
			if("head")
				limb_type = /obj/item/organ/limb/head
			if("chest")
				limb_type = /obj/item/organ/limb/chest
			if("l_arm")
				limb_type = /obj/item/organ/limb/l_arm
			if("r_arm")
				limb_type = /obj/item/organ/limb/r_arm
			if("l_leg")
				limb_type = /obj/item/organ/limb/l_leg
			if("r_leg")
				limb_type = /obj/item/organ/limb/r_leg
			else
				return ..()
		var/obj/item/organ/limb/limb = target.getlimb(limb_type)
		if(limb)
			limb.heal_damage(45,0,0)

	return ..()

/datum/surgery_step/proc/tool_check(mob/user, obj/item/tool)
	return 1

/datum/surgery_step/proc/Handle_Multi_Loc(mob/user, mob/living/carbon/target) //this is here so MultiLoc Surgeries don't need to rewrite it each time - RR

	if(user.zone_sel.selecting in allowed_organs)

		switch(user.zone_sel.selecting) //Switch, for Aran - RR
			if("r_arm")
				new_organ = target.getlimb(/obj/item/organ/limb/r_arm)
			if("l_arm")
				new_organ = target.getlimb(/obj/item/organ/limb/l_arm)
			if("r_leg")
				new_organ = target.getlimb(/obj/item/organ/limb/r_leg)
			if("l_leg")
				new_organ = target.getlimb(/obj/item/organ/limb/l_leg)
			if("chest")
				new_organ = target.getlimb(/obj/item/organ/limb/chest)
			if("groin")
				new_organ = target.getlimb(/obj/item/organ/limb/chest)
			if("head")
				new_organ = target.getlimb(/obj/item/organ/limb/head)
			if("eyes")
				new_organ = target.getlimb(/obj/item/organ/limb/head)
			if("mouth")
				new_organ = target.getlimb(/obj/item/organ/limb/head)
			else
				user << "You cannot perform this operation on this body part!" //Explain to the surgeon what went wrong - RR
				return 0

		return new_organ

	else
		return 0


code:
/obj/item/weapon/retractor
	name = "retractor"
	desc = "Retracts stuff."
	icon = 'icons/obj/surgery.dmi'
	icon_state = "retractor"
	m_amt = 6000
	g_amt = 3000
	flags = CONDUCT
	w_class = 1.0
	origin_tech = "materials=1;biotech=1"

/obj/item/weapon/hemostat
	name = "hemostat"
	desc = "You think you have seen this before."
	icon = 'icons/obj/surgery.dmi'
	icon_state = "hemostat"
	m_amt = 5000
	g_amt = 2500
	flags = CONDUCT
	w_class = 1.0
	origin_tech = "materials=1;biotech=1"
	attack_verb = list("attacked", "pinched")

/obj/item/weapon/cautery
	name = "cautery"
	desc = "This stops bleeding."
	icon = 'icons/obj/surgery.dmi'
	icon_state = "cautery"
	m_amt = 2500
	g_amt = 750
	flags = CONDUCT
	w_class = 1.0
	origin_tech = "materials=1;biotech=1"
	attack_verb = list("burnt")

/obj/item/weapon/surgicaldrill
	name = "surgical drill"
	desc = "You can drill using this item. You dig?"
	icon = 'icons/obj/surgery.dmi'
	icon_state = "drill"
	hitsound = 'sound/weapons/circsawhit.ogg'
	m_amt = 10000
	g_amt = 6000
	flags = CONDUCT
	force = 15.0
	w_class = 3.0
	origin_tech = "materials=1;biotech=1"
	attack_verb = list("drilled")

/obj/item/weapon/scalpel
	name = "scalpel"
	desc = "Cut, cut, and once more cut."
	icon = 'icons/obj/surgery.dmi'
	icon_state = "scalpel"
	flags = CONDUCT
	force = 10.0
	w_class = 1.0
	throwforce = 5.0
	throw_speed = 3
	throw_range = 5
	m_amt = 4000
	g_amt = 1000
	origin_tech = "materials=1;biotech=1"
	attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
	hitsound = 'sound/weapons/bladeslice.ogg'

/obj/item/weapon/scalpel/suicide_act(mob/user)
	user.visible_message(pick("[user] is slitting \his wrists with [src]! It looks like \he's trying to commit suicide.", \
						"[user] is slitting \his throat with [src]! It looks like \he's trying to commit suicide.", \
						"[user] is slitting \his stomach open with [src]! It looks like \he's trying to commit seppuku."))
	return (BRUTELOSS)

/obj/item/weapon/circular_saw
	name = "circular saw"
	desc = "For heavy duty cutting."
	icon = 'icons/obj/surgery.dmi'
	icon_state = "saw"
	hitsound = 'sound/weapons/circsawhit.ogg'
	throwhitsound =  'sound/weapons/pierce.ogg'
	flags = CONDUCT
	force = 15.0
	w_class = 3.0
	throwforce = 9.0
	throw_speed = 2
	throw_range = 5
	m_amt = 10000
	g_amt = 6000
	origin_tech = "materials=1;biotech=1"
	attack_verb = list("attacked", "slashed", "sawed", "cut")

/obj/item/weapon/surgical_drapes
	name = "surgical drapes"
	desc = "Nanotrasen brand surgical drapes provide optimal safety and infection control."
	icon = 'icons/obj/surgery.dmi'
	icon_state = "surgical_drapes"
	w_class = 1.0
	origin_tech = "biotech=1"
	attack_verb = list("slapped")

/obj/item/weapon/surgical_drapes/attack(mob/living/M, mob/user)
	if(!attempt_initiate_surgery(src, M, user))
		..()


code:
/datum/surgery/xenomorph_removal
	name = "xenomorph removal"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/xenomorph_removal, /datum/surgery_step/close)
	species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
	location = "chest"
	requires_organic_chest = 1

//remove xeno from premises
/datum/surgery_step/xenomorph_removal
	implements = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/shovel/spade = 65, /obj/item/weapon/minihoe = 50, /obj/item/weapon/crowbar = 35)
	time = 64

/datum/surgery_step/xenomorph_removal/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to search in [target]'s chest for a xenomorph embryo.", "You begin to search in [target]'s chest for a xenomorph embryo...")

/datum/surgery_step/xenomorph_removal/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(remove_xeno(user, target))
		user.visible_message("[user] successfully extracts the xenomorph embryo from [target]!", "You successfully extract the xenomorph embryo from [target].")
	else
		user.visible_message("[user] can't seem to find anything in [target]'s chest!", "You can't find anything in [target]'s chest!")
	return 1

/datum/surgery_step/xenomorph_removal/proc/remove_xeno(mob/user, mob/living/carbon/target)
	var/obj/item/body_egg/alien_embryo/A = locate() in target.contents
	if(A)
		user << "You found an unknown alien organism in [target]'s chest!"
		if(A.stage < 4)
			user << "It's small and weak, barely the size of a foetus."
		else
			user << "It's grown quite large, and writhes slightly as you look at it."
			if(prob(10))
				A.AttemptGrow()

		A.loc = get_turf(target)
		return 1

/datum/surgery_step/xenomorph_removal/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	var/obj/item/body_egg/alien_embryo/A = locate() in target.contents
	if(A)
		if(prob(50))
			A.AttemptGrow(0)
		user.visible_message("[user] accidentally pokes the xenomorph in [target]!", "You accidentally poke the xenomorph in [target]!")
	else
		target.adjustOxyLoss(30)
		user.visible_message("[user] accidentally pokes [target] in the lungs!", "You accidentally poke [target] in the lungs!")
	return 0

/datum/surgery/borer_removal
	name = "cortical borer removal"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/borer_removal, /datum/surgery_step/close)
	species = list(/mob/living/carbon/human, /mob/living/carbon/monkey, /mob/living/carbon/alien)
	location = "head"

//remove slug from premises
/datum/surgery_step/borer_removal
	implements = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/shovel/spade = 65, /obj/item/weapon/minihoe = 50, /obj/item/weapon/crowbar = 35) //Same shit as ayybortion
	time = 64

/datum/surgery_step/borer_removal/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to search in [target]'s head for a borer.")

/datum/surgery_step/borer_removal/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(remove_borer(user, target))
		user.visible_message("[user] successfully extracts the borer from [target]!")
	else
		user.visible_message("[user] can't find anything in [target]'s head!")
	return 1

/datum/surgery_step/borer_removal/proc/remove_borer(mob/user, mob/living/carbon/target)
	var/mob/living/simple_animal/borer/B = locate() in target.contents
	if(B)
		user << "You found an unknown alien organism in [target]'s brain!"

		if(B.controlling)
			target.release_control()
		B.detach()
		return 1

/datum/surgery_step/borer_removal/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	var/mob/living/simple_animal/borer/B = locate() in target.contents
	if(B)
		user.visible_message("[user] accidentally pokes the borer in [target]!")
	else
		target.adjustBrainLoss(30)
		user.visible_message("[user] accidentally pokes [target] in the brain!")
	return 0


code:
// Bluespace crystals, used in telescience and when crushed it will blink you to a random turf.

/obj/item/bluespace_crystal
	name = "bluespace crystal"
	desc = "A glowing bluespace crystal, not much is known about how they work. It looks very delicate."
	icon = 'icons/obj/telescience.dmi'
	icon_state = "bluespace_crystal"
	w_class = 1
	origin_tech = "bluespace=4;materials=3"
	var/blink_range = 8 // The teleport range when crushed/thrown at someone.

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

/obj/item/bluespace_crystal/attack_self(var/mob/user)
	user.visible_message("[user] crushes [src]!")
	new /obj/effect/effect/sparks(src.loc)
	playsound(src.loc, "sparks", 50, 1)
	blink_mob(user)
	user.drop_item()
	qdel(src)

/obj/item/bluespace_crystal/proc/blink_mob(var/mob/living/L)
	do_teleport(L, get_turf(L), blink_range, asoundin = 'sound/effects/phasein.ogg')

/obj/item/bluespace_crystal/throw_impact(atom/hit_atom)
	..()
	visible_message("[src] fizzles and disappears upon impact!")
	new /obj/effect/effect/sparks(src.loc)
	playsound(src.loc, "sparks", 50, 1)
	if(isliving(hit_atom))
		blink_mob(hit_atom)
	qdel(src)

// Artifical bluespace crystal, doesn't give you much research.

/obj/item/bluespace_crystal/artificial
	name = "artificial bluespace crystal"
	desc = "An artificially made bluespace crystal, it looks delicate."
	origin_tech = "bluespace=2"
	blink_range = 4 // Not as good as the organic stuff!


code:
var/list/GPS_list = list()
var/list/SPS_list = list()

/obj/item/device/gps
	name = "global positioning system"
	desc = "Helping lost spacemen find their way through the planets since 2016."
	icon = 'icons/obj/telescience.dmi'
	icon_state = "gps-c"
	w_class = 2.0
	slot_flags = SLOT_BELT
	origin_tech = "programming=2;engineering=2"
	var/gpstag = "COM0"
	var/emped = 0
	var/turf/locked_location

/obj/item/device/gps/New()
	..()
	GPS_list.Add(src)
	name = "global positioning system ([gpstag])"
	overlays += "working"

/obj/item/device/gps/Destroy()
	if(istype(src,/obj/item/device/gps/secure))
		SPS_list.Remove(src)
	else
		GPS_list.Remove(src)
	..()

/obj/item/device/gps/emp_act(severity)
	emped = 1
	overlays -= "working"
	overlays += "emp"
	spawn(300)
		emped = 0
		overlays -= "emp"
		overlays += "working"

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

	var/obj/item/device/gps/t = ""
	var/list/locallist = null
	if(istype(src,/obj/item/device/gps/secure))
		locallist = SPS_list.Copy()
	else
		locallist = GPS_list.Copy()
	var/gps_window_height = 110 + locallist.len * 20 // Variable window height, depending on how many GPS units there are to show
	if(emped)
		t += "ERROR"
	else
		t += "
Set Tag "
		t += "
Tag: [gpstag]"
		if(locked_location && locked_location.loc)
			t += "
Bluespace coordinates saved: [locked_location.loc]"
			gps_window_height += 20

		for(var/obj/item/device/gps/G in locallist)
			var/turf/pos = get_turf(G)
			var/area/gps_area = get_area(G)
			var/tracked_gpstag = G.gpstag
			if(G.emped == 1)
				t += "
[tracked_gpstag]: ERROR"
			else
				t += "
[tracked_gpstag]: [format_text(gps_area.name)] ([pos.x], [pos.y], [pos.z])"

	var/datum/browser/popup = new(user, "GPS", name, 360, min(gps_window_height, 800))
	popup.set_content(t)
	popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
	popup.open()

/obj/item/device/gps/Topic(href, href_list)
	..()
	if(href_list["tag"] )
		var/a = input("Please enter desired tag.", name, gpstag) as text
		a = uppertext(copytext(sanitize(a), 1, 5))
		if(src.loc == usr)
			gpstag = a
			name = "global positioning system ([gpstag])"
			attack_self(usr)

/obj/item/device/gps/science
	icon_state = "gps-s"
	gpstag = "SCI0"

/obj/item/device/gps/engineering
	icon_state = "gps-e"
	gpstag = "ENG0"

/obj/item/device/gps/mining
	icon_state = "gps-m"
	gpstag = "MINE0"
	desc = "A positioning system helpful for rescuing trapped or injured miners, keeping one on you at all times while mining might just save your life."

/obj/item/device/gps/secure
	name = "secure positioning system"
	desc = "A secure channel SPS with several features designed to keep its wearer safe."
	icon_state = "sps"
	gpstag = "SEC0"

/obj/item/device/gps/secure/New()
	SPS_list.Add(src)
	gpstag = "SEC0"
	name = "secure positioning system ([gpstag])"
	overlays += "working"

/obj/item/device/gps/secure/OnMobDeath(mob/holder)
	var/obj/item/device/gps/secure/S
	for(S in SPS_list)
		S.announce(holder, src, "died")
	..(holder)

/obj/item/device/gps/secure/dropped(mob/wearer as mob)
	..()
	spawn (1) //Race conditions
		if(istype(src.loc, /turf))
			for(var/obj/item/device/gps/secure/S in SPS_list)
				S.announce(wearer, src, "lost [wearer.gender == FEMALE ? "her" : "his"] SPS")
		else
			return

/obj/item/device/gps/secure/proc/announce(var/mob/wearer, var/obj/item/SPS, var/reason)
	var/mob/holder = src.loc
	if(holder)
		holder << "Your SPS beeps: Warning! [wearer] has [reason] at [get_area(SPS)]."


code:
///SCI TELEPAD///
/obj/machinery/telepad
	name = "telepad"
	desc = "A bluespace telepad used for teleporting objects to and from a location."
	icon = 'icons/obj/telescience.dmi'
	icon_state = "pad-idle"
	anchored = 1
	use_power = 1
	idle_power_usage = 200
	active_power_usage = 5000
	var/efficiency

/obj/machinery/telepad/New()
	..()
	component_parts = list()
	component_parts += new /obj/item/weapon/circuitboard/telesci_pad(null)
	component_parts += new /obj/item/bluespace_crystal/artificial(null)
	component_parts += new /obj/item/bluespace_crystal/artificial(null)
	component_parts += new /obj/item/weapon/stock_parts/capacitor(null)
	component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
	component_parts += new /obj/item/stack/cable_coil(null, 1)
	RefreshParts()

/obj/machinery/telepad/RefreshParts()
	var/E
	for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts)
		E += C.rating
	efficiency = E

/obj/machinery/telepad/attackby(obj/item/I, mob/user, params)
	if(default_deconstruction_screwdriver(user, "pad-idle-o", "pad-idle", I))
		return

	if(panel_open)
		if(istype(I, /obj/item/device/multitool))
			var/obj/item/device/multitool/M = I
			M.buffer = src
			user << "You save the data in the [I.name]'s buffer."

	if(exchange_parts(user, I))
		return

	default_deconstruction_crowbar(I)

//CARGO TELEPAD//
/obj/machinery/telepad_cargo
	name = "cargo telepad"
	desc = "A telepad used by the Rapid Crate Sender."
	icon = 'icons/obj/telescience.dmi'
	icon_state = "pad-idle"
	anchored = 1
	use_power = 1
	idle_power_usage = 20
	active_power_usage = 500
	var/stage = 0
/obj/machinery/telepad_cargo/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
	if(istype(W, /obj/item/weapon/wrench))
		anchored = 0
		playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
		if(anchored)
			anchored = 0
			user << " \The [src] can now be moved."
		else if(!anchored)
			anchored = 1
			user << " \The [src] is now secured."
	if(istype(W, /obj/item/weapon/screwdriver))
		if(stage == 0)
			playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
			user << " You unscrew the telepad's tracking beacon."
			stage = 1
		else if(stage == 1)
			playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
			user << " You screw in the telepad's tracking beacon."
			stage = 0
	if(istype(W, /obj/item/weapon/weldingtool) && stage == 1)
		playsound(src, 'sound/items/Welder.ogg', 50, 1)
		user << " You disassemble the telepad."
		new /obj/item/stack/sheet/metal(get_turf(src))
		new /obj/item/stack/sheet/glass(get_turf(src))
		qdel(src)

///TELEPAD CALLER///
/obj/item/device/telepad_beacon
	name = "telepad beacon"
	desc = "Use to warp in a cargo telepad."
	icon = 'icons/obj/radio.dmi'
	icon_state = "beacon"
	item_state = "signaler"
	origin_tech = "bluespace=3"

/obj/item/device/telepad_beacon/attack_self(mob/user as mob)
	if(user)
		user << " Locked In"
		new /obj/machinery/telepad_cargo(user.loc)
		playsound(src, 'sound/effects/pop.ogg', 100, 1, 1)
		qdel(src)
	return

///HANDHELD TELEPAD USER///
/obj/item/weapon/rcs
	name = "rapid-crate-sender (RCS)"
	desc = "Use this to send crates and closets to cargo telepads."
	icon = 'icons/obj/telescience.dmi'
	icon_state = "rcs"
	flags = CONDUCT
	force = 10.0
	throwforce = 10.0
	throw_speed = 2
	throw_range = 5
	var/rcharges = 10
	var/obj/machinery/pad = null
	var/last_charge = 30
	var/mode = 0
	var/rand_x = 0
	var/rand_y = 0
	var/emagged = 0
	var/teleporting = 0

/obj/item/weapon/rcs/New()
	..()
	SSobj.processing |= src

/obj/item/weapon/rcs/examine(mob/user)
	..()
	user << "There are [rcharges] charge\s left."

/obj/item/weapon/rcs/Destroy()
	SSobj.processing.Remove(src)
	..()
/obj/item/weapon/rcs/process()
	if(rcharges > 10)
		rcharges = 10
	if(last_charge == 0)
		rcharges++
		last_charge = 30
	else
		last_charge--

/obj/item/weapon/rcs/attack_self(mob/user)
	if(emagged)
		if(mode == 0)
			mode = 1
			playsound(src.loc, 'sound/effects/pop.ogg', 50, 0)
			user << " The telepad locator has become uncalibrated."
		else
			mode = 0
			playsound(src.loc, 'sound/effects/pop.ogg', 50, 0)
			user << " You calibrate the telepad locator."

/obj/item/weapon/rcs/emag_act(mob/user as mob)
	if(!emagged)
		emagged = 1
		var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
		s.set_up(5, 1, src)
		s.start()
		user << " You emag the RCS. Click on it to toggle between modes."


code:
/obj/machinery/computer/telescience
	name = "\improper Telepad Control Console"
	desc = "Used to teleport objects to and from the telescience telepad."
	icon_state = "teleport"
	circuit = /obj/item/weapon/circuitboard/telesci_console
	var/sending = 1
	var/obj/machinery/telepad/telepad = null
	var/temp_msg = "Telescience control console initialized.
Welcome."

	// VARIABLES //
	var/teles_left	// How many teleports left until it becomes uncalibrated
	var/datum/projectile_data/last_tele_data = null
	var/z_co = 1
	var/power_off
	var/rotation_off
	//var/angle_off
	var/last_target

	var/rotation = 0
	var/angle = 45
	var/power = 5

	// Based on the power used
	var/teleport_cooldown = 0 // every index requires a bluespace crystal
	var/list/power_options = list(5, 10, 20, 25, 30, 40, 50, 80, 100)
	var/teleporting = 0
	var/starting_crystals = 3
	var/max_crystals = 4
	var/list/crystals = list()
	var/obj/item/device/gps/inserted_gps

/obj/machinery/computer/telescience/New()
	..()
	recalibrate()

/obj/machinery/computer/telescience/Destroy()
	eject()
	if(inserted_gps)
		inserted_gps.loc = loc
		inserted_gps = null
	..()

/obj/machinery/computer/telescience/examine(mob/user)
	..()
	user << "There are [crystals.len ? crystals.len : "no"] bluespace crystal\s in the crystal slots."

/obj/machinery/computer/telescience/initialize()
	..()
	for(var/i = 1; i <= starting_crystals; i++)
		crystals += new /obj/item/bluespace_crystal/artificial(null) // starting crystals

/obj/machinery/computer/telescience/attack_paw(mob/user)
	user << "You are too primitive to use this computer."
	return

/obj/machinery/computer/telescience/attackby(obj/item/W, mob/user, params)
	if(istype(W, /obj/item/bluespace_crystal))
		if(crystals.len >= max_crystals)
			user << "There are not enough crystal slots."
			return
		user.drop_item()
		crystals += W
		W.loc = null
		user.visible_message("[user] inserts [W] into \the [src]'s crystal slot.")
		updateDialog()
	else if(istype(W, /obj/item/device/gps))
		if(!inserted_gps)
			inserted_gps = W
			user.unEquip(W)
			W.loc = src
			user.visible_message("[user] inserts [W] into \the [src]'s GPS device slot.")
	else if(istype(W, /obj/item/device/multitool))
		var/obj/item/device/multitool/M = W
		if(M.buffer && istype(M.buffer, /obj/machinery/telepad))
			telepad = M.buffer
			M.buffer = null
			user << "You upload the data from the [W.name]'s buffer."
	else
		..()

/obj/machinery/computer/telescience/attack_ai(mob/user)
	src.attack_hand(user)

/obj/machinery/computer/telescience/attack_hand(mob/user)
	if(..())
		return
	interact(user)

/obj/machinery/computer/telescience/interact(mob/user)
	var/t
	if(!telepad)
		in_use = 0     //Yeah so if you deconstruct teleporter while its in the process of shooting it wont disable the console
		t += "
No telepad located.
Please add telepad data.

"
	else
		if(inserted_gps)
			t += "Eject GPS"
			t += "Set GPS memory"
		else
			t += "Eject GPS"
			t += "Set GPS memory"
		t += "
[temp_msg]

"
		t += "Set Bearing"
		t += "
[rotation]�
"
		t += "Set Elevation"
		t += "
[angle]�
"
		t += "Set Power"
		t += "
"

		for(var/i = 1; i <= power_options.len; i++)
			if(crystals.len + telepad.efficiency  < i)
				t += "[power_options[i]]"
				continue
			if(power == power_options[i])
				t += "[power_options[i]]"
				continue
			t += "[power_options[i]]"
		t += "
"

		t += "Set Sector"
		t += "
[z_co ? z_co : "NULL"]
"

		t += "
Send"
		t += " Receive"
		t += "
Recalibrate Crystals Eject Crystals"

		// Information about the last teleport
		t += "

"
		if(!last_tele_data)
			t += "No teleport data found."
		else
			t += "Source Location: ([last_tele_data.src_x], [last_tele_data.src_y])
"
			//t += "Distance: [round(last_tele_data.distance, 0.1)]m
"
			t += "Time: [round(last_tele_data.time, 0.1)] secs
"
		t += "
"

	var/datum/browser/popup = new(user, "telesci", name, 300, 500)
	popup.set_content(t)
	popup.open()
	return

/obj/machinery/computer/telescience/proc/sparks()
	if(telepad)
		var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
		s.set_up(5, 1, get_turf(telepad))
		s.start()
	else
		return

/obj/machinery/computer/telescience/proc/telefail()
	sparks()
	visible_message("The telepad weakly fizzles.")
	return

/obj/machinery/computer/telescience/proc/doteleport(mob/user)

	if(teleport_cooldown > world.time)
		temp_msg = "Telepad is recharging power.
Please wait [round((teleport_cooldown - world.time) / 10)] seconds."
		return

	if(teleporting)
		temp_msg = "Telepad is in use.
Please wait."
		return

	if(telepad)

		var/truePower = Clamp(power + power_off, 1, 1000)
		var/trueRotation = rotation + rotation_off
		var/trueAngle = Clamp(angle, 1, 90)

		var/datum/projectile_data/proj_data = projectile_trajectory(telepad.x, telepad.y, trueRotation, trueAngle, truePower)
		last_tele_data = proj_data

		var/trueX = Clamp(round(proj_data.dest_x, 1), 1, world.maxx)
		var/trueY = Clamp(round(proj_data.dest_y, 1), 1, world.maxy)
		var/spawn_time = round(proj_data.time) * 10

		var/turf/target = locate(trueX, trueY, z_co)
		last_target = target
		var/area/A = get_area(target)
		flick("pad-beam", telepad)

		if(spawn_time > 15) // 1.5 seconds
			playsound(telepad.loc, 'sound/weapons/flash.ogg', 25, 1)
			// Wait depending on the time the projectile took to get there
			teleporting = 1
			temp_msg = "Powering up bluespace crystals.
Please wait."

		spawn(round(proj_data.time) * 10) // in seconds
			if(!telepad)
				return
			if(telepad.stat & NOPOWER)
				return
			teleporting = 0
			teleport_cooldown = world.time + (power * 2)
			teles_left -= 1

			// use a lot of power
			use_power(power * 10)

			var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
			s.set_up(5, 1, get_turf(telepad))
			s.start()

			temp_msg = "Teleport successful.
"
			if(teles_left < 10)
				temp_msg += "
Calibration required soon."
			else
				temp_msg += "Data printed below."

			var/sparks = get_turf(target)
			var/datum/effect/effect/system/spark_spread/y = new /datum/effect/effect/system/spark_spread
			y.set_up(5, 1, sparks)
			y.start()

			var/turf/source = target
			var/turf/dest = get_turf(telepad)
			var/log_msg = ""
			log_msg += ": [key_name(user)] has teleported "

			if(sending)
				source = dest
				dest = target

			flick("pad-beam", telepad)
			playsound(telepad.loc, 'sound/weapons/emitter2.ogg', 25, 1, extrarange = 3, falloff = 5)
			for(var/atom/movable/ROI in source)
				// if is anchored, don't let through
				if(ROI.anchored)
					if(isliving(ROI))
						var/mob/living/L = ROI
						if(L.buckled)
							// TP people on office chairs
							if(L.buckled.anchored)
								continue

							log_msg += "[key_name(L)] (on a chair), "
						else
							continue
					else if(!isobserver(ROI))
						continue
				if(ismob(ROI))
					var/mob/T = ROI
					log_msg += "[key_name(T)], "
				else
					log_msg += "[ROI.name]"
					if (istype(ROI, /obj/structure/closet))
						var/obj/structure/closet/C = ROI
						log_msg += " ("
						for(var/atom/movable/Q as mob|obj in C)
							if(ismob(Q))
								log_msg += "[key_name(Q)], "
							else
								log_msg += "[Q.name], "
						if (dd_hassuffix(log_msg, "("))
							log_msg += "empty)"
						else
							log_msg = dd_limittext(log_msg, length(log_msg) - 2)
							log_msg += ")"
					log_msg += ", "
				do_teleport(ROI, dest)

			if (dd_hassuffix(log_msg, ", "))
				log_msg = dd_limittext(log_msg, length(log_msg) - 2)
			else
				log_msg += "nothing"
			log_msg += " [sending ? "to" : "from"] [trueX], [trueY], [z_co] ([A ? A.name : "null area"])"
			investigate_log(log_msg, "telesci")
			updateDialog()

/obj/machinery/computer/telescience/proc/teleport(mob/user)
	if(rotation == null || angle == null || z_co == null)
		temp_msg = "ERROR!
Set a angle, rotation and sector."
		return
	if(power <= 0)
		telefail()
		temp_msg = "ERROR!
No power selected!"
		return
	if(angle < 1 || angle > 90)
		telefail()
		temp_msg = "ERROR!
Elevation is less than 1 or greater than 90."
		return
	if(z_co == 2 || z_co < 1 || z_co > 7)
		telefail()
		temp_msg = "ERROR! Sector is less than 1,
greater than 7, or equal to 2."
		return
	if(teles_left > 0)
		doteleport(user)
	else
		telefail()
		temp_msg = "ERROR!
Calibration required."
		return
	return

/obj/machinery/computer/telescience/proc/eject()
	for(var/obj/item/I in crystals)
		I.loc = src.loc
		crystals -= I
	power = 0

/obj/machinery/computer/telescience/Topic(href, href_list)
	if(..())
		return
	if(!telepad)
		updateDialog()
		return
	if(telepad.panel_open)
		temp_msg = "Telepad undergoing physical maintenance operations."

	if(href_list["setrotation"])
		var/new_rot = input("Please input desired bearing in degrees.", name, rotation) as num
		if(..()) // Check after we input a value, as they could've moved after they entered something
			return
		rotation = Clamp(new_rot, -900, 900)
		rotation = round(rotation, 0.01)

	if(href_list["setangle"])
		var/new_angle = input("Please input desired elevation in degrees.", name, angle) as num
		if(..())
			return
		angle = Clamp(round(new_angle, 0.1), 1, 9999)

	if(href_list["setpower"])
		var/index = href_list["setpower"]
		index = text2num(index)
		if(index != null && power_options[index])
			if(crystals.len + telepad.efficiency >= index)
				power = power_options[index]

	if(href_list["setz"])
		var/new_z = input("Please input desired sector.", name, z_co) as num
		if(..())
			return
		z_co = Clamp(round(new_z), 1, 10)

	if(href_list["ejectGPS"])
		if(inserted_gps)
			inserted_gps.loc = loc
			inserted_gps = null

	if(href_list["setMemory"])
		if(last_target && inserted_gps)
			inserted_gps.locked_location = last_target
			temp_msg = "Location saved."
		else
			temp_msg = "ERROR!
No data was stored."

	if(href_list["send"])
		sending = 1
		teleport(usr)

	if(href_list["receive"])
		sending = 0
		teleport(usr)

	if(href_list["recal"])
		recalibrate()
		sparks()
		temp_msg = "NOTICE:
Calibration successful."

	if(href_list["eject"])
		eject()
		temp_msg = "NOTICE:
Bluespace crystals ejected."

	updateDialog()

/obj/machinery/computer/telescience/proc/recalibrate()
	teles_left = rand(30, 40)
	//angle_off = rand(-25, 25)
	power_off = rand(-4, 0)
	rotation_off = rand(-10, 10)


code:
/world
	mob = /mob/new_player
	turf = /turf/space
	area = /area/space
	view = "15x15"
	cache_lifespan = 7

/world/New()
	map_ready = 1

#if (PRELOAD_RSC == 0)
	external_rsc_urls = file2list("config/external_rsc_urls.txt","\n")
	var/i=1
	while(i<=external_rsc_urls.len)
		if(external_rsc_urls[i])
			i++
		else
			external_rsc_urls.Cut(i,i+1)
#endif
	//logs
	var/date_string = time2text(world.realtime, "YYYY/MM-Month/DD-Day")
//	if(revdata && istext(revdata.revision) && length(revdata.revision)>7)
//		log = file("data/logs/runtime/[copytext(revdata.revision,1,8)].log")
//	else
//		log = file("data/logs/runtime/[time2text(world.realtime,"YYYY-MM")].log")		//funtimelog
	href_logfile = file("data/logs/[date_string] hrefs.htm")
	diary = file("data/logs/[date_string].log")
	diaryofmeanpeople = file("data/logs/[date_string] Attack.log")
	diary << "\n\nStarting up. [time2text(world.timeofday, "hh:mm.ss")]\n---------------------"
	diaryofmeanpeople << "\n\nStarting up. [time2text(world.timeofday, "hh:mm.ss")]\n---------------------"
	changelog_hash = md5('html/changelog.html')					//used for telling if the changelog has changed recently

	make_datum_references_lists()	//initialises global lists for referencing frequently used datums (so that we only ever do it once)

	load_configuration()
	load_mode()
	load_motd()
	load_admins()
	LoadBansjob()
	if(config.usewhitelist)
		load_whitelist()
	jobban_loadbanfile()
	appearance_loadbanfile()
	jobban_updatelegacybans()
	LoadBans()
	investigate_reset()

	if(config && config.server_name != null && config.server_suffix && world.port > 0)
		// dumb and hardcoded but I don't care~
		config.server_name += " #[(world.port % 1000) / 100]"

	timezoneOffset = text2num(time2text(0,"hh")) * 36000

	if(config.sql_enabled)
		if(!setup_database_connection())
			world.log << "Your server failed to establish a connection with the database."
		else
			world.log << "Database connection established."

	data_core = new /datum/datacore()

	spawn(-1)
		master_controller.setup()

	process_teleport_locs()			//Sets up the wizard teleport locations
	process_ghost_teleport_locs()	//Sets up ghost teleport locations.
	SortAreas()						//Build the list of all existing areas and sort it alphabetically

	#ifdef MAP_NAME
	map_name = "[MAP_NAME]"
	#else
	map_name = "Unknown"
	#endif

	return

/world/Topic(T, addr, master, key)
	diary << "TOPIC: \"[T]\", from:[addr], master:[master], key:[key]"

	if (T == "ping")
		var/x = 1
		for (var/client/C in clients)
			x++
		return x

	else if(T == "players")
		var/n = 0
		for(var/mob/M in player_list)
			if(M.client)
				n++
		return n

	else if (T == "status")
		var/list/s = list()
		// Please add new status indexes under the old ones, for the server banner (until that gets reworked)
		s["version"] = game_version
		s["mode"] = master_mode
		s["respawn"] = config ? abandon_allowed : 0
		s["enter"] = enter_allowed
		s["vote"] = config.allow_vote_mode
		s["ai"] = config.allow_ai
		s["host"] = host ? host : null

		var/admins = 0
		for(var/client/C in clients)
			if(C.holder)
				if(C.holder.fakekey)
					continue	//so stealthmins aren't revealed by the hub
				admins++

		s["active_players"] = get_active_player_count()
		s["players"] = clients.len
		s["revision"] = revdata.revision
		s["revision_date"] = revdata.date
		s["admins"] = admins
		s["gamestate"] = 1
		if(ticker)
			s["gamestate"] = ticker.current_state
		s["map_name"] = map_name ? map_name : "Unknown"

		return list2params(s)
	else if (copytext(T,1,9) == "announce")
		var/input[] = params2list(T)
		if(global.comms_allowed)
			if(input["key"] != global.comms_key)
				return "Bad Key"
			else
#define CHAT_PULLR	64 //for some reason this has to be here, not sure why. Look in preferences.dm for the "proper" definition.
				for(var/client/C in clients)
					if(C.prefs && (C.prefs.chat_toggles & CHAT_PULLR))
						C << "PR: [input["announce"]]"
#undef CHAT_PULLR

/world/Reboot(var/reason, var/feedback_c, var/feedback_r, var/time)
	var/delay

	if(time)
		delay = time
	else
		delay = ticker.restart_timeout
	if(ticker.delay_end)
		world << "An admin has delayed the round end."
		return
	world << "Rebooting World in [delay/10] [delay > 10 ? "seconds" : "second"]. [reason]"
	sleep(delay)
	if(blackbox)
		blackbox.save_all_data_to_sql()
	if(ticker.delay_end)
		world << "Reboot was cancelled by an admin."
		return
	feedback_set_details("[feedback_c]","[feedback_r]")
	log_game("Rebooting World. [reason]")
	kick_clients_in_lobby("The round came to an end with you in the lobby.", 1) //second parameter ensures only afk clients are kicked
#ifdef dellogging
	var/log = file("data/logs/del.log")
	log << time2text(world.realtime)
	//mergeSort(del_counter, /proc/cmp_descending_associative)	//still testing the sorting procs. Use notepad++ to sort the resultant logfile for now.
	for(var/index in del_counter)
		var/count = del_counter[index]
		if(count > 10)
			log << "#[count]\t[index]"
#endif
	spawn(0)
		world << sound(pick('sound/AI/newroundsexy.ogg','sound/misc/apcdestroyed.ogg','sound/misc/bangindonk.ogg','sound/misc/leavingtg.ogg')) // random end sounds!! - LastyBatsy

	for(var/client/C in clients)
		if(config.server)	//if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite
			C << link("byond://[config.server]")

	// Note: all clients automatically connect to the world after it restarts

	..(0)

/world/proc/load_mode()
	var/list/Lines = file2list("data/mode.txt")
	if(Lines.len)
		if(Lines[1])
			master_mode = Lines[1]
			diary << "Saved mode is '[master_mode]'"

/world/proc/save_mode(var/the_mode)
	var/F = file("data/mode.txt")
	fdel(F)
	F << the_mode

/world/proc/load_motd()
	join_motd = file2text("config/motd.txt")

/world/proc/load_configuration()
	config = new /datum/configuration()
	config.load("config/config.txt")
	config.load("config/game_options.txt","game_options")
	config.loadsql("config/dbconfig.txt")
	// apply some settings from config..
	abandon_allowed = config.respawn

/world/proc/update_status()
	var/s = ""

	if (config && config.server_name)
		s += "[config.server_name] — "

	s += "[station_name()]";
	s += " ("
	s += "" //Change this to wherever you want the hub to link to.
//	s += "[game_version]"
	s += "Default"  //Replace this with something else. Or ever better, delete it and uncomment the game version.
	s += ""
	s += ")"

	var/list/features = list()

	if(ticker)
		if(master_mode)
			features += master_mode
	else
		features += "STARTING"

	if (!enter_allowed)
		features += "closed"

	features += abandon_allowed ? "respawn" : "no respawn"

	if (config && config.allow_vote_mode)
		features += "vote"

	if (config && config.allow_ai)
		features += "AI allowed"

	var/n = 0
	for (var/mob/M in player_list)
		if (M.client)
			n++

	if (n > 1)
		features += "~[n] players"
	else if (n > 0)
		features += "~[n] player"

	/*
	is there a reason for this? the byond site shows 'hosted by X' when there is a proper host already.
	if (host)
		features += "hosted by [host]"
	*/

	if (!host && config && config.hostedby)
		features += "hosted by [config.hostedby]"

	if (features)
		s += ": [list2text(features, ", ")]"

	/* does this help? I do not know */
	if (src.status != s)
		src.status = s

#define FAILED_DB_CONNECTION_CUTOFF 5
var/failed_db_connections = 0

proc/setup_database_connection()

	if(failed_db_connections >= FAILED_DB_CONNECTION_CUTOFF)	//If it failed to establish a connection more than 5 times in a row, don't bother attempting to connect anymore.
		return 0

	if(!dbcon)
		dbcon = new()

	var/user = sqlfdbklogin
	var/pass = sqlfdbkpass
	var/db = sqlfdbkdb
	var/address = sqladdress
	var/port = sqlport

	dbcon.Connect("dbi:mysql:[db]:[address]:[port]","[user]","[pass]")
	. = dbcon.IsConnected()
	if ( . )
		failed_db_connections = 0	//If this connection succeeded, reset the failed connections counter.
	else
		failed_db_connections++		//If it failed, increase the failed connections counter.
		if(config.sql_enabled)
			world.log << "SQL error: " + dbcon.ErrorMsg()

	return .

//This proc ensures that the connection to the feedback database (global variable dbcon) is established
proc/establish_db_connection()
	if(failed_db_connections > FAILED_DB_CONNECTION_CUTOFF)
		return 0

	if(!dbcon || !dbcon.IsConnected())
		return setup_database_connection()
	else
		return 1

#undef FAILED_DB_CONNECTION_CUTOFF


code:
HOW TO CONVERT A MAP TO THE NEW (june 2008) ACCESS LEVEL SYSTEM
1. Open the .dmp file up in Notepad
2. Find all the "access = blahblah" attributes of doors.
3. Delete them.
4. Open the map up in Dream Maker. If you didn't get them all, it'll tell you so.
5. Assign the existing doors new access permissions using the method below.

HOW TO MAKE A MAP USING THE NEW (june 2008) ACCESS LEVEL SYSTEM
1. Make a map as normal
2. Select a door that you want to not be accessible to everybody
3. Right click on it and edit its attributes
4. Make the "req_access_txt" attribute be a semicolon-separated list of the permissions required to open the doors
5. Repeat for all doors.

For example, a brig door would have it be "2" while a door that requires you have toxins and teleporter access (for whatever reason) would have it be "9;20"

Here is a list of the permissions and their numbers (this may be out of date, see code/game/access.dm for an updated version):

	access_security = 1
	access_brig = 2
	access_security_lockers = 3
	access_forensics_lockers= 4
	access_security_records = 5
	access_medical_supplies = 6
	access_medical_records = 7
	access_morgue = 8
	access_tox = 9
	access_tox_storage = 10
	access_medlab = 11
	access_engine = 12
	access_eject_engine = 13
	access_maint_tunnels = 14
	access_external_airlocks = 15
	access_emergency_storage = 16
	access_apcs = 17
	access_change_ids = 18
	access_ai_upload = 19
	access_teleporter = 20
	access_eva = 21
	access_heads = 22
	access_captain = 23
	access_all_personal_lockers = 24
	access_chapel_office = 25
	access_tech_storage = 26
	access_atmospherics = 27
	access_bar = 28
	access_janitor = 29
	access_disposal_units = 30
	access_hydroponics = 35
	access_manufacturing = 36

path: config/access levels.txt


code:
##############################################################################################################
# ADMIN RANK DEFINES                                                                                #
# The format of this is very simple. Rank name goes first.                                                   #
# Rank is CASE-SENSITIVE, all punctuation save for '-', '_' and '@' will be stripped so spaces don't matter. #
# You can then define permissions for each rank by adding a '=' followed by keywords                         #
# These keywords represent groups of verbs and abilities.                                                    #
# keywords are preceded by either a '+' or a '-', + adds permissions, - takes them away.                     #
# +@ (or +prev) is a special shorthand which adds all the rights of the rank above it.                       #
# You can also specify verbs like so +/client/proc/some_added_verb or -/client/proc/some_restricted_verb     #
# Ranks with no keywords will just be given the most basic verbs and abilities                ~Carn          #
##############################################################################################################
# PLEASE NOTE: depending on config options, some abilities will be unavailable regardless if you have permission to use them!

# KEYWORDS:
# +ADMIN = general admin tools, verbs etc
# +FUN = events, other event-orientated actions. Access to the fun secrets in the secrets panel.
# +BAN = the ability to ban, jobban and fullban
# +STEALTH = the ability to stealthmin (make yourself appear with a fake name to everyone but other admins
# +POSSESS = the ability to possess objects
# +REJUV (or +REJUVINATE) = the ability to heal, respawn, modify damage and use godmode
# +BUILD (or +BUILDMODE) = the ability to use buildmode
# +SERVER = higher-risk admin verbs and abilities, such as those which affect the server configuration.
# +DEBUG = debug tools used for diagnosing and fixing problems. It's useful to give this to coders so they can investigate problems on a live server.
# +VAREDIT = everyone may view viewvars/debugvars/whatever you call it. This keyword allows you to actually EDIT those variables.
# +RIGHTS (or +PERMISSIONS) = allows you to promote and/or demote people.
# +SOUND (or +SOUNDS) = allows you to upload and play sounds
# +SPAWN (or +CREATE) = mob transformations, spawning of most atoms including mobs (high-risk atoms, e.g. blackholes, will require the +FUN flag too)
# +EVERYTHING (or +HOST or +ALL) = Simply gives you everything without having to type every flag

Admin Observer
Moderator		= +ADMIN +BAN
Trial Admin		= +@ +REJUV +STEALTH +FUN +SOUNDS
Badmin			= +@ +VAREDIT +SPAWN
Retired Host		= +@
Super Badmin		= +@ +BUILDMODE +DEBUG +POSSESS +SERVER

Head Shitmin            = +EVERYTHING

Coder			= +ADMIN +DEBUG +VAREDIT +SERVER +SPAWN
Coder-Admin		= +@ +FUN +SOUNDS +BAN +REJUV +STEALTH

Host                    = +EVERYTHING


code:
## You gotta do what you gotta do. (For free.)

Kuranyll = Host
Riesen = Head Shitmin
Kwata X11 = Super Badmin
Misterstaub = Super Badmin
DimJim = Badmin
GreyTideStationWide = Badmin
Dopaper = Badmin
AlwaysbetonNanako = Badmin
Hextopia = Badmin
0ak = Badmin
Captain Chen = Trial Admin