code:
#define TIME_MULTIPLIER 0.7 // so I can speed up/slow down shit

/datum/stockEvent
	var/name = "event"
	var/next_phase = 0
	var/datum/stock/company = null
	var/current_title = "A company holding an pangalactic conference in the Seattle Conference Center, Seattle, Earth"
	var/current_desc = "We will continue to monitor their stocks as the situation unfolds."
	var/phase_id = 0
	var/hidden = 0
	var/finished = 0
	var/last_change = 0

/datum/stockEvent/process()
	if (finished)
		return
	if (world.time > next_phase)
		transition()

/datum/stockEvent/proc/transition()
	return

/datum/stockEvent/proc/spacetime(var/ticks)
	var/seconds = round(ticks / 10)
	var/minutes = round(seconds / 60)
	seconds -= minutes * 60
	return "[minutes] minute(s) and [seconds] second(s)"

/datum/stockEvent/product
	name = "product"
	var/product_name = ""
	var/datum/article/product_article = null
	var/effect = 0

/datum/stockEvent/product/New(var/datum/stock/S)
	company = S
	var/mins = rand(5*TIME_MULTIPLIER,20*TIME_MULTIPLIER)
	next_phase = mins * (600*TIME_MULTIPLIER) + world.time
	current_title = "Product demo"
	current_desc = S.industry.detokenize("[S.name] will unveil a new product on an upcoming %industrial% conference held at spacetime [spacetime(next_phase)]")
	S.addEvent(src)

/datum/stockEvent/product/transition()
	last_change = world.time
	switch (phase_id)
		if (0)
			next_phase = world.time + rand(300*TIME_MULTIPLIER, 600*TIME_MULTIPLIER) * (10*TIME_MULTIPLIER)
			product_name = company.industry.generateProductName(company.name)
			current_title = "Product release: [product_name]"
			current_desc = "[company.name] unveiled their newest product, [product_name], at a conference. Product release is expected to happen at spacetime [spacetime(next_phase)]."
			var/datum/article/A = company.industry.generateInCharacterProductArticle(product_name, company)
			product_article = A
			effect = A.opinion + rand(-1, 1)
			company.affectPublicOpinion(effect)
			phase_id = 1
		if (1)
			finished = 1
			hidden = 1
			company.addArticle(product_article)
			effect += product_article.opinion * 5
			company.affectPublicOpinion(effect)
			phase_id = 2
			company.generateEvent(type)

/datum/stockEvent/bankruptcy
	name = "bankruptcy"
	var/effect = 0
	var/bailout_millions = 0

/datum/stockEvent/bankruptcy/New(var/datum/stock/S)
	hidden = 1
	company = S
	var/mins = rand(9*TIME_MULTIPLIER,60*TIME_MULTIPLIER)
	bailout_millions = rand(70, 190)
	next_phase = mins * 300*TIME_MULTIPLIER + world.time
	current_title = ""
	current_desc = ""
	S.addEvent(src)

/datum/stockEvent/bankruptcy/transition()
	switch (phase_id)
		if (0)
			next_phase = world.time + rand(300*TIME_MULTIPLIER, 600*TIME_MULTIPLIER) * (10*TIME_MULTIPLIER)
			var/datum/article/A = generateBankruptcyArticle()
			if (!A.opinion)
				effect = rand(5) * (prob(50) ? -1 : 1)
			else
				effect = prob(25) ? -A.opinion * rand(8) : A.opinion * rand(4)
			company.addArticle(A)
			company.affectPublicOpinion(rand(-6, -3))
			hidden = 0
			current_title = "Bailout pending due to bankruptcy"
			current_desc = "The government prepared a press release, which will occur at spacetime [spacetime(next_phase)]."
			phase_id = 1
		if (1)
			next_phase = world.time + rand(300*TIME_MULTIPLIER, 600*TIME_MULTIPLIER) * (10*TIME_MULTIPLIER)
			finished = 1
			if (effect <= -5 && prob(10))
				current_title = "[company.name]: Complete crash"
				current_desc = "The company had gone bankrupt, was not bailed out and could not recover. No further stock trade will take place. All shares in the company are effectively worthless."
				company.bankrupt = 1
				for (var/X in company.shareholders)
					var/amt = company.shareholders[X]
					stockExchange.balanceLog(X, -amt * company.current_value)
				company.shareholders = list()
				company.current_value = 0
				company.borrow_brokers = list()
				stockExchange.generateStocks(1)

			var/bailout = (effect > 0 && prob(80)) || (effect < 0 && prob(20))
			current_title = "[company.name] [bailout ? "bailed out" : "on a painful rebound"]"
			if (bailout)
				current_desc = "The company has been bailed out by the government. Investors are highly optimistic."
				company.affectPublicOpinion(abs(effect) * 2)
			else
				current_desc = "The company was not bailed out, but managed to crawl out of bankruptcy. Stockholder trust is severely dented."
				company.affectPublicOpinion(-abs(effect) / 2)
			company.generateEvent(type)

/datum/stockEvent/bankruptcy/proc/generateBankruptcyArticle()
	var/datum/article/A = new
	var/list/bankrupt_reason = list("investor pessimism", "failure of product lines", "economic recession", "overblown inflation", "overblown deflation", "collapsed pyramid schemes", "a Ponzi scheme", "economic terrorism", "extreme hedonism", "unfavourable economic climate", "rampant government corruption", "divine conspiracy", "some total bullshit", "volatile plans")
	A.about = company
	A.headline = pick(	"[company.name] filing for bankruptcy", \
						"[company.name] unable to pay, investors run", \
						"[company.name] crashes, in foreclosure", \
						"[company.name] in dire need of credits")
	A.subtitle = "Investors panic, bailout pending"
	if (prob(15))
		A.opinion = rand(-1, 1)
	var/article = "Another one might bite the dust: [company.current_trend > 0 ? "despite their positive trend" : "in line with their failing model"], [company.name] is files for bankruptcy citing [pick(bankrupt_reason)]. The president of %country% has been asked to bail the company out, "
	if (!A.opinion)
		article += "but no answer has been given by the government to date. Our tip to stay safe is: %sell%"
	else if (A.opinion > 0)
		article += "and the government responded positively. When the share value hits its lowest, it is a safe bet to %buy%"
	else
		article += "but the outlook is not good. For investors, now would be an ideal time to %sell%"
	A.article = A.detokenize(article, company.industry.tokens)
	return A

/datum/stockEvent/arrest
	name = "arrest"
	var/female = 0
	var/tname = "Elvis Presley"
	var/position = "CEO"
	var/offenses = "murder"
	var/effect = 0

/datum/stockEvent/arrest/New(var/datum/stock/S)
	hidden = 1
	company = S
	var/mins = rand(10*TIME_MULTIPLIER, 35*TIME_MULTIPLIER)
	next_phase = mins * 600*TIME_MULTIPLIER + world.time
	current_title = ""
	current_desc = ""
	female = prob(50)
	if (prob(50))
		position = "C[prob(20) ? vowel() : consonant()]O"
	else
		position = ucfirsts(company.industry.detokenize("Lead %industrial% Engineer"))
	offenses = ""
	var/list/O = list("corruption", "murder", "grand theft", "assault", "battery", "drug possession", "burglary", "theft", "grand sabotage", "bribery",
						"disorderly conduct", "treason", "sedition", "shoplifting", "tax evasion", "tax fraud", "insurance fraud", "perjury", "kidnapping", "manslaughter", "vandalism", "forgery", "extortion", "embezzlement",
						"public indecency", "public intoxication", "trespassing", "loitering", "littering", "vigilantism", "squatting", "panhandling", "arson", "spacepodjacking", "shuttlejacking", "carjacking", "singularityjacking",
						"dereliction of duty", "spacecraft piracy", "music piracy", "tabletop game piracy", "software piracy", "escaping from space prison", "seniornapping", "clownnapping", "corginapping", "catnapping",
						"sleeping on the job", "terrorism", "counterterrorism", "drug distribution", "insubordination", "jaywalking", "owning a computer", "owning a cellphone", "owning a PDA", "owning a pAI", "adultery",
						"committing an unnatural act with another person", "corrupting public morals", "skateboarding without a license", "shitcurity", "bestiality", "erotic roleplay")
	while (prob(60) && O.len > 2)
		var/offense = pick(O)
		O -= offense
		offense = "[prob(20) ? "attempted " : (prob(20) ? "being accessory to " : null)][offense][prob(5) ? " of the [pick("first", "second", "third", "fourth", "fifth", "sixth")] degree" : null]"
		if (offenses == "")
			offenses = offense
		else
			offenses += ", [offense]"
	offenses += " and [prob(20) ? "attempted " : null][pick(O)]" // lazy
	S.addEvent(src)

/datum/stockEvent/arrest/transition()
	switch (phase_id)
		if (0)
			tname = "[female ? pick(first_names_female) : pick(first_names_male)] [pick(last_names)]"
			next_phase = world.time + rand(300*TIME_MULTIPLIER, 600*TIME_MULTIPLIER) * (10*TIME_MULTIPLIER)
			var/datum/article/A = generateArrestArticle()
			if (!A.opinion)
				effect = rand(5) * (prob(50) ? -1 : 1)
			else
				effect = prob(25) ? -A.opinion * rand(5) : A.opinion * rand(3)
			company.addArticle(A)
			company.affectPublicOpinion(rand(-3, -1))
			hidden = 0
			current_title = "Trial of [tname] ([position]) scheduled"
			current_desc = "[female ? "She": "He"] has been charged with [offenses]; the trial is scheduled to occur at spacetime [spacetime(next_phase)]."
			phase_id = 1
		if (1)
			next_phase = world.time + rand(300*TIME_MULTIPLIER, 600*TIME_MULTIPLIER) * (10*TIME_MULTIPLIER)
			finished = 1
			current_title = "[tname] [effect > 0 ? "acquitted" : "found guilty"]"
			if (effect > 0)
				current_desc = "The accused has been acquitted of all charges. Investors optimistic."
			else
				current_desc = "The accused has been found guilty of all charges. Investor trust takes massive hit."
			company.affectPublicOpinion(effect)
			company.generateEvent(type)

/datum/stockEvent/arrest/proc/generateArrestArticle()
	var/datum/article/A = new
	A.about = company
	A.headline = company.industry.detokenize(pick( \
						"[tname], [position] of [company.name] arrested", \
						"[position] of [company.name] facing jail time", \
						"[tname] behind bars", \
						"[position] of %industrial% company before trial", \
						"Police arrest [tname] in daring raid", \
						"Job vacancy ahead: [company.name]'s [position] in serious trouble"))
	A.subtitle = "[A.author] reporting directly from the courtroom"
	if (prob(15))
		A.opinion = rand(-1, 1)
	var/article = "[pick("Security", "Law enforcement")] forces issued a statement that [tname], the [position] of [company.name], the %famous% %industrial% %company% was arrested %this_time%. The trial has been scheduled and the statement reports that the arrested individual is being charged with [offenses]. "
	if (!A.opinion)
		article += "While we cannot predict the outcome of this trial, our tip to stay safe is: %sell%"
	else if (A.opinion > 0)
		article += "Our own investigation shows that these charges are baseless and the arrest is most likely a publicity stunt. Our advice? You should %buy%"
	else
		article += "[tname] has a prior history of similar misdeeds and we're confident the charges will stand. For investors, now would be an ideal time to %sell%"
	A.article = A.detokenize(article, company.industry.tokens)
	return A


