code:
//See also controllers/globals.dm

/// Creates a global initializer with a given InitValue expression, do not use
#define GLOBAL_MANAGED(X, InitValue)\
/datum/controller/global_vars/proc/InitGlobal##X(){\
	##X = ##InitValue;\
	gvars_datum_init_order += #X;\
}
/// Creates an empty global initializer, do not use
#define GLOBAL_UNMANAGED(X) /datum/controller/global_vars/proc/InitGlobal##X() { return; }

/// Prevents a given global from being VV'd
#ifndef TESTING
#define GLOBAL_PROTECT(X)\
/datum/controller/global_vars/InitGlobal##X(){\
	..();\
	gvars_datum_protected_varlist[#X] = TRUE;\
}
#else
#define GLOBAL_PROTECT(X)
#endif

/// Standard BYOND global, do not use
#define GLOBAL_REAL_VAR(X) var/global/##X

/// Standard typed BYOND global, do not use
#define GLOBAL_REAL(X, Typepath) var/global##Typepath/##X

/// Defines a global var on the controller, do not use
#define GLOBAL_RAW(X) /datum/controller/global_vars/var/global##X

/// Create an untyped global with an initializer expression
#define GLOBAL_VAR_INIT(X, InitValue) GLOBAL_RAW(/##X); GLOBAL_MANAGED(X, InitValue)

/// Create a global const var, do not use
#define GLOBAL_VAR_CONST(X, InitValue) GLOBAL_RAW(/const/##X) = InitValue; GLOBAL_UNMANAGED(X)

/// Create a list global with an initializer expression
#define GLOBAL_LIST_INIT(X, InitValue) GLOBAL_RAW(/list/##X); GLOBAL_MANAGED(X, InitValue)

/// Create a list global that is initialized as an empty list
#define GLOBAL_LIST_EMPTY(X) GLOBAL_LIST_INIT(X, list())

/// Create a typed list global with an initializer expression
#define GLOBAL_LIST_INIT_TYPED(X, Typepath, InitValue) GLOBAL_RAW(/list##Typepath/X); GLOBAL_MANAGED(X, InitValue)

/// Create a typed list global that is initialized as an empty list
#define GLOBAL_LIST_EMPTY_TYPED(X, Typepath) GLOBAL_LIST_INIT_TYPED(X, Typepath, list())

/// Create a typed global with an initializer expression
#define GLOBAL_DATUM_INIT(X, Typepath, InitValue) GLOBAL_RAW(Typepath/##X); GLOBAL_MANAGED(X, InitValue)

/// Create an untyped null global
#define GLOBAL_VAR(X) GLOBAL_RAW(/##X); GLOBAL_UNMANAGED(X)

/// Create a null global list
#define GLOBAL_LIST(X) GLOBAL_RAW(/list/##X); GLOBAL_UNMANAGED(X)

/// Create a typed null global
#define GLOBAL_DATUM(X, Typepath) GLOBAL_RAW(Typepath/##X); GLOBAL_UNMANAGED(X)


code:
// Stuff that is relatively "core" and is used in other defines/helpers

//Returns the hex value of a decimal number
//len == length of returned string
#define num2hex(X, len) num2text(X, len, 16)

//Returns an integer given a hex input, supports negative values "-ff"
//skips preceding invalid characters
#define hex2num(X) text2num(X, 16)

/// Stringifies whatever you put into it.
#define STRINGIFY(argument) #argument

repo_name: AnalWerewolf/sundown

license: mit


code:
#if DM_BUILD >= 1506
// We don't actually care about storing the output here, this is just an easy way to ensure the profile runs first.
GLOBAL_REAL_VAR(world_init_profiler) = world.Profile(PROFILE_RESTART)
#endif


code:
///Protects a datum from being VV'd
#define GENERAL_PROTECT_DATUM(Path)\
##Path/can_vv_get(var_name){\
	return FALSE;\
}\
##Path/vv_edit_var(var_name, var_value){\
	return FALSE;\
}\
##Path/CanProcCall(procname){\
	return FALSE;\
}


code:
/// Percentage of tick to leave for master controller to run
#define MAPTICK_MC_MIN_RESERVE 70
#define MAPTICK_LAST_INTERNAL_TICK_USAGE (world.map_cpu)

/// Tick limit while running normally
#define TICK_BYOND_RESERVE 2
#define TICK_LIMIT_RUNNING (max(100 - TICK_BYOND_RESERVE - MAPTICK_LAST_INTERNAL_TICK_USAGE, MAPTICK_MC_MIN_RESERVE))
/// Tick limit used to resume things in stoplag
#define TICK_LIMIT_TO_RUN 70
/// Tick limit for MC while running
#define TICK_LIMIT_MC 70
/// Tick limit while initializing
#define TICK_LIMIT_MC_INIT_DEFAULT (100 - TICK_BYOND_RESERVE)

/// for general usage of tick_usage
#define TICK_USAGE world.tick_usage
/// to be used where the result isn't checked
#define TICK_USAGE_REAL world.tick_usage

/// Returns true if tick_usage is above the limit
#define TICK_CHECK ( TICK_USAGE > Master.current_ticklimit )
/// runs stoplag if tick_usage is above the limit
#define CHECK_TICK ( TICK_CHECK ? stoplag() : 0 )

/// Returns true if tick usage is above 95, for high priority usage
#define TICK_CHECK_HIGH_PRIORITY ( TICK_USAGE > 95 )
/// runs stoplag if tick_usage is above 95, for high priority usage
#define CHECK_TICK_HIGH_PRIORITY ( TICK_CHECK_HIGH_PRIORITY? stoplag() : 0 )


code:
// Security equipment, security records, gulag item storage, secbots
#define ACCESS_SECURITY 1
/// Brig cells+timers, permabrig, gulag+gulag shuttle, prisoner management console
#define ACCESS_BRIG 2
/// Armory, gulag teleporter, execution chamber
#define ACCESS_ARMORY 3
///Detective's office, forensics lockers, security+medical records
#define ACCESS_FORENSICS_LOCKERS 4
/// Medical general access
#define ACCESS_MEDICAL 5
/// Morgue access
#define ACCESS_MORGUE 6
/// R&D department and R&D console
#define ACCESS_RND 7
/// Ordnance lab and burn chamber
#define ACCESS_ORDNANCE 8
/// Genetics access
#define ACCESS_GENETICS 9
/// Engineering area, power monitor, power flow control console
#define ACCESS_ENGINE 10
///APCs, EngiVend/YouTool, engineering equipment lockers
#define ACCESS_ENGINE_EQUIP 11
#define ACCESS_MAINT_TUNNELS 12
#define ACCESS_EXTERNAL_AIRLOCKS 13
#define ACCESS_CHANGE_IDS 15
#define ACCESS_AI_UPLOAD 16
#define ACCESS_TELEPORTER 17
#define ACCESS_EVA 18
/// Bridge, EVA storage windoors, gateway shutters, AI integrity restorer, comms console
#define ACCESS_HEADS 19
#define ACCESS_CAPTAIN 20
#define ACCESS_ALL_PERSONAL_LOCKERS 21
#define ACCESS_CHAPEL_OFFICE 22
#define ACCESS_TECH_STORAGE 23
#define ACCESS_ATMOSPHERICS 24
#define ACCESS_BAR 25
#define ACCESS_JANITOR 26
#define ACCESS_CREMATORIUM 27
#define ACCESS_KITCHEN 28
#define ACCESS_ROBOTICS 29
#define ACCESS_RD 30
#define ACCESS_CARGO 31
#define ACCESS_CONSTRUCTION 32
///Allows access to chemistry factory areas on compatible maps
#define ACCESS_CHEMISTRY 33
#define ACCESS_HYDROPONICS 35
#define ACCESS_LIBRARY 37
#define ACCESS_LAWYER 38
#define ACCESS_VIROLOGY 39
#define ACCESS_CMO 40
#define ACCESS_QM 41
#define ACCESS_COURT 42
#define ACCESS_SURGERY 45
#define ACCESS_THEATRE 46
#define ACCESS_RESEARCH 47
#define ACCESS_MINING 48
#define ACCESS_MAILSORTING 50
#define ACCESS_VAULT 53
#define ACCESS_MINING_STATION 54
#define ACCESS_XENOBIOLOGY 55
#define ACCESS_CE 56
#define ACCESS_HOP 57
#define ACCESS_HOS 58
/// Request console announcements
#define ACCESS_RC_ANNOUNCE 59
/// Used for events which require at least two people to confirm them
#define ACCESS_KEYCARD_AUTH 60
/// has access to the entire telecomms satellite / machinery
#define ACCESS_TCOMSAT 61
#define ACCESS_GATEWAY 62
/// Outer brig doors, department security posts
#define ACCESS_SEC_DOORS 63
/// For releasing minerals from the ORM
#define ACCESS_MINERAL_STOREROOM 64
#define ACCESS_MINISAT 65
/// Weapon authorization for secbots
#define ACCESS_WEAPONS 66
/// NTnet diagnostics/monitoring software
#define ACCESS_NETWORK 67
/// Pharmacy access (Chemistry room in Medbay)
#define ACCESS_PHARMACY 69 ///Nice.
#define ACCESS_PSYCHOLOGY 70
/// Ordnance gas storage room access
#define ACCESS_ORDNANCE_STORAGE 71
/// Room and launching.
#define ACCESS_AUX_BASE 72

	//BEGIN CENTCOM ACCESS
	/*Should leave plenty of room if we need to add more access levels.
	Mostly for admin fun times.*/
/// General facilities. CentCom ferry.
#define ACCESS_CENT_GENERAL 101
/// Thunderdome.
#define ACCESS_CENT_THUNDER 102
/// Special Ops. Captain's display case, Marauder and Seraph mechs.
#define ACCESS_CENT_SPECOPS 103
/// Medical/Research
#define ACCESS_CENT_MEDICAL 104
/// Living quarters.
#define ACCESS_CENT_LIVING 105
/// Generic storage areas.
#define ACCESS_CENT_STORAGE 106
/// Teleporter.
#define ACCESS_CENT_TELEPORTER 107
/// Captain's office/ID comp/AI.
#define ACCESS_CENT_CAPTAIN 109
/// The non-existent CentCom Bar
#define ACCESS_CENT_BAR 110

	//The Syndicate
/// General Syndicate Access. Includes Syndicate mechs and ruins.
#define ACCESS_SYNDICATE 150
/// Nuke Op Leader Access
#define ACCESS_SYNDICATE_LEADER 151

	//Away Missions or Ruins
	/*For generic away-mission/ruin access. Why would normal crew have access to a long-abandoned derelict
	or a 2000 year-old temple? */
/// Away general facilities.
#define ACCESS_AWAY_GENERAL 200
/// Away maintenance
#define ACCESS_AWAY_MAINT 201
/// Away medical
#define ACCESS_AWAY_MED 202
/// Away security
#define ACCESS_AWAY_SEC 203
/// Away engineering
#define ACCESS_AWAY_ENGINE 204
///Away generic access
#define ACCESS_AWAY_GENERIC1 205
#define ACCESS_AWAY_GENERIC2 206
#define ACCESS_AWAY_GENERIC3 207
#define ACCESS_AWAY_GENERIC4 208

	//Special, for anything that's basically internal
#define ACCESS_BLOODCULT 250

	// Mech Access, allows maintanenace of internal components and altering keycard requirements.
#define ACCESS_MECH_MINING 300
#define ACCESS_MECH_MEDICAL 301
#define ACCESS_MECH_SECURITY 302
#define ACCESS_MECH_SCIENCE 303
#define ACCESS_MECH_ENGINE 304

/// A list of access levels that, when added to an ID card, will warn admins.
#define ACCESS_ALERT_ADMINS list(ACCESS_CHANGE_IDS)

/// Logging define for ID card access changes
#define LOG_ID_ACCESS_CHANGE(user, id_card, change_description) \
	log_game("[key_name(user)] [change_description] to an ID card [(id_card.registered_name) ? "belonging to [id_card.registered_name]." : "with no registered name."]"); \
	user.investigate_log("([key_name(user)]) [change_description] to an ID card [(id_card.registered_name) ? "belonging to [id_card.registered_name]." : "with no registered name."]", INVESTIGATE_ACCESSCHANGES); \
	user.log_message("[change_description] to an ID card [(id_card.registered_name) ? "belonging to [id_card.registered_name]." : "with no registered name."]", LOG_GAME); \

/// Displayed name for Common ID card accesses.
#define ACCESS_FLAG_COMMON_NAME "Common"
/// Bitflag for Common ID card accesses. See COMMON_ACCESS.
#define ACCESS_FLAG_COMMON (1 << 0)
/// Displayed name for Command ID card accesses.
#define ACCESS_FLAG_COMMAND_NAME "Command"
/// Bitflag for Command ID card accesses. See COMMAND_ACCESS.
#define ACCESS_FLAG_COMMAND (1 << 1)
/// Displayed name for Private Command ID card accesses.
#define ACCESS_FLAG_PRV_COMMAND_NAME "Private Command"
/// Bitflag for Private Command ID card accesses. See PRIVATE_COMMAND_ACCESS.
#define ACCESS_FLAG_PRV_COMMAND (1 << 2)
/// Displayed name for Captain ID card accesses.
#define ACCESS_FLAG_CAPTAIN_NAME "Captain"
/// Bitflag for Captain ID card accesses. See CAPTAIN_ACCESS.
#define ACCESS_FLAG_CAPTAIN (1 << 3)
/// Displayed name for Centcom ID card accesses.
#define ACCESS_FLAG_CENTCOM_NAME "Centcom"
/// Bitflag for Centcom ID card accesses. See CENTCOM_ACCESS.
#define ACCESS_FLAG_CENTCOM (1 << 4)
/// Displayed name for Syndicate ID card accesses.
#define ACCESS_FLAG_SYNDICATE_NAME "Syndicate"
/// Bitflag for Syndicate ID card accesses. See SYNDICATE_ACCESS.
#define ACCESS_FLAG_SYNDICATE (1 << 5)
/// Displayed name for Offstation/Ruin/Away Mission ID card accesses.
#define ACCESS_FLAG_AWAY_NAME "Away"
/// Bitflag for Offstation/Ruin/Away Mission ID card accesses. See AWAY_ACCESS.
#define ACCESS_FLAG_AWAY (1 << 6)
/// Displayed name for Special accesses that ordinaryily shouldn't be on ID cards.
#define ACCESS_FLAG_SPECIAL_NAME "Special"
/// Bitflag for Special accesses that ordinaryily shouldn't be on ID cards. See CULT_ACCESS.
#define ACCESS_FLAG_SPECIAL (1 << 7)

