code:
//Areas

/area/awaymission/caves/bmp_asteroid
	name = "\improper BMP Asteroid Level 1"
	icon_state = "awaycontent1"

/area/awaymission/caves/bmp_asteroid/level_two
	name = "\improper BMP Asteroid Level 2"
	icon_state = "awaycontent2"

/area/awaymission/caves/bmp_asteroid/level_three
	name = "\improper BMP Asteroid Level 3"
	icon_state = "awaycontent3"

/area/awaymission/caves/bmp_asteroid/level_four
	name = "\improper BMP Asteroid Level 4"
	icon_state = "awaycontent4"

/area/awaymission/caves/research
	name = "Research Outpost"
	icon_state = "awaycontent5"
	static_lighting = TRUE

/area/awaymission/caves/northblock //engineering, bridge (not really north but it doesnt really need its own APC)

/area/awaymission/caves/listeningpost
	name = "Listening Post"
	icon_state = "awaycontent6"
	requires_power = FALSE

//caves papers

/obj/item/paper/crumpled/awaymissions/caves/unsafe_area
	info = "WARNING

Majority of this area is considered 'unsafe' past this point. Theres an outpost directly south of here where you can get your bearing and travel further down if needed. Traveling in groups is HIGHLY advised, the shit out there can be extremely deadly if you're alone."

/obj/item/paper/fluff/awaymissions/caves/omega
	name = "Subject Omega Notes"
	info = "Testing Notes

Subject appears unresponsive to most interactions, refusing to move away from the corners or face any scientists. Subject appears to move between the two back corners every observation. A strange humming can be heard from inside the cell, appears to be originating from the subject itself, further testing is necessary to confirm or deny this."

/obj/item/paper/fluff/awaymissions/caves/magma
	info = " Mining is hell down here, you can feel the heat of the magma no matter how thick the suit is. Conditions are barely manageable as is, restless nights and horrid work conditions. The ore maybe rich down here, but we've already lost a few men to the faults shifting, god knows how much longer till it all just collapses down and consumes everyone with it."

/obj/item/paper/fluff/awaymissions/caves/work_notice
	name = "work notice"
	info = "Survival Info For Miners

The caves are an unforgiving place, the only thing you'll have to traverse is the supplies in your locker and your own wit. Travel in packs when mining and try to shut down the monster dens before they overwhelm you. The job is dangerous but the haul is good, so remember this information and hopefully we'll all go home alive."

/obj/item/paper/fluff/awaymissions/caves/shipment_notice
	name = "shipment notice"
	info = "We were supposed to get a shipment of these special laser rifles and a couple 'nades to help combat the wildlife down here, but it's been weeks since we last heard from the caravan carrying the shit down here. At this point we can only assume they fell victim to one of the monster nests or the dumbasses managed to trip into the lava. So much for that shipment, I guess."

/obj/item/paper/fluff/awaymissions/caves/safety_notice
	name = "safety notice"
	info = "Some of the miners have gone to laying some mine traps among the lower levels of the mine to keep the monsters at bay.  This probably isn't the smartest idea in a cavern like this but the boys seem to get a chuckle out of every distant blast they hear go off, so I guess it works "

/obj/item/paper/fluff/awaymissions/caves/shipment_receipt
	name = "Shipment Receipt"
	info = "CARAVAN SERVICES
Quality service since 2205

SHIPMENT CONTENTS:

4 scattershot rifles
6 grenades
1 laser rifle
1 blowup doll"

/obj/item/paper/fluff/awaymissions/caves/mech_notice
	name = "NOTICE!! paper"
	info = "NOTICE!!

Although you may seem indestructible in a mech, remember, THIS SHIT ISN'T LAVA PROOF!! The boys have already had to deal with loosing the last two to salvage because the dumbass thought he could just wade through the lower lakes like it was nothing. The fact he even managed to get back without being fused with what was left of the mech is a miracle in itself. They're built to be resistant against extreme heat, not heat PROOF!

Robotics Team"


code:
//centcomAway areas

/area/awaymission/centcom_away
	name = "XCC-P5831"
	icon_state = "away"
	requires_power = FALSE

/area/awaymission/centcom_away/general
	name = "XCC-P5831"
	ambientsounds = list('sound/ambience/ambigen3.ogg')

/area/awaymission/centcom_away/maint
	name = "XCC-P5831 Maintenance"
	icon_state = "away1"
	ambientsounds = list('sound/ambience/ambisin1.ogg')

/area/awaymission/centcom_away/thunderdome
	name = "XCC-P5831 Thunderdome"
	icon_state = "away2"
	ambientsounds = list('sound/ambience/ambisin2.ogg')

/area/awaymission/centcom_away/cafe
	name = "XCC-P5831 Kitchen Arena"
	icon_state = "away3"
	ambientsounds = list('sound/ambience/ambisin3.ogg')

/area/awaymission/centcom_away/courtroom
	name = "XCC-P5831 Courtroom"
	icon_state = "away4"
	ambientsounds = list('sound/ambience/ambisin4.ogg')

/area/awaymission/centcom_away/hangar
	name = "XCC-P5831 Hangars"
	icon_state = "away4"
	ambientsounds = list('sound/ambience/ambigen5.ogg')

//centcomAway items

/obj/item/paper/pamphlet/centcom/visitor_info
	name = "Visitor Info Pamphlet"
	info = " XCC-P5831 Visitor Information
\
	Greetings, visitor, to  XCC-P5831! As you may know, this outpost was once \
	used as Nanotrasen's CENTRAL COMMAND STATION, organizing and coordinating company \
	projects across the vastness of space.
\
	Since the completion of the much more efficient CC-A5831 on March 8, 2553, XCC-P5831 no longer \
	acts as NT's base of operations but still plays a very important role its corporate affairs; \
	serving as a supply and repair depot, as well as being host to its most important legal proceedings\
	and the thrilling pay-per-view broadcasts of PLASTEEL CHEF and THUNDERDOME LIVE.
 \
	We hope you enjoy your stay!"

/obj/item/paper/fluff/awaymissions/centcom/gateway_memo
	name = "Memo to XCC-P5831 QM"
	info = "From: XCC-P5831 Management Office
\
	To: Rolf Ingram, XCC-P5831 Quartermaster
\
	Hey, Rolf, once you pack that gateway into the ferry hangar, make absolutely sure \
	to deactivate it! As you may know, SS13 has recently got its network up and running, \
	which means that until we get this gate shipped off to the next colonization staging \
	area, they'll be able to hop straight in here if its hooked up on our end.
\
	Obviously, that's something I'd very much rather avoid. Our forensics and medical \
	teams never did figure out what happened that last time... and I can't wrap my head \
	around it myself. Why would a shuttle full of evacuees all snap and beat each other \
	to death the moment they reached safety?
\
	- D. Cereza"

repo_name: AnalWerewolf/sundown

license: mit


code:
//Challenge Areas

/area/awaymission/challenge/start
	name = "Where Am I?"
	icon_state = "away"

/area/awaymission/challenge/main
	name = "Danger Room"
	icon_state = "away1"
	requires_power = FALSE

/area/awaymission/challenge/end
	name = "Administration"
	icon_state = "away2"
	requires_power = FALSE

/obj/machinery/power/emitter/energycannon
	name = "Energy Cannon"
	desc = "A heavy duty industrial laser."
	icon = 'icons/obj/singularity.dmi'
	icon_state = "emitter_+a"
	base_icon_state = "emitter_+a"
	anchored = TRUE
	density = TRUE
	resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF

	use_power = NO_POWER_USE
	idle_power_usage = 0
	active_power_usage = 0

	active = TRUE
	locked = TRUE
	welded = TRUE

/obj/machinery/power/emitter/energycannon/RefreshParts()
	return


code:
/obj/structure/window/reinforced/fulltile/indestructable
	name = "robust window"
	flags_1 = PREVENT_CLICK_UNDER_1 | NODECONSTRUCT_1
	resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF

/obj/structure/grille/indestructable
	flags_1 = CONDUCT_1 | NODECONSTRUCT_1
	resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF

/obj/effect/spawner/structure/window/reinforced/indestructable
	spawn_list = list(/obj/structure/grille/indestructable, /obj/structure/window/reinforced/fulltile/indestructable)

/obj/structure/barricade/security/murderdome
	name = "respawnable barrier"
	desc = "A barrier. Provides cover in firefights."
	deploy_time = 0
	deploy_message = 0

/obj/structure/barricade/security/murderdome/make_debris()
	new /obj/effect/murderdome/dead_barricade(get_turf(src))

/obj/effect/murderdome/dead_barricade
	name = "dead barrier"
	desc = "It provided cover in fire fights. And now it's gone."
	icon = 'icons/obj/objects.dmi'
	icon_state = "barrier0"
	alpha = 100

/obj/effect/murderdome/dead_barricade/Initialize(mapload)
	. = ..()
	addtimer(CALLBACK(src, .proc/respawn), 3 MINUTES)

/obj/effect/murderdome/dead_barricade/proc/respawn()
	if(!QDELETED(src))
		new /obj/structure/barricade/security/murderdome(get_turf(src))
		qdel(src)


code:
//Research Base Areas//--

/area/awaymission/research
	name = "Research Outpost"
	icon_state = "away"
	static_lighting = TRUE

/area/awaymission/research/interior
	name = "Research Inside"
	requires_power = TRUE
	icon_state = "away2"

/area/awaymission/research/interior/cryo
	name = "Research Cryostasis Room"
	icon_state = "medbay"

/area/awaymission/research/interior/clonestorage
	name = "Research Clone Storage"
	icon_state = "cloning"

/area/awaymission/research/interior/genetics
	name = "Research Genetics Research"
	icon_state = "genetics"

/area/awaymission/research/interior/engineering
	name = "Research Engineering"
	icon_state = "engine"

/area/awaymission/research/interior/security
	name = "Research Security"
	icon_state = "security"

/area/awaymission/research/interior/secure
	name = "Research Secure Vault"

/area/awaymission/research/interior/maint
	name = "Research Maintenance"
	icon_state = "maintcentral"

/area/awaymission/research/interior/dorm
	name = "Research Dorms"
	icon_state = "Sleep"

/area/awaymission/research/interior/escapepods
	name = "Research Escape Wing"
	icon_state = "exit"

/area/awaymission/research/interior/gateway
	name = "Research Gateway"
	icon_state = "start"

/area/awaymission/research/interior/bathroom
	name = "Research Bathrooms"
	icon_state = "restrooms"

/area/awaymission/research/interior/medbay
	name = "Research Medbay"
	icon_state = "medbay"

/area/awaymission/research/exterior
	name = "Research Exterior"
	icon_state = "unknown"

//research papers

/obj/item/paper/crumpled/awaymissions/research/sensitive_info
	info = "Theres a lot of sensitive info on these disks, try and keep them secure! If these backup copies get into the wrong hands, god knows what they could do with the genetic research on these disk.."


code:
//Snow Valley Areas//--

/area/awaymission/snowdin
	name = "Snowdin"
	icon_state = "awaycontent1"
	requires_power = FALSE
	static_lighting = FALSE

/area/awaymission/snowdin/outside
	name = "Snowdin Tundra Plains"
	icon_state = "awaycontent25"

/area/awaymission/snowdin/post
	name = "Snowdin Outpost"
	icon_state = "awaycontent2"
	requires_power = TRUE
	static_lighting = TRUE

/area/awaymission/snowdin/post/medbay
	name = "Snowdin Outpost - Medbay"
	icon_state = "awaycontent3"

/area/awaymission/snowdin/post/secpost
	name = "Snowdin Outpost - Security Checkpoint"
	icon_state = "awaycontent4"

/area/awaymission/snowdin/post/hydro
	name = "Snowdin Outpost - Hydroponics"
	icon_state = "awaycontent5"

/area/awaymission/snowdin/post/messhall
	name = "Snowdin Outpost - Mess Hall"
	icon_state = "awaycontent6"

/area/awaymission/snowdin/post/gateway
	name = "Snowdin Outpost - Gateway"
	icon_state = "awaycontent7"

/area/awaymission/snowdin/post/dorm
	name = "Snowdin Outpost - Dorms"
	icon_state = "awaycontent8"

/area/awaymission/snowdin/post/kitchen
	name = "Snowdin Outpost - Kitchen"
	icon_state = "awaycontent9"

/area/awaymission/snowdin/post/engineering
	name = "Snowdin Outpost - Engineering"
	icon_state = "awaycontent10"

/area/awaymission/snowdin/post/custodials
	name = "Snowdin Outpost - Custodials"
	icon_state = "awaycontent11"

/area/awaymission/snowdin/post/research
	name = "Snowdin Outpost - Research Area"
	icon_state = "awaycontent12"

/area/awaymission/snowdin/post/garage
	name = "Snowdin Outpost - Garage"
	icon_state = "awaycontent13"

/area/awaymission/snowdin/post/minipost
	name = "Snowdin Outpost - Recon Post"
	icon_state = "awaycontent19"

/area/awaymission/snowdin/post/mining_main
	name = "Snowdin Outpost - Mining Post"
	icon_state = "awaycontent21"

/area/awaymission/snowdin/post/mining_main/mechbay
	name = "Snowdin Outpost - Mining Post Mechbay"
	icon_state = "awaycontent25"

/area/awaymission/snowdin/post/mining_main/robotics
	name = "Snowdin Outpost - Mining Post Robotics"
	icon_state = "awaycontent26"

/area/awaymission/snowdin/post/cavern1
	name = "Snowdin Outpost - Cavern Outpost 1"
	icon_state = "awaycontent27"

