code:
/datum/round_event_control/portal_storm_syndicate
	name = "Portal Storm: Syndicate Shocktroops"
	typepath = /datum/round_event/portal_storm/syndicate_shocktroop
	weight = 2
	min_players = 15
	earliest_start = 18000

/datum/round_event/portal_storm/syndicate_shocktroop
	boss_types = list(/mob/living/simple_animal/hostile/syndicate/melee/space/stormtrooper = 2)
	hostile_types = list(/mob/living/simple_animal/hostile/syndicate/melee/space/noloot = 8,\
						/mob/living/simple_animal/hostile/syndicate/ranged/space/noloot = 2)

/datum/round_event_control/portal_storm_narsie
	name = "Portal Storm: Nar-sie"
	typepath = /datum/round_event/portal_storm/portal_storm_narsie
	weight = 0
	max_occurrences = 0

/datum/round_event/portal_storm/portal_storm_narsie
	boss_types = list(/obj/singularity/narsie/large = 1)
	hostile_types = list(/mob/living/simple_animal/hostile/construct/armored/hostile = 10,\
						/mob/living/simple_animal/hostile/construct/wraith/hostile = 10)

/datum/round_event/portal_storm
	startWhen = 7
	endWhen = 999
	announceWhen = 1

	var/list/boss_spawn = list()
	var/list/boss_types = list() //only configure this if you have hostiles
	var/number_of_bosses
	var/next_boss_spawn
	var/list/hostiles_spawn = list()
	var/list/hostile_types = list()
	var/number_of_hostiles
	var/list/station_areas = list()
	var/image/storm

/datum/round_event/portal_storm/setup()
	storm = image('icons/obj/tesla_engine/energy_ball.dmi', "energy_ball_fast", layer=FLY_LAYER)
	storm.color = "#00FF00"

	station_areas = get_areas_in_z(ZLEVEL_STATION)

	number_of_bosses = 0
	for(var/boss in boss_types)
		number_of_bosses += boss_types[boss]

	number_of_hostiles = 0
	for(var/hostile in hostile_types)
		number_of_hostiles += hostile_types[hostile]

	var/list/b_spawns = generic_event_spawns.Copy()
	while(number_of_bosses > boss_spawn.len)
		var/turf/F = get_turf(pick_n_take(b_spawns))
		if(!F)
			F = safepick(get_area_turfs(pick(station_areas)))
		boss_spawn += F

	var/list/h_spawns = generic_event_spawns.Copy()
	while(number_of_hostiles > hostiles_spawn.len)
		var/turf/T = get_turf(pick_n_take(h_spawns))
		if(!T)
			T = safepick(get_area_turfs(pick(station_areas)))
		hostiles_spawn += T

	next_boss_spawn = startWhen + Ceiling(2 * number_of_hostiles / number_of_bosses)

/datum/round_event/portal_storm/announce()
	set waitfor = 0
	playsound_global('sound/magic/lightning_chargeup.ogg', repeat=0, channel=1, volume=100)
	sleep(80)
	priority_announce("Massive bluespace anomaly detected en route to [station_name()]. Brace for impact.")
	sleep(20)
	playsound_global('sound/magic/lightningbolt.ogg', repeat=0, channel=1, volume=100)

/datum/round_event/portal_storm/tick()
	spawn_effects()

	if(spawn_hostile())
		var/type = safepick(hostile_types)
		hostile_types[type] = hostile_types[type] - 1
		spawn_mob(type, hostiles_spawn)
		if(!hostile_types[type])
			hostile_types -= type

	if(spawn_boss())
		var/type = safepick(boss_types)
		boss_types[type] = boss_types[type] - 1
		spawn_mob(type, boss_spawn)
		if(!boss_types[type])
			boss_types -= type

	time_to_end()

/datum/round_event/portal_storm/proc/spawn_mob(type, spawn_list)
	if(!type)
		return
	var/turf/T = pick_n_take(spawn_list)
	if(!T)
		return
	new type(T)
	spawn_effects(T)

/datum/round_event/portal_storm/proc/spawn_effects(turf/T)
	if(T)
		T = get_step(T, SOUTHWEST) //align center of image with turf
		flick_overlay_static(storm, T, 15)
		playsound(T, 'sound/magic/lightningbolt.ogg', 100, 1)
	else
		for(var/V in station_areas)
			var/area/A = V
			var/turf/F = get_turf(pick(A.contents))
			flick_overlay_static(storm, F, 15)
			playsound(F, 'sound/magic/lightningbolt.ogg', 80, 1)

/datum/round_event/portal_storm/proc/spawn_hostile()
	if(!hostile_types || !hostile_types.len)
		return 0
	return IsMultiple(activeFor, 2)

/datum/round_event/portal_storm/proc/spawn_boss()
	if(!boss_types || !boss_types.len)
		return 0

	if(activeFor == next_boss_spawn)
		next_boss_spawn += Ceiling(number_of_hostiles / number_of_bosses)
		return 1

/datum/round_event/portal_storm/proc/time_to_end()
	if(!hostile_types.len && !boss_types.len)
		endWhen = activeFor

	if(!number_of_hostiles && number_of_bosses)
		endWhen = activeFor


code:
/datum/round_event_control/prison_break
	name = "Prison Break"
	typepath = /datum/round_event/prison_break
	max_occurrences = 2
	min_players = 5

/datum/round_event/prison_break
	announceWhen = 50
	endWhen = 20
	var/list/area/prisonAreas = list()

/datum/round_event/prison_break/setup()
	announceWhen = rand(50, 60)
	endWhen = rand(20, 30)

	for(var/area/security/A in world)
		if(istype(A, /area/security/prison) || istype(A, /area/security/brig))
			prisonAreas += A

/datum/round_event/prison_break/announce()
	if(prisonAreas && prisonAreas.len > 0)
		priority_announce("Gr3y.T1d3 virus detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert")
	else
		world.log << "ERROR: Could not initate grey-tide. Unable find prison or brig area."
		kill()

/datum/round_event/prison_break/start()
	for(var/area/A in prisonAreas)
		for(var/obj/machinery/light/L in A)
			L.flicker(10)

/datum/round_event/prison_break/end()
	for(var/area/A in prisonAreas)
		for(var/obj/O in A)
			if(istype(O,/obj/machinery/power/apc))
				var/obj/machinery/power/apc/temp = O
				temp.overload_lighting()
			else if(istype(O,/obj/structure/closet/secure_closet/brig))
				var/obj/structure/closet/secure_closet/brig/temp = O
				temp.locked = 0
				temp.update_icon()
			else if(istype(O,/obj/machinery/door/airlock/security))
				var/obj/machinery/door/airlock/security/temp = O
				temp.prison_open()
			else if(istype(O,/obj/machinery/door/airlock/glass_security))
				var/obj/machinery/door/airlock/glass_security/temp = O
				temp.prison_open()
			else if(istype(O,/obj/machinery/door_timer))
				var/obj/machinery/door_timer/temp = O
				temp.timer_end(forced = TRUE)

license: mit


code:
/datum/round_event_control/radiation_storm
	name = "Radiation Storm"
	typepath = /datum/round_event/radiation_storm
	max_occurrences = 1

/datum/round_event/radiation_storm
	var/list/protected_areas = list(/area/maintenance, /area/turret_protected/ai_upload, /area/turret_protected/ai_upload_foyer, /area/turret_protected/ai)

/datum/round_event/radiation_storm/setup()
	startWhen = rand(10, 20)
	endWhen = startWhen + 5
	announceWhen	= 1

/datum/round_event/radiation_storm/announce()
	priority_announce("High levels of radiation detected near the station. Maintenance is best shielded from radiation.", "Anomaly Alert", 'sound/AI/radiation.ogg')
	//sound not longer matches the text, but an audible warning is probably good

/datum/round_event/radiation_storm/start()
	for(var/mob/living/carbon/C in living_mob_list)
		var/turf/T = get_turf(C)
		if(!T)
			continue
		if(T.z != 1)
			continue

		var/skip = 0
		for(var/a in protected_areas)
			if(istype(T.loc, a))
				skip = 1
				continue

		if(skip)
			continue

		if(locate(/obj/machinery/power/apc) in T)	//damn you maint APCs!!
			continue

		if(istype(C, /mob/living/carbon/human))
			var/mob/living/carbon/human/H = C
			if(prob(5))
				H.rad_act(rand(100, 160))
			else
				H.rad_act(rand(15, 75))
			if(prob(25))
				if(prob(75))
					randmutb(H)
				else
					randmutg(H)
				H.domutcheck()

		else if(istype(C, /mob/living/carbon/monkey))
			var/mob/living/carbon/monkey/M = C
			M.rad_act(rand(15, 75))

/datum/round_event/radiation_storm/end()
	priority_announce("The radiation threat has passed. Please return to your workplaces.", "Anomaly Alert")


code:
#define HIJACK_SYNDIE 1
#define RUSKY_PARTY 2
#define SPIDER_GIFT 3
#define DEPARTMENT_RESUPPLY 4
#define ANTIDOTE_NEEDED 5

/datum/round_event_control/shuttle_loan
	name = "Shuttle loan"
	typepath = /datum/round_event/shuttle_loan
	max_occurrences = 1
	earliest_start = 4000

/datum/round_event/shuttle_loan
	announceWhen = 1
	endWhen = 500
	var/dispatched = 0
	var/dispatch_type = 0
	var/bonus_points = 10000
	var/thanks_msg = "The cargo shuttle should return in five minutes. Have some supply points for your trouble."

/datum/round_event/shuttle_loan/start()
	dispatch_type = pick(HIJACK_SYNDIE, RUSKY_PARTY, SPIDER_GIFT, DEPARTMENT_RESUPPLY, ANTIDOTE_NEEDED)

/datum/round_event/shuttle_loan/announce()
	SSshuttle.shuttle_loan = src
	switch(dispatch_type)
		if(HIJACK_SYNDIE)
			priority_announce("Cargo: The syndicate are trying to infiltrate your station. If you let them hijack your cargo shuttle, you'll save us a headache.","Centcom Counter Intelligence")
		if(RUSKY_PARTY)
			priority_announce("Cargo: A group of angry russians want to have a party, can you send them your cargo shuttle then make them disappear?","Centcom Russian Outreach Program")
		if(SPIDER_GIFT)
			priority_announce("Cargo: The Spider Clan has sent us a mysterious gift, can we ship it to you to see what's inside?","Centcom Diplomatic Corps")
		if(DEPARTMENT_RESUPPLY)
			priority_announce("Cargo: Seems we've ordered doubles of our department resupply packages this month. Can we send them to you?","Centcom Supply Department")
			thanks_msg = "The cargo shuttle should return in 5 minutes."
			bonus_points = 0
		if(ANTIDOTE_NEEDED)
			priority_announce("Cargo: Your station has been chosen for an epidemiological research project. Send us your cargo shuttle to receive your research samples.", "Centcom Research Initiatives")

/datum/round_event/shuttle_loan/proc/loan_shuttle()
	priority_announce(thanks_msg, "Cargo shuttle commandeered by Centcom.")

	dispatched = 1
	SSshuttle.points += bonus_points
	endWhen = activeFor + 1

	SSshuttle.supply.sell()
	SSshuttle.supply.enterTransit()
	if(SSshuttle.supply.z != ZLEVEL_STATION)
		SSshuttle.supply.mode = SHUTTLE_CALL
		SSshuttle.supply.destination = SSshuttle.getDock("supply_home")
	else
		SSshuttle.supply.mode = SHUTTLE_RECALL
	SSshuttle.supply.setTimer(3000)

	switch(dispatch_type)
		if(HIJACK_SYNDIE)
			SSshuttle.centcom_message += "Syndicate hijack team incoming."
		if(RUSKY_PARTY)
			SSshuttle.centcom_message += "Partying Russians incoming."
		if(SPIDER_GIFT)
			SSshuttle.centcom_message += "Spider Clan gift incoming."
		if(DEPARTMENT_RESUPPLY)
			SSshuttle.centcom_message += "Department resupply incoming."
		if(ANTIDOTE_NEEDED)
			SSshuttle.centcom_message += "Virus samples incoming."

/datum/round_event/shuttle_loan/tick()
	if(dispatched)
		if(SSshuttle.supply.mode != SHUTTLE_IDLE)
			endWhen = activeFor
		else
			endWhen = activeFor + 1