/// This wildcraft flag accepts any access level.
#define WILDCARD_FLAG_ALL ALL
/// Name associated with the all wildcard bitflag.
#define WILDCARD_NAME_ALL "All"
/// Access flags that can be applied to common wildcard slots.
#define WILDCARD_FLAG_COMMON ACCESS_FLAG_COMMON
/// Name associated with the common wildcard bitflag.
#define WILDCARD_NAME_COMMON ACCESS_FLAG_COMMON_NAME
/// Access flags that can be applied to command wildcard slots.
#define WILDCARD_FLAG_COMMAND ACCESS_FLAG_COMMON | ACCESS_FLAG_COMMAND
/// Name associated with the command wildcard bitflag.
#define WILDCARD_NAME_COMMAND ACCESS_FLAG_COMMAND_NAME
/// Access flags that can be applied to private command wildcard slots.
#define WILDCARD_FLAG_PRV_COMMAND ACCESS_FLAG_COMMON | ACCESS_FLAG_COMMAND | ACCESS_FLAG_PRV_COMMAND
/// Name associated with the private command wildcard bitflag.
#define WILDCARD_NAME_PRV_COMMAND ACCESS_FLAG_PRV_COMMAND_NAME
/// Access flags that can be applied to captain wildcard slots.
#define WILDCARD_FLAG_CAPTAIN ACCESS_FLAG_COMMON | ACCESS_FLAG_COMMAND | ACCESS_FLAG_PRV_COMMAND | ACCESS_FLAG_CAPTAIN
/// Name associated with the captain wildcard bitflag.
#define WILDCARD_NAME_CAPTAIN ACCESS_FLAG_CAPTAIN_NAME
/// Access flags that can be applied to centcom wildcard slots.
#define WILDCARD_FLAG_CENTCOM ACCESS_FLAG_COMMON | ACCESS_FLAG_COMMAND | ACCESS_FLAG_PRV_COMMAND | ACCESS_FLAG_CAPTAIN | ACCESS_FLAG_CENTCOM
/// Name associated with the centcom wildcard bitflag.
#define WILDCARD_NAME_CENTCOM ACCESS_FLAG_CENTCOM_NAME
/// Access flags that can be applied to syndicate wildcard slots.
#define WILDCARD_FLAG_SYNDICATE ACCESS_FLAG_COMMON | ACCESS_FLAG_COMMAND | ACCESS_FLAG_PRV_COMMAND | ACCESS_FLAG_CAPTAIN | ACCESS_FLAG_SYNDICATE
/// Name associated with the syndicate wildcard bitflag.
#define WILDCARD_NAME_SYNDICATE ACCESS_FLAG_SYNDICATE_NAME
/// Access flags that can be applied to offstation wildcard slots.
#define WILDCARD_FLAG_AWAY ACCESS_FLAG_AWAY
/// Name associated with the offstation wildcard bitflag.
#define WILDCARD_NAME_AWAY ACCESS_FLAG_AWAY_NAME
/// Access flags that can be applied to super special weird wildcard slots.
#define WILDCARD_FLAG_SPECIAL ACCESS_FLAG_SPECIAL
/// Name associated with the super special weird wildcard bitflag.
#define WILDCARD_NAME_SPECIAL ACCESS_FLAG_SPECIAL_NAME
/// Access flag that indicates a wildcard was forced onto an ID card.
#define WILDCARD_FLAG_FORCED ALL
/// Name associated with the wildcard bitflag that covers wildcards that have been forced onto an ID card that could not accept them.
#define WILDCARD_NAME_FORCED "Hacked"

/// Departmental/general/common area accesses. Do not use direct, access via SSid_access.get_flag_access_list(ACCESS_FLAG_COMMON)
#define COMMON_ACCESS list( \
	ACCESS_MECH_MINING, \
	ACCESS_MECH_MEDICAL, \
	ACCESS_MECH_SECURITY, \
	ACCESS_MECH_SCIENCE, \
	ACCESS_MECH_ENGINE, \
	ACCESS_AUX_BASE, \
	ACCESS_PSYCHOLOGY, \
	ACCESS_PHARMACY, \
	ACCESS_NETWORK, \
	ACCESS_WEAPONS, \
	ACCESS_MINERAL_STOREROOM, \
	ACCESS_SEC_DOORS, \
	ACCESS_XENOBIOLOGY, \
	ACCESS_MINING_STATION, \
	ACCESS_MAILSORTING, \
	ACCESS_MINING, \
	ACCESS_RESEARCH, \
	ACCESS_THEATRE, \
	ACCESS_SURGERY, \
	ACCESS_COURT, \
	ACCESS_QM, \
	ACCESS_VIROLOGY, \
	ACCESS_LAWYER, \
	ACCESS_LIBRARY, \
	ACCESS_HYDROPONICS, \
	ACCESS_CHEMISTRY, \
	ACCESS_CONSTRUCTION, \
	ACCESS_CARGO, \
	ACCESS_ROBOTICS, \
	ACCESS_KITCHEN, \
	ACCESS_CREMATORIUM, \
	ACCESS_JANITOR, \
	ACCESS_BAR, \
	ACCESS_CHAPEL_OFFICE, \
	ACCESS_EXTERNAL_AIRLOCKS, \
	ACCESS_MAINT_TUNNELS, \
	ACCESS_ENGINE_EQUIP, \
	ACCESS_ENGINE, \
	ACCESS_GENETICS, \
	ACCESS_RND, \
	ACCESS_MORGUE, \
	ACCESS_MEDICAL, \
	ACCESS_FORENSICS_LOCKERS, \
	ACCESS_BRIG, \
	ACCESS_SECURITY, \
)

/// Command staff/secure accesses, think bridge/armoury, AI upload, notably access to modify ID cards themselves. Do not use direct, access via SSid_access.get_flag_access_list(ACCESS_FLAG_COMMAND)
#define COMMAND_ACCESS list( \
	ACCESS_ORDNANCE_STORAGE, \
	ACCESS_MINISAT, \
	ACCESS_TCOMSAT, \
	ACCESS_KEYCARD_AUTH, \
	ACCESS_RC_ANNOUNCE, \
	ACCESS_VAULT, \
	ACCESS_ATMOSPHERICS, \
	ACCESS_TECH_STORAGE, \
	ACCESS_HEADS, \
	ACCESS_TELEPORTER, \
	ACCESS_ARMORY, \
	ACCESS_AI_UPLOAD, \
	ACCESS_CHANGE_IDS, \
	ACCESS_ORDNANCE, \
	ACCESS_EVA, \
	ACCESS_GATEWAY, \
	ACCESS_ALL_PERSONAL_LOCKERS, \
)

/// Private head of staff offices, usually only granted to most cards by trimming. Do not use direct, access via SSid_access.get_flag_access_list(ACCESS_FLAG_PRV_COMMAND)
#define PRIVATE_COMMAND_ACCESS list( \
	ACCESS_HOS, \
	ACCESS_HOP, \
	ACCESS_CE, \
	ACCESS_CMO, \
	ACCESS_RD, \
)

/// Captains private rooms. Do not use direct, access via SSid_access.get_flag_access_list(ACCESS_FLAG_CAPTAIN)
#define CAPTAIN_ACCESS list( \
	ACCESS_CAPTAIN, \
)
/// Centcom area stuff. Do not use direct, access via SSid_access.get_flag_access_list(ACCESS_FLAG_CENTCOM)
#define CENTCOM_ACCESS list( \
	ACCESS_CENT_BAR, \
	ACCESS_CENT_CAPTAIN, \
	ACCESS_CENT_TELEPORTER, \
	ACCESS_CENT_STORAGE, \
	ACCESS_CENT_LIVING, \
	ACCESS_CENT_MEDICAL, \
	ACCESS_CENT_SPECOPS, \
	ACCESS_CENT_THUNDER, \
	ACCESS_CENT_GENERAL, \
)

/// Syndicate areas off station. Do not use direct, access via SSid_access.get_flag_access_list(ACCESS_FLAG_SYNDICATE)
#define SYNDICATE_ACCESS list( \
	ACCESS_SYNDICATE_LEADER, \
	ACCESS_SYNDICATE, \
)

/// Away missions/gateway/space ruins.  Do not use direct, access via SSid_access.get_flag_access_list(ACCESS_FLAG_AWAY)
#define AWAY_ACCESS list( \
	ACCESS_AWAY_GENERAL, \
	ACCESS_AWAY_MAINT, \
	ACCESS_AWAY_MED, \
	ACCESS_AWAY_SEC, \
	ACCESS_AWAY_ENGINE, \
	ACCESS_AWAY_GENERIC1, \
	ACCESS_AWAY_GENERIC2, \
	ACCESS_AWAY_GENERIC3, \
	ACCESS_AWAY_GENERIC4, \
)

/// Weird internal Cult access that prevents non-cult from using their doors.  Do not use direct, access via SSid_access.get_flag_access_list(ACCESS_FLAG_SPECIAL)
#define CULT_ACCESS list( \
	ACCESS_BLOODCULT, \
)

/// Name for the Global region.
#define REGION_ALL_GLOBAL "All"
/// Used to seed the accesses_by_region list in SSid_access. A list of every single access in the game.
#define REGION_ACCESS_ALL_GLOBAL REGION_ACCESS_ALL_STATION + CENTCOM_ACCESS + SYNDICATE_ACCESS + AWAY_ACCESS + CULT_ACCESS
/// Name for the Station All Access region.
#define REGION_ALL_STATION "Station"
/// Used to seed the accesses_by_region list in SSid_access. A list of all station accesses.
#define REGION_ACCESS_ALL_STATION COMMON_ACCESS + COMMAND_ACCESS + PRIVATE_COMMAND_ACCESS + CAPTAIN_ACCESS
/// Name for the General region.
#define REGION_GENERAL "General"
/// Used to seed the accesses_by_region list in SSid_access. A list of general service accesses that are overseen by the HoP.
#define REGION_ACCESS_GENERAL list( \
	ACCESS_KITCHEN, \
	ACCESS_BAR, \
	ACCESS_HYDROPONICS, \
	ACCESS_JANITOR, \
	ACCESS_CHAPEL_OFFICE, \
	ACCESS_CREMATORIUM, \
	ACCESS_LIBRARY, \
	ACCESS_THEATRE, \
	ACCESS_LAWYER, \
)
/// Name for the Security region.
#define REGION_SECURITY "Security"
/// Used to seed the accesses_by_region list in SSid_access. A list of all security regional accesses that are overseen by the HoS.
#define REGION_ACCESS_SECURITY list( \
	ACCESS_SEC_DOORS, \
	ACCESS_WEAPONS, \
	ACCESS_SECURITY, \
	ACCESS_BRIG, \
	ACCESS_ARMORY, \
	ACCESS_FORENSICS_LOCKERS, \
	ACCESS_COURT, \
	ACCESS_MECH_SECURITY, \
	ACCESS_HOS, \
)
/// Name for the Medbay region.
#define REGION_MEDBAY "Medbay"
/// Used to seed the accesses_by_region list in SSid_access. A list of all medbay regional accesses that are overseen by the CMO.
#define REGION_ACCESS_MEDBAY list( \
	ACCESS_MEDICAL, \
	ACCESS_MORGUE, \
	ACCESS_CHEMISTRY, \
	ACCESS_VIROLOGY, \
	ACCESS_SURGERY, \
	ACCESS_MECH_MEDICAL, \
	ACCESS_CMO, \
	ACCESS_PHARMACY, \
	ACCESS_PSYCHOLOGY, \
)
/// Name for the Research region.
#define REGION_RESEARCH "Research"
/// Used to seed the accesses_by_region list in SSid_access. A list of all research regional accesses that are overseen by the RD.
#define REGION_ACCESS_RESEARCH list( \
	ACCESS_RESEARCH, \
	ACCESS_RND, \
	ACCESS_ORDNANCE, \
	ACCESS_ORDNANCE_STORAGE, \
	ACCESS_GENETICS, \
	ACCESS_ROBOTICS, \
	ACCESS_XENOBIOLOGY, \
	ACCESS_MECH_SCIENCE, \
	ACCESS_MINISAT, \
	ACCESS_RD, \
	ACCESS_NETWORK, \
)
/// Name for the Engineering region.
#define REGION_ENGINEERING "Engineering"
/// Used to seed the accesses_by_region list in SSid_access. A list of all engineering regional accesses that are overseen by the CE.
#define REGION_ACCESS_ENGINEERING list( \
	ACCESS_CONSTRUCTION, \
	ACCESS_AUX_BASE, \
	ACCESS_MAINT_TUNNELS, \
	ACCESS_ENGINE, \
	ACCESS_ENGINE_EQUIP, \
	ACCESS_EXTERNAL_AIRLOCKS, \
	ACCESS_TECH_STORAGE, \
	ACCESS_ATMOSPHERICS, \
	ACCESS_MECH_ENGINE, \
	ACCESS_TCOMSAT, \
	ACCESS_MINISAT, \
	ACCESS_CE, \
)
/// Name for the Supply region.
#define REGION_SUPPLY "Supply"
/// Used to seed the accesses_by_region list in SSid_access. A list of all cargo regional accesses that are overseen by the HoP.
#define REGION_ACCESS_SUPPLY list( \
	ACCESS_MAILSORTING, \
	ACCESS_MINING, \
	ACCESS_MINING_STATION, \
	ACCESS_MECH_MINING, \
	ACCESS_MINERAL_STOREROOM, \
	ACCESS_CARGO, \
	ACCESS_QM, \
	ACCESS_VAULT, \
)
/// Name for the Command region.
#define REGION_COMMAND "Command"
/// Used to seed the accesses_by_region list in SSid_access. A list of all command regional accesses that are overseen by the Captain.
#define REGION_ACCESS_COMMAND list( \
	ACCESS_HEADS, \
	ACCESS_RC_ANNOUNCE, \
	ACCESS_KEYCARD_AUTH, \
	ACCESS_CHANGE_IDS, \
	ACCESS_AI_UPLOAD, \
	ACCESS_TELEPORTER, \
	ACCESS_EVA, \
	ACCESS_GATEWAY, \
	ACCESS_ALL_PERSONAL_LOCKERS, \
	ACCESS_HOP, \
	ACCESS_CAPTAIN, \
	ACCESS_VAULT, \
)
/// Name for the Centcom region.
#define REGION_CENTCOM "Central Command"
/// Used to seed the accesses_by_region list in SSid_access. A list of all CENTCOM_ACCESS regional accesses.
#define REGION_ACCESS_CENTCOM CENTCOM_ACCESS

/**
 * A list of PDA paths that can be painted as well as the regional heads which should be able to paint them.
 * If a PDA is not in this list, it cannot be painted using the PDA & ID Painter.
 * If a PDA is in this list, it can always be painted with ACCESS_CHANGE_IDS.
 * Used to see pda_region in [/datum/controller/subsystem/id_access/proc/setup_tgui_lists]
 */
#define PDA_PAINTING_REGIONS list( \
	/obj/item/pda = list(REGION_GENERAL), \
	/obj/item/pda/clown = list(REGION_GENERAL), \
	/obj/item/pda/mime = list(REGION_GENERAL), \
	/obj/item/pda/medical = list(REGION_MEDBAY), \
	/obj/item/pda/viro = list(REGION_MEDBAY), \
	/obj/item/pda/engineering = list(REGION_ENGINEERING), \
	/obj/item/pda/security = list(REGION_SECURITY), \
	/obj/item/pda/detective = list(REGION_SECURITY), \
	/obj/item/pda/warden = list(REGION_SECURITY), \
	/obj/item/pda/janitor = list(REGION_GENERAL), \
	/obj/item/pda/science = list(REGION_RESEARCH), \
	/obj/item/pda/heads/hop = list(REGION_COMMAND), \
	/obj/item/pda/heads/hos = list(REGION_COMMAND), \
	/obj/item/pda/heads/cmo = list(REGION_COMMAND), \
	/obj/item/pda/heads/ce = list(REGION_COMMAND), \
	/obj/item/pda/heads/rd = list(REGION_COMMAND), \
	/obj/item/pda/captain = list(REGION_COMMAND), \
	/obj/item/pda/cargo = list(REGION_SUPPLY), \
	/obj/item/pda/quartermaster = list(REGION_SUPPLY), \
	/obj/item/pda/shaftminer = list(REGION_SUPPLY), \
	/obj/item/pda/chaplain = list(REGION_GENERAL), \
	/obj/item/pda/lawyer = list(REGION_GENERAL, REGION_SECURITY), \
	/obj/item/pda/botanist = list(REGION_GENERAL), \
	/obj/item/pda/roboticist = list(REGION_RESEARCH), \
	/obj/item/pda/curator = list(REGION_GENERAL), \
	/obj/item/pda/cook = list(REGION_GENERAL), \
	/obj/item/pda/bar = list(REGION_GENERAL), \
	/obj/item/pda/atmos = list(REGION_ENGINEERING), \
	/obj/item/pda/chemist = list(REGION_MEDBAY), \
	/obj/item/pda/geneticist = list(REGION_RESEARCH), \
)

/// All regions that make up the station area. Helper define to quickly designate a region as part of the station or not. Access via SSid_access.station_regions.
#define REGION_AREA_STATION list( \
	REGION_GENERAL, \
	REGION_SECURITY, \
	REGION_MEDBAY, \
	REGION_RESEARCH, \
	REGION_ENGINEERING, \
	REGION_SUPPLY, \
	REGION_COMMAND, \
)

