Documents 61 files (#9306)

* Document the world (#46495)

* Document drone verbs.dm

* Document the outfit datum with autodoc (#45415)

* Uncurse take_damage and document obj_defense.dm (#45146)

The original take_damage proc defined vars for no good reason had some 
duplicate code and wasn't very readable.

If you are wondering why it calls obj_break every time it takes damage 
while below integrity_failure, that's the way it used to be. Most (if 
not all) stuff that takes advantage of this functionality already 
accounts for this.

* Convert some code docs into the auto doc format (#45101)

* Commit Message

* Fixes

* e

* Documents browserOutput.dm (#51439)

* Add autodoc to the callback datum (#45463)

* Autodoc the vending machine (#45468)

* Autodoc the vending machine

* Update code/modules/vending/_vending.dm

Co-Authored-By: Tad Hardesty <tad@platymuus.com>

* autodoc organ helpers (#45464)

* timer proc autodocs (#46530)

* bunch of define autodocs

* ballistic guns autodoc (#45578)

* ballistic guns autodoc

* fixes

* client vars autodoc (#46446)

About The Pull Request

Autodocs client vars

* Autodoc for XB and Research

* shuttle docking autodoc (#48677)

* Add autodocs for reagents (#49478)

* Fix

Co-authored-by: oranges <email@oranges.net.nz>
Co-authored-by: Jonathan (JJRcop) Rubenstein <jrubcop@gmail.com>
Co-authored-by: nemvar <47324920+nemvar@users.noreply.github.com>
Co-authored-by: alexkar598 <>
Co-authored-by: Tad Hardesty <tad@platymuus.com>
Co-authored-by: spookydonut <github@spooksoftware.com>
Co-authored-by: actioninja <actioninja@gmail.com>
This commit is contained in:
alexkar598
2020-07-24 21:38:47 -04:00
committed by GitHub
parent f3b1d3d672
commit 8b963c9626
61 changed files with 3149 additions and 893 deletions

View File

@@ -91,9 +91,11 @@
#define TR_KEEPITEMS (1<<0)
#define TR_KEEPVIRUS (1<<1)
#define TR_KEEPDAMAGE (1<<2)
#define TR_HASHNAME (1<<3) // hashing names (e.g. monkey(e34f)) (only in monkeyize)
/// hashing names (e.g. monkey(e34f)) (only in monkeyize)
#define TR_HASHNAME (1<<3)
#define TR_KEEPIMPLANTS (1<<4)
#define TR_KEEPSE (1<<5) // changelings shouldn't edit the DNA's SE when turning into a monkey
/// changelings shouldn't edit the DNA's SE when turning into a monkey
#define TR_KEEPSE (1<<5)
#define TR_DEFAULTMSG (1<<6)
#define TR_KEEPORGANS (1<<8)
#define TR_KEEPSTUNS (1<<9)
@@ -111,18 +113,22 @@
#define LIPS 5
#define NOBLOOD 6
#define NOTRANSSTING 7
#define MUTCOLORS_PARTSONLY 8 //Used if we want the mutant colour to be only used by mutant bodyparts. Don't combine this with MUTCOLORS, or it will be useless.
/// Used if we want the mutant colour to be only used by mutant bodyparts. Don't combine this with MUTCOLORS, or it will be useless.
#define MUTCOLORS_PARTSONLY 8
#define NOZOMBIE 9
#define DIGITIGRADE 10 //Uses weird leg sprites. Optional for Lizards, required for ashwalkers. Don't give it to other races unless you make sprites for this (see human_parts_greyscale.dmi)
/// Uses weird leg sprites. Optional for Lizards, required for ashwalkers. Don't give it to other races unless you make sprites for this (see human_parts_greyscale.dmi)
#define DIGITIGRADE 10
#define NO_UNDERWEAR 11
#define NOLIVER 12
#define NOSTOMACH 13
#define NO_DNA_COPY 14
#define DRINKSBLOOD 15
#define NOFLASH 16
#define DYNCOLORS 17 //Use this if you want to change the race's color without the player being able to pick their own color. AKA special color shifting
/// Use this if you want to change the race's color without the player being able to pick their own color. AKA special color shifting
#define DYNCOLORS 17
#define AGENDER 18
#define NOEYESPRITES 19 //Do not draw eyes or eyeless overlay
/// Do not draw eyes or eyeless overlay
#define NOEYESPRITES 19
//organ slots
#define ORGAN_SLOT_BRAIN "brain"
@@ -152,7 +158,8 @@
//organ defines
#define STANDARD_ORGAN_THRESHOLD 100
#define STANDARD_ORGAN_HEALING 0.001
#define STANDARD_ORGAN_DECAY 0.00222 //designed to fail organs when left to decay for ~15 minutes
/// designed to fail organs when left to decay for ~15 minutes
#define STANDARD_ORGAN_DECAY 0.00222
//used for the can_chromosome var on mutations
#define CHROMOSOME_NEVER 0

View File

@@ -1,15 +1,15 @@
//See also controllers/globals.dm
//Creates a global initializer with a given InitValue expression, do not use
/// 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
/// 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
/// Prevents a given global from being VV'd
#ifndef TESTING
#define GLOBAL_PROTECT(X)\
/datum/controller/global_vars/InitGlobal##X(){\
@@ -20,41 +20,41 @@
#define GLOBAL_PROTECT(X)
#endif
//Standard BYOND global, do not use
/// Standard BYOND global, do not use
#define GLOBAL_REAL_VAR(X) var/global/##X
//Standard typed BYOND global, do not use
/// 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
/// 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
/// 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
/// 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
/// 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
/// 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
/// 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
/// 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
/// 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
/// Create an untyped null global
#define GLOBAL_VAR(X) GLOBAL_RAW(/##X); GLOBAL_UNMANAGED(X)
//Create a null global list
/// Create a null global list
#define GLOBAL_LIST(X) GLOBAL_RAW(/list/##X); GLOBAL_UNMANAGED(X)
//Create an typed null global
/// Create an typed null global
#define GLOBAL_DATUM(X, Typepath) GLOBAL_RAW(Typepath/##X); GLOBAL_UNMANAGED(X)

View File

@@ -1,3 +1,4 @@
///Protects a datum from being VV'd
#define GENERAL_PROTECT_DATUM(Path)\
##Path/can_vv_get(var_name){\
return FALSE;\
@@ -7,4 +8,4 @@
}\
##Path/CanProcCall(procname){\
return FALSE;\
}
}

View File

@@ -1,13 +1,23 @@
/// Tick limit while running normally
#define TICK_LIMIT_RUNNING 80
/// 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 98
#define TICK_USAGE world.tick_usage //for general usage
#define TICK_USAGE_REAL world.tick_usage //to be used where the result isn't checked
/// 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 )

View File

@@ -1,21 +1,33 @@
#define ACCESS_SECURITY 1 // Security equipment, security records, gulag item storage, secbots
#define ACCESS_BRIG 2 // Brig cells+timers, permabrig, gulag+gulag shuttle, prisoner management console
#define ACCESS_ARMORY 3 // Armory, gulag teleporter, execution chamber
#define ACCESS_FORENSICS_LOCKERS 4 //Detective's office, forensics lockers, security+medical records
// 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
#define ACCESS_TOX 7 //R&D department, R&D console, burn chamber on some maps
#define ACCESS_TOX_STORAGE 8 //Toxins storage, burn chamber on some maps
/// R&D department, R&D console, burn chamber on some maps
#define ACCESS_TOX 7
/// Toxins storage, burn chamber on some maps
#define ACCESS_TOX_STORAGE 8
/// Genetics access
#define ACCESS_GENETICS 9
#define ACCESS_ENGINE 10 //Engineering area, power monitor, power flow control console
#define ACCESS_ENGINE_EQUIP 11 //APCs, EngiVend/YouTool, engineering equipment lockers
/// 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
#define ACCESS_HEADS 19 //Bridge, EVA storage windoors, gateway shutters, AI integrity restorer, clone record deletion, comms console
/// Bridge, EVA storage windoors, gateway shutters, AI integrity restorer, clone record deletion, comms console
#define ACCESS_HEADS 19
#define ACCESS_CAPTAIN 20
#define ACCESS_ALL_PERSONAL_LOCKERS 21
#define ACCESS_CHAPEL_OFFICE 22
@@ -49,47 +61,74 @@
#define ACCESS_CE 56
#define ACCESS_HOP 57
#define ACCESS_HOS 58
#define ACCESS_RC_ANNOUNCE 59 //Request console announcements
#define ACCESS_KEYCARD_AUTH 60 //Used for events which require at least two people to confirm them
#define ACCESS_TCOMSAT 61 // has access to the entire telecomms satellite / machinery
/// 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
#define ACCESS_SEC_DOORS 63 // Outer brig doors, department security posts
#define ACCESS_MINERAL_STOREROOM 64 //For releasing minerals from the ORM
/// 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
#define ACCESS_WEAPONS 66 //Weapon authorization for secbots
#define ACCESS_NETWORK 67 //NTnet diagnostics/monitoring software
#define ACCESS_CLONING 68 //Cloning room and clone pod ejection
#define ACCESS_PARAMEDIC 69 //Paramedic Office
#define ACCESS_TCOM_ADMIN 70 // Access to the Signal Tech monitoring room
/// Weapon authorization for secbots
#define ACCESS_WEAPONS 66
/// NTnet diagnostics/monitoring software
#define ACCESS_NETWORK 67
///Cloning room and clone pod ejection
#define ACCESS_CLONING 68
///Paramedic Office
#define ACCESS_PARAMEDIC 69
///Access to the Signal Tech monitoring room
#define ACCESS_TCOM_ADMIN 70
#define ACCESS_FREEMINER 71
#define ACCESS_FREEMINER_CAPTAIN 72
//BEGIN CENTCOM ACCESS
/*Should leave plenty of room if we need to add more access levels.
Mostly for admin fun times.*/
#define ACCESS_CENT_GENERAL 101//General facilities. CentCom ferry.
#define ACCESS_CENT_THUNDER 102//Thunderdome.
#define ACCESS_CENT_SPECOPS 103//Special Ops. Captain's display case, Marauder and Seraph mechs.
#define ACCESS_CENT_MEDICAL 104//Medical/Research
#define ACCESS_CENT_LIVING 105//Living quarters.
#define ACCESS_CENT_STORAGE 106//Generic storage areas.
#define ACCESS_CENT_TELEPORTER 107//Teleporter.
#define ACCESS_CENT_CAPTAIN 109//Captain's office/ID comp/AI.
#define ACCESS_CENT_BAR 110 // The non-existent CentCom Bar
/// 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
#define ACCESS_SYNDICATE 150//General Syndicate Access. Includes Syndicate mechs and ruins.
#define ACCESS_SYNDICATE_LEADER 151//Nuke Op Leader Access
/// 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? */
#define ACCESS_AWAY_GENERAL 200//General facilities.
#define ACCESS_AWAY_MAINT 201//Away maintenance
#define ACCESS_AWAY_MED 202//Away medical
#define ACCESS_AWAY_SEC 203//Away security
#define ACCESS_AWAY_ENGINE 204//Away engineering
#define ACCESS_AWAY_GENERIC1 205//Away generic access
/// 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

View File

@@ -13,11 +13,13 @@
#define BANTYPE_TEMP 2
#define BANTYPE_JOB_PERMA 3
#define BANTYPE_JOB_TEMP 4
#define BANTYPE_ANY_FULLBAN 5 //used to locate stuff to unban.
/// used to locate stuff to unban.
#define BANTYPE_ANY_FULLBAN 5
#define BANTYPE_ADMIN_PERMA 7
#define BANTYPE_ADMIN_TEMP 8
#define BANTYPE_ANY_JOB 9 //used to remove jobbans
/// used to remove jobbans
#define BANTYPE_ANY_JOB 9
//Admin Permissions
#define R_BUILDMODE (1<<0)
@@ -78,14 +80,19 @@
#define AHELP_CLOSED 2
#define AHELP_RESOLVED 3
#define ROUNDSTART_LOGOUT_REPORT_TIME 6000 //Amount of time (in deciseconds) after the rounds starts, that the player disconnect report is issued.
/// Amount of time (in deciseconds) after the rounds starts, that the player disconnect report is issued.
#define ROUNDSTART_LOGOUT_REPORT_TIME 6000
#define SPAM_TRIGGER_WARNING 5 //Number of identical messages required before the spam-prevention will warn you to stfu
#define SPAM_TRIGGER_AUTOMUTE 10 //Number of identical messages required before the spam-prevention will automute you
/// 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
#define STICKYBAN_DB_CACHE_TIME 10 SECONDS
#define STICKYBAN_ROGUE_CHECK_TIME 5
#define POLICY_POLYMORPH "polymorph" //Shown to vicitm of staff of change and related effects.
#define POLICY_VERB_HEADER "policy_verb_header" //Shown on top of policy verb window
/// 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"

View File

@@ -26,10 +26,12 @@
//Blob
#define BLOB_REROLL_TIME 2400 //blob gets a free reroll every X time
/// blob gets a free reroll every X time
#define BLOB_REROLL_TIME 2400
#define BLOB_SPREAD_COST 4
#define BLOB_ATTACK_REFUND 2 //blob refunds this much if it attacks and doesn't spread
#define BLOB_REFLECTOR_COST 0 //yogs - reflectors are free
/// blob refunds this much if it attacks and doesn't spread
#define BLOB_ATTACK_REFUND 2
#define BLOB_REFLECTOR_COST 15
//ERT Types
@@ -47,11 +49,14 @@
#define DEATHSQUAD_LEADER "ds_leader"
//Shuttle hijacking
#define HIJACK_NEUTRAL 0 //Does not stop hijacking but itself won't hijack
#define HIJACK_HIJACKER 1 //Needs to be present for shuttle to be hijacked
#define HIJACK_PREVENT 2 //Prevents hijacking same way as non-antags
/// Does not stop hijacking but itself won't hijack
#define HIJACK_NEUTRAL 0
/// Needs to be present for shuttle to be hijacked
#define HIJACK_HIJACKER 1
/// Prevents hijacking same way as non-antags
#define HIJACK_PREVENT 2
//Overthrow time to update heads obj
///Overthrow time to update heads obj
#define OBJECTIVE_UPDATING_TIME 300
//Assimilation

View File

@@ -12,33 +12,57 @@
#define META_GAS_FUSION_POWER 7
//ATMOS
//stuff you should probably leave well alone!
#define R_IDEAL_GAS_EQUATION 8.31 //kPa*L/(K*mol)
#define ONE_ATMOSPHERE 101.325 //kPa
#define TCMB 2.7 // -270.3degC
#define TCRYO 225 // -48.15degC
#define T0C 273.15 // 0degC
#define T20C 293.15 // 20degC
/// 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
#define MOLES_CELLSTANDARD (ONE_ATMOSPHERE*CELL_VOLUME/(T20C*R_IDEAL_GAS_EQUATION)) //moles in a 2.5 m^3 cell at 101.325 Pa and 20 degC
#define M_CELL_WITH_RATIO (MOLES_CELLSTANDARD * 0.005) //compared against for superconductivity
#define O2STANDARD 0.21 //percentage of oxygen in a normal mixture of air
#define N2STANDARD 0.79 //same but for nitrogen
#define MOLES_O2STANDARD (MOLES_CELLSTANDARD*O2STANDARD) // O2 standard value (21%)
#define MOLES_N2STANDARD (MOLES_CELLSTANDARD*N2STANDARD) // N2 standard value (79%)
#define CELL_VOLUME 2500 //liters in a cell
#define BREATH_VOLUME 0.5 //liters in a normal breath
#define BREATH_PERCENTAGE (BREATH_VOLUME/CELL_VOLUME) //Amount of air to take a from a tile
///moles in a 2.5 m^3 cell at 101.325 Pa and 20 degC
#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
/// liters in a normal breath
#define BREATH_VOLUME 0.5
/// Amount of air to take a from a tile
#define BREATH_PERCENTAGE (BREATH_VOLUME/CELL_VOLUME)
//EXCITED GROUPS
#define EXCITED_GROUP_BREAKDOWN_CYCLES 4 //number of FULL air controller ticks before an excited group breaks down (averages gas contents across turfs)
#define EXCITED_GROUP_DISMANTLE_CYCLES 16 //number of FULL air controller ticks before an excited group dismantles and removes its turfs from active
#define MINIMUM_AIR_RATIO_TO_SUSPEND 0.1 //Ratio of air that must move to/from a tile to reset group processing
#define MINIMUM_AIR_RATIO_TO_MOVE 0.001 //Minimum ratio of air that must move to/from a tile
#define MINIMUM_AIR_TO_SUSPEND (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_SUSPEND) //Minimum amount of air that has to move before a group processing can be suspended
#define MINIMUM_MOLES_DELTA_TO_MOVE (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_MOVE) //Either this must be active
#define MINIMUM_TEMPERATURE_TO_MOVE (T20C+100) //or this (or both, obviously)
#define MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND 4 //Minimum temperature difference before group processing is suspended
#define MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER 0.5 //Minimum temperature difference before the gas temperatures are just set to be equal
/// number of FULL air controller ticks before an excited group breaks down (averages gas contents across turfs)
#define EXCITED_GROUP_BREAKDOWN_CYCLES 4
/// number of FULL air controller ticks before an excited group dismantles and removes its turfs from active
#define EXCITED_GROUP_DISMANTLE_CYCLES 16
/// 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
#define MINIMUM_AIR_TO_SUSPEND (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_SUSPEND)
/// Either this must be active
#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
#define MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION (T20C+10)
#define MINIMUM_TEMPERATURE_START_SUPERCONDUCTION (T20C+200)
@@ -47,8 +71,10 @@
//Should not exceed 0.4 else strange heat flow occur
#define WALL_HEAT_TRANSFER_COEFFICIENT 0.0
#define OPEN_HEAT_TRANSFER_COEFFICIENT 0.4
#define WINDOW_HEAT_TRANSFER_COEFFICIENT 0.1 //a hack for now
#define HEAT_CAPACITY_VACUUM 7000 //a hack to help make vacuums "cold", sacrificing realism for gameplay
/// 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
#define FIRE_MINIMUM_TEMPERATURE_TO_SPREAD (150+T0C)
@@ -62,10 +88,13 @@
//GASES
#define MIN_TOXIC_GAS_DAMAGE 1
#define MAX_TOXIC_GAS_DAMAGE 10
#define MOLES_GAS_VISIBLE 0.25 //Moles in a standard cell after which gases are visible
/// Moles in a standard cell after which gases are visible
#define MOLES_GAS_VISIBLE 0.25
#define FACTOR_GAS_VISIBLE_MAX 20 //moles_visible * FACTOR_GAS_VISIBLE_MAX = Moles after which gas is at maximum visibility
#define MOLES_GAS_VISIBLE_STEP 0.25 //Mole step for alpha updates. This means alpha can update at 0.25, 0.5, 0.75 and so on
/// 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
//REACTIONS
//return values for reactions (bitflags)
@@ -74,58 +103,94 @@
#define STOP_REACTIONS 2
// Pressure limits.
#define HAZARD_HIGH_PRESSURE 550 //This determins at what pressure the ultra-high pressure red icon is displayed. (This one is set as a constant)
#define WARNING_HIGH_PRESSURE 325 //This determins when the orange pressure icon is displayed (it is 0.7 * HAZARD_HIGH_PRESSURE)
#define WARNING_LOW_PRESSURE 50 //This is when the gray low pressure icon is displayed. (it is 2.5 * HAZARD_LOW_PRESSURE)
#define HAZARD_LOW_PRESSURE 20 //This is when the black ultra-low pressure icon is displayed. (This one is set as a constant)
/// 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
#define TEMPERATURE_DAMAGE_COEFFICIENT 1.5 //This is used in handle_temperature_damage() for humans, and in reagents that affect body temperature. Temperature damage is multiplied by this amount.
/// 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
#define BODYTEMP_NORMAL 310.15 //The natural temperature for a body
#define BODYTEMP_AUTORECOVERY_DIVISOR 11 //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_MINIMUM 12 //Minimum amount of kelvin moved toward 310K per tick. So long as abs(310.15 - bodytemp) is more than 50.
#define BODYTEMP_COLD_DIVISOR 6 //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_HEAT_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_COOLING_MAX -100 //The maximum number of degrees that your body can cool in 1 tick, due to the environment, when in a cold area.
#define BODYTEMP_HEATING_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.
/// 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 11
/// Minimum amount of kelvin moved toward 310K per tick. So long as abs(310.15 - bodytemp) is more than 50.
#define BODYTEMP_AUTORECOVERY_MINIMUM 12
///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 6
/// 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 -100
/// 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
#define BODYTEMP_HEAT_DAMAGE_LIMIT (BODYTEMP_NORMAL + 50) // The limit the human body can take before it starts taking damage from heat.
#define BODYTEMP_COLD_DAMAGE_LIMIT (BODYTEMP_NORMAL - 50) // The limit the human body can take before it starts taking damage from coldness.
/// The limit the human body can take before it starts taking damage from heat.
#define BODYTEMP_HEAT_DAMAGE_LIMIT (BODYTEMP_NORMAL + 50)
/// The limit the human body can take before it starts taking damage from coldness.
#define BODYTEMP_COLD_DAMAGE_LIMIT (BODYTEMP_NORMAL - 50)
#define SPACE_HELM_MIN_TEMP_PROTECT 2.0 //what min_cold_protection_temperature is set to for space-helmet quality headwear. MUST NOT BE 0.
#define SPACE_HELM_MAX_TEMP_PROTECT 1500 //Thermal insulation works both ways /Malkevin
#define SPACE_SUIT_MIN_TEMP_PROTECT 2.0 //what min_cold_protection_temperature is set to for space-suit quality jumpsuits or suits. MUST NOT BE 0.
/// 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
#define SPACE_SUIT_MAX_TEMP_PROTECT 1500
#define FIRE_SUIT_MIN_TEMP_PROTECT 60 //Cold protection for firesuits
#define FIRE_SUIT_MAX_TEMP_PROTECT 30000 //what max_heat_protection_temperature is set to for firesuit quality suits. MUST NOT BE 0.
#define FIRE_HELM_MIN_TEMP_PROTECT 60 //Cold protection for fire helmets
#define FIRE_HELM_MAX_TEMP_PROTECT 30000 //for fire helmet quality items (red and white hardhats)
/// 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
#define FIRE_IMMUNITY_MAX_TEMP_PROTECT 35000 //what max_heat_protection_temperature is set to for firesuit quality suits and helmets. MUST NOT BE 0.
/// 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
#define HELMET_MIN_TEMP_PROTECT 160 //For normal helmets
#define HELMET_MAX_TEMP_PROTECT 600 //For normal helmets
#define ARMOR_MIN_TEMP_PROTECT 160 //For armor
#define ARMOR_MAX_TEMP_PROTECT 600 //For armor
/// 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
#define GLOVES_MIN_TEMP_PROTECT 2.0 //For some gloves (black and)
#define GLOVES_MAX_TEMP_PROTECT 1500 //For some gloves
#define SHOES_MIN_TEMP_PROTECT 2.0 //For gloves
#define SHOES_MAX_TEMP_PROTECT 1500 //For gloves
/// 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
#define PRESSURE_DAMAGE_COEFFICIENT 4 //The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE
/// 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 4
#define MAX_HIGH_PRESSURE_DAMAGE 4
#define LOW_PRESSURE_DAMAGE 4 //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).
/// 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 4
#define COLD_SLOWDOWN_FACTOR 20 //Humans are slowed by the difference between bodytemp and BODYTEMP_COLD_DAMAGE_LIMIT divided by this
/// Humans are slowed by the difference between bodytemp and BODYTEMP_COLD_DAMAGE_LIMIT divided by this
#define COLD_SLOWDOWN_FACTOR 20
//PIPES
//Atmos pipe limits
#define MAX_OUTPUT_PRESSURE 4500 // (kPa) What pressure pumps and powered equipment max out at.
#define MAX_TRANSFER_RATE 200 // (L/s) Maximum speed powered equipment can work at.
#define VOLUME_PUMP_LEAK_AMOUNT 0.1 //10% of an overclocked volume pump leaks into the air
/// (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
/// 10% of an overclocked volume pump leaks into the air
#define VOLUME_PUMP_LEAK_AMOUNT 0.1
//used for device_type vars
#define UNARY 1
#define BINARY 2
@@ -133,11 +198,16 @@
#define QUATERNARY 4
//TANKS
#define TANK_MELT_TEMPERATURE 1000000 //temperature in kelvins at which a tank will start to melt
#define TANK_LEAK_PRESSURE (30.*ONE_ATMOSPHERE) //Tank starts leaking
#define TANK_RUPTURE_PRESSURE (35.*ONE_ATMOSPHERE) //Tank spills all contents into atmosphere
#define TANK_FRAGMENT_PRESSURE (40.*ONE_ATMOSPHERE) //Boom 3x3 base explosion
#define TANK_FRAGMENT_SCALE (6.*ONE_ATMOSPHERE) //+1 for each SCALE kPa aboe threshold
/// temperature in kelvins at which a tank will start to melt
#define TANK_MELT_TEMPERATURE 1000000
/// Tank starts leaking
#define TANK_LEAK_PRESSURE (30.*ONE_ATMOSPHERE)
/// Tank spills all contents into atmosphere
#define TANK_RUPTURE_PRESSURE (35.*ONE_ATMOSPHERE)
/// Boom 3x3 base explosion
#define TANK_FRAGMENT_PRESSURE (40.*ONE_ATMOSPHERE)
/// +1 for each SCALE kPa aboe threshold
#define TANK_FRAGMENT_SCALE (6.*ONE_ATMOSPHERE)
#define TANK_MAX_RELEASE_PRESSURE (ONE_ATMOSPHERE*3)
#define TANK_MIN_RELEASE_PRESSURE 0
#define TANK_DEFAULT_RELEASE_PRESSURE 17
@@ -145,19 +215,27 @@
//CANATMOSPASS
#define ATMOS_PASS_YES 1
#define ATMOS_PASS_NO 0
#define ATMOS_PASS_PROC -1 //ask CanAtmosPass()
#define ATMOS_PASS_DENSITY -2 //just check density
/// ask CanAtmosPass()
#define ATMOS_PASS_PROC -1
/// just check density
#define ATMOS_PASS_DENSITY -2
#define CANATMOSPASS(A, O) ( A.CanAtmosPass == ATMOS_PASS_PROC ? A.CanAtmosPass(O) : ( A.CanAtmosPass == ATMOS_PASS_DENSITY ? !A.density : A.CanAtmosPass ) )
#define CANVERTICALATMOSPASS(A, O) ( A.CanAtmosPassVertical == ATMOS_PASS_PROC ? A.CanAtmosPass(O, TRUE) : ( A.CanAtmosPassVertical == ATMOS_PASS_DENSITY ? !A.density : A.CanAtmosPassVertical ) )
//OPEN TURF ATMOS
#define OPENTURF_DEFAULT_ATMOS "o2=22;n2=82;TEMP=293.15" //the default air mix that open turfs spawn
#define TCOMMS_ATMOS "n2=100;TEMP=80" //-193,15°C telecommunications. also used for xenobiology slime killrooms
#define AIRLESS_ATMOS "TEMP=2.7" //space
#define FROZEN_ATMOS "o2=22;n2=82;TEMP=180" //-93.15°C snow and ice turfs
#define KITCHEN_COLDROOM_ATMOS "o2=33;n2=124;TEMP=193.15" //-80°C kitchen coldroom; higher amount of mol to reach about 101.3 kpA
#define BURNMIX_ATMOS "o2=100;plasma=200;TEMP=370" //used in the holodeck burn test program
/// the default air mix that open turfs spawn
#define OPENTURF_DEFAULT_ATMOS "o2=22;n2=82;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"
/// -80°C kitchen coldroom; higher amount of mol to reach about 101.3 kpA
#define KITCHEN_COLDROOM_ATMOS "o2=33;n2=124;TEMP=193.15"
/// 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"
@@ -168,7 +246,8 @@
#define ATMOS_TANK_AIRMIX "o2=2644;n2=10580;TEMP=293.15"
//LAVALAND
#define LAVALAND_EQUIPMENT_EFFECT_PRESSURE 50 //what pressure you have to be under to increase the effect of equipment meant for lavaland
/// what pressure you have to be under to increase the effect of equipment meant for lavaland
#define LAVALAND_EQUIPMENT_EFFECT_PRESSURE 50
//PLANETARY ATMOS MIXES
#define LAVALAND_DEFAULT_ATMOS "o2=14;n2=23;TEMP=300"
@@ -257,10 +336,14 @@
#define PIPING_LAYER_P_Y 5
#define PIPING_LAYER_LCHANGE 0.05
#define PIPING_ALL_LAYER (1<<0) //intended to connect with all layers, check for all instead of just one.
#define PIPING_ONE_PER_TURF (1<<1) //can only be built if nothing else with this flag is on the tile already.
#define PIPING_DEFAULT_LAYER_ONLY (1<<2) //can only exist at PIPING_LAYER_DEFAULT
#define PIPING_CARDINAL_AUTONORMALIZE (1<<3) //north/south east/west doesn't matter, auto normalize on build.
/// 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)
//HELPERS
#define PIPING_LAYER_SHIFT(T, PipingLayer) \

View File

@@ -2,28 +2,46 @@
// 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
#define HEALTH_HUD "1" // dead, alive, sick, health status
#define STATUS_HUD "2" // a simple line rounding the mob's number health
#define ID_HUD "3" // the job asigned to your ID
#define WANTED_HUD "4" // wanted, released, parroled, security status
#define IMPLOYAL_HUD "5" // loyality implant
#define IMPCHEM_HUD "6" // chemical implant
#define IMPTRACK_HUD "7" // tracking implant
#define DIAG_STAT_HUD "8" // Silicon/Mech/Circuit Status
#define DIAG_HUD "9" // Silicon health bar
#define DIAG_BATT_HUD "10"// Borg/Mech/Circutry power meter
#define DIAG_MECH_HUD "11"// Mech health bar
#define DIAG_BOT_HUD "12"// Bot HUDs
#define DIAG_CIRCUIT_HUD "13"// Circuit assembly health bar
#define DIAG_TRACK_HUD "14"// Mech/Silicon tracking beacon, Circutry long range icon
#define DIAG_AIRLOCK_HUD "15"//Airlock shock overlay
#define DIAG_PATH_HUD "16"//Bot path indicators
#define GLAND_HUD "17"//Gland indicators for abductors
/// 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"
#define NANITE_HUD "20"
#define DIAG_NANITE_FULL_HUD "21"
#define DIAG_LAUNCHPAD_HUD "22" //Displays launchpads' targeting reticle
/// Displays launchpads' targeting reticle
#define DIAG_LAUNCHPAD_HUD "22"
//for antag huds. these are used at the /mob level
#define ANTAG_HUD "23"
@@ -69,4 +87,5 @@
#define NOTIFY_ATTACK "attack"
#define NOTIFY_ORBIT "orbit"
#define ADD_HUD_TO_COOLDOWN 20 //cooldown for being shown the images for any particular data hud
/// cooldown for being shown the images for any particular data hud
#define ADD_HUD_TO_COOLDOWN 20

View File

@@ -1,4 +1,4 @@
#define GLOBAL_PROC "some_magic_bullshit"
/// A shorthand for the callback datum, [documented here](datum/callback.html)
#define CALLBACK new /datum/callback
#define INVOKE_ASYNC world.ImmediateInvokeAsync

View File

@@ -1,10 +1,14 @@
//Cleaning tool strength
// 1 is also a valid cleaning strength but completely unused so left undefined
#define CLEAN_WEAK 2
#define CLEAN_MEDIUM 3 // Acceptable tools
#define CLEAN_STRONG 4 // Industrial strength
#define CLEAN_IMPRESSIVE 5 // Cleaning strong enough your granny would be proud
#define CLEAN_GOD 6 // Cleans things spotless down to the atomic structure
/// Acceptable tools
#define CLEAN_MEDIUM 3
/// Industrial strength
#define CLEAN_STRONG 4
/// Cleaning strong enough your granny would be proud
#define CLEAN_IMPRESSIVE 5
/// Cleans things spotless down to the atomic structure
#define CLEAN_GOD 6
//How strong things have to be to wipe forensic evidence...
#define CLEAN_STRENGTH_FINGERPRINTS CLEAN_IMPRESSIVE

View File

@@ -1,25 +1,41 @@
//component id defines; sometimes these may not make sense in regards to their use in scripture but important ones are bright
#define BELLIGERENT_EYE "belligerent_eye" //Use this for offensive and damaging scripture!
#define VANGUARD_COGWHEEL "vanguard_cogwheel" //Use this for defensive and healing scripture!
#define GEIS_CAPACITOR "geis_capacitor" //Use this for niche scripture!
/// Use this for offensive and damaging scripture!
#define BELLIGERENT_EYE "belligerent_eye"
/// Use this for defensive and healing scripture!
#define VANGUARD_COGWHEEL "vanguard_cogwheel"
/// Use this for niche scripture!
#define GEIS_CAPACITOR "geis_capacitor"
#define REPLICANT_ALLOY "replicant_alloy"
#define HIEROPHANT_ANSIBLE "hierophant_ansible" //Use this for construction-related scripture!
/// Use this for construction-related scripture!
#define HIEROPHANT_ANSIBLE "hierophant_ansible"
GLOBAL_VAR_INIT(clockwork_construction_value, 0) //The total value of all structures built by the clockwork cult
GLOBAL_VAR_INIT(clockwork_vitality, 0) //How much Vitality is stored, total
GLOBAL_VAR_INIT(clockwork_power, 0) //How many joules of power are globally available to the clockwork cult
/// The total value of all structures built by the clockwork cult
GLOBAL_VAR_INIT(clockwork_construction_value, 0)
///How many joules of power are globally available to the clockwork cult
GLOBAL_VAR_INIT(clockwork_power, 0)
/// How much Vitality is stored, total
GLOBAL_VAR_INIT(clockwork_vitality, 0)
GLOBAL_LIST_EMPTY(all_clockwork_objects) //All clockwork items, structures, and effects in existence
GLOBAL_LIST_EMPTY(all_clockwork_mobs) //All clockwork SERVANTS (not creatures) in existence
/// All clockwork items, structures, and effects in existence
GLOBAL_LIST_EMPTY(all_clockwork_objects)
/// All clockwork SERVANTS (not creatures) in existence
GLOBAL_LIST_EMPTY(all_clockwork_mobs)
GLOBAL_VAR_INIT(ratvar_approaches, 0) //The servants can choose to "herald" Ratvar, permanently buffing them but announcing their presence to the crew.
GLOBAL_VAR_INIT(ratvar_awakens, 0) //If Ratvar has been summoned; not a boolean, for proper handling of multiple Ratvars
GLOBAL_VAR_INIT(ark_of_the_clockwork_justiciar, FALSE) //The Ark on the Reebe z-level
/// The servants can choose to "herald" Ratvar, permanently buffing them but announcing their presence to the crew.
GLOBAL_VAR_INIT(ratvar_approaches, 0)
/// If Ratvar has been summoned; not a boolean, for proper handling of multiple Ratvars
GLOBAL_VAR_INIT(ratvar_awakens, 0)
/// The Ark on the Reebe z-level
GLOBAL_VAR_INIT(ark_of_the_clockwork_justiciar, FALSE)
GLOBAL_VAR_INIT(clockwork_gateway_activated, FALSE) //if a gateway to the celestial derelict has ever been successfully activated
GLOBAL_VAR_INIT(script_scripture_unlocked, FALSE) //If script scripture is available, through converting at least one crewmember
GLOBAL_VAR_INIT(application_scripture_unlocked, FALSE) //If script scripture is available
GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not used to track existing scripture
/// if a gateway to the celestial derelict has ever been successfully activated
GLOBAL_VAR_INIT(clockwork_gateway_activated, FALSE)
/// If script scripture is available, through converting at least one crewmember
GLOBAL_VAR_INIT(script_scripture_unlocked, FALSE)
/// If script scripture is available
GLOBAL_VAR_INIT(application_scripture_unlocked, FALSE)
/// a list containing scripture instances; not used to track existing scripture
GLOBAL_LIST_EMPTY(all_scripture)
//Scripture tiers and requirements; peripherals should never be used
#define SCRIPTURE_PERIPHERAL "Peripheral"
@@ -28,64 +44,91 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
#define SCRIPTURE_APPLICATION "Application"
//Various costs related to power.
#define MAX_CLOCKWORK_POWER 50000 //The max power in J that the cult can stockpile
#define SCRIPT_UNLOCK_THRESHOLD 25000 //Scripts will unlock if the total power reaches this amount
#define APPLICATION_UNLOCK_THRESHOLD 40000 //Applications will unlock if the total powre reaches this amount
///The max power in W that the cult can stockpile
#define MAX_CLOCKWORK_POWER 50000
/// Scripts will unlock if the total power reaches this amount
#define SCRIPT_UNLOCK_THRESHOLD 25000
/// Applications will unlock if the total powre reaches this amount
#define APPLICATION_UNLOCK_THRESHOLD 40000
#define ABSCOND_ABDUCTION_COST 95
//clockcult power defines
#define MIN_CLOCKCULT_POWER 25 //the minimum amount of power clockcult machines will handle gracefully
/// the minimum amount of power clockcult machines will handle gracefully
#define MIN_CLOCKCULT_POWER 25
#define CLOCKCULT_POWER_UNIT (MIN_CLOCKCULT_POWER*100) //standard power amount for replica fabricator costs
/// standard power amount for replica fabricator costs
#define CLOCKCULT_POWER_UNIT (MIN_CLOCKCULT_POWER*100)
#define POWER_STANDARD (CLOCKCULT_POWER_UNIT*0.2) //how much power is in anything else; doesn't matter as much as the following
/// how much power is in anything else; doesn't matter as much as the following
#define POWER_STANDARD (CLOCKCULT_POWER_UNIT*0.2)
#define POWER_FLOOR (CLOCKCULT_POWER_UNIT*0.1) //how much power is in a clockwork floor, determines the cost of clockwork floor production
/// how much power is in a clockwork floor, determines the cost of clockwork floor production
#define POWER_FLOOR (CLOCKCULT_POWER_UNIT*0.1)
#define POWER_WALL_MINUS_FLOOR (CLOCKCULT_POWER_UNIT*0.4) //how much power is in a clockwork wall, determines the cost of clockwork wall production
/// how much power is in a clockwork wall, determines the cost of clockwork wall production
#define POWER_WALL_MINUS_FLOOR (CLOCKCULT_POWER_UNIT*0.4)
#define POWER_GEAR (CLOCKCULT_POWER_UNIT*0.3) //how much power is in a wall gear, minus the brass from the wall
/// how much power is in a wall gear, minus the brass from the wall
#define POWER_GEAR (CLOCKCULT_POWER_UNIT*0.3)
#define POWER_WALL_TOTAL (POWER_WALL_MINUS_FLOOR+POWER_FLOOR) //how much power is in a clockwork wall and the floor under it
/// how much power is in a clockwork wall and the floor under it
#define POWER_WALL_TOTAL (POWER_WALL_MINUS_FLOOR+POWER_FLOOR)
#define POWER_ROD (CLOCKCULT_POWER_UNIT*0.01) //how much power is in one rod
/// how much power is in one rod
#define POWER_ROD (CLOCKCULT_POWER_UNIT*0.01)
#define POWER_METAL (CLOCKCULT_POWER_UNIT*0.02) //how much power is in one sheet of metal
/// how much power is in one sheet of metal
#define POWER_METAL (CLOCKCULT_POWER_UNIT*0.02)
#define POWER_PLASTEEL (CLOCKCULT_POWER_UNIT*0.05) //how much power is in one sheet of plasteel
/// how much power is in one sheet of plasteel
#define POWER_PLASTEEL (CLOCKCULT_POWER_UNIT*0.05)
//Ark defines
#define GATEWAY_SUMMON_RATE 1 //the time amount the Gateway to the Celestial Derelict gets each process tick; defaults to 1 per tick
/// the time amount the Gateway to the Celestial Derelict gets each process tick; defaults to 1 per tick
#define GATEWAY_SUMMON_RATE 1
#define GATEWAY_REEBE_FOUND 240 //when progress is at or above this, the gateway finds reebe and begins drawing power
/// when progress is at or above this, the gateway finds reebe and begins drawing power
#define GATEWAY_REEBE_FOUND 240
#define GATEWAY_RATVAR_COMING 480 //when progress is at or above this, ratvar has entered and is coming through the gateway
/// when progress is at or above this, ratvar has entered and is coming through the gateway
#define GATEWAY_RATVAR_COMING 480
#define GATEWAY_RATVAR_ARRIVAL 600 //when progress is at or above this, game over ratvar's here everybody go home
/// when progress is at or above this, game over ratvar's here everybody go home
#define GATEWAY_RATVAR_ARRIVAL 600
//Objective text define
///Objective text define
#define CLOCKCULT_OBJECTIVE "Construct the Ark of the Clockwork Justicar and free Ratvar."
//Eminence defines
#define SUPERHEATED_CLOCKWORK_WALL_LIMIT 20 //How many walls can be superheated at once
/// How many walls can be superheated at once
#define SUPERHEATED_CLOCKWORK_WALL_LIMIT 20
//misc clockcult stuff
#define SIGIL_ACCESS_RANGE 2 //range at which transmission sigils can access power
/// range at which transmission sigils can access power
#define SIGIL_ACCESS_RANGE 2
#define FABRICATOR_REPAIR_PER_TICK 4 //how much a fabricator repairs each tick, and also how many deciseconds each tick is
/// how much a fabricator repairs each tick, and also how many deciseconds each tick is
#define FABRICATOR_REPAIR_PER_TICK 4
#define OCULAR_WARDEN_EXCLUSION_RANGE 3 //the range at which ocular wardens cannot be placed near other ocular wardens
/// the range at which ocular wardens cannot be placed near other ocular wardens
#define OCULAR_WARDEN_EXCLUSION_RANGE 3
#define CLOCKWORK_ARMOR_COOLDOWN 1800 //The cooldown period between summoning suits of clockwork armor
/// The cooldown period between summoning suits of clockwork armor
#define CLOCKWORK_ARMOR_COOLDOWN 1800
#define RATVARIAN_SPEAR_COOLDOWN 300 //The cooldown period between summoning another Ratvarian spear
/// The cooldown period between summoning another Ratvarian spear
#define RATVARIAN_SPEAR_COOLDOWN 300
#define MARAUDER_SCRIPTURE_SCALING_THRESHOLD 600 //The amount of deciseconds that must pass before marauder scripture will not gain a recital penalty
/// The amount of deciseconds that must pass before marauder scripture will not gain a recital penalty
#define MARAUDER_SCRIPTURE_SCALING_THRESHOLD 600
#define MARAUDER_SCRIPTURE_SCALING_TIME 20 //The amount of extra deciseconds tacked on to the marauder scripture recital time per recent marauder
/// The amount of extra deciseconds tacked on to the marauder scripture recital time per recent marauder
#define MARAUDER_SCRIPTURE_SCALING_TIME 20
#define MARAUDER_SCRIPTURE_SCALING_MAX 300 //The maximum extra time applied to the marauder scripture
/// The maximum extra time applied to the marauder scripture
#define MARAUDER_SCRIPTURE_SCALING_MAX 300
#define ARK_SCREAM_COOLDOWN 600 //This much time has to pass between instances of the Ark taking damage before it will "scream" again
/// This much time has to pass between instances of the Ark taking damage before it will "scream" again
#define ARK_SCREAM_COOLDOWN 600

View File

@@ -130,14 +130,32 @@
#define TRIGGER_GUARD_NONE 0
#define TRIGGER_GUARD_NORMAL 1
//Gun bolt types
///Gun has a bolt, it stays closed while not cycling. The gun must be racked to have a bullet chambered when a mag is inserted.
/// Example: c20, shotguns, m90
#define BOLT_TYPE_STANDARD 1
///Gun has a bolt, it is open when ready to fire. The gun can never have a chambered bullet with no magazine, but the bolt stays ready when a mag is removed.
/// Example: Some SMGs, the L6
#define BOLT_TYPE_OPEN 2
///Gun has no moving bolt mechanism, it cannot be racked. Also dumps the entire contents when emptied instead of a magazine.
/// Example: Break action shotguns, revolvers
#define BOLT_TYPE_NO_BOLT 3
///Gun has a bolt, it locks back when empty. It can be released to chamber a round if a magazine is in.
/// Example: Pistols with a slide lock, some SMGs
#define BOLT_TYPE_LOCKING 4
//Sawn off nerfs
///accuracy penalty of sawn off guns
#define SAWN_OFF_ACC_PENALTY 25
///added recoil of sawn off guns
#define SAWN_OFF_RECOIL 1
//ammo box sprite defines
///ammo box will always use provided icon state
#define AMMO_BOX_ONE_SPRITE 0
///ammo box will have a different state for each bullet; <icon_state>-<bullets left>
#define AMMO_BOX_PER_BULLET 1
///ammo box will have a different state for full and empty; <icon_state>-max_ammo and <icon_state>-0
#define AMMO_BOX_FULL_EMPTY 2
//Projectile Reflect
#define REFLECT_NORMAL (1<<0)
#define REFLECT_FAKEPROJECTILE (1<<1)

View File

@@ -5,17 +5,21 @@
#define COMPONENT_INCOMPATIBLE 1
#define COMPONENT_NOTRANSFER 2
#define ELEMENT_INCOMPATIBLE 1 // Return value to cancel attaching
/// Return value to cancel attaching
#define ELEMENT_INCOMPATIBLE 1
// /datum/element flags
/// /datum/element flags
#define ELEMENT_DETACH (1 << 0)
// How multiple components of the exact same type are handled in the same datum
#define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default)
#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed
#define COMPONENT_DUPE_UNIQUE 2 //new component is deleted
#define COMPONENT_DUPE_UNIQUE_PASSARGS 4 //old component is given the initialization args of the new
/// old component is deleted (default)
#define COMPONENT_DUPE_HIGHLANDER 0
/// duplicates allowed
#define COMPONENT_DUPE_ALLOWED 1
/// new component is deleted
#define COMPONENT_DUPE_UNIQUE 2
/// old component is given the initialization args of the new
#define COMPONENT_DUPE_UNIQUE_PASSARGS 4
// All signals. Format:
// When the signal is called: (signal arguments)
@@ -24,11 +28,16 @@
// global signals
// These are signals which can be listened to by any component on any parent
// start global signals with "!", this used to be necessary but now it's just a formatting choice
#define COMSIG_GLOB_NEW_Z "!new_z" //from base of datum/controller/subsystem/mapping/proc/add_new_zlevel(): (list/args)
#define COMSIG_GLOB_VAR_EDIT "!var_edit" //called after a successful var edit somewhere in the world: (list/args)
#define COMSIG_GLOB_MOB_CREATED "!mob_created" //mob was created somewhere : (mob)
#define COMSIG_GLOB_MOB_DEATH "!mob_death" //mob died somewhere : (mob , gibbed)
#define COMSIG_GLOB_LIVING_SAY_SPECIAL "!say_special" //global living say plug - use sparingly: (mob/speaker , message)
/// from base of datum/controller/subsystem/mapping/proc/add_new_zlevel(): (list/args)
#define COMSIG_GLOB_NEW_Z "!new_z"
/// called after a successful var edit somewhere in the world: (list/args)
#define COMSIG_GLOB_VAR_EDIT "!var_edit"
/// mob was created somewhere : (mob)
#define COMSIG_GLOB_MOB_CREATED "!mob_created"
/// mob died somewhere : (mob , gibbed)
#define COMSIG_GLOB_MOB_DEATH "!mob_death"
/// global living say plug - use sparingly: (mob/speaker , message)
#define COMSIG_GLOB_LIVING_SAY_SPECIAL "!say_special"
// signals from globally accessible objects
/// from SSsun when the sun changes position : (azimuth)
@@ -37,11 +46,16 @@
//////////////////////////////////////////////////////////////////
// /datum signals
#define COMSIG_COMPONENT_ADDED "component_added" //when a component is added to a datum: (/datum/component)
#define COMSIG_COMPONENT_REMOVING "component_removing" //before a component is removed from a datum because of RemoveComponent: (/datum/component)
#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" //before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation
#define COMSIG_PARENT_QDELETING "parent_qdeleting" //just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called
#define COMSIG_TOPIC "handle_topic" //generic topic handler (usr, href_list)
/// when a component is added to a datum: (/datum/component)
#define COMSIG_COMPONENT_ADDED "component_added"
/// before a component is removed from a datum because of RemoveComponent: (/datum/component)
#define COMSIG_COMPONENT_REMOVING "component_removing"
/// before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation
#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted"
/// just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called
#define COMSIG_PARENT_QDELETING "parent_qdeleting"
/// generic topic handler (usr, href_list)
#define COMSIG_TOPIC "handle_topic"
// /atom signals
#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params)

View File

@@ -5,5 +5,7 @@
#define CONFIG_MAPS_FILE "maps.txt"
//flags
#define CONFIG_ENTRY_LOCKED 1 //can't edit
#define CONFIG_ENTRY_HIDDEN 2 //can't see value
/// can't edit
#define CONFIG_ENTRY_LOCKED 1
/// can't see value
#define CONFIG_ENTRY_HIDDEN 2

View File

@@ -12,8 +12,10 @@
//blood magic
#define MAX_BLOODCHARGE 4
#define RUNELESS_MAX_BLOODCHARGE 1
#define CULT_RISEN 0.2 //percent before rise
#define CULT_ASCENDENT 0.4 //percent before ascend
/// percent before rise
#define CULT_RISEN 0.2
/// percent before ascend
#define CULT_ASCENDENT 0.4
#define BLOOD_SPEAR_COST 150
#define BLOOD_BARRAGE_COST 300
#define BLOOD_BEAM_COST 500
@@ -24,4 +26,4 @@
#define DEFAULT_TOOLTIP "6:-29,5:-2"
//misc
#define SOULS_TO_REVIVE 3
#define BLOODCULT_EYE "f00"
#define BLOODCULT_EYE "f00"

View File

@@ -20,10 +20,17 @@
#define DISEASE_SPREAD_AIRBORNE (1<<5)
//Severity Defines
#define DISEASE_SEVERITY_POSITIVE "Positive" //Diseases that buff, heal, or at least do nothing at all
#define DISEASE_SEVERITY_NONTHREAT "Harmless" //Diseases that may have annoying effects, but nothing disruptive (sneezing)
#define DISEASE_SEVERITY_MINOR "Minor" //Diseases that can annoy in concrete ways (dizziness)
#define DISEASE_SEVERITY_MEDIUM "Medium" //Diseases that can do minor harm, or severe annoyance (vomit)
#define DISEASE_SEVERITY_HARMFUL "Harmful" //Diseases that can do significant harm, or severe disruption (brainrot)
#define DISEASE_SEVERITY_DANGEROUS "Dangerous" //Diseases that can kill or maim if left untreated (flesh eating, blindness)
#define DISEASE_SEVERITY_BIOHAZARD "BIOHAZARD" //Diseases that can quickly kill an unprepared victim (fungal tb, gbs)
/// Diseases that buff, heal, or at least do nothing at all
#define DISEASE_SEVERITY_POSITIVE "Positive"
/// Diseases that may have annoying effects, but nothing disruptive (sneezing)
#define DISEASE_SEVERITY_NONTHREAT "Harmless"
/// Diseases that can annoy in concrete ways (dizziness)
#define DISEASE_SEVERITY_MINOR "Minor"
/// Diseases that can do minor harm, or severe annoyance (vomit)
#define DISEASE_SEVERITY_MEDIUM "Medium"
/// Diseases that can do significant harm, or severe disruption (brainrot)
#define DISEASE_SEVERITY_HARMFUL "Harmful"
/// Diseases that can kill or maim if left untreated (flesh eating, blindness)
#define DISEASE_SEVERITY_DANGEROUS "Dangerous"
/// Diseases that can quickly kill an unprepared victim (fungal tb, gbs)
#define DISEASE_SEVERITY_BIOHAZARD "BIOHAZARD"

View File

@@ -22,24 +22,37 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
//FLAGS BITMASK
#define HEAR_1 (1<<3) // This flag is what recursive_hear_check() uses to determine wether to add an item to the hearer list or not.
#define CHECK_RICOCHET_1 (1<<4) // Projectiels will check ricochet on things impacted that have this.
#define CONDUCT_1 (1<<5) // conducts electricity (metal etc.)
#define NODECONSTRUCT_1 (1<<7) // For machines and structures that should not break into parts, eg, holodeck stuff
#define OVERLAY_QUEUED_1 (1<<8) // atom queued to SSoverlay
#define ON_BORDER_1 (1<<9) // item has priority to check when entering or leaving
#define PREVENT_CLICK_UNDER_1 (1<<11) //Prevent clicking things below it on the same turf eg. doors/ fulltile windows
/// This flag is what recursive_hear_check() uses to determine wether to add an item to the hearer list or not.
#define HEAR_1 (1<<3)
/// Projectiels will check ricochet on things impacted that have this.
#define CHECK_RICOCHET_1 (1<<4)
/// conducts electricity (metal etc.)
#define CONDUCT_1 (1<<5)
/// For machines and structures that should not break into parts, eg, holodeck stuff
#define NODECONSTRUCT_1 (1<<7)
/// atom queued to SSoverlay
#define OVERLAY_QUEUED_1 (1<<8)
/// item has priority to check when entering or leaving
#define ON_BORDER_1 (1<<9)
/// Prevent clicking things below it on the same turf eg. doors/ fulltile windows
#define PREVENT_CLICK_UNDER_1 (1<<11)
#define HOLOGRAM_1 (1<<12)
#define TESLA_IGNORE_1 (1<<13) // TESLA_IGNORE grants immunity from being targeted by tesla-style electricity
#define INITIALIZED_1 (1<<14) //Whether /atom/Initialize() has already run for the object
#define ADMIN_SPAWNED_1 (1<<15) //was this spawned by an admin? used for stat tracking stuff.
/// TESLA_IGNORE grants immunity from being targeted by tesla-style electricity
#define TESLA_IGNORE_1 (1<<13)
///Whether /atom/Initialize() has already run for the object
#define INITIALIZED_1 (1<<14)
/// was this spawned by an admin? used for stat tracking stuff.
#define ADMIN_SPAWNED_1 (1<<15)
//turf-only flags
#define NOJAUNT_1 (1<<0)
#define UNUSED_RESERVATION_TURF_1 (1<<1)
#define CAN_BE_DIRTY_1 (1<<2) // If a turf can be made dirty at roundstart. This is also used in areas.
#define NO_LAVA_GEN_1 (1<<6) //Blocks lava rivers being generated on the turf
#define NO_RUINS_1 (1<<10) //Blocks ruins spawning on the turf
/// If a turf can be made dirty at roundstart. This is also used in areas.
#define CAN_BE_DIRTY_1 (1<<2)
/// Blocks lava rivers being generated on the turf
#define NO_LAVA_GEN_1 (1<<6)
/// Blocks ruins spawning on the turf
#define NO_RUINS_1 (1<<10)
/*
These defines are used specifically with the atom/pass_flags bitmask
@@ -61,17 +74,23 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define FLYING (1<<1)
#define VENTCRAWLING (1<<2)
#define FLOATING (1<<3)
#define UNSTOPPABLE (1<<4) //When moving, will Bump()/Cross()/Uncross() everything, but won't be stopped.
/// When moving, will Bump()/Cross()/Uncross() everything, but won't be stopped.
#define UNSTOPPABLE (1<<4)
//Fire and Acid stuff, for resistance_flags
#define LAVA_PROOF (1<<0)
#define FIRE_PROOF (1<<1) //100% immune to fire damage (but not necessarily to lava or heat)
/// 100% immune to fire damage (but not necessarily to lava or heat)
#define FIRE_PROOF (1<<1)
#define FLAMMABLE (1<<2)
#define ON_FIRE (1<<3)
#define UNACIDABLE (1<<4) //acid can't even appear on it, let alone melt it.
#define ACID_PROOF (1<<5) //acid stuck on it doesn't melt it.
#define INDESTRUCTIBLE (1<<6) //doesn't take damage
#define FREEZE_PROOF (1<<7) //can't be frozen
/// acid can't even appear on it, let alone melt it.
#define UNACIDABLE (1<<4)
/// acid stuck on it doesn't melt it.
#define ACID_PROOF (1<<5)
/// doesn't take damage
#define INDESTRUCTIBLE (1<<6)
/// can't be frozen
#define FREEZE_PROOF (1<<7)
//tesla_zap
#define TESLA_MACHINE_EXPLOSIVE (1<<0)
@@ -89,13 +108,20 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define EMP_PROTECT_WIRES (1<<2)
//Mob mobility var flags
#define MOBILITY_MOVE (1<<0) //can move
#define MOBILITY_STAND (1<<1) //can, and is, standing up
#define MOBILITY_PICKUP (1<<2) //can pickup items
#define MOBILITY_USE (1<<3) //can hold and use items
#define MOBILITY_UI (1<<4) //can use interfaces like machinery
#define MOBILITY_STORAGE (1<<5) //can use storage item
#define MOBILITY_PULL (1<<6) //can pull things
/// can move
#define MOBILITY_MOVE (1<<0)
/// can, and is, standing up
#define MOBILITY_STAND (1<<1)
/// can pickup items
#define MOBILITY_PICKUP (1<<2)
/// can hold and use items
#define MOBILITY_USE (1<<3)
/// can use interfaces like machinery
#define MOBILITY_UI (1<<4)
/// can use storage item
#define MOBILITY_STORAGE (1<<5)
/// can pull things
#define MOBILITY_PULL (1<<6)
#define MOBILITY_FLAGS_DEFAULT (MOBILITY_MOVE | MOBILITY_STAND | MOBILITY_PICKUP | MOBILITY_USE | MOBILITY_UI | MOBILITY_STORAGE | MOBILITY_PULL)
#define MOBILITY_FLAGS_INTERACTION (MOBILITY_USE | MOBILITY_PICKUP | MOBILITY_UI | MOBILITY_STORAGE)

View File

@@ -1,9 +1,13 @@
//HUD styles. Index order defines how they are cycled in F12.
#define HUD_STYLE_STANDARD 1 //Standard hud
#define HUD_STYLE_REDUCED 2 //Reduced hud (just hands and intent switcher)
#define HUD_STYLE_NOHUD 3 //No hud (for screenshots)
/// Standard hud
#define HUD_STYLE_STANDARD 1
/// Reduced hud (just hands and intent switcher)
#define HUD_STYLE_REDUCED 2
/// No hud (for screenshots)
#define HUD_STYLE_NOHUD 3
#define HUD_VERSIONS 3 //Used in show_hud(); Please ensure this is the same as the maximum index.
/// Used in show_hud(); Please ensure this is the same as the maximum index.
#define HUD_VERSIONS 3
//1:1 HUD layout stuff
#define UI_BOXCRAFT "EAST-4:22,SOUTH+1:6"

View File

@@ -1,22 +1,38 @@
/// whether can_interact() checks for anchored. only works on movables.
#define INTERACT_ATOM_REQUIRES_ANCHORED (1<<0)
/// calls try_interact() on attack_hand() and returns that.
#define INTERACT_ATOM_ATTACK_HAND (1<<1)
/// automatically calls and returns ui_interact() on interact().
#define INTERACT_ATOM_UI_INTERACT (1<<2)
/// user must be dextrous
#define INTERACT_ATOM_REQUIRES_DEXTERITY (1<<3)
/// ignores incapacitated check
#define INTERACT_ATOM_IGNORE_INCAPACITATED (1<<4)
/// incapacitated check ignores restrained
#define INTERACT_ATOM_IGNORE_RESTRAINED (1<<5)
/// incapacitated check checks grab
#define INTERACT_ATOM_CHECK_GRAB (1<<6)
/// prevents leaving fingerprints automatically on attack_hand
#define INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND (1<<7)
/// adds hiddenprints instead of fingerprints on interact
#define INTERACT_ATOM_NO_FINGERPRINT_INTERACT (1<<8)
#define INTERACT_ATOM_REQUIRES_ANCHORED (1<<0) //whether can_interact() checks for anchored. only works on movables.
#define INTERACT_ATOM_ATTACK_HAND (1<<1) //calls try_interact() on attack_hand() and returns that.
#define INTERACT_ATOM_UI_INTERACT (1<<2) //automatically calls and returns ui_interact() on interact().
#define INTERACT_ATOM_REQUIRES_DEXTERITY (1<<3) //user must be dextrous
#define INTERACT_ATOM_IGNORE_INCAPACITATED (1<<4) //ignores incapacitated check
#define INTERACT_ATOM_IGNORE_RESTRAINED (1<<5) //incapacitated check ignores restrained
#define INTERACT_ATOM_CHECK_GRAB (1<<6) //incapacitated check checks grab
#define INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND (1<<7) //prevents leaving fingerprints automatically on attack_hand
#define INTERACT_ATOM_NO_FINGERPRINT_INTERACT (1<<8) //adds hiddenprints instead of fingerprints on interact
/// attempt pickup on attack_hand for items
#define INTERACT_ITEM_ATTACK_HAND_PICKUP (1<<0)
#define INTERACT_ITEM_ATTACK_HAND_PICKUP (1<<0) //attempt pickup on attack_hand for items
#define INTERACT_MACHINE_OPEN (1<<0) //can_interact() while open
#define INTERACT_MACHINE_OFFLINE (1<<1) //can_interact() while offline
#define INTERACT_MACHINE_WIRES_IF_OPEN (1<<2) //try to interact with wires if open
#define INTERACT_MACHINE_ALLOW_SILICON (1<<3) //let silicons interact
#define INTERACT_MACHINE_OPEN_SILICON (1<<4) //let silicons interact while open
#define INTERACT_MACHINE_REQUIRES_SILICON (1<<5) //must be silicon to interact
#define INTERACT_MACHINE_SET_MACHINE (1<<6) //MACHINES HAVE THIS BY DEFAULT, SOMEONE SHOULD RUN THROUGH MACHINES AND REMOVE IT FROM THINGS LIKE LIGHT SWITCHES WHEN POSSIBLE!!--------------------------
//This flag determines if a machine set_machine's the user when the user uses it, making updateUsrDialog make the user re-call interact() on it.
//THIS FLAG IS ON ALL MACHINES BY DEFAULT, NEEDS TO BE RE-EVALUATED LATER!!
/// can_interact() while open
#define INTERACT_MACHINE_OPEN (1<<0)
/// can_interact() while offline
#define INTERACT_MACHINE_OFFLINE (1<<1)
/// try to interact with wires if open
#define INTERACT_MACHINE_WIRES_IF_OPEN (1<<2)
/// let silicons interact
#define INTERACT_MACHINE_ALLOW_SILICON (1<<3)
/// let silicons interact while open
#define INTERACT_MACHINE_OPEN_SILICON (1<<4)
/// must be silicon to interact
#define INTERACT_MACHINE_REQUIRES_SILICON (1<<5)
/// MACHINES HAVE THIS BY DEFAULT, SOMEONE SHOULD RUN THROUGH MACHINES AND REMOVE IT FROM THINGS LIKE LIGHT SWITCHES WHEN POSSIBLE!!--------------------------
/// This flag determines if a machine set_machine's the user when the user uses it, making updateUsrDialog make the user re-call interact() on it.
/// THIS FLAG IS ON ALL MACHINES BY DEFAULT, NEEDS TO BE RE-EVALUATED LATER!!
#define INTERACT_MACHINE_SET_MACHINE (1<<6)

View File

@@ -1,12 +1,18 @@
/*ALL DEFINES RELATED TO INVENTORY OBJECTS, MANAGEMENT, ETC, GO HERE*/
//ITEM INVENTORY WEIGHT, FOR w_class
#define WEIGHT_CLASS_TINY 1 //Usually items smaller then a human hand, (e.g. playing cards, lighter, scalpel, coins/holochips)
#define WEIGHT_CLASS_SMALL 2 //Pockets can hold small and tiny items, (e.g. flashlight, multitool, grenades, GPS device)
#define WEIGHT_CLASS_NORMAL 3 //Standard backpacks can carry tiny, small & normal items, (e.g. fire extinguisher, stun baton, gas mask, metal sheets)
#define WEIGHT_CLASS_BULKY 4 //Items that can be weilded or equipped but not stored in an inventory, (e.g. defibrillator, backpack, space suits)
#define WEIGHT_CLASS_HUGE 5 //Usually represents objects that require two hands to operate, (e.g. shotgun, two-handed melee weapons)
#define WEIGHT_CLASS_GIGANTIC 6 //Essentially means it cannot be picked up or placed in an inventory, (e.g. mech parts, safe)
/// Usually items smaller then a human hand, (e.g. playing cards, lighter, scalpel, coins/holochips)
#define WEIGHT_CLASS_TINY 1
/// Pockets can hold small and tiny items, (e.g. flashlight, multitool, grenades, GPS device)
#define WEIGHT_CLASS_SMALL 2
/// Standard backpacks can carry tiny, small & normal items, (e.g. fire extinguisher, stun baton, gas mask, metal sheets)
#define WEIGHT_CLASS_NORMAL 3
/// Items that can be weilded or equipped but not stored in an inventory, (e.g. defibrillator, backpack, space suits)
#define WEIGHT_CLASS_BULKY 4
/// Usually represents objects that require two hands to operate, (e.g. shotgun, two-handed melee weapons)
#define WEIGHT_CLASS_HUGE 5
/// Essentially means it cannot be picked up or placed in an inventory, (e.g. mech parts, safe)
#define WEIGHT_CLASS_GIGANTIC 6
//Inventory depth: limits how many nested storage items you can access directly.
//1: stuff in mob, 2: stuff in backpack, 3: stuff in box in backpack, etc
@@ -25,8 +31,10 @@
#define ITEM_SLOT_ID (1<<8)
#define ITEM_SLOT_BELT (1<<9)
#define ITEM_SLOT_BACK (1<<10)
#define ITEM_SLOT_POCKET (1<<11) // this is to allow items with a w_class of WEIGHT_CLASS_NORMAL or WEIGHT_CLASS_BULKY to fit in pockets.
#define ITEM_SLOT_DENYPOCKET (1<<12) // this is to deny items with a w_class of WEIGHT_CLASS_SMALL or WEIGHT_CLASS_TINY to fit in pockets.
/// this is to allow items with a w_class of WEIGHT_CLASS_NORMAL or WEIGHT_CLASS_BULKY to fit in pockets.
#define ITEM_SLOT_POCKET (1<<11)
/// this is to deny items with a w_class of WEIGHT_CLASS_SMALL or WEIGHT_CLASS_TINY to fit in pockets.
#define ITEM_SLOT_DENYPOCKET (1<<12)
#define ITEM_SLOT_NECK (1<<13)
#define ITEM_SLOT_HANDS (1<<14)
#define ITEM_SLOT_BACKPACK (1<<15)
@@ -36,8 +44,9 @@
#define SLOT_BACK 1
#define SLOT_WEAR_MASK 2
#define SLOT_HANDCUFFED 3
#define SLOT_HANDS 4 //wherever you provide a slot for hands you provide SLOT_HANDS
//SLOT_HANDS as a slot will pick ANY available hand
/// wherever you provide a slot for hands you provide SLOT_HANDS.
/// SLOT_HANDS as a slot will pick ANY available hand
#define SLOT_HANDS 4
#define SLOT_BELT 5
#define SLOT_WEAR_ID 6
#define SLOT_EARS 7

View File

@@ -1,20 +1,26 @@
//Bay lighting engine shit, not in /code/modules/lighting because BYOND is being shit about it
#define LIGHTING_INTERVAL 5 // frequency, in 1/10ths of a second, of the lighting process
/// frequency, in 1/10ths of a second, of the lighting process
#define LIGHTING_INTERVAL 5
#define MINIMUM_USEFUL_LIGHT_RANGE 1.4
#define LIGHTING_FALLOFF 1 // type of falloff to use for lighting; 1 for circular, 2 for square
#define LIGHTING_LAMBERTIAN 0 // use lambertian shading for light sources
#define LIGHTING_HEIGHT 1 // height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone
#define LIGHTING_ROUND_VALUE (1 / 64) //Value used to round lumcounts, values smaller than 1/129 don't matter (if they do, thanks sinking points), greater values will make lighting less precise, but in turn increase performance, VERY SLIGHTLY.
/// type of falloff to use for lighting; 1 for circular, 2 for square
#define LIGHTING_FALLOFF 1
/// use lambertian shading for light sources
#define LIGHTING_LAMBERTIAN 0
/// height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone
#define LIGHTING_HEIGHT 1
/// Value used to round lumcounts, values smaller than 1/129 don't matter (if they do, thanks sinking points), greater values will make lighting less precise, but in turn increase performance, VERY SLIGHTLY.
#define LIGHTING_ROUND_VALUE (1 / 64)
#define LIGHTING_ICON 'icons/effects/lighting_object.dmi' // icon used for lighting shading effects
/// icon used for lighting shading effects
#define LIGHTING_ICON 'icons/effects/lighting_object.dmi'
// If the max of the lighting lumcounts of each spectrum drops below this, disable luminosity on the lighting objects.
// Set to zero to disable soft lighting. Luminosity changes then work if it's lit at all.
/// If the max of the lighting lumcounts of each spectrum drops below this, disable luminosity on the lighting objects.
/// Set to zero to disable soft lighting. Luminosity changes then work if it's lit at all.
#define LIGHTING_SOFT_THRESHOLD 0
// If I were you I'd leave this alone.
/// If I were you I'd leave this alone.
#define LIGHTING_BASE_MATRIX \
list \
( \
@@ -29,45 +35,71 @@
//Some defines to generalise colours used in lighting.
//Important note on colors. Colors can end up significantly different from the basic html picture, especially when saturated
#define LIGHT_COLOR_WHITE "#FFFFFF"
#define LIGHT_COLOR_RED "#FA8282" //Warm but extremely diluted red. rgb(250, 130, 130)
#define LIGHT_COLOR_GREEN "#64C864" //Bright but quickly dissipating neon green. rgb(100, 200, 100)
#define LIGHT_COLOR_BLUE "#6496FA" //Cold, diluted blue. rgb(100, 150, 250)
/// Warm but extremely diluted red. rgb(250, 130, 130)
#define LIGHT_COLOR_RED "#FA8282"
/// Bright but quickly dissipating neon green. rgb(100, 200, 100)
#define LIGHT_COLOR_GREEN "#64C864"
/// Cold, diluted blue. rgb(100, 150, 250)
#define LIGHT_COLOR_BLUE "#6496FA"
/// Light blueish green. rgb(125, 225, 175)
#define LIGHT_COLOR_BLUEGREEN "#7DE1AF"
/// Diluted cyan. rgb(125, 225, 225)
#define LIGHT_COLOR_CYAN "#7DE1E1"
/// More-saturated cyan. rgb(64, 206, 255)
#define LIGHT_COLOR_LIGHT_CYAN "#40CEFF"
/// Saturated blue. rgb(51, 117, 248)
#define LIGHT_COLOR_DARK_BLUE "#6496FA"
/// Diluted, mid-warmth pink. rgb(225, 125, 225)
#define LIGHT_COLOR_PINK "#E17DE1"
/// Dimmed yellow, leaning kaki. rgb(225, 225, 125)
#define LIGHT_COLOR_YELLOW "#E1E17D"
/// Clear brown, mostly dim. rgb(150, 100, 50)
#define LIGHT_COLOR_BROWN "#966432"
/// Mostly pure orange. rgb(250, 150, 50)
#define LIGHT_COLOR_ORANGE "#FA9632"
/// Light Purple. rgb(149, 44, 244)
#define LIGHT_COLOR_PURPLE "#952CF4"
/// Less-saturated light purple. rgb(155, 81, 255)
#define LIGHT_COLOR_LAVENDER "#9B51FF"
#define LIGHT_COLOR_BLUEGREEN "#7DE1AF" //Light blueish green. rgb(125, 225, 175)
#define LIGHT_COLOR_CYAN "#7DE1E1" //Diluted cyan. rgb(125, 225, 225)
#define LIGHT_COLOR_LIGHT_CYAN "#40CEFF" //More-saturated cyan. rgb(64, 206, 255)
#define LIGHT_COLOR_DARK_BLUE "#6496FA" //Saturated blue. rgb(51, 117, 248)
#define LIGHT_COLOR_PINK "#E17DE1" //Diluted, mid-warmth pink. rgb(225, 125, 225)
#define LIGHT_COLOR_YELLOW "#E1E17D" //Dimmed yellow, leaning kaki. rgb(225, 225, 125)
#define LIGHT_COLOR_BROWN "#966432" //Clear brown, mostly dim. rgb(150, 100, 50)
#define LIGHT_COLOR_ORANGE "#FA9632" //Mostly pure orange. rgb(250, 150, 50)
#define LIGHT_COLOR_PURPLE "#952CF4" //Light Purple. rgb(149, 44, 244)
#define LIGHT_COLOR_LAVENDER "#9B51FF" //Less-saturated light purple. rgb(155, 81, 255)
#define LIGHT_COLOR_HOLY_MAGIC "#FFF743" //slightly desaturated bright yellow.
#define LIGHT_COLOR_BLOOD_MAGIC "#D00000" //deep crimson
///slightly desaturated bright yellow.
#define LIGHT_COLOR_HOLY_MAGIC "#FFF743"
/// deep crimson
#define LIGHT_COLOR_BLOOD_MAGIC "#D00000"
//These ones aren't a direct colour like the ones above, because nothing would fit
#define LIGHT_COLOR_FIRE "#FAA019" //Warm orange color, leaning strongly towards yellow. rgb(250, 160, 25)
#define LIGHT_COLOR_LAVA "#C48A18" //Very warm yellow, leaning slightly towards orange. rgb(196, 138, 24)
#define LIGHT_COLOR_FLARE "#FA644B" //Bright, non-saturated red. Leaning slightly towards pink for visibility. rgb(250, 100, 75)
#define LIGHT_COLOR_SLIME_LAMP "#AFC84B" //Weird color, between yellow and green, very slimy. rgb(175, 200, 75)
#define LIGHT_COLOR_TUNGSTEN "#FAE1AF" //Extremely diluted yellow, close to skin color (for some reason). rgb(250, 225, 175)
#define LIGHT_COLOR_HALOGEN "#F0FAFA" //Barely visible cyan-ish hue, as the doctor prescribed. rgb(240, 250, 250)
/// Warm orange color, leaning strongly towards yellow. rgb(250, 160, 25)
#define LIGHT_COLOR_FIRE "#FAA019"
/// Very warm yellow, leaning slightly towards orange. rgb(196, 138, 24)
#define LIGHT_COLOR_LAVA "#C48A18"
/// Bright, non-saturated red. Leaning slightly towards pink for visibility. rgb(250, 100, 75)
#define LIGHT_COLOR_FLARE "#FA644B"
/// Weird color, between yellow and green, very slimy. rgb(175, 200, 75)
#define LIGHT_COLOR_SLIME_LAMP "#AFC84B"
/// Extremely diluted yellow, close to skin color (for some reason). rgb(250, 225, 175)
#define LIGHT_COLOR_TUNGSTEN "#FAE1AF"
/// Barely visible cyan-ish hue, as the doctor prescribed. rgb(240, 250, 250)
#define LIGHT_COLOR_HALOGEN "#F0FAFA"
#define LIGHT_RANGE_FIRE 3 //How many tiles standard fires glow.
///How many tiles standard fires glow.
#define LIGHT_RANGE_FIRE 3
#define LIGHTING_PLANE_ALPHA_VISIBLE 255
#define LIGHTING_PLANE_ALPHA_NV_TRAIT 245
#define LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE 192
#define LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE 128 //For lighting alpha, small amounts lead to big changes. even at 128 its hard to figure out what is dark and what is light, at 64 you almost can't even tell.
/// For lighting alpha, small amounts lead to big changes. even at 128 its hard to figure out what is dark and what is light, at 64 you almost can't even tell.
#define LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE 128
#define LIGHTING_PLANE_ALPHA_INVISIBLE 0
//lighting area defines
#define DYNAMIC_LIGHTING_DISABLED 0 //dynamic lighting disabled (area stays at full brightness)
#define DYNAMIC_LIGHTING_ENABLED 1 //dynamic lighting enabled
#define DYNAMIC_LIGHTING_FORCED 2 //dynamic lighting enabled even if the area doesn't require power
#define DYNAMIC_LIGHTING_IFSTARLIGHT 3 //dynamic lighting enabled only if starlight is.
/// dynamic lighting disabled (area stays at full brightness)
#define DYNAMIC_LIGHTING_DISABLED 0
/// dynamic lighting enabled
#define DYNAMIC_LIGHTING_ENABLED 1
/// dynamic lighting enabled even if the area doesn't require power
#define DYNAMIC_LIGHTING_FORCED 2
/// dynamic lighting enabled only if starlight is.
#define DYNAMIC_LIGHTING_IFSTARLIGHT 3
#define IS_DYNAMIC_LIGHTING(A) A.dynamic_lighting

View File

@@ -1,9 +1,8 @@
///Defines for the R&D console, see: [/modules/research/rdconsole][rdconsole]
#define RDCONSOLE_UI_MODE_NORMAL 1
#define RDCONSOLE_UI_MODE_EXPERT 2
#define RDCONSOLE_UI_MODE_LIST 3
//RDSCREEN screens
#define RDSCREEN_MENU 0
#define RDSCREEN_TECHDISK 1
#define RDSCREEN_DESIGNDISK 20
@@ -27,6 +26,7 @@
#define RDSCREEN_NOBREAK "<NO_HTML_BREAK>"
///Sanity check defines for when these devices aren't connected or no disk is inserted
#define RDSCREEN_TEXT_NO_PROTOLATHE "<div><h3>No Protolathe Linked!</h3></div><br>"
#define RDSCREEN_TEXT_NO_IMPRINTER "<div><h3>No Circuit Imprinter Linked!</h3></div><br>"
#define RDSCREEN_TEXT_NO_DECONSTRUCT "<div><h3>No Destructive Analyzer Linked!</h3></div><br>"
@@ -43,12 +43,14 @@
#define RDSCREEN_UI_SNODE_CHECK if(!selected_node) { return RDSCREEN_TEXT_NO_SNODE }
#define RDSCREEN_UI_SDESIGN_CHECK if(!selected_design) { return RDSCREEN_TEXT_NO_SDESIGN }
///Defines for the Protolathe screens, see: [/modules/research/machinery/protolathe][Protolathe]
#define RESEARCH_FABRICATOR_SCREEN_MAIN 1
#define RESEARCH_FABRICATOR_SCREEN_CHEMICALS 2
#define RESEARCH_FABRICATOR_SCREEN_MATERIALS 3
#define RESEARCH_FABRICATOR_SCREEN_SEARCH 4
#define RESEARCH_FABRICATOR_SCREEN_CATEGORYVIEW 5
///Department flags for techwebs. Defines which department can print what from each protolathe so Cargo can't print guns, etc.
#define DEPARTMENTAL_FLAG_SECURITY (1<<0)
#define DEPARTMENTAL_FLAG_MEDICAL (1<<1)
#define DEPARTMENTAL_FLAG_CARGO (1<<2)
@@ -56,22 +58,25 @@
#define DEPARTMENTAL_FLAG_ENGINEERING (1<<4)
#define DEPARTMENTAL_FLAG_SERVICE (1<<5)
#define DEPARTMENTAL_FLAG_ALL (1<<6) //NO THIS DOESN'T ALLOW YOU TO PRINT EVERYTHING, IT'S FOR ALL DEPARTMENTS!
//#define DEPARTMENTAL_FLAG_MINING (1<<7)
//#define DEPARTMENTAL_FLAG_MINING (1<<7) //I swear I'm actually going to use this eventually leave it here
#define DESIGN_ID_IGNORE "IGNORE_THIS_DESIGN"
#define DESIGN_ID_IGNORE "IGNORE_THIS_DESIGN" ///For instances where we don't want a design showing up due to it being for debug/sanity purposes
#define RESEARCH_MATERIAL_RECLAMATION_ID "__materials"
//When adding new types, update the list below!
///Techweb names for new point types. Can be used to define specific point values for specific types of research (science, security, engineering, etc.)
#define TECHWEB_POINT_TYPE_GENERIC "General Research"
#define TECHWEB_POINT_TYPE_DEFAULT TECHWEB_POINT_TYPE_GENERIC
//defined here so people don't forget to change this!
///Associative names for techweb point values, see: [/modules/research/techweb/all_nodes][all_nodes]
#define TECHWEB_POINT_TYPE_LIST_ASSOCIATIVE_NAMES list(\
TECHWEB_POINT_TYPE_GENERIC = "General Research"\
)
#define TOXINS_RESEARCH_MAX 70000 // This is the maximum amount of research points a toxins bomb can get.
#define TOXINS_RESEARCH_LAMBDA 3940 // This determines how easy it is for a toxins bomb to reach the max research cap.
///This is the maximum amount of research points a toxins bomb can get.
#define TOXINS_RESEARCH_MAX 70000
///This determines how easy it is for a toxins bomb to reach the max research cap.
#define TOXINS_RESEARCH_LAMBDA 3940

View File

@@ -1,39 +1,91 @@
//Update this whenever the db schema changes
//make sure you add an update to the schema_version stable in the db changelog
//! Defines for subsystems and overlays
//!
//! Lots of important stuff in here, make sure you have your brain switched on
//! when editing this file
//! ## DB defines
/**
* DB major schema version
*
* Update this whenever the db schema changes
*
* make sure you add an update to the schema_version stable in the db changelog
*/
#define DB_MAJOR_VERSION 5
/**
* DB minor schema version
*
* Update this whenever the db schema changes
*
* make sure you add an update to the schema_version stable in the db changelog
*/
#define DB_MINOR_VERSION 4
//Timing subsystem
//Don't run if there is an identical unique timer active
//if the arguments to addtimer are the same as an existing timer, it doesn't create a new timer, and returns the id of the existing timer
//! ## Timing subsystem
/**
* Don't run if there is an identical unique timer active
*
* if the arguments to addtimer are the same as an existing timer, it doesn't create a new timer,
* and returns the id of the existing timer
*/
#define TIMER_UNIQUE (1<<0)
//For unique timers: Replace the old timer rather then not start this one
///For unique timers: Replace the old timer rather then not start this one
#define TIMER_OVERRIDE (1<<1)
//Timing should be based on how timing progresses on clients, not the sever.
// tracking this is more expensive,
// should only be used in conjuction with things that have to progress client side, such as animate() or sound()
/**
* Timing should be based on how timing progresses on clients, not the server.
*
* Tracking this is more expensive,
* should only be used in conjuction with things that have to progress client side, such as
* animate() or sound()
*/
#define TIMER_CLIENT_TIME (1<<2)
//Timer can be stopped using deltimer()
///Timer can be stopped using deltimer()
#define TIMER_STOPPABLE (1<<3)
//To be used with TIMER_UNIQUE
//prevents distinguishing identical timers with the wait variable
///prevents distinguishing identical timers with the wait variable
///
///To be used with TIMER_UNIQUE
#define TIMER_NO_HASH_WAIT (1<<4)
//Loops the timer repeatedly until qdeleted
//In most cases you want a subsystem instead
///Loops the timer repeatedly until qdeleted
///
///In most cases you want a subsystem instead, so don't use this unless you have a good reason
#define TIMER_LOOP (1<<5)
///Empty ID define
#define TIMER_ID_NULL -1
#define INITIALIZATION_INSSATOMS 0 //New should not call Initialize
#define INITIALIZATION_INNEW_MAPLOAD 2 //New should call Initialize(TRUE)
#define INITIALIZATION_INNEW_REGULAR 1 //New should call Initialize(FALSE)
//! ## Initialization subsystem
#define INITIALIZE_HINT_NORMAL 0 //Nothing happens
#define INITIALIZE_HINT_LATELOAD 1 //Call LateInitialize
#define INITIALIZE_HINT_QDEL 2 //Call qdel on the atom
///New should not call Initialize
#define INITIALIZATION_INSSATOMS 0
///New should call Initialize(TRUE)
#define INITIALIZATION_INNEW_MAPLOAD 2
///New should call Initialize(FALSE)
#define INITIALIZATION_INNEW_REGULAR 1
//type and all subtypes should always call Initialize in New()
//! ### Initialization hints
///Nothing happens
#define INITIALIZE_HINT_NORMAL 0
/**
* call LateInitialize at the end of all atom Initalization
*
* The item will be added to the late_loaders list, this is iterated over after
* initalization of subsystems is complete and calls LateInitalize on the atom
* see [this file for the LateIntialize proc](atom.html#proc/LateInitialize)
*/
#define INITIALIZE_HINT_LATELOAD 1
///Call qdel on the atom after intialization
#define INITIALIZE_HINT_QDEL 2
///type and all subtypes should always immediately call Initialize in New()
#define INITIALIZE_IMMEDIATE(X) ##X/New(loc, ...){\
..();\
if(!(flags_1 & INITIALIZED_1)) {\
@@ -127,7 +179,9 @@
// Truly disgusting, TG. Truly disgusting.
//! ## Overlays subsystem
///Compile all the overlays for an atom from the cache lists
#define COMPILE_OVERLAYS(A)\
if (TRUE) {\
var/list/ad = A.add_overlays;\

View File

@@ -1095,14 +1095,19 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0
obj_flags &= ~FROZEN
//Converts an icon to base64. Operates by putting the icon in the iconCache savefile,
// exporting it as text, and then parsing the base64 from that.
// (This relies on byond automatically storing icons in savefiles as base64)
/proc/icon2base64(icon/icon, iconKey = "misc")
/// Save file used in icon2base64. Used for converting icons to base64.
GLOBAL_DATUM_INIT(dummySave, /savefile, new("tmp/dummySave.sav")) //Cache of icons for the browser output
/**
* Converts an icon to base64. Operates by putting the icon in the iconCache savefile,
* exporting it as text, and then parsing the base64 from that.
* (This relies on byond automatically storing icons in savefiles as base64)
*/
/proc/icon2base64(icon/icon)
if (!isicon(icon))
return FALSE
WRITE_FILE(GLOB.iconCache[iconKey], icon)
var/iconData = GLOB.iconCache.ExportText(iconKey)
WRITE_FILE(GLOB.dummySave["dummy"], icon)
var/iconData = GLOB.dummySave.ExportText("dummy")
var/list/partial = splittext(iconData, "{")
return replacetext(copytext_char(partial[2], 3, -5), "\n", "")
@@ -1188,7 +1193,7 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0
I = icon()
I.Insert(temp, dir = SOUTH)
bicon_cache[key] = icon2base64(I, key)
bicon_cache[key] = icon2base64(I)
return "<img class='icon icon-[A.icon_state]' src='data:image/png;base64,[bicon_cache[key]]'>"

View File

@@ -8,6 +8,7 @@
**/
//This is the ABSOLUTE ONLY THING that should init globally like this
//2019 update: the failsafe,config and Global controllers also do it
GLOBAL_REAL(Master, /datum/controller/master) = new
//THIS IS THE INIT ORDER

View File

@@ -447,6 +447,7 @@ SUBSYSTEM_DEF(timer)
next.prev = src
prev.next = src
///Returns a string of the type of the callback for this timer
/datum/timedevent/proc/getcallingtype()
. = "ERROR"
if (callBack.object == GLOBAL_PROC)
@@ -454,6 +455,14 @@ SUBSYSTEM_DEF(timer)
else
. = "[callBack.object.type]"
/**
* Create a new timer and insert it in the queue
*
* Arguments:
* * callback the callback to call on timer finish
* * wait deciseconds to run the timer for
* * flags flags for this timer, see: code\__DEFINES\subsystems.dm
*/
/proc/addtimer(datum/callback/callback, wait = 0, flags = 0)
if (!callback)
CRASH("addtimer called without a callback")
@@ -498,6 +507,12 @@ SUBSYSTEM_DEF(timer)
var/datum/timedevent/timer = new(callback, wait, flags, hash)
return timer.id
/**
* Delete a timer
*
* Arguments:
* * id a timerid or a /datum/timedevent
*/
/proc/deltimer(id)
if (!id)
return FALSE
@@ -514,6 +529,26 @@ SUBSYSTEM_DEF(timer)
return TRUE
return FALSE
/**
* Get the remaining deciseconds on a timer
*
* Arguments:
* * id a timerid or a /datum/timedevent
*/
/proc/timeleft(id)
if (!id)
return null
if (id == TIMER_ID_NULL)
CRASH("Tried to get timeleft of a null timerid. Use TIMER_STOPPABLE flag")
if (!istext(id))
if (istype(id, /datum/timedevent))
var/datum/timedevent/timer = id
return timer.timeToRun - world.time
//id is string
var/datum/timedevent/timer = SStimer.timer_id_dict[id]
if (timer && !timer.spent)
return timer.timeToRun - world.time
return null
#undef BUCKET_LEN
#undef BUCKET_POS

View File

@@ -1,55 +1,72 @@
/*
USAGE:
var/datum/callback/C = new(object|null, /proc/type/path|"procstring", arg1, arg2, ... argn)
var/timerid = addtimer(C, time, timertype)
OR
var/timerid = addtimer(CALLBACK(object|null, /proc/type/path|procstring, arg1, arg2, ... argn), time, timertype)
Note: proc strings can only be given for datum proc calls, global procs must be proc paths
Also proc strings are strongly advised against because they don't compile error if the proc stops existing
See the note on proc typepath shortcuts
INVOKING THE CALLBACK:
var/result = C.Invoke(args, to, add) //additional args are added after the ones given when the callback was created
OR
var/result = C.InvokeAsync(args, to, add) //Sleeps will not block, returns . on the first sleep (then continues on in the "background" after the sleep/block ends), otherwise operates normally.
OR
INVOKE_ASYNC(<CALLBACK args>) to immediately create and call InvokeAsync
PROC TYPEPATH SHORTCUTS (these operate on paths, not types, so to these shortcuts, datum is NOT a parent of atom, etc...)
global proc while in another global proc:
.procname
Example:
CALLBACK(GLOBAL_PROC, .some_proc_here)
proc defined on current(src) object (when in a /proc/ and not an override) OR overridden at src or any of it's parents:
.procname
Example:
CALLBACK(src, .some_proc_here)
when the above doesn't apply:
.proc/procname
Example:
CALLBACK(src, .proc/some_proc_here)
proc defined on a parent of a some type:
/some/type/.proc/some_proc_here
Other wise you will have to do the full typepath of the proc (/type/of/thing/proc/procname)
*/
/**
*# Callback Datums
*A datum that holds a proc to be called on another object, used to track proccalls to other objects
*
* ## USAGE
*
* ```
* var/datum/callback/C = new(object|null, /proc/type/path|"procstring", arg1, arg2, ... argn)
* var/timerid = addtimer(C, time, timertype)
* you can also use the compiler define shorthand
* var/timerid = addtimer(CALLBACK(object|null, /proc/type/path|procstring, arg1, arg2, ... argn), time, timertype)
* ```
*
* Note: proc strings can only be given for datum proc calls, global procs must be proc paths
*
* Also proc strings are strongly advised against because they don't compile error if the proc stops existing
*
* In some cases you can provide a shortform of the procname, see the proc typepath shortcuts documentation below
*
* ## INVOKING THE CALLBACK
*`var/result = C.Invoke(args, to, add)` additional args are added after the ones given when the callback was created
*
* `var/result = C.InvokeAsync(args, to, add)` Asyncronous - returns . on the first sleep then continues on in the background
* after the sleep/block ends, otherwise operates normally.
*
* ## PROC TYPEPATH SHORTCUTS
* (these operate on paths, not types, so to these shortcuts, datum is NOT a parent of atom, etc...)
*
* ### global proc while in another global proc:
* .procname
*
* `CALLBACK(GLOBAL_PROC, .some_proc_here)`
*
* ### proc defined on current(src) object (when in a /proc/ and not an override) OR overridden at src or any of it's parents:
* .procname
*
* `CALLBACK(src, .some_proc_here)`
*
* ### when the above doesn't apply:
*.proc/procname
*
* `CALLBACK(src, .proc/some_proc_here)`
*
*
* proc defined on a parent of a some type
*
* `/some/type/.proc/some_proc_here`
*
* Otherwise you must always provide the full typepath of the proc (/type/of/thing/proc/procname)
*/
/datum/callback
///The object we will be calling the proc on
var/datum/object = GLOBAL_PROC
///The proc we will be calling on the object
var/delegate
///A list of arguments to pass into the proc
var/list/arguments
///A weak reference to the user who triggered this callback
var/datum/weakref/user
/**
* Create a new callback datum
*
* Arguments
* * thingtocall the object to call the proc on
* * proctocall the proc to call on the target object
* * ... an optional list of extra arguments to pass to the proc
*/
/datum/callback/New(thingtocall, proctocall, ...)
if (thingtocall)
object = thingtocall
@@ -58,7 +75,14 @@
arguments = args.Copy(3)
if(usr)
user = WEAKREF(usr)
/**
* Immediately Invoke proctocall on thingtocall, with waitfor set to false
*
* Arguments:
* * thingtocall Object to call on
* * proctocall Proc to call on that object
* * ... optional list of arguments to pass as arguments to the proc being called
*/
/world/proc/ImmediateInvokeAsync(thingtocall, proctocall, ...)
set waitfor = FALSE
@@ -72,6 +96,14 @@
else
call(thingtocall, proctocall)(arglist(calling_arguments))
/**
* Invoke this callback
*
* Calls the registered proc on the registered object, if the user ref
* can be resolved it also inclues that as an arg
*
* If the datum being called on is varedited, the call is wrapped via WrapAdminProcCall
*/
/datum/callback/proc/Invoke(...)
if(!usr)
var/datum/weakref/W = user
@@ -97,7 +129,14 @@
return call(delegate)(arglist(calling_arguments))
return call(object, delegate)(arglist(calling_arguments))
//copy and pasted because fuck proc overhead
/**
* Invoke this callback async (waitfor=false)
*
* Calls the registered proc on the registered object, if the user ref
* can be resolved it also inclues that as an arg
*
* If the datum being called on is varedited, the call is wrapped via WrapAdminProcCall
*/
/datum/callback/proc/InvokeAsync(...)
set waitfor = FALSE
@@ -125,7 +164,9 @@
return call(delegate)(arglist(calling_arguments))
return call(object, delegate)(arglist(calling_arguments))
/**
Helper datum for the select callbacks proc
*/
/datum/callback_select
var/list/finished
var/pendingcount
@@ -150,15 +191,17 @@
if (savereturn)
finished[index] = rtn
//runs a list of callbacks asynchronously, returning once all of them return.
//callbacks can be repeated.
//callbacks-args is an optional list of argument lists, in the same order as the callbacks,
// the inner lists will be sent to the callbacks when invoked() as additional args.
//can optionly save and return a list of return values, in the same order as the original list of callbacks
//resolution is the number of byond ticks between checks.
/**
* Runs a list of callbacks asyncronously, returning only when all have finished
*
* Callbacks can be repeated, to call it multiple times
*
* Arguments:
* * list/callbacks the list of callbacks to be called
* * list/callback_args the list of lists of arguments to pass into each callback
* * savereturns Optionally save and return the list of returned values from each of the callbacks
* * resolution The number of byond ticks between each time you check if all callbacks are complete
*/
/proc/callback_select(list/callbacks, list/callback_args, savereturns = TRUE, resolution = 1)
if (!callbacks)
return

View File

@@ -1,12 +1,38 @@
/**
* The absolute base class for everything
*
* A datum instantiated has no physical world prescence, use an atom if you want something
* that actually lives in the world
*
* Be very mindful about adding variables to this class, they are inherited by every single
* thing in the entire game, and so you can easily cause memory usage to rise a lot with careless
* use of variables at this level
*/
/datum
var/gc_destroyed //Time when this object was destroyed.
var/list/active_timers //for SStimer
var/list/datum_components //for /datum/components
/**
* Tick count time when this object was destroyed.
*
* If this is non zero then the object has been garbage collected and is awaiting either
* a hard del by the GC subsystme, or to be autocollected (if it has no references)
*/
var/gc_destroyed
/// Active timers with this datum as the target
var/list/active_timers
/// Components attached to this datum
var/list/datum_components
/// Status traits attached to this datum
var/list/status_traits
var/list/comp_lookup //it used to be for looking up components which had registered a signal but now anything can register
/// Any datum registered to receive signals from this datum is in this list
var/list/comp_lookup
/// List of callbacks for signal procs
var/list/list/datum/callback/signal_procs
/// Is this datum capable of sending signals?
var/signal_enabled = FALSE
/// Datum level flags
var/datum_flags = NONE
/// A weak reference to another datum
var/datum/weakref/weak_reference
#ifdef TESTING
@@ -18,13 +44,31 @@
var/list/cached_vars
#endif
/**
* Called when a href for this datum is clicked
*
* Sends a COMSIG_TOPIC signal
*/
/datum/Topic(href, href_list[])
..()
SEND_SIGNAL(src, COMSIG_TOPIC, usr, href_list)
// Default implementation of clean-up code.
// This should be overridden to remove all references pointing to the object being destroyed.
// Return the appropriate QDEL_HINT; in most cases this is QDEL_HINT_QUEUE.
/**
* Default implementation of clean-up code.
*
* This should be overridden to remove all references pointing to the object being destroyed, if
* you do override it, make sure to call the parent and return it's return value by default
*
* Return an appropriate QDEL_HINT to modify handling of your deletion;
* in most cases this is QDEL_HINT_QUEUE.
*
* The base case is responsible for doing the following
* * Erasing timers pointing to this datum
* * Erasing compenents on this datum
* * Notifying datums listening to signals from this datum that we are going away
*
* Returns QDEL_HINT_QUEUE
*/
/datum/proc/Destroy(force=FALSE, ...)
SHOULD_CALL_PARENT(TRUE)
tag = null
@@ -100,15 +144,15 @@
to_chat(target, txt_changed_vars())
#endif
//Return a LIST for serialize_datum to encode! Not the actual json!
///Return a LIST for serialize_datum to encode! Not the actual json!
/datum/proc/serialize_list(list/options)
CRASH("Attempted to serialize datum [src] of type [type] without serialize_list being implemented!")
//Accepts a LIST from deserialize_datum. Should return src or another datum.
///Accepts a LIST from deserialize_datum. Should return src or another datum.
/datum/proc/deserialize_list(json, list/options)
CRASH("Attempted to deserialize datum [src] of type [type] without deserialize_list being implemented!")
//Serializes into JSON. Does not encode type.
///Serializes into JSON. Does not encode type.
/datum/proc/serialize_json(list/options)
. = serialize_list(options)
if(!islist(.))
@@ -116,13 +160,14 @@
else
. = json_encode(.)
//Deserializes from JSON. Does not parse type.
///Deserializes from JSON. Does not parse type.
/datum/proc/deserialize_json(list/input, list/options)
var/list/jsonlist = json_decode(input)
. = deserialize_list(jsonlist)
if(!istype(., /datum))
. = null
///Convert a datum into a json blob
/proc/json_serialize_datum(datum/D, list/options)
if(!istype(D))
return
@@ -131,6 +176,7 @@
jsonlist["DATUM_TYPE"] = D.type
return json_encode(jsonlist)
/// Convert a list of json to datum
/proc/json_deserialize_datum(list/jsonlist, list/options, target_type, strict_target_type = FALSE)
if(!islist(jsonlist))
if(!istext(jsonlist))

View File

@@ -1,41 +1,153 @@
/**
* # Outfit datums
*
* This is a clean system of applying outfits to mobs, if you need to equip someone in a uniform
* this is the way to do it cleanly and properly.
*
* You can also specify an outfit datum on a job to have it auto equipped to the mob on join
*
* /mob/living/carbon/human/proc/equipOutfit(outfit) is the mob level proc to equip an outfit
* and you pass it the relevant datum outfit
*
* outfits can also be saved as json blobs downloadable by a client and then can be uploaded
* by that user to recreate the outfit, this is used by admins to allow for custom event outfits
* that can be restored at a later date
*/
/datum/outfit
///Name of the outfit (shows up in the equip admin verb)
var/name = "Naked"
/// Type path of item to go in uniform slot
var/uniform = null
/// Type path of item to go in suit slot
var/suit = null
var/toggle_helmet = TRUE
/// Type path of item to go in back slot
var/back = null
/// Type path of item to go in belt slot
var/belt = null
/// Type path of item to go in gloves slot
var/gloves = null
/// Type path of item to go in shoes slot
var/shoes = null
/// Type path of item to go in head slot
var/head = null
/// Type path of item to go in mask slot
var/mask = null
/// Type path of item to go in neck slot
var/neck = null
/// Type path of item to go in ears slot
var/ears = null
/// Type path of item to go in the glasses slot
var/glasses = null
/// Type path of item to go in the idcard slot
var/id = null
/// Type path of item for left pocket slot
var/l_pocket = null
/// Type path of item for right pocket slot
var/r_pocket = null
/**
* Type path of item to go in suit storage slot
*
* (make sure it's valid for that suit)
*/
var/suit_store = null
///Type path of item to go in the right hand
var/r_hand = null
//Type path of item to go in left hand
var/l_hand = null
var/internals_slot = null //ID of slot containing a gas tank
var/list/backpack_contents = null // In the list(path=count,otherpath=count) format
var/box // Internals box. Will be inserted at the start of backpack_contents
/// Should the toggle helmet proc be called on the helmet during equip
var/toggle_helmet = TRUE
///ID of the slot containing a gas tank
var/internals_slot = null
/**
* list of items that should go in the backpack of the user
*
* Format of this list should be: list(path=count,otherpath=count)
*/
var/list/backpack_contents = null
/// Internals box. Will be inserted at the start of backpack_contents
var/box
/**
* Any implants the mob should start implanted with
*
* Format of this list is (typepath, typepath, typepath)
*/
var/list/implants = null
/// Any clothing accessory item
var/accessory = null
var/can_be_admin_equipped = TRUE // Set to FALSE if your outfit requires runtime parameters
var/list/chameleon_extras //extra types for chameleon outfit changes, mostly guns
/// Set to FALSE if your outfit requires runtime parameters
var/can_be_admin_equipped = TRUE
/**
* extra types for chameleon outfit changes, mostly guns
*
* Format of this list is (typepath, typepath, typepath)
*
* These are all added and returns in the list for get_chamelon_diguise_info proc
*/
var/list/chameleon_extras
/**
* Called at the start of the equip proc
*
* Override to change the value of the slots depending on client prefs, species and
* other such sources of change
*
* Extra Arguments
* * visualsOnly true if this is only for display (in the character setup screen)
*
* If visualsOnly is true, you can omit any work that doesn't visually appear on the character sprite
*/
/datum/outfit/proc/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
//to be overridden for customization depending on client prefs,species etc
return
/**
* Called after the equip proc has finished
*
* All items are on the mob at this point, use this proc to toggle internals
* fiddle with id bindings and accesses etc
*
* Extra Arguments
* * visualsOnly true if this is only for display (in the character setup screen)
*
* If visualsOnly is true, you can omit any work that doesn't visually appear on the character sprite
*/
/datum/outfit/proc/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
//to be overridden for toggling internals, id binding, access etc
return
/**
* Equips all defined types and paths to the mob passed in
*
* Extra Arguments
* * visualsOnly true if this is only for display (in the character setup screen)
*
* If visualsOnly is true, you can omit any work that doesn't visually appear on the character sprite
*/
/datum/outfit/proc/equip(mob/living/carbon/human/H, visualsOnly = FALSE)
pre_equip(H, visualsOnly)
@@ -118,6 +230,13 @@
H.update_body()
return TRUE
/**
* Apply a fingerprint from the passed in human to all items in the outfit
*
* Used for forensics setup when the mob is first equipped at roundstart
* essentially calls add_fingerprint to every defined item on the human
*
*/
/datum/outfit/proc/apply_fingerprints(mob/living/carbon/human/H)
if(!istype(H))
return
@@ -159,12 +278,14 @@
I.add_fingerprint(H,1)
return 1
/// Return a list of all the types that are required to disguise as this outfit type
/datum/outfit/proc/get_chameleon_disguise_info()
var/list/types = list(uniform, suit, back, belt, gloves, shoes, head, mask, neck, ears, glasses, id, l_pocket, r_pocket, suit_store, r_hand, l_hand)
types += chameleon_extras
listclearnulls(types)
return types
/// Return a json list of this outfit
/datum/outfit/proc/get_json_data()
. = list()
.["outfit_type"] = type
@@ -193,6 +314,7 @@
.["implants"] = implants
.["accessory"] = accessory
/// Prompt the passed in mob client to download this outfit as a json blob
/datum/outfit/proc/save_to_file(mob/admin)
var/stored_data = get_json_data()
var/json = json_encode(stored_data)
@@ -202,6 +324,7 @@
WRITE_FILE(f,json)
admin << ftp(f,"[name].json")
/// Create an outfit datum from a list of json data
/datum/outfit/proc/load_from(list/outfit_data)
//This could probably use more strict validation
name = outfit_data["name"]

View File

@@ -1,13 +1,16 @@
// Areas.dm
/**
* # area
*
* A grouping of tiles into a logical space, mostly used by map editors
*/
/area
level = null
name = "Space"
icon = 'icons/turf/areas.dmi'
icon_state = "unknown"
layer = AREA_LAYER
plane = BLACKNESS_PLANE //Keeping this on the default plane, GAME_PLANE, will make area overlays fail to render on FLOOR_PLANE.
//Keeping this on the default plane, GAME_PLANE, will make area overlays fail to render on FLOOR_PLANE.
plane = BLACKNESS_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
invisibility = INVISIBILITY_LIGHTING
@@ -37,9 +40,9 @@
var/areasize = 0 //Size of the area in open turfs, only calculated for indoors areas.
//Bonus mood from being in this area
/// Bonus mood for being in this area
var/mood_bonus = 0
//Mood message for being here, only shows up if mood_bonus != 0
/// Mood message for being here, only shows up if mood_bonus != 0
var/mood_message = "<span class='nicegreen'>This area is pretty nice!\n</span>"
var/power_equip = TRUE
@@ -53,9 +56,12 @@
var/static_environ
var/has_gravity = 0
var/noteleport = FALSE //Are you forbidden from teleporting to the area? (centcom, mobs, wizard, hand teleporter)
var/hidden = FALSE //Hides area from player Teleport function.
var/safe = FALSE //Is the area teleport-safe: no space / radiation / aggresive mobs / other dangers
///Are you forbidden from teleporting to the area? (centcom, mobs, wizard, hand teleporter)
var/noteleport = FALSE
///Hides area from player Teleport function.
var/hidden = FALSE
///Is the area teleport-safe: no space / radiation / aggresive mobs / other dangers
var/safe = FALSE
/// If false, loading multiple maps with this area type will create multiple instances.
var/unique = TRUE
@@ -72,15 +78,30 @@
var/list/cameras
var/list/firealarms
var/firedoors_last_closed_on = 0
var/xenobiology_compatible = FALSE //Can the Xenobio management console transverse this area by default?
var/list/canSmoothWithAreas //typecache to limit the areas that atoms in this area can smooth with
/// Can the Xenobio management console transverse this area by default?
var/xenobiology_compatible = FALSE
/// typecache to limit the areas that atoms in this area can smooth with, used for shuttles IIRC
var/list/canSmoothWithAreas
var/minimap_color = null // if null, chooses random one
/*Adding a wizard area teleport list because motherfucking lag -- Urist*/
/*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/
/**
* A list of teleport locations
*
* Adding a wizard area teleport list because motherfucking lag -- Urist
* I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game
*/
GLOBAL_LIST_EMPTY(teleportlocs)
/**
* Generate a list of turfs you can teleport to from the areas list
*
* Includes areas if they're not a shuttle or not not teleport or have no contents
*
* The chosen turf is the first item in the areas contents that is a station level
*
* The returned list of turfs is sorted by name
*/
/proc/process_teleport_locs()
for(var/V in GLOB.sortedAreas)
var/area/AR = V
@@ -96,8 +117,11 @@ GLOBAL_LIST_EMPTY(teleportlocs)
sortTim(GLOB.teleportlocs, /proc/cmp_text_dsc)
// ===
/**
* Called when an area loads
*
* Adds the item to the GLOB.areas_by_type list based on area type
*/
/area/New()
if(!minimap_color) // goes in New() because otherwise it doesn't fucking work
// generate one using the icon_state
@@ -114,6 +138,14 @@ GLOBAL_LIST_EMPTY(teleportlocs)
GLOB.areas_by_type[type] = src
return ..()
/**
* Initalize this area
*
* intializes the dynamic area lighting and also registers the area with the z level via
* reg_in_areas_in_z
*
* returns INITIALIZE_HINT_LATELOAD
*/
/area/Initialize()
icon_state = ""
layer = AREA_LAYER
@@ -147,9 +179,21 @@ GLOBAL_LIST_EMPTY(teleportlocs)
return INITIALIZE_HINT_LATELOAD
/**
* Sets machine power levels in the area
*/
/area/LateInitialize()
power_change() // all machines set to current power level, also updates icon
/**
* Register this area as belonging to a z level
*
* Ensures the item is added to the SSmapping.areas_in_z list for this z
*
* It also goes through every item in this areas contents and sets the area level z to it
* breaking the exat first time it does this, this seems crazy but what would I know, maybe
* areas don't have a valid z themself or something
*/
/area/proc/reg_in_areas_in_z()
if(contents.len)
var/list/areas_in_z = SSmapping.areas_in_z
@@ -168,12 +212,25 @@ GLOBAL_LIST_EMPTY(teleportlocs)
areas_in_z["[z]"] = list()
areas_in_z["[z]"] += src
/**
* Destroy an area and clean it up
*
* Removes the area from GLOB.areas_by_type and also stops it processing on SSobj
*
* This is despite the fact that no code appears to put it on SSobj, but
* who am I to argue with old coders
*/
/area/Destroy()
if(GLOB.areas_by_type[type] == src)
GLOB.areas_by_type[type] = null
STOP_PROCESSING(SSobj, src)
return ..()
/**
* Generate a power alert for this area
*
* Sends to all ai players, alert consoles, drones and alarm monitor programs in the world
*/
/area/proc/poweralert(state, obj/source)
if (state != poweralm)
poweralm = state
@@ -205,6 +262,11 @@ GLOBAL_LIST_EMPTY(teleportlocs)
else
p.triggerAlarm("Power", src, cameras, source)
/**
* Generate an atmospheric alert for this area
*
* Sends to all ai players, alert consoles, drones and alarm monitor programs in the world
*/
/area/proc/atmosalert(danger_level, obj/source)
if(danger_level != atmosalm)
if (danger_level==2)
@@ -240,6 +302,9 @@ GLOBAL_LIST_EMPTY(teleportlocs)
return 1
return 0
/**
* Try to close all the firedoors in the area
*/
/area/proc/ModifyFiredoors(opening)
if(firedoors)
firedoors_last_closed_on = world.time
@@ -258,6 +323,13 @@ GLOBAL_LIST_EMPTY(teleportlocs)
else if(!(D.density ^ opening))
INVOKE_ASYNC(D, (opening ? /obj/machinery/door/firedoor.proc/open : /obj/machinery/door/firedoor.proc/close))
/**
* Generate an firealarm alert for this area
*
* Sends to all ai players, alert consoles, drones and alarm monitor programs in the world
*
* Also starts the area processing on SSobj
*/
/area/proc/firealert(obj/source)
if(always_unpowered == 1) //no fire alarms in space/asteroid
return
@@ -284,6 +356,14 @@ GLOBAL_LIST_EMPTY(teleportlocs)
START_PROCESSING(SSobj, src)
/**
* Reset the firealarm alert for this area
*
* resets the alert sent to all ai players, alert consoles, drones and alarm monitor programs
* in the world
*
* Also cycles the icons of all firealarms and deregisters the area from processing on SSOBJ
*/
/area/proc/firereset(obj/source)
if (fire)
unset_fire_alarm_effects()
@@ -307,16 +387,31 @@ GLOBAL_LIST_EMPTY(teleportlocs)
STOP_PROCESSING(SSobj, src)
/**
* If 100 ticks has elapsed, toggle all the firedoors closed again
*/
/area/process()
if(firedoors_last_closed_on + 100 < world.time) //every 10 seconds
ModifyFiredoors(FALSE)
/**
* Close and lock a door passed into this proc
*
* Does this need to exist on area? probably not
*/
/area/proc/close_and_lock_door(obj/machinery/door/DOOR)
set waitfor = FALSE
DOOR.close()
if(DOOR.density)
DOOR.lock()
/**
* Raise a burglar alert for this area
*
* Close and locks all doors in the area and alerts silicon mobs of a break in
*
* Alarm auto resets after 600 ticks
*/
/area/proc/burglaralert(obj/trigger)
if(always_unpowered) //no burglar alarms in space/asteroid
return
@@ -333,6 +428,11 @@ GLOBAL_LIST_EMPTY(teleportlocs)
//Cancel silicon alert after 1 minute
addtimer(CALLBACK(SILICON, /mob/living/silicon.proc/cancelAlarm,"Burglar",src,trigger), 600)
/**
* Trigger the fire alarm visual affects in an area
*
* Updates the fire light on fire alarms in the area and sets all lights to emergency mode
*/
/area/proc/set_fire_alarm_effect()
fire = TRUE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
@@ -342,6 +442,11 @@ GLOBAL_LIST_EMPTY(teleportlocs)
for(var/obj/machinery/light/L in src)
L.update()
/**
* unset the fire alarm visual affects in an area
*
* Updates the fire light on fire alarms in the area and sets all lights to emergency mode
*/
/area/proc/unset_fire_alarm_effects()
fire = FALSE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
@@ -363,6 +468,12 @@ GLOBAL_LIST_EMPTY(teleportlocs)
for(var/obj/machinery/light/L in src)
L.update()
/**
* Update the icon of the area
*
* Im not sure what the heck this does, somethign to do with weather being able to set icon
* states on areas?? where the heck would that even display?
*/
/area/proc/update_icon()
var/weather_icon
for(var/V in SSweather.processing)
@@ -373,15 +484,19 @@ GLOBAL_LIST_EMPTY(teleportlocs)
if(!weather_icon)
icon_state = null
/**
* Update the icon of the area (overridden to always be null for space
*/
/area/space/update_icon()
icon_state = null
/*
#define EQUIP 1
#define LIGHT 2
#define ENVIRON 3
*/
/**
* Returns int 1 or 0 if the area has power for the given channel
*
* evalutes a mixture of variables mappers can set, requires_power, always_unpowered and then
* per channel power_equip, power_light, power_environ
*/
/area/proc/powered(chan) // return true if the area has power to given channel
if(!requires_power)
@@ -398,16 +513,25 @@ GLOBAL_LIST_EMPTY(teleportlocs)
return 0
/**
* Space is not powered ever, so this returns 0
*/
/area/space/powered(chan) //Nope.avi
return 0
// called when power status changes
/**
* Called when the area power status changes
*
* Updates the area icon and calls power change on all machinees in the area
*/
/area/proc/power_change()
for(var/obj/machinery/M in src) // for each machine in the area
M.power_change() // reverify power status (to update icons etc.)
update_icon()
/**
* Return the usage of power per channel
*/
/area/proc/usage(chan)
var/used = 0
switch(chan)
@@ -427,6 +551,14 @@ GLOBAL_LIST_EMPTY(teleportlocs)
used += static_environ
return used
/**
* Add a static amount of power load to an area
*
* Possible channels
* *STATIC_EQUIP
* *STATIC_LIGHT
* *STATIC_ENVIRON
*/
/area/proc/addStaticPower(value, powerchannel)
switch(powerchannel)
if(STATIC_EQUIP)
@@ -436,11 +568,19 @@ GLOBAL_LIST_EMPTY(teleportlocs)
if(STATIC_ENVIRON)
static_environ += value
/**
* Clear all power usage in area
*
* Clears all power used for equipment, light and environment channels
*/
/area/proc/clear_usage()
used_equip = 0
used_light = 0
used_environ = 0
/**
* Add a power value amount to the stored used_x variables
*/
/area/proc/use_power(amount, chan)
switch(chan)
@@ -451,7 +591,13 @@ GLOBAL_LIST_EMPTY(teleportlocs)
if(ENVIRON)
used_environ += amount
/**
* Call back when an atom enters an area
*
* Sends signals COMSIG_AREA_ENTERED and COMSIG_ENTER_AREA (to the atom)
*
* If the area has ambience, then it plays some ambience music to the ambience channel
*/
/area/Entered(atom/movable/M)
set waitfor = FALSE
SEND_SIGNAL(src, COMSIG_AREA_ENTERED, M)
@@ -479,13 +625,35 @@ GLOBAL_LIST_EMPTY(teleportlocs)
L.client.played = TRUE
addtimer(CALLBACK(L.client, /client/proc/ResetAmbiencePlayed), 600)
/**
* Called when an atom exits an area
*
* Sends signals COMSIG_AREA_EXITED and COMSIG_EXIT_AREA (to the atom)
*/
/area/Exited(atom/movable/M)
SEND_SIGNAL(src, COMSIG_AREA_EXITED, M)
SEND_SIGNAL(M, COMSIG_EXIT_AREA, src) //The atom that exits the area
/**
* Reset the played var to false on the client
*/
/client/proc/ResetAmbiencePlayed()
played = FALSE
/**
* Returns true if this atom has gravity for the passed in turf
*
* Sends signals COMSIG_ATOM_HAS_GRAVITY and COMSIG_TURF_HAS_GRAVITY, both can force gravity with
* the forced gravity var
*
* Gravity situations:
* * No gravity if you're not in a turf
* * No gravity if this atom is in is a space turf
* * Gravity if the area it's in always has gravity
* * Gravity if there's a gravity generator on the z level
* * Gravity if the Z level has an SSMappingTrait for ZTRAIT_GRAVITY
* * otherwise no gravity
*/
/atom/proc/has_gravity(turf/T)
if(!T || !isturf(T))
T = get_turf(src)
@@ -517,7 +685,11 @@ GLOBAL_LIST_EMPTY(teleportlocs)
max_grav = max(G.setting,max_grav)
return max_grav
return SSmapping.level_trait(T.z, ZTRAIT_GRAVITY)
/**
* Setup an area (with the given name)
*
* Sets the area name, sets all status var's to false and adds the area to the sorted area list
*/
/area/proc/setup(a_name)
name = a_name
power_equip = FALSE
@@ -527,7 +699,12 @@ GLOBAL_LIST_EMPTY(teleportlocs)
valid_territory = FALSE
blob_allowed = FALSE
addSorted()
/**
* Set the area size of the area
*
* This is the number of open turfs in the area contents, or FALSE if the outdoors var is set
*
*/
/area/proc/update_areasize()
if(outdoors)
return FALSE
@@ -535,12 +712,18 @@ GLOBAL_LIST_EMPTY(teleportlocs)
for(var/turf/open/T in contents)
areasize++
/**
* Causes a runtime error
*/
/area/AllowDrop()
CRASH("Bad op: area/AllowDrop() called")
/**
* Causes a runtime error
*/
/area/drop_location()
CRASH("Bad op: area/drop_location() called")
// A hook so areas can modify the incoming args
/// A hook so areas can modify the incoming args (of what??)
/area/proc/PlaceOnTopReact(list/new_baseturfs, turf/fake_turf_type, flags)
return flags

View File

@@ -1,43 +1,72 @@
/**
* The base type for nearly all physical objects in SS13
* Lots and lots of functionality lives here, although in general we are striving to move
* as much as possible to the components/elements system
*/
/atom
layer = TURF_LAYER
plane = GAME_PLANE
var/level = 2
var/article // If non-null, overrides a/an/some in all cases
///If non-null, overrides a/an/some in all cases
var/article
///First atom flags var
var/flags_1 = NONE
///Intearaction flags
var/interaction_flags_atom = NONE
///Reagents holder
var/datum/reagents/reagents = null
//This atom's HUD (med/sec, etc) images. Associative list.
///This atom's HUD (med/sec, etc) images. Associative list.
var/list/image/hud_list = null
//HUD images that this atom can provide.
///HUD images that this atom can provide.
var/list/hud_possible
//Value used to increment ex_act() if reactionary_explosions is on
///Value used to increment ex_act() if reactionary_explosions is on
var/explosion_block = 0
var/list/atom_colours //used to store the different colors on an atom
//its inherent color, the colored paint applied on it, special color effect etc...
/**
* used to store the different colors on an atom
*
* its inherent color, the colored paint applied on it, special color effect etc...
*/
var/list/atom_colours
var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4.
var/list/remove_overlays // a very temporary list of overlays to remove
var/list/add_overlays // a very temporary list of overlays to add
var/list/managed_vis_overlays //vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays
///overlays that should remain on top and not normally removed when using cut_overlay functions, like c4.
var/list/priority_overlays
/// a very temporary list of overlays to remove
var/list/remove_overlays
/// a very temporary list of overlays to add
var/list/add_overlays
///vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays
var/list/managed_vis_overlays
///Proximity monitor associated with this atom
var/datum/proximity_monitor/proximity_monitor
///Cooldown tick timer for buckle messages
var/buckle_message_cooldown = 0
///Last fingerprints to touch this atom
var/fingerprintslast
var/list/filter_data //For handling persistent filters
///Economy cost of item
var/custom_price
///Economy cost of item in premium vendor
var/custom_premium_price
///Whether spessmen with an ID with an age below AGE_MINOR (21 by default) can buy this item
var/age_restricted = FALSE
//List of datums orbiting this atom
var/datum/component/orbiter/orbiters
var/rad_flags = NONE // Will move to flags_1 when i can be arsed to
/// Will move to flags_1 when i can be arsed to (2019, has not done so)
var/rad_flags = NONE
/// Radiation insulation types
var/rad_insulation = RAD_NO_INSULATION
var/chat_color_name // Last name used to calculate a color for the chatmessage overlays
@@ -47,6 +76,16 @@
var/chat_color_darkened // A luminescence-shifted value of the last color calculated for chatmessage overlays
/**
* Called when an atom is created in byond (built in engine proc)
*
* Not a lot happens here in SS13 code, as we offload most of the work to the
* [Intialization](atom.html#proc/Initialize) proc, mostly we run the preloader
* if the preloader is being used and then call InitAtom of which the ultimate
* result is that the Intialize proc is called.
*
* We also generate a tag here if the DF_USE_TAG flag is set on the atom
*/
/atom/New(loc, ...)
//atom creation method that preloads variables at creation
if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New()
@@ -63,17 +102,40 @@
return
SSdemo.mark_new(src)
//Called after New if the map is being loaded. mapload = TRUE
//Called from base of New if the map is not being loaded. mapload = FALSE
//This base must be called or derivatives must set initialized to TRUE
//must not sleep
//Other parameters are passed from New (excluding loc), this does not happen if mapload is TRUE
//Must return an Initialize hint. Defined in __DEFINES/subsystems.dm
//Note: the following functions don't call the base for optimization and must copypasta:
// /turf/Initialize
// /turf/open/space/Initialize
/**
* The primary method that objects are setup in SS13 with
*
* we don't use New as we have better control over when this is called and we can choose
* to delay calls or hook other logic in and so forth
*
* During roundstart map parsing, atoms are queued for intialization in the base atom/New(),
* After the map has loaded, then Initalize is called on all atoms one by one. NB: this
* is also true for loading map templates as well, so they don't Initalize until all objects
* in the map file are parsed and present in the world
*
* If you're creating an object at any point after SSInit has run then this proc will be
* immediately be called from New.
*
* mapload: This parameter is true if the atom being loaded is either being intialized during
* the Atom subsystem intialization, or if the atom is being loaded from the map template.
* If the item is being created at runtime any time after the Atom subsystem is intialized then
* it's false.
*
* You must always call the parent of this proc, otherwise failures will occur as the item
* will not be seen as initalized (this can lead to all sorts of strange behaviour, like
* the item being completely unclickable)
*
* You must not sleep in this proc, or any subprocs
*
* Any parameters from new are passed through (excluding loc), naturally if you're loading from a map
* there are no other arguments
*
* Must return an [initialization hint](code/__DEFINES/subsystems.html) or a runtime will occur.
*
* Note: the following functions don't call the base for optimization and must copypasta handling:
* * /turf/Initialize
* * /turf/open/space/Initialize
*/
/atom/proc/Initialize(mapload, ...)
SHOULD_CALL_PARENT(TRUE)
if(flags_1 & INITIALIZED_1)
@@ -98,14 +160,35 @@
return INITIALIZE_HINT_NORMAL
//called if Initialize returns INITIALIZE_HINT_LATELOAD
/**
* Late Intialization, for code that should run after all atoms have run Intialization
*
* To have your LateIntialize proc be called, your atoms [Initalization](atom.html#proc/Initialize)
* proc must return the hint
* [INITIALIZE_HINT_LATELOAD](code/__DEFINES/subsystems.html#define/INITIALIZE_HINT_LATELOAD)
* otherwise you will never be called.
*
* useful for doing things like finding other machines on GLOB.machines because you can guarantee
* that all atoms will actually exist in the "WORLD" at this time and that all their Intialization
* code has been run
*/
/atom/proc/LateInitialize()
return
// Put your AddComponent() calls here
/// Put your AddComponent() calls here
/atom/proc/ComponentInitialize()
return
/**
* Top level of the destroy chain for most atoms
*
* Cleans up the following:
* * Removes alternate apperances from huds that see them
* * qdels the reagent holder from atoms if it exists
* * clears the orbiters list
* * clears overlays and priority overlays
* * clears the light object
*/
/atom/Destroy()
if(alternate_appearances)
for(var/K in alternate_appearances)
@@ -127,6 +210,7 @@
/atom/proc/handle_ricochet(obj/item/projectile/P)
return
///Can the mover object pass this atom, while heading for the target turf
/atom/proc/CanPass(atom/movable/mover, turf/target)
SHOULD_CALL_PARENT(TRUE)
SHOULD_BE_PURE(TRUE)
@@ -143,6 +227,16 @@
SHOULD_BE_PURE(TRUE)
return !density
/**
* Is this atom currently located on centcom
*
* Specifically, is it on the z level and within the centcom areas
*
* You can also be in a shuttleshuttle during endgame transit
*
* Used in gamemode to identify mobs who have escaped and for some other areas of the code
* who don't want atoms where they shouldn't be
*/
/atom/proc/onCentCom()
var/turf/T = get_turf(src)
if(!T)
@@ -173,6 +267,13 @@
if(T in shuttle_area)
return TRUE
/**
* Is the atom in any of the centcom syndicate areas
*
* Either in the syndie base on centcom, or any of their shuttles
*
* Also used in gamemode code for win conditions
*/
/atom/proc/onSyndieBase()
var/turf/T = get_turf(src)
if(!T)
@@ -186,6 +287,7 @@
return FALSE
///This atom has been hit by a hulkified mob in hulk mode (user)
/atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user)
if(does_attack_animation)
@@ -193,6 +295,18 @@
log_combat(user, src, "punched", "hulk powers")
user.do_attack_animation(src, ATTACK_EFFECT_SMASH)
/**
* Ensure a list of atoms/reagents exists inside this atom
*
* Goes throught he list of passed in parts, if they're reagents, adds them to our reagent holder
* creating the reagent holder if it exists.
*
* If the part is a moveable atom and the previous location of the item was a mob/living,
* it calls the inventory handler transferItemToLoc for that mob/living and transfers the part
* to this atom
*
* Otherwise it simply forceMoves the atom into this atom
*/
/atom/proc/CheckParts(list/parts_list)
for(var/A in parts_list)
if(istype(A, /datum/reagent))
@@ -208,65 +322,91 @@
else
M.forceMove(src)
//common name
///Hook for multiz???
/atom/proc/update_multiz(prune_on_fail = FALSE)
return FALSE
///Take air from the passed in gas mixture datum
/atom/proc/assume_air(datum/gas_mixture/giver)
qdel(giver)
return null
///Remove air from this atom
/atom/proc/remove_air(amount)
return null
///Return the current air environment in this atom
/atom/proc/return_air()
if(loc)
return loc.return_air()
else
return null
///Return the air if we can analyze it
///Check if this atoms eye is still alive (probably)
/atom/proc/check_eye(mob/user)
return
/atom/proc/Bumped(atom/movable/AM)
set waitfor = FALSE
// Convenience procs to see if a container is open for chemistry handling
/// Convenience proc to see if a container is open for chemistry handling
/atom/proc/is_open_container()
return is_refillable() && is_drainable()
/// Is this atom injectable into other atoms
/atom/proc/is_injectable(mob/user, allowmobs = TRUE)
return reagents && (reagents.flags & (INJECTABLE | REFILLABLE))
/// Can we draw from this atom with an injectable atom
/atom/proc/is_drawable(mob/user, allowmobs = TRUE)
return reagents && (reagents.flags & (DRAWABLE | DRAINABLE))
/// Can this atoms reagents be refilled
/atom/proc/is_refillable()
return reagents && (reagents.flags & REFILLABLE)
/// Is this atom drainable of reagents
/atom/proc/is_drainable()
return reagents && (reagents.flags & DRAINABLE)
/// Are you allowed to drop this atom
/atom/proc/AllowDrop()
return FALSE
/atom/proc/CheckExit()
return 1
///Is this atom within 1 tile of another atom
/atom/proc/HasProximity(atom/movable/AM as mob|obj)
return
/**
* React to an EMP of the given severity
*
* Default behaviour is to send the COMSIG_ATOM_EMP_ACT signal
*
* If the signal does not return protection, and there are attached wires then we call
* emp_pulse() on the wires
*
* We then return the protection value
*/
/atom/proc/emp_act(severity)
var/protection = SEND_SIGNAL(src, COMSIG_ATOM_EMP_ACT, severity)
if(!(protection & EMP_PROTECT_WIRES) && istype(wires))
wires.emp_pulse()
return protection // Pass the protection value collected here upwards
/**
* React to a hit by a projectile object
*
* Default behaviour is to send the COMSIG_ATOM_BULLET_ACT and then call on_hit() on the projectile
*/
/atom/proc/bullet_act(obj/item/projectile/P, def_zone)
SEND_SIGNAL(src, COMSIG_ATOM_BULLET_ACT, P, def_zone)
. = P.on_hit(src, 0, def_zone)
///Return true if we're inside the passed in atom
/atom/proc/in_contents_of(container)//can take class or object instance as argument
if(ispath(container))
if(istype(src.loc, container))
@@ -275,6 +415,12 @@
return TRUE
return FALSE
/**
* Get the name of this object for examine
*
* You can override what is returned from this proc by registering to listen for the
* COMSIG_ATOM_GET_EXAMINE_NAME signal
*/
/atom/proc/get_examine_name(mob/user)
. = "\a [src]"
var/list/override = list(gender == PLURAL ? "some" : "a", " ", "[name]")
@@ -284,9 +430,18 @@
if(SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override) & COMPONENT_EXNAME_CHANGED)
. = override.Join("")
///Generate the full examine string of this atom (including icon for goonchat)
/atom/proc/get_examine_string(mob/user, thats = FALSE)
return "[icon2html(src, user)] [thats? "That's ":""][get_examine_name(user)]"
/**
* Called when a mob examines (shift click or verb) this atom
*
* Default behaviour is to get the name and icon of the object and it's reagents where
* the TRANSPARENT flag is set on the reagents holder
*
* Produces a signal COMSIG_PARENT_EXAMINE
*/
/atom/proc/examine(mob/user)
. = list("[get_examine_string(user, TRUE)].")
@@ -315,23 +470,41 @@
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .)
/**
* An atom we are buckled or is contained within us has tried to move
*
* Default behaviour is to send a warning that the user can't move while buckled as long
* as the buckle_message_cooldown has expired (50 ticks)
*/
/atom/proc/relaymove(mob/user)
if(buckle_message_cooldown <= world.time)
buckle_message_cooldown = world.time + 50
to_chat(user, "<span class='warning'>You can't move while buckled to [src]!</span>")
return
/// Return true if this atoms contents should not have ex_act called on ex_act
/atom/proc/prevent_content_explosion()
return FALSE
/// Handle what happens when your contents are exploded by a bomb
/atom/proc/contents_explosion(severity, target)
return //For handling the effects of explosions on contents that would not normally be effected
/**
* React to being hit by an explosion
*
* Default behaviour is to call contents_explosion() and send the COMSIG_ATOM_EX_ACT signal
*/
/atom/proc/ex_act(severity, target)
set waitfor = FALSE
contents_explosion(severity, target)
SEND_SIGNAL(src, COMSIG_ATOM_EX_ACT, severity, target)
/**
* React to a hit by a blob objecd
*
* default behaviour is to send the COMSIG_ATOM_BLOB_ACT signal
*/
/atom/proc/blob_act(obj/structure/blob/B)
SEND_SIGNAL(src, COMSIG_ATOM_BLOB_ACT, B)
return
@@ -340,23 +513,40 @@
SEND_SIGNAL(src, COMSIG_ATOM_FIRE_ACT, exposed_temperature, exposed_volume)
return
/**
* React to being hit by a thrown object
*
* Default behaviour is to call hitby_react() on ourselves after 2 seconds if we are dense
* and under normal gravity.
*
* Im not sure why this the case, maybe to prevent lots of hitby's if the thrown object is
* deleted shortly after hitting something (during explosions or other massive events that
* throw lots of items around - singularity being a notable example)
*/
/atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
if(density && !has_gravity(AM)) //thrown stuff bounces off dense stuff in no grav, unless the thrown stuff ends up inside what it hit(embedding, bola, etc...).
addtimer(CALLBACK(src, .proc/hitby_react, AM), 2)
/**
* We have have actually hit the passed in atom
*
* Default behaviour is to move back from the item that hit us
*/
/atom/proc/hitby_react(atom/movable/AM)
if(AM && isturf(AM.loc))
step(AM, turn(AM.dir, 180))
///Handle the atom being slipped over
/atom/proc/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube, paralyze, force_drop)
return
//returns the mob's dna info as a list, to be inserted in an object's blood_DNA list
///returns the mob's dna info as a list, to be inserted in an object's blood_DNA list
/mob/living/proc/get_blood_dna_list()
if(get_blood_id() != /datum/reagent/blood)
return
return list("ANIMAL DNA" = "Y-")
///Get the mobs dna list
/mob/living/carbon/get_blood_dna_list()
if(get_blood_id() != /datum/reagent/blood)
return
@@ -373,7 +563,7 @@
/mob/living/silicon/get_blood_dna_list()
return list("MOTOR OIL" = "SAE 5W-30") //just a little flavor text.
//to add a mob's dna info into an object's blood_DNA list.
///to add a mob's dna info into an object's blood_dna list.
/atom/proc/transfer_mob_blood_dna(mob/living/L)
// Returns 0 if we have that blood already
var/new_blood_dna = L.get_blood_dna_list()
@@ -385,58 +575,120 @@
return FALSE
return TRUE
//to add blood from a mob onto something, and transfer their dna info
///to add blood from a mob onto something, and transfer their dna info
/atom/proc/add_mob_blood(mob/living/M)
var/list/blood_dna = M.get_blood_dna_list()
if(!blood_dna)
return FALSE
return add_blood_DNA(blood_dna)
///wash cream off this object
///
///(for the love of space jesus please make this a component)
/atom/proc/wash_cream()
return TRUE
///Is this atom in space
/atom/proc/isinspace()
if(isspaceturf(get_turf(src)))
return TRUE
else
return FALSE
///Called when gravity returns after floating I think
/atom/proc/handle_fall()
return
///Respond to the singularity eating this atom
/atom/proc/singularity_act()
return
/**
* Respond to the singularity pulling on us
*
* Default behaviour is to send COMSIG_ATOM_SING_PULL and return
*/
/atom/proc/singularity_pull(obj/singularity/S, current_size)
SEND_SIGNAL(src, COMSIG_ATOM_SING_PULL, S, current_size)
/**
* Respond to acid being used on our atom
*
* Default behaviour is to send COMSIG_ATOM_ACID_ACT and return
*/
/atom/proc/acid_act(acidpwr, acid_volume)
SEND_SIGNAL(src, COMSIG_ATOM_ACID_ACT, acidpwr, acid_volume)
/**
* Respond to an emag being used on our atom
*
* Default behaviour is to send COMSIG_ATOM_EMAG_ACT and return
*/
/atom/proc/emag_act()
SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
/**
* Respond to a radioactive wave hitting this atom
*
* Default behaviour is to send COMSIG_ATOM_RAD_ACT and return
*/
/atom/proc/rad_act(strength)
SEND_SIGNAL(src, COMSIG_ATOM_RAD_ACT, strength)
/**
* Respond to narsie eating our atom
*
* Default behaviour is to send COMSIG_ATOM_NARSIE_ACT and return
*/
/atom/proc/narsie_act()
SEND_SIGNAL(src, COMSIG_ATOM_NARSIE_ACT)
/**
* Respond to ratvar eating our atom
*
* Default behaviour is to send COMSIG_ATOM_RATVAR_ACT and return
*/
/atom/proc/ratvar_act()
SEND_SIGNAL(src, COMSIG_ATOM_RATVAR_ACT)
///Return the values you get when an RCD eats you?
/atom/proc/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
return FALSE
/**
* Respond to an RCD acting on our item
*
* Default behaviour is to send COMSIG_ATOM_RCD_ACT and return FALSE
*/
/atom/proc/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode)
SEND_SIGNAL(src, COMSIG_ATOM_RCD_ACT, user, the_rcd, passed_mode)
return FALSE
/**
* Implement the behaviour for when a user click drags a storage object to your atom
*
* This behaviour is usually to mass transfer, but this is no longer a used proc as it just
* calls the underyling /datum/component/storage dump act if a component exists
*
* TODO these should be purely component items that intercept the atom clicks higher in the
* call chain
*/
/atom/proc/storage_contents_dump_act(obj/item/storage/src_object, mob/user)
if(GetComponent(/datum/component/storage))
return component_storage_contents_dump_act(src_object, user)
return FALSE
/**
* Implement the behaviour for when a user click drags another storage item to you
*
* In this case we get as many of the tiems from the target items compoent storage and then
* put everything into ourselves (or our storage component)
*
* TODO these should be purely component items that intercept the atom clicks higher in the
* call chain
*/
/atom/proc/component_storage_contents_dump_act(datum/component/storage/src_object, mob/user)
var/list/things = src_object.contents()
var/datum/progressbar/progress = new(user, things.len, src)
@@ -457,38 +709,64 @@
user.active_storage.show_to(user)
return TRUE
///Get the best place to dump the items contained in the source storage item?
/atom/proc/get_dumping_location(obj/item/storage/source,mob/user)
return null
//This proc is called on the location of an atom when the atom is Destroy()'d
/**
* This proc is called when an atom in our contents has it's Destroy() called
*
* Default behaviour is to simply send COMSIG_ATOM_CONTENTS_DEL
*/
/atom/proc/handle_atom_del(atom/A)
SEND_SIGNAL(src, COMSIG_ATOM_CONTENTS_DEL, A)
//called when the turf the atom resides on is ChangeTurfed
/**
* called when the turf the atom resides on is ChangeTurfed
*
* Default behaviour is to loop through atom contents and call their HandleTurfChange() proc
*/
/atom/proc/HandleTurfChange(turf/T)
for(var/a in src)
var/atom/A = a
A.HandleTurfChange(T)
//the vision impairment to give to the mob whose perspective is set to that atom (e.g. an unfocused camera giving you an impaired vision when looking through it)
/**
* the vision impairment to give to the mob whose perspective is set to that atom
*
* (e.g. an unfocused camera giving you an impaired vision when looking through it)
*/
/atom/proc/get_remote_view_fullscreens(mob/user)
return
//the sight changes to give to the mob whose perspective is set to that atom (e.g. A mob with nightvision loses its nightvision while looking through a normal camera)
/**
* the sight changes to give to the mob whose perspective is set to that atom
*
* (e.g. A mob with nightvision loses its nightvision while looking through a normal camera)
*/
/atom/proc/update_remote_sight(mob/living/user)
return
//Hook for running code when a dir change occurs
/**
* Hook for running code when a dir change occurs
*
* Not recommended to use, listen for the COMSIG_ATOM_DIR_CHANGE signal instead (sent by this proc)
*/
/atom/proc/setDir(newdir)
SHOULD_CALL_PARENT(TRUE)
SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, newdir)
dir = newdir
///Handle melee attack by a mech
/atom/proc/mech_melee_attack(obj/mecha/M)
return
//If a mob logouts/logins in side of an object you can use this proc
/**
* Called when the atom log's in or out
*
* Default behaviour is to call on_log on the location this atom is in
*/
/atom/proc/on_log(login)
if(loc)
loc.on_log(login)
@@ -502,9 +780,7 @@
*/
/*
Adds an instance of colour_type to the atom's atom_colours list
*/
///Adds an instance of colour_type to the atom's atom_colours list
/atom/proc/add_atom_colour(coloration, colour_priority)
if(!atom_colours || !atom_colours.len)
atom_colours = list()
@@ -517,9 +793,7 @@
update_atom_colour()
/*
Removes an instance of colour_type from the atom's atom_colours list
*/
///Removes an instance of colour_type from the atom's atom_colours list
/atom/proc/remove_atom_colour(colour_priority, coloration)
if(!atom_colours)
atom_colours = list()
@@ -532,10 +806,7 @@
update_atom_colour()
/*
Resets the atom's color to null, and then sets it to the highest priority
colour available
*/
///Resets the atom's color to null, and then sets it to the highest priority colour available
/atom/proc/update_atom_colour()
if(!atom_colours)
atom_colours = list()
@@ -551,6 +822,17 @@
color = C
return
/**
* call back when a var is edited on this atom
*
* Can be used to implement special handling of vars
*
* At the atom level, if you edit a var named "color" it will add the atom colour with
* admin level priority to the atom colours list
*
* Also, if GLOB.Debug2 is FALSE, it sets the ADMIN_SPAWNED_1 flag on flags_1, which signifies
* the object has been admin edited
*/
/atom/vv_edit_var(var_name, var_value)
if(!GLOB.Debug2)
flags_1 |= ADMIN_SPAWNED_1
@@ -559,6 +841,11 @@
if("color")
add_atom_colour(color, ADMIN_COLOUR_PRIORITY)
/**
* Return the markup to for the dropdown list for the VV panel for this atom
*
* Override in subtypes to add custom VV handling in the VV panel
*/
/atom/vv_get_dropdown()
. = ..()
. += "---"
@@ -570,29 +857,53 @@
.["Trigger EM pulse"] = "?_src_=vars;[HrefToken()];emp=[REF(src)]"
.["Trigger explosion"] = "?_src_=vars;[HrefToken()];explode=[REF(src)]"
///Where atoms should drop if taken from this atom
/atom/proc/drop_location()
var/atom/L = loc
if(!L)
return null
return L.AllowDrop() ? L : L.drop_location()
/**
* An atom has entered this atom's contents
*
* Default behaviour is to send the COMSIG_ATOM_ENTERED
*/
/atom/Entered(atom/movable/AM, atom/oldLoc)
SEND_SIGNAL(src, COMSIG_ATOM_ENTERED, AM, oldLoc)
/**
* An atom is attempting to exit this atom's contents
*
* Default behaviour is to send the COMSIG_ATOM_EXIT
*
* Return value should be set to FALSE if the moving atom is unable to leave,
* otherwise leave value the result of the parent call
*/
/atom/Exit(atom/movable/AM, atom/newLoc)
. = ..()
if(SEND_SIGNAL(src, COMSIG_ATOM_EXIT, AM, newLoc) & COMPONENT_ATOM_BLOCK_EXIT)
return FALSE
/**
* An atom has exited this atom's contents
*
* Default behaviour is to send the COMSIG_ATOM_EXITED
*/
/atom/Exited(atom/movable/AM, atom/newLoc)
SEND_SIGNAL(src, COMSIG_ATOM_EXITED, AM, newLoc)
///Return atom temperature
/atom/proc/return_temperature()
return
// Tool behavior procedure. Redirects to tool-specific procs by default.
// You can override it to catch all tool interactions, for use in complex deconstruction procs.
// Just don't forget to return ..() in the end.
/**
*Tool behavior procedure. Redirects to tool-specific procs by default.
*
* You can override it to catch all tool interactions, for use in complex deconstruction procs.
*
* Must return parent proc ..() in the end if overridden
*/
/atom/proc/tool_act(mob/living/user, obj/item/I, tool_type)
switch(tool_type)
if(TOOL_CROWBAR)
@@ -610,13 +921,18 @@
if(TOOL_ANALYZER)
return analyzer_act(user, I)
// Tool-specific behavior procs. To be overridden in subtypes.
//! Tool-specific behavior procs. To be overridden in subtypes.
///
///Crowbar act
/atom/proc/crowbar_act(mob/living/user, obj/item/I)
return
///Multitool act
/atom/proc/multitool_act(mob/living/user, obj/item/I)
return
///Check if the multitool has an item in it's data buffer
/atom/proc/multitool_check_buffer(user, obj/item/I, silent = FALSE)
if(!istype(I, /obj/item/multitool))
if(user && !silent)
@@ -624,29 +940,35 @@
return FALSE
return TRUE
///Screwdriver act
/atom/proc/screwdriver_act(mob/living/user, obj/item/I)
SEND_SIGNAL(src, COMSIG_ATOM_SCREWDRIVER_ACT, user, I)
///Wrench act
/atom/proc/wrench_act(mob/living/user, obj/item/I)
return
///Wirecutter act
/atom/proc/wirecutter_act(mob/living/user, obj/item/I)
return
///Welder act
/atom/proc/welder_act(mob/living/user, obj/item/I)
return
///Analyzer act
/atom/proc/analyzer_act(mob/living/user, obj/item/I)
return
///Generate a tag for this atom
/atom/proc/GenerateTag()
return
///Connect this atom to a shuttle
/atom/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
return
// Generic logging helper
/// Generic logging helper
/atom/proc/log_message(message, message_type, color=null, log_globally=TRUE)
if(!log_globally)
return
@@ -693,13 +1015,13 @@
stack_trace("Invalid individual logging type: [message_type]. Defaulting to [LOG_GAME] (LOG_GAME).")
log_game(log_text)
// Helper for logging chat messages or other logs with arbitrary inputs (e.g. announcements)
/// Helper for logging chat messages or other logs with arbitrary inputs (e.g. announcements)
/atom/proc/log_talk(message, message_type, tag=null, log_globally=TRUE, forced_by=null)
var/prefix = tag ? "([tag]) " : ""
var/suffix = forced_by ? " FORCED by [forced_by]" : ""
log_message("[prefix]\"[message]\"[suffix]", message_type, log_globally=log_globally)
// Helper for logging of messages with only one sender and receiver
/// Helper for logging of messages with only one sender and receiver
/proc/log_directed_talk(atom/source, atom/target, message, message_type, tag)
if(!tag)
stack_trace("Unspecified tag for private message")
@@ -709,15 +1031,15 @@
if(source != target)
target.log_talk(message, message_type, tag="[tag] from [key_name(source)]", log_globally=FALSE)
/*
Proc for attack log creation, because really why not
1 argument is the actor performing the action
2 argument is the target of the action
3 is a verb describing the action (e.g. punched, throwed, kicked, etc.)
4 is a tool with which the action was made (usually an item)
5 is any additional text, which will be appended to the rest of the log line
*/
/**
* Log a combat message in the attack log
*
* 1 argument is the actor performing the action
* 2 argument is the target of the action
* 3 is a verb describing the action (e.g. punched, throwed, kicked, etc.)
* 4 is a tool with which the action was made (usually an item)
* 5 is any additional text, which will be appended to the rest of the log line
*/
/proc/log_combat(atom/user, atom/target, what_done, atom/object=null, addition=null)
var/ssource = key_name(user)
var/starget = key_name(target)
@@ -741,7 +1063,6 @@ Proc for attack log creation, because really why not
var/reverse_message = "has been [what_done] by [ssource][postfix]"
target.log_message(reverse_message, LOG_ATTACK, color="orange", log_globally=FALSE)
// Filter stuff
/atom/movable/proc/add_filter(name,priority,list/params)
if(!filter_data)
filter_data = list()

View File

@@ -1,6 +1,6 @@
//the essential proc to call when an obj must receive damage of any kind.
/obj/proc/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir, armour_penetration = 0)
///the essential proc to call when an obj must receive damage of any kind.
/obj/proc/take_damage(damage_amount, damage_type = BRUTE, damage_flag = "", sound_effect = TRUE, attack_dir, armour_penetration = 0)
if(QDELETED(src))
stack_trace("[src] taking damage after deletion")
return
@@ -21,7 +21,7 @@
if(obj_integrity <= integrity_failure)
obj_break(damage_flag)
//returns the damage value of the attack after processing the obj's various armor protections
///returns the damage value of the attack after processing the obj's various armor protections
/obj/proc/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir, armour_penetration = 0)
switch(damage_type)
if(BRUTE)
@@ -35,7 +35,7 @@
armor_protection = clamp(armor_protection - armour_penetration, min(armor_protection, 0), 100)
return round(damage_amount * (100 - armor_protection)*0.01, DAMAGE_PRECISION)
//the sound played when the obj is damaged.
///the sound played when the obj is damaged.
/obj/proc/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
switch(damage_type)
if(BRUTE)
@@ -80,6 +80,7 @@
if(!QDELETED(src)) //Bullet on_hit effect might have already destroyed this object
take_damage(P.damage, P.damage_type, P.flag, 0, turn(P.dir, 180), P.armour_penetration)
///Called to get the damage that hulks will deal to the obj.
/obj/proc/hulk_damage()
return 150 //the damage hulks do on punches to this object, is affected by melee armor
@@ -175,7 +176,7 @@
GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/effects/effects.dmi', "acid"))
//the obj's reaction when touched by acid
///the obj's reaction when touched by acid
/obj/acid_act(acidpwr, acid_volume)
if(!(resistance_flags & UNACIDABLE) && acid_volume)
@@ -187,7 +188,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
acid_level = min(acid_level + acidpwr * acid_volume, acid_cap)
return 1
//the proc called by the acid subsystem to process the acid that's on the obj
///the proc called by the acid subsystem to process the acid that's on the obj
/obj/proc/acid_processing()
. = 1
if(!(resistance_flags & ACID_PROOF))
@@ -202,13 +203,14 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
if(!acid_level)
return 0
//called when the obj is destroyed by acid.
///called when the obj is destroyed by acid.
/obj/proc/acid_melt()
SSacid.processing -= src
deconstruct(FALSE)
//// FIRE
///Called when the obj is exposed to fire.
/obj/fire_act(exposed_temperature, exposed_volume)
if(isturf(loc))
var/turf/T = loc
@@ -222,18 +224,20 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
add_overlay(GLOB.fire_overlay, TRUE)
return 1
//called when the obj is destroyed by fire
///called when the obj is destroyed by fire
/obj/proc/burn()
if(resistance_flags & ON_FIRE)
SSfire_burning.processing -= src
deconstruct(FALSE)
///Called when the obj is no longer on fire.
/obj/proc/extinguish()
if(resistance_flags & ON_FIRE)
resistance_flags &= ~ON_FIRE
cut_overlay(GLOB.fire_overlay, TRUE)
SSfire_burning.processing -= src
///Called when the obj is hit by a tesla bolt.
/obj/proc/tesla_act(power, tesla_flags, shocked_targets)
obj_flags |= BEING_SHOCKED
var/power_bounced = power / 2
@@ -241,7 +245,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
addtimer(CALLBACK(src, .proc/reset_shocked), 10)
//The surgeon general warns that being buckled to certain objects receiving powerful shocks is greatly hazardous to your health
//Only tesla coils and grounding rods currently call this because mobs are already targeted over all other objects, but this might be useful for more things later.
///Only tesla coils and grounding rods currently call this because mobs are already targeted over all other objects, but this might be useful for more things later.
/obj/proc/tesla_buckle_check(var/strength)
if(has_buckled_mobs())
for(var/m in buckled_mobs)
@@ -251,16 +255,16 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
/obj/proc/reset_shocked()
obj_flags &= ~BEING_SHOCKED
//the obj is deconstructed into pieces, whether through careful disassembly or when destroyed.
///the obj is deconstructed into pieces, whether through careful disassembly or when destroyed.
/obj/proc/deconstruct(disassembled = TRUE)
SEND_SIGNAL(src, COMSIG_OBJ_DECONSTRUCT, disassembled)
qdel(src)
//what happens when the obj's health is below integrity_failure level.
///called after the obj takes damage and integrity is below integrity_failure level
/obj/proc/obj_break(damage_flag)
return
//what happens when the obj's integrity reaches zero.
///what happens when the obj's integrity reaches zero.
/obj/proc/obj_destruction(damage_flag)
if(damage_flag == "acid")
acid_melt()
@@ -269,8 +273,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
else
deconstruct(FALSE)
//changes max_integrity while retaining current health percentage
//returns TRUE if the obj broke, FALSE otherwise
///changes max_integrity while retaining current health percentage, returns TRUE if the obj got broken.
/obj/proc/modify_max_integrity(new_max, can_break = TRUE, damage_type = BRUTE, new_failure_integrity = null)
var/current_integrity = obj_integrity
var/current_max = max_integrity
@@ -290,6 +293,6 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
return TRUE
return FALSE
//returns how much the object blocks an explosion
///returns how much the object blocks an explosion. Used by subtypes.
/obj/proc/GetExplosionBlock()
CRASH("Unimplemented GetExplosionBlock()")

View File

@@ -7,8 +7,22 @@ GLOBAL_VAR(restart_counter)
if (dll)
call(dll, "debug_initialize")()
//This happens after the Master subsystem new(s) (it's a global datum)
//So subsystems globals exist, but are not initialised
/**
* World creation
*
* Here is where a round itself is actually begun and setup, lots of important config changes happen here
* * db connection setup
* * config loaded from files
* * loads admins
* * Sets up the dynamic menu system
* * and most importantly, calls initialize on the master subsystem, starting the game loop that causes the rest of the game to begin processing and setting up
*
* Note this happens after the Master subsystem is created (as that is a global datum), this means all the subsystems exist,
* but they have not been Initialized at this point, only their New proc has run
*
* Nothing happens until something moves. ~Albert Einstein
*
*/
/world/New()
enable_debugger() //This does nothing if you aren't trying to debug
log_world("World loaded at [time_stamp()]!")

View File

@@ -6,13 +6,20 @@
////////////////
//ADMIN THINGS//
////////////////
///Contains admin info. Null if client is not an admin.
var/datum/admins/holder = null
var/datum/click_intercept = null // Needs to implement InterceptClickOn(user,params,atom) proc
var/AI_Interact = 0
///Needs to implement InterceptClickOn(user,params,atom) proc
var/datum/click_intercept = null
///Used for admin AI interaction
var/AI_Interact = FALSE
var/ban_cache = null //Used to cache this client's bans to save on DB queries
var/last_message = "" //Contains the last message sent by this client - used to protect against copy-paste spamming.
var/last_message_count = 0 //contins a number of how many times a message identical to last_message was sent.
///Used to cache this client's bans to save on DB queries
var/ban_cache = null
///Contains the last message sent by this client - used to protect against copy-paste spamming.
var/last_message = ""
///contins a number of how many times a message identical to last_message was sent.
var/last_message_count = 0
///Internal counter for clients sending irc relay messages via ahelp to prevent spamming. Set to a number every time an admin reply is sent, decremented for every client send.
var/ircreplyamount = 0
var/total_message_count = 0 //How many messages sent in the last 10 seconds
@@ -21,10 +28,14 @@
/////////
//OTHER//
/////////
///Player preferences datum for the client
var/datum/preferences/prefs = null
///last turn of the controlled mob, I think this is only used by mechs?
var/last_turn = 0
///Move delay of controlled mob, related to input handling
var/move_delay = 0
var/area = null
///Current area of the controlled mob
var/area = null
var/cryo_warned = -3000 //when was the last time we warned them about not cryoing without an ahelp, set to -5 minutes so that rounstart cryo still warns
/////////
@@ -34,8 +45,10 @@
///////////////
//SOUND STUFF//
///////////////
var/ambience_playing= null
var/played = 0
///Currently playing ambience sound
var/ambience_playing = null
///Whether an ambience sound has been played and one shouldn't be played again, unset by a callback
var/played = FALSE
////////////
//SECURITY//
////////////
@@ -45,49 +58,73 @@
////////////////////////////////////
//things that require the database//
////////////////////////////////////
var/player_age = -1 //Used to determine how old the account is - in days.
var/player_join_date = null //Date that this account was first seen in the server
var/related_accounts_ip = "Requires database" //So admins know why it isn't working - Used to determine what other accounts previously logged in from this ip
var/related_accounts_cid = "Requires database" //So admins know why it isn't working - Used to determine what other accounts previously logged in from this computer id
var/account_join_date = null //Date of byond account creation in ISO 8601 format
var/account_age = -1 //Age of byond account in days
///Used to determine how old the account is - in days.
var/player_age = -1
///Date that this account was first seen in the server
var/player_join_date = null
///So admins know why it isn't working - Used to determine what other accounts previously logged in from this ip
var/related_accounts_ip = "Requires database"
///So admins know why it isn't working - Used to determine what other accounts previously logged in from this computer id
var/related_accounts_cid = "Requires database"
///Date of byond account creation in ISO 8601 format
var/account_join_date = null
///Age of byond account in days
var/account_age = -1
preload_rsc = PRELOAD_RSC
var/obj/screen/click_catcher/void
//These two vars are used to make a special mouse cursor, with a unique icon for clicking
///used to make a special mouse cursor, this one for mouse up icon
var/mouse_up_icon = null
///used to make a special mouse cursor, this one for mouse up icon
var/mouse_down_icon = null
///Used for ip intel checking to identify evaders, disabled because of issues with traffic
var/ip_intel = "Disabled"
//datum that controls the displaying and hiding of tooltips
///datum that controls the displaying and hiding of tooltips
var/datum/tooltip/tooltips
///Last ping of the client
var/lastping = 0
///Average ping of the client
var/avgping = 0
var/connection_time //world.time they connected
var/connection_realtime //world.realtime they connected
var/connection_timeofday //world.timeofday they connected
///world.time they connected
var/connection_time
///world.realtime they connected
var/connection_realtime
///world.timeofday they connected
var/connection_timeofday
///If the client is currently in player preferences
var/inprefs = FALSE
///Used for limiting the rate of topic sends by the client to avoid abuse
var/list/topiclimiter
///Used for limiting the rate of clicks sends by the client to avoid abuse
var/list/clicklimiter
///goonchat chatoutput of the client
var/datum/chatOutput/chatOutput
var/list/credits //lazy list of all credit object bound to this client
///lazy list of all credit object bound to this client
var/list/credits
var/datum/player_details/player_details //these persist between logins/logouts during the same round.
///these persist between logins/logouts during the same round.
var/datum/player_details/player_details
var/list/char_render_holders //Should only be a key-value list of north/south/east/west = obj/screen.
///Should only be a key-value list of north/south/east/west = obj/screen.
var/list/char_render_holders
///LibVG encoding
var/encoding = "1252"
var/encoding = "1252" // yogs - LibVG
var/list/seen_messages // Messages currently seen by this client
///Messages currently seen by this client
var/list/seen_messages
var/list/spell_tabs = list()
//rate limiting for the crew manifest
///rate limiting for the crew manifest
var/crew_manifest_delay
var/datum/viewData/view_size

View File

@@ -5,13 +5,26 @@ For the main html chat area
//Precaching a bunch of shit
GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of icons for the browser output
//On client, created on login
/// Should match the value set in the browser js
#define MAX_COOKIE_LENGTH 5
/**
* The chatOutput datum exists to handle the goonchat browser.
* On client, created on Client/New()
*/
/datum/chatOutput
var/client/owner //client ref
var/loaded = FALSE // Has the client loaded the browser output area?
var/list/messageQueue //If they haven't loaded chat, this is where messages will go until they do
var/cookieSent = FALSE // Has the client sent a cookie for analysis
var/broken = FALSE
/// The client that owns us.
var/client/owner
/// How many times client data has been checked
var/total_checks = 0
/// When to next clear the client data checks counter
var/next_time_to_clear = 0
/// Has the client loaded the browser output area?
var/loaded = FALSE
/// If they haven't loaded chat, this is where messages will go until they do
var/list/messageQueue
var/cookieSent = FALSE // Has the client sent a cookie for analysis
var/broken = FALSE
var/list/connectionHistory //Contains the connection history passed from chat cookie
var/adminMusicVolume = 25 //This is for the Play Global Sound verb
@@ -20,13 +33,18 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
messageQueue = list()
connectionHistory = list()
/**
* start: Tries to load the chat browser
* Aborts if a problem is encountered.
* Async because this is called from Client/New.
*/
/datum/chatOutput/proc/start()
set waitfor = FALSE
//Check for existing chat
if(!owner)
return FALSE
if(!winexists(owner, "browseroutput")) // Oh goddamnit.
set waitfor = FALSE
broken = TRUE
message_admins("Couldn't start chat for [key_name_admin(owner)]!")
. = FALSE
@@ -41,6 +59,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
return TRUE
/// Loads goonchat and sends assets.
/datum/chatOutput/proc/load()
set waitfor = FALSE
if(!owner)
@@ -51,6 +70,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
owner << browse(file('code/modules/goonchat/browserassets/html/browserOutput.html'), "window=browseroutput")
/// Interprets input from the client. Will send data back if required.
/datum/chatOutput/Topic(href, list/href_list)
if(usr.client != owner)
return TRUE
@@ -106,7 +126,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
ehjax_send(data = data)
//Called on chat output done-loading by JS.
/// Called on chat output done-loading by JS.
/datum/chatOutput/proc/doneLoading()
if(loaded)
return
@@ -126,15 +146,26 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
//do not convert to to_chat()
SEND_TEXT(owner, "<span class=\"userdanger\">Failed to load fancy chat, reverting to old chat. Certain features won't work.</span>")
/// Hides the standard output and makes the browser visible.
/datum/chatOutput/proc/showChat()
winset(owner, "output", "is-visible=false")
winset(owner, "browseroutput", "is-disabled=false;is-visible=true")
/// Sends json encoded data to the browser.
/datum/chatOutput/proc/ehjax_send(client/C = owner, window = "browseroutput", data)
if(islist(data))
data = json_encode(data)
C << output("[data]", "[window]:ehjaxCallback")
/**
* Sends music data to the browser. If enabled by the browser, it will start playing.
* Arguments:
* music must be a https adress.
* extra_data is a list. The keys "pitch", "start" and "end" are used.
** "pitch" determines the playback rate
** "start" determines the start time of the sound
** "end" determines when the musics stops playing
*/
/datum/chatOutput/proc/sendMusic(music, list/extra_data)
if(!findtext(music, GLOB.is_http_protocol))
return
@@ -147,14 +178,16 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
ehjax_send(data = music_data)
/// Stops music playing throw the browser.
/datum/chatOutput/proc/stopMusic()
ehjax_send(data = "stopMusic")
/// Setter for adminMusicVolume. Sanitizes the value to between 0 and 100.
/datum/chatOutput/proc/setMusicVolume(volume = "")
if(volume)
adminMusicVolume = clamp(text2num(volume), 0, 100)
//Sends client connection details to the chat to handle and save
/// Sends client connection details to the chat to handle and save
/datum/chatOutput/proc/sendClientData()
//Get dem deets
var/list/deets = list("clientData" = list())
@@ -164,7 +197,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
var/data = json_encode(deets)
ehjax_send(data = data)
//Called by client, sent data to investigate (cookie history so far)
/// Called by client, sent data to investigate (cookie history so far)
/datum/chatOutput/proc/analyzeClientData(cookie = "")
if(!cookie)
return
@@ -190,15 +223,15 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
cookieSent = TRUE
//Called by js client every 60 seconds
/// Called by js client every 60 seconds
/datum/chatOutput/proc/ping()
return "pong"
//Called by js client on js error
/// Called by js client on js error
/datum/chatOutput/proc/debug(error)
log_world("\[[time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")]\] Client: [(src.owner.key ? src.owner.key : src.owner)] triggered JS error: [error]")
//Global chat procs
/// Global chat proc. to_chat_immediate will circumvent SSchat and send data as soon as possible.
/proc/to_chat_immediate(target, message, handle_whitespace = TRUE, confidential = FALSE)
if(!target || !message)
return
@@ -253,14 +286,17 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
// url_encode it TWICE, this way any UTF-8 characters are able to be decoded by the Javascript.
C << output(url_encode(url_encode(message)), "browseroutput:output")
/// Sends a text message to the target.
/proc/to_chat(target, message, handle_whitespace = TRUE, confidential = FALSE)
if(Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized)
to_chat_immediate(target, message, handle_whitespace, confidential)
return
SSchat.queue(target, message, handle_whitespace, confidential)
/datum/chatOutput/proc/swaptolightmode() //Dark mode light mode stuff. Yell at KMC if this breaks! (See darkmode.dm for documentation)
/// Dark mode light mode stuff. Yell at KMC if this breaks! (See darkmode.dm for documentation)
/datum/chatOutput/proc/swaptolightmode()
owner.force_white_theme()
/// Light mode stuff. (See darkmode.dm for documentation)
/datum/chatOutput/proc/swaptodarkmode()
owner.force_dark_theme()

View File

@@ -4,7 +4,11 @@
///////////////
//Drone verbs that appear in the Drone tab and on buttons
/**
* Echoes drone laws to the user
*
* See [/mob/living/simple_animal/drone/var/laws]
*/
/mob/living/simple_animal/drone/verb/check_laws()
set category = "Drone"
set name = "Check Laws"
@@ -12,6 +16,17 @@
to_chat(src, "<b>Drone Laws</b>")
to_chat(src, laws)
/**
* Creates an alert to drones in the same network
*
* Prompts user for alert level of:
* * Low
* * Medium
* * High
* * Critical
*
* Attaches area name to message
*/
/mob/living/simple_animal/drone/verb/drone_ping()
set category = "Drone"
set name = "Drone ping"

View File

@@ -1,3 +1,26 @@
/**
* Run when a client is put in this mob or reconnets to byond and their client was on this mob
*
* Things it does:
* * Adds player to player_list
* * sets lastKnownIP
* * sets computer_id
* * logs the login
* * tells the world to update it's status (for player count)
* * create mob huds for the mob if needed
* * reset next_move to 1
* * parent call
* * if the client exists set the perspective to the mob loc
* * call on_log on the loc (sigh)
* * reload the huds for the mob
* * reload all full screen huds attached to this mob
* * load any global alternate apperances
* * sync the mind datum via sync_mind()
* * call any client login callbacks that exist
* * grant any actions the mob has to the client
* * calls [auto_deadmin_on_login](mob.html#proc/auto_deadmin_on_login)
* * send signal COMSIG_MOB_CLIENT_LOGIN
*/
/mob/Login()
if(!client)
return FALSE
@@ -58,6 +81,17 @@
log_message("Client [key_name(src)] has taken ownership of mob [src]([src.type])", LOG_OWNERSHIP)
SEND_SIGNAL(src, COMSIG_MOB_CLIENT_LOGIN, client)
/**
* Checks if the attached client is an admin and may deadmin them
*
* Configs:
* * flag/auto_deadmin_players
* * client.prefs?.toggles & DEADMIN_ALWAYS
* * User is antag and flag/auto_deadmin_antagonists or client.prefs?.toggles & DEADMIN_ANTAGONIST
* * or if their job demands a deadminning SSjob.handle_auto_deadmin_roles()
*
* Called from [login](mob.html#proc/Login)
*/
/mob/proc/auto_deadmin_on_login() //return true if they're not an admin at the end.
if(!client?.holder)
return TRUE

View File

@@ -1,3 +1,27 @@
/**
* Delete a mob
*
* Removes mob from the following global lists
* * GLOB.mob_list
* * GLOB.dead_mob_list
* * GLOB.alive_mob_list
* * GLOB.all_clockwork_mobs
* * GLOB.mob_directory
*
* Unsets the focus var
*
* Clears alerts for this mob
*
* Resets all the observers perspectives to the tile this mob is on
*
* qdels any client colours in place on this mob
*
* Ghostizes the client attached to this mob
*
* Parent call
*
* Returns QDEL_HINT_HARDDEL (don't change this)
*/
/mob/Destroy()//This makes sure that mobs with clients/keys are not just deleted from the game.
GLOB.mob_list -= src
GLOB.dead_mob_list -= src
@@ -19,6 +43,24 @@
..()
return QDEL_HINT_HARDDEL
/**
* Intialize a mob
*
* Sends global signal COMSIG_GLOB_MOB_CREATED
*
* Adds to global lists
* * GLOB.mob_list
* * GLOB.mob_directory (by tag)
* * GLOB.dead_mob_list - if mob is dead
* * GLOB.alive_mob_list - if the mob is alive
*
* Other stuff:
* * Sets the mob focus to itself
* * Generates huds
* * If there are any global alternate apperances apply them to this mob
* * set a random nutrition level
* * Intialize the movespeed of the mob
*/
/mob/Initialize()
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_MOB_CREATED, src)
GLOB.mob_list += src
@@ -39,9 +81,20 @@
update_config_movespeed()
update_movespeed(TRUE)
/**
* Generate the tag for this mob
*
* This is simply "mob_"+ a global incrementing counter that goes up for every mob
*/
/mob/GenerateTag()
tag = "mob_[next_mob_id++]"
/**
* Prepare the huds for this atom
*
* Goes through hud_possible list and adds the images to the hud_list variable (if not already
* cached)
*/
/atom/proc/prepare_huds()
hud_list = list()
for(var/hud in hud_possible)
@@ -54,6 +107,9 @@
I.appearance_flags = RESET_COLOR|RESET_TRANSFORM
hud_list[hud] = I
/**
* Some kind of debug verb that gives atmosphere environment details
*/
/mob/proc/Cell()
set category = "Admin"
set hidden = 1
@@ -71,9 +127,15 @@
to_chat(usr, t)
/**
* Return the desc of this mob for a photo
*/
/mob/proc/get_photo_description(obj/item/camera/camera)
return "a ... thing?"
/**
* Show a message to this mob (visual)
*/
/mob/proc/show_message(msg, type, alt_msg, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2)
if(!client)
@@ -104,15 +166,23 @@
else
to_chat(src, msg)
// Show a message to all player mobs who sees this atom
// Show a message to the src mob (if the src is a mob)
// Use for atoms performing visible actions
// message is output to anyone who can see, e.g. "The [src] does something!"
// self_message (optional) is what the src mob sees e.g. "You do something!"
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
// vision_distance (optional) define how many tiles away the message can be seen.
// ignored_mob (optional) doesn't show any message to a given mob if TRUE.
/**
* Generate a visible message from this atom
*
* Show a message to all player mobs who sees this atom
*
* Show a message to the src mob (if the src is a mob)
*
* Use for atoms performing visible actions
*
* message is output to anyone who can see, e.g. "The [src] does something!"
*
* Vars:
* * self_message (optional) is what the src mob sees e.g. "You do something!"
* * blind_message (optional) is what blind people will hear e.g. "You hear something!"
* * vision_distance (optional) define how many tiles away the message can be seen.
* * ignored_mob (optional) doesn't show any message to a given mob if TRUE.
*/
/atom/proc/visible_message(message, self_message, blind_message, vision_distance, list/ignored_mobs)
var/turf/T = get_turf(src)
if(!T)
@@ -147,13 +217,17 @@
M.show_message(msg,1,blind_message,2)
// Show a message to all mobs in earshot of this one
// This would be for audible actions by the src mob
// message is the message output to anyone who can hear.
// self_message (optional) is what the src mob hears.
// deaf_message (optional) is what deaf people will see.
// hearing_distance (optional) is the range, how many tiles away the message can be heard.
/**
* Show a message to all mobs in earshot of this one
*
* This would be for audible actions by the src mob
*
* vars:
* * message is the message output to anyone who can hear.
* * self_message (optional) is what the src mob hears.
* * deaf_message (optional) is what deaf people will see.
* * hearing_distance (optional) is the range, how many tiles away the message can be heard.
*/
/mob/audible_message(message, deaf_message, hearing_distance, self_message)
var/range = 7
if(hearing_distance)
@@ -164,12 +238,16 @@
msg = self_message
M.show_message( msg, 2, deaf_message, 1)
// Show a message to all mobs in earshot of this atom
// Use for objects performing audible actions
// message is the message output to anyone who can hear.
// deaf_message (optional) is what deaf people will see.
// hearing_distance (optional) is the range, how many tiles away the message can be heard.
/**
* Show a message to all mobs in earshot of this atom
*
* Use for objects performing audible actions
*
* vars:
* * message is the message output to anyone who can hear.
* * deaf_message (optional) is what deaf people will see.
* * hearing_distance (optional) is the range, how many tiles away the message can be heard.
*/
/atom/proc/audible_message(message, deaf_message, hearing_distance)
var/range = 7
if(hearing_distance)
@@ -177,16 +255,24 @@
for(var/mob/M in get_hearers_in_view(range, src))
M.show_message( message, 2, deaf_message, 1)
///Get the item on the mob in the storage slot identified by the id passed in
/mob/proc/get_item_by_slot(slot_id)
return null
///Is the mob restrained
/mob/proc/restrained(ignore_grab)
return
///Is the mob incapacitated
/mob/proc/incapacitated(ignore_restraints = FALSE, ignore_grab = FALSE, check_immobilized = FALSE)
return
//This proc is called whenever someone clicks an inventory ui slot.
/**
* This proc is called whenever someone clicks an inventory ui slot.
*
* Mostly tries to put the item into the slot if possible, or call attack hand
* on the item in the slot if the users active hand is empty
*/
/mob/proc/attack_ui(slot)
var/obj/item/W = get_active_held_item()
@@ -202,10 +288,17 @@
return 0
//This is a SAFE proc. Use this instead of equip_to_slot()!
//set qdel_on_fail to have it delete W if it fails to equip
//set disable_warning to disable the 'you are unable to equip that' warning.
//unset redraw_mob to prevent the mob from being redrawn at the end.
/**
* Try to equip an item to a slot on the mob
*
* This is a SAFE proc. Use this instead of equip_to_slot()!
*
* set qdel_on_fail to have it delete W if it fails to equip
*
* set disable_warning to disable the 'you are unable to equip that' warning.
*
* unset redraw_mob to prevent the mob icons from being redrawn at the end.
*/
/mob/proc/equip_to_slot_if_possible(obj/item/W, slot, qdel_on_fail = FALSE, disable_warning = FALSE, redraw_mob = TRUE, bypass_equip_delay_self = FALSE)
if(!istype(W))
return FALSE
@@ -219,18 +312,35 @@
equip_to_slot(W, slot, redraw_mob) //This proc should not ever fail.
return TRUE
//This is an UNSAFE proc. It merely handles the actual job of equipping. All the checks on whether you can or can't equip need to be done before! Use mob_can_equip() for that task.
//In most cases you will want to use equip_to_slot_if_possible()
/**
* Actually equips an item to a slot (UNSAFE)
*
* This is an UNSAFE proc. It merely handles the actual job of equipping. All the checks on
* whether you can or can't equip need to be done before! Use mob_can_equip() for that task.
*
*In most cases you will want to use equip_to_slot_if_possible()
*/
/mob/proc/equip_to_slot(obj/item/W, slot)
return
//This is just a commonly used configuration for the equip_to_slot_if_possible() proc, used to equip people when the round starts and when events happen and such.
//Also bypasses equip delay checks, since the mob isn't actually putting it on.
/**
* Equip an item to the slot or delete
*
* This is just a commonly used configuration for the equip_to_slot_if_possible() proc, used to
* equip people when the round starts and when events happen and such.
*
* Also bypasses equip delay checks, since the mob isn't actually putting it on.
*/
/mob/proc/equip_to_slot_or_del(obj/item/W, slot)
return equip_to_slot_if_possible(W, slot, TRUE, TRUE, FALSE, TRUE)
//puts the item "W" into an appropriate slot in a human's inventory
//returns 0 if it cannot, 1 if successful
/**
* Auto equip the passed in item the appropriate slot based on equipment priority
*
* puts the item "W" into an appropriate slot in a human's inventory
*
* returns 0 if it cannot, 1 if successful
*/
/mob/proc/equip_to_appropriate_slot(obj/item/W)
if(!istype(W))
return 0
@@ -253,9 +363,12 @@
return 1
return 0
// reset_perspective(thing) set the eye to the thing (if it's equal to current default reset to mob perspective)
// reset_perspective() set eye to common default : mob on turf, loc otherwise
/**
* Reset the attached clients perspective (viewpoint)
*
* reset_perspective() set eye to common default : mob on turf, loc otherwise
* reset_perspective(thing) set the eye to the thing (if it's equal to current default reset to mob perspective)
*/
/mob/proc/reset_perspective(atom/A)
if(client)
if(A)
@@ -287,6 +400,7 @@
client.eye = loc
return 1
/// Show the mob's inventory to another mob
/mob/proc/show_inv(mob/user)
return
@@ -300,7 +414,13 @@
var/mob/living/carbon/C = src
C.give()
//mob verbs are faster than object verbs. See https://secure.byond.com/forum/?post=1326139&page=2#comment8198716 for why this isn't atom/verb/examine()
/**
* Examine a mob
*
* mob verbs are faster than object verbs. See
* [this byond forum post](https://secure.byond.com/forum/?post=1326139&page=2#comment8198716)
* for why this isn't atom/verb/examine()
*/
/mob/verb/examinate(atom/A as mob|obj|turf in view()) //It used to be oview(12), but I can't really say why
set name = "Examine"
set category = "IC"
@@ -318,10 +438,19 @@
to_chat(src, result.Join("\n"))
SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A)
//same as above
//note: ghosts can point, this is intended
//visible_message will handle invisibility properly
//overridden here and in /mob/dead/observer for different point span classes and sanity checks
/**
* Point at an atom
*
* mob verbs are faster than object verbs. See
* [this byond forum post](https://secure.byond.com/forum/?post=1326139&page=2#comment8198716)
* for why this isn't atom/verb/pointed()
*
* note: ghosts can point, this is intended
*
* visible_message will handle invisibility properly
*
* overridden here and in /mob/dead/observer for different point span classes and sanity checks
*/
/mob/verb/pointed(atom/A as mob|obj|turf in view())
set name = "Point To"
set category = "Object"
@@ -341,9 +470,11 @@
return TRUE
///Can this mob resist (default FALSE)
/mob/proc/can_resist()
return FALSE //overridden in living.dm
///Spin this mob around it's central axis
/mob/proc/spin(spintime, speed)
set waitfor = 0
var/D = dir
@@ -363,16 +494,23 @@
setDir(D)
spintime -= speed
///Update the pulling hud icon
/mob/proc/update_pull_hud_icon()
if(hud_used)
if(hud_used.pull_icon)
hud_used.pull_icon.update_icon(src)
///Update the resting hud icon
/mob/proc/update_rest_hud_icon()
if(hud_used)
if(hud_used.rest_icon)
hud_used.rest_icon.update_icon(src)
/**
* Verb to activate the object in your held hand
*
* Calls attack self on the item and updates the inventory hud for hands
*/
/mob/verb/mode()
set name = "Activate Held Object"
set category = "Object"
@@ -389,6 +527,11 @@
I.attack_self(src)
update_inv_hands()
/**
* Get the notes of this mob
*
* This actually gets the mind datums notes
*/
/mob/verb/memory()
set name = "Notes"
set category = "IC"
@@ -398,6 +541,9 @@
else
to_chat(src, "You don't have a mind datum for some reason, so you can't look at your notes, if you had any.")
/**
* Add a note to the mind datum
*/
/mob/verb/add_memory(msg as message)
set name = "Add Note"
set category = "IC"
@@ -419,6 +565,13 @@
else
to_chat(src, "You don't have a mind datum for some reason, so you can't add a note to it.")
/**
* Allows you to respawn, abandoning your current mob
*
* This sends you back to the lobby creating a new dead mob
*
* Only works if flag/norespawn is allowed in config
*/
/mob/verb/abandon_mob()
set name = "Respawn"
set category = "OOC"
@@ -453,7 +606,9 @@
return
/**
* Sometimes helps if the user is stuck in another perspective or camera
*/
/mob/verb/cancel_camera()
set name = "Cancel Camera View"
set category = "OOC"
@@ -472,7 +627,13 @@
set hidden = TRUE
set category = null
return
/**
* Topic call back for any mob
*
* * Unset machines if "mach_close" sent
* * refresh the inventory of machines in range if "refresh" sent
* * handles the strip panel equip and unequip as well if "item" sent
*/
/mob/Topic(href, href_list)
if(href_list["mach_close"])
var/t1 = text("window=[href_list["mach_close"]]")
@@ -515,6 +676,9 @@
/mob/proc/stripPanelEquip(obj/item/what, mob/who)
return
/**
* Controls if a mouse drop succeeds (return null if it doesnt)
*/
/mob/MouseDrop(mob/M)
. = ..()
if(M != usr)
@@ -526,13 +690,25 @@
if(isAI(M))
return
show_inv(usr)
/**
* Handle the result of a click drag onto this mob
*
* For mobs this just shows the inventory
*/
///Is the mob muzzled (default false)
/mob/proc/is_muzzled()
return 0
/mob/proc/get_status_tab_items()
. = list()
/**
* Output an update to the stat panel for the client
*
* calculates client ping, round id, server time, time dilation and other data about the round
* and puts it in the mob status panel on a regular loop
*/
/mob/Stat()
..()
@@ -603,6 +779,11 @@
. += add_spells_to_statpanel(mind.spell_list)
. += add_spells_to_statpanel(mob_spell_list)
/**
* Convert a list of spells into a displyable list for the statpanel
*
* Shows charge and other important info
*/
/mob/proc/add_spells_to_statpanel(list/spells)
var/list/L = list()
for(var/obj/effect/proc_holder/spell/S in spells)
@@ -619,6 +800,16 @@
#define MOB_FACE_DIRECTION_DELAY 1
// facing verbs
/**
* Returns true if a mob can turn to face things
*
* Conditions:
* * client.last_turn > world.time
* * not dead or unconcious
* * not anchored
* * no transform not set
* * we are not restrained
*/
/mob/proc/canface()
if(world.time < client.last_turn)
return FALSE
@@ -632,11 +823,13 @@
return FALSE
return TRUE
///Checks mobility move as well as parent checks
/mob/living/canface()
if(!(mobility_flags & MOBILITY_MOVE))
return FALSE
return ..()
///Hidden verb to turn east
/mob/verb/eastface()
set hidden = TRUE
if(!canface())
@@ -645,6 +838,7 @@
client.last_turn = world.time + MOB_FACE_DIRECTION_DELAY
return TRUE
///Hidden verb to turn west
/mob/verb/westface()
set hidden = TRUE
if(!canface())
@@ -653,6 +847,7 @@
client.last_turn = world.time + MOB_FACE_DIRECTION_DELAY
return TRUE
///Hidden verb to turn north
/mob/verb/northface()
set hidden = TRUE
if(!canface())
@@ -661,6 +856,7 @@
client.last_turn = world.time + MOB_FACE_DIRECTION_DELAY
return TRUE
///Hidden verb to turn south
/mob/verb/southface()
set hidden = TRUE
if(!canface())
@@ -709,7 +905,8 @@
pixel_y--
is_shifted = TRUE
/mob/proc/IsAdvancedToolUser()//This might need a rename but it should replace the can this mob use things check
///This might need a rename but it should replace the can this mob use things check
/mob/proc/IsAdvancedToolUser()
return FALSE
/mob/proc/swap_hand()
@@ -721,24 +918,29 @@
/mob/proc/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null) //For sec bot threat assessment
return 0
///Get the ghost of this mob (from the mind)
/mob/proc/get_ghost(even_if_they_cant_reenter, ghosts_with_clients)
if(mind)
return mind.get_ghost(even_if_they_cant_reenter, ghosts_with_clients)
///Force get the ghost from the mind
/mob/proc/grab_ghost(force)
if(mind)
return mind.grab_ghost(force = force)
///Notify a ghost that it's body is being cloned
/mob/proc/notify_ghost_cloning(var/message = "Someone is trying to revive you. Re-enter your corpse if you want to be revived!", var/sound = 'sound/effects/genetics.ogg', var/atom/source = null, flashwindow)
var/mob/dead/observer/ghost = get_ghost()
if(ghost)
ghost.notify_cloning(message, sound, source, flashwindow)
return ghost
///Add a spell to the mobs spell list
/mob/proc/AddSpell(obj/effect/proc_holder/spell/S)
mob_spell_list += S
S.action?.Grant(src)
///Remove a spell from the mobs spell list
/mob/proc/RemoveSpell(obj/effect/proc_holder/spell/spell)
if(!spell)
return
@@ -748,6 +950,7 @@
mob_spell_list -= S
qdel(S)
///Return any anti magic atom on this mob that matches the magic type
/mob/proc/anti_magic_check(magic = TRUE, holy = FALSE, tinfoil = FALSE, chargecost = 1, self = FALSE)
if(!magic && !holy && !tinfoil)
return
@@ -760,7 +963,13 @@
if((magic && HAS_TRAIT(src, TRAIT_ANTIMAGIC)) || (holy && HAS_TRAIT(src, TRAIT_HOLY)))
return src
//You can buckle on mobs if you're next to them since most are dense
/**
* Buckle to another mob
*
* You can buckle on mobs if you're next to them since most are dense
*
* Turns you to face the other mob too
*/
/mob/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE)
if(M.buckled)
return 0
@@ -774,18 +983,18 @@
return 0
return ..()
//Default buckling shift visual for mobs
///Call back post buckle to a mob to offset your visual height
/mob/post_buckle_mob(mob/living/M)
var/height = M.get_mob_buckling_height(src)
M.pixel_y = initial(M.pixel_y) + height
if(M.layer < layer)
M.layer = layer + 0.1
///Call back post unbuckle from a mob, (reset your visual height here)
/mob/post_unbuckle_mob(mob/living/M)
M.layer = initial(M.layer)
M.pixel_y = initial(M.pixel_y)
//returns the height in pixel the mob should have when buckled to another mob.
///returns the height in pixel the mob should have when buckled to another mob.
/mob/proc/get_mob_buckling_height(mob/seat)
if(isliving(seat))
var/mob/living/L = seat
@@ -793,25 +1002,30 @@
return 0
return 9
//can the mob be buckled to something by default?
///can the mob be buckled to something by default?
/mob/proc/can_buckle()
return 1
//can the mob be unbuckled from something by default?
///can the mob be unbuckled from something by default?
/mob/proc/can_unbuckle()
return 1
//Can the mob interact() with an atom?
///Can the mob interact() with an atom?
/mob/proc/can_interact_with(atom/A)
return IsAdminGhost(src) || Adjacent(A)
//Can the mob use Topic to interact with machines
///Can the mob use Topic to interact with machines
/mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
return
///Can this mob use storage
/mob/proc/canUseStorage()
return FALSE
/**
* Check if the other mob has any factions the same as us
*
* If exact match is set, then all our factions must match exactly
*/
/mob/proc/faction_check_mob(mob/target, exact_match)
if(exact_match) //if we need an exact match, we need to do some bullfuckery.
var/list/faction_src = faction.Copy()
@@ -822,7 +1036,11 @@
faction_target -= "[REF(target)]" //same thing here.
return faction_check(faction_src, faction_target, TRUE)
return faction_check(faction, target.faction, FALSE)
/*
* Compare two lists of factions, returning true if any match
*
* If exact match is passed through we only return true if both faction lists match equally
*/
/proc/faction_check(list/faction_A, list/faction_B, exact_match)
var/list/match_list
if(exact_match)
@@ -836,8 +1054,13 @@
return FALSE
//This will update a mob's name, real_name, mind.name, GLOB.data_core records, pda, id and traitor text
//Calling this proc without an oldname will only update the mob and skip updating the pda, id and records ~Carn
/**
* Fully update the name of a mob
*
* This will update a mob's name, real_name, mind.name, GLOB.data_core records, pda, id and traitor text
*
* Calling this proc without an oldname will only update the mob and skip updating the pda, id and records ~Carn
*/
/mob/proc/fully_replace_character_name(oldname,newname)
log_message("[src] name changed from [oldname] to [newname]", LOG_OWNERSHIP)
if(!newname)
@@ -866,10 +1089,11 @@
obj.update_explanation_text()
return 1
//Updates GLOB.data_core records with new name , see mob/living/carbon/human
///Updates GLOB.data_core records with new name , see mob/living/carbon/human
/mob/proc/replace_records_name(oldname,newname)
return
///update the ID name of this mob
/mob/proc/replace_identification_name(oldname,newname)
var/list/searching = GetAllContents()
var/search_id = 1
@@ -902,16 +1126,19 @@
/mob/proc/update_health_hud()
return
///Update the lighting plane and sight of this mob (sends COMSIG_MOB_UPDATE_SIGHT)
/mob/proc/update_sight()
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
///Set the lighting plane hud alpha to the mobs lighting_alpha var
/mob/proc/sync_lighting_plane_alpha()
if(hud_used)
var/obj/screen/plane_master/lighting/L = hud_used.plane_masters["[LIGHTING_PLANE]"]
if (L)
L.alpha = lighting_alpha
///Update the mouse pointer of the attached client in this mob
/mob/proc/update_mouse_pointer()
if (!client)
return
@@ -926,10 +1153,11 @@
client.mouse_pointer_icon = E.mouse_pointer
///This mob is abile to read books
/mob/proc/is_literate()
return FALSE
///Can this mob read (is literate and not blind)
/mob/proc/can_read(obj/O)
if(is_blind(src))
to_chat(src, "<span class='warning'>As you are trying to read [O], you suddenly feel very stupid!</span>")
@@ -939,12 +1167,17 @@
return
return TRUE
///Can this mob hold items
/mob/proc/can_hold_items()
return FALSE
///Get the id card on this mob
/mob/proc/get_idcard(hand_first)
return
/**
* Get the mob VV dropdown extras
*/
/mob/vv_get_dropdown()
. = ..()
. += "---"
@@ -960,12 +1193,16 @@
.["Assume Direct Control"] = "?_src_=vars;[HrefToken()];direct_control=[REF(src)]"
.["Offer Control to Ghosts"] = "?_src_=vars;[HrefToken()];offer_control=[REF(src)]"
/**
* extra var handling for the logging var
*/
/mob/vv_get_var(var_name)
switch(var_name)
if("logging")
return debug_variable(var_name, logging, 0, src, FALSE)
. = ..()
///Show the language menu for this mob
/mob/verb/open_language_menu()
set name = "Open Language Menu"
set category = "IC"
@@ -973,12 +1210,15 @@
var/datum/language_holder/H = get_language_holder()
H.open_language_menu(usr)
///Adjust the nutrition of a mob
/mob/proc/adjust_nutrition(var/change) //Honestly FUCK the oldcoders for putting nutrition on /mob someone else can move it up because holy hell I'd have to fix SO many typechecks
nutrition = max(0, nutrition + change)
///Force set the mob nutrition
/mob/proc/set_nutrition(var/change) //Seriously fuck you oldcoders.
nutrition = max(0, change)
///Set the movement type of the mob and update it's movespeed
/mob/setMovetype(newval)
. = ..()
update_movespeed(FALSE)