code:
/datum/industry
	var/name = "Industry"
	var/list/tokens = list()

	var/list/title_templates = list("The brand new %product_name% by %company_name% will revolutionize %industry%", \
									"%jobs% rejoice as %product_name% hits shelves", \
									"Does %product_name% threaten to reorganize the %industrial% status quo?", \
									"%company_name% headed toward corporate renaissance with %product_name%")

	var/list/title_templates_neutral = list("%product_name%: as if nothing happened", \
											"Nothing new but the name: %product_name% not quite exciting %jobs%", \
											"Same old %company_name%, same old product", \
											"%product_name% underwhelms, but sells")

	var/list/title_templates_bad = list("%product_name% shaping up to be the disappointment of the century", \
										"Recipe for disaster: %company_name% releases %product_name%", \
										"Atrocious quality - %jobs% boycott %product_name%", \
										"%product_name%: Inside the worst product launch in recent history")

	var/list/title_templates_ooc = list("%company_name% is looking to enter the %industry% playing field with %product_name%", \
										"%company_name% broadens spectrum, %product_name% is their latest and greatest")
	var/list/subtitle_templates = list(	"%author% investigates whether or not you should invest!", \
										"%outlet%'s very own %author% takes it to the magnifying glass", \
										"%outlet% lets you know if you should use it", \
										"Read our top tips for investors", \
										"%author% wants you to know if it's a safe bet to buy")

/datum/industry/proc/generateProductName(var/company_name)
	return

/datum/industry/proc/generateInCharacterProductArticle(var/product_name, var/datum/stock/S)
	var/datum/article/A = new
	var/list/add_tokens = list("company_name" = S.name, "product_name" = product_name, "outlet" = A.outlet, "author" = A.author)
	A.about = S
	A.opinion = rand(-1, 1)

	A.subtitle = A.detokenize(pick(subtitle_templates), tokens, add_tokens)
	var/article = {"%company_name% %expand_influence% %industry%. [ucfirst(product_name)] %hit_shelves% %this_time% "}
	if (A.opinion > 0)
		A.headline = A.detokenize(pick(title_templates), tokens, add_tokens)
		article += "but %positive_outcome%, %signifying% the %resounding% %success% the product is. The %stock_market% is %excited% over this %development%, and %stockholder% optimism is expected to %rise% as well as the stock value. Our advice: %buy%."
	else if (A.opinion == 0)
		A.headline = A.detokenize(pick(title_templates_neutral), tokens, add_tokens)
		article += "but %neutral_outcome%. For the average %stockholder%, no significant change on the market will be apparent over this %development%. Our advice is to continue investing as if this product was never released."
	else
		A.headline = A.detokenize(pick(title_templates_bad), tokens, add_tokens)
		article += "but %negative_outcome%. Following this %complete% %failure%, %stockholder% optimism and stock value are projected to %dip%. Our advice: %sell%."
	A.article = A.detokenize(article, tokens, add_tokens)
	return A

/datum/industry/proc/detokenize(var/str)
	for (var/T in tokens)
		str = replacetext(str, "%[T]%", pick(tokens[T]))
	return str

/datum/industry/agriculture
	name = "Agriculture"
	tokens = list( \
		"industry" = list("agriculture", "farming", "botany", "horticulture", "hydroponics"), \
		"industrial" = list("agricultural", "horticultural", "botanical"), \
		"jobs" = list("farmers", "agricultural experts", "botanists", "assistant gardeners")
	)
	title_templates = list(	"The brand new %product_name% by %company_name% will revolutionize %industry%", \
							"%jobs% rejoice as %product_name% hits shelves", \
							"Does %product name% threaten to reorganize the %industrial% status quo?", \
							"Took it for a field trip: our first %sneak_peek% of %product_name%.", \
							"Reaping the fruits of %product_name% - %sneak_peek% by %author%", \
							"Cultivating a new %industrial% future with %product_name%", \
							"%company_name% grows and thrives: %product_name% now on the farmer's market", \
							"It's almost harvest season: %product_name% promises to ease your life", \
							"Become the best on the farmer's market with %product_name%", \
							"%product_name%: a gene-modified reimagination of an age-old classic")

	title_templates_ooc = list(	"%company_name% is looking to enter the %industry% playing field with %product_name%", \
								"A questionable decision: %product_name% grown on the soil of %company_name%", \
								"%company_name% broadens spectrum, %product_name% is their latest and greatest", \
								"Will %company_name% grow on %industrial% wasteland? Owners of %product_name% may decide", \
								"%company_name% looking to reap profits off the %industrial% sector with %product_name%")

/datum/industry/agriculture/generateProductName(var/company_name)
	var/list/products = list("water tank", "cattle prod", "scythe", "plough", "sickle", "cultivator", "loy", "spade", "hoe", "daisy grubber", "cotton gin")
	var/list/prefix = list("[company_name]'s ", "the [company_name] ", "the fully automatic ", "the full-duplex ", "the semi-automatic ", "the drone-mounted ", "the industry-leading ", "the world-class ")
	var/list/suffix = list(" of farming", " multiplex", " +[rand(1,15)]", " [consonant()][rand(1000, 9999)]", " hybrid", " maximus", " extreme")
	return "[pick(prefix)][pick(products)][pick(suffix)]"

/datum/industry/it
		name = "Information Technology"
		tokens = list( \
			"industry" = list("information technology", "computing", "computer industry"), \
			"industrial" = list("information technological", "computing", "computer industrial"), \
			"jobs" = list("coders", "electricians", "engineers", "programmers", "devops experts", "developers")
		)

/datum/industry/it/proc/latin_number(n)
	if (n < 20 || !(n % 10))
		switch(n)
			if (0) return "Nihil"
			if (1) return "Unus"
			if (2) return "Duo"
			if (3) return "Tres"
			if (4) return "Quattour"
			if (5) return "Quinque"
			if (6) return "Sex"
			if (7) return "Septem"
			if (8) return "Octo"
			if (9) return "Novem"
			if (10) return "Decim"
			if (11) return "Undecim"
			if (12) return "Duodecim"
			if (13) return "Tredecim"
			if (14) return "Quattourdecim"
			if (15) return "Quindecim"
			if (16) return "Sedecim"
			if (17) return "Septdecim"
			if (18) return "Duodeviginti"
			if (19) return "Undeviginti"
			if (20) return "Viginti"
			if (30) return "Triginta"
			if (40) return "Quadriginta"
			if (50) return "Quinquaginta"
			if (60) return "Sexaginta"
			if (70) return "Septuaginta"
			if (80) return "Octoginta"
			if (90) return "Nonaginta"
	else
		return "[latin_number(n - (n % 10))] [lowertext(latin_number(n % 10))]"

/datum/industry/it/generateProductName(var/company_name)
	var/list/products = list("generator", "laptop", "keyboard", "memory card", "display", "operating system", "processor", "graphics card", "nanobots", "power supply", "pAI", "mech", "capacitor", "cell")
	var/list/prefix = list("the [company_name] ", "the high performance ", "the mobile ", "the portable ", "the professional ", "the extreme ", "the incredible ", "the blazing fast ", "the bleeding edge ", "the bluespace-powered ", null)
	var/L = pick(consonant(), "Seed ", "Radiant ", "Robust ", "Pentathon ", "Athlete ", "Phantom ", "Semper Fi ")
	var/N = rand(0,99)
	var/prefix2 = "[L][N][prob(5) ? " " + latin_number(N) : null]"
	return "[pick(prefix)][prefix2] [pick(products)]"

/datum/industry/communications
	name = "Communications"
	tokens = list( \
		"industry" = list("telecommunications", "telecomms"), \
		"industrial" = list("telecommunicational"), \
		"jobs" = list("electrical engineers", "microengineers", "developers")
	)

/datum/industry/communications/generateProductName(var/company_name)
	var/list/products = list("mobile phone", "PDA", "tablet computer", "newscaster", "social network")
	var/list/prefix = list("the [company_name] ", "the high performance ", "the mobile ", "the portable ", "the professional ", "the extreme ", "the incredible ", "the blazing fast ", "the bleeding edge ", null)
	var/L = pick("[lowertext(consonant())]Phone ", "Universe ", "Xperience ", "Next ", "Engin Y ", "Cyborg ", "[consonant()]")
	var/N = rand(1,99)
	var/prefix2 = "[L][N][prob(25) ? pick(" Tiny", " Mini", " Micro", " Slim", " Water", " Air", " Fire", " Earth", " Nano", " Pico", " Femto", " Planck") : null]"
	return "[pick(prefix)][prefix2] [pick(products)]"

/datum/industry/health
	name = "Medicine"
	tokens = list( \
		"industry" = list("medicine"), \
		"industrial" = list("medicinal"), \
		"jobs" = list("medical doctors", "nurses", "paramedics", "psychologists", "psychiatrists", "chemists")
	)

/datum/industry/health/generateProductName(var/company_name)
	var/list/prefix = list("amino", "nucleo", "nitro", "panto", "meth", "eth", "as", "algo", "coca", "hero", "lotsu", "opiod", "morph", "trinitro", "prop", "but", "acet", "acyclo", "lansop", "dyclo", "hydro", "oxycod", "vicod", "cannabi", "cryo", "dex", "chloro")
	var/list/suffix = list("phen", "pirin", "pyrine", "ane", "amphetamine", "prazoline", "ine", "yl", "amine", "aminophen", "one", "ide", "phenate", "anol", "toulene", "glycerine", "vir", "tol", "trinic", "oxide")
	var/list/uses = list("antidepressant", "analgesic", "anesthetic", "antiretroviral", "antiviral", "antibiotic", "cough drop", "depressant", "hangover cure", "homeopathic", "fertility drug", "hypnotic", "narcotic", "laxative", "multivitamin", "patch", "purgative", "relaxant", "steroid", "sleeping pill", "suppository", "tranquilizer")
	return "[pick(prefix)][pick(suffix)], the [pick(uses)]"

/datum/industry/consumer
	name = "Consumer"
	tokens = list( \
		"industry" = list("shops", "stores"), \
		"industrial" = list("consumer industrial"), \
		"jobs" = list("shopkeepers", "assistants", "manual daytime hygiene engineers", "janitors", "chefs", "cooks")
	)

/datum/industry/consumer/generateProductName(var/company)
	var/list/meat = list("chicken", "lizard", "corgi", "monkey", "goat", "fly", "xenomorph", "human", "walrus", "wendigo", "bear", "clown", "turkey", "pork", "carp", "crab", "mimic", "mystery")
	var/list/qualifier = list("synthetic", "organic", "bio", "diet", "sugar-free", "paleolithic", "homeopathic", "recycled", "reclaimed", "vat-grown")
	return "the [pick(qualifier)] [pick(meat)] meat product line"

/datum/industry/mining
	name = "Mining"
	tokens = list( \
		"industry" = list("mines", "large scale mining operations"), \
		"industrial" = list("resource acquisitional"), \
		"jobs" = list("shaft miners", "drill operators", "mining foremen", "gibtonite handlers")
	)