/datum/round_event/shuttle_loan/end()
	if(SSshuttle.shuttle_loan && SSshuttle.shuttle_loan.dispatched)
		//make sure the shuttle was dispatched in time
		SSshuttle.shuttle_loan = null

		var/list/empty_shuttle_turfs = list()
		for(var/turf/open/floor/T in SSshuttle.supply.areaInstance)
			if(T.density || T.contents.len)
				continue
			empty_shuttle_turfs += T
		if(!empty_shuttle_turfs.len)
			return

		var/list/shuttle_spawns = list()
		switch(dispatch_type)
			if(HIJACK_SYNDIE)
				var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/emergency/specialops]
				pack.generate(pick_n_take(empty_shuttle_turfs))

				shuttle_spawns.Add(/mob/living/simple_animal/hostile/syndicate)
				shuttle_spawns.Add(/mob/living/simple_animal/hostile/syndicate)
				if(prob(75))
					shuttle_spawns.Add(/mob/living/simple_animal/hostile/syndicate)
				if(prob(50))
					shuttle_spawns.Add(/mob/living/simple_animal/hostile/syndicate)

			if(RUSKY_PARTY)
				var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/organic/party]
				pack.generate(pick_n_take(empty_shuttle_turfs))

				shuttle_spawns.Add(/mob/living/simple_animal/hostile/russian)
				shuttle_spawns.Add(/mob/living/simple_animal/hostile/russian/ranged)	//drops a mateba
				shuttle_spawns.Add(/mob/living/simple_animal/hostile/bear)
				if(prob(75))
					shuttle_spawns.Add(/mob/living/simple_animal/hostile/russian)
				if(prob(50))
					shuttle_spawns.Add(/mob/living/simple_animal/hostile/bear)

			if(SPIDER_GIFT)
				var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/emergency/specialops]
				pack.generate(pick_n_take(empty_shuttle_turfs))

				shuttle_spawns.Add(/mob/living/simple_animal/hostile/poison/giant_spider)
				shuttle_spawns.Add(/mob/living/simple_animal/hostile/poison/giant_spider)
				shuttle_spawns.Add(/mob/living/simple_animal/hostile/poison/giant_spider/nurse)
				if(prob(50))
					shuttle_spawns.Add(/mob/living/simple_animal/hostile/poison/giant_spider/hunter)

				var/turf/T = pick(empty_shuttle_turfs)
				empty_shuttle_turfs.Remove(T)

				new /obj/effect/decal/remains/human(T)
				new /obj/item/clothing/shoes/space_ninja(T)
				new /obj/item/clothing/mask/balaclava(T)

				T = pick(empty_shuttle_turfs)
				new /obj/effect/spider/stickyweb(T)
				T = pick(empty_shuttle_turfs)
				new /obj/effect/spider/stickyweb(T)
				T = pick(empty_shuttle_turfs)
				new /obj/effect/spider/stickyweb(T)
				T = pick(empty_shuttle_turfs)
				new /obj/effect/spider/stickyweb(T)
				T = pick(empty_shuttle_turfs)
				new /obj/effect/spider/stickyweb(T)

			if(ANTIDOTE_NEEDED)
				var/virus_type = pick(/datum/disease/beesease, /datum/disease/brainrot, /datum/disease/fluspanish)
				var/turf/T
				for(var/i=0, i<10, i++)
					if(prob(15))
						shuttle_spawns.Add(/obj/item/weapon/reagent_containers/glass/bottle)
					else if(prob(15))
						shuttle_spawns.Add(/obj/item/weapon/reagent_containers/syringe)
					else if(prob(25))
						shuttle_spawns.Add(/obj/item/weapon/shard)
					T = pick_n_take(empty_shuttle_turfs)
					var/obj/effect/decal/cleanable/blood/b = new(T)
					var/datum/disease/D = new virus_type()
					D.longevity = 1000
					b.viruses += D
					D.holder = b
				shuttle_spawns.Add(/obj/structure/closet/crate)
				shuttle_spawns.Add(/obj/item/weapon/reagent_containers/glass/bottle/pierrot_throat)
				shuttle_spawns.Add(/obj/item/weapon/reagent_containers/glass/bottle/magnitis)

			if(DEPARTMENT_RESUPPLY)
				var/list/crate_types = list(
					/datum/supply_pack/emergency/equipment,
					/datum/supply_pack/security/supplies,
					/datum/supply_pack/organic/food,
					/datum/supply_pack/emergency/weedcontrol,
					/datum/supply_pack/engineering/tools,
					/datum/supply_pack/engineering/engiequipment,
					/datum/supply_pack/science/robotics,
					/datum/supply_pack/science/plasma,
					/datum/supply_pack/medical/supplies
					)
				for(var/crate in crate_types)
					var/datum/supply_pack/pack = SSshuttle.supply_packs[crate]
					pack.generate(pick_n_take(empty_shuttle_turfs))

				for(var/i in 1 to 5)
					var/decal = pick(/obj/effect/decal/cleanable/flour, /obj/effect/decal/cleanable/robot_debris, /obj/effect/decal/cleanable/oil)
					new decal(pick_n_take(empty_shuttle_turfs))

		var/false_positive = 0
		while(shuttle_spawns.len && empty_shuttle_turfs.len)
			var/turf/T = pick_n_take(empty_shuttle_turfs)
			if(T.contents.len && false_positive < 5)
				false_positive++
				continue

			var/spawn_type = pick_n_take(shuttle_spawns)
			new spawn_type(T)

#undef HIJACK_SYNDIE
#undef RUSKY_PARTY
#undef SPIDER_GIFT
#undef DEPARTMENT_RESUPPLY
#undef ANTIDOTE_NEEDED


code:
/datum/round_event_control/spacevine
	name = "Spacevine"
	typepath = /datum/round_event/spacevine
	weight = 15
	max_occurrences = 3
	min_players = 10

/datum/round_event/spacevine/start()
	var/list/turfs = list() //list of all the empty floor turfs in the hallway areas

	var/obj/effect/spacevine/SV = new()

	for(var/area/hallway/A in world)
		for(var/turf/F in A)
			if(F.Enter(SV))
				turfs += F

	qdel(SV)

	if(turfs.len) //Pick a turf to spawn at if we can
		var/turf/T = pick(turfs)
		new/obj/effect/spacevine_controller(T) //spawn a controller at turf

/datum/spacevine_mutation
	var/name = ""
	var/severity = 1
	var/hue
	var/quality

/datum/spacevine_mutation/proc/process_mutation(obj/effect/spacevine/holder)
	return

/datum/spacevine_mutation/proc/process_temperature(obj/effect/spacevine/holder, temp, volume)
	return

/datum/spacevine_mutation/proc/on_birth(obj/effect/spacevine/holder)
	return

/datum/spacevine_mutation/proc/on_grow(obj/effect/spacevine/holder)
	return

/datum/spacevine_mutation/proc/on_death(obj/effect/spacevine/holder)
	return

/datum/spacevine_mutation/proc/on_hit(obj/effect/spacevine/holder, mob/hitter, obj/item/I)
	return

/datum/spacevine_mutation/proc/on_cross(obj/effect/spacevine/holder, mob/crosser)
	return

/datum/spacevine_mutation/proc/on_chem(obj/effect/spacevine/holder, datum/reagent/R)
	return

/datum/spacevine_mutation/proc/on_eat(obj/effect/spacevine/holder, mob/living/eater)
	return

/datum/spacevine_mutation/proc/on_spread(obj/effect/spacevine/holder, turf/target)
	return

/datum/spacevine_mutation/proc/on_buckle(obj/effect/spacevine/holder, mob/living/buckled)
	return

/datum/spacevine_mutation/proc/on_explosion(severity, target, obj/effect/spacevine/holder)
	return

/datum/spacevine_mutation/space_covering
	name = "space protective"
	hue = "#aa77aa"
	quality = POSITIVE

/turf/open/floor/vines
	color = "#aa77aa"
	icon_state = "vinefloor"
	broken_states = list()

//All of this shit is useless for vines

/turf/open/floor/vines/attackby()
	return

/turf/open/floor/vines/burn_tile()
	return

/turf/open/floor/vines/break_tile()
	return

/turf/open/floor/vines/make_plating()
	return

/turf/open/floor/vines/break_tile_to_plating()
	return

/turf/open/floor/vines/ex_act(severity, target)
	if(severity < 3 || target == src)
		ChangeTurf(src.baseturf)

/turf/open/floor/vines/narsie_act()
	if(prob(20))
		ChangeTurf(src.baseturf) //nar sie eats this shit

/turf/open/floor/vines/singularity_pull(S, current_size)
	if(current_size >= STAGE_FIVE)
		if(prob(50))
			ChangeTurf(src.baseturf)

/turf/open/floor/vines/ChangeTurf(turf/open/floor/T)
	for(var/obj/effect/spacevine/SV in src)
		qdel(SV)
	..()
	UpdateAffectingLights()

/datum/spacevine_mutation/space_covering/on_grow(obj/effect/spacevine/holder)
	if(istype(holder.loc, /turf/open/space))
		var/turf/open/spaceturf = holder.loc
		spaceturf.ChangeTurf(/turf/open/floor/vines)

/datum/spacevine_mutation/space_covering/process_mutation(obj/effect/spacevine/holder)
	if(istype(holder.loc, /turf/open/space))
		var/turf/open/spaceturf = holder.loc
		spaceturf.ChangeTurf(/turf/open/floor/vines)

/datum/spacevine_mutation/space_covering/on_death(obj/effect/spacevine/holder)
	if(istype(holder.loc, /turf/open/floor/vines))
		var/turf/open/spaceturf = holder.loc
		spawn(0)
			spaceturf.ChangeTurf(/turf/open/space)

/datum/spacevine_mutation/bluespace
	name = "bluespace"
	hue = "#3333ff"
	quality = MINOR_NEGATIVE

/datum/spacevine_mutation/bluespace/on_spread(obj/effect/spacevine/holder, turf/target)
	if(holder.energy > 1 && !locate(/obj/effect/spacevine) in target)
		holder.master.spawn_spacevine_piece(target, holder)

/datum/spacevine_mutation/light
	name = "light"
	hue = "#ffff00"
	quality = POSITIVE
	severity = 4

/datum/spacevine_mutation/light/on_grow(obj/effect/spacevine/holder)
	if(holder.energy)
		holder.SetLuminosity(severity, 3)

/datum/spacevine_mutation/toxicity
	name = "toxic"
	hue = "#ff00ff"
	severity = 10
	quality = NEGATIVE

/datum/spacevine_mutation/toxicity/on_cross(obj/effect/spacevine/holder, mob/living/crosser)
	if(issilicon(crosser))
		return
	if(prob(severity) && istype(crosser))
		crosser << "You accidently touch the vine and feel a strange sensation."
		crosser.adjustToxLoss(5)

/datum/spacevine_mutation/toxicity/on_eat(obj/effect/spacevine/holder, mob/living/eater)
	eater.adjustToxLoss(5)

/datum/spacevine_mutation/explosive  //OH SHIT IT CAN CHAINREACT RUN!!!
	name = "explosive"
	hue = "#ff0000"
	quality = NEGATIVE
	severity = 2

/datum/spacevine_mutation/explosive/on_explosion(explosion_severity, target, obj/effect/spacevine/holder)
	if(explosion_severity < 3)
		qdel(src)
	else
		. = 1
		spawn(5)
			qdel(src)

/datum/spacevine_mutation/explosive/on_death(obj/effect/spacevine/holder, mob/hitter, obj/item/I)
	explosion(holder.loc, 0, 0, severity, 0, 0)

/datum/spacevine_mutation/fire_proof
	name = "fire proof"
	hue = "#ff8888"
	quality = MINOR_NEGATIVE

/datum/spacevine_mutation/fire_proof/process_temperature(obj/effect/spacevine/holder, temp, volume)
	return 1

/datum/spacevine_mutation/vine_eating
	name = "vine eating"
	hue = "#ff7700"
	quality = MINOR_NEGATIVE

/datum/spacevine_mutation/vine_eating/on_spread(obj/effect/spacevine/holder, turf/target)
	var/obj/effect/spacevine/prey = locate() in target
	if(prey && !prey.mutations.Find(src))  //Eat all vines that are not of the same origin
		qdel(prey)

/datum/spacevine_mutation/aggressive_spread  //very OP, but im out of other ideas currently
	name = "aggressive spreading"
	hue = "#333333"
	severity = 3
	quality = NEGATIVE

/datum/spacevine_mutation/aggressive_spread/on_spread(obj/effect/spacevine/holder, turf/target)
	target.ex_act(severity, src)

/datum/spacevine_mutation/aggressive_spread/on_buckle(obj/effect/spacevine/holder, mob/living/buckled)
	buckled.ex_act(severity)

/datum/spacevine_mutation/transparency
	name = "transparent"
	hue = ""
	quality = POSITIVE

/datum/spacevine_mutation/transparency/on_grow(obj/effect/spacevine/holder)
	holder.SetOpacity(0)
	holder.alpha = 125

/datum/spacevine_mutation/oxy_eater
	name = "oxygen consuming"
	hue = "#ffff88"
	severity = 3
	quality = NEGATIVE

/datum/spacevine_mutation/oxy_eater/process_mutation(obj/effect/spacevine/holder)
	var/turf/open/floor/T = holder.loc
	if(istype(T))
		var/datum/gas_mixture/GM = T.air
		if(!GM.gases["o2"])
			return
		GM.gases["o2"][MOLES] -= severity * holder.energy
		GM.garbage_collect()

/datum/spacevine_mutation/nitro_eater
	name = "nitrogen consuming"
	hue = "#8888ff"
	severity = 3
	quality = NEGATIVE

/datum/spacevine_mutation/nitro_eater/process_mutation(obj/effect/spacevine/holder)
	var/turf/open/floor/T = holder.loc
	if(istype(T))
		var/datum/gas_mixture/GM = T.air
		if(!GM.gases["n2"])
			return
		GM.gases["n2"][MOLES] -= severity * holder.energy
		GM.garbage_collect()

/datum/spacevine_mutation/carbondioxide_eater
	name = "CO2 consuming"
	hue = "#00ffff"
	severity = 3
	quality = POSITIVE

/datum/spacevine_mutation/carbondioxide_eater/process_mutation(obj/effect/spacevine/holder)
	var/turf/open/floor/T = holder.loc
	if(istype(T))
		var/datum/gas_mixture/GM = T.air
		if(!GM.gases["co2"])
			return
		GM.gases["co2"][MOLES] -= severity * holder.energy
		GM.garbage_collect()

/datum/spacevine_mutation/plasma_eater
	name = "toxins consuming"
	hue = "#ffbbff"
	severity = 3
	quality = POSITIVE

/datum/spacevine_mutation/plasma_eater/process_mutation(obj/effect/spacevine/holder)
	var/turf/open/floor/T = holder.loc
	if(istype(T))
		var/datum/gas_mixture/GM = T.air
		if(!GM.gases["plasma"])
			return
		GM.gases["plasma"][MOLES] -= severity * holder.energy
		GM.garbage_collect()

/datum/spacevine_mutation/thorns
	name = "thorny"
	hue = "#666666"
	severity = 10
	quality = NEGATIVE

/datum/spacevine_mutation/thorns/on_cross(obj/effect/spacevine/holder, mob/living/crosser)
	if(prob(severity) && istype(crosser))
		var/mob/living/M = crosser
		M.adjustBruteLoss(5)
		M << "You cut yourself on the thorny vines."

/datum/spacevine_mutation/thorns/on_hit(obj/effect/spacevine/holder, mob/living/hitter)
	if(prob(severity) && istype(hitter))
		var/mob/living/M = hitter
		M.adjustBruteLoss(5)
		M << "You cut yourself on the thorny vines."

/datum/spacevine_mutation/woodening
	name = "hardened"
	hue = "#997700"
	quality = NEGATIVE

/datum/spacevine_mutation/woodening/on_grow(obj/effect/spacevine/holder)
	if(holder.energy)
		holder.density = 1

/datum/spacevine_mutation/woodening/on_hit(obj/effect/spacevine/holder, mob/hitter, obj/item/I)
	if(hitter)
		var/chance
		if(I)
			chance = I.force * 2
		else
			chance = 8
		if(prob(chance))
			qdel(holder)
	return 1

