anchor.diff:  /var/global/toggle_space_ninja = 1//If ninjas can spawn or not.
   /var/global/sent_ninja_to_station = 0//If a ninja is already on the station.
   
  -/proc/space_ninja_arrival()
  +var/ninja_selection_id = 1
  +var/ninja_selection_active = 0
  +var/ninja_confirmed_selection = 0
  +
  +/proc/space_ninja_arrival(var/assign_key = null, var/assign_mission = null)
  +
  +	if(ninja_selection_active)
  +		usr << "\red Ninja selection already in progress. Please wait until it ends."
  +		return
   
   	var/datum/game_mode/current_mode = ticker.mode
   	var/datum/mind/current_mind
  
positive.code: 			if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes")
  				return
  
  	var/list/spawn_list = list()
  	for(var/obj/effect/landmark/L in landmarks_list)
  		if (L.name == "carpspawn")
  			spawn_list.Add(L)
  
  
  	var/input = ckey(input("Pick character to spawn as the Space Ninja", "Key", ""))
  	if(!input)
  		return
  
  	var/mob/dead/observer/G
  	for(var/mob/dead/observer/G_find in player_list)
  		if(G_find.ckey == input)
  			G = G_find
  			break
  
  	if(!G)//If a ghost was not found.
  		alert("There is no active key like that in the game or the person is not currently a ghost. Aborting command.")
  		return
  
  	var/admin_name = src
  	var/mob/living/carbon/human/new_ninja = create_space_ninja(pick(spawn_list.len ? spawn_list : latejoin ))
  	new_ninja.wear_suit:randomize_param()
  
  	new_ninja.key = G.key
  	new_ninja.mind.store_memory("<B>Mission:</B> \red [mission].<br>")
  
  	new_ninja.internal = new_ninja.s_store //So the poor ninja has something to breath when they spawn in spess.
  	new_ninja.internals.icon_state = "internal1"
  	spawn(0)//Parallel process. Will speed things up a bit.
  		new_ninja.wear_suit:ninitialize(10,new_ninja)//If you're wondering why I'm passing the argument to the proc when the default should suffice,
  		//I'm also wondering that same thing. This makes sure it does not run time error though.
  
  	new_ninja << "\blue \nYou are an elite mercenary assassin of the Spider Clan, [new_ninja.real_name]. The dreaded \red <B>SPACE NINJA</B>!\blue You have a variety of abilities at your disposal, thanks to your nano-enhanced cyber armor. Remember your training! \nYour current mission is: \red <B>[mission]</B>"
  
  	message_admins("\blue [admin_name] has spawned [new_ninja.key] as a Space Ninja. Hide yo children! \nTheir <b>mission</b> is: [mission]", 1)
  	log_admin("[admin_name] used Spawn Space Ninja.")
  
  	return
  
  