/datum/industry/mining/generateProductName(var/company)
	var/list/equipment = list("drill", "pickaxe", "shovel", "jackhammer", "mini-pickaxe", "power hammer", "power gloves", "power armor", "hardsuit", "kinetic accelerator", "resonator", "oxygen tank", "emergency bike horn")
	var/list/material = list("mauxite", "pharosium", "molitz", "adamantium", "mithril", "cobryl", "bohrum", "claretine", "viscerite", "syreline", "cerenkite", "plasmastone", "gold", "koshmarite", "phoron", "carbon dioxide")
	return "the [pick(material)] [pick(equipment)]"

/datum/industry/defense
	name = "Defense"
	tokens = list ( \
		"industry" = list("defense", "warfare", "security", "law enforcement"), \
		"industrial" = list("defense"), \
		"jobs" = list("security officers", "government officials", "soldiers", "weapons engineers")
	)

/datum/industry/defense/generateProductName(var/company)
	var/list/equipment = list("energy gun", "laser gun", "machine gun", "grenade", "stun baton", "artillery", "bomb", "attack drone", "missile", "chem sprayer")
	var/list/material = list("bluespace", "stealth", "heat-seeking", "crime-seeking", "wide-range", "bioterror", "auto-reloading", "smart", "sentient", "rapid-fire", "species-targeting", "gibtonite", "mass-market", "perpetual-motion", "nuclear", "fission", "fusion")
	return "the [pick(material)] [pick(equipment)]"

license: mit


code:
/datum/stock_log
	var/user_name = ""
	var/company_name = ""
	var/shareprice
	var/money
	var/stocks
	var/time

/datum/stock_log/buy

/datum/stock_log/sell

/datum/stock_log/borrow


code:
/datum/stockMarket
	var/list/stocks = list()
	var/list/balances = list()
	var/list/last_read = list()
	var/list/stockBrokers = list()
	var/list/logs = list()

/datum/stockMarket/New()
		..()
		generateBrokers()
		generateStocks()
		SSobj.processing.Add(src)

/datum/stockMarket/proc/balanceLog(var/whose, var/net)
	if (!(whose in balances))
		balances[whose] = net
	else
		balances[whose] += net
/datum/stockMarket/proc/generateBrokers()
	stockBrokers = list()
	var/list/fnames = list("Goldman", "Edward", "James", "Luis", "Alexander", "Walter", "Eugene", "Mary", "Morgan", "Jane", "Elizabeth", "Xavier", "Hayden", "Samuel", "Lee")
	var/list/names = list("Johnson", "Rothschild", "Sachs", "Stanley", "Hepburn", "Brown", "McColl", "Fischer", "Edwards", "Becker", "Witter", "Walker", "Lambert", "Smith", "Montgomery", "Lynch", "Roosevelt", "Lehman")
	var/list/locations = list("Earth", "Luna", "Mars", "Saturn", "Jupiter", "Uranus", "Pluto", "Europa", "Io", "Phobos", "Deimos", "Space", "Venus", "Neptune", "Mercury", "Kalliope", "Ganymede", "Callisto", "Amalthea", "Himalia", "Sybil", "Basil", "Badger", "Terry", "Artyom")
	var/list/first = list("The", "First", "Premier", "Finest", "Prime")
	var/list/company = list("Investments", "Securities", "Corporation", "Bank", "Brokerage", "& Co.", "Brothers", "& Sons", "Investement Firm", "Union", "Partners", "Capital", "Trade", "Holdings")
	for(var/i in 1 to 5)
		var/pname = ""
		switch (rand(1,5))
			if (1)
				pname = "[prob(10) ? pick(first) + " " : null][pick(names)] [pick(company)]"
			if (2)
				pname = "[pick(names)] & [pick(names)][prob(25) ? " " + pick(company) : null]"
			if (3)
				pname = "[prob(45) ? pick(first) + " " : null][pick(locations)] [pick(company)]"
			if (4)
				pname = "[prob(10) ? "The " : null][pick(names)] [pick(locations)] [pick(company)]"
			if (5)
				pname = "[prob(10) ? "The " : null][pick(fnames)] [pick(names)][prob(10) ? " " + pick(company) : null]"
		if (pname in stockBrokers)
			i--
			continue
		stockBrokers += pname

/datum/stockMarket/proc/generateDesignation(var/name)
	if (length(name) <= 4)
		return uppertext(name)
	var/list/w = splittext(name, " ")
	if (w.len >= 2)
		var/d = ""
		for(var/i in 1 to min(5, w.len))
			d += uppertext(ascii2text(text2ascii(w[i], 1)))
		return d
	else
		var/d = uppertext(ascii2text(text2ascii(name, 1)))
		for(var/i in 2 to length(name))
			if (prob(100 / i))
				d += uppertext(ascii2text(text2ascii(name, i)))
		return d

/datum/stockMarket/proc/generateStocks(var/amt = 15)
	var/list/fruits = list("Banana", "Mimana", "Watermelon", "Ambrosia", "Pomegranate", "Reishi", "Papaya", "Mango", "Tomato", "Conkerberry", "Wood", "Lychee", "Mandarin", "Harebell", "Pumpkin", "Rhubarb", "Tamarillo", "Yantok", "Ziziphus", "Oranges", "Gatfruit", "Daisy", "Kudzu")
	var/list/tech_prefix = list("Nano", "Cyber", "Funk", "Astro", "Fusion", "Tera", "Exo", "Star", "Virtual", "Plasma", "Robust", "Bit", "Future", "Hugbox", "Carbon", "Nerf", "Buff", "Nova", "Space", "Meta", "Cyber")
	var/list/tech_short = list("soft", "tech", "prog", "tec", "tek", "ware", "", "gadgets", "nics", "tric", "trasen", "tronic", "coin")
	var/list/random_nouns = list("Johnson", "Cluwne", "General", "Specific", "Master", "King", "Queen", "Table", "Rupture", "Dynamic", "Massive", "Mega", "Giga", "Certain", "Singulo", "State", "National", "International", "Interplanetary", "Sector", "Planet", "Burn", "Robust", "Exotic", "Solar", "Lunar", "Chelp", "Corgi", "Lag", "Lizard")
	var/list/company = list("Company", "Factory", "Incorporated", "Industries", "Group", "Consolidated", "GmbH", "LLC", "Ltd", "Inc.", "Association", "Limited", "Software", "Technology", "Programming", "IT Group", "Electronics", "Nanotechnology", "Farms", "Stores", "Mobile", "Motors", "Electric", "Designs", "Energy", "Pharmaceuticals", "Communications", "Wholesale", "Holding", "Health", "Machines", "Astrotech", "Gadgets", "Kinetics")
	for (var/i = 1, i <= amt, i++)
		var/datum/stock/S = new
		var/sname = ""
		switch (rand(1,6))
			if(1)
				while (sname == "" || sname == "FAG") // honestly it's a 0.6% chance per round this happens - or once in 166 rounds - so i'm accounting for it before someone yells at me
					sname = "[consonant()][vowel()][consonant()]"
			if (2)
				sname = "[pick(tech_prefix)][pick(tech_short)][prob(20) ? " " + pick(company) : null]"
			if (3 to 4)
				var/fruit = pick(fruits)
				fruits -= fruit
				sname = "[prob(10) ? "The " : null][fruit][prob(40) ? " " + pick(company): null]"
			if (5 to 6)
				var/pname = pick(random_nouns)
				random_nouns -= pname
				switch (rand(1,3))
					if (1)
						sname = "[pname] & [pname]"
					if (2)
						sname = "[pname] [pick(company)]"
					if (3)
						sname = "[pname]"
		S.name = sname
		S.short_name = generateDesignation(S.name)
		S.current_value = rand(10, 125)
		var/dv = rand(10, 40) / 10
		S.fluctuational_coefficient = prob(50) ? (1 / dv) : dv
		S.average_optimism = rand(-10, 10) / 100
		S.optimism = S.average_optimism + (rand(-40, 40) / 100)
		S.current_trend = rand(-200, 200) / 10
		S.last_trend = S.current_trend
		S.disp_value_change = rand(-1, 1)
		S.speculation = rand(-20, 20)
		S.average_shares = round(rand(500, 10000) / 10)
		S.outside_shareholders = rand(1000, 30000)
		S.available_shares = rand(200000, 800000)
		S.fluctuation_rate = rand(6, 20)
		S.generateIndustry()
		S.generateEvents()
		stocks += S
		last_read[S] = list()

/datum/stockMarket/process()
	for (var/stock in stocks)
		var/datum/stock/S = stock
		S.process()

/datum/stockMarket/proc/add_log(var/log_type, var/user, var/company_name, var/stocks, var/shareprice, var/money)
	var/datum/stock_log/L = new log_type
	L.user_name = user
	L.company_name = company_name
	L.stocks = stocks
	L.shareprice = shareprice
	L.money = money
	L.time = time2text(world.timeofday, "hh:mm")
	logs += L

var/global/datum/stockMarket/stockExchange = new

/proc/plotBarGraph(var/list/points, var/base_text, var/width=400, var/height=400)
	var/output = "
"
	if (points.len && height > 20 && width > 20)
		var/min = points[1]
		var/max = points[1]
		for (var/v in points)
			if (v < min)
				min = v
			if (v > max)
				max = v
		var/cells = (height - 20) / 20
		if (cells > round(cells))
			cells = round(cells) + 1
		var/diff = max - min
		var/ost = diff / cells
		if (min > 0)
			min = max(min - ost, 0)
		diff = max - min
		ost = diff / cells
		var/cval = max
		var/cwid = width / (points.len + 1)
		for (var/y = cells, y > 0, y--)
			if (y == cells)
				output += "
"
			else
				output += "
"
			for (var/x = 0, x <= points.len, x++)
				if (x == 0)
					output += "[round(cval - ost)]	"
				else
					var/v = points[x]
					if (v >= cval)
						output += " 	"
					else
						output += " 	"
			output += "
"
			cval -= ost
		output += "
[base_text]
"
	else
		output += "

"
		output += "
[base_text]
"

	return "[output]
"


code:
/datum/borrow
	var/broker = ""
	var/borrower = ""
	var/datum/stock/stock = null
	var/lease_expires = 0
	var/lease_time = 0
	var/grace_time = 0
	var/grace_expires = 0
	var/share_amount = 0
	var/share_debt = 0
	var/deposit = 0
	var/offer_expires = 0

/datum/stock
	var/name = "Stock"
	var/short_name = "STK"
	var/desc = "A company that does not exist."
	var/list/values = list()
	var/current_value = 10
	var/last_value = 10
	var/list/products = list()

	var/performance = 0						// The current performance of the company. Tends itself to 0 when no events happen.

	// These variables determine standard fluctuational patterns for this stock.
	var/fluctuational_coefficient = 1		// How much the price fluctuates on an average daily basis
	var/average_optimism = 0				// The history of shareholder optimism of this stock
	var/current_trend = 0
	var/last_trend = 0
	var/speculation = 0
	var/bankrupt = 0

	var/disp_value_change = 0
	var/optimism = 0
	var/last_unification = 0
	var/average_shares = 100
	var/outside_shareholders = 10000		// The amount of offstation people holding shares in this company. The higher it is, the more fluctuation it causes.
	var/available_shares = 500000

	var/list/borrow_brokers = list()
	var/list/shareholders = list()
	var/list/borrows = list()
	var/list/events = list()
	var/list/articles = list()
	var/fluctuation_rate = 15
	var/fluctuation_counter = 0
	var/datum/industry/industry = null