/datum/spacevine_mutation/flowering
	name = "flowering"
	hue = "#0A480D"
	quality = NEGATIVE
	severity = 10

/datum/spacevine_mutation/flowering/on_grow(obj/effect/spacevine/holder)
	if(holder.energy == 2 && prob(severity) && !locate(/obj/structure/alien/resin/flower_bud_enemy) in range(5,holder))
		var/obj/structure/alien/resin/flower_bud_enemy/FBE = new /obj/structure/alien/resin/flower_bud_enemy (get_turf(holder))
		FBE.layer = holder.layer+0.1

/datum/spacevine_mutation/flowering/on_cross(obj/effect/spacevine/holder, mob/living/crosser)
	holder.entangle(crosser)

// SPACE VINES (Note that this code is very similar to Biomass code)
/obj/effect/spacevine
	name = "space vines"
	desc = "An extremely expansionistic species of vine."
	icon = 'icons/effects/spacevines.dmi'
	icon_state = "Light1"
	anchored = 1
	density = 0
	layer = MOB_LAYER + 0.8
	mouse_opacity = 2 //Clicking anywhere on the turf is good enough
	pass_flags = PASSTABLE | PASSGRILLE
	var/energy = 0
	var/obj/effect/spacevine_controller/master = null
	var/list/mutations = list()

/obj/effect/spacevine/Destroy()
	for(var/datum/spacevine_mutation/SM in mutations)
		SM.on_death(src)
	if(master)
		master.vines -= src
		master.growth_queue -= src
		if(!master.vines.len)
			var/obj/item/seeds/kudzu/KZ = new(loc)
			KZ.mutations |= mutations
			KZ.potency = min(100, master.mutativness * 10)
			KZ.production = (master.spread_cap / initial(master.spread_cap)) * 50
	mutations = list()
	SetOpacity(0)
	if(buckled_mobs.len)
		unbuckle_all_mobs(force=1)
	return ..()

/obj/effect/spacevine/proc/on_chem_effect(datum/reagent/R)
	var/override = 0
	for(var/datum/spacevine_mutation/SM in mutations)
		override += SM.on_chem(src, R)
	if(!override && istype(R, /datum/reagent/toxin/plantbgone))
		if(prob(50))
			qdel(src)

/obj/effect/spacevine/proc/eat(mob/eater)
	var/override = 0
	for(var/datum/spacevine_mutation/SM in mutations)
		override += SM.on_eat(src, eater)
	if(!override)
		if(prob(10))
			eater.say("Nom")
		qdel(src)

/obj/effect/spacevine/attackby(obj/item/weapon/W, mob/user, params)
	if (!W || !user || !W.type)
		return
	user.changeNext_move(CLICK_CD_MELEE)

	var/override = 0

	for(var/datum/spacevine_mutation/SM in mutations)
		override += SM.on_hit(src, user)

	if(override)
		..()
		return

	if(istype(W, /obj/item/weapon/scythe))
		for(var/obj/effect/spacevine/B in orange(1,src))
			if(prob(80))
				qdel(B)
		qdel(src)

	else if(W.is_sharp())
		qdel(src)

	else if(istype(W, /obj/item/weapon/weldingtool))
		var/obj/item/weapon/weldingtool/WT = W
		if(WT.remove_fuel(0, user))
			qdel(src)
		else
			user_unbuckle_mob(user,user)
			return
		//Plant-b-gone damage is handled in its entry in chemistry-reagents.dm
	..()

/obj/effect/spacevine/Crossed(mob/crosser)
	if(isliving(crosser))
		for(var/datum/spacevine_mutation/SM in mutations)
			SM.on_cross(src, crosser)

/obj/effect/spacevine/attack_hand(mob/user)
	for(var/datum/spacevine_mutation/SM in mutations)
		SM.on_hit(src, user)
	user_unbuckle_mob(user, user)

/obj/effect/spacevine/attack_paw(mob/living/user)
	user.do_attack_animation(src)
	for(var/datum/spacevine_mutation/SM in mutations)
		SM.on_hit(src, user)
	user_unbuckle_mob(user,user)

/obj/effect/spacevine_controller
	invisibility = 101
	var/list/obj/effect/spacevine/vines = list()
	var/list/growth_queue = list()
	var/spread_multiplier = 5
	var/spread_cap = 30
	var/list/mutations_list = list()
	var/mutativness = 1

/obj/effect/spacevine_controller/New(loc, list/muts, mttv, spreading)
	spawn_spacevine_piece(loc, , muts)
	SSobj.processing |= src
	init_subtypes(/datum/spacevine_mutation/, mutations_list)
	if(mttv != null)
		mutativness = mttv / 10
	if(spreading != null)
		spread_cap *= spreading / 50
		spread_multiplier /= spreading / 50

/obj/effect/spacevine_controller/ex_act() //only killing all vines will end this suffering
	return

/obj/effect/spacevine_controller/singularity_act()
	return

/obj/effect/spacevine_controller/singularity_pull()
	return

/obj/effect/spacevine_controller/Destroy()
	SSobj.processing.Remove(src)
	return ..()

/obj/effect/spacevine_controller/proc/spawn_spacevine_piece(turf/location, obj/effect/spacevine/parent, list/muts)
	var/obj/effect/spacevine/SV = new(location)
	growth_queue += SV
	vines += SV
	SV.master = src
	if(muts && muts.len)
		SV.mutations |= muts
	if(parent)
		SV.mutations |= parent.mutations
		SV.color = parent.color
		SV.desc = parent.desc
		if(prob(mutativness))
			SV.mutations |= pick(mutations_list)
			var/datum/spacevine_mutation/randmut = pick(SV.mutations)
			SV.color = randmut.hue
			SV.desc = "An extremely expansionistic species of vine. These are "
			for(var/datum/spacevine_mutation/M in SV.mutations)
				SV.desc += "[M.name] "
			SV.desc += "vines."

	for(var/datum/spacevine_mutation/SM in SV.mutations)
		SM.on_birth(SV)

/obj/effect/spacevine_controller/process()
	if(!vines)
		qdel(src) //space  vines exterminated. Remove the controller
		return
	if(!growth_queue)
		qdel(src) //Sanity check
		return

	var/length = 0

	length = min( spread_cap , max( 1 , vines.len / spread_multiplier ) )
	var/i = 0
	var/list/obj/effect/spacevine/queue_end = list()

	for( var/obj/effect/spacevine/SV in growth_queue )
		if(qdeleted(SV))
			continue
		i++
		queue_end += SV
		growth_queue -= SV
		for(var/datum/spacevine_mutation/SM in SV.mutations)
			SM.process_mutation(SV)
		if(SV.energy < 2) //If tile isn't fully grown
			if(prob(20))
				SV.grow()
		else //If tile is fully grown
			SV.entangle_mob()

		//if(prob(25))
		SV.spread()
		if(i >= length)
			break

	growth_queue = growth_queue + queue_end

/obj/effect/spacevine/proc/grow()
	if(!energy)
		src.icon_state = pick("Med1", "Med2", "Med3")
		energy = 1
		SetOpacity(1)
		layer = 5
	else
		src.icon_state = pick("Hvy1", "Hvy2", "Hvy3")
		energy = 2

	for(var/datum/spacevine_mutation/SM in mutations)
		SM.on_grow(src)

/obj/effect/spacevine/proc/entangle_mob()
	if(!buckled_mobs.len && prob(25))
		for(var/mob/living/V in src.loc)
			entangle(V)
			if(buckled_mobs.len)
				break //only capture one mob at a time

/obj/effect/spacevine/proc/entangle(mob/living/V)
	if(!V)
		return
	for(var/datum/spacevine_mutation/SM in mutations)
		SM.on_buckle(src, V)
	if((V.stat != DEAD) && (V.buckled != src)) //not dead or captured
		V << "The vines [pick("wind", "tangle", "tighten")] around you!"
		buckle_mob(V)

/obj/effect/spacevine/proc/spread()
	var/direction = pick(cardinal)
	var/turf/stepturf = get_step(src,direction)
	for(var/datum/spacevine_mutation/SM in mutations)
		SM.on_spread(src, stepturf)
		stepturf = get_step(src,direction) //in case turf changes, to make sure no runtimes happen
	if(!locate(/obj/effect/spacevine, stepturf))
		if(stepturf.Enter(src))
			if(master)
				master.spawn_spacevine_piece(stepturf, src)

/obj/effect/spacevine/ex_act(severity, target)
	if(istype(target, type)) //if its agressive spread vine dont do anything
		return
	var/i
	for(var/datum/spacevine_mutation/SM in mutations)
		i += SM.on_explosion(severity, target, src)
	if(!i && prob(100/severity))
		qdel(src)

/obj/effect/spacevine/temperature_expose(null, temp, volume)
	var/override = 0
	for(var/datum/spacevine_mutation/SM in mutations)
		override += SM.process_temperature(src, temp, volume)
	if(!override)
		qdel(src)


code:
/datum/round_event_control/spider_infestation
	name = "Spider Infestation"
	typepath = /datum/round_event/spider_infestation
	weight = 5
	max_occurrences = 1
	min_players = 15

/datum/round_event/spider_infestation
	announceWhen	= 400

	var/spawncount = 1

/datum/round_event/spider_infestation/setup()
	announceWhen = rand(announceWhen, announceWhen + 50)
	spawncount = rand(5, 8)

/datum/round_event/spider_infestation/announce()
	priority_announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", 'sound/AI/aliens.ogg')

/datum/round_event/spider_infestation/start()
	var/list/vents = list()
	for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in world)
		if(temp_vent.loc.z == ZLEVEL_STATION && !temp_vent.welded)
			var/datum/pipeline/temp_vent_parent = temp_vent.PARENT1
			if(temp_vent_parent.other_atmosmch.len > 20)
				vents += temp_vent

	while((spawncount >= 1) && vents.len)
		var/obj/vent = pick(vents)
		var/obj/effect/spider/spiderling/S = new(vent.loc)
		if(prob(66))
			S.grow_as = /mob/living/simple_animal/hostile/poison/giant_spider/nurse
		vents -= vent
		spawncount--


code:
/datum/round_event_control/spontaneous_appendicitis
	name = "Spontaneous Appendicitis"
	typepath = /datum/round_event/spontaneous_appendicitis
	weight = 20
	max_occurrences = 4
	earliest_start = 6000
	min_players = 5 // To make your chance of getting help a bit higher.

/datum/round_event/spontaneous_appendicitis/start()
	for(var/mob/living/carbon/human/H in shuffle(living_mob_list))
		var/foundAlready = 0	//don't infect someone that already has the virus
		for(var/datum/disease/D in H.viruses)
			foundAlready = 1
		if(H.stat == 2 || foundAlready)
			continue

		var/datum/disease/D = new /datum/disease/appendicitis
		H.ForceContractDisease(D)
		break


code:
/datum/round_event_control/vent_clog
	name = "Clogged Vents"
	typepath = /datum/round_event/vent_clog
	weight = 35

/datum/round_event/vent_clog
	announceWhen	= 1
	startWhen		= 5
	endWhen			= 35
	var/interval 	= 2
	var/list/vents  = list()
	var/list/gunk = list("water","carbon","flour","radium","toxin","cleaner","nutriment","condensedcapsaicin","mushroomhallucinogen","lube",
								 "plantbgone","banana","charcoal","space_drugs","morphine","holywater","ethanol","hot_coco","facid")

/datum/round_event/vent_clog/announce()
	priority_announce("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert")

/datum/round_event/vent_clog/setup()
	endWhen = rand(25, 100)
	for(var/obj/machinery/atmospherics/components/unary/vent_scrubber/temp_vent in machines)
		if(temp_vent.loc.z == ZLEVEL_STATION && !temp_vent.welded)
			var/datum/pipeline/temp_vent_parent = temp_vent.PARENT1
			if(temp_vent_parent.other_atmosmch.len > 20)
				vents += temp_vent
	if(!vents.len)
		return kill()

/datum/round_event/vent_clog/tick()
	if(activeFor % interval == 0)
		var/obj/machinery/atmospherics/components/unary/vent = pick_n_take(vents)
		while(vent && vent.welded)
			vent = pick_n_take(vents)

		if(vent && vent.loc)
			var/datum/reagents/R = new/datum/reagents(50)
			R.my_atom = vent
			R.add_reagent(pick(gunk), 50)

			var/datum/effect_system/smoke_spread/chem/smoke = new
			smoke.set_up(R, 1, vent, silent = 1)
			playsound(vent.loc, 'sound/effects/smoke.ogg', 50, 1, -3)
			smoke.start()
			qdel(R)

			var/cockroaches = prob(33) ? 3 : 0
			while(cockroaches)
				new /mob/living/simple_animal/cockroach(get_turf(vent))
				cockroaches--


code:
/datum/round_event_control/weightless
	name = "Gravity Systems Failure"
	typepath = /datum/round_event/weightless
	weight = 15

/datum/round_event/weightless
	startWhen = 5
	endWhen = 65
	announceWhen	= 1

/datum/round_event/weightless/setup()
	startWhen = rand(0,10)
	endWhen = rand(40,80)

/datum/round_event/weightless/announce()
	command_alert("Warning: Failsafes for the station's artificial gravity arrays have been triggered. Please be aware that if this problem recurs it may result in formation of gravitational anomalies. Nanotrasen wishes to remind you that the unauthorised formation of anomalies within Nanotrasen facilities is strictly prohibited by health and safety regulation [rand(99,9999)][pick("a","b","c")]:subclause[rand(1,20)][pick("a","b","c")].")

/datum/round_event/weightless/start()
	for(var/area/A in world)
		A.gravitychange(0)

	if(control)
		control.weight *= 2

/datum/round_event/weightless/end()
	for(var/area/A in world)
		A.gravitychange(1)

	if(announceWhen >= 0)
		command_alert("Artificial gravity arrays are now functioning within normal parameters. Please report any irregularities to your respective head of staff.")


code:
/datum/round_event_control/wizard/darkness
	name = "Advanced Darkness"
	weight = 2
	typepath = /datum/round_event/wizard/darkness
	max_occurrences = 2
	earliest_start = 0

/datum/round_event/wizard/darkness
	endWhen = 0
	var/started = FALSE

/datum/round_event/wizard/darkness/start()
	if(!started)
		started = TRUE
		var/datum/weather/advanced_darkness/darkness = new
		darkness.weather_start_up()


