code:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Large finds - (Potentially) active alien machinery from the dawn of time

/datum/artifact_find
	var/artifact_id
	var/artifact_find_type
	var/artifact_detect_range

/datum/artifact_find/New()
	artifact_detect_range = rand(5,300)

	artifact_id = "[pick("kappa","sigma","antaeres","beta","omicron","iota","epsilon","omega","gamma","delta","tau","alpha")]-[rand(100,999)]"

	artifact_find_type = pick(\
	5;/obj/structure/constructshell,\
	5;/obj/machinery/syndicate_beacon,\
	25;/obj/machinery/power/supermatter,\
	50;/obj/structure/cult/pylon,\
	100;/obj/machinery/auto_cloner,\
	100;/obj/machinery/giga_drill,\
	100;/obj/mecha/working/hoverpod,\
	100;/obj/machinery/replicator,\
	100;/obj/machinery/communication,\
	1000;/obj/machinery/artifact)

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Boulders - sometimes turn up after excavating turf - excavate further to try and find large xenoarch finds

/obj/structure/boulder
	name = "rocky debris"
	desc = "Leftover rock from an excavation, it's been partially dug out already but there's still a lot to go."
	icon = 'icons/obj/mining.dmi'
	icon_state = "boulder1"
	density = 1
	opacity = 1
	anchored = 1
	var/excavation_level = 0
	var/datum/geosample/geological_data
	var/datum/artifact_find/artifact_find
	var/last_act = 0

/obj/structure/boulder/New()
	..()
	icon_state = "boulder[rand(1,4)]"
	excavation_level = rand(5,50)

/obj/structure/boulder/attackby(obj/item/weapon/W as obj, mob/user as mob)
	if (istype(W, /obj/item/device/core_sampler))
		src.geological_data.artifact_distance = rand(-100,100) / 100
		src.geological_data.artifact_id = artifact_find.artifact_id

		var/obj/item/device/core_sampler/C = W
		C.sample_item(src, user)
		return

	if (istype(W, /obj/item/device/depth_scanner))
		var/obj/item/device/depth_scanner/C = W
		C.scan_atom(user, src)
		return

	if (istype(W, /obj/item/device/measuring_tape))
		var/obj/item/device/measuring_tape/P = W
		user.visible_message("[user] extends [P] towards [src].","You extend [P] towards [src].")
		if(do_after(user,40))
			user << "\icon[P] [src] has been excavated to a depth of [2*src.excavation_level]cm."
		return

	if (istype(W, /obj/item/weapon/pickaxe))
		var/obj/item/weapon/pickaxe/P = W

		if(last_act+P.digspeed > world.time)//prevents message spam
			return
		last_act = world.time

		user << "You start picking [src]."

		if(!do_after(user,P.digspeed))
			return

		user << "You finish cutting into [src]."
		excavation_level += P.excavation_amount

		if(excavation_level > 100)
			//failure
			src.visible_message("\The [src] suddenly crumbles away.")
			user << "\The [src] has disintegrated under your onslaught, any secrets it was holding are long gone."
			del(src)
			return

		if(prob(excavation_level))
			//success
			src.visible_message("[src] suddenly crumbles away.")
			if(artifact_find)
				var/spawn_type = artifact_find.artifact_find_type
				var/obj/O = new spawn_type(get_turf(src))
				if(istype(O,/obj/machinery/artifact))
					var/obj/machinery/artifact/X = O
					if(X.my_effect)
						X.my_effect.artifact_id = artifact_find.artifact_id
			else
				user << "[src] has been whittled away under your careful excavation, but there was nothing of interest inside."
			del(src)

/obj/structure/boulder/Bumped(AM)
	. = ..()
	if(istype(AM,/mob/living/carbon/human))
		var/mob/living/carbon/human/H = AM
		if(istype(H.get_active_hand(),/obj/item/weapon/pickaxe))
			attackby(H.get_active_hand(), H)
		else if(istype(H.get_inactive_hand(),/obj/item/weapon/pickaxe))
			attackby(H.get_inactive_hand(), H)

	else if(istype(AM,/mob/living/silicon/robot))
		var/mob/living/silicon/robot/R = AM
		if(istype(R.module_active,/obj/item/weapon/pickaxe))
			attackby(R.module_active, R)

	else if(istype(AM,/obj/mecha))
		var/obj/mecha/M = AM
		if(istype(M.selected,/obj/item/mecha_parts/mecha_equipment/tool/drill))
			M.selected.action(src)


code:
/obj/machinery/auto_cloner
	name = "mysterious pod"
	desc = "It's full of a viscous liquid, but appears dark and silent."
	icon = 'icons/obj/cryogenics.dmi'
	icon_state = "cellold0"
	var/spawn_type
	var/current_ticks_spawning = 0
	var/ticks_required_to_spawn
	density = 1
	var/previous_power_state = 0

	use_power = 1
	active_power_usage = 2000
	idle_power_usage = 1000

/obj/machinery/auto_cloner/New()
	..()

	ticks_required_to_spawn = rand(240,1440)

	//33% chance to spawn nasties
	if(prob(33))
		spawn_type = pick(\
		/mob/living/simple_animal/hostile/poison/giant_spider/nurse,\
		/mob/living/simple_animal/hostile/alien,\
		/mob/living/simple_animal/hostile/bear,\
		/mob/living/simple_animal/hostile/creature\
		)
	else
		spawn_type = pick(\
		/mob/living/simple_animal/cat,\
		/mob/living/simple_animal/corgi,\
		/mob/living/simple_animal/corgi/puppy,\
		/mob/living/simple_animal/chicken,\
		/mob/living/simple_animal/cow,\
		/mob/living/simple_animal/parrot,\
		/mob/living/simple_animal/slime,\
		/mob/living/simple_animal/crab,\
		/mob/living/simple_animal/mouse,\
		/mob/living/simple_animal/hostile/retaliate/goat,\
		/mob/living/carbon/monkey\
		)

//todo: how the hell is the asteroid permanently powered?
/obj/machinery/auto_cloner/process()
	if(powered(power_channel))
		if(!previous_power_state)
			previous_power_state = 1
			icon_state = "cellold1"
			src.visible_message("\icon[src] [src] suddenly comes to life!")

		//slowly grow a mob
		current_ticks_spawning++
		if(prob(5))
			src.visible_message("\icon[src] [src] [pick("gloops","glugs","whirrs","whooshes","hisses","purrs","hums","gushes")].")

		//if we've finished growing...
		if(current_ticks_spawning >= ticks_required_to_spawn)
			current_ticks_spawning = 0
			use_power = 1
			src.visible_message("\icon[src] [src] pings!")
			icon_state = "cellold1"
			desc = "It's full of a bubbling viscous liquid, and is lit by a mysterious glow."
			if(spawn_type)
				new spawn_type(src.loc)

		//if we're getting close to finished, kick into overdrive power usage
		if(current_ticks_spawning / ticks_required_to_spawn > 0.75)
			use_power = 2
			icon_state = "cellold2"
			desc = "It's full of a bubbling viscous liquid, and is lit by a mysterious glow. A dark shape appears to be forming inside..."
		else
			use_power = 1
			icon_state = "cellold1"
			desc = "It's full of a bubbling viscous liquid, and is lit by a mysterious glow."
	else
		if(previous_power_state)
			previous_power_state = 0
			icon_state = "cellold0"
			src.visible_message("\icon[src] [src] suddenly shuts down.")

		//cloned mob slowly breaks down
		if(current_ticks_spawning > 0)
			current_ticks_spawning--

license: mit


code:
/obj/machinery/communication
	name = "Ancient Device"
	desc = "There seems to be six slots capable of holding small crystals placed along its side"
	icon = 'icons/obj/xenoarchaeology.dmi'
	icon_state = "communication"
	stat = NOPOWER //Niggers you will wrench this shit down or else
	density = 1
	use_power = 1
	active_power_usage = 4000
	idle_power_usage = 1000
	var/list/obj/item/commstone/allstones = list()
	var/remaining = 6
//	machine_flags = WRENCHMOVE

/obj/machinery/communication/attackby(obj/item/W as obj, mob/user as mob)
	if(istype(W,/obj/item/commstone))
		if((W in allstones) && remaining < 6)
			user.drop_item()
			qdel(W)
			user << "You place one of the strange stones back onto the ancient device, it snaps into place."
			remaining++
			return

	if(default_unfasten_wrench(user, W, time = 60))
		power_change()
		return
	..()

/obj/machinery/communication/process()
	if(!anchored)
		stat = NOPOWER
	..()

/obj/machinery/communication/attack_ai(mob/user as mob)
	return //Robots HA

/obj/machinery/communication/attack_hand(mob/user as mob)
	if(..()) return 1
//	if(contents.len)
//		var/obj/item/commstone/stone = contents[1]
//		user.put_in_hands(stone)
//		user << "You delicately remove one of the strange stones from the ancient device."
//		return
	if(remaining)
		var/obj/item/commstone/stone = new(remaining)
		user.put_in_hands(stone)
		stone.commdevice = src
		allstones += stone
		remaining--
		user << "You delicately remove one of the strange stones from the ancient device."
		return

/obj/machinery/communication/examine(mob/user as mob)
	..()
	if(remaining)
		user << "The device's slots still apears to hold [remaining] stone\s."
	else
		user << "The device no longer has any stones in any of its holders."
	if(stat & NOPOWER)
		user << "It seems the machine is currently dark, perhaps it would activate when anchored into a powered area."

/obj/machinery/communication/Destroy()
	for(var/stone in contents)
		qdel(stone)
	..()

/obj/machinery/communication/proc/get_active_stones()
	if((stat & NOPOWER) && !anchored) return list()
	var/list/obj/item/commstone/thestones = allstones
	for(var/obj/item/commstone/check in thestones)
		if(check.loc == src)
			thestones -= check
	return thestones

/obj/item/commstone
	name = "Strange Stone"
	desc = "You can hear small voices coming from within, they whisper through to you a soft but persistent message - 'use .y'"
	icon = 'icons/obj/xenoarchaeology.dmi'
	icon_state = "crystal1"
	w_class = 2
	var/obj/machinery/communication/commdevice = null
	var/number = null

/obj/item/commstone/New(remaining)
	..()
	number = remaining
	update_icon()

/obj/item/commstone/Destroy()
	commdevice.allstones -= src
	..()

/obj/item/commstone/examine(mob/user as mob)
	..()
	if(!commdevice || (commdevice.stat & NOPOWER))
		user << "It seems to have lost its luster, perhaps the device it is connected to isn't functional."

/obj/item/commstone/update_icon()
	icon_state = "crystal[number]"


code:
/obj/structure/crystal
	name = "large crystal"
	icon = 'icons/obj/xenoarchaeology.dmi'
	icon_state = "crystal"
	density = 1

/obj/structure/crystal/New()
	..()

	icon_state = pick("ano70","ano80")

	desc = pick(\
	"It shines faintly as it catches the light.",\
	"It appears to have a faint inner glow.",\
	"It seems to draw you inward as you look it at.",\
	"Something twinkles faintly as you look at it.",\
	"It's mesmerizing to behold.")

/obj/structure/crystal/Destroy()
	src.visible_message("[src] shatters!")
/*	if(prob(75))
		getFromPool(/obj/item/weapon/shard/plasma, loc)
	if(prob(50))
		getFromPool(/obj/item/weapon/shard/plasma, loc)
	if(prob(25))
		getFromPool(/obj/item/weapon/shard/plasma, loc) */
	if(prob(75))
		new /obj/item/weapon/shard(loc)
	if(prob(50))
		new /obj/item/weapon/shard(loc)
	if(prob(25))
		new /obj/item/weapon/shard(loc)
	..()

//todo: laser_act


code:
/obj/machinery/giga_drill
	name = "alien drill"
	desc = "A giant, alien drill mounted on long treads."
	icon = 'icons/obj/mining.dmi'
	icon_state = "gigadrill"
	var/active = 0
	var/drill_time = 2.5
	var/turf/drilling_turf
	density = 1
	layer = 3.1		//to go over ores

/obj/machinery/giga_drill/attack_hand(mob/user as mob)
	if(active)
		active = 0
		icon_state = "gigadrill"
		user << "You press a button and [src] slowly spins down."
	else
		active = 1
		icon_state = "gigadrill_mov"
		user << "You press a button and [src] shudders to life."

/obj/machinery/giga_drill/Bump(atom/A)
	if(active && !drilling_turf)
		if(istype(A,/turf/simulated/mineral))
			var/turf/simulated/mineral/M = A
			drilling_turf = get_turf(src)
			src.visible_message("[src] begins to drill into [M]!")
			anchored = 1
			spawn(drill_time)
				if(get_turf(src) == drilling_turf && active)
					M.gets_drilled()
					src.loc = M
				drilling_turf = null
				anchored = 0


code:
/obj/mecha/working/hoverpod
	name = "hover pod"
	icon_state = "engineering_pod"
	desc = "Stubby and round, it has a human sized access hatch on the top."
	wreckage = /obj/effect/decal/mecha_wreckage/hoverpod
	stepsound = 'sound/machines/hiss.ogg'
	step_in = 2