/// Used in ID card access adding procs. Will try to add all accesses and utilises free wildcards, skipping over any accesses it can't add.
#define TRY_ADD_ALL 0
/// Used in ID card access adding procs. Will try to add all accesses and does not utilise wildcards, skipping anything requiring a wildcard.
#define TRY_ADD_ALL_NO_WILDCARD 1
/// Used in ID card access adding procs. Will forcefully add all accesses.
#define FORCE_ADD_ALL 2
/// Used in ID card access adding procs. Will stack trace on fail.
#define ERROR_ON_FAIL 3


code:
// Keep the identifiers here below 32 characters, you can put the full display name in the actual achievement datum

#define ACHIEVEMENT_DEFAULT "default"
#define ACHIEVEMENT_SCORE "score"

//Misc Medal hub IDs
#define MEDAL_METEOR "Your Life Before Your Eyes"
#define MEDAL_PULSE "Jackpot"
#define MEDAL_TIMEWASTE "Overextended The Joke"
#define MEDAL_RODSUPLEX "Feat of Strength"
#define MEDAL_CLOWNCARKING "Round and Full"
#define MEDAL_THANKSALOT "The Best Driver"
#define MEDAL_HELBITALJANKEN "Hel-bent on Winning"
#define MEDAL_MATERIALCRAFT "Getting an Upgrade"
#define MEDAL_DISKPLEASE "Disk, Please!"
#define MEDAL_GAMER "I'm Not Important"
#define MEDAL_VENDORSQUISH "Teenage Anarchist"
#define MEDAL_SWIRLIE "Bowl-d"
#define MEDAL_SELFOUCH "Hands???"
#define MEDAL_SANDMAN "Mister Sandman"
#define MEDAL_CLEANBOSS "Cleanboss"
#define MEDAL_RULE8 "Rule 8"
#define MEDAL_LONGSHIFT "longshift"
#define MEDAL_SNAIL "KKKiiilll mmmeee"
#define MEDAL_LOOKOUTSIR "Look Out, Sir!"
#define MEDAL_GOTTEM "GOTTEM"
#define MEDAL_ASCENSION "Ascension"
#define MEDAL_FRENCHING "FrenchingTheBubble"
#define MEDAL_ASH_ASCENSION "Ash"
#define MEDAL_FLESH_ASCENSION "Flesh"
#define MEDAL_RUST_ASCENSION "Rust"
#define MEDAL_VOID_ASCENSION "Void"
#define MEDAL_TOOLBOX_SOUL "Toolsoul"
#define MEDAL_CHEM_TUT          "Beginner Chemist"
#define MEDAL_HOT_DAMN "Hot Damn!"
#define MEDAL_CAYENNE_DISK "Very Important Piscis"
#define MEDAL_TRAM_SURFER "Tram Surfer"
#define MEDAL_CULT_SHUTTLE_OMFG "WHAT JUST HAPPENED"

//Skill medal hub IDs
#define MEDAL_LEGENDARY_MINER "Legendary Miner"

//Mafia medal hub IDs (wins)
#define MAFIA_MEDAL_ASSISTANT "Assistant"
#define MAFIA_MEDAL_DETECTIVE "Detective"
#define MAFIA_MEDAL_PSYCHOLOGIST "Psychologist"
#define MAFIA_MEDAL_CHAPLAIN "Chaplain"
#define MAFIA_MEDAL_MD "Medical Doctor"
#define MAFIA_MEDAL_OFFICER "Security Officer"
#define MAFIA_MEDAL_LAWYER "Lawyer"
#define MAFIA_MEDAL_HOP "Head of Personnel"
#define MAFIA_MEDAL_HOS "Head of Security"
#define MAFIA_MEDAL_WARDEN "Warden"
#define MAFIA_MEDAL_CHANGELING "CHANGELING"
#define MAFIA_MEDAL_THOUGHTFEEDER "Thoughtfeeder"
#define MAFIA_MEDAL_TRAITOR "Traitor"
#define MAFIA_MEDAL_NIGHTMARE "Nightmare"
#define MAFIA_MEDAL_FUGITIVE "Fugitive"
#define MAFIA_MEDAL_OBSESSED "Obsessed"
#define MAFIA_MEDAL_CLOWN "Clown"

//Mafia medal hub IDs (misc stuff)
#define MAFIA_MEDAL_HATED "Universally Hated"
#define MAFIA_MEDAL_CHARISMATIC "Charismatic"
#define MAFIA_MEDAL_VIP "VIP"

//Boss medals

// Medal hub IDs for boss medals (Pre-fixes)
#define BOSS_MEDAL_ANY   "Boss Killer"
#define BOSS_MEDAL_MINER   "Blood-drunk Miner Killer"
#define BOSS_MEDAL_FROSTMINER "Demonic-frost Miner Killer"
#define BOSS_MEDAL_BUBBLEGUM  "Bubblegum Killer"
#define BOSS_MEDAL_COLOSSUS   "Colossus Killer"
#define BOSS_MEDAL_DRAKE   "Drake Killer"
#define BOSS_MEDAL_HIEROPHANT "Hierophant Killer"
#define BOSS_MEDAL_LEGION   "Legion Killer"
#define BOSS_MEDAL_TENDRIL   "Tendril Exterminator"
#define BOSS_MEDAL_SWARMERS   "Swarmer Beacon Killer"
#define BOSS_MEDAL_WENDIGO    "Wendigo Killer"
#define BOSS_MEDAL_KINGGOAT   "King Goat Killer"

#define BOSS_MEDAL_MINER_CRUSHER "Blood-drunk Miner Crusher"
#define BOSS_MEDAL_FROSTMINER_CRUSHER "Demonic-frost Miner Crusher"
#define BOSS_MEDAL_BUBBLEGUM_CRUSHER "Bubblegum Crusher"
#define BOSS_MEDAL_COLOSSUS_CRUSHER "Colossus Crusher"
#define BOSS_MEDAL_DRAKE_CRUSHER "Drake Crusher"
#define BOSS_MEDAL_HIEROPHANT_CRUSHER "Hierophant Crusher"
#define BOSS_MEDAL_LEGION_CRUSHER "Legion Crusher"
#define BOSS_MEDAL_SWARMERS_CRUSHER "Swarmer Beacon Crusher"
#define BOSS_MEDAL_WENDIGO_CRUSHER "Wendigo Crusher"
#define BOSS_MEDAL_KINGGOAT_CRUSHER "King Goat Crusher"

// Medal hub IDs for boss-kill scores
#define BOSS_SCORE          "Bosses Killed"
#define MINER_SCORE  "BDMs Killed"
#define FROST_MINER_SCORE  "DFMs Killed"
#define BUBBLEGUM_SCORE  "Bubblegum Killed"
#define COLOSSUS_SCORE      "Colossus Killed"
#define DRAKE_SCORE      "Drakes Killed"
#define HIEROPHANT_SCORE  "Hierophants Killed"
#define LEGION_SCORE      "Legion Killed"
#define SWARMER_BEACON_SCORE "Swarmer Beacs Killed"
#define WENDIGO_SCORE  "Wendigos Killed"
#define KINGGOAT_SCORE      "King Goat Killed"
#define TENDRIL_CLEAR_SCORE  "Tendrils Killed"

// DB ID for hardcore random mode
#define HARDCORE_RANDOM_SCORE "Hardcore Random Score"

// DB ID for amount of consumed maintenance pills
#define MAINTENANCE_PILL_SCORE "Maintenance Pill Score"

// DB ID for intento score
#define INTENTO_SCORE "Intento Score"

// Tourist related achievements and scores

//centcom grades (achievement)

#define MEDAL_BAD_SERVICE "Bad Service"
#define MEDAL_OKAY_SERVICE "Okay Service"
#define MEDAL_GOOD_SERVICE "Good Service"

//scores

#define CHEF_TOURISTS_SERVED "Tourists Served As Chef"
#define BARTENDER_TOURISTS_SERVED "Tourists Served As Bartender"


code:
/// The acid power required to destroy most closed turfs.
#define ACID_POWER_MELT_TURF 200
/// The maximum amount of damage (per second) acid can deal to an [/obj].
#define OBJ_ACID_DAMAGE_MAX 300
/// Maximum acid volume that can be applied to an [/obj].
#define OBJ_ACID_VOLUME_MAX 300
/// Maximum acid volume that can be applied to a [/mob/living].
#define MOB_ACID_VOLUME_MAX 1000
/// Maximum acid volume that can be applied to a [/turf].
#define TURF_ACID_VOLUME_MAX 12000

// Acid decay rate constants.
/// The constant factor for the acid decay rate.
#define ACID_DECAY_BASE 1
/// The scaling factor for the acid decay rate.
#define ACID_DECAY_SCALING 1

/// The default icon state for the acid overlay. Not to be confused with the error icon state.
#define ACID_OVERLAY_DEFAULT "default"
/// The combined acid power and acid volume required to burn hands.
#define ACID_LEVEL_HANDBURN 20


code:
//ids
#define ACTIONSPEED_ID_SANITY "sanity_component"
#define ACTIONSPEED_ID_STIMULANTS "stimulant_withdrawal"


code:
//A set of constants used to determine which type of mute an admin wishes to apply:
//Please read and understand the muting/automuting stuff before changing these. MUTE_IC_AUTO etc = (MUTE_IC << 1)
//Therefore there needs to be a gap between the flags for the automute flags
#define MUTE_IC (1<<0)
#define MUTE_OOC (1<<1)
#define MUTE_PRAY (1<<2)
#define MUTE_ADMINHELP (1<<3)
#define MUTE_DEADCHAT (1<<4)
#define MUTE_ALL (~0)

//Some constants for DB_Ban
#define BANTYPE_PERMA 1
#define BANTYPE_TEMP 2
#define BANTYPE_JOB_PERMA 3
#define BANTYPE_JOB_TEMP 4
/// used to locate stuff to unban.
#define BANTYPE_ANY_FULLBAN 5

#define BANTYPE_ADMIN_PERMA 7
#define BANTYPE_ADMIN_TEMP 8
/// used to remove jobbans
#define BANTYPE_ANY_JOB 9

//Admin Permissions
#define R_BUILD (1<<0)
#define R_ADMIN (1<<1)
#define R_BAN (1<<2)
#define R_FUN (1<<3)
#define R_SERVER (1<<4)
#define R_DEBUG (1<<5)
#define R_POSSESS (1<<6)
#define R_PERMISSIONS (1<<7)
#define R_STEALTH (1<<8)
#define R_POLL (1<<9)
#define R_VAREDIT (1<<10)
#define R_SOUND (1<<11)
#define R_SPAWN (1<<12)
#define R_AUTOADMIN (1<<13)
#define R_DBRANKS (1<<14)

#define R_DEFAULT R_AUTOADMIN

#define R_EVERYTHING (1<<15)-1 //the sum of all other rank permissions, used for +EVERYTHING

#define ADMIN_QUE(user) "(?)"
#define ADMIN_FLW(user) "(FLW)"
#define ADMIN_PP(user) "(PP)"
#define ADMIN_VV(atom) "(VV)"
#define ADMIN_SM(user) "(SM)"
#define ADMIN_TP(user) "(TP)"
#define ADMIN_SP(user) "(SP)"
#define ADMIN_KICK(user) "(KICK)"
#define ADMIN_CENTCOM_REPLY(user) "(RPLY)"
#define ADMIN_SYNDICATE_REPLY(user) "(RPLY)"
#define ADMIN_SC(user) "(SC)"
#define ADMIN_SMITE(user) "(SMITE)"
#define ADMIN_LOOKUP(user) "[key_name_admin(user)][ADMIN_QUE(user)]"
#define ADMIN_LOOKUPFLW(user) "[key_name_admin(user)][ADMIN_QUE(user)] [ADMIN_FLW(user)]"
#define ADMIN_SET_SD_CODE "(SETCODE)"
#define ADMIN_FULLMONTY_NONAME(user) "[ADMIN_QUE(user)] [ADMIN_PP(user)] [ADMIN_VV(user)] [ADMIN_SM(user)] [ADMIN_FLW(user)] [ADMIN_TP(user)] [ADMIN_INDIVIDUALLOG(user)] [ADMIN_SMITE(user)]"
#define ADMIN_FULLMONTY(user) "[key_name_admin(user)] [ADMIN_FULLMONTY_NONAME(user)]"
#define ADMIN_JMP(src) "(JMP)"
#define COORD(src) "[src ? src.Admin_Coordinates_Readable() : "nonexistent location"]"
#define AREACOORD(src) "[src ? src.Admin_Coordinates_Readable(TRUE) : "nonexistent location"]"
#define ADMIN_COORDJMP(src) "[src ? src.Admin_Coordinates_Readable(FALSE, TRUE) : "nonexistent location"]"
#define ADMIN_VERBOSEJMP(src) "[src ? src.Admin_Coordinates_Readable(TRUE, TRUE) : "nonexistent location"]"
#define ADMIN_INDIVIDUALLOG(user) "(LOGS)"

/atom/proc/Admin_Coordinates_Readable(area_name, admin_jump_ref)
	var/turf/T = Safe_COORD_Location()
	return T ? "[area_name ? "[get_area_name(T, TRUE)] " : " "]([T.x],[T.y],[T.z])[admin_jump_ref ? " [ADMIN_JMP(T)]" : ""]" : "nonexistent location"

/atom/proc/Safe_COORD_Location()
	var/atom/A = drop_location()
	if(!A)
		return //not a valid atom.
	var/turf/T = get_step(A, 0) //resolve where the thing is.
	if(!T) //incase it's inside a valid drop container, inside another container. ie if a mech picked up a closet and has it inside it's internal storage.
		var/atom/last_try = A.loc?.drop_location() //one last try, otherwise fuck it.
		if(last_try)
			T = get_step(last_try, 0)
	return T

/turf/Safe_COORD_Location()
	return src

#define AHELP_ACTIVE 1
#define AHELP_CLOSED 2
#define AHELP_RESOLVED 3

/// Amount of time (in deciseconds) after the rounds starts, that the player disconnect report is issued.
#define ROUNDSTART_LOGOUT_REPORT_TIME 6000

/// Number of identical messages required before the spam-prevention will warn you to stfu
#define SPAM_TRIGGER_WARNING 5
/// Number of identical messages required before the spam-prevention will automute you
#define SPAM_TRIGGER_AUTOMUTE 10

///Max length of a keypress command before it's considered to be a forged packet/bogus command
#define MAX_KEYPRESS_COMMANDLENGTH 16
///Maximum keys that can be bound to one button
#define MAX_COMMANDS_PER_KEY 5
///Max amount of keypress messages per second over two seconds before client is autokicked
#define MAX_KEYPRESS_AUTOKICK 50
///Length of held key buffer
#define HELD_KEY_BUFFER_LENGTH 15

#define STICKYBAN_DB_CACHE_TIME 10 SECONDS
#define STICKYBAN_ROGUE_CHECK_TIME 5

/// Shown to vicitm of staff of change and related effects.
#define POLICY_POLYMORPH "polymorph"
/// Shown on top of policy verb window
#define POLICY_VERB_HEADER "policy_verb_header"

//How many things you can spawn at once with spawn verb/create panel
#define ADMIN_SPAWN_CAP 100

// LOG BROWSE TYPES
#define BROWSE_ROOT_ALL_LOGS 1
#define BROWSE_ROOT_CURRENT_LOGS 2

// allowed ghost roles this round, starts as everything allowed
GLOBAL_VAR_INIT(ghost_role_flags, (~0))

//Flags that control what ways ghosts can get back into the round
//ie fugitives, space dragon, etc. also includes dynamic midrounds as it's the same deal
#define GHOSTROLE_MIDROUND_EVENT (1<<0)
//ie ashwalkers, free golems, beach bums
#define GHOSTROLE_SPAWNER (1<<1)
//ie mind monkeys, sentience potion
#define GHOSTROLE_STATION_SENTIENCE (1<<2)
//ie pais, posibrains
#define GHOSTROLE_SILICONS (1<<3)
//ie mafia, ctf
#define GHOSTROLE_MINIGAME (1<<4)

//smite defines

#define LIGHTNING_BOLT_DAMAGE 75
#define LIGHTNING_BOLT_ELECTROCUTION_ANIMATION_LENGTH 40

/// for asay pings, this is the index in the return list for [/proc/check_admin_pings] that contains the message modified with underlines for the spotted names
#define ADMINSAY_PING_UNDERLINE_NAME_INDEX "!underlined_names"