/datum/stock/proc/addEvent(var/datum/stockEvent/E)
	events |= E

/datum/stock/proc/addArticle(var/datum/article/A)
	if (!(A in articles))
		articles.Insert(1, A)
	A.ticks = world.time

/datum/stock/proc/generateEvents()
	var/list/types = typesof(/datum/stockEvent) - /datum/stockEvent
	for (var/T in types)
		generateEvent(T)

/datum/stock/proc/generateEvent(var/T)
	var/datum/stockEvent/E = new T(src)
	addEvent(E)

/datum/stock/proc/affectPublicOpinion(var/boost)
	optimism += rand(0, 500) / 500 * boost
	average_optimism += rand(0, 150) / 5000 * boost
	speculation += rand(-1, 50) / 10 * boost
	performance += rand(0, 150) / 100 * boost

/datum/stock/proc/generateIndustry()
	if (findtext(name, "Farms"))
		industry = new /datum/industry/agriculture
	else if (findtext(name, "Software") || findtext(name, "Programming")  || findtext(name, "IT Group") || findtext(name, "Electronics") || findtext(name, "Electric") || findtext(name, "Nanotechnology"))
		industry = new /datum/industry/it
	else if (findtext(name, "Mobile") || findtext(name, "Communications"))
		industry = new /datum/industry/communications
	else if (findtext(name, "Pharmaceuticals") || findtext(name, "Health"))
		industry = new /datum/industry/health
	else if (findtext(name, "Wholesale") || findtext(name, "Stores"))
		industry = new /datum/industry/consumer
	else
		var/ts = typesof(/datum/industry) - /datum/industry
		var/in_t = pick(ts)
		industry = new in_t
	for (var/i = 0, i < rand(2, 5), i++)
		products += industry.generateProductName(name)

/datum/stock/proc/frc(amt)
	var/shares = available_shares + outside_shareholders * average_shares
	var/fr = amt / 100 / shares * fluctuational_coefficient * fluctuation_rate * max(-(current_trend / 100), 1)
	if (fr < 0 && speculation < 0 || fr > 0 && speculation > 0)
		fr *= max(abs(speculation) / 5, 1)
	else
		fr /= max(abs(speculation) / 5, 1)
	return fr

/datum/stock/proc/supplyGrowth(amt)
	var/fr = frc(amt)
	available_shares += amt
	if (abs(fr) < 0.0001)
		return
	current_value -= fr * current_value

/datum/stock/proc/supplyDrop(amt)
	supplyGrowth(-amt)

/datum/stock/proc/fluctuate()
	var/change = rand(-100, 100) / 10 + optimism * rand(200) / 10
	optimism -= (optimism - average_optimism) * (rand(10,80) / 1000)
	var/shift_score = change + current_trend
	var/as_score = abs(shift_score)
	var/sh_change_dev = rand(-10, 10) / 10
	var/sh_change = shift_score / (as_score + 100) + sh_change_dev
	var/shareholder_change = round(sh_change)
	outside_shareholders += shareholder_change
	var/share_change = shareholder_change * average_shares
	if (as_score > 20 && prob(as_score / 4))
		var/avg_change_dev = rand(-10, 10) / 10
		var/avg_change = shift_score / (as_score + 100) + avg_change_dev
		average_shares += avg_change
		share_change += outside_shareholders * avg_change

	var/cv = last_value
	supplyDrop(share_change)
	available_shares += share_change // temporary

	if (prob(25))
		average_optimism = max(min(average_optimism + (rand(-3, 3) - current_trend * 0.15) / 100, 1), -1)

	var/aspec = abs(speculation)
	if (prob((aspec - 75) * 2))
		speculation += rand(-4, 4)
	else
		if (prob(50))
			speculation += rand(-4, 4)
		else
			speculation += rand(-400, 0) / 1000 * speculation
			if (prob(1) && prob(5)) // pop that bubble
				speculation += rand(-4000, 0) / 1000 * speculation

	current_value += (speculation / rand(25000, 50000) + performance / rand(100, 800)) * current_value
	if (current_value < 5)
		current_value = 5

	if (performance != 0)
		performance = rand(900,1050) / 1000 * performance
		if (abs(performance) < 0.2)
			performance = 0

	disp_value_change = (cv < current_value) ? 1 : ((cv > current_value) ? -1 : 0)
	last_value = current_value
	if (values.len >= 50)
		values.Cut(1,2)
	values += current_value

	if (current_value < 10)
		unifyShares()

	last_trend = current_trend
	current_trend += rand(-200, 200) / 100 + optimism * rand(200) / 10 + max(50 - abs(speculation), 0) / 50 * rand(0, 200) / 1000 * (-current_trend) + max(speculation - 50, 0) * rand(0, 200) / 1000 * speculation / 400

/datum/stock/proc/unifyShares()
	for (var/I in shareholders)
		var/shr = shareholders[I]
		if (shr % 2)
			sellShares(I, 1)
		shr -= 1
		shareholders[I] /= 2
		if (!shareholders[I])
			shareholders -= I
	for (var/datum/borrow/B in borrow_brokers)
		B.share_amount = round(B.share_amount / 2)
		B.share_debt = round(B.share_debt / 2)
	for (var/datum/borrow/B in borrows)
		B.share_amount = round(B.share_amount / 2)
		B.share_debt = round(B.share_debt / 2)
	average_shares /= 2
	available_shares /= 2
	current_value *= 2
	last_unification = world.time

/datum/stock/process()
	for (var/B in borrows)
		var/datum/borrow/borrow = B
		if (world.time > borrow.grace_expires)
			modifyAccount(borrow.borrower, -max(current_value * borrow.share_debt, 0), 1)
			borrows -= borrow
			if (borrow.borrower in FrozenAccounts)
				FrozenAccounts[borrow.borrower] -= borrow
				if (length(FrozenAccounts[borrow.borrower]) == 0)
					FrozenAccounts -= borrow.borrower
			qdel(borrow)
		else if (world.time > borrow.lease_expires)
			if (borrow.borrower in shareholders)
				var/amt = shareholders[borrow.borrower]
				if (amt > borrow.share_debt)
					shareholders[borrow.borrower] -= borrow.share_debt
					borrows -= borrow
					if (borrow.borrower in FrozenAccounts)
						FrozenAccounts[borrow.borrower] -= borrow
					if (length(FrozenAccounts[borrow.borrower]) == 0)
						FrozenAccounts -= borrow.borrower
					qdel(borrow)
				else
					shareholders -= borrow.borrower
					borrow.share_debt -= amt
	if (bankrupt)
		return
	for (var/B in borrow_brokers)
		var/datum/borrow/borrow = B
		if (borrow.offer_expires < world.time)
			borrow_brokers -= borrow
			qdel(borrow)
	if (prob(5))
		generateBrokers()
	fluctuation_counter++
	if (fluctuation_counter >= fluctuation_rate)
		for (var/E in events)
			var/datum/stockEvent/EV = E
			EV.process()
		fluctuation_counter = 0
		fluctuate()

/datum/stock/proc/generateBrokers()
	if (borrow_brokers.len > 2)
		return
	if (!stockExchange.stockBrokers.len)
		stockExchange.generateBrokers()
	var/broker = pick(stockExchange.stockBrokers)
	var/datum/borrow/B = new
	B.broker = broker
	B.stock = src
	B.lease_time = rand(4, 7) * 600
	B.grace_time = rand(1, 3) * 600
	B.share_amount = rand(1, 10) * 100
	B.deposit = rand(20, 70) / 100
	B.share_debt = B.share_amount
	B.offer_expires = rand(5, 10) * 600 + world.time
	borrow_brokers += B

/datum/stock/proc/modifyAccount(whose, by, force=0)
	if (SSshuttle.points)
		if (by < 0 && SSshuttle.points + by < 0 && !force)
			return 0
		SSshuttle.points += by
		stockExchange.balanceLog(whose, by)
		return 1
	return 0

/datum/stock/proc/borrow(var/datum/borrow/B, var/who)
	if (B.lease_expires)
		return 0
	B.lease_expires = world.time + B.lease_time
	var/old_d = B.deposit
	var/d_amt = B.deposit * current_value * B.share_amount
	if (!modifyAccount(who, -d_amt))
		B.lease_expires = 0
		B.deposit = old_d
		return 0
	B.deposit = d_amt
	if (!(who in shareholders))
		shareholders[who] = B.share_amount
	else
		shareholders[who] += B.share_amount
	borrow_brokers -= B
	borrows += B
	B.borrower = who
	B.grace_expires = B.lease_expires + B.grace_time
	if (!(who in FrozenAccounts))
		FrozenAccounts[who] = list(B)
	else
		FrozenAccounts[who] += B
	return 1

/datum/stock/proc/buyShares(var/who, var/howmany)
	if (howmany <= 0)
		return
	howmany = round(howmany)
	var/loss = howmany * current_value
	if (available_shares < howmany)
		return 0
	if (modifyAccount(who, -loss))
		supplyDrop(howmany)
		if (!(who in shareholders))
			shareholders[who] = howmany
		else
			shareholders[who] += howmany
		return 1
	return 0

/datum/stock/proc/sellShares(var/whose, var/howmany)
	if (howmany < 0)
		return
	howmany = round(howmany)
	var/gain = howmany * current_value
	if (shareholders[whose] < howmany)
		return 0
	if (modifyAccount(whose, gain))
		supplyGrowth(howmany)
		shareholders[whose] -= howmany
		if (shareholders[whose] <= 0)
			shareholders -= whose
		return 1
	return 0

/datum/stock/proc/displayValues(var/mob/user)
	user << browse(plotBarGraph(values, "[name] share value per share"), "window=stock_[name];size=450x450")


code:
/datum/surgery/cavity_implant
	name = "cavity implant"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/incise, /datum/surgery_step/handle_cavity, /datum/surgery_step/close)
	species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
	possible_locs = list("chest")

//handle cavity
/datum/surgery_step/handle_cavity
	name = "implant item"
	accept_hand = 1
	accept_any_item = 1
	time = 32
	var/obj/item/IC = null

/datum/surgery_step/handle_cavity/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	for(var/obj/item/I in target.internal_organs)
		if(!istype(I, /obj/item/organ))
			IC = I
			break
	if(tool)
		user.visible_message("[user] begins to insert [tool] into [target]'s [target_zone].", "You begin to insert [tool] into [target]'s [target_zone]...")
	else
		user.visible_message("[user] checks for items in [target]'s [target_zone].", "You check for items in [target]'s [target_zone]...")

/datum/surgery_step/handle_cavity/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(tool)
		if(IC || tool.w_class > 3 || (NODROP in tool.flags) || istype(tool, /obj/item/organ))
			user << "You can't seem to fit [tool] in [target]'s [target_zone]!"
			return 0
		else
			user.visible_message("[user] stuffs [tool] into [target]'s [target_zone]!", "You stuff [tool] into [target]'s [target_zone].")
			user.drop_item()
			target.internal_organs += tool
			tool.loc = target
			return 1
	else
		if(IC)
			user.visible_message("[user] pulls [IC] out of [target]'s [target_zone]!", "You pull [IC] out of [target]'s [target_zone].")
			user.put_in_hands(IC)
			target.internal_organs -= IC
			return 1
		else
			user << "You don't find anything in [target]'s [target_zone]."
			return 0


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