/obj/mecha/working/hoverpod/Process_Spacemove(var/movement_dir = 0)
	return 1
/*
//duplicate of parent proc, but without space drifting
/obj/mecha/working/hoverpod/dyndomove(direction)
	if(!can_move)
		return 0
	if(src.pr_inertial_movement.active())
		return 0
	if(!has_charge(step_energy_drain))
		return 0
	var/move_result = 0
	if(hasInternalDamage(MECHA_INT_CONTROL_LOST))
		move_result = mechsteprand()
	else if(src.dir!=direction)
		move_result = mechturn(direction)
	else
		move_result	= mechstep(direction)
	if(move_result)
		can_move = 0
		use_power(step_energy_drain)
		if(do_after(step_in))
			can_move = 1
		return 1
	return 0
*/
//these three procs overriden to play different sounds
/obj/mecha/working/hoverpod/mechturn(direction)
	dir = direction
	//playsound(src,'sound/machines/hiss.ogg',40,1)
	return 1

/obj/effect/decal/mecha_wreckage/hoverpod
	name = "Hover pod wreckage"
	icon_state = "engineering_pod-broken"

	/*New()
		..()
		var/list/parts = list(

		for(var/i=0;i<2;i++)
			if(!isemptylist(parts) && prob(40))
				var/part = pick(parts)
				welder_salvage += part
				parts -= part
		return*/


code:
/obj/machinery/replicator
	name = "alien machine"
	desc = "It's some kind of pod with strange wires and gadgets all over it."
	icon = 'icons/obj/xenoarchaeology.dmi'
	icon_state = "borgcharger0(old)"
	density = 1

	idle_power_usage = 100
	active_power_usage = 1000
	use_power = 1

	var/spawn_progress = 0
	var/max_spawn_ticks = 5
	var/list/construction = list()
	var/list/spawning_types = list()

/obj/machinery/replicator/New()
	..()

	var/list/viables = list(\
	/obj/item/roller,\
	/obj/structure/closet/crate,\
	/obj/structure/closet/acloset,\
	/mob/living/simple_animal/hostile/mimic,\
	/mob/living/simple_animal/hostile/viscerator,\
	/mob/living/simple_animal/hostile/hivebot,\
	/obj/item/device/analyzer,\
	/obj/item/device/camera,\
	/obj/item/device/flash,\
	/obj/item/device/flashlight,\
	/obj/item/device/healthanalyzer,\
	/obj/item/device/multitool,\
	/obj/item/device/paicard,\
	/obj/item/device/radio,\
	/obj/item/device/radio/headset,\
	/obj/item/device/radio/beacon,\
/*	/obj/item/weapon/autopsy_scanner, \ */
	/obj/item/weapon/bikehorn,\
/*	/obj/item/weapon/bonesetter,\ */
	/obj/item/weapon/kitchenknife/butcher,
	/obj/item/weapon/caution,\
//	/obj/item/weapon/caution/cone,
	/obj/item/weapon/crowbar,\
	/obj/item/weapon/clipboard,\
	/obj/item/weapon/stock_parts/cell,\
	/obj/item/weapon/circular_saw,\
	/obj/item/weapon/hatchet,\
	/obj/item/weapon/restraints/handcuffs,\
	/obj/item/weapon/hemostat,\
	/obj/item/weapon/kitchenknife,\
	/obj/item/weapon/lighter,\
	/obj/item/weapon/lighter,\
	/obj/item/weapon/light/bulb,\
	/obj/item/weapon/light/tube,\
	/obj/item/weapon/pickaxe,\
/*	/obj/item/weapon/pickaxe/shovel,\
	/obj/item/weapon/table_parts,\ */
	/obj/item/weapon/weldingtool,\
	/obj/item/weapon/wirecutters,\
	/obj/item/weapon/wrench,\
	/obj/item/weapon/screwdriver,\
	/obj/item/weapon/grenade/chem_grenade/cleaner,\
	/obj/item/weapon/grenade/chem_grenade/metalfoam\
	)

	var/quantity = rand(5,15)
	for(var/i=0, i<quantity, i++)
		var/button_desc = "[pick("a yellow","a purple","a green","a blue","a red","an orange","a white")], "
		button_desc += "[pick("round","square","diamond","heart","dog","human")] shaped "
		button_desc += "[pick("toggle","switch","lever","button","pad","hole")]"
		var/type = pick(viables)
		viables.Remove(type)
		construction[button_desc] = type

/obj/machinery/replicator/process()
	if(spawning_types.len && powered())
		spawn_progress++
		if(spawn_progress > max_spawn_ticks)
			src.visible_message("\icon[src] [src] pings!")
			var/spawn_type = spawning_types[1]
			new spawn_type(src.loc)

			spawning_types.Remove(spawning_types[1])
			spawn_progress = 0
			max_spawn_ticks = rand(5,30)

			if(!spawning_types.len)
				use_power = 1
				icon_state = "borgcharger0(old)"

		else if(prob(5))
			src.visible_message("\icon[src] [src] [pick("clicks","whizzes","whirrs","whooshes","clanks","clongs","clonks","bangs")].")

/obj/machinery/replicator/attack_hand(mob/user as mob)
	interact(user)

/obj/machinery/replicator/interact(mob/user)
	var/dat = "The control panel displays an incomprehensible selection of controls, many with unusual markings or text around them.
"
	dat += "
"
	for(var/index=1, index<=construction.len, index++)
		dat += "\[[construction[index]]\]
"

	user << browse(dat, "window=alien_replicator")

/obj/machinery/replicator/Topic(href, href_list)

	if(href_list["activate"])
		var/index = text2num(href_list["activate"])
		if(index > 0 && index <= construction.len)
			if(spawning_types.len)
				src.visible_message("\icon[src] a [pick("light","dial","display","meter","pad")] on [src]'s front [pick("blinks","flashes")] [pick("red","yellow","blue","orange","purple","green","white")].")
			else
				src.visible_message("\icon[src] [src]'s front compartment slides shut.")

			spawning_types.Add(construction[construction[index]])
			spawn_progress = 0
			use_power = 2
			icon_state = "borgcharger1(old)"


code:
#define EFFECT_TOUCH 0
#define EFFECT_AURA 1
#define EFFECT_PULSE 2
#define MAX_EFFECT 2

#define TRIGGER_TOUCH 0
#define TRIGGER_WATER 1
#define TRIGGER_ACID 2
#define TRIGGER_VOLATILE 3
#define TRIGGER_TOXIN 4
#define TRIGGER_FORCE 5
#define TRIGGER_ENERGY 6
#define TRIGGER_HEAT 7
#define TRIGGER_COLD 8
#define TRIGGER_PLASMA 9
#define TRIGGER_OXY 10
#define TRIGGER_CO2 11
#define TRIGGER_NITRO 12
#define MAX_TRIGGER 12
/*
//sleeping gas appears to be bugged, currently
var/list/valid_primary_effect_types = list(\
	/datum/artifact_effect/cellcharge,\
	/datum/artifact_effect/celldrain,\
	/datum/artifact_effect/forcefield,\
	/datum/artifact_effect/gasoxy,\
	/datum/artifact_effect/gasplasma,\
/*	/datum/artifact_effect/gassleeping,\*/
	/datum/artifact_effect/heal,\
	/datum/artifact_effect/hurt,\
	/datum/artifact_effect/emp,\
	/datum/artifact_effect/teleport,\
	/datum/artifact_effect/robohurt,\
	/datum/artifact_effect/roboheal)

var/list/valid_secondary_effect_types = list(\
	/datum/artifact_effect/cold,\
	/datum/artifact_effect/badfeeling,\
	/datum/artifact_effect/cellcharge,\
	/datum/artifact_effect/celldrain,\
	/datum/artifact_effect/dnaswitch,\
	/datum/artifact_effect/emp,\
	/datum/artifact_effect/gasco2,\
	/datum/artifact_effect/gasnitro,\
	/datum/artifact_effect/gasoxy,\
	/datum/artifact_effect/gasplasma,\
/*	/datum/artifact_effect/gassleeping,\*/
	/datum/artifact_effect/goodfeeling,\
	/datum/artifact_effect/heal,\
	/datum/artifact_effect/hurt,\
	/datum/artifact_effect/radiate,\
	/datum/artifact_effect/roboheal,\
	/datum/artifact_effect/robohurt,\
	/datum/artifact_effect/sleepy,\
	/datum/artifact_effect/stun,\
	/datum/artifact_effect/teleport)
	*/

/obj/machinery/artifact
	name = "alien artifact"
	desc = "A large alien device."
	icon = 'icons/obj/xenoarchaeology.dmi'
	icon_state = "ano00"
	var/icon_num = 0
	density = 1
	var/datum/artifact_effect/my_effect
	var/datum/artifact_effect/secondary_effect
	var/being_used = 0

/obj/machinery/artifact/New()
	..()

	//setup primary effect - these are the main ones (mixed)
	var/effecttype = pick(typesof(/datum/artifact_effect) - /datum/artifact_effect)
	my_effect = new effecttype(src)

	//75% chance to have a secondary stealthy (and mostly bad) effect
	if(prob(75))
		effecttype = pick(typesof(/datum/artifact_effect) - /datum/artifact_effect)
		secondary_effect = new effecttype(src)
		if(prob(75))
			secondary_effect.ToggleActivate(0)

	icon_num = rand(0,11)
	icon_state = "ano[icon_num]0"
	if(icon_num == 7 || icon_num == 8)
		name = "large crystal"
		desc = pick("It shines faintly as it catches the light.",\
		"It appears to have a faint inner glow.",\
		"It seems to draw you inward as you look it at.",\
		"Something twinkles faintly as you look at it.",\
		"It's mesmerizing to behold.")
		if(prob(50))
			my_effect.trigger = TRIGGER_ENERGY
	else if(icon_num == 9)
		name = "alien computer"
		desc = "It is covered in strange markings."
		if(prob(75))
			my_effect.trigger = TRIGGER_TOUCH
	else if(icon_num == 10)
		desc = "A large alien device, there appear to be some kind of vents in the side."
		if(prob(50))
			my_effect.trigger = rand(6,12)
	else if(icon_num == 11)
		name = "sealed alien pod"
		desc = "A strange alien device."
		if(prob(25))
			my_effect.trigger = rand(1,4)

#define TRIGGER_PLASMA 9
#define TRIGGER_OXY 10
#define TRIGGER_CO2 11
#define TRIGGER_NITRO 12

/obj/machinery/artifact/process()

	var/turf/L = loc
	if(isnull(L) || !istype(L)) 	// We're inside a container or on null turf, either way stop processing effects
		return

	if(my_effect)
		my_effect.process()
	if(secondary_effect)
		secondary_effect.process()

	if(pulledby)
		if(!(!Adjacent(pulledby) || pulledby.stat || pulledby.sleeping || pulledby.lying || pulledby.weakened || pulledby.stunned)) //prevents CAN'T WAKE UP and other silliness
			if(prob(50))
				Bumped(pulledby)

	//if either of our effects rely on environmental factors, work that out
	var/trigger_cold = 0
	var/trigger_hot = 0
	var/trigger_plasma = 0
	var/trigger_oxy = 0
	var/trigger_co2 = 0
	var/trigger_nitro = 0
	if( (my_effect.trigger >= TRIGGER_HEAT && my_effect.trigger <= TRIGGER_NITRO) || (my_effect.trigger >= TRIGGER_HEAT && my_effect.trigger <= TRIGGER_NITRO) )
		var/turf/T = get_turf(src)
		var/datum/gas_mixture/env = T.return_air()
		if(env)
			if(env.temperature < 225)
				trigger_cold = 1
			else if(env.temperature > 375)
				trigger_hot = 1

			if(env.toxins >= 10)
				trigger_plasma = 1
			if(env.oxygen >= 10)
				trigger_oxy = 1
			if(env.carbon_dioxide >= 10)
				trigger_co2 = 1
			if(env.nitrogen >= 10)
				trigger_nitro = 1

	//COLD ACTIVATION
	if(trigger_cold)
		if(my_effect.trigger == TRIGGER_COLD && !my_effect.activated)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_COLD && !secondary_effect.activated)
			secondary_effect.ToggleActivate(0)
	else
		if(my_effect.trigger == TRIGGER_COLD && my_effect.activated)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_COLD && !secondary_effect.activated)
			secondary_effect.ToggleActivate(0)

	//HEAT ACTIVATION
	if(trigger_hot)
		if(my_effect.trigger == TRIGGER_HEAT && !my_effect.activated)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_HEAT && !secondary_effect.activated)
			secondary_effect.ToggleActivate(0)
	else
		if(my_effect.trigger == TRIGGER_HEAT && my_effect.activated)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_HEAT && !secondary_effect.activated)
			secondary_effect.ToggleActivate(0)

	//PLASMA GAS ACTIVATION
	if(trigger_plasma)
		if(my_effect.trigger == TRIGGER_PLASMA && !my_effect.activated)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_PLASMA && !secondary_effect.activated)
			secondary_effect.ToggleActivate(0)
	else
		if(my_effect.trigger == TRIGGER_PLASMA && my_effect.activated)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_PLASMA && !secondary_effect.activated)
			secondary_effect.ToggleActivate(0)

	//OXYGEN GAS ACTIVATION
	if(trigger_oxy)
		if(my_effect.trigger == TRIGGER_OXY && !my_effect.activated)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_OXY && !secondary_effect.activated)
			secondary_effect.ToggleActivate(0)
	else
		if(my_effect.trigger == TRIGGER_OXY && my_effect.activated)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_OXY && !secondary_effect.activated)
			secondary_effect.ToggleActivate(0)

	//CO2 GAS ACTIVATION
	if(trigger_co2)
		if(my_effect.trigger == TRIGGER_CO2 && !my_effect.activated)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_CO2 && !secondary_effect.activated)
			secondary_effect.ToggleActivate(0)
	else
		if(my_effect.trigger == TRIGGER_CO2 && my_effect.activated)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_CO2 && !secondary_effect.activated)
			secondary_effect.ToggleActivate(0)

	//NITROGEN GAS ACTIVATION
	if(trigger_nitro)
		if(my_effect.trigger == TRIGGER_NITRO && !my_effect.activated)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_NITRO && !secondary_effect.activated)
			secondary_effect.ToggleActivate(0)
	else
		if(my_effect.trigger == TRIGGER_NITRO && my_effect.activated)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_NITRO && !secondary_effect.activated)
			secondary_effect.ToggleActivate(0)