code:
#define ADVENTURE_DIR "[global.config.directory]/adventures/"

//Special preset nodes

/// Victory node - Get loot and exit
#define WIN_NODE "WIN"
/// Failure node - No loot, get damaged and exit.
#define FAIL_NODE "FAIL"
/// Failure node - No loot and drone blown up.
#define FAIL_DEATH_NODE "FAIL_DEATH"
/// Return node - navigates to previous adventure node.
#define GO_BACK_NODE "GO BACK"

//Adventure results
#define ADVENTURE_RESULT_SUCCESS "success"
#define ADVENTURE_RESULT_DAMAGE "damage"
#define ADVENTURE_RESULT_DEATH "death"

// Exploration drone states

/// Drone is stationside - allow changing tools and such.
#define EXODRONE_IDLE "idle"
/// Drone is traveling from or to the exploration site
#define EXODRONE_TRAVEL "travel"
/// Drone is in adventure/event caused timeout
#define EXODRONE_BUSY "busy"
/// Drone is at exploration site either idle or in simple event
#define EXODRONE_EXPLORATION "exploration"
/// Drone is currently playing an adventure
#define EXODRONE_ADVENTURE "adventure"

// Scanner bands, use these to guess what's in the site and prepare drone accordingly.
#define EXOSCANNER_BAND_PLASMA "Plasma absorption band"
#define EXOSCANNER_BAND_LIFE "Hydrocarbons/Molecular oxygen"
#define EXOSCANNER_BAND_TECH "Narrow-band radio waves"
#define EXOSCANNER_BAND_RADIATION "Exotic Radiation"
#define EXOSCANNER_BAND_DENSITY "Increased Density"
// Exodrone tools
#define EXODRONE_TOOL_WELDER "welder"
#define EXODRONE_TOOL_TRANSLATOR "translator"
#define EXODRONE_TOOL_LASER "laser"
#define EXODRONE_TOOL_MULTITOOL "multitool"
#define EXODRONE_TOOL_DRILL "drill"

GLOBAL_LIST_INIT(exodrone_tool_metadata,list(
	EXODRONE_TOOL_WELDER = list("description"="A heavy duty welder.","icon"="burn"),
	EXODRONE_TOOL_TRANSLATOR = list("description"="Powerful translation and data recording software.","icon"="language"),
	EXODRONE_TOOL_LASER = list("description"="Multipurpose tool suitable for combat and precision cutting.","icon"="bolt"),
	EXODRONE_TOOL_MULTITOOL = list("description"="Multipurpose tool for electronics manipulation. Comes with suite of radiation and radiowave sensors.","icon"="broadcast-tower"),
	EXODRONE_TOOL_DRILL = list("description"="Heavy duty drill useful for mining.","icon"="screwdriver")
))

// Site traits

/// Some kind of ruined interior
#define EXPLORATION_SITE_RUINS "ruins"
/// Power, wires and machinery present.
#define EXPLORATION_SITE_TECHNOLOGY "technology present"
/// It's a space station
#define EXPLORATION_SITE_STATION "space station"
/// It's ancient alien site
#define EXPLORATION_SITE_ALIEN "alien"
/// Carbon-based life-forms can live here
#define EXPLORATION_SITE_HABITABLE "habitable"
/// Site is in space
#define EXPLORATION_SITE_SPACE "in space"
/// Site is located on planet/moon/whatever surface
#define EXPLORATION_SITE_SURFACE "on surface"
/// Site is a space ship
#define EXPLORATION_SITE_SHIP "spaceship"
/// Site is civilized and populated, trading stations,cities etc. Lack of this trait means it's wilderness
#define EXPLORATION_SITE_CIVILIZED "civilized"

/// Scan types

// Wide scan, untargeted scan only reveals interest points. Cost increases exponentially with each firing. No scan conditions.
#define EXOSCAN_WIDE "wide"
// Point scan, reveals name/description and general band information. Flat cost. Affected by scan conditions of the site
#define EXOSCAN_POINT "point"
// Deep scan, reveals event scan texts. Linear cost increase with distance. Affected by scan conditions of the site.
#define EXOSCAN_DEEP "deep"

///  Adventure Effect Types

//completely removes the quality
#define ADVENTURE_EFFECT_TYPE_REMOVE "Remove"
//adds/substracts value from quality
#define ADVENTURE_EFFECT_TYPE_ADD "Add"
//sets quality to specific value
#define ADVENTURE_EFFECT_TYPE_SET "Set"

/// Adventure Effect Value Types

/// rolls value between low and high inclusive
#define ADVENTURE_QUALITY_TYPE_RANDOM "random"
#define ADVENTURE_RANDOM_QUALITY_LOW_FIELD "low"
#define ADVENTURE_RANDOM_QUALITY_HIGH_FIELD "high"


code:
#define GET_AI_BEHAVIOR(behavior_type) SSai_behaviors.ai_behaviors[behavior_type]
#define HAS_AI_CONTROLLER_TYPE(thing, type) istype(thing?.ai_controller, type)

#define AI_STATUS_ON 1
#define AI_STATUS_OFF 2

///For JPS pathing, the maximum length of a path we'll try to generate. Should be modularized depending on what we're doing later on
#define AI_MAX_PATH_LENGTH 30 // 30 is possibly overkill since by default we lose interest after 14 tiles of distance, but this gives wiggle room for weaving around obstacles

///Cooldown on planning if planning failed last time

#define AI_FAILED_PLANNING_COOLDOWN 1.5 SECONDS

///Flags for ai_behavior new()
#define AI_CONTROLLER_INCOMPATIBLE (1<<0)

///Does this task require movement from the AI before it can be performed?
#define AI_BEHAVIOR_REQUIRE_MOVEMENT (1<<0)
///Does this task let you perform the action while you move closer? (Things like moving and shooting)
#define AI_BEHAVIOR_MOVE_AND_PERFORM (1<<1)

///AI flags
#define STOP_MOVING_WHEN_PULLED (1<<0)

//Base Subtree defines

///This subtree should cancel any further planning, (Including from other subtrees)
#define SUBTREE_RETURN_FINISH_PLANNING 1

//Generic subtree defines

/// probability that the pawn should try resisting out of restraints
#define RESIST_SUBTREE_PROB 50
///macro for whether it's appropriate to resist right now, used by resist subtree
#define SHOULD_RESIST(source) (source.on_fire || source.buckled || HAS_TRAIT(source, TRAIT_RESTRAINED) || (source.pulledby && source.pulledby.grab_state > GRAB_PASSIVE))
///macro for whether the pawn can act, used generally to prevent some horrifying ai disasters
#define IS_DEAD_OR_INCAP(source) (source.incapacitated() || source.stat)

//Generic BB keys
#define BB_CURRENT_MIN_MOVE_DISTANCE "min_move_distance"
///time until we should next eat, set by the generic hunger subtree
#define BB_NEXT_HUNGRY "BB_NEXT_HUNGRY"
///what we're going to eat next
#define BB_FOOD_TARGET "bb_food_target"

//for songs

///song instrument blackboard, set by instrument subtrees
#define BB_SONG_INSTRUMENT "BB_SONG_INSTRUMENT"
///song lines blackboard, set by default on controllers
#define BB_SONG_LINES "song_lines"

// Monkey AI controller blackboard keys

#define BB_MONKEY_AGGRESSIVE "BB_monkey_aggressive"
#define BB_MONKEY_GUN_NEURONS_ACTIVATED "BB_monkey_gun_aware"
#define BB_MONKEY_GUN_WORKED "BB_monkey_gun_worked"
#define BB_MONKEY_BEST_FORCE_FOUND "BB_monkey_bestforcefound"
#define BB_MONKEY_ENEMIES "BB_monkey_enemies"
#define BB_MONKEY_BLACKLISTITEMS "BB_monkey_blacklistitems"
#define BB_MONKEY_PICKUPTARGET "BB_monkey_pickuptarget"
#define BB_MONKEY_PICKPOCKETING "BB_monkey_pickpocketing"
#define BB_MONKEY_CURRENT_ATTACK_TARGET "BB_monkey_current_attack_target"
#define BB_MONKEY_CURRENT_PRESS_TARGET "BB_monkey_current_press_target"
#define BB_MONKEY_CURRENT_GIVE_TARGET "BB_monkey_current_give_target"
#define BB_MONKEY_TARGET_DISPOSAL "BB_monkey_target_disposal"
#define BB_MONKEY_DISPOSING "BB_monkey_disposing"
#define BB_MONKEY_RECRUIT_COOLDOWN "BB_monkey_recruit_cooldown"

///Haunted item controller defines

///Chance for haunted item to haunt someone
#define HAUNTED_ITEM_ATTACK_HAUNT_CHANCE 10
///Chance for haunted item to try to get itself let go.
#define HAUNTED_ITEM_ESCAPE_GRASP_CHANCE 20
///Amount of aggro you get when picking up a haunted item
#define HAUNTED_ITEM_AGGRO_ADDITION 2

///Blackboard keys for haunted items
#define BB_TO_HAUNT_LIST "BB_to_haunt_list"
///Actual mob the item is haunting at the moment
#define BB_HAUNT_TARGET "BB_haunt_target"
///Amount of successful hits in a row this item has had
#define BB_HAUNTED_THROW_ATTEMPT_COUNT "BB_haunted_throw_attempt_count"
///If true, tolerates the equipper holding/equipping the hauntium
#define BB_LIKES_EQUIPPER "BB_likes_equipper"

///Cursed item controller defines

//defines
///how far a cursed item will still try to chase a target
#define CURSED_VIEW_RANGE 7
//blackboards

///Actual mob the item is haunting at the moment
#define BB_CURSE_TARGET "BB_haunt_target"
///Where the item wants to land on
#define BB_TARGET_SLOT "BB_target_slot"
///Amount of successful hits in a row this item has had
#define BB_CURSED_THROW_ATTEMPT_COUNT "BB_cursed_throw_attempt_count"

///Vending machine AI controller blackboard keys
#define BB_VENDING_CURRENT_TARGET "BB_vending_current_target"
#define BB_VENDING_TILT_COOLDOWN "BB_vending_tilt_cooldown"
#define BB_VENDING_UNTILT_COOLDOWN "BB_vending_untilt_cooldown"
#define BB_VENDING_BUSY_TILTING "BB_vending_busy_tilting"
#define BB_VENDING_LAST_HIT_SUCCESFUL "BB_vending_last_hit_succesful"

///Robot customer AI controller blackboard keys
#define BB_CUSTOMER_CURRENT_ORDER "BB_customer_current_order"
#define BB_CUSTOMER_MY_SEAT "BB_customer_my_seat"
#define BB_CUSTOMER_PATIENCE "BB_customer_patience"
#define BB_CUSTOMER_CUSTOMERINFO "BB_customer_customerinfo"
#define BB_CUSTOMER_EATING "BB_customer_eating"
#define BB_CUSTOMER_ATTENDING_VENUE "BB_customer_attending_avenue"
#define BB_CUSTOMER_LEAVING "BB_customer_leaving"
#define BB_CUSTOMER_CURRENT_TARGET "BB_customer_current_target"
/// Robot customer has said their can't find seat line at least once. Used to rate limit how often they'll complain after the first time.
#define BB_CUSTOMER_SAID_CANT_FIND_SEAT_LINE "BB_customer_said_cant_find_seat_line"

///Hostile AI controller blackboard keys
#define BB_HOSTILE_ORDER_MODE "BB_HOSTILE_ORDER_MODE"
#define BB_HOSTILE_FRIEND "BB_HOSTILE_FRIEND"
#define BB_HOSTILE_ATTACK_WORD "BB_HOSTILE_ATTACK_WORD"
#define BB_FOLLOW_TARGET "BB_FOLLOW_TARGET"
#define BB_ATTACK_TARGET "BB_ATTACK_TARGET"
#define BB_VISION_RANGE "BB_VISION_RANGE"

/// Basically, what is our vision/hearing range.
#define BB_HOSTILE_VISION_RANGE 10
/// After either being given a verbal order or a pointing order, ignore further of each for this duration
#define AI_HOSTILE_COMMAND_COOLDOWN 2 SECONDS

// hostile command modes (what pointing at something/someone does depending on the last order the carp heard)
/// Don't do anything (will still react to stuff around them though)
#define HOSTILE_COMMAND_NONE 0
/// Will attack a target.
#define HOSTILE_COMMAND_ATTACK 1
/// Will follow a target.
#define HOSTILE_COMMAND_FOLLOW 2

///Dog AI controller blackboard keys

#define BB_SIMPLE_CARRY_ITEM "BB_SIMPLE_CARRY_ITEM"
#define BB_FETCH_TARGET "BB_FETCH_TARGET"
#define BB_FETCH_IGNORE_LIST "BB_FETCH_IGNORE_LISTlist"
#define BB_FETCH_DELIVER_TO "BB_FETCH_DELIVER_TO"
#define BB_DOG_FRIENDS "BB_DOG_FRIENDS"
#define BB_DOG_ORDER_MODE "BB_DOG_ORDER_MODE"
#define BB_DOG_PLAYING_DEAD "BB_DOG_PLAYING_DEAD"
#define BB_DOG_HARASS_TARGET "BB_DOG_HARASS_TARGET"

/// Basically, what is our vision/hearing range for picking up on things to fetch/
#define AI_DOG_VISION_RANGE	10
/// What are the odds someone petting us will become our friend?
#define AI_DOG_PET_FRIEND_PROB 15
/// After this long without having fetched something, we clear our ignore list
#define AI_FETCH_IGNORE_DURATION 30 SECONDS
/// After being ordered to heel, we spend this long chilling out
#define AI_DOG_HEEL_DURATION 20 SECONDS
/// After either being given a verbal order or a pointing order, ignore further of each for this duration
#define AI_DOG_COMMAND_COOLDOWN	2 SECONDS

// dog command modes (what pointing at something/someone does depending on the last order the dog heard)
/// Don't do anything (will still react to stuff around them though)
#define DOG_COMMAND_NONE 0
/// Will try to pick up and bring back whatever you point to
#define DOG_COMMAND_FETCH 1
/// Will get within a few tiles of whatever you point at and continually growl/bark. If the target is a living mob who gets too close, the dog will attack them with bites
#define DOG_COMMAND_ATTACK 2

//enumerators for parsing command speech
#define COMMAND_HEEL "Heel"
#define COMMAND_FETCH "Fetch"
#define COMMAND_FOLLOW "Follow"
#define COMMAND_STOP "Stop"
#define COMMAND_ATTACK "Attack"
#define COMMAND_DIE "Play Dead"

///bane ai
#define BB_BANE_BATMAN "BB_bane_batman"
//yep thats it

//Hunting defines
#define SUCCESFUL_HUNT_COOLDOWN 5 SECONDS

///Hunting BB keys
#define BB_CURRENT_HUNTING_TARGET "BB_current_hunting_target"
#define BB_HUNTING_COOLDOWN "BB_HUNTING_COOLDOWN"

///Basic Mob Keys

///Tipped blackboards
///Bool that means a basic mob will start reacting to being tipped in it's planning
#define BB_BASIC_MOB_TIP_REACTING "BB_basic_tip_reacting"
///the motherfucker who tipped us
#define BB_BASIC_MOB_TIPPER "BB_basic_tip_tipper"

///Targetting subtrees
#define BB_BASIC_MOB_CURRENT_TARGET "BB_basic_current_target"
#define BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION "BB_basic_current_target_hiding_location"
#define BB_TARGETTING_DATUM "targetting_datum"


code:
//A set of defines to be used by the alarm datums
///Sent by air alarms, indecates something wrong with thier attached atmosphere
#define ALARM_ATMOS "Atmosphere"
///Sent by fire alarms when they are toggled
#define ALARM_FIRE "Fire"
///Sent by apcs when their power starts to fail
#define ALARM_POWER "Power"
///Sent by cameras when they're disabled in some manner
#define ALARM_CAMERA "Camera"
///Sent by display cases when they're broken into
#define ALARM_BURGLAR "Burglar"
///Sent by motion detecting cameras when they well, detect motion
#define ALARM_MOTION "Motion"