code:
//in this file: Various events that directly aid the wizard. This is the "lets entice the wizard to use summon events!" file.

/datum/round_event_control/wizard/robelesscasting //EI NUDTH!
	name = "Robeless Casting"
	weight = 2
	typepath = /datum/round_event/wizard/robelesscasting/
	max_occurrences = 1
	earliest_start = 0

/datum/round_event/wizard/robelesscasting/start()

	for(var/mob/living/L in mob_list) //Hey if a corgi has magic missle he should get the same benifit as anyone
		if(L.mind && L.mind.spell_list.len != 0)
			var/spell_improved = 0
			for(var/obj/effect/proc_holder/spell/S in L.mind.spell_list)
				if(S.clothes_req)
					S.clothes_req = 0
					spell_improved = 1
			if(spell_improved)
				L << "You suddenly feel like you never needed those garish robes in the first place..."

//--//

/datum/round_event_control/wizard/improvedcasting //blink x5 disintergrate x5 here I come!
	name = "Improved Casting"
	weight = 3
	typepath = /datum/round_event/wizard/improvedcasting/
	max_occurrences = 4 //because that'd be max level spells
	earliest_start = 0

/datum/round_event/wizard/improvedcasting/start()
	for(var/mob/living/L in mob_list)
		if(L.mind && L.mind.spell_list.len != 0)
			for(var/obj/effect/proc_holder/spell/S in L.mind.spell_list)
				S.name = initial(S.name)
				S.spell_level++
				if(S.spell_level >= 6 || S.charge_max <= 0) //Badmin checks, these should never be a problem in normal play
					continue
				if(S.level_max <= 0)
					continue
				S.charge_max = round(initial(S.charge_max) - S.spell_level * (initial(S.charge_max) - S.cooldown_min) / S.level_max)
				if(S.charge_max < S.charge_counter)
					S.charge_counter = S.charge_max
				switch(S.spell_level)
					if(1)
						S.name = "Efficient [S.name]"
					if(2)
						S.name = "Quickened [S.name]"
					if(3)
						S.name = "Free [S.name]"
					if(4)
						S.name = "Instant [S.name]"
					if(5)
						S.name = "Ludicrous [S.name]"

			L << "You suddenly feel more competent with your casting!"


code:
/datum/round_event_control/wizard/blobies //avast!
	name = "Zombie Outbreak"
	weight = 3
	typepath = /datum/round_event/wizard/blobies/
	max_occurrences = 3
	earliest_start = 12000 // 20 minutes (gotta get some bodies made!)

/datum/round_event/wizard/blobies/start()

	for(var/mob/living/carbon/human/H in dead_mob_list)
		new /mob/living/simple_animal/hostile/blob/blobspore(H.loc)


code:
/datum/round_event_control/wizard/cursed_items //fashion disasters
	name = "Cursed Items"
	weight = 3
	typepath = /datum/round_event/wizard/cursed_items/
	max_occurrences = 3
	earliest_start = 0

//Note about adding items to this: Because of how NODROP works if an item spawned to the hands can also be equiped to a slot
//it will be able to be put into that slot from the hand, but then get stuck there. To avoid this make a new subtype of any
//item you want to equip to the hand, and set its slots_flags = null. Only items equiped to hands need do this.

/datum/round_event/wizard/cursed_items/start()
	var/item_set = pick("wizardmimic", "swords", "bigfatdoobie", "boxing", "voicemodulators", "catgirls2015")
	var/list/wearslots	= list(slot_wear_suit, slot_shoes, slot_head, slot_wear_mask, slot_r_hand, slot_gloves, slot_ears)
	var/list/loadout = list()
	var/ruins_spaceworthiness
	var/ruins_wizard_loadout
	loadout.len = 7

	switch(item_set)
		if("wizardmimic")
			loadout = list(/obj/item/clothing/suit/wizrobe, /obj/item/clothing/shoes/sandal, /obj/item/clothing/head/wizard)
			ruins_spaceworthiness = 1
		if("swords")
			loadout[5] = /obj/item/weapon/katana/cursed
		if("bigfatdoobie")
			loadout[4] = /obj/item/clothing/mask/cigarette/rollie/trippy/
			ruins_spaceworthiness = 1
		if("boxing")
			loadout[4] = /obj/item/clothing/mask/luchador
			loadout[6] = /obj/item/clothing/gloves/boxing
			ruins_spaceworthiness = 1
		if("voicemodulators")
			loadout[4] = /obj/item/clothing/mask/chameleon
		if("catgirls2015")
			loadout[3] = /obj/item/clothing/head/kitty
			ruins_spaceworthiness = 1
			ruins_wizard_loadout = 1

	for(var/mob/living/carbon/human/H in living_mob_list)
		if(ruins_spaceworthiness && (H.z != 1 || istype(H.loc, /turf/open/space)))
			continue	//#savetheminers
		if(ruins_wizard_loadout && H.mind && ((H.mind in ticker.mode.wizards) || (H.mind in ticker.mode.apprentices)))
			continue
		if(item_set == "catgirls2015") //Wizard code means never having to say you're sorry
			H.gender = FEMALE
		var/list/slots		= list(H.wear_suit, H.shoes, H.head, H.wear_mask, H.r_hand, H.gloves, H.ears) //add new slots as needed to back
		for(var/i = 1, i <= loadout.len, i++)
			if(loadout[i])
				var/obj/item/J = loadout[i]
				var/obj/item/I = new J //dumb but required because of byond throwing a fit anytime new gets too close to a list
				H.unEquip(slots[i])
				H.equip_to_slot_or_del(I, wearslots[i])
				I.flags |= NODROP
				I.name = "cursed " + I.name

	for(var/mob/living/carbon/human/H in living_mob_list)
		var/datum/effect_system/smoke_spread/smoke = new
		smoke.set_up(0, H.loc)
		smoke.start()


code:
/datum/round_event_control/wizard/deprevolt //stationwide!
	name = "Departmental Uprising"
	weight = 0 //An order that requires order in a round of chaos was maybe not the best idea. Requiescat in pace departmental uprising August 2014 - March 2015
	typepath = /datum/round_event/wizard/deprevolt/
	max_occurrences = 1
	earliest_start = 0

/datum/round_event/wizard/deprevolt/start()

	var/list/tidecolor
	var/list/jobs_to_revolt	= 	list()
	var/nation
	var/list/citizens	=		list()

	tidecolor = pick("grey", "white", "yellow", "purple", "brown", "whatevercolorrepresentstheservicepeople")
	switch(tidecolor)
		if("grey") //God help you
			jobs_to_revolt = list("Assistant")
			nation = pick("Assa", "Mainte", "Tunnel", "Gris", "Grey", "Liath", "Grigio", "Ass", "Assi")
		if("white")
			jobs_to_revolt = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Geneticist", "Virologist")
			nation = pick("Mede", "Healtha", "Recova", "Chemi", "Geneti", "Viro", "Psych")
		if("yellow")
			jobs_to_revolt = list("Chief Engineer", "Station Engineer", "Atmospheric Technician")
			nation = pick("Atomo", "Engino", "Power", "Teleco")
		if("purple")
			jobs_to_revolt = list("Research Director","Scientist", "Roboticist")
			nation = pick("Sci", "Griffa", "Explosi", "Mecha", "Xeno")
		if("brown")
			jobs_to_revolt = list("Quartermaster", "Cargo Technician", "Shaft Miner")
			nation = pick("Cargo", "Guna", "Suppli", "Mule", "Crate", "Ore", "Mini", "Shaf")
		if("whatevercolorrepresentstheservicepeople") //the few, the proud, the technically aligned
			jobs_to_revolt = list("Bartender", "Cook", "Botanist", "Clown", "Mime", "Janitor", "Chaplain")
			nation = pick("Honka", "Boozo", "Fatu", "Danka", "Mimi", "Libra", "Jani", "Religi")

	nation += pick("stan", "topia", "land", "nia", "ca", "tova", "dor", "ador", "tia", "sia", "ano", "tica", "tide", "cis", "marea", "co", "taoide", "slavia", "stotzka")

	for(var/mob/living/carbon/human/H in mob_list)
		if(H.mind)
			var/datum/mind/M = H.mind
			if(M.assigned_role && !(M in ticker.mode.traitors))
				for(var/job in jobs_to_revolt)
					if(M.assigned_role == job)
						citizens += H
						ticker.mode.traitors += M
						M.special_role = "separatist"
						H.attack_log += "\[[time_stamp()]\] Was made into a separatist, long live [nation]!"
						H << "You are a separatist! [nation] forever! Protect the soverignty of your newfound land with your comrades in arms!"
	if(citizens.len)
		var/message
		for(var/job in jobs_to_revolt)
			message += "[job],"
		message_admins("The nation of [nation] has been formed. Affected jobs are [message]")


code:
/datum/round_event_control/wizard/fake_explosion //Oh no the station is gone!
	name = "Fake Nuclear Explosion"
	weight = 0 //Badmin exclusive now because once it's expected its not funny
	typepath = /datum/round_event/wizard/fake_explosion/
	max_occurrences = 1
	earliest_start = 0

/datum/round_event/wizard/fake_explosion/start()
	for(var/mob/M in player_list)
		M << 'sound/machines/Alarm.ogg'
	spawn(100)
		ticker.station_explosion_cinematic(1,"fake") //:o)


code:
/datum/round_event_control/wizard/ghost //The spook is real
	name = "G-G-G-Ghosts!"
	weight = 3
	typepath = /datum/round_event/wizard/ghost/
	max_occurrences = 5
	earliest_start = 0

/datum/round_event/wizard/ghost/start()
	for(var/mob/dead/observer/G in player_list)
		G.invisibility = 0
		G << "You suddenly feel extremely obvious..."

//--//

/datum/round_event_control/wizard/possession //Oh shit
	name = "Possessing G-G-G-Ghosts!"
	weight = 2
	typepath = /datum/round_event/wizard/possession
	max_occurrences = 5
	earliest_start = 0

/datum/round_event/wizard/possession/start()
	for(var/mob/dead/observer/G in player_list)
		G.verbs += /mob/dead/observer/verb/boo
		G.verbs += /mob/dead/observer/verb/possess
		G << "You suddenly feel a welling of new spooky powers..."


code:
/datum/round_event_control/wizard/greentext //Gotta have it!
	name = "Greentext"
	weight = 4
	typepath = /datum/round_event/wizard/greentext/
	max_occurrences = 1
	earliest_start = 0

/datum/round_event/wizard/greentext/start()

	var/list/holder_canadates = player_list.Copy()
	for(var/mob/M in holder_canadates)
		if(!ishuman(M))
			holder_canadates -= M
	if(!holder_canadates) //Very unlikely, but just in case
		return 0

	var/mob/living/carbon/human/H = pick(holder_canadates)
	new /obj/item/weapon/greentext(H.loc)
	H << "The mythical greentext appear at your feet! Pick it up if you dare..."

/obj/item/weapon/greentext
	name = "greentext"
	desc = "No one knows what this massive tome does, but it feels desirable all the same..."
	w_class = 4
	icon = 'icons/obj/wizard.dmi'
	icon_state = "greentext"
	var/mob/living/last_holder
	var/mob/living/new_holder
	var/list/color_altered_mobs = list()

/obj/item/weapon/greentext/New()
	..()
	poi_list |= src

/obj/item/weapon/greentext/equipped(mob/living/user as mob)
	user << "So long as you leave this place with greentext in hand you know will be happy..."
	if(user.mind && user.mind.objectives.len > 0)
		user << "... so long as you still perform your other objectives that is!"
	new_holder = user
	if(!last_holder)
		last_holder = user
	if(!(user in color_altered_mobs))
		color_altered_mobs += user
	user.color = "#00FF00"
	SSobj.processing |= src
	..()

/obj/item/weapon/greentext/dropped(mob/living/user as mob)
	if(user in color_altered_mobs)
		user << "A sudden wave of failure washes over you..."
		user.color = "#FF0000" //ya blew it
	last_holder 	= null
	new_holder 		= null
	SSobj.processing.Remove(src)
	..()

/obj/item/weapon/greentext/process()
	if(new_holder && new_holder.z == ZLEVEL_CENTCOM)//you're winner!
		new_holder << "At last it feels like victory is assured!"
		if(!(new_holder in ticker.mode.traitors))
			ticker.mode.traitors += new_holder.mind
		new_holder.mind.special_role = "winner"
		var/datum/objective/O = new /datum/objective("Succeed")
		O.completed = 1 //YES!
		O.owner = new_holder.mind
		new_holder.mind.objectives += O
		new_holder.attack_log += "\[[time_stamp()]\] Won with greentext!!!"
		color_altered_mobs -= new_holder
		qdel(src)

	if(last_holder && last_holder != new_holder) //Somehow it was swiped without ever getting dropped
		last_holder << "A sudden wave of failure washes over you..."
		last_holder.color = "#FF0000"
		last_holder = new_holder //long live the king

/obj/item/weapon/greentext/Destroy()
	poi_list.Remove(src)
	for(var/mob/M in mob_list)
		var/message = "A dark temptation has passed from this world"
		if(M in color_altered_mobs)
			message += " and you're finally able to forgive yourself"
			M.color = initial(M.color)
		message += "..."
		M << message
	return ..()


code:
/datum/round_event_control/wizard/imposter //Mirror Mania
	name = "Imposter Wizard"
	weight = 1
	typepath = /datum/round_event/wizard/imposter/
	max_occurrences = 1
	earliest_start = 0