View File

@@ -1,3 +1,11 @@
/**
* The mob, usually meant to be a creature of some type
*
* Has a client attached that is a living person (most of the time), although I have to admit
* sometimes it's hard to tell they're sentient
*
* Has a lot of the creature game world logic, such as health etc
*/
/mob
datum_flags = DF_USE_TAG
density = TRUE
@@ -13,102 +21,194 @@
var/datum/mind/mind
var/static/next_mob_id = 0
//MOVEMENT SPEED
/// List of movement speed modifiers applying to this mob
var/list/movespeed_modification //Lazy list, see mob_movespeed.dm
/// The calculated mob speed slowdown based on the modifiers list
var/cached_multiplicative_slowdown
//ACTIONS
/// List of action hud items the user has
var/list/datum/action/actions = list()
/// A special action? No idea why this lives here
var/list/datum/action/chameleon_item_actions
var/stat = CONSCIOUS //Whether a mob is alive or dead. TODO: Move this to living - Nodrak
/// Whether a mob is alive or dead. TODO: Move this to living - Nodrak (2019, still here)
var/stat = CONSCIOUS
/*A bunch of this stuff really needs to go under their own defines instead of being globally attached to mob.
/* A bunch of this stuff really needs to go under their own defines instead of being globally attached to mob.
A variable should only be globally attached to turfs/objects/whatever, when it is in fact needed as such.
The current method unnecessarily clusters up the variable list, especially for humans (although rearranging won't really clean it up a lot but the difference will be noticable for other mobs).
I'll make some notes on where certain variable defines should probably go.
Changing this around would probably require a good look-over the pre-existing code.
*/
/// The zone this mob is currently targeting
var/zone_selected = null
var/computer_id = null
var/list/logging = list()
/// The machine the mob is interacting with (this is very bad old code btw)
var/obj/machinery/machine = null
/// Tick time the mob can next move
var/next_move = null
/**
* Magic var that stops you moving and interacting with anything
*
* Set when you're being turned into something else and also used in a bunch of places
* it probably shouldn't really be
*/
var/notransform = null //Carbon
/// Is the mob blind
var/eye_blind = 0 //Carbon
/// Does the mob have blurry sight
var/eye_blurry = 0 //Carbon
/// What is the mobs real name (name is overridden for disguises etc)
var/real_name = null
/// Is the mob pixel shifted
var/is_shifted = FALSE
/// can this mob move freely in space (should be a trait)
var/spacewalk = FALSE
/**
* back up of the real name during admin possession
*
* If an admin possesses an object it's real name is set to the admin name and this
* stores whatever the real name was previously. When possession ends, the real name
* is reset to this value
*/
var/name_archive //For admin things like possession
/// Default body temperature
var/bodytemperature = BODYTEMP_NORMAL //310.15K / 98.6F
/// Drowsyness level of the mob
var/drowsyness = 0//Carbon
/// Dizziness level of the mob
var/dizziness = 0//Carbon
/// Jitteryness level of the mob
var/jitteriness = 0//Carbon
/// Hunger level of the mob
var/nutrition = NUTRITION_LEVEL_START_MIN // randomised in Initialize
/// Satiation level of the mob
var/satiety = 0//Carbon
/// How many ticks this mob has been over reating
var/overeatduration = 0 // How long this guy is overeating //Carbon
/// The current intent of the mob
var/a_intent = INTENT_HELP//Living
/// List of possible intents a mob can have
var/list/possible_a_intents = null//Living
/// The movement intent of the mob (run/wal)
var/m_intent = MOVE_INTENT_RUN//Living
/// The last known IP of the client who was in this mob
var/lastKnownIP = null
/// movable atoms buckled to this mob
var/atom/movable/buckled = null//Living
/// movable atom we are buckled to
var/atom/movable/buckling
//Hands
///What hand is the active hand
var/active_hand_index = 1
var/list/held_items = list() //len = number of hands, eg: 2 nulls is 2 empty hands, 1 item and 1 null is 1 full hand and 1 empty hand.
//held_items[active_hand_index] is the actively held item, but please use get_active_held_item() instead, because OOP
/**
* list of items held in hands
*
* len = number of hands, eg: 2 nulls is 2 empty hands, 1 item and 1 null is 1 full hand
* and 1 empty hand.
*
* NB: contains nulls!
*
* held_items[active_hand_index] is the actively held item, but please use
* get_active_held_item() instead, because OOP
*/
var/list/held_items = list()
//HUD things
/// Storage component (for mob inventory)
var/datum/component/storage/active_storage
/// Active hud
var/datum/hud/hud_used = null
/// I have no idea tbh
var/research_scanner = FALSE
/// Is the mob throw intent on
var/in_throw_mode = 0
/// What job does this mob have
var/job = null//Living
var/list/faction = list("neutral") //A list of factions that this mob is currently in, for hostile mob targetting, amongst other things
var/move_on_shuttle = 1 // Can move on the shuttle.
/// A list of factions that this mob is currently in, for hostile mob targetting, amongst other things
var/list/faction = list("neutral")
//The last mob/living/carbon to push/drag/grab this mob (mostly used by slimes friend recognition)
/// Can this mob enter shuttles
var/move_on_shuttle = 1
///The last mob/living/carbon to push/drag/grab this mob (exclusively used by slimes friend recognition)
var/mob/living/carbon/LAssailant = null
var/list/mob_spell_list = list() //construct spells and mime spells. Spells that do not transfer from one mob to another and can not be lost in mindswap.
/**
* construct spells and mime spells.
*
* Spells that do not transfer from one mob to another and can not be lost in mindswap.
* obviously do not live in the mind
*/
var/list/mob_spell_list = list()
var/status_flags = CANSTUN|CANKNOCKDOWN|CANUNCONSCIOUS|CANPUSH //bitflags defining which status effects can be inflicted (replaces canknockdown, canstun, etc)
/// bitflags defining which status effects can be inflicted (replaces canknockdown, canstun, etc)
var/status_flags = CANSTUN|CANKNOCKDOWN|CANUNCONSCIOUS|CANPUSH
var/digitalcamo = 0 // Can they be tracked by the AI?
var/digitalinvis = 0 //Are they ivisible to the AI?
var/image/digitaldisguise = null //what does the AI see instead of them?
/// Can they be tracked by the AI?
var/digitalcamo = 0
///Are they ivisible to the AI?
var/digitalinvis = 0
///what does the AI see instead of them?
var/image/digitaldisguise = null
var/has_unlimited_silicon_privilege = 0 // Can they interact with station electronics
/// Can they interact with station electronics
var/has_unlimited_silicon_privilege = 0
var/obj/control_object //Used by admins to possess objects. All mobs should have this var
var/atom/movable/remote_control //Calls relaymove() to whatever it is
///Used by admins to possess objects. All mobs should have this var
var/obj/control_object
var/deathsound //leave null for no sound. used for *deathgasp
///Calls relay_move() to whatever this is set to when the mob tries to move
var/atom/movable/remote_control
var/turf/listed_turf = null //the current turf being examined in the stat panel
/**
* The sound made on death
*
* leave null for no sound. used for *deathgasp
*/
var/deathsound
var/list/observers = null //The list of people observing this mob.
///the current turf being examined in the stat panel
var/turf/listed_turf = null
///The list of people observing this mob.
var/list/observers = null
///List of progress bars this mob is currently seeing for actions
var/list/progressbars = null //for stacking do_after bars
///List of datums that this has which make use of MouseMove()
var/list/mousemove_intercept_objects
///Allows a datum to intercept all click calls this mob is the so
var/datum/click_intercept
var/registered_z
///THe z level this mob is currently registered in
var/registered_z = null
///Size of the user's memory(IC notes)
var/memory_amt = 0
var/list/emotes_used /// Used for tracking last uses of emotes for cooldown purposes
/// Used for tracking last uses of emotes for cooldown purposes
var/list/emotes_used
///Whether the mob is updating glide size when movespeed updates or not
var/updating_glide_size = TRUE