/area/awaymission/snowdin/post/cavern2
	name = "Snowdin Outpost - Cavern Outpost 2"
	icon_state = "awaycontent28"

/area/awaymission/snowdin/post/mining_dock
	name = "Snowdin Outpost - Underground Mine Post"
	icon_state = "awaycontent22"

/area/awaymission/snowdin/post/broken_shuttle
	name = "Snowdin Outpost - Broken Transit Shuttle"
	icon_state = "awaycontent20"
	requires_power = FALSE

/area/awaymission/snowdin/igloo
	name = "Snowdin Igloos"
	icon_state = "awaycontent14"
	static_lighting = TRUE

/area/awaymission/snowdin/cave
	name = "Snowdin Caves"
	icon_state = "awaycontent15"
	static_lighting = TRUE

/area/awaymission/snowdin/cave/cavern
	name = "Snowdin Depths"
	icon_state = "awaycontent23"

/area/awaymission/snowdin/cave/mountain
	name = "Snowdin Mountains"
	icon_state = "awaycontent24"

/area/awaymission/snowdin/base
	name = "Snowdin Main Base"
	icon_state = "awaycontent16"
	static_lighting = TRUE
	requires_power = TRUE

/area/awaymission/snowdin/dungeon1
	name = "Snowdin Depths"
	icon_state = "awaycontent17"
	static_lighting = TRUE

/area/awaymission/snowdin/sekret
	name = "Snowdin Operations"
	icon_state = "awaycontent18"
	static_lighting = TRUE
	requires_power = TRUE

/area/shuttle/snowdin/elevator1
	name = "Excavation Elevator"

/area/shuttle/snowdin/elevator2
	name = "Mining Elevator"

//shuttle console for elevators//

/obj/machinery/computer/shuttle/snowdin/mining
	name = "shuttle console"
	desc = "A shuttle control computer."
	icon_screen = "shuttle"
	icon_keyboard = "tech_key"
	light_color = LIGHT_COLOR_CYAN
	shuttleId = "snowdin_mining"
	possible_destinations = "snowdin_mining_top;snowdin_mining_down"

//liquid plasma!!!!!!//

/turf/open/floor/iron/dark/snowdin
	initial_gas_mix = FROZEN_ATMOS
	planetary_atmos = 1
	temperature = 180

/turf/open/lava/plasma
	name = "liquid plasma"
	desc = "A flowing stream of chilled liquid plasma. You probably shouldn't get in."
	icon_state = "liquidplasma"
	initial_gas_mix = "n2=82;plasma=24;TEMP=120"
	baseturfs = /turf/open/lava/plasma

	light_range = 3
	light_power = 0.75
	light_color = LIGHT_COLOR_PURPLE
	immunity_trait = TRAIT_SNOWSTORM_IMMUNE
	immunity_resistance_flags = FREEZE_PROOF

/turf/open/lava/plasma/attackby(obj/item/I, mob/user, params)
	var/obj/item/reagent_containers/glass/C = I
	if(C.reagents.total_volume >= C.volume)
		to_chat(user, span_danger("[C] is full."))
		return
	C.reagents.add_reagent(/datum/reagent/toxin/plasma, rand(5, 10))
	user.visible_message(span_notice("[user] scoops some plasma from the [src] with \the [C]."), span_notice("You scoop out some plasma from the [src] using \the [C]."))

/turf/open/lava/plasma/do_burn(atom/movable/burn_target, delta_time = 1)
	. = TRUE
	if(isobj(burn_target))
		return FALSE // Does nothing against objects. Old code.

	var/mob/living/burn_living = burn_target
	burn_living.adjustFireLoss(2)
	if(QDELETED(burn_living))
		return
	burn_living.adjust_fire_stacks(20) //dipping into a stream of plasma would probably make you more flammable than usual
	burn_living.adjust_bodytemperature(-rand(50,65)) //its cold, man
	if(!ishuman(burn_living) || DT_PROB(65, delta_time))
		return
	var/mob/living/carbon/human/burn_human = burn_living
	var/datum/species/burn_species = burn_human.dna.species
	if(istype(burn_species, /datum/species/plasmaman) || istype(burn_species, /datum/species/android) || istype(burn_species, /datum/species/synth)) //ignore plasmamen/robotic species
		return

	var/list/plasma_parts = list()//a list of the organic parts to be turned into plasma limbs
	var/list/robo_parts = list()//keep a reference of robotic parts so we know if we can turn them into a plasmaman
	for(var/obj/item/bodypart/burn_limb as anything in burn_human.bodyparts)
		if(burn_limb.status == BODYPART_ORGANIC && burn_limb.species_id != SPECIES_PLASMAMAN) //getting every organic, non-plasmaman limb (augments/androids are immune to this)
			plasma_parts += burn_limb
		if(burn_limb.status == BODYPART_ROBOTIC)
			robo_parts += burn_limb

	burn_human.adjustToxLoss(15)
	burn_human.adjustFireLoss(25)
	if(plasma_parts.len)
		var/obj/item/bodypart/burn_limb = pick(plasma_parts) //using the above-mentioned list to get a choice of limbs
		burn_human.emote("scream")
		ADD_TRAIT(burn_limb, TRAIT_PLASMABURNT, src)
		burn_human.update_body_parts()
		burn_human.visible_message(span_warning("[burn_human] screams in pain as [burn_human.p_their()] [burn_limb] melts down to the bone!"), \
			span_userdanger("You scream out in pain as your [burn_limb] melts down to the bone, leaving an eerie plasma-like glow where flesh used to be!"))
	if(!plasma_parts.len && !robo_parts.len) //a person with no potential organic limbs left AND no robotic limbs, time to turn them into a plasmaman
		burn_human.IgniteMob()
		burn_human.set_species(/datum/species/plasmaman)
		burn_human.visible_message(span_warning("[burn_human] bursts into a brilliant purple flame as [burn_human.p_their()] entire body is that of a skeleton!"), \
			span_userdanger("Your senses numb as all of your remaining flesh is turned into a purple slurry, sloshing off your body and leaving only your bones to show in a vibrant purple!"))

//mafia specific tame happy plasma (normal atmos, no slowdown)
/turf/open/lava/plasma/mafia
	initial_gas_mix = OPENTURF_DEFAULT_ATMOS
	baseturfs = /turf/open/lava/plasma/mafia
	slowdown = 0

/////////// papers