/datum/round_event/wizard/imposter/start()

	for(var/datum/mind/M in ticker.mode.wizards)
		if(!ishuman(M.current))
			continue
		var/mob/living/carbon/human/W = M.current
		var/list/candidates = get_candidates(ROLE_WIZARD)
		if(!candidates)
			return //Sad Trombone
		var/client/C = pick(candidates)

		PoolOrNew(/obj/effect/particle_effect/smoke, W.loc)

		var/mob/living/carbon/human/I = new /mob/living/carbon/human(W.loc)
		W.dna.transfer_identity(I, transfer_SE=1)
		I.real_name = I.dna.real_name
		I.name = I.dna.real_name
		I.updateappearance(mutcolor_update=1)
		I.domutcheck()
		if(W.ears)
			I.equip_to_slot_or_del(new W.ears.type, slot_ears)
		if(W.w_uniform)
			I.equip_to_slot_or_del(new W.w_uniform.type	, slot_w_uniform)
		if(W.shoes)
			I.equip_to_slot_or_del(new W.shoes.type, slot_shoes)
		if(W.wear_suit)
			I.equip_to_slot_or_del(new W.wear_suit.type, slot_wear_suit)
		if(W.head)
			I.equip_to_slot_or_del(new W.head.type, slot_head)
		if(W.back)
			I.equip_to_slot_or_del(new W.back.type, slot_back)
		I.key = C.key

		//Operation: Fuck off and scare people
		I.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(null))
		I.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(null))
		I.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(null))

		ticker.mode.apprentices += I.mind
		I.mind.special_role = "imposter"

		var/datum/objective/protect/protect_objective = new /datum/objective/protect
		protect_objective.owner = I.mind
		protect_objective.target = W.mind
		protect_objective.explanation_text = "Protect [W.real_name], the wizard."
		I.mind.objectives += protect_objective
		ticker.mode.update_wiz_icons_added(I.mind)

		I.attack_log += "\[[time_stamp()]\] Is an imposter!"
		I << "You are an imposter! Trick and confuse the crew to misdirect malice from your handsome original!"
		I << sound('sound/effects/magic.ogg')


code:
/datum/round_event_control/wizard/invincible //Boolet Proof
	name = "Invincibility"
	weight = 3
	typepath = /datum/round_event/wizard/invincible/
	max_occurrences = 5
	earliest_start = 0

/datum/round_event/wizard/invincible/start()

	for(var/mob/living/carbon/human/H in living_mob_list)
		H.reagents.add_reagent("adminordrazine", 40) //100 ticks of absolute invinciblity (barring gibs)
		H << "You feel invincible, nothing can hurt you!"


code:
/datum/round_event_control/wizard/lava //THE LEGEND NEVER DIES
	name = "The Floor Is LAVA!"
	weight = 2
	typepath = /datum/round_event/wizard/lava/
	max_occurrences = 3
	earliest_start = 0

/datum/round_event/wizard/lava/
	endWhen = 0
	var/started = FALSE

/datum/round_event/wizard/lava/start()
	if(!started)
		started = TRUE
		var/datum/weather/floor_is_lava/LAVA = new /datum/weather/floor_is_lava
		LAVA.weather_start_up()


code:
/datum/round_event_control/wizard/magicarp //these fish is loaded
	name = "Magicarp"
	weight = 1
	typepath = /datum/round_event/wizard/magicarp/
	max_occurrences = 1
	earliest_start = 0

/datum/round_event/wizard/magicarp/
	announceWhen	= 3
	startWhen = 50

/datum/round_event/wizard/magicarp/setup()
	startWhen = rand(40, 60)

/datum/round_event/wizard/magicarp/announce()
	priority_announce("Unknown magical entities have been detected near [station_name()], please stand-by.", "Lifesign Alert")

/datum/round_event/wizard/magicarp/start()
	for(var/obj/effect/landmark/C in landmarks_list)
		if(C.name == "carpspawn")
			if(prob(5))
				new /mob/living/simple_animal/hostile/carp/ranged/chaos(C.loc)
			else
				new /mob/living/simple_animal/hostile/carp/ranged(C.loc)

/mob/living/simple_animal/hostile/carp/ranged
	name = "magicarp"
	desc = "50% magic, 50% carp, 100% horrible."
	icon_state = "magicarp"
	icon_living = "magicarp"
	icon_dead = "magicarp_dead"
	icon_gib = "magicarp_gib"
	ranged = 1
	retreat_distance = 2
	minimum_distance = 0 //Between shots they can and will close in to nash
	projectiletype = /obj/item/projectile/magic
	projectilesound = 'sound/weapons/emitter.ogg'
	maxHealth = 50
	health = 50

/mob/living/simple_animal/hostile/carp/ranged/New()
	projectiletype = pick(typesof(initial(projectiletype)))
	..()

/mob/living/simple_animal/hostile/carp/ranged/chaos
	name = "chaos magicarp"
	desc = "50% carp, 100% magic, 150% horrible."
	color = "#00FFFF"
	maxHealth = 75
	health = 75

/mob/living/simple_animal/hostile/carp/ranged/chaos/Shoot()
	projectiletype = pick(typesof(initial(projectiletype)))
	..()


code:
/datum/round_event_control/wizard/petsplosion //the horror
	name = "Petsplosion"
	weight = 2
	typepath = /datum/round_event/wizard/petsplosion/
	max_occurrences = 1 //Exponential growth is nothing to sneeze at!
	earliest_start = 0

/datum/round_event/wizard/petsplosion/
	endWhen = 61 //1 minute (+1 tick for endWhen not to interfere with tick)
	var/countdown = 0

/datum/round_event/wizard/petsplosion/tick()
	if(activeFor >= 30 * countdown) // 0 seconds : 2 animals | 30 seconds : 4 animals | 1 minute : 8 animals
		countdown += 1
		for(var/mob/living/simple_animal/F in living_mob_list) //If you cull the heard before the next replication, things will be easier for you
			if(!istype(F, /mob/living/simple_animal/hostile))
				new F.type(F.loc)


code:
/datum/round_event_control/wizard/race //Lizard Wizard? Lizard Wizard.
	name = "Race Swap"
	weight = 2
	typepath = /datum/round_event/wizard/race/
	max_occurrences = 5
	earliest_start = 0

/datum/round_event/wizard/race/start()

	var/all_the_same = 0
	var/all_species = list()

	for(var/speciestype in subtypesof(/datum/species))
		var/datum/species/S = new speciestype()
		if(!S.dangerous_existence)
			all_species += speciestype

	var/datum/species/new_species = pick(all_species)

	if(prob(50))
		all_the_same = 1

	for(var/mob/living/carbon/human/H in mob_list) //yes, even the dead
		H.set_species(new_species)
		H.real_name = new_species.random_name(H.gender,1)
		H.dna.unique_enzymes = H.dna.generate_unique_enzymes()
		H << "You feel somehow... different?"
		if(!all_the_same)
			new_species = pick(all_species)


code:
/datum/round_event_control/wizard/rpgloot //its time to minmax your shit
	name = "RPG Loot"
	weight = 3
	typepath = /datum/round_event/wizard/rpgloot/
	max_occurrences = 1
	earliest_start = 0

/datum/round_event/wizard/rpgloot/start()
	var/list/prefixespositive 	= list("greater", "major", "blessed", "superior", "enpowered", "honed", "true", "glorious", "robust")
	var/list/prefixesnegative 	= list("lesser", "minor", "blighted", "inferior", "enfeebled", "rusted", "unsteady", "tragic", "gimped")
	var/list/suffixes			= list("orc slaying", "elf slaying", "corgi slaying", "strength", "dexterity", "constitution", "intelligence", "wisdom", "charisma", "the forest", "the hills", "the plains", "the sea", "the sun", "the moon", "the void", "the world", "the fool", "many secrets", "many tales", "many colors", "rending", "sundering", "the night", "the day")
	var/upgrade_scroll_chance	= 0
	for(var/obj/item/I in world)
		if(istype(I,/obj/item/organ/))
			continue
		var/quality = pick(1;15, 2;14, 2;13, 2;12, 3;11, 3;10, 3;9, 4;8, 4;7, 4;6, 5;5, 5;4, 5;3, 6;2, 6;1, 6;0)
		if(prob(50))
			quality = -quality
		if(quality > 0)
			I.name = "[pick(prefixespositive)] [I.name] of [pick(suffixes)] +[quality]"
		else if(quality < 0)
			I.name = "[pick(prefixesnegative)] [I.name] of [pick(suffixes)] [quality]"
		else
			I.name = "[I.name] of [pick(suffixes)]"

		I.force 		= max(0,I.force + quality)
		I.throwforce	= max(0,I.throwforce + quality)
		for(var/value in I.armor)
			I.armor[value] += quality

		if(istype(I,/obj/item/weapon/storage))
			var/obj/item/weapon/storage/S = I
			if(prob(upgrade_scroll_chance) && S.contents.len < S.storage_slots)
				var/obj/item/upgradescroll/scroll = new
				S.handle_item_insertion(scroll,1)
				upgrade_scroll_chance = max(0,upgrade_scroll_chance-100)
			upgrade_scroll_chance += 25

/obj/item/upgradescroll
	name = "Item Fortification Scroll"
	desc = "Somehow, this piece of paper can be applied to items to make them \"better\". Apparently there's a risk of losing the item if it's already \"too good\". This all feels so arbitrary..."
	icon = 'icons/obj/wizard.dmi'
	icon_state = "scroll"
	w_class = 1

/obj/item/upgradescroll/afterattack(obj/item/target, mob/user , proximity)
	if(!proximity || !istype(target))
		return
	var/quality = target.force - initial(target.force)
	if(quality > 9 && prob((quality - 9)*10))
		user << "[target] catches fire!"
		if(target.burn_state == -1)
			target.burn_state = 0
		target.fire_act()
		qdel(src)
		return
	target.force 		+= 1
	target.throwforce	+= 1
	for(var/value in target.armor)
		target.armor[value] += 1
	user << "[target] glows blue and seems vaguely \"better\"!"
	qdel(src)


code:
/datum/round_event/wizard/shuffle/start()

/datum/round_event_control/wizard/shuffleloc //Somewhere an AI is crying
	name = "Change Places!"
	weight = 2
	typepath = /datum/round_event/wizard/shuffleloc/
	max_occurrences = 5
	earliest_start = 0

/datum/round_event/wizard/shuffleloc/start()
	var/list/moblocs = list()
	var/list/mobs	 = list()

	for(var/mob/living/carbon/human/H in living_mob_list)
		if(H.z != 1)
			continue //lets not try to strand people in space or stuck in the wizards den
		moblocs += H.loc
		mobs += H

	if(!mobs)
		return

	shuffle(moblocs)
	shuffle(mobs)

	for(var/mob/living/carbon/human/H in mobs)
		if(!moblocs)
			break //locs aren't always unique, so this may come into play
		do_teleport(H, moblocs[moblocs.len])
		moblocs.len -= 1

	for(var/mob/living/carbon/human/H in living_mob_list)
		var/datum/effect_system/smoke_spread/smoke = new
		smoke.set_up(0, H.loc)
		smoke.start()

//---//

/datum/round_event_control/wizard/shufflenames //Face/off joke
	name = "Change Faces!"
	weight = 4
	typepath = /datum/round_event/wizard/shufflenames/
	max_occurrences = 5
	earliest_start = 0

/datum/round_event/wizard/shufflenames/start()
	var/list/mobnames = list()
	var/list/mobs	 = list()

	for(var/mob/living/carbon/human/H in living_mob_list)
		mobnames += H.real_name
		mobs += H

	if(!mobs)
		return

	shuffle(mobnames)
	shuffle(mobs)

	for(var/mob/living/carbon/human/H in mobs)
		if(!mobnames)
			break
		H.real_name = mobnames[mobnames.len]
		mobnames.len -= 1

	for(var/mob/living/carbon/human/H in living_mob_list)
		var/datum/effect_system/smoke_spread/smoke = new
		smoke.set_up(0, H.loc)
		smoke.start()

//---//

/datum/round_event_control/wizard/shuffleminds //Basically Mass Ranged Mindswap
	name = "Change Minds!"
	weight = 1
	typepath = /datum/round_event/wizard/shuffleminds/
	max_occurrences = 3
	earliest_start = 0

/datum/round_event/wizard/shuffleminds/start()
	var/list/mobs	 = list()

	for(var/mob/living/carbon/human/H in living_mob_list)
		if(!H.stat || !H.mind || (H.mind in ticker.mode.wizards) || (H.mind in ticker.mode.apprentices))
			continue //the wizard(s) are spared on this one
		mobs += H

	if(!mobs)
		return

	shuffle(mobs)

	var/obj/effect/proc_holder/spell/targeted/mind_transfer/swapper = new /obj/effect/proc_holder/spell/targeted/mind_transfer/
	while(mobs.len > 1)
		var/mob/living/carbon/human/H = pick(mobs)
		mobs -= H
		swapper.cast(list(H), mobs[mobs.len], 1)
		mobs -= mobs[mobs.len]

	for(var/mob/living/carbon/human/H in living_mob_list)
		var/datum/effect_system/smoke_spread/smoke = new
		smoke.set_up(0, H.loc)
		smoke.start()


code:
/datum/round_event_control/wizard/summonguns //The Classic
	name = "Summon Guns"
	weight = 1
	typepath = /datum/round_event/wizard/summonguns/
	max_occurrences = 1
	earliest_start = 0

/datum/round_event_control/wizard/summonguns/New()
	if(config.no_summon_guns)
		weight = 0
	..()

/datum/round_event/wizard/summonguns/start()
	rightandwrong(0,,10)

/datum/round_event_control/wizard/summonmagic //The Somewhat Less Classic
	name = "Summon Magic"
	weight = 1
	typepath = /datum/round_event/wizard/summonmagic/
	max_occurrences = 1
	earliest_start = 0

/datum/round_event_control/wizard/summonmagic/New()
	if(config.no_summon_magic)
		weight = 0
	..()

/datum/round_event/wizard/summonmagic/start()
	rightandwrong(1,,10)


code:
/datum/round_event_control/wormholes
	name = "Wormholes"
	typepath = /datum/round_event/wormholes
	max_occurrences = 3
	weight = 2
	min_players = 2

/datum/round_event/wormholes
	announceWhen = 10
	endWhen = 60

	var/list/pick_turfs = list()
	var/list/wormholes = list()
	var/shift_frequency = 3
	var/number_of_wormholes = 400

/datum/round_event/wormholes/setup()
	announceWhen = rand(0, 20)
	endWhen = rand(40, 80)

/datum/round_event/wormholes/start()
	for(var/turf/open/floor/T in world)
		if(T.z == ZLEVEL_STATION)
			pick_turfs += T

	for(var/i = 1, i <= number_of_wormholes, i++)
		var/turf/T = pick(pick_turfs)
		wormholes += new /obj/effect/portal/wormhole(T, null, null, -1)

/datum/round_event/wormholes/announce()
	priority_announce("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert", 'sound/AI/spanomalies.ogg')