/datum/surgery/core_removal/can_start(mob/user, mob/living/carbon/target)
	if(target.stat == DEAD)
		return 1
	return 0

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

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

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

		new slime.coretype(slime.loc)

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


code:
/datum/surgery/dental_implant
	name = "dental implant"
	steps = list(/datum/surgery_step/drill, /datum/surgery_step/insert_pill)
	possible_locs = list("mouth")

/datum/surgery_step/insert_pill
	name = "insert pill"
	implements = list(/obj/item/weapon/reagent_containers/pill = 100)
	time = 16

/datum/surgery_step/insert_pill/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to wedge \the [tool] in [target]'s [parse_zone(target_zone)].", "You begin to wedge [tool] in [target]'s [parse_zone(target_zone)]...")

/datum/surgery_step/insert_pill/success(mob/user, mob/living/carbon/target, target_zone, var/obj/item/weapon/reagent_containers/pill/tool, datum/surgery/surgery)
	if(!istype(tool))
		return 0

	user.drop_item()
	target.internal_organs += tool
	tool.loc = target

	var/datum/action/item_action/hands_free/activate_pill/P = new
	P.button_icon_state = tool.icon_state
	P.target = tool
	P.Grant(target)

	user.visible_message("[user] wedges \the [tool] into [target]'s [parse_zone(target_zone)]!", "You wedge [tool] into [target]'s [parse_zone(target_zone)].")
	return 1

/datum/action/item_action/hands_free/activate_pill
	name = "Activate Pill"

/datum/action/item_action/hands_free/activate_pill/Trigger()
	if(!..())
		return 0
	owner << "You grit your teeth and burst the implanted [target]!"
	add_logs(owner, null, "swallowed an implanted pill", target)
	if(target.reagents.total_volume)
		target.reagents.reaction(owner, INGEST)
		target.reagents.trans_to(owner, target.reagents.total_volume)
	Remove(owner)
	qdel(target)
	return 1


code:
/datum/surgery/remove_thrall
	name = "dethralling"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/dethrall)
	possible_locs = list("head")

/datum/surgery/remove_thrall/can_start(mob/user, mob/living/carbon/target)
	return is_thrall(target)

/datum/surgery_step/dethrall
	name = "cleanse contamination"
	implements = list(/obj/item/device/assembly/flash = 100, /obj/item/device/flashlight/pen = 80, /obj/item/device/flashlight = 40)
	time = 30

/datum/surgery_step/dethrall/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] reaches into [target]'s head with [tool].", "You begin aligning [tool]'s light to the tumor on [target]'s brain...")

/datum/surgery_step/dethrall/success(mob/user, mob/living/carbon/target, target_zone, datum/surgery/surgery)
	if(target.dna.species.id == "l_shadowling") //Empowered thralls cannot be deconverted
		target << "NOT LIKE THIS!"
		user.visible_message("[target] suddenly slams upward and knocks down [user]!", \
							 "[target] suddenly bolts up and slams you with tremendous force!")
		user.resting = 0 //Remove all stuns
		user.SetSleeping(0)
		user.SetStunned(0)
		user.SetWeakened(0)
		user.SetParalysis(0)
		if(iscarbon(user))
			var/mob/living/carbon/C = user
			C.Weaken(6)
			C.apply_damage(20, "brute", "chest")
		else if(issilicon(user))
			var/mob/living/silicon/S = user
			S.Weaken(8)
			S.apply_damage(20, "brute")
			playsound(S, 'sound/effects/bang.ogg', 50, 1)
		return 0
	user.visible_message("[user] shines light onto the tumor in [target]'s head!", "You cleanse the contamination from [target]'s brain!")
	ticker.mode.remove_thrall(target.mind, 0)
	target.visible_message("A strange black mass falls from [target]'s head!")
	new /obj/item/organ/internal/shadowtumor(get_turf(target))
	return 1


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

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

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

/datum/surgery_step/fix_eyes/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] successfully fixes [target]'s eyes!", "You succeed in fixing [target]'s eyes.")
	target.cure_blind()
	target.set_blindness(0)
	target.cure_nearsighted()
	target.blur_eyes(35)	//this will fix itself slowly.
	target.set_eye_damage(0)
	return 1

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


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

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

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

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

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


code:
//make incision
/datum/surgery_step/incise
	name = "make incision"
	implements = list(/obj/item/weapon/scalpel = 100, /obj/item/weapon/melee/energy/sword = 75, /obj/item/weapon/kitchen/knife = 65, /obj/item/weapon/shard = 45)
	time = 16

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

//clamp bleeders
/datum/surgery_step/clamp_bleeders
	name = "clamp bleeders"
	implements = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/wirecutters = 60, /obj/item/stack/packageWrap = 35, /obj/item/stack/cable_coil = 15)
	time = 24

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

/datum/surgery_step/clamp_bleeders/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(locate(/datum/surgery_step/saw) in surgery.steps)
		target.heal_organ_damage(20,0)
	return ..()

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

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

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

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

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

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

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

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

	return 0

/datum/surgery_step/close/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(locate(/datum/surgery_step/saw) in surgery.steps)
		target.heal_organ_damage(45,0)
	return ..()

//saw bone
/datum/surgery_step/saw
	name = "saw bone"
	implements = list(/obj/item/weapon/circular_saw = 100, /obj/item/weapon/melee/energy/sword/cyborg/saw = 100, /obj/item/weapon/melee/arm_blade = 75, /obj/item/weapon/mounted_chainsaw = 65, /obj/item/weapon/twohanded/required/chainsaw = 50, /obj/item/weapon/twohanded/fireaxe = 50, /obj/item/weapon/hatchet = 35, /obj/item/weapon/kitchen/knife/butcher = 25)
	time = 54

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

/datum/surgery_step/saw/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(ishuman(target))
		var/mob/living/carbon/human/H = target
		H.apply_damage(50,"brute","[target_zone]")

	user.visible_message("[user] saws [target]'s [parse_zone(target_zone)] open!", "You saw [target]'s [parse_zone(target_zone)] open.")
	return 1

//drill bone
/datum/surgery_step/drill
	name = "drill bone"
	implements = list(/obj/item/weapon/surgicaldrill = 100, /obj/item/weapon/pickaxe/drill = 60, /obj/item/mecha_parts/mecha_equipment/drill = 60, /obj/item/weapon/screwdriver = 20)
	time = 30

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

/datum/surgery_step/drill/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] drills into [target]'s [parse_zone(target_zone)]!", "You drill into [target]'s [parse_zone(target_zone)].")
	return 1


code:
/proc/attempt_initiate_surgery(obj/item/I, mob/living/M, mob/user)
	if(istype(M))
		var/mob/living/carbon/human/H
		var/obj/item/organ/limb/affecting
		var/selected_zone = user.zone_selected

		if(istype(M, /mob/living/carbon/human))
			H = M
			affecting = H.get_organ(check_zone(selected_zone))

		if(M.lying || isslime(M))	//if they're prone or a slime
			var/datum/surgery/current_surgery

			for(var/datum/surgery/S in M.surgeries)
				if(S.location == selected_zone)
					current_surgery = S

			if(!current_surgery)
				var/list/all_surgeries = surgeries_list.Copy()
				var/list/available_surgeries = list()

				for(var/datum/surgery/S in all_surgeries)
					if(!S.possible_locs.Find(selected_zone))
						continue
					if(affecting && S.requires_organic_bodypart && affecting.status == ORGAN_ROBOTIC)
						continue
					if(!S.can_start(user, M))
						continue

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

				var/P = input("Begin which procedure?", "Surgery", null, null) as null|anything in available_surgeries
				if(P && user && user.Adjacent(M) && (I in user))
					var/datum/surgery/S = available_surgeries[P]
					var/datum/surgery/procedure = new S.type
					if(procedure)
						procedure.location = selected_zone
						if(procedure.ignore_clothes || get_location_accessible(M, selected_zone))
							M.surgeries += procedure
							procedure.organ = affecting
							user.visible_message("[user] drapes [I] over [M]'s [parse_zone(selected_zone)] to prepare for \an [procedure.name].", \
								"You drape [I] over [M]'s [parse_zone(selected_zone)] to prepare for \an [procedure.name].")

							add_logs(user, M, "operated", addition="Operation type: [procedure.name], location: [selected_zone]")
						else
							user << "You need to expose [M]'s [parse_zone(selected_zone)] first!"

			else if(!current_surgery.step_in_progress)
				if(current_surgery.status == 1)
					M.surgeries -= current_surgery
					user.visible_message("[user] removes the drapes from [M]'s [parse_zone(selected_zone)].", \
						"You remove the drapes from [M]'s [parse_zone(selected_zone)].")
					qdel(current_surgery)
				else if(istype(user.get_inactive_hand(), /obj/item/weapon/cautery) && current_surgery.can_cancel)
					M.surgeries -= current_surgery
					user.visible_message("[user] mends the incision and removes the drapes from [M]'s [parse_zone(selected_zone)].", \
						"You mend the incision and remove the drapes from [M]'s [parse_zone(selected_zone)].")
					qdel(current_surgery)
				else if(current_surgery.can_cancel)
					user << "You need to hold a cautery in inactive hand to stop [M]'s surgery!"

			return 1
	return 0

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

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

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

	return 1


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

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

/datum/surgery_step/extract_implant/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	I = locate(/obj/item/weapon/implant) in target
	if(I)
		user.visible_message("[user] begins to extract [I] from [target]'s [target_zone].", "You begin to extract [I] from [target]'s [target_zone]...")
	else
		user.visible_message("[user] looks for an implant in [target]'s [target_zone].", "You look for an implant in [target]'s [target_zone]...")

/datum/surgery_step/extract_implant/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(I)
		user.visible_message("[user] successfully removes [I] from [target]'s [target_zone]!", "You successfully remove [I] from [target]'s [target_zone].")
		I.removed(target)

		var/obj/item/weapon/implantcase/case

		if(istype(user.get_item_by_slot(slot_l_hand), /obj/item/weapon/implantcase))
			case = user.get_item_by_slot(slot_l_hand)
		else if(istype(user.get_item_by_slot(slot_r_hand), /obj/item/weapon/implantcase))
			case = user.get_item_by_slot(slot_r_hand)
		else
			case = locate(/obj/item/weapon/implantcase) in get_turf(target)

		if(case && !case.imp)
			case.imp = I
			I.loc = case
			case.update_icon()
			user.visible_message("[user] places [I] into [case]!", "You place [I] into [case].")
		else
			qdel(I)

	else
		user << "You can't find anything in [target]'s [target_zone]!"
	return 1


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

//SURGERY STEPS

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

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

/datum/surgery_step/add_limb
	name = "replace limb"
	implements = list(/obj/item/robot_parts = 100)
	time = 32
	var/obj/item/organ/limb/L = null // L because "limb"

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

//ACTUAL SURGERIES

/datum/surgery/augmentation
	name = "augmentation"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/replace, /datum/surgery_step/saw, /datum/surgery_step/add_limb)
	species = list(/mob/living/carbon/human)
	possible_locs = list("r_arm","l_arm","r_leg","l_leg","chest","head")

//SURGERY STEP SUCCESSES