/obj/machinery/artifact/attack_hand(var/mob/user as mob)
	if(isobserver(user))
		user << "Your ghostly hand goes right through!"
		return
	if (get_dist(user, src) > 1)
		user << "You can't reach [src] from here."
		return
	if(ishuman(user) && user:gloves)
		user << "You touch [src] with your gloved hands, [pick("but nothing of note happens","but nothing happens","but nothing interesting happens","but you notice nothing different","but nothing seems to have happened")]."
		return

	src.add_fingerprint(user)

	if(my_effect.trigger == TRIGGER_TOUCH)
		user << "You touch [src]."
		my_effect.ToggleActivate()
	else
		user << "You touch [src], [pick("but nothing of note happens","but nothing happens","but nothing interesting happens","but you notice nothing different","but nothing seems to have happened")]."

	if(prob(25) && secondary_effect && secondary_effect.trigger == TRIGGER_TOUCH)
		secondary_effect.ToggleActivate(0)

	if (my_effect.effect == EFFECT_TOUCH)
		my_effect.DoEffectTouch(user)

	if(secondary_effect && secondary_effect.effect == EFFECT_TOUCH && secondary_effect.activated)
		secondary_effect.DoEffectTouch(user)

/obj/machinery/artifact/attackby(obj/item/weapon/W as obj, mob/living/user as mob)

	if (istype(W, /obj/item/weapon/reagent_containers/glass) && W.is_open_container() ||\
		istype(W, /obj/item/weapon/reagent_containers/dropper))
		if(W.reagents.has_reagent("hydrogen", 1) || W.reagents.has_reagent("water", 1))
			if(my_effect.trigger == TRIGGER_WATER)
				my_effect.ToggleActivate()
			if(secondary_effect && secondary_effect.trigger == TRIGGER_WATER && prob(25))
				secondary_effect.ToggleActivate(0)
		else if(W.reagents.has_reagent("sacid", 1) || W.reagents.has_reagent("pacid", 1) || W.reagents.has_reagent("diethylamine", 1))
			if(my_effect.trigger == TRIGGER_ACID)
				my_effect.ToggleActivate()
			if(secondary_effect && secondary_effect.trigger == TRIGGER_ACID && prob(25))
				secondary_effect.ToggleActivate(0)
		else if(W.reagents.has_reagent("plasma", 1) || W.reagents.has_reagent("thermite", 1))
			if(my_effect.trigger == TRIGGER_VOLATILE)
				my_effect.ToggleActivate()
			if(secondary_effect && secondary_effect.trigger == TRIGGER_VOLATILE && prob(25))
				secondary_effect.ToggleActivate(0)
		else if(W.reagents.has_reagent("toxin", 1) || W.reagents.has_reagent("cyanide", 1) || W.reagents.has_reagent("amatoxin", 1) || W.reagents.has_reagent("neurotoxin", 1))
			if(my_effect.trigger == TRIGGER_TOXIN)
				my_effect.ToggleActivate()
			if(secondary_effect && secondary_effect.trigger == TRIGGER_TOXIN && prob(25))
				secondary_effect.ToggleActivate(0)
	else if(istype(W,/obj/item/weapon/melee/baton) && W:status ||\
			istype(W,/obj/item/weapon/melee/energy) ||\
			istype(W,/obj/item/weapon/melee/cultblade) ||\
			istype(W,/obj/item/weapon/card/emag) ||\
			istype(W,/obj/item/device/multitool))
		if (my_effect.trigger == TRIGGER_ENERGY)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_ENERGY && prob(25))
			secondary_effect.ToggleActivate(0)

	else if (istype(W,/obj/item/weapon/match) && W:lit ||\
			istype(W,/obj/item/weapon/weldingtool) && W:welding ||\
			istype(W,/obj/item/weapon/lighter) && W:lit)
		if(my_effect.trigger == TRIGGER_HEAT)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_HEAT && prob(25))
			secondary_effect.ToggleActivate(0)
	else
		..()
		if (my_effect.trigger == TRIGGER_FORCE && W.force >= 10)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_FORCE && prob(25))
			secondary_effect.ToggleActivate(0)

/obj/machinery/artifact/Bumped(M as mob|obj)
	if(istype(M,/obj))
		if(M:throwforce >= 10)
			if(my_effect.trigger == TRIGGER_FORCE)
				my_effect.ToggleActivate()
			if(secondary_effect && secondary_effect.trigger == TRIGGER_FORCE && prob(25))
				secondary_effect.ToggleActivate(0)
	else if(ishuman(M) && !istype(M:gloves,/obj/item/clothing/gloves))
		var/warn = 0

		if (my_effect.trigger == TRIGGER_TOUCH && prob(50))
			my_effect.ToggleActivate()
			warn = 1
		if(secondary_effect && secondary_effect.trigger == TRIGGER_TOUCH && prob(25))
			secondary_effect.ToggleActivate(0)
			warn = 1

		if (my_effect.effect == EFFECT_TOUCH && prob(50))
			my_effect.DoEffectTouch(M)
			warn = 1
		if(secondary_effect && secondary_effect.effect == EFFECT_TOUCH && secondary_effect.activated && prob(50))
			secondary_effect.DoEffectTouch(M)
			warn = 1

		if(warn)
			M << "You accidentally touch [src]."
	..()

/obj/machinery/artifact/bullet_act(var/obj/item/projectile/P)
	if(istype(P,/obj/item/projectile/bullet) ||\
		istype(P,/obj/item/projectile/hivebotbullet))
		if(my_effect.trigger == TRIGGER_FORCE)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_FORCE && prob(25))
			secondary_effect.ToggleActivate(0)

	else if(istype(P,/obj/item/projectile/beam) ||\
		istype(P,/obj/item/projectile/ion) ||\
		istype(P,/obj/item/projectile/energy))
		if(my_effect.trigger == TRIGGER_ENERGY)
			my_effect.ToggleActivate()
		if(secondary_effect && secondary_effect.trigger == TRIGGER_ENERGY && prob(25))
			secondary_effect.ToggleActivate(0)

/obj/machinery/artifact/ex_act(severity)
	switch(severity)
		if(1.0) qdel(src)
		if(2.0)
			if (prob(50))
				qdel(src)
			else
				if(my_effect.trigger == TRIGGER_FORCE || my_effect.trigger == TRIGGER_HEAT)
					my_effect.ToggleActivate()
				if(secondary_effect && (secondary_effect.trigger == TRIGGER_FORCE || secondary_effect.trigger == TRIGGER_HEAT) && prob(25))
					secondary_effect.ToggleActivate(0)
		if(3.0)
			if (my_effect.trigger == TRIGGER_FORCE || my_effect.trigger == TRIGGER_HEAT)
				my_effect.ToggleActivate()
			if(secondary_effect && (secondary_effect.trigger == TRIGGER_FORCE || secondary_effect.trigger == TRIGGER_HEAT) && prob(25))
				secondary_effect.ToggleActivate(0)
	return

/obj/machinery/artifact/Move()
	..()
	if(my_effect)
		my_effect.UpdateMove()
	if(secondary_effect)
		secondary_effect.UpdateMove()


code:
//Part of ISaidNo's public release around July 2011(ish), multiple changes
//many thanks

#define PLASMA_SPAWN 1
#define N2_SPAWN 2
#define CO2_SPAWN 3
#define RADIATE 4
#define VIRUS 5
#define HEAT 6
#define COLD 7

/obj/machinery/artifact
	name = "alien artifact"
	desc = "A large alien device."
	icon = 'icons/obj/xenoarchaeology.dmi'
	icon_state = "ano00"
	var/icon_num = 0
	anchored = 0
	density = 1
	var/origin = null          // Used in the randomisation/research of the artifact.
	var/activated = 0          // Whether or not the artifact has been unlocked.
	var/charged = 1            // Whether the artifact is ready to have it's effect.
	var/chargetime = 0         // How much time until the artifact is charged.
	var/recharge = 5           // How long does it take this artifact to recharge?
	var/display_id = ""        // Artifact ID to display once successfully scanned
	var/datum/artifact_effect/my_effect = null
	var/being_used = 0

/obj/machinery/artifact/New()
	..()
	// Origin and appearance randomisation

	my_effect = new()

	icon_num = rand(0,5)
	icon_state = "ano[icon_num]0"

	// Power randomisation
	my_effect.trigger = pick("force","energy","chemical","heat","touch","presence")
	if (my_effect.trigger == "chemical")
		my_effect.triggerX = pick("hydrogen","corrosive","volatile","toxic")

	my_effect.effecttype = pick("healing","injure","stun","roboheal","robohurt","cellcharge","celldrain","planthelper","forcefield","teleport","dnaswitch","emp","sleepy")

	// Select range based on the power
	var/canworldpulse = 1
	switch(my_effect.effecttype)
		if("healing")
			my_effect.effectmode = pick("aura","pulse","contact")
		if("injure")
			my_effect.effectmode = pick("aura","pulse","contact")
		if("stun")
			my_effect.effectmode = pick("aura","pulse","contact")
		if("roboheal")
			my_effect.effectmode = pick("aura","pulse","contact")
		if("robohurt")
			my_effect.effectmode = pick("aura","pulse","contact")
		if("sleepy")
			my_effect.effectmode = pick("aura","pulse","contact")
		if("cellcharge")
			my_effect.effectmode = pick("aura","pulse")
		if("celldrain")
			my_effect.effectmode = pick("aura","pulse")
		if("planthelper")
			my_effect.effectmode = pick("aura","pulse")
			canworldpulse = 0
		if("forcefield")
			my_effect.effectmode = "contact"
			canworldpulse = 0
		if("teleport")
			my_effect.effectmode = pick("pulse","contact")
		if("genderswitch")
			my_effect.effectmode = pick("pulse","contact")
		if("emp")
			my_effect.effectmode = pick("pulse","contact")

	// Recharge timer & range setup
	if (my_effect.effectmode == "aura")
		my_effect.aurarange = rand(1,4)
	if (my_effect.effectmode == "contact")
		src.recharge = rand(5,15)
	if (my_effect.effectmode == "pulse")
		my_effect.aurarange = rand(2,14)
		src.recharge = rand(5,20)
	if (canworldpulse == 1 && prob(1))
		my_effect.effectmode = "worldpulse"
		src.recharge = rand(40,120)

	/*
	display_id += pick("kappa","sigma","antaeres","beta","lorard","omicron","iota","upsilon","omega","gamma","delta")
	display_id += "-"
	display_id += num2text(rand(100,999))
	*/

/obj/machinery/artifact/Del()
	..()
	my_effect.HaltEffect()

/obj/machinery/artifact/attack_hand(var/mob/user as mob)
	if (istype(user, /mob/living/silicon/ai) || istype(user, /mob/dead/)) return
	if (istype(user, /mob/living/silicon/robot))
		if (get_dist(user, src) > 1)
			user << "You can't reach [src] from here."
			return
	if(ishuman(user) && istype(user:gloves,/obj/item/clothing/gloves))
		return ..()
	for(var/mob/O in viewers(src, null))
		O.show_message(text("[] touches [].", user, src), 1)
	src.add_fingerprint(user)
	src.Artifact_Contact(user)

