/*
NOTE: IF YOU UPDATE THE REAGENT-SYSTEM, ALSO UPDATE THIS README.

Structure: ///////////////////          //////////////////////////
		   // Mob or object // -------> // Reagents var (datum) // 	    Is a reference to the datum that holds the reagents.
		   ///////////////////          //////////////////////////
		   			|				    			 |
    The object that holds everything.   			 V
		   							      reagent_list var (list)   	A List of datums, each datum is a reagent.

		   							      |          |          |
		   							      V          V          V

		   							         reagents (datums)	    	Reagents. I.e. Water , antitoxins or mercury.


Random important notes:

	An objects on_reagent_change will be called every time the objects reagents change.
	Useful if you want to update the objects icon etc.

About the Holder:

	The holder (reagents datum) is the datum that holds a list of all reagents
	currently in the object.It also has all the procs needed to manipulate reagents

	Vars:
		list/datum/reagent/reagent_list
			List of reagent datums.

		total_volume
			Total volume of all reagents.

		maximum_volume
			Maximum volume.

		atom/my_atom
			Reference to the object that contains this.

	Procs:

		get_free_space()
			Returns the remaining free volume in the holder.

		get_master_reagent()
			Returns the reference to the reagent with the largest volume

		get_master_reagent_name()
			Ditto, but returns the name.

		get_master_reagent_id()
			Ditto, but returns ID.

		update_total()
			Updates total volume, called automatically.

		handle_reactions()
			Checks reagents and triggers any reactions that happen. Usually called automatically.

		add_reagent(var/id, var/amount, var/data = null, var/safety = 0)
			Adds [amount] units of [id] reagent. [data] will be passed to reagent's mix_data() or initialize_data(). If [safety] is 0, handle_reactions() will be called. Returns 1 if successful, 0 otherwise.

		remove_reagent(var/id, var/amount, var/safety = 0)
			Ditto, but removes reagent. Returns 1 if successful, 0 otherwise.

		del_reagent(var/id)
			Removes all of the reagent.

		has_reagent(var/id, var/amount = 0)
			Checks if holder has at least [amount] of [id] reagent. Returns 1 if the reagent is found and volume is above [amount]. Returns 0 otherwise.

		clear_reagents()
			Removes all reagents.

		get_reagent_amount(var/id)
			Returns reagent volume. Returns 0 if reagent is not found.

		get_data(var/id)
			Returns get_data() of the reagent.

		get_reagents()
			Returns a string containing all reagent ids and volumes, e.g. "carbon(4),nittrogen(5)".

		remove_any(var/amount = 1)
			Removes up to [amount] of reagents from [src]. Returns actual amount removed.

		trans_to_holder(var/datum/reagents/target, var/amount = 1, var/multiplier = 1, var/copy = 0)
			Transfers [amount] reagents from [src] to [target], multiplying them by [multiplier]. Returns actual amount removed from [src] (not amount transferred to [target]). If [copy] is 1, copies reagents instead.

		touch(var/atom/target)
			When applying reagents to an atom externally, touch() is called to trigger any on-touch effects of the reagent.
			This does not handle transferring reagents to things.
			For example, splashing someone with water will get them wet and extinguish them if they are on fire,
			even if they are wearing an impermeable suit that prevents the reagents from contacting the skin.
			Basically just defers to touch_mob(target), touch_turf(target), or touch_obj(target), depending on target's type.
			Not recommended to use this directly, since trans_to() calls it before attempting to transfer.

		touch_mob(var/mob/target)
			Calls each reagent's touch_mob(target).

		touch_turf(var/turf/target)
			Calls each reagent's touch_turf(target).

		touch_obj(var/obj/target)
			Calls each reagent's touch_obj(target).

		trans_to(var/atom/target, var/amount = 1, var/multiplier = 1, var/copy = 0)
			The general proc for applying reagents to things externally (as opposed to directly injected into the contents). 
			It first calls touch, then the appropriate trans_to_*() or splash_mob().
			If for some reason you want touch effects to be bypassed (e.g. injecting stuff directly into a reagent container or person), call the appropriate trans_to_*() proc.
			
			Calls touch() before checking the type of [target], calling splash_mob(target, amount), trans_to_turf(target, amount, multiplier, copy), or trans_to_obj(target, amount, multiplier, copy).

		trans_id_to(var/atom/target, var/id, var/amount = 1)
			Transfers [amount] of [id] to [target]. Returns amount transferred.

		splash_mob(var/mob/target, var/amount = 1, var/clothes = 1)
			Checks mob's clothing if [clothes] is 1 and transfers [amount] reagents to mob's skin.
			Don't call this directly. Call apply_to() instead.

		trans_to_mob(var/mob/target, var/amount = 1, var/chem_type = CHEM_BLOOD, var/multiplier = 1, var/copy = 0)
			Transfers [amount] reagents to the mob's appropriate holder, depending on [type]. Ignores protection.

		trans_to_turf(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0)
			Turfs don't currently have any reagents. Puts [amount] reagents into a temporary holder, calls touch_turf(target) from it, and deletes it.

		trans_to_obj(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0)
			If target has reagents, transfers [amount] to it. Otherwise, same as trans_to_turf().

		atom/proc/create_reagents(var/max_vol)
			Creates a new reagent datum.

About Reagents:

	Reagents are all the things you can mix and fille in bottles etc. This can be anything from
	rejuvs over water to... iron.

	Vars:

		name
			Name that shows up in-game.

		id
			ID that is used for internal tracking. MUST BE UNIQUE.

		description
			Description that shows up in-game.

		datum/reagents/holder
			Reference to holder.

		reagent_state
			Could be GAS, LIQUID, or SOLID. Affects nothing. Reserved for future use.

		list/data
			Use varies by reagent. Custom variable. For example, blood stores blood group and viruses.

		volume
			Current volume.

		metabolism
			How quickly reagent is processed in mob's bloodstream; by default aslo affects ingest and touch metabolism.

		ingest_met
			How quickly reagent is processed when ingested; [metabolism] is used if zero.

		touch_met
			Ditto when touching.

		dose
			How much of the reagent has been processed, limited by [max_dose]. Used for reagents with varying effects (e.g. ethanol or rezadone) and overdosing.

		max_dose
			Maximum amount of reagent that has ever been in a mob. Exists so dose won't grow infinitely when small amounts of reagent are added over time.

		overdose
			If [dose] is bigger than [overdose], overdose() proc is called every tick.

		scannable
			If set to 1, will show up on health analyzers by name.

		affects_dead
			If set to 1, will affect dead players. Used by Adminordrazine.

		glass_icon_state
			Used by drinks. icon_state of the glass when this reagent is the master reagent.

		glass_name
			Ditto for glass name.

		glass_desc
			Ditto for glass desciption.

		glass_center_of_mass
			Used for glass placement on tables.

		color
			"#RRGGBB" or "#RRGGBBAA" where A is alpha channel.

		color_weight
			How much reagent affects color of holder. Used by paint.

	Procs:

		remove_self(var/amount)
			Removes [amount] of itself.

		touch_mob(var/mob/M)
			Called when reagent is in another holder and not splashing the mob. Can be used with noncarbons.

		touch_obj(var/obj/O)
			How reagent reacts with objects.

		touch_turf(var/turf/T)
			How reagent reacts with turfs.

		on_mob_life(var/mob/living/carbon/M, var/alien, var/location)
			Makes necessary checks and calls one of affect procs.

		affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
			How reagent affects mob when injected. [removed] is the amount of reagent that has been removed this tick. [alien] is the mob's reagent flag.

		affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
			Ditto, ingested. Defaults to affect_blood with halved dose.

		affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
			Ditto, touching.

		overdose(var/mob/living/carbon/M, var/alien)
			Called when dose is above overdose. Defaults to M.adjustToxLoss(REM).

		initialize_data(var/newdata)
			Called when reagent is created. Defaults to setting [data] to [newdata].

		mix_data(var/newdata, var/newamount)
			Called when [newamount] of reagent with [newdata] data is added to the current reagent. Used by paint.

		get_data()
			Returns data. Can be overridden.

About Recipes:

	Recipes are simple datums that contain a list of required reagents and a result.
	They also have a proc that is called when the recipe is matched.

	Vars:

		name
			Name of the reaction, currently unused.

		id
			ID of the reaction, must be unique.

		result
			ID of the resulting reagent. Can be null.

		list/required_reagents
			Reagents that are required for the reaction and are used up during it.

		list/catalysts
			Ditto, but not used up.

		list/inhibitors
			Opposite, prevent the reaction from happening.

		result_amount
			Amount of resulting reagent.

		mix_message
			Message that is shown to mobs when reaction happens.

	Procs:

		can_happen(var/datum/reagents/holder)
			Customizable. If it returns 0, reaction will not happen. Defaults to always returning 1. Used by slime core reactions.

		on_reaction(var/datum/reagents/holder, var/created_volume)
			Called when reaction happens. Used by explosives.

		send_data(var/datum/reagents/T)
			Sets resulting reagent's data. Used by blood paint.

About the Tools:

	By default, all atom have a reagents var - but its empty. if you want to use an object for the chem.
	system you'll need to add something like this in its new proc:

		atom/proc/create_reagents(var/max_volume)

	Other important stuff:

		amount_per_transfer_from_this var
			This var is mostly used by beakers and bottles.
			It simply tells us how much to transfer when
			'pouring' our reagents into something else.

		atom/proc/is_open_container()
			Checks atom/var/flags & OPENCONTAINER.
			If this returns 1 , you can use syringes, beakers etc
			to manipulate the contents of this object.
			If it's 0, you'll need to write your own custom reagent
			transfer code since you will not be able to use the standard
			tools to manipulate it.

*/