/datum/surgery_step/add_limb/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(L)
		if(ishuman(target))
			var/mob/living/carbon/human/H = target
			user.visible_message("[user] successfully augments [target]'s [parse_zone(target_zone)]!", "You successfully augment [target]'s [parse_zone(target_zone)].")
			L.loc = get_turf(target)
			H.organs -= L
			switch(target_zone)
				if("r_leg")
					H.organs += new /obj/item/organ/limb/robot/r_leg(src)
				if("l_leg")
					H.organs += new /obj/item/organ/limb/robot/l_leg(src)
				if("r_arm")
					H.organs += new /obj/item/organ/limb/robot/r_arm(src)
				if("l_arm")
					H.organs += new /obj/item/organ/limb/robot/l_arm(src)
				if("head")
					H.organs += new /obj/item/organ/limb/robot/head(src)
				if("chest")
					H.organs += new /obj/item/organ/limb/robot/chest(src)
			user.drop_item()
			qdel(tool)
			H.update_damage_overlays(0)
			H.update_augments() //Gives them the Cyber limb overlay
			H.updatehealth()
			add_logs(user, target, "augmented", addition="by giving him new [parse_zone(target_zone)] INTENT: [uppertext(user.a_intent)]")
	else
		user << "[target] has no organic [parse_zone(target_zone)] there!"
	return 1

/datum/surgery/chainsaw
	name = "chainsaw augmentation"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders,
	/datum/surgery_step/incise, /datum/surgery_step/chainsaw)
	species = list(/mob/living/carbon/human)
	possible_locs = list("r_arm", "l_arm")
	requires_organic_bodypart = 0

/datum/surgery_step/chainsaw
	time = 64
	name = "insert chainsaw"
	implements = list(/obj/item/weapon/twohanded/required/chainsaw = 100)

/datum/surgery_step/chainsaw/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins to install the chainsaw onto [target].", "You begin to install the chainsaw onto [target]...")

/datum/surgery_step/chainsaw/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(target.l_hand && target.r_hand)
		user << "You can't fit the chainsaw in while [target]'s hands are full!"
		return 0
	else
		user.visible_message("[user] finishes installing the chainsaw!", "You install the chainsaw.")
		user.unEquip(tool)
		qdel(tool)
		var/obj/item/weapon/mounted_chainsaw/sawarms = new(target)
		target.put_in_hands(sawarms)

		return 1

/datum/surgery/chainsaw_removal
	name = "chainsaw removal"
	steps = list(/datum/surgery_step/chainsaw_removal)
	species = list(/mob/living/carbon/human)
	possible_locs = list("r_arm", "l_arm")
	requires_organic_bodypart = 0

/datum/surgery/chainsaw_removal/can_start(mob/user, mob/living/carbon/target)
	var/list/hands = get_both_hands(target)
	var/M = locate(/obj/item/weapon/mounted_chainsaw) in hands
	if(M)
		return 1//can continue surgery
	else
		return 0//surgery will never be available

/datum/surgery_step/chainsaw_removal
	time = 128
	name = "saw off chainsaw"
	implements = list(/obj/item/weapon/circular_saw = 100, /obj/item/weapon/melee/energy/sword/cyborg/saw = 100, /obj/item/weapon/melee/arm_blade = 75, /obj/item/weapon/mounted_chainsaw = 65, /obj/item/weapon/twohanded/fireaxe = 50, /obj/item/weapon/twohanded/required/chainsaw = 50, /obj/item/weapon/hatchet = 35, /obj/item/weapon/kitchen/knife/butcher = 25)

/datum/surgery_step/chainsaw_removal/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] begins sawing the chainsaw off of [target]'s arms.", "You begin removing [target]'s chainsaw...")

/datum/surgery_step/chainsaw_removal/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	var/list/hands = get_both_hands(target)
	for(var/obj/item/weapon/mounted_chainsaw/V in hands)
		qdel(V)
		new /obj/item/weapon/twohanded/required/chainsaw(get_turf(target))
		user.visible_message("[user] carefully saws [target]'s arm free of the chainsaw.", "You remove the chainsaw.")
		return 1


code:
/datum/surgery/lipoplasty
	name = "lipoplasty"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/cut_fat, /datum/surgery_step/remove_fat, /datum/surgery_step/close)
	possible_locs = list("chest")

/datum/surgery/lipoplasty/can_start(mob/user, mob/living/carbon/target)
	if(target.disabilities & FAT)
		return 1
	return 0

//cut fat
/datum/surgery_step/cut_fat
	name = "cut excess fat"
	implements = list(/obj/item/weapon/circular_saw = 100, /obj/item/weapon/melee/energy/sword/cyborg/saw = 100, /obj/item/weapon/hatchet = 35, /obj/item/weapon/kitchen/knife/butcher = 25)
	time = 64

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

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

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

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

/datum/surgery_step/remove_fat/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	user.visible_message("[user] extracts [target]'s fat!", "You extract [target]'s fat.")
	target.overeatduration = 0 //patient is unfatted
	var/removednutriment = target.nutrition
	target.nutrition = NUTRITION_LEVEL_WELL_FED
	removednutriment -= 450 //whatever was removed goes into the meat
	var/mob/living/carbon/human/H = target
	var/typeofmeat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human

	if(H.dna && H.dna.species)
		typeofmeat = H.dna.species.meat

	var/obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/newmeat = new typeofmeat
	newmeat.name = "fatty meat"
	newmeat.desc = "Extremely fatty tissue taken from a patient."
	newmeat.subjectname = H.real_name
	newmeat.subjectjob = H.job
	newmeat.reagents.add_reagent ("nutriment", (removednutriment / 15)) //To balance with nutriment_factor of nutriment
	newmeat.loc = target.loc
	return 1


code:
/datum/surgery/organ_manipulation
	name = "organ manipulation"
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders,
	/datum/surgery_step/incise, /datum/surgery_step/manipulate_organs)
	species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
	possible_locs = list("chest", "head")
	requires_organic_bodypart = 0

/datum/surgery/organ_manipulation/soft
	possible_locs = list("groin", "eyes", "mouth", "l_arm", "r_arm")
	steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/clamp_bleeders,
	/datum/surgery_step/incise, /datum/surgery_step/manipulate_organs)

/datum/surgery/organ_manipulation/alien
	name = "alien organ manipulation"
	possible_locs = list("chest", "head", "groin", "eyes", "mouth", "l_arm", "r_arm")
	species = list(/mob/living/carbon/alien/humanoid)
	steps = list(/datum/surgery_step/saw, /datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/manipulate_organs)

/datum/surgery_step/manipulate_organs
	time = 64
	name = "manipulate organs"
	implements = list(/obj/item/organ/internal = 100, /obj/item/weapon/reagent_containers/food/snacks/organ = 0)
	var/implements_extract = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/crowbar = 55)
	var/implements_mend = list(/obj/item/weapon/cautery = 100, /obj/item/weapon/weldingtool = 70, /obj/item/weapon/lighter = 45, /obj/item/weapon/match = 20)
	var/current_type
	var/obj/item/organ/internal/I = null

/datum/surgery_step/manipulate_organs/New()
	..()
	implements = implements + implements_extract + implements_mend

/datum/surgery_step/manipulate_organs/tool_check(mob/user, obj/item/tool)
	if(istype(tool, /obj/item/weapon/weldingtool))
		var/obj/item/weapon/weldingtool/WT = tool
		if(!WT.isOn())
			return 0

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

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

	return 1

/datum/surgery_step/manipulate_organs/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	I = null
	if(isorgan(tool))
		current_type = "insert"
		I = tool
		if(target_zone != I.zone || target.getorganslot(I.slot))
			user << "There is no room for [I] in [target]'s [parse_zone(target_zone)]!"
			return -1

		user.visible_message("[user] begins to insert [tool] into [target]'s [parse_zone(target_zone)].",
			"You begin to insert [tool] into [target]'s [parse_zone(target_zone)]...")

	else if(implement_type in implements_extract)
		current_type = "extract"
		var/list/organs = target.getorganszone(target_zone)
		if(!organs.len)
			user << "There is no removeable organs in [target]'s [parse_zone(target_zone)]!"
			return -1
		else
			for(var/obj/item/organ/internal/O in organs)
				O.on_find(user)
				organs -= O
				organs[O.name] = O

			I = input("Remove which organ?", "Surgery", null, null) as null|anything in organs
			if(I && user && target && user.Adjacent(target) && user.get_active_hand() == tool)
				I = organs[I]
				if(!I) return -1
				user.visible_message("[user] begins to extract [I] from [target]'s [parse_zone(target_zone)].",
					"You begin to extract [I] from [target]'s [parse_zone(target_zone)]...")
			else
				return -1

	else if(implement_type in implements_mend)
		current_type = "mend"
		user.visible_message("[user] begins to mend the incision in [target]'s [parse_zone(target_zone)].",
			"You begin to mend the incision in [target]'s [parse_zone(target_zone)]...")

	else if(istype(tool, /obj/item/weapon/reagent_containers/food/snacks/organ))
		user << "[tool] was biten by someone! It's too damaged to use!"
		return -1

/datum/surgery_step/manipulate_organs/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
	if(current_type == "mend")
		user.visible_message("[user] mends the incision in [target]'s [parse_zone(target_zone)].",
			"You mend the incision in [target]'s [parse_zone(target_zone)].")
		return 1
	else if(current_type == "insert")
		I = tool
		user.drop_item()
		I.Insert(target)
		user.visible_message("[user] inserts [tool] into [target]'s [parse_zone(target_zone)]!",
			"You insert [tool] into [target]'s [parse_zone(target_zone)].")

	else if(current_type == "extract")
		if(I && I.owner == target)
			user.visible_message("[user] successfully extracts [I] from [target]'s [parse_zone(target_zone)]!",
				"You successfully extract [I] from [target]'s [parse_zone(target_zone)].")
			add_logs(user, target, "surgically removed [I.name] from", addition="INTENT: [uppertext(user.a_intent)]")
			I.Remove(target)
			I.loc = get_turf(target)
		else
			user.visible_message("[user] can't seem to extract anything from [target]'s [parse_zone(target_zone)]!",
				"You can't extract anything from [target]'s [parse_zone(target_zone)]!")
	return 0


code:
/obj/item/organ/internal/cyberimp/arm
	name = "arm-mounted implant"
	desc = "You shouldn't see this! Adminhelp and report this as an issue on github!"
	zone = "r_arm"
	slot = "r_arm_device"
	icon_state = "implant-toolkit"
	w_class = 3
	actions_types = list(/datum/action/item_action/organ_action/toggle)

	var/list/items_list = list()
	// Used to store a list of all items inside, for multi-item implants.
	// I would use contents, but they shuffle on every activation/deactivation leading to interface inconsistencies.

	var/obj/item/holder = null
	// You can use this var for item path, it would be converted into an item on New()

/obj/item/organ/internal/cyberimp/arm/New()
	..()
	if(ispath(holder))
		holder = new holder(src)

	update_icon()
	slot = zone + "_device"
	items_list = contents.Copy()

/obj/item/organ/internal/cyberimp/arm/update_icon()
	if(zone == "r_arm")
		transform = null
	else // Mirroring the icon
		transform = matrix(-1, 0, 0, 0, 1, 0)

/obj/item/organ/internal/cyberimp/arm/examine(mob/user)
	..()
	user << "[src] is assembled in the [zone == "r_arm" ? "right" : "left"] arm configuration. You can use a screwdriver to reassemble it."

