code:
/datum/keybinding/carbon/select_help_intent
	hotkey_keys = list("1")
	name = "select_help_intent"
	full_name = "Select help intent"
	description = ""
	category = CATEGORY_CARBON
	keybind_signal = COMSIG_KB_CARBON_SELECTHELPINTENT_DOWN

/datum/keybinding/carbon/select_help_intent/down(client/user)
	. = ..()
	if(.)
		return
	var/mob/living/L = user.mob
	if(istype(L))
		L.a_intent_change(INTENT_HELP)
	return TRUE

/datum/keybinding/carbon/select_disarm_intent
	hotkey_keys = list("2")
	name = "select_disarm_intent"
	full_name = "Select disarm intent"
	description = ""
	category = CATEGORY_CARBON
	keybind_signal = COMSIG_KB_CARBON_SELECTDISARMINTENT_DOWN

/datum/keybinding/carbon/select_disarm_intent/down(client/user)
	. = ..()
	if(.)
		return
	var/mob/living/L = user.mob
	if(istype(L))
		L.a_intent_change(INTENT_DISARM)
	return TRUE

/datum/keybinding/carbon/select_grab_intent
	hotkey_keys = list("3")
	name = "select_grab_intent"
	full_name = "Select grab intent"
	description = ""
	category = CATEGORY_CARBON
	keybind_signal = COMSIG_KB_CARBON_SELECTGRABINTENT_DOWN

/datum/keybinding/carbon/select_grab_intent/down(client/user)
	. = ..()
	if(.)
		return
	var/mob/living/L = user.mob
	if(istype(L))
		L.a_intent_change(INTENT_GRAB)
	return TRUE

/datum/keybinding/carbon/select_harm_intent
	hotkey_keys = list("4")
	name = "select_harm_intent"
	full_name = "Select harm intent"
	description = ""
	category = CATEGORY_CARBON
	keybind_signal = COMSIG_KB_CARBON_SELECTHARMINTENT_DOWN

/datum/keybinding/carbon/select_harm_intent/down(client/user)
	. = ..()
	if(.)
		return
	var/mob/living/L = user.mob
	if(istype(L))
		L.a_intent_change(INTENT_HARM)
	return TRUE

/datum/keybinding/carbon/cycle_intent_right
	hotkey_keys = list("Northwest") // HOME
	name = "cycle_intent_right"
	full_name = "Cycle Intent Right"
	description = ""
	keybind_signal = COMSIG_KB_MOB_CYCLEINTENTRIGHT_DOWN

/datum/keybinding/carbon/cycle_intent_right/down(client/user)
	. = ..()
	if(.)
		return
	var/mob/living/L = user.mob
	if(istype(L))
		L.a_intent_change(INTENT_HOTKEY_RIGHT)
	return TRUE

/datum/keybinding/carbon/cycle_intent_left
	hotkey_keys = list("Insert")
	name = "cycle_intent_left"
	full_name = "Cycle Intent Left"
	description = ""
	keybind_signal = COMSIG_KB_MOB_CYCLEINTENTLEFT_DOWN

/datum/keybinding/carbon/cycle_intent_left/down(client/user)
	. = ..()
	if(.)
		return
	var/mob/living/L = user.mob
	if(istype(L))
		L.a_intent_change(INTENT_HOTKEY_LEFT)
	return TRUE

/datum/keybinding/carbon/fixeye
	hotkey_keys = list("F")
	name = "fixeye"
	full_name = "Fix Eye"
	description = "Fix the direction you're staring at."
	category = CATEGORY_MOVEMENT
	keybind_signal = COMSIG_KB_FIXEYE_DOWN

/datum/keybinding/carbon/fixeye/down(client/user)
	. = ..()
	var/mob/living/L = user.mob
	if(istype(L))
		SEND_SIGNAL(L, COMSIG_FIXEYE_TOGGLE)
	return TRUE

/datum/keybinding/carbon/toggle_throw_mode
	hotkey_keys = list("R")

/datum/keybinding/carbon/hold_throw_mode
	hotkey_keys = list("Unbound")

/datum/keybinding/carbon/sprint
	hotkey_keys = list("V")
	name = "sprint"
	full_name = "Sprint"
	description = "Toggle sprinting."
	category = CATEGORY_MOVEMENT
	keybind_signal = COMSIG_KB_CARBON_SPRINT_DOWN

/datum/keybinding/carbon/sprint/down(client/user)
	. = ..()
	var/mob/living/L = user.mob
	if(istype(L))
		L.toggle_sprint()
	return TRUE

/datum/keybinding/carbon/wield
	hotkey_keys = list("X")
	name = "wield"
	full_name = "Wield"
	description = "Wield/unwield active held item."
	category = CATEGORY_MOVEMENT
	keybind_signal = COMSIG_KB_CARBON_SPRINT_DOWN

/datum/keybinding/carbon/wield/down(client/user)
	. = ..()
	var/mob/living/L = user.mob
	if(istype(L))
		L.wield_active_hand()
	return TRUE


code:
/datum/keybinding/client/communication/say/down(client/user)
	. = ..()
	user.mob?.set_typing_indicator(TRUE)

/datum/keybinding/client/communication/me/down(client/user)
	. = ..()
	user.mob?.set_typing_indicator(TRUE)

/datum/keybinding/client/communication/whisper
	hotkey_keys = list("Y")
	name = "Whisper"
	full_name = "IC Whisper"
	keybind_signal = COMSIG_KB_CLIENT_WHISPER_DOWN

/datum/keybinding/client/communication/whisper/down(client/user)
	. = ..()
	user.mob?.set_typing_indicator(TRUE)

repo_name: AnalWerewolf/sundown

license: mit


code:
/datum/keybinding/living/rest
	hotkey_keys = list("H")


code:
/datum/keybinding/mob/stop_pulling
	hotkey_keys = list("N", "Delete")

/datum/keybinding/mob/swap_hands
	hotkey_keys = list("Space")

/datum/keybinding/mob/target_left_arm
	full_name = "Target: Left Arm"

/datum/keybinding/mob/target_r_arm
	full_name = "Target: Right Arm"


code:
/datum/map_config
	var/map_lore = "You are in a planet, named Nevado, in the far reaches of the Andromeda galaxy, in the outpost of \
		Baluarte. Humanity is a million years past it's prime, only having survived due to a cryogenic accident. You must \
		help rekindle the fires of humanity, or die trying."
	var/command_name = "Baluarte Outpost"

/datum/map_config/LoadConfig(filename, error_if_missing)
	. = ..()
	if(!.)
		return
	var/json = file(filename)
	if(!json)
		log_world("Could not open map_config: [filename]")
		return

	json = file2text(json)
	if(!json)
		log_world("map_config is not text: [filename]")
		return

	json = json_decode(json)
	if(!json)
		log_world("map_config is not json: [filename]")
		return

	if("map_lore" in json)
		map_lore = json["map_lore"]

	if("command_name" in json)
		command_name = json["command_name"]
		change_command_name(command_name)


code:
/datum/biome/plains/nevado_surface
	turf_type = /turf/open/floor/plating/asteroid/snow/nevado_surface
	flora_types = list(/obj/structure/flora/grass,
				/obj/structure/flora/tree/pine,
				/obj/structure/flora/stump,
				/obj/structure/flora/rock,
				/obj/structure/flora/rock/pile)
	flora_density = 10

/datum/biome/jungle/nevado_surface
	turf_type = /turf/open/floor/plating/asteroid/snow/nevado_surface
	flora_types = list(/obj/structure/flora/grass,
				/obj/structure/flora/bush,
				/obj/structure/flora/tree/pine,
				/obj/structure/flora/rock)
	flora_density = 35

/datum/biome/jungle/deep/nevado_surface
	turf_type = /turf/open/floor/plating/asteroid/snow/nevado_surface
	flora_types = list(/obj/structure/flora/grass,
				/obj/structure/flora/bush,
				/obj/structure/flora/tree/pine,
				/obj/structure/flora/rock)
	flora_density = 50

/datum/biome/water/nevado_surface
	turf_type = /turf/open/floor/plating/asteroid/snow/river/nevado_surface

/datum/biome/mountain/nevado_surface
	turf_type = /turf/closed/mineral/snowmountain/nevado_surface


code:
/datum/map_generator/cave_generator/nevado
	open_turf_types = list(/turf/open/floor/plating/asteroid/nevado_caves = 1)
	closed_turf_types =  list(/turf/closed/mineral/random/nevado_caves = 1)
	flora_spawn_list = list(/obj/structure/flora/ash/leaf_shroom = 2 , /obj/structure/flora/ash/cap_shroom = 2 , /obj/structure/flora/ash/stem_shroom = 2 , /obj/structure/flora/ash/cacti = 1, /obj/structure/flora/ash/tall_shroom = 2, /obj/structure/flora/ash/seraka = 2)
	feature_spawn_list = list(/obj/structure/geyser/wittel = 6, /obj/structure/geyser/random = 2, /obj/structure/geyser/plasma_oxide = 10, /obj/structure/geyser/protozine = 10, /obj/structure/geyser/hollowwater = 10)

	initial_closed_chance = 30
	smoothing_iterations = 50
	birth_limit = 4
	death_limit = 3


code:
/datum/map_generator/nevado_surface_generator
	///2D list of all biomes based on heat and humidity combos.
	var/list/possible_biomes = list(
		BIOME_LOW_HUMIDITY = /datum/biome/plains/nevado_surface,
		BIOME_LOWMEDIUM_HUMIDITY = /datum/biome/plains/nevado_surface,
		BIOME_HIGHMEDIUM_HUMIDITY = /datum/biome/jungle/deep/nevado_surface,
		BIOME_HIGH_HUMIDITY = /datum/biome/water/nevado_surface,
	)
	///Used to select "zoom" level into the perlin noise, higher numbers result in slower transitions
	var/perlin_zoom = 50

///Seeds the rust-g perlin noise with a random number.
/datum/map_generator/nevado_surface_generator/generate_terrain(list/turfs)
	. = ..()
	var/height_seed = rand(0, 50000)
	var/humidity_seed = rand(0, 50000)

	for(var/t in turfs) //Go through all the turfs and generate them
		var/turf/gen_turf = t
		var/drift_x = (gen_turf.x + rand(-BIOME_RANDOM_SQUARE_DRIFT, BIOME_RANDOM_SQUARE_DRIFT)) / perlin_zoom
		var/drift_y = (gen_turf.y + rand(-BIOME_RANDOM_SQUARE_DRIFT, BIOME_RANDOM_SQUARE_DRIFT)) / perlin_zoom

		var/height = text2num(rustg_noise_get_at_coordinates("[height_seed]", "[drift_x]", "[drift_y]"))

		var/datum/biome/selected_biome
		if(height <= 0.75) //If height is less than 0.75, we generate biomes based on the humidity of the area.
			var/humidity = text2num(rustg_noise_get_at_coordinates("[humidity_seed]", "[drift_x]", "[drift_y]"))
			var/humidity_level  //Type of humidity zone we're in LOW-MEDIUM-HIGH
			switch(humidity)
				if(0 to 0.25)
					humidity_level = BIOME_LOW_HUMIDITY
				if(0.25 to 0.5)
					humidity_level = BIOME_LOWMEDIUM_HUMIDITY
				if(0.5 to 0.75)
					humidity_level = BIOME_HIGHMEDIUM_HUMIDITY
				if(0.75 to 1)
					humidity_level = BIOME_HIGH_HUMIDITY
			selected_biome = possible_biomes[humidity_level]
		else //Over 0.75; It's a mountain
			selected_biome = /datum/biome/mountain
		selected_biome = SSmapping.biomes[selected_biome] //Get the instance of this biome from SSmapping
		selected_biome.generate_turf(gen_turf)
		CHECK_TICK


code:
/datum/mind
	/// Music when combat mode is on
	var/combat_music = 'modular_septic/sound/music/combat/ritual.ogg'


code:
/datum/mood_event/fraggot
	description = span_flashingdanger("I must kill the fraggot!")
	mood_change = -5
	timeout = 0

/datum/mood_event/fraggot/add_effects(mob/living/fraggot)
	description = span_flashingdanger("I must kill [fraggot.real_name]!")


code:
//Turned into a brain
/datum/mood_event/freakofnature
	description = span_warning("Where's is my body?! What did they do to me?!!")
	mood_change = -15
	timeout = 12 MINUTES

//Revived after suicide
/datum/mood_event/letmedie
	description = span_warning("I don't want to live again...")
	mood_change = -12
	timeout = 12 MINUTES

//Got cloned recently
/datum/mood_event/clooned
	description = span_boldwarning("Awake... but at what cost?")
	mood_change = -8
	timeout = 15 MINUTES

//Cringe filter
/datum/mood_event/cringe
	description = span_boldwarning("I tried to say something stupid.")
	mood_change = -4
	timeout = 5 MINUTES

/datum/mood_event/ultracringe
	description = span_boldwarning("I am fucking retarded!")
	mood_change = -8
	timeout = 15 MINUTES

//Pain mood
/datum/mood_event/painbad
	description = span_danger("I am feeling so much pain!")
	mood_change = -5
	timeout = 3 MINUTES

//Saw a badly injured crewmember
/datum/mood_event/saw_injured
	description = span_danger("I have seen terrible things!")
	mood_change = -3
	timeout = 5 MINUTES