/obj/item/paper/crumpled/ruins/snowdin/foreshadowing
	name = "scribbled note"
	info = {"Something's gone VERY wrong here. Jouslen has been mumbling about some weird shit in his cabin during the night and he seems always tired when we're working. I tried to confront him about it and he blew up on me,
		telling me to mind my own business. I reported him to the officer, said he'd look into it. We only got another 2 months here before we're pulled for another assignment, so this shit can't go any quicker..."}

/obj/item/paper/crumpled/ruins/snowdin/misc1
	name = "Mission Prologue"
	info = {"Holy shit, what a rush! Those Nanotrasen bastards didn't even know what hit 'em! All five of us dropped in right on the captain, didn't even have time to yell! We were in and out with that disk in mere minutes!
	Crew didn't even know what was happening till the delta alert went down and by then we were already gone. We got a case to drink on the way home to celebrate, fuckin' job well done!"}

/obj/item/paper/crumpled/ruins/snowdin/dontdeadopeninside
	name = "scribbled note"
	info = {"If you're reading this: GET OUT! The mining go on here has unearthed something that was once-trapped by the layers of ice on this hell-hole. The overseer and Jouslen have gone missing. The officer is
		keeping the rest of us on lockdown and I swear to god I keep hearing strange noises outside the walls at night. The gateway link has gone dead and without a supply of resources from Central, we're left
		for dead here. We haven't heard anything back from the mining squad either, so I can only assume whatever the fuck they unearthed got them first before coming for us. I don't want to die here..."}

/obj/item/paper/fluff/awaymissions/snowdin/saw_usage
	name = "SAW Usage"
	info = "YOU SEEN IVAN, WHEN YOU HOLD SAAW LIKE PEESTOL, YOU STRONGER THAN RECOIL FOR FEAR OF HITTING FACE!"

/obj/item/paper/fluff/awaymissions/snowdin/research_feed
	name = "Research Feed"
	info = {"A page full of graphs and other detailed information on the seismic activity of the surrounding area."}

//profile of each of the old crewmembers for the outpost

/obj/item/paper/fluff/awaymissions/snowdin/profile/overseer
	name = "Personnel Record AOP#01"
	info = {"Personnel Log

Name:Caleb Reed
Age:38
Gender:Male
On-Site Profession:Outpost Overseer

Information
Caleb Reed lead several expeditions
		among uncharted planets in search of plasma for Nanotrasen, scouring from hot savanas to freezing arctics. Track record is fairly clean with only incidient including the loss of two researchers during the
		expedition of _______, where mis-used of explosive ordinance for tunneling causes a cave-in."}

/obj/item/paper/fluff/awaymissions/snowdin/profile/sec1
	name = "Personnel Record AOP#02"
	info = {"Personnel Log

Name:James Reed
Age:43
Gender:Male
On-Site Profession:Outpost Security

Information
James Reed has been a part
		of Nanotrasen's security force for over 20 years, first joining in 22XX. A clean record and unwavering loyalty to the corperation through numerous deployments to various sites makes him a valuable asset to Natotrasen
		when it comes to keeping the peace while prioritizing Nanotrasen privacy matters. "}

/obj/item/paper/fluff/awaymissions/snowdin/profile/hydro1
	name = "Personnel Record AOP#03"
	info = {"Personnel Log

Name:Katherine Esterdeen
Age:27
Gender:Female
On-Site Profession:Outpost Botanist

Information
Katherine Esterdeen is a recent
		graduate with a major in Botany and a PH.D in Ecology. Having a clean record and eager to work, Esterdeen seems to be the right fit for maintaining plants in the middle of nowhere."}

/obj/item/paper/fluff/awaymissions/snowdin/profile/engi1
	name = "Personnel Record AOP#04"
	info = {"Personnel Log

Name:Rachel Migro
Age:35
Gender:Female
On-Site Profession:Outpost Engineer

Information
Recently certified to be a full-time Journeyman, Rachel has
		been assigned various construction projects in the past 5 years. Competent and has no past infractions, should be of little concern."}

/obj/item/paper/fluff/awaymissions/snowdin/profile/research1
	name = "Personnel Record AOP#05"
	info = {"Personnel Log

Name:Jacob Ullman
Age:27
Gender:Male
On-Site Profession:Outpost Researcher

Information
"}

/obj/item/paper/fluff/awaymissions/snowdin/profile/research2
	name = "Personnel Record AOP#06"
	info = {"Personnel Log

Name:Elizabeth Queef
Age:28
Gender:Female
On-Site Profession:Outpost Researcher

Information
"}

/obj/item/paper/fluff/awaymissions/snowdin/profile/research3
	name = "Personnel Record AOP#07"
	info = {"Personnel Log

Name:Jouslen McGee
Age:38
Gender:Male
On-Site Profession:Outpost Researcher

Information
"}

/obj/item/paper/fluff/awaymissions/snowdin/secnotice
	name = "Security Notice"
	info = {"YOu have been assigned to this Arctic Post with intention of protecting Nanotrasen assets and ensuring vital information is kept secure while the stationed crew obeys protocol. The picked
		staff for this post have been pre-screened with no prior incidients on record, but incase of an issue you have been given a single holding cell and instructions to contact Central to terminate the
		offending crewmember."}

/obj/item/paper/fluff/awaymissions/snowdin/mining
	name = "Assignment Notice"
	info = {"This cold-ass planet is the new-age equivalent of striking gold. Huge deposits of plasma and literal streams of plasma run through the caverns under all this ice and we're here to mine it all.\
		Nanotrasen pays by the pound, so get minin' boys!"}

/obj/item/paper/crumpled/ruins/snowdin/lootstructures
	name = "scribbled note"
	info = {"There's some ruins scattered along the cavern, their walls seem to be made of some sort of super-condensed mixture of ice and snow. We've already barricaded up the ones we've found so far,
		since we keep hearing some strange noises from inside. Besides, what sort of fool would wrecklessly run into ancient ruins full of monsters for some old gear, anyway?"}

/obj/item/paper/crumpled/ruins/snowdin/shovel
	name = "shoveling duties"
	info = {"Snow piles up bad here all-year round, even worse during the winter months. Keeping a constant rotation of shoveling that shit out of the way of the airlocks and keeping the paths decently clear
	is a good step towards not getting stuck walking through knee-deep snow."}

//holo disk recording//--

/obj/item/disk/holodisk/snowdin/weregettingpaidright
	name = "Conversation #AOP#23"
	preset_image_type = /datum/preset_holoimage/researcher
	preset_record_text = {"
	NAME Jacob Ullman
	DELAY 10
	SAY Have you gotten anything interesting on the scanners yet? The deep-drilling from the plasma is making it difficult to get anything that isn't useless noise.
	DELAY 45
	NAME Elizabeth Queef
	DELAY 10
	SAY Nah. I've been feeding the AI the results for the past 2 weeks to sift through the garbage and haven't seen anything out of the usual, at least whatever Nanotrasen is looking for.
	DELAY 45
	NAME Jacob Ullman
	DELAY 10
	SAY Figured as much. Dunno what Nanotrasen expects to find out here past the plasma. At least we're getting paid to fuck around for a couple months while the AI does the hard work.
	DELAY 45
	NAME Elizabeth Queef
	DELAY 10
	SAY . . .
	DELAY 10
	SAY ..We're getting paid?
	DELAY 20
	NAME Jacob Ullman
	DELAY 10
	SAY ..We are getting paid, aren't we..?
	DELAY 15
	PRESET /datum/preset_holoimage/captain
	NAME Caleb Reed
	DELAY 10
	SAY Paid in experience! That's the Nanotrasen Motto!
	DELAY 30;"}

/obj/item/disk/holodisk/snowdin/welcometodie
	name = "Conversation #AOP#1"
	preset_image_type = /datum/preset_holoimage/corgi
	preset_record_text = {"
	NAME Friendly AI Unit
	DELAY 10
	SAY Hello! Welcome to the Arctic Post *338-3**$$!
	DELAY 30
	SAY You have been selected out of $)@! potential candidates for this post!
	DELAY 30
	SAY Nanotrasen is pleased to have you working in one of the many top-of-the-line research posts within the $%@!! sector!
	DELAY 30
	SAY Further job assignment information can be found at your local security post! Have a secure day!
	DELAY 20;"}

/obj/item/disk/holodisk/snowdin/overrun
	name = "Conversation #AOP#55"
	preset_image_type = /datum/preset_holoimage/nanotrasenprivatesecurity
	preset_record_text = {"
	NAME James Reed
	DELAY 10
	SAY Jesus christ, what is that thing??
	DELAY 30
	PRESET /datum/preset_holoimage/researcher
	NAME Elizabeth Queef
	DELAY 10
	SAY Hell if I know! Just shoot it already!
	DELAY 30
	PRESET /datum/preset_holoimage/nanotrasenprivatesecurity
	NAME James Reed
	DELAY 10
	SOUND sound/weapons/laser.ogg
	DELAY 10
	SOUND sound/weapons/laser.ogg
	DELAY 10
	SOUND sound/weapons/laser.ogg
	DELAY 10
	SOUND sound/weapons/laser.ogg
	DELAY 15
	SAY Just go! I'll keep it busy, there's an outpost south of here with an elevator to the surface.
	NAME Jacob Ullman
	PRESET /datum/preset_holoimage/researcher.
	DELAY 15
	Say I don't have to be told twice! Let's get the fuck out of here.
	DELAY 20;"}

/obj/item/disk/holodisk/snowdin/ripjacob
	name = "Conversation #AOP#62"
	preset_image_type = /datum/preset_holoimage/researcher
	preset_record_text = {"
	NAME Jacob Ullman
	DELAY 10
	SAY Get the elevator called. We got no idea how many of those fuckers are down here and I'd rather get off this planet as soon as possible.
	DELAY 45
	NAME Elizabeth Queef
	DELAY 10
	SAY You don't need to tell me twice, I just need to swipe access and then..
	DELAY 15
	SOUND sound/effects/glassbr1.ogg
	DELAY 10
	SOUND sound/effects/glassbr2.ogg
	DELAY 15
	NAME Jacob Ullman
	DELAY 10
	SAY What the FUCK was that?
	DELAY 20
	SAY OH FUCK THERE'S MORE OF THEM. CALL FASTER JESUS CHRIST.
	DELAY 20
	NAME Elizabeth Queef
	DELAY 10
	SAY DON'T FUCKING RUSH ME ALRIGHT IT'S BEING CALLED.
	DELAY 15
	SOUND sound/effects/huuu.ogg
	DELAY 5
	SOUND sound/effects/huuu.ogg
	DELAY 15
	SOUND sound/effects/woodhit.ogg
	DELAY 2
	SOUND sound/effects/bodyfall3.ogg
	DELAY 5
	SOUND sound/effects/meow1.ogg
	DELAY 15
	NAME Jacob Ullman
	DELAY 15
	SAY OH FUCK IT'S GOT ME JESUS CHRIIIiiii-
	NAME Elizabeth Queef
	SAY AAAAAAAAAAAAAAAA FUCK THAT
	DELAY 15;"}

//special items//--

/obj/structure/barricade/wooden/snowed
	name = "crude plank barricade"
	desc = "This space is blocked off by a wooden barricade. It seems to be covered in a layer of snow."
	icon_state = "woodenbarricade-snow"
	max_integrity = 125

/obj/item/clothing/under/syndicate/coldres
	name = "insulated tactical turtleneck"
	desc = "A nondescript and slightly suspicious-looking turtleneck with digital camouflage cargo pants. The interior has been padded with special insulation for both warmth and protection."
	armor = list(MELEE = 20, BULLET = 10, LASER = 0,ENERGY = 5, BOMB = 0, BIO = 0, RAD = 0, FIRE = 25, ACID = 25)
	cold_protection = CHEST|GROIN|ARMS|LEGS
	min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT

/obj/item/clothing/shoes/combat/coldres
	name = "insulated combat boots"
	desc = "High speed, low drag combat boots, now with an added layer of insulation."
	min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT

/obj/item/gun/magic/wand/fireball/inert
	name = "weakened wand of fireball"
	desc = "This wand shoots scorching balls of fire that explode into destructive flames. The years of the cold have weakened the magic inside the wand."
	max_charges = 4

/obj/item/gun/magic/wand/resurrection/inert
	name = "weakened wand of healing"
	desc = "This wand uses healing magics to heal and revive. The years of the cold have weakened the magic inside the wand."
	max_charges = 5

/obj/effect/mob_spawn/human/syndicatesoldier/coldres
	name = "Syndicate Snow Operative"
	outfit = /datum/outfit/snowsyndie/corpse

/datum/outfit/snowsyndie/corpse
	name = "Syndicate Snow Operative Corpse"
	implants = null

/obj/effect/mob_spawn/human/syndicatesoldier/coldres/alive
	name = "sleeper"
	mob_name = "Syndicate Snow Operative"
	icon = 'icons/obj/machines/sleeper.dmi'
	icon_state = "sleeper"
	roundstart = FALSE
	death = FALSE
	faction = list(ROLE_SYNDICATE)
	outfit = /datum/outfit/snowsyndie
	short_desc = "You are a syndicate operative recently awoken from cryostasis in an underground outpost."
	flavour_text = "You are a syndicate operative recently awoken from cryostasis in an underground outpost. Monitor Nanotrasen communications and record information. All intruders should be \
	disposed of swiftly to assure no gathered information is stolen or lost. Try not to wander too far from the outpost as the caves can be a deadly place even for a trained operative such as yourself."

/datum/outfit/snowsyndie
	name = "Syndicate Snow Operative"
	uniform = /obj/item/clothing/under/syndicate/coldres
	shoes = /obj/item/clothing/shoes/combat/coldres
	ears = /obj/item/radio/headset/syndicate/alt
	r_pocket = /obj/item/gun/ballistic/automatic/pistol
	id = /obj/item/card/id/advanced/chameleon
	implants = list(/obj/item/implant/exile)
	id_trim = /datum/id_trim/chameleon/operative

/obj/effect/mob_spawn/human/syndicatesoldier/coldres/alive/female
	mob_gender = FEMALE

//mobs//--

//ice spiders moved to giant_spiders.dm

//objs//--

/obj/structure/flora/rock/icy
	name = "icy rock"
	color = rgb(204,233,235)

/obj/structure/flora/rock/pile/icy
	name = "icey rocks"
	color = rgb(204,233,235)

//decals//--
/obj/effect/turf_decal/snowdin_station_sign
	icon_state = "AOP1"

/obj/effect/turf_decal/snowdin_station_sign/two
	icon_state = "AOP2"

/obj/effect/turf_decal/snowdin_station_sign/three
	icon_state = "AOP3"

/obj/effect/turf_decal/snowdin_station_sign/four
	icon_state = "AOP4"

/obj/effect/turf_decal/snowdin_station_sign/five
	icon_state = "AOP5"

/obj/effect/turf_decal/snowdin_station_sign/six
	icon_state = "AOP6"

/obj/effect/turf_decal/snowdin_station_sign/seven
	icon_state = "AOP7"

/obj/effect/turf_decal/snowdin_station_sign/up
	icon_state = "AOPU1"

/obj/effect/turf_decal/snowdin_station_sign/up/two
	icon_state = "AOPU2"

/obj/effect/turf_decal/snowdin_station_sign/up/three
	icon_state = "AOPU3"

/obj/effect/turf_decal/snowdin_station_sign/up/four
	icon_state = "AOPU4"

/obj/effect/turf_decal/snowdin_station_sign/up/five
	icon_state = "AOPU5"

/obj/effect/turf_decal/snowdin_station_sign/up/six
	icon_state = "AOPU6"

/obj/effect/turf_decal/snowdin_station_sign/up/seven
	icon_state = "AOPU7"


code:
//Spacebattle Areas

/area/awaymission/spacebattle
	name = "Space Battle"
	icon_state = "awaycontent1"
	requires_power = FALSE

/area/awaymission/spacebattle/cruiser
	name = "\improper Nanotrasen Cruiser"
	icon_state = "awaycontent2"

/area/awaymission/spacebattle/syndicate1
	name = "Syndicate Assault Ship 1"
	icon_state = "awaycontent3"

/area/awaymission/spacebattle/syndicate2
	name = "Syndicate Assault Ship 2"
	icon_state = "awaycontent4"

/area/awaymission/spacebattle/syndicate3
	name = "Syndicate Assault Ship 3"
	icon_state = "awaycontent5"

/area/awaymission/spacebattle/syndicate4
	name = "Syndicate War Sphere 1"
	icon_state = "awaycontent6"

/area/awaymission/spacebattle/syndicate5
	name = "Syndicate War Sphere 2"
	icon_state = "awaycontent7"

/area/awaymission/spacebattle/syndicate6
	name = "Syndicate War Sphere 3"
	icon_state = "awaycontent8"

/area/awaymission/spacebattle/syndicate7
	name = "Syndicate Fighter"
	icon_state = "awaycontent9"

/area/awaymission/spacebattle/secret
	name = "Hidden Chamber"
	icon_state = "awaycontent10"

/mob/living/simple_animal/hostile/syndicate/ranged/spacebattle
	loot = list(/obj/effect/mob_spawn/human/corpse/syndicatesoldier,
				/obj/item/gun/ballistic/automatic/c20r,
				/obj/item/shield/energy)

/mob/living/simple_animal/hostile/syndicate/melee/spacebattle
	deathmessage = "falls limp as they release their grip from the energy weapons, activating their self-destruct function!"
	loot = list(/obj/effect/mob_spawn/human/corpse/syndicatesoldier)


code:
/* Station-Collision(sc) away mission map specific stuff
 *
 * Notes:
 * Feel free to use parts of this map, or even all of it for your own project. Just include me in the credits :)
 *
 * Some of this code unnecessary, but the intent is to add a little bit of everything to serve as examples
 * for anyone who wants to make their own stuff.
 *
 * Contains:
 * Landmarks
 * Guns
 * Safe code hints
 * Captain's safe
 * Modified Nar'Sie
 */

/*
 * Landmarks - Instead of spawning a new object type, I'll spawn the bible using a landmark!
 */
/obj/effect/landmark/sc_bible_spawner
	name = "Safecode hint spawner"

/obj/effect/landmark/sc_bible_spawner/Initialize(mapload)
	..()
	var/obj/item/storage/book/bible/B = new /obj/item/storage/book/bible/booze(loc)
	B.name = "The Holy book of the Geometer"
	B.deity_name = "Narsie"
	B.icon_state = "melted"
	B.inhand_icon_state = "melted"
	B.lefthand_file = 'icons/mob/inhands/misc/books_lefthand.dmi'
	B.righthand_file = 'icons/mob/inhands/misc/books_righthand.dmi'
	new /obj/item/paper/fluff/awaymissions/stationcollision/safehint_paper_bible(B)
	new /obj/item/pen(B)
	return INITIALIZE_HINT_QDEL

/*
 * Guns - I'm making these specifically so that I dont spawn a pile of fully loaded weapons on the map.
 */
//Captain's retro laser - Fires practice laser shots instead.
/obj/item/gun/energy/laser/retro/sc_retro
	name ="retro laser"
	icon_state = "retro"
	desc = "An older model of the basic lasergun, no longer used by Nanotrasen's security or military forces."
	clumsy_check = FALSE //No sense in having a harmless gun blow up in the clowns face

//Syndicate sub-machine guns.
/obj/item/gun/ballistic/automatic/c20r/sc_c20r

/obj/item/gun/ballistic/automatic/c20r/sc_c20r/Initialize(mapload)
	. = ..()
	for(var/ammo in magazine.stored_ammo)
		if(prob(95)) //95% chance
			magazine.stored_ammo -= ammo

//Barman's shotgun
/obj/item/gun/ballistic/shotgun/sc_pump

/obj/item/gun/ballistic/shotgun/sc_pump/Initialize(mapload)
	. = ..()
	for(var/ammo in magazine.stored_ammo)
		if(prob(95)) //95% chance
			magazine.stored_ammo -= ammo

//Lasers
/obj/item/gun/energy/laser/practice/sc_laser
	name = "Old laser"
	desc = "A once potent weapon, years of dust have collected in the chamber and lens of this weapon, weakening the beam significantly."
	clumsy_check = FALSE

/*
 * Safe code hints
 */

//These vars hold the code itself, they'll be generated at round-start
GLOBAL_VAR_INIT(sc_safecode1, "[rand(0,9)]")
GLOBAL_VAR_INIT(sc_safecode2, "[rand(0,9)]")
GLOBAL_VAR_INIT(sc_safecode3, "[rand(0,9)]")
GLOBAL_VAR_INIT(sc_safecode4, "[rand(0,9)]")
GLOBAL_VAR_INIT(sc_safecode5, "[rand(0,9)]")

//Pieces of paper actually containing the hints
/obj/item/paper/fluff/awaymissions/stationcollision/safehint_paper_prison
	name = "smudged paper"

/obj/item/paper/fluff/awaymissions/stationcollision/safehint_paper_prison/Initialize(mapload)
	. = ..()
	info = "The ink is smudged, you can only make out a couple numbers: '[GLOB.sc_safecode1]**[GLOB.sc_safecode4]*'"

/obj/item/paper/fluff/awaymissions/stationcollision/safehint_paper_hydro
	name = "shredded paper"
/obj/item/paper/fluff/awaymissions/stationcollision/safehint_paper_hydro/Initialize(mapload)
	. = ..()
	info = "Although the paper is shredded, you can clearly see the number: '[GLOB.sc_safecode2]'"

/obj/item/paper/fluff/awaymissions/stationcollision/safehint_paper_caf
	name = "blood-soaked paper"
	//This does not have to be in New() because it is a constant. There are no variables in it i.e. [sc_safcode]
	info = "This paper is soaked in blood, it is impossible to read any text."

/obj/item/paper/fluff/awaymissions/stationcollision/safehint_paper_bible
	name = "hidden paper"
/obj/item/paper/fluff/awaymissions/stationcollision/safehint_paper_bible/Initialize(mapload)
	. = ..()
	info = {"It would appear that the pen hidden with the paper had leaked ink over the paper.
			However you can make out the last three digits:'[GLOB.sc_safecode3][GLOB.sc_safecode4][GLOB.sc_safecode5]'
			"}

/obj/item/paper/fluff/awaymissions/stationcollision/safehint_paper_shuttle
	info = {"Target: Research-station Epsilon

			Objective: Prototype weaponry. The captain likely keeps them locked in her safe.

			Our on-board spy has learned the code and has hidden away a few copies of the code around the station. Unfortunately he has been captured by security
			Your objective is to split up, locate any of the papers containing the captain's safe code, open the safe and
			secure anything found inside. If possible, recover the imprisioned syndicate operative and receive the code from him.

			As always, eliminate anyone who gets in the way.

			Your assigned ship is designed specifically for penetrating the hull of another station or ship with minimal damage to operatives.
			It is completely fly-by-wire meaning you have just have to enjoy the ride and when the red light comes on... find something to hold onto!
			"}
/*
 * Captain's safe
 */
/obj/item/storage/secure/safe/sc_ssafe
	name = "Captain's secure safe"

/obj/item/storage/secure/safe/sc_ssafe/Initialize(mapload)
	. = ..()
	l_code = "[GLOB.sc_safecode1][GLOB.sc_safecode2][GLOB.sc_safecode3][GLOB.sc_safecode4][GLOB.sc_safecode5]"
	l_set = 1
	new /obj/item/gun/energy/mindflayer(src)
	new /obj/item/soulstone(src)
	new /obj/item/clothing/suit/space/hardsuit/cult(src)
	//new /obj/item/teleportation_scroll(src)
	new /obj/item/stack/ore/diamond(src)


code:
// undergroundoutpost45

//Areas
/area/awaymission/undergroundoutpost45
	name = "space"
	icon_state = "awaycontent1"

/area/awaymission/undergroundoutpost45/central
	name = "UO45 Central Hall"
	icon_state = "awaycontent2"

/area/awaymission/undergroundoutpost45/crew_quarters
	name = "UO45 Crew Quarters"
	icon_state = "awaycontent3"

/area/awaymission/undergroundoutpost45/engineering
	name = "UO45 Engineering"
	icon_state = "awaycontent4"

/area/awaymission/undergroundoutpost45/mining
	name = "UO45 Mining"
	icon_state = "awaycontent5"

/area/awaymission/undergroundoutpost45/research
	name = "UO45 Research"
	icon_state = "awaycontent6"

/area/awaymission/undergroundoutpost45/gateway
	name = "UO45 Gateway"
	icon_state = "awaycontent7"

/area/awaymission/undergroundoutpost45/caves
	name = "UO45 Caves"
	icon_state = "awaycontent8"
	always_unpowered = TRUE
	power_environ = FALSE
	power_equip = FALSE
	power_light = FALSE


code:
/* Code for the Wild West map by Brotemis
 * Contains:
 * Wish Granter
 * Meat Grinder
 */

//Areas

/area/awaymission/wildwest/mines
	name = "Wild West Mines"
	icon_state = "away1"
	requires_power = FALSE

/area/awaymission/wildwest/gov
	name = "Wild West Mansion"
	icon_state = "away2"
	requires_power = FALSE

/area/awaymission/wildwest/refine
	name = "Wild West Refinery"
	icon_state = "away3"
	requires_power = FALSE

/area/awaymission/wildwest/vault
	name = "Wild West Vault"
	icon_state = "away3"

/area/awaymission/wildwest/vaultdoors
	name = "Wild West Vault Doors"  // this is to keep the vault area being entirely lit because of requires_power
	icon_state = "away2"
	requires_power = FALSE

///////// wildwest papers

/obj/item/paper/fluff/awaymissions/wildwest/grinder
	info = "meat grinder requires sacri"

/obj/item/paper/fluff/awaymissions/wildwest/journal/page1
	name = "Planer Saul's Journal: Page 1"
	info = "We've discovered something floating in space. We can't really tell how old it is, but it is scraped and bent to hell. There object is the size of about a room with double doors that we have yet to break into.   It is a lot sturdier than we could have imagined.  We have decided to call it 'The Vault' "

/obj/item/paper/fluff/awaymissions/wildwest/journal/page4
	name = "Planer Saul's Journal: Page 4"
	info = " The miners in the town have become sick and almost all production has stopped. They, in a fit of delusion, tossed all of their mining equipment into the furnaces.  They all claimed the same thing. A voice beckoning them to lay down their arms. Stupid miners."

/obj/item/paper/fluff/awaymissions/wildwest/journal/page7
	name = "Planer Sauls' Journal: Page 7"
	info = "The Vault...it just keeps growing and growing.  I went on my daily walk through the garden and now it's just right outside the mansion... a few days ago it was only barely visible. But whatever is inside...it's calling to me."

/obj/item/paper/fluff/awaymissions/wildwest/journal/page8
	name = "Planer Saul's Journal: Page 8"
	info = "The syndicate have invaded.  Their ships appeared out of nowhere and now they likely intend to kill us all and take everything.  On the off-chance that the Vault may grant us sanctuary, many of us have decided to force our way inside and bolt the door, taking as many provisions with us as we can carry.  In case you find this, send for help immediately and open the Vault. Find us inside."

/*
 * Wish Granter
 */
/obj/machinery/wish_granter_dark
	name = "Wish Granter"
	desc = "You're not so sure about this, anymore..."
	icon = 'icons/obj/device.dmi'
	icon_state = "syndbeacon"

	density = TRUE
	use_power = NO_POWER_USE

	var/chargesa = 1
	var/insistinga = 0

/obj/machinery/wish_granter_dark/interact(mob/living/carbon/human/user)
	if(chargesa <= 0)
		to_chat(user, "The Wish Granter lies silent.")
		return

	else if(!ishuman(user))
		to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.")
		return

	else if(is_special_character(user))
		to_chat(user, "Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away.")

	else if (!insistinga)
		to_chat(user, "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?")
		insistinga++

	else
		chargesa--
		insistinga = 0
		var/wish = input("You want...","Wish") as null|anything in sort_list(list("Power","Wealth","Immortality","Peace"))
		switch(wish)
			if("Power")
				to_chat(user, "Your wish is granted, but at a terrible cost...")
				to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.")
				user.dna.add_mutation(LASEREYES)
				user.dna.add_mutation(SPACEMUT)
				user.dna.add_mutation(XRAY)
				user.set_species(/datum/species/shadow)
			if("Wealth")
				to_chat(user, "Your wish is granted, but at a terrible cost...")
				to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.")
				new /obj/structure/closet/syndicate/resources/everything(loc)
				user.set_species(/datum/species/shadow)
			if("Immortality")
				to_chat(user, "Your wish is granted, but at a terrible cost...")
				to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.")
				add_verb(user, /mob/living/carbon/proc/immortality)
				user.set_species(/datum/species/shadow)
			if("Peace")
				to_chat(user, "Whatever alien sentience that the Wish Granter possesses is satisfied with your wish. There is a distant wailing as the last of the Faithless begin to die, then silence.")
				to_chat(user, "You feel as if you just narrowly avoided a terrible fate...")
				for(var/mob/living/simple_animal/hostile/faithless/F in GLOB.mob_living_list)
					F.death()

///////////////Meatgrinder//////////////

/obj/effect/meatgrinder
	name = "Meat Grinder"
	desc = "What is that thing?"
	density = TRUE
	anchored = TRUE
	icon = 'icons/mob/blob.dmi'
	icon_state = "blobpod"
	var/triggered = 0

/obj/effect/meatgrinder/Initialize(mapload)
	. = ..()
	var/static/list/loc_connections = list(
		COMSIG_ATOM_ENTERED = .proc/on_entered,
	)
	AddElement(/datum/element/connect_loc, loc_connections)

/obj/effect/meatgrinder/proc/on_entered(datum/source, atom/movable/AM)
	SIGNAL_HANDLER
	Bumped(AM)

/obj/effect/meatgrinder/Bumped(atom/movable/AM)

	if(triggered)
		return
	if(!ishuman(AM))
		return

	var/mob/living/carbon/human/M = AM

	if(M.stat != DEAD && M.ckey)
		visible_message(span_warning("[M] triggered [src]!"))
		triggered = 1

		var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
		s.set_up(3, 1, src)
		s.start()
		explosion(src, devastation_range = 1, explosion_cause = src)
		qdel(src)

/////For the Wishgranter///////////

/mob/living/carbon/proc/immortality() //Mob proc so people cant just clone themselves to get rid of the shadowperson race. No hiding your wickedness.
	set category = "Immortality"
	set name = "Resurrection"

	var/mob/living/carbon/C = usr
	if(!C.stat)
		to_chat(C, span_notice("You're not dead yet!"))
		return
	if(C.has_status_effect(STATUS_EFFECT_WISH_GRANTERS_GIFT))
		to_chat(C, span_warning("You're already resurrecting!"))
		return
	C.apply_status_effect(STATUS_EFFECT_WISH_GRANTERS_GIFT)
	return 1


code:
/obj/item/paper/pamphlet
	name = "pamphlet"
	icon_state = "pamphlet"
	show_written_words = FALSE

/obj/item/paper/pamphlet/radstorm
	name = "pamphlet - \'Radstorm Safety Measures and How to Not Become Monkey\'"
	info = "Has your station's preemptive radstorm safety alarm gone off and you don't see a nearby maintenance hatch to escape to? Never fear, for NT truly thinks of everything! \
		Several public-access shelters have been installed around the upper station with express purpose of protecting your fragile meaty bits from becoming the next medical disaster! \
		Please see subsection 4.3 V2-3 in your employee handbook for appropriate procedures to deal with excessive radiation damage if you do not make it to a shelter in time."

/obj/item/paper/pamphlet/violent_video_games
	name = "pamphlet - \'Violent Video Games and You\'"
	desc = "A pamphlet encouraging the reader to maintain a balanced lifestyle and take care of their mental health, while still enjoying video games in a healthy way. You probably don't need this..."
	info = "They don't make you kill people. There, we said it. Now get back to work!"

/obj/item/paper/pamphlet/gateway
	info = "Welcome to the Nanotrasen Gateway project...
\
			Congratulations! If you're reading this, you and your superiors have decided that you're \
			ready to commit to a life spent colonising the rolling hills of far away worlds. You \
			must be ready for a lifetime of adventure, a little bit of hard work, and an award \
			winning dental plan- but that's not all the Nanotrasen Gateway project has to offer.
\

Because we care about you, we feel it is only fair to make sure you know the risks \
			before you commit to joining the Nanotrasen Gateway project. All away destinations have \
			been fully scanned by a Nanotrasen expeditionary team, and are certified to be 100% safe. \
			We've even left a case of space beer along with the basic materials you'll need to expand \
			Nanotrasen's operational area and start your new life.

\
			Gateway Operation Basics
\
			All Nanotrasen approved Gateways operate on the same basic principals. They operate off \
			area equipment power as you would expect, and without this supply, it cannot safely function, \
			causinng it to reject all attempts at operation.

\
			Once it is correctly setup, and once it has enough power to operate, the Gateway will begin \
			searching for an output location. The amount of time this takes is variable, but the Gateway \
			interface will give you an estimate accurate to the minute. Power loss will not interrupt the \
			searching process. Influenza will not interrupt the searching process. Temporal anomalies \
			may cause the estimate to be inaccurate, but will not interrupt the searching process.

 \
			Life On The Other Side
\
			Once you have traversed the Gateway, you may experience some disorientation. Do not panic. \
			This is a normal side effect of travelling vast distances in a short period of time. You should \
			survey the immediate area, and attempt to locate your complimentary case of space beer. Our \
			expeditionary teams have ensured the complete safety of all away locations, but in a small \
			number of cases, the Gateway they have established may not be immediately obvious. \
			Do not panic if you cannot locate the return Gateway. Begin colonisation of the destination. \

A New World
\
			As a participant in the Nanotrasen Gateway Project, you will be on the frontiers of space. \
			Though complete safety is assured, participants are advised to prepare for inhospitable \
			environs."


code:
/*An alternative to exit gateways, signposts send you back to somewhere safe onstation with their semiotic magic.*/
/obj/structure/signpost
	icon = 'icons/obj/stationobjs.dmi'
	icon_state = "signpost"
	anchored = TRUE
	density = TRUE
	var/question = "Travel back?"
	var/list/zlevels

/obj/structure/signpost/Initialize(mapload)
	. = ..()
	set_light(2)
	zlevels = SSmapping.levels_by_trait(ZTRAIT_STATION)

/obj/structure/signpost/interact(mob/user)
	. = ..()
	if(.)
		return
	if(tgui_alert(usr,question,name,list("Yes","No")) == "Yes" && Adjacent(user))
		var/turf/T = find_safe_turf(zlevels=zlevels)

		if(T)
			var/atom/movable/AM = user.pulling
			if(AM)
				AM.forceMove(T)
			user.forceMove(T)
			if(AM)
				user.start_pulling(AM)
			to_chat(user, span_notice("You blink and find yourself in [get_area_name(T)]."))
		else
			to_chat(user, "Nothing happens. You feel that this is a bad sign.")

/obj/structure/signpost/attackby(obj/item/W, mob/user, params)
	return interact(user)

/obj/structure/signpost/attack_paw(mob/user, list/modifiers)
	return interact(user)

/obj/structure/signpost/attack_hulk(mob/user)
	return

/obj/structure/signpost/attack_larva(mob/user)
	return interact(user)

/obj/structure/signpost/attack_robot(mob/user)
	if (Adjacent(user))
		return interact(user)

/obj/structure/signpost/attack_slime(mob/user)
	return interact(user)

/obj/structure/signpost/attack_animal(mob/user, list/modifiers)
	return interact(user)

/obj/structure/signpost/salvation
	name = "\proper salvation"
	desc = "In the darkest times, we will find our way home."
	resistance_flags = INDESTRUCTIBLE

/obj/structure/signpost/exit
	name = "exit"
	desc = "Make sure to bring all your belongings with you when you \
		exit the area."
	question = "Leave? You might never come back."

/obj/structure/signpost/exit/Initialize(mapload)
	. = ..()
	zlevels = list()
	for(var/i in 1 to world.maxz)
		zlevels += i
	zlevels -= SSmapping.levels_by_trait(ZTRAIT_CENTCOM) // no easy victory, even with meme signposts
	// also, could you think of the horror if they ended up in a holodeck
	// template or something


code:
/obj/structure/speaking_tile
	name = "strange tile"
	desc = "A weird tile that beckons you towards it. Maybe it can help you get out of this mess..."
	verb_say = "intones"
	icon = 'icons/obj/structures.dmi'
	icon_state = "speaking_tile"
	layer = 5
	resistance_flags = INDESTRUCTIBLE
	var/speaking = FALSE
	var/times_spoken_to = 0
	var/list/shenanigans = list()

/obj/structure/speaking_tile/Initialize(mapload)
	. = ..()
	var/json_file = file("data/npc_saves/Poly.json")
	if(!fexists(json_file))
		return
	var/list/json = json_decode(file2text(json_file))
	shenanigans = json["phrases"]

/obj/structure/speaking_tile/interact(mob/user)
	if(!isliving(user) || speaking)
		return
	speaking = TRUE

	switch(times_spoken_to)
		if(0)
			SpeakPeace(list("Welcome to the error handling room.","Something's goofed up bad to send you here.","You should probably tell an admin what you were doing, or make a bug report."))
			for(var/obj/structure/signpost/salvation/S in orange(7))
				S.invisibility = 0
				var/datum/effect_system/smoke_spread/smoke = new
				smoke.set_up(1, S.loc)
				smoke.start()
				break
		if(1)
			SpeakPeace(list("Take that ladder up.","It'll send you back to the station.","Hopefully you'll never need to see this place again."))
		if(2)
			SpeakPeace(list("Curious about what happened?","Somehow your corporeal form was sent to nullspace with you still in it.","Lucky for you this room exists to save you from that horrible fate."))
		if(3)
			SpeakPeace(list("So yeah, you're welcome.","Anyway don't you have things to do?","There's no real point to sticking around here forever."))
		if(4)
			SpeakPeace(list("I'm flattered you care this much about this room.","However it's not proper to just stand in here all shift and see what I'll say.","I'm going to work hard to be more boring so you'll leave."))
		if(5 to 8)
			SpeakPeace(list("..."))
		if(9)
			SpeakPeace(list("Alright maybe that's <b>too</b> boring.", "I can't keep manually typing these lines out though.", "It's hard to explain but the code structure I'm using is kind of terrible."))
		if(10)
			SpeakPeace(list("Oh I have an idea!", "Lets outsource this endless banter to Poly!", "Then you'll be able to keep listening to this without getting bored!"))
			if(isnull(shenanigans) || !shenanigans.len)
				shenanigans = list("Except the poly file is missing...")
		if(11 to 14, 16 to 50, 52 to 99, 103 to 107, 109 to 203, 205 to 249, 252 to 665, 667 to 999, 1001 to 5642)
			SpeakPeace(list(pick(shenanigans),pick(shenanigans),pick(shenanigans)))
			if(times_spoken_to % 10 == 0)
				SpeakPeace(list("That's [times_spoken_to] times you've spoken to me by the way."))
		if(15)
			SpeakPeace(list("See? Isn't this fun?","Now you can mash this for hours without getting bored.","Anyway I'll leave you it."))
		if(51)
			SpeakPeace(list("The fun never ends around here.", "The Poly text files stores up to 500 statements.", "But you've probably heard a few repeats by now."))
		if(100)
			SpeakPeace(list("And that's a solid hundred.", "Good hustle I guess.", "You've probably heard a lot of repeats by now."))
		if(101)
			SpeakPeace(list("I hope you're getting the reference this room is presenting.", "As well as the more obscure meta reference this conversation is presenting.", "This stuff has layers."))
		if(102)
			SpeakPeace(list("I am very tempted to just stretch this out forever.","It's technically easier than doing this.","Just an option."))
		if(108)
			SpeakPeace(list("But you have my respect for being this dedicated to the joke.", "So tell you what we're going to do, we're going to set a goal.", "250 is your final mission."))
		if(204)
			SpeakPeace(list("Notice how there was no special message at 200?", "The slow automation of what used to be meaningful milestones?","It's all part of the joke."))
		if(250)
			SpeakPeace(list("Congratulations.", "By my very loose calculations you've now wasted a decent chunk of the round doing this.", "But you've seen this meme to its conclusion, and that's an experience in itself, right?"))
		if(251)
			SpeakPeace(list("Anyway, here.", "I can't give you anything that would impact the progression of the round.","But you've earned this at least."))
			var/obj/item/reagent_containers/food/drinks/trophy/silver_cup/the_ride = new(get_turf(user))
			the_ride.name = "Overextending The Joke: Second Place"
			the_ride.desc = "There's a point where this needed to stop, and we've clearly passed it."
		if(252)
			SpeakPeace(list("You know what this means right?", "Of course it's not over!", "The question becomes now is it more impressive to solider on to an unknown finish, or to have to common sense to stop here?"))
		if(666)
			SpeakPeace(list("The darkness in your heart won't be filled by simple platitudes.","You won't stop now, you're in this to the end.", "Will you reach the finish line before the round ends?"))
		if(1000)
			SpeakPeace(list("The ends exists somewhere beyond meaningful milestones.", "There will be no more messages until then.", "You disgust me."))
		if(5643)
			user.client.give_award(/datum/award/achievement/misc/time_waste, user)
			var/obj/item/reagent_containers/food/drinks/trophy/gold_cup/never_ends = new(get_turf(user))
			never_ends.name = "Overextending The Joke: First Place"
			never_ends.desc = "And so we are left alone with our regrets."
		else
			y += 2
	speaking = FALSE
	times_spoken_to++

/obj/structure/speaking_tile/attackby(obj/item/W, mob/user, params)
	return interact(user)

/obj/structure/speaking_tile/attack_paw(mob/user, list/modifiers)
	return interact(user)

/obj/structure/speaking_tile/attack_hulk(mob/user)
	return

/obj/structure/speaking_tile/attack_larva(mob/user)
	return interact(user)

/obj/structure/speaking_tile/attack_ai(mob/user)
	return interact(user)

/obj/structure/speaking_tile/attack_slime(mob/user)
	return interact(user)

/obj/structure/speaking_tile/attack_animal(mob/user, list/modifiers)
	return interact(user)

/obj/structure/speaking_tile/proc/SpeakPeace(list/statements)
	for(var/i in 1 to statements.len)
		say(span_deadsay("[statements[i]]"), sanitize=FALSE)
		if(i != statements.len)
			sleep(30)

/obj/item/rupee
	name = "weird crystal"
	desc = "Your excitement boils away as you realize it's just colored glass. Why would someone hoard these things?"
	icon = 'icons/obj/economy.dmi'
	icon_state = "rupee"
	w_class = WEIGHT_CLASS_SMALL
	custom_materials = list(/datum/material/glass = 500)

/obj/item/rupee/Initialize(mapload)
	. = ..()
	var/newcolor = color2hex(pick(10;"green", 5;"blue", 3;"red", 1;"purple"))
	add_atom_colour(newcolor, FIXED_COLOUR_PRIORITY)
	var/static/list/loc_connections = list(
		COMSIG_ATOM_ENTERED = .proc/on_entered,
	)
	AddElement(/datum/element/connect_loc, loc_connections)

/obj/item/rupee/proc/on_entered(datum/source, atom/movable/AM)
	SIGNAL_HANDLER
	if(!ismob(AM))
		return
	INVOKE_ASYNC(src, .proc/put_in_crossers_hands, AM)

/obj/item/rupee/proc/put_in_crossers_hands(mob/crosser)
	if(crosser.put_in_hands(src))
		if(src != crosser.get_active_held_item())
			crosser.swap_hand()
		equip_to_best_slot(crosser)

/obj/item/rupee/equipped(mob/user, slot)
	playsound(get_turf(loc), 'sound/misc/server-ready.ogg', 50, TRUE, -1)
	..()

/obj/effect/landmark/error
	name = "error"
	icon_state = "error_room"


code:
// How much "space" we give the edge of the map
GLOBAL_LIST_INIT(potentialRandomZlevels, generateMapList(filename = "[global.config.directory]/awaymissionconfig.txt"))
GLOBAL_LIST_INIT(potentialConfigRandomZlevels, generateConfigMapList(directory = "[global.config.directory]/away_missions/"))

/proc/createRandomZlevel(config_gateway = FALSE)
	var/map
	if(config_gateway && GLOB.potentialConfigRandomZlevels?.len)
		map = pick_n_take(GLOB.potentialConfigRandomZlevels)
	else if(GLOB.potentialRandomZlevels?.len)
		map = pick_n_take(GLOB.potentialRandomZlevels)
	else
		return to_chat(world, span_boldannounce("No valid away mission files, loading aborted."))
	to_chat(world, span_boldannounce("Loading away mission..."))
	var/loaded = load_new_z_level(map, "Away Mission", config_gateway)
	to_chat(world, span_boldannounce("Away mission [loaded ? "loaded" : "aborted due to errors"]."))
	if(!loaded)
		message_admins("Away mission [map] loading failed due to errors.")
		log_admin("Away mission [map] loading failed due to errors.")
		createRandomZlevel(config_gateway)

/obj/effect/landmark/awaystart
	name = "away mission spawn"
	desc = "Randomly picked away mission spawn points."
	var/id
	var/delay = TRUE // If the generated destination should be delayed by configured gateway delay

/obj/effect/landmark/awaystart/Initialize(mapload)
	. = ..()
	var/datum/gateway_destination/point/current
	for(var/datum/gateway_destination/point/D in GLOB.gateway_destinations)
		if(D.id == id)
			current = D
	if(!current)
		current = new
		current.id = id
		if(delay)
			current.wait = CONFIG_GET(number/gateway_delay)
		GLOB.gateway_destinations += current
	current.target_turfs += get_turf(src)

/obj/effect/landmark/awaystart/nodelay
	delay = FALSE

/proc/generateMapList(filename)
	. = list()
	var/list/Lines = world.file2list(filename)

	if(!Lines.len)
		return
	for (var/t in Lines)
		if (!t)
			continue

		t = trim(t)
		if (length(t) == 0)
			continue
		else if (t[1] == "#")
			continue

		var/pos = findtext(t, " ")
		var/name = null

		if (pos)
			name = lowertext(copytext(t, 1, pos))

		else
			name = lowertext(t)

		if (!name)
			continue

		. += t

/proc/generateConfigMapList(directory)
	var/list/config_maps = list()
	var/list/maps = flist(directory)
	for(var/map_file in maps)
		if(!findtext(map_file, ".dmm"))
			continue
		config_maps += (directory + map_file)
	return config_maps


code:
#define BALLOON_TEXT_WIDTH 200
#define BALLOON_TEXT_SPAWN_TIME (0.2 SECONDS)
#define BALLOON_TEXT_FADE_TIME (0.1 SECONDS)
#define BALLOON_TEXT_FULLY_VISIBLE_TIME (0.7 SECONDS)
#define BALLOON_TEXT_TOTAL_LIFETIME(mult) (BALLOON_TEXT_SPAWN_TIME + BALLOON_TEXT_FULLY_VISIBLE_TIME*mult + BALLOON_TEXT_FADE_TIME)
/// The increase in duration per character in seconds
#define BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MULT (0.05)
/// The amount of characters needed before this increase takes into effect
#define BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MIN 10

/// Creates text that will float from the atom upwards to the viewer.
/atom/proc/balloon_alert(mob/viewer, text)
	SHOULD_NOT_SLEEP(TRUE)

	INVOKE_ASYNC(src, .proc/balloon_alert_perform, viewer, text)

/// Create balloon alerts (text that floats up) to everything within range.
/// Will only display to people who can see.
/atom/proc/balloon_alert_to_viewers(message, self_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs)
	SHOULD_NOT_SLEEP(TRUE)

	var/list/hearers = get_hearers_in_view(vision_distance, src)
	hearers -= ignored_mobs

	for (var/mob/hearer in hearers)
		if (hearer.is_blind())
			continue

		balloon_alert(hearer, (hearer == src && self_message) || message)

// Do not use.
// MeasureText blocks. I have no idea for how long.
// I would've made the maptext_height update on its own, but I don't know
// if this would look bad on laggy clients.
/atom/proc/balloon_alert_perform(mob/viewer, text)
	var/client/viewer_client = viewer.client
	if (isnull(viewer_client))
		return

	var/bound_width = world.icon_size
	if (ismovable(src))
		var/atom/movable/movable_source = src
		bound_width = movable_source.bound_width

	var/image/balloon_alert = image(loc = get_atom_on_turf(src), layer = ABOVE_MOB_LAYER)
	balloon_alert.plane = BALLOON_CHAT_PLANE
	balloon_alert.alpha = 0
	balloon_alert.appearance_flags = RESET_ALPHA|RESET_COLOR|RESET_TRANSFORM
	balloon_alert.maptext = MAPTEXT("[text]")
	balloon_alert.maptext_x = (BALLOON_TEXT_WIDTH - bound_width) * -0.5
	balloon_alert.maptext_height = WXH_TO_HEIGHT(viewer_client?.MeasureText(text, null, BALLOON_TEXT_WIDTH))
	balloon_alert.maptext_width = BALLOON_TEXT_WIDTH

	viewer_client?.images += balloon_alert

	var/duration_mult = 1
	var/duration_length = length(text) - BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MIN

	if(duration_length > 0)
		duration_mult += duration_length*BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MULT

	animate(
		balloon_alert,
		pixel_y = world.icon_size * 1.2,
		time = BALLOON_TEXT_TOTAL_LIFETIME(1),
		easing = SINE_EASING | EASE_OUT,
	)

	animate(
		alpha = 255,
		time = BALLOON_TEXT_SPAWN_TIME,
		easing = CUBIC_EASING | EASE_OUT,
		flags = ANIMATION_PARALLEL,
	)

	animate(
		alpha = 0,
		time = BALLOON_TEXT_FULLY_VISIBLE_TIME*duration_mult,
		easing = CUBIC_EASING | EASE_IN,
	)

	addtimer(CALLBACK(GLOBAL_PROC, .proc/remove_image_from_client, balloon_alert, viewer_client), BALLOON_TEXT_TOTAL_LIFETIME(duration_mult))

#undef BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MIN
#undef BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MULT
#undef BALLOON_TEXT_FADE_TIME
#undef BALLOON_TEXT_FULLY_VISIBLE_TIME
#undef BALLOON_TEXT_SPAWN_TIME
#undef BALLOON_TEXT_TOTAL_LIFETIME
#undef BALLOON_TEXT_WIDTH


code:
# Buildmode

## Code layout

### Buildmode

Manager for buildmode modes. Contains logic to manage switching between each mode, and presenting a suitable user interface.

### Effects

Special graphics used by buildmode modes for user interface purposes.

### Buildmode Mode

Implementer of buildmode behaviors.

Existing varieties:

+ Basic

	**Description**:

	Allows creation of simple structures consisting of floors, walls, windows, and airlocks.

	**Controls**:

	+ *Left click a turf*:

		"Upgrades" the turf based on the following rules below:

		+ Space -> Tiled floor
		+ Simulated floor -> Regular wall
		+ Wall -> Reinforced wall

	+ *Right click a turf*:

		"Downgrades" the turf based on the following rules below:

		+ Reinforced wall -> Regular wall
		+ Wall -> Tiled floor
		+ Simulated floor -> Space

	+ *Right click an object*:

		Deletes the clicked object.

	+ *Alt+Left click a location*:

		Places an airlock at the clicked location.

	+ *Ctrl+Left click a location*:

		Places a window at the clicked location.

+ Advanced

	**Description**:

	Creates an instance of a configurable atom path where you click.

	**Controls**:

	+ *Right click on the mode selector*:

		Choose a path to spawn.

	+ *Left click a location* (requires chosen path):

		Place an instance of the chosen path at the location.

	+ *Right click an object*:

		Delete the object.

+ Fill

	**Description**:

	Creates an instance of an atom path on every tile in a chosen region.

	With a special control input, instead deletes everything within the region.

	**Controls**:

	+ *Right click on the mode selector*:

		Choose a path to spawn.

	+ *Left click on a region* (requires chosen path):

		Fill the region with the chosen path.

	+ *Alt+Left click on a region*:

		Deletes everything within the region.

	+ *Right click during region selection*:

		Cancel region selection.

+ Copy

	**Description**:

	Take an existing object in the world, and place duplicates with identical attributes where you click.

	May not always work nicely - "deep" variables such as lists or datums may malfunction.

	**Controls**:

	+ *Right click an existing object*:

		Select the clicked object as a template.

	+ *Left click a location* (Requires a selected object as template):

		Place a duplicate of the template at the clicked location.

+ Area Edit

	**Description**:

	Modifies and creates areas.

	The active area will be highlighted in yellow.

	**Controls**:

	+ *Right click the mode selector*:

		Create a new area, and make it active.

	+ *Right click an existing area*:

		Make the clicked area active.

	+ *Left click a turf*:

		When an area is active, adds the turf to the active area.

+ Var Edit

	**Description**:

	Allows for setting and resetting variables of objects with a click.

	If the object does not have the var, will do nothing and print a warning message.

	**Controls**:

	+ *Right click the mode selector*:

		Choose which variable to set, and what to set it to.

	+ *Left click an atom*:

		Change the clicked atom's variables as configured.

	+ *Right click an atom*:

		Reset the targeted variable to its original value in the code.

+ Map Generator

	**Description**:

	Fills rectangular regions with algorithmically generated content. Right click during region selection to cancel.

	See the `procedural_mapping` module for the generators themselves.

	**Controls**:

	+ *Right-click on the mode selector*:

		Select a map generator from all the generators present in the codebase.

	+ *Left click two corners of an area*:

		Use the generator to populate the region.

	+ *Right click during region selection*:

		Cancel region selection.

+ Throwing

	**Description**:

	Select an object with left click, and right click to throw it towards where you clicked.

	**Controls**:

	+ *Left click on a movable atom*:

		Select the atom for throwing.

	+ *Right click on a location*:

		Throw the selected atom towards that location.

+ Boom

	**Description**:

	Make explosions where you click.

	**Controls**:

	+ *Right click the mode selector*:

		Configure the explosion size.

	+ *Left click a location*:

		Cause an explosion where you clicked.


code:
/datum/buildmode_mode
	var/key = "oops"

	var/datum/buildmode/BM

	// would corner selection work better as a component?
	var/use_corner_selection = FALSE
	var/list/preview
	var/turf/cornerA
	var/turf/cornerB

/datum/buildmode_mode/New(datum/buildmode/BM)
	src.BM = BM
	preview = list()
	return ..()

/datum/buildmode_mode/Destroy()
	cornerA = null
	cornerB = null
	QDEL_LIST(preview)
	preview = null
	return ..()

/datum/buildmode_mode/proc/enter_mode(datum/buildmode/BM)
	return

/datum/buildmode_mode/proc/exit_mode(datum/buildmode/BM)
	return

/datum/buildmode_mode/proc/get_button_iconstate()
	return "buildmode_[key]"

/datum/buildmode_mode/proc/show_help(client/c)
	CRASH("No help defined, yell at a coder")

/datum/buildmode_mode/proc/change_settings(client/c)
	to_chat(c, span_warning("There is no configuration available for this mode"))
	return

/datum/buildmode_mode/proc/Reset()
	deselect_region()

/datum/buildmode_mode/proc/select_tile(turf/T, corner_to_select)
	var/overlaystate
	BM.holder.images -= preview
	switch(corner_to_select)
		if(AREASELECT_CORNERA)
			overlaystate = "greenOverlay"
		if(AREASELECT_CORNERB)
			overlaystate = "blueOverlay"

	var/image/I = image('icons/turf/overlays.dmi', T, overlaystate)
	I.plane = ABOVE_LIGHTING_PLANE
	preview += I
	BM.holder.images += preview
	return T

/datum/buildmode_mode/proc/highlight_region(region)
	BM.holder.images -= preview
	for(var/t in region)
		var/image/I = image('icons/turf/overlays.dmi', t, "redOverlay")
		I.plane = ABOVE_LIGHTING_PLANE
		preview += I
	BM.holder.images += preview

/datum/buildmode_mode/proc/deselect_region()
	BM.holder.images -= preview
	preview.Cut()
	cornerA = null
	cornerB = null

/datum/buildmode_mode/proc/handle_click(client/c, params, object)
	var/list/modifiers = params2list(params)
	if(use_corner_selection)
		if(LAZYACCESS(modifiers, LEFT_CLICK))
			if(!cornerA)
				cornerA = select_tile(get_turf(object), AREASELECT_CORNERA)
				return
			if(cornerA && !cornerB)
				cornerB = select_tile(get_turf(object), AREASELECT_CORNERB)
				to_chat(c, span_boldwarning("Region selected, if you're happy with your selection left click again, otherwise right click."))
				return
			handle_selected_area(c, params)
			deselect_region()
		else
			to_chat(c, span_notice("Region selection canceled!"))
			deselect_region()
	return

/datum/buildmode_mode/proc/handle_selected_area(client/c, params)


code:
#define BM_SWITCHSTATE_NONE 0
#define BM_SWITCHSTATE_MODE 1
#define BM_SWITCHSTATE_DIR 2

/datum/buildmode
	var/build_dir = SOUTH
	var/datum/buildmode_mode/mode
	var/client/holder

	// login callback
	var/li_cb

	// SECTION UI
	var/list/buttons

	// Switching management
	var/switch_state = BM_SWITCHSTATE_NONE
	var/switch_width = 4
	// modeswitch UI
	var/atom/movable/screen/buildmode/mode/modebutton
	var/list/modeswitch_buttons = list()
	// dirswitch UI
	var/atom/movable/screen/buildmode/bdir/dirbutton
	var/list/dirswitch_buttons = list()

/datum/buildmode/New(client/c)
	mode = new /datum/buildmode_mode/basic(src)
	holder = c
	buttons = list()
	li_cb = CALLBACK(src, .proc/post_login)
	holder.player_details.post_login_callbacks += li_cb
	holder.show_popup_menus = FALSE
	create_buttons()
	holder.screen += buttons
	holder.click_intercept = src
	mode.enter_mode(src)

/datum/buildmode/proc/quit()
	mode.exit_mode(src)
	holder.screen -= buttons
	holder.click_intercept = null
	holder.show_popup_menus = TRUE
	qdel(src)

/datum/buildmode/Destroy()
	close_switchstates()
	holder.player_details.post_login_callbacks -= li_cb
	li_cb = null
	holder = null
	QDEL_NULL(mode)
	QDEL_LIST(buttons)
	QDEL_LIST(modeswitch_buttons)
	QDEL_LIST(dirswitch_buttons)
	return ..()

/datum/buildmode/proc/post_login()
	// since these will get wiped upon login
	holder.screen += buttons
	// re-open the according switch mode
	switch(switch_state)
		if(BM_SWITCHSTATE_MODE)
			open_modeswitch()
		if(BM_SWITCHSTATE_DIR)
			open_dirswitch()

/datum/buildmode/proc/create_buttons()
	// keep a reference so we can update it upon mode switch
	modebutton = new /atom/movable/screen/buildmode/mode(src)
	buttons += modebutton
	buttons += new /atom/movable/screen/buildmode/help(src)
	// keep a reference so we can update it upon dir switch
	dirbutton = new /atom/movable/screen/buildmode/bdir(src)
	buttons += dirbutton
	buttons += new /atom/movable/screen/buildmode/quit(src)
	// build the lists of switching buttons
	build_options_grid(subtypesof(/datum/buildmode_mode), modeswitch_buttons, /atom/movable/screen/buildmode/modeswitch)
	build_options_grid(GLOB.alldirs, dirswitch_buttons, /atom/movable/screen/buildmode/dirswitch)

// this creates a nice offset grid for choosing between buildmode options,
// because going "click click click ah hell" sucks.
/datum/buildmode/proc/build_options_grid(list/elements, list/buttonslist, buttontype)
	var/pos_idx = 0
	for(var/thing in elements)
		var/x = pos_idx % switch_width
		var/y = FLOOR(pos_idx / switch_width, 1)
		var/atom/movable/screen/buildmode/B = new buttontype(src, thing)
		// extra .5 for a nice offset look
		B.screen_loc = "NORTH-[(1 + 0.5 + y*1.5)],WEST+[0.5 + x*1.5]"
		buttonslist += B
		pos_idx++

/datum/buildmode/proc/close_switchstates()
	switch(switch_state)
		if(BM_SWITCHSTATE_MODE)
			close_modeswitch()
		if(BM_SWITCHSTATE_DIR)
			close_dirswitch()

/datum/buildmode/proc/toggle_modeswitch()
	if(switch_state == BM_SWITCHSTATE_MODE)
		close_modeswitch()
	else
		close_switchstates()
		open_modeswitch()

/datum/buildmode/proc/open_modeswitch()
	switch_state = BM_SWITCHSTATE_MODE
	holder.screen += modeswitch_buttons

/datum/buildmode/proc/close_modeswitch()
	switch_state = BM_SWITCHSTATE_NONE
	holder.screen -= modeswitch_buttons

/datum/buildmode/proc/toggle_dirswitch()
	if(switch_state == BM_SWITCHSTATE_DIR)
		close_dirswitch()
	else
		close_switchstates()
		open_dirswitch()

/datum/buildmode/proc/open_dirswitch()
	switch_state = BM_SWITCHSTATE_DIR
	holder.screen += dirswitch_buttons

/datum/buildmode/proc/close_dirswitch()
	switch_state = BM_SWITCHSTATE_NONE
	holder.screen -= dirswitch_buttons

/datum/buildmode/proc/change_mode(newmode)
	mode.exit_mode(src)
	QDEL_NULL(mode)
	close_switchstates()
	mode = new newmode(src)
	mode.enter_mode(src)
	modebutton.update_appearance()

/datum/buildmode/proc/change_dir(newdir)
	build_dir = newdir
	close_dirswitch()
	dirbutton.update_appearance()
	return 1

/datum/buildmode/proc/InterceptClickOn(mob/user, params, atom/object)
	mode.handle_click(user.client, params, object)
	return TRUE // no doing underlying actions

/proc/togglebuildmode(mob/M as mob in GLOB.player_list)
	set name = "Toggle Build Mode"
	set category = "Event"

	if(M.client)
		if(istype(M.client.click_intercept,/datum/buildmode))
			var/datum/buildmode/B = M.client.click_intercept
			B.quit()
			log_admin("[key_name(usr)] has left build mode.")
		else
			new /datum/buildmode(M.client)
			message_admins("[key_name_admin(usr)] has entered build mode.")
			log_admin("[key_name(usr)] has entered build mode.")

#undef BM_SWITCHSTATE_NONE
#undef BM_SWITCHSTATE_MODE
#undef BM_SWITCHSTATE_DIR


code:
/atom/movable/screen/buildmode
	icon = 'icons/misc/buildmode.dmi'
	var/datum/buildmode/bd
	// If we don't do this, we get occluded by item action buttons
	plane = ABOVE_HUD_PLANE

/atom/movable/screen/buildmode/New(bld)
	bd = bld
	return ..()

/atom/movable/screen/buildmode/Destroy()
	bd = null
	return ..()

/atom/movable/screen/buildmode/mode
	name = "Toggle Mode"
	icon_state = "buildmode_basic"
	screen_loc = "NORTH,WEST"

/atom/movable/screen/buildmode/mode/Click(location, control, params)
	var/list/modifiers = params2list(params)
	if(LAZYACCESS(modifiers, LEFT_CLICK))
		bd.toggle_modeswitch()
	else if(LAZYACCESS(modifiers, RIGHT_CLICK))
		bd.mode.change_settings(usr.client)

	update_appearance()
	return 1

/atom/movable/screen/buildmode/mode/update_icon_state()
	icon_state = bd.mode.get_button_iconstate()
	return ..()

/atom/movable/screen/buildmode/help
	icon_state = "buildhelp"
	screen_loc = "NORTH,WEST+1"
	name = "Buildmode Help"

/atom/movable/screen/buildmode/help/Click(location, control, params)
	bd.mode.show_help(usr.client)
	return 1

/atom/movable/screen/buildmode/bdir
	icon_state = "build"
	screen_loc = "NORTH,WEST+2"
	name = "Change Dir"

/atom/movable/screen/buildmode/bdir/update_icon_state()
	dir = bd.build_dir
	return ..()

/atom/movable/screen/buildmode/bdir/Click()
	bd.toggle_dirswitch()
	update_appearance()
	return 1

// used to switch between modes
/atom/movable/screen/buildmode/modeswitch
	var/datum/buildmode_mode/modetype

/atom/movable/screen/buildmode/modeswitch/New(bld, mt)
	modetype = mt
	icon_state = "buildmode_[initial(modetype.key)]"
	name = initial(modetype.key)
	return ..(bld)

/atom/movable/screen/buildmode/modeswitch/Click()
	bd.change_mode(modetype)
	return 1

// used to switch between dirs
/atom/movable/screen/buildmode/dirswitch
	icon_state = "build"

/atom/movable/screen/buildmode/dirswitch/New(bld, dir)
	src.dir = dir
	name = dir2text(dir)
	return ..(bld)

/atom/movable/screen/buildmode/dirswitch/Click()
	bd.change_dir(dir)
	return 1

/atom/movable/screen/buildmode/quit
	icon_state = "buildquit"
	screen_loc = "NORTH,WEST+3"
	name = "Quit Buildmode"

/atom/movable/screen/buildmode/quit/Click()
	bd.quit()
	return 1


code:
/datum/buildmode_mode/advanced
	key = "advanced"
	var/atom/objholder = null

// FIXME: add logic which adds a button displaying the icon
// of the currently selected path

/datum/buildmode_mode/advanced/show_help(client/c)
	to_chat(c, span_notice("***********************************************************"))
	to_chat(c, span_notice("Right Mouse Button on buildmode button = Set object type"))
	to_chat(c, span_notice("Left Mouse Button + alt on turf/obj    = Copy object type"))
	to_chat(c, span_notice("Left Mouse Button on turf/obj          = Place objects"))
	to_chat(c, span_notice("Right Mouse Button                     = Delete objects"))
	to_chat(c, "")
	to_chat(c, span_notice("Use the button in the upper left corner to"))
	to_chat(c, span_notice("change the direction of built objects."))
	to_chat(c, span_notice("***********************************************************"))

/datum/buildmode_mode/advanced/change_settings(client/c)
	var/target_path = input(c, "Enter typepath:", "Typepath", "/obj/structure/closet")
	objholder = text2path(target_path)
	if(!ispath(objholder))
		objholder = pick_closest_path(target_path)
		if(!objholder)
			tgui_alert(usr,"No path was selected")
			return
		else if(ispath(objholder, /area))
			objholder = null
			tgui_alert(usr,"That path is not allowed.")
			return

/datum/buildmode_mode/advanced/handle_click(client/c, params, obj/object)
	var/list/modifiers = params2list(params)
	var/left_click = LAZYACCESS(modifiers, LEFT_CLICK)
	var/right_click = LAZYACCESS(modifiers, RIGHT_CLICK)
	var/alt_click = LAZYACCESS(modifiers, ALT_CLICK)

	if(left_click && alt_click)
		if (istype(object, /turf) || istype(object, /obj) || istype(object, /mob))
			objholder = object.type
			to_chat(c, span_notice("[initial(object.name)] ([object.type]) selected."))
		else
			to_chat(c, span_notice("[initial(object.name)] is not a turf, object, or mob! Please select again."))
	else if(left_click)
		if(ispath(objholder,/turf))
			var/turf/T = get_turf(object)
			log_admin("Build Mode: [key_name(c)] modified [T] in [AREACOORD(object)] to [objholder]")
			T = T.ChangeTurf(objholder)
			T.setDir(BM.build_dir)
		else if(ispath(objholder, /obj/effect/turf_decal))
			var/turf/T = get_turf(object)
			T.AddElement(/datum/element/decal, initial(objholder.icon), initial(objholder.icon_state), BM.build_dir, null, null, initial(objholder.alpha), initial(objholder.color), null, FALSE, null)
			log_admin("Build Mode: [key_name(c)] in [AREACOORD(object)] added a [initial(objholder.name)] decal with dir [BM.build_dir] to [T]")
		else if(!isnull(objholder))
			var/obj/A = new objholder (get_turf(object))
			A.setDir(BM.build_dir)
			log_admin("Build Mode: [key_name(c)] modified [A]'s [COORD(A)] dir to [BM.build_dir]")
		else
			to_chat(c, span_warning("Select object type first."))
	else if(right_click)
		if(isobj(object))
			log_admin("Build Mode: [key_name(c)] deleted [object] at [AREACOORD(object)]")
			qdel(object)


code:
/datum/buildmode_mode/area_edit
	key = "areaedit"
	use_corner_selection = TRUE
	var/area/storedarea
	var/image/areaimage

/datum/buildmode_mode/area_edit/New()
	areaimage = image('icons/turf/areas.dmi', null, "yellow")
	..()

/datum/buildmode_mode/area_edit/enter_mode(datum/buildmode/BM)
	BM.holder.images += areaimage

/datum/buildmode_mode/area_edit/exit_mode(datum/buildmode/BM)
	areaimage.loc = null // de-color the area
	BM.holder.images -= areaimage
	return ..()

/datum/buildmode_mode/area_edit/Destroy()
	QDEL_NULL(areaimage)
	storedarea = null
	return ..()

/datum/buildmode_mode/area_edit/show_help(client/c)
	to_chat(c, span_notice("***********************************************************"))
	to_chat(c, span_notice("Left Mouse Button on obj/turf/mob = Select corner"))
	to_chat(c, "<span class='notice'>Left Mouse Button + Alt on turf/obj/mob = Paint area/span>")
	to_chat(c, span_notice("Right Mouse Button on obj/turf/mob = Select area to paint"))
	to_chat(c, span_notice("Right Mouse Button on buildmode button = Create new area"))
	to_chat(c, span_notice("***********************************************************"))

/datum/buildmode_mode/area_edit/change_settings(client/c)
	var/target_path = input(c, "Enter typepath:", "Typepath", "/area")
	var/areatype = text2path(target_path)
	if(ispath(areatype,/area))
		var/areaname = input(c, "Enter area name:", "Area name", "Area")
		if(!areaname || !length(areaname))
			return
		storedarea = new areatype
		storedarea.power_equip = 0
		storedarea.power_light = 0
		storedarea.power_environ = 0
		storedarea.always_unpowered = 0
		storedarea.name = areaname
		areaimage.loc = storedarea // color our area

/datum/buildmode_mode/area_edit/handle_click(client/c, params, object)
	var/list/modifiers = params2list(params)

	if(LAZYACCESS(modifiers, LEFT_CLICK))
		if(!storedarea)
			to_chat(c, span_warning("Configure or select the area you want to paint first!"))
			return
		if(LAZYACCESS(modifiers, ALT_CLICK))
			var/turf/T = get_turf(object)
			if(get_area(T) != storedarea)
				log_admin("Build Mode: [key_name(c)] added [AREACOORD(T)] to [storedarea]")
				storedarea.contents.Add(T)
			return
		return ..()
	else if(LAZYACCESS(modifiers, RIGHT_CLICK))
		var/turf/T = get_turf(object)
		storedarea = get_area(T)
		areaimage.loc = storedarea // color our area

/datum/buildmode_mode/area_edit/handle_selected_area(client/c, params)
	var/list/modifiers = params2list(params)

	if(LAZYACCESS(modifiers, LEFT_CLICK))
		var/choice = alert("Are you sure you want to fill area?", "Area Fill Confirmation", "Yes", "No")
		if(choice != "Yes")
			return
		for(var/turf/T in block(get_turf(cornerA),get_turf(cornerB)))
			storedarea.contents.Add(T)
		log_admin("Build Mode: [key_name(c)] set the area of the region from [AREACOORD(cornerA)] through [AREACOORD(cornerB)] to [storedarea].")


code:
/datum/buildmode_mode/basic
	key = "basic"

/datum/buildmode_mode/basic/show_help(client/c)
	to_chat(c, span_notice("***********************************************************"))
	to_chat(c, span_notice("Left Mouse Button        = Construct / Upgrade"))
	to_chat(c, span_notice("Right Mouse Button       = Deconstruct / Delete / Downgrade"))
	to_chat(c, span_notice("Left Mouse Button + ctrl = R-Window"))
	to_chat(c, span_notice("Left Mouse Button + alt  = Airlock"))
	to_chat(c, "")
	to_chat(c, span_notice("Use the button in the upper left corner to"))
	to_chat(c, span_notice("change the direction of built objects."))
	to_chat(c, span_notice("***********************************************************"))

/datum/buildmode_mode/basic/handle_click(client/c, params, obj/object)
	var/list/modifiers = params2list(params)

	var/left_click = LAZYACCESS(modifiers, LEFT_CLICK)
	var/right_click = LAZYACCESS(modifiers, RIGHT_CLICK)
	var/alt_click = LAZYACCESS(modifiers, ALT_CLICK)
	var/ctrl_click = LAZYACCESS(modifiers, CTRL_CLICK)

	if(istype(object,/turf) && left_click && !alt_click && !ctrl_click)
		var/turf/T = object
		if(isspaceturf(object))
			T.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
		else if(isplatingturf(object))
			T.PlaceOnTop(/turf/open/floor/iron, flags = CHANGETURF_INHERIT_AIR)
		else if(isfloorturf(object))
			T.PlaceOnTop(/turf/closed/wall)
		else if(iswallturf(object))
			T.PlaceOnTop(/turf/closed/wall/r_wall)
		log_admin("Build Mode: [key_name(c)] built [T] at [AREACOORD(T)]")
		return
	else if(right_click)
		log_admin("Build Mode: [key_name(c)] deleted [object] at [AREACOORD(object)]")
		if(isturf(object))
			var/turf/T = object
			T.ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
		else if(isobj(object))
			qdel(object)
		return
	else if(istype(object,/turf) && alt_click && left_click)
		log_admin("Build Mode: [key_name(c)] built an airlock at [AREACOORD(object)]")
		new/obj/machinery/door/airlock(get_turf(object))
	else if(istype(object,/turf) && ctrl_click && left_click)
		var/obj/structure/window/reinforced/window
		if(BM.build_dir in GLOB.diagonals)
			window = new /obj/structure/window/reinforced/fulltile(get_turf(object))
		else
			window = new /obj/structure/window/reinforced(get_turf(object))
			window.setDir(BM.build_dir)
		log_admin("Build Mode: [key_name(c)] built a window at [AREACOORD(object)]")


code:
/datum/buildmode_mode/boom
	key = "boom"

	var/devastation = -1
	var/heavy = -1
	var/light = -1
	var/flash = -1
	var/flames = -1

/datum/buildmode_mode/boom/show_help(client/c)
	to_chat(c, span_notice("***********************************************************"))
	to_chat(c, span_notice("Mouse Button on obj  = Kaboom"))
	to_chat(c, span_notice("NOTE: Using the \"Config/Launch Supplypod\" verb allows you to do this in an IC way (i.e., making a cruise missile come down from the sky and explode wherever you click!)"))
	to_chat(c, span_notice("***********************************************************"))

/datum/buildmode_mode/boom/change_settings(client/c)
	devastation = input(c, "Range of total devastation. -1 to none", text("Input")) as num|null
	if(devastation == null)
		devastation = -1
	heavy = input(c, "Range of heavy impact. -1 to none", text("Input")) as num|null
	if(heavy == null)
		heavy = -1
	light = input(c, "Range of light impact. -1 to none", text("Input")) as num|null
	if(light == null)
		light = -1
	flash = input(c, "Range of flash. -1 to none", text("Input")) as num|null
	if(flash == null)
		flash = -1
	flames = input(c, "Range of flames. -1 to none", text("Input")) as num|null
	if(flames == null)
		flames = -1

/datum/buildmode_mode/boom/handle_click(client/c, params, obj/object)
	var/list/modifiers = params2list(params)

	if(LAZYACCESS(modifiers, LEFT_CLICK))
		explosion(object, devastation, heavy, light, flames, flash, adminlog = FALSE, ignorecap = TRUE)
		log_admin("Build Mode: [key_name(c)] caused an explosion(dev=[devastation], hvy=[heavy], lgt=[light], flash=[flash], flames=[flames]) at [AREACOORD(object)]")


code:
/datum/buildmode_mode/copy
	key = "copy"
	var/atom/movable/stored = null

/datum/buildmode_mode/copy/Destroy()
	stored = null
	return ..()

/datum/buildmode_mode/copy/show_help(client/c)
	to_chat(c, span_notice("***********************************************************"))
	to_chat(c, span_notice("Left Mouse Button on obj/turf/mob   = Spawn a Copy of selected target"))
	to_chat(c, span_notice("Right Mouse Button on obj/mob = Select target to copy"))
	to_chat(c, span_notice("***********************************************************"))

/datum/buildmode_mode/copy/handle_click(client/c, params, obj/object)
	var/list/modifiers = params2list(params)

	if(LAZYACCESS(modifiers, LEFT_CLICK))
		var/turf/T = get_turf(object)
		if(stored)
			DuplicateObject(stored, perfectcopy=1, sameloc=0,newloc=T)
			log_admin("Build Mode: [key_name(c)] copied [stored] to [AREACOORD(object)]")
	else if(LAZYACCESS(modifiers, RIGHT_CLICK))
		if(ismovable(object)) // No copying turfs for now.
			to_chat(c, span_notice("[object] set as template."))
			stored = object


code:
/datum/buildmode_mode/delete
	key = "delete"

/datum/buildmode_mode/delete/show_help(client/c)
	to_chat(c, "***********************************************************\n\
		Left Mouse Button on anything to delete it. If you break it, you buy it.\n\
		Right Mouse Button on anything to delete everything of the type. Probably don\'t do this unless you know what you are doing.\n\
		***********************************************************")

/datum/buildmode_mode/delete/handle_click(client/c, params, object)
	var/list/modifiers = params2list(params)

	if(LAZYACCESS(modifiers, LEFT_CLICK))
		if(isturf(object))
			var/turf/T = object
			T.ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
		else if(isatom(object))
			qdel(object)

	if(LAZYACCESS(modifiers, RIGHT_CLICK))
		if(check_rights(R_DEBUG|R_SERVER)) //Prevents buildmoded non-admins from breaking everything.
			if(isturf(object))
				return
			var/atom/deleting = object
			var/action_type = tgui_alert(usr,"Strict type ([deleting.type]) or type and all subtypes?",,list("Strict type","Type and subtypes","Cancel"))
			if(action_type == "Cancel" || !action_type)
				return

			if(tgui_alert(usr,"Are you really sure you want to delete all instances of type [deleting.type]?",,list("Yes","No")) != "Yes")
				return

			if(tgui_alert(usr,"Second confirmation required. Delete?",,list("Yes","No")) != "Yes")
				return

			var/O_type = deleting.type
			switch(action_type)
				if("Strict type")
					var/i = 0
					for(var/atom/Obj in world)
						if(Obj.type == O_type)
							i++
							qdel(Obj)
						CHECK_TICK
					if(!i)
						to_chat(usr, "No instances of this type exist")
						return
					log_admin("[key_name(usr)] deleted all instances of type [O_type] ([i] instances deleted) ")
					message_admins(span_notice("[key_name(usr)] deleted all instances of type [O_type] ([i] instances deleted) "))
				if("Type and subtypes")
					var/i = 0
					for(var/Obj in world)
						if(istype(Obj,O_type))
							i++
							qdel(Obj)
						CHECK_TICK
					if(!i)
						to_chat(usr, "No instances of this type exist")
						return
					log_admin("[key_name(usr)] deleted all instances of type or subtype of [O_type] ([i] instances deleted) ")
					message_admins(span_notice("[key_name(usr)] deleted all instances of type or subtype of [O_type] ([i] instances deleted) "))


code:
#define FILL_WARNING_MIN 150

/datum/buildmode_mode/fill
	key = "fill"

	use_corner_selection = TRUE
	var/atom/objholder = null

/datum/buildmode_mode/fill/show_help(client/c)
	to_chat(c, span_notice("***********************************************************"))
	to_chat(c, span_notice("Left Mouse Button on turf/obj/mob      = Select corner"))
	to_chat(c, span_notice("Left Mouse Button + Alt on turf/obj/mob = Delete region"))
	to_chat(c, span_notice("Right Mouse Button on buildmode button = Select object type"))
	to_chat(c, span_notice("***********************************************************"))

/datum/buildmode_mode/fill/change_settings(client/c)
	var/target_path = input(c, "Enter typepath:" ,"Typepath","/obj/structure/closet")
	objholder = text2path(target_path)
	if(!ispath(objholder))
		objholder = pick_closest_path(target_path)
		if(!objholder)
			tgui_alert(usr,"No path has been selected.")
			return
		else if(ispath(objholder, /area))
			objholder = null
			tgui_alert(usr,"Area paths are not supported for this mode, use the area edit mode instead.")
			return
	deselect_region()

/datum/buildmode_mode/fill/handle_click(client/c, params, obj/object)
	if(isnull(objholder))
		to_chat(c, span_warning("Select an object type first."))
		deselect_region()
		return
	..()

/datum/buildmode_mode/fill/handle_selected_area(client/c, params)
	var/list/modifiers = params2list(params)

	if(LAZYACCESS(modifiers, LEFT_CLICK)) //rectangular
		if(LAZYACCESS(modifiers, ALT_CLICK))
			var/list/deletion_area = block(get_turf(cornerA),get_turf(cornerB))
			for(var/beep in deletion_area)
				var/turf/T = beep
				for(var/atom/movable/AM in T)
					qdel(AM)
				// extreme haircut
				T.ScrapeAway(INFINITY, CHANGETURF_DEFER_CHANGE)
			for(var/beep in deletion_area)
				var/turf/T = beep
				T.AfterChange()
			log_admin("Build Mode: [key_name(c)] deleted turfs from [AREACOORD(cornerA)] through [AREACOORD(cornerB)]")
			// if there's an analogous proc for this on tg lmk
			// empty_region(block(get_turf(cornerA),get_turf(cornerB)))
		else
			var/selection_size = abs(cornerA.x - cornerB.x) * abs(cornerA.y - cornerB.y)

			if(selection_size > FILL_WARNING_MIN) // Confirm fill if the number of tiles in the selection is greater than FILL_WARNING_MIN
				var/choice = tgui_alert(usr,"Your selected area is [selection_size] tiles! Continue?", "Large Fill Confirmation", list("Yes", "No"))
				if(choice != "Yes")
					return

			for(var/turf/T in block(get_turf(cornerA),get_turf(cornerB)))
				if(ispath(objholder,/turf))
					T = T.ChangeTurf(objholder)
					T.setDir(BM.build_dir)
				else if(ispath(objholder, /obj/effect/turf_decal))
					T.AddElement(/datum/element/decal, initial(objholder.icon), initial(objholder.icon_state), BM.build_dir, null, null, initial(objholder.alpha), initial(objholder.color), null, FALSE, null)
				else
					var/obj/A = new objholder(T)
					A.setDir(BM.build_dir)
			log_admin("Build Mode: [key_name(c)] with path [objholder], filled the region from [AREACOORD(cornerA)] through [AREACOORD(cornerB)]")

#undef FILL_WARNING_MIN


code:
/datum/buildmode_mode/mapgen
	key = "mapgen"

	use_corner_selection = TRUE
	var/generator_path

/datum/buildmode_mode/mapgen/show_help(client/c)
	to_chat(c, span_notice("***********************************************************"))
	to_chat(c, span_notice("Left Mouse Button on turf/obj/mob      = Select corner"))
	to_chat(c, span_notice("Right Mouse Button on buildmode button = Select generator"))
	to_chat(c, span_notice("***********************************************************"))

/datum/buildmode_mode/mapgen/change_settings(client/c)
	var/list/gen_paths = subtypesof(/datum/map_generator)
	var/list/options = list()
	for(var/path in gen_paths)
		var/datum/map_generator/MP = path
		options[initial(MP.buildmode_name)] = path
	var/type = input(c,"Select Generator Type","Type") as null|anything in options
	if(!type)
		return

	generator_path = options[type]
	deselect_region()

/datum/buildmode_mode/mapgen/handle_click(client/c, params, obj/object)
	if(isnull(generator_path))
		to_chat(c, span_warning("Select generator type first."))
		deselect_region()
		return
	..()

/datum/buildmode_mode/mapgen/handle_selected_area(client/c, params)
	var/list/modifiers = params2list(params)

	if(LAZYACCESS(modifiers, LEFT_CLICK))
		var/datum/map_generator/G = new generator_path
		if(istype(G, /datum/map_generator/repair/reload_station_map))
			if(GLOB.reloading_map)
				to_chat(c, span_boldwarning("You are already reloading an area! Please wait for it to fully finish loading before trying to load another!"))
				deselect_region()
				return
		G.defineRegion(cornerA, cornerB, 1)
		highlight_region(G.map)
		var/confirm = tgui_alert(usr,"Are you sure you want to run the map generator?", "Run generator", list("Yes", "No"))
		if(confirm == "Yes")
			G.generate()
		log_admin("Build Mode: [key_name(c)] ran the map generator '[G.buildmode_name]' in the region from [AREACOORD(cornerA)] to [AREACOORD(cornerB)]")


code:
/datum/buildmode_mode/outfit
	key = "outfit"
	var/datum/outfit/dressuptime

/datum/buildmode_mode/outfit/Destroy()
	dressuptime = null
	return ..()

/datum/buildmode_mode/outfit/show_help(client/c)
	to_chat(c, "***********************************************************\n\
		Right Mouse Button on buildmode button = Select outfit to equip.\n\
		Left Mouse Button on mob/living/carbon/human = Equip the selected outfit.\n\
		Right Mouse Button on mob/living/carbon/human = Strip and delete current outfit.\n\
		***********************************************************")

/datum/buildmode_mode/outfit/Reset()
	. = ..()
	dressuptime = null

/datum/buildmode_mode/outfit/change_settings(client/c)
	dressuptime = c.robust_dress_shop()

/datum/buildmode_mode/outfit/handle_click(client/c, params, object)
	var/list/modifiers = params2list(params)

	if(!ishuman(object))
		return
	var/mob/living/carbon/human/dollie = object

	if(LAZYACCESS(modifiers, LEFT_CLICK))
		if(isnull(dressuptime))
			to_chat(c, span_warning("Pick an outfit first."))
			return

		for (var/item in dollie.get_equipped_items(TRUE))
			qdel(item)
		if(dressuptime != "Naked")
			dollie.equipOutfit(dressuptime)

	if(LAZYACCESS(modifiers, RIGHT_CLICK))
		for (var/item in dollie.get_equipped_items(TRUE))
			qdel(item)


code:
/datum/buildmode_mode/smite
	key = "smite"
	var/datum/smite/selected_smite

/datum/buildmode_mode/smite/Destroy()
	selected_smite = null
	return ..()

/datum/buildmode_mode/smite/show_help(client/user)
	to_chat(user, "***********************************************************\n\
		Right Mouse Button on buildmode button = Select smite to use.\n\
		Left Mouse Button on mob/living = Smite the mob.\n\
		***********************************************************")

/datum/buildmode_mode/smite/change_settings(client/user)
	var/punishment = input(user, "Choose a punishment", "DIVINE SMITING") as null|anything in GLOB.smites
	var/smite_path = GLOB.smites[punishment]
	var/datum/smite/picking_smite = new smite_path
	var/configuration_success = picking_smite.configure(user)
	if (configuration_success == FALSE)
		return
	selected_smite = picking_smite

/datum/buildmode_mode/smite/handle_click(client/user, params, object)
	var/list/modifiers = params2list(params)

	if (!check_rights(R_ADMIN | R_FUN))
		return

	if (!LAZYACCESS(modifiers, LEFT_CLICK))
		return

	if (!isliving(object))
		return

	if (selected_smite == null)
		to_chat(user, span_notice("No smite selected."))
		return

	selected_smite.effect(user, object)