code:
#define NUKE_RESULT_FLUKE 0
#define NUKE_RESULT_NUKE_WIN 1
#define NUKE_RESULT_CREW_WIN 2
#define NUKE_RESULT_CREW_WIN_SYNDIES_DEAD 3
#define NUKE_RESULT_DISK_LOST 4
#define NUKE_RESULT_DISK_STOLEN 5
#define NUKE_RESULT_NOSURVIVORS 6
#define NUKE_RESULT_WRONG_STATION 7
#define NUKE_RESULT_WRONG_STATION_DEAD 8

//fugitive end results
#define FUGITIVE_RESULT_BADASS_HUNTER 0
#define FUGITIVE_RESULT_POSTMORTEM_HUNTER 1
#define FUGITIVE_RESULT_MAJOR_HUNTER 2
#define FUGITIVE_RESULT_HUNTER_VICTORY 3
#define FUGITIVE_RESULT_MINOR_HUNTER 4
#define FUGITIVE_RESULT_STALEMATE 5
#define FUGITIVE_RESULT_MINOR_FUGITIVE 6
#define FUGITIVE_RESULT_FUGITIVE_VICTORY 7
#define FUGITIVE_RESULT_MAJOR_FUGITIVE 8

#define APPRENTICE_DESTRUCTION "destruction"
#define APPRENTICE_BLUESPACE "bluespace"
#define APPRENTICE_ROBELESS "robeless"
#define APPRENTICE_HEALING "healing"

//ERT Types
#define ERT_BLUE "Blue"
#define ERT_RED  "Red"
#define ERT_AMBER "Amber"
#define ERT_DEATHSQUAD "Deathsquad"

//ERT subroles
#define ERT_SEC "sec"
#define ERT_MED "med"
#define ERT_ENG "eng"
#define ERT_LEADER "leader"
#define DEATHSQUAD "ds"
#define DEATHSQUAD_LEADER "ds_leader"

//Shuttle elimination hijacking
/// Does not stop elimination hijacking but itself won't elimination hijack
#define ELIMINATION_NEUTRAL 0
/// Needs to be present for shuttle to be elimination hijacked
#define ELIMINATION_ENABLED 1
/// Prevents elimination hijack same way as non-antags
#define ELIMINATION_PREVENT 2

//Syndicate Contracts
#define CONTRACT_STATUS_INACTIVE 1
#define CONTRACT_STATUS_ACTIVE 2
#define CONTRACT_STATUS_BOUNTY_CONSOLE_ACTIVE 3
#define CONTRACT_STATUS_EXTRACTING 4
#define CONTRACT_STATUS_COMPLETE 5
#define CONTRACT_STATUS_ABORTED 6

#define CONTRACT_PAYOUT_LARGE 1
#define CONTRACT_PAYOUT_MEDIUM 2
#define CONTRACT_PAYOUT_SMALL 3

#define CONTRACT_UPLINK_PAGE_CONTRACTS "CONTRACTS"
#define CONTRACT_UPLINK_PAGE_HUB "HUB"

GLOBAL_LIST_INIT(heretic_start_knowledge,list(/datum/eldritch_knowledge/spell/basic,/datum/eldritch_knowledge/living_heart,/datum/eldritch_knowledge/codex_cicatrix))

#define PATH_SIDE "Side"

#define PATH_ASH "Ash"
#define PATH_RUST "Rust"
#define PATH_FLESH "Flesh"
#define PATH_VOID "Void"

/// Forces the blob to place the core where they currently are, ignoring any checks.
#define BLOB_FORCE_PLACEMENT -1
/// Normal blob placement, does the regular checks to make sure the blob isn't placing itself in an invalid location
#define BLOB_NORMAL_PLACEMENT 0
/// Selects a random location for the blob to be placed.
#define BLOB_RANDOM_PLACEMENT 1

#define CONSTRUCT_JUGGERNAUT "Juggernaut"
#define CONSTRUCT_WRAITH "Wraith"
#define CONSTRUCT_ARTIFICER "Artificer"

/// How many telecrystals a normal traitor starts with
#define TELECRYSTALS_DEFAULT 20
/// How many telecrystals mapper/admin only "precharged" uplink implant
#define TELECRYSTALS_PRELOADED_IMPLANT 10
/// The normal cost of an uplink implant; used for calcuating how many
/// TC to charge someone if they get a free implant through choice or
/// because they have nothing else that supports an implant.
#define UPLINK_IMPLANT_TELECRYSTAL_COST 4

/// The Classic Wizard wizard loadout.
#define WIZARD_LOADOUT_CLASSIC "loadout_classic"
/// Mjolnir's Power wizard loadout.
#define WIZARD_LOADOUT_MJOLNIR "loadout_hammer"
/// Fantastical Army wizard loadout.
#define WIZARD_LOADOUT_WIZARMY "loadout_army"
/// Soul Tapper wizard loadout.
#define WIZARD_LOADOUT_SOULTAP "loadout_tap"
/// Convenient list of all wizard loadouts for unit testing.
#define ALL_WIZARD_LOADOUTS list( \
	WIZARD_LOADOUT_CLASSIC, \
	WIZARD_LOADOUT_MJOLNIR, \
	WIZARD_LOADOUT_WIZARMY, \
	WIZARD_LOADOUT_SOULTAP, \
)

///File to the traitor flavor
#define TRAITOR_FLAVOR_FILE "traitor_flavor.json"

///employers that are from the syndicate
GLOBAL_LIST_INIT(syndicate_employers, list(
	"Tiger Cooperative Fanatic",
	"Waffle Corporation Terrorist",
	"Animal Rights Consortium",
	"Bee Liberation Front",
	"Cybersun Industries",
	"MI13",
	"Gorlex Marauders",
	"Donk Corporation",
	"Waffle Corporation",
))
///employers that are from nanotrasen
GLOBAL_LIST_INIT(nanotrasen_employers, list(
	"Gone Postal",
	"Internal Affairs Agent",
	"Corporate Climber",
	"Legal Trouble"
))

///employers who hire agents to do the hijack
GLOBAL_LIST_INIT(hijack_employers, list(
	"Tiger Cooperative Fanatic",
	"Waffle Corporation Terrorist",
	"Animal Rights Consortium",
	"Bee Liberation Front",
	"Gone Postal"
))

///employers who hire agents to do a task and escape... or martyrdom. whatever
GLOBAL_LIST_INIT(normal_employers, list(
	"Cybersun Industries",
	"MI13",
	"Gorlex Marauders",
	"Donk Corporation",
	"Waffle Corporation",
	"Internal Affairs Agent",
	"Corporate Climber",
	"Legal Trouble"
))

///how long traitors will have to wait before an unreasonable objective is rerolled
#define OBJECTIVE_REROLL_TIMER 10 MINUTES

///all the employers that are syndicate
#define FACTION_SYNDICATE "syndicate"
///all the employers that are nanotrasen
#define FACTION_NANOTRASEN "nanotrasen"

#define UPLINK_THEME_SYNDICATE "syndicate"

#define UPLINK_THEME_UNDERWORLD_MARKET "neutral"

/// Checks if the given mob is a blood cultist
#define IS_CULTIST(mob) (mob?.mind?.has_antag_datum(/datum/antagonist/cult))

/// Checks if the given mind is a leader of the monkey antagonists
#define IS_MONKEY_LEADER(mind) mind?.has_antag_datum(/datum/antagonist/monkey/leader)

/// Checks if the given mind is a monkey antagonist
#define IS_INFECTED_MONKEY(mind) mind?.has_antag_datum(/datum/antagonist/monkey)

/// Checks if the given mob is a nuclear operative
#define IS_NUKE_OP(mob) (mob?.mind?.has_antag_datum(/datum/antagonist/nukeop))

#define IS_HERETIC(mob) (mob.mind?.has_antag_datum(/datum/antagonist/heretic))

#define IS_HERETIC_MONSTER(mob) (mob.mind?.has_antag_datum(/datum/antagonist/heretic_monster))

/// Checks if the given mob is a wizard
#define IS_WIZARD(mob) (mob?.mind?.has_antag_datum(/datum/antagonist/wizard))

/// Checks if the given mob is a revolutionary. Will return TRUE for rev heads as well.
#define IS_REVOLUTIONARY(mob) (mob?.mind?.has_antag_datum(/datum/antagonist/rev))

/// Checks if the given mob is a head revolutionary.
#define IS_HEAD_REVOLUTIONARY(mob) (mob?.mind?.has_antag_datum(/datum/antagonist/rev/head))

/// The dimensions of the antagonist preview icon. Will be scaled to this size.
#define ANTAGONIST_PREVIEW_ICON_SIZE 96


code:
#define AQUARIUM_ANIMATION_FISH_SWIM "fish"
#define AQUARIUM_ANIMATION_FISH_DEAD "dead"

#define AQUARIUM_PROPERTIES_PX_MIN "px_min"
#define AQUARIUM_PROPERTIES_PX_MAX "px_max"
#define AQUARIUM_PROPERTIES_PY_MIN "py_min"
#define AQUARIUM_PROPERTIES_PY_MAX "py_max"

#define AQUARIUM_LAYER_MODE_BOTTOM "bottom"
#define AQUARIUM_LAYER_MODE_TOP "top"
#define AQUARIUM_LAYER_MODE_AUTO "auto"

#define FISH_ALIVE "alive"
#define FISH_DEAD "dead"

#define MIN_AQUARIUM_TEMP T0C
#define MAX_AQUARIUM_TEMP T0C + 100
#define DEFAULT_AQUARIUM_TEMP 300

#define FISH_RARITY_BASIC 1000
#define FISH_RARITY_RARE 400
#define FISH_RARITY_VERY_RARE 200
#define FISH_RARITY_GOOD_LUCK_FINDING_THIS 1

#define AQUARIUM_FLUID_FRESHWATER "Freshwater"
#define AQUARIUM_FLUID_SALTWATER "Saltwater"
#define AQUARIUM_FLUID_SULPHWATEVER "Sulphuric Water"
#define AQUARIUM_FLUID_AIR "Air"

#define AQUARIUM_COMPANY "Aquatech Ltd."


code:
// art quality defines, used in datums/components/art.dm, elsewhere
#define BAD_ART 12.5
#define OK_ART 20
#define GOOD_ART 25
#define GREAT_ART 50

///tgui tab portrait categories- they're the same across all portrait tguis.
#define TAB_LIBRARY 1
#define TAB_SECURE 2
#define TAB_PRIVATE 3


code:
//LISTMOS
//indices of values in gas lists.
///Amount of total moles in said gas mixture
#define MOLES 1
///Archived version of MOLES
#define ARCHIVE 2
///All gas related variables
#define GAS_META 3
///Gas specific heat per mole
#define META_GAS_SPECIFIC_HEAT 1
///Name of the gas
#define META_GAS_NAME 2
///Amount of moles required of the gas to be visible
#define META_GAS_MOLES_VISIBLE 3
///Overlay path of the gas, also setup the alpha based on the amount
#define META_GAS_OVERLAY 4
///Let the air alarm know if the gas is dangerous
#define META_GAS_DANGER 5
///Id of the gas for quick access
#define META_GAS_ID 6
///Power of the gas when used in the current iteration of fusion
#define META_GAS_FUSION_POWER 7
//ATMOS
//stuff you should probably leave well alone!
/// kPa*L/(K*mol)
#define R_IDEAL_GAS_EQUATION 8.31
/// kPa
#define ONE_ATMOSPHERE 101.325
/// -270.3degC
#define TCMB 2.7
/// -48.15degC
#define TCRYO 225
/// 0degC
#define T0C 273.15
/// 20degC
#define T20C 293.15
/// -14C - Temperature used for kitchen cold room, medical freezer, etc.
#define COLD_ROOM_TEMP 259.15

/**
 *I feel the need to document what happens here. Basically this is used
 *catch rounding errors, and make gas go away in small portions.
 *People have raised it to higher levels in the past, do not do this. Consider this number a soft limit
 *If you're making gasmixtures that have unexpected behavior related to this value, you're doing something wrong.
 *
 *On an unrelated note this may cause a bug that creates negative gas, related to round(). When it has a second arg it will round up.
 *So for instance round(0.5, 1) == 1. I've hardcoded a fix for this into share, by forcing the garbage collect.
 *Any other attempts to fix it just killed atmos. I leave this to a greater man then I
 */
/// The minimum heat capacity of a gas
#define MINIMUM_HEAT_CAPACITY 0.0003
/// Minimum mole count of a gas
#define MINIMUM_MOLE_COUNT 0.01
/// Molar accuracy to round to
#define MOLAR_ACCURACY  1E-4
/// Types of gases (based on gaslist_cache)
#define GAS_TYPE_COUNT GLOB.gaslist_cache.len
/// Maximum error caused by QUANTIZE when removing gas (roughly, in reality around 2 * MOLAR_ACCURACY less)
#define MAXIMUM_ERROR_GAS_REMOVAL (MOLAR_ACCURACY * GAS_TYPE_COUNT)

/// Moles in a standard cell after which gases are visible
#define MOLES_GAS_VISIBLE 0.25

/// moles_visible * FACTOR_GAS_VISIBLE_MAX = Moles after which gas is at maximum visibility
#define FACTOR_GAS_VISIBLE_MAX 20
/// Mole step for alpha updates. This means alpha can update at 0.25, 0.5, 0.75 and so on
#define MOLES_GAS_VISIBLE_STEP 0.25
/// The total visible states
#define TOTAL_VISIBLE_STATES (FACTOR_GAS_VISIBLE_MAX * (1 / MOLES_GAS_VISIBLE_STEP))

//REACTIONS
//return values for reactions (bitflags)
///The gas mixture is not reacting
#define NO_REACTION 0
///The gas mixture is reacting
#define REACTING 1
///The gas mixture is able to stop all reactions
#define STOP_REACTIONS 2

//Fusion
///Max amount of radiation that can be emitted per reaction cycle
#define FUSION_RAD_MAX 5000
///Maximum instability before the reaction goes endothermic
#define FUSION_INSTABILITY_ENDOTHERMALITY 4
///Maximum reachable fusion temperature
#define FUSION_MAXIMUM_TEMPERATURE 1e8

//EXCITED GROUPS
/**
 * Some further context on breakdown. Unlike dismantle, the breakdown ticker doesn't reset itself when a tile is added
 * This is because we cannot expect maps to have small spaces, so we need to even ourselves out often
 * We do this to avoid equalizing a large space in one tick, with some significant amount of say heat diff
 * This way large areas don't suddenly all become cold at once, it acts more like a wave
 *
 * Because of this and the behavior of share(), the breakdown cycles value can be tweaked directly to effect how fast we want gas to move
 */
/// number of FULL air controller ticks before an excited group breaks down (averages gas contents across turfs)
#define EXCITED_GROUP_BREAKDOWN_CYCLES 5
/// number of FULL air controller ticks before an excited group dismantles and removes its turfs from active
#define EXCITED_GROUP_DISMANTLE_CYCLES (EXCITED_GROUP_BREAKDOWN_CYCLES * 2) + 1 //Reset after 2 breakdowns
/// Ratio of air that must move to/from a tile to reset group processing
#define MINIMUM_AIR_RATIO_TO_SUSPEND 0.1
/// Minimum ratio of air that must move to/from a tile
#define MINIMUM_AIR_RATIO_TO_MOVE 0.001
/// Minimum amount of air that has to move before a group processing can be suspended (Round about 10)
#define MINIMUM_AIR_TO_SUSPEND (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_SUSPEND)
/// Either this must be active (round about 0.1) //Might need to raise this a tad to better support space leaks. we'll see
#define MINIMUM_MOLES_DELTA_TO_MOVE (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_MOVE)
/// or this (or both, obviously)
#define MINIMUM_TEMPERATURE_TO_MOVE (T20C+100)
/// Minimum temperature difference before group processing is suspended
#define MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND 4
/// Minimum temperature difference before the gas temperatures are just set to be equal
#define MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER 0.5
///Minimum temperature to continue superconduction once started
#define MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION (T20C+80)
///Minimum temperature to start doing superconduction calculations
#define MINIMUM_TEMPERATURE_START_SUPERCONDUCTION (T20C+400)