View File

@@ -1,11 +1,13 @@
// see _DEFINES/is_helpers.dm for mob type checks
///Find the mob at the bottom of a buckle chain
/mob/proc/lowest_buckled_mob()
. = src
if(buckled && ismob(buckled))
var/mob/Buckled = buckled
. = Buckled.lowest_buckled_mob()
///Convert a PRECISE ZONE into the BODY_ZONE
/proc/check_zone(zone)
if(!zone)
return BODY_ZONE_CHEST
@@ -26,7 +28,12 @@
zone = BODY_ZONE_CHEST
return zone
/**
* Return the zone or randomly, another valid zone
*
* probability controls the chance it chooses the passed in zone, or another random zone
* defaults to 80
*/
/proc/ran_zone(zone, probability = 80)
if(prob(probability))
zone = check_zone(zone)
@@ -34,29 +41,45 @@
zone = pickweight(list(BODY_ZONE_HEAD = 1, BODY_ZONE_CHEST = 1, BODY_ZONE_L_ARM = 4, BODY_ZONE_R_ARM = 4, BODY_ZONE_L_LEG = 4, BODY_ZONE_R_LEG = 4))
return zone
///Would this zone be above the neck
/proc/above_neck(zone)
var/list/zones = list(BODY_ZONE_HEAD, BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_PRECISE_EYES)
if(zones.Find(zone))
return 1
else
return 0
/**
* Convert random parts of a passed in message to stars
*
* * n - the string to convert
* * pr - probability any character gets changed
*
* This proc is dangerously laggy, avoid it or die
*/
/proc/stars(n, pr)
n = html_encode(n)
if (pr == null)
pr = 25
if (pr <= 0)
return null
else
if (pr >= 100)
return n
var/te = n
var/t = ""
n = length(n)
/proc/stars(phrase, probability = 25)
if(probability <= 0)
return phrase
phrase = html_decode(phrase)
var/leng = length(phrase)
. = ""
var/char = ""
for(var/i = 1, i <= leng, i += length(char))
char = phrase[i]
if(char == " " || !prob(probability))
. += char
for(var/p = 1 to min(n,MAX_BROADCAST_LEN))
if ((copytext(te, p, p + 1) == " " || prob(pr)))
t = text("[][]", t, copytext(te, p, p + 1))
else
. += "*"
return sanitize(.)
t = text("[]*", t)
if(n > MAX_BROADCAST_LEN)
t += "..." //signals missing text
return sanitize(t)
/**
* Makes you speak like you're drunk
*/
/proc/slur(phrase)
phrase = html_decode(phrase)
var/leng = length(phrase)
@@ -92,7 +115,7 @@
. += "[newletter]"
return sanitize(.)
/// Makes you talk like you got cult stunned, which is slurring but with some dark messages
/proc/cultslur(phrase) // Inflicted on victims of a stun talisman
phrase = html_decode(phrase)
var/leng = length(phrase)
@@ -135,7 +158,7 @@
. += newletter
return sanitize(.)
///Adds stuttering to the message passed in
/proc/stutter(phrase)
phrase = html_decode(phrase)
var/leng = length(phrase)
@@ -156,6 +179,7 @@
. += newletter
return sanitize(.)
///Convert a message to derpy speak
/proc/derpspeech(message, stuttering)
message = replacetext(message, " am ", " ")
message = replacetext(message, " is ", " ")
@@ -176,7 +200,7 @@
/**
* Turn text into complete gibberish!
*
* text is the inputted message, replace_characters will cause original letters to be replaced and chance are the odds that a character gets modified.
* text is the inputted message, and any value higher than 70 for chance will cause letters to be replaced instead of added
*/
/proc/Gibberish(text, replace_characters = FALSE, chance = 50)
text = html_decode(text)
@@ -195,6 +219,9 @@
return sanitize(.)
///Shake the camera of the person viewing the mob SO REAL!
/proc/shake_camera(mob/M, duration, strength=1)
if(!M || !M.client || duration < 1)
return
@@ -212,7 +239,7 @@
animate(pixel_x=oldx, pixel_y=oldy, time=1)
///Find if the message has the real name of any user mob in the mob_list
/proc/findname(msg)
if(!istext(msg))
msg = "[msg]"
@@ -222,13 +249,18 @@
return M
return 0
///Find the first name of a mob from the real name with regex
/mob/proc/first_name()
var/static/regex/firstname = new("^\[^\\s-\]+") //First word before whitespace or "-"
firstname.Find(real_name)
return firstname.match
//change a mob's act-intent. Input the intent as a string such as "help" or use "right"/"left
/**
* change a mob's act-intent.
*
* Input the intent as a string such as "help" or use "right"/"left
*/
/mob/verb/a_intent_change(input as text)
set name = "a-intent"
set hidden = 1
@@ -261,7 +293,7 @@
if(hud_used && hud_used.action_intent)
hud_used.action_intent.icon_state = "[a_intent]"
///Checks if passed through item is blind
/proc/is_blind(A)
SHOULD_BE_PURE(TRUE)
if(ismob(A))
@@ -269,10 +301,19 @@
return B.eye_blind
return FALSE
///Is the mob hallucinating?
/mob/proc/hallucinating()
return FALSE
/proc/is_special_character(mob/M) // returns 1 for special characters and 2 for heroes of gamemode //moved out of admins.dm because things other than admin procs were calling this.
// moved out of admins.dm because things other than admin procs were calling this.
/**
* Is this mob special to the gamemode?
*
* returns 1 for special characters and 2 for heroes of gamemode
*
*/
/proc/is_special_character(mob/M)
if(!SSticker.HasRoundStarted())
return FALSE
if(!istype(M))
@@ -315,9 +356,29 @@
return TRUE
return FALSE
/mob/proc/reagent_check(datum/reagent/R) // utilized in the species code
return 1
/**
* Fancy notifications for ghosts
*
* The kitchen sink of notification procs
*
* Arguments:
* * message
* * ghost_sound sound to play
* * enter_link Href link to enter the ghost role being notified for
* * source The source of the notification
* * alert_overlay The alert overlay to show in the alert message
* * action What action to take upon the ghost interacting with the notification, defaults to NOTIFY_JUMP
* * flashwindow Flash the byond client window
* * ignore_key Ignore keys if they're in the GLOB.poll_ignore list
* * header The header of the notifiaction
* * notify_suiciders If it should notify suiciders (who do not qualify for many ghost roles)
* * notify_volume How loud the sound should be to spook the user
*/
/proc/notify_ghosts(var/message, var/ghost_sound = null, var/enter_link = null, var/atom/source = null, var/mutable_appearance/alert_overlay = null, var/action = NOTIFY_JUMP, flashwindow = TRUE, ignore_mapload = TRUE, ignore_key, header = null, notify_suiciders = TRUE, var/notify_volume = 100) //Easy notification of ghosts.
if(ignore_mapload && SSatoms.initialized != INITIALIZATION_INNEW_REGULAR) //don't notify for objects created during a map load
return
@@ -351,6 +412,9 @@
alert_overlay.plane = FLOAT_PLANE
A.add_overlay(alert_overlay)
/**
* Heal a robotic body part on a mob
*/
/proc/item_heal_robotic(mob/living/carbon/human/H, mob/user, brute_heal, burn_heal)
var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected))
if(affecting && affecting.status == BODYPART_ROBOTIC)
@@ -368,7 +432,7 @@
else
to_chat(user, "<span class='warning'>[affecting] is already in good condition!</span>")
///Is the passed in mob an admin ghost
/proc/IsAdminGhost(var/mob/user)
if(!user) //Are they a mob? Auto interface updates call this with a null src
return
@@ -382,6 +446,11 @@
return
return TRUE
/**
* Offer control of the passed in mob to dead player
*
* Automatic logging and uses pollCandidatesForMob, how convenient
*/
/proc/offer_control(mob/M)
to_chat(M, "Control of your mob has been offered to dead players.")
if(usr)
@@ -410,12 +479,14 @@
message_admins("No ghosts were willing to take control of [ADMIN_LOOKUPFLW(M)])")
return FALSE
///Is the mob a flying mob
/mob/proc/is_flying(mob/M = src)
if(M.movement_type & FLYING)
return 1
else
return 0
///Clicks a random nearby mob with the source from this mob
/mob/proc/click_random_mob()
var/list/nearby_mobs = list()
for(var/mob/living/L in range(1, src))
@@ -425,7 +496,7 @@
var/mob/living/T = pick(nearby_mobs)
ClickOn(T)
// Logs a message in a mob's individual log, and in the global logs as well if log_globally is true
/// Logs a message in a mob's individual log, and in the global logs as well if log_globally is true
/mob/log_message(message, message_type, color=null, log_globally = TRUE)
if(!LAZYLEN(message))
stack_trace("Empty message")
@@ -457,14 +528,25 @@
..()
///Can the mob hear
/mob/proc/can_hear()
. = TRUE
//Examine text for traits shared by multiple types. I wish examine was less copypasted.
/**
* Examine text for traits shared by multiple types.
*
* I wish examine was less copypasted. (oranges say, be the change you want to see buddy)
*/
/mob/proc/common_trait_examine()
if(HAS_TRAIT(src, TRAIT_DISSECTED))
. += "<span class='notice'>This body has been dissected and analyzed. It is no longer worth experimenting on.</span><br>"
/**
* Get the list of keywords for policy config
*
* This gets the type, mind assigned roles and antag datums as a list, these are later used
* to send the user relevant headadmin policy config
*/
/mob/proc/get_policy_keywords()
. = list()
. += "[type]"
@@ -474,6 +556,6 @@
for(var/datum/antagonist/A in mind.antag_datums)
. += "[A.type]"
//Can the mob see reagents inside of containers?
///Can the mob see reagents inside of containers?
/mob/proc/can_see_reagents()
return stat == DEAD || has_unlimited_silicon_privilege //Dead guys and silicons can always see reagents