/datum/mood_event/saw_injured/lesser
	mood_change = -1
	timeout = 5 MINUTES

//Saw a crewmember die
/datum/mood_event/saw_dead
	description = span_dead("I have seen someone die!")
	mood_change = -5
	timeout = 10 MINUTES

/datum/mood_event/saw_dead/lesser
	mood_change = -2
	timeout = 5 MINUTES

//Died
/datum/mood_event/died
	description = span_dead("<b>I saw the afterlife, and i don't like it!</b>")
	mood_change = -6
	timeout = 10 MINUTES

//Bad smell
/datum/mood_event/miasma
	description = span_warning("I smell something putrid!")
	mood_change = -3
	timeout = 2 MINUTES

/datum/mood_event/miasma/harsh
	description = span_danger("The rotting stench, it's unbearable!")
	mood_change = -6


code:
//Buried/cremated someone
/datum/mood_event/proper_burial
	description = span_nicegreen("Not everyone can be saved. At least they have been put to rest.")
	mood_change = 2
	timeout = 15 MINUTES

//Masochist mood
/datum/mood_event/paingood
	description = span_nicegreen("Pain cleanses the mind and the soul.")
	mood_change = 4
	timeout = 2 MINUTES

//Antag mood nerf
/datum/mood_event/focused
	description = span_nicegreen("I have a goal, and I will reach it, whatever it takes!")
	mood_change = 2
	hidden = TRUE


code:
//hydration
/datum/mood_event/thirsty
	description = span_warning("I'm getting a bit thirsty.")
	mood_change = -4

/datum/mood_event/dehydrated
	description = span_boldwarning("I am dehydrated!")
	mood_change = -6

//nutrition
/datum/mood_event/hungry
	mood_change = -4

/datum/mood_event/starving
	mood_change = -6

//urination
/datum/mood_event/needpiss
	description = span_warning("I need to pee.")
	mood_change = -3

/datum/mood_event/reallyneedpiss
	description = span_boldwarning("My bladder is going to explode!")
	mood_change = -5

/datum/mood_event/pissed_self
	description = span_necrosis("I have pissed my pants. This day is ruined.")
	mood_change = -8
	timeout = 10 MINUTES

//defecation
/datum/mood_event/needshit
	description = span_warning("I need to poop.")
	mood_change = -3

/datum/mood_event/reallyneedshit
	description = span_boldwarning("My anus is <b>BLEEDING!</b>")
	mood_change = -5

/datum/mood_event/shat_self
	description = span_necrosis("I have shat my pants. This day is ruined.")
	mood_change = -8
	timeout = 10 MINUTES

//hygiene
/datum/mood_event/clean
	description = span_nicegreen("I am so clean!")
	mood_change = 2

/datum/mood_event/needshower
	description = span_warning("I need to shower.")
	mood_change = -2

/datum/mood_event/reallyneedshower
	description = span_infection("I am filthy.")
	mood_change = -4

/datum/mood_event/smashplayer
	description = span_necrosis("My stench is unbearable.")
	mood_change = -6

//sex!
/datum/mood_event/needsex
	description = span_love("I feel horny.")
	mood_change = -3

/datum/mood_event/reallyneedsex
	description = span_userlove("I want to be RAVAGED!")
	mood_change = -6


code:
/datum/pollutant
	/// Name of the pollutant, if null will be treated as abstract and wont be initialized as singleton
	var/name
	/// Flags of the pollutant, determine whether it has an appearance, smell, touch act, breath act
	var/pollutant_flags = NONE
	/// Below are variables for appearance
	/// What color will the pollutant be, can be left null
	var/color
	/// What is it desired alpha?
	var/alpha = 255
	/// How "thick" is it, the thicker the quicker it gets to desired alpha and is stronger than other pollutants in blending appearance
	var/thickness = 1
	///FILL THE BELOW OUT IF ITS SMELLABLE!
	/// How intense is one unit of the pollutant for smell purposes?
	var/smell_intensity
	/// Descriptor of the smell
	var/descriptor
	/// Scent of the smell
	var/scent

/// When a pollutant touches an unprotected carbon mob
/datum/pollutant/proc/touch_act(mob/living/carbon/victim, amount)
	return

/// When a carbon mob breathes in the pollutant
/datum/pollutant/proc/breathe_act(mob/living/carbon/victim, amount)
	return


code:
///Smoke coming from cigarettes and fires
/datum/pollutant/smoke
	name = "Smoke"
	pollutant_flags = POLLUTANT_APPEARANCE|POLLUTANT_SMELL|POLLUTANT_BREATHE_ACT
	smell_intensity = 1
	descriptor = SCENT_DESC_SMELL
	scent = "smoke"

/datum/pollutant/smoke/breathe_act(mob/living/carbon/victim, amount)
	if(amount <= 50)
		return
	if(prob(20))
		victim.emote("cough")

///Miasma coming from corpses
/datum/pollutant/miasma
	name = "Rotting"
	pollutant_flags = POLLUTANT_APPEARANCE|POLLUTANT_SMELL|POLLUTANT_BREATHE_ACT
	smell_intensity = 4
	descriptor = SCENT_DESC_ODOR
	scent = "rotting carcasses"
	color = "#9500b3"

/datum/pollutant/miasma/breathe_act(mob/living/carbon/victim, amount)
	if(prob(50))
		return
	var/message
	switch(amount)
		if(0 to 15)
			message = span_warning("Ugh, what is this smell?")
			if(prob(15))
				victim.emote("gag")
		if(15 to 35)
			message = span_warning("I'm gonna puke...")
			if(prob(25))
				victim.vomit(rand(5, 10), prob(amount))
				SEND_SIGNAL(victim, COMSIG_ADD_MOOD_EVENT, "pollution", /datum/mood_event/miasma)
		if(35 to INFINITY)
			message = span_bolddanger("This stench is unbearable!")
			SEND_SIGNAL(victim, COMSIG_ADD_MOOD_EVENT, "pollution", /datum/mood_event/miasma/harsh)
			victim.adjustToxLoss(5)
			if(prob(35))
				victim.vomit(rand(10, 15), prob(amount))
	if(prob(20))
		to_chat(victim, message)

///From smoking weed
/datum/pollutant/smoke/cannabis
	name = "Cannabis"
	smell_intensity = 2 //Stronger than the normal smoke
	scent = "cannabis"

/datum/pollutant/smoke/vape
	name = "Vape Cloud"
	thickness = 2
	scent = "pleasant and soft vapour"

///Dust from mining drills
/datum/pollutant/dust
	name = "Dust"
	pollutant_flags = POLLUTANT_APPEARANCE|POLLUTANT_BREATHE_ACT
	thickness = 2
	color = "#ffed9c"

/datum/pollutant/dust/breathe_act(mob/living/carbon/victim, amount)
	if(amount <= 10)
		return
	if(prob(40))
		victim.losebreath += 3 //Get in your lungs real bad
		victim.emote("cough")

///Sulphur coming from igniting matches
/datum/pollutant/sulphur
	name = "Sulphur"
	pollutant_flags = POLLUTANT_SMELL
	smell_intensity = 5 //Very pronounced smell (and good too, sniff sniff)
	descriptor = SCENT_DESC_SMELL
	scent = "sulphur"

///Organic waste and garbage makes this
/datum/pollutant/decaying_waste
	name = "Decaying Waste"
	pollutant_flags = POLLUTANT_SMELL
	smell_intensity = 3
	descriptor = SCENT_DESC_ODOR
	scent = "decaying waste"

///Splashing blood makes a tiny bit of this
/datum/pollutant/metallic_scent
	name = "Metallic Scent"
	pollutant_flags = POLLUTANT_SMELL
	smell_intensity = 1
	descriptor = SCENT_DESC_SMELL
	scent = "a metallic scent"

///Green goo piles and medicine chemical reactions make this
/datum/pollutant/chemical_vapors
	name = "Chemical Vapors"
	pollutant_flags = POLLUTANT_SMELL
	smell_intensity = 1
	descriptor = SCENT_DESC_SMELL
	scent = "chemicals"

///Dangerous fires release this from the waste they're burning
/datum/pollutant/carbon_air_pollution
	name = "Carbon Air Pollution"
	pollutant_flags = POLLUTANT_BREATHE_ACT

/datum/pollutant/carbon_air_pollution/breathe_act(mob/living/carbon/victim, amount)
	if(amount <= 10)
		return
	victim.adjustOxyLoss(rand(1,3))
	victim.adjustToxLoss(1)
	if(prob(amount*0.5))
		victim.losebreath += 3

//Food related smells
/datum/pollutant/food
	pollutant_flags = POLLUTANT_SMELL
	smell_intensity = 0.5 //Low intensity because we want to carry it farther with more amounts
	descriptor = SCENT_DESC_SMELL

/datum/pollutant/food/fried_meat
	name = "Fried Meat"
	scent = "fried meat"

/datum/pollutant/food/fried_chicken
	name = "Fried Chicke"
	scent = "fried chicken"

/datum/pollutant/food/fried_bacon
	name = "Fried Bacon"
	scent = "fried bacon"

/datum/pollutant/food/fried_fish
	name = "Fried Fish"
	scent = "fried fish"

/datum/pollutant/food/pancakes
	name = "Pancakes"
	scent = "pancakes"

/datum/pollutant/food/coffee
	name = "Coffee"
	scent = "coffee"

/datum/pollutant/food/tea
	name = "Tea"
	scent = "tea"

/datum/pollutant/food/chocolate
	name = "Chocolate"
	scent = "chocolate"

/datum/pollutant/food/spicy_noodles
	name = "Spicy Noodles"
	scent = "spicy noodles"

/// Fragrances that we spray on thing to make them smell nice
/datum/pollutant/fragrance
	pollutant_flags = POLLUTANT_SMELL
	smell_intensity = 1
	descriptor = SCENT_DESC_FRAGRANCE

/datum/pollutant/fragrance/air_refresher
	name = "Air Refresher"
	scent = "a strong flowery scent"
	smell_intensity = 3

//simple fragrances
/datum/pollutant/fragrance/cologne
	name = "Cologne Water"
	scent = "cologne"

/datum/pollutant/fragrance/wood
	name = "Wood Perfume"
	scent = "aging wood"

/datum/pollutant/fragrance/rose
	name = "Rose Perfume"
	scent = "roses"

/datum/pollutant/fragrance/jasmine
	name = "Jasmine Perfume"
	scent = "jasmine"

/datum/pollutant/fragrance/mint
	name = "Mint Perfume"
	scent = "mint"

/datum/pollutant/fragrance/vanilla
	name = "Vanilla Perfume"
	scent = "vanilla"

/datum/pollutant/fragrance/pear
	name = "Pear Perfume"
	scent = "pear"

/datum/pollutant/fragrance/strawberry
	name = "Strawberry Perfume"
	scent = "strawberries"

/datum/pollutant/fragrance/cherry
	name = "Cherry Perfume"
	scent = "cherries"

/datum/pollutant/fragrance/amber
	name = "Amber Perfume"
	scent = "a sweet and powdery scent"


code:
 //gets a list of all quirk datums
/mob/living/proc/get_quirks(category = CAT_QUIRK_ALL)
	var/list/get_quirks = list()
	switch(category)
		//All quirks
		if(CAT_QUIRK_ALL)
			for(var/Q in quirks)
				get_quirks += Q
		//Major Disabilities
		if(CAT_QUIRK_MAJOR_DISABILITY)
			for(var/V in quirks)
				var/datum/quirk/Q = V
				if(Q.value < -4)
					get_quirks += Q
		//Minor Disabilities
		if(CAT_QUIRK_MINOR_DISABILITY)
			for(var/V in quirks)
				var/datum/quirk/Q = V
				if(Q.value >= -4 && Q.value < 0)
					get_quirks += Q
		//Neutral and Positive quirks
		if(CAT_QUIRK_NOTES)
			for(var/V in quirks)
				var/datum/quirk/Q = V
				if(Q.value > -1)
					get_quirks += Q
	return get_quirks


code:
/mob/living/carbon/proc/toggle_speech_mod(modifier_type)
	for(var/datum/speech_modifier/speech_modifier in speech_modifiers)
		if(istype(speech_modifier, modifier_type))
			speech_modifier.remove_speech_modifier()
			qdel(speech_modifier)
			return
	var/datum/speech_modifier/speech = new modifier_type()
	speech.add_speech_modifier(src)

/mob/living/carbon/proc/add_speech_modifier(modifier_type)
	for(var/datum/speech_modifier/speech_modifier as anything in speech_modifiers)
		if(istype(speech_modifier, modifier_type))
			return
	var/datum/speech_modifier/speech = new modifier_type()
	speech.add_speech_modifier(src)

/mob/living/carbon/proc/remove_speech_modifier(modifier_type)
	for(var/datum/speech_modifier/speech_modifier as anything in speech_modifiers)
		if(istype(speech_modifier, modifier_type))
			speech_modifier.remove_speech_modifier()
			qdel(speech_modifier)

/datum/speech_modifier
	var/soundtext = ""
	var/mob/living/carbon/affected_mob = null

/datum/speech_modifier/Destroy()
	if(affected_mob)
		remove_speech_modifier()
	return ..()

/datum/speech_modifier/proc/handle_speech(datum/source, list/speech_args)
	return

/datum/speech_modifier/proc/after_add()
	if(affected_mob && soundtext)
		to_chat(affected_mob, "I start [soundtext].")