/obj/item/organ/internal/cyberimp/arm/attackby(obj/item/weapon/W, mob/user, params)
	..()
	if(istype(W, /obj/item/weapon/screwdriver))
		if(zone == "r_arm")
			zone = "l_arm"
		else
			zone = "r_arm"
		slot = zone + "_device"
		user << "You modify [src] to be installed on the [zone == "r_arm" ? "right" : "left"] arm."
		update_icon()
	else if(istype(W, /obj/item/weapon/card/emag))
		emag_act()

/obj/item/organ/internal/cyberimp/arm/Remove(mob/living/carbon/M, special = 0)
	Retract()
	..()

/obj/item/organ/internal/cyberimp/arm/emag_act()
	return 0

/obj/item/organ/internal/cyberimp/arm/gun/emp_act(severity)
	if(prob(15/severity))
		owner << "[src] is hit by EMP!"
		// give the owner an idea about why his implant is glitching
		Retract()
	..()

/obj/item/organ/internal/cyberimp/arm/proc/Retract()
	if(!holder || (holder in src))
		return

	owner.visible_message("[owner] retracts [holder] back into \his [zone == "r_arm" ? "right" : "left"] arm.",
		"[holder] snaps back into your [zone == "r_arm" ? "right" : "left"] arm.",
		"You hear a short mechanical noise.")

	owner.unEquip(holder, 1)
	holder.loc = src
	holder = null
	playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1)

/obj/item/organ/internal/cyberimp/arm/proc/Extend(var/obj/item/item)
	if(!(item in src))
		return

	holder = item

	holder.flags |= NODROP
	holder.unacidable = 1
	holder.slot_flags = null
	holder.w_class = 5
	holder.materials = null

	var/arm_slot = (zone == "r_arm" ? slot_r_hand : slot_l_hand)
	var/obj/item/arm_item = owner.get_item_by_slot(arm_slot)

	if(arm_item)
		if(!owner.unEquip(arm_item))
			owner << "Your [arm_item] interferes with [src]!"
			return
		else
			owner << "You drop [arm_item] to activate [src]!"

	if(zone == "r_arm" ? !owner.put_in_r_hand(holder) : !owner.put_in_l_hand(holder))
		owner << "Your [src] fails to activate!"
		return

	// Activate the hand that now holds our item.
	if(zone == "r_arm" ? owner.hand : !owner.hand)
		owner.swap_hand()

	owner.visible_message("[owner] extends [holder] from \his [zone == "r_arm" ? "right" : "left"] arm.",
		"You extend [holder] from your [zone == "r_arm" ? "right" : "left"] arm.",
		"You hear a short mechanical noise.")
	playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1)

/obj/item/organ/internal/cyberimp/arm/ui_action_click()
	if(crit_fail || (!holder && !contents.len))
		owner << "The implant doesn't respond. It seems to be broken..."
		return

	// You can emag the arm-mounted implant by activating it while holding emag in it's hand.
	var/arm_slot = (zone == "r_arm" ? slot_r_hand : slot_l_hand)
	if(istype(owner.get_item_by_slot(arm_slot), /obj/item/weapon/card/emag) && emag_act())
		return

	if(!holder || (holder in src))
		holder = null
		if(contents.len == 1)
			Extend(contents[1])
		else // TODO: make it similar to borg's storage-like module selection
			var/obj/item/choise = input("Activate which item?", "Arm Implant", null, null) as null|anything in items_list
			if(owner && owner == usr && owner.stat != DEAD && (src in owner.internal_organs) && !holder && istype(choise) && (choise in contents))
				// This monster sanity check is a nice example of how bad input() is.
				Extend(choise)
	else
		Retract()

/obj/item/organ/internal/cyberimp/arm/gun/emp_act(severity)
	if(prob(30/severity) && owner && !crit_fail)
		Retract()
		owner.visible_message("A loud bang comes from [owner]\'s [zone == "r_arm" ? "right" : "left"] arm!")
		playsound(get_turf(owner), 'sound/weapons/flashbang.ogg', 100, 1)
		owner << "You feel an explosion erupt inside your [zone == "r_arm" ? "right" : "left"] arm as your implant breaks!"
		owner.adjust_fire_stacks(20)
		owner.IgniteMob()
		owner.adjustFireLoss(25)
		crit_fail = 1
	else // The gun will still discharge anyway.
		..()

/obj/item/organ/internal/cyberimp/arm/gun/laser
	name = "arm-mounted laser implant"
	desc = "A variant of the arm cannon implant that fires lethal laser beams. The cannon emerges from the subject's arm and remains inside when not in use."
	icon_state = "arm_laser"
	origin_tech = "materials=5;combat=5;biotech=4;powerstorage=4;syndicate=5"//this is kinda nutty and i might lower it
	holder = /obj/item/weapon/gun/energy/laser/mounted

/obj/item/organ/internal/cyberimp/arm/gun/laser/l/zone = "l_arm"

/obj/item/organ/internal/cyberimp/arm/gun/taser
	name = "arm-mounted taser implant"
	desc = "A variant of the arm cannon implant that fires electrodes and disabler shots. The cannon emerges from the subject's arm and remains inside when not in use."
	icon_state = "arm_taser"
	origin_tech = "materials=5;combat=5;biotech=4;powerstorage=4"
	holder = /obj/item/weapon/gun/energy/gun/advtaser/mounted

/obj/item/organ/internal/cyberimp/arm/gun/taser/l/zone = "l_arm"

/obj/item/organ/internal/cyberimp/arm/toolset
	name = "integrated toolset implant"
	desc = "A stripped-down version of engineering cyborg toolset, designed to be installed on subject's arm. Contains all neccessary tools."
	origin_tech = "materials=5;engineering=5;biotech=4;powerstorage=3"
	contents = newlist(/obj/item/weapon/screwdriver/cyborg, /obj/item/weapon/wrench/cyborg, /obj/item/weapon/weldingtool/largetank/cyborg,
		/obj/item/weapon/crowbar/cyborg, /obj/item/weapon/wirecutters/cyborg, /obj/item/device/multitool/cyborg)

/obj/item/organ/internal/cyberimp/arm/toolset/l/zone = "l_arm"

/obj/item/organ/internal/cyberimp/arm/toolset/emag_act()
	if(!(locate(/obj/item/weapon/kitchen/knife/combat/cyborg) in items_list))
		usr << "You unlock [src]'s integrated knife!"
		items_list += new /obj/item/weapon/kitchen/knife/combat/cyborg(src)
		return 1
	return 0


code:
/obj/item/organ/internal/cyberimp/chest
	name = "cybernetic torso implant"
	desc = "implants for the organs in your torso"
	icon_state = "chest_implant"
	implant_overlay = "chest_implant_overlay"
	zone = "chest"

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

/obj/item/organ/internal/cyberimp/chest/nutriment/on_life()
	if(synthesizing)
		return

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

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

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

/obj/item/organ/internal/cyberimp/chest/reviver
	name = "Reviver implant"
	desc = "This implant will attempt to revive you if you lose consciousness. For the faint of heart!"
	icon_state = "chest_implant"
	implant_color = "#AD0000"
	origin_tech = "materials=6;programming=3;biotech=6;syndicate=4"
	slot = "heartdrive"
	var/revive_cost = 0
	var/reviving = 0
	var/cooldown = 0

/obj/item/organ/internal/cyberimp/chest/reviver/on_life()
	if(reviving)
		if(owner.stat == UNCONSCIOUS)
			spawn(30)
				if(prob(90) && owner.getOxyLoss())
					owner.adjustOxyLoss(-3)
					revive_cost += 5
				if(prob(75) && owner.getBruteLoss())
					owner.adjustBruteLoss(-1)
					revive_cost += 20
				if(prob(75) && owner.getFireLoss())
					owner.adjustFireLoss(-1)
					revive_cost += 20
				if(prob(40) && owner.getToxLoss())
					owner.adjustToxLoss(-1)
					revive_cost += 50
		else
			cooldown = revive_cost + world.time
			reviving = 0
		return

	if(cooldown > world.time)
		return
	if(owner.stat != UNCONSCIOUS)
		return
	if(owner.suiciding)
		return

	revive_cost = 0
	reviving = 1

/obj/item/organ/internal/cyberimp/chest/reviver/emp_act(severity)
	if(!owner)
		return

	if(reviving)
		revive_cost += 200
	else
		cooldown += 200

	if(istype(owner, /mob/living/carbon/human))
		var/mob/living/carbon/human/H = owner
		if(H.stat != DEAD && prob(50 / severity))
			H.heart_attack = 1
			spawn(600 / severity)
				H.heart_attack = 0
				if(H.stat == CONSCIOUS)
					H << "You feel your heart beating again!"

/obj/item/organ/internal/cyberimp/chest/thrusters
	name = "implantable thrusters set"
	desc = "An implantable set of thruster ports. They use the gas from environment or subject's internals for propulsion in zero-gravity areas. \
	Unlike regular jetpack, this device has no stablilzation system."
	slot = "thrusters"
	icon_state = "imp_jetpack"
	origin_tech = "materials=6;programming=4;magnets=3;biotech=4;engineering=4"
	implant_overlay = null
	implant_color = null
	actions_types = list(/datum/action/item_action/organ_action/toggle)
	w_class = 3
	var/on = 0
	var/datum/effect_system/trail_follow/ion/ion_trail

/obj/item/organ/internal/cyberimp/chest/thrusters/Insert(mob/living/carbon/M, special = 0)
	..()
	if(!ion_trail)
		ion_trail = new
	ion_trail.set_up(M)

/obj/item/organ/internal/cyberimp/chest/thrusters/Remove(mob/living/carbon/M, special = 0)
	if(on)
		toggle(silent=1)
	..()

/obj/item/organ/internal/cyberimp/chest/thrusters/ui_action_click()
	toggle()

/obj/item/organ/internal/cyberimp/chest/thrusters/proc/toggle(silent=0)
	if(!on)
		if(crit_fail)
			if(!silent)
				owner << "Your thrusters set seems to be broken!"
			return 0
		on = 1
		if(allow_thrust(0.01))
			ion_trail.start()
			if(!silent)
				owner << "You turn your thrusters set on."
	else
		ion_trail.stop()
		if(!silent)
			owner << "You turn your thrusters set off."
		on = 0
	update_icon()

/obj/item/organ/internal/cyberimp/chest/thrusters/update_icon()
	if(on)
		icon_state = "imp_jetpack-on"
	else
		icon_state = "imp_jetpack"
	for(var/X in actions)
		var/datum/action/A = X
		A.UpdateButtonIcon()

/obj/item/organ/internal/cyberimp/chest/thrusters/proc/allow_thrust(num)
	if(!on || !owner)
		return 0

	var/turf/T = get_turf(owner)
	if(!T) // No more runtimes from being stuck in nullspace.
		return 0

	// Priority 1: use air from environment.
	var/datum/gas_mixture/environment = T.return_air()
	if(environment && environment.return_pressure() > 30)
		return 1

	// Priority 2: use plasma from internal plasma storage.
	// (just in case someone would ever use this implant system to make cyber-alien ops with jetpacks and taser arms)
	if(owner.getPlasma() >= num*100)
		owner.adjustPlasma(-num*100)
		return 1

	// Priority 3: use internals tank.
	var/obj/item/weapon/tank/I = owner.internal
	if(I && I.air_contents && I.air_contents.total_moles() > num)
		var/datum/gas_mixture/removed = I.air_contents.remove(num)
		if(removed.total_moles() > 0.005)
			T.assume_air(removed)
			return 1
		else
			T.assume_air(removed)

	toggle(silent=1)
	return 0


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

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

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

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

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

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

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

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