//HEAT TRANSFER COEFFICIENTS
//Must be between 0 and 1. Values closer to 1 equalize temperature faster
//Should not exceed 0.4 else strange heat flow occur
#define WALL_HEAT_TRANSFER_COEFFICIENT 0.0
#define OPEN_HEAT_TRANSFER_COEFFICIENT 0.4
/// a hack for now
#define WINDOW_HEAT_TRANSFER_COEFFICIENT 0.1
/// a hack to help make vacuums "cold", sacrificing realism for gameplay
#define HEAT_CAPACITY_VACUUM 7000

//FIRE
///Minimum temperature for fire to move to the next turf (150 °C or 433 K)
#define FIRE_MINIMUM_TEMPERATURE_TO_SPREAD (150+T0C)
///Minimum temperature for fire to exist on a turf (100 °C or 373 K)
#define FIRE_MINIMUM_TEMPERATURE_TO_EXIST (100+T0C)
///Multiplier for the temperature shared to other turfs
#define FIRE_SPREAD_RADIOSITY_SCALE 0.85
///Helper for small fires to grow
#define FIRE_GROWTH_RATE 40000
///Minimum temperature to burn plasma
#define PLASMA_MINIMUM_BURN_TEMPERATURE (100+T0C)
///Upper temperature ceiling for plasmafire reaction calculations for fuel consumption
#define PLASMA_UPPER_TEMPERATURE (1370+T0C)
///Multiplier for plasmafire with O2 moles * PLASMA_OXYGEN_FULLBURN for the maximum fuel consumption
#define PLASMA_OXYGEN_FULLBURN 10
///Minimum temperature to burn hydrogen
#define HYDROGEN_MINIMUM_BURN_TEMPERATURE (100+T0C)
///Upper temperature ceiling for h2fire reaction calculations for fuel consumption
#define HYDROGEN_UPPER_TEMPERATURE (1370+T0C)
///Multiplier for h2fire with O2 moles * HYDROGEN_OXYGEN_FULLBURN for the maximum fuel consumption
#define HYDROGEN_OXYGEN_FULLBURN 10

//COLD FIRE (this is used only for the freon-o2 reaction, there is no fire still)
///fire will spread if the temperature is -10 °C
#define COLD_FIRE_MAXIMUM_TEMPERATURE_TO_SPREAD 263
///fire will start if the temperature is 0 °C
#define COLD_FIRE_MAXIMUM_TEMPERATURE_TO_EXIST 273
#define COLD_FIRE_SPREAD_RADIOSITY_SCALE 0.95 //Not yet implemented
#define COLD_FIRE_GROWTH_RATE 40000 //Not yet implemented
///Maximum temperature to burn freon
#define FREON_MAXIMUM_BURN_TEMPERATURE 283
///Minimum temperature allowed for the burn to go, we would have negative pressure otherwise
#define FREON_LOWER_TEMPERATURE 60
///Multiplier for freonfire with O2 moles * FREON_OXYGEN_FULLBURN for the maximum fuel consumption
#define FREON_OXYGEN_FULLBURN 10

///moles in a 2.5 m^3 cell at 101.325 Pa and 20 degC (103 or so)
#define MOLES_CELLSTANDARD (ONE_ATMOSPHERE*CELL_VOLUME/(T20C*R_IDEAL_GAS_EQUATION))
///compared against for superconductivity
#define M_CELL_WITH_RATIO (MOLES_CELLSTANDARD * 0.005)
/// percentage of oxygen in a normal mixture of air
#define O2STANDARD 0.21
/// same but for nitrogen
#define N2STANDARD 0.79
/// O2 standard value (21%)
#define MOLES_O2STANDARD (MOLES_CELLSTANDARD*O2STANDARD)
/// N2 standard value (79%)
#define MOLES_N2STANDARD (MOLES_CELLSTANDARD*N2STANDARD)
/// liters in a cell
#define CELL_VOLUME 2500

//CANATMOSPASS
#define ATMOS_PASS_YES 1
#define ATMOS_PASS_NO 0
/// ask can_atmos_pass()
#define ATMOS_PASS_PROC -1
/// just check density
#define ATMOS_PASS_DENSITY -2

//Adjacent turf related defines, they dictate what to do with a turf once it's been recalculated
//Used as "state" in CALCULATE_ADJACENT_TURFS
///Normal non-active turf
#define NORMAL_TURF 1
///Set the turf to be activated on the next calculation
#define MAKE_ACTIVE 2
///Disable excited group
#define KILL_EXCITED 3


code:
//DO NOT USE THESE FOR ACCESSING ATMOS DATA, THEY MUTATE THINGS WHEN CALLED. I WILL BEAT YOU WITH A STICK. See the actual proc for more details
///Check if the turfs allows gas passage based on density, do not use.
#define CANATMOSPASS(A, O) ( A.can_atmos_pass == ATMOS_PASS_PROC ? A.can_atmos_pass(O) : ( A.can_atmos_pass == ATMOS_PASS_DENSITY ? !A.density : A.can_atmos_pass ) )
///Check if the turfs allows gas passage on a z level, do not use.
#define CANVERTICALATMOSPASS(A, O) ( A.can_atmos_pass_vertical == ATMOS_PASS_PROC ? A.can_atmos_pass(O, TRUE) : ( A.can_atmos_pass_vertical == ATMOS_PASS_DENSITY ? !A.density : A.can_atmos_pass_vertical ) )