/datum/speech_modifier/proc/add_speech_modifier(mob/living/carbon/new_owner)
	affected_mob = new_owner
	LAZYADD(affected_mob.speech_modifiers, src)
	RegisterSignal(affected_mob, COMSIG_MOB_SAY, .proc/handle_speech)
	after_add()

/datum/speech_modifier/proc/before_remove()
	if(affected_mob && soundtext)
		to_chat(affected_mob, "I stop [soundtext].")

/datum/speech_modifier/proc/remove_speech_modifier()
	UnregisterSignal(affected_mob, COMSIG_MOB_SAY)
	LAZYREMOVE(affected_mob.speech_modifiers, src)
	affected_mob = null


code:
//Lisp caused by lack of teeth
/datum/speech_modifier/lisp
	var/lisp_power = 0

/datum/speech_modifier/lisp/add_speech_modifier(mob/living/carbon/new_owner)
	. = ..()
	update_lisp()

/datum/speech_modifier/lisp/handle_speech(datum/source, list/speech_args)
	update_lisp()
	if(QDELETED(src))
		return
	var/message = speech_args[SPEECH_MESSAGE]
	if(message[1] != "*")
		message = prob(lisp_power) ? replacetext(message, "f", "ph") : message
		message = prob(lisp_power) ? replacetext(message, "t", "ph") : message
		message = prob(lisp_power) ? replacetext(message, "s", "sh") : message
		message = prob(lisp_power) ? replacetext(message, "th", "hh") : message
		message = prob(lisp_power) ? replacetext(message, "ck", "gh") : message
		message = prob(lisp_power) ? replacetext(message, "c", "gh") : message
		message = prob(lisp_power) ? replacetext(message, "k", "gh") : message
	speech_args[SPEECH_MESSAGE] = message

/datum/speech_modifier/lisp/proc/update_lisp()
	var/obj/item/bodypart/mouth/jaw = affected_mob.get_bodypart_nostump(BODY_ZONE_PRECISE_MOUTH)
	if(jaw)
		lisp_power = (1 - jaw.get_teeth_amount()/jaw.max_teeth) * 100
	else
		lisp_power = 100
	//Remove if we have teeth (aka stopped being british)
	if(!lisp_power || (jaw.get_teeth_amount() >= jaw.max_teeth))
		remove_speech_modifier()


code:
/datum/status_effect/high_blood_pressure
	alert_type = null

/datum/status_effect/high_blood_pressure/on_apply()
	if(iscarbon(owner))
		var/mob/living/carbon/carbon = owner
		carbon.add_chem_effect(CE_PULSE, 2, "highbloodpressure")

/datum/status_effect/high_blood_pressure/on_remove()
	if(iscarbon(owner))
		var/mob/living/carbon/carbon = owner
		carbon.remove_chem_effect(CE_PULSE, "highbloodpressure")


code:
//DAZED
/datum/status_effect/incapacitating/dazed
	id = "dazed"

/datum/status_effect/incapacitating/dazed/on_apply()
	. = ..()
	ADD_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id))

/datum/status_effect/incapacitating/dazed/on_remove()
	. = ..()
	REMOVE_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id))

//STUMBLE
/datum/status_effect/incapacitating/dazed/stumble
	id = "stumble"
	var/didknockdown = FALSE

/datum/status_effect/incapacitating/dazed/stumble/on_apply()
	. = ..()
	owner.add_movespeed_modifier(/datum/movespeed_modifier/shove)
	ADD_TRAIT(owner, TRAIT_STUMBLE, TRAIT_STATUS_EFFECT(id))
	if(!didknockdown && iscarbon(owner))
		var/mob/living/C = owner
		switch(C.diceroll(GET_MOB_ATTRIBUTE_VALUE(C, STAT_ENDURANCE)))
			if(DICE_FAILURE)
				C.CombatKnockdown(50)
				didknockdown = TRUE
			if(DICE_CRIT_FAILURE)
				C.CombatKnockdown(75)
				didknockdown = TRUE

/datum/status_effect/incapacitating/dazed/stumble/on_remove()
	. = ..()
	owner.remove_movespeed_modifier(/datum/movespeed_modifier/shove)
	REMOVE_TRAIT(owner, TRAIT_STUMBLE, TRAIT_STATUS_EFFECT(id))
	if(!didknockdown && iscarbon(owner))
		var/mob/living/C = owner
		switch(C.diceroll(GET_MOB_ATTRIBUTE_VALUE(C, STAT_ENDURANCE)))
			if(DICE_FAILURE)
				C.CombatKnockdown(50)
				didknockdown = TRUE
			if(DICE_CRIT_FAILURE)
				C.CombatKnockdown(75)
				didknockdown = TRUE


code:
/datum/status_effect/water_affected
	id = "wateraffected"
	alert_type = null
	duration = -1

/datum/status_effect/water_affected/on_apply()
	. = ..()
	//We should be inside a liquid turf if this is applied
	calculate_water_slow()

/datum/status_effect/water_affected/proc/calculate_water_slow()
	//Factor in swimming skill here?
	var/turf/owner_turf = get_turf(owner)
	var/slowdown_amount = owner_turf.liquids.liquid_state * 0.5
	owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/status_effect/water_slowdown, multiplicative_slowdown = slowdown_amount)

/datum/status_effect/water_affected/tick()
	var/turf/owner_turf = get_turf(owner)
	if(!owner_turf?.liquids || owner_turf.liquids.liquid_state == LIQUID_STATE_PUDDLE)
		qdel(src)
		return
	calculate_water_slow()
	//Make the reagents touch the person
	var/fraction = SUBMERGEMENT_PERCENT(owner, owner_turf.liquids)
	var/datum/reagents/temporary_holder = owner_turf.liquids.simulate_reagents_flat(SUBMERGEMENT_REAGENTS_TOUCH_AMOUNT*fraction)
	temporary_holder.expose(owner, TOUCH)
	qdel(temporary_holder)
	return ..()

/datum/status_effect/water_affected/on_remove()
	. = ..()
	owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/water_slowdown)


code:
//HEAD RAPE
//DURATION SHOULD ALWAYS BE DIVISIBLE BY 40 (4 SECONDS) TO ENSURE SMOOTH ANIMATION.
//IF YOU DON'T ABIDE BY THE ABOVE, YOUR MAILBOX WILL RECEIVE A VERY NASTY SURPRISE.
/datum/status_effect/incapacitating/headrape
	id = "head_rape"
	status_type = STATUS_EFFECT_REFRESH
	processing_speed = STATUS_EFFECT_FAST_PROCESS
	tick_interval = 4 SECONDS
	//Plane master controller we are messing with
	var/atom/movable/plane_master_controller/our_controller
	//Alpha of the first composite layer
	var/static/starting_alpha = 128
	//How many total layers we get, each new layer halving the previous alpha
	var/intensity = 3
	//Each filter we are handling, assoc list
	var/list/list/filters_handled = list()

/datum/status_effect/incapacitating/headrape/on_apply()
	. = ..()
	if(owner?.hud_used)
		our_controller = owner.hud_used.plane_master_controllers[PLANE_MASTERS_GAME]
		for(var/i in 1 to intensity)
			var/color = rgb(255, 255, 255, starting_alpha/i)
			filters_handled["headrape[i]"]  = list("type" = "layer", "x" = 0, "y" = 0, "color" = color)
		//Using the add filter proc does not work, we need the render source
		for(var/plane in our_controller.controlled_planes)
			var/atom/movable/screen/plane_master/plane_iterator = our_controller.controlled_planes[plane]
			for(var/i in 1 to intensity)
				var/list/filter_params = filters_handled["headrape[i]"].Copy()
				filter_params["render_source"] = plane_iterator.render_target
				plane_iterator.add_filter("headrape[i]", 1, filter_params)

/datum/status_effect/incapacitating/headrape/tick()
	. = ..()
	INVOKE_ASYNC(src, .proc/perform_animation)

/datum/status_effect/incapacitating/headrape/before_remove()
	. = ..()
	end_animation()

/datum/status_effect/incapacitating/headrape/proc/perform_animation()
	for(var/i in 1 to intensity)
		filters_handled["headrape[i]"]["x"] = rand(-16, 16)
		filters_handled["headrape[i]"]["y"] = rand(-16, 16)
	update_filters()

/datum/status_effect/incapacitating/headrape/proc/end_animation()
	for(var/i in 1 to intensity)
		filters_handled["headrape[i]"]  = list("type" = "layer", "x" = 0, "y" = 0)
	update_filters()
	sleep(4 SECONDS)
	//KILL the filters now
	for(var/plane in our_controller.controlled_planes)
		var/atom/movable/screen/plane_master/plane_iterator = our_controller.controlled_planes[plane]
		for(var/i in 1 to intensity)
			plane_iterator.remove_filter("headrape[i]")

/datum/status_effect/incapacitating/headrape/proc/update_filters(time = 4 SECONDS)
	for(var/plane in our_controller.controlled_planes)
		var/atom/movable/screen/plane_master/plane_iterator = our_controller.controlled_planes[plane]
		for(var/i in 1 to intensity)
			var/list/filter_params = filters_handled["headrape[i]"].Copy()
			filter_params["render_source"] = plane_iterator.render_target
			plane_iterator.transition_filter("headrape[i]", time, filter_params, LINEAR_EASING, FALSE)


code:
// The shattered remnants of your broken limbs fill you with determination!
/atom/movable/screen/alert/status_effect/determined
	//This doesn't actually get used tho
	name = "Determined"
	desc = "The serious wounds you've sustained have put your body into fight-or-flight mode! Now's the time to look for an exit!"
	icon_state = "regenerative_core"

/datum/status_effect/determined
	id = "determined"

/datum/status_effect/determined/on_apply()
	. = ..()
	if(ishuman(owner))
		var/mob/living/carbon/human/human_owner = owner
		human_owner.physiology.bleed_mod *= WOUND_DETERMINATION_BLEED_MOD

/datum/status_effect/determined/on_remove()
	if(ishuman(owner))
		var/mob/living/carbon/human/human_owner = owner
		human_owner.physiology.bleed_mod /= WOUND_DETERMINATION_BLEED_MOD
	return ..()

/datum/status_effect/limp
	id = "limp"
	status_type = STATUS_EFFECT_REPLACE
	tick_interval = 10
	alert_type = /atom/movable/screen/alert/status_effect/limp
	var/msg_stage = 0//so you dont get the most intense messages immediately
	/// The left leg of the limping person
	var/obj/item/bodypart/l_leg/left_leg
	/// The right leg of the limping person
	var/obj/item/bodypart/r_leg/right_leg
	/// The left leg of the limping person
	var/obj/item/bodypart/l_foot/left_foot
	/// The right leg of the limping person
	var/obj/item/bodypart/r_foot/right_foot
	/// Which leg/foot we're limping with next
	var/obj/item/bodypart/next_leg
	/// How many deciseconds we limp for on the left leg/foot
	var/slowdown_left = 0
	/// How many deciseconds we limp for on the right leg/foot
	var/slowdown_right = 0

/datum/status_effect/limp/on_apply()
	if(!iscarbon(owner))
		return FALSE
	var/mob/living/carbon/C = owner
	left_leg = LAZYACCESS(C.leg_bodyparts, 1)
	right_leg = LAZYACCESS(C.leg_bodyparts, 2)
	left_foot = LAZYACCESS(C.leg_bodyparts, 3)
	right_foot = LAZYACCESS(C.leg_bodyparts, 4)
	update_limp()
	RegisterSignal(C, COMSIG_MOVABLE_MOVED, .proc/check_step)
	RegisterSignal(C, list(COMSIG_CARBON_GAIN_WOUND, COMSIG_CARBON_LOSE_WOUND, COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB), .proc/update_limp)
	return TRUE

/datum/status_effect/limp/on_remove()
	. = ..()
	UnregisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_CARBON_GAIN_WOUND, COMSIG_CARBON_LOSE_WOUND, COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB))

/atom/movable/screen/alert/status_effect/limp
	name = "Limping"
	desc = "One or more of your legs has been wounded, slowing down steps with that leg! Get it fixed, or at least in a sling of gauze!"

/datum/status_effect/limp/proc/check_step(mob/whocares, OldLoc, Dir, forced)
	SIGNAL_HANDLER
	if(!owner.client || owner.body_position == LYING_DOWN || !owner.has_gravity() || (owner.movement_type & FLYING) || forced || owner.buckled)
		return

	// less limping while we have determination still
	var/determined_mod = owner.has_status_effect(STATUS_EFFECT_DETERMINED) ? 0.5 : 1
	if(next_leg == left_leg)
		owner.client.move_delay += slowdown_left * determined_mod
		next_leg = right_leg
	else
		owner.client.move_delay += slowdown_right * determined_mod
		next_leg = left_leg