View File

@@ -1,14 +1,33 @@
//DO NOT USE THIS UNLESS YOU ABSOLUTELY HAVE TO. THIS IS BEING PHASED OUT FOR THE MOVESPEED MODIFICATION SYSTEM.
//See mob_movespeed.dm
///Can the atom pass this mob (always true for /mob)
/**
* Get the current movespeed delay of the mob
*
* DO NOT OVERRIDE THIS UNLESS YOU ABSOLUTELY HAVE TO.
* THIS IS BEING PHASED OUT FOR THE MOVESPEED MODIFICATION SYSTEM.
* See mob_movespeed.dm
*/
/mob/proc/movement_delay() //update /living/movement_delay() if you change this
return cached_multiplicative_slowdown
/**
* If your mob is concious, drop the item in the active hand
*
* This is a hidden verb, likely for binding with winset for hotkeys
*/
/client/verb/drop_item()
set hidden = 1
if(!iscyborg(mob) && mob.stat == CONSCIOUS)
mob.dropItemToGround(mob.get_active_held_item())
return
/**
* force move the control_object of your client mob
*
* Used in admin possession and called from the client Move proc
* ensures the possessed object moves and not the admin mob
*
* Has no sanity other than checking density
*/
/client/proc/Move_object(direct)
if(mob && mob.control_object)
if(mob.control_object.density)
@@ -26,17 +45,17 @@
* Move a client in a direction
*
* Huge proc, has a lot of functionality
*
*
* Mostly it will despatch to the mob that you are the owner of to actually move
* in the physical realm
*
*
* Things that stop you moving as a mob:
* * world time being less than your next move_delay
* * not being in a mob, or that mob not having a loc
* * missing the n and direction parameters
* * being in remote control of an object (calls Moveobject instead)
* * being dead (it ghosts you instead)
*
*
* Things that stop you moving as a mob living (why even have OO if you're just shoving it all
* in the parent proc with istype checks right?):
* * having incorporeal_move set (calls Process_Incorpmove() instead)
@@ -56,7 +75,7 @@
*
* Finally if you're pulling an object and it's dense, you are turned 180 after the move
* (if you ask me, this should be at the top of the move so you don't dance around)
*
*
*/
/client/Move(n, direct)
if(world.time < move_delay) //do not move anything ahead of this check please
@@ -147,9 +166,11 @@
if(P && !ismob(P) && P.density)
mob.setDir(turn(mob.dir, 180))
///Process_Grab()
///Called by client/Move()
///Checks to see if you are being grabbed and if so attemps to break it
/**
* Checks to see if you're being grabbed and if so attempts to break it
*
* Called by client/Move()
*/
/client/proc/Process_Grab()
if(mob.pulledby)
if((mob.pulledby == mob.pulling) && (mob.pulledby.grab_state == GRAB_PASSIVE)) //Don't autoresist passive grabs if we're grabbing them too.
@@ -168,7 +189,7 @@
* Allows mobs to ignore density and phase through objects
*
* Called by client/Move()
*
*
* The behaviour depends on the incorporeal_move value of the mob
*
* * INCORPOREAL_MOVE_BASIC - forceMoved to the next tile with no stop
@@ -256,9 +277,9 @@
* Handles mob/living movement in space (or no gravity)
*
* Called by /client/Move()
*
*
* return TRUE for movement or FALSE for none
*
*
* You can move in space if you have a spacewalk ability
*/
/mob/Process_Spacemove(movement_dir = 0)
@@ -272,6 +293,9 @@
return TRUE
return FALSE
/**
* Find movable atoms? near a mob that are viable for pushing off when moving
*/
/mob/get_spacemove_backup()
for(var/A in orange(1, get_turf(src)))
if(isarea(A))
@@ -298,27 +322,42 @@
continue
. = AM
/**
* Returns true if a mob has gravity
*
* I hate that this exists
*/
/mob/proc/mob_has_gravity()
return has_gravity()
/**
* Does this mob ignore gravity
*/
/mob/proc/mob_negates_gravity()
return FALSE
/// Called when this mob slips over, override as needed
/mob/proc/slip(knockdown_amount, obj/O, lube, paralyze, force_drop)
return
/// Update the gravity status of this mob
/mob/proc/update_gravity()
return
//bodypart selection - Cyberboss
//8 toggles through head - eyes - mouth
//bodypart selection verbs - Cyberboss
//8:repeated presses toggles through head - eyes - mouth
//4: r-arm 5: chest 6: l-arm
//1: r-leg 2: groin 3: l-leg
///Validate the client's mob has a valid zone selected
/client/proc/check_has_body_select()
return mob && mob.hud_used && mob.hud_used.zone_select && istype(mob.hud_used.zone_select, /obj/screen/zone_sel)
/**
* Hidden verb to set the target zone of a mob to the head
*
* (bound to 8) - repeated presses toggles through head - eyes - mouth
*/
/client/verb/body_toggle_head()
set name = "body-toggle-head"
set hidden = 1
@@ -338,6 +377,7 @@
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(next_in_line, mob)
///Hidden verb to target the right arm, bound to 4
/client/verb/body_r_arm()
set name = "body-r-arm"
set hidden = 1
@@ -348,6 +388,7 @@
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(BODY_ZONE_R_ARM, mob)
///Hidden verb to target the chest, bound to 5
/client/verb/body_chest()
set name = "body-chest"
set hidden = 1
@@ -358,6 +399,7 @@
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(BODY_ZONE_CHEST, mob)
///Hidden verb to target the left arm, bound to 6
/client/verb/body_l_arm()
set name = "body-l-arm"
set hidden = 1
@@ -368,6 +410,7 @@
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(BODY_ZONE_L_ARM, mob)
///Hidden verb to target the right leg, bound to 1
/client/verb/body_r_leg()
set name = "body-r-leg"
set hidden = 1
@@ -378,6 +421,7 @@
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(BODY_ZONE_R_LEG, mob)
///Hidden verb to target the groin, bound to 2
/client/verb/body_groin()
set name = "body-groin"
set hidden = 1
@@ -388,6 +432,7 @@
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(BODY_ZONE_PRECISE_GROIN, mob)
///Hidden verb to target the left leg, bound to 3
/client/verb/body_l_leg()
set name = "body-l-leg"
set hidden = 1
@@ -398,6 +443,7 @@
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(BODY_ZONE_L_LEG, mob)
///Verb to toggle the walk or run status
/client/verb/toggle_walk_run()
set name = "toggle-walk-run"
set hidden = TRUE
@@ -407,7 +453,7 @@
/**
* Toggle the move intent of the mob
*
*
* triggers an update the move intent hud as well
*/
/mob/proc/toggle_move_intent(mob/user)
@@ -419,6 +465,7 @@
for(var/obj/screen/mov_intent/selector in hud_used.static_inventory)
selector.update_icon(src)
///Moves a mob upwards in z level
/mob/verb/up()
set name = "Move Upwards"
set category = "IC"
@@ -426,6 +473,7 @@
if(zMove(UP, TRUE))
to_chat(src, "<span class='notice'>You move upwards.</span>")
///Moves a mob down a z level
/mob/verb/down()
set name = "Move Down"
set category = "IC"
@@ -433,6 +481,7 @@
if(zMove(DOWN, TRUE))
to_chat(src, "<span class='notice'>You move down.</span>")
///Move a mob between z levels, if it's valid to move z's on this turf
/mob/proc/zMove(dir, feedback = FALSE)
if(dir != UP && dir != DOWN)
return FALSE
@@ -448,5 +497,6 @@
forceMove(target)
return TRUE
/// Can this mob move between z levels
/mob/proc/canZMove(direction, turf/target)
return FALSE

View File

@@ -1,13 +1,40 @@
/*! How move speed for mobs works
/*Current movespeed modification list format: list(id = list(
priority,
flags,
legacy slowdown/speedup amount,
movetype_flags
))
Move speed is now calculated by using a list of movespeed modifiers, which is a list itself (to avoid datum overhead)
This gives us the ability to have multiple sources of movespeed, reliabily keep them applied and remove them when they should be
THey can have unique sources and a bunch of extra fancy flags that control behaviour
Previously trying to update move speed was a shot in the dark that usually meant mobs got stuck going faster or slower
This list takes the following format
```Current movespeed modification list format:
list(
id = list(
priority,
flags,
legacy slowdown/speedup amount,
movetype_flags
)
)
```
WHen update movespeed is called, the list of items is iterated, according to flags priority and a bunch of conditions
this spits out a final calculated value which is used as a modifer to last_move + modifier for calculating when a mob
can next move
Key procs
* [add_movespeed_modifier](mob.html#proc/add_movespeed_modifier)
* [remove_movespeed_modifier](mob.html#proc/remove_movespeed_modifier)
* [has_movespeed_modifier](mob.html#proc/has_movespeed_modifier)
* [update_movespeed](mob.html#proc/update_movespeed)
*/
//ANY ADD/REMOVE DONE IN UPDATE_MOVESPEED MUST HAVE THE UPDATE ARGUMENT SET AS FALSE!
///Add a move speed modifier to a mob
/mob/proc/add_movespeed_modifier(id, update=TRUE, priority=0, flags=NONE, override=FALSE, multiplicative_slowdown=0, movetypes=ALL, blacklisted_movetypes=NONE, conflict=FALSE)
var/list/temp = list(priority, flags, multiplicative_slowdown, movetypes, blacklisted_movetypes, conflict) //build the modification list
var/resort = TRUE
@@ -24,6 +51,7 @@
update_movespeed(resort)
return TRUE
///Remove a move speed modifier from a mob
/mob/proc/remove_movespeed_modifier(id, update = TRUE)
if(!LAZYACCESS(movespeed_modification, id))
return FALSE
@@ -33,6 +61,7 @@
update_movespeed(FALSE)
return TRUE
///Handles the special case of editing the movement var
/mob/vv_edit_var(var_name, var_value)
var/slowdown_edit = (var_name == NAMEOF(src, cached_multiplicative_slowdown))
var/diff
@@ -43,18 +72,22 @@
if(. && slowdown_edit && isnum(diff))
add_movespeed_modifier(MOVESPEED_ID_ADMIN_VAREDIT, TRUE, 100, override = TRUE, multiplicative_slowdown = diff)
///Is there a movespeed modifier for this mob
/mob/proc/has_movespeed_modifier(id)
return LAZYACCESS(movespeed_modification, id)
///Set or update the global movespeed config on a mob
/mob/proc/update_config_movespeed()
add_movespeed_modifier(MOVESPEED_ID_CONFIG_SPEEDMOD, FALSE, 100, override = TRUE, multiplicative_slowdown = get_config_multiplicative_speed())
///Get the global config movespeed of a mob by type
/mob/proc/get_config_multiplicative_speed()
if(!islist(GLOB.mob_config_movespeed_type_lookup) || !GLOB.mob_config_movespeed_type_lookup[type])
return 0
else
return GLOB.mob_config_movespeed_type_lookup[type]
///Go through the list of movespeed modifiers and calculate a final movespeed
/mob/proc/update_movespeed(resort = TRUE)
if(resort)
sort_movespeed_modlist()
@@ -78,9 +111,11 @@
. += amt
cached_multiplicative_slowdown = .
///Get the move speed modifiers list of the mob
/mob/proc/get_movespeed_modifiers()
return movespeed_modification
///Check if a movespeed modifier is identical to another
/mob/proc/movespeed_modifier_identical_check(list/mod1, list/mod2)
if(!islist(mod1) || !islist(mod2) || mod1.len < MOVESPEED_DATA_INDEX_MAX || mod2.len < MOVESPEED_DATA_INDEX_MAX)
return FALSE
@@ -89,18 +124,25 @@
return FALSE
return TRUE
///Calculate the total slowdown of all movespeed modifiers
/mob/proc/total_multiplicative_slowdown()
. = 0
for(var/id in get_movespeed_modifiers())
var/list/data = movespeed_modification[id]
. += data[MOVESPEED_DATA_INDEX_MULTIPLICATIVE_SLOWDOWN]
///Checks if a move speed modifier is valid and not missing any data
/proc/movespeed_data_null_check(list/data) //Determines if a data list is not meaningful and should be discarded.
. = TRUE
if(data[MOVESPEED_DATA_INDEX_MULTIPLICATIVE_SLOWDOWN])
. = FALSE
/mob/proc/sort_movespeed_modlist() //Verifies it too. Sorts highest priority (first applied) to lowest priority (last applied)
/**
* Sort the list of move speed modifiers
*
* Verifies it too. Sorts highest priority (first applied) to lowest priority (last applied)
*/
/mob/proc/sort_movespeed_modlist()
if(!movespeed_modification)
return
var/list/assembled = list()

View File

@@ -1,4 +1,6 @@
//Speech verbs.
///Say verb
/mob/verb/say_verb(message as text)
set name = "Say"
set category = "IC"
@@ -18,7 +20,7 @@
if(message)
say(message)
///Whisper verb
/mob/verb/whisper_verb(message as text)
set name = "Whisper"
set category = "IC"
@@ -36,9 +38,11 @@
return
whisper(message)
///whisper a message
/mob/proc/whisper(message, datum/language/language=null)
say(message, language) //only living mobs actually whisper, everything else just talks
///The me emote verb
/mob/verb/me_verb(message as text)
set name = "Me"
set category = "IC"
@@ -51,6 +55,7 @@
usr.emote("me",1,message,TRUE)
///Speak as a dead person (ghost etc)
/mob/proc/say_dead(var/message)
var/name = real_name
var/alt_name = ""
@@ -99,17 +104,28 @@
log_talk(message, LOG_SAY, tag="DEAD")
deadchat_broadcast(rendered, source, follow_target = src, speaker_key = key)
///Check if this message is an emote
/mob/proc/check_emote(message, forced)
if(message[1] == "*")
emote(copytext(message, length(message[1]) + 1), intentional = !forced)
return TRUE
///Check if the mob has a hivemind channel
/mob/proc/hivecheck()
return 0
///Check if the mob has a ling hivemind
/mob/proc/lingcheck()
return LINGHIVE_NONE
/**
* Get the mode of a message
*
* Result can be
* * MODE_WHISPER (Quiet speech)
* * MODE_HEADSET (Common radio channel)
* * A department radio (lots of values here)
*/
/mob/proc/get_message_mode(message)
var/key = message[1]
if(key == "#")

View File

@@ -1,6 +1,7 @@
/*=============================================================
======================MIAUW'S SAY REWRITE======================
===============================================================
# Say code basics
This document is a little dated but I believe it's accurate mostly (oranges 2019)
# MIAUW'S SAY REWRITE
This is a basic explanation of how say() works. Read this if you don't understand something.
@@ -14,8 +15,9 @@ If you came here to see how to use saycode, all you will ever really need to cal
To have things react when other things speak around them, add the HEAR_1 flag to their flags variable and
override their Hear() proc.
=======================PROCS & VARIABLES=======================
Here follows a list of say()-related procs and variables.
# PROCS & VARIABLES
Here follows a list of say()-related procs and variables.
```
global procs
get_radio_span(freq)
Returns the span class associated with that frequency.
@@ -76,7 +78,8 @@ global procs
Passes message_mode to say_quote.
say_quote(input, spans, message_mode)
Adds a verb and quotes to a message. Also attaches span classes to a message. Verbs are determined by verb_say/verb_ask/verb_yell variables. Called on the speaker.
Adds a verb and quotes to a message. Also attaches span classes to a message.
Verbs are determined by verb_say/verb_ask/verb_yell variables. Called on the speaker.
/mob
say_dead(message)
@@ -145,8 +148,8 @@ global procs
Return 0 if no radio was spoken into.
IMPORTANT: remember to call ..() and check for ..()'s return value properly!
============================RADIOS=============================
```
# RADIOS
I did not want to interfere with radios too much, but I sort of had to.
For future generations, here is how radio code works:
@@ -162,9 +165,10 @@ This is an associative list, and the numbers as strings are the keys. The values
To add a radio, simply use add_radio(radio, frequency). To remove a radio, use remove_radio(radio, frequency).
To remove a radio from ALL frequencies, use remove_radio_all(radio).
VIRTUAL SPEAKERS:
## VIRTUAL SPEAKERS:
Virtual speakers are simply atom/movables with a few extra variables.
If radio_freq is not null, the code will rely on the fact that the speaker is virtual. This means that several procs will return something:
```
(all of these procs are defined at the atom/movable level and return "" at that level.)
GetJob()
Returns the job string variable of the virtual speaker.
@@ -174,7 +178,7 @@ If radio_freq is not null, the code will rely on the fact that the speaker is vi
Returns the source of the virtual speaker.
GetRadio()
Returns the radio that was spoken through by the source. Needed for AI tracking.
```
This is fairly hacky, but it means that I can advoid using istypes. It's mainly relevant for AI tracking and AI job display.
That's all, folks!*/
That's all, folks!

View File

@@ -5,21 +5,23 @@
/////////////////////////////////// JITTERINESS ////////////////////////////////////
///Set the jitter of a mob
/mob/proc/Jitter(amount)
jitteriness = max(jitteriness,amount,0)
/////////////////////////////////// DIZZINESS ////////////////////////////////////
/**
* Set the dizzyness of a mob to a passed in amount
*
* Except if dizziness is already higher in which case it does nothing
*/
/mob/proc/Dizzy(amount)
dizziness = max(dizziness,amount,0)
///FOrce set the dizzyness of a mob
/mob/proc/set_dizziness(amount)
dizziness = max(amount, 0)
/////////////////////////////////// EYE_BLIND ////////////////////////////////////
///Blind a mobs eyes by amount
/mob/proc/blind_eyes(amount)
if(amount>0)
var/old_eye_blind = eye_blind
@@ -29,6 +31,11 @@
throw_alert("blind", /obj/screen/alert/blind)
overlay_fullscreen("blind", /obj/screen/fullscreen/blind)
/**
* Adjust a mobs blindness by an amount
*
* Will apply the blind alerts if needed
*/
/mob/proc/adjust_blindness(amount)
if(amount>0)
var/old_eye_blind = eye_blind
@@ -49,7 +56,9 @@
if(!eye_blind)
clear_alert("blind")
clear_fullscreen("blind")
/**
* Force set the blindness of a mob to some level
*/
/mob/proc/set_blindness(amount)
if(amount>0)
var/old_eye_blind = eye_blind
@@ -71,21 +80,27 @@
clear_alert("blind")
clear_fullscreen("blind")
/////////////////////////////////// EYE_BLURRY ////////////////////////////////////
/**
* Make the mobs vision blurry
*/
/mob/proc/blur_eyes(amount)
if(amount>0)
eye_blurry = max(amount, eye_blurry)
update_eye_blur()
/**
* Adjust the current blurriness of the mobs vision by amount
*/
/mob/proc/adjust_blurriness(amount)
eye_blurry = max(eye_blurry+amount, 0)
update_eye_blur()
///Set the mobs blurriness of vision to an amount
/mob/proc/set_blurriness(amount)
eye_blurry = max(amount, 0)
update_eye_blur()
///Apply the blurry overlays to a mobs clients screen
/mob/proc/update_eye_blur()
if(!client)
return
@@ -94,24 +109,23 @@
GW.backdrop(src)
OT.backdrop(src)
/////////////////////////////////// DRUGGY ////////////////////////////////////
///Adjust the drugginess of a mob
/mob/proc/adjust_drugginess(amount)
return
///Set the drugginess of a mob
/mob/proc/set_drugginess(amount)
return
/////////////////////////////////// GROSSED OUT ////////////////////////////////////
///Adjust the disgust level of a mob
/mob/proc/adjust_disgust(amount)
return
///Set the disgust level of a mob
/mob/proc/set_disgust(amount)
return
/////////////////////////////////// TEMPERATURE ////////////////////////////////////
///Adjust the body temperature of a mob, with min/max settings
/mob/proc/adjust_bodytemperature(amount,min_temp=0,max_temp=INFINITY)
if(bodytemperature >= min_temp && bodytemperature <= max_temp)
bodytemperature = clamp(bodytemperature + amount,min_temp,max_temp)

View File

@@ -1,5 +1,7 @@
# Modular computer programs
How module computer programs work
Ok. so a quick rundown on how to make a program. This is kind of a shitty documentation, but oh well I was asked to.
## Base setup

View File

@@ -13,15 +13,24 @@
w_class = WEIGHT_CLASS_TINY
throw_speed = 3
throw_range = 7
///list containing the actual ammo within the magazine
var/list/stored_ammo = list()
///type that the magazine will be searching for, rejects if not a subtype of
var/ammo_type = /obj/item/ammo_casing
///maximum amount of ammo in the magazine
var/max_ammo = 7
var/multiple_sprites = 0
///Controls how sprites are updated for the ammo box; see defines in combat.dm: AMMO_BOX_ONE_SPRITE; AMMO_BOX_PER_BULLET; AMMO_BOX_FULL_EMPTY
var/multiple_sprites = AMMO_BOX_ONE_SPRITE
///String, used for checking if ammo of different types but still fits can fit inside it; generally used for magazines
var/caliber
///Allows multiple bullets to be loaded in from one click of another box/magazine
var/multiload = TRUE
///Whether the magazine should start with nothing in it
var/start_empty = FALSE
///cost of all the bullets in the magazine/box
var/list/bullet_cost
var/list/base_cost// override this one as well if you override bullet_cost
///cost of the materials in the magazine/box itself
var/list/base_cost
/obj/item/ammo_box/Initialize()
. = ..()
@@ -44,6 +53,7 @@
/obj/item/ammo_box/autolathe_crafted()
calc_mats(force = TRUE)
///gets a round from the magazine, if keep is TRUE the round will stay in the gun
/obj/item/ammo_box/proc/get_round(keep = FALSE)
if (!stored_ammo.len)
return null
@@ -54,6 +64,7 @@
stored_ammo.Insert(1,b)
return b
///puts a round into the magazine
/obj/item/ammo_box/proc/give_round(obj/item/ammo_casing/R, replace_spent = 0)
// Boxes don't have a caliber type, magazines do. Not sure if it's intended or not, but if we fail to find a caliber, then we fall back to ammo_type.
if(!R || (caliber && R.caliber != caliber) || (!caliber && R.type != ammo_type))
@@ -76,6 +87,7 @@
return TRUE
return FALSE
///Whether or not the box can be loaded, used in overrides
/obj/item/ammo_box/proc/can_load(mob/user)
return TRUE
@@ -119,9 +131,9 @@
/obj/item/ammo_box/update_icon()
var/shells_left = stored_ammo.len
switch(multiple_sprites)
if(1)
if(AMMO_BOX_PER_BULLET)
icon_state = "[initial(icon_state)]-[shells_left]"
if(2)
if(AMMO_BOX_FULL_EMPTY)
icon_state = "[initial(icon_state)]-[shells_left ? "[max_ammo]" : "0"]"
desc = "[initial(desc)] There [(shells_left == 1) ? "is" : "are"] [shells_left] shell\s left!"
for (var/material in bullet_cost)
@@ -129,7 +141,7 @@
material_amount = (material_amount*stored_ammo.len) + base_cost[material]
materials[material] = material_amount
//Behavior for magazines
///Count of number of bullets in the magazine
/obj/item/ammo_box/magazine/proc/ammo_count(countempties = TRUE)
var/boolets = 0
for(var/obj/item/ammo_casing/bullet in stored_ammo)
@@ -137,12 +149,14 @@
boolets++
return boolets
///list of every bullet in the magazine
/obj/item/ammo_box/magazine/proc/ammo_list(drop_list = FALSE)
var/list/L = stored_ammo.Copy()
if(drop_list)
stored_ammo.Cut()
return L
///drops the entire contents of the magazine on the floor
/obj/item/ammo_box/magazine/proc/empty_magazine()
var/turf_mag = get_turf(src)
for(var/obj/item/ammo in stored_ammo)

View File

@@ -4,7 +4,7 @@
icon_state = "357"
ammo_type = /obj/item/ammo_casing/a357
max_ammo = 7
multiple_sprites = 1
multiple_sprites = AMMO_BOX_PER_BULLET
/obj/item/ammo_box/c38
name = "speed loader (.38)"
@@ -12,7 +12,7 @@
icon_state = "38"
ammo_type = /obj/item/ammo_casing/c38
max_ammo = 6
multiple_sprites = 1
multiple_sprites = AMMO_BOX_PER_BULLET
materials = list(MAT_METAL = 20000)
/obj/item/ammo_box/c38/trac
@@ -53,7 +53,7 @@
icon_state = "40mm"
ammo_type = /obj/item/ammo_casing/a40mm
max_ammo = 4
multiple_sprites = 1
multiple_sprites = AMMO_BOX_PER_BULLET
/obj/item/ammo_box/a762
name = "stripper clip (7.62mm)"
@@ -61,7 +61,7 @@
icon_state = "762"
ammo_type = /obj/item/ammo_casing/a762
max_ammo = 5
multiple_sprites = 1
multiple_sprites = AMMO_BOX_PER_BULLET
/obj/item/ammo_box/n762
name = "ammo box (7.62x38mmR)"
@@ -80,4 +80,4 @@
/obj/item/ammo_box/foambox/riot
icon_state = "foambox_riot"
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot
materials = list(MAT_METAL = 50000)
materials = list(MAT_METAL = 50000)

View File

@@ -3,6 +3,6 @@
icon_state = "75"
ammo_type = /obj/item/ammo_casing/caseless/a75
caliber = "75"
multiple_sprites = 2
multiple_sprites = AMMO_BOX_FULL_EMPTY
max_ammo = 8

View File

@@ -5,7 +5,7 @@
ammo_type = /obj/item/ammo_casing/c10mm
caliber = "10mm"
max_ammo = 8
multiple_sprites = 2
multiple_sprites = AMMO_BOX_FULL_EMPTY
/obj/item/ammo_box/magazine/m10mm/fire
name = "pistol magazine (10mm incendiary)"
@@ -56,4 +56,4 @@
ammo_type = /obj/item/ammo_casing/a50AE
caliber = ".50"
max_ammo = 7
multiple_sprites = 1
multiple_sprites = AMMO_BOX_PER_BULLET

View File

@@ -19,4 +19,4 @@
ammo_type = /obj/item/ammo_casing/a556
caliber = "a556"
max_ammo = 30
multiple_sprites = 2
multiple_sprites = AMMO_BOX_FULL_EMPTY

View File

@@ -23,7 +23,7 @@
name = "foam force pistol magazine"
icon_state = "9x19p"
max_ammo = 8
multiple_sprites = 2
multiple_sprites = AMMO_BOX_FULL_EMPTY
/obj/item/ammo_box/magazine/toy/pistol/riot
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot

View File

@@ -1,59 +1,91 @@
///Subtype for any kind of ballistic gun
///This has a shitload of vars on it, and I'm sorry for that, but it does make making new subtypes really easy
/obj/item/gun/ballistic
desc = "Now comes in flavors like GUN. Uses 10mm ammo, for some reason."
name = "projectile gun"
icon_state = "pistol"
w_class = WEIGHT_CLASS_NORMAL
//sound info vars
///sound when inserting magazine
var/load_sound = "gun_insert_full_magazine"
///sound when inserting an empty magazine
var/load_empty_sound = "gun_insert_empty_magazine"
///volume of loading sound
var/load_sound_volume = 40
///whether loading sound should vary
var/load_sound_vary = TRUE
///sound of racking
var/rack_sound = "gun_slide_lock"
///volume of racking
var/rack_sound_volume = 60
///whether racking sound should vary
var/rack_sound_vary = TRUE
///sound of when the bolt is locked back manually
var/lock_back_sound = "sound/weapons/pistollock.ogg"
///volume of lock back
var/lock_back_sound_volume = 60
///whether lock back varies
var/lock_back_sound_vary = TRUE
///Sound of ejecting a magazine
var/eject_sound = "gun_remove_empty_magazine"
///sound of ejecting an empty magazine
var/eject_empty_sound = "gun_remove_full_magazine"
///volume of ejecting a magazine
var/eject_sound_volume = 40
///whether eject sound should vary
var/eject_sound_vary = TRUE
///sound of dropping the bolt or releasing a slide
var/bolt_drop_sound = 'sound/weapons/gun_chamber_round.ogg'
///volume of bolt drop/slide release
var/bolt_drop_sound_volume = 60
///empty alarm sound (if enabled)
var/empty_alarm_sound = 'sound/weapons/smg_empty_alarm.ogg'
///empty alarm volume sound
var/empty_alarm_volume = 70
///whether empty alarm sound varies
var/empty_alarm_vary = TRUE
///Whether the gun will spawn loaded with a magazine
var/spawnwithmagazine = TRUE
///Compatible magazines with the gun
var/mag_type = /obj/item/ammo_box/magazine/m10mm //Removes the need for max_ammo and caliber info
var/mag_display = FALSE //Whether the sprite has a visible magazine or not
var/mag_display_ammo = FALSE //Whether the sprite has a visible ammo display or not
var/empty_indicator = FALSE //Whether the sprite has an indicator for being empty or not.
var/empty_alarm = FALSE //Whether the gun alarms when empty or not.
var/special_mags = FALSE //Whether the gun supports multiple special mag types
///Whether the sprite has a visible magazine or not
var/mag_display = FALSE
///Whether the sprite has a visible ammo display or not
var/mag_display_ammo = FALSE
///Whether the sprite has a visible indicator for being empty or not.
var/empty_indicator = FALSE
///Whether the gun alarms when empty or not.
var/empty_alarm = FALSE
///Whether the gun supports multiple special mag types
var/special_mags = FALSE
///Whether the gun is currently alarmed to prevent it from spamming sounds
var/alarmed = FALSE
//Four bolt types:
//BOLT_TYPE_STANDARD: Gun has a bolt, it stays closed while not cycling. The gun must be racked to have a bullet chambered when a mag is inserted.
//Example: c20, shotguns, m90
//BOLT_TYPE_OPEN: Gun has a bolt, it is open when ready to fire. The gun can never have a chambered bullet with no magazine, but the bolt stays ready when a mag is removed.
//Example: Some SMGs, the L6
//BOLT_TYPE_NO_BOLT: Gun has no moving bolt mechanism, it cannot be racked. Also dumps the entire contents when emptied instead of a magazine.
//Example: Break action shotguns, revolvers
//BOLT_TYPE_LOCKING: Gun has a bolt, it locks back when empty. It can be released to chamber a round if a magazine is in.
//Example: Pistols with a slide lock, some SMGs
///The bolt type of the gun, affects quite a bit of functionality, see combat.dm defines for bolt types: BOLT_TYPE_STANDARD; BOLT_TYPE_LOCKING; BOLT_TYPE_OPEN; BOLT_TYPE_NO_BOLT
var/bolt_type = BOLT_TYPE_STANDARD
var/bolt_locked = FALSE //Used for locking bolt and open bolt guns. Set a bit differently for the two but prevents firing when true for both.
var/bolt_wording = "bolt" //bolt, slide, etc.
var/semi_auto = TRUE //Whether the gun has to be racked each shot or not.
///Used for locking bolt and open bolt guns. Set a bit differently for the two but prevents firing when true for both.
var/bolt_locked = FALSE
///Whether the gun has to be racked each shot or not.
var/semi_auto = TRUE
///Actual magazine currently contained within the gun
var/obj/item/ammo_box/magazine/magazine
var/casing_ejector = TRUE //whether the gun ejects the chambered casing
var/internal_magazine = FALSE //Whether the gun has an internal magazine or a detatchable one. Overridden by BOLT_TYPE_NO_BOLT.
///whether the gun ejects the chambered casing
var/casing_ejector = TRUE
///Whether the gun has an internal magazine or a detatchable one. Overridden by BOLT_TYPE_NO_BOLT.
var/internal_magazine = FALSE
///Phrasing of the bolt in examine and notification messages; ex: bolt, slide, etc.
var/bolt_wording = "bolt"
///Phrasing of the magazine in examine and notification messages; ex: magazine, box, etx
var/magazine_wording = "magazine"
///Phrasing of the cartridge in examine and notification messages; ex: bullet, shell, dart, etc.
var/cartridge_wording = "bullet"
///length between individual racks
var/rack_delay = 5
///time of the most recent rack, used for cooldown purposes
var/recent_rack = 0
///Whether the gun can be tacloaded by slapping a fresh magazine directly on it
var/tac_reloads = TRUE //Snowflake mechanic no more.
///Whether the gun can be sawn off by sawing tools
var/can_be_sawn_off = FALSE
/obj/item/gun/ballistic/Initialize()
@@ -121,6 +153,7 @@
if (chamber_next_round && (magazine?.max_ammo > 1))
chamber_round()
///Used to chamber a new round and eject the old one
/obj/item/gun/ballistic/proc/chamber_round(keep_bullet = FALSE)
if (chambered || !magazine)
return
@@ -129,6 +162,7 @@
if (bolt_type != BOLT_TYPE_OPEN)
chambered.forceMove(src)
///updates a bunch of racking related stuff and also handles the sound effects and the like
/obj/item/gun/ballistic/proc/rack(mob/user = null)
if (bolt_type == BOLT_TYPE_NO_BOLT) //If there's no bolt, nothing to rack
return
@@ -148,6 +182,7 @@
playsound(src, rack_sound, rack_sound_volume, rack_sound_vary)
update_icon()
///Drops the bolt from a locked position
/obj/item/gun/ballistic/proc/drop_bolt(mob/user = null)
playsound(src, bolt_drop_sound, bolt_drop_sound_volume, FALSE)
if (user)
@@ -156,6 +191,7 @@
bolt_locked = FALSE
update_icon()
///Handles all the logic needed for magazine insertion
/obj/item/gun/ballistic/proc/insert_magazine(mob/user, obj/item/ammo_box/magazine/AM, display_message = TRUE)
if(!istype(AM, mag_type))
to_chat(user, "<span class='warning'>\The [AM] doesn't seem to fit into \the [src]...</span>")
@@ -173,6 +209,7 @@
to_chat(user, "<span class='warning'>You cannot seem to get \the [src] out of your hands!</span>")
return FALSE
///Handles all the logic of magazine ejection, if tac_load is set that magazine will be tacloaded in the place of the old eject
/obj/item/gun/ballistic/proc/eject_magazine(mob/user, display_message = TRUE, obj/item/ammo_box/magazine/tac_load = null)
if(bolt_type == BOLT_TYPE_OPEN)
chambered = null
@@ -252,8 +289,8 @@
bonus_spread += SAWN_OFF_ACC_PENALTY
. = ..()
///Installs a new suppressor, assumes that the suppressor is already in the contents of src
/obj/item/gun/ballistic/proc/install_suppressor(obj/item/suppressor/S)
// this proc assumes that the suppressor is already inside src
suppressed = S
w_class += S.w_class //so pistols do not fit in pockets when suppressed
update_icon()
@@ -274,6 +311,7 @@
update_icon()
return
///Prefire empty checks for the bolt drop
/obj/item/gun/ballistic/proc/prefire_empty_checks()
if (!chambered && !get_ammo())
if (bolt_type == BOLT_TYPE_OPEN && !bolt_locked)
@@ -281,7 +319,7 @@
playsound(src, bolt_drop_sound, bolt_drop_sound_volume)
update_icon()
///postfire empty checks for bolt locking and sound alarms
/obj/item/gun/ballistic/proc/postfire_empty_checks()
if (!chambered && !get_ammo())
if (!alarmed && empty_alarm)
@@ -344,6 +382,7 @@
if (suppressed)
. += "It has a suppressor attached that can be removed with <b>alt+click</b>."
///Gets the number of bullets in the gun
/obj/item/gun/ballistic/proc/get_ammo(countchambered = TRUE)
var/boolets = 0 //mature var names for mature people
if (chambered && countchambered)
@@ -352,6 +391,7 @@
boolets += magazine.ammo_count()
return boolets
///gets a list of every bullet in the gun
/obj/item/gun/ballistic/proc/get_ammo_list(countchambered = TRUE, drop_all = FALSE)
var/list/rounds = list()
if(chambered && countchambered)
@@ -397,6 +437,7 @@ GLOBAL_LIST_INIT(gun_saw_types, typecacheof(list(
/obj/item/nullrod/chainsaw,
/obj/item/mounted_chainsaw)))
///Handles all the logic of sawing off guns,
/obj/item/gun/ballistic/proc/sawoff(mob/user, obj/item/saw)
if(!saw.is_sharp() || !is_type_in_typecache(saw, GLOB.gun_saw_types)) //needs to be sharp. Otherwise turned off eswords can cut this.
return
@@ -429,7 +470,7 @@ GLOBAL_LIST_INIT(gun_saw_types, typecacheof(list(
update_icon()
return TRUE
// Sawing guns related proc
///used for sawing guns, causes the gun to fire without the input of the user
/obj/item/gun/ballistic/proc/blow_up(mob/user)
. = FALSE
for(var/obj/item/ammo_casing/AC in magazine.stored_ammo)

View File

@@ -47,15 +47,25 @@
///////////////////////////////////////////////////////////////////////////////////
/// Holder for a bunch of [/datum/reagent]
/datum/reagents
/// The reagents being held
var/list/datum/reagent/reagent_list = new/list()
/// Current volume of all the reagents
var/total_volume = 0
/// Max volume of this holder
var/maximum_volume = 100
/// The atom this holder is attached to
var/atom/my_atom = null
/// Current temp of the holder volume
var/chem_temp = 150
/// unused
var/last_tick = 1
/// see [/datum/reagents/proc/metabolize] for usage
var/addiction_tick = 1
/// currently addicted reagents
var/list/datum/reagent/addiction_list = new/list()
/// various flags, see code\__DEFINES\reagents.dm
var/flags
/datum/reagents/New(maximum=100, new_flags=0)
@@ -81,7 +91,9 @@
my_atom.reagents = null
my_atom = null
// Used in attack logs for reagents in pills and such
/**
* Used in attack logs for reagents in pills and such
*/
/datum/reagents/proc/log_list()
if(!length(reagent_list))
return "no reagents"
@@ -93,6 +105,7 @@
//Using IDs because SOME chemicals (I'm looking at you, chlorhydrate-beer) have the same names as other chemicals.
return english_list(data)
/// Remove an amount of reagents without caring about what they are
/datum/reagents/proc/remove_any(amount = 1)
var/list/cached_reagents = reagent_list
var/total_transfered = 0
@@ -119,6 +132,7 @@
handle_reactions()
return total_transfered
/// Removes all reagents from this holder
/datum/reagents/proc/remove_all(amount = 1)
var/list/cached_reagents = reagent_list
if(total_volume > 0)
@@ -131,6 +145,7 @@
handle_reactions()
return amount
/// Get the name of the reagent there is the most of in this holder
/datum/reagents/proc/get_master_reagent_name()
var/list/cached_reagents = reagent_list
var/name
@@ -143,6 +158,7 @@
return name
/// Get the id of the reagent there is the most of in this holder
/datum/reagents/proc/get_master_reagent_id()
var/list/cached_reagents = reagent_list
var/max_type
@@ -155,6 +171,7 @@
return max_type
/// Get a reference to the reagent there is the most of in this holder
/datum/reagents/proc/get_master_reagent()
var/list/cached_reagents = reagent_list
var/datum/reagent/master
@@ -167,8 +184,22 @@
return master
/**
* Transfer some stuff from this holder to a target object
*
* Arguments:
* * obj/target - Target to attempt transfer to
* * amount - amount of reagent volume to transfer
* * multiplier - multiplies amount of each reagent by this number
* * preserve_data - if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred.
* * no_react - passed through to [/datum/reagents/proc/add_reagent]
* * mob/transfered_by - used for logging
* * remove_blacklisted - skips transferring of reagents with can_synth = FALSE
* * method - passed through to [/datum/reagents/proc/react_single] and [/datum/reagent/proc/on_transfer]
* * show_message - passed through to [/datum/reagents/proc/react_single]
* * round_robin - if round_robin=TRUE, so transfer 5 from 15 water, 15 sugar and 15 plasma becomes 10, 15, 15 instead of 13.3333, 13.3333 13.3333. Good if you hate floating point errors
*/
/datum/reagents/proc/trans_to(obj/target, amount = 1, multiplier = 1, preserve_data = TRUE, no_react = FALSE, mob/transfered_by, remove_blacklisted = FALSE)
//if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred.
var/list/cached_reagents = reagent_list
if(!target || !total_volume)
return
@@ -210,6 +241,7 @@
src.handle_reactions()
return amount
/// Copies the reagents to the target object
/datum/reagents/proc/copy_to(obj/target, amount=1, multiplier=1, preserve_data=1)
var/list/cached_reagents = reagent_list
if(!target || !total_volume)
@@ -241,6 +273,7 @@
src.handle_reactions()
return amount
/// Transfer a specific reagent id to the target object
/datum/reagents/proc/trans_id_to(obj/target, reagent, amount=1, preserve_data=1)//Not sure why this proc didn't exist before. It does now! /N
var/list/cached_reagents = reagent_list
if (!target)
@@ -269,6 +302,14 @@
R.handle_reactions()
return amount
/**
* Triggers metabolizing the reagents in this holder
*
* Arguments:
* * mob/living/carbon/C - The mob to metabolize in, if null it uses [/datum/reagents/var/my_atom]
* * can_overdose - Allows overdosing
* * liverless - Stops reagents that aren't set as [/datum/reagent/var/self_consuming] from metabolizing
*/
/datum/reagents/proc/metabolize(mob/living/carbon/C, can_overdose = FALSE, liverless = FALSE)
var/list/cached_reagents = reagent_list
var/list/cached_addictions = addiction_list
@@ -338,7 +379,8 @@
C.update_stamina()
update_total()
//Signals that metabolization has stopped, triggering the end of trait-based effects
/// Removes addiction to a specific reagent on [/datum/reagents/var/my_atom]
/// Signals that metabolization has stopped, triggering the end of trait-based effects
/datum/reagents/proc/end_metabolization(mob/living/carbon/C, keep_liverless = TRUE)
var/list/cached_reagents = reagent_list
for(var/reagent in cached_reagents)
@@ -353,6 +395,13 @@
R.metabolizing = FALSE
R.on_mob_end_metabolize(C)
/**
* Calls [/datum/reagent/proc/on_move] on every reagent in this holder
*
* Arguments:
* * atom/A - passed to on_move
* * Running - passed to on_move
*/
/datum/reagents/proc/conditional_update_move(atom/A, Running = 0)
var/list/cached_reagents = reagent_list
for(var/reagent in cached_reagents)
@@ -360,6 +409,12 @@
R.on_move (A, Running)
update_total()
/**
* Calls [/datum/reagent/proc/on_update] on every reagent in this holder
*
* Arguments:
* * atom/A - passed to on_update
*/
/datum/reagents/proc/conditional_update(atom/A)
var/list/cached_reagents = reagent_list
for(var/reagent in cached_reagents)
@@ -367,6 +422,7 @@
R.on_update (A)
update_total()
/// Handle any reactions possible in this holder
/datum/reagents/proc/handle_reactions()
if(flags & NO_REACT)
return //Yup, no reactions here. No siree.
@@ -486,6 +542,7 @@
update_total()
return 0
/// Remove every reagent except this one
/datum/reagents/proc/isolate_reagent(reagent)
var/list/cached_reagents = reagent_list
for(var/_reagent in cached_reagents)
@@ -494,6 +551,7 @@
del_reagent(R.type)
update_total()
/// Fuck this one reagent
/datum/reagents/proc/del_reagent(reagent)
var/list/cached_reagents = reagent_list
for(var/_reagent in cached_reagents)
@@ -512,6 +570,7 @@
my_atom.on_reagent_change(DEL_REAGENT)
return 1
/// Updates [/datum/reagents/var/total_volume]
/datum/reagents/proc/update_total()
var/list/cached_reagents = reagent_list
total_volume = 0
@@ -524,6 +583,7 @@
return 0
/// Removes all reagents
/datum/reagents/proc/clear_reagents()
var/list/cached_reagents = reagent_list
for(var/reagent in cached_reagents)
@@ -531,6 +591,12 @@
del_reagent(R.type)
return 0
/**
* Applies the relevant reaction_ proc for every reagent in this holder
* * [/datum/reagent/proc/reaction_mob]
* * [/datum/reagent/proc/reaction_turf]
* * [/datum/reagent/proc/reaction_obj]
*/
/datum/reagents/proc/reaction(atom/A, method = TOUCH, volume_modifier = 1, show_message = 1)
var/react_type
if(isliving(A))
@@ -559,12 +625,14 @@
if("OBJ")
R.reaction_obj(A, R.volume * volume_modifier, show_message)
/// Same as [/datum/reagents/proc/reaction] but only for one reagent
/// Is this holder full or not
/datum/reagents/proc/holder_full()
if(total_volume >= maximum_volume)
return TRUE
return FALSE
//Returns the average specific heat for all reagents currently in this holder.
/// Returns the average specific heat for all reagents currently in this holder.
/datum/reagents/proc/specific_heat()
. = 0
var/cached_amount = total_volume //cache amount
@@ -577,6 +645,16 @@
var/S = specific_heat()
chem_temp = clamp(chem_temp + (J / (S * total_volume)), 2.7, 1000)
/**
* Adds a reagent to this holder
*
* Arguments:
* * reagent - The reagent id to add
* * amount - Amount to add
* * list/data - Any reagent data for this reagent, used for transferring data with reagents
* * reagtemp - Temperature of this reagent, will be equalized
* * no_react - prevents reactions being triggered by this addition
*/
/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = 300, no_react = 0)
if(!isnum(amount) || !amount)
return FALSE
@@ -648,11 +726,13 @@
handle_reactions()
return TRUE
/datum/reagents/proc/add_reagent_list(list/list_reagents, list/data=null) // Like add_reagent but you can enter a list. Format it like this: list(/datum/reagent/toxin = 10, "beer" = 15)
/// Like add_reagent but you can enter a list. Format it like this: list(/datum/reagent/toxin = 10, "beer" = 15)
/datum/reagents/proc/add_reagent_list(list/list_reagents, list/data=null)
for(var/r_id in list_reagents)
var/amt = list_reagents[r_id]
add_reagent(r_id, amt, data)
/// Remove a specific reagent
/datum/reagents/proc/remove_reagent(reagent, amount, safety)//Added a safety check for the trans_id_to
if(isnull(amount))
@@ -683,6 +763,7 @@
return FALSE
/// Check if this holder contains this reagent
/datum/reagents/proc/has_reagent(reagent, amount = -1, needs_metabolizing = FALSE)
var/list/cached_reagents = reagent_list
for(var/_reagent in cached_reagents)
@@ -702,6 +783,7 @@
return 0
/// Get the amount of this reagent
/datum/reagents/proc/get_reagent_amount(reagent)
var/list/cached_reagents = reagent_list
for(var/_reagent in cached_reagents)
@@ -711,6 +793,7 @@
return 0
/// Get a comma separated string of every reagent name in this holder
/datum/reagents/proc/get_reagents()
var/list/names = list()
var/list/cached_reagents = reagent_list
@@ -720,7 +803,8 @@
return jointext(names, ",")
/datum/reagents/proc/remove_all_type(reagent_type, amount, strict = 0, safety = 1) // Removes all reagent of X type. @strict set to 1 determines whether the childs of the type are included.
/// Removes all reagent of X type. @strict set to 1 determines whether the childs of the type are included.
/datum/reagents/proc/remove_all_type(reagent_type, amount, strict = 0, safety = 1)
if(!isnum(amount))
return 1
var/list/cached_reagents = reagent_list
@@ -743,7 +827,7 @@
return has_removed_reagent
//two helper functions to preserve data across reactions (needed for xenoarch)
/// helper function to preserve data across reactions (needed for xenoarch)
/datum/reagents/proc/get_data(reagent_id)
var/list/cached_reagents = reagent_list
for(var/reagent in cached_reagents)
@@ -751,6 +835,7 @@
if(R.type == reagent_id)
return R.data
/// helper function to preserve data across reactions (needed for xenoarch)
/datum/reagents/proc/set_data(reagent_id, new_data)
var/list/cached_reagents = reagent_list
for(var/reagent in cached_reagents)
@@ -758,6 +843,7 @@
if(R.type == reagent_id)
R.data = new_data
/// Shallow copies (deep copy of viruses) data from the provided reagent into our copy of that reagent
/datum/reagents/proc/copy_data(datum/reagent/current_reagent)
if(!current_reagent || !current_reagent.data)
return null
@@ -779,12 +865,18 @@
return trans_data
/// Get a reference to the reagent if it exists
/datum/reagents/proc/get_reagent(type)
var/list/cached_reagents = reagent_list
. = locate(type) in cached_reagents
/**
* Returns what this holder's reagents taste like
*
* Arguments:
* * minimum_percent - the lower the minimum percent, the more sensitive the message is.
*/
/datum/reagents/proc/generate_taste_message(minimum_percent=15)
// the lower the minimum percent, the more sensitive the message is.
var/list/out = list()
var/list/tastes = list() //descriptor = strength
if(minimum_percent <= 100)
@@ -828,6 +920,7 @@
return english_list(out, "something indescribable")
/// Applies heat to this holder
/datum/reagents/proc/expose_temperature(var/temperature, var/coeff=0.02)
var/temp_delta = (temperature - chem_temp) * coeff
if(temp_delta > 0)
@@ -840,8 +933,13 @@
///////////////////////////////////////////////////////////////////////////////////
// Convenience proc to create a reagents holder for an atom
// Max vol is maximum volume of holder
/**
* Convenience proc to create a reagents holder for an atom
*
* Arguments:
* * max_vol - maximum volume of holder
* * flags - flags to pass to the holder
*/
/atom/proc/create_reagents(max_vol, flags)
if(reagents)
qdel(reagents)

View File

@@ -14,37 +14,65 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
//Toxin & acid reagents
//Hydroponics stuff
/// A single reagent
/datum/reagent
/// datums don't have names by default
var/name = "Reagent"
/// nor do they have descriptions
var/description = ""
var/specific_heat = SPECIFIC_HEAT_DEFAULT //J/(K*mol)
///J/(K*mol)
var/specific_heat = SPECIFIC_HEAT_DEFAULT
/// used by taste messages
var/taste_description = "metaphorical salt"
var/taste_mult = 1 //how this taste compares to others. Higher values means it is more noticable
var/glass_name = "glass of ...what?" // use for specialty drinks.
///how this taste compares to others. Higher values means it is more noticable
var/taste_mult = 1
/// use for specialty drinks.
var/glass_name = "glass of ...what?"
/// desc applied to glasses with this reagent
var/glass_desc = "You can't really tell what this is."
var/glass_icon_state = null // Otherwise just sets the icon to a normal glass with the mixture of the reagents in the glass.
/// Otherwise just sets the icon to a normal glass with the mixture of the reagents in the glass.
var/glass_icon_state = null
/// used for shot glasses, mostly for alcohol
var/shot_glass_icon_state = null
/// reagent holder this belongs to
var/datum/reagents/holder = null
/// LIQUID, SOLID, GAS
var/reagent_state = LIQUID
/// special data associated with this like viruses etc
var/list/data
/// increments everytime on_mob_life is called
var/current_cycle = 0
var/volume = 0 //pretend this is moles
///pretend this is moles
var/volume = 0
/// color it looks in containers etc
var/color = "#000000" // rgb: 0, 0, 0
var/can_synth = TRUE // can this reagent be synthesized? (for example: odysseus syringe gun)
var/metabolization_rate = REAGENTS_METABOLISM //how fast the reagent is metabolized by the mob
/// can this reagent be synthesized? (for example: odysseus syringe gun)
var/can_synth = TRUE
///how fast the reagent is metabolized by the mob
var/metabolization_rate = REAGENTS_METABOLISM
/// appears unused
var/overrides_metab = 0
/// above this overdoses happen
var/overdose_threshold = 0
/// above this amount addictions start
var/addiction_threshold = 0
/// increases as addiction gets worse
var/addiction_stage = 0
var/overdosed = 0 // You fucked up and this is now triggering its overdose effects, purge that shit quick.
/// You fucked up and this is now triggering its overdose effects, purge that shit quick.
var/overdosed = 0
///if false stops metab in liverless mobs
var/self_consuming = FALSE
var/reagent_weight = 1 //affects how far it travels when sprayed
///affects how far it travels when sprayed
var/reagent_weight = 1
///is it currently metabolizing
var/metabolizing = FALSE
/// Are we from a material? We might wanna know that for special stuff. Like metalgen. Is replaced with a ref of the material on New()
/datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references
. = ..()
holder = null
/// Applies this reagent to a [/mob/living]
/datum/reagent/proc/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1, touch_protection = 0)
if(!istype(M))
return 0
@@ -56,78 +84,90 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
M.reagents.add_reagent(type, amount)
return 1
/// Applies this reagent to an [/obj]
/datum/reagent/proc/reaction_obj(obj/O, volume)
return
/// Applies this reagent to a [/turf]
/datum/reagent/proc/reaction_turf(turf/T, volume)
return
/// Called from [/datum/reagents/proc/metabolize]
/datum/reagent/proc/on_mob_life(mob/living/carbon/M)
current_cycle++
holder.remove_reagent(type, metabolization_rate * M.metabolism_efficiency) //By default it slowly disappears.
return
// Called when this reagent is first added to a mob
///Called after a reagent is transfered
/datum/reagent/proc/on_transfer(atom/A, method=TOUCH, trans_volume)
/// Called when this reagent is first added to a mob
/datum/reagent/proc/on_mob_add(mob/living/L)
return
// Called when this reagent is removed while inside a mob
/// Called when this reagent is removed while inside a mob
/datum/reagent/proc/on_mob_delete(mob/living/L)
return
// Called when this reagent first starts being metabolized by a liver
/// Called when this reagent first starts being metabolized by a liver
/datum/reagent/proc/on_mob_metabolize(mob/living/L)
return
// Called when this reagent stops being metabolized by a liver
/// Called when this reagent stops being metabolized by a liver
/datum/reagent/proc/on_mob_end_metabolize(mob/living/L)
return
/// Called by [/datum/reagents/proc/conditional_update_move]
/datum/reagent/proc/on_move(mob/M)
return
// Called after add_reagents creates a new reagent.
/// Called after add_reagents creates a new reagent.
/datum/reagent/proc/on_new(data)
return
// Called when two reagents of the same are mixing.
/// Called when two reagents of the same are mixing.
/datum/reagent/proc/on_merge(data)
return
/// Called by [/datum/reagents/proc/conditional_update]
/datum/reagent/proc/on_update(atom/A)
return
// Called when the reagent container is hit by an explosion
/// Called when the reagent container is hit by an explosion
/datum/reagent/proc/on_ex_act(severity)
return
// Called if the reagent has passed the overdose threshold and is set to be triggering overdose effects
/// Called if the reagent has passed the overdose threshold and is set to be triggering overdose effects
/datum/reagent/proc/overdose_process(mob/living/M)
return
/// Called when an overdose starts
/datum/reagent/proc/overdose_start(mob/living/M)
to_chat(M, "<span class='userdanger'>You feel like you took too much of [name]!</span>")
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[type]_overdose", /datum/mood_event/overdose, name)
return
/// Called when addiction hits stage1, see [/datum/reagents/proc/metabolize]
/datum/reagent/proc/addiction_act_stage1(mob/living/M)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[type]_overdose", /datum/mood_event/withdrawal_light, name)
if(prob(30))
to_chat(M, "<span class='notice'>You feel like having some [name] right about now.</span>")
return
/// Called when addiction hits stage2, see [/datum/reagents/proc/metabolize]
/datum/reagent/proc/addiction_act_stage2(mob/living/M)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[type]_overdose", /datum/mood_event/withdrawal_medium, name)
if(prob(30))
to_chat(M, "<span class='notice'>You feel like you need [name]. You just can't get enough.</span>")
return
/// Called when addiction hits stage3, see [/datum/reagents/proc/metabolize]
/datum/reagent/proc/addiction_act_stage3(mob/living/M)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[type]_overdose", /datum/mood_event/withdrawal_severe, name)
if(prob(30))
to_chat(M, "<span class='danger'>You have an intense craving for [name].</span>")
return
/// Called when addiction hits stage4, see [/datum/reagents/proc/metabolize]
/datum/reagent/proc/addiction_act_stage4(mob/living/M)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[type]_overdose", /datum/mood_event/withdrawal_critical, name)
if(prob(30))

View File

@@ -11,10 +11,10 @@
throw_speed = 3
throw_range = 6
grind_results = list()
var/Uses = 1 // uses before it goes inert
var/qdel_timer = null // deletion timer, for delayed reactions
var/effectmod
var/list/activate_reagents = list() //Reagents required for activation
var/Uses = 1 ///uses before it goes inert
var/qdel_timer = null ///deletion timer, for delayed reactions
var/effectmod ///Which type of crossbred
var/list/activate_reagents = list() ///Reagents required for activation
var/recurring = FALSE
/obj/item/slime_extract/examine(mob/user)
@@ -44,12 +44,24 @@
if(Uses)
grind_results[/datum/reagent/toxin/slimejelly] = 20
//Effect when activated by a Luminescent. Separated into a minor and major effect. Returns cooldown in deciseconds.
/**
* Effect when activated by a Luminescent.
*
* This proc is called whenever a Luminescent consumes a slime extract. Each one is separated into major and minor effects depending on the extract. Cooldown is measured in deciseconds.
*
* * arg1 - The mob absorbing the slime extract.
* * arg2 - The valid species for the absorbtion. Should always be a Luminescent unless something very major has changed.
* * arg3 - Whether or not the activation is major or minor. Major activations have large, complex effects, minor are simple.
*/
/obj/item/slime_extract/proc/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
to_chat(user, "<span class='notice'>Nothing happened... This slime extract cannot be activated this way.</span>")
return 0
//Core-crossing: Feeding adult slimes extracts to obtain a much more powerful, single extract.
/**
* Core-crossing: Feeding adult slimes extracts to obtain a much more powerful, single extract.
*
* By using a valid core on a living adult slime, then feeding it nine more of the same type, you can mutate it into more useful items. Not every slime type has an implemented core cross.
*/
/obj/item/slime_extract/attack(mob/living/simple_animal/slime/M, mob/user)
if(!isslime(M))
return ..()
@@ -608,6 +620,16 @@
////Slime-derived potions///
/**
* #Slime potions
*
* Feed slimes potions either by hand or using the slime console.
*
* Slime potions either augment the slime's behavior, its extract output, or its intelligence. These all come either from extract effects or cross cores.
* A few of the more powerful ones can modify someone's equipment or gender.
* New ones should probably be accessible only through cross cores as all the normal core types already have uses. Rule of thumb is 'stronger effects go in cross cores'.
*/
/obj/item/slimepotion
name = "slime potion"
desc = "A hard yet gelatinous capsule excreted by a slime, containing mysterious substances."
@@ -976,6 +998,8 @@
imp.implant(M, user)
qdel(src)
///Definitions for slime products that don't have anywhere else to go (Floor tiles, blueprints).
/obj/item/stack/tile/bluespace
name = "bluespace floor tile"
singular_name = "floor tile"

View File

@@ -11,17 +11,26 @@
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
anchored = TRUE
//
/// The identifier of the port or ship.
/// This will be used in numerous other places like the console,
/// stationary ports and whatnot to tell them your ship's mobile
/// port can be used in these places, or the docking port is compatible, etc.
var/id
// this should point -away- from the dockingport door, ie towards the ship
///Common standard is for this to point -away- from the dockingport door, ie towards the ship
dir = NORTH
var/width = 0 //size of covered area, perpendicular to dir
var/height = 0 //size of covered area, parallel to dir
var/dwidth = 0 //position relative to covered area, perpendicular to dir
var/dheight = 0 //position relative to covered area, parallel to dir
///size of covered area, perpendicular to dir. You shouldn't modify this for mobile dockingports, set automatically.
var/width = 0
///size of covered area, parallel to dir. You shouldn't modify this for mobile dockingports, set automatically.
var/height = 0
///position relative to covered area, perpendicular to dir. You shouldn't modify this for mobile dockingports, set automatically.
var/dwidth = 0
///position relative to covered area, parallel to dir. You shouldn't modify this for mobile dockingports, set automatically.
var/dheight = 0
var/area_type
var/hidden = FALSE //are we invisible to shuttle navigation computers?
///are we invisible to shuttle navigation computers?
var/hidden = FALSE
//these objects are indestructible
/obj/docking_port/Destroy(force)
@@ -243,18 +252,25 @@
var/list/shuttle_areas
var/timer //used as a timer (if you want time left to complete move, use timeLeft proc)
///used as a timer (if you want time left to complete move, use timeLeft proc)
var/timer
var/last_timer_length
///current shuttle mode
var/mode = SHUTTLE_IDLE
///time spent in transit (deciseconds). Should not be lower then 10 seconds without editing the animation of the hyperspace ripples.
var/callTime = 100
/// time spent "starting the engines". Also rate limits how often we try to reserve transit space if its ever full of transiting shuttles.
var/ignitionTime = 55
/// time spent after arrival before being able to begin ignition
var/rechargeTime = 0
/// time spent after transit 'landing' before actually arriving
var/prearrivalTime = 0
var/mode = SHUTTLE_IDLE //current shuttle mode
var/callTime = 100 //time spent in transit (deciseconds). Should not be lower then 10 seconds without editing the animation of the hyperspace ripples.
var/ignitionTime = 55 // time spent "starting the engines". Also rate limits how often we try to reserve transit space if its ever full of transiting shuttles.
var/rechargeTime = 0 // time spent after arrival before being able to begin ignition
var/prearrivalTime = 0 // time spent after transit 'landing' before actually arriving
// The direction the shuttle prefers to travel in
/// The direction the shuttle prefers to travel in, ie what direction
/// the animation will cause it to appear to be traveling in
var/preferred_direction = NORTH
// And the angle from the front of the shuttle to the port
/// relative direction of the docking port from the front of the shuttle
/// NORTH is towards front, EAST would be starboard side, WEST port, etc.
var/port_direction = NORTH
var/obj/docking_port/stationary/destination
@@ -264,14 +280,16 @@
var/launch_status = NOLAUNCH
///Whether or not you want your ship to knock people down, and also whether it will throw them several tiles upon launching.
var/list/movement_force = list("KNOCKDOWN" = 3, "THROW" = 0)
var/list/ripples = list()
var/engine_coeff = 1 //current engine coeff
var/current_engines = 0 //current engine power
var/initial_engines = 0 //initial engine power
var/engine_coeff = 1
var/current_engines = 0
var/initial_engines = 0
var/list/engine_list = list()
var/can_move_docking_ports = FALSE //if this shuttle can move docking ports other than the one it is docked at
///if this shuttle can move docking ports other than the one it is docked at
var/can_move_docking_ports = FALSE
var/list/hidden_turfs = list()
/obj/docking_port/mobile/proc/register()

View File

@@ -1,9 +1,27 @@
/**
* Get the organ object from the mob matching the passed in typepath
*
* Arguments:
* * typepath The typepath of the organ to get
*/
/mob/proc/getorgan(typepath)
return
/**
* Get organ objects by zone
*
* This will return a list of all the organs that are relevant to the zone that is passedin
*
* Arguments:
* * zone [a BODY_ZONE_X define](https://github.com/tgstation/tgstation/blob/master/code/__DEFINES/combat.dm#L187-L200)
*/
/mob/proc/getorganszone(zone)
return
/**
* Get an organ relating to a specific slot
*
* Arguments:
* * slot Slot to get the organ from
*/
/mob/proc/getorganslot(slot)
return

View File

@@ -15,17 +15,31 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
*/
#define MAX_VENDING_INPUT_AMOUNT 30
/**
* # vending record datum
*
* A datum that represents a product that is vendable
*/
/datum/data/vending_product
name = "generic"
///Typepath of the product that is created when this record "sells"
var/product_path = null
///How many of this product we currently have
var/amount = 0
///How many we can store at maximum
var/max_amount = 0
///Does the item have a custom price override
var/custom_price
///Does the item have a custom premium price override
var/custom_premium_price
///Whether spessmen with an ID with an age below AGE_MINOR (21 by default) can buy this item
var/age_restricted = FALSE
/**
* # vending machines
*
* Captalism in the year 2525, everything in a vending machine, even love
*/
/obj/machinery/vending
name = "\improper Vendomat"
desc = "A generic vending machine."
@@ -41,56 +55,115 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
armor = list("melee" = 20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70)
circuit = /obj/item/circuitboard/machine/vendor
payment_department = ACCOUNT_SRV
var/active = 1 //No sales pitches if off!
var/vend_ready = 1 //Are we ready to vend?? Is it time??
/// Is the machine active (No sales pitches if off)!
var/active = 1
///Are we ready to vend?? Is it time??
var/vend_ready = 1
///Next world time to send a purchase message
var/purchase_message_cooldown
///Last mob to shop with us
var/last_shopper
// To be filled out at compile time
var/list/products = list() //For each, use the following pattern:
var/list/contraband = list() //list(/type/path = amount, /type/path2 = amount2)
var/list/premium = list() //No specified amount = only one in stock
/**
* List of products this machine sells
*
* form should be list(/type/path = amount, /type/path2 = amount2)
*/
var/list/products = list()
/**
* List of products this machine sells when you hack it
*
* form should be list(/type/path = amount, /type/path2 = amount2)
*/
var/list/contraband = list()
/**
* List of premium products this machine sells
*
* form should be list(/type/path, /type/path2) as there is only ever one in stock
*/
var/list/premium = list()
///String of slogans separated by semicolons, optional
var/product_slogans = ""
///String of small ad messages in the vending screen - random chance
var/product_ads = ""
var/product_slogans = "" //String of slogans separated by semicolons, optional
var/product_ads = "" //String of small ad messages in the vending screen - random chance
var/list/product_records = list()
var/list/hidden_records = list()
var/list/coin_records = list()
var/list/slogan_list = list()
var/list/small_ads = list() //Small ad messages in the vending screen - random chance of popping up whenever you open it
var/vend_reply //Thank you for shopping!
///Small ad messages in the vending screen - random chance of popping up whenever you open it
var/list/small_ads = list()
///Message sent post vend (Thank you for shopping!)
var/vend_reply
///Last world tick we sent a vent reply
var/last_reply = 0
var/last_slogan = 0 //When did we last pitch?
var/slogan_delay = 6000 //How long until we can pitch again?
var/icon_vend //Icon_state when vending!
var/icon_deny //Icon_state when vending!
var/seconds_electrified = MACHINE_NOT_ELECTRIFIED //Shock customers like an airlock.
var/shoot_inventory = 0 //Fire items at customers! We're broken!
///Last world tick we sent a slogan message out
var/last_slogan = 0
///How many ticks until we can send another
var/slogan_delay = 6000
///Icon when vending an item to the user
var/icon_vend
///Icon to flash when user is denied a vend
var/icon_deny
///World ticks the machine is electified for
var/seconds_electrified = MACHINE_NOT_ELECTRIFIED
///When this is TRUE, we fire items at customers! We're broken!
var/shoot_inventory = 0
///How likely this is to happen (prob 100)
var/shoot_inventory_chance = 2
var/shut_up = 0 //Stop spouting those godawful pitches!
var/extended_inventory = 0 //can we access the hidden inventory?
//Stop spouting those godawful pitches!
var/shut_up = 0
///can we access the hidden inventory?
var/extended_inventory = 0
///Are we checking the users ID
var/scan_id = 1
///Coins that we accept?
var/obj/item/coin/coin
///Bills we accept?
var/obj/item/stack/spacecash/bill
var/chef_price = 10
///Default price of items if not overridden
var/default_price = 25
///Default price of premium items if not overridden
var/extra_price = 50
///Whether our age check is currently functional
var/age_restrictions = TRUE
var/onstation = TRUE //if it doesn't originate from off-station during mapload, everything is free
/**
* Is this item on station or not
*
* if it doesn't originate from off-station during mapload, everything is free
*/
var/onstation = TRUE
///ID's that can load this vending machine wtih refills
var/list/canload_access_list
var/list/vending_machine_input = list()
///Display header on the input view
var/input_display_header = "Custom Compartment"
var/obj/item/vending_refill/refill_canister = null //The type of refill canisters used by this machine.
//The type of refill canisters used by this machine.
var/obj/item/vending_refill/refill_canister = null
/// used for narcing on underages
var/obj/item/radio/alertradio
/obj/item/circuitboard
var/onstation = TRUE //if the circuit board originated from a vendor off station or not.
///determines if the circuit board originated from a vendor off station or not.
var/onstation = TRUE
/**
* Initialize the vending machine
*
* Builds the vending machine inventory, sets up slogans and other such misc work
*
* This also sets the onstation var to:
* * FALSE - if the machine was maploaded on a zlevel that doesn't pass the is_station_level check
* * TRUE - all other cases
*/
/obj/machinery/vending/Initialize(mapload)
var/build_inv = FALSE
if(!refill_canister)
@@ -192,7 +265,15 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
return
GLOBAL_LIST_EMPTY(vending_products)
/**
* Build the inventory of the vending machine from it's product and record lists
*
* This builds up a full set of /datum/data/vending_products from the product list of the vending machine type
* Arguments:
* * productlist - the list of products that need to be converted
* * recordlist - the list containing /datum/data/vending_product datums
* * startempty - should we set vending_product record amount from the product list (so it's prefilled at roundstart)
*/
/obj/machinery/vending/proc/build_inventory(list/productlist, list/recordlist, start_empty = FALSE)
for(var/typepath in productlist)
var/amount = productlist[typepath]
@@ -211,7 +292,14 @@ GLOBAL_LIST_EMPTY(vending_products)
R.custom_premium_price = initial(temp.custom_premium_price)
R.age_restricted = initial(temp.age_restricted)
recordlist += R
/**
* Refill a vending machine from a refill canister
*
* This takes the products from the refill canister and then fills the products,contraband and premium product categories
*
* Arguments:
* * canister - the vending canister we are refilling from
*/
/obj/machinery/vending/proc/restock(obj/item/vending_refill/canister)
if (!canister.products)
canister.products = products.Copy()
@@ -223,7 +311,13 @@ GLOBAL_LIST_EMPTY(vending_products)
. += refill_inventory(canister.products, product_records)
. += refill_inventory(canister.contraband, hidden_records)
. += refill_inventory(canister.premium, coin_records)
/**
* Refill our inventory from the passed in product list into the record list
*
* Arguments:
* * productlist - list of types -> amount
* * recordlist - existing record datums
*/
/obj/machinery/vending/proc/refill_inventory(list/productlist, list/recordlist)
. = 0
for(var/R in recordlist)
@@ -233,7 +327,11 @@ GLOBAL_LIST_EMPTY(vending_products)
productlist[record.product_path] -= diff
record.amount += diff
. += diff
/**
* Set up a refill canister that matches this machines products
*
* This is used when the machine is deconstructed, so the items aren't "lost"
*/
/obj/machinery/vending/proc/update_canister()
if (!component_parts)
return
@@ -246,6 +344,9 @@ GLOBAL_LIST_EMPTY(vending_products)
R.contraband = unbuild_inventory(hidden_records)
R.premium = unbuild_inventory(coin_records)
/**
* Given a record list, go through and and return a list of type -> amount
*/
/obj/machinery/vending/proc/unbuild_inventory(list/recordlist)
. = list()
for(var/R in recordlist)
@@ -555,7 +656,14 @@ GLOBAL_LIST_EMPTY(vending_products)
if(shoot_inventory && prob(shoot_inventory_chance))
throw_item()
/**
* Speak the given message verbally
*
* Checks if the machine is powered and the message exists
*
* Arguments:
* * message - the message to speak
*/
/obj/machinery/vending/proc/speak(message)
if(stat & (BROKEN|NOPOWER))
return
@@ -577,6 +685,12 @@ GLOBAL_LIST_EMPTY(vending_products)
update_icon()
//Somebody cut an important wire and now we're following a new definition of "pitch."
/**
* Throw an item from our internal inventory out in front of us
*
* This is called when we are hacked, it selects a random product from the records that has an amount > 0
* This item is then created and tossed out in front of us with a visible message
*/
/obj/machinery/vending/proc/throw_item()
var/obj/throw_item = null
var/mob/living/target = locate() in view(7,src)
@@ -601,10 +715,26 @@ GLOBAL_LIST_EMPTY(vending_products)
throw_item.throw_at(target, 16, 3)
visible_message("<span class='danger'>[src] launches [throw_item] at [target]!</span>")
return 1
/**
* A callback called before an item is tossed out
*
* Override this if you need to do any special case handling
*
* Arguments:
* * I - obj/item being thrown
*/
/obj/machinery/vending/proc/pre_throw(obj/item/I)
return
/**
* Shock the passed in user
*
* This checks we have power and that the passed in prob is passed, then generates some sparks
* and calls electrocute_mob on the user
*
* Arguments:
* * user - the user to shock
* * prb - probability the shock happens
*/
/obj/machinery/vending/proc/shock(mob/user, prb)
if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
return FALSE
@@ -616,10 +746,21 @@ GLOBAL_LIST_EMPTY(vending_products)
return TRUE
else
return FALSE
/**
* Are we able to load the item passed in
*
* Arguments:
* * I - the item being loaded
* * user - the user doing the loading
*/
/obj/machinery/vending/proc/canLoadItem(obj/item/I,mob/user)
return FALSE
/**
* Is the passed in user allowed to load this vending machines compartments
*
* Arguments:
* * user - mob that is doing the loading of the vending machine
*/
/obj/machinery/vending/proc/compartmentLoadAccessCheck(mob/user)
if(!canload_access_list)
return TRUE

View File

@@ -1,6 +1,15 @@
//This file is just for the necessary /world definition
//Try looking in game/world.dm
/**
* # World
*
* Two possibilities exist: either we are alone in the Universe or we are not. Both are equally terrifying. ~ Arthur C. Clarke
*
* The byond world object stores some basic byond level config, and has a few hub specific procs for managing hub visiblity
*
* The world /New() is the root of where a round itself begins
*/
/world
mob = /mob/dead/new_player
turf = /turf/open/space/basic