//Helpers
///Moves the icon of the device based on the piping layer and on the direction
#define PIPING_LAYER_SHIFT(T, PipingLayer) \
	if(T.dir & (NORTH|SOUTH)) { \
		T.pixel_x = (PipingLayer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X;\
	} \
	if(T.dir & (EAST|WEST)) { \
		T.pixel_y = (PipingLayer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y;\
	}

///Moves the icon of the device based on the piping layer and on the direction, the shift amount is dictated by more_shift
#define PIPING_FORWARD_SHIFT(T, PipingLayer, more_shift) \
	if(T.dir & (NORTH|SOUTH)) { \
		T.pixel_y += more_shift * (PipingLayer - PIPING_LAYER_DEFAULT);\
	} \
	if(T.dir & (EAST|WEST)) { \
		T.pixel_x += more_shift * (PipingLayer - PIPING_LAYER_DEFAULT);\
	}

///Moves the icon of the device based on the piping layer on both x and y
#define PIPING_LAYER_DOUBLE_SHIFT(T, PipingLayer) \
	T.pixel_x = (PipingLayer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X;\
	T.pixel_y = (PipingLayer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y;

///Calculate the thermal energy of the selected gas (J)
#define THERMAL_ENERGY(gas) (gas.temperature * gas.heat_capacity())

///Directly adds a gas to a gas mixture without checking for its presence beforehand, use only if is certain the absence of said gas
#define ADD_GAS(gas_id, out_list)\
	var/list/tmp_gaslist = GLOB.gaslist_cache[gas_id]; out_list[gas_id] = tmp_gaslist.Copy();

///Adds a gas to a gas mixture but checks if is already present, faster than the same proc
#define ASSERT_GAS(gas_id, gas_mixture) if (!gas_mixture.gases[gas_id]) { ADD_GAS(gas_id, gas_mixture.gases) };

//prefer this to gas_mixture/total_moles in performance critical areas
///Calculate the total moles of the gas mixture, faster than the proc, good for performance critical areas
#define TOTAL_MOLES(cached_gases, out_var)\
	out_var = 0;\
	for(var/total_moles_id in cached_gases){\
		out_var += cached_gases[total_moles_id][MOLES];\
	}

GLOBAL_LIST_INIT(nonoverlaying_gases, typecache_of_gases_with_no_overlays())
///Returns a list of overlays of every gas in the mixture
#define GAS_OVERLAYS(gases, out_var)\
	out_var = list();\
	for(var/_ID in gases){\
		if(GLOB.nonoverlaying_gases[_ID]) continue;\
		var/_GAS = gases[_ID];\
		var/_GAS_META = _GAS[GAS_META];\
		if(_GAS[MOLES] <= _GAS_META[META_GAS_MOLES_VISIBLE]) continue;\
		var/_GAS_OVERLAY = _GAS_META[META_GAS_OVERLAY];\
		out_var += _GAS_OVERLAY[min(TOTAL_VISIBLE_STATES, CEILING(_GAS[MOLES] / MOLES_GAS_VISIBLE_STEP, 1))];\
	}

#ifdef TESTING
GLOBAL_LIST_INIT(atmos_adjacent_savings, list(0,0))
#define CALCULATE_ADJACENT_TURFS(T, state) if (SSadjacent_air.queue[T]) { GLOB.atmos_adjacent_savings[1] += 1 } else { GLOB.atmos_adjacent_savings[2] += 1; SSadjacent_air.queue[T] = state}
#else
#define CALCULATE_ADJACENT_TURFS(T, state) SSadjacent_air.queue[T] = state
#endif

//If you're doing spreading things related to atmos, DO NOT USE CANATMOSPASS, IT IS NOT CHEAP. use this instead, the info is cached after all. it's tweaked just a bit to allow for circular checks
#define TURFS_CAN_SHARE(T1, T2) (LAZYACCESS(T2.atmos_adjacent_turfs, T1) || LAZYLEN(T1.atmos_adjacent_turfs & T2.atmos_adjacent_turfs))
//Use this to see if a turf is fully blocked or not, think windows or firelocks. Fails with 1x1 non full tile windows, but it's not worth the cost.
#define TURF_SHARES(T) (LAZYLEN(T.atmos_adjacent_turfs))


code:
//OPEN TURF ATMOS
/// the default air mix that open turfs spawn
#define OPENTURF_DEFAULT_ATMOS "o2=22;n2=82;TEMP=293.15"
#define OPENTURF_LOW_PRESSURE "o2=14;n2=30;TEMP=293.15"
/// -193,15°C telecommunications. also used for xenobiology slime killrooms
#define TCOMMS_ATMOS "n2=100;TEMP=80"
/// space
#define AIRLESS_ATMOS "TEMP=2.7"
/// -93.15°C snow and ice turfs
#define FROZEN_ATMOS "o2=22;n2=82;TEMP=180"
/// -14°C kitchen coldroom, just might loss your tail; higher amount of mol to reach about 101.3 kpA
#define KITCHEN_COLDROOM_ATMOS "o2=26;n2=97;TEMP=[COLD_ROOM_TEMP]"
/// used in the holodeck burn test program
#define BURNMIX_ATMOS "o2=2500;plasma=5000;TEMP=370"

//ATMOSPHERICS DEPARTMENT GAS TANK TURFS
#define ATMOS_TANK_N2O "n2o=6000;TEMP=293.15"
#define ATMOS_TANK_CO2 "co2=50000;TEMP=293.15"
#define ATMOS_TANK_PLASMA "plasma=70000;TEMP=293.15"
#define ATMOS_TANK_O2 "o2=100000;TEMP=293.15"
#define ATMOS_TANK_N2 "n2=100000;TEMP=293.15"
#define ATMOS_TANK_BZ "bz=100000;TEMP=293.15"
#define ATMOS_TANK_FREON "freon=100000;TEMP=293.15"
#define ATMOS_TANK_HALON "halon=100000;TEMP=293.15"
#define ATMOS_TANK_HEALIUM "healium=100000;TEMP=293.15"
#define ATMOS_TANK_H2 "hydrogen=100000;TEMP=293.15"
#define ATMOS_TANK_HYPERNOBLIUM "nob=100000;TEMP=293.15"
#define ATMOS_TANK_MIASMA "miasma=100000;TEMP=293.15"
#define ATMOS_TANK_NO2 "no2=100000;TEMP=293.15"
#define ATMOS_TANK_PLUOXIUM "pluox=100000;TEMP=293.15"
#define ATMOS_TANK_PROTO_NITRATE "proto_nitrate=100000;TEMP=293.15"
#define ATMOS_TANK_STIMULUM "stim=100000;TEMP=293.15"
#define ATMOS_TANK_TRITIUM "tritium=100000;TEMP=293.15"
#define ATMOS_TANK_H2O "water_vapor=100000;TEMP=293.15"
#define ATMOS_TANK_ZAUKER "zauker=100000;TEMP=293.15"
#define ATMOS_TANK_HELIUM "helium=100000;TEMP=293.15"
#define ATMOS_TANK_ANTINOBLIUM "antinoblium=100000;TEMP=293.15"
#define ATMOS_TANK_AIRMIX "o2=2644;n2=10580;TEMP=293.15"

//LAVALAND
/// what pressure you have to be under to increase the effect of equipment meant for lavaland
#define LAVALAND_EQUIPMENT_EFFECT_PRESSURE 50

//ATMOS MIX IDS
#define LAVALAND_DEFAULT_ATMOS "LAVALAND_ATMOS"
#define ICEMOON_DEFAULT_ATMOS "ICEMOON_ATMOS"

//ATMOSIA GAS MONITOR TAGS
#define ATMOS_GAS_MONITOR_INPUT_O2 "o2_in"
#define ATMOS_GAS_MONITOR_OUTPUT_O2 "o2_out"
#define ATMOS_GAS_MONITOR_SENSOR_O2 "o2_sensor"

#define ATMOS_GAS_MONITOR_INPUT_PLAS "plas_in"
#define ATMOS_GAS_MONITOR_OUTPUT_PLAS "plas_out"
#define ATMOS_GAS_MONITOR_SENSOR_PLAS "plas_sensor"

#define ATMOS_GAS_MONITOR_INPUT_AIR "air_in"
#define ATMOS_GAS_MONITOR_OUTPUT_AIR "air_out"
#define ATMOS_GAS_MONITOR_SENSOR_AIR "air_sensor"

#define ATMOS_GAS_MONITOR_INPUT_MIX "mix_in"
#define ATMOS_GAS_MONITOR_OUTPUT_MIX "mix_out"
#define ATMOS_GAS_MONITOR_SENSOR_MIX "mix_sensor"

#define ATMOS_GAS_MONITOR_INPUT_N2O "n2o_in"
#define ATMOS_GAS_MONITOR_OUTPUT_N2O "n2o_out"
#define ATMOS_GAS_MONITOR_SENSOR_N2O "n2o_sensor"

#define ATMOS_GAS_MONITOR_INPUT_N2 "n2_in"
#define ATMOS_GAS_MONITOR_OUTPUT_N2 "n2_out"
#define ATMOS_GAS_MONITOR_SENSOR_N2 "n2_sensor"

#define ATMOS_GAS_MONITOR_INPUT_CO2 "co2_in"
#define ATMOS_GAS_MONITOR_OUTPUT_CO2 "co2_out"
#define ATMOS_GAS_MONITOR_SENSOR_CO2 "co2_sensor"

#define ATMOS_GAS_MONITOR_INPUT_BZ "bz_in"
#define ATMOS_GAS_MONITOR_OUTPUT_BZ "bz_out"
#define ATMOS_GAS_MONITOR_SENSOR_BZ "bz_sensor"

#define ATMOS_GAS_MONITOR_INPUT_FREON "freon_in"
#define ATMOS_GAS_MONITOR_OUTPUT_FREON "freon_out"
#define ATMOS_GAS_MONITOR_SENSOR_FREON "freon_sensor"

#define ATMOS_GAS_MONITOR_INPUT_HALON "halon_in"
#define ATMOS_GAS_MONITOR_OUTPUT_HALON "halon_out"
#define ATMOS_GAS_MONITOR_SENSOR_HALON "halon_sensor"

#define ATMOS_GAS_MONITOR_INPUT_HEALIUM "healium_in"
#define ATMOS_GAS_MONITOR_OUTPUT_HEALIUM "healium_out"
#define ATMOS_GAS_MONITOR_SENSOR_HEALIUM "healium_sensor"

#define ATMOS_GAS_MONITOR_INPUT_H2 "h2_in"
#define ATMOS_GAS_MONITOR_OUTPUT_H2 "h2_out"
#define ATMOS_GAS_MONITOR_SENSOR_H2 "h2_sensor"

#define ATMOS_GAS_MONITOR_INPUT_HYPERNOBLIUM "hypernoblium_in"
#define ATMOS_GAS_MONITOR_OUTPUT_HYPERNOBLIUM "hypernoblium_out"
#define ATMOS_GAS_MONITOR_SENSOR_HYPERNOBLIUM "hypernoblium_sensor"

#define ATMOS_GAS_MONITOR_INPUT_MIASMA "miasma_in"
#define ATMOS_GAS_MONITOR_OUTPUT_MIASMA "miasma_out"
#define ATMOS_GAS_MONITOR_SENSOR_MIASMA "miasma_sensor"

#define ATMOS_GAS_MONITOR_INPUT_NO2 "no2_in"
#define ATMOS_GAS_MONITOR_OUTPUT_NO2 "no2_out"
#define ATMOS_GAS_MONITOR_SENSOR_NO2 "no2_sensor"

#define ATMOS_GAS_MONITOR_INPUT_PLUOXIUM "pluoxium_in"
#define ATMOS_GAS_MONITOR_OUTPUT_PLUOXIUM "pluoxium_out"
#define ATMOS_GAS_MONITOR_SENSOR_PLUOXIUM "pluoxium_sensor"

#define ATMOS_GAS_MONITOR_INPUT_PROTO_NITRATE "proto-nitrate_in"
#define ATMOS_GAS_MONITOR_OUTPUT_PROTO_NITRATE "proto-nitrate_out"
#define ATMOS_GAS_MONITOR_SENSOR_PROTO_NITRATE "proto-nitrate_sensor"

#define ATMOS_GAS_MONITOR_INPUT_STIMULUM "stimulum_in"
#define ATMOS_GAS_MONITOR_OUTPUT_STIMULUM "stimulum_out"
#define ATMOS_GAS_MONITOR_SENSOR_STIMULUM "stimulum_sensor"

#define ATMOS_GAS_MONITOR_INPUT_TRITIUM "tritium_in"
#define ATMOS_GAS_MONITOR_OUTPUT_TRITIUM "tritium_out"
#define ATMOS_GAS_MONITOR_SENSOR_TRITIUM "tritium_sensor"

#define ATMOS_GAS_MONITOR_INPUT_H2O "h2o_in"
#define ATMOS_GAS_MONITOR_OUTPUT_H2O "h2o_out"
#define ATMOS_GAS_MONITOR_SENSOR_H2O "h2o_sensor"

#define ATMOS_GAS_MONITOR_INPUT_ZAUKER "zauker_in"
#define ATMOS_GAS_MONITOR_OUTPUT_ZAUKER "zauker_out"
#define ATMOS_GAS_MONITOR_SENSOR_ZAUKER "zauker_sensor"

#define ATMOS_GAS_MONITOR_INPUT_HELIUM "helium_in"
#define ATMOS_GAS_MONITOR_OUTPUT_HELIUM "helium_out"
#define ATMOS_GAS_MONITOR_SENSOR_HELIUM "helium_sensor"

#define ATMOS_GAS_MONITOR_INPUT_ANTINOBLIUM "antinoblium_in"
#define ATMOS_GAS_MONITOR_OUTPUT_ANTINOBLIUM "antinoblium_out"
#define ATMOS_GAS_MONITOR_SENSOR_ANTINOBLIUM "antinoblium_sensor"

#define ATMOS_GAS_MONITOR_INPUT_INCINERATOR "incinerator_in"
#define ATMOS_GAS_MONITOR_OUTPUT_INCINERATOR "incinerator_out"
#define ATMOS_GAS_MONITOR_SENSOR_INCINERATOR "incinerator_sensor"

#define ATMOS_GAS_MONITOR_INPUT_ORDNANCE_LAB "ordnancelab_in"
#define ATMOS_GAS_MONITOR_OUTPUT_ORDNANCE_LAB "ordnancelab_out"
#define ATMOS_GAS_MONITOR_SENSOR_ORDNANCE_LAB "ordnancelab_sensor"

#define ATMOS_GAS_MONITOR_LOOP_DISTRIBUTION "distro-loop_meter"
#define ATMOS_GAS_MONITOR_LOOP_ATMOS_WASTE "atmos-waste_loop_meter"

//AIRLOCK CONTROLLER TAGS

//RnD ordnance burn chamber
#define INCINERATOR_ORDMIX_IGNITER "ordmix_igniter"
#define INCINERATOR_ORDMIX_VENT "ordmix_vent"
#define INCINERATOR_ORDMIX_DP_VENTPUMP "ordmix_airlock_pump"
#define INCINERATOR_ORDMIX_AIRLOCK_SENSOR "ordmix_airlock_sensor"
#define INCINERATOR_ORDMIX_AIRLOCK_CONTROLLER "ordmix_airlock_controller"
#define INCINERATOR_ORDMIX_AIRLOCK_INTERIOR "ordmix_airlock_interior"
#define INCINERATOR_ORDMIX_AIRLOCK_EXTERIOR "ordmix_airlock_exterior"

//Atmospherics/maintenance incinerator
#define INCINERATOR_ATMOS_IGNITER "atmos_incinerator_igniter"
#define INCINERATOR_ATMOS_MAINVENT "atmos_incinerator_mainvent"
#define INCINERATOR_ATMOS_AUXVENT "atmos_incinerator_auxvent"
#define INCINERATOR_ATMOS_DP_VENTPUMP "atmos_incinerator_airlock_pump"
#define INCINERATOR_ATMOS_AIRLOCK_SENSOR "atmos_incinerator_airlock_sensor"
#define INCINERATOR_ATMOS_AIRLOCK_CONTROLLER "atmos_incinerator_airlock_controller"
#define INCINERATOR_ATMOS_AIRLOCK_INTERIOR "atmos_incinerator_airlock_interior"
#define INCINERATOR_ATMOS_AIRLOCK_EXTERIOR "atmos_incinerator_airlock_exterior"
#define TEST_ROOM_ATMOS_MAINVENT_1 "atmos_test_room_mainvent_1"
#define TEST_ROOM_ATMOS_MAINVENT_2 "atmos_test_room_mainvent_2"

//Syndicate lavaland base incinerator (lavaland_surface_syndicate_base1.dmm)
#define INCINERATOR_SYNDICATELAVA_IGNITER "syndicatelava_igniter"
#define INCINERATOR_SYNDICATELAVA_MAINVENT "syndicatelava_mainvent"
#define INCINERATOR_SYNDICATELAVA_AUXVENT "syndicatelava_auxvent"
#define INCINERATOR_SYNDICATELAVA_DP_VENTPUMP "syndicatelava_airlock_pump"
#define INCINERATOR_SYNDICATELAVA_AIRLOCK_SENSOR "syndicatelava_airlock_sensor"
#define INCINERATOR_SYNDICATELAVA_AIRLOCK_CONTROLLER "syndicatelava_airlock_controller"
#define INCINERATOR_SYNDICATELAVA_AIRLOCK_INTERIOR "syndicatelava_airlock_interior"
#define INCINERATOR_SYNDICATELAVA_AIRLOCK_EXTERIOR "syndicatelava_airlock_exterior"


code:
/** liters in a normal breath. note that breaths are taken once every 4 life ticks, which is 8 seconds
 * Addendum for people tweaking this value in the future.
 * Because o2 tank release values/human o2 requirements are very strictly set to the same pressure, small errors can cause breakage
 * This comes from QUANTIZE being used in /datum/gas_mixture.remove(), forming a slight sawtooth pattern of the added/removed gas, centered on the actual pressure
 * Changing BREATH_VOLUME can set us on the lower half of this sawtooth, making humans unable to breath at standard pressure.
 * There's no good way I can come up with to hardcode a fix for this. So if you're going to change this variable
 * graph the functions that describe how it is used/how it interacts with breath code, and pick something on the upper half of the sawtooth
 *
**/
#define BREATH_VOLUME 1.99
/// Amount of air to take a from a tile
#define BREATH_PERCENTAGE (BREATH_VOLUME/CELL_VOLUME)

//Defines for N2O and Healium euphoria moodlets
#define EUPHORIA_INACTIVE 0
#define EUPHORIA_ACTIVE 1
#define EUPHORIA_LAST_FLAG 2

#define MIASMA_CORPSE_MOLES 0.02
#define MIASMA_GIBS_MOLES 0.005

#define MIN_TOXIC_GAS_DAMAGE 1
#define MAX_TOXIC_GAS_DAMAGE 10

// Pressure limits.
/// This determins at what pressure the ultra-high pressure red icon is displayed. (This one is set as a constant)
#define HAZARD_HIGH_PRESSURE 550
/// This determins when the orange pressure icon is displayed (it is 0.7 * HAZARD_HIGH_PRESSURE)
#define WARNING_HIGH_PRESSURE 325
/// This is when the gray low pressure icon is displayed. (it is 2.5 * HAZARD_LOW_PRESSURE)
#define WARNING_LOW_PRESSURE 50
/// This is when the black ultra-low pressure icon is displayed. (This one is set as a constant)
#define HAZARD_LOW_PRESSURE 20

/// This is used in handle_temperature_damage() for humans, and in reagents that affect body temperature. Temperature damage is multiplied by this amount.
#define TEMPERATURE_DAMAGE_COEFFICIENT 1.5

/// The natural temperature for a body
#define BODYTEMP_NORMAL 310.15
/// This is the divisor which handles how much of the temperature difference between the current body temperature and 310.15K (optimal temperature) humans auto-regenerate each tick. The higher the number, the slower the recovery. This is applied each tick, so long as the mob is alive.
#define BODYTEMP_AUTORECOVERY_DIVISOR 28
/// Minimum amount of kelvin moved toward 310K per tick. So long as abs(310.15 - bodytemp) is more than 50.
#define BODYTEMP_AUTORECOVERY_MINIMUM 3
///Similar to the BODYTEMP_AUTORECOVERY_DIVISOR, but this is the divisor which is applied at the stage that follows autorecovery. This is the divisor which comes into play when the human's loc temperature is lower than their body temperature. Make it lower to lose bodytemp faster.
#define BODYTEMP_COLD_DIVISOR 15
/// Similar to the BODYTEMP_AUTORECOVERY_DIVISOR, but this is the divisor which is applied at the stage that follows autorecovery. This is the divisor which comes into play when the human's loc temperature is higher than their body temperature. Make it lower to gain bodytemp faster.
#define BODYTEMP_HEAT_DIVISOR 15
/// The maximum number of degrees that your body can cool in 1 tick, due to the environment, when in a cold area.
#define BODYTEMP_COOLING_MAX -30
/// The maximum number of degrees that your body can heat up in 1 tick, due to the environment, when in a hot area.
#define BODYTEMP_HEATING_MAX 30
/// The body temperature limit the human body can take before it starts taking damage from heat.
/// This also affects how fast the body normalises it's temperature when hot.
/// 340k is about 66c, and rather high for a human.
#define BODYTEMP_HEAT_DAMAGE_LIMIT (BODYTEMP_NORMAL + 30)
/// The body temperature limit the human body can take before it starts taking damage from cold.
/// This also affects how fast the body normalises it's temperature when cold.
/// 270k is about -3c, that is below freezing and would hurt over time.
#define BODYTEMP_COLD_DAMAGE_LIMIT (BODYTEMP_NORMAL - 40)
/// The body temperature limit the human body can take before it will take wound damage.
#define BODYTEMP_HEAT_WOUND_LIMIT (BODYTEMP_NORMAL + 90) // 400.5 k
/// The modifier on cold damage limit hulks get ontop of their regular limit
#define BODYTEMP_HULK_COLD_DAMAGE_LIMIT_MODIFIER 25
/// The modifier on cold damage hulks get.
#define HULK_COLD_DAMAGE_MOD 2

// Body temperature warning icons
/// The temperature the red icon is displayed.
#define BODYTEMP_HEAT_WARNING_3 (BODYTEMP_HEAT_DAMAGE_LIMIT + 360) //+700k
/// The temperature the orange icon is displayed.
#define BODYTEMP_HEAT_WARNING_2 (BODYTEMP_HEAT_DAMAGE_LIMIT + 120) //460K
/// The temperature the yellow icon is displayed.
#define BODYTEMP_HEAT_WARNING_1 (BODYTEMP_HEAT_DAMAGE_LIMIT) //340K
/// The temperature the light green icon is displayed.
#define BODYTEMP_COLD_WARNING_1 (BODYTEMP_COLD_DAMAGE_LIMIT) //270k
/// The temperature the cyan icon is displayed.
#define BODYTEMP_COLD_WARNING_2 (BODYTEMP_COLD_DAMAGE_LIMIT - 70) //200k
/// The temperature the blue icon is displayed.
#define BODYTEMP_COLD_WARNING_3 (BODYTEMP_COLD_DAMAGE_LIMIT - 150) //120k

/// The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE
#define PRESSURE_DAMAGE_COEFFICIENT 2
#define MAX_HIGH_PRESSURE_DAMAGE 2
/// The amount of damage someone takes when in a low pressure area (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value).
#define LOW_PRESSURE_DAMAGE 2

/// Humans are slowed by the difference between bodytemp and BODYTEMP_COLD_DAMAGE_LIMIT divided by this
#define COLD_SLOWDOWN_FACTOR 20

//CLOTHES

/// what min_cold_protection_temperature is set to for space-helmet quality headwear. MUST NOT BE 0.
#define SPACE_HELM_MIN_TEMP_PROTECT 2.0
/// Thermal insulation works both ways /Malkevin
#define SPACE_HELM_MAX_TEMP_PROTECT 1500
/// what min_cold_protection_temperature is set to for space-suit quality jumpsuits or suits. MUST NOT BE 0.
#define SPACE_SUIT_MIN_TEMP_PROTECT 2.0
/// The min cold protection of a space suit without the heater active
#define SPACE_SUIT_MIN_TEMP_PROTECT_OFF 72
#define SPACE_SUIT_MAX_TEMP_PROTECT 1500

/// Cold protection for firesuits
#define FIRE_SUIT_MIN_TEMP_PROTECT 60
/// what max_heat_protection_temperature is set to for firesuit quality suits. MUST NOT BE 0.
#define FIRE_SUIT_MAX_TEMP_PROTECT 30000
/// Cold protection for fire helmets
#define FIRE_HELM_MIN_TEMP_PROTECT 60
/// for fire helmet quality items (red and white hardhats)
#define FIRE_HELM_MAX_TEMP_PROTECT 30000

/// what max_heat_protection_temperature is set to for firesuit quality suits and helmets. MUST NOT BE 0.
#define FIRE_IMMUNITY_MAX_TEMP_PROTECT 35000

/// For normal helmets
#define HELMET_MIN_TEMP_PROTECT 160
/// For normal helmets
#define HELMET_MAX_TEMP_PROTECT 600
/// For armor
#define ARMOR_MIN_TEMP_PROTECT 160
/// For armor
#define ARMOR_MAX_TEMP_PROTECT 600

/// For some gloves (black and)
#define GLOVES_MIN_TEMP_PROTECT 2.0
/// For some gloves
#define GLOVES_MAX_TEMP_PROTECT 1500
/// For gloves
#define SHOES_MIN_TEMP_PROTECT 2.0
/// For gloves
#define SHOES_MAX_TEMP_PROTECT 1500


code:
//PIPES
//Defines for pipe bitmasking
#define NORTH_FULLPIPE (1<<0) //also just NORTH
#define SOUTH_FULLPIPE (1<<1) //also just SOUTH
#define EAST_FULLPIPE (1<<2) //also just EAST
#define WEST_FULLPIPE (1<<3) //also just WEST
#define NORTH_SHORTPIPE (1<<4)
#define SOUTH_SHORTPIPE (1<<5)
#define EAST_SHORTPIPE (1<<6)
#define WEST_SHORTPIPE (1<<7)
// Helpers to convert cardinals to and from pipe bitfields
// Assumes X_FULLPIPE = X, X_SHORTPIPE >> 4 = X as above
#define FULLPIPE_TO_CARDINALS(bitfield) ((bitfield) & ALL_CARDINALS)
#define SHORTPIPE_TO_CARDINALS(bitfield) (((bitfield) >> 4) & ALL_CARDINALS)
#define CARDINAL_TO_FULLPIPES(cardinals) (cardinals)
#define CARDINAL_TO_SHORTPIPES(cardinals) ((cardinals) << 4)
// A pipe is a stub if it only has zero or one permitted direction. For a regular pipe this is nonsensical, and there are no pipe sprites for this, so it is not allowed.
#define ISSTUB(bits) !((bits) & (bits - 1))
#define ISNOTSTUB(bits) ((bits) & (bits - 1))
//Atmos pipe limits
/// (kPa) What pressure pumps and powered equipment max out at.
#define MAX_OUTPUT_PRESSURE 4500
/// (L/s) Maximum speed powered equipment can work at.
#define MAX_TRANSFER_RATE 200
/// How many percent of the contents that an overclocked volume pumps leak into the air
#define VOLUME_PUMP_LEAK_AMOUNT 0.1
//used for device_type vars
#define UNARY 1
#define BINARY 2
#define TRINARY 3
#define QUATERNARY 4

//TANKS
/// The volume of the standard handheld gas tanks on the station.
#define TANK_STANDARD_VOLUME 70
/// The minimum pressure an gas tanks release valve can be set to.
#define TANK_MIN_RELEASE_PRESSURE 0
/// The maximum pressure an gas tanks release valve can be set to.
#define TANK_MAX_RELEASE_PRESSURE (ONE_ATMOSPHERE*3)
/// The default initial value gas tanks release valves are set to. (At least the ones containing pure plasma/oxygen.)
#define TANK_DEFAULT_RELEASE_PRESSURE 16
/// The internal temperature in kelvins at which a handheld gas tank begins to take damage.
#define TANK_MELT_TEMPERATURE 1000000
/// The internal pressure in kPa at which a handheld gas tank begins to take damage.
#define TANK_LEAK_PRESSURE (30.*ONE_ATMOSPHERE)
/// The internal pressure in kPa at which a handheld gas tank almost immediately ruptures.
#define TANK_RUPTURE_PRESSURE (35.*ONE_ATMOSPHERE)
/// The internal pressure in kPa at which an gas tank that breaks will cause an explosion.
#define TANK_FRAGMENT_PRESSURE (40.*ONE_ATMOSPHERE)
/// Range scaling constant for tank explosions. Calibrated so that a TTV assembled using two 70L tanks will hit the maxcap at at least 160atm.
#define TANK_FRAGMENT_SCALE (84.*ONE_ATMOSPHERE)

//MULTIPIPES
//IF YOU EVER CHANGE THESE CHANGE SPRITES TO MATCH.
//layer = initial(layer) + piping_layer / 1000 in atmospherics/update_icon() to determine order of pipe overlap
#define PIPING_LAYER_MIN 1
#define PIPING_LAYER_MAX 5
#define PIPING_LAYER_DEFAULT 3
#define PIPING_LAYER_P_X 5
#define PIPING_LAYER_P_Y 5
#define PIPING_LAYER_LCHANGE 0.05

/// intended to connect with all layers, check for all instead of just one.
#define PIPING_ALL_LAYER (1<<0)
/// can only be built if nothing else with this flag is on the tile already.
#define PIPING_ONE_PER_TURF (1<<1)
/// can only exist at PIPING_LAYER_DEFAULT
#define PIPING_DEFAULT_LAYER_ONLY (1<<2)
/// north/south east/west doesn't matter, auto normalize on build.
#define PIPING_CARDINAL_AUTONORMALIZE (1<<3)
/// intended to connect with everything, both layers and colors
#define PIPING_ALL_COLORS (1<<4)
/// can bridge over pipenets
#define PIPING_BRIDGE (1<<5)

// Ventcrawling bitflags, handled in var/vent_movement
///Allows for ventcrawling to occur. All atmospheric machines have this flag on by default. Cryo is the exception
#define VENTCRAWL_ALLOWED	(1<<0)
///Allows mobs to enter or leave from atmospheric machines. On for passive, unary, and scrubber vents.
#define VENTCRAWL_ENTRANCE_ALLOWED (1<<1)
///Used to check if a machinery is visible. Called by update_pipe_vision(). On by default for all except cryo.
#define VENTCRAWL_CAN_SEE	(1<<2)


code:
// for secHUDs and medHUDs and variants. The number is the location of the image on the list hud_list
// note: if you add more HUDs, even for non-human atoms, make sure to use unique numbers for the defines!
// /datum/atom_hud expects these to be unique
// these need to be strings in order to make them associative lists
/// dead, alive, sick, health status
#define HEALTH_HUD "1"
/// a simple line rounding the mob's number health
#define STATUS_HUD "2"
/// the job asigned to your ID
#define ID_HUD "3"
/// wanted, released, parroled, security status
#define WANTED_HUD "4"
/// loyality implant
#define IMPLOYAL_HUD "5"
/// chemical implant
#define IMPCHEM_HUD "6"
/// tracking implant
#define IMPTRACK_HUD "7"
/// Silicon/Mech/Circuit Status
#define DIAG_STAT_HUD "8"
/// Silicon health bar
#define DIAG_HUD "9"
/// Borg/Mech/Circutry power meter
#define DIAG_BATT_HUD "10"
/// Mech health bar
#define DIAG_MECH_HUD "11"
/// Bot HUDs
#define DIAG_BOT_HUD "12"
/// Circuit assembly health bar
#define DIAG_CIRCUIT_HUD "13"
/// Mech/Silicon tracking beacon, Circutry long range icon
#define DIAG_TRACK_HUD "14"
/// Airlock shock overlay
#define DIAG_AIRLOCK_HUD "15"
/// Bot path indicators
#define DIAG_PATH_HUD "16"
/// Gland indicators for abductors
#define GLAND_HUD "17"
#define SENTIENT_DISEASE_HUD "18"
#define AI_DETECT_HUD "19"
/// Displays launchpads' targeting reticle
#define DIAG_LAUNCHPAD_HUD "22"
//for antag huds. these are used at the /mob level
#define ANTAG_HUD "23"
// for fans to identify pins
#define FAN_HUD "24"

//by default everything in the hud_list of an atom is an image
//a value in hud_list with one of these will change that behavior
#define HUD_LIST_LIST 1

//data HUD (medhud, sechud) defines
//Don't forget to update human/New() if you change these!
#define DATA_HUD_SECURITY_BASIC 1
#define DATA_HUD_SECURITY_ADVANCED 2
#define DATA_HUD_MEDICAL_BASIC 3
#define DATA_HUD_MEDICAL_ADVANCED 4
#define DATA_HUD_DIAGNOSTIC_BASIC 5
#define DATA_HUD_DIAGNOSTIC_ADVANCED 6
#define DATA_HUD_ABDUCTOR 7
#define DATA_HUD_SENTIENT_DISEASE 8
#define DATA_HUD_AI_DETECT 9
#define DATA_HUD_FAN 10

//antag HUD defines
#define ANTAG_HUD_CULT 11
#define ANTAG_HUD_REV 12
#define ANTAG_HUD_OPS 13
#define ANTAG_HUD_WIZ 14
#define ANTAG_HUD_SHADOW 15
#define ANTAG_HUD_TRAITOR 16
#define ANTAG_HUD_NINJA 17
#define ANTAG_HUD_CHANGELING 18
#define ANTAG_HUD_ABDUCTOR 19
#define ANTAG_HUD_BROTHER 20
#define ANTAG_HUD_OBSESSED 21
#define ANTAG_HUD_FUGITIVE 22
#define ANTAG_HUD_GANGSTER 23
#define ANTAG_HUD_SPACECOP 24
#define ANTAG_HUD_HERETIC 25
#define ANTAG_HUD_BRAINWASHED 26

// Notification action types
#define NOTIFY_JUMP "jump"
#define NOTIFY_ATTACK "attack"
#define NOTIFY_ORBIT "orbit"

/// cooldown for being shown the images for any particular data hud
#define ADD_HUD_TO_COOLDOWN 20


code:
#define BASIC_MOB_MAX_STAMINALOSS 200

///Basic mob flags
#define DEL_ON_DEATH (1<<0)


code:
#define DEFINE_BITFIELD(_variable, _flags) /datum/bitfield/##_variable { \
	flags = ##_flags; \
	variable = #_variable; \
}


code:
// Shipping methods

// The BEST way of shipping items: accurate, "undetectable"
#define SHIPPING_METHOD_LTSRBT "LTSRBT"
// Picks a random area to teleport the item to and gives you a minute to get there before it is sent.
#define SHIPPING_METHOD_TELEPORT "Teleport"
// Throws the item from somewhere at the station.
#define SHIPPING_METHOD_LAUNCH "Launch"


code:
// Overmind defines

#define OVERMIND_MAX_POINTS_DEFAULT 100 // Max point storage
#define OVERMIND_STARTING_POINTS 60 // Points granted upon start
#define OVERMIND_STARTING_REROLLS 1 // Free strain rerolls at the start
#define OVERMIND_STARTING_MIN_PLACE_TIME 1 MINUTES // Minimum time before the core can be placed
#define OVERMIND_STARTING_AUTO_PLACE_TIME 6 MINUTES // After this time, randomly place the core somewhere viable
#define OVERMIND_WIN_CONDITION_AMOUNT 400 // Blob structures required to win
#define OVERMIND_ANNOUNCEMENT_MIN_SIZE 75 // Once the blob has this many structures, announce their presence
#define OVERMIND_ANNOUNCEMENT_MAX_TIME 10 MINUTES // If the blob hasn't reached the minimum size before this time, announce their presence
#define OVERMIND_MAX_CAMERA_STRAY "3x3" // How far the overmind camera is allowed to stray from blob tiles. 3x3 is 1 tile away, 5x5 2 tiles etc

// Generic blob defines

#define BLOB_BASE_POINT_RATE 2 // Base amount of points per process()
#define BLOB_EXPAND_COST 4 // Price to expand onto a new tile
#define BLOB_ATTACK_REFUND 2 // Points 'refunded' when the expand attempt actually attacks something instead
#define BLOB_BRUTE_RESIST 0.5 // Brute damage taken gets multiplied by this value
#define BLOB_FIRE_RESIST 1 // Burn damage taken gets multiplied by this value
#define BLOB_EXPAND_CHANCE_MULTIPLIER 1 // Increase this value to make blobs naturally expand faster
#define BLOB_REINFORCE_CHANCE 2.5 // The delta_time chance for cores/nodes to reinforce their surroundings
#define BLOB_REAGENTATK_VOL 25 // Amount of strain-reagents that get injected when the blob attacks: main source of blob damage

// Structure properties

#define BLOB_CORE_MAX_HP 400
#define BLOB_CORE_HP_REGEN 2 // Bases health regeneration rate every process(), can be added on by strains
#define BLOB_CORE_CLAIM_RANGE 12 // Range in which blob tiles are 'claimed' (converted from dead to alive, rarely useful)
#define BLOB_CORE_PULSE_RANGE 4 // The radius up to which the core activates structures, and up to which structures can be built
#define BLOB_CORE_EXPAND_RANGE 3 // Radius of automatic expansion
#define BLOB_CORE_STRONG_REINFORCE_RANGE 1 // The radius of tiles surrounding the core that get upgraded
#define BLOB_CORE_REFLECTOR_REINFORCE_RANGE 0
#define BLOB_CORE_MAX_SPORES 0 // Spores that the core can produce for free

#define BLOB_NODE_MAX_HP 200
#define BLOB_NODE_HP_REGEN 3
#define BLOB_NODE_MIN_DISTANCE 5 // Minimum distance between nodes
#define BLOB_NODE_CLAIM_RANGE 10
#define BLOB_NODE_PULSE_RANGE 3 // The radius up to which the core activates structures, and up to which structures can be built
#define BLOB_NODE_EXPAND_RANGE 2 // Radius of automatic expansion
#define BLOB_NODE_STRONG_REINFORCE_RANGE 0 // The radius of tiles surrounding the node that get upgraded
#define BLOB_NODE_REFLECTOR_REINFORCE_RANGE 0
#define BLOB_NODE_MAX_SPORES 0 // Spores that nodes can maintain

#define BLOB_FACTORY_MAX_HP 200
#define BLOB_FACTORY_HP_REGEN 1
#define BLOB_FACTORY_MIN_DISTANCE 7 // Minimum distance between factories
#define BLOB_FACTORY_MAX_SPORES 3

#define BLOB_RESOURCE_MAX_HP 60
#define BLOB_RESOURCE_HP_REGEN 15
#define BLOB_RESOURCE_MIN_DISTANCE 4 // Minimum distance between resource blobs
#define BLOB_RESOURCE_GATHER_DELAY 4 SECONDS // Gather points when pulsed outside this interval
#define BLOB_RESOURCE_GATHER_ADDED_DELAY 0.25 SECONDS // Every additional resource blob adds this amount to the gather delay
#define BLOB_RESOURCE_GATHER_AMOUNT 1 // The amount of points added to the overmind

#define BLOB_REGULAR_MAX_HP 25
#define BLOB_REGULAR_HP_INIT 21 // The starting HP of a normal blob tile
#define BLOB_REGULAR_HP_REGEN 1 // Health regenerated when pulsed by a node/core

#define BLOB_STRONG_MAX_HP 150
#define BLOB_STRONG_HP_REGEN 2

#define BLOB_REFLECTOR_MAX_HP 150
#define BLOB_REFLECTOR_HP_REGEN 2

// Structure purchasing

#define BLOB_UPGRADE_STRONG_COST 15 // Upgrade and build costs here
#define BLOB_UPGRADE_REFLECTOR_COST 15
#define BLOB_STRUCTURE_RESOURCE_COST 40
#define BLOB_STRUCTURE_FACTORY_COST 60
#define BLOB_STRUCTURE_NODE_COST 50

#define BLOB_REFUND_STRONG_COST 4 // Points refunded when destroying the structure
#define BLOB_REFUND_REFLECTOR_COST 8
#define BLOB_REFUND_RESOURCE_COST 15
#define BLOB_REFUND_FACTORY_COST 25
#define BLOB_REFUND_NODE_COST 25

// Blob power properties

#define BLOB_POWER_RELOCATE_COST 80 // Resource cost to move your core to a different node
#define BLOB_POWER_REROLL_COST 40 // Strain reroll
#define BLOB_POWER_REROLL_FREE_TIME 4 MINUTES // Gain a free strain reroll every x minutes
#define BLOB_POWER_REROLL_CHOICES 6 // Possibilities to choose from; keep in mind increasing this might fuck with the radial menu

// Mob defines

#define BLOBMOB_HEALING_MULTIPLIER 0.0125 // Multiplies by -maxHealth and heals the blob by this amount every blob_act
#define BLOBMOB_SPORE_HEALTH 30 // Base spore health
#define BLOBMOB_SPORE_SPAWN_COOLDOWN 8 SECONDS
#define BLOBMOB_SPORE_DMG_LOWER 2
#define BLOBMOB_SPORE_DMG_UPPER 4
#define BLOBMOB_BLOBBERNAUT_RESOURCE_COST 40 // Purchase price for making a blobbernaut
#define BLOBMOB_BLOBBERNAUT_HEALTH 200 // Base blobbernaut health
#define BLOBMOB_BLOBBERNAUT_DMG_SOLO_LOWER 20 // Damage without active overmind (core dead or xenobio mob)
#define BLOBMOB_BLOBBERNAUT_DMG_SOLO_UPPER 20
#define BLOBMOB_BLOBBERNAUT_DMG_LOWER 4 // Damage dealt with active overmind (most damage comes from strain chems)
#define BLOBMOB_BLOBBERNAUT_DMG_UPPER 4
#define BLOBMOB_BLOBBERNAUT_REAGENTATK_VOL 20 // Amounts of strain reagents applied on attack -- basically the main damage stat
#define BLOBMOB_BLOBBERNAUT_DMG_OBJ 60 // Damage dealth to objects/machines
#define BLOBMOB_BLOBBERNAUT_HEALING_CORE 0.05 // Percentage multiplier HP restored on Life() when within 2 tiles of the blob core
#define BLOBMOB_BLOBBERNAUT_HEALING_NODE 0.025 // Same, but for a nearby node
#define BLOBMOB_BLOBBERNAUT_HEALTH_DECAY 0.0125 // Percentage multiplier HP lost when not near blob tiles or without factory