/datum/status_effect/limp/proc/update_limp()
	SIGNAL_HANDLER
	var/mob/living/carbon/C = owner
	left_leg = LAZYACCESS(C.leg_bodyparts, 1)
	right_leg = LAZYACCESS(C.leg_bodyparts, 2)
	left_foot = LAZYACCESS(C.leg_bodyparts, 3)
	right_foot = LAZYACCESS(C.leg_bodyparts, 4)

	if(!left_leg && !right_leg && !left_foot && !right_foot)
		C.remove_status_effect(src)
		return

	slowdown_left = 0
	slowdown_right = 0

	if(left_leg)
		for(var/thing in left_leg.wounds)
			var/datum/wound/W = thing
			slowdown_left += W.limp_slowdown

	if(left_foot)
		for(var/thing in left_foot.wounds)
			var/datum/wound/W = thing
			slowdown_left += W.limp_slowdown

	if(right_leg)
		for(var/thing in right_leg.wounds)
			var/datum/wound/W = thing
			slowdown_right += W.limp_slowdown

	if(right_foot)
		for(var/thing in right_foot.wounds)
			var/datum/wound/W = thing
			slowdown_right += W.limp_slowdown

	// this handles losing your leg with the limp and the other one being in good shape as well
	if(!slowdown_left && !slowdown_right)
		C.remove_status_effect(src)
		return

/////////////////////////
//////// WOUNDS /////////
/////////////////////////
// wound alert
/atom/movable/screen/alert/status_effect/wound
	name = "Wounded"
	desc = "Your body has sustained serious damage, click here to inspect yourself."

/atom/movable/screen/alert/status_effect/wound/Click()
	. = ..()
	if(!.)
		return

	var/mob/living/carbon/carbon_owner = owner
	carbon_owner.check_self_for_injuries()

// wound status effect base
/datum/status_effect/wound
	id = "wound"
	status_type = STATUS_EFFECT_MULTIPLE
	var/obj/item/bodypart/linked_limb
	var/datum/wound/linked_wound
	alert_type = NONE

/datum/status_effect/wound/on_creation(mob/living/new_owner, incoming_wound)
	. = ..()
	linked_wound = incoming_wound
	linked_limb = linked_wound.limb

/datum/status_effect/wound/on_remove()
	linked_wound = null
	linked_limb = null
	UnregisterSignal(owner, COMSIG_CARBON_LOSE_WOUND)

/datum/status_effect/wound/on_apply()
	if(!iscarbon(owner))
		return FALSE
	RegisterSignal(owner, COMSIG_CARBON_LOSE_WOUND, .proc/check_remove)
	return TRUE

/// check if the wound getting removed is the wound we're tied to
/datum/status_effect/wound/proc/check_remove(mob/living/L, datum/wound/W)
	SIGNAL_HANDLER
	if(W == linked_wound)
		qdel(src)

// bones
/datum/status_effect/wound/blunt

/datum/status_effect/wound/blunt/on_apply()
	. = ..()
	RegisterSignal(owner, COMSIG_MOB_SWAP_HANDS, .proc/on_swap_hands)
	on_swap_hands()

/datum/status_effect/wound/blunt/on_remove()
	. = ..()
	UnregisterSignal(owner, COMSIG_MOB_SWAP_HANDS)
	var/mob/living/carbon/wound_owner = owner
	wound_owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/blunt_wound)

/datum/status_effect/wound/blunt/proc/on_swap_hands()
	SIGNAL_HANDLER
	var/mob/living/carbon/wound_owner = owner
	if(wound_owner.get_active_hand() == linked_limb)
		wound_owner.add_actionspeed_modifier(/datum/actionspeed_modifier/blunt_wound, (linked_wound.interaction_efficiency_penalty - 1))
	else
		wound_owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/blunt_wound)

/datum/status_effect/wound/blunt/nextmove_modifier()
	var/mob/living/carbon/C = owner
	if(C.get_active_hand() == linked_limb)
		return linked_wound.interaction_efficiency_penalty
	return TRUE

// blunt
/datum/status_effect/wound/blunt/moderate
	id = "disjoint"

/datum/status_effect/wound/blunt/severe
	id = "hairline"

/datum/status_effect/wound/blunt/critical
	id = "compound"


code: /// This is purely a instructional datum used for the operating computer to tell you how to do... surgeries.


code:
//This datum is used solely to manage the "adminwho" verb tgui
/datum/adminwho

/datum/adminwho/ui_interact(mob/user, datum/tgui/ui)
	. = ..()
	ui = SStgui.try_update_ui(user, src, ui)
	if(!ui)
		ui = new(user, src, "AdminWhoMenu")
		ui.open()

/datum/adminwho/ui_state(mob/user)
	return GLOB.always_state

/datum/adminwho/ui_data(mob/user)
	var/list/data = list()

	var/datum/admins/holder = user.client.holder
	var/list/admins = list()
	var/client/admin //faster declaration
	for(var/thing in GLOB.admins)
		var/list/this_admin = list()
		admin = thing
		//Don't show fakemins to plebs
		if(admin.holder.fakekey && !holder)
			continue
		//Don't show afk admins to plebs
		if(admin.is_afk() && !holder)
			continue
		//KEY
		var/key = "[admin.key]"
		if(admin.holder.fakekey && holder)
			key += " (as [admin.holder.fakekey])"
		if(admin.is_afk() && holder)
			key += " \[AFK\]"
		this_admin["key"] = key
		//RANK
		this_admin["rank"] = "[admin.holder.rank.name]"

		admins += list(this_admin)
	data["admins"] = admins
	data["total_admins"] = length(admins)
	return data


code:
//This datum is used solely to manage the "who" verb tgui
/datum/who

/datum/who/ui_interact(mob/user, datum/tgui/ui)
	. = ..()
	ui = SStgui.try_update_ui(user, src, ui)
	if(!ui)
		ui = new(user, src, "WhoMenu")
		ui.open()

/datum/who/ui_state(mob/user)
	return GLOB.always_state

/datum/who/ui_data(mob/user)
	var/list/data = list()
	data["clients"] = list()
	var/mob/dead/observer/observer
	var/datum/admins/holder = user.client.holder
	if(isobserver(user))
		observer = user
		if(!observer.started_as_observer && !observer.client.holder)
			observer = null
	var/client/player //faster declaration
	for(var/thing in GLOB.clients)
		var/list/this_player = list()
		player = thing
		//KEY
		if(holder?.fakekey)
			if(observer)
				this_player["key"] = "[player.key] (as [player.holder.fakekey])"
			else
				this_player["key"] = "[player.holder.fakekey]"
		else
			this_player["key"] = "[player.key]"
		//STATUS
		if(isnewplayer(player.mob))
			this_player["status"] = "In Lobby"
		else
			if(observer)
				var/status = "Playing as [player.mob.real_name]"
				switch(player.mob.stat)
					if(UNCONSCIOUS, HARD_CRIT)
						status += " (Unconscious)"
					if(DEAD)
						if(isobserver(player.mob))
							var/mob/dead/observer/O = player.mob
							if(O.started_as_observer)
								status += " (Observing)"
							else
								status += " (Observing, Dead)"
						else
							status += " (Dead)"
				this_player["status"] = status
			else
				this_player["status"] = "Playing"
		//JOB
		if(isnewplayer(player.mob) || isobserver(player.mob))
			this_player["job"] = "N/A"
		else
			var/job = "[player.mob?.job ? player.mob.job : "None"]"
			if(observer)
				if(is_special_character(player.mob))
					job += " (Antagonist)"
				if(holder)
					job += " [ADMIN_QUE(player.mob)]"
			this_player["job"] = "[player.mob.job ? player.mob.job : "None"]"
		//PING
		this_player["ping"] = "[round(player.avgping, 1)]ms"
		//COUNTRY
		this_player["country"] = "[player.country]"

		data["clients"] += list(this_player)
	data["total_clients"] = length(GLOB.clients)
	return data


code:
/datum/wield_info
	/// WIELD_WIELDABLE, WIELD_ALWAYS_TWOHANDED, WIELD_NO_ATTACK_SELF
	var/wield_flags = NONE
	/// The multiplier applied to force when wielded, does not work with force_wielded nor force_unwielded
	var/force_multiplier = null
	/// The force of the item when wielded
	var/force_wielded = null
	/// The force of the item when unwielded
	var/force_unwielded = null
	/// Play this sound when wielded
	var/wield_sound = null
	/// Play this sound when unwielded
	var/unwield_sound = null
	/// Play this sound on attack when wielded
	var/wield_hitsound = null
	/// The inhand icon that will be used when wielded
	var/icon_wielded = null


code:
/datum/wield_info/standard
	wield_flags = WIELD_WIELDABLE|WIELD_NO_ATTACK_SELF
	force_multiplier = 1.2


code:
/datum/wield_info/twohand_required
	wield_flags = WIELD_WIELDABLE|WIELD_ALWAYS_TWOHANDED
	force_multiplier = 1.2


code:
/datum/wield_info/unwieldable
	wield_flags = NONE


code:
/datum/wires/ui_act(action, params) //modularizing because i plan :tm: to eventually expand on this
	. = ..()
	if(. || !interactable(usr))
		return
	var/target_wire = params["wire"]
	var/mob/living/L = usr
	var/obj/item/I
	if((L.diceroll(GET_MOB_ATTRIBUTE_VALUE(L, SKILL_ELECTRONICS)) <= DICE_FAILURE) && action != "attach") //Ultra shitcode, ik
		to_chat(L, span_warning(fail_msg())) //But detaching shit would be basically impossible otherwise
		target_wire = pick(colors)
	switch(action)
		if("cut")
			if(GET_MOB_ATTRIBUTE_VALUE(L, SKILL_ELECTRONICS) < 6)
				to_chat(L, span_warning("I don't... know how to do this."))
				return
			I = L.is_holding_tool_quality(TOOL_WIRECUTTER)
			if(I || isAdminGhostAI(usr))
				if(I && holder)
					I.play_tool_sound(holder, 20)
				cut_color(target_wire)
				. = TRUE
		if("pulse")
			if(GET_MOB_ATTRIBUTE_VALUE(L, SKILL_ELECTRONICS) < 8)
				to_chat(L, span_warning("I don't... know how to do this."))
				return
			I = L.is_holding_tool_quality(TOOL_MULTITOOL)
			if(I || isAdminGhostAI(usr))
				if(I && holder)
					I.play_tool_sound(holder, 20)
				pulse_color(target_wire, L)
				. = TRUE
		if("attach")
			if(GET_MOB_ATTRIBUTE_VALUE(L, SKILL_ELECTRONICS) < 8) //It's basically a multitool.
				to_chat(L, span_warning("I don't... know how to do this."))
				return
			if(is_attached(target_wire))
				I = detach_assembly(target_wire)
				if(I)
					L.put_in_hands(I)
					. = TRUE
			else
				I = L.get_active_held_item()
				if(istype(I, /obj/item/assembly))
					var/obj/item/assembly/A = I
					if(A.attachable)
						if(!L.temporarilyRemoveItemFromInventory(A))
							return
						if(!attach_assembly(target_wire, A))
							A.forceMove(L.drop_location())
						. = TRUE


code:
/area
	var/room_name
	var/room_desc
	var/droning_sound = DRONING_DEFAULT
	var/droning_vary = 0
	var/droning_repeat = TRUE
	var/droning_wait = 0
	var/droning_volume = 25
	var/droning_channel = CHANNEL_BUZZ
	var/droning_frequency = 0

/area/Entered(atom/movable/arrived, area/old_area)
	set waitfor = FALSE
	SEND_SIGNAL(src, COMSIG_AREA_ENTERED, arrived, old_area)
	var/mob/living/living_arrived = arrived
	if(istype(living_arrived) && living_arrived.client && !living_arrived.combat_mode)
		//Ambience if combat mode is off
		SSdroning.area_entered(src, living_arrived.client)
	if(!LAZYACCESS(arrived.important_recursive_contents, RECURSIVE_CONTENTS_AREA_SENSITIVE))
		return
	for(var/atom/movable/recipient as anything in arrived.important_recursive_contents[RECURSIVE_CONTENTS_AREA_SENSITIVE])
		SEND_SIGNAL(recipient, COMSIG_ENTER_AREA, src)


code:
//AI sounds
/area/ai_monitored
	droning_sound = DRONING_AI


code:
/area/command/heads_quarters/hop/gatekeeper
	name = "\improper Gatekeeper's Office"

/area/command/heads_quarters/hop/gatekeeper/private
	name = "\improper Gatekeeper's Quarters"

/area/hallway/entrance
	name = "\improper Outpost Entrance"
	icon_state = "hallA"

/area/hallway/train_station
	name = "\improper Train Station"
	icon_state = "hallF"
	droning_sound = DRONING_TRAIN

/area/hallway/train_station/arrival
	name = "\improper Arrival Station"
	icon_state = "hallF"

/area/hallway/train_station/path
	name = "\improper Train Path"
	icon_state = "hallP"

/area/hallway/streets
	name = "\improper Streets"
	icon_state = "hallS"
	droning_sound = DRONING_BALUARTE

/area/maintenance/lift
	name = "Central Lift"
	icon_state = "maintcentral"
	droning_sound = DRONING_LIFT

/area/maintenance/pitofdespair
	name = "PIT OF DESPAIR"
	icon_state = "showroom"
	droning_sound = DRONING_PITOFDESPAIR


code:
//Nevado sounds
/area/mine
	droning_sound = DRONING_NEVADO

//Space sounds
/area/asteroid
	droning_sound = DRONING_SPACE

//Base nevado type
/area/nevado
	icon_state = "mining"
	has_gravity = STANDARD_GRAVITY
	flags_1 = NONE
	area_flags = UNIQUE_AREA | FLORA_ALLOWED
	sound_environment = SOUND_AREA_ICEMOON