/obj/machinery/artifact/attackby(obj/item/weapon/W as obj, mob/living/user as mob)
	/*if (istype(W, /obj/item/weapon/cargotele))
		W:cargoteleport(src, user)
		return*/
	if (my_effect.trigger == "chemical" && istype(W, /obj/item/weapon/reagent_containers/))
		switch(my_effect.triggerX)
			if("hydrogen")
				if (W.reagents.has_reagent("hydrogen", 1) || W.reagents.has_reagent("water", 1))
					src.Artifact_Activate()
					return
			if("corrosive")
				if (W.reagents.has_reagent("acid", 1) || W.reagents.has_reagent("pacid", 1) || W.reagents.has_reagent("diethylamine", 1))
					src.Artifact_Activate()
					return
			if("volatile")
				if (W.reagents.has_reagent("plasma", 1) || W.reagents.has_reagent("thermite", 1))
					src.Artifact_Activate()
					return
			if("toxic")
				if (W.reagents.has_reagent("toxin", 1) || W.reagents.has_reagent("cyanide", 1) || W.reagents.has_reagent("amanitin", 1) || W.reagents.has_reagent("neurotoxin", 1))
					src.Artifact_Activate()
					return
	..()
	if (my_effect.trigger == "force" && W.force >= 10 && !src.activated) src.Artifact_Activate()
	if (my_effect.trigger == "energy")
		if (istype(W,/obj/item/weapon/melee/baton) && W:status) src.Artifact_Activate()
		if (istype(W,/obj/item/weapon/melee/energy)) src.Artifact_Activate()
		if (istype(W,/obj/item/weapon/melee/cultblade)) src.Artifact_Activate()
		if (istype(W,/obj/item/weapon/gun/energy/)) src.Artifact_Activate()
		if (istype(W,/obj/item/device/multitool)) src.Artifact_Activate()
		if (istype(W,/obj/item/weapon/card/emag)) src.Artifact_Activate()
	if (my_effect.trigger == "heat")
		if (istype(W,/obj/item/weapon/match) && W:lit) src.Artifact_Activate()
		if (istype(W, /obj/item/weapon/weldingtool) && W:welding) src.Artifact_Activate()
		if (istype(W, /obj/item/weapon/lighter) && W:lit) src.Artifact_Activate()

	//Bump(atom/A)

/obj/machinery/artifact/Bumped(M as mob|obj)
	if (istype(M,/obj/item/weapon/) && my_effect.trigger == "force" && M:throwforce >= 10) src.Artifact_Activate()

/obj/machinery/artifact/bullet_act(var/obj/item/projectile/P)
	if (my_effect.trigger == "force")
		if(istype(P,/obj/item/projectile/bullet)) src.Artifact_Activate()
		else if(istype(P,/obj/item/projectile/hivebotbullet)) src.Artifact_Activate()
	if (my_effect.trigger == "energy")
		if(istype(P,/obj/item/projectile/beam)) src.Artifact_Activate()
		else if(istype(P,/obj/item/projectile/ion)) src.Artifact_Activate()
		else if(istype(P,/obj/item/projectile/energy)) src.Artifact_Activate()
	if (my_effect.trigger == "heat")
		if(istype(P,/obj/item/projectile/temp)) src.Artifact_Activate()

/obj/machinery/artifact/ex_act(severity)
	switch(severity)
		if(1.0) del src
		if(2.0)
			if (prob(50)) del src
			if (my_effect.trigger == "force") src.Artifact_Activate()
			if (my_effect.trigger == "heat") src.Artifact_Activate()
		if(3.0)
			if (my_effect.trigger == "force") src.Artifact_Activate()
			if (my_effect.trigger == "heat") src.Artifact_Activate()
	return

/obj/machinery/artifact/temperature_expose(null, temp, volume)
	if (my_effect.trigger == "heat") src.Artifact_Activate()

/obj/machinery/artifact/process()
	if (!src.activated)
		return
	if (chargetime > 0)
		chargetime -= 1
	else
		src.charged = 1

	my_effect.UpdateEffect(src.loc)

	//activate
	if( (my_effect.effectmode == "pulse" || my_effect.effecttype == "worldpulse") && activated)
		if(src.charged && my_effect.DoEffect(src))
			src.charged = 0
			src.chargetime = src.recharge

/obj/machinery/artifact/proc/Artifact_Activate()
	src.activated = !src.activated
	var/display_msg = ""
	if(activated)
		if(prob(30))
			switch(rand(4))
				if(0)
					display_msg = "momentarily glows brightly!"
				if(1)
					display_msg = "distorts slightly for a moment!"
				if(2)
					display_msg = "makes a slightly clicking noise!"
				if(3)
					display_msg = "flickers slightly!"
				if(4)
					display_msg = "vibrates!"
	else
		my_effect.HaltEffect()
		if(prob(30))
			switch(rand(2))
				if(0)
					display_msg = "grows dull!"
				if(1)
					display_msg = "fades in intensity!"
				if(2)
					display_msg = "suddenly becomes very quiet!"

	icon_state = "ano[icon_num][activated]"
	for(var/mob/O in viewers(src, null))
		O.show_message(text("[] [display_msg]", src), 1)

/obj/machinery/artifact/proc/Artifact_Contact(var/mob/user as mob)
	// Trigger Code
	if (istype (user,/mob/living/carbon/) && my_effect.trigger == "touch" && !src.activated) src.Artifact_Activate()
	else if (my_effect.trigger != "touch" && !src.activated) user << "Nothing happens."

	if (my_effect.effectmode == "contact" && src.activated && src.charged)
		my_effect.DoEffect(user)
		src.charged = 0
		src.chargetime = src.recharge

// this was used in QM for a time but it fell into disuse and wasn't removed, the purpose being to check if an artifact
// was benevolent or malicious, to determine whether QMs would be paid or punished for shipping it

/obj/machinery/artifact/Move()
	..()
	my_effect.update_move(src, src.loc)


code:
//override procs in children as necessary
/datum/artifact_effect
	var/effecttype = "unknown"		//purely used for admin checks ingame, not needed any more
	var/effect = EFFECT_TOUCH
	var/effectrange = 4
	var/trigger = TRIGGER_TOUCH
	var/atom/movable/holder
	var/activated = 0
	var/chargelevel = 0
	var/chargelevelmax = 10
	var/artifact_id = ""
	var/effect_type = 0

//0 = Unknown / none detectable
//1 = Concentrated energy
//2 = Intermittent psionic wavefront
//3 = Electromagnetic energy
//4 = Particle field
//5 = Organically reactive exotic particles
//6 = Interdimensional/bluespace? phasing
//7 = Atomic synthesis

/datum/artifact_effect/New(var/atom/location)
	..()
	holder = location
	effect = rand(0,MAX_EFFECT)
	trigger = rand(0,MAX_TRIGGER)

	//this will be replaced by the excavation code later, but it's here just in case
	artifact_id = "[pick("kappa","sigma","antaeres","beta","omicron","iota","epsilon","omega","gamma","delta","tau","alpha")]-[rand(100,999)]"

	//random charge time and distance
	switch(pick(100;1, 50;2, 25;3))
		if(1)
			//short range, short charge time
			chargelevelmax = rand(3, 20)
			effectrange = rand(1, 3)
		if(2)
			//medium range, medium charge time
			chargelevelmax = rand(15, 40)
			effectrange = rand(5, 15)
		if(3)
			//large range, long charge time
			chargelevelmax = rand(20, 120)
			effectrange = rand(20, 200)

/datum/artifact_effect/proc/ToggleActivate(var/reveal_toggle = 1)
	//so that other stuff happens first
	spawn(0)
		if(activated)
			activated = 0
		else
			activated = 1
		if(reveal_toggle && holder)
			if(istype(holder, /obj/machinery/artifact))
				var/obj/machinery/artifact/A = holder
				A.icon_state = "ano[A.icon_num][activated]"
			var/display_msg
			if(activated)
				display_msg = pick("momentarily glows brightly!","distorts slightly for a moment!","flickers slightly!","vibrates!","shimmers slightly for a moment!")
			else
				display_msg = pick("grows dull!","fades in intensity!","suddenly becomes very still!","suddenly becomes very quiet!")
			var/atom/toplevelholder = holder
			while(!istype(toplevelholder.loc, /turf))
				toplevelholder = toplevelholder.loc
			toplevelholder.visible_message("\icon[toplevelholder] [toplevelholder] [display_msg]")

/datum/artifact_effect/proc/DoEffectTouch(var/mob/user)
/datum/artifact_effect/proc/DoEffectAura(var/atom/holder)
/datum/artifact_effect/proc/DoEffectPulse(var/atom/holder)
/datum/artifact_effect/proc/UpdateMove()

/datum/artifact_effect/process()
	if(chargelevel < chargelevelmax)
		chargelevel++

	if(activated)
		if(effect == EFFECT_AURA)
			DoEffectAura()
		else if(effect == EFFECT_PULSE && chargelevel >= chargelevelmax)
			chargelevel = 0
			DoEffectPulse()

//returns 0..1, with 1 being no protection and 0 being fully protected
proc/GetAnomalySusceptibility(var/mob/living/carbon/human/H)
	if(!H || !istype(H))
		return 1

	var/protected = 0

	//anomaly suits give best protection, but excavation suits are almost as good
	if(istype(H.wear_suit,/obj/item/clothing/suit/bio_suit/anomaly))
		protected += 0.6
	else if(istype(H.wear_suit,/obj/item/clothing/suit/space/anomaly))
		protected += 0.5

	if(istype(H.head,/obj/item/clothing/head/bio_hood/anomaly))
		protected += 0.3
	else if(istype(H.head,/obj/item/clothing/head/helmet/space/anomaly))
		protected += 0.2

	//latex gloves and science goggles also give a bit of bonus protection
	if(istype(H.gloves,/obj/item/clothing/gloves/color/latex))
		protected += 0.1

	if(istype(H.glasses,/obj/item/clothing/glasses/science))
		protected += 0.1

	return 1 - protected


code:
//

/datum/artifact_effect
	var/artifact_id = ""       // Display ID of the spawning artifact
	var/trigger = "touch"      // What activates it?
	var/triggerX = "none"      // Used for more varied triggers
	var/effecttype = "healing" // What does it do?
	var/effectmode = "aura"    // How does it carry out the effect?
	var/aurarange = 4          // How far the artifact will extend an aura effect.
	var/list/created_field
	var/archived_loc

/datum/artifact_effect/New()
	//
	created_field = new()

/datum/artifact_effect/proc/GetOriginString(var/origin)

/datum/artifact_effect/proc/GetEffectString(var/effect)

/datum/artifact_effect/proc/GetTriggerString(var/trigger)

/datum/artifact_effect/proc/GetRangeString(var/range)
	switch(effectmode)
		if("aura") return "Constant Short-Range Energy Field"
		if("pulse")
			if(aurarange > 7) return "Long Range Energy Pulses"
			else return "Medium Range Energy Pulses"
		if("worldpulse") return "Extreme Range Energy Pulses"
		if("contact") return "Requires contact with subject"
		else return "Unknown Range"

/datum/artifact_effect/proc/HaltEffect()
	for(var/obj/effect/energy_field/F in created_field)
		created_field.Remove(F)
		del F

/datum/artifact_effect/proc/UpdateEffect(var/atom/originator)
	/*for(var/obj/effect/energy_field/F in created_field)
		created_field.Remove(F)
		del F*/
	if(originator.loc != archived_loc)
		archived_loc = originator.loc
		update_move(originator)

	for(var/obj/effect/energy_field/E in created_field)
		if(E.strength < 5)
			E.Strengthen(0.2)