negative.code: 	//Here we pick a location and spawn the ninja.
  	var/list/spawn_list = list()
  	for(var/obj/effect/landmark/L in landmarks_list)
  		if(L.name == "ninjaspawn")
  			spawn_list.Add(L)
  
  	if(!spawn_list.len)
  		for(var/obj/effect/landmark/L in landmarks_list)
  			if(L.name == "carpspawn")
  				spawn_list.Add(L)
  
  	var/ninja_key = null
  
  	if(assign_key)
  		ninja_key = assign_key
  	else
  
  		var/list/candidates = list()	//list of candidate keys
  		for(var/mob/dead/observer/G in player_list)
  			if(G.client && !G.client.holder && ((G.client.inactivity/10)/60) <= 5)
  				if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
  					candidates += G.key
  		if(!candidates.len)	return
  		candidates = shuffle(candidates)//Incorporating Donkie's list shuffle
  
  		ninja_key = pick(candidates)
  
  
  	var/mob/candidate_mob
  	for(var/mob/M in player_list)
  		if((M.key == ninja_key || M.ckey == ninja_key) && M.client)
  			candidate_mob = M
  			break
  
  	if(!candidate_mob)
  		usr << "\red The randomly chosen mob was not found in the second check."
  		return
  
  	ninja_selection_active = 1
  	ninja_selection_id++
  	var/this_selection_id = ninja_selection_id
  
  	spawn(1)
  		if(alert(candidate_mob, "You have been selected to play as a space ninja. Would you like to play as this role? (You have 30 seconds to accept - You will spawn in 30 seconds if you accept)",,"Yes","No")!="Yes")
  			usr << "\red The selected candidate for space ninja declined."
  			return
  
  		ninja_confirmed_selection = this_selection_id
  
  	spawn(300)
  		if(!ninja_selection_active || (this_selection_id != ninja_selection_id ))
  			ninja_selection_active = 0
  			candidate_mob << "\red Sorry, you were too late. You only had 30 seconds to accept."
  			return
  
  		if(ninja_confirmed_selection != ninja_selection_id)
  			ninja_selection_active = 0
  			usr << "\red The ninja did not accept the role in time."
  			return
  
  		ninja_selection_active = 0
  
  		//The ninja will be created on the right spawn point or at late join.
  		var/mob/living/carbon/human/new_ninja = create_space_ninja(pick(spawn_list.len ? spawn_list : latejoin ))
  		new_ninja.key = ninja_key
  		new_ninja.wear_suit:randomize_param()//Give them a random set of suit parameters.
  		new_ninja.internal = new_ninja.s_store //So the poor ninja has something to breath when they spawn in spess.
  		new_ninja.internals.icon_state = "internal1"
  
  		//Now for the rest of the stuff.
  
  		var/datum/mind/ninja_mind = new_ninja.mind//For easier reference.
  		var/mission_set = 0//To determine if we need to do further processing.
  		//Xenos and deathsquads take precedence over everything else.
  
  		//Unless the xenos are hiding in a locker somewhere, this'll find em.
  		for(var/mob/living/carbon/alien/humanoid/xeno in player_list)
  			if(istype(xeno))
  				xeno_list += xeno
  
  		if(assign_mission)
  			new_ninja.mind.store_memory("<B>Mission:</B> \red [assign_mission].<br>")
  			new_ninja << "\blue \nYou are an elite mercenary assassin of the Spider Clan, [new_ninja.real_name]. The dreaded \red <B>SPACE NINJA</B>!\blue You have a variety of abilities at your disposal, thanks to your nano-enhanced cyber armor. Remember your training! \nYour current mission is: \red <B>[assign_mission]</B>"
  		else
  			if(xeno_list.len>3)//If there are more than three humanoid xenos on the station, time to get dangerous.
  				//Here we want the ninja to murder all the queens. The other aliens don't really matter.
  				var/xeno_queen_list[] = list()
  				for(var/mob/living/carbon/alien/humanoid/queen/xeno_queen in xeno_list)
  					if(xeno_queen.mind&&xeno_queen.stat!=2)
  						xeno_queen_list += xeno_queen
  				if(xeno_queen_list.len&&side=="face")//If there are queen about and the probability is 50.
  					for(var/mob/living/carbon/alien/humanoid/queen/xeno_queen in xeno_queen_list)
  						var/datum/objective/assassinate/ninja_objective = new
  						//We'll do some manual overrides to properly set it up.
  						ninja_objective.owner = ninja_mind
  						ninja_objective.target = xeno_queen.mind
  						ninja_objective.explanation_text = "Kill \the [xeno_queen]."
  						ninja_mind.objectives += ninja_objective
  					mission_set = 1
  
  			if(sent_strike_team&&side=="heel"&&antagonist_list.len)//If a strike team was sent, murder them all like a champ.
  				for(current_mind in antagonist_list)//Search and destroy. Since we already have an antagonist list, they should appear there.
  					if(current_mind && current_mind.special_role=="Death Commando")
  						commando_list += current_mind
  				if(commando_list.len)//If there are living commandos still in play.
  					for(var/mob/living/carbon/human/commando in commando_list)
  						var/datum/objective/assassinate/ninja_objective = new
  						ninja_objective.owner = ninja_mind
  						ninja_objective.find_target_by_role(commando.mind.special_role,1)
  						ninja_mind.objectives += ninja_objective
  					mission_set = 1
  		/*
  		If there are no antogonists left it could mean one of two things:
  			A) The round is about to end. No harm in spawning the ninja here.
  			B) The round is still going and ghosts are probably rioting for something to happen.
  		In either case, it's a good idea to spawn the ninja with a semi-random set of objectives.
  		*/
  			if(!mission_set)//If mission was not set.
  
  				var/current_minds[]//List being looked on in the following code.
  				var/side_list = side=="face" ? 2 : 1//For logic gating.
  				var/hostile_targets[] = list()//The guys actually picked for the assassination or whatever.
  				var/friendly_targets[] = list()//The guys the ninja must protect.
  
  				for(var/i=2,i>0,i--)//Two lists.
  					current_minds = i==2 ? antagonist_list : protagonist_list//Which list are we looking at?
  					for(var/t=3,(current_minds.len&&t>0),t--)//While the list is not empty and targets remain. Also, 3 targets is good.
  						current_mind = pick(current_minds)//Pick a random person.
  						/*I'm creating a logic gate here based on the ninja affiliation that compares the list being
  						looked at to the affiliation. Affiliation is just a number used to compare. Meaning comes from the logic involved.
  						If the list being looked at is equal to the ninja's affiliation, add the mind to hostiles.
  						If not, add the mind to friendlies. Since it can't be both, it will be added only to one or the other.*/
  						hostile_targets += i==side_list ? current_mind : null//Adding null doesn't add anything.
  						friendly_targets += i!=side_list ? current_mind : null
  						current_minds -= current_mind//Remove the mind so it's not picked again.
  
  				var/objective_list[] = list(1,2,3,4,5,6)//To remove later.
  				for(var/i=rand(1,3),i>0,i--)//Want to get a few random objectives. Currently up to 3.
  					if(!hostile_targets.len)//Remove appropriate choices from switch list if the target lists are empty.
  						objective_list -= 1
  						objective_list -= 4
  					if(!friendly_targets.len)
  						objective_list -= 3
  					switch(pick(objective_list))
  						if(1)//kill
  							current_mind = pick(hostile_targets)
  
  							if(current_mind)
  								var/datum/objective/assassinate/ninja_objective = new
  								ninja_objective.owner = ninja_mind
  								ninja_objective.find_target_by_role((current_mind.special_role ? current_mind.special_role : current_mind.assigned_role),(current_mind.special_role?1:0))//If they have a special role, use that instead to find em.
  								ninja_mind.objectives += ninja_objective
  
  							else
  								i++
  
  							hostile_targets -= current_mind//Remove them from the list.
  						if(2)//Steal
  							var/datum/objective/steal/ninja_objective = new
  							var/target_item = pick(ninja_objective.possible_items_special)
  							ninja_objective.set_target(target_item)
  							ninja_mind.objectives += ninja_objective
  
  							objective_list -= 2
  						if(3)//Protect. Keeping people alive can be pretty difficult.
  							current_mind = pick(friendly_targets)
  
  							if(current_mind)
  
  								var/datum/objective/protect/ninja_objective = new
  								ninja_objective.owner = ninja_mind
  								ninja_objective.find_target_by_role((current_mind.special_role ? current_mind.special_role : current_mind.assigned_role),(current_mind.special_role?1:0))
  								ninja_mind.objectives += ninja_objective
  
  							else
  								i++
  
  							friendly_targets -= current_mind
  						if(4)//Debrain
  							current_mind = pick(hostile_targets)
  
  							if(current_mind)
  
  								var/datum/objective/debrain/ninja_objective = new
  								ninja_objective.owner = ninja_mind
  								ninja_objective.find_target_by_role((current_mind.special_role ? current_mind.special_role : current_mind.assigned_role),(current_mind.special_role?1:0))
  								ninja_mind.objectives += ninja_objective
  
  							else
  								i++
  
  							hostile_targets -= current_mind//Remove them from the list.
  						if(5)//Download research
  							var/datum/objective/download/ninja_objective = new
  							ninja_objective.gen_amount_goal()
  							ninja_mind.objectives += ninja_objective
  
  							objective_list -= 5
  						if(6)//Capture
  							var/datum/objective/capture/ninja_objective = new
  							ninja_objective.gen_amount_goal()
  							ninja_mind.objectives += ninja_objective
  
  							objective_list -= 6
  
  				if(ninja_mind.objectives.len)//If they got some objectives out of that.
  					mission_set = 1
  
  			if(!ninja_mind.objectives.len||!mission_set)//If they somehow did not get an objective at this point, time to destroy the station.
  				var/nuke_code
  				var/temp_code
  				for(var/obj/machinery/nuclearbomb/N in world)
  					temp_code = text2num(N.r_code)
  					if(temp_code)//if it's actually a number. It won't convert any non-numericals.
  						nuke_code = N.r_code
  						break
  				if(nuke_code)//If there is a nuke device in world and we got the code.
  					var/datum/objective/nuclear/ninja_objective = new//Fun.
  					ninja_objective.owner = ninja_mind
  					ninja_objective.explanation_text = "Destroy the station with a nuclear device. The code is [nuke_code]." //Let them know what the code is.
  
  			//Finally add a survival objective since it's usually broad enough for any round type.
  			var/datum/objective/survive/ninja_objective = new
  			ninja_objective.owner = ninja_mind
  			ninja_mind.objectives += ninja_objective
  
  			var/directive = generate_ninja_directive(side)
  			new_ninja << "\blue \nYou are an elite mercenary assassin of the Spider Clan, [new_ninja.real_name]. The dreaded \red <B>SPACE NINJA</B>!\blue You have a variety of abilities at your disposal, thanks to your nano-enhanced cyber armor. Remember your training (initialize your suit by right clicking on it)! \nYour current directive is: \red <B>[directive]</B>"
  			new_ninja.mind.store_memory("<B>Directive:</B> \red [directive]<br>")
  
  			var/obj_count = 1
  			new_ninja << "\blue Your current objectives:"
  			for(var/datum/objective/objective in ninja_mind.objectives)
  				new_ninja << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
  				obj_count++
  
  		sent_ninja_to_station = 1//And we're done.
  		return new_ninja//Return the ninja in case we need to reference them later.
  
  /*
  This proc will give the ninja a directive to follow. They are not obligated to do so but it's a fun roleplay reminder.
  