//Nevado surface
/area/nevado/surface
	name = "Nevado Surface"
	icon_state = "explored"
	outdoors = FALSE
	always_unpowered = TRUE
	power_environ = FALSE
	power_equip = FALSE
	power_light = FALSE
	requires_power = TRUE
	ambience_index = AMBIENCE_MINING
	area_flags = UNIQUE_AREA | FLORA_ALLOWED | NO_ALERTS
	min_ambience_cooldown = 70 SECONDS
	max_ambience_cooldown = 220 SECONDS

/area/nevado/surface/outdoors
	name = "Nevado Outdoors"
	outdoors = TRUE

/area/nevado/surface/outdoors/unexplored
	name = "Nevado Wastes"
	icon_state = "unexplored"
	map_generator = /datum/map_generator/nevado_surface_generator

//Nevado caves
/area/nevado/caves
	name = "Nevado Underground"
	icon_state = "explored"
	outdoors = FALSE
	always_unpowered = TRUE
	power_environ = FALSE
	power_equip = FALSE
	power_light = FALSE
	ambience_index = AMBIENCE_MINING
	area_flags = UNIQUE_AREA | FLORA_ALLOWED | NO_ALERTS
	min_ambience_cooldown = 70 SECONDS
	max_ambience_cooldown = 220 SECONDS

/area/nevado/caves/outdoors
	name = "Nevado Caves"
	outdoors = TRUE

/area/nevado/caves/outdoors/unexplored
	name = "Nevado Caves"
	icon_state = "unexplored"
	map_generator = /datum/map_generator/cave_generator/nevado


code:
//Shuttle sounds
/area/shuttle
	droning_sound = DRONING_SHUTTLE


code:
//Space sounds
/area/space
	droning_sound = DRONING_SPACE


code:
//AI sounds
/area/tcommsat
	droning_sound = DRONING_AI

/area/comms
	droning_sound = DRONING_AI

/area/server
	droning_sound = DRONING_AI

//Maintenance sounds
/area/maintenance
	droning_sound = DRONING_MAINT

//Engineering sounds
/area/engineering
	droning_sound = DRONING_ENGI

/area/construction
	droning_sound = DRONING_ENGI

/area/solars
	droning_sound = DRONING_ENGI

//Baluarte sounds
/area/hallway
	droning_sound = DRONING_BALUARTE

/area/commons
	droning_sound = DRONING_BALUARTE

/area/command
	droning_sound = DRONING_BALUARTE

/area/medical
	droning_sound = DRONING_BALUARTE

/area/security
	droning_sound = DRONING_BALUARTE

/area/cargo
	droning_sound = DRONING_BALUARTE

/area/service
	droning_sound = DRONING_BALUARTE

/area/science
	droning_sound = DRONING_BALUARTE

//Tavern sounds
/area/service/bar
	droning_sound = DRONING_TAVERN
	droning_channel = CHANNEL_JUKEBOX

/area/service/theater
	droning_sound = DRONING_TAVERN
	droning_channel = CHANNEL_JUKEBOX

//Shuttle sounds
/area/hallway/secondary/exit
	droning_sound = DRONING_SHUTTLE


code:
// I hate that i have to give fucking areas a germ level but it be like that
/atom
	/// Basically the level of dirtiness on an atom, which will spread to wounds and stuff and cause infections
	var/germ_level = GERM_LEVEL_AMBIENT

// Thrown stuff only bounced in no gravity for some reason, i have fixed this blunder!
/atom/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
	SEND_SIGNAL(src, COMSIG_ATOM_HITBY, AM, skipcatch, hitpush, blocked, throwingdatum)
	if(density)
		sound_hint()
		addtimer(CALLBACK(src, .proc/hitby_react, AM, throwingdatum.speed), 2)

/atom/hitby_react(atom/movable/AM, speed = 0)
	if(AM && !QDELETED(AM) && isturf(AM.loc) && !AM.anchored)
		if(isitem(AM))
			var/obj/item/item = AM
			item.undo_messy()
			item.do_messy(duration = 4)
		step(AM, turn(AM.dir, 180))
		if(ismob(src) || ismob(AM))
			playsound(src, 'modular_septic/sound/effects/colision_bodyalt.ogg', 65, 0)
		else
			playsound(src, pick('modular_septic/sound/effects/colision1.ogg', 'modular_septic/sound/effects/colision2.ogg', 'modular_septic/sound/effects/colision3.ogg', 'modular_septic/sound/effects/colision4.ogg'), 65, 0)

/// Used to add or reduce germ level on an atom
/atom/proc/adjust_germ_level(add_germs, minimum_germs = 0, maximum_germs = MAXIMUM_GERM_LEVEL)
	germ_level = clamp(germ_level + add_germs, minimum_germs, maximum_germs)

/// Force set the germ level
/atom/proc/set_germ_level(germs)
	var/delta = (germs - germ_level)
	return adjust_germ_level(delta)

/// Ramming into walls (TODO: Turn into element!)
/atom/proc/on_rammed(mob/living/carbon/rammer)
	return FALSE


code:
// Generate the full examine string of this atom (including icon for goonchat)
/atom/get_examine_string(mob/user, thats = FALSE)
	return "[icon2html(src, user)] [thats ? "That's ":""][thats ? "[get_examine_name(user)]" : get_examine_name(user)]"

// Calling on_examine()
/atom/examine(mob/user)
	. = list("[get_examine_string(user, TRUE)].")
	. += get_name_chaser(user)
	. += "

"
	if(desc)
		. += desc
	if(custom_materials)
		var/list/materials_list = list()
		for(var/i in custom_materials)
			var/datum/material/M = i
			materials_list += "[M.name]"
		. += "[p_they(TRUE)] [p_are()] made out of [english_list(materials_list)]."
	if(reagents)
		if(reagents.flags & TRANSPARENT)
			. += "[p_they(TRUE)] contain[p_s()]:"
			if(length(reagents.reagent_list))
				if(user.can_see_reagents()) //Show each individual reagent
					for(var/datum/reagent/R in reagents.reagent_list)
						. += "[round(R.volume, 0.01)] units of [R.name]"
					if(reagents.is_reacting)
						. += span_warning("It is currently reacting!")
					. += span_notice("The solution's pH is [round(reagents.ph, 0.01)] and has a temperature of [reagents.chem_temp]K.")
				else //Otherwise, just show the total volume
					var/total_volume = 0
					for(var/datum/reagent/R in reagents.reagent_list)
						total_volume += R.volume
					. += "[total_volume] units of various reagents"
			else
				. += "Nothing."
		else if(reagents.flags & AMOUNT_VISIBLE)
			if(reagents.total_volume)
				. += span_notice("[p_they(TRUE)] [p_have()] [reagents.total_volume] unit\s left.")
			else
				. += span_danger("[p_they(TRUE)] [p_are()] empty.")
	var/filth_examine = germ_level_examine(user)
	if(filth_examine)
		. += filth_examine
	var/examine_chaser = examine_chaser(user)
	if(examine_chaser)
		. += examine_chaser
	SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .)
	if(on_examined_check(user, FALSE))
		user.on_examine_atom(src, FALSE)

/atom/examine_more(mob/user)
	. = list()
	SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE_MORE, user, .)
	if(on_examined_check(user, TRUE))
		user.on_examine_atom(src, TRUE)

/// Currently only matters for items
/atom/proc/germ_level_examine(mob/user)
	return

/// Displayed after germ_level_examine(), but before other examine child calls
/atom/proc/examine_chaser(mob/user)
	return

/// Override this to impede examine messages etc
/atom/proc/on_examined_check(mob/user, examine_more = FALSE)
	return TRUE


code:
/atom/movable/throw_at(atom/target, range, speed, mob/thrower, spin, diagonals_first, datum/callback/callback, force, gentle, quickstart)
	spin = FALSE
	return ..()

/atom/movable/do_item_attack_animation(atom/A, visual_effect_icon, obj/item/used_item)
	var/image/I
	if(visual_effect_icon)
		I = image('icons/effects/effects.dmi', A, visual_effect_icon, A.layer + 0.1)

	if(!I)
		return

	flick_overlay(I, GLOB.clients, 10)

	// And animate the attack!
	animate(I, alpha = 175, transform = matrix() * 0.75, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3)
	animate(time = 1)
	animate(alpha = 0, time = 3, easing = CIRCULAR_EASING|EASE_OUT)

/atom/movable/can_zFall(turf/source, levels = 1, turf/target, direction)
	if(!direction)
		direction = DOWN
	if(!source)
		source = get_turf(src)
		if(!source)
			return FALSE
	if(!target)
		target = get_step_multiz(source, direction)
		if(!target)
			return FALSE
	return !(movement_type & FLYING) && !(movement_type & FLOATING) && has_gravity(source) && !throwing

/atom/movable/onZImpact(turf/T, levels)
	var/atom/highest = T
	for(var/i in T.contents)
		var/atom/A = i
		if(!A.density)
			continue
		if(isobj(A) || ismob(A))
			if(A.layer > highest.layer)
				highest = A
	return TRUE


code:
// Update the screentip to reflect what we're hovering over
/atom
	var/screentip_flags = DEFAULT_SCREENTIP_FLAGS

/atom/Click(location, control, params)
	. = ..()
	// Screentips
	if((screentip_flags & SCREENTIP_ON_MOUSE_CLICK) && (usr.hud_used?.screentips_enabled))
		// This is VERY dumb
		addtimer(CALLBACK(src, .proc/update_screentip, usr, params, SCREENTIP_ON_MOUSE_CLICK), 1)

/atom/MouseEntered(location, control, params)
	. = ..()
	// Screentips
	if((screentip_flags & SCREENTIP_ON_MOUSE_ENTERED) && (usr.hud_used?.screentips_enabled))
		update_screentip(usr, params, SCREENTIP_ON_MOUSE_ENTERED)

/atom/MouseMove(location, control, params)
	. = ..()
	// Screentips
	if((screentip_flags & SCREENTIP_ON_MOUSE_MOVE) && (usr.hud_used?.screentips_enabled))
		update_screentip(usr, params, SCREENTIP_ON_MOUSE_MOVE)

/atom/proc/return_screentip(mob/user, params)
	if(flags_1 & NO_SCREENTIPS_1)
		return ""
	return SCREENTIP_OBJ(uppertext(name))

/atom/proc/update_screentip(mob/user, params, mode = DEFAULT_SCREENTIP_FLAGS)
	user?.hud_used?.screentip_text?.maptext = return_screentip(user, params)


code:
/obj/machinery/button/Initialize(mapload, ndir, built)
	. = ..()
	AddElement(/datum/element/multitool_emaggable)


code:
/obj/machinery/computer/apc_control/Initialize(mapload, obj/item/circuitboard/C)
	. = ..()
	AddElement(/datum/element/multitool_emaggable)


code:
/obj/structure/barricade/sandbags/Initialize()
	. = ..()
	AddElement(/datum/element/liquids_height, 20)


code:
/obj/machinery/door/airlock
	icon = 'modular_septic/icons/obj/doors/airlocks/station/public.dmi'
	overlays_file = 'modular_septic/icons/obj/doors/airlocks/station/overlays.dmi'
	doorOpen = 'modular_septic/sound/machinery/airlock_open.wav'
	doorClose = 'modular_septic/sound/machinery/airlock_close.wav'
	boltUp = 'modular_septic/sound/machinery/airlock_bolt.wav'
	boltDown = 'modular_septic/sound/machinery/airlock_unbolt.wav'
	doorDeni = 'modular_septic/sound/machinery/airlock_deny.ogg'
	var/force_entered = FALSE

/obj/machinery/door/airlock/on_rammed(mob/living/carbon/rammer)
	rammer.ram_stun()
	var/smash_sound = pick('modular_septic/sound/gore/smash1.ogg',
						'modular_septic/sound/gore/smash2.ogg',
						'modular_septic/sound/gore/smash3.ogg')
	playsound(src, smash_sound, 75)
	rammer.sound_hint()
	sound_hint()


code:
/obj/machinery/door/airlock
	icon = 'modular_septic/icons/obj/doors/airlocks/station/public.dmi'
	overlays_file = 'modular_septic/icons/obj/doors/airlocks/station/overlays.dmi'


code:
// Machinery always returns INITIALIZE_HINT_LATELOAD
/obj/machinery/door/LateInitialize()
	. = ..()
	if(LAZYLEN(req_access) || LAZYLEN(req_one_access) || LAZYLEN(text2access(req_access_txt)) || LAZYLEN(text2access(req_one_access_txt)))
		lock()

/obj/machinery/door/proc/try_door_unlock(user)
	if(allowed(user))
		if(locked)
			unlock()
		else
			lock()
	else
		if(density)
			do_animate("deny")
	return TRUE


code:
/obj/machinery/firealarm/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
	if(obj_flags & EMAGGED || machine_stat)
		return FALSE
	var/turf/turf_loc = loc
	if(istype(turf_loc) && turf_loc.turf_fire)
		return TRUE
	if(exposed_temperature > T0C + 80 || exposed_temperature < T0C - 10)
		return TRUE


code:
// Changing mob planes
/atom/movable/buckle_mob(mob/living/M, force, check_loc, buckle_mob_flags, ignore_self = FALSE)
	. = ..()
	if(.)
		plane = M.plane

/atom/movable/unbuckle_mob(mob/living/buckled_mob, force)
	. = ..()
	if(.)
		plane = initial(plane)