/datum/artifact_effect/proc/DoEffect(var/atom/originator)
	archived_loc = originator.loc
	if (src.effectmode == "contact")
		var/mob/living/user = originator
		if(!user)
			return
		switch(src.effecttype)
			if("healing")
				//caeltodo
				if (istype(user, /mob/living/carbon/human/))
					user << "You feel a soothing energy invigorate you."

					var/mob/living/carbon/human/H = user
					for(var/datum/organ/external/affecting in H.organs)
						if(!affecting)    continue
						if(!istype(affecting, /datum/organ/external))    continue
						affecting.heal_damage(25, 25)    //fixes getting hit after ingestion, killing you when game updates organ health
						//user:heal_organ_damage(25, 25)
						//
						user.adjustOxyLoss(-25)
						user.adjustToxLoss(-25)
						user.adjustBruteLoss(-25)
						user.adjustFireLoss(-25)
						user.adjustBrainLoss(-25)
						user.radiation -= min(user.radiation, 25)
						user.nutrition += 50
						H.bodytemperature = initial(H.bodytemperature)
						//
						H.vessel.add_reagent("blood",50)
						spawn(1)
							H.fixblood()
						H.regenerate_icons()
					return 1
					//
				if (istype(user, /mob/living/carbon/monkey/))
					user << "You feel a soothing energy invigorate you."
					user.adjustOxyLoss(-25)
					user.adjustToxLoss(-25)
					user.adjustBruteLoss(-25)
					user.adjustFireLoss(-25)
					user.adjustBrainLoss(-25)
					return 1
				else user << "Nothing happens."
			if("injure")
				if (istype(user, /mob/living/carbon/))
					user << "A painful discharge of energy strikes you!"
					user.adjustOxyLoss(rand(5,25))
					user.adjustToxLoss(rand(5,25))
					user.adjustBruteLoss(rand(5,25))
					user.adjustFireLoss(rand(5,25))
					user.adjustBrainLoss(rand(5,25))
					user.radiation += 25
					user.nutrition -= min(50, user.nutrition)
					user.Dizzy(6)
					user.weakened += 6
					return 1
				else user << "Nothing happens."
			if("stun")
				if (istype(user, /mob/living/carbon/))
					user << "A powerful force overwhelms your consciousness."
					user.weakened += 45
					user.stuttering += 45
					if(prob(50))
						user.stunned += rand(1,10)
					return 1
				else user << "Nothing happens."
			if("roboheal")
				if (istype(user, /mob/living/silicon/robot))
					user << "Your systems report damaged components mending by themselves!"
					user.adjustBruteLoss(rand(-10,-30))
					user.adjustFireLoss(rand(-10,-30))
					return 1
				else user << "Nothing happens."
			if("robohurt")
				if (istype(user, /mob/living/silicon/robot))
					user << "Your systems report severe damage has been inflicted!"
					user.adjustBruteLoss(rand(10,50))
					user.adjustFireLoss(rand(10,50))
					return 1
				else user << "Nothing happens."
			if("forcefield")
				while(created_field.len < 16)
					var/obj/effect/energy_field/E = new (locate(user.x,user.y,user.z))
					created_field.Add(E)
					E.strength = 1
					E.density = 1
					E.anchored = 1
					E.invisibility = 0
				return 1
			if("teleport")
				var/list/randomturfs = new/list()
				for(var/turf/T in orange(user, 50))
					if(!istype(T, /turf/simulated/floor) || T.density)
						continue
					randomturfs.Add(T)
				if(randomturfs.len > 0)
					user << "You are suddenly zapped away elsewhere!"
					if (user.buckled)
						user.buckled.unbuckle()
					user.loc = pick(randomturfs)
					var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
					sparks.set_up(3, 0, get_turf(originator)) //no idea what the 0 is
					sparks.start()
				return 1
			if("sleepy")
				user << pick("You feel like taking a nap.","You feel a yawn coming on.","You feel a little tired.")
				user.drowsyness = min(user.drowsyness + rand(5,25), 50)
				user.eye_blurry = min(user.eye_blurry + rand(1,3), 50)
				return 1
	else if (src.effectmode == "aura")
		switch(src.effecttype)
			//caeltodo
			if("healing")
				for (var/mob/living/carbon/M in range(src.aurarange,originator))
					if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly))
						continue
					if(prob(10)) M << "You feel a soothing energy radiating from something nearby."
					M.adjustBruteLoss(-1)
					M.adjustFireLoss(-1)
					M.adjustToxLoss(-1)
					M.adjustOxyLoss(-1)
					M.adjustBrainLoss(-1)
					M.updatehealth()
				return 1
			if("injure")
				for (var/mob/living/carbon/M in range(src.aurarange,originator))
					if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly))
						continue
					if(prob(10)) M << "You feel a painful force radiating from something nearby."
					M.adjustBruteLoss(1)
					M.adjustFireLoss(1)
					M.adjustToxLoss(1)
					M.adjustOxyLoss(1)
					M.adjustBrainLoss(1)
					M.updatehealth()
				return 1
			if("stun")
				for (var/mob/living/carbon/M in range(src.aurarange,originator))
					if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly))
						continue
					if(prob(10)) M << "Energy radiating from the [originator] is making you feel numb."
					if(prob(20))
						M << "Your body goes numb for a moment."
						M.stunned += 2
						M.weakened += 2
						M.stuttering += 2
				return 1
			if("roboheal")
				for (var/mob/living/silicon/robot/M in range(src.aurarange,originator))
					if(prob(10)) M << "SYSTEM ALERT: Beneficial energy field detected!"
					M.adjustBruteLoss(-1)
					M.adjustFireLoss(-1)
					M.updatehealth()
				return 1
			if("robohurt")
				for (var/mob/living/silicon/robot/M in range(src.aurarange,originator))
					if(prob(10)) M << "SYSTEM ALERT: Harmful energy field detected!"
					M.adjustBruteLoss(1)
					M.adjustFireLoss(1)
					M.updatehealth()
				return 1
			if("cellcharge")
				for (var/obj/machinery/power/apc/C in range(src.aurarange,originator))
					for (var/obj/item/weapon/cell/B in C.contents)
						B.charge += 10
				for (var/obj/machinery/power/smes/S in range (src.aurarange,originator)) S.charge += 20
				for (var/mob/living/silicon/robot/M in range(src.aurarange,originator))
					for (var/obj/item/weapon/cell/D in M.contents)
						D.charge += 10
						if(prob(10)) M << "SYSTEM ALERT: Energy boosting field detected!"
				return 1
			if("celldrain")
				for (var/obj/machinery/power/apc/C in range(src.aurarange,originator))
					for (var/obj/item/weapon/cell/B in C.contents)
						B.charge = max(B.charge-10,0)
				for (var/obj/machinery/power/smes/S in range (src.aurarange,originator))
					S.charge = max(S.charge-20,0)
				for (var/mob/living/silicon/robot/M in range(src.aurarange,originator))
					for (var/obj/item/weapon/cell/D in M.contents)
						D.charge = max(D.charge-10,0)
						if(prob(10)) M << "SYSTEM ALERT: Energy draining field detected!"
				return 1
			if("planthelper")
				for (var/obj/machinery/hydroponics/H in range(src.aurarange,originator))
					//makes weeds and shrooms and stuff more potent too
					if(H.planted)
						H.waterlevel += 2
						H.nutrilevel += 2
						if(H.toxic > 0)
							H.toxic -= 1
						H.health += 1
						if(H.pestlevel > 0)
							H.pestlevel -= 1
						if(H.weedlevel > 0)
							H.weedlevel -= 1
						H.lastcycle += 5
				return 1
			if("sleepy")
				for (var/mob/living/carbon/M in range(src.aurarange,originator))
					if(prob(10))
						M << pick("You feel like taking a nap.","You feel a yawn coming on.","You feel a little tired.")
					M.drowsyness = min(M.drowsyness + 1, 25)
					M.eye_blurry = min(M.eye_blurry + 1, 25)
				return 1
	else if (src.effectmode == "pulse")
		for(var/mob/O in viewers(originator, null))
			O.show_message(text("[] emits a pulse of energy!", originator), 1)
		switch(src.effecttype)
			//caeltodo
			if("healing")
				for (var/mob/living/carbon/M in range(src.aurarange,originator))
					if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly))
						continue
					M << "A wave of energy invigorates you."
					M.adjustBruteLoss(-5)
					M.adjustFireLoss(-5)
					M.adjustToxLoss(-5)
					M.adjustOxyLoss(-5)
					M.adjustBrainLoss(-5)
					M.updatehealth()
				return 1
			if("injure")
				for (var/mob/living/carbon/M in range(src.aurarange,originator))
					if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly))
						continue
					M << "A wave of energy causes you great pain!"
					M.adjustBruteLoss(5)
					M.adjustFireLoss(5)
					M.adjustToxLoss(5)
					M.adjustOxyLoss(5)
					M.adjustBrainLoss(5)
					M.Dizzy(6)
					M.weakened += 3
					M.updatehealth()
				return 1
			if("stun")
				for (var/mob/living/carbon/M in range(src.aurarange,originator))
					if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly))
						continue
					M << "A wave of energy overwhelms your senses!"
					M.paralysis += 3
					M.weakened += 4
					M.stuttering += 4
				return 1
			if("roboheal")
				for (var/mob/living/silicon/robot/M in range(src.aurarange,originator))
					M << "SYSTEM ALERT: Structural damage has been repaired by energy pulse!"
					M.adjustBruteLoss(-10)
					M.adjustFireLoss(-10)
					M.updatehealth()
				return 1
			if("robohurt")
				for (var/mob/living/silicon/robot/M in range(src.aurarange,originator))
					M << "SYSTEM ALERT: Structural damage inflicted by energy pulse!"
					M.adjustBruteLoss(10)
					M.adjustFireLoss(10)
					M.updatehealth()
				return 1
			if("cellcharge")
				for (var/obj/machinery/power/apc/C in range(src.aurarange,originator))
					for (var/obj/item/weapon/cell/B in C.contents)
						B.charge += 250
				for (var/obj/machinery/power/smes/S in range (src.aurarange,originator)) S.charge += 400
				for (var/mob/living/silicon/robot/M in range(src.aurarange,originator))
					for (var/obj/item/weapon/cell/D in M.contents)
						D.charge += 250
						M << "SYSTEM ALERT: Large energy boost detected!"
				return 1
			if("celldrain")
				for (var/obj/machinery/power/apc/C in range(src.aurarange,originator))
					for (var/obj/item/weapon/cell/B in C.contents)
						B.charge = max(B.charge-500,0)
				for (var/obj/machinery/power/smes/S in range (src.aurarange,originator))
					S.charge = max(S.charge-400,0)
				for (var/mob/living/silicon/robot/M in range(src.aurarange,originator))
					for (var/obj/item/weapon/cell/D in M.contents)
						D.charge = max(D.charge-500,0)
						M << "SYSTEM ALERT: Severe energy drain detected!"
				return 1
			if("planthelper")
				//makes weeds and shrooms and stuff more potent too
				for (var/obj/machinery/hydroponics/H in range(src.aurarange,originator))
					if(H.planted)
						H.dead = 0
						H.waterlevel = 200
						H.nutrilevel = 200
						H.toxic = 0
						H.health = 100
						H.pestlevel = 0
						H.weedlevel = 0
						H.lastcycle = H.cycledelay
				return 1
			if("teleport")
				for (var/mob/living/M in range(src.aurarange,originator))
					if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly))
						continue
					var/list/randomturfs = new/list()
					for(var/turf/T in orange(M, 30))
						if(!istype(T, /turf/simulated/floor) || T.density)
							continue
						randomturfs.Add(T)
					if(randomturfs.len > 0)
						M << "You are displaced by a strange force!"
						if(M.buckled)
							M.buckled.unbuckle()
						M.loc = pick(randomturfs)
						var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
						sparks.set_up(3, 0, get_turf(originator)) //no idea what the 0 is
						sparks.start()
				return 1
			if("dnaswitch")
				for(var/mob/living/H in range(src.aurarange,originator))
					if(ishuman(H) && istype(H:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(H:head,/obj/item/clothing/head/bio_hood/anomaly))
						continue

					if(prob(30))
						H << pick("You feel a little different.","You feel strange.","You feel different.")
					//todo
					if (H.gender == FEMALE)
						H.setGender(MALE)
					else
						H.setGender(FEMALE)
					/*H.dna.ready_dna(H)
					H.update_body()
					H.update_face()*/
				return 1
			if("emp")
				empulse(get_turf(originator), aurarange/2, aurarange)
				return 1
			if("sleepy")
				for (var/mob/living/carbon/M in range(src.aurarange,originator))
					if(prob(30))
						M << pick("You feel like taking a nap.","You feel a yawn coming on.","You feel a little tired.")
					if(prob(50))
						M.drowsyness = min(M.drowsyness + rand(1,5), 25)
					if(prob(50))
						M.eye_blurry = min(M.eye_blurry + rand(1,5), 25)
				return 1
	else if (src.effectmode == "worldpulse")
		for(var/mob/O in viewers(originator, null))
			O.show_message(text("[] emits a powerful burst of energy!", originator), 1)
		switch(src.effecttype)
			if("healing")
				for (var/mob/living/carbon/M in range(200, originator))
					if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly))
						continue
					M << "Waves of soothing energy wash over you."
					M.adjustBruteLoss(-3)
					M.adjustFireLoss(-3)
					M.adjustToxLoss(-3)
					M.adjustOxyLoss(-3)
					M.adjustBrainLoss(-3)
					M.updatehealth()
				return 1
			if("injure")
				for (var/mob/living/carbon/human/M in range(200, originator))
					M << "A wave of painful energy strikes you!"
					M.adjustBruteLoss(3)
					M.adjustFireLoss(3)
					M.adjustToxLoss(3)
					M.adjustOxyLoss(3)
					M.adjustBrainLoss(3)
					M.updatehealth()
				return 1
			if("stun")
				for (var/mob/living/carbon/M in range(200, originator))
					if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly))
						continue
					M << "A powerful force causes you to black out momentarily."
					M.paralysis += 5
					M.weakened += 8
					M.stuttering += 8
				return 1
			if("roboheal")
				for (var/mob/living/silicon/robot/M in range(200, originator))
					M << "SYSTEM ALERT: Structural damage has been repaired by energy pulse!"
					M.adjustBruteLoss(-5)
					M.adjustFireLoss(-5)
					M.updatehealth()
				return 1
			if("robohurt")
				for (var/mob/living/silicon/robot/M in range(200, originator))
					M << "SYSTEM ALERT: Structural damage inflicted by energy pulse!"
					M.adjustBruteLoss(5)
					M.adjustFireLoss(5)
					M.updatehealth()
				return 1
			if("cellcharge")
				for (var/obj/machinery/power/apc/C in range(200, originator))
					for (var/obj/item/weapon/cell/B in C.contents)
						B.charge += 100
				for (var/obj/machinery/power/smes/S in range (src.aurarange,src)) S.charge += 250
				for (var/mob/living/silicon/robot/M in mob_list)
					for (var/obj/item/weapon/cell/D in M.contents)
						D.charge += 100
						M << "SYSTEM ALERT: Energy boost detected!"
				return 1
			if("celldrain")
				for (var/obj/machinery/power/apc/C in range(200, originator))
					for (var/obj/item/weapon/cell/B in C.contents)
						B.charge = max(B.charge-250,0)
				for (var/obj/machinery/power/smes/S in range (src.aurarange,src))
					S.charge = max(S.charge-250,0)
				for (var/mob/living/silicon/robot/M mob_list)
					for (var/obj/item/weapon/cell/D in M.contents)
						D.charge = max(D.charge-250,0)
						M << "SYSTEM ALERT: Energy drain detected!"
				return 1
			if("teleport")
				for (var/mob/living/M in range(200, originator))
					if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly))
						continue
					var/list/randomturfs = new/list()
					for(var/turf/T in orange(M, 15))
						if(!istype(T, /turf/simulated/floor) || T.density)
							continue
						randomturfs.Add(T)
					if(randomturfs.len > 0)
						M << "You are displaced by a strange force!"
						if(M.buckled)
							M.buckled.unbuckle()
						M.loc = pick(randomturfs)
						var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
						sparks.set_up(3, 0, get_turf(originator)) //no idea what the 0 is
						sparks.start()
				return 1
			if("dnaswitch")
				for(var/mob/living/H in range(200, originator))
					if(ishuman(H) && istype(H:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(H:head,/obj/item/clothing/head/bio_hood/anomaly))
						continue

					if(prob(30))
						H << pick("You feel a little different.","You feel strange.","You feel different.")
					//todo
					if (H.gender == FEMALE)
						H.setGender(MALE)
					else
						H.setGender(FEMALE)
					/*H.dna.ready_dna(H)
					H.update_body()
					H.update_face()*/
				return 1
			if("sleepy")
				for(var/mob/living/H in range(200, originator))
					H.drowsyness = min(H.drowsyness + rand(5,15), 50)
					H.eye_blurry = min(H.eye_blurry + rand(5,15), 50)
				return 1

//initially for the force field artifact
/datum/artifact_effect/proc/update_move(var/atom/originator)
	switch(effecttype)
		if("forcefield")
			while(created_field.len < 16)
				//for now, just instantly respawn the fields when they get destroyed
				var/obj/effect/energy_field/E = new (locate(originator.x,originator.y,originator))
				created_field.Add(E)
				E.strength = 1
				E.density = 1
				E.anchored = 1
				E.invisibility = 0

			var/obj/effect/energy_field/E = created_field[1]
			E.loc = locate(originator.x + 2,originator.y + 2,originator.z)
			E = created_field[2]
			E.loc = locate(originator.x + 2,originator.y + 1,originator.z)
			E = created_field[3]
			E.loc = locate(originator.x + 2,originator.y,originator.z)
			E = created_field[4]
			E.loc = locate(originator.x + 2,originator.y - 1,originator.z)
			E = created_field[5]
			E.loc = locate(originator.x + 2,originator.y - 2,originator.z)
			E = created_field[6]
			E.loc = locate(originator.x + 1,originator.y + 2,originator.z)
			E = created_field[7]
			E.loc = locate(originator.x + 1,originator.y - 2,originator.z)
			E = created_field[8]
			E.loc = locate(originator.x,originator.y + 2,originator.z)
			E = created_field[9]
			E.loc = locate(originator.x,originator.y - 2,originator.z)
			E = created_field[10]
			E.loc = locate(originator.x - 1,originator.y + 2,originator.z)
			E = created_field[11]
			E.loc = locate(originator.x - 1,originator.y - 2,originator.z)
			E = created_field[12]
			E.loc = locate(originator.x - 2,originator.y + 2,originator.z)
			E = created_field[13]
			E.loc = locate(originator.x - 2,originator.y + 1,originator.z)
			E = created_field[14]
			E.loc = locate(originator.x - 2,originator.y,originator.z)
			E = created_field[15]
			E.loc = locate(originator.x - 2,originator.y - 1,originator.z)
			E = created_field[16]
			E.loc = locate(originator.x - 2,originator.y - 2,originator.z)


code:
//inverse of /datum/artifact_effect/heat, the two effects split up for neatness' sake
/datum/artifact_effect/cold
	effecttype = "cold"
	var/target_temp

/datum/artifact_effect/cold/New()
	..()
	target_temp = rand(0, 250)
	effect = pick(EFFECT_TOUCH, EFFECT_AURA)
	effect_type = pick(5,6,7)

/datum/artifact_effect/cold/DoEffectTouch(var/mob/user)
	if(holder)
		var/datum/gas_mixture/env = holder.loc.return_air()
		if(env)
			env.temperature = max(env.temperature - rand(5,50), 0)

/datum/artifact_effect/cold/DoEffectAura()
	if(holder)
		var/datum/gas_mixture/env = holder.loc.return_air()
		if(env && env.temperature > target_temp)
			env.temperature -= pick(0, 0, 1)


code:
/datum/artifact_effect/badfeeling
	effecttype = "badfeeling"
	effect_type = 2
	var/list/messages = list("You feel worried.",\
		"Something doesn't feel right.",\
		"You get a strange feeling in your gut.",\
		"Your instincts are trying to warn you about something.",\
		"Someone just walked over your grave.",\
		"There's a strange feeling in the air.",\
		"There's a strange smell in the air.",\
		"The tips of your fingers feel tingly.",\
		"You feel witchy.",\
		"You have a terrible sense of foreboding.",\
		"You've got a bad feeling about this.",\
		"Your scalp prickles.",\
		"The light seems to flicker.",\
		"The shadows seem to lengthen.",\
		"The walls are getting closer.",\
		"Something is wrong")

	var/list/drastic_messages = list("You've got to get out of here!",\
		"Someone's trying to kill you!",\
		"There's something out there!",\
		"What's happening to you?",\
		"OH GOD!",\
		"HELP ME!")

/datum/artifact_effect/badfeeling/DoEffectTouch(var/mob/user)
	if(user)
		if (istype(user, /mob/living/carbon/human))
			var/mob/living/carbon/human/H = user
			if(prob(50))
				if(prob(75))
					H << "[pick(drastic_messages)]"
				else
					H << "[pick(messages)]"

			if(prob(50))
				H.dizziness += rand(3,5)

/datum/artifact_effect/badfeeling/DoEffectAura()
	if(holder)
		for (var/mob/living/carbon/human/H in range(src.effectrange,holder))
			if(prob(5))
				if(prob(75))
					H << "[pick(messages)]"
				else
					H << "[pick(drastic_messages)]"

			if(prob(10))
				H.dizziness += rand(3,5)
		return 1

/datum/artifact_effect/badfeeling/DoEffectPulse()
	if(holder)
		for (var/mob/living/carbon/human/H in range(src.effectrange,holder))
			if(prob(50))
				if(prob(95))
					H << "[pick(drastic_messages)]"
				else
					H << "[pick(messages)]"

			if(prob(50))
				H.dizziness += rand(3,5)
			else if(prob(25))
				H.dizziness += rand(5,15)
		return 1


code:
//todo
/datum/artifact_effect/cellcharge
	effecttype = "cellcharge"
	effect_type = 3
	var/next_message

/datum/artifact_effect/cellcharge/DoEffectTouch(var/mob/user)
	if(user)
		if(istype(user, /mob/living/silicon/robot))
			var/mob/living/silicon/robot/R = user
			for (var/obj/item/weapon/stock_parts/cell/D in R.contents)
				D.charge += rand() * 100 + 50
				R << "SYSTEM ALERT: Large energy boost detected!"
			return 1

/datum/artifact_effect/cellcharge/DoEffectAura()
	if(holder)
		for (var/obj/machinery/power/apc/C in range(200, holder))
			C.cell.charge += 25
		for (var/mob/living/silicon/robot/M in mob_list)
			for (var/obj/item/weapon/stock_parts/cell/D in M.contents)
				D.charge += 25
				if(world.time >= next_message)
					M << "SYSTEM ALERT: Energy boost detected!"
		if(world.time >= next_message)
			next_message = world.time + 100
		return 1

/datum/artifact_effect/cellcharge/DoEffectPulse()
	if(holder)
		for (var/obj/machinery/power/apc/C in range(200, holder))
			C.cell.charge += rand() * 100
		for (var/mob/living/silicon/robot/M in mob_list)
			for (var/obj/item/weapon/stock_parts/cell/D in M.contents)
				D.charge += rand() * 100
				M << "SYSTEM ALERT: Energy boost detected!"
		return 1


code:
//todo
/datum/artifact_effect/celldrain
	effecttype = "celldrain"
	effect_type = 3

/datum/artifact_effect/celldrain/DoEffectTouch(var/mob/user)
	if(user)
		if(istype(user, /mob/living/silicon/robot))
			var/mob/living/silicon/robot/R = user
			for (var/obj/item/weapon/stock_parts/cell/D in R.contents)
				D.charge = max(D.charge - rand() * 100, 0)
				R << "SYSTEM ALERT: Energy drain detected!"
			return 1

		return 1

/datum/artifact_effect/celldrain/DoEffectAura()
	if(holder)
		for (var/obj/machinery/power/apc/C in range(200, holder))
			C.cell.charge = max(C.cell.charge - 50,0)
		for (var/mob/living/silicon/robot/M in mob_list)
			for (var/obj/item/weapon/stock_parts/cell/D in M.contents)
				D.charge = max(D.charge - 50,0)
				M << "SYSTEM ALERT: Energy drain detected!"
	return 1

/datum/artifact_effect/celldrain/DoEffectPulse()
	if(holder)
		for (var/obj/machinery/power/apc/C in range(200, holder))
			C.cell.charge = max(C.cell.charge - rand() * 150,0)
		for (var/mob/living/silicon/robot/M in mob_list)
			for (var/obj/item/weapon/stock_parts/cell/D in M.contents)
				D.charge = max(D.charge - rand() * 150,0)
				M << "SYSTEM ALERT: Energy drain detected!"
	return 1


code:
//todo
/datum/artifact_effect/dnaswitch
	effecttype = "dnaswitch"
	effect_type = 5
	var/severity

/datum/artifact_effect/dnaswitch/New()
	..()
	if(effect == EFFECT_AURA)
		severity = rand(5,30)
	else
		severity = rand(25,95)

/datum/artifact_effect/dnaswitch/DoEffectTouch(var/mob/toucher)
	var/weakness = GetAnomalySusceptibility(toucher)
	if(ishuman(toucher) && prob(weakness * 100))
		toucher << pick("You feel a little different.",\
		"You feel very strange.",\
		"Your stomach churns.",\
		"Your skin feels loose.",\
		"You feel a stabbing pain in your head.",\
		"You feel a tingling sensation in your chest.",\
		"Your entire body vibrates.")
		if(prob(75))
			scramble(1, toucher, weakness * severity)
		else
			scramble(0, toucher, weakness * severity)
	return 1

/datum/artifact_effect/dnaswitch/DoEffectAura()
	if(holder)
		for(var/mob/living/carbon/human/H in range(src.effectrange,holder))
			var/weakness = GetAnomalySusceptibility(H)
			if(prob(weakness * 100))
				if(prob(30))
					H << pick("You feel a little different.",\
					"You feel very strange.",\
					"Your stomach churns.",\
					"Your skin feels loose.",\
					"You feel a stabbing pain in your head.",\
					"You feel a tingling sensation in your chest.",\
					"Your entire body vibrates.")
				if(prob(50))
					scramble(1, H, weakness * severity)
				else
					scramble(0, H, weakness * severity)

/datum/artifact_effect/dnaswitch/DoEffectPulse()
	if(holder)
		for(var/mob/living/carbon/human/H in range(200, holder))
			var/weakness = GetAnomalySusceptibility(H)
			if(prob(weakness * 100))
				if(prob(75))
					H << pick("You feel a little different.",\
					"You feel very strange.",\
					"Your stomach churns.",\
					"Your skin feels loose.",\
					"You feel a stabbing pain in your head.",\
					"You feel a tingling sensation in your chest.",\
					"Your entire body vibrates.")
				if(prob(25))
					if(prob(75))
						scramble(1, H, weakness * severity)
					else
						scramble(0, H, weakness * severity)


code:
/datum/artifact_effect/emp
	effecttype = "emp"
	effect_type = 3

/datum/artifact_effect/emp/New()
	..()
	effect = EFFECT_PULSE

/datum/artifact_effect/emp/DoEffectPulse()
	if(holder)
		empulse(get_turf(holder), effectrange/2, effectrange)
		return 1


code:
/datum/artifact_effect/gasco2
	effecttype = "gasco2"
	var/max_pressure
	var/target_percentage

/datum/artifact_effect/heat/New()
	..()
	effect_type = pick(6,7)

/datum/artifact_effect/gasco2/New()
	..()
	effect = pick(EFFECT_TOUCH, EFFECT_AURA)
	max_pressure = rand(115,1000)

/datum/artifact_effect/gasco2/DoEffectTouch(var/mob/user)
	if(holder)
		var/datum/gas_mixture/env = holder.loc.return_air()
		if(env)
			env.carbon_dioxide += rand(2,15)
			holder.air_update_turf(0)

/datum/artifact_effect/gasco2/DoEffectAura()
	if(holder)
		var/datum/gas_mixture/env = holder.loc.return_air()
		if(env && env.total_moles() < max_pressure)
			env.carbon_dioxide += pick(0, 0, 0.1, rand())
			holder.air_update_turf(0)


code:
/datum/artifact_effect/gasnitro
	effecttype = "gasnitro"
	var/max_pressure
	var/target_percentage

/datum/artifact_effect/gasnitro/New()
	..()
	effect = pick(EFFECT_TOUCH, EFFECT_AURA)
	effect_type = pick(6,7)
	max_pressure = rand(115,1000)

/datum/artifact_effect/gasnitro/DoEffectTouch(var/mob/user)
	if(holder)
		var/datum/gas_mixture/env = holder.loc.return_air()
		if(env)
			env.nitrogen += rand(2,15)
			holder.air_update_turf(0)

/datum/artifact_effect/gasnitro/DoEffectAura()
	if(holder)
		var/datum/gas_mixture/env = holder.loc.return_air()
		if(env && env.total_moles() < max_pressure)
			env.nitrogen += pick(0, 0, 0.1, rand())
			holder.air_update_turf(0)


code:
/datum/artifact_effect/gasoxy
	effecttype = "gasoxy"
	var/max_pressure

/datum/artifact_effect/gasoxy/New()
	..()
	effect = pick(EFFECT_TOUCH, EFFECT_AURA)
	max_pressure = rand(115,1000)
	effect_type = pick(6,7)

/datum/artifact_effect/gasoxy/DoEffectTouch(var/mob/user)
	if(holder)
		var/datum/gas_mixture/env = holder.loc.return_air()
		if(env)
			env.oxygen += rand(2,15)
			holder.air_update_turf(0)

/datum/artifact_effect/gasoxy/DoEffectAura()
	if(holder)
		var/datum/gas_mixture/env = holder.loc.return_air()
		if(env && env.total_moles() < max_pressure)
			env.oxygen += pick(0, 0, 0.1, rand())
			holder.air_update_turf(0)


code:
/datum/artifact_effect/gasplasma
	effecttype = "gasplasma"
	var/max_pressure
	var/target_percentage

/datum/artifact_effect/gasplasma/New()
	..()
	effect = pick(EFFECT_TOUCH, EFFECT_AURA)
	max_pressure = rand(115,1000)
	effect_type = pick(6,7)

/datum/artifact_effect/gasplasma/DoEffectTouch(var/mob/user)
	if(holder)
		var/datum/gas_mixture/env = holder.loc.return_air()
		if(env)
			env.toxins += rand(2,15)
			holder.air_update_turf(0)

/datum/artifact_effect/gasplasma/DoEffectAura()
	if(holder)
		var/datum/gas_mixture/env = holder.loc.return_air()
		if(env && env.total_moles() < max_pressure)
			env.toxins += pick(0, 0, 0.1, rand())
			holder.air_update_turf(0)


code:
/datum/artifact_effect/gassleeping
	effecttype = "gassleeping"
	var/max_pressure
	var/target_percentage

/datum/artifact_effect/gassleeping/New()
	..()
	effect = pick(EFFECT_TOUCH, EFFECT_AURA)
	max_pressure = rand(115,1000)
	effect_type = pick(6,7)

/datum/artifact_effect/gassleeping/DoEffectTouch(var/mob/user)
	if(holder)
		var/datum/gas_mixture/env = holder.loc.return_air()
		if(env)
			var/datum/gas/sleeping_agent/trace_gas = new
			env.trace_gases += trace_gas
			trace_gas.moles = rand(2,15)
			holder.air_update_turf(0)
		//	env.update_values()

/datum/artifact_effect/gassleeping/DoEffectAura()
	if(holder)
		var/datum/gas_mixture/env = holder.loc.return_air()
		if(env && env.total_moles() < max_pressure)
			var/datum/gas/sleeping_agent/trace_gas = new
			env.trace_gases += trace_gas
			trace_gas.moles = pick(0, 0, 0.1, rand())
			holder.air_update_turf(0)
		//	env.update_values()


code:
/datum/artifact_effect/goodfeeling
	effecttype = "goodfeeling"
	effect_type = 2
	var/list/messages = list("You feel good.",\
		"Everything seems to be going alright",\
		"You've got a good feeling about this",\
		"Your instincts tell you everything is going to be getting better.",\
		"There's a good feeling in the air.",\
		"Something smells... good.",\
		"The tips of your fingers feel tingly.",\
		"You've got a good feeling about this.",\
		"You feel happy.",\
		"You fight the urge to smile.",\
		"Your scalp prickles.",\
		"All the colours seem a bit more vibrant.",\
		"Everything seems a little lighter.",\
		"The troubles of the world seem to fade away.")

	var/list/drastic_messages = list("You want to hug everyone you meet!",\
		"Everything is going so well!",\
		"You feel euphoric.",\
		"You feel giddy.",\
		"You're so happy suddenly, you almost want to dance and sing.",\
		"You feel like the world is out to help you.")

/datum/artifact_effect/goodfeeling/DoEffectTouch(var/mob/user)
	if(user)
		if (istype(user, /mob/living/carbon/human))
			var/mob/living/carbon/human/H = user
			if(prob(50))
				if(prob(75))
					H << "[pick(drastic_messages)]"
				else
					H << "[pick(messages)]"

			if(prob(50))
				H.dizziness += rand(3,5)

/datum/artifact_effect/goodfeeling/DoEffectAura()
	if(holder)
		for (var/mob/living/carbon/human/H in range(src.effectrange,holder))
			if(prob(5))
				if(prob(75))
					H << "[pick(messages)]"
				else
					H << "[pick(drastic_messages)]"

			if(prob(5))
				H.dizziness += rand(3,5)
		return 1

/datum/artifact_effect/goodfeeling/DoEffectPulse()
	if(holder)
		for (var/mob/living/carbon/human/H in range(src.effectrange,holder))
			if(prob(50))
				if(prob(95))
					H << "[pick(drastic_messages)]"
				else
					H << "[pick(messages)]"

			if(prob(50))
				H.dizziness += rand(3,5)
			else if(prob(25))
				H.dizziness += rand(5,15)
		return 1


code:
/datum/artifact_effect/heal
	effecttype = "heal"
	effect_type = 5

/datum/artifact_effect/heal/DoEffectTouch(var/mob/toucher)
	//todo: check over this properly
	if(toucher && iscarbon(toucher))
		var/weakness = GetAnomalySusceptibility(toucher)
		if(prob(weakness * 100))
			var/mob/living/carbon/C = toucher
			C << "You feel a soothing energy invigorate you."

			if(ishuman(toucher))
				var/mob/living/carbon/human/H = toucher
			//	for(var/datum/organ/external/affecting in H.organs)
			//		if(affecting && istype(affecting))
			//			affecting.heal_damage(25 * weakness, 25 * weakness)
				//H:heal_organ_damage(25, 25)
				H.vessel.add_reagent("blood",5)
				H.nutrition += 50 * weakness
				H.adjustBrainLoss(-25 * weakness)
				H.radiation -= min(H.radiation, 25 * weakness)
				H.bodytemperature = initial(H.bodytemperature)
				spawn(1)
					H.fixblood()
			//
			C.adjustOxyLoss(-25 * weakness)
			C.adjustToxLoss(-25 * weakness)
			C.adjustBruteLoss(-25 * weakness)
			C.adjustFireLoss(-25 * weakness)
			//
			C.regenerate_icons()
			return 1

/datum/artifact_effect/heal/DoEffectAura()
	//todo: check over this properly
	if(holder)
		for (var/mob/living/carbon/C in range(src.effectrange,holder))
			var/weakness = GetAnomalySusceptibility(C)
			if(prob(weakness * 100))
				if(prob(10))
					C << "You feel a soothing energy radiating from something nearby."
				C.adjustBruteLoss(-1 * weakness)
				C.adjustFireLoss(-1 * weakness)
				C.adjustToxLoss(-1 * weakness)
				C.adjustOxyLoss(-1 * weakness)
				C.adjustBrainLoss(-1 * weakness)
				C.updatehealth()

/datum/artifact_effect/heal/DoEffectPulse()
	//todo: check over this properly
	if(holder)
		for (var/mob/living/carbon/C in range(src.effectrange,holder))
			var/weakness = GetAnomalySusceptibility(C)
			if(prob(weakness * 100))
				C << "A wave of energy invigorates you."
				C.adjustBruteLoss(-5 * weakness)
				C.adjustFireLoss(-5 * weakness)
				C.adjustToxLoss(-5 * weakness)
				C.adjustOxyLoss(-5 * weakness)
				C.adjustBrainLoss(-5 * weakness)
				C.updatehealth()


code:
//inverse of /datum/artifact_effect/cold, the two effects split up for neatness' sake
/datum/artifact_effect/heat
	effecttype = "heat"
	var/target_temp

/datum/artifact_effect/heat/New()
	..()
	effect_type = pick(5,6,7)

/datum/artifact_effect/heat/New()
	..()
	target_temp = rand(300,600)
	effect = pick(EFFECT_TOUCH, EFFECT_AURA)

/datum/artifact_effect/heat/DoEffectTouch(var/mob/user)
	if(holder)
		var/datum/gas_mixture/env = holder.loc.return_air()
		if(env)
			env.temperature += rand(5,50)

/datum/artifact_effect/heat/DoEffectAura()
	if(holder)
		var/datum/gas_mixture/env = holder.loc.return_air()
		if(env && env.temperature < target_temp)
			env.temperature += pick(0, 0, 1)


code:
/datum/artifact_effect/hurt
//	effecttype = I_HURT
	effect_type = 5

/datum/artifact_effect/hurt/DoEffectTouch(var/mob/toucher)
	if(toucher)
		var/weakness = GetAnomalySusceptibility(toucher)
		if(iscarbon(toucher) && prob(weakness * 100))
			var/mob/living/carbon/C = toucher
			C << "A painful discharge of energy strikes you!"
			C.adjustOxyLoss(rand(5,25) * weakness)
			C.adjustToxLoss(rand(5,25) * weakness)
			C.adjustBruteLoss(rand(5,25) * weakness)
			C.adjustFireLoss(rand(5,25) * weakness)
			C.adjustBrainLoss(rand(5,25) * weakness)
			C.radiation += 25 * weakness
			C.nutrition -= min(50 * weakness, C.nutrition)
			C.Dizzy(6 * weakness)
			C.weakened += 6 * weakness

/datum/artifact_effect/hurt/DoEffectAura()
	if(holder)
		for (var/mob/living/carbon/C in range(src.effectrange,holder))
			var/weakness = GetAnomalySusceptibility(C)
			if(prob(weakness * 100))
				if(prob(10))
					C << "You feel a painful force radiating from something nearby."
				C.adjustBruteLoss(1 * weakness)
				C.adjustFireLoss(1 * weakness)
				C.adjustToxLoss(1 * weakness)
				C.adjustOxyLoss(1 * weakness)
				C.adjustBrainLoss(1 * weakness)
				C.updatehealth()

/datum/artifact_effect/hurt/DoEffectPulse()
	if(holder)
		for (var/mob/living/carbon/C in range(effectrange, holder))
			var/weakness = GetAnomalySusceptibility(C)
			if(prob(weakness * 100))
				C << "A wave of painful energy strikes you!"
				C.adjustBruteLoss(3 * weakness)
				C.adjustFireLoss(3 * weakness)
				C.adjustToxLoss(3 * weakness)
				C.adjustOxyLoss(3 * weakness)
				C.adjustBrainLoss(3 * weakness)
				C.updatehealth()


code:
/datum/artifact_effect/radiate
	effecttype = "radiate"
	var/radiation_amount

/datum/artifact_effect/radiate/New()
	..()
	radiation_amount = rand(1, 10)
	effect_type = pick(4,5)

/datum/artifact_effect/radiate/DoEffectTouch(var/mob/living/user)
	if(user)
		user.apply_effect(radiation_amount * 5,IRRADIATE,0)
		user.updatehealth()
		return 1

/datum/artifact_effect/radiate/DoEffectAura()
	if(holder)
		for (var/mob/living/M in range(src.effectrange,holder))
			M.apply_effect(radiation_amount,IRRADIATE,0)
			M.updatehealth()
		return 1

/datum/artifact_effect/radiate/DoEffectPulse()
	if(holder)
		for (var/mob/living/M in range(src.effectrange,holder))
			M.apply_effect(radiation_amount * 25,IRRADIATE,0)
			M.updatehealth()
		return 1


code:
/datum/artifact_effect/roboheal
	effecttype = "roboheal"

/datum/artifact_effect/roboheal/New()
	..()
	effect_type = pick(3,4)

/datum/artifact_effect/roboheal/DoEffectTouch(var/mob/user)
	if(user)
		if (istype(user, /mob/living/silicon/robot))
			var/mob/living/silicon/robot/R = user
			R << "Your systems report damaged components mending by themselves!"
			R.adjustBruteLoss(rand(-10,-30))
			R.adjustFireLoss(rand(-10,-30))
			return 1

/datum/artifact_effect/roboheal/DoEffectAura()
	if(holder)
		for (var/mob/living/silicon/robot/M in range(src.effectrange,holder))
			if(prob(10))
				M << "SYSTEM ALERT: Beneficial energy field detected!"
			M.adjustBruteLoss(-1)
			M.adjustFireLoss(-1)
			M.updatehealth()
		return 1

/datum/artifact_effect/roboheal/DoEffectPulse()
	if(holder)
		for (var/mob/living/silicon/robot/M in range(src.effectrange,holder))
			M << "SYSTEM ALERT: Structural damage has been repaired by energy pulse!"
			M.adjustBruteLoss(-10)
			M.adjustFireLoss(-10)
			M.updatehealth()
		return 1


code:
/datum/artifact_effect/robohurt
	effecttype = "robohurt"

/datum/artifact_effect/robohurt/New()
	..()
	effect_type = pick(3,4)

/datum/artifact_effect/robohurt/DoEffectTouch(var/mob/user)
	if(user)
		if (istype(user, /mob/living/silicon/robot))
			var/mob/living/silicon/robot/R = user
			R << "Your systems report severe damage has been inflicted!"
			R.adjustBruteLoss(rand(10,50))
			R.adjustFireLoss(rand(10,50))
			return 1

/datum/artifact_effect/robohurt/DoEffectAura()
	if(holder)
		for (var/mob/living/silicon/robot/M in range(src.effectrange,holder))
			if(prob(10)) M << "SYSTEM ALERT: Harmful energy field detected!"
			M.adjustBruteLoss(1)
			M.adjustFireLoss(1)
			M.updatehealth()
		return 1

/datum/artifact_effect/robohurt/DoEffectPulse()
	if(holder)
		for (var/mob/living/silicon/robot/M in range(src.effectrange,holder))
			M << "SYSTEM ALERT: Structural damage inflicted by energy pulse!"
			M.adjustBruteLoss(10)
			M.adjustFireLoss(10)
			M.updatehealth()
		return 1


code:
//todo
/datum/artifact_effect/sleepy
	effecttype = "sleepy"

/datum/artifact_effect/sleepy/New()
	..()
	effect_type = pick(5,2)

/datum/artifact_effect/sleepy/DoEffectTouch(var/mob/toucher)
	if(toucher)
		var/weakness = GetAnomalySusceptibility(toucher)
		if(ishuman(toucher) && prob(weakness * 100))
			var/mob/living/carbon/human/H = toucher
			H << pick("You feel like taking a nap.","You feel a yawn coming on.","You feel a little tired.")
			H.drowsyness = min(H.drowsyness + rand(5,25) * weakness, 50 * weakness)
			H.eye_blurry = min(H.eye_blurry + rand(1,3) * weakness, 50 * weakness)
			return 1
		else if(isrobot(toucher))
			toucher << "SYSTEM ALERT: CPU cycles slowing down."
			return 1

/datum/artifact_effect/sleepy/DoEffectAura()
	if(holder)
		for (var/mob/living/carbon/human/H in range(src.effectrange,holder))
			var/weakness = GetAnomalySusceptibility(H)
			if(prob(weakness * 100))
				if(prob(10))
					H << pick("You feel like taking a nap.","You feel a yawn coming on.","You feel a little tired.")
				H.drowsyness = min(H.drowsyness + 1 * weakness, 25 * weakness)
				H.eye_blurry = min(H.eye_blurry + 1 * weakness, 25 * weakness)
		for (var/mob/living/silicon/robot/R in range(src.effectrange,holder))
			R << "SYSTEM ALERT: CPU cycles slowing down."
		return 1

/datum/artifact_effect/sleepy/DoEffectPulse()
	if(holder)
		for(var/mob/living/carbon/human/H in range(src.effectrange, holder))
			var/weakness = GetAnomalySusceptibility(H)
			if(prob(weakness * 100))
				H << pick("You feel like taking a nap.","You feel a yawn coming on.","You feel a little tired.")
				H.drowsyness = min(H.drowsyness + rand(5,15) * weakness, 50 * weakness)
				H.eye_blurry = min(H.eye_blurry + rand(5,15) * weakness, 50 * weakness)
		for (var/mob/living/silicon/robot/R in range(src.effectrange,holder))
			R << "SYSTEM ALERT: CPU cycles slowing down."
		return 1


code:
/datum/artifact_effect/stun
	effecttype = "stun"

/datum/artifact_effect/stun/New()
	..()
	effect_type = pick(2,5)

/datum/artifact_effect/stun/DoEffectTouch(var/mob/toucher)
	if(toucher && iscarbon(toucher))
		var/mob/living/carbon/C = toucher
		var/weakness = GetAnomalySusceptibility(C)
		if(prob(weakness * 100))
			C << "A powerful force overwhelms your consciousness."
			C.weakened += 45 * weakness
			C.stuttering += 45 * weakness
			C.stunned += rand(1,10) * weakness

/datum/artifact_effect/stun/DoEffectAura()
	if(holder)
		for (var/mob/living/carbon/C in range(src.effectrange,holder))
			var/weakness = GetAnomalySusceptibility(C)
			if(prob(10 * weakness))
				C << "Your body goes numb for a moment."
				C.weakened += 2
				C.stuttering += 2
				if(prob(10))
					C.stunned += 1
			else if(prob(10))
				C << "You feel numb."

/datum/artifact_effect/stun/DoEffectPulse()
	if(holder)
		for (var/mob/living/carbon/C in range(src.effectrange,holder))
			var/weakness = GetAnomalySusceptibility(C)
			if(prob(100 * weakness))
				C << "A wave of energy overwhelms your senses!"
				C.weakened += 4 * weakness
				C.stuttering += 4 * weakness
				if(prob(10))
					C.stunned += 1 * weakness


code:
/datum/artifact_effect/teleport
	effecttype = "teleport"
	effect_type = 6

/datum/artifact_effect/teleport/DoEffectTouch(var/mob/user)
	var/weakness = GetAnomalySusceptibility(user)
	if(prob(100 * weakness))
		var/list/randomturfs = new/list()
		for(var/turf/simulated/floor/T in orange(user, 50))
			randomturfs.Add(T)
		if(randomturfs.len > 0)
			user << "You are suddenly zapped away elsewhere!"
			if (user.buckled)
				user.buckled.unbuckle_mob()

			var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
			sparks.set_up(3, 0, get_turf(user))
			sparks.start()
			user.loc = pick(randomturfs)
			sparks = new /datum/effect/effect/system/spark_spread()
			sparks.set_up(3, 0, get_turf(user))
			sparks.start()

/datum/artifact_effect/teleport/DoEffectAura()
	if(holder)
		for (var/mob/living/M in range(src.effectrange,holder))
			var/weakness = GetAnomalySusceptibility(M)
			if(prob(100 * weakness))
				var/list/randomturfs = new/list()
				for(var/turf/simulated/floor/T in orange(M, 30))
					randomturfs.Add(T)
				if(randomturfs.len > 0)
					M << "You are displaced by a strange force!"
					if(M.buckled)
						M.buckled.unbuckle_mob()

					var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
					sparks.set_up(3, 0, get_turf(M))
					sparks.start()
					M.loc = pick(randomturfs)
					sparks = new /datum/effect/effect/system/spark_spread()
					sparks.set_up(3, 0, get_turf(M))
					sparks.start()

/datum/artifact_effect/teleport/DoEffectPulse()
	if(holder)
		for (var/mob/living/M in range(src.effectrange, holder))
			var/weakness = GetAnomalySusceptibility(M)
			if(prob(100 * weakness))
				var/list/randomturfs = new/list()
				for(var/turf/simulated/floor/T in orange(M, 15))
					randomturfs.Add(T)
				if(randomturfs.len > 0)
					M << "You are displaced by a strange force!"

					var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
					sparks.set_up(3, 0, get_turf(M))
					sparks.start()
					if(M.buckled)
						M.buckled.unbuckle_mob()
					M.loc = pick(randomturfs)
					sparks = new /datum/effect/effect/system/spark_spread()
					sparks.set_up(3, 0, get_turf(M))
					sparks.start()


code:
//chemistry stuff here so that it can be easily viewed/modified

/datum/reagent/tungsten
	name = "Tungsten"
	id = "tungsten"
	description = "A chemical element, and a strong oxidising agent."
	reagent_state = SOLID
	color = "#DCDCDC"  // rgb: 220, 220, 220, silver

/datum/reagent/lithiumsodiumtungstate
	name = "Lithium Sodium Tungstate"
	id = "lithiumsodiumtungstate"
	description = "A reducing agent for geological compounds."
	reagent_state = LIQUID
	color = "#C0C0C0"  // rgb: 192, 192, 192, darker silver

/datum/reagent/ground_rock
	name = "Ground Rock"
	id = "ground_rock"
	description = "A fine dust made of ground up rock."
	reagent_state = SOLID
	color = "#A0522D"   //rgb: 160, 82, 45, brown

/datum/reagent/density_separated_sample
	name = "Density separated sample"
	id = "density_separated_sample"
	description = "A watery paste used in chemical analysis, there are some chunks floating in it."
	reagent_state = LIQUID
	color = "#DEB887"   //rgb: 222, 184, 135, light brown

/datum/reagent/analysis_sample
	name = "Analysis liquid"
	id = "analysis_sample"
	description = "A watery paste used in chemical analysis."
	reagent_state = LIQUID
	color = "#F5FFFA"   //rgb: 245, 255, 250, almost white

/datum/chemical_reaction/lithiumsodiumtungstate	//LiNa2WO4, not the easiest chem to mix
	name = "Lithium Sodium Tungstate"
	id = "lithiumsodiumtungstate"
	result = "lithiumsodiumtungstate"
	required_reagents = list("lithium" = 1, "sodium" = 2, "tungsten" = 1, "oxygen" = 4)
	result_amount = 8

/datum/chemical_reaction/density_separated_liquid
	name = "Density separated sample"
	id = "density_separated_sample"
	result = "density_separated_sample"
	required_reagents = list("ground_rock" = 1, "lithiumsodiumtungstate" = 2)
	result_amount = 2

/datum/chemical_reaction/analysis_liquid
	name = "Analysis sample"
	id = "analysis_sample"
	result = "analysis_sample"
	required_reagents = list("density_separated_sample" = 5)
	result_amount = 4
	required_temp = 480

/obj/item/weapon/reagent_containers/glass/solution_tray
	name = "solution tray"
	desc = "A small, open-topped glass container for delicate research samples. It sports a re-useable strip for labelling with a pen."
	icon = 'icons/obj/device.dmi'
	icon_state = "solution_tray"
	m_amt = 0
	g_amt = 50
	w_class = 1.0
	amount_per_transfer_from_this = 1
	possible_transfer_amounts = list(1, 2)
	volume = 2
	flags = FPRINT | OPENCONTAINER

///obj/item/weapon/reagent_containers/glass/solution_tray/mop_act(obj/item/weapon/mop/M, mob/user)
//	return 1
obj/item/weapon/reagent_containers/glass/solution_tray/attackby(obj/item/weapon/W as obj, mob/living/user as mob)
	if(istype(W, /obj/item/weapon/pen) || istype(W, /obj/item/device/flashlight/pen))
		var/new_label = copytext(sanitize(input("What should the new label be?","Label solution tray") as text|null), 1, MAX_NAME_LEN)
		if(new_label && Adjacent(user) && !user.stat)
			name = "solution tray ([new_label])"
			user << " You write on the label of the solution tray."
	else
		..(W, user)

/obj/item/weapon/storage/box/solution_trays
	name = "solution tray box"
	icon_state = "solution_trays"

	New()
		..()
		new /obj/item/weapon/reagent_containers/glass/solution_tray( src )
		new /obj/item/weapon/reagent_containers/glass/solution_tray( src )
		new /obj/item/weapon/reagent_containers/glass/solution_tray( src )
		new /obj/item/weapon/reagent_containers/glass/solution_tray( src )
		new /obj/item/weapon/reagent_containers/glass/solution_tray( src )
		new /obj/item/weapon/reagent_containers/glass/solution_tray( src )
		new /obj/item/weapon/reagent_containers/glass/solution_tray( src )

/obj/item/weapon/reagent_containers/glass/beaker/tungsten
	name = "beaker 'tungsten'"
	New()
		..()
		reagents.add_reagent("tungsten",50)
		update_icon()

/obj/item/weapon/reagent_containers/glass/beaker/oxygen
	name = "beaker 'oxygen'"
	New()
		..()
		reagents.add_reagent("oxygen",50)
		update_icon()

/obj/item/weapon/reagent_containers/glass/beaker/sodium
	name = "beaker 'sodium'"
	New()
		..()
		reagents.add_reagent("sodium",50)
		update_icon()

/obj/item/weapon/reagent_containers/glass/beaker/lithium
	name = "beaker 'lithium'"

	New()
		..()
		reagents.add_reagent("lithium",50)
		update_icon()

/obj/item/weapon/reagent_containers/glass/beaker/water
	name = "beaker 'water'"

	New()
		..()
		reagents.add_reagent("water",50)
		update_icon()

/obj/item/weapon/reagent_containers/glass/beaker/water
	name = "beaker 'water'"

	New()
		..()
		reagents.add_reagent("water",50)
		update_icon()

/obj/item/weapon/reagent_containers/glass/beaker/fuel
	name = "beaker 'fuel'"

	New()
		..()
		reagents.add_reagent("fuel",50)
		update_icon()