code:
/obj/item/organ/internal/cyberimp/eyes
	name = "cybernetic eyes"
	desc = "artificial photoreceptors with specialized functionality"
	icon_state = "eye_implant"
	implant_overlay = "eye_implant_overlay"
	slot = "eye_sight"
	zone = "eyes"
	w_class = 1

	var/sight_flags = 0
	var/dark_view = 0
	var/eye_color = "fff"
	var/old_eye_color = "fff"
	var/flash_protect = 0
	var/see_invisible = 0
	var/aug_message = "Your vision is augmented!"

/obj/item/organ/internal/cyberimp/eyes/Insert(var/mob/living/carbon/M, var/special = 0)
	..()
	if(istype(owner, /mob/living/carbon/human) && eye_color)
		var/mob/living/carbon/human/HMN = owner
		old_eye_color = HMN.eye_color
		HMN.eye_color = eye_color
		HMN.regenerate_icons()
	if(aug_message && !special)
		owner << "[aug_message]"

	owner.update_sight()

/obj/item/organ/internal/cyberimp/eyes/Remove(var/mob/living/carbon/M, var/special = 0)
	M.sight ^= sight_flags
	if(istype(M,/mob/living/carbon/human) && eye_color)
		var/mob/living/carbon/human/HMN = owner
		HMN.eye_color = old_eye_color
		HMN.regenerate_icons()
	..()

/obj/item/organ/internal/cyberimp/eyes/emp_act(severity)
	if(!owner)
		return
	if(severity > 1)
		if(prob(10 * severity))
			return
	owner << "Static obfuscates your vision!"
	owner.flash_eyes(visual = 1)

/obj/item/organ/internal/cyberimp/eyes/xray
	name = "X-ray implant"
	desc = "These cybernetic eye implants will give you X-ray vision. Blinking is futile."
	eye_color = "000"
	implant_color = "#000000"
	origin_tech = "materials=6;programming=4;biotech=6;magnets=5"
	dark_view = 8
	sight_flags = SEE_MOBS | SEE_OBJS | SEE_TURFS

/obj/item/organ/internal/cyberimp/eyes/thermals
	name = "Thermals implant"
	desc = "These cybernetic eye implants will give you Thermal vision. Vertical slit pupil included."
	eye_color = "FC0"
	implant_color = "#FFCC00"
	origin_tech = "materials=6;programming=4;biotech=5;magnets=5;syndicate=4"
	sight_flags = SEE_MOBS
	see_invisible = SEE_INVISIBLE_MINIMUM
	flash_protect = -1
	dark_view = 8
	aug_message = "You see prey everywhere you look..."

// HUD implants
/obj/item/organ/internal/cyberimp/eyes/hud
	name = "HUD implant"
	desc = "These cybernetic eyes will display a HUD over everything you see. Maybe."
	slot = "eye_hud"
	var/HUD_type = 0

/obj/item/organ/internal/cyberimp/eyes/hud/Insert(var/mob/living/carbon/M, var/special = 0)
	..()
	if(HUD_type)
		var/datum/atom_hud/H = huds[HUD_type]
		H.add_hud_to(M)
		M.permanent_huds |= H

/obj/item/organ/internal/cyberimp/eyes/hud/Remove(var/mob/living/carbon/M, var/special = 0)
	if(HUD_type)
		var/datum/atom_hud/H = huds[HUD_type]
		M.permanent_huds ^= H
		H.remove_hud_from(M)
	..()

/obj/item/organ/internal/cyberimp/eyes/hud/medical
	name = "Medical HUD implant"
	desc = "These cybernetic eye implants will display a medical HUD over everything you see."
	eye_color = "0ff"
	implant_color = "#00FFFF"
	origin_tech = "materials=4;programming=3;biotech=4"
	aug_message = "You suddenly see health bars floating above people's heads..."
	HUD_type = DATA_HUD_MEDICAL_ADVANCED

/obj/item/organ/internal/cyberimp/eyes/hud/security
	name = "Security HUD implant"
	desc = "These cybernetic eye implants will display a security HUD over everything you see."
	eye_color = "d00"
	implant_color = "#CC0000"
	origin_tech = "materials=4;programming=4;biotech=3;combat=1"
	aug_message = "Job indicator icons pop up in your vision. That is not a certified surgeon..."
	HUD_type = DATA_HUD_SECURITY_ADVANCED

// Welding shield implant
/obj/item/organ/internal/cyberimp/eyes/shield
	name = "welding shield implant"
	desc = "These reactive micro-shields will protect you from welders and flashes without obscuring your vision."
	slot = "eye_shield"
	origin_tech = "materials=4;biotech=3"
	implant_color = "#101010"
	flash_protect = 2
	aug_message = null
	eye_color = null

/obj/item/organ/internal/cyberimp/eyes/shield/emp_act(severity)
	return


code:
#define STUN_SET_AMOUNT	2

/obj/item/organ/internal/cyberimp
	name = "cybernetic implant"
	desc = "a state-of-the-art implant that improves a baseline's functionality"
	status = ORGAN_ROBOTIC
	var/implant_color = "#FFFFFF"
	var/implant_overlay

/obj/item/organ/internal/cyberimp/New(var/mob/M = null)
	if(iscarbon(M))
		src.Insert(M)
	if(implant_overlay)
		var/image/overlay = new /image(icon, implant_overlay)
		overlay.color = implant_color
		overlays |= overlay
	return ..()

//[[[[BRAIN]]]]

/obj/item/organ/internal/cyberimp/brain
	name = "cybernetic brain implant"
	desc = "injectors of extra sub-routines for the brain"
	icon_state = "brain_implant"
	implant_overlay = "brain_implant_overlay"
	zone = "head"
	w_class = 1

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

/obj/item/organ/internal/cyberimp/brain/anti_drop
	name = "anti-drop implant"
	desc = "This cybernetic brain implant will allow you to force your hand muscles to contract, preventing item dropping. Twitch ear to toggle."
	var/active = 0
	var/l_hand_ignore = 0
	var/r_hand_ignore = 0
	var/obj/item/l_hand_obj = null
	var/obj/item/r_hand_obj = null
	implant_color = "#DE7E00"
	slot = "brain_antidrop"
	origin_tech = "materials=5;programming=4;biotech=4"
	actions_types = list(/datum/action/item_action/organ_action/toggle)

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

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

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

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

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

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

/obj/item/organ/internal/cyberimp/brain/anti_drop/Remove(var/mob/living/carbon/M, special = 0)
	if(active)
		ui_action_click()
	..()

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

/obj/item/organ/internal/cyberimp/brain/anti_stun/on_life()
	..()
	if(crit_fail)
		return

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

/obj/item/organ/internal/cyberimp/brain/anti_stun/emp_act(severity)
	if(crit_fail)
		return
	crit_fail = 1
	spawn(90 / severity)
		crit_fail = 0

//[[[[MOUTH]]]]
/obj/item/organ/internal/cyberimp/mouth
	zone = "mouth"

/obj/item/organ/internal/cyberimp/mouth/breathing_tube
	name = "breathing tube implant"
	desc = "This simple implant adds an internals connector to your back, allowing you to use internals without a mask and protecting you from being choked."
	icon_state = "implant_mask"
	slot = "breathing_tube"
	w_class = 1
	origin_tech = "materials=2;biotech=3"

/obj/item/organ/internal/cyberimp/mouth/breathing_tube/emp_act(severity)
	if(prob(60/severity))
		owner << "Your breathing tube suddenly closes!"
		owner.losebreath += 2

//BOX O' IMPLANTS

/obj/item/weapon/storage/box/cyber_implants
	name = "boxed cybernetic implant"
	desc = "A sleek, sturdy box."
	icon_state = "cyber_implants"

/obj/item/weapon/storage/box/cyber_implants/New(loc, implant)
	..()
	new /obj/item/device/autoimplanter(src)
	if(ispath(implant))
		new implant(src)

/obj/item/weapon/storage/box/cyber_implants/bundle
	name = "boxed cybernetic implants"
	var/list/boxed = list(/obj/item/organ/internal/cyberimp/eyes/xray,/obj/item/organ/internal/cyberimp/eyes/thermals,
						/obj/item/organ/internal/cyberimp/brain/anti_stun, /obj/item/organ/internal/cyberimp/chest/reviver)
	var/amount = 5

/obj/item/weapon/storage/box/cyber_implants/bundle/New()
	..()
	var/implant
	while(contents.len <= amount + 1) // +1 for the autoimplanter.
		implant = pick(boxed)
		new implant(src)


code:
/obj/item/device/autoimplanter
	name = "autoimplanter"
	desc = "A device that automatically injects a cyber-implant into the user without the hassle of extensive surgery. It has a slot to insert implants and a screwdriver slot for removing accidentally added implants."
	icon_state = "autoimplanter"
	item_state = "walkietalkie"//left as this so as to intentionally not have inhands
	w_class = 2
	var/obj/item/organ/internal/cyberimp/storedorgan

/obj/item/device/autoimplanter/attack_self(mob/user)//when the object it used...
	if(!storedorgan)
		user << "[src] currently has no implant stored."
		return
	storedorgan.Insert(user)//insert stored organ into the user
	user.visible_message("[user] presses a button on [src], and you hear a short mechanical noise.", "You feel a sharp sting as [src] plunges into your body.")
	playsound(get_turf(user), 'sound/weapons/circsawhit.ogg', 50, 1)
	storedorgan = null

/obj/item/device/autoimplanter/attackby(obj/item/I, mob/user, params)
	if(istype(I, /obj/item/organ/internal/cyberimp))
		if(storedorgan)
			user << "[src] already has an implant stored."
			return
		if(!user.drop_item())
			return
		I.loc = src
		storedorgan = I
		user << "You insert the [I] into [src]."
	else if(istype(I, /obj/item/weapon/screwdriver))
		if(!storedorgan)
			user << "There's no implant in [src] for you to remove."
		else
			var/turf/open/floorloc = get_turf(user)
			floorloc.contents += contents
			user << "You remove the [storedorgan] from [src]."
			playsound(get_turf(user), 'sound/items/Screwdriver.ogg', 50, 1)
			storedorgan = null


code:
mob/proc/getorgan(typepath)
	return

mob/proc/getorganszone(zone)
	return

mob/proc/getorganslot(slot)
	return

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

mob/living/carbon/getorganszone(zone, var/subzones = 0)
	var/list/returnorg = list()
	if(subzones)
		// Include subzones - groin for chest, eyes and mouth for head
		if(zone == "head")
			returnorg = getorganszone("eyes") + getorganszone("mouth")
		if(zone == "chest")
			returnorg = getorganszone("groin")

	for(var/obj/item/organ/internal/O in internal_organs)
		if(zone == O.zone)
			returnorg += O
	return returnorg

mob/living/carbon/getorganslot(slot)
	return internal_organs_slot[slot]

mob/proc/getlimb()
	return

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

proc/isorgan(atom/A)
	return istype(A, /obj/item/organ/internal)