code:
/obj/structure/sign/poster
	icon = 'modular_septic/icons/obj/contraband.dmi'

/obj/structure/sign/poster/contraband/billyh
	name = "Billy"
	desc = "A poster with depicting a muscular man."
	icon_state = "posterbilly"

/obj/structure/sign/poster/contraband/billyh2
	name = "Billy"
	desc = "A poster depicting a muscular man in a seductive pose."
	icon_state = "posterbilly2"


code:
/obj/effect/decal/cleanable/can_bloodcrawl_in()
	if(blood_state in list(BLOOD_STATE_HUMAN, BLOOD_STATE_XENO))
		return bloodiness
	else
		return 0


code:
/obj/effect/decal/cleanable/blood
	name = "blood"
	desc = "It's red and gooey."
	icon = 'modular_septic/icons/effects/blood.dmi'
	icon_state = "floor1"
	random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", \
						"floor7", "floor8", "floor9", "floor10", "floor11", "floor12")

/obj/effect/decal/cleanable/blood/drip/update_icon_state()
	. = ..()
	if(drips > 5)
		cut_overlays()
		icon_state = "bigdrip[rand(1, 4)]"

/obj/effect/decal/cleanable/blood/footprints
	icon = 'modular_septic/icons/effects/blood_footprints.dmi'

/obj/effect/decal/cleanable/blood/footprints/can_bloodcrawl_in()
	if(blood_state in list(BLOOD_STATE_HUMAN, BLOOD_STATE_XENO))
		return TRUE
	return FALSE


code:
/obj/effect/decal/cleanable/blood/cum
	name = "cum"
	desc = "Someone had fun."
	dryname = "dry cum"
	drydesc = "Someone had fun, a long time ago..."
	icon = 'modular_septic/icons/effects/cum.dmi'
	icon_state = "cum1"
	random_icon_states = list("cum1", "cum2", "cum3", "cum4", "cum5", \
						"cum6", "cum7", "cum8", "cum9", "cum10", \
						"cum11", "cum12")
	color = COLOR_WHITE_CUM
	blood_state = BLOOD_STATE_CUM
	beauty = -200
	clean_type = CLEAN_TYPE_BLOOD

/obj/effect/decal/cleanable/blood/footprints/cum
	name = "cum footprints"
	desc = "Someone had fun."
	dryname = "dry cum footprints"
	drydesc = "Someone had fun, a long time ago..."
	icon = 'modular_septic/icons/effects/cum_footprints.dmi'
	icon_state = "cum1"
	color = COLOR_WHITE_CUM
	blood_state = BLOOD_STATE_CUM
	beauty = -200
	clean_type = CLEAN_TYPE_BLOOD


code:
/obj/effect/decal/cleanable/blood/femcum
	name = "squirt"
	desc = "Someone had fun."
	dryname = "dry squirt"
	drydesc = "Someone had fun, a long time ago..."
	icon = 'modular_septic/icons/effects/femcum.dmi'
	icon_state = "femcum1"
	random_icon_states = list("femcum1", "femcum2", "femcum3", "femcum4", "femcum5", \
						"femcum6", "femcum7", "femcum8", "femcum9", "femcum10", \
						"femcum11", "femcum12")
	color = COLOR_WHITE_FEMCUM
	blood_state = BLOOD_STATE_FEMCUM
	beauty = -200
	clean_type = CLEAN_TYPE_BLOOD

/obj/effect/decal/cleanable/blood/footprints/femcum
	name = "squirt footprints"
	desc = "Someone had fun."
	dryname = "dry squirt footprints"
	drydesc = "Someone had fun, a long time ago..."
	icon = 'modular_septic/icons/effects/femcum_footprints.dmi'
	icon_state = "femcum1"
	color = COLOR_WHITE_FEMCUM
	blood_state = BLOOD_STATE_FEMCUM
	beauty = -200
	clean_type = CLEAN_TYPE_BLOOD


code:
//Blood splattering, taken from hippiestation
/obj/effect/decal/cleanable/blood/hitsplatter
	name = "blood splatter"
	pass_flags = PASSTABLE | PASSMOB
	icon = 'modular_septic/icons/effects/blood.dmi'
	icon_state = "hitsplatter1"
	random_icon_states = list("hitsplatter1", "hitsplatter2", "hitsplatter3")
	var/turf/prev_loc
	var/loc_gets_bloody = TRUE
	var/amount = 2

/obj/effect/decal/cleanable/blood/hitsplatter/Initialize(mapload, list/blood_dna, bloody = TRUE)
	. = ..()
	add_blood_DNA(blood_dna)
	loc_gets_bloody = bloody
	prev_loc = loc //Just so we are sure prev_loc exists

/obj/effect/decal/cleanable/blood/hitsplatter/Destroy()
	if(isturf(loc) && loc_gets_bloody)
		loc.add_blood_DNA(return_blood_DNA())
	prev_loc = null
	return ..()

/obj/effect/decal/cleanable/blood/hitsplatter/proc/do_squirt(direction = SOUTH, range = 3, instant = FALSE)
	if(!direction)
		direction = pick(GLOB.alldirs)
		INVOKE_ASYNC(src, .proc/squirt_process, direction, range, instant)
		return TRUE
	//we need to return IMMEDIATELY to avoid bonkers stuff
	INVOKE_ASYNC(src, .proc/squirt_process, direction, range, instant)
	return TRUE

/obj/effect/decal/cleanable/blood/hitsplatter/proc/squirt_process(direction, range, instant = FALSE)
	if(range)
		for(var/i in 1 to range)
			if(QDELETED(src))
				return
			prev_loc = loc
			if(!instant)
				sleep(1)
			Move(get_step(src, direction))
	if(!QDELETED(src))
		qdel(src)

/obj/effect/decal/cleanable/blood/hitsplatter/Bump(atom/A)
	. = ..()
	if(istype(A, /turf/closed/wall) || istype(A, /obj/structure/window) || istype(A, /obj/structure/grille))
		var/commit_die = TRUE
		var/direction = get_dir(src, A)
		if(istype(A, /obj/structure/window))
			var/obj/structure/window/window = A
			if(!window.fulltile)
				if(!(direction == window.dir || direction == REVERSE_DIR(window.dir)))
					commit_die = FALSE
		if(commit_die)
			loc_gets_bloody = FALSE
			var/obj/effect/decal/cleanable/blood/splatter/blood = new(loc)
			blood.add_blood_DNA(return_blood_DNA())
			blood.layer = BELOW_MOB_LAYER
			blood.plane = GAME_PLANE
			//Adjust pixel offset to make splatters appear on the wall
			blood.pixel_x = (dir == EAST ? 32 : (dir == WEST ? -32 : 0))
			blood.pixel_y = (dir == NORTH ? 32 : (dir == SOUTH ? -32 : 0))
			qdel(src)
	else
		A.add_blood_DNA(return_blood_DNA())
	amount--
	A.update_appearance()
	if(amount <= 0 && !QDELETED(src))
		qdel(src)


code:
/obj/effect/decal/cleanable/blood/shit
	name = "shit"
	desc = "This is disgusting."
	dryname = "crusty dry shit"
	drydesc = "At least it doesn't smell as bad as before..."
	icon = 'modular_septic/icons/effects/shit.dmi'
	icon_state = "poosplat1"
	random_icon_states = list("poosplat1", "poosplat2", "poosplat3", "poosplat4", "poosplat5", \
						"poosplat6", "poosplat7", "poosplat8")
	blood_state = BLOOD_STATE_SHIT
	beauty = -300
	clean_type = CLEAN_TYPE_BLOOD

/obj/effect/decal/cleanable/blood/footprints/shit
	name = "shitty footprints"
	desc = "This is disgusting."
	dryname = "dry shitty footprints"
	drydesc = "At least it doesn't smell as bad as before..."
	icon = 'modular_septic/icons/effects/shit_footprints.dmi'
	icon_state = "poo1"
	blood_state = BLOOD_STATE_SHIT
	beauty = -300
	clean_type = CLEAN_TYPE_BLOOD


code:
/obj/effect/decal/cleanable/vomit/Initialize()
	. = ..()
	AddElement(/datum/element/pollution_emitter, /datum/pollutant/decaying_waste, 10)


code:
/obj/effect/decal/cleanable/greenglow/Initialize()
	. = ..()
	AddElement(/datum/element/pollution_emitter, /datum/pollutant/chemical_vapors, 10)


code:
/obj/effect/turf_decal
	icon = 'modular_septic/icons/turf/decals.dmi'


code:
/obj/effect/turf_decal/stripes/line
	icon_state = "warningline"

/obj/effect/turf_decal/stripes/end
	icon_state = "warn_end"

/obj/effect/turf_decal/stripes/corner
	icon_state = "warninglinecorner"

/obj/effect/turf_decal/stripes/box
	icon_state = "warn_box"

/obj/effect/turf_decal/stripes/full
	icon_state = "warn_full"

/obj/effect/turf_decal/stripes/asteroid/line
	icon_state = "ast_warn"

/obj/effect/turf_decal/stripes/asteroid/end
	icon_state = "ast_warn_end"

/obj/effect/turf_decal/stripes/asteroid/corner
	icon_state = "ast_warn_corner"

/obj/effect/turf_decal/stripes/asteroid/box
	icon_state = "ast_warn_box"

/obj/effect/turf_decal/stripes/asteroid/full
	icon_state = "ast_warn_full"

/obj/effect/turf_decal/stripes/white
	color = "#A7A3A6"

/obj/effect/turf_decal/stripes/white/line
	icon_state = "gs_wline"

/obj/effect/turf_decal/stripes/white/end
	icon_state = "gs_wline_end"

/obj/effect/turf_decal/stripes/white/corner
	icon_state = "gs_wline_corner"

/obj/effect/turf_decal/stripes/white/box
	icon_state = "gs_wbox"

/obj/effect/turf_decal/stripes/white/full
	icon_state = "gs_wbox_full"

/obj/effect/turf_decal/stripes/red
	color = "#801000"

/obj/effect/turf_decal/stripes/red/line
	icon_state = "gs_wline"

/obj/effect/turf_decal/stripes/red/end
	icon_state = "gs_wline_end"

/obj/effect/turf_decal/stripes/red/corner
	icon_state = "gs_wline_corner"

/obj/effect/turf_decal/stripes/red/box
	icon_state = "gs_wbox"

/obj/effect/turf_decal/stripes/red/full
	icon_state = "gs_wbox_full"

/obj/effect/turf_decal/delivery
	icon_state = "gs_delivery"
	color = "#DCDC4BD7"

/obj/effect/turf_decal/delivery/white
	color = "#A7A3A6"

/obj/effect/turf_decal/delivery/red
	color = "#801000"

/obj/effect/turf_decal/bot
	icon_state = "gs_bot"
	color = "#DCDC4BD7" //okay, i've sacrificed a goat and my firstborn. let's hope that works

/obj/effect/turf_decal/bot/right
	icon_state = "gs_bot_sr"

/obj/effect/turf_decal/bot/left
	icon_state = "gs_bot_sl"

/obj/effect/turf_decal/bot_white
	icon_state = "gs_bot"
	color = "#A7A3A6"

/obj/effect/turf_decal/bot_white/right
	icon_state = "gs_bot_sr"

/obj/effect/turf_decal/bot_white/left
	icon_state = "gs_bot_sl"

/obj/effect/turf_decal/bot_red
	icon_state = "gs_bot"
	color = "#801000"

/obj/effect/turf_decal/bot_red/right
	icon_state = "gs_bot_sr"

/obj/effect/turf_decal/bot_red/left
	icon_state = "gs_bot_sl"

/obj/effect/turf_decal/loading_area
	icon_state = "gs_larea_full"
	color = "#DCDC4BD7"

/obj/effect/turf_decal/loading_area/white
	color = "#A7A3A6"

/obj/effect/turf_decal/loading_area/red
	color = "#801000"

/obj/effect/turf_decal/caution
	icon_state = "gs_caution"
	color = "#DCDC4BD7"

/obj/effect/turf_decal/caution/white
	color = "#A7A3A6"

/obj/effect/turf_decal/caution/red
	color = "#801000"

/obj/effect/turf_decal/caution/stand_clear
	icon_state = "gs_stand_clear"
	color = "#DCDC4BD7"

/obj/effect/turf_decal/caution/stand_clear/white
	color = "#A7A3A6"

/obj/effect/turf_decal/caution/stand_clear/red
	color = "#801000"

/obj/effect/turf_decal/arrows
	icon_state = "gs_arrows"
	color = "#DCDC4BD7"

/obj/effect/turf_decal/arrows/white
	color = "#A7A3A6"

/obj/effect/turf_decal/arrows/red
	color = "#801000"

/obj/effect/turf_decal/box
	icon_state = "gs_rbox"
	color = "#DCDC4BD7"

/obj/effect/turf_decal/box/corners
	icon_state = "gs_rbox_corner"

/obj/effect/turf_decal/box/white
	color = "#A7A3A6"

/obj/effect/turf_decal/box/white/corners
	icon_state = "gs_rbox_corner"
	color = "#A7A3A6"

/obj/effect/turf_decal/box/red
	color = "#801000"

/obj/effect/turf_decal/box/red/corners
	icon_state = "gs_rbox_corner"
	color = "#801000"

/obj/effect/turf_decal/plaque
	icon_state = "plaque"