/datum/round_event/wormholes/tick()
	if(activeFor % shift_frequency == 0)
		for(var/obj/effect/portal/wormhole/O in wormholes)
			var/turf/T = pick(pick_turfs)
			if(T)
				O.loc = T

/datum/round_event/wormholes/end()
	portals.Remove(wormholes)
	for(var/obj/effect/portal/wormhole/O in wormholes)
		O.loc = null
	wormholes.Cut()

/obj/effect/portal/wormhole
	name = "wormhole"
	desc = "It looks highly unstable; It could close at any moment."
	icon = 'icons/obj/objects.dmi'
	icon_state = "anom"

/obj/effect/portal/wormhole/attack_hand(mob/user)
	teleport(user)

/obj/effect/portal/wormhole/attackby(obj/item/I, mob/user, params)
	teleport(user)

/obj/effect/portal/wormhole/teleport(atom/movable/M)
	if(istype(M, /obj/effect))	//sparks don't teleport
		return
	if(M.anchored && istype(M, /obj/mecha))
		return

	if(istype(M, /atom/movable))
		var/turf/target
		if(portals.len)
			var/obj/effect/portal/P = pick(portals)
			if(P && isturf(P.loc))
				target = P.loc
		if(!target)
			return
		do_teleport(M, target, 1, 1, 0, 0) ///You will appear adjacent to the beacon


code:
/mob/living/carbon/proc/dream()
	set waitfor = 0
	dreaming = 1
	var/list/dreams = list(
		"an ID card","a bottle","a familiar face","a crewmember","a toolbox","a security officer","the captain",
		"voices from all around","deep space","a doctor","the engine","a traitor","an ally","darkness",
		"light","a scientist","a monkey","a catastrophe","a loved one","a gun","warmth","freezing","the sun",
		"a hat","the Luna","a ruined station","a planet","plasma","air","the medical bay","the bridge","blinking lights",
		"a blue light","an abandoned laboratory","Nanotrasen","The Syndicate","blood","healing","power","respect",
		"riches","space","a crash","happiness","pride","a fall","water","flames","ice","melons","flying"
		)
	for(var/i = rand(1,4),i > 0, i--)
		var/dream_image = pick(dreams)
		dreams -= dream_image
		src << "... [dream_image] ..."
		sleep(rand(40,70))
		if(paralysis <= 0)
			dreaming = 0
			return 0
	dreaming = 0
	return 1

/mob/living/carbon/proc/handle_dreams()
	if(prob(5) && !dreaming) dream()

/mob/living/carbon/var/dreaming = 0


code:
/*
Ideas for the subtle effects of hallucination:

Light up oxygen/plasma indicators (done)
Cause health to look critical/dead, even when standing (done)
Characters silently watching you
Brief flashes of fire/space/bombs/c4/dangerous shit (done)
Items that are rare/traitorous/don't exist appearing in your inventory slots (done)
Strange audio (should be rare) (done)
Gunshots/explosions/opening doors/less rare audio (done)

*/

/mob/living/carbon/
	var/image/halimage
	var/image/halbody
	var/obj/halitem
	var/hal_screwyhud = 0 //1 - critical, 2 - dead, 3 - oxygen indicator, 4 - toxin indicator, 5 - perfect health
	var/handling_hal = 0

/mob/living/carbon/proc/handle_hallucinations()
	if(handling_hal)
		return

	//Least obvious
	var/list/minor = list("sounds"=20,"bolts_minor"=10,"whispers"=15,"message"=5)
	//Something's wrong here
	var/list/medium = list("hudscrew"=15,"items"=15,"dangerflash"=15,"bolts"=10,"flood"=10,"husks"=10,"battle"=10)
	//AAAAH
	var/list/major = list("fake"=10,"death"=5,"xeno"=10,"singulo"=10,"delusion"=10)

	var/grade = 0
	var/current = list()
	var/trip_length = 0

	handling_hal = 1
	while(hallucination > 20)
		sleep(rand(200,500)/(hallucination/25))
		trip_length += 1
		if(prob(min(20,trip_length*2)))
			grade = min(3,grade+1)
		if(prob(20))
			continue
		current = list()
		for(var/a in minor)
			current[a] = minor[a] * (grade==0?2:1)
		for(var/b in medium)
			current[b] = medium[b] * (grade==1?2:1)
		for(var/c in major)
			current[c] = major[c] * (grade==2?2:1)

		var/halpick = pickweight(current)

		hallucinate(halpick)
	handling_hal = 0

/obj/effect/hallucination
	invisibility = INVISIBILITY_OBSERVER
	var/mob/living/carbon/target = null

/obj/effect/hallucination/simple
	var/image_icon = 'icons/mob/alien.dmi'
	var/image_state = "alienh_pounce"
	var/px = 0
	var/py = 0
	var/col_mod = null
	var/image/current_image = null
	var/image_layer = MOB_LAYER
	var/active = 1 //qdelery

/obj/effect/hallucination/simple/New(loc,var/mob/living/carbon/T)
	target = T
	current_image = GetImage()
	if(target.client) target.client.images |= current_image
	return

/obj/effect/hallucination/simple/proc/GetImage()
	var/image/I = image(image_icon,loc,image_state,image_layer,dir=src.dir)
	I.pixel_x = px
	I.pixel_y = py
	if(col_mod)
		I.color = col_mod
	return I

/obj/effect/hallucination/simple/proc/Show(update=1)
	if(active)
		if(target.client) target.client.images.Remove(current_image)
		if(update)
			current_image = GetImage()
		if(target.client) target.client.images |= current_image

/obj/effect/hallucination/simple/update_icon(new_state,new_icon,new_px=0,new_py=0)
	image_state = new_state
	if(new_icon)
		image_icon = new_icon
	else
		image_icon = initial(image_icon)
	px = new_px
	py = new_py
	Show()

/obj/effect/hallucination/simple/Moved(atom/OldLoc, Dir)
	Show()
	return

/obj/effect/hallucination/simple/Destroy()
	if(target.client) target.client.images.Remove(current_image)
	active = 0
	return ..()

#define FAKE_FLOOD_EXPAND_TIME 30
#define FAKE_FLOOD_MAX_RADIUS 7

/obj/effect/hallucination/fake_flood
	//Plasma/N2O starts flooding from the nearby vent
	var/list/flood_images = list()
	var/list/turf/flood_turfs = list()
	var/image_icon = 'icons/effects/tile_effects.dmi'
	var/image_state = "plasma"
	var/radius = 0
	var/next_expand = 0

/obj/effect/hallucination/fake_flood/New(loc,var/mob/living/carbon/T)
	..()
	target = T
	for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in orange(7,target))
		if(!U.welded)
			src.loc = U.loc
			break
	image_state = pick("plasma","nitrous_oxide")
	flood_images += image(image_icon,src,image_state,MOB_LAYER)
	flood_turfs += get_turf(src.loc)
	if(target.client) target.client.images |= flood_images
	next_expand = world.time + FAKE_FLOOD_EXPAND_TIME
	SSobj.processing |= src

/obj/effect/hallucination/fake_flood/process()
	if(next_expand <= world.time)
		radius++
		if(radius > FAKE_FLOOD_MAX_RADIUS)
			qdel(src)
			return
		Expand()
		next_expand = world.time + FAKE_FLOOD_EXPAND_TIME

/obj/effect/hallucination/fake_flood/proc/Expand()
	for(var/turf/T in circlerangeturfs(loc,radius))
		if((T in flood_turfs)|| T.blocks_air)
			continue
		flood_images += image(image_icon,T,image_state,MOB_LAYER)
		flood_turfs += T
	if(target.client)
		target.client.images |= flood_images

/obj/effect/hallucination/fake_flood/Destroy()
	SSobj.processing.Remove(src)
	qdel(flood_turfs)
	flood_turfs = list()
	if(target.client)
		target.client.images.Remove(flood_images)
	target = null
	qdel(flood_images)
	flood_images = list()
	return ..()

/obj/effect/hallucination/simple/xeno
	image_icon = 'icons/mob/alien.dmi'
	image_state = "alienh_pounce"

/obj/effect/hallucination/simple/xeno/New(loc,var/mob/living/carbon/T)
	..()
	name = "alien hunter ([rand(1, 1000)])"
	return

/obj/effect/hallucination/simple/xeno/throw_impact(A)
	update_icon("alienh_pounce")
	if(A == target)
		target.Weaken(5)
		target.visible_message("[target] flails around wildly.","[name] pounces on you!")

/obj/effect/hallucination/xeno_attack
	//Xeno crawls from nearby vent,jumps at you, and goes back in
	var/obj/machinery/atmospherics/components/unary/vent_pump/pump = null
	var/obj/effect/hallucination/simple/xeno/xeno = null

/obj/effect/hallucination/xeno_attack/New(loc,var/mob/living/carbon/T)
	target = T
	for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in orange(7,target))
		if(!U.welded)
			pump = U
			break
	if(pump)
		xeno = new(pump.loc,target)
		sleep(10)
		xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
		xeno.throw_at(target,7,1, spin = 0, diagonals_first = 1)
		sleep(10)
		xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
		xeno.throw_at(pump,7,1, spin = 0, diagonals_first = 1)
		sleep(10)
		var/xeno_name = xeno.name
		target << "[xeno_name] begins climbing into the ventilation system..."
		sleep(10)
		qdel(xeno)
		target << "[xeno_name] scrambles into the ventilation ducts!"
	qdel(src)

/obj/effect/hallucination/singularity_scare
	//Singularity moving towards you.
	//todo Hide where it moved with fake space images
	var/obj/effect/hallucination/simple/singularity/s = null

/obj/effect/hallucination/singularity_scare/New(loc,var/mob/living/carbon/T)
	target = T
	var/turf/start = T.loc
	var/screen_border = pick(SOUTH,EAST,WEST,NORTH)
	for(var/i = 0,i<11,i++)
		start = get_step(start,screen_border)
	s = new(start,target)
	for(var/i = 0,i<11,i++)
		sleep(5)
		s.loc = get_step(get_turf(s),get_dir(s,target))
		s.Show()
		s.Eat()
	qdel(s)

/obj/effect/hallucination/simple/singularity
	image_icon = 'icons/effects/224x224.dmi'
	image_state = "singularity_s7"
	image_layer = 6
	px = -96
	py = -96

/obj/effect/hallucination/simple/singularity/proc/Eat(atom/OldLoc, Dir)
	var/target_dist = get_dist(src,target)
	if(target_dist<=3) //"Eaten"
		target.hal_screwyhud = 1
		target.SetSleeping(20)
		spawn(rand(50,100))
			target.hal_screwyhud = 0
			target.SetSleeping(0)

/obj/effect/hallucination/battle

/obj/effect/hallucination/battle/New(loc,var/mob/living/carbon/T)
	target = T
	var/hits = rand(3,6)
	switch(rand(1,5))
		if(1) //Laser fight
			for(var/i=0,i<hits,i++)
				target << sound('sound/weapons/Laser.ogg',0,1,0,25)
				sleep(rand(1,5))
			target << sound(get_sfx("bodyfall"),0,1,0,25)
		if(2) //Esword fight
			target << sound('sound/weapons/saberon.ogg',0,1,0,15)
			for(var/i=0,i<hits,i++)
				target << sound('sound/weapons/blade1.ogg',,0,1,0,25)
				sleep(rand(1,5))
			target << sound(get_sfx("bodyfall"),0,1,0,25)
			target << sound('sound/weapons/saberoff.ogg',0,1,0,15)
		if(3) //Gun fight
			for(var/i=0,i<hits,i++)
				target << sound(get_sfx("gunshot"),0,1,0,25)
				sleep(rand(1,5))
			target << sound(get_sfx("bodyfall"),0,1,0,25)
		if(4) //Stunprod + cablecuff
			target << sound('sound/weapons/Egloves.ogg',0,1,40)
			target << sound(get_sfx("bodyfall"),0,1,0,25)
			sleep(30)
			target << sound('sound/weapons/cablecuff.ogg',0,1,0,15)
		if(5) // Tick Tock
			for(var/i=0,i<hits,i++)
				target << sound('sound/items/timer.ogg',0,1,0,25)
				sleep(15)
	qdel(src)

/obj/effect/hallucination/delusion
	var/list/image/delusions = list()

/obj/effect/hallucination/delusion/New(loc,mob/living/carbon/T,force_kind = null , duration = 300,skip_nearby = 1, custom_icon = null, custom_icon_file = null)
	target = T
	var/image/A = null
	var/kind = force_kind ? force_kind : pick("clown","corgi","carp","skeleton","demon")
	for(var/mob/living/carbon/human/H in living_mob_list)
		if(H == target)
			continue
		if(skip_nearby && (H in view(target)))
			continue
		switch(kind)
			if("clown")//Clown
				A = image('icons/mob/animal.dmi',H,"clown")
			if("carp")//Carp
				A = image('icons/mob/animal.dmi',H,"carp")
			if("corgi")//Corgi
				A = image('icons/mob/pets.dmi',H,"corgi")
			if("skeleton")//Skeletons
				A = image('icons/mob/human.dmi',H,"skeleton_s")
			if("demon")//Demon
				A = image('icons/mob/mob.dmi',H,"daemon")
			if("custom")
				A = image(custom_icon_file, H, custom_icon)
		A.override = 1
		if(target.client)
			delusions |= A
			target.client.images |= A
	sleep(duration)
	for(var/image/I in delusions)
		if(target.client)
			target.client.images.Remove(I)
	qdel(src)

/obj/effect/hallucination/fakeattacker/New(loc,var/mob/living/carbon/T)
	target = T
	var/mob/living/carbon/human/clone = null
	var/clone_weapon = null

	for(var/mob/living/carbon/human/H in living_mob_list)
		if(H.stat || H.lying)
			continue
		clone = H
		break

	if(!clone)
		return

	var/obj/effect/fake_attacker/F = new/obj/effect/fake_attacker(get_turf(target),target)
	if(clone.l_hand)
		if(!(locate(clone.l_hand) in non_fakeattack_weapons))
			clone_weapon = clone.l_hand.name
			F.weap = clone.l_hand
	else if (clone.r_hand)
		if(!(locate(clone.r_hand) in non_fakeattack_weapons))
			clone_weapon = clone.r_hand.name
			F.weap = clone.r_hand

	F.name = clone.name
	F.my_target = target
	F.weapon_name = clone_weapon

	F.left = image(clone,dir = WEST)
	F.right = image(clone,dir = EAST)
	F.up = image(clone,dir = NORTH)
	F.down = image(clone,dir = SOUTH)

	F.updateimage()
	qdel(src)