/obj/effect/turf_decal/mining
	icon_state = "mining"

/obj/effect/turf_decal/mining/survival
	icon_state = "survival"

/obj/effect/turf_decal/siding
	icon_state = "siding_line"

/obj/effect/turf_decal/siding/white
	color = "#BCBCBC"

/obj/effect/turf_decal/siding/white/corner
	icon_state = "siding_corner"

/obj/effect/turf_decal/siding/white/end
	icon_state = "siding_end"

/obj/effect/turf_decal/siding/red
	color = "#DE3A3A"

/obj/effect/turf_decal/siding/red/corner
	icon_state = "siding_corner"

/obj/effect/turf_decal/siding/red/end
	icon_state = "siding_end"

/obj/effect/turf_decal/siding/green
	color = "#9FED58"

/obj/effect/turf_decal/siding/green/corner
	icon_state = "siding_corner"

/obj/effect/turf_decal/siding/green/end
	icon_state = "siding_end"

/obj/effect/turf_decal/siding/blue
	color = "#52B4E9"

/obj/effect/turf_decal/siding/blue/corner
	icon_state = "siding_corner"

/obj/effect/turf_decal/siding/blue/end
	icon_state = "siding_end"

/obj/effect/turf_decal/siding/yellow
	color = "#EFB341"

/obj/effect/turf_decal/siding/yellow/corner
	icon_state = "siding_corner"

/obj/effect/turf_decal/siding/yellow/end
	icon_state = "siding_end"

/obj/effect/turf_decal/siding/purple
	color = "#D381C9"

/obj/effect/turf_decal/siding/purple/corner
	icon_state = "siding_corner"

/obj/effect/turf_decal/siding/purple/end
	icon_state = "siding_end"

/obj/effect/turf_decal/siding/brown
	color = "#A46106"

/obj/effect/turf_decal/siding/brown/corner
	icon_state = "siding_corner"

/obj/effect/turf_decal/siding/brown/end
	icon_state = "siding_end"

/obj/effect/turf_decal/siding/wood
	icon_state = "siding_wood_line"
	color = "#55391A"

/obj/effect/turf_decal/siding/wood/corner
	icon_state = "siding_wood_corner"

/obj/effect/turf_decal/siding/wood/end
	icon_state = "siding_wood_end"

/obj/effect/turf_decal/siding/thinplating
	icon_state = "siding_thinplating_line"
	color = "#aaaaaa"

/obj/effect/turf_decal/siding/thinplating/corner
	icon_state = "siding_thinplating_corner"

/obj/effect/turf_decal/siding/thinplating/end
	icon_state = "siding_thinplating_end"

/obj/effect/turf_decal/siding/thinplating/light
	color = "#FFFFFF"

/obj/effect/turf_decal/siding/thinplating/light/corner
	icon_state = "siding_thinplating_corner"

/obj/effect/turf_decal/siding/thinplating/light/end
	icon_state = "siding_thinplating_end"

/obj/effect/turf_decal/siding/thinplating/dark
	icon_state = "siding_thinplating_line"
	color = "#474747"

/obj/effect/turf_decal/siding/thinplating/dark/corner
	icon_state = "siding_thinplating_corner"

/obj/effect/turf_decal/siding/thinplating/dark/end
	icon_state = "siding_thinplating_end"

/obj/effect/turf_decal/siding/wideplating
	icon_state = "siding_wideplating_line"
	color = "#aaaaaa"

/obj/effect/turf_decal/siding/wideplating/corner
	icon_state = "siding_wideplating_corner"

/obj/effect/turf_decal/siding/wideplating/end
	icon_state = "siding_wideplating_end"

/obj/effect/turf_decal/siding/wideplating/light
	color = "#FFFFFF"

/obj/effect/turf_decal/siding/wideplating/light/corner
	icon_state = "siding_wideplating_corner"

/obj/effect/turf_decal/siding/wideplating/light/end
	icon_state = "siding_wideplating_end"

/obj/effect/turf_decal/siding/wideplating/dark
	icon_state = "siding_wideplating_line"
	color = "#474747"

/obj/effect/turf_decal/siding/wideplating/dark/corner
	icon_state = "siding_wideplating_corner"

/obj/effect/turf_decal/siding/wideplating/dark/end
	icon_state = "siding_wideplating_end"

/obj/effect/turf_decal/raven_ship_sign
	icon_state = "RAVEN2"

/obj/effect/turf_decal/raven/one
	icon_state = "RAVEN1"

/obj/effect/turf_decal/raven/two
	icon_state = "RAVEN2"

/obj/effect/turf_decal/raven/three
	icon_state = "RAVEN3"

/obj/effect/turf_decal/raven/four
	icon_state = "RAVEN4"

/obj/effect/turf_decal/raven/five
	icon_state = "RAVEN5"

/obj/effect/turf_decal/raven/six
	icon_state = "RAVEN6"

/obj/effect/turf_decal/raven/seven
	icon_state = "RAVEN7"

/obj/effect/turf_decal/raven/eight
	icon_state = "RAVEN8"

/obj/effect/turf_decal/raven/nine
	icon_state = "RAVEN9"

/obj/effect/turf_decal/monocolor/white
	color = "#A7A3A6"

/obj/effect/turf_decal/monocolor/white/oxy
	icon_state = "gs_oxy"

/obj/effect/turf_decal/monocolor/white/n2
	icon_state = "gs_n2"

/obj/effect/turf_decal/monocolor/white/air
	icon_state = "gs_air"

/obj/effect/turf_decal/monocolor/white/co2
	icon_state = "gs_co2"

/obj/effect/turf_decal/monocolor/white/plasma
	icon_state = "gs_tox"

/obj/effect/turf_decal/monocolor/white/n2o
	icon_state = "gs_n2o"

/obj/effect/turf_decal/monocolor/white/mix
	icon_state = "gs_mix"

/obj/effect/turf_decal/monocolor/white/radwarning
	icon_state = "gs_radwarn"

/obj/effect/turf_decal/monocolor/white/number/one
	icon_state = "gs_nr_1"

/obj/effect/turf_decal/monocolor/white/number/two
	icon_state = "gs_nr_2"

/obj/effect/turf_decal/monocolor/white/number/three
	icon_state = "gs_nr_3"

/obj/effect/turf_decal/monocolor/white/number/four
	icon_state = "gs_nr_4"

/obj/effect/turf_decal/monocolor/white/number/five
	icon_state = "gs_nr_5"

/obj/effect/turf_decal/monocolor/white/number/six
	icon_state = "gs_nr_6"

/obj/effect/turf_decal/monocolor/white/number/seven
	icon_state = "gs_nr_7"

/obj/effect/turf_decal/monocolor/white/number/eight
	icon_state = "gs_nr_8"

/obj/effect/turf_decal/monocolor/white/number/nine
	icon_state = "gs_nr_9"

/obj/effect/turf_decal/monocolor/white/number/zero
	icon_state = "gs_nr_0"

/obj/effect/turf_decal/monocolor/white/hop
	icon_state = "gs_hop"

/obj/effect/turf_decal/monocolor/white/cargo
	icon_state = "gs_cargo"

/obj/effect/turf_decal/monocolor/white/med
	icon_state = "gs_mef"

/obj/effect/turf_decal/monocolor/white/sci
	icon_state = "gs_scir"

/obj/effect/turf_decal/monocolor/white/sec
	icon_state = "gs_sec"

/obj/effect/turf_decal/monocolor/white/mine
	icon_state = "gs_mine"

/obj/effect/turf_decal/monocolor/white/bar
	icon_state = "gs_bar"

/obj/effect/turf_decal/monocolor/white/zoo
	icon_state = "gs_zoo"

/obj/effect/turf_decal/no_entry
	icon_state = "no_entry"

/obj/effect/turf_decal/rad_warning
	icon_state = "radwarn"


code:
/obj/effect/turf_decal/tile/Initialize()
	if(SSevents.holidays && SSevents.holidays[APRIL_FOOLS])
		color = "#[random_short_color()]"
	return ..()

/// White tiles, fuck TG

/obj/effect/turf_decal/tile/white
	name = "white corner"
	color = "#FFFFFF"

/obj/effect/turf_decal/tile/white/half
	icon_state = "tile_half"
	name = "white half"

/obj/effect/turf_decal/tile/white/anticorner
	icon_state = "tile_anticorner"
	name = "white anticorner"

/obj/effect/turf_decal/tile/white/full
	icon_state = "tile_full"
	name = "white full"


code:
/obj/effect/temp_visual/dir_setting/firing_effect
	light_range = 2
	light_power = 1
	light_color = LIGHT_COLOR_FIRE


code:
/obj/item
	drop_sound = 'modular_septic/sound/items/drop.wav'

	/// How much time we (normally) take to recover from attacking with this
	var/attack_delay = CLICK_CD_MELEE
	/// How much fatigue we (normally) take away from the user when attacking with this - If null, we assume a standard value
	var/attack_fatigue_cost = null

	/// Organ storage component requires this
	var/atom/stored_in
	/// Stat used in melee combat
	var/stat_melee = STAT_DEXTERITY
	/// Skill used in melee combat
	var/skill_melee = SKILL_MELEE
	/// Specialty skill used in melee combat (polearm, blunt, axe, etc)
	var/specialty_melee
	/// Stat used in ranged combat
	var/stat_ranged = STAT_INTELLIGENCE
	/// Skill used in  ranged combat
	var/skill_ranged = SKILL_RANGED
	/// Specialty skill used in ranged combat
	var/specialty_ranged
	/// Used for unturning when picked up by a mob
	var/our_angle = 0

	//Mutant icon garbage
	var/worn_icon_muzzled = 'modular_septic/icons/mob/clothing/head_muzzled.dmi'
	var/worn_icon_digi = 'modular_septic/icons/mob/clothing/suit_digi.dmi'
	var/worn_icon_taur_snake = 'modular_septic/icons/mob/clothing/suit_taur_snake.dmi'
	var/worn_icon_taur_paw = 'modular_septic/icons/mob/clothing/suit_taur_paw.dmi'
	var/worn_icon_taur_hoof = 'modular_septic/icons/mob/clothing/suit_taur_hoof.dmi'
	var/mutant_variants = NONE

	//Only mattters when worn on the head
	var/fov_angle = 0
	var/fov_shadow_angle

	//This is used to calculate encumbrance on human mobs
	var/carry_weight


code:
//initializing carry weight
/obj/item/Initialize()
	. = ..()
	//we don't want items to have no carry weight - default to (w_class^2)/2
	if(isnull(carry_weight))
		carry_weight = (w_class**2)/4
	//we don't want items with null attack cost
	if(isnull(attack_fatigue_cost))
		attack_fatigue_cost = 1.5*w_class

//organ storage stuff
/obj/item/Destroy()
	if(stored_in)
		stored_in.handle_atom_del(src)
	return ..()

//cool throwing animation
/obj/item/on_thrown(mob/living/carbon/user, atom/target)
	if((item_flags & ABSTRACT) || HAS_TRAIT(src, TRAIT_NODROP))
		return
	user.dropItemToGround(src, silent = TRUE)
	if(throwforce && HAS_TRAIT(user, TRAIT_PACIFISM))
		to_chat(user, span_notice("I set [src] down gently on the ground."))
		return
	undo_messy()
	do_messy(duration = 4)
	return src

//fov stuff
/obj/item/equipped(mob/user, slot, initial)
	. = ..()
	if((fov_angle || fov_shadow_angle) && (slot & ITEM_SLOT_HEAD|ITEM_SLOT_MASK))
		var/datum/component/field_of_vision/fov = user.GetComponent(/datum/component/field_of_vision)
		if(fov)
			fov.generate_fov_holder(source = user, _angle = fov_angle, _shadow_angle = fov_shadow_angle)

//after attack cancelling
/obj/item/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
	if(SEND_SIGNAL(src, COMSIG_ITEM_AFTERATTACK, target, user, proximity_flag, click_parameters) & COMPONENT_CANCEL_ATTACK_CHAIN)
		return TRUE
	else if(SEND_SIGNAL(user, COMSIG_MOB_ITEM_AFTERATTACK, target, user, proximity_flag, click_parameters) & COMPONENT_CANCEL_ATTACK_CHAIN)
		return TRUE

//embedding stuff
/obj/item/embedded(atom/embedded_target, obj/item/bodypart/part)
	SEND_SIGNAL(src, COMSIG_ITEM_EMBEDDED, embedded_target, part)
	return ..()

/obj/item/unembedded(atom/embedded_target, obj/item/bodypart/part)
	SEND_SIGNAL(src, COMSIG_ITEM_UNEMBEDDED, embedded_target, part)
	return ..()

//fuck this
/obj/item/do_pickup_animation(atom/target)
	return

/obj/item/on_exit_storage(datum/component/storage/concrete/master_storage)
	. = ..()
	stored_in =  null

/obj/item/onZImpact(turf/T, levels)
	. = ..()
	undo_messy()
	do_messy(duration = 4)

/obj/item/germ_level_examine(mob/user)
	switch(germ_level)
		if(0 to GERM_LEVEL_DIRTY)
			return "[src] is clean."
		if(GERM_LEVEL_DIRTY to GERM_LEVEL_FILTHY)
			return "[src] is a bit dirty."
		if(GERM_LEVEL_FILTHY to GERM_LEVEL_SMASHPLAYER)
			return span_warning("[src] is filthy.")
		if(GERM_LEVEL_SMASHPLAYER to INFINITY)
			return span_warning("[src] is abominably foul.")