/obj/effect/fake_attacker
	icon = null
	icon_state = null
	name = ""
	desc = ""
	density = 0
	anchored = 1
	opacity = 0
	var/mob/living/carbon/human/my_target = null
	var/weapon_name = null
	var/obj/item/weap = null
	var/image/stand_icon = null
	var/image/currentimage = null
	var/icon/base = null
	var/skin_tone
	var/mob/living/clone = null
	var/image/left
	var/image/right
	var/image/up
	var/collapse
	var/image/down

	var/health = 100

/obj/effect/fake_attacker/attackby(obj/item/weapon/P, mob/living/user, params)
	step_away(src,my_target,2)
	user.changeNext_move(CLICK_CD_MELEE)
	user.do_attack_animation(src)
	my_target << sound(pick('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg'))
	my_target.visible_message("[my_target] flails around wildly.", \
							"[my_target] has attacked [src]!")

	src.health -= P.force
	return

/obj/effect/fake_attacker/Crossed(mob/M, somenumber)
	if(M == my_target)
		step_away(src,my_target,2)
		if(prob(30))
			for(var/mob/O in oviewers(world.view , my_target))
				O << "[my_target] stumbles around."

/obj/effect/fake_attacker/New(loc,var/mob/living/carbon/T)
	..()
	my_target = T
	spawn(300)
		qdel(src)
	step_away(src,my_target,2)
	spawn(0)
		attack_loop()

/obj/effect/fake_attacker/proc/updateimage()
//	del src.currentimage
	if(src.dir == NORTH)
		del src.currentimage
		src.currentimage = new /image(up,src)
	else if(src.dir == SOUTH)
		del src.currentimage
		src.currentimage = new /image(down,src)
	else if(src.dir == EAST)
		del src.currentimage
		src.currentimage = new /image(right,src)
	else if(src.dir == WEST)
		del src.currentimage
		src.currentimage = new /image(left,src)
	my_target << currentimage

/obj/effect/fake_attacker/proc/attack_loop()
	while(1)
		sleep(rand(5,10))
		if(src.health < 0)
			collapse()
			continue
		if(get_dist(src,my_target) > 1)
			src.dir = get_dir(src,my_target)
			step_towards(src,my_target)
			updateimage()
		else
			if(prob(15))
				src.do_attack_animation(my_target)
				if(weapon_name)
					my_target << sound(pick('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg'))
					my_target.show_message("[src.name] has attacked [my_target] with [weapon_name]!", 1)
					my_target.staminaloss += 30
					if(prob(20))
						my_target.blur_eyes(3)
					if(prob(33))
						if(!locate(/obj/effect/overlay) in my_target.loc)
							fake_blood(my_target)
				else
					my_target << sound(pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg'))
					my_target.show_message("[src.name] has punched [my_target]!", 1)
					my_target.staminaloss += 30
					if(prob(33))
						if(!locate(/obj/effect/overlay) in my_target.loc)
							fake_blood(my_target)

		if(prob(15))
			step_away(src,my_target,2)

/obj/effect/fake_attacker/proc/collapse()
	collapse = 1
	updateimage()

/obj/effect/fake_attacker/proc/fake_blood(mob/target)
	var/obj/effect/overlay/O = new/obj/effect/overlay(target.loc)
	O.name = "blood"
	var/image/I = image('icons/effects/blood.dmi',O,"floor[rand(1,7)]",O.dir,1)
	target << I
	spawn(300)
		qdel(O)
	return

var/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/projectile, /obj/item/ammo_box/a357,\
	/obj/item/weapon/gun/energy/kinetic_accelerator/crossbow, /obj/item/weapon/melee/energy/sword/saber,\
	/obj/item/weapon/storage/box/syndicate, /obj/item/weapon/storage/box/emps,\
	/obj/item/weapon/cartridge/syndicate, /obj/item/clothing/under/chameleon,\
	/obj/item/clothing/shoes/chameleon, /obj/item/weapon/card/id/syndicate,\
	/obj/item/clothing/mask/chameleon, /obj/item/clothing/glasses/thermal,\
	/obj/item/device/chameleon, /obj/item/weapon/card/emag,\
	/obj/item/weapon/storage/toolbox/syndicate, /obj/item/weapon/aiModule,\
	/obj/item/device/radio/headset/syndicate,	/obj/item/weapon/c4,\
	/obj/item/device/powersink, /obj/item/weapon/storage/box/syndie_kit,\
	/obj/item/toy/syndicateballoon, /obj/item/weapon/gun/energy/laser/captain,\
	/obj/item/weapon/hand_tele, /obj/item/weapon/rcd, /obj/item/weapon/tank/jetpack,\
	/obj/item/clothing/under/rank/captain, /obj/item/device/aicard,\
	/obj/item/clothing/shoes/magboots, /obj/item/areaeditor/blueprints, /obj/item/weapon/disk/nuclear,\
	/obj/item/clothing/suit/space/nasavoid, /obj/item/weapon/tank)

/obj/effect/hallucination/bolts
	var/list/doors = list()

/obj/effect/hallucination/bolts/New(loc,var/mob/living/carbon/T,var/door_number=-1) //-1 for sever 1-2 for subtle
	target = T
	var/image/I = null
	var/count = 0
	for(var/obj/machinery/door/airlock/A in range(7, target))
		if(count>door_number && door_number>0)
			break
		count++
		I = image(A.icon,A,"door_locked",layer=A.layer+0.1)
		doors += I
		if(target.client)
			target.client.images |= I
		sleep(2)
	sleep(100)
	for(var/image/B in doors)
		if(target.client)
			target.client.images.Remove(B)
	qdel(src)

/obj/effect/hallucination/whispers

/obj/effect/hallucination/whispers/New(loc,var/mob/living/carbon/T)
	target = T
	var/speak_messages = list("I'm watching you...","[target.name]!","Go away!","Kchck-Chkck? Kchchck!","Did you hear that?","What did you do ?","Why?","Give me that!","Honk!","HELP!!")
	var/radio_messages = list("Xenos!","Singularity loose!","They are arming the nuke!","They butchered Ian!","H-help!","[pick(teleportlocs)]!!","Where's [target.name]?","Call the shuttle!")

	var/list/mob/living/carbon/people = list()
	var/list/mob/living/carbon/person = null
	for(var/mob/living/carbon/H in view(target))
		if(H == target)
			continue
		if(!person)
			person = H
		else
			if(get_dist(target,H)<get_dist(target,person))
				person = H
		people += H
	if(person) //Basic talk
		target << target.compose_message(person,person.languages,pick(speak_messages),null,person.get_spans())
	else // Radio talk
		var/list/humans = list()
		for(var/mob/living/carbon/human/H in living_mob_list)
			humans += H
		person = pick(humans)
		target << target.compose_message(person,person.languages,pick(radio_messages),"1459",person.get_spans())
	qdel(src)

/obj/effect/hallucination/message

/obj/effect/hallucination/message/New(loc,var/mob/living/carbon/T)
	target = T
	var/chosen = pick("The light burns you!", \
		"You don't feel like yourself.", \
		"Unknown has punched [target]!", \
		"You hear something squeezing through the ducts...", \
		"You hear a distant scream.", \
		"You feel invincible, nothing can hurt you!", \
		"[target] sneezes.", \
		"You feel faint.", \
		"You hear a strange, alien voice in your head...[pick("Hiss","Ssss")]", \
		"You can see...everything!")
	target << chosen
	qdel(src)

/mob/living/carbon/proc/hallucinate(hal_type) // Todo -> proc / defines
	switch(hal_type)
		if("xeno")
			new /obj/effect/hallucination/xeno_attack(src.loc,src)
		if("singulo")
			new /obj/effect/hallucination/singularity_scare(src.loc,src)
		if("battle")
			new /obj/effect/hallucination/battle(src.loc,src)
		if("flood")
			new /obj/effect/hallucination/fake_flood(src.loc,src)
		if("delusion")
			new /obj/effect/hallucination/delusion(src.loc,src)
		if("fake")
			new /obj/effect/hallucination/fakeattacker(src.loc,src)
		if("bolts")
			new /obj/effect/hallucination/bolts(src.loc,src)
		if("bolts_minor")
			new /obj/effect/hallucination/bolts(src.loc,src,rand(1,2))
		if("whispers")
			new /obj/effect/hallucination/whispers(src.loc,src)
		if("message")
			new /obj/effect/hallucination/message(src.loc,src)
		if("sounds")
			//Strange audio
			//src << "Strange Audio"
			switch(rand(1,18))
				if(1) src << 'sound/machines/airlock.ogg'
				if(2)
					if(prob(50))src << 'sound/effects/Explosion1.ogg'
					else src << 'sound/effects/Explosion2.ogg'
				if(3) src << 'sound/effects/explosionfar.ogg'
				if(4) src << 'sound/effects/Glassbr1.ogg'
				if(5) src << 'sound/effects/Glassbr2.ogg'
				if(6) src << 'sound/effects/Glassbr3.ogg'
				if(7) src << 'sound/machines/twobeep.ogg'
				if(8) src << 'sound/machines/windowdoor.ogg'
				if(9)
					//To make it more realistic, I added two gunshots (enough to kill)
					src << 'sound/weapons/Gunshot.ogg'
					spawn(rand(10,30))
						src << 'sound/weapons/Gunshot.ogg'
				if(10) src << 'sound/weapons/smash.ogg'
				if(11)
					//Same as above, but with tasers.
					src << 'sound/weapons/Taser.ogg'
					spawn(rand(10,30))
						src << 'sound/weapons/Taser.ogg'
			//Rare audio
				if(12)
			//These sounds are (mostly) taken from Hidden: Source
					var/list/creepyasssounds = list('sound/effects/ghost.ogg', 'sound/effects/ghost2.ogg', 'sound/effects/Heart Beat.ogg', 'sound/effects/screech.ogg',\
						'sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/behind_you2.ogg', 'sound/hallucinations/far_noise.ogg', 'sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg',\
						'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\
						'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\
						'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg')
					src << pick(creepyasssounds)
				if(13)
					src << "You feel a tiny prick!"
				if(14)
					src << "
Priority Announcement
"
					src << "

The Emergency Shuttle has docked with the station. You have 3 minutes to board the Emergency Shuttle.

"
					src << sound('sound/AI/shuttledock.ogg')
				if(15)
					src << 'sound/items/Welder.ogg'
				if(16)
					src << 'sound/items/Screwdriver.ogg'
				if(17)
					src << 'sound/weapons/saberon.ogg'
				if(18)
					src << 'sound/weapons/saberoff.ogg'
		if("hudscrew")
			//Screwy HUD
			//src << "Screwy HUD"
			hal_screwyhud = pick(1,2,3,3,4,4)
			spawn(rand(100,250))
				hal_screwyhud = 0
		if("items")
			//Strange items
			//src << "Traitor Items"
			if(!halitem)
				halitem = new
				var/list/slots_free = list(ui_lhand,ui_rhand)
				if(l_hand) slots_free -= ui_lhand
				if(r_hand) slots_free -= ui_rhand
				if(istype(src,/mob/living/carbon/human))
					var/mob/living/carbon/human/H = src
					if(!H.belt) slots_free += ui_belt
					if(!H.l_store) slots_free += ui_storage1
					if(!H.r_store) slots_free += ui_storage2
				if(slots_free.len)
					halitem.screen_loc = pick(slots_free)
					halitem.layer = 50
					switch(rand(1,6))
						if(1) //revolver
							halitem.icon = 'icons/obj/guns/projectile.dmi'
							halitem.icon_state = "revolver"
							halitem.name = "Revolver"
						if(2) //c4
							halitem.icon = 'icons/obj/assemblies.dmi'
							halitem.icon_state = "plastic-explosive0"
							halitem.name = "Mysterious Package"
							if(prob(25))
								halitem.icon_state = "c4small_1"
						if(3) //sword
							halitem.icon = 'icons/obj/weapons.dmi'
							halitem.icon_state = "sword1"
							halitem.name = "Sword"
						if(4) //stun baton
							halitem.icon = 'icons/obj/weapons.dmi'
							halitem.icon_state = "stunbaton"
							halitem.name = "Stun Baton"
						if(5) //emag
							halitem.icon = 'icons/obj/card.dmi'
							halitem.icon_state = "emag"
							halitem.name = "Cryptographic Sequencer"
						if(6) //flashbang
							halitem.icon = 'icons/obj/grenade.dmi'
							halitem.icon_state = "flashbang1"
							halitem.name = "Flashbang"
					if(client) client.screen += halitem
					spawn(rand(100,250))
						qdel(halitem)
		if("dangerflash")
			//Flashes of danger
			//src << "Danger Flash"
			if(!halimage)
				var/list/possible_points = list()
				for(var/turf/open/floor/F in view(src,world.view))
					possible_points += F
				if(possible_points.len)
					var/turf/open/floor/target = pick(possible_points)

					switch(rand(1,3))
						if(1)
							//src << "Space"
							halimage = image('icons/turf/space.dmi',target,"[rand(1,25)]",TURF_LAYER)
						if(2)
							//src << "Fire"
							halimage = image('icons/effects/fire.dmi',target,"1",TURF_LAYER)
						if(3)
							//src << "C4"
							halimage = image('icons/obj/assemblies.dmi',target,"plastic-explosive2",OBJ_LAYER+0.01)

					if(client) client.images += halimage
					spawn(rand(10,50)) //Only seen for a brief moment.
						if(client) client.images -= halimage
						halimage = null
		if("death")
			//Fake death
			hal_screwyhud = 1
			SetSleeping(20)
			spawn(rand(50,100))
				hal_screwyhud = 0
				SetSleeping(0)
		if("husks")
			if(!halbody)
				var/list/possible_points = list()
				for(var/turf/open/floor/F in view(src,world.view))
					possible_points += F
				if(possible_points.len)
					var/turf/open/floor/target = pick(possible_points)
					switch(rand(1,4))
						if(1)
							var/image/body = image('icons/mob/human.dmi',target,"husk_s",TURF_LAYER)
							var/matrix/M = matrix()
							M.Turn(90)
							body.transform = M
							halbody = body
						if(2,3)
							halbody = image('icons/mob/human.dmi',target,"husk_s",TURF_LAYER)
						if(4)
							halbody = image('icons/mob/alien.dmi',target,"alienother",TURF_LAYER)

					if(client) client.images += halbody
					spawn(rand(50,80)) //Only seen for a brief moment.
						if(client) client.images -= halbody
						halbody = null


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