/obj/item/examine_chaser(mob/user)
	if(src in user.held_items)
		return "[src] weighs around <b>[FLOOR(get_carry_weight(), 1)]kg</b>."

//cool drop and throw effect
/obj/item/proc/do_messy(pixel_variation = 8, angle_variation = 360, duration = 0)
	if(item_flags & NO_PIXEL_RANDOM_DROP)
		return
	animate(src, pixel_x = (base_pixel_x+rand(-pixel_variation,pixel_variation)), duration)
	animate(src, pixel_y = (base_pixel_y+rand(-pixel_variation,pixel_variation)), duration)
	if(our_angle)
		animate(src, transform = transform.Turn(-our_angle), duration)
		our_angle = 0
	our_angle = rand(0,angle_variation)
	transform = transform.Turn(our_angle)

/obj/item/proc/undo_messy(duration = 0)
	animate(src, pixel_x = base_pixel_x, duration)
	animate(src, pixel_y = base_pixel_y, duration)
	if(our_angle)
		animate(src, transform = transform.Turn(-our_angle), duration)
		our_angle = 0

/obj/item/proc/spread_filth(atom/filthy)
	var/filth = FLOOR(germ_level/10, 1)
	if(filth && filthy)
		filthy.adjust_germ_level(filth)

/obj/item/proc/get_carry_weight()
	. = carry_weight
	var/datum/component/storage/storage = GetComponent(/datum/component/storage)
	if(storage)
		. += storage.get_carry_weight()


code:
/obj/item/match
	carry_weight = 0.05

/obj/item/match/matchignite()
	if(lit || burnt)
		return

	playsound(src, 'sound/items/match_strike.ogg', 15, TRUE)
	lit = TRUE
	var/turf/my_turf = get_turf(src)
	if(istype(my_turf))
		my_turf.pollute_turf(/datum/pollutant/sulphur, 5)
	icon_state = "match_lit"
	damtype = BURN
	force = 3
	hitsound = 'sound/items/welder.ogg'
	inhand_icon_state = "cigon"
	name = "lit [initial(name)]"
	desc = "A [initial(name)]. This one is lit."
	attack_verb_continuous = string_list(list("burns", "singes"))
	attack_verb_simple = string_list(list("burn", "singe"))
	START_PROCESSING(SSobj, src)
	update_appearance()

/obj/item/clothing/mask/cigarette
	name = "cancer stick"
	desc = "Now with 99% less asbestos. Still not very safe for human consumption."
	lung_harm = 0
	carry_weight = 0.1
	/// What type of pollution does this produce on smoking, changed to weed pollution sometimes
	var/pollution_type = /datum/pollutant/smoke

/obj/item/clothing/mask/cigarette/light(flavor_text = null)
	if(lit)
		return
	if(!(flags_1 & INITIALIZED_1))
		icon_state = icon_on
		inhand_icon_state = icon_on
		return

	lit = TRUE
	name = "lit [name]"
	attack_verb_continuous = string_list(list("burns", "singes"))
	attack_verb_simple = string_list(list("burn", "singe"))
	hitsound = 'sound/items/welder.ogg'
	damtype = BURN
	force = 4
	if(reagents.get_reagent_amount(/datum/reagent/toxin/plasma)) // the plasma explodes when exposed to fire
		var/datum/effect_system/reagents_explosion/e = new()
		e.set_up(round(reagents.get_reagent_amount(/datum/reagent/toxin/plasma) / 2.5, 1), get_turf(src), 0, 0)
		e.start()
		qdel(src)
		return
	if(reagents.get_reagent_amount(/datum/reagent/fuel)) // the fuel explodes, too, but much less violently
		var/datum/effect_system/reagents_explosion/e = new()
		e.set_up(round(reagents.get_reagent_amount(/datum/reagent/fuel) / 5, 1), get_turf(src), 0, 0)
		e.start()
		qdel(src)
		return
	// Setting the puffed pollutant to cannabis if we're smoking the space drugs reagent(obtained from cannabis)
	if(reagents.has_reagent(/datum/reagent/drug/space_drugs))
		pollution_type = /datum/pollutant/smoke/cannabis
	// allowing reagents to react after being lit
	reagents.flags &= ~(NO_REACT)
	reagents.handle_reactions()
	icon_state = icon_on
	inhand_icon_state = icon_on
	if(flavor_text)
		var/turf/T = get_turf(src)
		T.visible_message(flavor_text)
	START_PROCESSING(SSobj, src)

	//can't think of any other way to update the overlays :<
	if(ismob(loc))
		var/mob/M = loc
		M.update_inv_wear_mask()
		M.update_inv_hands()

/obj/item/clothing/mask/cigarette/process(delta_time)
	var/turf/location = get_turf(src)
	var/mob/living/M = loc
	if(isliving(loc))
		M.IgniteMob()
	if(!reagents.has_reagent(/datum/reagent/oxygen)) //cigarettes need oxygen
		var/datum/gas_mixture/air = return_air()
		if(!air || !air.has_gas(/datum/gas/oxygen, 1)) //or oxygen on a tile to burn
			extinguish()
			return
	if(pollution_type)
		location.pollute_turf(pollution_type, 10)
	smoketime -= delta_time * (1 SECONDS)
	if(smoketime <= 0)
		new type_butt(location)
		if(ismob(loc))
			to_chat(M, span_notice("Your [name] goes out."))
		qdel(src)
		return

	open_flame(heat)
	if((reagents?.total_volume) && COOLDOWN_FINISHED(src, drag_cooldown))
		COOLDOWN_START(src, drag_cooldown, dragtime)
		handle_reagents()

/obj/item/clothing/mask/cigarette/space_cigarette
	name = "asbestos stick"
	desc = "A very low quality cigarette. Smoking this can't do you any good."
	lung_harm = 1

/obj/item/clothing/mask/cigarette/rollie
	name = "cancer roll"
	desc = "A roll of dried plant matter wrapped in thin paper. About as cancerous as the factory-made stuff."

/obj/item/clothing/mask/cigarette/candy
	name = "\improper little Timmy's first carcinoma"

/obj/item/clothing/mask/cigarette/cigar
	name = "cancer cylinder"
	lung_harm = 0

/obj/item/clothing/mask/cigarette/cigar/cohiba
	name = "\improper Cohiba Robusto cancer cylinder"

/obj/item/clothing/mask/cigarette/cigar/havana
	name = "premium Havanian carcinoma"

/obj/item/clothing/mask/vape/process(delta_time)
	var/mob/living/M = loc

	if(isliving(loc))
		M.IgniteMob()

	if(!reagents.total_volume)
		if(ismob(loc))
			to_chat(M, span_warning("[src] is empty!"))
			STOP_PROCESSING(SSobj, src)
			//it's reusable so it won't unequip when empty
		return

	if(!COOLDOWN_FINISHED(src, drag_cooldown))
		return

	//Time to start puffing those fat vapes, yo.
	var/turf/my_turf = get_turf(src)
	if(istype(my_turf))
		my_turf.pollute_turf(/datum/pollutant/smoke/vape, 10)
	COOLDOWN_START(src, drag_cooldown, dragtime)
	if(obj_flags & EMAGGED)
		var/datum/effect_system/smoke_spread/chem/smoke_machine/s = new
		s.set_up(reagents, 4, 24, loc)
		s.start()
		if(prob(5)) //small chance for the vape to break and deal damage if it's emagged
			playsound(get_turf(src), 'sound/effects/pop_expl.ogg', 50, FALSE)
			M.apply_damage(20, BURN, BODY_ZONE_HEAD)
			M.Paralyze(300)
			var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread
			sp.set_up(5, 1, src)
			sp.start()
			to_chat(M, span_userdanger("[src] suddenly explodes in your mouth!"))
			qdel(src)
			return
	else if(super)
		var/datum/effect_system/smoke_spread/chem/smoke_machine/s = new
		s.set_up(reagents, 1, 24, loc)
		s.start()

	handle_reagents()


code:
/obj/item/candle
	carry_weight = 0.1
	/// Pollutant type for scented candles
	var/scented_type

/obj/item/candle/process(delta_time)
	if(!lit)
		return PROCESS_KILL
	if(!infinite)
		wax -= delta_time
	if(wax <= 0)
		new /obj/item/trash/candle(loc)
		qdel(src)
	if(scented_type)
		var/turf/my_turf = get_turf(src)
		if(istype(my_turf))
			my_turf.pollute_turf(scented_type, 5)
	update_appearance()
	open_flame()

/obj/item/candle/vanilla
	name = "vanilla scented candle"
	scented_type = /datum/pollutant/fragrance/vanilla

/obj/item/candle/pear
	name = "pear scented candle"
	scented_type = /datum/pollutant/fragrance/pear

/obj/item/candle/amber
	name = "amber scented candle"
	scented_type = /datum/pollutant/fragrance/amber

/obj/item/candle/jasmine
	name = "jasmine scented candle"
	scented_type = /datum/pollutant/fragrance/jasmine

/obj/item/candle/mint
	name = "mint scented candle"
	scented_type = /datum/pollutant/fragrance/mint


code:
//SS13 ones seem to be on the heavier side of defibs
/obj/item/defibrillator
	carry_weight = 4

/obj/item/defibrillator/Initialize()
	. = ..()
	AddElement(/datum/element/multitool_emaggable)

/obj/item/defibrillator/compact
	carry_weight = 3


code:
/obj/item/radio/headset
	carry_weight = 0.25
	send_chatter = sound('modular_septic/sound/radio/common.ogg', FALSE, 0, CHANNEL_RADIO_CHATTER, 50)

/obj/item/radio/headset/headset_sec/alt
	send_chatter = sound('modular_septic/sound/radio/security.ogg', FALSE, 0, CHANNEL_RADIO_CHATTER, 60)

/obj/item/radio/headset/heads/captain/alt
	send_chatter = sound('modular_septic/sound/radio/security.ogg', FALSE, 0, CHANNEL_RADIO_CHATTER, 60)

/obj/item/radio/headset/heads/hos/alt
	send_chatter = sound('modular_septic/sound/radio/security.ogg', FALSE, 0, CHANNEL_RADIO_CHATTER, 60)

/obj/item/radio/headset/headset_cent/alt
	send_chatter = sound('modular_septic/sound/radio/security.ogg', FALSE, 0, CHANNEL_RADIO_CHATTER, 60)

/obj/item/radio/headset/syndicate
	//Somewhat stealthy
	send_chatter = sound('modular_septic/sound/radio/syndie.ogg', FALSE, 0, CHANNEL_RADIO_CHATTER, 35)


code:
//add whatsapp
/obj/item/pda
	carry_weight = 0.5
	ttone = "zap"

/obj/item/pda/receive_message(datum/signal/subspace/messaging/pda/signal)
	tnote += "← From [signal.data["name"]] ([signal.data["job"]]):
[signal.format_message()]
"

	if (!silent)
		if(HAS_TRAIT(SSstation, STATION_TRAIT_PDA_GLITCHED))
			playsound(src, pick('sound/machines/twobeep_voice1.ogg', 'sound/machines/twobeep_voice2.ogg'), 50, TRUE)
		else if(ttone != "zap")
			playsound(src, 'sound/machines/twobeep_high.ogg', 50, TRUE)
		else
			playsound(src, 'modular_septic/sound/effects/whatsapp.ogg', 40, FALSE)
		audible_message(span_infoplain("[icon2html(src, hearers(src))] *[ttone]*"), null, 3)
	//Search for holder of the PDA.
	var/mob/living/L = null
	if(loc && isliving(loc))
		L = loc
	//Maybe they are a pAI!
	else
		L = get(src, /mob/living/silicon)

	if(L && (L.stat == CONSCIOUS || L.stat == SOFT_CRIT))
		var/reply = "(Reply)"
		var/hrefstart
		var/hrefend
		if (isAI(L))
			hrefstart = ""
			hrefend = ""

		if(signal.data["automated"])
			reply = "\[Automated Message\]"

		var/inbound_message = signal.format_message()
		if(signal.data["emojis"] == TRUE)//so will not parse emojis as such from pdas that don't send emojis
			inbound_message = emoji_parse(inbound_message)

		to_chat(L, span_infoplain("[icon2html(src)] PDA message from [hrefstart][signal.data["name"]] ([signal.data["job"]])[hrefend], [inbound_message] [reply]"))

	update_appearance()
	add_overlay(icon_alert)


code:
/obj/item/radio
	carry_weight = 0.6
	var/sound/send_chatter = sound('modular_septic/sound/radio/common.ogg', FALSE, 0, CHANNEL_RADIO_CHATTER, 50)
	var/sound/receive_chatter = sound('modular_septic/sound/radio/radio_chatter.ogg', FALSE, 0, CHANNEL_RADIO_CHATTER, 50)

/obj/item/radio/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods)
	. = ..()
	if(radio_freq && receive_chatter)
		playsound(src, receive_chatter.file, receive_chatter.volume, FALSE, channel = receive_chatter.channel)

/obj/item/radio/talk_into(atom/movable/M, message, channel, list/spans, datum/language/language, list/message_mods)
	. = ..()
	if(send_chatter)
		playsound(src, send_chatter.file, send_chatter.volume, FALSE, channel = send_chatter.channel)