//is this shit even used at all
/proc/NewStutter(phrase,stunned)
	phrase = html_decode(phrase)

	var/list/split_phrase = splittext(phrase," ") //Split it up into words.

	var/list/unstuttered_words = split_phrase.Copy()
	var/i = rand(1,3)
	if(stunned) i = split_phrase.len
	for(,i > 0,i--) //Pick a few words to stutter on.

		if (!unstuttered_words.len)
			break
		var/word = pick(unstuttered_words)
		unstuttered_words -= word //Remove from unstuttered words so we don't stutter it again.
		var/index = split_phrase.Find(word) //Find the word in the split phrase so we can replace it.

		//Search for dipthongs (two letters that make one sound.)
		var/first_sound = copytext(word,1,3)
		var/first_letter = copytext(word,1,2)
		if(lowertext(first_sound) in list("ch","th","sh"))
			first_letter = first_sound

		//Repeat the first letter to create a stutter.
		var/rnum = rand(1,3)
		switch(rnum)
			if(1)
				word = "[first_letter]-[word]"
			if(2)
				word = "[first_letter]-[first_letter]-[word]"
			if(3)
				word = "[first_letter]-[word]"

		split_phrase[index] = word

	return sanitize(jointext(split_phrase," "))

/proc/Stagger(mob/M,d) //Technically not a filter, but it relates to drunkenness.
	step(M, pick(d,turn(d,90),turn(d,-90)))

/proc/Ellipsis(original_msg, chance = 50, keep_words)
	if(chance <= 0) return "..."
	if(chance >= 100) return original_msg

	var/list
		words = splittext(original_msg," ")
		new_words = list()

	var/new_msg = ""

	for(var/w in words)
		if(prob(chance))
			new_words += "..."
			if(!keep_words)
				continue
		new_words += w

	new_msg = jointext(new_words," ")

	return new_msg


code:
////////////////////////////////////////////////////////////////////////////////
/// Drinks.
////////////////////////////////////////////////////////////////////////////////
/obj/item/weapon/reagent_containers/food/drinks
	name = "drink"
	desc = "yummy"
	icon = 'icons/obj/drinks.dmi'
	icon_state = null
	flags = OPENCONTAINER
	var/gulp_size = 5 //This is now officially broken ... need to think of a nice way to fix it.
	possible_transfer_amounts = list(5,10,15,20,25,30,50)
	volume = 50
	burn_state = FIRE_PROOF

/obj/item/weapon/reagent_containers/food/drinks/New()
	..()
	pixel_x = rand(-5, 5)
	pixel_y = rand(-5, 5)

/obj/item/weapon/reagent_containers/food/drinks/on_reagent_change()
	if (gulp_size < 5) gulp_size = 5
	else gulp_size = max(round(reagents.total_volume / 5), 5)

/obj/item/weapon/reagent_containers/food/drinks/attack(mob/M, mob/user, def_zone)

	if(!reagents || !reagents.total_volume)
		user << "[src] is empty!"
		return 0

	if(!canconsume(M, user))
		return 0

	if(M == user)
		M << "You swallow a gulp of [src]."

	else
		M.visible_message("[user] attempts to feed the contents of [src] to [M].", "[user] attempts to feed the contents of [src] to [M].")
		if(!do_mob(user, M))
			return
		if(!reagents || !reagents.total_volume)
			return // The drink might be empty after the delay, such as by spam-feeding
		M.visible_message("[user] feeds the contents of [src] to [M].", "[user] feeds the contents of [src] to [M].")
		add_logs(user, M, "fed", reagentlist(src))
	var/fraction = min(gulp_size/reagents.total_volume, 1)
	reagents.reaction(M, INGEST, fraction)
	reagents.trans_to(M, gulp_size)
	playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1)
	return 1

/obj/item/weapon/reagent_containers/food/drinks/afterattack(obj/target, mob/user , proximity)
	if(!proximity) return
	if(istype(target, /obj/structure/reagent_dispensers)) //A dispenser. Transfer FROM it TO us.

		if(!target.reagents.total_volume)
			user << "[target] is empty."
			return

		if(reagents.total_volume >= reagents.maximum_volume)
			user << "[src] is full."
			return

		var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
		user << "You fill [src] with [trans] units of the contents of [target]."

	else if(target.is_open_container()) //Something like a glass. Player probably wants to transfer TO it.
		if(!reagents.total_volume)
			user << "[src] is empty."
			return

		if(target.reagents.total_volume >= target.reagents.maximum_volume)
			user << "[target] is full."
			return
		var/refill = reagents.get_master_reagent_id()
		var/trans = src.reagents.trans_to(target, amount_per_transfer_from_this)
		user << "You transfer [trans] units of the solution to [target]."

		if(isrobot(user)) //Cyborg modules that include drinks automatically refill themselves, but drain the borg's cell
			var/mob/living/silicon/robot/bro = user
			bro.cell.use(30)
			spawn(600)
				reagents.add_reagent(refill, trans)

	return

/obj/item/weapon/reagent_containers/food/drinks/attackby(obj/item/I, mob/user, params)
	if(I.is_hot())
		var/added_heat = (I.is_hot() / 100) //ishot returns a temperature
		if(reagents)
			reagents.chem_temp += added_heat
			user << "You heat [src] with [I]."
			reagents.handle_reactions()
	..()

////////////////////////////////////////////////////////////////////////////////
/// Drinks. END
////////////////////////////////////////////////////////////////////////////////

/obj/item/weapon/reagent_containers/food/drinks/trophy
	name = "pewter cup"
	desc = "Everyone gets a trophy."
	icon_state = "pewter_cup"
	w_class = 1
	force = 1
	throwforce = 1
	amount_per_transfer_from_this = 5
	materials = list(MAT_METAL=100)
	possible_transfer_amounts = list()
	volume = 5
	flags = CONDUCT | OPENCONTAINER
	spillable = 1

/obj/item/weapon/reagent_containers/food/drinks/trophy/gold_cup
	name = "gold cup"
	desc = "You're winner!"
	icon_state = "golden_cup"
	w_class = 4
	force = 14
	throwforce = 10
	amount_per_transfer_from_this = 20
	materials = list(MAT_GOLD=1000)
	volume = 150

/obj/item/weapon/reagent_containers/food/drinks/trophy/silver_cup
	name = "silver cup"
	desc = "Best loser!"
	icon_state = "silver_cup"
	w_class = 3
	force = 10
	throwforce = 8
	amount_per_transfer_from_this = 15
	materials = list(MAT_SILVER=800)
	volume = 100

/obj/item/weapon/reagent_containers/food/drinks/trophy/bronze_cup
	name = "bronze cup"
	desc = "At least you ranked!"
	icon_state = "bronze_cup"
	w_class = 2
	force = 5
	throwforce = 4
	amount_per_transfer_from_this = 10
	materials = list(MAT_METAL=400)
	volume = 25

///////////////////////////////////////////////Drinks
//Notes by Darem: Drinks are simply containers that start preloaded. Unlike condiments, the contents can be ingested directly
//	rather then having to add it to something else first. They should only contain liquids. They have a default container size of 50.
//	Formatting is the same as food.

/obj/item/weapon/reagent_containers/food/drinks/coffee
	name = "Robust Coffee"
	desc = "Careful, the beverage you're about to enjoy is extremely hot."
	icon_state = "coffee"
	list_reagents = list("coffee" = 30)
	spillable = 1

/obj/item/weapon/reagent_containers/food/drinks/ice
	name = "Ice Cup"
	desc = "Careful, cold ice, do not chew."
	icon_state = "coffee"
	list_reagents = list("ice" = 30)
	spillable = 1

/obj/item/weapon/reagent_containers/food/drinks/mug/ // parent type is literally just so empty mug sprites are a thing
	name = "mug"
	desc = "A drink served in a classy mug."
	icon_state = "tea"
	item_state = "coffee"
	spillable = 1

/obj/item/weapon/reagent_containers/food/drinks/mug/on_reagent_change()
	if(reagents.total_volume)
		icon_state = "tea"
	else
		icon_state = "tea_empty"

/obj/item/weapon/reagent_containers/food/drinks/mug/tea
	name = "Duke Purple Tea"
	desc = "An insult to Duke Purple is an insult to the Space Queen! Any proper gentleman will fight you, if you sully this tea."
	list_reagents = list("tea" = 30)

/obj/item/weapon/reagent_containers/food/drinks/mug/coco
	name = "Dutch Hot Coco"
	desc = "Made in Space South America."
	list_reagents = list("hot_coco" = 30, "sugar" = 5)

/obj/item/weapon/reagent_containers/food/drinks/dry_ramen
	name = "Cup Ramen"
	desc = "Just add 10ml of water, self heats! A taste that reminds you of your school years."
	icon_state = "ramen"
	list_reagents = list("dry_ramen" = 30)

/obj/item/weapon/reagent_containers/food/drinks/beer
	name = "Space Beer"
	desc = "Beer. In space."
	icon_state = "beer"
	list_reagents = list("beer" = 30)

/obj/item/weapon/reagent_containers/food/drinks/ale
	name = "Magm-Ale"
	desc = "A true dorf's drink of choice."
	icon_state = "alebottle"
	item_state = "beer"
	list_reagents = list("ale" = 30)

/obj/item/weapon/reagent_containers/food/drinks/sillycup
	name = "Paper Cup"
	desc = "A paper water cup."
	icon_state = "water_cup_e"
	possible_transfer_amounts = list()
	volume = 10
	spillable = 1

/obj/item/weapon/reagent_containers/food/drinks/sillycup/on_reagent_change()
	if(reagents.total_volume)
		icon_state = "water_cup"
	else
		icon_state = "water_cup_e"

//////////////////////////drinkingglass and shaker//
//Note by Darem: This code handles the mixing of drinks. New drinks go in three places: In Chemistry-Reagents.dm (for the drink
//	itself), in Chemistry-Recipes.dm (for the reaction that changes the components into the drink), and here (for the drinking glass
//	icon states.

/obj/item/weapon/reagent_containers/food/drinks/shaker
	name = "shaker"
	desc = "A metal shaker to mix drinks in."
	icon_state = "shaker"
	amount_per_transfer_from_this = 10
	volume = 100

/obj/item/weapon/reagent_containers/food/drinks/flask
	name = "captain's flask"
	desc = "A silver flask belonging to the captain."
	icon_state = "flask"
	materials = list(MAT_SILVER=500)
	volume = 60

/obj/item/weapon/reagent_containers/food/drinks/flask/det
	name = "detective's flask"
	desc = "The detective's only true friend."
	icon_state = "detflask"
	materials = list(MAT_METAL=250)
	list_reagents = list("whiskey" = 30)

/obj/item/weapon/reagent_containers/food/drinks/britcup
	name = "cup"
	desc = "A cup with the british flag emblazoned on it."
	icon_state = "britcup"
	volume = 30
	spillable = 1

//////////////////////////soda_cans//
//These are in their own group to be used as IED's in /obj/item/weapon/grenade/ghettobomb.dm

/obj/item/weapon/reagent_containers/food/drinks/soda_cans
	name = "soda can"

/obj/item/weapon/reagent_containers/food/drinks/soda_cans/attack(mob/M, mob/user)
	if(M == user && !src.reagents.total_volume && user.a_intent == "harm" && user.zone_selected == "head")
		user.visible_message("[user] crushes the can of [src] on \his forehead!", "You crush the can of [src] on your forehead.")
		playsound(user.loc,'sound/weapons/pierce.ogg', rand(10,50), 1)
		var/obj/item/trash/can/crushed_can = new /obj/item/trash/can(user.loc)
		crushed_can.icon_state = icon_state
		qdel(src)
	..()

/obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola
	name = "Space Cola"
	desc = "Cola. in space."
	icon_state = "cola"
	list_reagents = list("cola" = 30)

/obj/item/weapon/reagent_containers/food/drinks/soda_cans/tonic
	name = "T-Borg's Tonic Water"
	desc = "Quinine tastes funny, but at least it'll keep that Space Malaria away."
	icon_state = "tonic"
	list_reagents = list("tonic" = 50)

/obj/item/weapon/reagent_containers/food/drinks/soda_cans/sodawater
	name = "Soda Water"
	desc = "A can of soda water. Why not make a scotch and soda?"
	icon_state = "sodawater"
	list_reagents = list("sodawater" = 50)

/obj/item/weapon/reagent_containers/food/drinks/soda_cans/lemon_lime
	name = "Orange Soda"
	desc = "You wanted ORANGE. It gave you Lemon Lime."
	icon_state = "lemon-lime"
	list_reagents = list("lemon_lime" = 30)

/obj/item/weapon/reagent_containers/food/drinks/soda_cans/lemon_lime/New()
	..()
	name = "Lemon-Lime Soda"

/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_up
	name = "Space-Up"
	desc = "Tastes like a hull breach in your mouth."
	icon_state = "space-up"
	list_reagents = list("space_up" = 30)

/obj/item/weapon/reagent_containers/food/drinks/soda_cans/starkist
	name = "Star-kist"
	desc = "The taste of a star in liquid form. And, a bit of tuna...?"
	icon_state = "starkist"
	list_reagents = list("cola" = 15, "orangejuice" = 15)

/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_mountain_wind
	name = "Space Mountain Wind"
	desc = "Blows right through you like a space wind."
	icon_state = "space_mountain_wind"
	list_reagents = list("spacemountainwind" = 30)

/obj/item/weapon/reagent_containers/food/drinks/soda_cans/thirteenloko
	name = "Thirteen Loko"
	desc = "The CMO has advised crew members that consumption of Thirteen Loko may result in seizures, blindness, drunkeness, or even death. Please Drink Responsibly."
	icon_state = "thirteen_loko"
	list_reagents = list("thirteenloko" = 30)

/obj/item/weapon/reagent_containers/food/drinks/soda_cans/dr_gibb
	name = "Dr. Gibb"
	desc = "A delicious mixture of 42 different flavors."
	icon_state = "dr_gibb"
	list_reagents = list("dr_gibb" = 30)