diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000000..cd6a32d5e9e
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,10 @@
+[*]
+indent_style = space
+indent_size = 2
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.dm]
+indent_style = tab
+indent_size = 4
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
index 3158997945b..c3b24c12791 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,10 +1,60 @@
-# dmm map merger hook
-# needs additional setup, see tools/mapmerge/install.txt
-*.dmm merge=merge-dmm eol=crlf
-
-# dmi icon merger hook
-# needs additional setup, see tools/dmitool/merging.txt
-*.dmi merge=merge-dmi
-
-# force changelog merging to use union
-html/changelog.html merge=union
+# dmm map merger hook
+# needs additional setup, see tools/mapmerge/install.txt
+*.dmm merge=merge-dmm eol=crlf
+
+# dmi icon merger hook
+# needs additional setup, see tools/dmitool/merging.txt
+*.dmi merge=merge-dmi
+
+# force changelog merging to use union
+html/changelog.html merge=union
+
+# Enforce Line Endings
+* text=auto
+
+*.ai binary
+*.dmi binary
+*.exe binary
+*.fla binary
+*.gif binary
+*.jar binary
+*.jpg binary
+*.mid binary
+*.ogg binary
+*.pdb binary
+*.png binary
+*.psd binary
+*.s3m binary
+*.sav binary
+*.so binary
+*.svg binary
+*.wav binary
+*.xcf binary
+*.xlsx binary
+
+*.awk text
+*.bat text
+*.conf text
+*.cpp text
+*.cs text
+*.css text
+*.dm text
+*.dmf text
+*.dmm text
+*.gitkeep text
+*.hook text
+*.html text
+*.java text
+*.js text
+*.json text
+*.log text
+*.map text
+*.md text
+*.php text
+*.py text
+*.scss text
+*.sh text
+*.sql text
+*.tmpl text
+*.txt text
+*.vue text
\ No newline at end of file
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 4949f485941..0dd0bd0ac02 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -1,5 +1,5 @@
# Licensing
-Aurora Station code is licensed under the GNU Affero General Public License version 3, which can be found in full in LICENSE-AGPL3.txt.
+Aurora Station code is licensed under the [GNU Affero General Public License version 3](https://www.gnu.org/licenses/agpl-3.0.en.html), which can be found in full in LICENSE-AGPL3.txt.
Commits with a git authorship date prior to `1420675200 +0000` (2015/01/08 00:00) are licensed under the GNU General Public License version 3, which can be found in full in LICENSE-GPL3.txt.
@@ -9,6 +9,39 @@ All assets including icons and sound are under a [Creative Commons 3.0 BY-SA](ht
# Github Standards
+### Sub-licensing External Content
+**When does this section apply to me?** When you are integrating content that is **not** licensed under [AGPLv3](https://www.gnu.org/licenses/agpl-3.0.en.html) (code)
+or [Creative Commons 3.0 BY-SA](https://creativecommons.org/licenses/by-sa/3.0/) (icons and sounds). The most common application here is for icons and sounds gathered
+from an external source or repository.
+
+As a contributor, you must do your utmost to pay respect to international copyright law. This means that, if copying code or content from an external source, you **must**
+be aware of what license it is published under. And you must ensure that the conditions of said license are followed when integrating the content into the codebase. (Sometimes
+this is not possible, and the content cannot be used.)
+
+**If you cannot locate or reasonably dicern authorship or the license associated with given content, we ask that you not submit it into a pull request.**
+
+As a courtesy, attribution of authorship is also encouraged, even if the license of the content does not require this outright. Generally this is done in the PR by declaring
+the source of the material, the author(s) (if known), and adding similar attributions to the relevant changelog entry (if applicable). This may be both done in the `author` field
+or within the plain text describing the change itself.
+
+When reading the sub-sections that follow, note that these will be **generalizations**, and the specifics will be dictated by the license itself.
+
+#### Code
+Code from most other open source SS13 code bases is GPLv3 or AGPLv3. This means that it's free to be copied without any additional effort. Though any notes of authorship within
+the code files, if presents, must be kept intact. Be wary of **Goon**: their code is licensed under CC-BY-SA-NC and is **not** directly compatible with our codebase's license.
+Porting Goon code directly is highly discouraged as a result.
+
+If the code is external, or licensed under something else (example being the TGS library), then ensure that the copyright notices within the file(s) (if present) are kept intact,
+and that a separate license file (if present in/packaged with the original source) is added to the repository. This generally means that you have to put all of the code you are
+porting in this manner into a `modules/` sub folder, and stick the license file in there.
+
+#### Other Assets (Sound, Icons)
+If the material is distributed under CC-BY-SA 3.0, then it can go straight into the relevant folders, as long as you attribute the author(s) in the PR and changelog if they can be
+identified.
+
+In any other case, create a subfolder somewhere in the relevant structure, stick the items in there, and provide a copy of the license with the content. Also, ensure that the
+license permits the intended use of the content in the appropriate manner.
+
### Peer Review
All pull requests are subject to peer review prior to being merged. After said reviews, they are given a final once-over by a maintainer and
then merged if good.
@@ -135,7 +168,7 @@ For reference, here are the standard span classes for user output, and the corre
* `` also corresponds to `\red` and is not bold.
* `` corresponds to `\blue` and is not bold.
-There exist pre-processor macros for using these spans. `span(class, text)` which is the equivilant of typing a string that looks like this: `"[text]"`.
+There exist pre-processor macros for using these spans. `span(class, text)` which is the equivalent of typing a string that looks like this: `"[text]"` and macros such as `SPAN_WARNING(text)`, `SPAN_NOTICE(text)`, `SPAN_DANGER(text)`.
The stylesheet available for use within DM can be found in `code/stylesheet.dm`.
@@ -186,3 +219,24 @@ for (var/client/C in world)
All tables for the database should be prefixed according to the following list:
* `ss13_` for tables in which ingame data is held.
* `discord_` for tables in which BOREALIS data is held.
+
+# HTML UI Standards
+
+### UI conversion policy
+Due to our current situation with 5 different HTML UI systems we are now enforcing a policy that all new UIs should be made using the VueUi UI system. This policy also applies to editing existing UIs, with the following exceptions:
+
+ 1. Modification is security / severe bug fix.
+ 0. It is typo fix.
+ 0. Touched UI file is too large.
+ 0. VueUi can't accommodate that type of UI.
+
+### Responsiveness
+All new UIs must be responsive, that means that when parameters change in game world, UI data must update as quickly as possible to reflect that change. If change is time dependant, then client side time approximation should be used.
+
+### Conditional usage policy
+If you need to use conditional rendering inside UI, then try to put conditional statements on elements you want to hide, then try using `` to apply condition to multiple components.
+
+For conditional rendering try to prefer to use `v-show` attribute when change is expected to be often occurring. Use `v-if` when you need `v-else` and switch is expected expected not often.
+
+### Reusability
+If there is segment of UI that is used multiple times with different content, then we strongly encourage making of new component. If that component is general or may be reused globally, then it should be made in to global component (placed in `vui` folder), else it should be made in to UI specific component that must be placed in folder inside `view` folder.
diff --git a/.gitignore b/.gitignore
index 125182d4b1b..7daad5e4219 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,18 +1,19 @@
-#ignore misc BYOND files
-Thumbs.db
-*.log
-*.rsc
-*.int
-*.dmb
-*.lk
-*.backup
-*.before
-data/
-cfg/
-build_log.txt
-
-__pycache__/
-*.py[cod]
-*$py.class
-/.atom-build.json
-.vscode/
+#ignore misc BYOND files
+Thumbs.db
+*.log
+*.rsc
+*.int
+*.dmb
+*.lk
+*.backup
+*.before
+data/
+cfg/
+build_log.txt
+
+__pycache__/
+*.py[cod]
+*$py.class
+/.atom-build.json
+.vscode/
+.vs/
diff --git a/.travis.yml b/.travis.yml
index 4b6f2418746..68b78f11cf4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,12 +3,13 @@ sudo: false
env:
global:
- BYOND_MAJOR="512"
- BYOND_MINOR="1454"
+ BYOND_MAJOR="513"
+ BYOND_MINOR="1517"
MACRO_COUNT=77
- FLYWAY_BUILD="5.1.4"
+ FLYWAY_BUILD="5.2.4"
NODE_VERSION=10
RUST_G_VERSION="0.4.1"
+ SPACEMAN_DMM_VERSION="suite-1.4"
matrix:
- USE_MAP=aurora
- USE_MAP=runtime
@@ -72,6 +73,8 @@ jobs:
- pip3 install --user bidict -q
- chmod +x ./vueui/install
- ./vueui/install
+ - chmod +x ./scripts/install-spaceman-dmm.sh
+ - ./scripts/install-spaceman-dmm.sh dreamchecker
- chmod +x ./scripts/rust_g.sh
- ./scripts/rust_g.sh
script:
@@ -79,12 +82,14 @@ jobs:
- (! find nano/templates/ -type f -exec md5sum {} + | sort | uniq -D -w 32 | grep nano)
- (! grep -E "<\s*span\s+class\s*=\s*('[^'>]+|[^'>]+')\s*>" **/*.dm)
- (! grep -r --include=\*.dm '#define UIDEBUG' ./)
+ - (! grep -r --include=\*.dm 'to_chat(.*,\s*link(' ./)
- (cd vueui && (npm run lint | tee lint.log))
- grep "No lint errors found!" vueui/lint.log
- (cd vueui && npm run build)
- (num=`grep -E '\\\\(red|blue|green|black|b|i[^mc])' **/*.dm | wc -l`; echo "$num escapes (expecting ${MACRO_COUNT} or less)"; [ $num -le ${MACRO_COUNT} ])
- awk -f tools/indentation.awk **/*.dm
- - md5sum -c - <<< "c3aa6d9bf053dba0a2f763ed314304e2 *html/changelogs/example.yml"
+ - md5sum -c - <<< "60a49502d9f6dfdcc255deb98c901b72 *html/changelogs/example.yml"
- python tools/TagMatcher/tag-matcher.py ../..
- python tools/GenerateChangelog/ss13_genchangelog.py html/changelog.html html/changelogs --dry-run
- python3 tools/mapmerge2/travis_mapcheck.py
+ - ~/dreamchecker
diff --git a/ByondPOST.dll b/ByondPOST.dll
deleted file mode 100644
index 6cc763ade64..00000000000
Binary files a/ByondPOST.dll and /dev/null differ
diff --git a/README.md b/README.md
index 8811b08f895..5218aca790e 100644
--- a/README.md
+++ b/README.md
@@ -1,96 +1,96 @@
-# Aurorastation
-
-**[Website](https://aurorastation.org/)**
-
-**[Code](https://github.com/Aurorastation/Aurora.3)**
-
-[![Krihelimeter](http://www.krihelinator.xyz/badge/Aurorastation/Aurora.3)](http://www.krihelinator.xyz/repositories/Aurorastation/Aurora.3)
-
-[![Build Status](https://api.travis-ci.org/Aurorastation/Aurora.3.svg?branch=master)](https://travis-ci.org/Aurorastation/Aurora.3)
-
----
-
-### LICENSE
-Aurorastation is licensed under the GNU Affero General Public License version 3, which can be found in full in LICENSE.
-
-Commits with a git authorship date prior to `1420675200 +0000` (2015/01/08 00:00) are licensed under the GNU General Public License version 3, which can be found in full in LICENSE-GPL3.txt.
-
-All commits whose authorship dates are not prior to `1420675200 +0000` are assumed to be licensed under AGPL v3, if you wish to license under GPL v3 please make this clear in the commit message and any added files.
-
-If you wish to develop and host this codebase in a closed source manner you may use all commits prior to `1420675200 +0000`, which are licensed under GPL v3. The major change here is that if you host a server using any code licensed under AGPLv3 you are required to provide full source code for your servers users as well including addons and modifications you have made.
-
-See [here](https://www.gnu.org/licenses/why-affero-gpl.html) for more information.
-
-### GETTING THE CODE
-The simplest way to obtain the code is using the github .zip feature.
-
-Click [here](https://github.com/Aurorastation/Aurora.3/archive/master.zip) to get the latest stable code as a .zip file, then unzip it to wherever you want.
-
-The more complicated and easier to update method is using git. You'll need to download git or some client from [here](http://git-scm.com/). When that's installed, right click in any folder and click on "Git Bash". When that opens, type in:
-
- git clone https://github.com/Aurorastation/Aurora.3.git
-
-(hint: hold down ctrl and press insert to paste into git bash)
-
-This will take a while to download, but it provides an easier method for updating.
-
-### INSTALLATION
-
-First-time installation should be fairly straightforward. First, you'll need BYOND installed. You can get it from [here](http://www.byond.com/).
-
-This is a sourcecode-only release, so the next step is to compile the server files. Open aurorastation.dme by double-clicking it, open the Build menu, and click compile. This'll take a little while, and if everything's done right you'll get a message like this:
-
- saving aurorastation.dmb (DEBUG mode)
-
- aurorastation.dmb - 0 errors, 0 warnings
-
-If you see any errors or warnings, something has gone wrong - possibly a corrupt download or the files extracted wrong, or a code issue on the main repo. Ask on the server Discord if you're completely lost.
-
-Once that's done, open up the config folder. You'll want to edit config.txt to set the probabilities for different gamemodes in Secret and to set your server location so that all your players don't get disconnected at the end of each round. It's recommended you don't turn on the gamemodes with probability 0, as they have various issues and aren't currently being tested, so they may have unknown and bizarre bugs.
-
-You'll also want to edit admins.txt to remove the default admins and add your own. "Game Master" is the highest level of access, and the other recommended admin levels for now are "Game Admin" and "Moderator". The format is:
-
- byondkey - Rank
-
-where the BYOND key must be in lowercase and the admin rank must be properly capitalised. There are a bunch more admin ranks, but these two should be enough for most servers, assuming you have trustworthy admins.
-
-Finally, to start the server, run Dream Daemon and enter the path to your compiled aurorastation.dmb file. Make sure to set the port to the one you specified in the config.txt, and set the Security box to 'Trusted'. Then press GO and the server should start up and be ready to join.
-
----
-
-### UPDATING
-
-To update an existing installation, first back up your /config and /data folders
-as these store your server configuration, player preferences and banlist.
-
-If you used the zip method, you'll need to download the zip file again and unzip it somewhere else, and then copy the /config and /data folders over.
-
-If you used the git method, you simply need to type this in to git bash:
-
- git pull
-
-When this completes, copy over your /data and /config folders again, just in case.
-
-When you have done this, you'll need to recompile the code, but then it should work fine.
-
----
-
-### Configuration
-
-For a basic setup, simply copy every file from config/example to config.
-
-For more advanced setups, setting the server `tick_lag` in the config as well as configuring SQL are good first steps.
-
----
-
-### SQL Setup
-
-The SQL backend for the library and stats tracking requires a MySQL server, as does the optional SQL saves system. Your server details go in config/dbconfig.txt, and initial database setup is done with [flyway](https://flywaydb.org/). Detailed instructions can be found [here](https://github.com/Aurorastation/Aurora.3/tree/master/SQL).
-
----
-
-### Discord Bot
-
-The Aurorastation codebase uses a built-in Discord bot to interface with Discord. Some of its features rely on the MySQL database, specifically, channel storage and configuration. So a database is required for its operation. If that is present, then setup is relatively easy: simply set up the `config/discord.txt` file according to the example located in the `config/example/` folder, and populate the database with appropriate channel and server information.
-
-At present, there is no built in GUI for doing the latter. So direct database modification is required unless you set up the python companion bot. The python companion bot is BOREALIS II, and can be located [here](https://github.com/Aurorastation/BOREALISbot2). Though not required, it makes database modification easier. See commands that start with `channel_`.
+# Aurorastation
+
+**[Website](https://aurorastation.org/)**
+
+**[Code](https://github.com/Aurorastation/Aurora.3)**
+
+[![Krihelimeter](http://www.krihelinator.xyz/badge/Aurorastation/Aurora.3)](http://www.krihelinator.xyz/repositories/Aurorastation/Aurora.3)
+
+[![Build Status](https://api.travis-ci.org/Aurorastation/Aurora.3.svg?branch=master)](https://travis-ci.org/Aurorastation/Aurora.3)
+
+---
+
+### LICENSE
+Aurorastation is licensed under the GNU Affero General Public License version 3, which can be found in full in LICENSE.
+
+Commits with a git authorship date prior to `1420675200 +0000` (2015/01/08 00:00) are licensed under the GNU General Public License version 3, which can be found in full in LICENSE-GPL3.txt.
+
+All commits whose authorship dates are not prior to `1420675200 +0000` are assumed to be licensed under AGPL v3, if you wish to license under GPL v3 please make this clear in the commit message and any added files.
+
+If you wish to develop and host this codebase in a closed source manner you may use all commits prior to `1420675200 +0000`, which are licensed under GPL v3. The major change here is that if you host a server using any code licensed under AGPLv3 you are required to provide full source code for your servers users as well including addons and modifications you have made.
+
+See [here](https://www.gnu.org/licenses/why-affero-gpl.html) for more information.
+
+### GETTING THE CODE
+The simplest way to obtain the code is using the github .zip feature.
+
+Click [here](https://github.com/Aurorastation/Aurora.3/archive/master.zip) to get the latest stable code as a .zip file, then unzip it to wherever you want.
+
+The more complicated and easier to update method is using git. You'll need to download git or some client from [here](http://git-scm.com/). When that's installed, right click in any folder and click on "Git Bash". When that opens, type in:
+
+ git clone https://github.com/Aurorastation/Aurora.3.git
+
+(hint: hold down ctrl and press insert to paste into git bash)
+
+This will take a while to download, but it provides an easier method for updating.
+
+### INSTALLATION
+
+First-time installation should be fairly straightforward. First, you'll need BYOND installed. You can get it from [here](http://www.byond.com/).
+
+This is a sourcecode-only release, so the next step is to compile the server files. Open aurorastation.dme by double-clicking it, open the Build menu, and click compile. This'll take a little while, and if everything's done right you'll get a message like this:
+
+ saving aurorastation.dmb (DEBUG mode)
+
+ aurorastation.dmb - 0 errors, 0 warnings
+
+If you see any errors or warnings, something has gone wrong - possibly a corrupt download or the files extracted wrong, or a code issue on the main repo. Ask on the server Discord if you're completely lost.
+
+Once that's done, open up the config folder. You'll want to edit config.txt to set the probabilities for different gamemodes in Secret and to set your server location so that all your players don't get disconnected at the end of each round. It's recommended you don't turn on the gamemodes with probability 0, as they have various issues and aren't currently being tested, so they may have unknown and bizarre bugs.
+
+You'll also want to edit admins.txt to remove the default admins and add your own. "Game Master" is the highest level of access, and the other recommended admin levels for now are "Game Admin" and "Moderator". The format is:
+
+ byondkey - Rank
+
+where the BYOND key must be in lowercase and the admin rank must be properly capitalised. There are a bunch more admin ranks, but these two should be enough for most servers, assuming you have trustworthy admins.
+
+Finally, to start the server, run Dream Daemon and enter the path to your compiled aurorastation.dmb file. Make sure to set the port to the one you specified in the config.txt, and set the Security box to 'Trusted'. Then press GO and the server should start up and be ready to join.
+
+---
+
+### UPDATING
+
+To update an existing installation, first back up your /config and /data folders
+as these store your server configuration, player preferences and banlist.
+
+If you used the zip method, you'll need to download the zip file again and unzip it somewhere else, and then copy the /config and /data folders over.
+
+If you used the git method, you simply need to type this in to git bash:
+
+ git pull
+
+When this completes, copy over your /data and /config folders again, just in case.
+
+When you have done this, you'll need to recompile the code, but then it should work fine.
+
+---
+
+### Configuration
+
+For a basic setup, simply copy every file from config/example to config.
+
+For more advanced setups, setting the server `tick_lag` in the config as well as configuring SQL are good first steps.
+
+---
+
+### SQL Setup
+
+The SQL backend for the library and stats tracking requires a MySQL server, as does the optional SQL saves system. Your server details go in config/dbconfig.txt, and initial database setup is done with [flyway](https://flywaydb.org/). Detailed instructions can be found [here](https://github.com/Aurorastation/Aurora.3/tree/master/SQL).
+
+---
+
+### Discord Bot
+
+The Aurorastation codebase uses a built-in Discord bot to interface with Discord. Some of its features rely on the MySQL database, specifically, channel storage and configuration. So a database is required for its operation. If that is present, then setup is relatively easy: simply set up the `config/discord.txt` file according to the example located in the `config/example/` folder, and populate the database with appropriate channel and server information.
+
+At present, there is no built in GUI for doing the latter. So direct database modification is required unless you set up the python companion bot. The python companion bot is BOREALIS II, and can be located [here](https://github.com/Aurorastation/BOREALISbot2). Though not required, it makes database modification easier. See commands that start with `channel_`.
diff --git a/SQL/migrate/V001__Initial_schema.sql b/SQL/migrate/V001__Initial_schema.sql
index 74fce0b0a63..66dd529cd8b 100644
--- a/SQL/migrate/V001__Initial_schema.sql
+++ b/SQL/migrate/V001__Initial_schema.sql
@@ -367,7 +367,7 @@ CREATE TABLE `ss13_characters_flavour` (
`robot_research` text,
PRIMARY KEY (`char_id`),
CONSTRAINT `ss13_flavour_fk_char_id` FOREIGN KEY (`char_id`) REFERENCES `ss13_characters` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
-) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT;
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Table for housing IC criminal records
diff --git a/SQL/migrate/V036__Docs.sql b/SQL/migrate/V036__Docs.sql
new file mode 100644
index 00000000000..05022af76a8
--- /dev/null
+++ b/SQL/migrate/V036__Docs.sql
@@ -0,0 +1,20 @@
+--
+-- Create the Documents database.
+--
+
+CREATE TABLE `ss13_documents` (
+ `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `name` VARCHAR(100) NOT NULL,
+ `title` VARCHAR(26) NOT NULL,
+ `chance` FLOAT UNSIGNED NOT NULL DEFAULT '1',
+ `content` VARCHAR(3072) NOT NULL,
+ `tags` JSON NOT NULL,
+ `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `deleted_at` DATETIME NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE INDEX `name` (`name`)
+)
+COLLATE='utf8_bin'
+ENGINE=InnoDB
+;
diff --git a/SQL/migrate/V037__Reset_Factions.sql b/SQL/migrate/V037__Reset_Factions.sql
new file mode 100644
index 00000000000..0dc4dc2dfd2
--- /dev/null
+++ b/SQL/migrate/V037__Reset_Factions.sql
@@ -0,0 +1,5 @@
+--
+-- Sets the faction variable to NanoTrasen for the factions PR.
+--
+
+UPDATE ss13_characters SET faction = "NanoTrasen";
diff --git a/SQL/migrate/V038__ccia_reports.sql b/SQL/migrate/V038__ccia_reports.sql
new file mode 100644
index 00000000000..5ea5648d158
--- /dev/null
+++ b/SQL/migrate/V038__ccia_reports.sql
@@ -0,0 +1,35 @@
+--
+-- Adds tables to store ccia interviews
+--
+
+CREATE TABLE `ss13_ccia_reports` (
+ `id` INT(11) NOT NULL AUTO_INCREMENT,
+ `report_date` DATE NOT NULL,
+ `title` VARCHAR(200) NOT NULL COLLATE 'utf8mb4_unicode_ci',
+ `status` ENUM('new','approved','rejected','completed') NOT NULL COLLATE 'utf8mb4_unicode_ci',
+ `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `deleted_at` DATETIME NULL DEFAULT NULL,
+ PRIMARY KEY (`id`)
+)
+COLLATE='utf8mb4_unicode_ci'
+ENGINE=InnoDB
+;
+
+CREATE TABLE `ss13_ccia_reports_transcripts` (
+ `id` INT(11) NOT NULL AUTO_INCREMENT,
+ `report_id` INT(11) NOT NULL,
+ `character_id` INT(11) NOT NULL,
+ `interviewer` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci',
+ `text` LONGTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci',
+ `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `deleted_at` DATETIME NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ INDEX `report_id` (`report_id`),
+ INDEX `character_id` (`character_id`),
+ CONSTRAINT `report_id` FOREIGN KEY (`report_id`) REFERENCES `ss13_ccia_reports` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
+)
+COLLATE='utf8mb4_unicode_ci'
+ENGINE=InnoDB
+;
diff --git a/SQL/migrate/V039__stickybans.sql b/SQL/migrate/V039__stickybans.sql
new file mode 100644
index 00000000000..230cb5e9840
--- /dev/null
+++ b/SQL/migrate/V039__stickybans.sql
@@ -0,0 +1,36 @@
+--
+-- Tables for holding stickyban/PRISM stuff.
+--
+
+CREATE TABLE `ss13_stickyban` (
+ `ckey` VARCHAR(32) NOT NULL,
+ `reason` VARCHAR(2048) NOT NULL,
+ `banning_admin` VARCHAR(32) NOT NULL,
+ `datetime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (`ckey`)
+) ENGINE=InnoDB;
+
+CREATE TABLE `ss13_stickyban_matched_ckey` (
+ `stickyban` VARCHAR(32) NOT NULL,
+ `matched_ckey` VARCHAR(32) NOT NULL,
+ `first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `exempt` TINYINT(1) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`stickyban`, `matched_ckey`)
+) ENGINE=InnoDB;
+
+CREATE TABLE `ss13_stickyban_matched_ip` (
+ `stickyban` VARCHAR(32) NOT NULL,
+ `matched_ip` INT UNSIGNED NOT NULL,
+ `first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`stickyban`, `matched_ip`)
+) ENGINE=InnoDB;
+
+CREATE TABLE `ss13_stickyban_matched_cid` (
+ `stickyban` VARCHAR(32) NOT NULL,
+ `matched_cid` VARCHAR(32) NOT NULL,
+ `first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`stickyban`, `matched_cid`)
+) ENGINE=InnoDB;
diff --git a/SQL/migrate/V040__CustomSynths.sql b/SQL/migrate/V040__CustomSynths.sql
new file mode 100644
index 00000000000..f1e2077ad62
--- /dev/null
+++ b/SQL/migrate/V040__CustomSynths.sql
@@ -0,0 +1,16 @@
+--
+-- Create the Custom Synths database.
+--
+
+CREATE TABLE `ss13_customsynths` (
+ `synthname` VARCHAR(128) NOT NULL,
+ `synthckey` varchar(32) CHARACTER SET latin1 NOT NULL,
+ `synthicon` VARCHAR(26) NOT NULL,
+ `aichassisicon` VARCHAR(100) NOT NULL,
+ `aiholoicon` VARCHAR(100) NOT NULL,
+ `paiicon` VARCHAR(100) NOT NULL,
+ PRIMARY KEY (`synthname`),
+ CONSTRAINT `fk_ss13_custom_synths_ss13_players` FOREIGN KEY (`synthckey`) REFERENCES `ss13_player` (`ckey`) ON DELETE CASCADE ON UPDATE CASCADE
+)
+ENGINE=InnoDB
+;
diff --git a/SQL/migrate/V041__SQL-Cleanup.sql b/SQL/migrate/V041__SQL-Cleanup.sql
new file mode 100644
index 00000000000..424ab4667f6
--- /dev/null
+++ b/SQL/migrate/V041__SQL-Cleanup.sql
@@ -0,0 +1,885 @@
+--
+-- Cleans up the database
+--
+
+-- This is specifically created for the current Aurorastation Database.
+-- IF YOU RUN THIS ON YOUR DOWNSTREAM SERVER IT IS STRONGLY ADVICED TO EXECUTE THIS IN A TEST SYTEM FIRST AND FIX POTENTIAL ERRORS
+
+-- Delete unused git_pull tables
+SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
+DROP TABLE IF EXISTS `ss13_git_pull_todo_stats`;
+DROP TABLE IF EXISTS `ss13_git_pull_todos`;
+DROP TABLE IF EXISTS `ss13_git_pull_requests`;
+DROP TABLE IF EXISTS `ss13_santa`;
+DROP TABLE IF EXISTS `ss13_contest_participants`;
+DROP TABLE IF EXISTS `ss13_contest_reports`;
+DROP TABLE IF EXISTS `ss13_directives`;
+
+
+-- Fix data issues
+UPDATE ss13_ban SET expiration_time = bantime WHERE expiration_time = 0;
+UPDATE ss13_library SET uploadtime = "2015-04-26" WHERE uploadtime = 0;
+UPDATE
+ ss13_news_stories
+SET
+ publish_at = created_at,
+ publish_until = DATE_ADD(created_at, INTERVAL 7 DAY),
+ ic_timestamp = DATE_ADD(created_at, INTERVAL 442 YEAR)
+WHERE
+ publish_at = 0 OR
+ publish_until = 0 OR
+ ic_timestamp = 0;
+
+-- Update charset and collation
+ALTER TABLE `discord_bans`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `discord_bans`
+ ALTER `user_id` DROP DEFAULT,
+ ALTER `user_name` DROP DEFAULT,
+ ALTER `server_id` DROP DEFAULT,
+ ALTER `ban_type` DROP DEFAULT;
+ALTER TABLE `discord_bans`
+ CHANGE COLUMN `user_id` `user_id` VARCHAR(45) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `user_name` `user_name` VARCHAR(45) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `user_id`,
+ CHANGE COLUMN `server_id` `server_id` VARCHAR(45) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `user_name`,
+ CHANGE COLUMN `ban_type` `ban_type` VARCHAR(45) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `server_id`,
+ CHANGE COLUMN `ban_reason` `ban_reason` LONGTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ban_duration`,
+ CHANGE COLUMN `admin_id` `admin_id` VARCHAR(45) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `expiration_time`,
+ CHANGE COLUMN `admin_name` `admin_name` VARCHAR(45) NULL DEFAULT 'BOREALIS' COLLATE 'utf8mb4_unicode_ci' AFTER `admin_id`;
+
+ALTER TABLE `discord_channels`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `discord_channels`
+ ALTER `channel_group` DROP DEFAULT;
+ALTER TABLE `discord_channels`
+ CHANGE COLUMN `channel_group` `channel_group` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `channel_id` `channel_id` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `channel_group`,
+ CHANGE COLUMN `server_id` `server_id` VARCHAR(45) NOT NULL DEFAULT '' COLLATE 'utf8mb4_unicode_ci' AFTER `pin_flag`;
+
+ALTER TABLE `discord_log`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `discord_log`
+ CHANGE COLUMN `action` `action` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `action_time`,
+ CHANGE COLUMN `admin_id` `admin_id` VARCHAR(45) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `action`,
+ CHANGE COLUMN `user_id` `user_id` VARCHAR(45) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `admin_id`;
+
+ALTER TABLE `discord_strikes`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `discord_strikes`
+ ALTER `user_id` DROP DEFAULT,
+ ALTER `user_name` DROP DEFAULT,
+ ALTER `admin_id` DROP DEFAULT,
+ ALTER `admin_name` DROP DEFAULT;
+ALTER TABLE `discord_strikes`
+ CHANGE COLUMN `user_id` `user_id` VARCHAR(45) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `user_name` `user_name` VARCHAR(45) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `user_id`,
+ CHANGE COLUMN `action_type` `action_type` VARCHAR(45) NOT NULL DEFAULT 'WARNING' COLLATE 'utf8mb4_unicode_ci' AFTER `user_name`,
+ CHANGE COLUMN `admin_id` `admin_id` VARCHAR(45) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `strike_time`,
+ CHANGE COLUMN `admin_name` `admin_name` VARCHAR(45) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `admin_id`;
+
+ALTER TABLE `discord_subscribers`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `discord_subscribers`
+ ALTER `user_id` DROP DEFAULT;
+ALTER TABLE `discord_subscribers`
+ CHANGE COLUMN `user_id` `user_id` VARCHAR(45) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`;
+
+ALTER TABLE `ss13_admin_log`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_admin_log`
+ ALTER `adminckey` DROP DEFAULT,
+ ALTER `adminip` DROP DEFAULT;
+ALTER TABLE `ss13_admin_log`
+ CHANGE COLUMN `adminckey` `adminckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `datetime`,
+ CHANGE COLUMN `adminip` `adminip` VARCHAR(18) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `adminckey`,
+ CHANGE COLUMN `log` `log` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `adminip`;
+
+ALTER TABLE `ss13_antag_log`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_antag_log`
+ ALTER `ckey` DROP DEFAULT,
+ ALTER `game_id` DROP DEFAULT,
+ ALTER `special_role_name` DROP DEFAULT;
+ALTER TABLE `ss13_antag_log`
+ CHANGE COLUMN `ckey` `ckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `game_id` `game_id` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `char_id`,
+ CHANGE COLUMN `char_name` `char_name` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `game_id`,
+ CHANGE COLUMN `special_role_name` `special_role_name` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `datetime`;
+
+ALTER TABLE `ss13_api_commands`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_api_commands`
+ ALTER `command` DROP DEFAULT;
+ALTER TABLE `ss13_api_commands`
+ CHANGE COLUMN `command` `command` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `description` `description` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `command`;
+
+ALTER TABLE `ss13_api_tokens`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_api_tokens`
+ ALTER `token` DROP DEFAULT,
+ ALTER `creator` DROP DEFAULT,
+ ALTER `description` DROP DEFAULT;
+ALTER TABLE `ss13_api_tokens`
+ CHANGE COLUMN `token` `token` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `ip` `ip` VARCHAR(16) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `token`,
+ CHANGE COLUMN `creator` `creator` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ip`,
+ CHANGE COLUMN `description` `description` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `creator`;
+
+ALTER TABLE `ss13_api_token_command`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+
+ALTER TABLE `ss13_ban`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_ban`
+ ALTER `serverip` DROP DEFAULT,
+ ALTER `bantype` DROP DEFAULT,
+ ALTER `ckey` DROP DEFAULT,
+ ALTER `computerid` DROP DEFAULT,
+ ALTER `ip` DROP DEFAULT,
+ ALTER `a_ckey` DROP DEFAULT,
+ ALTER `a_computerid` DROP DEFAULT,
+ ALTER `a_ip` DROP DEFAULT;
+ALTER TABLE `ss13_ban`
+ CHANGE COLUMN `serverip` `serverip` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `bantime`,
+ CHANGE COLUMN `bantype` `bantype` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `serverip`,
+ CHANGE COLUMN `reason` `reason` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `bantype`,
+ CHANGE COLUMN `job` `job` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `reason`,
+ CHANGE COLUMN `ckey` `ckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `expiration_time`,
+ CHANGE COLUMN `computerid` `computerid` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ckey`,
+ CHANGE COLUMN `ip` `ip` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `computerid`,
+ CHANGE COLUMN `a_ckey` `a_ckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ip`,
+ CHANGE COLUMN `a_computerid` `a_computerid` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `a_ckey`,
+ CHANGE COLUMN `a_ip` `a_ip` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `a_computerid`,
+ CHANGE COLUMN `who` `who` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `a_ip`,
+ CHANGE COLUMN `adminwho` `adminwho` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `who`,
+ CHANGE COLUMN `edits` `edits` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `adminwho`,
+ CHANGE COLUMN `unbanned_reason` `unbanned_reason` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `unbanned_datetime`,
+ CHANGE COLUMN `unbanned_ckey` `unbanned_ckey` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `unbanned_reason`,
+ CHANGE COLUMN `unbanned_computerid` `unbanned_computerid` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `unbanned_ckey`,
+ CHANGE COLUMN `unbanned_ip` `unbanned_ip` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `unbanned_computerid`;
+
+ALTER TABLE `ss13_ban_mirrors`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_ban_mirrors`
+ ALTER `ckey` DROP DEFAULT,
+ ALTER `ip` DROP DEFAULT,
+ ALTER `computerid` DROP DEFAULT,
+ ALTER `source` DROP DEFAULT;
+ALTER TABLE `ss13_ban_mirrors`
+ CHANGE COLUMN `ckey` `ckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ban_id`,
+ CHANGE COLUMN `ip` `ip` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ckey`,
+ CHANGE COLUMN `computerid` `computerid` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ip`,
+ CHANGE COLUMN `source` `source` ENUM('legacy','conninfo','isbanned') NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `datetime`,
+ CHANGE COLUMN `extra_info` `extra_info` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `source`;
+
+ALTER TABLE `ss13_cargo_categories`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_cargo_categories`
+ ALTER `name` DROP DEFAULT,
+ ALTER `display_name` DROP DEFAULT,
+ ALTER `description` DROP DEFAULT,
+ ALTER `icon` DROP DEFAULT;
+ALTER TABLE `ss13_cargo_categories`
+ CHANGE COLUMN `name` `name` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `display_name` `display_name` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `name`,
+ CHANGE COLUMN `description` `description` VARCHAR(300) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `display_name`,
+ CHANGE COLUMN `icon` `icon` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `description`,
+ CHANGE COLUMN `order_by` `order_by` VARCHAR(5) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `price_modifier`;
+
+ALTER TABLE `ss13_cargo_items`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_cargo_items`
+ CHANGE COLUMN `name` `name` VARCHAR(100) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `supplier` `supplier` VARCHAR(50) NOT NULL DEFAULT 'nt' COLLATE 'utf8mb4_unicode_ci' AFTER `name`,
+ CHANGE COLUMN `description` `description` VARCHAR(300) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `supplier`,
+ CHANGE COLUMN `container_type` `container_type` VARCHAR(50) NOT NULL DEFAULT 'crate' COLLATE 'utf8mb4_unicode_ci' AFTER `access`,
+ CHANGE COLUMN `order_by` `order_by` VARCHAR(5) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `groupable`,
+ CHANGE COLUMN `created_by` `created_by` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `order_by`,
+ CHANGE COLUMN `approved_by` `approved_by` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `created_by`,
+ DROP COLUMN `suppliers_old`,
+ DROP COLUMN `path_old`;
+ALTER TABLE `ss13_cargo_items`
+ ALTER `categories` DROP DEFAULT;
+ALTER TABLE `ss13_cargo_items`
+ CHANGE COLUMN `categories` `categories` JSON NOT NULL AFTER `description`,
+ CHANGE COLUMN `items` `items` JSON NULL DEFAULT NULL AFTER `price`;
+
+ALTER TABLE `ss13_cargo_suppliers`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_cargo_suppliers`
+ ALTER `short_name` DROP DEFAULT,
+ ALTER `name` DROP DEFAULT,
+ ALTER `description` DROP DEFAULT,
+ ALTER `tag_line` DROP DEFAULT;
+ALTER TABLE `ss13_cargo_suppliers`
+ CHANGE COLUMN `short_name` `short_name` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `name` `name` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `short_name`,
+ CHANGE COLUMN `description` `description` VARCHAR(300) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `name`,
+ CHANGE COLUMN `tag_line` `tag_line` VARCHAR(300) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `description`;
+
+ALTER TABLE `ss13_ccia_actions`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_ccia_actions`
+ ALTER `type` DROP DEFAULT,
+ ALTER `issuedby` DROP DEFAULT,
+ ALTER `url` DROP DEFAULT;
+ALTER TABLE `ss13_ccia_actions`
+ CHANGE COLUMN `title` `title` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `type` `type` ENUM('injunction','suspension','reprimand','demotion','other') NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `title`,
+ CHANGE COLUMN `issuedby` `issuedby` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `type`,
+ CHANGE COLUMN `details` `details` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `issuedby`,
+ CHANGE COLUMN `url` `url` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `details`;
+
+ALTER TABLE `ss13_ccia_action_char`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+
+ALTER TABLE `ss13_ccia_general_notice_list`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_ccia_general_notice_list`
+ ALTER `title` DROP DEFAULT;
+ALTER TABLE `ss13_ccia_general_notice_list`
+ CHANGE COLUMN `title` `title` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `message` `message` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `title`;
+
+ALTER TABLE `ss13_ccia_reports`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_ccia_reports`
+ ALTER `title` DROP DEFAULT,
+ ALTER `status` DROP DEFAULT;
+ALTER TABLE `ss13_ccia_reports`
+ CHANGE COLUMN `title` `title` VARCHAR(200) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `report_date`,
+ CHANGE COLUMN `status` `status` ENUM('new','in progress','review required','approved','rejected','completed') NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `title`;
+
+ALTER TABLE `ss13_ccia_reports_transcripts`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_ccia_reports_transcripts`
+ ALTER `interviewer` DROP DEFAULT;
+ALTER TABLE `ss13_ccia_reports_transcripts`
+ CHANGE COLUMN `interviewer` `interviewer` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `character_id`,
+ CHANGE COLUMN `text` `text` LONGTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `character_id`;
+
+ALTER TABLE `ss13_characters`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_characters`
+ ALTER `ckey` DROP DEFAULT;
+ALTER TABLE `ss13_characters`
+ CHANGE COLUMN `ckey` `ckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `name` `name` VARCHAR(128) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ckey`,
+ CHANGE COLUMN `metadata` `metadata` VARCHAR(512) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `name`,
+ CHANGE COLUMN `be_special_role` `be_special_role` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `metadata`,
+ CHANGE COLUMN `gender` `gender` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `be_special_role`,
+ CHANGE COLUMN `species` `species` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `age`,
+ CHANGE COLUMN `language` `language` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `species`,
+ CHANGE COLUMN `hair_colour` `hair_colour` VARCHAR(7) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `language`,
+ CHANGE COLUMN `facial_colour` `facial_colour` VARCHAR(7) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `hair_colour`,
+ CHANGE COLUMN `skin_colour` `skin_colour` VARCHAR(7) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `skin_tone`,
+ CHANGE COLUMN `hair_style` `hair_style` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `skin_colour`,
+ CHANGE COLUMN `facial_style` `facial_style` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `hair_style`,
+ CHANGE COLUMN `eyes_colour` `eyes_colour` VARCHAR(7) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `facial_style`,
+ CHANGE COLUMN `underwear` `underwear` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `eyes_colour`,
+ CHANGE COLUMN `undershirt` `undershirt` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `underwear`,
+ CHANGE COLUMN `socks` `socks` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `undershirt`,
+ CHANGE COLUMN `b_type` `b_type` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `backbag_style`,
+ CHANGE COLUMN `spawnpoint` `spawnpoint` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `b_type`,
+ CHANGE COLUMN `jobs` `jobs` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `spawnpoint`,
+ CHANGE COLUMN `alternate_titles` `alternate_titles` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `alternate_option`,
+ CHANGE COLUMN `disabilities` `disabilities` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `alternate_titles`,
+ CHANGE COLUMN `skills` `skills` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `disabilities`,
+ CHANGE COLUMN `skill_specialization` `skill_specialization` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `skills`,
+ CHANGE COLUMN `home_system` `home_system` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `skill_specialization`,
+ CHANGE COLUMN `citizenship` `citizenship` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `home_system`,
+ CHANGE COLUMN `faction` `faction` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `citizenship`,
+ CHANGE COLUMN `religion` `religion` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `faction`,
+ CHANGE COLUMN `nt_relation` `nt_relation` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `religion`,
+ CHANGE COLUMN `uplink_location` `uplink_location` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `nt_relation`,
+ CHANGE COLUMN `organs_data` `organs_data` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `uplink_location`,
+ CHANGE COLUMN `organs_robotic` `organs_robotic` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `organs_data`,
+ CHANGE COLUMN `body_markings` `body_markings` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `organs_robotic`,
+ CHANGE COLUMN `gear` `gear` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `body_markings`;
+
+ALTER TABLE `ss13_characters_flavour`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_characters_flavour`
+ CHANGE COLUMN `signature` `signature` TEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `char_id`,
+ CHANGE COLUMN `signature_font` `signature_font` TEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `signature`,
+ CHANGE COLUMN `records_employment` `records_employment` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `signature_font`,
+ CHANGE COLUMN `records_medical` `records_medical` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `records_employment`,
+ CHANGE COLUMN `records_security` `records_security` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `records_medical`,
+ CHANGE COLUMN `records_exploit` `records_exploit` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `records_security`,
+ CHANGE COLUMN `records_ccia` `records_ccia` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `records_exploit`,
+ CHANGE COLUMN `flavour_general` `flavour_general` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `records_ccia`,
+ CHANGE COLUMN `flavour_head` `flavour_head` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `flavour_general`,
+ CHANGE COLUMN `flavour_face` `flavour_face` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `flavour_head`,
+ CHANGE COLUMN `flavour_eyes` `flavour_eyes` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `flavour_face`,
+ CHANGE COLUMN `flavour_torso` `flavour_torso` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `flavour_eyes`,
+ CHANGE COLUMN `flavour_arms` `flavour_arms` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `flavour_torso`,
+ CHANGE COLUMN `flavour_hands` `flavour_hands` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `flavour_arms`,
+ CHANGE COLUMN `flavour_legs` `flavour_legs` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `flavour_hands`,
+ CHANGE COLUMN `flavour_feet` `flavour_feet` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `flavour_legs`,
+ CHANGE COLUMN `robot_default` `robot_default` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `flavour_feet`,
+ CHANGE COLUMN `robot_standard` `robot_standard` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `robot_default`,
+ CHANGE COLUMN `robot_engineering` `robot_engineering` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `robot_standard`,
+ CHANGE COLUMN `robot_construction` `robot_construction` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `robot_engineering`,
+ CHANGE COLUMN `robot_medical` `robot_medical` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `robot_construction`,
+ CHANGE COLUMN `robot_rescue` `robot_rescue` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `robot_medical`,
+ CHANGE COLUMN `robot_mining` `robot_mining` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `robot_rescue`,
+ CHANGE COLUMN `robot_custodial` `robot_custodial` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `robot_mining`,
+ CHANGE COLUMN `robot_service` `robot_service` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `robot_custodial`,
+ CHANGE COLUMN `robot_clerical` `robot_clerical` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `robot_service`,
+ CHANGE COLUMN `robot_security` `robot_security` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `robot_clerical`,
+ CHANGE COLUMN `robot_research` `robot_research` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `robot_security`;
+
+ALTER TABLE `ss13_characters_log`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_characters_log`
+ ALTER `game_id` DROP DEFAULT;
+ALTER TABLE `ss13_characters_log`
+ CHANGE COLUMN `game_id` `game_id` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `char_id`,
+ CHANGE COLUMN `job_name` `job_name` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `datetime`,
+ CHANGE COLUMN `alt_title` `alt_title` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `job_name`;
+
+ALTER TABLE `ss13_character_incidents`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_character_incidents`
+ ALTER `UID` DROP DEFAULT,
+ ALTER `datetime` DROP DEFAULT,
+ ALTER `game_id` DROP DEFAULT;
+ALTER TABLE `ss13_character_incidents`
+ CHANGE COLUMN `UID` `UID` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `char_id`,
+ CHANGE COLUMN `datetime` `datetime` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `UID`,
+ CHANGE COLUMN `notes` `notes` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `datetime`,
+ CHANGE COLUMN `charges` `charges` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `notes`,
+ CHANGE COLUMN `evidence` `evidence` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `charges`,
+ CHANGE COLUMN `arbiters` `arbiters` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `evidence`,
+ CHANGE COLUMN `created_by` `created_by` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `felony`,
+ CHANGE COLUMN `deleted_by` `deleted_by` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `created_by`,
+ CHANGE COLUMN `game_id` `game_id` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `deleted_by`;
+
+ALTER TABLE `ss13_connection_log`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_connection_log`
+ ALTER `ckey` DROP DEFAULT,
+ ALTER `serverip` DROP DEFAULT,
+ ALTER `ip` DROP DEFAULT,
+ ALTER `computerid` DROP DEFAULT;
+ALTER TABLE `ss13_connection_log`
+ CHANGE COLUMN `ckey` `ckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `serverip` `serverip` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `datetime`,
+ CHANGE COLUMN `ip` `ip` VARCHAR(18) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `serverip`,
+ CHANGE COLUMN `computerid` `computerid` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ip`,
+ CHANGE COLUMN `game_id` `game_id` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `byond_build`;
+
+ALTER TABLE `ss13_customsynths`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_customsynths`
+ ALTER `synthname` DROP DEFAULT,
+ ALTER `synthckey` DROP DEFAULT,
+ ALTER `synthicon` DROP DEFAULT,
+ ALTER `aichassisicon` DROP DEFAULT,
+ ALTER `aiholoicon` DROP DEFAULT,
+ ALTER `paiicon` DROP DEFAULT;
+ALTER TABLE `ss13_customsynths`
+ CHANGE COLUMN `synthname` `synthname` VARCHAR(128) NOT NULL COLLATE 'utf8mb4_unicode_ci' FIRST,
+ CHANGE COLUMN `synthckey` `synthckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `synthname`,
+ CHANGE COLUMN `synthicon` `synthicon` VARCHAR(26) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `synthckey`,
+ CHANGE COLUMN `aichassisicon` `aichassisicon` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `synthicon`,
+ CHANGE COLUMN `aiholoicon` `aiholoicon` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `aichassisicon`,
+ CHANGE COLUMN `paiicon` `paiicon` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `aiholoicon`;
+
+ALTER TABLE `ss13_death`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_death`
+ CHANGE COLUMN `pod` `pod` MEDIUMTEXT NOT NULL COMMENT 'Place of death' COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `coord` `coord` MEDIUMTEXT NOT NULL COMMENT 'X, Y, Z POD' COLLATE 'utf8mb4_unicode_ci' AFTER `pod`,
+ CHANGE COLUMN `job` `job` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `tod`,
+ CHANGE COLUMN `special` `special` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `job`,
+ CHANGE COLUMN `name` `name` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `special`,
+ CHANGE COLUMN `byondkey` `byondkey` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `name`,
+ CHANGE COLUMN `laname` `laname` MEDIUMTEXT NOT NULL COMMENT 'Last attacker name' COLLATE 'utf8mb4_unicode_ci' AFTER `byondkey`,
+ CHANGE COLUMN `lakey` `lakey` MEDIUMTEXT NOT NULL COMMENT 'Last attacker key' COLLATE 'utf8mb4_unicode_ci' AFTER `laname`,
+ CHANGE COLUMN `gender` `gender` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `lakey`;
+
+ALTER TABLE `ss13_documents`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_documents`
+ ALTER `name` DROP DEFAULT,
+ ALTER `title` DROP DEFAULT,
+ ALTER `content` DROP DEFAULT;
+ALTER TABLE `ss13_documents`
+ CHANGE COLUMN `name` `name` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `title` `title` VARCHAR(26) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `name`,
+ CHANGE COLUMN `content` `content` VARCHAR(3072) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `chance`,
+ CHANGE COLUMN `tags` `tags` LONGTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `content`;
+
+ALTER TABLE `ss13_feedback`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_feedback`
+ ALTER `game_id` DROP DEFAULT,
+ ALTER `var_name` DROP DEFAULT;
+ALTER TABLE `ss13_feedback`
+ CHANGE COLUMN `game_id` `game_id` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `time`,
+ CHANGE COLUMN `var_name` `var_name` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `game_id`,
+ CHANGE COLUMN `details` `details` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `var_value`;
+
+ALTER TABLE `ss13_forms`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_forms`
+ ALTER `id` DROP DEFAULT,
+ ALTER `name` DROP DEFAULT,
+ ALTER `department` DROP DEFAULT;
+ALTER TABLE `ss13_forms`
+ CHANGE COLUMN `id` `id` VARCHAR(4) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `form_id`,
+ CHANGE COLUMN `name` `name` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `department` `department` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `name`,
+ CHANGE COLUMN `data` `data` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `department`,
+ CHANGE COLUMN `info` `info` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `data`;
+
+ALTER TABLE `ss13_ipc_tracking`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_ipc_tracking`
+ ALTER `player_ckey` DROP DEFAULT,
+ ALTER `character_name` DROP DEFAULT;
+ALTER TABLE `ss13_ipc_tracking`
+ CHANGE COLUMN `player_ckey` `player_ckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `character_name` `character_name` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `player_ckey`;
+
+ALTER TABLE `ss13_ipintel`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+
+ALTER TABLE `ss13_law`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_law`
+ ALTER `law_id` DROP DEFAULT,
+ ALTER `name` DROP DEFAULT,
+ ALTER `description` DROP DEFAULT;
+ALTER TABLE `ss13_law`
+ CHANGE COLUMN `law_id` `law_id` VARCHAR(4) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `name` `name` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `law_id`,
+ CHANGE COLUMN `description` `description` VARCHAR(500) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `name`;
+
+ALTER TABLE `ss13_library`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_library`
+ ALTER `uploader` DROP DEFAULT;
+ALTER TABLE `ss13_library`
+ CHANGE COLUMN `author` `author` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `title` `title` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `author`,
+ CHANGE COLUMN `content` `content` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `title`,
+ CHANGE COLUMN `category` `category` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `content`,
+ CHANGE COLUMN `uploader` `uploader` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `uploadtime`;
+
+ALTER TABLE `ss13_news_channels`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_news_channels`
+ ALTER `name` DROP DEFAULT,
+ ALTER `author` DROP DEFAULT,
+ ALTER `created_by` DROP DEFAULT;
+ALTER TABLE `ss13_news_channels`
+ CHANGE COLUMN `name` `name` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `author` `author` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `name`,
+ CHANGE COLUMN `announcement` `announcement` VARCHAR(200) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `is_admin_channel`,
+ CHANGE COLUMN `created_by` `created_by` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `announcement`;
+
+ALTER TABLE `ss13_news_stories`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_news_stories`
+ ALTER `author` DROP DEFAULT,
+ ALTER `created_by` DROP DEFAULT;
+ALTER TABLE `ss13_news_stories`
+ CHANGE COLUMN `author` `author` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `channel_id`,
+ CHANGE COLUMN `body` `body` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `author`,
+ CHANGE COLUMN `message_type` `message_type` VARCHAR(50) NOT NULL DEFAULT 'Story' COLLATE 'utf8mb4_unicode_ci' AFTER `body`,
+ CHANGE COLUMN `url` `url` VARCHAR(250) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `publish_until`,
+ CHANGE COLUMN `created_by` `created_by` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ic_timestamp`,
+ CHANGE COLUMN `approved_by` `approved_by` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `created_at`;
+
+ALTER TABLE `ss13_notes`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_notes`
+ ALTER `ckey` DROP DEFAULT,
+ ALTER `a_ckey` DROP DEFAULT;
+ALTER TABLE `ss13_notes`
+ CHANGE COLUMN `ckey` `ckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `adddate`,
+ CHANGE COLUMN `ip` `ip` VARCHAR(18) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ckey`,
+ CHANGE COLUMN `computerid` `computerid` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ip`,
+ CHANGE COLUMN `a_ckey` `a_ckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `computerid`,
+ CHANGE COLUMN `content` `content` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `a_ckey`,
+ CHANGE COLUMN `lasteditor` `lasteditor` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `edited`;
+
+ALTER TABLE `ss13_player`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_player`
+ ALTER `ckey` DROP DEFAULT,
+ ALTER `ip` DROP DEFAULT,
+ ALTER `computerid` DROP DEFAULT;
+ALTER TABLE `ss13_player`
+ CHANGE COLUMN `ckey` `ckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `ip` `ip` VARCHAR(18) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `lastseen`,
+ CHANGE COLUMN `computerid` `computerid` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ip`,
+ CHANGE COLUMN `lastadminrank` `lastadminrank` VARCHAR(32) NOT NULL DEFAULT 'Player' COLLATE 'utf8mb4_unicode_ci' AFTER `byond_build`,
+ CHANGE COLUMN `rank` `rank` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `migration_status`,
+ CHANGE COLUMN `discord_id` `discord_id` VARCHAR(45) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `flags`;
+
+ALTER TABLE `ss13_player_linking`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_player_linking`
+ ALTER `forum_username_short` DROP DEFAULT,
+ ALTER `forum_username` DROP DEFAULT,
+ ALTER `player_ckey` DROP DEFAULT,
+ ALTER `status` DROP DEFAULT;
+ALTER TABLE `ss13_player_linking`
+ CHANGE COLUMN `forum_username_short` `forum_username_short` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `forum_id`,
+ CHANGE COLUMN `forum_username` `forum_username` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `forum_username_short`,
+ CHANGE COLUMN `player_ckey` `player_ckey` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `forum_username`,
+ CHANGE COLUMN `status` `status` ENUM('new','confirmed','rejected','linked') NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `player_ckey`;
+
+ALTER TABLE `ss13_player_notifications`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_player_notifications`
+ ALTER `ckey` DROP DEFAULT,
+ ALTER `type` DROP DEFAULT,
+ ALTER `message` DROP DEFAULT,
+ ALTER `created_by` DROP DEFAULT;
+ALTER TABLE `ss13_player_notifications`
+ CHANGE COLUMN `ckey` `ckey` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `type` `type` ENUM('player_greeting','player_greeting_chat','admin','ccia') NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ckey`,
+ CHANGE COLUMN `message` `message` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `type`,
+ CHANGE COLUMN `created_by` `created_by` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `message`,
+ CHANGE COLUMN `acked_by` `acked_by` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `created_at`;
+
+ALTER TABLE `ss13_player_pai`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_player_pai`
+ ALTER `ckey` DROP DEFAULT;
+ALTER TABLE `ss13_player_pai`
+ CHANGE COLUMN `ckey` `ckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' FIRST,
+ CHANGE COLUMN `name` `name` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ckey`,
+ CHANGE COLUMN `description` `description` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `name`,
+ CHANGE COLUMN `role` `role` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `description`,
+ CHANGE COLUMN `comments` `comments` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `role`;
+
+ALTER TABLE `ss13_player_preferences`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_player_preferences`
+ ALTER `ckey` DROP DEFAULT;
+ALTER TABLE `ss13_player_preferences`
+ CHANGE COLUMN `ckey` `ckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' FIRST,
+ CHANGE COLUMN `ooccolor` `ooccolor` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ckey`,
+ CHANGE COLUMN `lastchangelog` `lastchangelog` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ooccolor`,
+ CHANGE COLUMN `UI_style` `UI_style` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `lastchangelog`,
+ CHANGE COLUMN `UI_style_color` `UI_style_color` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `toggles`,
+ CHANGE COLUMN `lastmotd` `lastmotd` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `asfx_togs`,
+ CHANGE COLUMN `lastmemo` `lastmemo` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `lastmotd`,
+ CHANGE COLUMN `language_prefixes` `language_prefixes` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `lastmemo`,
+ CHANGE COLUMN `html_UI_style` `html_UI_style` VARCHAR(32) NULL DEFAULT 'Nano' COLLATE 'utf8mb4_unicode_ci' AFTER `parallax_speed`;
+
+
+ALTER TABLE `ss13_poll_option`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_poll_option`
+ ALTER `text` DROP DEFAULT;
+ALTER TABLE `ss13_poll_option`
+ CHANGE COLUMN `text` `text` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `pollid`,
+ CHANGE COLUMN `descmin` `descmin` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `maxval`,
+ CHANGE COLUMN `descmid` `descmid` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `descmin`,
+ CHANGE COLUMN `descmax` `descmax` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `descmid`;
+
+ALTER TABLE `ss13_poll_question`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_poll_question`
+ ALTER `question` DROP DEFAULT;
+ALTER TABLE `ss13_poll_question`
+ CHANGE COLUMN `polltype` `polltype` VARCHAR(16) NOT NULL DEFAULT 'OPTION' COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `question` `question` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `endtime`,
+ CHANGE COLUMN `viewtoken` `viewtoken` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `publicresult`,
+ CHANGE COLUMN `createdby_ckey` `createdby_ckey` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `viewtoken`,
+ CHANGE COLUMN `createdby_ip` `createdby_ip` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `createdby_ckey`,
+ CHANGE COLUMN `link` `link` VARCHAR(250) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `createdby_ip`;
+
+ALTER TABLE `ss13_poll_textreply`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_poll_textreply`
+ ALTER `ckey` DROP DEFAULT,
+ ALTER `ip` DROP DEFAULT;
+ALTER TABLE `ss13_poll_textreply`
+ CHANGE COLUMN `ckey` `ckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `pollid`,
+ CHANGE COLUMN `ip` `ip` VARCHAR(18) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ckey`,
+ CHANGE COLUMN `replytext` `replytext` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ip`,
+ CHANGE COLUMN `adminrank` `adminrank` VARCHAR(32) NOT NULL DEFAULT 'Player' COLLATE 'utf8mb4_unicode_ci' AFTER `replytext`;
+
+ALTER TABLE `ss13_poll_vote`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_poll_vote`
+ ALTER `ckey` DROP DEFAULT,
+ ALTER `ip` DROP DEFAULT,
+ ALTER `adminrank` DROP DEFAULT;
+ALTER TABLE `ss13_poll_vote`
+ CHANGE COLUMN `ckey` `ckey` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `optionid`,
+ CHANGE COLUMN `ip` `ip` VARCHAR(16) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ckey`,
+ CHANGE COLUMN `adminrank` `adminrank` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ip`;
+
+ALTER TABLE `ss13_population`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+
+ALTER TABLE `ss13_syndie_contracts`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_syndie_contracts`
+ ALTER `contractee_name` DROP DEFAULT,
+ ALTER `status` DROP DEFAULT,
+ ALTER `title` DROP DEFAULT;
+ALTER TABLE `ss13_syndie_contracts`
+ CHANGE COLUMN `contractee_name` `contractee_name` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `contractee_id`,
+ CHANGE COLUMN `status` `status` ENUM('new','open','mod-nok','completed','closed','reopened','canceled') NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `contractee_name`,
+ CHANGE COLUMN `title` `title` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `status`,
+ CHANGE COLUMN `description` `description` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `title`,
+ CHANGE COLUMN `reward_other` `reward_other` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `reward_credits`,
+ CHANGE COLUMN `completer_name` `completer_name` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `completer_id`;
+
+ALTER TABLE `ss13_syndie_contracts_comments`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_syndie_contracts_comments`
+ ALTER `commentor_name` DROP DEFAULT,
+ ALTER `title` DROP DEFAULT,
+ ALTER `image_name` DROP DEFAULT,
+ ALTER `type` DROP DEFAULT;
+ALTER TABLE `ss13_syndie_contracts_comments`
+ CHANGE COLUMN `commentor_name` `commentor_name` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `commentor_id`,
+ CHANGE COLUMN `title` `title` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `commentor_name`,
+ CHANGE COLUMN `comment` `comment` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `title`,
+ CHANGE COLUMN `image_name` `image_name` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `comment`,
+ CHANGE COLUMN `type` `type` ENUM('mod-author','mod-ooc','ic','ic-comprep','ic-failrep','ic-cancel','ooc') NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `image_name`,
+ CHANGE COLUMN `report_status` `report_status` ENUM('waiting-approval','accepted','rejected') NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `deleted_at`;
+
+ALTER TABLE `ss13_syndie_contracts_comments_completers`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+
+ALTER TABLE `ss13_syndie_contracts_comments_objectives`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+
+ALTER TABLE `ss13_syndie_contracts_objectives`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_syndie_contracts_objectives`
+ ALTER `status` DROP DEFAULT,
+ ALTER `title` DROP DEFAULT;
+ALTER TABLE `ss13_syndie_contracts_objectives`
+ CHANGE COLUMN `status` `status` ENUM('open','closed','deleted') NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `contract_id`,
+ CHANGE COLUMN `title` `title` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `status`,
+ CHANGE COLUMN `description` `description` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `title`,
+ CHANGE COLUMN `reward_other` `reward_other` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `reward_credits_update`,
+ CHANGE COLUMN `reward_other_update` `reward_other_update` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `reward_other`;
+
+ALTER TABLE `ss13_syndie_contracts_subscribers`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+
+ALTER TABLE `ss13_tickets`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_tickets`
+ ALTER `game_id` DROP DEFAULT,
+ ALTER `opened_by` DROP DEFAULT,
+ ALTER `closed_by` DROP DEFAULT;
+ALTER TABLE `ss13_tickets`
+ CHANGE COLUMN `game_id` `game_id` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `admin_list` `admin_list` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `admin_count`,
+ CHANGE COLUMN `opened_by` `opened_by` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `admin_list`,
+ CHANGE COLUMN `taken_by` `taken_by` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `opened_by`,
+ CHANGE COLUMN `closed_by` `closed_by` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `taken_by`;
+
+ALTER TABLE `ss13_warnings`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_warnings`
+ ALTER `ckey` DROP DEFAULT,
+ ALTER `computerid` DROP DEFAULT,
+ ALTER `ip` DROP DEFAULT,
+ ALTER `a_ckey` DROP DEFAULT;
+ALTER TABLE `ss13_warnings`
+ CHANGE COLUMN `reason` `reason` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `severity`,
+ CHANGE COLUMN `notes` `notes` MEDIUMTEXT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `reason`,
+ CHANGE COLUMN `ckey` `ckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `notes`,
+ CHANGE COLUMN `computerid` `computerid` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ckey`,
+ CHANGE COLUMN `ip` `ip` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `computerid`,
+ CHANGE COLUMN `a_ckey` `a_ckey` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ip`,
+ CHANGE COLUMN `a_computerid` `a_computerid` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `a_ckey`,
+ CHANGE COLUMN `a_ip` `a_ip` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `a_computerid`,
+ CHANGE COLUMN `lasteditor` `lasteditor` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `edited`;
+
+ALTER TABLE `ss13_webhooks`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_webhooks`
+ CHANGE COLUMN `url` `url` LONGTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `tags` `tags` LONGTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `url`,
+ CHANGE COLUMN `mention` `mention` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `tags`;
+
+ALTER TABLE `ss13_web_sso`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_web_sso`
+ ALTER `ckey` DROP DEFAULT,
+ ALTER `token` DROP DEFAULT,
+ ALTER `ip` DROP DEFAULT;
+ALTER TABLE `ss13_web_sso`
+ CHANGE COLUMN `ckey` `ckey` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `id`,
+ CHANGE COLUMN `token` `token` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ckey`,
+ CHANGE COLUMN `ip` `ip` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `token`;
+
+ALTER TABLE `ss13_whitelist_log`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_whitelist_log`
+ ALTER `user` DROP DEFAULT;
+ALTER TABLE `ss13_whitelist_log`
+ CHANGE COLUMN `user` `user` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `datetime`,
+ CHANGE COLUMN `action_method` `action_method` VARCHAR(32) NOT NULL DEFAULT 'Game Server' COLLATE 'utf8mb4_unicode_ci' AFTER `user`,
+ CHANGE COLUMN `action` `action` LONGTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `action_method`;
+
+ALTER TABLE `ss13_whitelist_statuses`
+ COLLATE='utf8mb4_unicode_ci',
+ CONVERT TO CHARSET utf8mb4;
+ALTER TABLE `ss13_whitelist_statuses`
+ ALTER `status_name` DROP DEFAULT;
+ALTER TABLE `ss13_whitelist_statuses`
+ CHANGE COLUMN `status_name` `status_name` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `flag`;
+SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
+
+-- Allows the char name of the antag log to be nulled
+ALTER TABLE `ss13_antag_log`
+ ALTER `char_name` DROP DEFAULT;
+ALTER TABLE `ss13_antag_log`
+ CHANGE COLUMN `char_name` `char_name` VARCHAR(50) NULL AFTER `game_id`;
+
+-- Allows ip and computerid in the ss13_player table to be nulled
+ALTER TABLE `ss13_player`
+ ALTER `ip` DROP DEFAULT,
+ ALTER `computerid` DROP DEFAULT;
+ALTER TABLE `ss13_player`
+ CHANGE COLUMN `ip` `ip` VARCHAR(18) NULL COLLATE 'utf8mb4_unicode_ci' AFTER `lastseen`,
+ CHANGE COLUMN `computerid` `computerid` VARCHAR(32) NULL COLLATE 'utf8mb4_unicode_ci' AFTER `ip`;
+
+-- Allows the ss13_library uploader to be nulled
+ALTER TABLE `ss13_library`
+ CHANGE COLUMN `uploader` `uploader` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `uploadtime`;
+
+-- Add/Update forein keys for ckeys
+ALTER TABLE `ss13_admin_log`
+ ADD CONSTRAINT `FK_ss13_admin_log_ss13_player` FOREIGN KEY (`adminckey`) REFERENCES `ss13_player` (`ckey`) ON UPDATE CASCADE;
+
+ALTER TABLE `ss13_antag_log`
+ ADD CONSTRAINT `FK_ss13_antag_log_ss13_player` FOREIGN KEY (`ckey`) REFERENCES `ss13_player` (`ckey`) ON UPDATE CASCADE;
+
+
+INSERT INTO ss13_player (ckey, firstseen, lastseen, ip, computerid)
+SELECT ss13_ban.ckey, ss13_ban.bantime AS first, ss13_ban.bantime AS last, ss13_ban.computerid, ss13_ban.ip
+FROM ss13_ban
+LEFT JOIN ss13_player
+ ON ss13_player.ckey = ss13_ban.ckey
+WHERE ss13_player.ckey IS NULL
+ON DUPLICATE KEY UPDATE byond_version = null;
+
+ALTER TABLE `ss13_ban`
+ ADD CONSTRAINT `FK_ss13_ban_ss13_player_ckey` FOREIGN KEY (`ckey`) REFERENCES `ss13_player` (`ckey`) ON UPDATE CASCADE;
+
+ALTER TABLE `ss13_ban`
+ ADD CONSTRAINT `FK_ss13_ban_ss13_player_a_ckey` FOREIGN KEY (`a_ckey`) REFERENCES `ss13_player` (`ckey`) ON UPDATE CASCADE;
+
+ALTER TABLE `ss13_ccia_reports_transcripts`
+ ADD CONSTRAINT `FK_ss13_ccia_reports_transcripts_ss13_characters` FOREIGN KEY (`character_id`) REFERENCES `ss13_characters` (`id`) ON UPDATE CASCADE;
+
+ALTER TABLE `ss13_ipc_tracking`
+ ADD CONSTRAINT `FK_ss13_ipc_tracking_ss13_player` FOREIGN KEY (`player_ckey`) REFERENCES `ss13_player` (`ckey`) ON UPDATE CASCADE;
+
+
+UPDATE `ss13_library` SET `uploader` = NULL WHERE `uploader` = "";
+UPDATE `ss13_library` SET `uploader` = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(LOWER(`uploader`),' ',''),'_',''),'-',''),'.',''),'@','');
+
+ALTER TABLE `ss13_library`
+ ADD CONSTRAINT `FK_ss13_library_ss13_player` FOREIGN KEY (`uploader`) REFERENCES `ss13_player` (`ckey`) ON UPDATE CASCADE;
+
+
+UPDATE `ss13_notes` SET `ckey` = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(LOWER(`ckey`),' ',''),'_',''),'-',''),'.',''),'@','');
+
+INSERT INTO ss13_player (ckey, firstseen, lastseen, ip, computerid)
+SELECT ss13_notes.ckey, ss13_notes.adddate AS first, ss13_notes.adddate AS lst, ss13_notes.computerid, ss13_notes.ip
+FROM ss13_notes
+LEFT JOIN ss13_player
+ ON ss13_player.ckey = ss13_notes.ckey
+WHERE ss13_player.ckey IS NULL
+ON DUPLICATE KEY UPDATE ss13_player.byond_version = NULL;
+
+ALTER TABLE `ss13_notes`
+ ADD CONSTRAINT `FK_ss13_notes_ss13_player_ckey` FOREIGN KEY (`ckey`) REFERENCES `ss13_player` (`ckey`) ON UPDATE CASCADE;
+
+UPDATE `ss13_notes` SET `a_ckey` = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(LOWER(`a_ckey`),' ',''),'_',''),'-',''),'.',''),'@','');
+
+ALTER TABLE `ss13_notes`
+ ADD CONSTRAINT `FK_ss13_notes_ss13_player_a_ckey` FOREIGN KEY (`a_ckey`) REFERENCES `ss13_player` (`ckey`) ON UPDATE CASCADE;
+
+ALTER TABLE `ss13_player_notifications`
+ ADD CONSTRAINT `FK_ss13_player_notifications_ss13_player` FOREIGN KEY (`ckey`) REFERENCES `ss13_player` (`ckey`) ON UPDATE CASCADE;
+
+ALTER TABLE `ss13_poll_textreply`
+ ADD CONSTRAINT `FK_ss13_poll_textreply_ss13_player` FOREIGN KEY (`ckey`) REFERENCES `ss13_player` (`ckey`) ON UPDATE CASCADE;
+
+ALTER TABLE `ss13_poll_vote`
+ ADD CONSTRAINT `FK_ss13_poll_vote_ss13_player` FOREIGN KEY (`ckey`) REFERENCES `ss13_player` (`ckey`) ON UPDATE CASCADE;
+
+ALTER TABLE `ss13_warnings`
+ ADD CONSTRAINT `FK_ss13_warnings_ss13_player_ckey` FOREIGN KEY (`ckey`) REFERENCES `ss13_player` (`ckey`) ON UPDATE CASCADE;
+
+ALTER TABLE `ss13_warnings`
+ ADD CONSTRAINT `FK_ss13_warnings_ss13_player_a_ckey` FOREIGN KEY (`a_ckey`) REFERENCES `ss13_player` (`ckey`) ON UPDATE CASCADE;
\ No newline at end of file
diff --git a/SQL/migrate/V042__random_job_removal.sql b/SQL/migrate/V042__random_job_removal.sql
new file mode 100644
index 00000000000..82940dfe437
--- /dev/null
+++ b/SQL/migrate/V042__random_job_removal.sql
@@ -0,0 +1,6 @@
+--
+-- Removes the Random Job Option
+--
+
+UPDATE ss13_characters SET alternate_option = 0 WHERE alternate_option = 1;
+UPDATE ss13_characters SET alternate_option = 1 WHERE alternate_option = 2;
\ No newline at end of file
diff --git a/SQL/migrate/V043__Skin_Themes.sql b/SQL/migrate/V043__Skin_Themes.sql
new file mode 100644
index 00000000000..4b709d34775
--- /dev/null
+++ b/SQL/migrate/V043__Skin_Themes.sql
@@ -0,0 +1,6 @@
+--
+-- Adds HTML style value to the player preferences table.
+--
+
+ALTER TABLE `ss13_player_preferences`
+ ADD `skin_theme` VARCHAR(32) DEFAULT 'Light';
diff --git a/SQL/migrate/V044__client_fps.sql b/SQL/migrate/V044__client_fps.sql
new file mode 100644
index 00000000000..8a544dca608
--- /dev/null
+++ b/SQL/migrate/V044__client_fps.sql
@@ -0,0 +1,6 @@
+--
+-- Complimentary of PR #7127
+--
+
+ALTER TABLE `ss13_player_preferences`
+ ADD `clientfps` INT DEFAULT '0' AFTER `ooccolor`;
diff --git a/SQL/migrate/V045__underwear_updates.sql b/SQL/migrate/V045__underwear_updates.sql
new file mode 100644
index 00000000000..6651b2da420
--- /dev/null
+++ b/SQL/migrate/V045__underwear_updates.sql
@@ -0,0 +1,11 @@
+--
+-- Adds support for underwear updates in PR #6973.
+-- This collates all underwear data into one column, with an additional column for custom colours.
+--
+
+ALTER TABLE `ss13_characters`
+ ADD COLUMN `all_underwear` JSON NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `eyes_colour`,
+ DROP COLUMN `underwear`,
+ DROP COLUMN `undershirt`,
+ DROP COLUMN `socks`,
+ ADD COLUMN `all_underwear_metadata` JSON NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `all_underwear`;
diff --git a/SQL/migrate/V046__radials.sql b/SQL/migrate/V046__radials.sql
new file mode 100644
index 00000000000..05294a2a95e
--- /dev/null
+++ b/SQL/migrate/V046__radials.sql
@@ -0,0 +1,7 @@
+--
+-- Adds support for underwear updates in PR #8710.
+-- What else do you think this does?
+--
+
+ALTER TABLE `ss13_player_preferences`
+ ADD `tooltip_style` ENUM('Midnight', 'Plasmafire', 'Retro', 'Slimecore', 'Operative', 'Clockwork') NULL DEFAULT 'Midnight';
diff --git a/TGS3.json b/TGS3.json
index 0a39b575898..9613631c728 100644
--- a/TGS3.json
+++ b/TGS3.json
@@ -14,7 +14,8 @@
],
"static_directories": [
"config",
- "data"
+ "data",
+ "dynamic_maps"
],
"dlls": [
"libmysql.dll"
diff --git a/UDPShipper.dll b/UDPShipper.dll
deleted file mode 100644
index ceef0d0d392..00000000000
Binary files a/UDPShipper.dll and /dev/null differ
diff --git a/aurorastation.dme b/aurorastation.dme
index ef5c1a8ceb8..66820e30554 100644
--- a/aurorastation.dme
+++ b/aurorastation.dme
@@ -23,27 +23,35 @@
#include "code\__defines\battle_monsters.dm"
#include "code\__defines\callback.dm"
#include "code\__defines\chemistry.dm"
+#include "code\__defines\color.dm"
#include "code\__defines\damage_organs.dm"
#include "code\__defines\dna.dm"
#include "code\__defines\dview.dm"
+#include "code\__defines\flags.dm"
#include "code\__defines\gamemode.dm"
+#include "code\__defines\guns.dm"
#include "code\__defines\hydroponics.dm"
#include "code\__defines\items_clothing.dm"
#include "code\__defines\lighting.dm"
#include "code\__defines\lists.dm"
#include "code\__defines\machinery.dm"
#include "code\__defines\master_controller.dm"
+#include "code\__defines\materials.dm"
#include "code\__defines\math_physics.dm"
#include "code\__defines\minimap.dm"
#include "code\__defines\mining.dm"
#include "code\__defines\misc.dm"
#include "code\__defines\mobs.dm"
#include "code\__defines\modular_guns.dm"
+#include "code\__defines\obj.dm"
+#include "code\__defines\psi.dm"
#include "code\__defines\qdel.dm"
#include "code\__defines\radio.dm"
#include "code\__defines\regex.dm"
#include "code\__defines\research.dm"
#include "code\__defines\rust_g.dm"
+#include "code\__defines\shuttle.dm"
+#include "code\__defines\spaceman_dmm.dm"
#include "code\__defines\species_languages.dm"
#include "code\__defines\subsystem-defines.dm"
#include "code\__defines\subsystem-priority.dm"
@@ -54,6 +62,7 @@
#include "code\__defines\vueui.dm"
#include "code\__defines\webhook.dm"
#include "code\__defines\ZAS.dm"
+#include "code\_helpers\_global_objects.dm"
#include "code\_helpers\_string_lists.dm"
#include "code\_helpers\area_movement.dm"
#include "code\_helpers\areas.dm"
@@ -93,7 +102,6 @@
#include "code\_onclick\observer.dm"
#include "code\_onclick\other_mobs.dm"
#include "code\_onclick\rig.dm"
-#include "code\_onclick\telekinesis.dm"
#include "code\_onclick\hud\_defines.dm"
#include "code\_onclick\hud\action.dm"
#include "code\_onclick\hud\ai.dm"
@@ -104,6 +112,8 @@
#include "code\_onclick\hud\movable_screen_objects.dm"
#include "code\_onclick\hud\other_mobs.dm"
#include "code\_onclick\hud\parallax.dm"
+#include "code\_onclick\hud\radial.dm"
+#include "code\_onclick\hud\radial_persistent.dm"
#include "code\_onclick\hud\robot.dm"
#include "code\_onclick\hud\screen_objects.dm"
#include "code\_onclick\hud\spell_screen_objects.dm"
@@ -160,15 +170,20 @@
#include "code\controllers\subsystems\battle_monsters.dm"
#include "code\controllers\subsystems\cargo.dm"
#include "code\controllers\subsystems\chemistry.dm"
+#include "code\controllers\subsystems\documents.dm"
#include "code\controllers\subsystems\economy.dm"
#include "code\controllers\subsystems\effects.dm"
#include "code\controllers\subsystems\emergency_shuttle.dm"
#include "code\controllers\subsystems\event.dm"
#include "code\controllers\subsystems\explosives.dm"
+#include "code\controllers\subsystems\fail2topic.dm"
#include "code\controllers\subsystems\falling.dm"
#include "code\controllers\subsystems\garbage-debug.dm"
#include "code\controllers\subsystems\garbage.dm"
+#include "code\controllers\subsystems\ghostroles.dm"
#include "code\controllers\subsystems\global_listener.dm"
+#include "code\controllers\subsystems\hallucinations.dm"
+#include "code\controllers\subsystems\http.dm"
#include "code\controllers\subsystems\icon_cache.dm"
#include "code\controllers\subsystems\icon_smooth.dm"
#include "code\controllers\subsystems\icon_updates.dm"
@@ -177,6 +192,7 @@
#include "code\controllers\subsystems\law.dm"
#include "code\controllers\subsystems\lighting.dm"
#include "code\controllers\subsystems\machinery.dm"
+#include "code\controllers\subsystems\materials.dm"
#include "code\controllers\subsystems\mob.dm"
#include "code\controllers\subsystems\mob_ai.dm"
#include "code\controllers\subsystems\news.dm"
@@ -188,14 +204,18 @@
#include "code\controllers\subsystems\plants.dm"
#include "code\controllers\subsystems\power.dm"
#include "code\controllers\subsystems\radio.dm"
+#include "code\controllers\subsystems\records.dm"
#include "code\controllers\subsystems\responseteam.dm"
#include "code\controllers\subsystems\statistics.dm"
+#include "code\controllers\subsystems\stickyban.dm"
#include "code\controllers\subsystems\sun.dm"
#include "code\controllers\subsystems\sunlight.dm"
+#include "code\controllers\subsystems\theming.dm"
#include "code\controllers\subsystems\ticker.dm"
#include "code\controllers\subsystems\timer.dm"
#include "code\controllers\subsystems\trade.dm"
#include "code\controllers\subsystems\traumas.dm"
+#include "code\controllers\subsystems\virtual_reality.dm"
#include "code\controllers\subsystems\vote.dm"
#include "code\controllers\subsystems\zcopy.dm"
#include "code\controllers\subsystems\initialization\atlas.dm"
@@ -217,18 +237,17 @@
#include "code\controllers\subsystems\processing\pipenet.dm"
#include "code\controllers\subsystems\processing\processing.dm"
#include "code\controllers\subsystems\processing\projectiles.dm"
+#include "code\controllers\subsystems\processing\psi.dm"
#include "code\controllers\subsystems\processing\shuttle.dm"
#include "code\controllers\subsystems\processing\vueui.dm"
#include "code\datums\ai_law_sets.dm"
#include "code\datums\ai_laws.dm"
-#include "code\datums\api.dm"
#include "code\datums\beam.dm"
#include "code\datums\browser.dm"
#include "code\datums\callback.dm"
#include "code\datums\cargo.dm"
#include "code\datums\category.dm"
#include "code\datums\computerfiles.dm"
-#include "code\datums\datacore.dm"
#include "code\datums\datum.dm"
#include "code\datums\disease.dm"
#include "code\datums\feedback.dm"
@@ -237,6 +256,7 @@
#include "code\datums\modules.dm"
#include "code\datums\position_point_vector.dm"
#include "code\datums\progressbar.dm"
+#include "code\datums\records.dm"
#include "code\datums\server_greeting.dm"
#include "code\datums\statistic.dm"
#include "code\datums\weakref.dm"
@@ -267,7 +287,6 @@
#include "code\datums\diseases\rhumba_beat.dm"
#include "code\datums\diseases\robotic_transformation.dm"
#include "code\datums\diseases\wizarditis.dm"
-#include "code\datums\diseases\xeno_transformation.dm"
#include "code\datums\diseases\advance\advance.dm"
#include "code\datums\diseases\advance\presets.dm"
#include "code\datums\diseases\advance\symptoms\confusion.dm"
@@ -285,6 +304,10 @@
#include "code\datums\diseases\advance\symptoms\voice_change.dm"
#include "code\datums\diseases\advance\symptoms\vomit.dm"
#include "code\datums\diseases\advance\symptoms\weight.dm"
+#include "code\datums\ert\nanotrasen.dm"
+#include "code\datums\ert\outsider.dm"
+#include "code\datums\ert\responseteam.dm"
+#include "code\datums\ert\tcfl.dm"
#include "code\datums\expansions\expansion.dm"
#include "code\datums\expansions\multitool\_multitool.dm"
#include "code\datums\expansions\multitool\multitool.dm"
@@ -294,21 +317,34 @@
#include "code\datums\expansions\multitool\items\cable.dm"
#include "code\datums\expansions\multitool\items\items.dm"
#include "code\datums\expansions\multitool\machinery\cloning.dm"
+#include "code\datums\helper_datums\away_mission.dm"
#include "code\datums\helper_datums\construction_datum.dm"
#include "code\datums\helper_datums\events.dm"
#include "code\datums\helper_datums\getrev.dm"
+#include "code\datums\helper_datums\synthsprites.dm"
#include "code\datums\helper_datums\teleport.dm"
#include "code\datums\helper_datums\topic_input.dm"
+#include "code\datums\looping_sounds\_looping_sound.dm"
+#include "code\datums\looping_sounds\machinery_sounds.dm"
#include "code\datums\observation\_debug.dm"
#include "code\datums\observation\destroyed.dm"
#include "code\datums\observation\moved.dm"
#include "code\datums\observation\observation.dm"
#include "code\datums\outfits\outfit.dm"
#include "code\datums\outfits\outfit_admin.dm"
+#include "code\datums\outfits\outfit_antag.dm"
+#include "code\datums\outfits\ert\deathsquad.dm"
+#include "code\datums\outfits\ert\iac.dm"
+#include "code\datums\outfits\ert\kataphract.dm"
+#include "code\datums\outfits\ert\mercenary.dm"
+#include "code\datums\outfits\ert\nt_ert.dm"
+#include "code\datums\outfits\ert\syndicate.dm"
+#include "code\datums\outfits\ert\tcfl.dm"
#include "code\datums\radio\frequency.dm"
#include "code\datums\radio\signal.dm"
#include "code\datums\repositories\cameras.dm"
#include "code\datums\repositories\crew.dm"
+#include "code\datums\repositories\decls.dm"
#include "code\datums\repositories\repository.dm"
#include "code\datums\trading\_trading_defines.dm"
#include "code\datums\trading\ai.dm"
@@ -320,16 +356,26 @@
#include "code\datums\trading\unique.dm"
#include "code\datums\trading\vox.dm"
#include "code\datums\trading\weaponry.dm"
+#include "code\datums\underwear\bottom.dm"
+#include "code\datums\underwear\socks.dm"
+#include "code\datums\underwear\top.dm"
+#include "code\datums\underwear\undershirt.dm"
+#include "code\datums\underwear\underwear.dm"
#include "code\datums\uplink\ammunition.dm"
#include "code\datums\uplink\announcements.dm"
#include "code\datums\uplink\badassery.dm"
+#include "code\datums\uplink\corporate_equipment.dm"
#include "code\datums\uplink\devices and tools.dm"
+#include "code\datums\uplink\exosuit.dm"
+#include "code\datums\uplink\exosuit_equipment.dm"
+#include "code\datums\uplink\gear loadout.dm"
#include "code\datums\uplink\grenades.dm"
#include "code\datums\uplink\hardsuit_modules.dm"
#include "code\datums\uplink\highly visible and dangerous weapons.dm"
#include "code\datums\uplink\implants.dm"
#include "code\datums\uplink\medical.dm"
#include "code\datums\uplink\ninja_modules.dm"
+#include "code\datums\uplink\revolution.dm"
#include "code\datums\uplink\specialty.dm"
#include "code\datums\uplink\stealth and camouflage items.dm"
#include "code\datums\uplink\stealthy and inconspicuous weapons.dm"
@@ -353,6 +399,7 @@
#include "code\datums\wires\vending.dm"
#include "code\datums\wires\wires.dm"
#include "code\defines\gases.dm"
+#include "code\defines\mutable_appearance.dm"
#include "code\defines\obj.dm"
#include "code\defines\obj\weapon.dm"
#include "code\defines\procs\announce.dm"
@@ -382,11 +429,9 @@
#include "code\game\antagonist\antagonist_print.dm"
#include "code\game\antagonist\antagonist_update.dm"
#include "code\game\antagonist\alien\borer.dm"
-#include "code\game\antagonist\alien\xenomorph.dm"
#include "code\game\antagonist\outsider\commando.dm"
#include "code\game\antagonist\outsider\deathsquad.dm"
#include "code\game\antagonist\outsider\ert.dm"
-#include "code\game\antagonist\outsider\legion.dm"
#include "code\game\antagonist\outsider\mercenary.dm"
#include "code\game\antagonist\outsider\ninja.dm"
#include "code\game\antagonist\outsider\raider.dm"
@@ -417,22 +462,59 @@
#include "code\game\gamemodes\game_mode_latespawn.dm"
#include "code\game\gamemodes\objective.dm"
#include "code\game\gamemodes\setupgame.dm"
+#include "code\game\gamemodes\borer\borer.dm"
#include "code\game\gamemodes\calamity\calamity.dm"
-#include "code\game\gamemodes\changeling\changeling.dm"
-#include "code\game\gamemodes\changeling\changeling_items.dm"
-#include "code\game\gamemodes\changeling\changeling_powers.dm"
-#include "code\game\gamemodes\changeling\modularchangling.dm"
+#include "code\game\gamemodes\changeling\helpers\_framework.dm"
+#include "code\game\gamemodes\changeling\helpers\_store.dm"
+#include "code\game\gamemodes\changeling\helpers\changeling.dm"
+#include "code\game\gamemodes\changeling\implements\items.dm"
+#include "code\game\gamemodes\changeling\implements\powers\body.dm"
+#include "code\game\gamemodes\changeling\implements\powers\resources.dm"
+#include "code\game\gamemodes\changeling\implements\powers\stings.dm"
+#include "code\game\gamemodes\changeling\implements\powers\suck.dm"
#include "code\game\gamemodes\cult\cult.dm"
-#include "code\game\gamemodes\cult\cult_items.dm"
-#include "code\game\gamemodes\cult\cult_structures.dm"
#include "code\game\gamemodes\cult\hell_universe.dm"
#include "code\game\gamemodes\cult\narsie.dm"
-#include "code\game\gamemodes\cult\ritual.dm"
-#include "code\game\gamemodes\cult\runes.dm"
-#include "code\game\gamemodes\cult\talisman.dm"
#include "code\game\gamemodes\cult\cultify\mob.dm"
#include "code\game\gamemodes\cult\cultify\obj.dm"
#include "code\game\gamemodes\cult\cultify\turf.dm"
+#include "code\game\gamemodes\cult\items\armor.dm"
+#include "code\game\gamemodes\cult\items\clothes.dm"
+#include "code\game\gamemodes\cult\items\sword.dm"
+#include "code\game\gamemodes\cult\items\talisman.dm"
+#include "code\game\gamemodes\cult\items\tome.dm"
+#include "code\game\gamemodes\cult\runes\armor.dm"
+#include "code\game\gamemodes\cult\runes\blind_others.dm"
+#include "code\game\gamemodes\cult\runes\blood_boil.dm"
+#include "code\game\gamemodes\cult\runes\blood_drain.dm"
+#include "code\game\gamemodes\cult\runes\communicate.dm"
+#include "code\game\gamemodes\cult\runes\conversion.dm"
+#include "code\game\gamemodes\cult\runes\create_construct.dm"
+#include "code\game\gamemodes\cult\runes\create_talisman.dm"
+#include "code\game\gamemodes\cult\runes\deafen_others.dm"
+#include "code\game\gamemodes\cult\runes\emp.dm"
+#include "code\game\gamemodes\cult\runes\free_cultist.dm"
+#include "code\game\gamemodes\cult\runes\ghost_mode.dm"
+#include "code\game\gamemodes\cult\runes\hide_runes.dm"
+#include "code\game\gamemodes\cult\runes\manifest_ghost.dm"
+#include "code\game\gamemodes\cult\runes\raise_dead.dm"
+#include "code\game\gamemodes\cult\runes\reveal_runes.dm"
+#include "code\game\gamemodes\cult\runes\rune.dm"
+#include "code\game\gamemodes\cult\runes\sacrifice.dm"
+#include "code\game\gamemodes\cult\runes\see_invisible.dm"
+#include "code\game\gamemodes\cult\runes\stun.dm"
+#include "code\game\gamemodes\cult\runes\summon_cultist.dm"
+#include "code\game\gamemodes\cult\runes\summon_narsie.dm"
+#include "code\game\gamemodes\cult\runes\summon_soulstone.dm"
+#include "code\game\gamemodes\cult\runes\summon_tome.dm"
+#include "code\game\gamemodes\cult\runes\teleport.dm"
+#include "code\game\gamemodes\cult\runes\wall.dm"
+#include "code\game\gamemodes\cult\structures\altar.dm"
+#include "code\game\gamemodes\cult\structures\desk.dm"
+#include "code\game\gamemodes\cult\structures\forge.dm"
+#include "code\game\gamemodes\cult\structures\gateway.dm"
+#include "code\game\gamemodes\cult\structures\pylon.dm"
+#include "code\game\gamemodes\cult\structures\structure.dm"
#include "code\game\gamemodes\endgame\endgame.dm"
#include "code\game\gamemodes\endgame\supermatter_cascade\blob.dm"
#include "code\game\gamemodes\endgame\supermatter_cascade\portal.dm"
@@ -460,15 +542,20 @@
#include "code\game\gamemodes\malfunction\newmalf_ability_trees\tree_synthetic.dm"
#include "code\game\gamemodes\meteor\meteor.dm"
#include "code\game\gamemodes\meteor\meteors.dm"
+#include "code\game\gamemodes\mixed\acolytes.dm"
#include "code\game\gamemodes\mixed\bughunt.dm"
#include "code\game\gamemodes\mixed\conflux.dm"
#include "code\game\gamemodes\mixed\crossfire.dm"
#include "code\game\gamemodes\mixed\feeding.dm"
+#include "code\game\gamemodes\mixed\incursion.dm"
#include "code\game\gamemodes\mixed\infestation.dm"
#include "code\game\gamemodes\mixed\infiltration.dm"
+#include "code\game\gamemodes\mixed\insurrection.dm"
#include "code\game\gamemodes\mixed\intrigue.dm"
#include "code\game\gamemodes\mixed\paranoia.dm"
#include "code\game\gamemodes\mixed\siege.dm"
+#include "code\game\gamemodes\mixed\spyvspy.dm"
+#include "code\game\gamemodes\mixed\towerdefense.dm"
#include "code\game\gamemodes\mixed\traitorling.dm"
#include "code\game\gamemodes\mixed\uprising.dm"
#include "code\game\gamemodes\mixed\veilparty.dm"
@@ -489,6 +576,14 @@
#include "code\game\jobs\access_datum.dm"
#include "code\game\jobs\jobs.dm"
#include "code\game\jobs\whitelist.dm"
+#include "code\game\jobs\faction\eridani.dm"
+#include "code\game\jobs\faction\faction.dm"
+#include "code\game\jobs\faction\hephaestus.dm"
+#include "code\game\jobs\faction\idris.dm"
+#include "code\game\jobs\faction\nanotrasen.dm"
+#include "code\game\jobs\faction\necropolis.dm"
+#include "code\game\jobs\faction\unaffiliated.dm"
+#include "code\game\jobs\faction\zeng_hu.dm"
#include "code\game\jobs\job\assistant.dm"
#include "code\game\jobs\job\captain.dm"
#include "code\game\jobs\job\civilian.dm"
@@ -500,6 +595,7 @@
#include "code\game\jobs\job\security.dm"
#include "code\game\jobs\job\silicon.dm"
#include "code\game\jobs\job\outsider\merchant.dm"
+#include "code\game\jobs\job\outsider\representative.dm"
#include "code\game\machinery\adv_med.dm"
#include "code\game\machinery\ai_slipper.dm"
#include "code\game\machinery\alarm.dm"
@@ -530,6 +626,7 @@
#include "code\game\machinery\floor_light.dm"
#include "code\game\machinery\floorlayer.dm"
#include "code\game\machinery\from_beyond.dm"
+#include "code\game\machinery\gumball.dm"
#include "code\game\machinery\hologram.dm"
#include "code\game\machinery\holosign.dm"
#include "code\game\machinery\igniter.dm"
@@ -539,6 +636,8 @@
#include "code\game\machinery\machinery.dm"
#include "code\game\machinery\magnet.dm"
#include "code\game\machinery\mass_driver.dm"
+#include "code\game\machinery\mech_recharger.dm"
+#include "code\game\machinery\mecha_fabricator.dm"
#include "code\game\machinery\megavend.dm"
#include "code\game\machinery\navbeacon.dm"
#include "code\game\machinery\newscaster.dm"
@@ -594,20 +693,16 @@
#include "code\game\machinery\computer\camera.dm"
#include "code\game\machinery\computer\cloning.dm"
#include "code\game\machinery\computer\computer.dm"
-#include "code\game\machinery\computer\crew.dm"
#include "code\game\machinery\computer\guestpass.dm"
#include "code\game\machinery\computer\law.dm"
-#include "code\game\machinery\computer\medical.dm"
#include "code\game\machinery\computer\message.dm"
#include "code\game\machinery\computer\Operating.dm"
#include "code\game\machinery\computer\pod.dm"
#include "code\game\machinery\computer\prisoner.dm"
#include "code\game\machinery\computer\RCON_Console.dm"
#include "code\game\machinery\computer\robot.dm"
-#include "code\game\machinery\computer\security.dm"
#include "code\game\machinery\computer\sentencing.dm"
#include "code\game\machinery\computer\shuttle.dm"
-#include "code\game\machinery\computer\skills.dm"
#include "code\game\machinery\computer\slotmachine.dm"
#include "code\game\machinery\computer\specops_shuttle.dm"
#include "code\game\machinery\computer\station_alert.dm"
@@ -658,36 +753,6 @@
#include "code\game\machinery\telecomms\telecomunications.dm"
#include "code\game\machinery\telecomms\telemonitor.dm"
#include "code\game\machinery\telecomms\traffic_control.dm"
-#include "code\game\magic\Uristrunes.dm"
-#include "code\game\mecha\mech_bay.dm"
-#include "code\game\mecha\mech_fabricator.dm"
-#include "code\game\mecha\mech_sensor.dm"
-#include "code\game\mecha\mecha.dm"
-#include "code\game\mecha\mecha_construction_paths.dm"
-#include "code\game\mecha\mecha_control_console.dm"
-#include "code\game\mecha\mecha_parts.dm"
-#include "code\game\mecha\mecha_wreckage.dm"
-#include "code\game\mecha\combat\combat.dm"
-#include "code\game\mecha\combat\durand.dm"
-#include "code\game\mecha\combat\gygax.dm"
-#include "code\game\mecha\combat\honker.dm"
-#include "code\game\mecha\combat\marauder.dm"
-#include "code\game\mecha\combat\phazon.dm"
-#include "code\game\mecha\combat\tank.dm"
-#include "code\game\mecha\equipment\mecha_equipment.dm"
-#include "code\game\mecha\equipment\tracking_beacon.dm"
-#include "code\game\mecha\equipment\tools\medical_tools.dm"
-#include "code\game\mecha\equipment\tools\tools.dm"
-#include "code\game\mecha\equipment\weapons\mecha_ballistics.dm"
-#include "code\game\mecha\equipment\weapons\mecha_energy.dm"
-#include "code\game\mecha\equipment\weapons\mecha_grenades.dm"
-#include "code\game\mecha\equipment\weapons\weapons.dm"
-#include "code\game\mecha\medical\medical.dm"
-#include "code\game\mecha\medical\odysseus.dm"
-#include "code\game\mecha\working\hermes.dm"
-#include "code\game\mecha\working\hoverpod.dm"
-#include "code\game\mecha\working\ripley.dm"
-#include "code\game\mecha\working\working.dm"
#include "code\game\modifiers\modifiers.dm"
#include "code\game\modifiers\modifiers_chem.dm"
#include "code\game\objects\buckling.dm"
@@ -696,7 +761,6 @@
#include "code\game\objects\items.dm"
#include "code\game\objects\objs.dm"
#include "code\game\objects\structures.dm"
-#include "code\game\objects\weapons.dm"
#include "code\game\objects\effects\aliens.dm"
#include "code\game\objects\effects\bump_teleporter.dm"
#include "code\game\objects\effects\effect_system.dm"
@@ -732,7 +796,9 @@
#include "code\game\objects\effects\projectile\projectile_tracer.dm"
#include "code\game\objects\effects\spawners\bombspawner.dm"
#include "code\game\objects\effects\spawners\gibspawner.dm"
+#include "code\game\objects\effects\temporary_visuals\blaster_effect.dm"
#include "code\game\objects\effects\temporary_visuals\blood_splatter.dm"
+#include "code\game\objects\effects\temporary_visuals\nuke.dm"
#include "code\game\objects\effects\temporary_visuals\temporary_visual.dm"
#include "code\game\objects\items\airbubble.dm"
#include "code\game\objects\items\apc_frame.dm"
@@ -741,23 +807,27 @@
#include "code\game\objects\items\bodybag.dm"
#include "code\game\objects\items\contraband.dm"
#include "code\game\objects\items\crayons.dm"
+#include "code\game\objects\items\draftingchalk.dm"
#include "code\game\objects\items\eightball.dm"
#include "code\game\objects\items\glassjar.dm"
#include "code\game\objects\items\latexballoon.dm"
#include "code\game\objects\items\paintkit.dm"
#include "code\game\objects\items\shooting_range.dm"
+#include "code\game\objects\items\skrell.dm"
#include "code\game\objects\items\spirit_board.dm"
+#include "code\game\objects\items\tajara.dm"
#include "code\game\objects\items\toys.dm"
#include "code\game\objects\items\trash.dm"
#include "code\game\objects\items\devices\aicard.dm"
+#include "code\game\objects\items\devices\augment_implanter.dm"
#include "code\game\objects\items\devices\binoculars.dm"
#include "code\game\objects\items\devices\chameleonproj.dm"
#include "code\game\objects\items\devices\debugger.dm"
#include "code\game\objects\items\devices\dociler.dm"
#include "code\game\objects\items\devices\flash.dm"
-#include "code\game\objects\items\devices\flashlight.dm"
#include "code\game\objects\items\devices\floor_painter.dm"
#include "code\game\objects\items\devices\hacktool.dm"
+#include "code\game\objects\items\devices\hearing_aid.dm"
#include "code\game\objects\items\devices\holowarrant.dm"
#include "code\game\objects\items\devices\laserpointer.dm"
#include "code\game\objects\items\devices\lightmeter.dm"
@@ -777,6 +847,7 @@
#include "code\game\objects\items\devices\spy_bug.dm"
#include "code\game\objects\items\devices\suit_cooling.dm"
#include "code\game\objects\items\devices\t_scanner.dm"
+#include "code\game\objects\items\devices\tagger.dm"
#include "code\game\objects\items\devices\taperecorder.dm"
#include "code\game\objects\items\devices\traitordevices.dm"
#include "code\game\objects\items\devices\transfer_valve.dm"
@@ -784,10 +855,17 @@
#include "code\game\objects\items\devices\uplink_random_lists.dm"
#include "code\game\objects\items\devices\violin.dm"
#include "code\game\objects\items\devices\whistle.dm"
+#include "code\game\objects\items\devices\drop_targeter\_droptargeter.dm"
+#include "code\game\objects\items\devices\drop_targeter\orbital_drops.dm"
+#include "code\game\objects\items\devices\lighting\flare.dm"
+#include "code\game\objects\items\devices\lighting\flashlight.dm"
+#include "code\game\objects\items\devices\lighting\glowstick.dm"
+#include "code\game\objects\items\devices\lighting\lamp.dm"
#include "code\game\objects\items\devices\PDA\cart.dm"
#include "code\game\objects\items\devices\PDA\chatroom.dm"
#include "code\game\objects\items\devices\PDA\PDA.dm"
#include "code\game\objects\items\devices\PDA\radio.dm"
+#include "code\game\objects\items\devices\radio\_radio_defines.dm"
#include "code\game\objects\items\devices\radio\beacon.dm"
#include "code\game\objects\items\devices\radio\electropack.dm"
#include "code\game\objects\items\devices\radio\encryptionkey.dm"
@@ -803,16 +881,21 @@
#include "code\game\objects\items\stacks\rods.dm"
#include "code\game\objects\items\stacks\stack.dm"
#include "code\game\objects\items\stacks\telecrystal.dm"
+#include "code\game\objects\items\stacks\wrap.dm"
+#include "code\game\objects\items\stacks\sheets\glass.dm"
#include "code\game\objects\items\stacks\sheets\leather.dm"
+#include "code\game\objects\items\stacks\tiles\light.dm"
#include "code\game\objects\items\stacks\tiles\tile_types.dm"
#include "code\game\objects\items\weapons\AI_modules.dm"
#include "code\game\objects\items\weapons\autopsy.dm"
#include "code\game\objects\items\weapons\candle.dm"
#include "code\game\objects\items\weapons\cards_ids.dm"
#include "code\game\objects\items\weapons\cards_ids_syndicate.dm"
+#include "code\game\objects\items\weapons\cards_tech_support.dm"
+#include "code\game\objects\items\weapons\chaplain_items.dm"
+#include "code\game\objects\items\weapons\chewables.dm"
#include "code\game\objects\items\weapons\cigs_lighters.dm"
#include "code\game\objects\items\weapons\cloaking_device.dm"
-#include "code\game\objects\items\weapons\clown_items.dm"
#include "code\game\objects\items\weapons\cosmetics.dm"
#include "code\game\objects\items\weapons\dice.dm"
#include "code\game\objects\items\weapons\dna_injector.dm"
@@ -821,6 +904,7 @@
#include "code\game\objects\items\weapons\flamethrower.dm"
#include "code\game\objects\items\weapons\gift_wrappaper.dm"
#include "code\game\objects\items\weapons\handcuffs.dm"
+#include "code\game\objects\items\weapons\hydroponics.dm"
#include "code\game\objects\items\weapons\improvised_components.dm"
#include "code\game\objects\items\weapons\landmines.dm"
#include "code\game\objects\items\weapons\manuals.dm"
@@ -829,14 +913,14 @@
#include "code\game\objects\items\weapons\paiwire.dm"
#include "code\game\objects\items\weapons\policetape.dm"
#include "code\game\objects\items\weapons\power_cells.dm"
-#include "code\game\objects\items\weapons\RCD.dm"
-#include "code\game\objects\items\weapons\RSF.dm"
-#include "code\game\objects\items\weapons\RTF.dm"
+#include "code\game\objects\items\weapons\RFD.dm"
#include "code\game\objects\items\weapons\scrolls.dm"
#include "code\game\objects\items\weapons\shields.dm"
+#include "code\game\objects\items\weapons\soap.dm"
#include "code\game\objects\items\weapons\stunbaton.dm"
#include "code\game\objects\items\weapons\surgery_tools.dm"
#include "code\game\objects\items\weapons\swords_axes_etc.dm"
+#include "code\game\objects\items\weapons\syndie.dm"
#include "code\game\objects\items\weapons\tape.dm"
#include "code\game\objects\items\weapons\teleportation.dm"
#include "code\game\objects\items\weapons\tools.dm"
@@ -846,7 +930,7 @@
#include "code\game\objects\items\weapons\vaurca_items.dm"
#include "code\game\objects\items\weapons\weaponry.dm"
#include "code\game\objects\items\weapons\weldbackpack.dm"
-#include "code\game\objects\items\weapons\wires.dm"
+#include "code\game\objects\items\weapons\circuitboards\_defines.dm"
#include "code\game\objects\items\weapons\circuitboards\broken.dm"
#include "code\game\objects\items\weapons\circuitboards\circuitboard.dm"
#include "code\game\objects\items\weapons\circuitboards\mecha.dm"
@@ -875,6 +959,7 @@
#include "code\game\objects\items\weapons\circuitboards\machinery\unary_atmos.dm"
#include "code\game\objects\items\weapons\grenades\anti_photon_grenade.dm"
#include "code\game\objects\items\weapons\grenades\chem_grenade.dm"
+#include "code\game\objects\items\weapons\grenades\dynamite.dm"
#include "code\game\objects\items\weapons\grenades\emgrenade.dm"
#include "code\game\objects\items\weapons\grenades\fake_grenade.dm"
#include "code\game\objects\items\weapons\grenades\flashbang.dm"
@@ -884,7 +969,6 @@
#include "code\game\objects\items\weapons\grenades\spawnergrenade.dm"
#include "code\game\objects\items\weapons\implants\implant.dm"
#include "code\game\objects\items\weapons\implants\implantcase.dm"
-#include "code\game\objects\items\weapons\implants\implantchair.dm"
#include "code\game\objects\items\weapons\implants\implantcircuits.dm"
#include "code\game\objects\items\weapons\implants\implanter.dm"
#include "code\game\objects\items\weapons\implants\implantfreedom.dm"
@@ -909,6 +993,7 @@
#include "code\game\objects\items\weapons\storage\bible.dm"
#include "code\game\objects\items\weapons\storage\boxes.dm"
#include "code\game\objects\items\weapons\storage\briefcase.dm"
+#include "code\game\objects\items\weapons\storage\cell_backpack.dm"
#include "code\game\objects\items\weapons\storage\fancy.dm"
#include "code\game\objects\items\weapons\storage\field_ration.dm"
#include "code\game\objects\items\weapons\storage\firstaid.dm"
@@ -942,7 +1027,6 @@
#include "code\game\objects\structures\inflatable.dm"
#include "code\game\objects\structures\janicart.dm"
#include "code\game\objects\structures\kitchen_spike.dm"
-#include "code\game\objects\structures\lamarr_cage.dm"
#include "code\game\objects\structures\lattice.dm"
#include "code\game\objects\structures\mirror.dm"
#include "code\game\objects\structures\mop_bucket.dm"
@@ -950,6 +1034,7 @@
#include "code\game\objects\structures\musician.dm"
#include "code\game\objects\structures\noticeboard.dm"
#include "code\game\objects\structures\plasticflaps.dm"
+#include "code\game\objects\structures\railing.dm"
#include "code\game\objects\structures\safe.dm"
#include "code\game\objects\structures\sarcophagus.dm"
#include "code\game\objects\structures\shotgun_rack.dm"
@@ -961,12 +1046,12 @@
#include "code\game\objects\structures\tranqcabinet.dm"
#include "code\game\objects\structures\transit_tubes.dm"
#include "code\game\objects\structures\under_wardrobe.dm"
+#include "code\game\objects\structures\warp_drive.dm"
#include "code\game\objects\structures\watercloset.dm"
#include "code\game\objects\structures\windoor_assembly.dm"
#include "code\game\objects\structures\window.dm"
#include "code\game\objects\structures\window_spawner.dm"
#include "code\game\objects\structures\alien\alien.dm"
-#include "code\game\objects\structures\alien\egg.dm"
#include "code\game\objects\structures\alien\node.dm"
#include "code\game\objects\structures\alien\resin.dm"
#include "code\game\objects\structures\crates_lockers\closets.dm"
@@ -979,6 +1064,7 @@
#include "code\game\objects\structures\crates_lockers\closets\job_closets.dm"
#include "code\game\objects\structures\crates_lockers\closets\l3closet.dm"
#include "code\game\objects\structures\crates_lockers\closets\malfunction.dm"
+#include "code\game\objects\structures\crates_lockers\closets\sol_gear.dm"
#include "code\game\objects\structures\crates_lockers\closets\statue.dm"
#include "code\game\objects\structures\crates_lockers\closets\syndicate.dm"
#include "code\game\objects\structures\crates_lockers\closets\utility_closets.dm"
@@ -995,11 +1081,15 @@
#include "code\game\objects\structures\crates_lockers\closets\secure\scientist.dm"
#include "code\game\objects\structures\crates_lockers\closets\secure\secure_closets.dm"
#include "code\game\objects\structures\crates_lockers\closets\secure\security.dm"
+#include "code\game\objects\structures\crates_lockers\crates\gear_loadout.dm"
#include "code\game\objects\structures\stool_bed_chair_nest\alien_nests.dm"
#include "code\game\objects\structures\stool_bed_chair_nest\bed.dm"
#include "code\game\objects\structures\stool_bed_chair_nest\chairs.dm"
#include "code\game\objects\structures\stool_bed_chair_nest\stools.dm"
#include "code\game\objects\structures\stool_bed_chair_nest\wheelchair.dm"
+#include "code\game\objects\structures\vr\_remote_chair.dm"
+#include "code\game\objects\structures\vr\mech_chair.dm"
+#include "code\game\objects\structures\vr\robot_chair.dm"
#include "code\game\turfs\simulated.dm"
#include "code\game\turfs\turf.dm"
#include "code\game\turfs\turf_changing.dm"
@@ -1017,6 +1107,7 @@
#include "code\game\turfs\simulated\floor_icon.dm"
#include "code\game\turfs\simulated\floor_static.dm"
#include "code\game\turfs\simulated\floor_types.dm"
+#include "code\game\turfs\simulated\shuttle_turfs.dm"
#include "code\game\turfs\simulated\wall_attacks.dm"
#include "code\game\turfs\simulated\wall_icon.dm"
#include "code\game\turfs\simulated\wall_types.dm"
@@ -1052,6 +1143,7 @@
#include "code\modules\admin\player_notes.dm"
#include "code\modules\admin\player_notes_sql.dm"
#include "code\modules\admin\player_panel.dm"
+#include "code\modules\admin\stickyban.dm"
#include "code\modules\admin\ticket.dm"
#include "code\modules\admin\topic.dm"
#include "code\modules\admin\callproc\callproc.dm"
@@ -1088,14 +1180,12 @@
#include "code\modules\admin\secrets\fun_secrets\power_all_smes.dm"
#include "code\modules\admin\secrets\fun_secrets\remove_all_clothing.dm"
#include "code\modules\admin\secrets\fun_secrets\remove_internal_clothing.dm"
-#include "code\modules\admin\secrets\fun_secrets\send_strike_team.dm"
#include "code\modules\admin\secrets\fun_secrets\toggle_bomb_cap.dm"
#include "code\modules\admin\secrets\fun_secrets\triple_ai_mode.dm"
#include "code\modules\admin\secrets\fun_secrets\turn_humans_into_corgies.dm"
#include "code\modules\admin\secrets\fun_secrets\turn_humans_into_monkeys.dm"
#include "code\modules\admin\secrets\random_events\gravity.dm"
#include "code\modules\admin\secrets\random_events\trigger_cordical_borer_infestation.dm"
-#include "code\modules\admin\secrets\random_events\trigger_xenomorph_infestation.dm"
#include "code\modules\admin\verbs\access_control.dm"
#include "code\modules\admin\verbs\adminhelp.dm"
#include "code\modules\admin\verbs\adminjump.dm"
@@ -1118,6 +1208,7 @@
#include "code\modules\admin\verbs\mapping.dm"
#include "code\modules\admin\verbs\massmodvar.dm"
#include "code\modules\admin\verbs\modifyvariables.dm"
+#include "code\modules\admin\verbs\ntsl.dm"
#include "code\modules\admin\verbs\playsound.dm"
#include "code\modules\admin\verbs\possess.dm"
#include "code\modules\admin\verbs\pray.dm"
@@ -1125,7 +1216,6 @@
#include "code\modules\admin\verbs\SDQL.dm"
#include "code\modules\admin\verbs\SDQL_2.dm"
#include "code\modules\admin\verbs\SDQL_2_parser.dm"
-#include "code\modules\admin\verbs\striketeam.dm"
#include "code\modules\admin\verbs\ticklag.dm"
#include "code\modules\admin\verbs\tripAI.dm"
#include "code\modules\admin\verbs\warning.dm"
@@ -1141,7 +1231,6 @@
#include "code\modules\alarm\power_alarm.dm"
#include "code\modules\ambient_occlusion\ao_turf.dm"
#include "code\modules\ambient_occlusion\ao_verbs.dm"
-#include "code\modules\antag_contest\sol_items.dm"
#include "code\modules\assembly\assembly.dm"
#include "code\modules\assembly\bomb.dm"
#include "code\modules\assembly\helpers.dm"
@@ -1162,6 +1251,20 @@
#include "code\modules\awaymissions\pamphlet.dm"
#include "code\modules\awaymissions\trigger.dm"
#include "code\modules\awaymissions\zlevel.dm"
+#include "code\modules\background\defines.dm"
+#include "code\modules\background\citizenship\citizenship.dm"
+#include "code\modules\background\citizenship\human.dm"
+#include "code\modules\background\citizenship\ipc.dm"
+#include "code\modules\background\citizenship\skrell.dm"
+#include "code\modules\background\citizenship\tajara.dm"
+#include "code\modules\background\citizenship\unathi.dm"
+#include "code\modules\background\citizenship\vaurca.dm"
+#include "code\modules\background\religion\human.dm"
+#include "code\modules\background\religion\religion.dm"
+#include "code\modules\background\religion\skrell.dm"
+#include "code\modules\background\religion\tajara.dm"
+#include "code\modules\background\religion\unathi.dm"
+#include "code\modules\background\religion\vaurca.dm"
#include "code\modules\battlemonsters\datum_core.dm"
#include "code\modules\battlemonsters\datum_elements.dm"
#include "code\modules\battlemonsters\datum_monsters.dm"
@@ -1183,7 +1286,6 @@
#include "code\modules\cargo\bounties\bot.dm"
#include "code\modules\cargo\bounties\chef.dm"
#include "code\modules\cargo\bounties\item.dm"
-#include "code\modules\cargo\bounties\mech.dm"
#include "code\modules\cargo\bounties\reagent.dm"
#include "code\modules\cargo\bounties\science.dm"
#include "code\modules\cargo\bounties\security.dm"
@@ -1201,14 +1303,12 @@
#include "code\modules\cargo\exports\weapons.dm"
#include "code\modules\cargo\random_stock\_defs.dm"
#include "code\modules\cargo\random_stock\large.dm"
-#include "code\modules\cargo\random_stock\large_exosuit.dm"
#include "code\modules\cargo\random_stock\t1_common.dm"
#include "code\modules\cargo\random_stock\t2_uncommon.dm"
#include "code\modules\cargo\random_stock\t3_rare.dm"
#include "code\modules\cargo\random_stock\~undefs.dm"
#include "code\modules\cciaa\cciaa.dm"
#include "code\modules\cciaa\cciaa_items.dm"
-#include "code\modules\cciaa\ert_cmd.dm"
#include "code\modules\client\asset_cache.dm"
#include "code\modules\client\client defines.dm"
#include "code\modules\client\client procs.dm"
@@ -1216,7 +1316,6 @@
#include "code\modules\client\movement.dm"
#include "code\modules\client\preferences.dm"
#include "code\modules\client\preferences_ambience.dm"
-#include "code\modules\client\preferences_factions.dm"
#include "code\modules\client\preferences_notification.dm"
#include "code\modules\client\preferences_savefile.dm"
#include "code\modules\client\preferences_spawnpoints.dm"
@@ -1236,16 +1335,21 @@
#include "code\modules\client\preference_setup\global\02_settings.dm"
#include "code\modules\client\preference_setup\global\03_language.dm"
#include "code\modules\client\preference_setup\global\04_pai.dm"
+#include "code\modules\client\preference_setup\loadout\_defines.dm"
#include "code\modules\client\preference_setup\loadout\gear_tweaks.dm"
#include "code\modules\client\preference_setup\loadout\loadout.dm"
#include "code\modules\client\preference_setup\loadout\loadout_accessories.dm"
+#include "code\modules\client\preference_setup\loadout\loadout_augments.dm"
+#include "code\modules\client\preference_setup\loadout\loadout_computer.dm"
#include "code\modules\client\preference_setup\loadout\loadout_cosmetics.dm"
#include "code\modules\client\preference_setup\loadout\loadout_ears.dm"
#include "code\modules\client\preference_setup\loadout\loadout_eyes.dm"
+#include "code\modules\client\preference_setup\loadout\loadout_factions.dm"
#include "code\modules\client\preference_setup\loadout\loadout_general.dm"
#include "code\modules\client\preference_setup\loadout\loadout_gloves.dm"
#include "code\modules\client\preference_setup\loadout\loadout_head.dm"
#include "code\modules\client\preference_setup\loadout\loadout_mask.dm"
+#include "code\modules\client\preference_setup\loadout\loadout_religion.dm"
#include "code\modules\client\preference_setup\loadout\loadout_shoes.dm"
#include "code\modules\client\preference_setup\loadout\loadout_smoking.dm"
#include "code\modules\client\preference_setup\loadout\loadout_suit.dm"
@@ -1265,7 +1369,9 @@
#include "code\modules\clothing\clothing.dm"
#include "code\modules\clothing\clothing_accessories.dm"
#include "code\modules\clothing\ears\bandanna.dm"
+#include "code\modules\clothing\ears\earmuffs.dm"
#include "code\modules\clothing\ears\skrell.dm"
+#include "code\modules\clothing\factions\dominia.dm"
#include "code\modules\clothing\glasses\glasses.dm"
#include "code\modules\clothing\glasses\hud.dm"
#include "code\modules\clothing\gloves\arm_guard.dm"
@@ -1273,6 +1379,7 @@
#include "code\modules\clothing\gloves\color.dm"
#include "code\modules\clothing\gloves\miscellaneous.dm"
#include "code\modules\clothing\gloves\stungloves.dm"
+#include "code\modules\clothing\gloves\xeno\tajara.dm"
#include "code\modules\clothing\head\collectable.dm"
#include "code\modules\clothing\head\hardhat.dm"
#include "code\modules\clothing\head\helmet.dm"
@@ -1280,11 +1387,13 @@
#include "code\modules\clothing\head\misc.dm"
#include "code\modules\clothing\head\misc_special.dm"
#include "code\modules\clothing\head\soft_caps.dm"
+#include "code\modules\clothing\head\xenos\tajara.dm"
#include "code\modules\clothing\masks\boxing.dm"
#include "code\modules\clothing\masks\breath.dm"
#include "code\modules\clothing\masks\gasmask.dm"
#include "code\modules\clothing\masks\miscellaneous.dm"
#include "code\modules\clothing\masks\voice.dm"
+#include "code\modules\clothing\masks\xeno\tajara.dm"
#include "code\modules\clothing\rings\material.dm"
#include "code\modules\clothing\rings\rings.dm"
#include "code\modules\clothing\shoes\colour.dm"
@@ -1292,6 +1401,8 @@
#include "code\modules\clothing\shoes\leg_guard.dm"
#include "code\modules\clothing\shoes\magboots.dm"
#include "code\modules\clothing\shoes\miscellaneous.dm"
+#include "code\modules\clothing\shoes\vaurca.dm"
+#include "code\modules\clothing\shoes\xeno\tajara.dm"
#include "code\modules\clothing\spacesuits\alien.dm"
#include "code\modules\clothing\spacesuits\breaches.dm"
#include "code\modules\clothing\spacesuits\miscellaneous.dm"
@@ -1317,11 +1428,12 @@
#include "code\modules\clothing\spacesuits\rig\suits\merc.dm"
#include "code\modules\clothing\spacesuits\rig\suits\station.dm"
#include "code\modules\clothing\spacesuits\rig\suits\terminator.dm"
+#include "code\modules\clothing\spacesuits\void\alien.dm"
#include "code\modules\clothing\spacesuits\void\captain.dm"
#include "code\modules\clothing\spacesuits\void\merc.dm"
+#include "code\modules\clothing\spacesuits\void\misc.dm"
#include "code\modules\clothing\spacesuits\void\station.dm"
#include "code\modules\clothing\spacesuits\void\void.dm"
-#include "code\modules\clothing\spacesuits\void\wizard.dm"
#include "code\modules\clothing\suits\alien.dm"
#include "code\modules\clothing\suits\armor.dm"
#include "code\modules\clothing\suits\bio.dm"
@@ -1332,6 +1444,7 @@
#include "code\modules\clothing\suits\storage.dm"
#include "code\modules\clothing\suits\utility.dm"
#include "code\modules\clothing\suits\wiz_robe.dm"
+#include "code\modules\clothing\suits\xeno\tajara.dm"
#include "code\modules\clothing\under\color.dm"
#include "code\modules\clothing\under\miscellaneous.dm"
#include "code\modules\clothing\under\shorts.dm"
@@ -1344,13 +1457,16 @@
#include "code\modules\clothing\under\accessories\lockets.dm"
#include "code\modules\clothing\under\accessories\shirts.dm"
#include "code\modules\clothing\under\accessories\storage.dm"
+#include "code\modules\clothing\under\accessories\xeno\tajara.dm"
#include "code\modules\clothing\under\jobs\civilian.dm"
#include "code\modules\clothing\under\jobs\engineering.dm"
#include "code\modules\clothing\under\jobs\medsci.dm"
#include "code\modules\clothing\under\jobs\security.dm"
-#include "code\modules\clothing\under\xenos\resomi.dm"
+#include "code\modules\clothing\under\jobs\sol.dm"
+#include "code\modules\clothing\under\xenos\skrell.dm"
#include "code\modules\clothing\under\xenos\tajara.dm"
#include "code\modules\clothing\under\xenos\unathi.dm"
+#include "code\modules\clothing\under\xenos\vaurca.dm"
#include "code\modules\custom_ka\barrels.dm"
#include "code\modules\custom_ka\cells.dm"
#include "code\modules\custom_ka\core.dm"
@@ -1369,6 +1485,7 @@
#include "code\modules\detectivework\tools\luminol.dm"
#include "code\modules\detectivework\tools\rag.dm"
#include "code\modules\detectivework\tools\sample_kits.dm"
+#include "code\modules\detectivework\tools\scene_cards.dm"
#include "code\modules\detectivework\tools\storage.dm"
#include "code\modules\detectivework\tools\swabs.dm"
#include "code\modules\detectivework\tools\uvlight.dm"
@@ -1434,7 +1551,6 @@
#include "code\modules\examine\descriptions\weapons.dm"
#include "code\modules\ext_scripts\python.dm"
#include "code\modules\flufftext\Dreaming.dm"
-#include "code\modules\flufftext\Hallucination.dm"
#include "code\modules\flufftext\TextFilters.dm"
#include "code\modules\food\recipe.dm"
#include "code\modules\food\recipes_fryer.dm"
@@ -1446,13 +1562,72 @@
#include "code\modules\games\spaceball_cards.dm"
#include "code\modules\games\tarot.dm"
#include "code\modules\genetics\side_effects.dm"
+#include "code\modules\ghostroles\spawner\base.dm"
+#include "code\modules\ghostroles\spawner\human\admin.dm"
+#include "code\modules\ghostroles\spawner\human\emergencypod.dm"
+#include "code\modules\ghostroles\spawner\human\golem.dm"
+#include "code\modules\ghostroles\spawner\human\human.dm"
+#include "code\modules\ghostroles\spawner\human\kataphract.dm"
+#include "code\modules\ghostroles\spawner\human\merchant.dm"
+#include "code\modules\ghostroles\spawner\human\pra.dm"
+#include "code\modules\ghostroles\spawner\human\visitor.dm"
+#include "code\modules\ghostroles\spawner\human\zenghu.dm"
+#include "code\modules\ghostroles\spawner\human\responseteams\deathsquad.dm"
+#include "code\modules\ghostroles\spawner\human\responseteams\iac.dm"
+#include "code\modules\ghostroles\spawner\human\responseteams\kataphracts.dm"
+#include "code\modules\ghostroles\spawner\human\responseteams\mercenary.dm"
+#include "code\modules\ghostroles\spawner\human\responseteams\nt_ert.dm"
+#include "code\modules\ghostroles\spawner\human\responseteams\response_team.dm"
+#include "code\modules\ghostroles\spawner\human\responseteams\syndicate.dm"
+#include "code\modules\ghostroles\spawner\human\responseteams\tcfl.dm"
+#include "code\modules\ghostroles\spawner\simplemob\maintdrone.dm"
+#include "code\modules\ghostroles\spawner\simplemob\rat.dm"
+#include "code\modules\ghostroles\spawner\simplemob\spider.dm"
+#include "code\modules\ghostroles\spawnpoint\spawnpoint.dm"
#include "code\modules\ghosttrap\trap.dm"
#include "code\modules\global_listener\devices.dm"
#include "code\modules\global_listener\interfaces.dm"
+#include "code\modules\hallucinations\hallucinations.dm"
+#include "code\modules\hallucinations\mob.dm"
+#include "code\modules\hallucinations\types\basic.dm"
+#include "code\modules\hallucinations\types\mirage.dm"
+#include "code\modules\hallucinations\types\powers.dm"
+#include "code\modules\hallucinations\types\sound.dm"
+#include "code\modules\heavy_vehicle\_mech_setup.dm"
+#include "code\modules\heavy_vehicle\mech_construction.dm"
+#include "code\modules\heavy_vehicle\mech_damage.dm"
+#include "code\modules\heavy_vehicle\mech_damage_immunity.dm"
+#include "code\modules\heavy_vehicle\mech_icon.dm"
+#include "code\modules\heavy_vehicle\mech_interaction.dm"
+#include "code\modules\heavy_vehicle\mech_life.dm"
+#include "code\modules\heavy_vehicle\mech_wreckage.dm"
+#include "code\modules\heavy_vehicle\mecha.dm"
+#include "code\modules\heavy_vehicle\components\_components.dm"
+#include "code\modules\heavy_vehicle\components\armor.dm"
+#include "code\modules\heavy_vehicle\components\arms.dm"
+#include "code\modules\heavy_vehicle\components\body.dm"
+#include "code\modules\heavy_vehicle\components\frame.dm"
+#include "code\modules\heavy_vehicle\components\head.dm"
+#include "code\modules\heavy_vehicle\components\legs.dm"
+#include "code\modules\heavy_vehicle\components\software.dm"
+#include "code\modules\heavy_vehicle\equipment\_equipment.dm"
+#include "code\modules\heavy_vehicle\equipment\combat.dm"
+#include "code\modules\heavy_vehicle\equipment\engineering.dm"
+#include "code\modules\heavy_vehicle\equipment\medical.dm"
+#include "code\modules\heavy_vehicle\equipment\utility.dm"
+#include "code\modules\heavy_vehicle\interface\_interface.dm"
+#include "code\modules\heavy_vehicle\interface\screen_objectsa.dm"
+#include "code\modules\heavy_vehicle\premade\_premade.dm"
+#include "code\modules\heavy_vehicle\premade\combat.dm"
+#include "code\modules\heavy_vehicle\premade\heavy.dm"
+#include "code\modules\heavy_vehicle\premade\hoverpod.dm"
+#include "code\modules\heavy_vehicle\premade\light.dm"
+#include "code\modules\heavy_vehicle\premade\miner.dm"
+#include "code\modules\heavy_vehicle\premade\misc.dm"
+#include "code\modules\heavy_vehicle\premade\powerloader.dm"
#include "code\modules\holodeck\HolodeckControl.dm"
#include "code\modules\holodeck\HolodeckObjects.dm"
#include "code\modules\holodeck\HolodeckPrograms.dm"
-#include "code\modules\http\post_request.dm"
#include "code\modules\hydroponics\grown.dm"
#include "code\modules\hydroponics\grown_inedible.dm"
#include "code\modules\hydroponics\grown_predefined.dm"
@@ -1462,9 +1637,13 @@
#include "code\modules\hydroponics\seed_mobs.dm"
#include "code\modules\hydroponics\seed_packets.dm"
#include "code\modules\hydroponics\seed_storage.dm"
+#include "code\modules\hydroponics\beekeeping\bee_pack.dm"
#include "code\modules\hydroponics\beekeeping\beehive.dm"
+#include "code\modules\hydroponics\beekeeping\honey_extractor.dm"
+#include "code\modules\hydroponics\beekeeping\honey_frame.dm"
#include "code\modules\hydroponics\beekeeping\net.dm"
#include "code\modules\hydroponics\beekeeping\smoker.dm"
+#include "code\modules\hydroponics\beekeeping\wax.dm"
#include "code\modules\hydroponics\spreading\spreading.dm"
#include "code\modules\hydroponics\spreading\spreading_growth.dm"
#include "code\modules\hydroponics\spreading\spreading_response.dm"
@@ -1483,6 +1662,8 @@
#include "code\modules\integrated_electronics\core\pins.dm"
#include "code\modules\integrated_electronics\core\printer.dm"
#include "code\modules\integrated_electronics\core\tools.dm"
+#include "code\modules\integrated_electronics\core\assemblies\clothing.dm"
+#include "code\modules\integrated_electronics\core\assemblies\generic.dm"
#include "code\modules\integrated_electronics\core\special_pins\boolean_pin.dm"
#include "code\modules\integrated_electronics\core\special_pins\char_pin.dm"
#include "code\modules\integrated_electronics\core\special_pins\color_pin.dm"
@@ -1545,6 +1726,7 @@
#include "code\modules\lock\key.dm"
#include "code\modules\lock\lock.dm"
#include "code\modules\lock\lock_construct.dm"
+#include "code\modules\makeshift\makeshift_reagents.dm"
#include "code\modules\maps\dmm_suite.dm"
#include "code\modules\maps\map_template.dm"
#include "code\modules\maps\reader.dm"
@@ -1580,9 +1762,9 @@
#include "code\modules\mining\minebot.dm"
#include "code\modules\mining\mineral_effect.dm"
#include "code\modules\mining\mint.dm"
-#include "code\modules\mining\money_bag.dm"
#include "code\modules\mining\ore.dm"
#include "code\modules\mining\ore_datum.dm"
+#include "code\modules\mining\ore_satchel.dm"
#include "code\modules\mining\satchel_ore_boxdm.dm"
#include "code\modules\mining\drilling\drill.dm"
#include "code\modules\mining\drilling\scanner.dm"
@@ -1612,6 +1794,7 @@
#include "code\modules\mob\abstract\freelook\chunk.dm"
#include "code\modules\mob\abstract\freelook\eye.dm"
#include "code\modules\mob\abstract\freelook\life.dm"
+#include "code\modules\mob\abstract\freelook\logging.dm"
#include "code\modules\mob\abstract\freelook\read_me.dm"
#include "code\modules\mob\abstract\freelook\update_triggers.dm"
#include "code\modules\mob\abstract\freelook\visualnet.dm"
@@ -1619,10 +1802,6 @@
#include "code\modules\mob\abstract\freelook\ai\chunk.dm"
#include "code\modules\mob\abstract\freelook\ai\eye.dm"
#include "code\modules\mob\abstract\freelook\ai\update_triggers.dm"
-#include "code\modules\mob\abstract\freelook\mask\chunk.dm"
-#include "code\modules\mob\abstract\freelook\mask\cultnet.dm"
-#include "code\modules\mob\abstract\freelook\mask\eye.dm"
-#include "code\modules\mob\abstract\freelook\mask\update_triggers.dm"
#include "code\modules\mob\abstract\new_player\character_traits.dm"
#include "code\modules\mob\abstract\new_player\login.dm"
#include "code\modules\mob\abstract\new_player\logout.dm"
@@ -1635,6 +1814,7 @@
#include "code\modules\mob\abstract\observer\logout.dm"
#include "code\modules\mob\abstract\observer\observer.dm"
#include "code\modules\mob\abstract\observer\say.dm"
+#include "code\modules\mob\abstract\unauthed\login.dm"
#include "code\modules\mob\language\generic.dm"
#include "code\modules\mob\language\language.dm"
#include "code\modules\mob\language\monkey.dm"
@@ -1644,7 +1824,6 @@
#include "code\modules\mob\living\autohiss.dm"
#include "code\modules\mob\living\damage_procs.dm"
#include "code\modules\mob\living\default_language.dm"
-#include "code\modules\mob\living\devour.dm"
#include "code\modules\mob\living\life.dm"
#include "code\modules\mob\living\living.dm"
#include "code\modules\mob\living\living_defense.dm"
@@ -1664,11 +1843,9 @@
#include "code\modules\mob\living\carbon\carbon.dm"
#include "code\modules\mob\living\carbon\carbon_defense.dm"
#include "code\modules\mob\living\carbon\carbon_defines.dm"
-#include "code\modules\mob\living\carbon\carbon_powers.dm"
#include "code\modules\mob\living\carbon\diona_base.dm"
#include "code\modules\mob\living\carbon\give.dm"
#include "code\modules\mob\living\carbon\resist.dm"
-#include "code\modules\mob\living\carbon\shock.dm"
#include "code\modules\mob\living\carbon\taste.dm"
#include "code\modules\mob\living\carbon\viruses.dm"
#include "code\modules\mob\living\carbon\alien\alien.dm"
@@ -1685,9 +1862,6 @@
#include "code\modules\mob\living\carbon\alien\diona\life.dm"
#include "code\modules\mob\living\carbon\alien\diona\progression.dm"
#include "code\modules\mob\living\carbon\alien\diona\update_icons.dm"
-#include "code\modules\mob\living\carbon\alien\larva\larva.dm"
-#include "code\modules\mob\living\carbon\alien\larva\life.dm"
-#include "code\modules\mob\living\carbon\alien\larva\progression.dm"
#include "code\modules\mob\living\carbon\brain\brain.dm"
#include "code\modules\mob\living\carbon\brain\brain_item.dm"
#include "code\modules\mob\living\carbon\brain\death.dm"
@@ -1700,6 +1874,7 @@
#include "code\modules\mob\living\carbon\brain\say.dm"
#include "code\modules\mob\living\carbon\human\appearance.dm"
#include "code\modules\mob\living\carbon\human\death.dm"
+#include "code\modules\mob\living\carbon\human\devour.dm"
#include "code\modules\mob\living\carbon\human\diona_gestalt.dm"
#include "code\modules\mob\living\carbon\human\emote.dm"
#include "code\modules\mob\living\carbon\human\examine.dm"
@@ -1732,40 +1907,41 @@
#include "code\modules\mob\living\carbon\human\species\outsider\undead.dm"
#include "code\modules\mob\living\carbon\human\species\outsider\vox.dm"
#include "code\modules\mob\living\carbon\human\species\station\golem.dm"
-#include "code\modules\mob\living\carbon\human\species\station\human_subspecies.dm"
-#include "code\modules\mob\living\carbon\human\species\station\machine_subspecies.dm"
#include "code\modules\mob\living\carbon\human\species\station\monkey.dm"
-#include "code\modules\mob\living\carbon\human\species\station\resomi.dm"
#include "code\modules\mob\living\carbon\human\species\station\slime.dm"
-#include "code\modules\mob\living\carbon\human\species\station\station.dm"
-#include "code\modules\mob\living\carbon\human\species\station\tajaran_subspecies.dm"
-#include "code\modules\mob\living\carbon\human\species\station\unathi_subspecies.dm"
-#include "code\modules\mob\living\carbon\human\species\station\vaurca_subspecies.dm"
-#include "code\modules\mob\living\carbon\human\species\xenomorphs\alien_embryo.dm"
-#include "code\modules\mob\living\carbon\human\species\xenomorphs\alien_facehugger.dm"
-#include "code\modules\mob\living\carbon\human\species\xenomorphs\alien_powers.dm"
-#include "code\modules\mob\living\carbon\human\species\xenomorphs\alien_species.dm"
-#include "code\modules\mob\living\carbon\human\species\xenomorphs\xenomorphs.dm"
-#include "code\modules\mob\living\carbon\metroid\death.dm"
-#include "code\modules\mob\living\carbon\metroid\emote.dm"
-#include "code\modules\mob\living\carbon\metroid\examine.dm"
-#include "code\modules\mob\living\carbon\metroid\hud.dm"
-#include "code\modules\mob\living\carbon\metroid\items.dm"
-#include "code\modules\mob\living\carbon\metroid\life.dm"
-#include "code\modules\mob\living\carbon\metroid\login.dm"
-#include "code\modules\mob\living\carbon\metroid\metroid.dm"
-#include "code\modules\mob\living\carbon\metroid\powers.dm"
-#include "code\modules\mob\living\carbon\metroid\say.dm"
-#include "code\modules\mob\living\carbon\metroid\subtypes.dm"
-#include "code\modules\mob\living\carbon\metroid\update_icons.dm"
+#include "code\modules\mob\living\carbon\human\species\station\diona\diona.dm"
+#include "code\modules\mob\living\carbon\human\species\station\human\human.dm"
+#include "code\modules\mob\living\carbon\human\species\station\human\human_subspecies.dm"
+#include "code\modules\mob\living\carbon\human\species\station\ipc\ipc.dm"
+#include "code\modules\mob\living\carbon\human\species\station\ipc\ipc_subspecies.dm"
+#include "code\modules\mob\living\carbon\human\species\station\skrell\skrell.dm"
+#include "code\modules\mob\living\carbon\human\species\station\tajara\tajara.dm"
+#include "code\modules\mob\living\carbon\human\species\station\tajara\tajaran_subspecies.dm"
+#include "code\modules\mob\living\carbon\human\species\station\unathi\unathi.dm"
+#include "code\modules\mob\living\carbon\human\species\station\unathi\unathi_subspecies.dm"
+#include "code\modules\mob\living\carbon\human\species\station\vaurca\vaurca.dm"
+#include "code\modules\mob\living\carbon\human\species\station\vaurca\vaurca_subspecies.dm"
+#include "code\modules\mob\living\carbon\slime\_mood.dm"
+#include "code\modules\mob\living\carbon\slime\death.dm"
+#include "code\modules\mob\living\carbon\slime\emote.dm"
+#include "code\modules\mob\living\carbon\slime\examine.dm"
+#include "code\modules\mob\living\carbon\slime\hud.dm"
+#include "code\modules\mob\living\carbon\slime\items.dm"
+#include "code\modules\mob\living\carbon\slime\life.dm"
+#include "code\modules\mob\living\carbon\slime\login.dm"
+#include "code\modules\mob\living\carbon\slime\powers.dm"
+#include "code\modules\mob\living\carbon\slime\say.dm"
+#include "code\modules\mob\living\carbon\slime\slime.dm"
+#include "code\modules\mob\living\carbon\slime\subtypes.dm"
+#include "code\modules\mob\living\carbon\slime\update_icons.dm"
#include "code\modules\mob\living\parasite\meme.dm"
#include "code\modules\mob\living\parasite\meme_captive.dm"
+#include "code\modules\mob\living\silicon\computer.dm"
#include "code\modules\mob\living\silicon\death.dm"
#include "code\modules\mob\living\silicon\laws.dm"
#include "code\modules\mob\living\silicon\login.dm"
#include "code\modules\mob\living\silicon\say.dm"
#include "code\modules\mob\living\silicon\silicon.dm"
-#include "code\modules\mob\living\silicon\subystems.dm"
#include "code\modules\mob\living\silicon\ai\ai.dm"
#include "code\modules\mob\living\silicon\ai\ai_movement.dm"
#include "code\modules\mob\living\silicon\ai\death.dm"
@@ -1826,17 +2002,24 @@
#include "code\modules\mob\living\simple_animal\borer\borer_captive.dm"
#include "code\modules\mob\living\simple_animal\borer\borer_powers.dm"
#include "code\modules\mob\living\simple_animal\borer\say.dm"
-#include "code\modules\mob\living\simple_animal\constructs\constructs.dm"
#include "code\modules\mob\living\simple_animal\constructs\soulstone.dm"
+#include "code\modules\mob\living\simple_animal\constructs\constructs\artificer.dm"
+#include "code\modules\mob\living\simple_animal\constructs\constructs\cult_construct.dm"
+#include "code\modules\mob\living\simple_animal\constructs\constructs\harvester.dm"
+#include "code\modules\mob\living\simple_animal\constructs\constructs\juggernaut.dm"
+#include "code\modules\mob\living\simple_animal\constructs\constructs\wraith.dm"
#include "code\modules\mob\living\simple_animal\familiars\familiars.dm"
+#include "code\modules\mob\living\simple_animal\friendly\adhomai.dm"
+#include "code\modules\mob\living\simple_animal\friendly\carp.dm"
#include "code\modules\mob\living\simple_animal\friendly\cat.dm"
#include "code\modules\mob\living\simple_animal\friendly\corgi.dm"
#include "code\modules\mob\living\simple_animal\friendly\crab.dm"
#include "code\modules\mob\living\simple_animal\friendly\farm_animals.dm"
#include "code\modules\mob\living\simple_animal\friendly\fox.dm"
+#include "code\modules\mob\living\simple_animal\friendly\hakhma.dm"
#include "code\modules\mob\living\simple_animal\friendly\lizard.dm"
-#include "code\modules\mob\living\simple_animal\friendly\mouse.dm"
#include "code\modules\mob\living\simple_animal\friendly\mushroom.dm"
+#include "code\modules\mob\living\simple_animal\friendly\rat.dm"
#include "code\modules\mob\living\simple_animal\friendly\ratking.dm"
#include "code\modules\mob\living\simple_animal\friendly\slime.dm"
#include "code\modules\mob\living\simple_animal\friendly\spiderbot.dm"
@@ -1855,8 +2038,10 @@
#include "code\modules\mob\living\simple_animal\hostile\mimic.dm"
#include "code\modules\mob\living\simple_animal\hostile\moghesfauna.dm"
#include "code\modules\mob\living\simple_animal\hostile\pirate.dm"
+#include "code\modules\mob\living\simple_animal\hostile\pra.dm"
#include "code\modules\mob\living\simple_animal\hostile\russian.dm"
#include "code\modules\mob\living\simple_animal\hostile\sarlacc.dm"
+#include "code\modules\mob\living\simple_animal\hostile\spider_queen.dm"
#include "code\modules\mob\living\simple_animal\hostile\syndicate.dm"
#include "code\modules\mob\living\simple_animal\hostile\tree.dm"
#include "code\modules\mob\living\simple_animal\hostile\commanded\_command_defines.dm"
@@ -1877,11 +2062,16 @@
#include "code\modules\modular_computers\computers\modular_computer\variables.dm"
#include "code\modules\modular_computers\computers\subtypes\dev_console.dm"
#include "code\modules\modular_computers\computers\subtypes\dev_laptop.dm"
+#include "code\modules\modular_computers\computers\subtypes\dev_silicon.dm"
#include "code\modules\modular_computers\computers\subtypes\dev_tablet.dm"
#include "code\modules\modular_computers\computers\subtypes\dev_telescreen.dm"
+#include "code\modules\modular_computers\computers\subtypes\dev_wristbound.dm"
#include "code\modules\modular_computers\computers\subtypes\preset_console.dm"
+#include "code\modules\modular_computers\computers\subtypes\preset_laptop.dm"
+#include "code\modules\modular_computers\computers\subtypes\preset_silicon.dm"
#include "code\modules\modular_computers\computers\subtypes\preset_tablet.dm"
#include "code\modules\modular_computers\computers\subtypes\preset_telescreen.dm"
+#include "code\modules\modular_computers\computers\subtypes\preset_wristbound.dm"
#include "code\modules\modular_computers\file_system\computer_file.dm"
#include "code\modules\modular_computers\file_system\data.dm"
#include "code\modules\modular_computers\file_system\news_article.dm"
@@ -1904,13 +2094,15 @@
#include "code\modules\modular_computers\file_system\programs\games\sudoku\sudoku.dm"
#include "code\modules\modular_computers\file_system\programs\generic\news_browser.dm"
#include "code\modules\modular_computers\file_system\programs\generic\ntnrc_client.dm"
+#include "code\modules\modular_computers\file_system\programs\generic\ntsl2_interpreter.dm"
#include "code\modules\modular_computers\file_system\programs\generic\nttransfer.dm"
+#include "code\modules\modular_computers\file_system\programs\generic\records.dm"
#include "code\modules\modular_computers\file_system\programs\medical\suit_sensors.dm"
#include "code\modules\modular_computers\file_system\programs\research\ai_restorer.dm"
-#include "code\modules\modular_computers\file_system\programs\research\exosuit_monitor.dm"
#include "code\modules\modular_computers\file_system\programs\research\ntmonitor.dm"
#include "code\modules\modular_computers\file_system\programs\security\camera.dm"
#include "code\modules\modular_computers\file_system\programs\security\digitalwarrant.dm"
+#include "code\modules\modular_computers\file_system\programs\security\penalmechs.dm"
#include "code\modules\modular_computers\file_system\programs\system\client_manager.dm"
#include "code\modules\modular_computers\file_system\programs\system\configurator.dm"
#include "code\modules\modular_computers\file_system\programs\system\file_browser.dm"
@@ -1959,43 +2151,47 @@
#include "code\modules\nano\modules\alarm_monitor.dm"
#include "code\modules\nano\modules\atmos_control.dm"
#include "code\modules\nano\modules\crew_monitor.dm"
-#include "code\modules\nano\modules\exosuit_control.dm"
#include "code\modules\nano\modules\human_appearance.dm"
#include "code\modules\nano\modules\law_manager.dm"
#include "code\modules\nano\modules\lighting_ctrl.dm"
#include "code\modules\nano\modules\nano_module.dm"
#include "code\modules\nano\modules\power_monitor.dm"
#include "code\modules\nano\modules\rcon.dm"
+#include "code\modules\ntsl2\guide.dm"
+#include "code\modules\ntsl2\ntsl2.dm"
+#include "code\modules\ntsl2\program.dm"
+#include "code\modules\ntsl2\telecomms.dm"
#include "code\modules\orbit\orbit.dm"
#include "code\modules\organs\blood.dm"
#include "code\modules\organs\misc.dm"
#include "code\modules\organs\organ.dm"
#include "code\modules\organs\organ_external.dm"
#include "code\modules\organs\organ_icon.dm"
-#include "code\modules\organs\organ_internal.dm"
#include "code\modules\organs\organ_stump.dm"
#include "code\modules\organs\pain.dm"
#include "code\modules\organs\robolimbs.dm"
#include "code\modules\organs\wound.dm"
+#include "code\modules\organs\internal\_internal.dm"
+#include "code\modules\organs\internal\appendix.dm"
+#include "code\modules\organs\internal\brain.dm"
+#include "code\modules\organs\internal\eyes.dm"
+#include "code\modules\organs\internal\heart.dm"
+#include "code\modules\organs\internal\kidneys.dm"
+#include "code\modules\organs\internal\liver.dm"
+#include "code\modules\organs\internal\lungs.dm"
+#include "code\modules\organs\internal\stomach.dm"
+#include "code\modules\organs\internal\species\diona.dm"
+#include "code\modules\organs\subtypes\augment.dm"
#include "code\modules\organs\subtypes\autakh.dm"
#include "code\modules\organs\subtypes\diona.dm"
#include "code\modules\organs\subtypes\industrial.dm"
#include "code\modules\organs\subtypes\machine.dm"
#include "code\modules\organs\subtypes\parasite.dm"
-#include "code\modules\organs\subtypes\resomi.dm"
#include "code\modules\organs\subtypes\skrell.dm"
#include "code\modules\organs\subtypes\standard.dm"
#include "code\modules\organs\subtypes\unbreakable.dm"
#include "code\modules\organs\subtypes\vaurca.dm"
#include "code\modules\organs\subtypes\xenos.dm"
-#include "code\modules\overmap\_defines.dm"
-#include "code\modules\overmap\sectors.dm"
-#include "code\modules\overmap\ships\ship.dm"
-#include "code\modules\overmap\ships\computers\engine_control.dm"
-#include "code\modules\overmap\ships\computers\helm.dm"
-#include "code\modules\overmap\ships\computers\shuttle.dm"
-#include "code\modules\overmap\ships\engines\engine.dm"
-#include "code\modules\overmap\ships\engines\thermal.dm"
#include "code\modules\paperwork\carbonpaper.dm"
#include "code\modules\paperwork\clipboard.dm"
#include "code\modules\paperwork\faxmachine.dm"
@@ -2083,14 +2279,17 @@
#include "code\modules\projectiles\guns\energy\temperature.dm"
#include "code\modules\projectiles\guns\launcher\crossbow.dm"
#include "code\modules\projectiles\guns\launcher\grenade_launcher.dm"
+#include "code\modules\projectiles\guns\launcher\harpoon.dm"
#include "code\modules\projectiles\guns\launcher\pneumatic.dm"
#include "code\modules\projectiles\guns\launcher\rocket.dm"
#include "code\modules\projectiles\guns\launcher\syringe_gun.dm"
#include "code\modules\projectiles\guns\projectile\automatic.dm"
+#include "code\modules\projectiles\guns\projectile\cannon.dm"
#include "code\modules\projectiles\guns\projectile\dartgun.dm"
#include "code\modules\projectiles\guns\projectile\improvised.dm"
#include "code\modules\projectiles\guns\projectile\minigun.dm"
#include "code\modules\projectiles\guns\projectile\pistol.dm"
+#include "code\modules\projectiles\guns\projectile\plasma.dm"
#include "code\modules\projectiles\guns\projectile\revolver.dm"
#include "code\modules\projectiles\guns\projectile\rifle.dm"
#include "code\modules\projectiles\guns\projectile\shotgun.dm"
@@ -2110,6 +2309,31 @@
#include "code\modules\projectiles\targeting\targeting_mob.dm"
#include "code\modules\projectiles\targeting\targeting_overlay.dm"
#include "code\modules\projectiles\targeting\targeting_triggers.dm"
+#include "code\modules\psionics\complexus\complexus.dm"
+#include "code\modules\psionics\complexus\complexus_helpers.dm"
+#include "code\modules\psionics\complexus\complexus_latency.dm"
+#include "code\modules\psionics\complexus\complexus_power_cache.dm"
+#include "code\modules\psionics\complexus\complexus_process.dm"
+#include "code\modules\psionics\equipment\cerebro_enhancers.dm"
+#include "code\modules\psionics\equipment\psipower.dm"
+#include "code\modules\psionics\equipment\psipower_blade.dm"
+#include "code\modules\psionics\equipment\psipower_tinker.dm"
+#include "code\modules\psionics\equipment\psipower_tk.dm"
+#include "code\modules\psionics\events\_psi.dm"
+#include "code\modules\psionics\events\mini_spasm.dm"
+#include "code\modules\psionics\events\psi_balm.dm"
+#include "code\modules\psionics\events\psi_wail.dm"
+#include "code\modules\psionics\faculties\_faculty.dm"
+#include "code\modules\psionics\faculties\_power.dm"
+#include "code\modules\psionics\faculties\coercion.dm"
+#include "code\modules\psionics\faculties\energistics.dm"
+#include "code\modules\psionics\faculties\psychokinesis.dm"
+#include "code\modules\psionics\faculties\redaction.dm"
+#include "code\modules\psionics\interface\ui.dm"
+#include "code\modules\psionics\interface\ui_hub.dm"
+#include "code\modules\psionics\mob\mob.dm"
+#include "code\modules\psionics\mob\mob_assay.dm"
+#include "code\modules\psionics\mob\mob_interactions.dm"
#include "code\modules\random_map\_random_map_setup.dm"
#include "code\modules\random_map\random_map.dm"
#include "code\modules\random_map\random_map_verbs.dm"
@@ -2142,6 +2366,7 @@
#include "code\modules\reagents\reagent_dispenser.dm"
#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Core.dm"
#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Dispenser.dm"
+#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Drugs.dm"
#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Food-Drinks.dm"
#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Medicine.dm"
#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Other.dm"
@@ -2164,6 +2389,7 @@
#include "code\modules\reagents\reagent_containers\pill.dm"
#include "code\modules\reagents\reagent_containers\spray.dm"
#include "code\modules\reagents\reagent_containers\syringes.dm"
+#include "code\modules\reagents\reagent_containers\tooth_paste.dm"
#include "code\modules\reagents\reagent_containers\food\cans.dm"
#include "code\modules\reagents\reagent_containers\food\condiment.dm"
#include "code\modules\reagents\reagent_containers\food\drinks.dm"
@@ -2182,7 +2408,6 @@
#include "code\modules\recycling\disposal.dm"
#include "code\modules\recycling\sortingmachinery.dm"
#include "code\modules\research\circuitprinter.dm"
-#include "code\modules\research\designs.dm"
#include "code\modules\research\destructive_analyzer.dm"
#include "code\modules\research\message_server.dm"
#include "code\modules\research\protolathe.dm"
@@ -2192,16 +2417,36 @@
#include "code\modules\research\research.dm"
#include "code\modules\research\server.dm"
#include "code\modules\research\stockparts.dm"
-#include "code\modules\research\designs\AI_modules_designs.dm"
-#include "code\modules\research\designs\circuit_designs.dm"
-#include "code\modules\research\designs\mechfab_designs.dm"
-#include "code\modules\research\designs\medical_designs.dm"
-#include "code\modules\research\designs\mining_designs.dm"
-#include "code\modules\research\designs\modular_computer_designs.dm"
-#include "code\modules\research\designs\power_designs.dm"
-#include "code\modules\research\designs\stock_parts_designs.dm"
-#include "code\modules\research\designs\tcom_designs.dm"
-#include "code\modules\research\designs\weapon_designs.dm"
+#include "code\modules\research\designs\designs.dm"
+#include "code\modules\research\designs\circuit\AI_law_boards.dm"
+#include "code\modules\research\designs\circuit\circuits.dm"
+#include "code\modules\research\designs\circuit\computer_circuits.dm"
+#include "code\modules\research\designs\circuit\exosuit_circuits.dm"
+#include "code\modules\research\designs\circuit\hardsuit_circuits.dm"
+#include "code\modules\research\designs\circuit\machine_circuits.dm"
+#include "code\modules\research\designs\circuit\misc_electronics.dm"
+#include "code\modules\research\designs\circuit\shield_designs.dm"
+#include "code\modules\research\designs\circuit\tcom_designs.dm"
+#include "code\modules\research\designs\mechfab\hardsuit\modules.dm"
+#include "code\modules\research\designs\mechfab\hardsuit\rigs.dm"
+#include "code\modules\research\designs\mechfab\mechs\designs_exosuits.dm"
+#include "code\modules\research\designs\mechfab\prosthetics\external.dm"
+#include "code\modules\research\designs\mechfab\prosthetics\internal.dm"
+#include "code\modules\research\designs\mechfab\robot\robot.dm"
+#include "code\modules\research\designs\mechfab\robot\robot_upgrades.dm"
+#include "code\modules\research\designs\protolathe\disk_designs.dm"
+#include "code\modules\research\designs\protolathe\hud_glasses_designs.dm"
+#include "code\modules\research\designs\protolathe\implant_designs.dm"
+#include "code\modules\research\designs\protolathe\integrated_electronics_designs.dm"
+#include "code\modules\research\designs\protolathe\medical_designs.dm"
+#include "code\modules\research\designs\protolathe\mining_designs.dm"
+#include "code\modules\research\designs\protolathe\modular_computer_designs.dm"
+#include "code\modules\research\designs\protolathe\modular_gun_designs.dm"
+#include "code\modules\research\designs\protolathe\pda_designs.dm"
+#include "code\modules\research\designs\protolathe\power_designs.dm"
+#include "code\modules\research\designs\protolathe\stock_parts_designs.dm"
+#include "code\modules\research\designs\protolathe\tool_designs.dm"
+#include "code\modules\research\designs\protolathe\weapon_designs.dm"
#include "code\modules\research\xenoarchaeology\chemistry.dm"
#include "code\modules\research\xenoarchaeology\geosample.dm"
#include "code\modules\research\xenoarchaeology\manuals.dm"
@@ -2217,7 +2462,6 @@
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_badfeeling.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_cellcharge.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_celldrain.dm"
-#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_dnaswitch.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_emp.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_forcefield.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_gasco2.dm"
@@ -2245,7 +2489,6 @@
#include "code\modules\research\xenoarchaeology\machinery\artifact_analyser.dm"
#include "code\modules\research\xenoarchaeology\machinery\artifact_harvester.dm"
#include "code\modules\research\xenoarchaeology\machinery\artifact_scanner.dm"
-#include "code\modules\research\xenoarchaeology\machinery\coolant.dm"
#include "code\modules\research\xenoarchaeology\machinery\geosample_scanner.dm"
#include "code\modules\research\xenoarchaeology\tools\ano_device_battery.dm"
#include "code\modules\research\xenoarchaeology\tools\anomaly_suit.dm"
@@ -2291,79 +2534,133 @@
#include "code\modules\shuttles\antagonist.dm"
#include "code\modules\shuttles\departmental.dm"
#include "code\modules\shuttles\escape_pods.dm"
+#include "code\modules\shuttles\landmarks.dm"
#include "code\modules\shuttles\shuttle.dm"
#include "code\modules\shuttles\shuttle_arrival.dm"
+#include "code\modules\shuttles\shuttle_autodock.dm"
+#include "code\modules\shuttles\shuttle_autoreturn.dm"
#include "code\modules\shuttles\shuttle_console.dm"
+#include "code\modules\shuttles\shuttle_console_multi.dm"
#include "code\modules\shuttles\shuttle_emergency.dm"
#include "code\modules\shuttles\shuttle_ferry.dm"
#include "code\modules\shuttles\shuttle_specops.dm"
#include "code\modules\shuttles\shuttle_supply.dm"
#include "code\modules\shuttles\shuttles_multi.dm"
-#include "code\modules\spells\artifacts.dm"
-#include "code\modules\spells\construct_spells.dm"
-#include "code\modules\spells\contracts.dm"
-#include "code\modules\spells\monster_manual.dm"
-#include "code\modules\spells\no_clothes.dm"
-#include "code\modules\spells\spell_code.dm"
-#include "code\modules\spells\spell_projectile.dm"
-#include "code\modules\spells\spell_verb.dm"
-#include "code\modules\spells\spellbook.dm"
-#include "code\modules\spells\spells.dm"
-#include "code\modules\spells\storage.dm"
-#include "code\modules\spells\aoe_turf\aoe_turf.dm"
-#include "code\modules\spells\aoe_turf\blink.dm"
-#include "code\modules\spells\aoe_turf\charge.dm"
-#include "code\modules\spells\aoe_turf\disable_tech.dm"
-#include "code\modules\spells\aoe_turf\knock.dm"
-#include "code\modules\spells\aoe_turf\smoke.dm"
-#include "code\modules\spells\aoe_turf\summons.dm"
-#include "code\modules\spells\aoe_turf\conjure\conjure.dm"
-#include "code\modules\spells\aoe_turf\conjure\construct.dm"
-#include "code\modules\spells\aoe_turf\conjure\druidic_spells.dm"
-#include "code\modules\spells\aoe_turf\conjure\forcewall.dm"
-#include "code\modules\spells\aoe_turf\conjure\golem.dm"
-#include "code\modules\spells\aoe_turf\conjure\grove.dm"
-#include "code\modules\spells\general\area_teleport.dm"
-#include "code\modules\spells\general\contract_spells.dm"
-#include "code\modules\spells\general\mark_recall.dm"
-#include "code\modules\spells\general\return_master.dm"
-#include "code\modules\spells\general\rune_write.dm"
-#include "code\modules\spells\hand\hand.dm"
-#include "code\modules\spells\hand\hand_item.dm"
-#include "code\modules\spells\spellbook\battlemage.dm"
-#include "code\modules\spells\spellbook\cleric.dm"
-#include "code\modules\spells\spellbook\druid.dm"
-#include "code\modules\spells\spellbook\necromancer.dm"
-#include "code\modules\spells\spellbook\spatial.dm"
-#include "code\modules\spells\spellbook\standard.dm"
-#include "code\modules\spells\spellbook\student.dm"
-#include "code\modules\spells\targeted\cleric_spells.dm"
-#include "code\modules\spells\targeted\entangle.dm"
-#include "code\modules\spells\targeted\ethereal_jaunt.dm"
-#include "code\modules\spells\targeted\flesh_to_stone.dm"
-#include "code\modules\spells\targeted\genetic.dm"
-#include "code\modules\spells\targeted\harvest.dm"
-#include "code\modules\spells\targeted\mind_transfer.dm"
-#include "code\modules\spells\targeted\mindcontrol.dm"
-#include "code\modules\spells\targeted\necromancer_spells.dm"
-#include "code\modules\spells\targeted\shapeshift.dm"
-#include "code\modules\spells\targeted\shift.dm"
-#include "code\modules\spells\targeted\subjugate.dm"
-#include "code\modules\spells\targeted\swap.dm"
-#include "code\modules\spells\targeted\targeted.dm"
-#include "code\modules\spells\targeted\torment.dm"
-#include "code\modules\spells\targeted\equip\equip.dm"
-#include "code\modules\spells\targeted\equip\holy_relic.dm"
-#include "code\modules\spells\targeted\equip\horsemask.dm"
-#include "code\modules\spells\targeted\equip\party_hardy.dm"
-#include "code\modules\spells\targeted\equip\seed.dm"
-#include "code\modules\spells\targeted\equip\shield.dm"
-#include "code\modules\spells\targeted\projectile\dumbfire.dm"
-#include "code\modules\spells\targeted\projectile\fireball.dm"
-#include "code\modules\spells\targeted\projectile\magic_missile.dm"
-#include "code\modules\spells\targeted\projectile\passage.dm"
-#include "code\modules\spells\targeted\projectile\projectile.dm"
-#include "code\modules\spells\targeted\projectile\stuncuff.dm"
+#include "code\modules\spell_system\artifacts\armor\bone_armor.dm"
+#include "code\modules\spell_system\artifacts\armor\wizard_voidsuit.dm"
+#include "code\modules\spell_system\artifacts\items\bone_spear.dm"
+#include "code\modules\spell_system\artifacts\items\lich_phylactery.dm"
+#include "code\modules\spell_system\artifacts\items\monster_manual.dm"
+#include "code\modules\spell_system\artifacts\items\poppet.dm"
+#include "code\modules\spell_system\artifacts\items\rune_sword.dm"
+#include "code\modules\spell_system\artifacts\items\scrying_orb.dm"
+#include "code\modules\spell_system\artifacts\storage\closets\artifact_closet.dm"
+#include "code\modules\spell_system\artifacts\storage\closets\scrying_S.dm"
+#include "code\modules\spell_system\artifacts\storage\closets\soul_shards_S.dm"
+#include "code\modules\spell_system\artifacts\storage\closets\wizard_voidsuit_S.dm"
+#include "code\modules\spell_system\contracts\contracts.dm"
+#include "code\modules\spell_system\contracts\acadamy\acadamy_contracts.dm"
+#include "code\modules\spell_system\contracts\acadamy\xray_vision.dm"
+#include "code\modules\spell_system\contracts\boon\artificer.dm"
+#include "code\modules\spell_system\contracts\boon\boon_contracts.dm"
+#include "code\modules\spell_system\contracts\boon\charge.dm"
+#include "code\modules\spell_system\contracts\boon\fireball.dm"
+#include "code\modules\spell_system\contracts\boon\force_wall.dm"
+#include "code\modules\spell_system\contracts\boon\gestalt.dm"
+#include "code\modules\spell_system\contracts\boon\knock.dm"
+#include "code\modules\spell_system\contracts\boon\mindswap.dm"
+#include "code\modules\spell_system\contracts\boon\smoke.dm"
+#include "code\modules\spell_system\contracts\boon\statue.dm"
+#include "code\modules\spell_system\contracts\wizard\apprentice.dm"
+#include "code\modules\spell_system\spellbook\spellbook.dm"
+#include "code\modules\spell_system\spellbook\variants\battlemage.dm"
+#include "code\modules\spell_system\spellbook\variants\cleric.dm"
+#include "code\modules\spell_system\spellbook\variants\druid.dm"
+#include "code\modules\spell_system\spellbook\variants\necromancer.dm"
+#include "code\modules\spell_system\spellbook\variants\spatial.dm"
+#include "code\modules\spell_system\spellbook\variants\standard.dm"
+#include "code\modules\spell_system\spellbook\variants\student.dm"
+#include "code\modules\spell_system\spells\spell_code.dm"
+#include "code\modules\spell_system\spells\spell_projectile.dm"
+#include "code\modules\spell_system\spells\spell_verb.dm"
+#include "code\modules\spell_system\spells\spells.dm"
+#include "code\modules\spell_system\spells\hand\hand.dm"
+#include "code\modules\spell_system\spells\hand\hand_item.dm"
+#include "code\modules\spell_system\spells\spell_list\aoe_turf.dm"
+#include "code\modules\spell_system\spells\spell_list\conjure.dm"
+#include "code\modules\spell_system\spells\spell_list\construct_spells.dm"
+#include "code\modules\spell_system\spells\spell_list\dumbfire.dm"
+#include "code\modules\spell_system\spells\spell_list\equip.dm"
+#include "code\modules\spell_system\spells\spell_list\genetic.dm"
+#include "code\modules\spell_system\spells\spell_list\projectile.dm"
+#include "code\modules\spell_system\spells\spell_list\shapeshift.dm"
+#include "code\modules\spell_system\spells\spell_list\targeted_spells.dm"
+#include "code\modules\spell_system\spells\spell_list\others\area\blind.dm"
+#include "code\modules\spell_system\spells\spell_list\others\area\disable_tech.dm"
+#include "code\modules\spell_system\spells\spell_list\others\area\knock.dm"
+#include "code\modules\spell_system\spells\spell_list\others\area\smoke.dm"
+#include "code\modules\spell_system\spells\spell_list\others\area\torment.dm"
+#include "code\modules\spell_system\spells\spell_list\others\contracts\contract_spells.dm"
+#include "code\modules\spell_system\spells\spell_list\others\contracts\punish.dm"
+#include "code\modules\spell_system\spells\spell_list\others\contracts\reward.dm"
+#include "code\modules\spell_system\spells\spell_list\others\equip\party_hardy.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\baleful_polymorph.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\entangle.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\flesh_to_stone.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\harvest.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\heal_target.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\heal_target_area.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\heal_target_major.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\heal_target_sacrifice.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\life_steal.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\mend.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\mind_transfer.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\mindcontrol.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\raise_dead.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\resurrection.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\subjugate.dm"
+#include "code\modules\spell_system\spells\spell_list\others\generic\swap.dm"
+#include "code\modules\spell_system\spells\spell_list\others\projectile\fireball.dm"
+#include "code\modules\spell_system\spells\spell_list\others\projectile\magic_missile.dm"
+#include "code\modules\spell_system\spells\spell_list\others\projectile\stuncuff.dm"
+#include "code\modules\spell_system\spells\spell_list\self\area\blink.dm"
+#include "code\modules\spell_system\spells\spell_list\self\area\charge.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\druidic_spells.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\forcewall.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\gestalt_grove.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\golem.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\grove.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\plant_sanctuary.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\summon_carp.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\summon_demon_creature.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\summon_ed_swarm.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\summon_harmless_carp.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\construct_spells\construct_shell.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\construct_spells\create_altar.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\construct_spells\create_floor.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\construct_spells\create_forcewall.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\construct_spells\create_forge.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\construct_spells\create_wall.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\construct_spells\cultify_area.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\construct_spells\summon_pylon.dm"
+#include "code\modules\spell_system\spells\spell_list\self\conjure\construct_spells\summon_soulstone.dm"
+#include "code\modules\spell_system\spells\spell_list\self\equip\holy_relic.dm"
+#include "code\modules\spell_system\spells\spell_list\self\equip\seed.dm"
+#include "code\modules\spell_system\spells\spell_list\self\equip\shield.dm"
+#include "code\modules\spell_system\spells\spell_list\self\generic\area_teleport.dm"
+#include "code\modules\spell_system\spells\spell_list\self\generic\avian.dm"
+#include "code\modules\spell_system\spells\spell_list\self\generic\corrupt_form.dm"
+#include "code\modules\spell_system\spells\spell_list\self\generic\dark_resurrection.dm"
+#include "code\modules\spell_system\spells\spell_list\self\generic\ethereal_jaunt.dm"
+#include "code\modules\spell_system\spells\spell_list\self\generic\lichdom.dm"
+#include "code\modules\spell_system\spells\spell_list\self\generic\mark_recall.dm"
+#include "code\modules\spell_system\spells\spell_list\self\generic\mutate.dm"
+#include "code\modules\spell_system\spells\spell_list\self\generic\no_clothes.dm"
+#include "code\modules\spell_system\spells\spell_list\self\generic\return_master.dm"
+#include "code\modules\spell_system\spells\spell_list\self\generic\rune_write.dm"
+#include "code\modules\spell_system\spells\spell_list\self\generic\shadow_shroud.dm"
+#include "code\modules\spell_system\spells\spell_list\self\generic\shift.dm"
+#include "code\modules\spell_system\spells\spell_list\self\projectile\passage.dm"
#include "code\modules\supermatter\setup_supermatter.dm"
#include "code\modules\supermatter\supermatter.dm"
#include "code\modules\surgery\_defines.dm"
@@ -2391,6 +2688,7 @@
#include "code\modules\telesci\telepad.dm"
#include "code\modules\telesci\telesci_computer.dm"
#include "code\modules\tgs\includes.dm"
+#include "code\modules\tooltip\tooltip.dm"
#include "code\modules\turbolift\turbolift.dm"
#include "code\modules\turbolift\turbolift_areas.dm"
#include "code\modules\turbolift\turbolift_console.dm"
@@ -2425,6 +2723,15 @@
#include "code\modules\vueui\ui.dm"
#include "code\modules\vueui\var_monitor.dm"
#include "code\modules\web_interface\webint_procs.dm"
+#include "code\modules\world_api\api_command.dm"
+#include "code\modules\world_api\helpers.dm"
+#include "code\modules\world_api\commands\admin.dm"
+#include "code\modules\world_api\commands\api_helpers.dm"
+#include "code\modules\world_api\commands\cciaa.dm"
+#include "code\modules\world_api\commands\misc.dm"
+#include "code\modules\world_api\commands\server_management.dm"
+#include "code\modules\world_api\commands\server_query.dm"
+#include "code\modules\world_api\commands\tickets.dm"
#include "code\modules\xgm\xgm_gas_data.dm"
#include "code\modules\xgm\xgm_gas_mixture.dm"
#include "code\unit_tests\chemistry_tests.dm"
@@ -2434,6 +2741,7 @@
#include "code\unit_tests\mob_tests.dm"
#include "code\unit_tests\object_tests.dm"
#include "code\unit_tests\observation_tests.dm"
+#include "code\unit_tests\spawner_tests.dm"
#include "code\unit_tests\sql_tests.dm"
#include "code\unit_tests\ss_test.dm"
#include "code\unit_tests\unit_test.dm"
@@ -2484,4 +2792,6 @@
#include "maps\exodus\code\exodus_unittest.dm"
#include "maps\runtime\code\runtime.dm"
#include "maps\runtime\code\runtime_unittest.dm"
+#include "maps\templates\distress\distress_equipment.dm"
+#include "maps\templates\orbital\orbital_templates.dm"
// END_INCLUDE
diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm
index d32b433db5e..9e948d66eed 100644
--- a/code/ATMOSPHERICS/atmospherics.dm
+++ b/code/ATMOSPHERICS/atmospherics.dm
@@ -1,140 +1,136 @@
-/*
-Quick overview:
-
-Pipes combine to form pipelines
-Pipelines and other atmospheric objects combine to form pipe_networks
- Note: A single pipe_network represents a completely open space
-
-Pipes -> Pipelines
-Pipelines + Other Objects -> Pipe network
-
-*/
-/obj/machinery/atmospherics
- anchored = 1
- idle_power_usage = 0
- active_power_usage = 0
- power_channel = ENVIRON
- var/nodealert = 0
- var/power_rating //the maximum amount of power the machine can use to do work, affects how powerful the machine is, in Watts
-
- layer = 2.4 //under wires with their 2.44
-
- var/connect_types = CONNECT_TYPE_REGULAR
- var/icon_connect_type = "" //"-supply" or "-scrubbers"
-
- var/initialize_directions = 0
- var/pipe_color
-
- var/global/datum/pipe_icon_manager/icon_manager
- var/obj/machinery/atmospherics/node1
- var/obj/machinery/atmospherics/node2
- gfi_layer_rotation = GFI_ROTATION_OVERDIR
-
-/obj/machinery/atmospherics/Initialize(mapload)
- . = ..()
- if(!icon_manager)
- icon_manager = new()
-
- if(!pipe_color)
- pipe_color = color
- color = null
-
- if(!pipe_color_check(pipe_color))
- pipe_color = null
-
- if (mapload)
- return INITIALIZE_HINT_LATELOAD
-
-/obj/machinery/atmospherics/Destroy()
- ..()
- return QDEL_HINT_HARDDEL // fuck it
-
-/obj/machinery/atmospherics/proc/atmos_init()
-
-// atmos_init() and Initialize() must be separate, as atmos_init() can be called multiple times after the machine has been initialized.
-
-/obj/machinery/atmospherics/LateInitialize()
- atmos_init()
-
-/obj/machinery/atmospherics/attackby(atom/A, mob/user as mob)
- if(istype(A, /obj/item/device/pipe_painter))
- return
- ..()
-
-/obj/machinery/atmospherics/proc/add_underlay(var/turf/T, var/obj/machinery/atmospherics/node, var/direction, var/icon_connect_type)
- if(node)
- if(!T.is_plating() && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
- //underlays += icon_manager.get_atmos_icon("underlay_down", direction, color_cache_name(node))
- underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "down" + icon_connect_type)
- else
- //underlays += icon_manager.get_atmos_icon("underlay_intact", direction, color_cache_name(node))
- underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
- else
- //underlays += icon_manager.get_atmos_icon("underlay_exposed", direction, pipe_color)
- underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "exposed" + icon_connect_type)
-
-/obj/machinery/atmospherics/proc/update_underlays()
- if(check_icon_cache())
- return 1
- else
- return 0
-
-obj/machinery/atmospherics/proc/check_connect_types(obj/machinery/atmospherics/atmos1, obj/machinery/atmospherics/atmos2)
- return (atmos1.connect_types & atmos2.connect_types)
-
-/obj/machinery/atmospherics/proc/check_connect_types_construction(obj/machinery/atmospherics/atmos1, obj/item/pipe/pipe2)
- return (atmos1.connect_types & pipe2.connect_types)
-
-/obj/machinery/atmospherics/proc/check_icon_cache(var/safety = 0)
- if(!istype(icon_manager))
- if(!safety) //to prevent infinite loops
- icon_manager = new()
- check_icon_cache(1)
- return 0
-
- return 1
-
-/obj/machinery/atmospherics/proc/color_cache_name(var/obj/machinery/atmospherics/node)
- //Don't use this for standard pipes
- if(!istype(node))
- return null
-
- return node.pipe_color
-
-/obj/machinery/atmospherics/machinery_process()
- last_flow_rate = 0
- last_power_draw = 0
-
-/obj/machinery/atmospherics/proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
- // Check to see if should be added to network. Add self if so and adjust variables appropriately.
- // Note don't forget to have neighbors look as well!
-
- return null
-
-/obj/machinery/atmospherics/proc/build_network()
- // Called to build a network from this node
-
- return null
-
-/obj/machinery/atmospherics/proc/return_network(obj/machinery/atmospherics/reference)
- // Returns pipe_network associated with connection to reference
- // Notes: should create network if necessary
- // Should never return null
-
- return null
-
-/obj/machinery/atmospherics/proc/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
- // Used when two pipe_networks are combining
-
-/obj/machinery/atmospherics/proc/remove_network(datum/pipe_network/network)
- reassign_network(network, null)
-
-/obj/machinery/atmospherics/proc/return_network_air(datum/network/reference)
- // Return a list of gas_mixture(s) in the object
- // associated with reference pipe_network for use in rebuilding the networks gases list
- // Is permitted to return null
-
-/obj/machinery/atmospherics/proc/disconnect(obj/machinery/atmospherics/reference)
-
-/obj/machinery/atmospherics/update_icon()
- return null
+/*
+Quick overview:
+
+Pipes combine to form pipelines
+Pipelines and other atmospheric objects combine to form pipe_networks
+ Note: A single pipe_network represents a completely open space
+
+Pipes -> Pipelines
+Pipelines + Other Objects -> Pipe network
+
+*/
+/obj/machinery/atmospherics
+ anchored = 1
+ idle_power_usage = 0
+ active_power_usage = 0
+ power_channel = ENVIRON
+ var/nodealert = 0
+ var/power_rating //the maximum amount of power the machine can use to do work, affects how powerful the machine is, in Watts
+
+ layer = 2.4 //under wires with their 2.44
+
+ var/connect_types = CONNECT_TYPE_REGULAR
+ var/icon_connect_type = "" //"-supply" or "-scrubbers"
+
+ var/initialize_directions = 0
+ var/pipe_color
+
+ var/global/datum/pipe_icon_manager/icon_manager
+ var/obj/machinery/atmospherics/node1
+ var/obj/machinery/atmospherics/node2
+ gfi_layer_rotation = GFI_ROTATION_OVERDIR
+
+/obj/machinery/atmospherics/Initialize(mapload)
+ . = ..()
+ if(!icon_manager)
+ icon_manager = new()
+
+ if(!pipe_color)
+ pipe_color = color
+ color = null
+
+ if(!pipe_color_check(pipe_color))
+ pipe_color = null
+
+ if (mapload)
+ return INITIALIZE_HINT_LATELOAD
+
+/obj/machinery/atmospherics/proc/atmos_init()
+
+// atmos_init() and Initialize() must be separate, as atmos_init() can be called multiple times after the machine has been initialized.
+
+/obj/machinery/atmospherics/LateInitialize()
+ atmos_init()
+
+/obj/machinery/atmospherics/attackby(atom/A, mob/user as mob)
+ if(istype(A, /obj/item/device/pipe_painter))
+ return
+ ..()
+
+/obj/machinery/atmospherics/proc/add_underlay(var/turf/T, var/obj/machinery/atmospherics/node, var/direction, var/icon_connect_type)
+ if(node)
+ if(!T.is_plating() && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
+ //underlays += icon_manager.get_atmos_icon("underlay_down", direction, color_cache_name(node))
+ underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "down" + icon_connect_type)
+ else
+ //underlays += icon_manager.get_atmos_icon("underlay_intact", direction, color_cache_name(node))
+ underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
+ else
+ //underlays += icon_manager.get_atmos_icon("underlay_exposed", direction, pipe_color)
+ underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "exposed" + icon_connect_type)
+
+/obj/machinery/atmospherics/proc/update_underlays()
+ if(check_icon_cache())
+ return 1
+ else
+ return 0
+
+obj/machinery/atmospherics/proc/check_connect_types(obj/machinery/atmospherics/atmos1, obj/machinery/atmospherics/atmos2)
+ return (atmos1.connect_types & atmos2.connect_types)
+
+/obj/machinery/atmospherics/proc/check_connect_types_construction(obj/machinery/atmospherics/atmos1, obj/item/pipe/pipe2)
+ return (atmos1.connect_types & pipe2.connect_types)
+
+/obj/machinery/atmospherics/proc/check_icon_cache(var/safety = 0)
+ if(!istype(icon_manager))
+ if(!safety) //to prevent infinite loops
+ icon_manager = new()
+ check_icon_cache(1)
+ return 0
+
+ return 1
+
+/obj/machinery/atmospherics/proc/color_cache_name(var/obj/machinery/atmospherics/node)
+ //Don't use this for standard pipes
+ if(!istype(node))
+ return null
+
+ return node.pipe_color
+
+/obj/machinery/atmospherics/machinery_process()
+ last_flow_rate = 0
+ last_power_draw = 0
+
+/obj/machinery/atmospherics/proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
+ // Check to see if should be added to network. Add self if so and adjust variables appropriately.
+ // Note don't forget to have neighbors look as well!
+
+ return null
+
+/obj/machinery/atmospherics/proc/build_network()
+ // Called to build a network from this node
+
+ return null
+
+/obj/machinery/atmospherics/proc/return_network(obj/machinery/atmospherics/reference)
+ // Returns pipe_network associated with connection to reference
+ // Notes: should create network if necessary
+ // Should never return null
+
+ return null
+
+/obj/machinery/atmospherics/proc/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
+ // Used when two pipe_networks are combining
+
+/obj/machinery/atmospherics/proc/remove_network(datum/pipe_network/network)
+ reassign_network(network, null)
+
+/obj/machinery/atmospherics/proc/return_network_air(datum/pipe_network/reference)
+ // Return a list of gas_mixture(s) in the object
+ // associated with reference pipe_network for use in rebuilding the networks gases list
+ // Is permitted to return null
+
+/obj/machinery/atmospherics/proc/disconnect(obj/machinery/atmospherics/reference)
+
+/obj/machinery/atmospherics/update_icon()
+ return null
diff --git a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
index 5a1486de568..8528d636be2 100644
--- a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
@@ -1,134 +1,134 @@
-obj/machinery/atmospherics/binary
- dir = SOUTH
- initialize_directions = SOUTH|NORTH
- use_power = 1
-
- var/datum/gas_mixture/air1
- var/datum/gas_mixture/air2
-
- var/datum/pipe_network/network1
- var/datum/pipe_network/network2
-
- Initialize()
- switch(dir)
- if(NORTH)
- initialize_directions = NORTH|SOUTH
- if(SOUTH)
- initialize_directions = NORTH|SOUTH
- if(EAST)
- initialize_directions = EAST|WEST
- if(WEST)
- initialize_directions = EAST|WEST
- air1 = new
- air2 = new
-
- air1.volume = 200
- air2.volume = 200
- . = ..()
-
-// Housekeeping and pipe network stuff below
- network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
- if(reference == node1)
- network1 = new_network
-
- else if(reference == node2)
- network2 = new_network
-
- if(new_network.normal_members.Find(src))
- return 0
-
- new_network.normal_members += src
-
- return null
-
- Destroy()
- QDEL_NULL(air1)
- QDEL_NULL(air2)
-
- if(node1)
- node1.disconnect(src)
- QDEL_NULL(network1)
- if(node2)
- node2.disconnect(src)
- QDEL_NULL(network2)
-
- node1 = null
- node2 = null
-
- return ..()
-
- atmos_init()
- if(node1 && node2) return
-
- var/node2_connect = dir
- var/node1_connect = turn(dir, 180)
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node1 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node2 = target
- break
-
- update_icon()
- update_underlays()
-
- build_network()
- if(!network1 && node1)
- network1 = new /datum/pipe_network()
- network1.normal_members += src
- network1.build_network(node1, src)
-
- if(!network2 && node2)
- network2 = new /datum/pipe_network()
- network2.normal_members += src
- network2.build_network(node2, src)
-
-
- return_network(obj/machinery/atmospherics/reference)
- build_network()
-
- if(reference==node1)
- return network1
-
- if(reference==node2)
- return network2
-
- return null
-
- reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
- if(network1 == old_network)
- network1 = new_network
- if(network2 == old_network)
- network2 = new_network
-
- return 1
-
- return_network_air(datum/pipe_network/reference)
- var/list/results = list()
-
- if(network1 == reference)
- results += air1
- if(network2 == reference)
- results += air2
-
- return results
-
- disconnect(obj/machinery/atmospherics/reference)
- if(reference==node1)
- qdel(network1)
- node1 = null
-
- else if(reference==node2)
- qdel(network2)
- node2 = null
-
- update_icon()
- update_underlays()
-
- return null
+obj/machinery/atmospherics/binary
+ dir = SOUTH
+ initialize_directions = SOUTH|NORTH
+ use_power = 1
+
+ var/datum/gas_mixture/air1
+ var/datum/gas_mixture/air2
+
+ var/datum/pipe_network/network1
+ var/datum/pipe_network/network2
+
+ Initialize()
+ switch(dir)
+ if(NORTH)
+ initialize_directions = NORTH|SOUTH
+ if(SOUTH)
+ initialize_directions = NORTH|SOUTH
+ if(EAST)
+ initialize_directions = EAST|WEST
+ if(WEST)
+ initialize_directions = EAST|WEST
+ air1 = new
+ air2 = new
+
+ air1.volume = 200
+ air2.volume = 200
+ . = ..()
+
+// Housekeeping and pipe network stuff below
+ network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
+ if(reference == node1)
+ network1 = new_network
+
+ else if(reference == node2)
+ network2 = new_network
+
+ if(new_network.normal_members.Find(src))
+ return 0
+
+ new_network.normal_members += src
+
+ return null
+
+ Destroy()
+ QDEL_NULL(air1)
+ QDEL_NULL(air2)
+
+ if(node1)
+ node1.disconnect(src)
+ QDEL_NULL(network1)
+ if(node2)
+ node2.disconnect(src)
+ QDEL_NULL(network2)
+
+ node1 = null
+ node2 = null
+
+ return ..()
+
+ atmos_init()
+ if(node1 && node2) return
+
+ var/node2_connect = dir
+ var/node1_connect = turn(dir, 180)
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node1 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node2 = target
+ break
+
+ update_icon()
+ update_underlays()
+
+ build_network()
+ if(!network1 && node1)
+ network1 = new /datum/pipe_network()
+ network1.normal_members += src
+ network1.build_network(node1, src)
+
+ if(!network2 && node2)
+ network2 = new /datum/pipe_network()
+ network2.normal_members += src
+ network2.build_network(node2, src)
+
+
+ return_network(obj/machinery/atmospherics/reference)
+ build_network()
+
+ if(reference==node1)
+ return network1
+
+ if(reference==node2)
+ return network2
+
+ return null
+
+ reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
+ if(network1 == old_network)
+ network1 = new_network
+ if(network2 == old_network)
+ network2 = new_network
+
+ return 1
+
+ return_network_air(datum/pipe_network/reference)
+ var/list/results = list()
+
+ if(network1 == reference)
+ results += air1
+ if(network2 == reference)
+ results += air2
+
+ return results
+
+ disconnect(obj/machinery/atmospherics/reference)
+ if(reference==node1)
+ qdel(network1)
+ node1 = null
+
+ else if(reference==node2)
+ qdel(network2)
+ node2 = null
+
+ update_icon()
+ update_underlays()
+
+ return null
diff --git a/code/ATMOSPHERICS/components/binary_devices/circulator.dm b/code/ATMOSPHERICS/components/binary_devices/circulator.dm
index a00205b1c0c..803ac0977e7 100644
--- a/code/ATMOSPHERICS/components/binary_devices/circulator.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/circulator.dm
@@ -1,145 +1,123 @@
-//node1, air1, network1 correspond to input
-//node2, air2, network2 correspond to output
-
-/obj/machinery/atmospherics/binary/circulator
- name = "circulator"
- desc = "A gas circulator turbine and heat exchanger."
- icon = 'icons/obj/pipes.dmi'
- icon_state = "circ-off"
- anchored = 0
-
- var/kinetic_efficiency = 0.04 //combined kinetic and kinetic-to-electric efficiency
- var/volume_ratio = 0.2
-
- var/recent_moles_transferred = 0
- var/last_heat_capacity = 0
- var/last_temperature = 0
- var/last_pressure_delta = 0
- var/last_worldtime_transfer = 0
- var/last_stored_energy_transferred = 0
- var/volume_capacity_used = 0
- var/stored_energy = 0
-
- density = 1
-
-/obj/machinery/atmospherics/binary/circulator/Initialize()
- . = ..()
- desc = initial(desc) + " Its outlet port is to the [dir2text(dir)]."
- air1.volume = 400
-
-/obj/machinery/atmospherics/binary/circulator/proc/return_transfer_air()
- var/datum/gas_mixture/removed
- if(anchored && !(stat&BROKEN) && network1)
- var/input_starting_pressure = air1.return_pressure()
- var/output_starting_pressure = air2.return_pressure()
- last_pressure_delta = max(input_starting_pressure - output_starting_pressure - 5, 0)
-
- //only circulate air if there is a pressure difference (plus 5kPa kinetic, 10kPa static friction)
- if(air1.temperature > 0 && last_pressure_delta > 5)
-
- //Calculate necessary moles to transfer using PV = nRT
- recent_moles_transferred = (last_pressure_delta*network1.volume/(air1.temperature * R_IDEAL_GAS_EQUATION))/3 //uses the volume of the whole network, not just itself
- volume_capacity_used = min( (last_pressure_delta*network1.volume/3)/(input_starting_pressure*air1.volume) , 1) //how much of the gas in the input air volume is consumed
-
- //Calculate energy generated from kinetic turbine
- stored_energy += 1/ADIABATIC_EXPONENT * min(last_pressure_delta * network1.volume , input_starting_pressure*air1.volume) * (1 - volume_ratio**ADIABATIC_EXPONENT) * kinetic_efficiency
-
- //Actually transfer the gas
- removed = air1.remove(recent_moles_transferred)
- if(removed)
- last_heat_capacity = removed.heat_capacity()
- last_temperature = removed.temperature
-
- //Update the gas networks.
- network1.update = 1
-
- last_worldtime_transfer = world.time
- else
- recent_moles_transferred = 0
-
- update_icon()
- return removed
-
-/obj/machinery/atmospherics/binary/circulator/proc/return_stored_energy()
- last_stored_energy_transferred = stored_energy
- stored_energy = 0
- return last_stored_energy_transferred
-
-/obj/machinery/atmospherics/binary/circulator/machinery_process()
- ..()
-
- if(last_worldtime_transfer < world.time - 50)
- recent_moles_transferred = 0
- update_icon()
-
-/obj/machinery/atmospherics/binary/circulator/update_icon()
- if(stat & (BROKEN|NOPOWER) || !anchored)
- icon_state = "circ-p"
- else if(last_pressure_delta > 0 && recent_moles_transferred > 0)
- if(last_pressure_delta > 5*ONE_ATMOSPHERE)
- icon_state = "circ-run"
- else
- icon_state = "circ-slow"
- else
- icon_state = "circ-off"
-
- return 1
-
-/obj/machinery/atmospherics/binary/circulator/attackby(obj/item/weapon/W as obj, mob/user as mob)
- if (W.iswrench())
- playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
- anchored = !anchored
- user.visible_message("[user.name] [anchored ? "secures" : "unsecures"] the bolts holding [src.name] to the floor.", \
- "You [anchored ? "secure" : "unsecure"] the bolts holding [src] to the floor.", \
- "You hear a ratchet")
-
- if(anchored)
- if(dir & (NORTH|SOUTH))
- initialize_directions = NORTH|SOUTH
- else if(dir & (EAST|WEST))
- initialize_directions = EAST|WEST
-
- atmos_init()
- build_network()
- if (node1)
- node1.atmos_init()
- node1.build_network()
- if (node2)
- node2.atmos_init()
- node2.build_network()
- else
- if(node1)
- node1.disconnect(src)
- qdel(network1)
- if(node2)
- node2.disconnect(src)
- qdel(network2)
-
- node1 = null
- node2 = null
-
- else
- ..()
-
-/obj/machinery/atmospherics/binary/circulator/verb/rotate_clockwise()
- set category = "Object"
- set name = "Rotate Circulator (Clockwise)"
- set src in view(1)
-
- if (usr.stat || usr.restrained() || anchored)
- return
-
- src.set_dir(turn(src.dir, 90))
- desc = initial(desc) + " Its outlet port is to the [dir2text(dir)]."
-
-
-/obj/machinery/atmospherics/binary/circulator/verb/rotate_anticlockwise()
- set category = "Object"
- set name = "Rotate Circulator (Counterclockwise)"
- set src in view(1)
-
- if (usr.stat || usr.restrained() || anchored)
- return
-
- src.set_dir(turn(src.dir, -90))
- desc = initial(desc) + " Its outlet port is to the [dir2text(dir)]."
+//node1, air1, network1 correspond to input
+//node2, air2, network2 correspond to output
+
+/obj/machinery/atmospherics/binary/circulator
+ name = "circulator"
+ desc = "A gas circulator turbine and heat exchanger."
+ icon = 'icons/obj/pipes.dmi'
+ icon_state = "circ-off"
+ anchored = FALSE
+ obj_flags = OBJ_FLAG_ROTATABLE
+
+ var/kinetic_efficiency = 0.04 //combined kinetic and kinetic-to-electric efficiency
+ var/volume_ratio = 0.2
+
+ var/recent_moles_transferred = 0
+ var/last_heat_capacity = 0
+ var/last_temperature = 0
+ var/last_pressure_delta = 0
+ var/last_worldtime_transfer = 0
+ var/last_stored_energy_transferred = 0
+ var/volume_capacity_used = 0
+ var/stored_energy = 0
+
+ density = TRUE
+
+/obj/machinery/atmospherics/binary/circulator/Initialize()
+ . = ..()
+ desc = initial(desc) + " Its outlet port is to the [dir2text(dir)]."
+ air1.volume = 400
+
+/obj/machinery/atmospherics/binary/circulator/proc/return_transfer_air()
+ var/datum/gas_mixture/removed
+ if(anchored && !(stat&BROKEN) && network1)
+ var/input_starting_pressure = air1.return_pressure()
+ var/output_starting_pressure = air2.return_pressure()
+ last_pressure_delta = max(input_starting_pressure - output_starting_pressure - 5, 0)
+
+ //only circulate air if there is a pressure difference (plus 5kPa kinetic, 10kPa static friction)
+ if(air1.temperature > 0 && last_pressure_delta > 5)
+
+ //Calculate necessary moles to transfer using PV = nRT
+ recent_moles_transferred = (last_pressure_delta*network1.volume/(air1.temperature * R_IDEAL_GAS_EQUATION))/3 //uses the volume of the whole network, not just itself
+ volume_capacity_used = min( (last_pressure_delta*network1.volume/3)/(input_starting_pressure*air1.volume) , 1) //how much of the gas in the input air volume is consumed
+
+ //Calculate energy generated from kinetic turbine
+ stored_energy += 1/ADIABATIC_EXPONENT * min(last_pressure_delta * network1.volume , input_starting_pressure*air1.volume) * (1 - volume_ratio**ADIABATIC_EXPONENT) * kinetic_efficiency
+
+ //Actually transfer the gas
+ removed = air1.remove(recent_moles_transferred)
+ if(removed)
+ last_heat_capacity = removed.heat_capacity()
+ last_temperature = removed.temperature
+
+ //Update the gas networks.
+ network1.update = 1
+
+ last_worldtime_transfer = world.time
+ else
+ recent_moles_transferred = 0
+
+ update_icon()
+ return removed
+
+/obj/machinery/atmospherics/binary/circulator/proc/return_stored_energy()
+ last_stored_energy_transferred = stored_energy
+ stored_energy = 0
+ return last_stored_energy_transferred
+
+/obj/machinery/atmospherics/binary/circulator/machinery_process()
+ ..()
+
+ if(last_worldtime_transfer < world.time - 50)
+ recent_moles_transferred = 0
+ update_icon()
+
+/obj/machinery/atmospherics/binary/circulator/update_icon()
+ if(stat & (BROKEN|NOPOWER) || !anchored)
+ icon_state = "circ-p"
+ else if(last_pressure_delta > 0 && recent_moles_transferred > 0)
+ if(last_pressure_delta > 5*ONE_ATMOSPHERE)
+ icon_state = "circ-run"
+ else
+ icon_state = "circ-slow"
+ else
+ icon_state = "circ-off"
+
+ return 1
+
+/obj/machinery/atmospherics/binary/circulator/attackby(obj/item/W as obj, mob/user as mob)
+ if (W.iswrench())
+ playsound(src.loc, W.usesound, 75, 1)
+ anchored = !anchored
+ user.visible_message("[user.name] [anchored ? "secures" : "unsecures"] the bolts holding [src.name] to the floor.", \
+ "You [anchored ? "secure" : "unsecure"] the bolts holding [src] to the floor.", \
+ "You hear a ratchet")
+
+ if(anchored)
+ if(dir & (NORTH|SOUTH))
+ initialize_directions = NORTH|SOUTH
+ else if(dir & (EAST|WEST))
+ initialize_directions = EAST|WEST
+
+ atmos_init()
+ build_network()
+ if (node1)
+ node1.atmos_init()
+ node1.build_network()
+ if (node2)
+ node2.atmos_init()
+ node2.build_network()
+ else
+ if(node1)
+ node1.disconnect(src)
+ qdel(network1)
+ if(node2)
+ node2.disconnect(src)
+ qdel(network2)
+
+ node1 = null
+ node2 = null
+
+ else
+ ..()
diff --git a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
index 5c021e2bddf..a549eeb0160 100644
--- a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
@@ -1,265 +1,265 @@
-#define DEFAULT_PRESSURE_DELTA 10000
-
-#define EXTERNAL_PRESSURE_BOUND ONE_ATMOSPHERE
-#define INTERNAL_PRESSURE_BOUND 0
-#define PRESSURE_CHECKS 1
-
-#define PRESSURE_CHECK_EXTERNAL 1
-#define PRESSURE_CHECK_INPUT 2
-#define PRESSURE_CHECK_OUTPUT 4
-
-/obj/machinery/atmospherics/binary/dp_vent_pump
- icon = 'icons/atmos/vent_pump.dmi'
- icon_state = "map_dp_vent"
-
- //node2 is output port
- //node1 is input port
-
- name = "Dual Port Air Vent"
- desc = "Has a valve and pump attached to it. There are two ports."
-
- level = 1
-
- use_power = 0
- idle_power_usage = 150 //internal circuitry, friction losses and stuff
- power_rating = 7500 //7500 W ~ 10 HP
-
- connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER //connects to regular, supply and scrubbers pipes
-
- var/pump_direction = 1 //0 = siphoning, 1 = releasing
-
- var/external_pressure_bound = EXTERNAL_PRESSURE_BOUND
- var/input_pressure_min = INTERNAL_PRESSURE_BOUND
- var/output_pressure_max = DEFAULT_PRESSURE_DELTA
-
- var/frequency = 0
- var/id = null
- var/datum/radio_frequency/radio_connection
-
- var/pressure_checks = PRESSURE_CHECK_EXTERNAL
- //1: Do not pass external_pressure_bound
- //2: Do not pass input_pressure_min
- //4: Do not pass output_pressure_max
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/Initialize()
- . = ..()
- air1.volume = ATMOS_DEFAULT_VOLUME_PUMP
- air2.volume = ATMOS_DEFAULT_VOLUME_PUMP
- icon = null
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume
- name = "Large Dual Port Air Vent"
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume/Initialize()
- . = ..()
- air1.volume = ATMOS_DEFAULT_VOLUME_PUMP + 800
- air2.volume = ATMOS_DEFAULT_VOLUME_PUMP + 800
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/update_icon(var/safety = 0)
- if(!check_icon_cache())
- return
-
- var/istate = ""
-
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
-
- if(!T.is_plating() && node1 && node2 && node1.level == 1 && node2.level == 1 && istype(node1, /obj/machinery/atmospherics/pipe) && istype(node2, /obj/machinery/atmospherics/pipe))
- istate += "h"
-
- if(!powered())
- istate += "off"
- else
- istate += "[use_power ? "[pump_direction ? "out" : "in"]" : "off"]"
-
- icon_state = istate
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- if(!T.is_plating() && node1 && node2 && node1.level == 1 && node2.level == 1 && istype(node1, /obj/machinery/atmospherics/pipe) && istype(node2, /obj/machinery/atmospherics/pipe))
- return
- else
- if (node1)
- add_underlay(T, node1, turn(dir, -180), node1.icon_connect_type)
- else
- add_underlay(T, node1, turn(dir, -180))
- if (node2)
- add_underlay(T, node2, dir, node2.icon_connect_type)
- else
- add_underlay(T, node2, dir)
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/hide(var/i)
- update_icon()
- update_underlays()
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/machinery_process()
- ..()
-
- last_power_draw = 0
- last_flow_rate = 0
-
- if(stat & (NOPOWER|BROKEN) || !use_power)
- return 0
-
- var/datum/gas_mixture/environment = loc.return_air()
-
- var/power_draw = -1
-
- //Figure out the target pressure difference
- var/pressure_delta = get_pressure_delta(environment)
-
- if(pressure_delta > 0.5)
- if(pump_direction) //internal -> external
- if (node1 && (environment.temperature || air1.temperature))
- var/transfer_moles = calculate_transfer_moles(air1, environment, pressure_delta)
- power_draw = pump_gas(src, air1, environment, transfer_moles, power_rating)
-
- if(power_draw >= 0 && network1)
- network1.update = 1
- else //external -> internal
- if (node2 && (environment.temperature || air2.temperature))
- var/transfer_moles = calculate_transfer_moles(environment, air2, pressure_delta, (network2)? network2.volume : 0)
-
- //limit flow rate from turfs
- transfer_moles = min(transfer_moles, environment.total_moles*air2.volume/environment.volume) //group_multiplier gets divided out here
- power_draw = pump_gas(src, environment, air2, transfer_moles, power_rating)
-
- if(power_draw >= 0 && network2)
- network2.update = 1
-
- if (power_draw >= 0)
- last_power_draw = power_draw
- use_power(power_draw)
-
- return 1
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/proc/get_pressure_delta(datum/gas_mixture/environment)
- var/pressure_delta = DEFAULT_PRESSURE_DELTA
- var/environment_pressure = environment.return_pressure()
-
- if(pump_direction) //internal -> external
- if(pressure_checks & PRESSURE_CHECK_EXTERNAL)
- pressure_delta = min(pressure_delta, external_pressure_bound - environment_pressure) //increasing the pressure here
- if(pressure_checks & PRESSURE_CHECK_INPUT)
- pressure_delta = min(pressure_delta, air1.return_pressure() - input_pressure_min) //decreasing the pressure here
- else //external -> internal
- if(pressure_checks & PRESSURE_CHECK_EXTERNAL)
- pressure_delta = min(pressure_delta, environment_pressure - external_pressure_bound) //decreasing the pressure here
- if(pressure_checks & PRESSURE_CHECK_OUTPUT)
- pressure_delta = min(pressure_delta, output_pressure_max - air2.return_pressure()) //increasing the pressure here
-
- return pressure_delta
-
-
-//Radio remote control
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/proc/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- if(frequency)
- radio_connection = SSradio.add_object(src, frequency, filter = RADIO_ATMOSIA)
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/proc/broadcast_status()
- if(!radio_connection)
- return 0
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
- "tag" = id,
- "device" = "ADVP",
- "power" = use_power,
- "direction" = pump_direction?("release"):("siphon"),
- "checks" = pressure_checks,
- "input" = input_pressure_min,
- "output" = output_pressure_max,
- "external" = external_pressure_bound,
- "sigtype" = "status"
- )
- radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
-
- return 1
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/atmos_init()
- ..()
- if(frequency)
- set_frequency(frequency)
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/examine(mob/user)
- if(..(user, 1))
- to_chat(user, "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W")
-
-
-/obj/machinery/atmospherics/unary/vent_pump/power_change()
- var/old_stat = stat
- ..()
- if(old_stat != stat)
- update_icon()
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/receive_signal(datum/signal/signal)
- if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
- return 0
- if(signal.data["power"])
- use_power = text2num(signal.data["power"])
-
- if(signal.data["power_toggle"])
- use_power = !use_power
-
- if(signal.data["direction"])
- pump_direction = text2num(signal.data["direction"])
-
- if(signal.data["checks"])
- pressure_checks = text2num(signal.data["checks"])
-
- if(signal.data["purge"])
- pressure_checks &= ~1
- pump_direction = 0
-
- if(signal.data["stabalize"])
- pressure_checks |= 1
- pump_direction = 1
-
- if(signal.data["set_input_pressure"])
- input_pressure_min = between(
- 0,
- text2num(signal.data["set_input_pressure"]),
- ONE_ATMOSPHERE*50
- )
-
- if(signal.data["set_output_pressure"])
- output_pressure_max = between(
- 0,
- text2num(signal.data["set_output_pressure"]),
- ONE_ATMOSPHERE*50
- )
-
- if(signal.data["set_external_pressure"])
- external_pressure_bound = between(
- 0,
- text2num(signal.data["set_external_pressure"]),
- ONE_ATMOSPHERE*50
- )
-
- if(signal.data["status"])
- addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
- return //do not update_icon
-
- addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
- update_icon()
-
-#undef DEFAULT_PRESSURE_DELTA
-
-#undef EXTERNAL_PRESSURE_BOUND
-#undef INTERNAL_PRESSURE_BOUND
-#undef PRESSURE_CHECKS
-
-#undef PRESSURE_CHECK_EXTERNAL
-#undef PRESSURE_CHECK_INPUT
-#undef PRESSURE_CHECK_OUTPUT
+#define DEFAULT_PRESSURE_DELTA 10000
+
+#define EXTERNAL_PRESSURE_BOUND ONE_ATMOSPHERE
+#define INTERNAL_PRESSURE_BOUND 0
+#define PRESSURE_CHECKS 1
+
+#define PRESSURE_CHECK_EXTERNAL 1
+#define PRESSURE_CHECK_INPUT 2
+#define PRESSURE_CHECK_OUTPUT 4
+
+/obj/machinery/atmospherics/binary/dp_vent_pump
+ icon = 'icons/atmos/vent_pump.dmi'
+ icon_state = "map_dp_vent"
+
+ //node2 is output port
+ //node1 is input port
+
+ name = "Dual Port Air Vent"
+ desc = "Has a valve and pump attached to it. There are two ports."
+
+ level = 1
+
+ use_power = 0
+ idle_power_usage = 150 //internal circuitry, friction losses and stuff
+ power_rating = 7500 //7500 W ~ 10 HP
+
+ connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER //connects to regular, supply and scrubbers pipes
+
+ var/pump_direction = 1 //0 = siphoning, 1 = releasing
+
+ var/external_pressure_bound = EXTERNAL_PRESSURE_BOUND
+ var/input_pressure_min = INTERNAL_PRESSURE_BOUND
+ var/output_pressure_max = DEFAULT_PRESSURE_DELTA
+
+ var/frequency = 0
+ var/id = null
+ var/datum/radio_frequency/radio_connection
+
+ var/pressure_checks = PRESSURE_CHECK_EXTERNAL
+ //1: Do not pass external_pressure_bound
+ //2: Do not pass input_pressure_min
+ //4: Do not pass output_pressure_max
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/Initialize()
+ . = ..()
+ air1.volume = ATMOS_DEFAULT_VOLUME_PUMP
+ air2.volume = ATMOS_DEFAULT_VOLUME_PUMP
+ icon = null
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume
+ name = "Large Dual Port Air Vent"
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume/Initialize()
+ . = ..()
+ air1.volume = ATMOS_DEFAULT_VOLUME_PUMP + 800
+ air2.volume = ATMOS_DEFAULT_VOLUME_PUMP + 800
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/update_icon(var/safety = 0)
+ if(!check_icon_cache())
+ return
+
+ var/istate = ""
+
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+
+ if(!T.is_plating() && node1 && node2 && node1.level == 1 && node2.level == 1 && istype(node1, /obj/machinery/atmospherics/pipe) && istype(node2, /obj/machinery/atmospherics/pipe))
+ istate += "h"
+
+ if(!powered())
+ istate += "off"
+ else
+ istate += "[use_power ? "[pump_direction ? "out" : "in"]" : "off"]"
+
+ icon_state = istate
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ if(!T.is_plating() && node1 && node2 && node1.level == 1 && node2.level == 1 && istype(node1, /obj/machinery/atmospherics/pipe) && istype(node2, /obj/machinery/atmospherics/pipe))
+ return
+ else
+ if (node1)
+ add_underlay(T, node1, turn(dir, -180), node1.icon_connect_type)
+ else
+ add_underlay(T, node1, turn(dir, -180))
+ if (node2)
+ add_underlay(T, node2, dir, node2.icon_connect_type)
+ else
+ add_underlay(T, node2, dir)
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/hide(var/i)
+ update_icon()
+ update_underlays()
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/machinery_process()
+ ..()
+
+ last_power_draw = 0
+ last_flow_rate = 0
+
+ if(stat & (NOPOWER|BROKEN) || !use_power)
+ return 0
+
+ var/datum/gas_mixture/environment = loc.return_air()
+
+ var/power_draw = -1
+
+ //Figure out the target pressure difference
+ var/pressure_delta = get_pressure_delta(environment)
+
+ if(pressure_delta > 0.5)
+ if(pump_direction) //internal -> external
+ if (node1 && (environment.temperature || air1.temperature))
+ var/transfer_moles = calculate_transfer_moles(air1, environment, pressure_delta)
+ power_draw = pump_gas(src, air1, environment, transfer_moles, power_rating)
+
+ if(power_draw >= 0 && network1)
+ network1.update = 1
+ else //external -> internal
+ if (node2 && (environment.temperature || air2.temperature))
+ var/transfer_moles = calculate_transfer_moles(environment, air2, pressure_delta, (network2)? network2.volume : 0)
+
+ //limit flow rate from turfs
+ transfer_moles = min(transfer_moles, environment.total_moles*air2.volume/environment.volume) //group_multiplier gets divided out here
+ power_draw = pump_gas(src, environment, air2, transfer_moles, power_rating)
+
+ if(power_draw >= 0 && network2)
+ network2.update = 1
+
+ if (power_draw >= 0)
+ last_power_draw = power_draw
+ use_power(power_draw)
+
+ return 1
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/proc/get_pressure_delta(datum/gas_mixture/environment)
+ var/pressure_delta = DEFAULT_PRESSURE_DELTA
+ var/environment_pressure = environment.return_pressure()
+
+ if(pump_direction) //internal -> external
+ if(pressure_checks & PRESSURE_CHECK_EXTERNAL)
+ pressure_delta = min(pressure_delta, external_pressure_bound - environment_pressure) //increasing the pressure here
+ if(pressure_checks & PRESSURE_CHECK_INPUT)
+ pressure_delta = min(pressure_delta, air1.return_pressure() - input_pressure_min) //decreasing the pressure here
+ else //external -> internal
+ if(pressure_checks & PRESSURE_CHECK_EXTERNAL)
+ pressure_delta = min(pressure_delta, environment_pressure - external_pressure_bound) //decreasing the pressure here
+ if(pressure_checks & PRESSURE_CHECK_OUTPUT)
+ pressure_delta = min(pressure_delta, output_pressure_max - air2.return_pressure()) //increasing the pressure here
+
+ return pressure_delta
+
+
+//Radio remote control
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/proc/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ if(frequency)
+ radio_connection = SSradio.add_object(src, frequency, filter = RADIO_ATMOSIA)
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/proc/broadcast_status()
+ if(!radio_connection)
+ return 0
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+
+ signal.data = list(
+ "tag" = id,
+ "device" = "ADVP",
+ "power" = use_power,
+ "direction" = pump_direction?("release"):("siphon"),
+ "checks" = pressure_checks,
+ "input" = input_pressure_min,
+ "output" = output_pressure_max,
+ "external" = external_pressure_bound,
+ "sigtype" = "status"
+ )
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
+
+ return 1
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/atmos_init()
+ ..()
+ if(frequency)
+ set_frequency(frequency)
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/examine(mob/user)
+ if(..(user, 1))
+ to_chat(user, "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W")
+
+
+/obj/machinery/atmospherics/unary/vent_pump/power_change()
+ var/old_stat = stat
+ ..()
+ if(old_stat != stat)
+ update_icon()
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/receive_signal(datum/signal/signal)
+ if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
+ return 0
+ if(signal.data["power"])
+ use_power = text2num(signal.data["power"])
+
+ if(signal.data["power_toggle"])
+ use_power = !use_power
+
+ if(signal.data["direction"])
+ pump_direction = text2num(signal.data["direction"])
+
+ if(signal.data["checks"])
+ pressure_checks = text2num(signal.data["checks"])
+
+ if(signal.data["purge"])
+ pressure_checks &= ~1
+ pump_direction = 0
+
+ if(signal.data["stabalize"])
+ pressure_checks |= 1
+ pump_direction = 1
+
+ if(signal.data["set_input_pressure"])
+ input_pressure_min = between(
+ 0,
+ text2num(signal.data["set_input_pressure"]),
+ ONE_ATMOSPHERE*50
+ )
+
+ if(signal.data["set_output_pressure"])
+ output_pressure_max = between(
+ 0,
+ text2num(signal.data["set_output_pressure"]),
+ ONE_ATMOSPHERE*50
+ )
+
+ if(signal.data["set_external_pressure"])
+ external_pressure_bound = between(
+ 0,
+ text2num(signal.data["set_external_pressure"]),
+ ONE_ATMOSPHERE*50
+ )
+
+ if(signal.data["status"])
+ addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
+ return //do not update_icon
+
+ addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
+ update_icon()
+
+#undef DEFAULT_PRESSURE_DELTA
+
+#undef EXTERNAL_PRESSURE_BOUND
+#undef INTERNAL_PRESSURE_BOUND
+#undef PRESSURE_CHECKS
+
+#undef PRESSURE_CHECK_EXTERNAL
+#undef PRESSURE_CHECK_INPUT
+#undef PRESSURE_CHECK_OUTPUT
diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
index 5f1b1fafadc..d0a2e940c23 100644
--- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
@@ -1,261 +1,261 @@
-#define REGULATE_NONE 0
-#define REGULATE_INPUT 1 //shuts off when input side is below the target pressure
-#define REGULATE_OUTPUT 2 //shuts off when output side is above the target pressure
-
-/obj/machinery/atmospherics/binary/passive_gate
- icon = 'icons/atmos/passive_gate.dmi'
- icon_state = "map"
- level = 1
-
- name = "pressure regulator"
- desc = "A one-way air valve that can be used to regulate input or output pressure, and flow rate. Does not require power."
-
- use_power = 0
- interact_offline = 1
- var/unlocked = 0 //If 0, then the valve is locked closed, otherwise it is open(-able, it's a one-way valve so it closes if gas would flow backwards).
- var/target_pressure = ONE_ATMOSPHERE
- var/max_pressure_setting = 15000 //kPa
- var/set_flow_rate = ATMOS_DEFAULT_VOLUME_PUMP * 2.5
- var/regulate_mode = REGULATE_OUTPUT
-
- var/flowing = 0 //for icons - becomes zero if the valve closes itself due to regulation mode
-
- var/frequency = 0
- var/id = null
- var/datum/radio_frequency/radio_connection
-
-/obj/machinery/atmospherics/binary/passive_gate/Initialize()
- . = ..()
- air1.volume = ATMOS_DEFAULT_VOLUME_PUMP * 2.5
- air2.volume = ATMOS_DEFAULT_VOLUME_PUMP * 2.5
-
-/obj/machinery/atmospherics/binary/passive_gate/update_icon()
- icon_state = (unlocked && flowing)? "on" : "off"
-
-/obj/machinery/atmospherics/binary/passive_gate/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- add_underlay(T, node1, turn(dir, 180))
- add_underlay(T, node2, dir)
-
-/obj/machinery/atmospherics/binary/passive_gate/hide(var/i)
- update_underlays()
-
-/obj/machinery/atmospherics/binary/passive_gate/machinery_process()
- ..()
-
- last_flow_rate = 0
-
- if(!unlocked)
- return 0
-
- var/output_starting_pressure = air2.return_pressure()
- var/input_starting_pressure = air1.return_pressure()
-
- var/pressure_delta
- switch (regulate_mode)
- if (REGULATE_INPUT)
- pressure_delta = input_starting_pressure - target_pressure
- if (REGULATE_OUTPUT)
- pressure_delta = target_pressure - output_starting_pressure
-
- //-1 if pump_gas() did not move any gas, >= 0 otherwise
- var/returnval = -1
- if((regulate_mode == REGULATE_NONE || pressure_delta > 0.01) && (air1.temperature > 0 || air2.temperature > 0)) //since it's basically a valve, it makes sense to check both temperatures
- flowing = 1
-
- //flow rate limit
- var/transfer_moles = (set_flow_rate/air1.volume)*air1.total_moles
-
- //Figure out how much gas to transfer to meet the target pressure.
- switch (regulate_mode)
- if (REGULATE_INPUT)
- transfer_moles = min(transfer_moles, calculate_transfer_moles(air2, air1, pressure_delta, (network1)? network1.volume : 0))
- if (REGULATE_OUTPUT)
- transfer_moles = min(transfer_moles, calculate_transfer_moles(air1, air2, pressure_delta, (network2)? network2.volume : 0))
-
- //pump_gas() will return a negative number if no flow occurred
- returnval = pump_gas_passive(src, air1, air2, transfer_moles)
-
- if (returnval >= 0)
- if(network1)
- network1.update = 1
-
- if(network2)
- network2.update = 1
-
- if (last_flow_rate)
- flowing = 1
-
- update_icon()
-
-
-//Radio remote control
-
-/obj/machinery/atmospherics/binary/passive_gate/proc/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- if(frequency)
- radio_connection = SSradio.add_object(src, frequency, filter = RADIO_ATMOSIA)
-
-/obj/machinery/atmospherics/binary/passive_gate/proc/broadcast_status()
- if(!radio_connection)
- return 0
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
- "tag" = id,
- "device" = "AGP",
- "power" = unlocked,
- "target_output" = target_pressure,
- "regulate_mode" = regulate_mode,
- "set_flow_rate" = set_flow_rate,
- "sigtype" = "status"
- )
-
- radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
-
- return 1
-
-/obj/machinery/atmospherics/binary/passive_gate/atmos_init()
- ..()
- if(frequency)
- set_frequency(frequency)
-
-/obj/machinery/atmospherics/binary/passive_gate/receive_signal(datum/signal/signal)
- if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
- return 0
-
- if("power" in signal.data)
- unlocked = text2num(signal.data["power"])
-
- if("power_toggle" in signal.data)
- unlocked = !unlocked
-
- if("set_target_pressure" in signal.data)
- target_pressure = between(
- 0,
- text2num(signal.data["set_target_pressure"]),
- max_pressure_setting
- )
-
- if("set_regulate_mode" in signal.data)
- regulate_mode = text2num(signal.data["set_regulate_mode"])
-
- if("set_flow_rate" in signal.data)
- regulate_mode = text2num(signal.data["set_flow_rate"])
-
- if("status" in signal.data)
- addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
- return //do not update_icon
-
- addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
- update_icon()
- return
-
-/obj/machinery/atmospherics/binary/passive_gate/attack_hand(user as mob)
- if(..())
- return
- src.add_fingerprint(usr)
- if(!src.allowed(user))
- to_chat(user, "Access denied.")
- return
- usr.set_machine(src)
- ui_interact(user)
- return
-
-/obj/machinery/atmospherics/binary/passive_gate/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
- if(stat & (BROKEN|NOPOWER))
- return
-
- // this is the data which will be sent to the ui
- var/data[0]
-
- data = list(
- "on" = unlocked,
- "pressure_set" = round(target_pressure*100), //Nano UI can't handle rounded non-integers, apparently.
- "max_pressure" = max_pressure_setting,
- "input_pressure" = round(air1.return_pressure()*100),
- "output_pressure" = round(air2.return_pressure()*100),
- "regulate_mode" = regulate_mode,
- "set_flow_rate" = round(set_flow_rate*10),
- "last_flow_rate" = round(last_flow_rate*10)
- )
-
- // update the ui if it exists, returns null if no ui is passed/found
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- // the ui does not exist, so we'll create a new() one
- // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
- ui = new(user, src, ui_key, "pressure_regulator.tmpl", name, 470, 370)
- ui.set_initial_data(data) // when the ui is first opened this is the data it will use
- ui.open() // open the new ui window
- ui.set_auto_update(1) // auto update every Master Controller tick
-
-
-/obj/machinery/atmospherics/binary/passive_gate/Topic(href,href_list)
- if(..()) return 1
-
- if(href_list["toggle_valve"])
- unlocked = !unlocked
-
- if(href_list["regulate_mode"])
- switch(href_list["regulate_mode"])
- if ("off") regulate_mode = REGULATE_NONE
- if ("input") regulate_mode = REGULATE_INPUT
- if ("output") regulate_mode = REGULATE_OUTPUT
-
- switch(href_list["set_press"])
- if ("min")
- target_pressure = 0
- if ("max")
- target_pressure = max_pressure_setting
- if ("set")
- var/new_pressure = input(usr,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure Control",src.target_pressure) as num
- src.target_pressure = between(0, new_pressure, max_pressure_setting)
-
- switch(href_list["set_flow_rate"])
- if ("min")
- set_flow_rate = 0
- if ("max")
- set_flow_rate = air1.volume
- if ("set")
- var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[air1.volume]kPa)","Flow Rate Control",src.set_flow_rate) as num
- src.set_flow_rate = between(0, new_flow_rate, air1.volume)
-
- usr.set_machine(src) //Is this even needed with NanoUI?
- src.update_icon()
- src.add_fingerprint(usr)
- return
-
-/obj/machinery/atmospherics/binary/passive_gate/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
- if (!W.iswrench())
- return ..()
- if (unlocked)
- to_chat(user, "You cannot unwrench \the [src], turn it off first.")
- return 1
- var/datum/gas_mixture/int_air = return_air()
- var/datum/gas_mixture/env_air = loc.return_air()
- if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
- to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
- add_fingerprint(user)
- return 1
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
- if (do_after(user, 40, act_target = src))
- user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
- "You hear ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
-
-#undef REGULATE_NONE
-#undef REGULATE_INPUT
-#undef REGULATE_OUTPUT
+#define REGULATE_NONE 0
+#define REGULATE_INPUT 1 //shuts off when input side is below the target pressure
+#define REGULATE_OUTPUT 2 //shuts off when output side is above the target pressure
+
+/obj/machinery/atmospherics/binary/passive_gate
+ icon = 'icons/atmos/passive_gate.dmi'
+ icon_state = "map"
+ level = 1
+
+ name = "pressure regulator"
+ desc = "A one-way air valve that can be used to regulate input or output pressure, and flow rate. Does not require power."
+
+ use_power = 0
+ interact_offline = 1
+ var/unlocked = 0 //If 0, then the valve is locked closed, otherwise it is open(-able, it's a one-way valve so it closes if gas would flow backwards).
+ var/target_pressure = ONE_ATMOSPHERE
+ var/max_pressure_setting = 15000 //kPa
+ var/set_flow_rate = ATMOS_DEFAULT_VOLUME_PUMP * 2.5
+ var/regulate_mode = REGULATE_OUTPUT
+
+ var/flowing = 0 //for icons - becomes zero if the valve closes itself due to regulation mode
+
+ var/frequency = 0
+ var/id = null
+ var/datum/radio_frequency/radio_connection
+
+/obj/machinery/atmospherics/binary/passive_gate/Initialize()
+ . = ..()
+ air1.volume = ATMOS_DEFAULT_VOLUME_PUMP * 2.5
+ air2.volume = ATMOS_DEFAULT_VOLUME_PUMP * 2.5
+
+/obj/machinery/atmospherics/binary/passive_gate/update_icon()
+ icon_state = (unlocked && flowing)? "on" : "off"
+
+/obj/machinery/atmospherics/binary/passive_gate/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ add_underlay(T, node1, turn(dir, 180))
+ add_underlay(T, node2, dir)
+
+/obj/machinery/atmospherics/binary/passive_gate/hide(var/i)
+ update_underlays()
+
+/obj/machinery/atmospherics/binary/passive_gate/machinery_process()
+ ..()
+
+ last_flow_rate = 0
+
+ if(!unlocked)
+ return 0
+
+ var/output_starting_pressure = air2.return_pressure()
+ var/input_starting_pressure = air1.return_pressure()
+
+ var/pressure_delta
+ switch (regulate_mode)
+ if (REGULATE_INPUT)
+ pressure_delta = input_starting_pressure - target_pressure
+ if (REGULATE_OUTPUT)
+ pressure_delta = target_pressure - output_starting_pressure
+
+ //-1 if pump_gas() did not move any gas, >= 0 otherwise
+ var/returnval = -1
+ if((regulate_mode == REGULATE_NONE || pressure_delta > 0.01) && (air1.temperature > 0 || air2.temperature > 0)) //since it's basically a valve, it makes sense to check both temperatures
+ flowing = 1
+
+ //flow rate limit
+ var/transfer_moles = (set_flow_rate/air1.volume)*air1.total_moles
+
+ //Figure out how much gas to transfer to meet the target pressure.
+ switch (regulate_mode)
+ if (REGULATE_INPUT)
+ transfer_moles = min(transfer_moles, calculate_transfer_moles(air2, air1, pressure_delta, (network1)? network1.volume : 0))
+ if (REGULATE_OUTPUT)
+ transfer_moles = min(transfer_moles, calculate_transfer_moles(air1, air2, pressure_delta, (network2)? network2.volume : 0))
+
+ //pump_gas() will return a negative number if no flow occurred
+ returnval = pump_gas_passive(src, air1, air2, transfer_moles)
+
+ if (returnval >= 0)
+ if(network1)
+ network1.update = 1
+
+ if(network2)
+ network2.update = 1
+
+ if (last_flow_rate)
+ flowing = 1
+
+ update_icon()
+
+
+//Radio remote control
+
+/obj/machinery/atmospherics/binary/passive_gate/proc/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ if(frequency)
+ radio_connection = SSradio.add_object(src, frequency, filter = RADIO_ATMOSIA)
+
+/obj/machinery/atmospherics/binary/passive_gate/proc/broadcast_status()
+ if(!radio_connection)
+ return 0
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+
+ signal.data = list(
+ "tag" = id,
+ "device" = "AGP",
+ "power" = unlocked,
+ "target_output" = target_pressure,
+ "regulate_mode" = regulate_mode,
+ "set_flow_rate" = set_flow_rate,
+ "sigtype" = "status"
+ )
+
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
+
+ return 1
+
+/obj/machinery/atmospherics/binary/passive_gate/atmos_init()
+ ..()
+ if(frequency)
+ set_frequency(frequency)
+
+/obj/machinery/atmospherics/binary/passive_gate/receive_signal(datum/signal/signal)
+ if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
+ return 0
+
+ if("power" in signal.data)
+ unlocked = text2num(signal.data["power"])
+
+ if("power_toggle" in signal.data)
+ unlocked = !unlocked
+
+ if("set_target_pressure" in signal.data)
+ target_pressure = between(
+ 0,
+ text2num(signal.data["set_target_pressure"]),
+ max_pressure_setting
+ )
+
+ if("set_regulate_mode" in signal.data)
+ regulate_mode = text2num(signal.data["set_regulate_mode"])
+
+ if("set_flow_rate" in signal.data)
+ regulate_mode = text2num(signal.data["set_flow_rate"])
+
+ if("status" in signal.data)
+ addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
+ return //do not update_icon
+
+ addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
+ update_icon()
+ return
+
+/obj/machinery/atmospherics/binary/passive_gate/attack_hand(user as mob)
+ if(..())
+ return
+ src.add_fingerprint(usr)
+ if(!src.allowed(user))
+ to_chat(user, "Access denied.")
+ return
+ usr.set_machine(src)
+ ui_interact(user)
+ return
+
+/obj/machinery/atmospherics/binary/passive_gate/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ if(stat & (BROKEN|NOPOWER))
+ return
+
+ // this is the data which will be sent to the ui
+ var/data[0]
+
+ data = list(
+ "on" = unlocked,
+ "pressure_set" = round(target_pressure*100), //Nano UI can't handle rounded non-integers, apparently.
+ "max_pressure" = max_pressure_setting,
+ "input_pressure" = round(air1.return_pressure()*100),
+ "output_pressure" = round(air2.return_pressure()*100),
+ "regulate_mode" = regulate_mode,
+ "set_flow_rate" = round(set_flow_rate*10),
+ "last_flow_rate" = round(last_flow_rate*10)
+ )
+
+ // update the ui if it exists, returns null if no ui is passed/found
+ ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if (!ui)
+ // the ui does not exist, so we'll create a new() one
+ // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
+ ui = new(user, src, ui_key, "pressure_regulator.tmpl", name, 470, 370)
+ ui.set_initial_data(data) // when the ui is first opened this is the data it will use
+ ui.open() // open the new ui window
+ ui.set_auto_update(1) // auto update every Master Controller tick
+
+
+/obj/machinery/atmospherics/binary/passive_gate/Topic(href,href_list)
+ if(..()) return 1
+
+ if(href_list["toggle_valve"])
+ unlocked = !unlocked
+
+ if(href_list["regulate_mode"])
+ switch(href_list["regulate_mode"])
+ if ("off") regulate_mode = REGULATE_NONE
+ if ("input") regulate_mode = REGULATE_INPUT
+ if ("output") regulate_mode = REGULATE_OUTPUT
+
+ switch(href_list["set_press"])
+ if ("min")
+ target_pressure = 0
+ if ("max")
+ target_pressure = max_pressure_setting
+ if ("set")
+ var/new_pressure = input(usr,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure Control",src.target_pressure) as num
+ src.target_pressure = between(0, new_pressure, max_pressure_setting)
+
+ switch(href_list["set_flow_rate"])
+ if ("min")
+ set_flow_rate = 0
+ if ("max")
+ set_flow_rate = air1.volume
+ if ("set")
+ var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[air1.volume]kPa)","Flow Rate Control",src.set_flow_rate) as num
+ src.set_flow_rate = between(0, new_flow_rate, air1.volume)
+
+ usr.set_machine(src) //Is this even needed with NanoUI?
+ src.update_icon()
+ src.add_fingerprint(usr)
+ return
+
+/obj/machinery/atmospherics/binary/passive_gate/attackby(var/obj/item/W as obj, var/mob/user as mob)
+ if (!W.iswrench())
+ return ..()
+ if (unlocked)
+ to_chat(user, "You cannot unwrench \the [src], turn it off first.")
+ return 1
+ var/datum/gas_mixture/int_air = return_air()
+ var/datum/gas_mixture/env_air = loc.return_air()
+ if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
+ to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
+ add_fingerprint(user)
+ return 1
+ playsound(src.loc, W.usesound, 50, 1)
+ to_chat(user, "You begin to unfasten \the [src]...")
+ if (do_after(user, 40/W.toolspeed, act_target = src))
+ user.visible_message( \
+ "\The [user] unfastens \the [src].", \
+ "You have unfastened \the [src].", \
+ "You hear ratchet.")
+ new /obj/item/pipe(loc, make_from=src)
+ qdel(src)
+
+#undef REGULATE_NONE
+#undef REGULATE_INPUT
+#undef REGULATE_OUTPUT
diff --git a/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm b/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm
index 708bad6ec13..e9785fad2ea 100644
--- a/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm
@@ -5,6 +5,7 @@
icon_state = "turbine"
anchored = 0
density = 1
+ obj_flags = OBJ_FLAG_ROTATABLE
var/efficiency = 0.4
var/kin_energy = 0
@@ -85,7 +86,7 @@
if (kin_energy > 1000000)
add_overlay("hi-turb")
- attackby(obj/item/weapon/W as obj, mob/user as mob)
+ attackby(obj/item/W as obj, mob/user as mob)
if(W.iswrench())
anchored = !anchored
to_chat(user, "You [anchored ? "secure" : "unsecure"] the bolts holding \the [src] to the floor.")
@@ -118,27 +119,6 @@
else
..()
- verb/rotate_clockwise()
- set category = "Object"
- set name = "Rotate Circulator (Clockwise)"
- set src in view(1)
-
- if (usr.stat || usr.restrained() || anchored)
- return
-
- src.set_dir(turn(src.dir, -90))
-
-
- verb/rotate_anticlockwise()
- set category = "Object"
- set name = "Rotate Circulator (Counterclockwise)"
- set src in view(1)
-
- if (usr.stat || usr.restrained() || anchored)
- return
-
- src.set_dir(turn(src.dir, 90))
-
//Goddamn copypaste from binary base class because atmospherics machinery API is not damn flexible
network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
if(reference == node1)
@@ -230,6 +210,7 @@
icon_state = "motor"
anchored = 0
density = 1
+ obj_flags = OBJ_FLAG_ROTATABLE
var/kin_to_el_ratio = 0.1 //How much kinetic energy will be taken from turbine and converted into electricity
var/obj/machinery/atmospherics/pipeturbine/turbine
@@ -259,7 +240,7 @@
add_avail(power_generated)
- attackby(obj/item/weapon/W as obj, mob/user as mob)
+ attackby(obj/item/W as obj, mob/user as mob)
if(W.iswrench())
anchored = !anchored
turbine = null
@@ -267,23 +248,3 @@
updateConnection()
else
..()
-
- verb/rotate_clock()
- set category = "Object"
- set name = "Rotate Motor Clockwise"
- set src in view(1)
-
- if (usr.stat || usr.restrained() || anchored)
- return
-
- src.set_dir(turn(src.dir, -90))
-
- verb/rotate_anticlock()
- set category = "Object"
- set name = "Rotate Motor Counterclockwise"
- set src in view(1)
-
- if (usr.stat || usr.restrained() || anchored)
- return
-
- src.set_dir(turn(src.dir, 90))
diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm
index 2476eb9024a..c90b6281fd0 100644
--- a/code/ATMOSPHERICS/components/binary_devices/pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm
@@ -1,236 +1,238 @@
-/*
-Every cycle, the pump uses the air in air_in to try and make air_out the perfect pressure.
-
-node1, air1, network1 correspond to input
-node2, air2, network2 correspond to output
-
-Thus, the two variables affect pump operation are set in New():
- air1.volume
- This is the volume of gas available to the pump that may be transfered to the output
- air2.volume
- Higher quantities of this cause more air to be perfected later
- but overall network volume is also increased as this increases...
-*/
-
-/obj/machinery/atmospherics/binary/pump
- icon = 'icons/atmos/pump.dmi'
- icon_state = "map_off"
- level = 1
-
- name = "gas pump"
- desc = "A pump"
-
- var/target_pressure = ONE_ATMOSPHERE
-
- //var/max_volume_transfer = 10000
-
- use_power = 0
- idle_power_usage = 150 //internal circuitry, friction losses and stuff
- power_rating = 7500 //7500 W ~ 10 HP
-
- var/max_pressure_setting = 15000 //kPa
-
- var/frequency = 0
- var/id = null
- var/datum/radio_frequency/radio_connection
-
-/obj/machinery/atmospherics/binary/pump/Initialize()
- . = ..()
- air1.volume = ATMOS_DEFAULT_VOLUME_PUMP
- air2.volume = ATMOS_DEFAULT_VOLUME_PUMP
-
-/obj/machinery/atmospherics/binary/pump/on
- icon_state = "map_on"
- use_power = 1
-
-
-/obj/machinery/atmospherics/binary/pump/update_icon()
- if(!powered())
- icon_state = "off"
- else
- icon_state = "[use_power ? "on" : "off"]"
-
-/obj/machinery/atmospherics/binary/pump/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- add_underlay(T, node1, turn(dir, -180))
- add_underlay(T, node2, dir)
-
-/obj/machinery/atmospherics/binary/pump/hide(var/i)
- update_underlays()
-
-/obj/machinery/atmospherics/binary/pump/machinery_process()
- last_power_draw = 0
- last_flow_rate = 0
-
- if((stat & (NOPOWER|BROKEN)) || !use_power)
- return
-
- var/power_draw = -1
- var/pressure_delta = target_pressure - air2.return_pressure()
-
- if(pressure_delta > 0.01 && air1.temperature > 0)
- //Figure out how much gas to transfer to meet the target pressure.
- var/transfer_moles = calculate_transfer_moles(air1, air2, pressure_delta, (network2)? network2.volume : 0)
- power_draw = pump_gas(src, air1, air2, transfer_moles, power_rating)
-
- if (power_draw >= 0)
- last_power_draw = power_draw
- use_power(power_draw)
-
- if(network1)
- network1.update = 1
-
- if(network2)
- network2.update = 1
-
- return 1
-
-//Radio remote control
-
-/obj/machinery/atmospherics/binary/pump/proc/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- if(frequency)
- radio_connection = SSradio.add_object(src, frequency, filter = RADIO_ATMOSIA)
-
-/obj/machinery/atmospherics/binary/pump/proc/broadcast_status()
- if(!radio_connection)
- return 0
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
- "tag" = id,
- "device" = "AGP",
- "power" = use_power,
- "target_output" = target_pressure,
- "sigtype" = "status"
- )
-
- radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
-
- return 1
-
-/obj/machinery/atmospherics/binary/pump/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
- if(stat & (BROKEN|NOPOWER))
- return
-
- // this is the data which will be sent to the ui
- var/data[0]
-
- data = list(
- "on" = use_power,
- "pressure_set" = round(target_pressure*100), //Nano UI can't handle rounded non-integers, apparently.
- "max_pressure" = max_pressure_setting,
- "last_flow_rate" = round(last_flow_rate*10),
- "last_power_draw" = round(last_power_draw),
- "max_power_draw" = power_rating
- )
-
- // update the ui if it exists, returns null if no ui is passed/found
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- // the ui does not exist, so we'll create a new() one
- // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
- ui = new(user, src, ui_key, "gas_pump.tmpl", name, 470, 290)
- ui.set_initial_data(data) // when the ui is first opened this is the data it will use
- ui.open() // open the new ui window
- ui.set_auto_update(1) // auto update every Master Controller tick
-
-/obj/machinery/atmospherics/binary/pump/atmos_init()
- ..()
- if(frequency)
- set_frequency(frequency)
-
-/obj/machinery/atmospherics/binary/pump/receive_signal(datum/signal/signal)
- if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
- return 0
-
- if(signal.data["power"])
- if(text2num(signal.data["power"]))
- use_power = 1
- else
- use_power = 0
-
- if("power_toggle" in signal.data)
- use_power = !use_power
-
- if(signal.data["set_output_pressure"])
- target_pressure = between(
- 0,
- text2num(signal.data["set_output_pressure"]),
- ONE_ATMOSPHERE*50
- )
-
- if(signal.data["status"])
- addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
- return //do not update_icon
-
- addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
- update_icon()
- return
-
-/obj/machinery/atmospherics/binary/pump/attack_hand(user as mob)
- if(..())
- return
- src.add_fingerprint(usr)
- if(!src.allowed(user))
- to_chat(user, "Access denied.")
- return
- usr.set_machine(src)
- ui_interact(user)
- return
-
-/obj/machinery/atmospherics/binary/pump/Topic(href,href_list)
- if(..()) return 1
-
- if(href_list["power"])
- use_power = !use_power
-
- switch(href_list["set_press"])
- if ("min")
- target_pressure = 0
- if ("max")
- target_pressure = max_pressure_setting
- if ("set")
- var/new_pressure = input(usr,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure control",src.target_pressure) as num
- src.target_pressure = between(0, new_pressure, max_pressure_setting)
-
- usr.set_machine(src)
- src.add_fingerprint(usr)
-
- src.update_icon()
-
-/obj/machinery/atmospherics/binary/pump/power_change()
- var/old_stat = stat
- ..()
- if(old_stat != stat)
- update_icon()
-
-/obj/machinery/atmospherics/binary/pump/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
- if (!W.iswrench())
- return ..()
- if (!(stat & NOPOWER) && use_power)
- to_chat(user, "You cannot unwrench this [src], turn it off first.")
- return 1
- var/datum/gas_mixture/int_air = return_air()
- var/datum/gas_mixture/env_air = loc.return_air()
- if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
- to_chat(user, "You cannot unwrench this [src], it too exerted due to internal pressure.")
- add_fingerprint(user)
- return 1
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
- if (do_after(user, 40, act_target = src))
- user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
- "You hear ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
+/*
+Every cycle, the pump uses the air in air_in to try and make air_out the perfect pressure.
+
+node1, air1, network1 correspond to input
+node2, air2, network2 correspond to output
+
+Thus, the two variables affect pump operation are set in New():
+ air1.volume
+ This is the volume of gas available to the pump that may be transfered to the output
+ air2.volume
+ Higher quantities of this cause more air to be perfected later
+ but overall network volume is also increased as this increases...
+*/
+
+/obj/machinery/atmospherics/binary/pump
+ icon = 'icons/atmos/pump.dmi'
+ icon_state = "map_off"
+ level = 1
+
+ name = "gas pump"
+ desc = "A pump"
+
+ var/target_pressure = ONE_ATMOSPHERE
+
+ //var/max_volume_transfer = 10000
+
+ use_power = 0
+ idle_power_usage = 150 //internal circuitry, friction losses and stuff
+ power_rating = 7500 //7500 W ~ 10 HP
+
+ var/max_pressure_setting = 15000 //kPa
+
+ var/frequency = 0
+ var/id = null
+ var/datum/radio_frequency/radio_connection
+
+/obj/machinery/atmospherics/binary/pump/Initialize()
+ . = ..()
+ air1.volume = ATMOS_DEFAULT_VOLUME_PUMP
+ air2.volume = ATMOS_DEFAULT_VOLUME_PUMP
+
+/obj/machinery/atmospherics/binary/pump/on
+ icon_state = "map_on"
+ use_power = 1
+
+
+/obj/machinery/atmospherics/binary/pump/update_icon()
+ if(!powered())
+ icon_state = "off"
+ else
+ icon_state = "[use_power ? "on" : "off"]"
+
+/obj/machinery/atmospherics/binary/pump/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ add_underlay(T, node1, turn(dir, -180))
+ add_underlay(T, node2, dir)
+
+/obj/machinery/atmospherics/binary/pump/hide(var/i)
+ update_underlays()
+
+/obj/machinery/atmospherics/binary/pump/machinery_process()
+ last_power_draw = 0
+ last_flow_rate = 0
+
+ if((stat & (NOPOWER|BROKEN)) || !use_power)
+ return
+
+ var/power_draw = -1
+ var/pressure_delta = target_pressure - air2.return_pressure()
+
+ if(pressure_delta > 0.01 && air1.temperature > 0)
+ //Figure out how much gas to transfer to meet the target pressure.
+ var/transfer_moles = calculate_transfer_moles(air1, air2, pressure_delta, (network2)? network2.volume : 0)
+ power_draw = pump_gas(src, air1, air2, transfer_moles, power_rating)
+
+ if (power_draw >= 0)
+ last_power_draw = power_draw
+ use_power(power_draw)
+
+ if(network1)
+ network1.update = 1
+
+ if(network2)
+ network2.update = 1
+
+ return 1
+
+//Radio remote control
+
+/obj/machinery/atmospherics/binary/pump/proc/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ if(frequency)
+ radio_connection = SSradio.add_object(src, frequency, filter = RADIO_ATMOSIA)
+
+/obj/machinery/atmospherics/binary/pump/proc/broadcast_status()
+ if(!radio_connection)
+ return 0
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+
+ signal.data = list(
+ "tag" = id,
+ "device" = "AGP",
+ "power" = use_power,
+ "target_output" = target_pressure,
+ "sigtype" = "status"
+ )
+
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
+
+ return 1
+
+/obj/machinery/atmospherics/binary/pump/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ if(stat & (BROKEN|NOPOWER))
+ return
+
+ // this is the data which will be sent to the ui
+ var/data[0]
+
+ data = list(
+ "on" = use_power,
+ "pressure_set" = round(target_pressure*100), //Nano UI can't handle rounded non-integers, apparently.
+ "max_pressure" = max_pressure_setting,
+ "last_flow_rate" = round(last_flow_rate*10),
+ "last_power_draw" = round(last_power_draw),
+ "max_power_draw" = power_rating
+ )
+
+ // update the ui if it exists, returns null if no ui is passed/found
+ ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if (!ui)
+ // the ui does not exist, so we'll create a new() one
+ // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
+ ui = new(user, src, ui_key, "gas_pump.tmpl", name, 470, 290)
+ ui.set_initial_data(data) // when the ui is first opened this is the data it will use
+ ui.open() // open the new ui window
+ ui.set_auto_update(1) // auto update every Master Controller tick
+
+/obj/machinery/atmospherics/binary/pump/atmos_init()
+ ..()
+ if(frequency)
+ set_frequency(frequency)
+
+/obj/machinery/atmospherics/binary/pump/receive_signal(datum/signal/signal)
+ if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
+ return 0
+
+ if(signal.data["power"])
+ if(text2num(signal.data["power"]))
+ use_power = 1
+ else
+ use_power = 0
+
+ if("power_toggle" in signal.data)
+ use_power = !use_power
+
+ if(signal.data["set_output_pressure"])
+ target_pressure = between(
+ 0,
+ text2num(signal.data["set_output_pressure"]),
+ ONE_ATMOSPHERE*50
+ )
+
+ if(signal.data["status"])
+ addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
+ return //do not update_icon
+
+ addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
+ update_icon()
+ return
+
+/obj/machinery/atmospherics/binary/pump/attack_hand(user as mob)
+ if(..())
+ return
+ src.add_fingerprint(usr)
+ if(!src.allowed(user))
+ to_chat(user, "Access denied.")
+ return
+ usr.set_machine(src)
+ ui_interact(user)
+ return
+
+/obj/machinery/atmospherics/binary/pump/Topic(href,href_list)
+ if(..()) return 1
+
+ if(href_list["power"])
+ use_power = !use_power
+
+ switch(href_list["set_press"])
+ if ("min")
+ target_pressure = 0
+ if ("max")
+ target_pressure = max_pressure_setting
+ if ("set")
+ var/new_pressure = input(usr,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure control",src.target_pressure) as num
+ src.target_pressure = between(0, new_pressure, max_pressure_setting)
+
+ usr.set_machine(src)
+ src.add_fingerprint(usr)
+
+ src.update_icon()
+
+/obj/machinery/atmospherics/binary/pump/power_change()
+ var/old_stat = stat
+ ..()
+ if(old_stat != stat)
+ update_icon()
+
+/obj/machinery/atmospherics/binary/pump/attackby(var/obj/item/W as obj, var/mob/user as mob)
+ if (!W.iswrench() && !istype(W, /obj/item/pipewrench))
+ return ..()
+ if (!(stat & NOPOWER) && use_power)
+ to_chat(user, "You cannot unwrench this [src], turn it off first.")
+ return 1
+ var/datum/gas_mixture/int_air = return_air()
+ var/datum/gas_mixture/env_air = loc.return_air()
+ if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE && !istype(W, /obj/item/pipewrench))
+ to_chat(user, "You cannot unwrench this [src], it's too exerted due to internal pressure.")
+ add_fingerprint(user)
+ return 1
+ else
+ to_chat(user, "You struggle to unwrench \the [src] with your pipe wrench.")
+ playsound(src.loc, W.usesound, 50, 1)
+ to_chat(user, "You begin to unfasten \the [src]...")
+ if (do_after(user, istype(W, /obj/item/pipewrench) ? 80/W.toolspeed : 40/W.toolspeed, act_target = src))
+ user.visible_message( \
+ "\The [user] unfastens \the [src].", \
+ "You have unfastened \the [src].", \
+ "You hear a ratchet.")
+ new /obj/item/pipe(loc, make_from=src)
+ qdel(src)
diff --git a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm
index 42b02282cc2..fff0c747c6f 100644
--- a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm
@@ -1,19 +1,19 @@
-/obj/machinery/atmospherics/binary/pump/high_power
- icon = 'icons/atmos/volume_pump.dmi'
- icon_state = "map_off"
- level = 1
-
- name = "high power gas pump"
- desc = "A pump. Has double the power rating of the standard gas pump."
-
- power_rating = 15000 //15000 W ~ 20 HP
-
-/obj/machinery/atmospherics/binary/pump/high_power/on
- use_power = 1
- icon_state = "map_on"
-
-/obj/machinery/atmospherics/binary/pump/high_power/update_icon()
- if(!powered())
- icon_state = "off"
- else
+/obj/machinery/atmospherics/binary/pump/high_power
+ icon = 'icons/atmos/volume_pump.dmi'
+ icon_state = "map_off"
+ level = 1
+
+ name = "high power gas pump"
+ desc = "A pump. Has double the power rating of the standard gas pump."
+
+ power_rating = 15000 //15000 W ~ 20 HP
+
+/obj/machinery/atmospherics/binary/pump/high_power/on
+ use_power = 1
+ icon_state = "map_on"
+
+/obj/machinery/atmospherics/binary/pump/high_power/update_icon()
+ if(!powered())
+ icon_state = "off"
+ else
icon_state = "[use_power ? "on" : "off"]"
\ No newline at end of file
diff --git a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
index 22453d3635b..85605a05a7b 100644
--- a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
+++ b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
@@ -82,7 +82,7 @@
if(old_stat != stat)
update_icon()
-/obj/machinery/atmospherics/omni/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+/obj/machinery/atmospherics/omni/attackby(var/obj/item/W as obj, var/mob/user as mob)
if(!W.iswrench())
return ..()
@@ -95,8 +95,8 @@
add_fingerprint(user)
return 1
to_chat(user, "You begin to unfasten \the [src]...")
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- if(do_after(user, 40, act_target = src))
+ playsound(src.loc, W.usesound, 50, 1)
+ if(do_after(user, 40/W.toolspeed, act_target = src))
user.visible_message( \
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
diff --git a/code/ATMOSPHERICS/components/portables_connector.dm b/code/ATMOSPHERICS/components/portables_connector.dm
index c15e89418f6..8f848cc77ae 100644
--- a/code/ATMOSPHERICS/components/portables_connector.dm
+++ b/code/ATMOSPHERICS/components/portables_connector.dm
@@ -1,155 +1,155 @@
-/obj/machinery/atmospherics/portables_connector
- icon = 'icons/atmos/connector.dmi'
- icon_state = "map_connector"
-
- name = "Connector Port"
- desc = "For connecting portables devices related to atmospherics control."
-
- dir = SOUTH
- initialize_directions = SOUTH
-
- var/obj/machinery/portable_atmospherics/connected_device
-
- var/obj/machinery/atmospherics/node
-
- var/datum/pipe_network/network
-
- var/on = 0
- use_power = 0
- level = 1
-
-
-/obj/machinery/atmospherics/portables_connector/Initialize()
- initialize_directions = dir
- . = ..()
-
-/obj/machinery/atmospherics/portables_connector/update_icon()
- icon_state = "connector"
-
-/obj/machinery/atmospherics/portables_connector/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- add_underlay(T, node, dir)
-
-/obj/machinery/atmospherics/portables_connector/hide(var/i)
- update_underlays()
-
-/obj/machinery/atmospherics/portables_connector/machinery_process()
- ..()
- if(!on)
- return
- if(!connected_device)
- on = 0
- return
- if(network)
- network.update = 1
- return 1
-
-// Housekeeping and pipe network stuff below
-/obj/machinery/atmospherics/portables_connector/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
- if(reference == node)
- network = new_network
-
- if(new_network.normal_members.Find(src))
- return 0
-
- new_network.normal_members += src
-
- return null
-
-/obj/machinery/atmospherics/portables_connector/Destroy()
- loc = null
-
- if(connected_device)
- connected_device.disconnect()
-
- if(node)
- node.disconnect(src)
- qdel(network)
-
- node = null
-
- return ..()
-
-/obj/machinery/atmospherics/portables_connector/atmos_init()
- if(node) return
-
- var/node_connect = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node_connect))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node = target
- break
-
- update_icon()
- update_underlays()
-
-/obj/machinery/atmospherics/portables_connector/build_network()
- if(!network && node)
- network = new /datum/pipe_network()
- network.normal_members += src
- network.build_network(node, src)
-
-
-/obj/machinery/atmospherics/portables_connector/return_network(obj/machinery/atmospherics/reference)
- build_network()
-
- if(reference==node)
- return network
-
- if(reference==connected_device)
- return network
-
- return null
-
-/obj/machinery/atmospherics/portables_connector/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
- if(network == old_network)
- network = new_network
-
- return 1
-
-/obj/machinery/atmospherics/portables_connector/return_network_air(datum/pipe_network/reference)
- var/list/results = list()
-
- if(connected_device)
- results += connected_device.air_contents
-
- return results
-
-/obj/machinery/atmospherics/portables_connector/disconnect(obj/machinery/atmospherics/reference)
- if(reference==node)
- qdel(network)
- node = null
-
- update_underlays()
-
- return null
-
-
-/obj/machinery/atmospherics/portables_connector/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
- if (!W.iswrench())
- return ..()
- if (connected_device)
- to_chat(user, "You cannot unwrench \the [src], dettach \the [connected_device] first.")
- return 1
- if (locate(/obj/machinery/portable_atmospherics, src.loc))
- return 1
- var/datum/gas_mixture/int_air = return_air()
- var/datum/gas_mixture/env_air = loc.return_air()
- if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
- to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
- add_fingerprint(user)
- return 1
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
- if (do_after(user, 40, act_target = src))
- user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
- "You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
+/obj/machinery/atmospherics/portables_connector
+ icon = 'icons/atmos/connector.dmi'
+ icon_state = "map_connector"
+
+ name = "Connector Port"
+ desc = "For connecting portables devices related to atmospherics control."
+
+ dir = SOUTH
+ initialize_directions = SOUTH
+
+ var/obj/machinery/portable_atmospherics/connected_device
+
+ var/obj/machinery/atmospherics/node
+
+ var/datum/pipe_network/network
+
+ var/on = 0
+ use_power = 0
+ level = 1
+
+
+/obj/machinery/atmospherics/portables_connector/Initialize()
+ initialize_directions = dir
+ . = ..()
+
+/obj/machinery/atmospherics/portables_connector/update_icon()
+ icon_state = "connector"
+
+/obj/machinery/atmospherics/portables_connector/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ add_underlay(T, node, dir)
+
+/obj/machinery/atmospherics/portables_connector/hide(var/i)
+ update_underlays()
+
+/obj/machinery/atmospherics/portables_connector/machinery_process()
+ ..()
+ if(!on)
+ return
+ if(!connected_device)
+ on = 0
+ return
+ if(network)
+ network.update = 1
+ return 1
+
+// Housekeeping and pipe network stuff below
+/obj/machinery/atmospherics/portables_connector/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
+ if(reference == node)
+ network = new_network
+
+ if(new_network.normal_members.Find(src))
+ return 0
+
+ new_network.normal_members += src
+
+ return null
+
+/obj/machinery/atmospherics/portables_connector/Destroy()
+ loc = null
+
+ if(connected_device)
+ connected_device.disconnect()
+
+ if(node)
+ node.disconnect(src)
+ qdel(network)
+
+ node = null
+
+ return ..()
+
+/obj/machinery/atmospherics/portables_connector/atmos_init()
+ if(node) return
+
+ var/node_connect = dir
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node = target
+ break
+
+ update_icon()
+ update_underlays()
+
+/obj/machinery/atmospherics/portables_connector/build_network()
+ if(!network && node)
+ network = new /datum/pipe_network()
+ network.normal_members += src
+ network.build_network(node, src)
+
+
+/obj/machinery/atmospherics/portables_connector/return_network(obj/machinery/atmospherics/reference)
+ build_network()
+
+ if(reference==node)
+ return network
+
+ if(reference==connected_device)
+ return network
+
+ return null
+
+/obj/machinery/atmospherics/portables_connector/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
+ if(network == old_network)
+ network = new_network
+
+ return 1
+
+/obj/machinery/atmospherics/portables_connector/return_network_air(datum/pipe_network/reference)
+ var/list/results = list()
+
+ if(connected_device)
+ results += connected_device.air_contents
+
+ return results
+
+/obj/machinery/atmospherics/portables_connector/disconnect(obj/machinery/atmospherics/reference)
+ if(reference==node)
+ qdel(network)
+ node = null
+
+ update_underlays()
+
+ return null
+
+
+/obj/machinery/atmospherics/portables_connector/attackby(var/obj/item/W as obj, var/mob/user as mob)
+ if (!W.iswrench())
+ return ..()
+ if (connected_device)
+ to_chat(user, "You cannot unwrench \the [src], dettach \the [connected_device] first.")
+ return 1
+ if (locate(/obj/machinery/portable_atmospherics, src.loc))
+ return 1
+ var/datum/gas_mixture/int_air = return_air()
+ var/datum/gas_mixture/env_air = loc.return_air()
+ if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
+ to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
+ add_fingerprint(user)
+ return 1
+ playsound(src.loc, W.usesound, 50, 1)
+ to_chat(user, "You begin to unfasten \the [src]...")
+ if (do_after(user, 40/W.toolspeed, act_target = src))
+ user.visible_message( \
+ "\The [user] unfastens \the [src].", \
+ "You have unfastened \the [src].", \
+ "You hear a ratchet.")
+ new /obj/item/pipe(loc, make_from=src)
+ qdel(src)
diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
index 34bdb74d155..df1abd0d212 100755
--- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
@@ -1,277 +1,277 @@
-/obj/machinery/atmospherics/trinary/filter
- icon = 'icons/atmos/filter.dmi'
- icon_state = "map"
- density = 0
- level = 1
-
- name = "Gas filter"
-
- use_power = 1
- idle_power_usage = 150 //internal circuitry, friction losses and stuff
- power_rating = 7500 //This also doubles as a measure of how powerful the filter is, in Watts. 7500 W ~ 10 HP
-
- var/temp = null // -- TLE
-
- var/set_flow_rate = ATMOS_DEFAULT_VOLUME_FILTER
-
- /*
- Filter types:
- -1: Nothing
- 0: Phoron: Phoron, Oxygen Agent B
- 1: Oxygen: Oxygen ONLY
- 2: Nitrogen: Nitrogen ONLY
- 3: Carbon Dioxide: Carbon Dioxide ONLY
- 4: Sleeping Agent (N2O)
- */
- var/filter_type = -1
- var/list/filtered_out = list()
-
-
- var/frequency = 0
- var/datum/radio_frequency/radio_connection
-
-/obj/machinery/atmospherics/trinary/filter/proc/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- if(frequency)
- radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
-
-/obj/machinery/atmospherics/trinary/filter/Initialize()
- . = ..()
- switch(filter_type)
- if(0) //removing hydrocarbons
- filtered_out = list("phoron")
- if(1) //removing O2
- filtered_out = list("oxygen")
- if(2) //removing N2
- filtered_out = list("nitrogen")
- if(3) //removing CO2
- filtered_out = list("carbon_dioxide")
- if(4)//removing N2O
- filtered_out = list("sleeping_agent")
-
- air1.volume = ATMOS_DEFAULT_VOLUME_FILTER
- air2.volume = ATMOS_DEFAULT_VOLUME_FILTER
- air3.volume = ATMOS_DEFAULT_VOLUME_FILTER
-
-/obj/machinery/atmospherics/trinary/filter/update_icon()
- if(istype(src, /obj/machinery/atmospherics/trinary/filter/m_filter))
- icon_state = "m"
- else
- icon_state = ""
-
- if(!powered())
- icon_state += "off"
- else if(node2 && node3 && node1)
- icon_state += use_power ? "on" : "off"
- else
- icon_state += "off"
- use_power = 0
-
-/obj/machinery/atmospherics/trinary/filter/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
-
- add_underlay(T, node1, turn(dir, -180))
-
- if(istype(src, /obj/machinery/atmospherics/trinary/filter/m_filter))
- add_underlay(T, node2, turn(dir, 90))
- else
- add_underlay(T, node2, turn(dir, -90))
-
- add_underlay(T, node3, dir)
-
-/obj/machinery/atmospherics/trinary/filter/hide(var/i)
- update_underlays()
-
-/obj/machinery/atmospherics/trinary/filter/power_change()
- var/old_stat = stat
- ..()
- if(old_stat != stat)
- update_icon()
-
-/obj/machinery/atmospherics/trinary/filter/machinery_process()
- ..()
-
- last_power_draw = 0
- last_flow_rate = 0
-
- if((stat & (NOPOWER|BROKEN)) || !use_power)
- return
-
- //Figure out the amount of moles to transfer
- var/transfer_moles = (set_flow_rate/air1.volume)*air1.total_moles
-
- var/power_draw = -1
- if (transfer_moles > MINIMUM_MOLES_TO_FILTER)
- power_draw = filter_gas(src, filtered_out, air1, air2, air3, transfer_moles, power_rating)
-
- if(network2)
- network2.update = 1
-
- if(network3)
- network3.update = 1
-
- if(network1)
- network1.update = 1
-
- if (power_draw >= 0)
- last_power_draw = power_draw
- use_power(power_draw)
-
- return 1
-
-/obj/machinery/atmospherics/trinary/filter/atmos_init()
- set_frequency(frequency)
- ..()
-
-/obj/machinery/atmospherics/trinary/filter/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
- if (!W.iswrench())
- return ..()
- var/datum/gas_mixture/int_air = return_air()
- var/datum/gas_mixture/env_air = loc.return_air()
- if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
- to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
- add_fingerprint(user)
- return 1
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
- if (do_after(user, 40, act_target = src))
- user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
- "You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
-
-
-/obj/machinery/atmospherics/trinary/filter/attack_hand(user as mob) // -- TLE
- if(..())
- return
-
- if(!src.allowed(user))
- to_chat(user, "Access denied.")
- return
-
- var/dat
- var/current_filter_type
- switch(filter_type)
- if(0)
- current_filter_type = "Phoron"
- if(1)
- current_filter_type = "Oxygen"
- if(2)
- current_filter_type = "Nitrogen"
- if(3)
- current_filter_type = "Carbon Dioxide"
- if(4)
- current_filter_type = "Nitrous Oxide"
- if(-1)
- current_filter_type = "Nothing"
- else
- current_filter_type = "ERROR - Report this bug to the admin, please!"
-
- dat += {"
- Power: [use_power?"On":"Off"]
- Filtering: [current_filter_type]
- Set Filter Type:
- Phoron
- Oxygen
- Nitrogen
- Carbon Dioxide
- Nitrous Oxide
- Nothing
-
- Set Flow Rate Limit:
- [src.set_flow_rate]L/s | Change
- Flow rate: [round(last_flow_rate, 0.1)]L/s
- "}
-
- user << browse("[src.name] control[dat]", "window=atmo_filter")
- onclose(user, "atmo_filter")
- return
-
-/obj/machinery/atmospherics/trinary/filter/Topic(href, href_list) // -- TLE
- if(..())
- return 1
- usr.set_machine(src)
- src.add_fingerprint(usr)
- if(href_list["filterset"])
- filter_type = text2num(href_list["filterset"])
-
- filtered_out.Cut() //no need to create new lists unnecessarily
- switch(filter_type)
- if(0) //removing hydrocarbons
- filtered_out += "phoron"
- if(1) //removing O2
- filtered_out += "oxygen"
- if(2) //removing N2
- filtered_out += "nitrogen"
- if(3) //removing CO2
- filtered_out += "carbon_dioxide"
- if(4)//removing N2O
- filtered_out += "sleeping_agent"
-
- if (href_list["temp"])
- src.temp = null
- if(href_list["set_flow_rate"])
- var/new_flow_rate = input(usr,"Enter new flow rate (0-[air1.volume]L/s)","Flow Rate Control",src.set_flow_rate) as num
- src.set_flow_rate = max(0, min(air1.volume, new_flow_rate))
- if(href_list["power"])
- use_power=!use_power
- src.update_icon()
- src.updateUsrDialog()
-/*
- for(var/mob/M in viewers(1, src))
- if ((M.client && M.machine == src))
- src.attack_hand(M)
-*/
- return
-
-/obj/machinery/atmospherics/trinary/filter/m_filter
- icon_state = "mmap"
-
- dir = SOUTH
- initialize_directions = SOUTH|NORTH|EAST
-
-obj/machinery/atmospherics/trinary/filter/m_filter/Initialize()
- switch(dir)
- if(NORTH)
- initialize_directions = WEST|NORTH|SOUTH
- if(SOUTH)
- initialize_directions = SOUTH|EAST|NORTH
- if(EAST)
- initialize_directions = EAST|WEST|NORTH
- if(WEST)
- initialize_directions = WEST|SOUTH|EAST
- . = ..()
-
-/obj/machinery/atmospherics/trinary/filter/m_filter/atmos_init()
- set_frequency(frequency)
-
- if(node1 && node2 && node3) return
-
- var/node1_connect = turn(dir, -180)
- var/node2_connect = turn(dir, 90)
- var/node3_connect = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
- if(target.initialize_directions & get_dir(target,src))
- node1 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
- if(target.initialize_directions & get_dir(target,src))
- node2 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node3_connect))
- if(target.initialize_directions & get_dir(target,src))
- node3 = target
- break
-
- update_icon()
- update_underlays()
+/obj/machinery/atmospherics/trinary/filter
+ icon = 'icons/atmos/filter.dmi'
+ icon_state = "map"
+ density = 0
+ level = 1
+
+ name = "Gas filter"
+
+ use_power = 1
+ idle_power_usage = 150 //internal circuitry, friction losses and stuff
+ power_rating = 7500 //This also doubles as a measure of how powerful the filter is, in Watts. 7500 W ~ 10 HP
+
+ var/temp = null // -- TLE
+
+ var/set_flow_rate = ATMOS_DEFAULT_VOLUME_FILTER
+
+ /*
+ Filter types:
+ -1: Nothing
+ 0: Phoron: Phoron, Oxygen Agent B
+ 1: Oxygen: Oxygen ONLY
+ 2: Nitrogen: Nitrogen ONLY
+ 3: Carbon Dioxide: Carbon Dioxide ONLY
+ 4: Sleeping Agent (N2O)
+ */
+ var/filter_type = -1
+ var/list/filtered_out = list()
+
+
+ var/frequency = 0
+ var/datum/radio_frequency/radio_connection
+
+/obj/machinery/atmospherics/trinary/filter/proc/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ if(frequency)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
+
+/obj/machinery/atmospherics/trinary/filter/Initialize()
+ . = ..()
+ switch(filter_type)
+ if(0) //removing hydrocarbons
+ filtered_out = list("phoron")
+ if(1) //removing O2
+ filtered_out = list("oxygen")
+ if(2) //removing N2
+ filtered_out = list("nitrogen")
+ if(3) //removing CO2
+ filtered_out = list("carbon_dioxide")
+ if(4)//removing N2O
+ filtered_out = list("sleeping_agent")
+
+ air1.volume = ATMOS_DEFAULT_VOLUME_FILTER
+ air2.volume = ATMOS_DEFAULT_VOLUME_FILTER
+ air3.volume = ATMOS_DEFAULT_VOLUME_FILTER
+
+/obj/machinery/atmospherics/trinary/filter/update_icon()
+ if(istype(src, /obj/machinery/atmospherics/trinary/filter/m_filter))
+ icon_state = "m"
+ else
+ icon_state = ""
+
+ if(!powered())
+ icon_state += "off"
+ else if(node2 && node3 && node1)
+ icon_state += use_power ? "on" : "off"
+ else
+ icon_state += "off"
+ use_power = 0
+
+/obj/machinery/atmospherics/trinary/filter/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+
+ add_underlay(T, node1, turn(dir, -180))
+
+ if(istype(src, /obj/machinery/atmospherics/trinary/filter/m_filter))
+ add_underlay(T, node2, turn(dir, 90))
+ else
+ add_underlay(T, node2, turn(dir, -90))
+
+ add_underlay(T, node3, dir)
+
+/obj/machinery/atmospherics/trinary/filter/hide(var/i)
+ update_underlays()
+
+/obj/machinery/atmospherics/trinary/filter/power_change()
+ var/old_stat = stat
+ ..()
+ if(old_stat != stat)
+ update_icon()
+
+/obj/machinery/atmospherics/trinary/filter/machinery_process()
+ ..()
+
+ last_power_draw = 0
+ last_flow_rate = 0
+
+ if((stat & (NOPOWER|BROKEN)) || !use_power)
+ return
+
+ //Figure out the amount of moles to transfer
+ var/transfer_moles = (set_flow_rate/air1.volume)*air1.total_moles
+
+ var/power_draw = -1
+ if (transfer_moles > MINIMUM_MOLES_TO_FILTER)
+ power_draw = filter_gas(src, filtered_out, air1, air2, air3, transfer_moles, power_rating)
+
+ if(network2)
+ network2.update = 1
+
+ if(network3)
+ network3.update = 1
+
+ if(network1)
+ network1.update = 1
+
+ if (power_draw >= 0)
+ last_power_draw = power_draw
+ use_power(power_draw)
+
+ return 1
+
+/obj/machinery/atmospherics/trinary/filter/atmos_init()
+ set_frequency(frequency)
+ ..()
+
+/obj/machinery/atmospherics/trinary/filter/attackby(var/obj/item/W as obj, var/mob/user as mob)
+ if (!W.iswrench())
+ return ..()
+ var/datum/gas_mixture/int_air = return_air()
+ var/datum/gas_mixture/env_air = loc.return_air()
+ if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
+ to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
+ add_fingerprint(user)
+ return 1
+ playsound(src.loc, W.usesound, 50, 1)
+ to_chat(user, "You begin to unfasten \the [src]...")
+ if (do_after(user, 40/W.toolspeed, act_target = src))
+ user.visible_message( \
+ "\The [user] unfastens \the [src].", \
+ "You have unfastened \the [src].", \
+ "You hear a ratchet.")
+ new /obj/item/pipe(loc, make_from=src)
+ qdel(src)
+
+
+/obj/machinery/atmospherics/trinary/filter/attack_hand(user as mob) // -- TLE
+ if(..())
+ return
+
+ if(!src.allowed(user))
+ to_chat(user, "Access denied.")
+ return
+
+ var/dat
+ var/current_filter_type
+ switch(filter_type)
+ if(0)
+ current_filter_type = "Phoron"
+ if(1)
+ current_filter_type = "Oxygen"
+ if(2)
+ current_filter_type = "Nitrogen"
+ if(3)
+ current_filter_type = "Carbon Dioxide"
+ if(4)
+ current_filter_type = "Nitrous Oxide"
+ if(-1)
+ current_filter_type = "Nothing"
+ else
+ current_filter_type = "ERROR - Report this bug to the admin, please!"
+
+ dat += {"
+ Power: [use_power?"On":"Off"]
+ Filtering: [current_filter_type]
+ Set Filter Type:
+ Phoron
+ Oxygen
+ Nitrogen
+ Carbon Dioxide
+ Nitrous Oxide
+ Nothing
+
+ Set Flow Rate Limit:
+ [src.set_flow_rate]L/s | Change
+ Flow rate: [round(last_flow_rate, 0.1)]L/s
+ "}
+
+ user << browse("[src.name] control[dat]", "window=atmo_filter")
+ onclose(user, "atmo_filter")
+ return
+
+/obj/machinery/atmospherics/trinary/filter/Topic(href, href_list) // -- TLE
+ if(..())
+ return 1
+ usr.set_machine(src)
+ src.add_fingerprint(usr)
+ if(href_list["filterset"])
+ filter_type = text2num(href_list["filterset"])
+
+ filtered_out.Cut() //no need to create new lists unnecessarily
+ switch(filter_type)
+ if(0) //removing hydrocarbons
+ filtered_out += "phoron"
+ if(1) //removing O2
+ filtered_out += "oxygen"
+ if(2) //removing N2
+ filtered_out += "nitrogen"
+ if(3) //removing CO2
+ filtered_out += "carbon_dioxide"
+ if(4)//removing N2O
+ filtered_out += "sleeping_agent"
+
+ if (href_list["temp"])
+ src.temp = null
+ if(href_list["set_flow_rate"])
+ var/new_flow_rate = input(usr,"Enter new flow rate (0-[air1.volume]L/s)","Flow Rate Control",src.set_flow_rate) as num
+ src.set_flow_rate = max(0, min(air1.volume, new_flow_rate))
+ if(href_list["power"])
+ use_power=!use_power
+ src.update_icon()
+ src.updateUsrDialog()
+/*
+ for(var/mob/M in viewers(1, src))
+ if ((M.client && M.machine == src))
+ src.attack_hand(M)
+*/
+ return
+
+/obj/machinery/atmospherics/trinary/filter/m_filter
+ icon_state = "mmap"
+
+ dir = SOUTH
+ initialize_directions = SOUTH|NORTH|EAST
+
+obj/machinery/atmospherics/trinary/filter/m_filter/Initialize()
+ switch(dir)
+ if(NORTH)
+ initialize_directions = WEST|NORTH|SOUTH
+ if(SOUTH)
+ initialize_directions = SOUTH|EAST|NORTH
+ if(EAST)
+ initialize_directions = EAST|WEST|NORTH
+ if(WEST)
+ initialize_directions = WEST|SOUTH|EAST
+ . = ..()
+
+/obj/machinery/atmospherics/trinary/filter/m_filter/atmos_init()
+ set_frequency(frequency)
+
+ if(node1 && node2 && node3) return
+
+ var/node1_connect = turn(dir, -180)
+ var/node2_connect = turn(dir, 90)
+ var/node3_connect = dir
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ node1 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ node2 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node3_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ node3 = target
+ break
+
+ update_icon()
+ update_underlays()
diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
index e076eaf1dcf..350eb8a0a05 100644
--- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
@@ -1,276 +1,276 @@
-/obj/machinery/atmospherics/trinary/mixer
- icon = 'icons/atmos/mixer.dmi'
- icon_state = "map"
- density = 0
- level = 1
-
- name = "Gas mixer"
-
- use_power = 1
- idle_power_usage = 150 //internal circuitry, friction losses and stuff
- power_rating = 3700 //This also doubles as a measure of how powerful the mixer is, in Watts. 3700 W ~ 5 HP
-
- var/set_flow_rate = ATMOS_DEFAULT_VOLUME_MIXER
- var/list/mixing_inputs
-
- //for mapping
- var/node1_concentration = 0.5
- var/node2_concentration = 0.5
-
- //node 3 is the outlet, nodes 1 & 2 are intakes
-
-/obj/machinery/atmospherics/trinary/mixer/update_icon(var/safety = 0)
- if(istype(src, /obj/machinery/atmospherics/trinary/mixer/m_mixer))
- icon_state = "m"
- else if(istype(src, /obj/machinery/atmospherics/trinary/mixer/t_mixer))
- icon_state = "t"
- else
- icon_state = ""
-
- if(!powered())
- icon_state += "off"
- else if(node2 && node3 && node1)
- icon_state += use_power ? "on" : "off"
- else
- icon_state += "off"
- use_power = 0
-
-/obj/machinery/atmospherics/trinary/mixer/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
-
- if(istype(src, /obj/machinery/atmospherics/trinary/mixer/t_mixer))
- add_underlay(T, node1, turn(dir, -90))
- else
- add_underlay(T, node1, turn(dir, -180))
-
- if(istype(src, /obj/machinery/atmospherics/trinary/mixer/m_mixer) || istype(src, /obj/machinery/atmospherics/trinary/mixer/t_mixer))
- add_underlay(T, node2, turn(dir, 90))
- else
- add_underlay(T, node2, turn(dir, -90))
-
- add_underlay(T, node3, dir)
-
-/obj/machinery/atmospherics/trinary/mixer/hide(var/i)
- update_underlays()
-
-/obj/machinery/atmospherics/trinary/mixer/power_change()
- var/old_stat = stat
- ..()
- if(old_stat != stat)
- update_icon()
-
-/obj/machinery/atmospherics/trinary/mixer/Initialize()
- . = ..()
- air1.volume = ATMOS_DEFAULT_VOLUME_MIXER
- air2.volume = ATMOS_DEFAULT_VOLUME_MIXER
- air3.volume = ATMOS_DEFAULT_VOLUME_MIXER * 1.5
-
- if (!mixing_inputs)
- mixing_inputs = list(src.air1 = node1_concentration, src.air2 = node2_concentration)
-
-/obj/machinery/atmospherics/trinary/mixer/machinery_process()
- ..()
-
- last_power_draw = 0
- last_flow_rate = 0
-
- if((stat & (NOPOWER|BROKEN)) || !use_power)
- return
-
- //Figure out the amount of moles to transfer
- var/transfer_moles = (set_flow_rate*mixing_inputs[air1]/air1.volume)*air1.total_moles + (set_flow_rate*mixing_inputs[air1]/air2.volume)*air2.total_moles
-
- var/power_draw = -1
- if (transfer_moles > MINIMUM_MOLES_TO_FILTER)
- power_draw = mix_gas(src, mixing_inputs, air3, transfer_moles, power_rating)
-
- if(network1 && mixing_inputs[air1])
- network1.update = 1
-
- if(network2 && mixing_inputs[air2])
- network2.update = 1
-
- if(network3)
- network3.update = 1
-
- if (power_draw >= 0)
- last_power_draw = power_draw
- use_power(power_draw)
-
- return 1
-
-/obj/machinery/atmospherics/trinary/mixer/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
- if (!W.iswrench())
- return ..()
- var/datum/gas_mixture/int_air = return_air()
- var/datum/gas_mixture/env_air = loc.return_air()
- if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
- to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
- add_fingerprint(user)
- return 1
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
- if (do_after(user, 40, act_target = src))
- user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
- "You hear ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
-
-/obj/machinery/atmospherics/trinary/mixer/attack_hand(user as mob)
- if(..())
- return
- src.add_fingerprint(usr)
- if(!src.allowed(user))
- to_chat(user, "Access denied.")
- return
- usr.set_machine(src)
- var/dat = {"Power: [use_power?"On":"Off"]
- Set Flow Rate Limit:
- [set_flow_rate]L/s | Change
-
- Flow Rate: [round(last_flow_rate, 0.1)]L/s
-
- Node 1 Concentration:
- -
- -
- [mixing_inputs[air1]]([mixing_inputs[air1]*100]%)
- +
- +
-
- Node 2 Concentration:
- -
- -
- [mixing_inputs[air2]]([mixing_inputs[air2]*100]%)
- +
- +
- "}
-
- user << browse("[src.name] control[dat]", "window=atmo_mixer")
- onclose(user, "atmo_mixer")
- return
-
-/obj/machinery/atmospherics/trinary/mixer/Topic(href,href_list)
- if(..()) return 1
- if(href_list["power"])
- use_power = !use_power
- if(href_list["set_press"])
- var/max_flow_rate = min(air1.volume, air2.volume)
- var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",src.set_flow_rate) as num
- src.set_flow_rate = max(0, min(max_flow_rate, new_flow_rate))
- if(href_list["node1_c"])
- var/value = text2num(href_list["node1_c"])
- src.mixing_inputs[air1] = max(0, min(1, src.mixing_inputs[air1] + value))
- src.mixing_inputs[air2] = 1.0 - mixing_inputs[air1]
- if(href_list["node2_c"])
- var/value = text2num(href_list["node2_c"])
- src.mixing_inputs[air2] = max(0, min(1, src.mixing_inputs[air2] + value))
- src.mixing_inputs[air1] = 1.0 - mixing_inputs[air2]
- src.update_icon()
- src.updateUsrDialog()
- return
-
-obj/machinery/atmospherics/trinary/mixer/t_mixer
- icon_state = "tmap"
-
- dir = SOUTH
- initialize_directions = SOUTH|EAST|WEST
-
- //node 3 is the outlet, nodes 1 & 2 are intakes
-
-obj/machinery/atmospherics/trinary/mixer/t_mixer/north
- icon_state = "tmap"
-
- dir = NORTH
- initialize_directions = NORTH|EAST|WEST
-
- //node 3 is the outlet, nodes 1 & 2 are intakes
-
-obj/machinery/atmospherics/trinary/mixer/t_mixer/Initialize()
- switch(dir)
- if(NORTH)
- initialize_directions = EAST|NORTH|WEST
- if(SOUTH)
- initialize_directions = SOUTH|WEST|EAST
- if(EAST)
- initialize_directions = EAST|NORTH|SOUTH
- if(WEST)
- initialize_directions = WEST|NORTH|SOUTH
- . = ..()
-
-obj/machinery/atmospherics/trinary/mixer/t_mixer/atmos_init()
- ..()
- if(node1 && node2 && node3) return
-
- var/node1_connect = turn(dir, -90)
- var/node2_connect = turn(dir, 90)
- var/node3_connect = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
- if(target.initialize_directions & get_dir(target,src))
- node1 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
- if(target.initialize_directions & get_dir(target,src))
- node2 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node3_connect))
- if(target.initialize_directions & get_dir(target,src))
- node3 = target
- break
-
- update_icon()
- update_underlays()
-
-obj/machinery/atmospherics/trinary/mixer/m_mixer
- icon_state = "mmap"
-
- dir = SOUTH
- initialize_directions = SOUTH|NORTH|EAST
-
- //node 3 is the outlet, nodes 1 & 2 are intakes
-
-obj/machinery/atmospherics/trinary/mixer/m_mixer/Initialize()
- switch(dir)
- if(NORTH)
- initialize_directions = WEST|NORTH|SOUTH
- if(SOUTH)
- initialize_directions = SOUTH|EAST|NORTH
- if(EAST)
- initialize_directions = EAST|WEST|NORTH
- if(WEST)
- initialize_directions = WEST|SOUTH|EAST
- . = ..()
-
-obj/machinery/atmospherics/trinary/mixer/m_mixer/atmos_init()
- ..()
- if(node1 && node2 && node3) return
-
- var/node1_connect = turn(dir, -180)
- var/node2_connect = turn(dir, 90)
- var/node3_connect = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
- if(target.initialize_directions & get_dir(target,src))
- node1 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
- if(target.initialize_directions & get_dir(target,src))
- node2 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node3_connect))
- if(target.initialize_directions & get_dir(target,src))
- node3 = target
- break
-
- update_icon()
- update_underlays()
+/obj/machinery/atmospherics/trinary/mixer
+ icon = 'icons/atmos/mixer.dmi'
+ icon_state = "map"
+ density = 0
+ level = 1
+
+ name = "Gas mixer"
+
+ use_power = 1
+ idle_power_usage = 150 //internal circuitry, friction losses and stuff
+ power_rating = 3700 //This also doubles as a measure of how powerful the mixer is, in Watts. 3700 W ~ 5 HP
+
+ var/set_flow_rate = ATMOS_DEFAULT_VOLUME_MIXER
+ var/list/mixing_inputs
+
+ //for mapping
+ var/node1_concentration = 0.5
+ var/node2_concentration = 0.5
+
+ //node 3 is the outlet, nodes 1 & 2 are intakes
+
+/obj/machinery/atmospherics/trinary/mixer/update_icon(var/safety = 0)
+ if(istype(src, /obj/machinery/atmospherics/trinary/mixer/m_mixer))
+ icon_state = "m"
+ else if(istype(src, /obj/machinery/atmospherics/trinary/mixer/t_mixer))
+ icon_state = "t"
+ else
+ icon_state = ""
+
+ if(!powered())
+ icon_state += "off"
+ else if(node2 && node3 && node1)
+ icon_state += use_power ? "on" : "off"
+ else
+ icon_state += "off"
+ use_power = 0
+
+/obj/machinery/atmospherics/trinary/mixer/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+
+ if(istype(src, /obj/machinery/atmospherics/trinary/mixer/t_mixer))
+ add_underlay(T, node1, turn(dir, -90))
+ else
+ add_underlay(T, node1, turn(dir, -180))
+
+ if(istype(src, /obj/machinery/atmospherics/trinary/mixer/m_mixer) || istype(src, /obj/machinery/atmospherics/trinary/mixer/t_mixer))
+ add_underlay(T, node2, turn(dir, 90))
+ else
+ add_underlay(T, node2, turn(dir, -90))
+
+ add_underlay(T, node3, dir)
+
+/obj/machinery/atmospherics/trinary/mixer/hide(var/i)
+ update_underlays()
+
+/obj/machinery/atmospherics/trinary/mixer/power_change()
+ var/old_stat = stat
+ ..()
+ if(old_stat != stat)
+ update_icon()
+
+/obj/machinery/atmospherics/trinary/mixer/Initialize()
+ . = ..()
+ air1.volume = ATMOS_DEFAULT_VOLUME_MIXER
+ air2.volume = ATMOS_DEFAULT_VOLUME_MIXER
+ air3.volume = ATMOS_DEFAULT_VOLUME_MIXER * 1.5
+
+ if (!mixing_inputs)
+ mixing_inputs = list(src.air1 = node1_concentration, src.air2 = node2_concentration)
+
+/obj/machinery/atmospherics/trinary/mixer/machinery_process()
+ ..()
+
+ last_power_draw = 0
+ last_flow_rate = 0
+
+ if((stat & (NOPOWER|BROKEN)) || !use_power)
+ return
+
+ //Figure out the amount of moles to transfer
+ var/transfer_moles = (set_flow_rate*mixing_inputs[air1]/air1.volume)*air1.total_moles + (set_flow_rate*mixing_inputs[air1]/air2.volume)*air2.total_moles
+
+ var/power_draw = -1
+ if (transfer_moles > MINIMUM_MOLES_TO_FILTER)
+ power_draw = mix_gas(src, mixing_inputs, air3, transfer_moles, power_rating)
+
+ if(network1 && mixing_inputs[air1])
+ network1.update = 1
+
+ if(network2 && mixing_inputs[air2])
+ network2.update = 1
+
+ if(network3)
+ network3.update = 1
+
+ if (power_draw >= 0)
+ last_power_draw = power_draw
+ use_power(power_draw)
+
+ return 1
+
+/obj/machinery/atmospherics/trinary/mixer/attackby(var/obj/item/W as obj, var/mob/user as mob)
+ if (!W.iswrench())
+ return ..()
+ var/datum/gas_mixture/int_air = return_air()
+ var/datum/gas_mixture/env_air = loc.return_air()
+ if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
+ to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
+ add_fingerprint(user)
+ return 1
+ playsound(src.loc, W.usesound, 50, 1)
+ to_chat(user, "You begin to unfasten \the [src]...")
+ if (do_after(user, 40/W.toolspeed, act_target = src))
+ user.visible_message( \
+ "\The [user] unfastens \the [src].", \
+ "You have unfastened \the [src].", \
+ "You hear ratchet.")
+ new /obj/item/pipe(loc, make_from=src)
+ qdel(src)
+
+/obj/machinery/atmospherics/trinary/mixer/attack_hand(user as mob)
+ if(..())
+ return
+ src.add_fingerprint(usr)
+ if(!src.allowed(user))
+ to_chat(user, "Access denied.")
+ return
+ usr.set_machine(src)
+ var/dat = {"Power: [use_power?"On":"Off"]
+ Set Flow Rate Limit:
+ [set_flow_rate]L/s | Change
+
+ Flow Rate: [round(last_flow_rate, 0.1)]L/s
+
+ Node 1 Concentration:
+ -
+ -
+ [mixing_inputs[air1]]([mixing_inputs[air1]*100]%)
+ +
+ +
+
+ Node 2 Concentration:
+ -
+ -
+ [mixing_inputs[air2]]([mixing_inputs[air2]*100]%)
+ +
+ +
+ "}
+
+ user << browse("[src.name] control[dat]", "window=atmo_mixer")
+ onclose(user, "atmo_mixer")
+ return
+
+/obj/machinery/atmospherics/trinary/mixer/Topic(href,href_list)
+ if(..()) return 1
+ if(href_list["power"])
+ use_power = !use_power
+ if(href_list["set_press"])
+ var/max_flow_rate = min(air1.volume, air2.volume)
+ var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",src.set_flow_rate) as num
+ src.set_flow_rate = max(0, min(max_flow_rate, new_flow_rate))
+ if(href_list["node1_c"])
+ var/value = text2num(href_list["node1_c"])
+ src.mixing_inputs[air1] = max(0, min(1, src.mixing_inputs[air1] + value))
+ src.mixing_inputs[air2] = 1.0 - mixing_inputs[air1]
+ if(href_list["node2_c"])
+ var/value = text2num(href_list["node2_c"])
+ src.mixing_inputs[air2] = max(0, min(1, src.mixing_inputs[air2] + value))
+ src.mixing_inputs[air1] = 1.0 - mixing_inputs[air2]
+ src.update_icon()
+ src.updateUsrDialog()
+ return
+
+obj/machinery/atmospherics/trinary/mixer/t_mixer
+ icon_state = "tmap"
+
+ dir = SOUTH
+ initialize_directions = SOUTH|EAST|WEST
+
+ //node 3 is the outlet, nodes 1 & 2 are intakes
+
+obj/machinery/atmospherics/trinary/mixer/t_mixer/north
+ icon_state = "tmap"
+
+ dir = NORTH
+ initialize_directions = NORTH|EAST|WEST
+
+ //node 3 is the outlet, nodes 1 & 2 are intakes
+
+obj/machinery/atmospherics/trinary/mixer/t_mixer/Initialize()
+ switch(dir)
+ if(NORTH)
+ initialize_directions = EAST|NORTH|WEST
+ if(SOUTH)
+ initialize_directions = SOUTH|WEST|EAST
+ if(EAST)
+ initialize_directions = EAST|NORTH|SOUTH
+ if(WEST)
+ initialize_directions = WEST|NORTH|SOUTH
+ . = ..()
+
+obj/machinery/atmospherics/trinary/mixer/t_mixer/atmos_init()
+ ..()
+ if(node1 && node2 && node3) return
+
+ var/node1_connect = turn(dir, -90)
+ var/node2_connect = turn(dir, 90)
+ var/node3_connect = dir
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ node1 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ node2 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node3_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ node3 = target
+ break
+
+ update_icon()
+ update_underlays()
+
+obj/machinery/atmospherics/trinary/mixer/m_mixer
+ icon_state = "mmap"
+
+ dir = SOUTH
+ initialize_directions = SOUTH|NORTH|EAST
+
+ //node 3 is the outlet, nodes 1 & 2 are intakes
+
+obj/machinery/atmospherics/trinary/mixer/m_mixer/Initialize()
+ switch(dir)
+ if(NORTH)
+ initialize_directions = WEST|NORTH|SOUTH
+ if(SOUTH)
+ initialize_directions = SOUTH|EAST|NORTH
+ if(EAST)
+ initialize_directions = EAST|WEST|NORTH
+ if(WEST)
+ initialize_directions = WEST|SOUTH|EAST
+ . = ..()
+
+obj/machinery/atmospherics/trinary/mixer/m_mixer/atmos_init()
+ ..()
+ if(node1 && node2 && node3) return
+
+ var/node1_connect = turn(dir, -180)
+ var/node2_connect = turn(dir, 90)
+ var/node3_connect = dir
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ node1 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ node2 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node3_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ node3 = target
+ break
+
+ update_icon()
+ update_underlays()
diff --git a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm
index 4559adc7054..d3a3d93ed6d 100644
--- a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm
@@ -1,169 +1,169 @@
-obj/machinery/atmospherics/trinary
- dir = SOUTH
- initialize_directions = SOUTH|NORTH|WEST
- use_power = 0
-
- var/datum/gas_mixture/air1
- var/datum/gas_mixture/air2
- var/datum/gas_mixture/air3
-
- var/obj/machinery/atmospherics/node3
-
- var/datum/pipe_network/network1
- var/datum/pipe_network/network2
- var/datum/pipe_network/network3
-
- Initialize()
- switch(dir)
- if(NORTH)
- initialize_directions = EAST|NORTH|SOUTH
- if(SOUTH)
- initialize_directions = SOUTH|WEST|NORTH
- if(EAST)
- initialize_directions = EAST|WEST|SOUTH
- if(WEST)
- initialize_directions = WEST|NORTH|EAST
- air1 = new
- air2 = new
- air3 = new
-
- air1.volume = 200
- air2.volume = 200
- air3.volume = 200
- . = ..()
-
-// Housekeeping and pipe network stuff below
- network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
- if(reference == node1)
- network1 = new_network
-
- else if(reference == node2)
- network2 = new_network
-
- else if (reference == node3)
- network3 = new_network
-
- if(new_network.normal_members.Find(src))
- return 0
-
- new_network.normal_members += src
-
- return null
-
- Destroy()
- QDEL_NULL(air1)
- QDEL_NULL(air2)
- QDEL_NULL(air3)
-
- if(node1)
- node1.disconnect(src)
- QDEL_NULL(network1)
- if(node2)
- node2.disconnect(src)
- QDEL_NULL(network2)
- if(node3)
- node3.disconnect(src)
- QDEL_NULL(network3)
-
- node1 = null
- node2 = null
- node3 = null
-
- return ..()
-
- atmos_init()
- if(node1 && node2 && node3) return
-
- var/node1_connect = turn(dir, -180)
- var/node2_connect = turn(dir, -90)
- var/node3_connect = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node1 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node2 = target
- break
- for(var/obj/machinery/atmospherics/target in get_step(src,node3_connect))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node3 = target
- break
-
- update_icon()
- update_underlays()
-
- build_network()
- if(!network1 && node1)
- network1 = new /datum/pipe_network()
- network1.normal_members += src
- network1.build_network(node1, src)
-
- if(!network2 && node2)
- network2 = new /datum/pipe_network()
- network2.normal_members += src
- network2.build_network(node2, src)
-
- if(!network3 && node3)
- network3 = new /datum/pipe_network()
- network3.normal_members += src
- network3.build_network(node3, src)
-
-
- return_network(obj/machinery/atmospherics/reference)
- build_network()
-
- if(reference==node1)
- return network1
-
- if(reference==node2)
- return network2
-
- if(reference==node3)
- return network3
-
- return null
-
- reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
- if(network1 == old_network)
- network1 = new_network
- if(network2 == old_network)
- network2 = new_network
- if(network3 == old_network)
- network3 = new_network
-
- return 1
-
- return_network_air(datum/pipe_network/reference)
- var/list/results = list()
-
- if(network1 == reference)
- results += air1
- if(network2 == reference)
- results += air2
- if(network3 == reference)
- results += air3
-
- return results
-
- disconnect(obj/machinery/atmospherics/reference)
- if(reference==node1)
- qdel(network1)
- node1 = null
-
- else if(reference==node2)
- qdel(network2)
- node2 = null
-
- else if(reference==node3)
- qdel(network3)
- node3 = null
-
- update_underlays()
-
- return null
+obj/machinery/atmospherics/trinary
+ dir = SOUTH
+ initialize_directions = SOUTH|NORTH|WEST
+ use_power = 0
+
+ var/datum/gas_mixture/air1
+ var/datum/gas_mixture/air2
+ var/datum/gas_mixture/air3
+
+ var/obj/machinery/atmospherics/node3
+
+ var/datum/pipe_network/network1
+ var/datum/pipe_network/network2
+ var/datum/pipe_network/network3
+
+ Initialize()
+ switch(dir)
+ if(NORTH)
+ initialize_directions = EAST|NORTH|SOUTH
+ if(SOUTH)
+ initialize_directions = SOUTH|WEST|NORTH
+ if(EAST)
+ initialize_directions = EAST|WEST|SOUTH
+ if(WEST)
+ initialize_directions = WEST|NORTH|EAST
+ air1 = new
+ air2 = new
+ air3 = new
+
+ air1.volume = 200
+ air2.volume = 200
+ air3.volume = 200
+ . = ..()
+
+// Housekeeping and pipe network stuff below
+ network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
+ if(reference == node1)
+ network1 = new_network
+
+ else if(reference == node2)
+ network2 = new_network
+
+ else if (reference == node3)
+ network3 = new_network
+
+ if(new_network.normal_members.Find(src))
+ return 0
+
+ new_network.normal_members += src
+
+ return null
+
+ Destroy()
+ QDEL_NULL(air1)
+ QDEL_NULL(air2)
+ QDEL_NULL(air3)
+
+ if(node1)
+ node1.disconnect(src)
+ QDEL_NULL(network1)
+ if(node2)
+ node2.disconnect(src)
+ QDEL_NULL(network2)
+ if(node3)
+ node3.disconnect(src)
+ QDEL_NULL(network3)
+
+ node1 = null
+ node2 = null
+ node3 = null
+
+ return ..()
+
+ atmos_init()
+ if(node1 && node2 && node3) return
+
+ var/node1_connect = turn(dir, -180)
+ var/node2_connect = turn(dir, -90)
+ var/node3_connect = dir
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node1 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node2 = target
+ break
+ for(var/obj/machinery/atmospherics/target in get_step(src,node3_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node3 = target
+ break
+
+ update_icon()
+ update_underlays()
+
+ build_network()
+ if(!network1 && node1)
+ network1 = new /datum/pipe_network()
+ network1.normal_members += src
+ network1.build_network(node1, src)
+
+ if(!network2 && node2)
+ network2 = new /datum/pipe_network()
+ network2.normal_members += src
+ network2.build_network(node2, src)
+
+ if(!network3 && node3)
+ network3 = new /datum/pipe_network()
+ network3.normal_members += src
+ network3.build_network(node3, src)
+
+
+ return_network(obj/machinery/atmospherics/reference)
+ build_network()
+
+ if(reference==node1)
+ return network1
+
+ if(reference==node2)
+ return network2
+
+ if(reference==node3)
+ return network3
+
+ return null
+
+ reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
+ if(network1 == old_network)
+ network1 = new_network
+ if(network2 == old_network)
+ network2 = new_network
+ if(network3 == old_network)
+ network3 = new_network
+
+ return 1
+
+ return_network_air(datum/pipe_network/reference)
+ var/list/results = list()
+
+ if(network1 == reference)
+ results += air1
+ if(network2 == reference)
+ results += air2
+ if(network3 == reference)
+ results += air3
+
+ return results
+
+ disconnect(obj/machinery/atmospherics/reference)
+ if(reference==node1)
+ qdel(network1)
+ node1 = null
+
+ else if(reference==node2)
+ qdel(network2)
+ node2 = null
+
+ else if(reference==node3)
+ qdel(network3)
+ node3 = null
+
+ update_underlays()
+
+ return null
diff --git a/code/ATMOSPHERICS/components/tvalve.dm b/code/ATMOSPHERICS/components/tvalve.dm
index 4a567679f1a..ba56dcce33a 100644
--- a/code/ATMOSPHERICS/components/tvalve.dm
+++ b/code/ATMOSPHERICS/components/tvalve.dm
@@ -252,7 +252,7 @@
return 1
-/obj/machinery/atmospherics/tvalve/return_network_air(datum/network/reference)
+/obj/machinery/atmospherics/tvalve/return_network_air(datum/pipe_network/reference)
return null
/obj/machinery/atmospherics/tvalve/disconnect(obj/machinery/atmospherics/reference)
@@ -341,7 +341,7 @@
else
go_to_side()
-/obj/machinery/atmospherics/tvalve/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+/obj/machinery/atmospherics/tvalve/attackby(var/obj/item/W as obj, var/mob/user as mob)
if (!W.iswrench())
return ..()
if (istype(src, /obj/machinery/atmospherics/tvalve/digital))
@@ -353,9 +353,9 @@
to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
add_fingerprint(user)
return 1
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src.loc, W.usesound, 50, 1)
to_chat(user, "You begin to unfasten \the [src]...")
- if (do_after(user, 40, act_target = src))
+ if (do_after(user, 40/W.toolspeed, act_target = src))
user.visible_message( \
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
diff --git a/code/ATMOSPHERICS/components/unary/cold_sink.dm b/code/ATMOSPHERICS/components/unary/cold_sink.dm
index 0dbe652c39d..09588b2c4cc 100644
--- a/code/ATMOSPHERICS/components/unary/cold_sink.dm
+++ b/code/ATMOSPHERICS/components/unary/cold_sink.dm
@@ -1,186 +1,186 @@
-//TODO: Put this under a common parent type with heaters to cut down on the copypasta
-#define FREEZER_PERF_MULT 2.5
-
-/obj/machinery/atmospherics/unary/freezer
- name = "gas cooling system"
- desc = "Cools gas when connected to pipe network"
- icon = 'icons/obj/Cryogenic2.dmi'
- icon_state = "freezer_0"
- density = 1
- anchored = 1
- use_power = 0
- idle_power_usage = 5 // 5 Watts for thermostat related circuitry
-
- var/heatsink_temperature = T20C // The constant temperature reservoir into which the freezer pumps heat. Probably the hull of the station or something.
- var/internal_volume = 600 // L
-
- var/max_power_rating = 20000 // Power rating when the usage is turned up to 100
- var/power_setting = 100
-
- var/set_temperature = T20C // Thermostat
- var/cooling = 0
-
- component_types = list(
- /obj/item/weapon/circuitboard/unary_atmos/cooler,
- /obj/item/weapon/stock_parts/matter_bin,
- /obj/item/weapon/stock_parts/capacitor = 2,
- /obj/item/weapon/stock_parts/manipulator,
- /obj/item/stack/cable_coil{amount = 2}
- )
-
-/obj/machinery/atmospherics/unary/freezer/Initialize()
- initialize_directions = dir
- . = ..()
-
-/obj/machinery/atmospherics/unary/freezer/atmos_init()
- if(node)
- return
-
- var/node_connect = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src, node_connect))
- if(target.initialize_directions & get_dir(target, src))
- node = target
- break
-
- //copied from pipe construction code since heaters/freezers don't use fittings and weren't doing this check - this all really really needs to be refactored someday.
- //check that there are no incompatible pipes/machinery in our own location
- for(var/obj/machinery/atmospherics/M in src.loc)
- if(M != src && (M.initialize_directions & node_connect) && M.check_connect_types(M,src)) // matches at least one direction on either type of pipe & same connection type
- node = null
- break
-
- update_icon()
-
-/obj/machinery/atmospherics/unary/freezer/update_icon()
- if(node)
- if(use_power && cooling)
- icon_state = "freezer_1"
- else
- icon_state = "freezer"
- else
- icon_state = "freezer_0"
- return
-
-/obj/machinery/atmospherics/unary/freezer/attack_ai(mob/user as mob)
- ui_interact(user)
-
-/obj/machinery/atmospherics/unary/freezer/attack_hand(mob/user as mob)
- ui_interact(user)
-
-/obj/machinery/atmospherics/unary/freezer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
- // this is the data which will be sent to the ui
- var/data[0]
- data["on"] = use_power ? 1 : 0
- data["gasPressure"] = round(air_contents.return_pressure())
- data["gasTemperature"] = round(air_contents.temperature)
- data["minGasTemperature"] = 0
- data["maxGasTemperature"] = round(T20C+500)
- data["targetGasTemperature"] = round(set_temperature)
- data["powerSetting"] = power_setting
-
- var/temp_class = "good"
- if(air_contents.temperature > (T0C - 20))
- temp_class = "bad"
- else if(air_contents.temperature < (T0C - 20) && air_contents.temperature > (T0C - 100))
- temp_class = "average"
- data["gasTemperatureClass"] = temp_class
-
- // update the ui if it exists, returns null if no ui is passed/found
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if(!ui)
- // the ui does not exist, so we'll create a new() one
- // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
- ui = new(user, src, ui_key, "freezer.tmpl", "Gas Cooling System", 440, 300)
- // when the ui is first opened this is the data it will use
- ui.set_initial_data(data)
- // open the new ui window
- ui.open()
- // auto update every Master Controller tick
- ui.set_auto_update(1)
-
-/obj/machinery/atmospherics/unary/freezer/Topic(href, href_list)
- if(..())
- return 1
- if(href_list["toggleStatus"])
- use_power = !use_power
- update_icon()
- if(href_list["temp"])
- var/amount = text2num(href_list["temp"])
- if(amount > 0)
- set_temperature = min(set_temperature + amount, 1000)
- else
- set_temperature = max(set_temperature + amount, 0)
- if(href_list["setPower"]) //setting power to 0 is redundant anyways
- var/new_setting = between(0, text2num(href_list["setPower"]), 100)
- set_power_level(new_setting)
-
- add_fingerprint(usr)
-
-/obj/machinery/atmospherics/unary/freezer/machinery_process()
- ..()
-
- if(stat & (NOPOWER|BROKEN) || !use_power)
- cooling = 0
- update_icon()
- return
-
- if(network && air_contents.temperature > set_temperature)
- cooling = 1
-
- var/heat_transfer = max( -air_contents.get_thermal_energy_change(set_temperature - 5), 0 )
-
- //Assume the heat is being pumped into the hull which is fixed at heatsink_temperature
- //not /really/ proper thermodynamics but whatever
- var/cop = FREEZER_PERF_MULT * air_contents.temperature/heatsink_temperature //heatpump coefficient of performance from thermodynamics -> power used = heat_transfer/cop
- heat_transfer = min(heat_transfer, cop * power_rating) //limit heat transfer by available power
-
- var/removed = -air_contents.add_thermal_energy(-heat_transfer) //remove the heat
- if(debug)
- visible_message("[src]: Removing [removed] W.")
-
- use_power(power_rating)
-
- network.update = 1
- else
- cooling = 0
-
- update_icon()
-
-//upgrading parts
-/obj/machinery/atmospherics/unary/freezer/RefreshParts()
- ..()
- var/cap_rating = 0
- var/manip_rating = 0
- var/bin_rating = 0
- for(var/obj/item/weapon/stock_parts/P in component_parts)
- if(iscapacitor(P))
- cap_rating += P.rating
- else if(ismanipulator(P))
- manip_rating += P.rating
- else if(ismatterbin(P))
- bin_rating += P.rating
-
- power_rating = initial(power_rating) * cap_rating / 2 //more powerful
- heatsink_temperature = initial(heatsink_temperature) / ((manip_rating + bin_rating) / 2) //more efficient
- air_contents.volume = max(initial(internal_volume) - 200, 0) + 200 * bin_rating
- set_power_level(power_setting)
-
-/obj/machinery/atmospherics/unary/freezer/proc/set_power_level(var/new_power_setting)
- power_setting = new_power_setting
- power_rating = max_power_rating * (power_setting/100)
-
-/obj/machinery/atmospherics/unary/freezer/attackby(var/obj/item/O as obj, var/mob/user as mob)
- if(default_deconstruction_screwdriver(user, O))
- return
- if(default_deconstruction_crowbar(user, O))
- return
- if(default_part_replacement(user, O))
- return
-
- ..()
-
-/obj/machinery/atmospherics/unary/freezer/examine(mob/user)
- ..(user)
- if(panel_open)
- to_chat(user, "The maintenance hatch is open.")
+//TODO: Put this under a common parent type with heaters to cut down on the copypasta
+#define FREEZER_PERF_MULT 2.5
+
+/obj/machinery/atmospherics/unary/freezer
+ name = "gas cooling system"
+ desc = "Cools gas when connected to pipe network"
+ icon = 'icons/obj/sleeper.dmi'
+ icon_state = "freezer_0"
+ density = 1
+ anchored = 1
+ use_power = 0
+ idle_power_usage = 5 // 5 Watts for thermostat related circuitry
+
+ var/heatsink_temperature = T20C // The constant temperature reservoir into which the freezer pumps heat. Probably the hull of the station or something.
+ var/internal_volume = 600 // L
+
+ var/max_power_rating = 20000 // Power rating when the usage is turned up to 100
+ var/power_setting = 100
+
+ var/set_temperature = T20C // Thermostat
+ var/cooling = 0
+
+ component_types = list(
+ /obj/item/circuitboard/unary_atmos/cooler,
+ /obj/item/stock_parts/matter_bin,
+ /obj/item/stock_parts/capacitor = 2,
+ /obj/item/stock_parts/manipulator,
+ /obj/item/stack/cable_coil{amount = 2}
+ )
+
+/obj/machinery/atmospherics/unary/freezer/Initialize()
+ initialize_directions = dir
+ . = ..()
+
+/obj/machinery/atmospherics/unary/freezer/atmos_init()
+ if(node)
+ return
+
+ var/node_connect = dir
+
+ for(var/obj/machinery/atmospherics/target in get_step(src, node_connect))
+ if(target.initialize_directions & get_dir(target, src))
+ node = target
+ break
+
+ //copied from pipe construction code since heaters/freezers don't use fittings and weren't doing this check - this all really really needs to be refactored someday.
+ //check that there are no incompatible pipes/machinery in our own location
+ for(var/obj/machinery/atmospherics/M in src.loc)
+ if(M != src && (M.initialize_directions & node_connect) && M.check_connect_types(M,src)) // matches at least one direction on either type of pipe & same connection type
+ node = null
+ break
+
+ update_icon()
+
+/obj/machinery/atmospherics/unary/freezer/update_icon()
+ if(node)
+ if(use_power && cooling)
+ icon_state = "freezer_1"
+ else
+ icon_state = "freezer"
+ else
+ icon_state = "freezer_0"
+ return
+
+/obj/machinery/atmospherics/unary/freezer/attack_ai(mob/user as mob)
+ ui_interact(user)
+
+/obj/machinery/atmospherics/unary/freezer/attack_hand(mob/user as mob)
+ ui_interact(user)
+
+/obj/machinery/atmospherics/unary/freezer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ // this is the data which will be sent to the ui
+ var/data[0]
+ data["on"] = use_power ? 1 : 0
+ data["gasPressure"] = round(air_contents.return_pressure())
+ data["gasTemperature"] = round(air_contents.temperature)
+ data["minGasTemperature"] = 0
+ data["maxGasTemperature"] = round(T20C+500)
+ data["targetGasTemperature"] = round(set_temperature)
+ data["powerSetting"] = power_setting
+
+ var/temp_class = "good"
+ if(air_contents.temperature > (T0C - 20))
+ temp_class = "bad"
+ else if(air_contents.temperature < (T0C - 20) && air_contents.temperature > (T0C - 100))
+ temp_class = "average"
+ data["gasTemperatureClass"] = temp_class
+
+ // update the ui if it exists, returns null if no ui is passed/found
+ ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if(!ui)
+ // the ui does not exist, so we'll create a new() one
+ // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
+ ui = new(user, src, ui_key, "freezer.tmpl", "Gas Cooling System", 440, 300)
+ // when the ui is first opened this is the data it will use
+ ui.set_initial_data(data)
+ // open the new ui window
+ ui.open()
+ // auto update every Master Controller tick
+ ui.set_auto_update(1)
+
+/obj/machinery/atmospherics/unary/freezer/Topic(href, href_list)
+ if(..())
+ return 1
+ if(href_list["toggleStatus"])
+ use_power = !use_power
+ update_icon()
+ if(href_list["temp"])
+ var/amount = text2num(href_list["temp"])
+ if(amount > 0)
+ set_temperature = min(set_temperature + amount, 1000)
+ else
+ set_temperature = max(set_temperature + amount, 0)
+ if(href_list["setPower"]) //setting power to 0 is redundant anyways
+ var/new_setting = between(0, text2num(href_list["setPower"]), 100)
+ set_power_level(new_setting)
+
+ add_fingerprint(usr)
+
+/obj/machinery/atmospherics/unary/freezer/machinery_process()
+ ..()
+
+ if(stat & (NOPOWER|BROKEN) || !use_power)
+ cooling = 0
+ update_icon()
+ return
+
+ if(network && air_contents.temperature > set_temperature)
+ cooling = 1
+
+ var/heat_transfer = max( -air_contents.get_thermal_energy_change(set_temperature - 5), 0 )
+
+ //Assume the heat is being pumped into the hull which is fixed at heatsink_temperature
+ //not /really/ proper thermodynamics but whatever
+ var/cop = FREEZER_PERF_MULT * air_contents.temperature/heatsink_temperature //heatpump coefficient of performance from thermodynamics -> power used = heat_transfer/cop
+ heat_transfer = min(heat_transfer, cop * power_rating) //limit heat transfer by available power
+
+ var/removed = -air_contents.add_thermal_energy(-heat_transfer) //remove the heat
+ if(debug)
+ visible_message("[src]: Removing [removed] W.")
+
+ use_power(power_rating)
+
+ network.update = 1
+ else
+ cooling = 0
+
+ update_icon()
+
+//upgrading parts
+/obj/machinery/atmospherics/unary/freezer/RefreshParts()
+ ..()
+ var/cap_rating = 0
+ var/manip_rating = 0
+ var/bin_rating = 0
+ for(var/obj/item/stock_parts/P in component_parts)
+ if(iscapacitor(P))
+ cap_rating += P.rating
+ else if(ismanipulator(P))
+ manip_rating += P.rating
+ else if(ismatterbin(P))
+ bin_rating += P.rating
+
+ power_rating = initial(power_rating) * cap_rating / 2 //more powerful
+ heatsink_temperature = initial(heatsink_temperature) / ((manip_rating + bin_rating) / 2) //more efficient
+ air_contents.volume = max(initial(internal_volume) - 200, 0) + 200 * bin_rating
+ set_power_level(power_setting)
+
+/obj/machinery/atmospherics/unary/freezer/proc/set_power_level(var/new_power_setting)
+ power_setting = new_power_setting
+ power_rating = max_power_rating * (power_setting/100)
+
+/obj/machinery/atmospherics/unary/freezer/attackby(var/obj/item/O as obj, var/mob/user as mob)
+ if(default_deconstruction_screwdriver(user, O))
+ return
+ if(default_deconstruction_crowbar(user, O))
+ return
+ if(default_part_replacement(user, O))
+ return
+
+ ..()
+
+/obj/machinery/atmospherics/unary/freezer/examine(mob/user)
+ ..(user)
+ if(panel_open)
+ to_chat(user, "The maintenance hatch is open.")
diff --git a/code/ATMOSPHERICS/components/unary/generator_input.dm b/code/ATMOSPHERICS/components/unary/generator_input.dm
index 2b31097dc41..3a4d11428bb 100644
--- a/code/ATMOSPHERICS/components/unary/generator_input.dm
+++ b/code/ATMOSPHERICS/components/unary/generator_input.dm
@@ -1,21 +1,21 @@
-/obj/machinery/atmospherics/unary/generator_input
- icon = 'icons/obj/atmospherics/heat_exchanger.dmi'
- icon_state = "intact"
- density = 1
-
- name = "Generator Input"
- desc = "Placeholder"
-
- var/update_cycle
-
- update_icon()
- if(node)
- icon_state = "intact"
- else
- icon_state = "exposed"
-
- return
-
- proc
- return_exchange_air()
+/obj/machinery/atmospherics/unary/generator_input
+ icon = 'icons/obj/atmospherics/heat_exchanger.dmi'
+ icon_state = "intact"
+ density = 1
+
+ name = "Generator Input"
+ desc = "Placeholder"
+
+ var/update_cycle
+
+ update_icon()
+ if(node)
+ icon_state = "intact"
+ else
+ icon_state = "exposed"
+
+ return
+
+ proc
+ return_exchange_air()
return air_contents
\ No newline at end of file
diff --git a/code/ATMOSPHERICS/components/unary/heat_exchanger.dm b/code/ATMOSPHERICS/components/unary/heat_exchanger.dm
index 7e92d8b0041..67461129228 100644
--- a/code/ATMOSPHERICS/components/unary/heat_exchanger.dm
+++ b/code/ATMOSPHERICS/components/unary/heat_exchanger.dm
@@ -1,89 +1,89 @@
-/obj/machinery/atmospherics/unary/heat_exchanger
-
- icon = 'icons/obj/atmospherics/heat_exchanger.dmi'
- icon_state = "intact"
- density = 1
-
- name = "Heat Exchanger"
- desc = "Exchanges heat between two input gases. Setup for fast heat transfer"
-
- var/obj/machinery/atmospherics/unary/heat_exchanger/partner = null
- var/update_cycle
-
- update_icon()
- if(node)
- icon_state = "intact"
- else
- icon_state = "exposed"
-
- return
-
- atmos_init()
- if(!partner)
- var/partner_connect = turn(dir,180)
-
- for(var/obj/machinery/atmospherics/unary/heat_exchanger/target in get_step(src,partner_connect))
- if(target.dir & get_dir(src,target))
- partner = target
- partner.partner = src
- break
-
- ..()
-
- machinery_process()
- ..()
- if(QDELETED(partner))
- return 0
-
- if(!SSair || SSair.times_fired <= update_cycle)
- return 0
-
- update_cycle = SSair.times_fired
- partner.update_cycle = SSair.times_fired
-
- var/air_heat_capacity = air_contents.heat_capacity()
- var/other_air_heat_capacity = partner.air_contents.heat_capacity()
- var/combined_heat_capacity = other_air_heat_capacity + air_heat_capacity
-
- var/old_temperature = air_contents.temperature
- var/other_old_temperature = partner.air_contents.temperature
-
- if(combined_heat_capacity > 0)
- var/combined_energy = partner.air_contents.temperature*other_air_heat_capacity + air_heat_capacity*air_contents.temperature
-
- var/new_temperature = combined_energy/combined_heat_capacity
- air_contents.temperature = new_temperature
- partner.air_contents.temperature = new_temperature
-
- if(network)
- if(abs(old_temperature-air_contents.temperature) > 1)
- network.update = 1
-
- if(partner.network)
- if(abs(other_old_temperature-partner.air_contents.temperature) > 1)
- partner.network.update = 1
-
- return 1
-
- attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
- if (!W.iswrench())
- return ..()
- var/turf/T = src.loc
- if (level==1 && isturf(T) && !T.is_plating())
- to_chat(user, "You must remove the plating first.")
- return 1
- var/datum/gas_mixture/int_air = return_air()
- var/datum/gas_mixture/env_air = loc.return_air()
- if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
- to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
- add_fingerprint(user)
- return 1
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
- if (do_after(user, 40, act_target = src))
- user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
- "You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
+/obj/machinery/atmospherics/unary/heat_exchanger
+
+ icon = 'icons/obj/atmospherics/heat_exchanger.dmi'
+ icon_state = "intact"
+ density = 1
+
+ name = "Heat Exchanger"
+ desc = "Exchanges heat between two input gases. Setup for fast heat transfer"
+
+ var/obj/machinery/atmospherics/unary/heat_exchanger/partner = null
+ var/update_cycle
+
+ update_icon()
+ if(node)
+ icon_state = "intact"
+ else
+ icon_state = "exposed"
+
+ return
+
+ atmos_init()
+ if(!partner)
+ var/partner_connect = turn(dir,180)
+
+ for(var/obj/machinery/atmospherics/unary/heat_exchanger/target in get_step(src,partner_connect))
+ if(target.dir & get_dir(src,target))
+ partner = target
+ partner.partner = src
+ break
+
+ ..()
+
+ machinery_process()
+ ..()
+ if(QDELETED(partner))
+ return 0
+
+ if(!SSair || SSair.times_fired <= update_cycle)
+ return 0
+
+ update_cycle = SSair.times_fired
+ partner.update_cycle = SSair.times_fired
+
+ var/air_heat_capacity = air_contents.heat_capacity()
+ var/other_air_heat_capacity = partner.air_contents.heat_capacity()
+ var/combined_heat_capacity = other_air_heat_capacity + air_heat_capacity
+
+ var/old_temperature = air_contents.temperature
+ var/other_old_temperature = partner.air_contents.temperature
+
+ if(combined_heat_capacity > 0)
+ var/combined_energy = partner.air_contents.temperature*other_air_heat_capacity + air_heat_capacity*air_contents.temperature
+
+ var/new_temperature = combined_energy/combined_heat_capacity
+ air_contents.temperature = new_temperature
+ partner.air_contents.temperature = new_temperature
+
+ if(network)
+ if(abs(old_temperature-air_contents.temperature) > 1)
+ network.update = 1
+
+ if(partner.network)
+ if(abs(other_old_temperature-partner.air_contents.temperature) > 1)
+ partner.network.update = 1
+
+ return 1
+
+ attackby(var/obj/item/W as obj, var/mob/user as mob)
+ if (!W.iswrench())
+ return ..()
+ var/turf/T = src.loc
+ if (level==1 && isturf(T) && !T.is_plating())
+ to_chat(user, "You must remove the plating first.")
+ return 1
+ var/datum/gas_mixture/int_air = return_air()
+ var/datum/gas_mixture/env_air = loc.return_air()
+ if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
+ to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
+ add_fingerprint(user)
+ return 1
+ playsound(src.loc, W.usesound, 50, 1)
+ to_chat(user, "You begin to unfasten \the [src]...")
+ if (do_after(user, 40/W.toolspeed, act_target = src))
+ user.visible_message( \
+ "\The [user] unfastens \the [src].", \
+ "You have unfastened \the [src].", \
+ "You hear a ratchet.")
+ new /obj/item/pipe(loc, make_from=src)
+ qdel(src)
diff --git a/code/ATMOSPHERICS/components/unary/heat_source.dm b/code/ATMOSPHERICS/components/unary/heat_source.dm
index 4f324a717e0..a44d857d7a1 100644
--- a/code/ATMOSPHERICS/components/unary/heat_source.dm
+++ b/code/ATMOSPHERICS/components/unary/heat_source.dm
@@ -1,172 +1,172 @@
-//TODO: Put this under a common parent type with freezers to cut down on the copypasta
-#define HEATER_PERF_MULT 2.5
-
-/obj/machinery/atmospherics/unary/heater
- name = "gas heating system"
- desc = "Heats gas when connected to a pipe network"
- icon = 'icons/obj/Cryogenic2.dmi'
- icon_state = "heater_0"
- density = 1
- anchored = 1
- use_power = 0
- idle_power_usage = 5 //5 Watts for thermostat related circuitry
-
- var/max_temperature = T20C + 680
- var/internal_volume = 600 //L
-
- var/max_power_rating = 20000 //power rating when the usage is turned up to 100
- var/power_setting = 100
-
- var/set_temperature = T20C //thermostat
- var/heating = 0 //mainly for icon updates
-
- component_types = list(
- /obj/item/weapon/circuitboard/unary_atmos/heater,
- /obj/item/weapon/stock_parts/matter_bin,
- /obj/item/weapon/stock_parts/capacitor = 2,
- /obj/item/stack/cable_coil{amount = 5}
- )
-
-/obj/machinery/atmospherics/unary/heater/Initialize()
- initialize_directions = dir
- . = ..()
-
-/obj/machinery/atmospherics/unary/heater/atmos_init()
- if(node)
- return
-
- var/node_connect = dir
-
- //check that there is something to connect to
- for(var/obj/machinery/atmospherics/target in get_step(src, node_connect))
- if(target.initialize_directions & get_dir(target, src))
- node = target
- break
-
- //copied from pipe construction code since heaters/freezers don't use fittings and weren't doing this check - this all really really needs to be refactored someday.
- //check that there are no incompatible pipes/machinery in our own location
- for(var/obj/machinery/atmospherics/M in src.loc)
- if(M != src && (M.initialize_directions & node_connect) && M.check_connect_types(M,src)) // matches at least one direction on either type of pipe & same connection type
- node = null
- break
-
- update_icon()
-
-
-/obj/machinery/atmospherics/unary/heater/update_icon()
- if(node)
- if(use_power && heating)
- icon_state = "heater_1"
- else
- icon_state = "heater"
- else
- icon_state = "heater_0"
- return
-
-
-/obj/machinery/atmospherics/unary/heater/machinery_process()
- ..()
-
- if(stat & (NOPOWER|BROKEN) || !use_power)
- heating = 0
- update_icon()
- return
-
- if(network && air_contents.total_moles && air_contents.temperature < set_temperature)
- air_contents.add_thermal_energy(power_rating * HEATER_PERF_MULT)
- use_power(power_rating)
-
- heating = 1
- network.update = 1
- else
- heating = 0
-
- update_icon()
-
-/obj/machinery/atmospherics/unary/heater/attack_ai(mob/user as mob)
- ui_interact(user)
-
-/obj/machinery/atmospherics/unary/heater/attack_hand(mob/user as mob)
- ui_interact(user)
-
-/obj/machinery/atmospherics/unary/heater/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
- // this is the data which will be sent to the ui
- var/data[0]
- data["on"] = use_power ? 1 : 0
- data["gasPressure"] = round(air_contents.return_pressure())
- data["gasTemperature"] = round(air_contents.temperature)
- data["minGasTemperature"] = 0
- data["maxGasTemperature"] = round(max_temperature)
- data["targetGasTemperature"] = round(set_temperature)
- data["powerSetting"] = power_setting
-
- var/temp_class = "normal"
- if(air_contents.temperature > (T20C+40))
- temp_class = "bad"
- data["gasTemperatureClass"] = temp_class
-
- // update the ui if it exists, returns null if no ui is passed/found
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if(!ui)
- // the ui does not exist, so we'll create a new() one
- // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
- ui = new(user, src, ui_key, "freezer.tmpl", "Gas Heating System", 440, 300)
- // when the ui is first opened this is the data it will use
- ui.set_initial_data(data)
- // open the new ui window
- ui.open()
- // auto update every Master Controller tick
- ui.set_auto_update(1)
-
-/obj/machinery/atmospherics/unary/heater/Topic(href, href_list)
- if(..())
- return 1
- if(href_list["toggleStatus"])
- use_power = !use_power
- update_icon()
- if(href_list["temp"])
- var/amount = text2num(href_list["temp"])
- if(amount > 0)
- set_temperature = min(set_temperature + amount, max_temperature)
- else
- set_temperature = max(set_temperature + amount, 0)
- if(href_list["setPower"]) //setting power to 0 is redundant anyways
- var/new_setting = between(0, text2num(href_list["setPower"]), 100)
- set_power_level(new_setting)
-
- add_fingerprint(usr)
-
-//upgrading parts
-/obj/machinery/atmospherics/unary/heater/RefreshParts()
- ..()
- var/cap_rating = 0
- var/bin_rating = 0
- for(var/obj/item/weapon/stock_parts/P in component_parts)
- if(iscapacitor(P))
- cap_rating += P.rating
- else if(ismatterbin(P))
- bin_rating += P.rating
-
- max_power_rating = initial(max_power_rating) * cap_rating / 2
- max_temperature = max(initial(max_temperature) - T20C, 0) * ((bin_rating * 4 + cap_rating) / 5) + T20C
- air_contents.volume = max(initial(internal_volume) - 200, 0) + 200 * bin_rating
- set_power_level(power_setting)
-
-/obj/machinery/atmospherics/unary/heater/proc/set_power_level(var/new_power_setting)
- power_setting = new_power_setting
- power_rating = max_power_rating * (power_setting/100)
-
-/obj/machinery/atmospherics/unary/heater/attackby(var/obj/item/O as obj, var/mob/user as mob)
- if(default_deconstruction_screwdriver(user, O))
- return
- if(default_deconstruction_crowbar(user, O))
- return
- if(default_part_replacement(user, O))
- return
-
- ..()
-
-/obj/machinery/atmospherics/unary/heater/examine(mob/user)
- ..(user)
- if(panel_open)
- to_chat(user, "The maintenance hatch is open.")
+//TODO: Put this under a common parent type with freezers to cut down on the copypasta
+#define HEATER_PERF_MULT 2.5
+
+/obj/machinery/atmospherics/unary/heater
+ name = "gas heating system"
+ desc = "Heats gas when connected to a pipe network"
+ icon = 'icons/obj/sleeper.dmi'
+ icon_state = "heater_0"
+ density = 1
+ anchored = 1
+ use_power = 0
+ idle_power_usage = 5 //5 Watts for thermostat related circuitry
+
+ var/max_temperature = T20C + 680
+ var/internal_volume = 600 //L
+
+ var/max_power_rating = 20000 //power rating when the usage is turned up to 100
+ var/power_setting = 100
+
+ var/set_temperature = T20C //thermostat
+ var/heating = 0 //mainly for icon updates
+
+ component_types = list(
+ /obj/item/circuitboard/unary_atmos/heater,
+ /obj/item/stock_parts/matter_bin,
+ /obj/item/stock_parts/capacitor = 2,
+ /obj/item/stack/cable_coil{amount = 5}
+ )
+
+/obj/machinery/atmospherics/unary/heater/Initialize()
+ initialize_directions = dir
+ . = ..()
+
+/obj/machinery/atmospherics/unary/heater/atmos_init()
+ if(node)
+ return
+
+ var/node_connect = dir
+
+ //check that there is something to connect to
+ for(var/obj/machinery/atmospherics/target in get_step(src, node_connect))
+ if(target.initialize_directions & get_dir(target, src))
+ node = target
+ break
+
+ //copied from pipe construction code since heaters/freezers don't use fittings and weren't doing this check - this all really really needs to be refactored someday.
+ //check that there are no incompatible pipes/machinery in our own location
+ for(var/obj/machinery/atmospherics/M in src.loc)
+ if(M != src && (M.initialize_directions & node_connect) && M.check_connect_types(M,src)) // matches at least one direction on either type of pipe & same connection type
+ node = null
+ break
+
+ update_icon()
+
+
+/obj/machinery/atmospherics/unary/heater/update_icon()
+ if(node)
+ if(use_power && heating)
+ icon_state = "heater_1"
+ else
+ icon_state = "heater"
+ else
+ icon_state = "heater_0"
+ return
+
+
+/obj/machinery/atmospherics/unary/heater/machinery_process()
+ ..()
+
+ if(stat & (NOPOWER|BROKEN) || !use_power)
+ heating = 0
+ update_icon()
+ return
+
+ if(network && air_contents.total_moles && air_contents.temperature < set_temperature)
+ air_contents.add_thermal_energy(power_rating * HEATER_PERF_MULT)
+ use_power(power_rating)
+
+ heating = 1
+ network.update = 1
+ else
+ heating = 0
+
+ update_icon()
+
+/obj/machinery/atmospherics/unary/heater/attack_ai(mob/user as mob)
+ ui_interact(user)
+
+/obj/machinery/atmospherics/unary/heater/attack_hand(mob/user as mob)
+ ui_interact(user)
+
+/obj/machinery/atmospherics/unary/heater/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ // this is the data which will be sent to the ui
+ var/data[0]
+ data["on"] = use_power ? 1 : 0
+ data["gasPressure"] = round(air_contents.return_pressure())
+ data["gasTemperature"] = round(air_contents.temperature)
+ data["minGasTemperature"] = 0
+ data["maxGasTemperature"] = round(max_temperature)
+ data["targetGasTemperature"] = round(set_temperature)
+ data["powerSetting"] = power_setting
+
+ var/temp_class = "normal"
+ if(air_contents.temperature > (T20C+40))
+ temp_class = "bad"
+ data["gasTemperatureClass"] = temp_class
+
+ // update the ui if it exists, returns null if no ui is passed/found
+ ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if(!ui)
+ // the ui does not exist, so we'll create a new() one
+ // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
+ ui = new(user, src, ui_key, "freezer.tmpl", "Gas Heating System", 440, 300)
+ // when the ui is first opened this is the data it will use
+ ui.set_initial_data(data)
+ // open the new ui window
+ ui.open()
+ // auto update every Master Controller tick
+ ui.set_auto_update(1)
+
+/obj/machinery/atmospherics/unary/heater/Topic(href, href_list)
+ if(..())
+ return 1
+ if(href_list["toggleStatus"])
+ use_power = !use_power
+ update_icon()
+ if(href_list["temp"])
+ var/amount = text2num(href_list["temp"])
+ if(amount > 0)
+ set_temperature = min(set_temperature + amount, max_temperature)
+ else
+ set_temperature = max(set_temperature + amount, 0)
+ if(href_list["setPower"]) //setting power to 0 is redundant anyways
+ var/new_setting = between(0, text2num(href_list["setPower"]), 100)
+ set_power_level(new_setting)
+
+ add_fingerprint(usr)
+
+//upgrading parts
+/obj/machinery/atmospherics/unary/heater/RefreshParts()
+ ..()
+ var/cap_rating = 0
+ var/bin_rating = 0
+ for(var/obj/item/stock_parts/P in component_parts)
+ if(iscapacitor(P))
+ cap_rating += P.rating
+ else if(ismatterbin(P))
+ bin_rating += P.rating
+
+ max_power_rating = initial(max_power_rating) * cap_rating / 2
+ max_temperature = max(initial(max_temperature) - T20C, 0) * ((bin_rating * 4 + cap_rating) / 5) + T20C
+ air_contents.volume = max(initial(internal_volume) - 200, 0) + 200 * bin_rating
+ set_power_level(power_setting)
+
+/obj/machinery/atmospherics/unary/heater/proc/set_power_level(var/new_power_setting)
+ power_setting = new_power_setting
+ power_rating = max_power_rating * (power_setting/100)
+
+/obj/machinery/atmospherics/unary/heater/attackby(var/obj/item/O as obj, var/mob/user as mob)
+ if(default_deconstruction_screwdriver(user, O))
+ return
+ if(default_deconstruction_crowbar(user, O))
+ return
+ if(default_part_replacement(user, O))
+ return
+
+ ..()
+
+/obj/machinery/atmospherics/unary/heater/examine(mob/user)
+ ..(user)
+ if(panel_open)
+ to_chat(user, "The maintenance hatch is open.")
diff --git a/code/ATMOSPHERICS/components/unary/outlet_injector.dm b/code/ATMOSPHERICS/components/unary/outlet_injector.dm
index 1081a4b575e..5991c0fd9de 100644
--- a/code/ATMOSPHERICS/components/unary/outlet_injector.dm
+++ b/code/ATMOSPHERICS/components/unary/outlet_injector.dm
@@ -1,152 +1,152 @@
-//Basically a one way passive valve. If the pressure inside is greater than the environment then gas will flow passively,
-//but it does not permit gas to flow back from the environment into the injector. Can be turned off to prevent any gas flow.
-//When it receives the "inject" signal, it will try to pump it's entire contents into the environment regardless of pressure, using power.
-
-/obj/machinery/atmospherics/unary/outlet_injector
- icon = 'icons/atmos/injector.dmi'
- icon_state = "map_injector"
- layer = 3
-
- name = "air injector"
- desc = "Passively injects air into its surroundings. Has a valve attached to it that can control flow rate."
-
- use_power = 0
- idle_power_usage = 150 //internal circuitry, friction losses and stuff
- power_rating = 15000 //15000 W ~ 20 HP
-
- var/injecting = 0
-
- var/volume_rate = 50 //flow rate limit
-
- var/frequency = 0
- var/id = null
- var/datum/radio_frequency/radio_connection
-
- level = 1
-
-/obj/machinery/atmospherics/unary/outlet_injector/Initialize()
- . = ..()
- air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP + 500 //Give it a small reservoir for injecting. Also allows it to have a higher flow rate limit than vent pumps, to differentiate injectors a bit more.
-
-/obj/machinery/atmospherics/unary/outlet_injector/update_icon()
- if(!powered())
- icon_state = "off"
- else
- icon_state = "[use_power ? "on" : "off"]"
-
-/obj/machinery/atmospherics/unary/outlet_injector/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- add_underlay(T, node, dir)
-
-/obj/machinery/atmospherics/unary/outlet_injector/power_change()
- var/old_stat = stat
- ..()
- if(old_stat != stat)
- update_icon()
-
-/obj/machinery/atmospherics/unary/outlet_injector/machinery_process()
- ..()
-
- last_power_draw = 0
- last_flow_rate = 0
-
- if((stat & (NOPOWER|BROKEN)) || !use_power)
- return
-
- var/power_draw = -1
- var/datum/gas_mixture/environment = loc.return_air()
-
- if(environment && air_contents.temperature > 0)
- var/transfer_moles = (volume_rate/air_contents.volume)*air_contents.total_moles //apply flow rate limit
- power_draw = pump_gas(src, air_contents, environment, transfer_moles, power_rating)
-
- if (power_draw >= 0)
- last_power_draw = power_draw
- use_power(power_draw)
-
- if(network)
- network.update = 1
-
- return 1
-
-/obj/machinery/atmospherics/unary/outlet_injector/proc/inject()
- if(injecting || (stat & NOPOWER))
- return 0
-
- var/datum/gas_mixture/environment = loc.return_air()
- if (!environment)
- return 0
-
- injecting = 1
-
- if(air_contents.temperature > 0)
- var/power_used = pump_gas(src, air_contents, environment, air_contents.total_moles, power_rating)
- use_power(power_used)
-
- if(network)
- network.update = 1
-
- flick("inject", src)
-
-/obj/machinery/atmospherics/unary/outlet_injector/proc/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- if(frequency)
- radio_connection = SSradio.add_object(src, frequency)
-
-/obj/machinery/atmospherics/unary/outlet_injector/proc/broadcast_status()
- if(!radio_connection)
- return 0
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
- "tag" = id,
- "device" = "AO",
- "power" = use_power,
- "volume_rate" = volume_rate,
- "sigtype" = "status"
- )
-
- radio_connection.post_signal(src, signal)
-
- return 1
-
-/obj/machinery/atmospherics/unary/outlet_injector/atmos_init()
- ..()
-
- set_frequency(frequency)
-
-/obj/machinery/atmospherics/unary/outlet_injector/receive_signal(datum/signal/signal)
- if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
- return 0
-
- if(signal.data["power"])
- use_power = text2num(signal.data["power"])
-
- if(signal.data["power_toggle"])
- use_power = !use_power
-
- if(signal.data["inject"])
- spawn inject()
- return
-
- if(signal.data["set_volume_rate"])
- var/number = text2num(signal.data["set_volume_rate"])
- volume_rate = between(0, number, air_contents.volume)
-
- if(signal.data["status"])
- addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
- return //do not update_icon
-
- addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
- update_icon()
-
-/obj/machinery/atmospherics/unary/outlet_injector/hide(var/i)
- update_underlays()
+//Basically a one way passive valve. If the pressure inside is greater than the environment then gas will flow passively,
+//but it does not permit gas to flow back from the environment into the injector. Can be turned off to prevent any gas flow.
+//When it receives the "inject" signal, it will try to pump it's entire contents into the environment regardless of pressure, using power.
+
+/obj/machinery/atmospherics/unary/outlet_injector
+ icon = 'icons/atmos/injector.dmi'
+ icon_state = "map_injector"
+ layer = 3
+
+ name = "air injector"
+ desc = "Passively injects air into its surroundings. Has a valve attached to it that can control flow rate."
+
+ use_power = 0
+ idle_power_usage = 150 //internal circuitry, friction losses and stuff
+ power_rating = 15000 //15000 W ~ 20 HP
+
+ var/injecting = 0
+
+ var/volume_rate = 50 //flow rate limit
+
+ var/frequency = 0
+ var/id = null
+ var/datum/radio_frequency/radio_connection
+
+ level = 1
+
+/obj/machinery/atmospherics/unary/outlet_injector/Initialize()
+ . = ..()
+ air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP + 500 //Give it a small reservoir for injecting. Also allows it to have a higher flow rate limit than vent pumps, to differentiate injectors a bit more.
+
+/obj/machinery/atmospherics/unary/outlet_injector/update_icon()
+ if(!powered())
+ icon_state = "off"
+ else
+ icon_state = "[use_power ? "on" : "off"]"
+
+/obj/machinery/atmospherics/unary/outlet_injector/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ add_underlay(T, node, dir)
+
+/obj/machinery/atmospherics/unary/outlet_injector/power_change()
+ var/old_stat = stat
+ ..()
+ if(old_stat != stat)
+ update_icon()
+
+/obj/machinery/atmospherics/unary/outlet_injector/machinery_process()
+ ..()
+
+ last_power_draw = 0
+ last_flow_rate = 0
+
+ if((stat & (NOPOWER|BROKEN)) || !use_power)
+ return
+
+ var/power_draw = -1
+ var/datum/gas_mixture/environment = loc.return_air()
+
+ if(environment && air_contents.temperature > 0)
+ var/transfer_moles = (volume_rate/air_contents.volume)*air_contents.total_moles //apply flow rate limit
+ power_draw = pump_gas(src, air_contents, environment, transfer_moles, power_rating)
+
+ if (power_draw >= 0)
+ last_power_draw = power_draw
+ use_power(power_draw)
+
+ if(network)
+ network.update = 1
+
+ return 1
+
+/obj/machinery/atmospherics/unary/outlet_injector/proc/inject()
+ if(injecting || (stat & NOPOWER))
+ return 0
+
+ var/datum/gas_mixture/environment = loc.return_air()
+ if (!environment)
+ return 0
+
+ injecting = 1
+
+ if(air_contents.temperature > 0)
+ var/power_used = pump_gas(src, air_contents, environment, air_contents.total_moles, power_rating)
+ use_power(power_used)
+
+ if(network)
+ network.update = 1
+
+ flick("inject", src)
+
+/obj/machinery/atmospherics/unary/outlet_injector/proc/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ if(frequency)
+ radio_connection = SSradio.add_object(src, frequency)
+
+/obj/machinery/atmospherics/unary/outlet_injector/proc/broadcast_status()
+ if(!radio_connection)
+ return 0
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+
+ signal.data = list(
+ "tag" = id,
+ "device" = "AO",
+ "power" = use_power,
+ "volume_rate" = volume_rate,
+ "sigtype" = "status"
+ )
+
+ radio_connection.post_signal(src, signal)
+
+ return 1
+
+/obj/machinery/atmospherics/unary/outlet_injector/atmos_init()
+ ..()
+
+ set_frequency(frequency)
+
+/obj/machinery/atmospherics/unary/outlet_injector/receive_signal(datum/signal/signal)
+ if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
+ return 0
+
+ if(signal.data["power"])
+ use_power = text2num(signal.data["power"])
+
+ if(signal.data["power_toggle"])
+ use_power = !use_power
+
+ if(signal.data["inject"])
+ spawn inject()
+ return
+
+ if(signal.data["set_volume_rate"])
+ var/number = text2num(signal.data["set_volume_rate"])
+ volume_rate = between(0, number, air_contents.volume)
+
+ if(signal.data["status"])
+ addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
+ return //do not update_icon
+
+ addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
+ update_icon()
+
+/obj/machinery/atmospherics/unary/outlet_injector/hide(var/i)
+ update_underlays()
diff --git a/code/ATMOSPHERICS/components/unary/oxygen_generator.dm b/code/ATMOSPHERICS/components/unary/oxygen_generator.dm
index 3c48ed7d2ff..93207f310a7 100644
--- a/code/ATMOSPHERICS/components/unary/oxygen_generator.dm
+++ b/code/ATMOSPHERICS/components/unary/oxygen_generator.dm
@@ -1,48 +1,48 @@
-obj/machinery/atmospherics/unary/oxygen_generator
- icon = 'icons/obj/atmospherics/oxygen_generator.dmi'
- icon_state = "intact_off"
- density = 1
-
- name = "Oxygen Generator"
- desc = ""
-
- dir = SOUTH
- initialize_directions = SOUTH
-
- var/on = 0
-
- var/oxygen_content = 10
-
- update_icon()
- if(node)
- icon_state = "intact_[on?("on"):("off")]"
- else
- icon_state = "exposed_off"
-
- on = 0
-
- return
-
- Initialize()
- . = ..()
- air_contents.volume = 50
-
- machinery_process()
- ..()
- if(!on)
- return 0
-
- var/total_moles = air_contents.total_moles
-
- if(total_moles < oxygen_content)
- var/current_heat_capacity = air_contents.heat_capacity()
-
- var/added_oxygen = oxygen_content - total_moles
-
- air_contents.temperature = (current_heat_capacity*air_contents.temperature + 20*added_oxygen*T0C)/(current_heat_capacity+20*added_oxygen)
- air_contents.adjust_gas("oxygen", added_oxygen)
-
- if(network)
- network.update = 1
-
- return 1
+obj/machinery/atmospherics/unary/oxygen_generator
+ icon = 'icons/obj/atmospherics/oxygen_generator.dmi'
+ icon_state = "intact_off"
+ density = 1
+
+ name = "Oxygen Generator"
+ desc = ""
+
+ dir = SOUTH
+ initialize_directions = SOUTH
+
+ var/on = 0
+
+ var/oxygen_content = 10
+
+ update_icon()
+ if(node)
+ icon_state = "intact_[on?("on"):("off")]"
+ else
+ icon_state = "exposed_off"
+
+ on = 0
+
+ return
+
+ Initialize()
+ . = ..()
+ air_contents.volume = 50
+
+ machinery_process()
+ ..()
+ if(!on)
+ return 0
+
+ var/total_moles = air_contents.total_moles
+
+ if(total_moles < oxygen_content)
+ var/current_heat_capacity = air_contents.heat_capacity()
+
+ var/added_oxygen = oxygen_content - total_moles
+
+ air_contents.temperature = (current_heat_capacity*air_contents.temperature + 20*added_oxygen*T0C)/(current_heat_capacity+20*added_oxygen)
+ air_contents.adjust_gas("oxygen", added_oxygen)
+
+ if(network)
+ network.update = 1
+
+ return 1
diff --git a/code/ATMOSPHERICS/components/unary/unary_base.dm b/code/ATMOSPHERICS/components/unary/unary_base.dm
index e6681d010ca..1f232b1213a 100644
--- a/code/ATMOSPHERICS/components/unary/unary_base.dm
+++ b/code/ATMOSPHERICS/components/unary/unary_base.dm
@@ -1,102 +1,102 @@
-/obj/machinery/atmospherics/unary
- dir = SOUTH
- initialize_directions = SOUTH
- //layer = TURF_LAYER+0.1
-
- var/datum/gas_mixture/air_contents
-
- var/obj/machinery/atmospherics/node
-
- var/datum/pipe_network/network
-
- Initialize()
- initialize_directions = dir
- air_contents = new
- air_contents.volume = 200
- . = ..()
-
-// Housekeeping and pipe network stuff below
- network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
- if(reference == node)
- network = new_network
-
- if(new_network.normal_members.Find(src))
- return 0
-
- new_network.normal_members += src
-
- return null
-
- Destroy()
- QDEL_NULL(air_contents)
-
- if(node)
- node.disconnect(src)
- QDEL_NULL(network)
-
- node = null
-
- return ..()
-
- atmos_init()
- if(node) return
-
- var/node_connect = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node_connect))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node = target
- break
-
- update_icon()
- update_underlays()
-
- build_network()
- if(!network && node)
- network = new /datum/pipe_network()
- network.normal_members += src
- network.build_network(node, src)
-
-
- return_network(obj/machinery/atmospherics/reference)
- build_network()
-
- if(reference==node)
- return network
-
- return null
-
- reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
- if(network == old_network)
- network = new_network
-
- return 1
-
- return_network_air(datum/pipe_network/reference)
- var/list/results = list()
-
- if(network == reference)
- results += air_contents
-
- return results
-
- disconnect(obj/machinery/atmospherics/reference)
- if(reference==node)
- qdel(network)
- node = null
-
- update_icon()
- update_underlays()
-
- return null
-
-/obj/machinery/atmospherics/unary/vent_pump/proc/is_welded() // TODO: refactor welding into unary
- if (welded > 0)
- return 1
- return 0
-
-/obj/machinery/atmospherics/unary/vent_scrubber/proc/is_welded()
- if (welded > 0)
- return 1
- return 0
+/obj/machinery/atmospherics/unary
+ dir = SOUTH
+ initialize_directions = SOUTH
+ //layer = TURF_LAYER+0.1
+
+ var/datum/gas_mixture/air_contents
+
+ var/obj/machinery/atmospherics/node
+
+ var/datum/pipe_network/network
+
+ Initialize()
+ initialize_directions = dir
+ air_contents = new
+ air_contents.volume = 200
+ . = ..()
+
+// Housekeeping and pipe network stuff below
+ network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
+ if(reference == node)
+ network = new_network
+
+ if(new_network.normal_members.Find(src))
+ return 0
+
+ new_network.normal_members += src
+
+ return null
+
+ Destroy()
+ QDEL_NULL(air_contents)
+
+ if(node)
+ node.disconnect(src)
+ QDEL_NULL(network)
+
+ node = null
+
+ return ..()
+
+ atmos_init()
+ if(node) return
+
+ var/node_connect = dir
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node_connect))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node = target
+ break
+
+ update_icon()
+ update_underlays()
+
+ build_network()
+ if(!network && node)
+ network = new /datum/pipe_network()
+ network.normal_members += src
+ network.build_network(node, src)
+
+
+ return_network(obj/machinery/atmospherics/reference)
+ build_network()
+
+ if(reference==node)
+ return network
+
+ return null
+
+ reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
+ if(network == old_network)
+ network = new_network
+
+ return 1
+
+ return_network_air(datum/pipe_network/reference)
+ var/list/results = list()
+
+ if(network == reference)
+ results += air_contents
+
+ return results
+
+ disconnect(obj/machinery/atmospherics/reference)
+ if(reference==node)
+ qdel(network)
+ node = null
+
+ update_icon()
+ update_underlays()
+
+ return null
+
+/obj/machinery/atmospherics/unary/vent_pump/proc/is_welded() // TODO: refactor welding into unary
+ if (welded > 0)
+ return 1
+ return 0
+
+/obj/machinery/atmospherics/unary/vent_scrubber/proc/is_welded()
+ if (welded > 0)
+ return 1
+ return 0
diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm
index 53059109594..97edf465885 100644
--- a/code/ATMOSPHERICS/components/unary/vent_pump.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm
@@ -1,426 +1,424 @@
-#define DEFAULT_PRESSURE_DELTA 10000
-
-#define EXTERNAL_PRESSURE_BOUND ONE_ATMOSPHERE
-#define INTERNAL_PRESSURE_BOUND 0
-#define PRESSURE_CHECKS 1
-
-#define PRESSURE_CHECK_EXTERNAL 1
-#define PRESSURE_CHECK_INTERNAL 2
-
-/obj/machinery/atmospherics/unary/vent_pump
- icon = 'icons/atmos/vent_pump.dmi'
- icon_state = "map_vent"
-
- name = "Air Vent"
- desc = "Has a valve and pump attached to it"
- use_power = 0
- idle_power_usage = 150 //internal circuitry, friction losses and stuff
- power_rating = 7500 //7500 W ~ 10 HP
-
- connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY //connects to regular and supply pipes
-
- var/area/initial_loc
- level = 1
- var/area_uid
- var/id_tag = null
-
- var/hibernate = 0 //Do we even process?
- var/pump_direction = 1 //0 = siphoning, 1 = releasing
-
- var/external_pressure_bound = EXTERNAL_PRESSURE_BOUND
- var/internal_pressure_bound = INTERNAL_PRESSURE_BOUND
-
- var/pressure_checks = PRESSURE_CHECKS
- //1: Do not pass external_pressure_bound
- //2: Do not pass internal_pressure_bound
- //3: Do not pass either
-
- // Used when handling incoming radio signals requesting default settings
- var/external_pressure_bound_default = EXTERNAL_PRESSURE_BOUND
- var/internal_pressure_bound_default = INTERNAL_PRESSURE_BOUND
- var/pressure_checks_default = PRESSURE_CHECKS
-
- var/welded = 0 // Added for aliens -- TLE
-
- var/frequency = 1439
- var/datum/radio_frequency/radio_connection
-
- var/radio_filter_out
- var/radio_filter_in
-
-/obj/machinery/atmospherics/unary/vent_pump/on
- use_power = 1
- icon_state = "map_vent_out"
-
-/obj/machinery/atmospherics/unary/vent_pump/siphon
- pump_direction = 0
-
-/obj/machinery/atmospherics/unary/vent_pump/siphon/on
- use_power = 1
- icon_state = "map_vent_in"
-
-/obj/machinery/atmospherics/unary/vent_pump/siphon/on/atmos
- use_power = 1
- icon_state = "map_vent_in"
- external_pressure_bound = 0
- external_pressure_bound_default = 0
- internal_pressure_bound = 2000
- internal_pressure_bound_default = 2000
- pressure_checks = 2
- pressure_checks_default = 2
-
-/obj/machinery/atmospherics/unary/vent_pump/Initialize()
- . = ..()
- air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP
-
- initial_loc = loc.loc
- area_uid = initial_loc.uid
- if (!id_tag)
- assign_uid()
- id_tag = num2text(uid)
-
- //some vents work his own special way
- radio_filter_in = frequency == 1439 ? (RADIO_FROM_AIRALARM) : null
- radio_filter_out = frequency == 1439 ? (RADIO_TO_AIRALARM) : null
- if(frequency)
- radio_connection = register_radio(src, frequency, frequency, radio_filter_in)
-
-// Different from the above.
-/obj/machinery/atmospherics/unary/vent_pump/atmos_init()
- ..()
- broadcast_status()
-
-/obj/machinery/atmospherics/unary/vent_pump/Destroy()
- unregister_radio(src, frequency)
- return ..()
-
-/obj/machinery/atmospherics/unary/vent_pump/high_volume
- name = "Large Air Vent"
- power_channel = EQUIP
- power_rating = 15000 //15 kW ~ 20 HP
-
-/obj/machinery/atmospherics/unary/vent_pump/high_volume/Initialize()
- . = ..()
- air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP + 800
-
-/obj/machinery/atmospherics/unary/vent_pump/engine
- name = "Engine Core Vent"
- power_channel = ENVIRON
- power_rating = 30000 //15 kW ~ 20 HP
-
-/obj/machinery/atmospherics/unary/vent_pump/engine/Initialize()
- . = ..()
- air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP + 500 //meant to match air injector
-
-/obj/machinery/atmospherics/unary/vent_pump/update_icon(var/safety = 0)
- if (!node)
- use_power = 0
-
- var/vent_icon = ""
-
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
-
- if(!T.is_plating() && node && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
- vent_icon += "h"
-
- if(welded)
- vent_icon += "weld"
- else if(!powered())
- vent_icon += "off"
- else
- vent_icon += "[use_power ? "[pump_direction ? "out" : "in"]" : "off"]"
-
- icon_state = vent_icon
-
- update_underlays()
-
-/obj/machinery/atmospherics/unary/vent_pump/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- if(!T.is_plating() && node && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
- return
- else
- if(node)
- add_underlay(T, node, dir, node.icon_connect_type)
- else
- add_underlay(T,, dir)
-
-/obj/machinery/atmospherics/unary/vent_pump/hide()
- queue_icon_update()
-
-/obj/machinery/atmospherics/unary/vent_pump/proc/can_pump()
- if(stat & (NOPOWER|BROKEN))
- return 0
- if(!use_power)
- return 0
- if(welded)
- return 0
- return 1
-
-/obj/machinery/atmospherics/unary/vent_pump/machinery_process()
- ..()
-
- if (hibernate > world.time)
- return 1
-
- if (!node)
- use_power = 0
- if(!can_pump())
- return 0
-
- var/datum/gas_mixture/environment = loc.return_air()
-
- var/power_draw = -1
-
- //Figure out the target pressure difference
- var/pressure_delta = get_pressure_delta(environment)
- //src.visible_message("DEBUG >>> [src]: pressure_delta = [pressure_delta]")
-
- if((environment.temperature || air_contents.temperature) && pressure_delta > 0.5)
- if(pump_direction) //internal -> external
- var/transfer_moles = calculate_transfer_moles(air_contents, environment, pressure_delta)
- power_draw = pump_gas(src, air_contents, environment, transfer_moles, power_rating)
- else //external -> internal
- var/transfer_moles = calculate_transfer_moles(environment, air_contents, pressure_delta, (network)? network.volume : 0)
-
- //limit flow rate from turfs
- transfer_moles = min(transfer_moles, environment.total_moles*air_contents.volume/environment.volume) //group_multiplier gets divided out here
- power_draw = pump_gas(src, environment, air_contents, transfer_moles, power_rating)
-
- else
- //If we're in an area that is fucking ideal, and we don't have to do anything, chances are we won't next tick either so why redo these calculations?
- //JESUS FUCK. THERE ARE LITERALLY 250 OF YOU MOTHERFUCKERS ON ZLEVEL ONE AND YOU DO THIS SHIT EVERY TICK WHEN VERY OFTEN THERE IS NO REASON TO
- if(pump_direction && pressure_checks == PRESSURE_CHECK_EXTERNAL) //99% of all vents
- hibernate = world.time + (rand(100,200))
-
-
- if (power_draw >= 0)
- last_power_draw = power_draw
- use_power(power_draw)
- if(network)
- network.update = 1
-
- return 1
-
-/obj/machinery/atmospherics/unary/vent_pump/proc/get_pressure_delta(datum/gas_mixture/environment)
- var/pressure_delta = DEFAULT_PRESSURE_DELTA
- var/environment_pressure = environment.return_pressure()
-
- if(pump_direction) //internal -> external
- if(pressure_checks & PRESSURE_CHECK_EXTERNAL)
- pressure_delta = min(pressure_delta, external_pressure_bound - environment_pressure) //increasing the pressure here
- if(pressure_checks & PRESSURE_CHECK_INTERNAL)
- pressure_delta = min(pressure_delta, air_contents.return_pressure() - internal_pressure_bound) //decreasing the pressure here
- else //external -> internal
- if(pressure_checks & PRESSURE_CHECK_EXTERNAL)
- pressure_delta = min(pressure_delta, environment_pressure - external_pressure_bound) //decreasing the pressure here
- if(pressure_checks & PRESSURE_CHECK_INTERNAL)
- pressure_delta = min(pressure_delta, internal_pressure_bound - air_contents.return_pressure()) //increasing the pressure here
-
- return pressure_delta
-
-/obj/machinery/atmospherics/unary/vent_pump/proc/broadcast_status()
- if(!radio_connection)
- return 0
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
- "area" = src.area_uid,
- "tag" = src.id_tag,
- "device" = "AVP",
- "power" = use_power,
- "direction" = pump_direction?("release"):("siphon"),
- "checks" = pressure_checks,
- "internal" = internal_pressure_bound,
- "external" = external_pressure_bound,
- "timestamp" = world.time,
- "sigtype" = "status",
- "power_draw" = last_power_draw,
- "flow_rate" = last_flow_rate
- )
-
- var/area/A = get_area(src)
- if(!A.air_vent_names[id_tag])
- var/new_name = "[A.name] Vent Pump #[A.air_vent_names.len+1]"
- A.air_vent_names[id_tag] = new_name
- src.name = new_name
- A.air_vent_info[id_tag] = signal.data
-
- radio_connection.post_signal(src, signal, radio_filter_out)
-
- return 1
-
-/obj/machinery/atmospherics/unary/vent_pump/receive_signal(datum/signal/signal)
- if(stat & (NOPOWER|BROKEN))
- return
-
- hibernate = 0
-
- //log_debug("DEBUG \[[world.timeofday]\]: /obj/machinery/atmospherics/unary/vent_pump/receive_signal([signal.debug_print()])")
- if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command"))
- return 0
-
- if(signal.data["purge"] != null)
- pressure_checks &= ~1
- pump_direction = 0
-
- if(signal.data["stabalize"] != null)
- pressure_checks |= 1
- pump_direction = 1
-
- if(signal.data["power"] != null)
- use_power = text2num(signal.data["power"])
-
- if(signal.data["power_toggle"] != null)
- use_power = !use_power
-
- if(signal.data["checks"] != null)
- if (signal.data["checks"] == "default")
- pressure_checks = pressure_checks_default
- else
- pressure_checks = text2num(signal.data["checks"])
-
- if(signal.data["checks_toggle"] != null)
- pressure_checks = (pressure_checks?0:3)
-
- if(signal.data["direction"] != null)
- pump_direction = text2num(signal.data["direction"])
-
- if(signal.data["set_internal_pressure"] != null)
- if (signal.data["set_internal_pressure"] == "default")
- internal_pressure_bound = internal_pressure_bound_default
- else
- internal_pressure_bound = between(
- 0,
- text2num(signal.data["set_internal_pressure"]),
- ONE_ATMOSPHERE*50
- )
-
- if(signal.data["set_external_pressure"] != null)
- if (signal.data["set_external_pressure"] == "default")
- external_pressure_bound = external_pressure_bound_default
- else
- external_pressure_bound = between(
- 0,
- text2num(signal.data["set_external_pressure"]),
- ONE_ATMOSPHERE*50
- )
-
- if(signal.data["adjust_internal_pressure"] != null)
- internal_pressure_bound = between(
- 0,
- internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]),
- ONE_ATMOSPHERE*50
- )
-
- if(signal.data["adjust_external_pressure"] != null)
-
-
- external_pressure_bound = between(
- 0,
- external_pressure_bound + text2num(signal.data["adjust_external_pressure"]),
- ONE_ATMOSPHERE*50
- )
-
- if(signal.data["init"] != null)
- name = signal.data["init"]
- return
-
- if(signal.data["status"] != null)
- addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
- return //do not update_icon
-
- //log_debug("DEBUG \[[world.timeofday]\]: vent_pump/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]")
- addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
-
- update_icon()
- return
-
-/obj/machinery/atmospherics/unary/vent_pump/attackby(obj/item/W, mob/user)
- if(W.iswelder())
- var/obj/item/weapon/weldingtool/WT = W
- if (!WT.welding)
- to_chat(user, "\The [WT] must be turned on!")
- else if (WT.remove_fuel(0,user))
- to_chat(user, "Now welding the vent.")
- if(do_after(user, 20))
- if(!src || !WT.isOn()) return
- playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
- if(!welded)
- user.visible_message("\The [user] welds \the [src] shut.", "You weld \the [src] shut.", "You hear welding.")
- welded = 1
- update_icon()
- else
- user.visible_message("[user] unwelds \the [src].", "You unweld \the [src].", "You hear welding.")
- welded = 0
- update_icon()
- else
- to_chat(user, "You fail to complete the welding.")
- else
- to_chat(user, "You need more welding fuel to complete this task.")
- return 1
- else
- ..()
-
-/obj/machinery/atmospherics/unary/vent_pump/examine(mob/user)
- if(..(user, 1))
- to_chat(user, "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W")
- else
- to_chat(user, "You are too far away to read the gauge.")
- if(welded)
- to_chat(user, "It seems welded shut.")
-
-/obj/machinery/atmospherics/unary/vent_pump/power_change()
- var/old_stat = stat
- ..()
- if(old_stat != stat)
- update_icon()
-
-/obj/machinery/atmospherics/unary/vent_pump/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
- if (!W.iswrench())
- return ..()
- if (!(stat & NOPOWER) && use_power)
- to_chat(user, "You cannot unwrench \the [src], turn it off first.")
- return 1
- var/turf/T = src.loc
- if (node && node.level==1 && isturf(T) && !T.is_plating())
- to_chat(user, "You must remove the plating first.")
- return 1
- var/datum/gas_mixture/int_air = return_air()
- var/datum/gas_mixture/env_air = loc.return_air()
- if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
- to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
- add_fingerprint(user)
- return 1
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
- if (do_after(user, 40))
- user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
- "You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
-
-/obj/machinery/atmospherics/unary/vent_pump/Destroy()
- if(initial_loc)
- initial_loc.air_vent_info -= id_tag
- initial_loc.air_vent_names -= id_tag
- return ..()
-
-#undef DEFAULT_PRESSURE_DELTA
-
-#undef EXTERNAL_PRESSURE_BOUND
-#undef INTERNAL_PRESSURE_BOUND
-#undef PRESSURE_CHECKS
-
-#undef PRESSURE_CHECK_EXTERNAL
-#undef PRESSURE_CHECK_INTERNAL
+#define DEFAULT_PRESSURE_DELTA 10000
+
+#define EXTERNAL_PRESSURE_BOUND ONE_ATMOSPHERE
+#define INTERNAL_PRESSURE_BOUND 0
+#define PRESSURE_CHECKS 1
+
+#define PRESSURE_CHECK_EXTERNAL 1
+#define PRESSURE_CHECK_INTERNAL 2
+
+/obj/machinery/atmospherics/unary/vent_pump
+ icon = 'icons/atmos/vent_pump.dmi'
+ icon_state = "map_vent"
+
+ name = "Air Vent"
+ desc = "Has a valve and pump attached to it"
+ use_power = 0
+ idle_power_usage = 150 //internal circuitry, friction losses and stuff
+ power_rating = 7500 //7500 W ~ 10 HP
+
+ connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY //connects to regular and supply pipes
+
+ var/area/initial_loc
+ level = 1
+ var/area_uid
+ var/id_tag = null
+
+ var/hibernate = 0 //Do we even process?
+ var/pump_direction = 1 //0 = siphoning, 1 = releasing
+
+ var/external_pressure_bound = EXTERNAL_PRESSURE_BOUND
+ var/internal_pressure_bound = INTERNAL_PRESSURE_BOUND
+
+ var/pressure_checks = PRESSURE_CHECKS
+ //1: Do not pass external_pressure_bound
+ //2: Do not pass internal_pressure_bound
+ //3: Do not pass either
+
+ // Used when handling incoming radio signals requesting default settings
+ var/external_pressure_bound_default = EXTERNAL_PRESSURE_BOUND
+ var/internal_pressure_bound_default = INTERNAL_PRESSURE_BOUND
+ var/pressure_checks_default = PRESSURE_CHECKS
+
+ var/welded = 0 // Added for aliens -- TLE
+
+ var/frequency = 1439
+ var/datum/radio_frequency/radio_connection
+
+ var/radio_filter_out
+ var/radio_filter_in
+
+/obj/machinery/atmospherics/unary/vent_pump/on
+ use_power = 1
+ icon_state = "map_vent_out"
+
+/obj/machinery/atmospherics/unary/vent_pump/siphon
+ pump_direction = 0
+
+/obj/machinery/atmospherics/unary/vent_pump/siphon/on
+ use_power = 1
+ icon_state = "map_vent_in"
+
+/obj/machinery/atmospherics/unary/vent_pump/siphon/on/atmos
+ use_power = 1
+ icon_state = "map_vent_in"
+ external_pressure_bound = 0
+ external_pressure_bound_default = 0
+ internal_pressure_bound = 2000
+ internal_pressure_bound_default = 2000
+ pressure_checks = 2
+ pressure_checks_default = 2
+
+/obj/machinery/atmospherics/unary/vent_pump/Initialize()
+ . = ..()
+ air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP
+
+ initial_loc = loc.loc
+ area_uid = initial_loc.uid
+ if (!id_tag)
+ assign_uid()
+ id_tag = num2text(uid)
+
+ //some vents work his own special way
+ radio_filter_in = frequency == 1439 ? (RADIO_FROM_AIRALARM) : null
+ radio_filter_out = frequency == 1439 ? (RADIO_TO_AIRALARM) : null
+ if(frequency)
+ radio_connection = register_radio(src, frequency, frequency, radio_filter_in)
+
+// Different from the above.
+/obj/machinery/atmospherics/unary/vent_pump/atmos_init()
+ ..()
+ broadcast_status()
+
+/obj/machinery/atmospherics/unary/vent_pump/Destroy()
+ unregister_radio(src, frequency)
+ return ..()
+
+/obj/machinery/atmospherics/unary/vent_pump/high_volume
+ name = "Large Air Vent"
+ power_channel = EQUIP
+ power_rating = 15000 //15 kW ~ 20 HP
+
+/obj/machinery/atmospherics/unary/vent_pump/high_volume/Initialize()
+ . = ..()
+ air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP + 800
+
+/obj/machinery/atmospherics/unary/vent_pump/engine
+ name = "Engine Core Vent"
+ power_channel = ENVIRON
+ power_rating = 30000 //15 kW ~ 20 HP
+
+/obj/machinery/atmospherics/unary/vent_pump/engine/Initialize()
+ . = ..()
+ air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP + 500 //meant to match air injector
+
+/obj/machinery/atmospherics/unary/vent_pump/update_icon(var/safety = 0)
+ if (!node)
+ use_power = 0
+
+ var/vent_icon = ""
+
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+
+ if(!T.is_plating() && node && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
+ vent_icon += "h"
+
+ if(welded)
+ vent_icon += "weld"
+ else if(!powered())
+ vent_icon += "off"
+ else
+ vent_icon += "[use_power ? "[pump_direction ? "out" : "in"]" : "off"]"
+
+ icon_state = vent_icon
+
+ update_underlays()
+
+/obj/machinery/atmospherics/unary/vent_pump/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ if(!T.is_plating() && node && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
+ return
+ else
+ if(node)
+ add_underlay(T, node, dir, node.icon_connect_type)
+ else
+ add_underlay(T,, dir)
+
+/obj/machinery/atmospherics/unary/vent_pump/hide()
+ queue_icon_update()
+
+/obj/machinery/atmospherics/unary/vent_pump/proc/can_pump()
+ if(stat & (NOPOWER|BROKEN))
+ return 0
+ if(!use_power)
+ return 0
+ if(welded)
+ return 0
+ return 1
+
+/obj/machinery/atmospherics/unary/vent_pump/machinery_process()
+ ..()
+
+ if (hibernate > world.time)
+ return 1
+
+ if (!node)
+ use_power = 0
+ if(!can_pump())
+ return 0
+
+ var/datum/gas_mixture/environment = loc.return_air()
+
+ var/power_draw = -1
+
+ //Figure out the target pressure difference
+ var/pressure_delta = get_pressure_delta(environment)
+ //src.visible_message("DEBUG >>> [src]: pressure_delta = [pressure_delta]")
+
+ if((environment.temperature || air_contents.temperature) && pressure_delta > 0.5)
+ if(pump_direction) //internal -> external
+ var/transfer_moles = calculate_transfer_moles(air_contents, environment, pressure_delta)
+ power_draw = pump_gas(src, air_contents, environment, transfer_moles, power_rating)
+ else //external -> internal
+ var/transfer_moles = calculate_transfer_moles(environment, air_contents, pressure_delta, (network)? network.volume : 0)
+
+ //limit flow rate from turfs
+ transfer_moles = min(transfer_moles, environment.total_moles*air_contents.volume/environment.volume) //group_multiplier gets divided out here
+ power_draw = pump_gas(src, environment, air_contents, transfer_moles, power_rating)
+
+ else
+ //If we're in an area that is fucking ideal, and we don't have to do anything, chances are we won't next tick either so why redo these calculations?
+ //JESUS FUCK. THERE ARE LITERALLY 250 OF YOU MOTHERFUCKERS ON ZLEVEL ONE AND YOU DO THIS SHIT EVERY TICK WHEN VERY OFTEN THERE IS NO REASON TO
+ if(pump_direction && pressure_checks == PRESSURE_CHECK_EXTERNAL) //99% of all vents
+ hibernate = world.time + (rand(100,200))
+
+
+ if (power_draw >= 0)
+ last_power_draw = power_draw
+ use_power(power_draw)
+ if(network)
+ network.update = 1
+
+ return 1
+
+/obj/machinery/atmospherics/unary/vent_pump/proc/get_pressure_delta(datum/gas_mixture/environment)
+ var/pressure_delta = DEFAULT_PRESSURE_DELTA
+ var/environment_pressure = environment.return_pressure()
+
+ if(pump_direction) //internal -> external
+ if(pressure_checks & PRESSURE_CHECK_EXTERNAL)
+ pressure_delta = min(pressure_delta, external_pressure_bound - environment_pressure) //increasing the pressure here
+ if(pressure_checks & PRESSURE_CHECK_INTERNAL)
+ pressure_delta = min(pressure_delta, air_contents.return_pressure() - internal_pressure_bound) //decreasing the pressure here
+ else //external -> internal
+ if(pressure_checks & PRESSURE_CHECK_EXTERNAL)
+ pressure_delta = min(pressure_delta, environment_pressure - external_pressure_bound) //decreasing the pressure here
+ if(pressure_checks & PRESSURE_CHECK_INTERNAL)
+ pressure_delta = min(pressure_delta, internal_pressure_bound - air_contents.return_pressure()) //increasing the pressure here
+
+ return pressure_delta
+
+/obj/machinery/atmospherics/unary/vent_pump/proc/broadcast_status()
+ if(!radio_connection)
+ return 0
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+
+ signal.data = list(
+ "area" = src.area_uid,
+ "tag" = src.id_tag,
+ "device" = "AVP",
+ "power" = use_power,
+ "direction" = pump_direction?("release"):("siphon"),
+ "checks" = pressure_checks,
+ "internal" = internal_pressure_bound,
+ "external" = external_pressure_bound,
+ "timestamp" = world.time,
+ "sigtype" = "status",
+ "power_draw" = last_power_draw,
+ "flow_rate" = last_flow_rate
+ )
+
+ var/area/A = get_area(src)
+ if(!A.air_vent_names[id_tag])
+ var/new_name = "[A.name] Vent Pump #[A.air_vent_names.len+1]"
+ A.air_vent_names[id_tag] = new_name
+ src.name = new_name
+ A.air_vent_info[id_tag] = signal.data
+
+ radio_connection.post_signal(src, signal, radio_filter_out)
+
+ return 1
+
+/obj/machinery/atmospherics/unary/vent_pump/receive_signal(datum/signal/signal)
+ if(stat & (NOPOWER|BROKEN))
+ return
+
+ hibernate = 0
+
+ //log_debug("DEBUG \[[world.timeofday]\]: /obj/machinery/atmospherics/unary/vent_pump/receive_signal([signal.debug_print()])")
+ if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command"))
+ return 0
+
+ if(signal.data["purge"] != null)
+ pressure_checks &= ~1
+ pump_direction = 0
+
+ if(signal.data["stabalize"] != null)
+ pressure_checks |= 1
+ pump_direction = 1
+
+ if(signal.data["power"] != null)
+ use_power = text2num(signal.data["power"])
+
+ if(signal.data["power_toggle"] != null)
+ use_power = !use_power
+
+ if(signal.data["checks"] != null)
+ if (signal.data["checks"] == "default")
+ pressure_checks = pressure_checks_default
+ else
+ pressure_checks = text2num(signal.data["checks"])
+
+ if(signal.data["checks_toggle"] != null)
+ pressure_checks = (pressure_checks?0:3)
+
+ if(signal.data["direction"] != null)
+ pump_direction = text2num(signal.data["direction"])
+
+ if(signal.data["set_internal_pressure"] != null)
+ if (signal.data["set_internal_pressure"] == "default")
+ internal_pressure_bound = internal_pressure_bound_default
+ else
+ internal_pressure_bound = between(
+ 0,
+ text2num(signal.data["set_internal_pressure"]),
+ ONE_ATMOSPHERE*50
+ )
+
+ if(signal.data["set_external_pressure"] != null)
+ if (signal.data["set_external_pressure"] == "default")
+ external_pressure_bound = external_pressure_bound_default
+ else
+ external_pressure_bound = between(
+ 0,
+ text2num(signal.data["set_external_pressure"]),
+ ONE_ATMOSPHERE*50
+ )
+
+ if(signal.data["adjust_internal_pressure"] != null)
+ internal_pressure_bound = between(
+ 0,
+ internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]),
+ ONE_ATMOSPHERE*50
+ )
+
+ if(signal.data["adjust_external_pressure"] != null)
+
+
+ external_pressure_bound = between(
+ 0,
+ external_pressure_bound + text2num(signal.data["adjust_external_pressure"]),
+ ONE_ATMOSPHERE*50
+ )
+
+ if(signal.data["init"] != null)
+ name = signal.data["init"]
+ return
+
+ if(signal.data["status"] != null)
+ addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
+ return //do not update_icon
+
+ //log_debug("DEBUG \[[world.timeofday]\]: vent_pump/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]")
+ addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
+
+ update_icon()
+ return
+
+/obj/machinery/atmospherics/unary/vent_pump/attackby(obj/item/W, mob/user)
+ if(W.iswelder())
+ var/obj/item/weldingtool/WT = W
+ if (!WT.welding)
+ to_chat(user, span("danger", "\The [WT] must be turned on!"))
+ else if (WT.remove_fuel(0,user))
+ to_chat(user, span("notice", "Now welding the vent."))
+ if(do_after(user, 30/W.toolspeed))
+ if(!src || !WT.isOn())
+ return
+ welded = !welded
+ update_icon()
+ playsound(src, 'sound/items/Welder2.ogg', 50, 1)
+ user.visible_message(span("notice", "\The [user] [welded ? "welds \the [src] shut" : "unwelds \the [src]"]."), \
+ span("notice", "You [welded ? "weld \the [src] shut" : "unweld \the [src]"]."), \
+ "You hear welding.")
+ else
+ to_chat(user, span("notice", "You fail to complete the welding."))
+ else
+ to_chat(user, span("warning", "You need more welding fuel to complete this task."))
+ return 1
+ else
+ ..()
+
+/obj/machinery/atmospherics/unary/vent_pump/examine(mob/user)
+ if(..(user, 1))
+ to_chat(user, "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W")
+ else
+ to_chat(user, "You are too far away to read the gauge.")
+ if(welded)
+ to_chat(user, "It seems welded shut.")
+
+/obj/machinery/atmospherics/unary/vent_pump/power_change()
+ var/old_stat = stat
+ ..()
+ if(old_stat != stat)
+ update_icon()
+
+/obj/machinery/atmospherics/unary/vent_pump/attackby(var/obj/item/W as obj, var/mob/user as mob)
+ if (!W.iswrench())
+ return ..()
+ if (!(stat & NOPOWER) && use_power)
+ to_chat(user, span("warning", "You cannot unwrench \the [src], turn it off first."))
+ return 1
+ var/turf/T = src.loc
+ if (node && node.level==1 && isturf(T) && !T.is_plating())
+ to_chat(user, span("warning", "You must remove the plating first."))
+ return 1
+ var/datum/gas_mixture/int_air = return_air()
+ var/datum/gas_mixture/env_air = loc.return_air()
+ if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
+ to_chat(user, span("warning", "You cannot unwrench \the [src], it is too exerted due to internal pressure."))
+ add_fingerprint(user)
+ return 1
+ playsound(src.loc, W.usesound, 50, 1)
+ to_chat(user, span("notice", "You begin to unfasten \the [src]..."))
+ if (do_after(user, 40/W.toolspeed))
+ user.visible_message( \
+ span("notice", "\The [user] unfastens \the [src]."), \
+ span("notice", "You have unfastened \the [src]."), \
+ "You hear a ratchet.")
+ new /obj/item/pipe(loc, make_from=src)
+ qdel(src)
+
+/obj/machinery/atmospherics/unary/vent_pump/Destroy()
+ if(initial_loc)
+ initial_loc.air_vent_info -= id_tag
+ initial_loc.air_vent_names -= id_tag
+ return ..()
+
+#undef DEFAULT_PRESSURE_DELTA
+
+#undef EXTERNAL_PRESSURE_BOUND
+#undef INTERNAL_PRESSURE_BOUND
+#undef PRESSURE_CHECKS
+
+#undef PRESSURE_CHECK_EXTERNAL
+#undef PRESSURE_CHECK_INTERNAL
diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
index 0cb9f0de5c6..b4d316c60aa 100644
--- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
@@ -1,318 +1,316 @@
-/obj/machinery/atmospherics/unary/vent_scrubber
- icon = 'icons/atmos/vent_scrubber.dmi'
- icon_state = "map_scrubber_off"
-
- name = "Air Scrubber"
- desc = "Has a valve and pump attached to it"
- use_power = 0
- idle_power_usage = 150 //internal circuitry, friction losses and stuff
- power_rating = 7500 //7500 W ~ 10 HP
-
- connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SCRUBBER //connects to regular and scrubber pipes
-
- level = 1
-
- var/area/initial_loc
- var/id_tag = null
- var/frequency = 1439
- var/datum/radio_frequency/radio_connection
-
- var/hibernate = 0 //Do we even process?
- var/scrubbing = 1 //0 = siphoning, 1 = scrubbing
- var/list/scrubbing_gas = list("carbon_dioxide")
-
- var/panic = 0 //is this scrubber panicked?
-
- var/area_uid
- var/radio_filter_out
- var/radio_filter_in
-
- var/welded = 0
-
-/obj/machinery/atmospherics/unary/vent_scrubber/on
- use_power = 1
- icon_state = "map_scrubber_on"
-
-/obj/machinery/atmospherics/unary/vent_scrubber/Initialize()
- . = ..()
- air_contents.volume = ATMOS_DEFAULT_VOLUME_FILTER
-
- initial_loc = get_area(loc)
- area_uid = initial_loc.uid
- if (!id_tag)
- assign_uid()
- id_tag = num2text(uid)
-
- radio_filter_in = frequency==initial(frequency)?(RADIO_FROM_AIRALARM):null
- radio_filter_out = frequency==initial(frequency)?(RADIO_TO_AIRALARM):null
- if (frequency)
- set_frequency(frequency)
-
-/obj/machinery/atmospherics/unary/vent_scrubber/atmos_init()
- ..()
- broadcast_status()
-
-/obj/machinery/atmospherics/unary/vent_scrubber/Destroy()
- unregister_radio(src, frequency)
- return ..()
-
-/obj/machinery/atmospherics/unary/vent_scrubber/update_icon(var/safety = 0)
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
-
- if (welded)
- icon_state = "weld"
- return
-
- if (!powered() || !use_power)
- icon_state = "off"
- else if (scrubbing)
- icon_state = "on"
- else
- icon_state = "in"
-
-/obj/machinery/atmospherics/unary/vent_scrubber/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- if(!T.is_plating() && node && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
- return
- else
- if(node)
- add_underlay(T, node, dir, node.icon_connect_type)
- else
- add_underlay(T,, dir)
-
-/obj/machinery/atmospherics/unary/vent_scrubber/proc/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- radio_connection = SSradio.add_object(src, frequency, radio_filter_in)
-
-/obj/machinery/atmospherics/unary/vent_scrubber/proc/broadcast_status()
- if(!radio_connection)
- return 0
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
- signal.data = list(
- "area" = area_uid,
- "tag" = id_tag,
- "device" = "AScr",
- "timestamp" = world.time,
- "power" = use_power,
- "scrubbing" = scrubbing,
- "panic" = panic,
- "filter_o2" = ("oxygen" in scrubbing_gas),
- "filter_n2" = ("nitrogen" in scrubbing_gas),
- "filter_co2" = ("carbon_dioxide" in scrubbing_gas),
- "filter_phoron" = ("phoron" in scrubbing_gas),
- "filter_n2o" = ("sleeping_agent" in scrubbing_gas),
- "sigtype" = "status"
- )
-
- var/area/A = get_area(src)
- if(!A.air_scrub_names[id_tag])
- var/new_name = "[A.name] Air Scrubber #[A.air_scrub_names.len+1]"
- A.air_scrub_names[id_tag] = new_name
- src.name = new_name
- A.air_scrub_info[id_tag] = signal.data
- radio_connection.post_signal(src, signal, radio_filter_out)
-
- return 1
-
-/obj/machinery/atmospherics/unary/vent_scrubber/machinery_process()
- ..()
-
- if (hibernate > world.time)
- return 1
-
- if (!node)
- use_power = 0
- //broadcast_status()
- if(!use_power || (stat & (NOPOWER|BROKEN)))
- return 0
- if(welded)
- return 0
-
- var/datum/gas_mixture/environment = loc.return_air()
-
- var/power_draw = -1
- if(scrubbing)
- //limit flow rate from turfs
- var/transfer_moles = min(environment.total_moles, environment.total_moles*MAX_SCRUBBER_FLOWRATE/environment.volume) //group_multiplier gets divided out here
-
- power_draw = scrub_gas(src, scrubbing_gas, environment, air_contents, transfer_moles, power_rating)
- else //Just siphon all air
- //limit flow rate from turfs
- var/transfer_moles = min(environment.total_moles, environment.total_moles*MAX_SIPHON_FLOWRATE/environment.volume) //group_multiplier gets divided out here
-
- power_draw = pump_gas(src, environment, air_contents, transfer_moles, power_rating)
-
- if(scrubbing && power_draw <= 0) //99% of all scrubbers
- //Fucking hibernate because you ain't doing shit.
- hibernate = world.time + (rand(100,200))
-
- if (power_draw >= 0)
- last_power_draw = power_draw
- use_power(power_draw)
-
- if(network)
- network.update = 1
-
- return 1
-
-/obj/machinery/atmospherics/unary/vent_scrubber/hide(var/i) //to make the little pipe section invisible, the icon changes.
- update_icon()
- update_underlays()
-
-/obj/machinery/atmospherics/unary/vent_scrubber/receive_signal(datum/signal/signal)
- if(stat & (NOPOWER|BROKEN))
- return
- if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command"))
- return 0
-
- if(signal.data["power"] != null)
- use_power = text2num(signal.data["power"])
- if(signal.data["power_toggle"] != null)
- use_power = !use_power
-
- if(signal.data["panic_siphon"]) //must be before if("scrubbing" thing
- panic = text2num(signal.data["panic_siphon"])
- if(panic)
- use_power = 1
- scrubbing = 0
- else
- scrubbing = 1
- if(signal.data["toggle_panic_siphon"] != null)
- panic = !panic
- if(panic)
- use_power = 1
- scrubbing = 0
- else
- scrubbing = 1
-
- if(signal.data["scrubbing"] != null)
- scrubbing = text2num(signal.data["scrubbing"])
- if(scrubbing)
- panic = 0
- if(signal.data["toggle_scrubbing"])
- scrubbing = !scrubbing
- if(scrubbing)
- panic = 0
-
- var/list/toggle = list()
-
- if(!isnull(signal.data["o2_scrub"]) && text2num(signal.data["o2_scrub"]) != ("oxygen" in scrubbing_gas))
- toggle += "oxygen"
- else if(signal.data["toggle_o2_scrub"])
- toggle += "oxygen"
-
- if(!isnull(signal.data["n2_scrub"]) && text2num(signal.data["n2_scrub"]) != ("nitrogen" in scrubbing_gas))
- toggle += "nitrogen"
- else if(signal.data["toggle_n2_scrub"])
- toggle += "nitrogen"
-
- if(!isnull(signal.data["co2_scrub"]) && text2num(signal.data["co2_scrub"]) != ("carbon_dioxide" in scrubbing_gas))
- toggle += "carbon_dioxide"
- else if(signal.data["toggle_co2_scrub"])
- toggle += "carbon_dioxide"
-
- if(!isnull(signal.data["tox_scrub"]) && text2num(signal.data["tox_scrub"]) != ("phoron" in scrubbing_gas))
- toggle += "phoron"
- else if(signal.data["toggle_tox_scrub"])
- toggle += "phoron"
-
- if(!isnull(signal.data["n2o_scrub"]) && text2num(signal.data["n2o_scrub"]) != ("sleeping_agent" in scrubbing_gas))
- toggle += "sleeping_agent"
- else if(signal.data["toggle_n2o_scrub"])
- toggle += "sleeping_agent"
-
- scrubbing_gas ^= toggle
-
- if(signal.data["init"] != null)
- name = signal.data["init"]
- return
-
- if(signal.data["status"] != null)
- addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
- return //do not update_icon
-
-// log_debug("DEBUG \[[world.timeofday]\]: vent_scrubber/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]")
- addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
- update_icon()
- return
-
-/obj/machinery/atmospherics/unary/vent_scrubber/power_change()
- var/old_stat = stat
- ..()
- if(old_stat != stat)
- update_icon()
-
-/obj/machinery/atmospherics/unary/vent_scrubber/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
- if (W.iswrench())
- if (!(stat & NOPOWER) && use_power)
- to_chat(user, "You cannot unwrench \the [src], turn it off first.")
- return 1
- var/turf/T = src.loc
- if (node && node.level==1 && isturf(T) && !T.is_plating())
- to_chat(user, "You must remove the plating first.")
- return 1
- var/datum/gas_mixture/int_air = return_air()
- var/datum/gas_mixture/env_air = loc.return_air()
- if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
- to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
- add_fingerprint(user)
- return 1
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
- if (do_after(user, 40, act_target = src))
- user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
- "You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
- return 1
-
- if(W.iswelder())
- var/obj/item/weapon/weldingtool/WT = W
- if (!WT.welding)
- to_chat(user, "\The [WT] must be turned on!")
- else if (WT.remove_fuel(0,user))
- to_chat(user, "Now welding \the [src].")
- if(do_after(user, 20, act_target = src))
- if(!src || !WT.isOn()) return
- playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
- if(!welded)
- user.visible_message("\The [user] welds \the [src] shut.", "You weld \the [src] shut.", "You hear welding.")
- welded = 1
- update_icon()
- else
- user.visible_message("[user] unwelds \the [src].", "You unweld \the [src].", "You hear welding.")
- welded = 0
- update_icon()
- else
- to_chat(user, "You fail to complete the welding.")
- else
- to_chat(user, "You need more welding fuel to complete this task.")
- return 1
- return ..()
-
-/obj/machinery/atmospherics/unary/vent_scrubber/examine(mob/user)
- if(..(user, 1))
- to_chat(user, "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W")
- else
- to_chat(user, "You are too far away to read the gauge.")
- if(welded)
- to_chat(user, "It seems welded shut.")
-
-/obj/machinery/atmospherics/unary/vent_scrubber/Destroy()
- if(initial_loc)
- initial_loc.air_scrub_info -= id_tag
- initial_loc.air_scrub_names -= id_tag
-
- return ..()
+/obj/machinery/atmospherics/unary/vent_scrubber
+ icon = 'icons/atmos/vent_scrubber.dmi'
+ icon_state = "map_scrubber_off"
+
+ name = "Air Scrubber"
+ desc = "Has a valve and pump attached to it"
+ use_power = 0
+ idle_power_usage = 150 //internal circuitry, friction losses and stuff
+ power_rating = 7500 //7500 W ~ 10 HP
+
+ connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SCRUBBER //connects to regular and scrubber pipes
+
+ level = 1
+
+ var/area/initial_loc
+ var/id_tag = null
+ var/frequency = 1439
+ var/datum/radio_frequency/radio_connection
+
+ var/hibernate = 0 //Do we even process?
+ var/scrubbing = 1 //0 = siphoning, 1 = scrubbing
+ var/list/scrubbing_gas = list("carbon_dioxide")
+
+ var/panic = 0 //is this scrubber panicked?
+
+ var/area_uid
+ var/radio_filter_out
+ var/radio_filter_in
+
+ var/welded = 0
+
+/obj/machinery/atmospherics/unary/vent_scrubber/on
+ use_power = 1
+ icon_state = "map_scrubber_on"
+
+/obj/machinery/atmospherics/unary/vent_scrubber/Initialize()
+ . = ..()
+ air_contents.volume = ATMOS_DEFAULT_VOLUME_FILTER
+
+ initial_loc = get_area(loc)
+ area_uid = initial_loc.uid
+ if (!id_tag)
+ assign_uid()
+ id_tag = num2text(uid)
+
+ radio_filter_in = frequency==initial(frequency)?(RADIO_FROM_AIRALARM):null
+ radio_filter_out = frequency==initial(frequency)?(RADIO_TO_AIRALARM):null
+ if (frequency)
+ set_frequency(frequency)
+
+/obj/machinery/atmospherics/unary/vent_scrubber/atmos_init()
+ ..()
+ broadcast_status()
+
+/obj/machinery/atmospherics/unary/vent_scrubber/Destroy()
+ unregister_radio(src, frequency)
+ if(initial_loc)
+ initial_loc.air_scrub_info -= id_tag
+ initial_loc.air_scrub_names -= id_tag
+
+ return ..()
+
+/obj/machinery/atmospherics/unary/vent_scrubber/update_icon(var/safety = 0)
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+
+ if (welded)
+ icon_state = "weld"
+ return
+
+ if (!powered() || !use_power)
+ icon_state = "off"
+ else if (scrubbing)
+ icon_state = "on"
+ else
+ icon_state = "in"
+
+/obj/machinery/atmospherics/unary/vent_scrubber/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ if(!T.is_plating() && node && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
+ return
+ else
+ if(node)
+ add_underlay(T, node, dir, node.icon_connect_type)
+ else
+ add_underlay(T,, dir)
+
+/obj/machinery/atmospherics/unary/vent_scrubber/proc/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ radio_connection = SSradio.add_object(src, frequency, radio_filter_in)
+
+/obj/machinery/atmospherics/unary/vent_scrubber/proc/broadcast_status()
+ if(!radio_connection)
+ return 0
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+ signal.data = list(
+ "area" = area_uid,
+ "tag" = id_tag,
+ "device" = "AScr",
+ "timestamp" = world.time,
+ "power" = use_power,
+ "scrubbing" = scrubbing,
+ "panic" = panic,
+ "filter_o2" = ("oxygen" in scrubbing_gas),
+ "filter_n2" = ("nitrogen" in scrubbing_gas),
+ "filter_co2" = ("carbon_dioxide" in scrubbing_gas),
+ "filter_phoron" = ("phoron" in scrubbing_gas),
+ "filter_n2o" = ("sleeping_agent" in scrubbing_gas),
+ "sigtype" = "status"
+ )
+
+ var/area/A = get_area(src)
+ if(!A.air_scrub_names[id_tag])
+ var/new_name = "[A.name] Air Scrubber #[A.air_scrub_names.len+1]"
+ A.air_scrub_names[id_tag] = new_name
+ src.name = new_name
+ A.air_scrub_info[id_tag] = signal.data
+ radio_connection.post_signal(src, signal, radio_filter_out)
+
+ return 1
+
+/obj/machinery/atmospherics/unary/vent_scrubber/machinery_process()
+ ..()
+
+ if (hibernate > world.time)
+ return 1
+
+ if (!node)
+ use_power = 0
+ //broadcast_status()
+ if(!use_power || (stat & (NOPOWER|BROKEN)))
+ return 0
+ if(welded)
+ return 0
+
+ var/datum/gas_mixture/environment = loc.return_air()
+
+ var/power_draw = -1
+ if(scrubbing)
+ //limit flow rate from turfs
+ var/transfer_moles = min(environment.total_moles, environment.total_moles*MAX_SCRUBBER_FLOWRATE/environment.volume) //group_multiplier gets divided out here
+
+ power_draw = scrub_gas(src, scrubbing_gas, environment, air_contents, transfer_moles, power_rating)
+ else //Just siphon all air
+ //limit flow rate from turfs
+ var/transfer_moles = min(environment.total_moles, environment.total_moles*MAX_SIPHON_FLOWRATE/environment.volume) //group_multiplier gets divided out here
+
+ power_draw = pump_gas(src, environment, air_contents, transfer_moles, power_rating)
+
+ if(scrubbing && power_draw <= 0) //99% of all scrubbers
+ //Fucking hibernate because you ain't doing shit.
+ hibernate = world.time + (rand(100,200))
+
+ if (power_draw >= 0)
+ last_power_draw = power_draw
+ use_power(power_draw)
+
+ if(network)
+ network.update = 1
+
+ return 1
+
+/obj/machinery/atmospherics/unary/vent_scrubber/hide(var/i) //to make the little pipe section invisible, the icon changes.
+ update_icon()
+ update_underlays()
+
+/obj/machinery/atmospherics/unary/vent_scrubber/receive_signal(datum/signal/signal)
+ if(stat & (NOPOWER|BROKEN))
+ return
+ if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command"))
+ return 0
+
+ if(signal.data["power"] != null)
+ use_power = text2num(signal.data["power"])
+ if(signal.data["power_toggle"] != null)
+ use_power = !use_power
+
+ if(signal.data["panic_siphon"]) //must be before if("scrubbing" thing
+ panic = text2num(signal.data["panic_siphon"])
+ if(panic)
+ use_power = 1
+ scrubbing = 0
+ else
+ scrubbing = 1
+ if(signal.data["toggle_panic_siphon"] != null)
+ panic = !panic
+ if(panic)
+ use_power = 1
+ scrubbing = 0
+ else
+ scrubbing = 1
+
+ if(signal.data["scrubbing"] != null)
+ scrubbing = text2num(signal.data["scrubbing"])
+ if(scrubbing)
+ panic = 0
+ if(signal.data["toggle_scrubbing"])
+ scrubbing = !scrubbing
+ if(scrubbing)
+ panic = 0
+
+ var/list/toggle = list()
+
+ if(!isnull(signal.data["o2_scrub"]) && text2num(signal.data["o2_scrub"]) != ("oxygen" in scrubbing_gas))
+ toggle += "oxygen"
+ else if(signal.data["toggle_o2_scrub"])
+ toggle += "oxygen"
+
+ if(!isnull(signal.data["n2_scrub"]) && text2num(signal.data["n2_scrub"]) != ("nitrogen" in scrubbing_gas))
+ toggle += "nitrogen"
+ else if(signal.data["toggle_n2_scrub"])
+ toggle += "nitrogen"
+
+ if(!isnull(signal.data["co2_scrub"]) && text2num(signal.data["co2_scrub"]) != ("carbon_dioxide" in scrubbing_gas))
+ toggle += "carbon_dioxide"
+ else if(signal.data["toggle_co2_scrub"])
+ toggle += "carbon_dioxide"
+
+ if(!isnull(signal.data["tox_scrub"]) && text2num(signal.data["tox_scrub"]) != ("phoron" in scrubbing_gas))
+ toggle += "phoron"
+ else if(signal.data["toggle_tox_scrub"])
+ toggle += "phoron"
+
+ if(!isnull(signal.data["n2o_scrub"]) && text2num(signal.data["n2o_scrub"]) != ("sleeping_agent" in scrubbing_gas))
+ toggle += "sleeping_agent"
+ else if(signal.data["toggle_n2o_scrub"])
+ toggle += "sleeping_agent"
+
+ scrubbing_gas ^= toggle
+
+ if(signal.data["init"] != null)
+ name = signal.data["init"]
+ return
+
+ if(signal.data["status"] != null)
+ addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
+ return //do not update_icon
+
+// log_debug("DEBUG \[[world.timeofday]\]: vent_scrubber/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]")
+ addtimer(CALLBACK(src, .proc/broadcast_status), 2, TIMER_UNIQUE)
+ update_icon()
+ return
+
+/obj/machinery/atmospherics/unary/vent_scrubber/power_change()
+ var/old_stat = stat
+ ..()
+ if(old_stat != stat)
+ update_icon()
+
+/obj/machinery/atmospherics/unary/vent_scrubber/attackby(var/obj/item/W as obj, var/mob/user as mob)
+ if (W.iswrench())
+ if (!(stat & NOPOWER) && use_power)
+ to_chat(user, span("warning", "You cannot unwrench \the [src], turn it off first."))
+ return 1
+ var/turf/T = src.loc
+ if (node && node.level==1 && isturf(T) && !T.is_plating())
+ to_chat(user, span("warning", "You must remove the plating first."))
+ return 1
+ var/datum/gas_mixture/int_air = return_air()
+ var/datum/gas_mixture/env_air = loc.return_air()
+ if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
+ to_chat(user, span("warning", "You cannot unwrench \the [src], it is too exerted due to internal pressure."))
+ add_fingerprint(user)
+ return 1
+ playsound(src.loc, W.usesound, 50, 1)
+ to_chat(user, span("notice", "You begin to unfasten \the [src]..."))
+ if (do_after(user, 40/W.toolspeed, act_target = src))
+ user.visible_message( \
+ span("notice", "\The [user] unfastens \the [src]."), \
+ span("notice", "You have unfastened \the [src]."), \
+ "You hear a ratchet.")
+ new /obj/item/pipe(loc, make_from=src)
+ qdel(src)
+ return 1
+
+ if(W.iswelder())
+ var/obj/item/weldingtool/WT = W
+ if (!WT.welding)
+ to_chat(user, span("danger", "\The [WT] must be turned on!"))
+ else if (WT.remove_fuel(0,user))
+ to_chat(user, span("notice", "Now welding \the [src]."))
+ playsound(src, 'sound/items/Welder.ogg', 50, 1)
+ if(do_after(user, 20/W.toolspeed, act_target = src))
+ if(!src || !WT.isOn())
+ return
+ welded = !welded
+ update_icon()
+ playsound(src, 'sound/items/Welder2.ogg', 50, 1)
+ user.visible_message(span("notice", "\The [user] [welded ? "welds \the [src] shut" : "unwelds \the [src]"]."), \
+ span("notice", "You [welded ? "weld \the [src] shut" : "unweld \the [src]"]."), \
+ "You hear welding.")
+ else
+ to_chat(user, span("notice", "You fail to complete the welding."))
+ else
+ to_chat(user, span("warning", "You need more welding fuel to complete this task."))
+ return 1
+ return ..()
+
+/obj/machinery/atmospherics/unary/vent_scrubber/examine(mob/user)
+ if(..(user, 1))
+ to_chat(user, "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W")
+ else
+ to_chat(user, "You are too far away to read the gauge.")
+ if(welded)
+ to_chat(user, "It seems welded shut.")
+
+
diff --git a/code/ATMOSPHERICS/components/valve.dm b/code/ATMOSPHERICS/components/valve.dm
index 796cecc5c71..9d985828ca0 100644
--- a/code/ATMOSPHERICS/components/valve.dm
+++ b/code/ATMOSPHERICS/components/valve.dm
@@ -1,326 +1,326 @@
-/obj/machinery/atmospherics/valve
- icon = 'icons/atmos/valve.dmi'
- icon_state = "map_valve0"
-
- name = "manual valve"
- desc = "A pipe valve"
-
- level = 1
- dir = SOUTH
- initialize_directions = SOUTH|NORTH
-
- var/open = 0
- var/openDuringInit = 0
-
- var/datum/pipe_network/network_node1
- var/datum/pipe_network/network_node2
-
-/obj/machinery/atmospherics/valve/open
- open = 1
- icon_state = "map_valve1"
-
-/obj/machinery/atmospherics/valve/update_icon(animation)
- if(animation)
- flick("valve[src.open][!src.open]",src)
- else
- icon_state = "valve[open]"
-
-/obj/machinery/atmospherics/valve/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- add_underlay(T, node1, get_dir(src, node1))
- add_underlay(T, node2, get_dir(src, node2))
-
-/obj/machinery/atmospherics/valve/hide(var/i)
- update_underlays()
-
-/obj/machinery/atmospherics/valve/Initialize()
- switch(dir)
- if(NORTH || SOUTH)
- initialize_directions = NORTH|SOUTH
- if(EAST || WEST)
- initialize_directions = EAST|WEST
- . = ..()
-
-/obj/machinery/atmospherics/valve/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
- if(reference == node1)
- network_node1 = new_network
- if(open)
- network_node2 = new_network
- else if(reference == node2)
- network_node2 = new_network
- if(open)
- network_node1 = new_network
-
- if(new_network.normal_members.Find(src))
- return 0
-
- new_network.normal_members += src
-
- if(open)
- if(reference == node1)
- if(node2)
- return node2.network_expand(new_network, src)
- else if(reference == node2)
- if(node1)
- return node1.network_expand(new_network, src)
-
- return null
-
-/obj/machinery/atmospherics/valve/Destroy()
- loc = null
-
- if(node1)
- node1.disconnect(src)
- qdel(network_node1)
- if(node2)
- node2.disconnect(src)
- qdel(network_node2)
-
- node1 = null
- node2 = null
-
- return ..()
-
-/obj/machinery/atmospherics/valve/proc/open()
- if(open) return 0
-
- open = 1
- update_icon()
-
- if(network_node1&&network_node2)
- network_node1.merge(network_node2)
- network_node2 = network_node1
-
- if(network_node1)
- network_node1.update = 1
- else if(network_node2)
- network_node2.update = 1
-
- return 1
-
-/obj/machinery/atmospherics/valve/proc/close()
- if(!open)
- return 0
-
- open = 0
- update_icon()
-
- if(network_node1)
- qdel(network_node1)
- if(network_node2)
- qdel(network_node2)
-
- build_network()
-
- return 1
-
-/obj/machinery/atmospherics/valve/proc/normalize_dir()
- if(dir==3)
- set_dir(1)
- else if(dir==12)
- set_dir(4)
-
-/obj/machinery/atmospherics/valve/attack_ai(mob/user as mob)
- return
-
-/obj/machinery/atmospherics/valve/attack_hand(mob/user as mob)
- src.add_fingerprint(usr)
- update_icon(1)
- sleep(10)
- if (src.open)
- src.close()
- else
- src.open()
-
-/obj/machinery/atmospherics/valve/machinery_process()
- ..()
- return PROCESS_KILL
-
-/obj/machinery/atmospherics/valve/atmos_init()
- normalize_dir()
-
- var/node1_dir
- var/node2_dir
-
- for(var/direction in cardinal)
- if(direction&initialize_directions)
- if (!node1_dir)
- node1_dir = direction
- else if (!node2_dir)
- node2_dir = direction
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node1 = target
- break
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node2 = target
- break
-
- build_network()
-
- queue_icon_update()
- update_underlays()
-
- if(openDuringInit)
- close()
- open()
- openDuringInit = 0
-
-/obj/machinery/atmospherics/valve/build_network()
- if(!network_node1 && node1)
- network_node1 = new /datum/pipe_network()
- network_node1.normal_members += src
- network_node1.build_network(node1, src)
-
- if(!network_node2 && node2)
- network_node2 = new /datum/pipe_network()
- network_node2.normal_members += src
- network_node2.build_network(node2, src)
-
-/obj/machinery/atmospherics/valve/return_network(obj/machinery/atmospherics/reference)
- build_network()
-
- if(reference==node1)
- return network_node1
-
- if(reference==node2)
- return network_node2
-
- return null
-
-/obj/machinery/atmospherics/valve/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
- if(network_node1 == old_network)
- network_node1 = new_network
- if(network_node2 == old_network)
- network_node2 = new_network
-
- return 1
-
-/obj/machinery/atmospherics/valve/return_network_air(datum/network/reference)
- return null
-
-/obj/machinery/atmospherics/valve/disconnect(obj/machinery/atmospherics/reference)
- if(reference==node1)
- qdel(network_node1)
- node1 = null
-
- else if(reference==node2)
- qdel(network_node2)
- node2 = null
-
- update_underlays()
-
- return null
-
-/obj/machinery/atmospherics/valve/digital // can be controlled by AI
- name = "digital valve"
- desc = "A digitally controlled valve."
- icon = 'icons/atmos/digital_valve.dmi'
-
- var/frequency = 0
- var/id = null
- var/datum/radio_frequency/radio_connection
-
-/obj/machinery/atmospherics/valve/digital/attack_ai(mob/user as mob)
- return src.attack_hand(user)
-
-/obj/machinery/atmospherics/valve/digital/attack_hand(mob/user as mob)
- if(!powered())
- return
- if(!src.allowed(user))
- to_chat(user, "Access denied.")
- return
- ..()
-
- log_and_message_admins("has [open ? "OPENED" : "closed"] [name].", user)
-
-/obj/machinery/atmospherics/valve/digital/AltClick(var/mob/abstract/observer/admin)
- if (istype(admin))
- if (admin.client && admin.client.holder && ((R_MOD|R_ADMIN) & admin.client.holder.rights))
- if (open)
- close()
- else
- if (alert(admin, "The valve is currently closed. Do you want to open it?", "Open the valve?", "Yes", "No") == "No")
- return
- open()
-
- log_and_message_admins("has [open ? "opened" : "closed"] [name].", admin)
-
-/obj/machinery/atmospherics/valve/digital/open
- open = 1
- icon_state = "map_valve1"
-
-/obj/machinery/atmospherics/valve/digital/power_change()
- var/old_stat = stat
- ..()
- if(old_stat != stat)
- queue_icon_update()
-
-/obj/machinery/atmospherics/valve/digital/update_icon()
- ..()
- if(!powered())
- icon_state = "valve[open]nopower"
-
-/obj/machinery/atmospherics/valve/digital/proc/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- if(frequency)
- radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
-
-/obj/machinery/atmospherics/valve/digital/atmos_init()
- ..()
- if(frequency)
- set_frequency(frequency)
-
-/obj/machinery/atmospherics/valve/digital/receive_signal(datum/signal/signal)
- if(!signal.data["tag"] || (signal.data["tag"] != id))
- return 0
-
- switch(signal.data["command"])
- if("valve_open")
- if(!open)
- open()
-
- if("valve_close")
- if(open)
- close()
-
- if("valve_toggle")
- if(open)
- close()
- else
- open()
-
-/obj/machinery/atmospherics/valve/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
- if (!W.iswrench())
- return ..()
- if (istype(src, /obj/machinery/atmospherics/valve/digital))
- to_chat(user, "You cannot unwrench \the [src], it's too complicated.")
- return 1
- var/datum/gas_mixture/int_air = return_air()
- var/datum/gas_mixture/env_air = loc.return_air()
- if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
- to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
- add_fingerprint(user)
- return 1
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
- if (do_after(user, 40, act_target = src))
- user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
- "You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
-
-/obj/machinery/atmospherics/valve/examine(mob/user)
- ..()
- to_chat(user, "It is [open ? "open" : "closed"].")
+/obj/machinery/atmospherics/valve
+ icon = 'icons/atmos/valve.dmi'
+ icon_state = "map_valve0"
+
+ name = "manual valve"
+ desc = "A pipe valve"
+
+ level = 1
+ dir = SOUTH
+ initialize_directions = SOUTH|NORTH
+
+ var/open = 0
+ var/openDuringInit = 0
+
+ var/datum/pipe_network/network_node1
+ var/datum/pipe_network/network_node2
+
+/obj/machinery/atmospherics/valve/open
+ open = 1
+ icon_state = "map_valve1"
+
+/obj/machinery/atmospherics/valve/update_icon(animation)
+ if(animation)
+ flick("valve[src.open][!src.open]",src)
+ else
+ icon_state = "valve[open]"
+
+/obj/machinery/atmospherics/valve/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ add_underlay(T, node1, get_dir(src, node1))
+ add_underlay(T, node2, get_dir(src, node2))
+
+/obj/machinery/atmospherics/valve/hide(var/i)
+ update_underlays()
+
+/obj/machinery/atmospherics/valve/Initialize()
+ switch(dir)
+ if(NORTH || SOUTH)
+ initialize_directions = NORTH|SOUTH
+ if(EAST || WEST)
+ initialize_directions = EAST|WEST
+ . = ..()
+
+/obj/machinery/atmospherics/valve/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
+ if(reference == node1)
+ network_node1 = new_network
+ if(open)
+ network_node2 = new_network
+ else if(reference == node2)
+ network_node2 = new_network
+ if(open)
+ network_node1 = new_network
+
+ if(new_network.normal_members.Find(src))
+ return 0
+
+ new_network.normal_members += src
+
+ if(open)
+ if(reference == node1)
+ if(node2)
+ return node2.network_expand(new_network, src)
+ else if(reference == node2)
+ if(node1)
+ return node1.network_expand(new_network, src)
+
+ return null
+
+/obj/machinery/atmospherics/valve/Destroy()
+ loc = null
+
+ if(node1)
+ node1.disconnect(src)
+ qdel(network_node1)
+ if(node2)
+ node2.disconnect(src)
+ qdel(network_node2)
+
+ node1 = null
+ node2 = null
+
+ return ..()
+
+/obj/machinery/atmospherics/valve/proc/open()
+ if(open) return 0
+
+ open = 1
+ update_icon()
+
+ if(network_node1&&network_node2)
+ network_node1.merge(network_node2)
+ network_node2 = network_node1
+
+ if(network_node1)
+ network_node1.update = 1
+ else if(network_node2)
+ network_node2.update = 1
+
+ return 1
+
+/obj/machinery/atmospherics/valve/proc/close()
+ if(!open)
+ return 0
+
+ open = 0
+ update_icon()
+
+ if(network_node1)
+ qdel(network_node1)
+ if(network_node2)
+ qdel(network_node2)
+
+ build_network()
+
+ return 1
+
+/obj/machinery/atmospherics/valve/proc/normalize_dir()
+ if(dir==3)
+ set_dir(1)
+ else if(dir==12)
+ set_dir(4)
+
+/obj/machinery/atmospherics/valve/attack_ai(mob/user as mob)
+ return
+
+/obj/machinery/atmospherics/valve/attack_hand(mob/user as mob)
+ src.add_fingerprint(usr)
+ update_icon(1)
+ sleep(10)
+ if (src.open)
+ src.close()
+ else
+ src.open()
+
+/obj/machinery/atmospherics/valve/machinery_process()
+ ..()
+ return PROCESS_KILL
+
+/obj/machinery/atmospherics/valve/atmos_init()
+ normalize_dir()
+
+ var/node1_dir
+ var/node2_dir
+
+ for(var/direction in cardinal)
+ if(direction&initialize_directions)
+ if (!node1_dir)
+ node1_dir = direction
+ else if (!node2_dir)
+ node2_dir = direction
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node1 = target
+ break
+ for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node2 = target
+ break
+
+ build_network()
+
+ queue_icon_update()
+ update_underlays()
+
+ if(openDuringInit)
+ close()
+ open()
+ openDuringInit = 0
+
+/obj/machinery/atmospherics/valve/build_network()
+ if(!network_node1 && node1)
+ network_node1 = new /datum/pipe_network()
+ network_node1.normal_members += src
+ network_node1.build_network(node1, src)
+
+ if(!network_node2 && node2)
+ network_node2 = new /datum/pipe_network()
+ network_node2.normal_members += src
+ network_node2.build_network(node2, src)
+
+/obj/machinery/atmospherics/valve/return_network(obj/machinery/atmospherics/reference)
+ build_network()
+
+ if(reference==node1)
+ return network_node1
+
+ if(reference==node2)
+ return network_node2
+
+ return null
+
+/obj/machinery/atmospherics/valve/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
+ if(network_node1 == old_network)
+ network_node1 = new_network
+ if(network_node2 == old_network)
+ network_node2 = new_network
+
+ return 1
+
+/obj/machinery/atmospherics/valve/return_network_air(datum/pipe_network/reference)
+ return null
+
+/obj/machinery/atmospherics/valve/disconnect(obj/machinery/atmospherics/reference)
+ if(reference==node1)
+ qdel(network_node1)
+ node1 = null
+
+ else if(reference==node2)
+ qdel(network_node2)
+ node2 = null
+
+ update_underlays()
+
+ return null
+
+/obj/machinery/atmospherics/valve/digital // can be controlled by AI
+ name = "digital valve"
+ desc = "A digitally controlled valve."
+ icon = 'icons/atmos/digital_valve.dmi'
+
+ var/frequency = 0
+ var/id = null
+ var/datum/radio_frequency/radio_connection
+
+/obj/machinery/atmospherics/valve/digital/attack_ai(mob/user as mob)
+ return src.attack_hand(user)
+
+/obj/machinery/atmospherics/valve/digital/attack_hand(mob/user as mob)
+ if(!powered())
+ return
+ if(!src.allowed(user))
+ to_chat(user, "Access denied.")
+ return
+ ..()
+
+ log_and_message_admins("has [open ? "OPENED" : "closed"] [name].", user)
+
+/obj/machinery/atmospherics/valve/digital/AltClick(var/mob/abstract/observer/admin)
+ if (istype(admin))
+ if (admin.client && admin.client.holder && ((R_MOD|R_ADMIN) & admin.client.holder.rights))
+ if (open)
+ close()
+ else
+ if (alert(admin, "The valve is currently closed. Do you want to open it?", "Open the valve?", "Yes", "No") == "No")
+ return
+ open()
+
+ log_and_message_admins("has [open ? "opened" : "closed"] [name].", admin)
+
+/obj/machinery/atmospherics/valve/digital/open
+ open = 1
+ icon_state = "map_valve1"
+
+/obj/machinery/atmospherics/valve/digital/power_change()
+ var/old_stat = stat
+ ..()
+ if(old_stat != stat)
+ queue_icon_update()
+
+/obj/machinery/atmospherics/valve/digital/update_icon()
+ ..()
+ if(!powered())
+ icon_state = "valve[open]nopower"
+
+/obj/machinery/atmospherics/valve/digital/proc/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ if(frequency)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
+
+/obj/machinery/atmospherics/valve/digital/atmos_init()
+ ..()
+ if(frequency)
+ set_frequency(frequency)
+
+/obj/machinery/atmospherics/valve/digital/receive_signal(datum/signal/signal)
+ if(!signal.data["tag"] || (signal.data["tag"] != id))
+ return 0
+
+ switch(signal.data["command"])
+ if("valve_open")
+ if(!open)
+ open()
+
+ if("valve_close")
+ if(open)
+ close()
+
+ if("valve_toggle")
+ if(open)
+ close()
+ else
+ open()
+
+/obj/machinery/atmospherics/valve/attackby(var/obj/item/W as obj, var/mob/user as mob)
+ if (!W.iswrench())
+ return ..()
+ if (istype(src, /obj/machinery/atmospherics/valve/digital))
+ to_chat(user, "You cannot unwrench \the [src], it's too complicated.")
+ return 1
+ var/datum/gas_mixture/int_air = return_air()
+ var/datum/gas_mixture/env_air = loc.return_air()
+ if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
+ to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
+ add_fingerprint(user)
+ return 1
+ playsound(src.loc, W.usesound, 50, 1)
+ to_chat(user, "You begin to unfasten \the [src]...")
+ if (do_after(user, 40/W.toolspeed, act_target = src))
+ user.visible_message( \
+ "\The [user] unfastens \the [src].", \
+ "You have unfastened \the [src].", \
+ "You hear a ratchet.")
+ new /obj/item/pipe(loc, make_from=src)
+ qdel(src)
+
+/obj/machinery/atmospherics/valve/examine(mob/user)
+ ..()
+ to_chat(user, "It is [open ? "open" : "closed"].")
diff --git a/code/ATMOSPHERICS/datum_pipe_network.dm b/code/ATMOSPHERICS/datum_pipe_network.dm
index e952364cb33..634c04f9e0e 100644
--- a/code/ATMOSPHERICS/datum_pipe_network.dm
+++ b/code/ATMOSPHERICS/datum_pipe_network.dm
@@ -1,91 +1,91 @@
-/datum/pipe_network
- var/list/datum/gas_mixture/gases = list() //All of the gas_mixtures continuously connected in this network
- var/volume = 0 //caches the total volume for atmos machines to use in gas calculations
-
- var/list/obj/machinery/atmospherics/normal_members = list()
- var/list/datum/pipeline/line_members = list()
- //membership roster to go through for updates and what not
-
- var/update = 1
- //var/datum/gas_mixture/air_transient = null
-
-/*
-/datum/pipe_network/New()
- //air_transient = new()
-
- ..()*/
-
-/datum/pipe_network/process()
- //Equalize gases amongst pipe if called for
- if(update)
- update = 0
- reconcile_air() //equalize_gases(gases)
-
- //Give pipelines their process call for pressure checking and what not. Have to remove pressure checks for the time being as pipes dont radiate heat - Mport
- //for(var/datum/pipeline/line_member in line_members)
- // line_member.process()
-
-/datum/pipe_network/proc/build_network(obj/machinery/atmospherics/start_normal, obj/machinery/atmospherics/reference)
- //Purpose: Generate membership roster
- //Notes: Assuming that members will add themselves to appropriate roster in network_expand()
-
- if(!start_normal)
- qdel(src)
-
- start_normal.network_expand(src, reference)
-
- update_network_gases()
-
- if((normal_members.len>0)||(line_members.len>0))
- START_PROCESSING(SSpipenet, src)
- else
- qdel(src)
-
-/datum/pipe_network/proc/merge(datum/pipe_network/giver)
- if(giver==src) return 0
-
- normal_members |= giver.normal_members
-
- line_members |= giver.line_members
-
- for(var/obj/machinery/atmospherics/normal_member in giver.normal_members)
- normal_member.reassign_network(giver, src)
-
- for(var/datum/pipeline/line_member in giver.line_members)
- line_member.network = src
-
- update_network_gases()
- return 1
-
-/datum/pipe_network/proc/update_network_gases()
- //Go through membership roster and make sure gases is up to date
-
- gases = list()
- volume = 0
-
- for(var/obj/machinery/atmospherics/normal_member in normal_members)
- var/result = normal_member.return_network_air(src)
- if(result) gases += result
-
- for(var/datum/pipeline/line_member in line_members)
- gases += line_member.air
-
- for(var/datum/gas_mixture/air in gases)
- volume += air.volume
-
-/datum/pipe_network/proc/reconcile_air()
- equalize_gases(gases)
-
-/datum/pipe_network/Destroy(force = FALSE)
- STOP_PROCESSING(SSpipenet, src)
- for (var/datum/pipeline/pipeline in line_members)
- pipeline.network = null
-
- line_members = null
-
- for (var/obj/machinery/atmospherics/thing in normal_members)
- thing.remove_network(src)
-
- normal_members = null
-
- return ..()
+/datum/pipe_network
+ var/list/datum/gas_mixture/gases = list() //All of the gas_mixtures continuously connected in this network
+ var/volume = 0 //caches the total volume for atmos machines to use in gas calculations
+
+ var/list/obj/machinery/atmospherics/normal_members = list()
+ var/list/datum/pipeline/line_members = list()
+ //membership roster to go through for updates and what not
+
+ var/update = 1
+ //var/datum/gas_mixture/air_transient = null
+
+/*
+/datum/pipe_network/New()
+ //air_transient = new()
+
+ ..()*/
+
+/datum/pipe_network/process()
+ //Equalize gases amongst pipe if called for
+ if(update)
+ update = 0
+ reconcile_air() //equalize_gases(gases)
+
+ //Give pipelines their process call for pressure checking and what not. Have to remove pressure checks for the time being as pipes dont radiate heat - Mport
+ //for(var/datum/pipeline/line_member in line_members)
+ // line_member.process()
+
+/datum/pipe_network/proc/build_network(obj/machinery/atmospherics/start_normal, obj/machinery/atmospherics/reference)
+ //Purpose: Generate membership roster
+ //Notes: Assuming that members will add themselves to appropriate roster in network_expand()
+
+ if(!start_normal)
+ qdel(src)
+
+ start_normal.network_expand(src, reference)
+
+ update_network_gases()
+
+ if((normal_members.len>0)||(line_members.len>0))
+ START_PROCESSING(SSpipenet, src)
+ else
+ qdel(src)
+
+/datum/pipe_network/proc/merge(datum/pipe_network/giver)
+ if(giver==src) return 0
+
+ normal_members |= giver.normal_members
+
+ line_members |= giver.line_members
+
+ for(var/obj/machinery/atmospherics/normal_member in giver.normal_members)
+ normal_member.reassign_network(giver, src)
+
+ for(var/datum/pipeline/line_member in giver.line_members)
+ line_member.network = src
+
+ update_network_gases()
+ return 1
+
+/datum/pipe_network/proc/update_network_gases()
+ //Go through membership roster and make sure gases is up to date
+
+ gases = list()
+ volume = 0
+
+ for(var/obj/machinery/atmospherics/normal_member in normal_members)
+ var/result = normal_member.return_network_air(src)
+ if(result) gases += result
+
+ for(var/datum/pipeline/line_member in line_members)
+ gases += line_member.air
+
+ for(var/datum/gas_mixture/air in gases)
+ volume += air.volume
+
+/datum/pipe_network/proc/reconcile_air()
+ equalize_gases(gases)
+
+/datum/pipe_network/Destroy(force = FALSE)
+ STOP_PROCESSING(SSpipenet, src)
+ for (var/datum/pipeline/pipeline in line_members)
+ pipeline.network = null
+
+ line_members = null
+
+ for (var/obj/machinery/atmospherics/thing in normal_members)
+ thing.reassign_network(src, null)
+
+ normal_members = null
+
+ return ..()
diff --git a/code/ATMOSPHERICS/datum_pipeline.dm b/code/ATMOSPHERICS/datum_pipeline.dm
index de600d78a0b..63fe30225d9 100644
--- a/code/ATMOSPHERICS/datum_pipeline.dm
+++ b/code/ATMOSPHERICS/datum_pipeline.dm
@@ -1,218 +1,220 @@
-
-/datum/pipeline
- var/datum/gas_mixture/air
-
- var/list/obj/machinery/atmospherics/pipe/members
- var/list/obj/machinery/atmospherics/pipe/edges //Used for building networks
-
- var/datum/pipe_network/network
-
- var/alert_pressure = 0
-
-/datum/pipeline/Destroy()
- if(network)
- QDEL_NULL(network)
-
- if(air && air.volume)
- temporarily_store_air()
- QDEL_NULL(air)
-
- for (var/obj/machinery/atmospherics/pipe/thing in members)
- thing.parent = null
-
- return ..()
-
-/datum/pipeline/process()//This use to be called called from the pipe networks
- //Check to see if pressure is within acceptable limits
- var/pressure = air.return_pressure()
- if(pressure > alert_pressure)
- for(var/obj/machinery/atmospherics/pipe/member in members)
- if(!member.check_pressure(pressure))
- break //Only delete 1 pipe per process
-
-/datum/pipeline/proc/temporarily_store_air()
- //Update individual gas_mixtures by volume ratio
-
- for(var/obj/machinery/atmospherics/pipe/member in members)
- member.air_temporary = new
- member.air_temporary.copy_from(air)
- member.air_temporary.volume = member.volume
- member.air_temporary.multiply(member.volume / air.volume)
-
-/datum/pipeline/proc/build_pipeline(obj/machinery/atmospherics/pipe/base)
- air = new
-
- var/list/possible_expansions = list(base)
- members = list(base)
- edges = list()
-
- var/volume = base.volume
- base.parent = src
- alert_pressure = base.alert_pressure
-
- if(base.air_temporary)
- air = base.air_temporary
- base.air_temporary = null
- else
- air = new
-
- while(possible_expansions.len>0)
- for(var/obj/machinery/atmospherics/pipe/borderline in possible_expansions)
-
- var/list/result = borderline.pipeline_expansion()
- var/edge_check = result.len
-
- if(result.len>0)
- for(var/obj/machinery/atmospherics/pipe/item in result)
- if(!members.Find(item))
- members += item
- possible_expansions += item
-
- volume += item.volume
- item.parent = src
-
- alert_pressure = min(alert_pressure, item.alert_pressure)
-
- if(item.air_temporary)
- air.merge(item.air_temporary)
-
- edge_check--
-
- if(edge_check>0)
- edges += borderline
-
- possible_expansions -= borderline
-
- air.volume = volume
-
-/datum/pipeline/proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
-
- if(new_network.line_members.Find(src))
- return 0
-
- new_network.line_members += src
-
- network = new_network
-
- for(var/obj/machinery/atmospherics/pipe/edge in edges)
- for(var/obj/machinery/atmospherics/result in edge.pipeline_expansion())
- if(!istype(result,/obj/machinery/atmospherics/pipe) && (result!=reference))
- result.network_expand(new_network, edge)
-
- return 1
-
-/datum/pipeline/proc/return_network(obj/machinery/atmospherics/reference)
- if(!network)
- network = new /datum/pipe_network
- network.build_network(src, null)
- //technically passing these parameters should not be allowed
- //however pipe_network.build_network(..) and pipeline.network_extend(...)
- // were setup to properly handle this case
-
- return network
-
-/datum/pipeline/proc/mingle_with_turf(turf/simulated/target, mingle_volume)
- var/datum/gas_mixture/air_sample = air.remove_ratio(mingle_volume/air.volume)
- air_sample.volume = mingle_volume
-
- if(istype(target) && target.zone)
- //Have to consider preservation of group statuses
- var/datum/gas_mixture/turf_copy = new
-
- turf_copy.copy_from(target.zone.air)
- turf_copy.volume = target.zone.air.volume //Copy a good representation of the turf from parent group
-
- equalize_gases(list(air_sample, turf_copy))
- air.merge(air_sample)
-
- turf_copy.subtract(target.zone.air)
-
- target.zone.air.merge(turf_copy)
-
- else
- var/datum/gas_mixture/turf_air = target.return_air()
-
- equalize_gases(list(air_sample, turf_air))
- air.merge(air_sample)
- //turf_air already modified by equalize_gases()
-
- if(network)
- network.update = 1
-
-/datum/pipeline/proc/temperature_interact(turf/target, share_volume, thermal_conductivity)
- var/total_heat_capacity = air.heat_capacity()
- var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume)
-
- if(istype(target, /turf/simulated))
- var/turf/simulated/modeled_location = target
-
- if(modeled_location.blocks_air)
-
- if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0))
- var/delta_temperature = air.temperature - modeled_location.temperature
-
- var/heat = thermal_conductivity*delta_temperature* \
- (partial_heat_capacity*modeled_location.heat_capacity/(partial_heat_capacity+modeled_location.heat_capacity))
-
- air.temperature -= heat/total_heat_capacity
- modeled_location.temperature += heat/modeled_location.heat_capacity
-
- else
- var/delta_temperature = 0
- var/sharer_heat_capacity = 0
-
- if(modeled_location.zone)
- delta_temperature = (air.temperature - modeled_location.zone.air.temperature)
- sharer_heat_capacity = modeled_location.zone.air.heat_capacity()
- else
- delta_temperature = (air.temperature - modeled_location.air.temperature)
- sharer_heat_capacity = modeled_location.air.heat_capacity()
-
- var/self_temperature_delta = 0
- var/sharer_temperature_delta = 0
-
- if((sharer_heat_capacity>0) && (partial_heat_capacity>0))
- var/heat = thermal_conductivity*delta_temperature* \
- (partial_heat_capacity*sharer_heat_capacity/(partial_heat_capacity+sharer_heat_capacity))
-
- self_temperature_delta = -heat/total_heat_capacity
- sharer_temperature_delta = heat/sharer_heat_capacity
- else
- return 1
-
- air.temperature += self_temperature_delta
-
- if(modeled_location.zone)
- modeled_location.zone.air.temperature += sharer_temperature_delta/modeled_location.zone.air.group_multiplier
- else
- modeled_location.air.temperature += sharer_temperature_delta
-
-
- else
- if((target.heat_capacity>0) && (partial_heat_capacity>0))
- var/delta_temperature = air.temperature - target.temperature
-
- var/heat = thermal_conductivity*delta_temperature* \
- (partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity))
-
- air.temperature -= heat/total_heat_capacity
- if(network)
- network.update = 1
-
- //surface must be the surface area in m^2
-/datum/pipeline/proc/radiate_heat_to_space(surface, thermal_conductivity)
- var/gas_density = air.total_moles/air.volume
- thermal_conductivity *= min(gas_density / ( RADIATOR_OPTIMUM_PRESSURE/(R_IDEAL_GAS_EQUATION*GAS_CRITICAL_TEMPERATURE) ), 1) //mult by density ratio
-
- // We only get heat from the star on the exposed surface area.
- // If the HE pipes gain more energy from AVERAGE_SOLAR_RADIATION than they can radiate, then they have a net heat increase.
- var/heat_gain = AVERAGE_SOLAR_RADIATION * (RADIATOR_EXPOSED_SURFACE_AREA_RATIO * surface) * thermal_conductivity
-
- // Previously, the temperature would enter equilibrium at 26C or 294K.
- // Only would happen if both sides (all 2 square meters of surface area) were exposed to sunlight. We now assume it aligned edge on.
- // It currently should stabilise at 129.6K or -143.6C
- heat_gain -= surface * STEFAN_BOLTZMANN_CONSTANT * thermal_conductivity * (air.temperature - COSMIC_RADIATION_TEMPERATURE) ** 4
-
- air.add_thermal_energy(heat_gain)
- if(network)
- network.update = 1
+
+/datum/pipeline
+ var/datum/gas_mixture/air
+
+ var/list/obj/machinery/atmospherics/pipe/members
+ var/list/obj/machinery/atmospherics/pipe/edges //Used for building networks
+
+ var/datum/pipe_network/network
+
+ var/alert_pressure = 0
+
+/datum/pipeline/Destroy()
+ if(network)
+ QDEL_NULL(network)
+
+ if(air && air.volume)
+ temporarily_store_air()
+ QDEL_NULL(air)
+
+ for (var/obj/machinery/atmospherics/pipe/thing in members)
+ thing.parent = null
+
+ members = null
+
+ return ..()
+
+/datum/pipeline/process()//This use to be called called from the pipe networks
+ //Check to see if pressure is within acceptable limits
+ var/pressure = air.return_pressure()
+ if(pressure > alert_pressure)
+ for(var/obj/machinery/atmospherics/pipe/member in members)
+ if(!member.check_pressure(pressure))
+ break //Only delete 1 pipe per process
+
+/datum/pipeline/proc/temporarily_store_air()
+ //Update individual gas_mixtures by volume ratio
+
+ for(var/obj/machinery/atmospherics/pipe/member in members)
+ member.air_temporary = new
+ member.air_temporary.copy_from(air)
+ member.air_temporary.volume = member.volume
+ member.air_temporary.multiply(member.volume / air.volume)
+
+/datum/pipeline/proc/build_pipeline(obj/machinery/atmospherics/pipe/base)
+ air = new
+
+ var/list/possible_expansions = list(base)
+ members = list(base)
+ edges = list()
+
+ var/volume = base.volume
+ base.parent = src
+ alert_pressure = base.alert_pressure
+
+ if(base.air_temporary)
+ air = base.air_temporary
+ base.air_temporary = null
+ else
+ air = new
+
+ while(possible_expansions.len>0)
+ for(var/obj/machinery/atmospherics/pipe/borderline in possible_expansions)
+
+ var/list/result = borderline.pipeline_expansion()
+ var/edge_check = result.len
+
+ if(result.len>0)
+ for(var/obj/machinery/atmospherics/pipe/item in result)
+ if(!members.Find(item))
+ members += item
+ possible_expansions += item
+
+ volume += item.volume
+ item.parent = src
+
+ alert_pressure = min(alert_pressure, item.alert_pressure)
+
+ if(item.air_temporary)
+ air.merge(item.air_temporary)
+
+ edge_check--
+
+ if(edge_check>0)
+ edges += borderline
+
+ possible_expansions -= borderline
+
+ air.volume = volume
+
+/datum/pipeline/proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
+
+ if(new_network.line_members.Find(src))
+ return 0
+
+ new_network.line_members += src
+
+ network = new_network
+
+ for(var/obj/machinery/atmospherics/pipe/edge in edges)
+ for(var/obj/machinery/atmospherics/result in edge.pipeline_expansion())
+ if(!istype(result,/obj/machinery/atmospherics/pipe) && (result!=reference))
+ result.network_expand(new_network, edge)
+
+ return 1
+
+/datum/pipeline/proc/return_network(obj/machinery/atmospherics/reference)
+ if(!network)
+ network = new /datum/pipe_network
+ network.build_network(src, null)
+ //technically passing these parameters should not be allowed
+ //however pipe_network.build_network(..) and pipeline.network_extend(...)
+ // were setup to properly handle this case
+
+ return network
+
+/datum/pipeline/proc/mingle_with_turf(turf/simulated/target, mingle_volume)
+ var/datum/gas_mixture/air_sample = air.remove_ratio(mingle_volume/air.volume)
+ air_sample.volume = mingle_volume
+
+ if(istype(target) && target.zone)
+ //Have to consider preservation of group statuses
+ var/datum/gas_mixture/turf_copy = new
+
+ turf_copy.copy_from(target.zone.air)
+ turf_copy.volume = target.zone.air.volume //Copy a good representation of the turf from parent group
+
+ equalize_gases(list(air_sample, turf_copy))
+ air.merge(air_sample)
+
+ turf_copy.subtract(target.zone.air)
+
+ target.zone.air.merge(turf_copy)
+
+ else
+ var/datum/gas_mixture/turf_air = target.return_air()
+
+ equalize_gases(list(air_sample, turf_air))
+ air.merge(air_sample)
+ //turf_air already modified by equalize_gases()
+
+ if(network)
+ network.update = 1
+
+/datum/pipeline/proc/temperature_interact(turf/target, share_volume, thermal_conductivity)
+ var/total_heat_capacity = air.heat_capacity()
+ var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume)
+
+ if(istype(target, /turf/simulated))
+ var/turf/simulated/modeled_location = target
+
+ if(modeled_location.blocks_air)
+
+ if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0))
+ var/delta_temperature = air.temperature - modeled_location.temperature
+
+ var/heat = thermal_conductivity*delta_temperature* \
+ (partial_heat_capacity*modeled_location.heat_capacity/(partial_heat_capacity+modeled_location.heat_capacity))
+
+ air.temperature -= heat/total_heat_capacity
+ modeled_location.temperature += heat/modeled_location.heat_capacity
+
+ else
+ var/delta_temperature = 0
+ var/sharer_heat_capacity = 0
+
+ if(modeled_location.zone)
+ delta_temperature = (air.temperature - modeled_location.zone.air.temperature)
+ sharer_heat_capacity = modeled_location.zone.air.heat_capacity()
+ else
+ delta_temperature = (air.temperature - modeled_location.air.temperature)
+ sharer_heat_capacity = modeled_location.air.heat_capacity()
+
+ var/self_temperature_delta = 0
+ var/sharer_temperature_delta = 0
+
+ if((sharer_heat_capacity>0) && (partial_heat_capacity>0))
+ var/heat = thermal_conductivity*delta_temperature* \
+ (partial_heat_capacity*sharer_heat_capacity/(partial_heat_capacity+sharer_heat_capacity))
+
+ self_temperature_delta = -heat/total_heat_capacity
+ sharer_temperature_delta = heat/sharer_heat_capacity
+ else
+ return 1
+
+ air.temperature += self_temperature_delta
+
+ if(modeled_location.zone)
+ modeled_location.zone.air.temperature += sharer_temperature_delta/modeled_location.zone.air.group_multiplier
+ else
+ modeled_location.air.temperature += sharer_temperature_delta
+
+
+ else
+ if((target.heat_capacity>0) && (partial_heat_capacity>0))
+ var/delta_temperature = air.temperature - target.temperature
+
+ var/heat = thermal_conductivity*delta_temperature* \
+ (partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity))
+
+ air.temperature -= heat/total_heat_capacity
+ if(network)
+ network.update = 1
+
+ //surface must be the surface area in m^2
+/datum/pipeline/proc/radiate_heat_to_space(surface, thermal_conductivity)
+ var/gas_density = air.total_moles/air.volume
+ thermal_conductivity *= min(gas_density / ( RADIATOR_OPTIMUM_PRESSURE/(R_IDEAL_GAS_EQUATION*GAS_CRITICAL_TEMPERATURE) ), 1) //mult by density ratio
+
+ // We only get heat from the star on the exposed surface area.
+ // If the HE pipes gain more energy from AVERAGE_SOLAR_RADIATION than they can radiate, then they have a net heat increase.
+ var/heat_gain = AVERAGE_SOLAR_RADIATION * (RADIATOR_EXPOSED_SURFACE_AREA_RATIO * surface) * thermal_conductivity
+
+ // Previously, the temperature would enter equilibrium at 26C or 294K.
+ // Only would happen if both sides (all 2 square meters of surface area) were exposed to sunlight. We now assume it aligned edge on.
+ // It currently should stabilise at 129.6K or -143.6C
+ heat_gain -= surface * STEFAN_BOLTZMANN_CONSTANT * thermal_conductivity * (air.temperature - COSMIC_RADIATION_TEMPERATURE) ** 4
+
+ air.add_thermal_energy(heat_gain)
+ if(network)
+ network.update = 1
diff --git a/code/ATMOSPHERICS/he_pipes.dm b/code/ATMOSPHERICS/he_pipes.dm
index 217c89a08c4..0a1d923ed54 100644
--- a/code/ATMOSPHERICS/he_pipes.dm
+++ b/code/ATMOSPHERICS/he_pipes.dm
@@ -1,146 +1,146 @@
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging
- icon = 'icons/atmos/heat.dmi'
- icon_state = "intact"
- pipe_icon = "hepipe"
- color = "#404040"
- level = 2
- connect_types = CONNECT_TYPE_HE
- layer = 2.41
- var/initialize_directions_he
- var/surface = 2 //surface area in m^2
- var/icon_temperature = T20C //stop small changes in temperature causing an icon refresh
-
- minimum_temperature_difference = 20
- thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
-
- buckle_lying = 1
-
- // BubbleWrap
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/Initialize()
- . = ..()
- initialize_directions_he = initialize_directions // The auto-detection from /pipe is good enough for a simple HE pipe
-// BubbleWrap END
- color = "#404040" //we don't make use of the fancy overlay system for colours, use this to set the default.
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/atmos_init()
- normalize_dir()
- var/node1_dir
- var/node2_dir
-
- for(var/direction in cardinal)
- if(direction&initialize_directions_he)
- if (!node1_dir)
- node1_dir = direction
- else if (!node2_dir)
- node2_dir = direction
-
- for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,node1_dir))
- if(target.initialize_directions_he & get_dir(target,src))
- node1 = target
- break
- for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,node2_dir))
- if(target.initialize_directions_he & get_dir(target,src))
- node2 = target
- break
- if(!node1 && !node2)
- qdel(src)
- return
-
- queue_icon_update()
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/machinery_process()
- if(!parent)
- ..()
- else
- var/datum/gas_mixture/pipe_air = return_air()
- if(istype(loc, /turf/simulated/))
- var/environment_temperature = 0
- if(loc:blocks_air)
- environment_temperature = loc:temperature
- else
- var/datum/gas_mixture/environment = loc.return_air()
- environment_temperature = environment.temperature
- if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference)
- parent.temperature_interact(loc, volume, thermal_conductivity)
- else if(istype(loc, /turf/space/))
- parent.radiate_heat_to_space(surface, 1)
-
- if(buckled_mob)
- var/hc = pipe_air.heat_capacity()
- var/avg_temp = (pipe_air.temperature * hc + buckled_mob.bodytemperature * 3500) / (hc + 3500)
- pipe_air.temperature = avg_temp
- buckled_mob.bodytemperature = avg_temp
-
- var/heat_limit = 1000
-
- var/mob/living/carbon/human/H = buckled_mob
- if(istype(H) && H.species)
- heat_limit = H.species.heat_level_3
-
- if(pipe_air.temperature > heat_limit + 1)
- buckled_mob.apply_damage(4 * log(pipe_air.temperature - heat_limit), BURN, "chest", used_weapon = "Excessive Heat")
-
- //fancy radiation glowing
- if(pipe_air.temperature && (icon_temperature > 500 || pipe_air.temperature > 500)) //start glowing at 500K
- if(abs(pipe_air.temperature - icon_temperature) > 10)
- icon_temperature = pipe_air.temperature
-
- var/h_r = heat2color_r(icon_temperature)
- var/h_g = heat2color_g(icon_temperature)
- var/h_b = heat2color_b(icon_temperature)
-
- if(icon_temperature < 2000) //scale up overlay until 2000K
- var/scale = (icon_temperature - 500) / 1500
- h_r = 64 + (h_r - 64)*scale
- h_g = 64 + (h_g - 64)*scale
- h_b = 64 + (h_b - 64)*scale
-
- var/list/animate_targets = get_above_oo() + src
- for (var/thing in animate_targets)
- var/atom/movable/AM = thing
- animate(AM, color = rgb(h_r, h_g, h_b), time = 20, easing = SINE_EASING)
-
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction
- icon = 'icons/atmos/junction.dmi'
- icon_state = "intact"
- pipe_icon = "hejunction"
- level = 2
- connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_HE
- minimum_temperature_difference = 300
- thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
-
-// BubbleWrap
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/Initialize()
- . = ..()
- switch (dir)
- if (SOUTH)
- initialize_directions = NORTH
- initialize_directions_he = SOUTH
- if (NORTH)
- initialize_directions = SOUTH
- initialize_directions_he = NORTH
- if (EAST)
- initialize_directions = WEST
- initialize_directions_he = EAST
- if (WEST)
- initialize_directions = EAST
- initialize_directions_he = WEST
- // BubbleWrap END
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/atmos_init()
- for(var/obj/machinery/atmospherics/target in get_step(src,initialize_directions))
- if(target.initialize_directions & get_dir(target,src))
- node1 = target
- break
-
- for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,initialize_directions_he))
- if(target.initialize_directions_he & get_dir(target,src))
- node2 = target
- break
-
- if(!node1 && !node2)
- qdel(src)
- return
-
- queue_icon_update()
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging
+ icon = 'icons/atmos/heat.dmi'
+ icon_state = "intact"
+ pipe_icon = "hepipe"
+ color = "#404040"
+ level = 2
+ connect_types = CONNECT_TYPE_HE
+ layer = 2.41
+ var/initialize_directions_he
+ var/surface = 2 //surface area in m^2
+ var/icon_temperature = T20C //stop small changes in temperature causing an icon refresh
+
+ minimum_temperature_difference = 20
+ thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
+
+ buckle_lying = 1
+
+ // BubbleWrap
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/Initialize()
+ . = ..()
+ initialize_directions_he = initialize_directions // The auto-detection from /pipe is good enough for a simple HE pipe
+// BubbleWrap END
+ color = "#404040" //we don't make use of the fancy overlay system for colours, use this to set the default.
+
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/atmos_init()
+ normalize_dir()
+ var/node1_dir
+ var/node2_dir
+
+ for(var/direction in cardinal)
+ if(direction&initialize_directions_he)
+ if (!node1_dir)
+ node1_dir = direction
+ else if (!node2_dir)
+ node2_dir = direction
+
+ for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,node1_dir))
+ if(target.initialize_directions_he & get_dir(target,src))
+ node1 = target
+ break
+ for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,node2_dir))
+ if(target.initialize_directions_he & get_dir(target,src))
+ node2 = target
+ break
+ if(!node1 && !node2)
+ qdel(src)
+ return
+
+ queue_icon_update()
+
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/machinery_process()
+ if(!parent)
+ ..()
+ else
+ var/datum/gas_mixture/pipe_air = return_air()
+ if(istype(loc, /turf/simulated/))
+ var/environment_temperature = 0
+ if(loc:blocks_air)
+ environment_temperature = loc:temperature
+ else
+ var/datum/gas_mixture/environment = loc.return_air()
+ environment_temperature = environment.temperature
+ if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference)
+ parent.temperature_interact(loc, volume, thermal_conductivity)
+ else if(istype(loc, /turf/space/))
+ parent.radiate_heat_to_space(surface, 1)
+
+ if(buckled_mob)
+ var/hc = pipe_air.heat_capacity()
+ var/avg_temp = (pipe_air.temperature * hc + buckled_mob.bodytemperature * 3500) / (hc + 3500)
+ pipe_air.temperature = avg_temp
+ buckled_mob.bodytemperature = avg_temp
+
+ var/heat_limit = 1000
+
+ var/mob/living/carbon/human/H = buckled_mob
+ if(istype(H) && H.species)
+ heat_limit = H.species.heat_level_3
+
+ if(pipe_air.temperature > heat_limit + 1)
+ buckled_mob.apply_damage(4 * log(pipe_air.temperature - heat_limit), BURN, BP_CHEST, used_weapon = "Excessive Heat")
+
+ //fancy radiation glowing
+ if(pipe_air.temperature && (icon_temperature > 500 || pipe_air.temperature > 500)) //start glowing at 500K
+ if(abs(pipe_air.temperature - icon_temperature) > 10)
+ icon_temperature = pipe_air.temperature
+
+ var/h_r = heat2color_r(icon_temperature)
+ var/h_g = heat2color_g(icon_temperature)
+ var/h_b = heat2color_b(icon_temperature)
+
+ if(icon_temperature < 2000) //scale up overlay until 2000K
+ var/scale = (icon_temperature - 500) / 1500
+ h_r = 64 + (h_r - 64)*scale
+ h_g = 64 + (h_g - 64)*scale
+ h_b = 64 + (h_b - 64)*scale
+
+ var/list/animate_targets = get_above_oo() + src
+ for (var/thing in animate_targets)
+ var/atom/movable/AM = thing
+ animate(AM, color = rgb(h_r, h_g, h_b), time = 20, easing = SINE_EASING)
+
+
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction
+ icon = 'icons/atmos/junction.dmi'
+ icon_state = "intact"
+ pipe_icon = "hejunction"
+ level = 2
+ connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_HE
+ minimum_temperature_difference = 300
+ thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
+
+// BubbleWrap
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/Initialize()
+ . = ..()
+ switch (dir)
+ if (SOUTH)
+ initialize_directions = NORTH
+ initialize_directions_he = SOUTH
+ if (NORTH)
+ initialize_directions = SOUTH
+ initialize_directions_he = NORTH
+ if (EAST)
+ initialize_directions = WEST
+ initialize_directions_he = EAST
+ if (WEST)
+ initialize_directions = EAST
+ initialize_directions_he = WEST
+ // BubbleWrap END
+
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/atmos_init()
+ for(var/obj/machinery/atmospherics/target in get_step(src,initialize_directions))
+ if(target.initialize_directions & get_dir(target,src))
+ node1 = target
+ break
+
+ for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,initialize_directions_he))
+ if(target.initialize_directions_he & get_dir(target,src))
+ node2 = target
+ break
+
+ if(!node1 && !node2)
+ qdel(src)
+ return
+
+ queue_icon_update()
diff --git a/code/ATMOSPHERICS/mainspipe.dm b/code/ATMOSPHERICS/mainspipe.dm
index df396d81e55..635323e5df9 100644
--- a/code/ATMOSPHERICS/mainspipe.dm
+++ b/code/ATMOSPHERICS/mainspipe.dm
@@ -75,7 +75,6 @@ obj/machinery/atmospherics/mains_pipe
update_icon()
proc/burst()
- ..()
for(var/obj/machinery/atmospherics/pipe/mains_component/pipe in contents)
burst()
diff --git a/code/ATMOSPHERICS/pipes.dm b/code/ATMOSPHERICS/pipes.dm
index bc91e6e9fe2..bdb4008268e 100644
--- a/code/ATMOSPHERICS/pipes.dm
+++ b/code/ATMOSPHERICS/pipes.dm
@@ -1,1412 +1,1404 @@
-/obj/machinery/atmospherics/pipe
-
- var/datum/gas_mixture/air_temporary // used when reconstructing a pipeline that broke
- var/datum/pipeline/parent
- var/volume = 0
- force = 20
-
- layer = PIPE_LAYER
- use_power = 0
-
- var/alert_pressure = 80*ONE_ATMOSPHERE
- //minimum pressure before check_pressure(...) should be called
-
- can_buckle = 1
- buckle_require_restraints = 1
- buckle_lying = -1
-
-/obj/machinery/atmospherics/pipe/drain_power()
- return -1
-
-/obj/machinery/atmospherics/pipe/Initialize()
- if(istype(get_turf(src), /turf/simulated/wall) || istype(get_turf(src), /turf/simulated/shuttle/wall) || istype(get_turf(src), /turf/unsimulated/wall))
- level = 1
- . = ..()
-
-/obj/machinery/atmospherics/pipe/hides_under_flooring()
- return level != 2
-
-/obj/machinery/atmospherics/pipe/proc/pipeline_expansion()
- return null
-
-/obj/machinery/atmospherics/pipe/proc/check_pressure(pressure)
- //Return 1 if parent should continue checking other pipes
- //Return null if parent should stop checking other pipes. Recall: qdel(src) will by default return null
-
- return 1
-
-/obj/machinery/atmospherics/pipe/return_air()
- if(!parent)
- parent = new /datum/pipeline()
- parent.build_pipeline(src)
-
- return parent.air
-
-/obj/machinery/atmospherics/pipe/build_network()
- if(!parent)
- parent = new /datum/pipeline()
- parent.build_pipeline(src)
-
- return parent.return_network()
-
-/obj/machinery/atmospherics/pipe/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
- if(!parent)
- parent = new /datum/pipeline()
- parent.build_pipeline(src)
-
- return parent.network_expand(new_network, reference)
-
-/obj/machinery/atmospherics/pipe/return_network(obj/machinery/atmospherics/reference)
- if(!parent)
- parent = new /datum/pipeline()
- parent.build_pipeline(src)
-
- return parent.return_network(reference)
-
-/obj/machinery/atmospherics/pipe/Destroy()
- QDEL_NULL(parent)
- if(air_temporary)
- loc.assume_air(air_temporary)
- QDEL_NULL(air_temporary)
-
- return ..()
-
-/obj/machinery/atmospherics/pipe/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
- if (istype(src, /obj/machinery/atmospherics/pipe/tank))
- return ..()
- if (istype(src, /obj/machinery/atmospherics/pipe/vent))
- return ..()
-
- if(istype(W,/obj/item/device/pipe_painter))
- return 0
-
- if (!W.iswrench() && !istype(W, /obj/item/weapon/pipewrench))
- return ..()
- var/turf/T = src.loc
- if (level==1 && isturf(T) && !T.is_plating())
- to_chat(user, "You must remove the plating first.")
- return 1
- var/datum/gas_mixture/int_air = return_air()
- var/datum/gas_mixture/env_air = loc.return_air()
- if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
- if(!istype(W, /obj/item/weapon/pipewrench))
- to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
- add_fingerprint(user)
- return 1
- else
- to_chat(user, "You struggle to unwrench \the [src] with your pipe wrench.")
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
- if (do_after(user, istype(W, /obj/item/weapon/pipewrench) ? 80 : 40, act_target = src))
- user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
- "You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- for (var/obj/machinery/meter/meter in T)
- if (meter.target == src)
- new /obj/item/pipe_meter(T)
- qdel(meter)
- qdel(src)
-
-/obj/machinery/atmospherics/proc/change_color(var/new_color)
- //only pass valid pipe colors please ~otherwise your pipe will turn invisible
- if(!pipe_color_check(new_color))
- return
-
- pipe_color = new_color
- update_icon()
-
-/*
-/obj/machinery/atmospherics/pipe/add_underlay(var/obj/machinery/atmospherics/node, var/direction)
- if(istype(src, /obj/machinery/atmospherics/pipe/tank)) //todo: move tanks to unary devices
- return ..()
-
- if(node)
- var/temp_dir = get_dir(src, node)
- underlays += icon_manager.get_atmos_icon("pipe_underlay_intact", temp_dir, color_cache_name(node))
- return temp_dir
- else if(direction)
- underlays += icon_manager.get_atmos_icon("pipe_underlay_exposed", direction, pipe_color)
- else
- return null
-*/
-
-/obj/machinery/atmospherics/pipe/color_cache_name(var/obj/machinery/atmospherics/node)
- if(istype(src, /obj/machinery/atmospherics/pipe/tank))
- return ..()
-
- if(istype(node, /obj/machinery/atmospherics/pipe/manifold) || istype(node, /obj/machinery/atmospherics/pipe/manifold4w))
- if(pipe_color == node.pipe_color)
- return node.pipe_color
- else
- return null
- else if(istype(node, /obj/machinery/atmospherics/pipe/simple))
- return node.pipe_color
- else
- return pipe_color
-
-/obj/machinery/atmospherics/pipe/simple
- icon = 'icons/atmos/pipes.dmi'
- icon_state = ""
- var/pipe_icon = "" //what kind of pipe it is and from which dmi is the icon manager getting its icons, "" for simple pipes, "hepipe" for HE pipes, "hejunction" for HE junctions
- name = "pipe"
- desc = "A one meter section of regular pipe"
-
- volume = ATMOS_DEFAULT_VOLUME_PIPE
-
- dir = SOUTH
- initialize_directions = SOUTH|NORTH
-
- var/minimum_temperature_difference = 300
- var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No
-
- var/maximum_pressure = 70*ONE_ATMOSPHERE
- var/fatigue_pressure = 55*ONE_ATMOSPHERE
- alert_pressure = 55*ONE_ATMOSPHERE
-
- level = 1
- gfi_layer_rotation = GFI_ROTATION_DEFDIR
-
-/obj/machinery/atmospherics/pipe/simple/Initialize()
-
- // Pipe colors and icon states are handled by an image cache - so color and icon should
- // be null. For mapping purposes color is defined in the object definitions.
- icon = null
- alpha = 255
-
- switch(dir)
- if(SOUTH || NORTH)
- initialize_directions = SOUTH|NORTH
- if(EAST || WEST)
- initialize_directions = EAST|WEST
- if(NORTHEAST)
- initialize_directions = NORTH|EAST
- if(NORTHWEST)
- initialize_directions = NORTH|WEST
- if(SOUTHEAST)
- initialize_directions = SOUTH|EAST
- if(SOUTHWEST)
- initialize_directions = SOUTH|WEST
- . = ..()
-
-/obj/machinery/atmospherics/pipe/simple/hide(var/i)
- if(istype(loc, /turf/simulated))
- invisibility = i ? 101 : 0
- queue_icon_update()
-
-/obj/machinery/atmospherics/pipe/simple/machinery_process()
- if(!parent) //This should cut back on the overhead calling build_network thousands of times per cycle
- ..()
- else
- . = PROCESS_KILL
-
-/obj/machinery/atmospherics/pipe/simple/check_pressure(pressure)
- var/datum/gas_mixture/environment = loc.return_air()
-
- var/pressure_difference = pressure - environment.return_pressure()
-
- if(pressure_difference > maximum_pressure)
- burst()
-
- else if(pressure_difference > fatigue_pressure)
- //TODO: leak to turf, doing pfshhhhh
- if(prob(5))
- burst()
-
- else return 1
-
-/obj/machinery/atmospherics/pipe/simple/proc/burst()
- src.visible_message("\The [src] bursts!");
- playsound(src.loc, 'sound/effects/bang.ogg', 25, 1)
- var/datum/effect/effect/system/smoke_spread/smoke = new
- smoke.set_up(1,0, src.loc, 0)
- smoke.start()
- qdel(src)
-
-/obj/machinery/atmospherics/pipe/simple/proc/normalize_dir()
- if(dir==3)
- set_dir(1)
- else if(dir==12)
- set_dir(4)
-
-/obj/machinery/atmospherics/pipe/simple/Destroy()
- if(node1)
- node1.disconnect(src)
- if(node2)
- node2.disconnect(src)
-
- node1 = null
- node2 = null
-
- return ..()
-
-/obj/machinery/atmospherics/pipe/simple/pipeline_expansion()
- return list(node1, node2)
-
-/obj/machinery/atmospherics/pipe/simple/change_color(var/new_color)
- ..()
- //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
- if(node1)
- node1.update_underlays()
- if(node2)
- node2.update_underlays()
-
-/obj/machinery/atmospherics/pipe/simple/update_icon(var/safety = 0)
- if(!check_icon_cache())
- return
-
- alpha = 255
-
- cut_overlays()
-
- if(!node1 && !node2)
- var/turf/T = get_turf(src)
- new /obj/item/pipe(loc, make_from=src)
- for (var/obj/machinery/meter/meter in T)
- if (meter.target == src)
- new /obj/item/pipe_meter(T)
- qdel(meter)
- qdel(src)
- else if(node1 && node2)
- add_overlay(icon_manager.get_atmos_icon("pipe", , pipe_color, "[pipe_icon]intact[icon_connect_type]"))
- else
- add_overlay(icon_manager.get_atmos_icon("pipe", , pipe_color, "[pipe_icon]exposed[node1?1:0][node2?1:0][icon_connect_type]"))
-
-/obj/machinery/atmospherics/pipe/simple/update_underlays()
- return
-
-/obj/machinery/atmospherics/pipe/simple/atmos_init()
- normalize_dir()
- var/node1_dir
- var/node2_dir
-
- for(var/direction in cardinal)
- if(direction&initialize_directions)
- if (!node1_dir)
- node1_dir = direction
- else if (!node2_dir)
- node2_dir = direction
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node1 = target
- break
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node2 = target
- break
-
- if(!node1 && !node2)
- qdel(src)
- return
-
- var/turf/T = loc
- if(level == 1 && !T.is_plating()) hide(1)
- queue_icon_update()
-
-/obj/machinery/atmospherics/pipe/simple/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node1)
- if(istype(node1, /obj/machinery/atmospherics/pipe))
- QDEL_NULL(parent)
- node1 = null
-
- if(reference == node2)
- if(istype(node2, /obj/machinery/atmospherics/pipe))
- QDEL_NULL(parent)
- node2 = null
-
- update_icon()
-
- return null
-
-/obj/machinery/atmospherics/pipe/simple/visible
- icon_state = "intact"
- level = 2
-
-/obj/machinery/atmospherics/pipe/simple/visible/scrubbers
- name = "Scrubbers pipe"
- desc = "A one meter section of scrubbers pipe"
- icon_state = "intact-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/simple/visible/supply
- name = "Air supply pipe"
- desc = "A one meter section of supply pipe"
- icon_state = "intact-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/simple/visible/yellow
- color = PIPE_COLOR_YELLOW
-
-/obj/machinery/atmospherics/pipe/simple/visible/cyan
- color = PIPE_COLOR_CYAN
-
-/obj/machinery/atmospherics/pipe/simple/visible/green
- color = PIPE_COLOR_GREEN
-
-/obj/machinery/atmospherics/pipe/simple/visible/black
- color = PIPE_COLOR_BLACK
-
-/obj/machinery/atmospherics/pipe/simple/visible/red
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/simple/visible/blue
- color = PIPE_COLOR_BLUE
-
-
-/obj/machinery/atmospherics/pipe/simple/hidden
- icon_state = "intact"
- level = 1
- alpha = 128 //set for the benefit of mapping - this is reset to opaque when the pipe is spawned in game
-
-/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers
- name = "Scrubbers pipe"
- desc = "A one meter section of scrubbers pipe"
- icon_state = "intact-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/simple/hidden/supply
- name = "Air supply pipe"
- desc = "A one meter section of supply pipe"
- icon_state = "intact-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/simple/hidden/yellow
- color = PIPE_COLOR_YELLOW
-
-/obj/machinery/atmospherics/pipe/simple/hidden/cyan
- color = PIPE_COLOR_CYAN
-
-/obj/machinery/atmospherics/pipe/simple/hidden/green
- color = PIPE_COLOR_GREEN
-
-/obj/machinery/atmospherics/pipe/simple/hidden/black
- color = PIPE_COLOR_BLACK
-
-/obj/machinery/atmospherics/pipe/simple/hidden/red
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/simple/hidden/blue
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/simple/insulated
- icon = 'icons/obj/atmospherics/red_pipe.dmi'
- icon_state = "intact"
-
- minimum_temperature_difference = 10000
- thermal_conductivity = 0
- maximum_pressure = 1000*ONE_ATMOSPHERE
- fatigue_pressure = 900*ONE_ATMOSPHERE
- alert_pressure = 900*ONE_ATMOSPHERE
-
- level = 2
-
-
-/obj/machinery/atmospherics/pipe/manifold
- icon = 'icons/atmos/manifold.dmi'
- icon_state = ""
- name = "pipe manifold"
- desc = "A manifold composed of regular pipes"
-
- volume = ATMOS_DEFAULT_VOLUME_PIPE * 1.5
-
- dir = SOUTH
- initialize_directions = EAST|NORTH|WEST
-
- var/obj/machinery/atmospherics/node3
-
- level = 1
- layer = 2.4 //under wires with their 2.44
-
- gfi_layer_rotation = GFI_ROTATION_OVERDIR
-
-/obj/machinery/atmospherics/pipe/manifold/Initialize()
- alpha = 255
- icon = null
-
- switch(dir)
- if(NORTH)
- initialize_directions = EAST|SOUTH|WEST
- if(SOUTH)
- initialize_directions = WEST|NORTH|EAST
- if(EAST)
- initialize_directions = SOUTH|WEST|NORTH
- if(WEST)
- initialize_directions = NORTH|EAST|SOUTH
- . = ..()
-
-/obj/machinery/atmospherics/pipe/manifold/hide(var/i)
- if(istype(loc, /turf/simulated))
- invisibility = i ? 101 : 0
- queue_icon_update()
-
-/obj/machinery/atmospherics/pipe/manifold/pipeline_expansion()
- return list(node1, node2, node3)
-
-/obj/machinery/atmospherics/pipe/manifold/machinery_process()
- if(!parent)
- ..()
- else
- . = PROCESS_KILL
-
-/obj/machinery/atmospherics/pipe/manifold/Destroy()
- if(node1)
- node1.disconnect(src)
- if(node2)
- node2.disconnect(src)
- if(node3)
- node3.disconnect(src)
-
- node1 = null
- node2 = null
- node3 = null
-
- return ..()
-
-/obj/machinery/atmospherics/pipe/manifold/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node1)
- if(istype(node1, /obj/machinery/atmospherics/pipe))
- QDEL_NULL(parent)
- node1 = null
-
- if(reference == node2)
- if(istype(node2, /obj/machinery/atmospherics/pipe))
- QDEL_NULL(parent)
- node2 = null
-
- if(reference == node3)
- if(istype(node3, /obj/machinery/atmospherics/pipe))
- QDEL_NULL(parent)
- node3 = null
-
- update_icon()
-
- ..()
-
-/obj/machinery/atmospherics/pipe/manifold/change_color(var/new_color)
- ..()
- //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
- if(node1)
- node1.update_underlays()
- if(node2)
- node2.update_underlays()
- if(node3)
- node3.update_underlays()
-
-/obj/machinery/atmospherics/pipe/manifold/update_icon(var/safety = 0)
- if(!check_icon_cache())
- return
-
- alpha = 255
-
- if(!node1 && !node2 && !node3)
- var/turf/T = get_turf(src)
- new /obj/item/pipe(loc, make_from=src)
- for (var/obj/machinery/meter/meter in T)
- if (meter.target == src)
- new /obj/item/pipe_meter(T)
- qdel(meter)
- qdel(src)
- else
- cut_overlays()
- add_overlay(icon_manager.get_atmos_icon("manifold", , pipe_color, "core" + icon_connect_type))
- add_overlay(icon_manager.get_atmos_icon("manifold", , , "clamps" + icon_connect_type))
-
- // Can't handle underlays with SSoverlay.
- underlays.Cut()
-
- var/turf/T = get_turf(src)
- var/list/directions = list(NORTH, SOUTH, EAST, WEST)
- var/node1_direction = get_dir(src, node1)
- var/node2_direction = get_dir(src, node2)
- var/node3_direction = get_dir(src, node3)
-
- directions -= dir
-
- directions -= add_underlay(T,node1,node1_direction,icon_connect_type)
- directions -= add_underlay(T,node2,node2_direction,icon_connect_type)
- directions -= add_underlay(T,node3,node3_direction,icon_connect_type)
-
- for(var/D in directions)
- add_underlay(T,,D,icon_connect_type)
-
-
-/obj/machinery/atmospherics/pipe/manifold/update_underlays()
- ..()
- queue_icon_update()
-
-/obj/machinery/atmospherics/pipe/manifold/atmos_init()
- var/connect_directions = (NORTH|SOUTH|EAST|WEST)&(~dir)
-
- for(var/direction in cardinal)
- if(direction&connect_directions)
- for(var/obj/machinery/atmospherics/target in get_step(src,direction))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node1 = target
- connect_directions &= ~direction
- break
- if (node1)
- break
-
-
- for(var/direction in cardinal)
- if(direction&connect_directions)
- for(var/obj/machinery/atmospherics/target in get_step(src,direction))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node2 = target
- connect_directions &= ~direction
- break
- if (node2)
- break
-
-
- for(var/direction in cardinal)
- if(direction&connect_directions)
- for(var/obj/machinery/atmospherics/target in get_step(src,direction))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node3 = target
- connect_directions &= ~direction
- break
- if (node3)
- break
-
- if(!node1 && !node2 && !node3)
- qdel(src)
- return
-
- var/turf/T = get_turf(src)
- if(level == 1 && !T.is_plating()) hide(1)
- queue_icon_update()
-
-/obj/machinery/atmospherics/pipe/manifold/visible
- icon_state = "map"
- level = 2
-
-/obj/machinery/atmospherics/pipe/manifold/visible/scrubbers
- name="Scrubbers pipe manifold"
- desc = "A manifold composed of scrubbers pipes"
- icon_state = "map-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold/visible/supply
- name="Air supply pipe manifold"
- desc = "A manifold composed of supply pipes"
- icon_state = "map-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/manifold/visible/yellow
- color = PIPE_COLOR_YELLOW
-
-/obj/machinery/atmospherics/pipe/manifold/visible/cyan
- color = PIPE_COLOR_CYAN
-
-/obj/machinery/atmospherics/pipe/manifold/visible/green
- color = PIPE_COLOR_GREEN
-
-/obj/machinery/atmospherics/pipe/manifold/visible/black
- color = PIPE_COLOR_BLACK
-
-/obj/machinery/atmospherics/pipe/manifold/visible/red
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold/visible/blue
- color = PIPE_COLOR_BLUE
-
-
-/obj/machinery/atmospherics/pipe/manifold/hidden
- icon_state = "map"
- level = 1
- alpha = 128 //set for the benefit of mapping - this is reset to opaque when the pipe is spawned in game
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers
- name="Scrubbers pipe manifold"
- desc = "A manifold composed of scrubbers pipes"
- icon_state = "map-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/supply
- name="Air supply pipe manifold"
- desc = "A manifold composed of supply pipes"
- icon_state = "map-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/yellow
- color = PIPE_COLOR_YELLOW
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/cyan
- color = PIPE_COLOR_CYAN
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/green
- color = PIPE_COLOR_GREEN
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/black
- color = PIPE_COLOR_BLACK
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/red
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/blue
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/manifold4w
- icon = 'icons/atmos/manifold.dmi'
- icon_state = ""
- name = "4-way pipe manifold"
- desc = "A manifold composed of regular pipes"
-
- volume = ATMOS_DEFAULT_VOLUME_PIPE * 2
-
- dir = SOUTH
- initialize_directions = NORTH|SOUTH|EAST|WEST
-
- var/obj/machinery/atmospherics/node3
- var/obj/machinery/atmospherics/node4
-
- level = 1
- layer = 2.4 //under wires with their 2.44
-
-/obj/machinery/atmospherics/pipe/manifold4w/Initialize()
- . = ..()
- alpha = 255
- icon = null
-
-/obj/machinery/atmospherics/pipe/manifold4w/pipeline_expansion()
- return list(node1, node2, node3, node4)
-
-/obj/machinery/atmospherics/pipe/manifold4w/machinery_process()
- if(!parent)
- ..()
- else
- . = PROCESS_KILL
-
-/obj/machinery/atmospherics/pipe/manifold4w/Destroy()
- if(node1)
- node1.disconnect(src)
- if(node2)
- node2.disconnect(src)
- if(node3)
- node3.disconnect(src)
- if(node4)
- node4.disconnect(src)
-
- node1 = null
- node2 = null
- node3 = null
- node4 = null
-
- return ..()
-
-/obj/machinery/atmospherics/pipe/manifold4w/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node1)
- if(istype(node1, /obj/machinery/atmospherics/pipe))
- QDEL_NULL(parent)
- node1 = null
-
- if(reference == node2)
- if(istype(node2, /obj/machinery/atmospherics/pipe))
- QDEL_NULL(parent)
- node2 = null
-
- if(reference == node3)
- if(istype(node3, /obj/machinery/atmospherics/pipe))
- QDEL_NULL(parent)
- node3 = null
-
- if(reference == node4)
- if(istype(node4, /obj/machinery/atmospherics/pipe))
- QDEL_NULL(parent)
- node4 = null
-
- update_icon()
-
- ..()
-
-/obj/machinery/atmospherics/pipe/manifold4w/change_color(var/new_color)
- ..()
- //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
- if(node1)
- node1.update_underlays()
- if(node2)
- node2.update_underlays()
- if(node3)
- node3.update_underlays()
- if(node4)
- node4.update_underlays()
-
-/obj/machinery/atmospherics/pipe/manifold4w/update_icon(var/safety = 0)
- if(!check_icon_cache())
- return
-
- alpha = 255
-
- if(!node1 && !node2 && !node3 && !node4)
- var/turf/T = get_turf(src)
- new /obj/item/pipe(loc, make_from=src)
- for (var/obj/machinery/meter/meter in T)
- if (meter.target == src)
- new /obj/item/pipe_meter(T)
- qdel(meter)
- qdel(src)
- else
- cut_overlays()
- add_overlay(icon_manager.get_atmos_icon("manifold", , pipe_color, "4way" + icon_connect_type))
- add_overlay(icon_manager.get_atmos_icon("manifold", , , "clamps_4way" + icon_connect_type))
-
- underlays.Cut()
-
- /*
- var/list/directions = list(NORTH, SOUTH, EAST, WEST)
-
-
- directions -= add_underlay(node1)
- directions -= add_underlay(node2)
- directions -= add_underlay(node3)
- directions -= add_underlay(node4)
-
- for(var/D in directions)
- add_underlay(,D)
- */
-
- var/turf/T = get_turf(src)
- var/list/directions = list(NORTH, SOUTH, EAST, WEST)
- var/node1_direction = get_dir(src, node1)
- var/node2_direction = get_dir(src, node2)
- var/node3_direction = get_dir(src, node3)
- var/node4_direction = get_dir(src, node4)
-
- directions -= dir
-
- directions -= add_underlay(T,node1,node1_direction,icon_connect_type)
- directions -= add_underlay(T,node2,node2_direction,icon_connect_type)
- directions -= add_underlay(T,node3,node3_direction,icon_connect_type)
- directions -= add_underlay(T,node4,node4_direction,icon_connect_type)
-
- for(var/D in directions)
- add_underlay(T,,D,icon_connect_type)
-
-
-/obj/machinery/atmospherics/pipe/manifold4w/update_underlays()
- ..()
- queue_icon_update()
-
-/obj/machinery/atmospherics/pipe/manifold4w/hide(var/i)
- if(istype(loc, /turf/simulated))
- invisibility = i ? 101 : 0
- queue_icon_update()
-
-/obj/machinery/atmospherics/pipe/manifold4w/atmos_init()
-
- for(var/obj/machinery/atmospherics/target in get_step(src,1))
- if(target.initialize_directions & 2)
- if (check_connect_types(target,src))
- node1 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,2))
- if(target.initialize_directions & 1)
- if (check_connect_types(target,src))
- node2 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,4))
- if(target.initialize_directions & 8)
- if (check_connect_types(target,src))
- node3 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,8))
- if(target.initialize_directions & 4)
- if (check_connect_types(target,src))
- node4 = target
- break
-
- if(!node1 && !node2 && !node3 && !node4)
- qdel(src)
- return
-
- var/turf/T = get_turf(src)
- if(level == 1 && !T.is_plating()) hide(1)
- queue_icon_update()
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible
- icon_state = "map_4way"
- level = 2
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/scrubbers
- name="4-way scrubbers pipe manifold"
- desc = "A manifold composed of scrubbers pipes"
- icon_state = "map_4way-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/supply
- name="4-way air supply pipe manifold"
- desc = "A manifold composed of supply pipes"
- icon_state = "map_4way-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/yellow
- color = PIPE_COLOR_YELLOW
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/cyan
- color = PIPE_COLOR_CYAN
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/green
- color = PIPE_COLOR_GREEN
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/black
- color = PIPE_COLOR_BLACK
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/red
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/blue
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden
- icon_state = "map_4way"
- level = 1
- alpha = 128 //set for the benefit of mapping - this is reset to opaque when the pipe is spawned in game
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers
- name="4-way scrubbers pipe manifold"
- desc = "A manifold composed of scrubbers pipes"
- icon_state = "map_4way-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/supply
- name="4-way air supply pipe manifold"
- desc = "A manifold composed of supply pipes"
- icon_state = "map_4way-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/yellow
- color = PIPE_COLOR_YELLOW
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/cyan
- color = PIPE_COLOR_CYAN
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/green
- color = PIPE_COLOR_GREEN
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/black
- color = PIPE_COLOR_BLACK
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/red
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/blue
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/cap
- name = "pipe endcap"
- desc = "An endcap for pipes"
- icon = 'icons/atmos/pipes.dmi'
- icon_state = ""
- level = 2
- layer = 2.4 //under wires with their 2.44
-
- volume = 35
-
- dir = SOUTH
- initialize_directions = SOUTH
-
- var/obj/machinery/atmospherics/node
-
-/obj/machinery/atmospherics/pipe/cap/Initialize()
- initialize_directions = dir
- . = ..()
-
-/obj/machinery/atmospherics/pipe/cap/hide(var/i)
- if(istype(loc, /turf/simulated))
- invisibility = i ? 101 : 0
- queue_icon_update()
-
-/obj/machinery/atmospherics/pipe/cap/pipeline_expansion()
- return list(node)
-
-/obj/machinery/atmospherics/pipe/cap/machinery_process()
- if(!parent)
- ..()
- else
- . = PROCESS_KILL
-/obj/machinery/atmospherics/pipe/cap/Destroy()
- if(node)
- node.disconnect(src)
-
- node = null
-
- return ..()
-
-/obj/machinery/atmospherics/pipe/cap/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node)
- if(istype(node, /obj/machinery/atmospherics/pipe))
- QDEL_NULL(parent)
- node = null
-
- update_icon()
-
- ..()
-
-/obj/machinery/atmospherics/pipe/cap/change_color(var/new_color)
- ..()
- //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
- if(node)
- node.update_underlays()
-
-/obj/machinery/atmospherics/pipe/cap/update_icon(var/safety = 0)
- if(!check_icon_cache())
- return
-
- alpha = 255
-
- cut_overlays()
- add_overlay(icon_manager.get_atmos_icon("pipe", , pipe_color, "cap"))
-
-/obj/machinery/atmospherics/pipe/cap/atmos_init()
- for(var/obj/machinery/atmospherics/target in get_step(src, dir))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node = target
- break
-
- var/turf/T = src.loc // hide if turf is not intact
- if(level == 1 && !T.is_plating()) hide(1)
- queue_icon_update()
-
-/obj/machinery/atmospherics/pipe/cap/visible
- level = 2
- icon_state = "cap"
-
-/obj/machinery/atmospherics/pipe/cap/visible/scrubbers
- name = "scrubbers pipe endcap"
- desc = "An endcap for scrubbers pipes"
- icon_state = "cap-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/cap/visible/supply
- name = "supply pipe endcap"
- desc = "An endcap for supply pipes"
- icon_state = "cap-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/cap/hidden
- level = 1
- icon_state = "cap"
- alpha = 128
-
-/obj/machinery/atmospherics/pipe/cap/hidden/scrubbers
- name = "scrubbers pipe endcap"
- desc = "An endcap for scrubbers pipes"
- icon_state = "cap-f-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/cap/hidden/supply
- name = "supply pipe endcap"
- desc = "An endcap for supply pipes"
- icon_state = "cap-f-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-
-/obj/machinery/atmospherics/pipe/tank
- icon = 'icons/atmos/tank.dmi'
- icon_state = "air_map"
-
- name = "Pressure Tank"
- desc = "A large vessel containing pressurized gas."
-
- volume = 10000 //in liters, 1 meters by 1 meters by 2 meters ~tweaked it a little to simulate a pressure tank without needing to recode them yet
- var/start_pressure = 25*ONE_ATMOSPHERE
-
- level = 1
- dir = SOUTH
- initialize_directions = SOUTH
- density = 1
-
-/obj/machinery/atmospherics/pipe/tank/Initialize()
- icon_state = "air"
- initialize_directions = dir
- . = ..()
-
-/obj/machinery/atmospherics/pipe/tank/machinery_process()
- if(!parent)
- ..()
- else
- . = PROCESS_KILL
-
-/obj/machinery/atmospherics/pipe/tank/Destroy()
- if(node1)
- node1.disconnect(src)
-
- node1 = null
-
- return ..()
-
-/obj/machinery/atmospherics/pipe/tank/pipeline_expansion()
- return list(node1)
-
-/obj/machinery/atmospherics/pipe/tank/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- add_underlay(T, node1, dir)
-
-/obj/machinery/atmospherics/pipe/tank/hide()
- update_underlays()
-
-/obj/machinery/atmospherics/pipe/tank/atmos_init()
- var/connect_direction = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src,connect_direction))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node1 = target
- break
-
- update_underlays()
-
-/obj/machinery/atmospherics/pipe/tank/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node1)
- if(istype(node1, /obj/machinery/atmospherics/pipe))
- QDEL_NULL(parent)
- node1 = null
-
- update_underlays()
-
- return null
-
-/obj/machinery/atmospherics/pipe/tank/attackby(var/obj/item/W as obj, var/mob/user as mob)
- if(istype(W, /obj/item/device/pipe_painter))
- return
-
- if(istype(W, /obj/item/device/analyzer) && in_range(user, src))
- var/obj/item/device/analyzer/A = W
- A.analyze_gases(src, user)
-
-/obj/machinery/atmospherics/pipe/tank/air
- name = "Pressure Tank (Air)"
- icon_state = "air_map"
-
-/obj/machinery/atmospherics/pipe/tank/air/Initialize()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T20C
-
- air_temporary.adjust_multi("oxygen", (start_pressure*O2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature), \
- "nitrogen",(start_pressure*N2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
-
- . = ..()
- icon_state = "air"
-
-/obj/machinery/atmospherics/pipe/tank/oxygen
- name = "Pressure Tank (Oxygen)"
- icon_state = "o2_map"
-
-/obj/machinery/atmospherics/pipe/tank/oxygen/Initialize()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T20C
-
- air_temporary.adjust_gas("oxygen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
- . = ..()
- icon_state = "o2"
-
-/obj/machinery/atmospherics/pipe/tank/nitrogen
- name = "Pressure Tank (Nitrogen)"
- icon_state = "n2_map"
-
-/obj/machinery/atmospherics/pipe/tank/nitrogen/Initialize()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T20C
-
- air_temporary.adjust_gas("nitrogen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
- . = ..()
- icon_state = "n2"
-
-/obj/machinery/atmospherics/pipe/tank/carbon_dioxide
- name = "Pressure Tank (Carbon Dioxide)"
- icon_state = "co2_map"
-
-/obj/machinery/atmospherics/pipe/tank/carbon_dioxide/Initialize()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T20C
-
- air_temporary.adjust_gas("carbon_dioxide", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
- . = ..()
- icon_state = "co2"
-
-/obj/machinery/atmospherics/pipe/tank/phoron
- name = "Pressure Tank (Phoron)"
- icon_state = "phoron_map"
-
-/obj/machinery/atmospherics/pipe/tank/phoron/Initialize()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T20C
-
- air_temporary.adjust_gas("phoron", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
- . = ..()
- icon_state = "phoron"
-
-/obj/machinery/atmospherics/pipe/tank/nitrous_oxide
- name = "Pressure Tank (Nitrous Oxide)"
- icon_state = "n2o_map"
-
-/obj/machinery/atmospherics/pipe/tank/nitrous_oxide/Initialize()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T0C
-
- air_temporary.adjust_gas("sleeping_agent", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
- . = ..()
- icon_state = "n2o"
-
-/obj/machinery/atmospherics/pipe/vent
- icon = 'icons/obj/atmospherics/pipe_vent.dmi'
- icon_state = "intact"
-
- name = "Vent"
- desc = "A large air vent"
-
- level = 1
-
- volume = 250
-
- dir = SOUTH
- initialize_directions = SOUTH
-
- var/build_killswitch = 1
-
-/obj/machinery/atmospherics/pipe/vent/Initialize()
- initialize_directions = dir
- . = ..()
-
-/obj/machinery/atmospherics/pipe/vent/high_volume
- name = "Larger vent"
- volume = 1000
-
-/obj/machinery/atmospherics/pipe/vent/machinery_process()
- if(!parent)
- if(build_killswitch <= 0)
- . = PROCESS_KILL
- else
- build_killswitch--
- ..()
- return
- else
- parent.mingle_with_turf(loc, volume)
-
-/obj/machinery/atmospherics/pipe/vent/Destroy()
- if(node1)
- node1.disconnect(src)
-
- node1 = null
-
- return ..()
-
-/obj/machinery/atmospherics/pipe/vent/pipeline_expansion()
- return list(node1)
-
-/obj/machinery/atmospherics/pipe/vent/update_icon()
- if(node1)
- icon_state = "intact"
-
- set_dir(get_dir(src, node1))
-
- else
- icon_state = "exposed"
-
-/obj/machinery/atmospherics/pipe/vent/atmos_init()
- var/connect_direction = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src,connect_direction))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node1 = target
- break
-
- queue_icon_update()
-
-/obj/machinery/atmospherics/pipe/vent/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node1)
- if(istype(node1, /obj/machinery/atmospherics/pipe))
- QDEL_NULL(parent)
- node1 = null
-
- update_icon()
-
- return null
-
-/obj/machinery/atmospherics/pipe/vent/hide(var/i) //to make the little pipe section invisible, the icon changes.
- if(node1)
- icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]intact"
- set_dir(get_dir(src, node1))
- else
- icon_state = "exposed"
-
-
-/obj/machinery/atmospherics/pipe/simple/visible/universal
- name="Universal pipe adapter"
- desc = "An adapter for regular, supply and scrubbers pipes"
- connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER
- icon_state = "map_universal"
- gfi_layer_rotation = GFI_ROTATION_OVERDIR
-
-/obj/machinery/atmospherics/pipe/simple/visible/universal/update_icon(var/safety = 0)
- if(!check_icon_cache())
- return
-
- alpha = 255
-
- cut_overlays()
- add_overlay(icon_manager.get_atmos_icon("pipe", , pipe_color, "universal"))
- underlays.Cut()
-
- if (node1)
- universal_underlays(node1)
- if(node2)
- universal_underlays(node2)
- else
- var/node1_dir = get_dir(node1,src)
- universal_underlays(,node1_dir)
- else if (node2)
- universal_underlays(node2)
- else
- universal_underlays(,dir)
- universal_underlays(,turn(dir, -180))
-
-/obj/machinery/atmospherics/pipe/simple/visible/universal/update_underlays()
- ..()
- queue_icon_update()
-
-
-
-/obj/machinery/atmospherics/pipe/simple/hidden/universal
- name="Universal pipe adapter"
- desc = "An adapter for regular, supply and scrubbers pipes"
- connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER
- icon_state = "map_universal"
- gfi_layer_rotation = GFI_ROTATION_OVERDIR
-
-/obj/machinery/atmospherics/pipe/simple/hidden/universal/update_icon(var/safety = 0)
- if(!check_icon_cache())
- return
-
- alpha = 255
-
- cut_overlays()
- add_overlay(icon_manager.get_atmos_icon("pipe", , pipe_color, "universal"))
-
- underlays.Cut()
-
- if (node1)
- universal_underlays(node1)
- if(node2)
- universal_underlays(node2)
- else
- var/node2_dir = turn(get_dir(src,node1),-180)
- universal_underlays(,node2_dir)
- else if (node2)
- universal_underlays(node2)
- var/node1_dir = turn(get_dir(src,node2),-180)
- universal_underlays(,node1_dir)
- else
- universal_underlays(,dir)
- universal_underlays(,turn(dir, -180))
-
-/obj/machinery/atmospherics/pipe/simple/hidden/universal/update_underlays()
- ..()
- queue_icon_update()
-
-/obj/machinery/atmospherics/proc/universal_underlays(var/obj/machinery/atmospherics/node, var/direction)
- var/turf/T = loc
- if(node)
- var/node_dir = get_dir(src,node)
- if(node.icon_connect_type == "-supply")
- add_underlay_adapter(T, , node_dir, "")
- add_underlay_adapter(T, node, node_dir, "-supply")
- add_underlay_adapter(T, , node_dir, "-scrubbers")
- else if (node.icon_connect_type == "-scrubbers")
- add_underlay_adapter(T, , node_dir, "")
- add_underlay_adapter(T, , node_dir, "-supply")
- add_underlay_adapter(T, node, node_dir, "-scrubbers")
- else
- add_underlay_adapter(T, node, node_dir, "")
- add_underlay_adapter(T, , node_dir, "-supply")
- add_underlay_adapter(T, , node_dir, "-scrubbers")
- else
- add_underlay_adapter(T, , direction, "-supply")
- add_underlay_adapter(T, , direction, "-scrubbers")
- add_underlay_adapter(T, , direction, "")
-
-/obj/machinery/atmospherics/proc/add_underlay_adapter(var/turf/T, var/obj/machinery/atmospherics/node, var/direction, var/icon_connect_type) //modified from add_underlay, does not make exposed underlays
- if(node)
- if(!T.is_plating() && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
- underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "down" + icon_connect_type)
- else
- underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
- else
- underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "retracted" + icon_connect_type)
+/obj/machinery/atmospherics/pipe
+
+ var/datum/gas_mixture/air_temporary // used when reconstructing a pipeline that broke
+ var/datum/pipeline/parent
+ var/volume = 0
+ force = 20
+
+ layer = PIPE_LAYER
+ use_power = 0
+
+ var/alert_pressure = 80*ONE_ATMOSPHERE
+ //minimum pressure before check_pressure(...) should be called
+
+ can_buckle = 1
+ buckle_require_restraints = 1
+ buckle_lying = -1
+
+/obj/machinery/atmospherics/pipe/drain_power()
+ return -1
+
+/obj/machinery/atmospherics/pipe/Initialize()
+ if(istype(get_turf(src), /turf/simulated/wall) || istype(get_turf(src), /turf/unsimulated/wall))
+ level = 1
+ . = ..()
+
+/obj/machinery/atmospherics/pipe/hides_under_flooring()
+ return level != 2
+
+/obj/machinery/atmospherics/pipe/proc/pipeline_expansion()
+ return null
+
+/obj/machinery/atmospherics/pipe/proc/check_pressure(pressure)
+ //Return 1 if parent should continue checking other pipes
+ //Return null if parent should stop checking other pipes. Recall: qdel(src) will by default return null
+
+ return 1
+
+/obj/machinery/atmospherics/pipe/return_air()
+ if(!parent)
+ parent = new /datum/pipeline()
+ parent.build_pipeline(src)
+
+ return parent.air
+
+/obj/machinery/atmospherics/pipe/build_network()
+ if(!parent)
+ parent = new /datum/pipeline()
+ parent.build_pipeline(src)
+
+ return parent.return_network()
+
+/obj/machinery/atmospherics/pipe/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
+ if(!parent)
+ parent = new /datum/pipeline()
+ parent.build_pipeline(src)
+
+ return parent.network_expand(new_network, reference)
+
+/obj/machinery/atmospherics/pipe/return_network(obj/machinery/atmospherics/reference)
+ if(!parent)
+ parent = new /datum/pipeline()
+ parent.build_pipeline(src)
+
+ return parent.return_network(reference)
+
+/obj/machinery/atmospherics/pipe/Destroy()
+ QDEL_NULL(parent)
+ if(air_temporary)
+ loc.assume_air(air_temporary)
+
+ return ..()
+
+/obj/machinery/atmospherics/pipe/attackby(var/obj/item/W as obj, var/mob/user as mob)
+ if (istype(src, /obj/machinery/atmospherics/pipe/tank))
+ return ..()
+ if (istype(src, /obj/machinery/atmospherics/pipe/vent))
+ return ..()
+
+ if(istype(W,/obj/item/device/pipe_painter))
+ return 0
+
+ if (!W.iswrench() && !istype(W, /obj/item/pipewrench))
+ return ..()
+ var/turf/T = src.loc
+ if (level==1 && isturf(T) && !T.is_plating())
+ to_chat(user, "You must remove the plating first.")
+ return 1
+ var/datum/gas_mixture/int_air = return_air()
+ var/datum/gas_mixture/env_air = loc.return_air()
+ if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
+ if(!istype(W, /obj/item/pipewrench))
+ to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
+ add_fingerprint(user)
+ return 1
+ else
+ to_chat(user, "You struggle to unwrench \the [src] with your pipe wrench.")
+ playsound(src.loc, W.usesound, 50, 1)
+ to_chat(user, "You begin to unfasten \the [src]...")
+ if (do_after(user, istype(W, /obj/item/pipewrench) ? 80/W.toolspeed : 40/W.toolspeed, act_target = src))
+ user.visible_message( \
+ "\The [user] unfastens \the [src].", \
+ "You have unfastened \the [src].", \
+ "You hear a ratchet.")
+ new /obj/item/pipe(loc, make_from=src)
+ for (var/obj/machinery/meter/meter in T)
+ if (meter.target == src)
+ new /obj/item/pipe_meter(T)
+ qdel(meter)
+ qdel(src)
+
+/obj/machinery/atmospherics/proc/change_color(var/new_color)
+ //only pass valid pipe colors please ~otherwise your pipe will turn invisible
+ if(!pipe_color_check(new_color))
+ return
+
+ pipe_color = new_color
+ update_icon()
+
+/*
+/obj/machinery/atmospherics/pipe/add_underlay(var/obj/machinery/atmospherics/node, var/direction)
+ if(istype(src, /obj/machinery/atmospherics/pipe/tank)) //todo: move tanks to unary devices
+ return ..()
+
+ if(node)
+ var/temp_dir = get_dir(src, node)
+ underlays += icon_manager.get_atmos_icon("pipe_underlay_intact", temp_dir, color_cache_name(node))
+ return temp_dir
+ else if(direction)
+ underlays += icon_manager.get_atmos_icon("pipe_underlay_exposed", direction, pipe_color)
+ else
+ return null
+*/
+
+/obj/machinery/atmospherics/pipe/color_cache_name(var/obj/machinery/atmospherics/node)
+ if(istype(src, /obj/machinery/atmospherics/pipe/tank))
+ return ..()
+
+ if(istype(node, /obj/machinery/atmospherics/pipe/manifold) || istype(node, /obj/machinery/atmospherics/pipe/manifold4w))
+ if(pipe_color == node.pipe_color)
+ return node.pipe_color
+ else
+ return null
+ else if(istype(node, /obj/machinery/atmospherics/pipe/simple))
+ return node.pipe_color
+ else
+ return pipe_color
+
+/obj/machinery/atmospherics/pipe/simple
+ icon = 'icons/atmos/pipes.dmi'
+ icon_state = ""
+ var/pipe_icon = "" //what kind of pipe it is and from which dmi is the icon manager getting its icons, "" for simple pipes, "hepipe" for HE pipes, "hejunction" for HE junctions
+ name = "pipe"
+ desc = "A one meter section of regular pipe"
+
+ volume = ATMOS_DEFAULT_VOLUME_PIPE
+
+ dir = SOUTH
+ initialize_directions = SOUTH|NORTH
+
+ var/minimum_temperature_difference = 300
+ var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No
+
+ var/maximum_pressure = 70*ONE_ATMOSPHERE
+ var/fatigue_pressure = 55*ONE_ATMOSPHERE
+ alert_pressure = 55*ONE_ATMOSPHERE
+
+ level = 1
+ gfi_layer_rotation = GFI_ROTATION_DEFDIR
+
+/obj/machinery/atmospherics/pipe/simple/Initialize()
+
+ // Pipe colors and icon states are handled by an image cache - so color and icon should
+ // be null. For mapping purposes color is defined in the object definitions.
+ icon = null
+ alpha = 255
+
+ switch(dir)
+ if(SOUTH || NORTH)
+ initialize_directions = SOUTH|NORTH
+ if(EAST || WEST)
+ initialize_directions = EAST|WEST
+ if(NORTHEAST)
+ initialize_directions = NORTH|EAST
+ if(NORTHWEST)
+ initialize_directions = NORTH|WEST
+ if(SOUTHEAST)
+ initialize_directions = SOUTH|EAST
+ if(SOUTHWEST)
+ initialize_directions = SOUTH|WEST
+ . = ..()
+
+/obj/machinery/atmospherics/pipe/simple/hide(var/i)
+ if(istype(loc, /turf/simulated))
+ invisibility = i ? 101 : 0
+ queue_icon_update()
+
+/obj/machinery/atmospherics/pipe/simple/machinery_process()
+ if(!parent) //This should cut back on the overhead calling build_network thousands of times per cycle
+ ..()
+ else
+ . = PROCESS_KILL
+
+/obj/machinery/atmospherics/pipe/simple/check_pressure(pressure)
+ var/datum/gas_mixture/environment = loc.return_air()
+
+ var/pressure_difference = pressure - environment.return_pressure()
+
+ if(pressure_difference > maximum_pressure)
+ burst()
+
+ else if(pressure_difference > fatigue_pressure)
+ //TODO: leak to turf, doing pfshhhhh
+ if(prob(5))
+ burst()
+
+ else return 1
+
+/obj/machinery/atmospherics/pipe/simple/proc/burst()
+ src.visible_message("\The [src] bursts!");
+ playsound(src.loc, 'sound/effects/bang.ogg', 25, 1)
+ var/datum/effect/effect/system/smoke_spread/smoke = new
+ smoke.set_up(1,0, src.loc, 0)
+ smoke.start()
+ qdel(src)
+
+/obj/machinery/atmospherics/pipe/simple/proc/normalize_dir()
+ if(dir==3)
+ set_dir(1)
+ else if(dir==12)
+ set_dir(4)
+
+/obj/machinery/atmospherics/pipe/simple/Destroy()
+ if(node1)
+ node1.disconnect(src)
+ node1 = null
+ if(node2)
+ node2.disconnect(src)
+ node2 = null
+
+ return ..()
+
+/obj/machinery/atmospherics/pipe/simple/pipeline_expansion()
+ return list(node1, node2)
+
+/obj/machinery/atmospherics/pipe/simple/change_color(var/new_color)
+ ..()
+ //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
+ if(node1)
+ node1.update_underlays()
+ if(node2)
+ node2.update_underlays()
+
+/obj/machinery/atmospherics/pipe/simple/update_icon(var/safety = 0)
+ if(!check_icon_cache())
+ return
+
+ alpha = 255
+
+ cut_overlays()
+
+ if(!node1 && !node2)
+ var/turf/T = get_turf(src)
+ new /obj/item/pipe(loc, make_from=src)
+ for (var/obj/machinery/meter/meter in T)
+ if (meter.target == src)
+ new /obj/item/pipe_meter(T)
+ qdel(meter)
+ qdel(src)
+ else if(node1 && node2)
+ add_overlay(icon_manager.get_atmos_icon("pipe", , pipe_color, "[pipe_icon]intact[icon_connect_type]"))
+ else
+ add_overlay(icon_manager.get_atmos_icon("pipe", , pipe_color, "[pipe_icon]exposed[node1?1:0][node2?1:0][icon_connect_type]"))
+
+/obj/machinery/atmospherics/pipe/simple/update_underlays()
+ return
+
+/obj/machinery/atmospherics/pipe/simple/atmos_init()
+ normalize_dir()
+ var/node1_dir
+ var/node2_dir
+
+ for(var/direction in cardinal)
+ if(direction&initialize_directions)
+ if (!node1_dir)
+ node1_dir = direction
+ else if (!node2_dir)
+ node2_dir = direction
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node1 = target
+ break
+ for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node2 = target
+ break
+
+ if(!node1 && !node2)
+ qdel(src)
+ return
+
+ var/turf/T = loc
+ if(level == 1 && !T.is_plating()) hide(1)
+ queue_icon_update()
+
+/obj/machinery/atmospherics/pipe/simple/disconnect(obj/machinery/atmospherics/reference)
+ if(reference == node1)
+ if(istype(node1, /obj/machinery/atmospherics/pipe))
+ QDEL_NULL(parent)
+ node1 = null
+
+ if(reference == node2)
+ if(istype(node2, /obj/machinery/atmospherics/pipe))
+ QDEL_NULL(parent)
+ node2 = null
+
+ update_icon()
+
+ return null
+
+/obj/machinery/atmospherics/pipe/simple/visible
+ icon_state = "intact"
+ level = 2
+
+/obj/machinery/atmospherics/pipe/simple/visible/scrubbers
+ name = "Scrubbers pipe"
+ desc = "A one meter section of scrubbers pipe"
+ icon_state = "intact-scrubbers"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/simple/visible/supply
+ name = "Air supply pipe"
+ desc = "A one meter section of supply pipe"
+ icon_state = "intact-supply"
+ connect_types = CONNECT_TYPE_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/simple/visible/yellow
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/simple/visible/cyan
+ color = PIPE_COLOR_CYAN
+
+/obj/machinery/atmospherics/pipe/simple/visible/green
+ color = PIPE_COLOR_GREEN
+
+/obj/machinery/atmospherics/pipe/simple/visible/black
+ color = PIPE_COLOR_BLACK
+
+/obj/machinery/atmospherics/pipe/simple/visible/red
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/simple/visible/blue
+ color = PIPE_COLOR_BLUE
+
+
+/obj/machinery/atmospherics/pipe/simple/hidden
+ icon_state = "intact"
+ level = 1
+ alpha = 128 //set for the benefit of mapping - this is reset to opaque when the pipe is spawned in game
+
+/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers
+ name = "Scrubbers pipe"
+ desc = "A one meter section of scrubbers pipe"
+ icon_state = "intact-scrubbers"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/simple/hidden/supply
+ name = "Air supply pipe"
+ desc = "A one meter section of supply pipe"
+ icon_state = "intact-supply"
+ connect_types = CONNECT_TYPE_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/simple/hidden/yellow
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/simple/hidden/cyan
+ color = PIPE_COLOR_CYAN
+
+/obj/machinery/atmospherics/pipe/simple/hidden/green
+ color = PIPE_COLOR_GREEN
+
+/obj/machinery/atmospherics/pipe/simple/hidden/black
+ color = PIPE_COLOR_BLACK
+
+/obj/machinery/atmospherics/pipe/simple/hidden/red
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/simple/hidden/blue
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/simple/insulated
+ icon = 'icons/obj/atmospherics/red_pipe.dmi'
+ icon_state = "intact"
+
+ minimum_temperature_difference = 10000
+ thermal_conductivity = 0
+ maximum_pressure = 1000*ONE_ATMOSPHERE
+ fatigue_pressure = 900*ONE_ATMOSPHERE
+ alert_pressure = 900*ONE_ATMOSPHERE
+
+ level = 2
+
+
+/obj/machinery/atmospherics/pipe/manifold
+ icon = 'icons/atmos/manifold.dmi'
+ icon_state = ""
+ name = "pipe manifold"
+ desc = "A manifold composed of regular pipes"
+
+ volume = ATMOS_DEFAULT_VOLUME_PIPE * 1.5
+
+ dir = SOUTH
+ initialize_directions = EAST|NORTH|WEST
+
+ var/obj/machinery/atmospherics/node3
+
+ level = 1
+ layer = 2.4 //under wires with their 2.44
+
+ gfi_layer_rotation = GFI_ROTATION_OVERDIR
+
+/obj/machinery/atmospherics/pipe/manifold/Initialize()
+ alpha = 255
+ icon = null
+
+ switch(dir)
+ if(NORTH)
+ initialize_directions = EAST|SOUTH|WEST
+ if(SOUTH)
+ initialize_directions = WEST|NORTH|EAST
+ if(EAST)
+ initialize_directions = SOUTH|WEST|NORTH
+ if(WEST)
+ initialize_directions = NORTH|EAST|SOUTH
+ . = ..()
+
+/obj/machinery/atmospherics/pipe/manifold/hide(var/i)
+ if(istype(loc, /turf/simulated))
+ invisibility = i ? 101 : 0
+ queue_icon_update()
+
+/obj/machinery/atmospherics/pipe/manifold/pipeline_expansion()
+ return list(node1, node2, node3)
+
+/obj/machinery/atmospherics/pipe/manifold/machinery_process()
+ if(!parent)
+ ..()
+ else
+ . = PROCESS_KILL
+
+/obj/machinery/atmospherics/pipe/manifold/Destroy()
+ if(node1)
+ node1.disconnect(src)
+ node1 = null
+ if(node2)
+ node2.disconnect(src)
+ node2 = null
+ if(node3)
+ node3.disconnect(src)
+ node3 = null
+
+ return ..()
+
+/obj/machinery/atmospherics/pipe/manifold/disconnect(obj/machinery/atmospherics/reference)
+ if(reference == node1)
+ if(istype(node1, /obj/machinery/atmospherics/pipe))
+ QDEL_NULL(parent)
+ node1 = null
+
+ if(reference == node2)
+ if(istype(node2, /obj/machinery/atmospherics/pipe))
+ QDEL_NULL(parent)
+ node2 = null
+
+ if(reference == node3)
+ if(istype(node3, /obj/machinery/atmospherics/pipe))
+ QDEL_NULL(parent)
+ node3 = null
+
+ update_icon()
+
+ ..()
+
+/obj/machinery/atmospherics/pipe/manifold/change_color(var/new_color)
+ ..()
+ //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
+ if(node1)
+ node1.update_underlays()
+ if(node2)
+ node2.update_underlays()
+ if(node3)
+ node3.update_underlays()
+
+/obj/machinery/atmospherics/pipe/manifold/update_icon(var/safety = 0)
+ if(!check_icon_cache())
+ return
+
+ alpha = 255
+
+ if(!node1 && !node2 && !node3)
+ var/turf/T = get_turf(src)
+ new /obj/item/pipe(loc, make_from=src)
+ for (var/obj/machinery/meter/meter in T)
+ if (meter.target == src)
+ new /obj/item/pipe_meter(T)
+ qdel(meter)
+ qdel(src)
+ else
+ cut_overlays()
+ add_overlay(icon_manager.get_atmos_icon("manifold", , pipe_color, "core" + icon_connect_type))
+ add_overlay(icon_manager.get_atmos_icon("manifold", , , "clamps" + icon_connect_type))
+
+ // Can't handle underlays with SSoverlay.
+ underlays.Cut()
+
+ var/turf/T = get_turf(src)
+ var/list/directions = list(NORTH, SOUTH, EAST, WEST)
+ var/node1_direction = get_dir(src, node1)
+ var/node2_direction = get_dir(src, node2)
+ var/node3_direction = get_dir(src, node3)
+
+ directions -= dir
+
+ directions -= add_underlay(T,node1,node1_direction,icon_connect_type)
+ directions -= add_underlay(T,node2,node2_direction,icon_connect_type)
+ directions -= add_underlay(T,node3,node3_direction,icon_connect_type)
+
+ for(var/D in directions)
+ add_underlay(T,,D,icon_connect_type)
+
+
+/obj/machinery/atmospherics/pipe/manifold/update_underlays()
+ ..()
+ queue_icon_update()
+
+/obj/machinery/atmospherics/pipe/manifold/atmos_init()
+ var/connect_directions = (NORTH|SOUTH|EAST|WEST)&(~dir)
+
+ for(var/direction in cardinal)
+ if(direction&connect_directions)
+ for(var/obj/machinery/atmospherics/target in get_step(src,direction))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node1 = target
+ connect_directions &= ~direction
+ break
+ if (node1)
+ break
+
+
+ for(var/direction in cardinal)
+ if(direction&connect_directions)
+ for(var/obj/machinery/atmospherics/target in get_step(src,direction))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node2 = target
+ connect_directions &= ~direction
+ break
+ if (node2)
+ break
+
+
+ for(var/direction in cardinal)
+ if(direction&connect_directions)
+ for(var/obj/machinery/atmospherics/target in get_step(src,direction))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node3 = target
+ connect_directions &= ~direction
+ break
+ if (node3)
+ break
+
+ if(!node1 && !node2 && !node3)
+ qdel(src)
+ return
+
+ var/turf/T = get_turf(src)
+ if(level == 1 && !T.is_plating()) hide(1)
+ queue_icon_update()
+
+/obj/machinery/atmospherics/pipe/manifold/visible
+ icon_state = "map"
+ level = 2
+
+/obj/machinery/atmospherics/pipe/manifold/visible/scrubbers
+ name="Scrubbers pipe manifold"
+ desc = "A manifold composed of scrubbers pipes"
+ icon_state = "map-scrubbers"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold/visible/supply
+ name="Air supply pipe manifold"
+ desc = "A manifold composed of supply pipes"
+ icon_state = "map-supply"
+ connect_types = CONNECT_TYPE_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/manifold/visible/yellow
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/manifold/visible/cyan
+ color = PIPE_COLOR_CYAN
+
+/obj/machinery/atmospherics/pipe/manifold/visible/green
+ color = PIPE_COLOR_GREEN
+
+/obj/machinery/atmospherics/pipe/manifold/visible/black
+ color = PIPE_COLOR_BLACK
+
+/obj/machinery/atmospherics/pipe/manifold/visible/red
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold/visible/blue
+ color = PIPE_COLOR_BLUE
+
+
+/obj/machinery/atmospherics/pipe/manifold/hidden
+ icon_state = "map"
+ level = 1
+ alpha = 128 //set for the benefit of mapping - this is reset to opaque when the pipe is spawned in game
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers
+ name="Scrubbers pipe manifold"
+ desc = "A manifold composed of scrubbers pipes"
+ icon_state = "map-scrubbers"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/supply
+ name="Air supply pipe manifold"
+ desc = "A manifold composed of supply pipes"
+ icon_state = "map-supply"
+ connect_types = CONNECT_TYPE_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/yellow
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/cyan
+ color = PIPE_COLOR_CYAN
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/green
+ color = PIPE_COLOR_GREEN
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/black
+ color = PIPE_COLOR_BLACK
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/red
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/blue
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/manifold4w
+ icon = 'icons/atmos/manifold.dmi'
+ icon_state = ""
+ name = "4-way pipe manifold"
+ desc = "A manifold composed of regular pipes"
+
+ volume = ATMOS_DEFAULT_VOLUME_PIPE * 2
+
+ dir = SOUTH
+ initialize_directions = NORTH|SOUTH|EAST|WEST
+
+ var/obj/machinery/atmospherics/node3
+ var/obj/machinery/atmospherics/node4
+
+ level = 1
+ layer = 2.4 //under wires with their 2.44
+
+/obj/machinery/atmospherics/pipe/manifold4w/Initialize()
+ . = ..()
+ alpha = 255
+ icon = null
+
+/obj/machinery/atmospherics/pipe/manifold4w/pipeline_expansion()
+ return list(node1, node2, node3, node4)
+
+/obj/machinery/atmospherics/pipe/manifold4w/machinery_process()
+ if(!parent)
+ ..()
+ else
+ . = PROCESS_KILL
+
+/obj/machinery/atmospherics/pipe/manifold4w/Destroy()
+ if(node1)
+ node1.disconnect(src)
+ node1 = null
+ if(node2)
+ node2.disconnect(src)
+ node2 = null
+ if(node3)
+ node3.disconnect(src)
+ node3 = null
+ if(node4)
+ node4.disconnect(src)
+ node4 = null
+
+ return ..()
+
+/obj/machinery/atmospherics/pipe/manifold4w/disconnect(obj/machinery/atmospherics/reference)
+ if(reference == node1)
+ if(istype(node1, /obj/machinery/atmospherics/pipe))
+ QDEL_NULL(parent)
+ node1 = null
+
+ if(reference == node2)
+ if(istype(node2, /obj/machinery/atmospherics/pipe))
+ QDEL_NULL(parent)
+ node2 = null
+
+ if(reference == node3)
+ if(istype(node3, /obj/machinery/atmospherics/pipe))
+ QDEL_NULL(parent)
+ node3 = null
+
+ if(reference == node4)
+ if(istype(node4, /obj/machinery/atmospherics/pipe))
+ QDEL_NULL(parent)
+ node4 = null
+
+ update_icon()
+
+ ..()
+
+/obj/machinery/atmospherics/pipe/manifold4w/change_color(var/new_color)
+ ..()
+ //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
+ if(node1)
+ node1.update_underlays()
+ if(node2)
+ node2.update_underlays()
+ if(node3)
+ node3.update_underlays()
+ if(node4)
+ node4.update_underlays()
+
+/obj/machinery/atmospherics/pipe/manifold4w/update_icon(var/safety = 0)
+ if(!check_icon_cache())
+ return
+
+ alpha = 255
+
+ if(!node1 && !node2 && !node3 && !node4)
+ var/turf/T = get_turf(src)
+ new /obj/item/pipe(loc, make_from=src)
+ for (var/obj/machinery/meter/meter in T)
+ if (meter.target == src)
+ new /obj/item/pipe_meter(T)
+ qdel(meter)
+ qdel(src)
+ else
+ cut_overlays()
+ add_overlay(icon_manager.get_atmos_icon("manifold", , pipe_color, "4way" + icon_connect_type))
+ add_overlay(icon_manager.get_atmos_icon("manifold", , , "clamps_4way" + icon_connect_type))
+
+ underlays.Cut()
+
+ /*
+ var/list/directions = list(NORTH, SOUTH, EAST, WEST)
+
+
+ directions -= add_underlay(node1)
+ directions -= add_underlay(node2)
+ directions -= add_underlay(node3)
+ directions -= add_underlay(node4)
+
+ for(var/D in directions)
+ add_underlay(,D)
+ */
+
+ var/turf/T = get_turf(src)
+ var/list/directions = list(NORTH, SOUTH, EAST, WEST)
+ var/node1_direction = get_dir(src, node1)
+ var/node2_direction = get_dir(src, node2)
+ var/node3_direction = get_dir(src, node3)
+ var/node4_direction = get_dir(src, node4)
+
+ directions -= dir
+
+ directions -= add_underlay(T,node1,node1_direction,icon_connect_type)
+ directions -= add_underlay(T,node2,node2_direction,icon_connect_type)
+ directions -= add_underlay(T,node3,node3_direction,icon_connect_type)
+ directions -= add_underlay(T,node4,node4_direction,icon_connect_type)
+
+ for(var/D in directions)
+ add_underlay(T,,D,icon_connect_type)
+
+
+/obj/machinery/atmospherics/pipe/manifold4w/update_underlays()
+ ..()
+ queue_icon_update()
+
+/obj/machinery/atmospherics/pipe/manifold4w/hide(var/i)
+ if(istype(loc, /turf/simulated))
+ invisibility = i ? 101 : 0
+ queue_icon_update()
+
+/obj/machinery/atmospherics/pipe/manifold4w/atmos_init()
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,1))
+ if(target.initialize_directions & 2)
+ if (check_connect_types(target,src))
+ node1 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,2))
+ if(target.initialize_directions & 1)
+ if (check_connect_types(target,src))
+ node2 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,4))
+ if(target.initialize_directions & 8)
+ if (check_connect_types(target,src))
+ node3 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,8))
+ if(target.initialize_directions & 4)
+ if (check_connect_types(target,src))
+ node4 = target
+ break
+
+ if(!node1 && !node2 && !node3 && !node4)
+ qdel(src)
+ return
+
+ var/turf/T = get_turf(src)
+ if(level == 1 && !T.is_plating()) hide(1)
+ queue_icon_update()
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible
+ icon_state = "map_4way"
+ level = 2
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/scrubbers
+ name="4-way scrubbers pipe manifold"
+ desc = "A manifold composed of scrubbers pipes"
+ icon_state = "map_4way-scrubbers"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/supply
+ name="4-way air supply pipe manifold"
+ desc = "A manifold composed of supply pipes"
+ icon_state = "map_4way-supply"
+ connect_types = CONNECT_TYPE_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/yellow
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/cyan
+ color = PIPE_COLOR_CYAN
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/green
+ color = PIPE_COLOR_GREEN
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/black
+ color = PIPE_COLOR_BLACK
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/red
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/blue
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden
+ icon_state = "map_4way"
+ level = 1
+ alpha = 128 //set for the benefit of mapping - this is reset to opaque when the pipe is spawned in game
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers
+ name="4-way scrubbers pipe manifold"
+ desc = "A manifold composed of scrubbers pipes"
+ icon_state = "map_4way-scrubbers"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/supply
+ name="4-way air supply pipe manifold"
+ desc = "A manifold composed of supply pipes"
+ icon_state = "map_4way-supply"
+ connect_types = CONNECT_TYPE_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/yellow
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/cyan
+ color = PIPE_COLOR_CYAN
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/green
+ color = PIPE_COLOR_GREEN
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/black
+ color = PIPE_COLOR_BLACK
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/red
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/blue
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/cap
+ name = "pipe endcap"
+ desc = "An endcap for pipes"
+ icon = 'icons/atmos/pipes.dmi'
+ icon_state = ""
+ level = 2
+ layer = 2.4 //under wires with their 2.44
+
+ volume = 35
+
+ dir = SOUTH
+ initialize_directions = SOUTH
+
+ var/obj/machinery/atmospherics/node
+
+/obj/machinery/atmospherics/pipe/cap/Initialize()
+ initialize_directions = dir
+ . = ..()
+
+/obj/machinery/atmospherics/pipe/cap/hide(var/i)
+ if(istype(loc, /turf/simulated))
+ invisibility = i ? 101 : 0
+ queue_icon_update()
+
+/obj/machinery/atmospherics/pipe/cap/pipeline_expansion()
+ return list(node)
+
+/obj/machinery/atmospherics/pipe/cap/machinery_process()
+ if(!parent)
+ ..()
+ else
+ . = PROCESS_KILL
+/obj/machinery/atmospherics/pipe/cap/Destroy()
+ if(node)
+ node.disconnect(src)
+
+ node = null
+
+ return ..()
+
+/obj/machinery/atmospherics/pipe/cap/disconnect(obj/machinery/atmospherics/reference)
+ if(reference == node)
+ if(istype(node, /obj/machinery/atmospherics/pipe))
+ QDEL_NULL(parent)
+ node = null
+
+ update_icon()
+
+ ..()
+
+/obj/machinery/atmospherics/pipe/cap/change_color(var/new_color)
+ ..()
+ //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
+ if(node)
+ node.update_underlays()
+
+/obj/machinery/atmospherics/pipe/cap/update_icon(var/safety = 0)
+ if(!check_icon_cache())
+ return
+
+ alpha = 255
+
+ cut_overlays()
+ add_overlay(icon_manager.get_atmos_icon("pipe", , pipe_color, "cap"))
+
+/obj/machinery/atmospherics/pipe/cap/atmos_init()
+ for(var/obj/machinery/atmospherics/target in get_step(src, dir))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node = target
+ break
+
+ var/turf/T = src.loc // hide if turf is not intact
+ if(level == 1 && !T.is_plating()) hide(1)
+ queue_icon_update()
+
+/obj/machinery/atmospherics/pipe/cap/visible
+ level = 2
+ icon_state = "cap"
+
+/obj/machinery/atmospherics/pipe/cap/visible/scrubbers
+ name = "scrubbers pipe endcap"
+ desc = "An endcap for scrubbers pipes"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/cap/visible/supply
+ name = "supply pipe endcap"
+ desc = "An endcap for supply pipes"
+ connect_types = CONNECT_TYPE_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/cap/hidden
+ level = 1
+ icon_state = "cap"
+ alpha = 128
+
+/obj/machinery/atmospherics/pipe/cap/hidden/scrubbers
+ name = "scrubbers pipe endcap"
+ desc = "An endcap for scrubbers pipes"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/cap/hidden/supply
+ name = "supply pipe endcap"
+ desc = "An endcap for supply pipes"
+ connect_types = CONNECT_TYPE_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
+
+
+/obj/machinery/atmospherics/pipe/tank
+ icon = 'icons/atmos/tank.dmi'
+ icon_state = "air_map"
+
+ name = "Pressure Tank"
+ desc = "A large vessel containing pressurized gas."
+
+ volume = 10000 //in liters, 1 meters by 1 meters by 2 meters ~tweaked it a little to simulate a pressure tank without needing to recode them yet
+ var/start_pressure = 25*ONE_ATMOSPHERE
+
+ level = 1
+ dir = SOUTH
+ initialize_directions = SOUTH
+ density = 1
+
+/obj/machinery/atmospherics/pipe/tank/Initialize()
+ icon_state = "air"
+ initialize_directions = dir
+ . = ..()
+
+/obj/machinery/atmospherics/pipe/tank/machinery_process()
+ if(!parent)
+ ..()
+ else
+ . = PROCESS_KILL
+
+/obj/machinery/atmospherics/pipe/tank/Destroy()
+ if(node1)
+ node1.disconnect(src)
+
+ node1 = null
+
+ return ..()
+
+/obj/machinery/atmospherics/pipe/tank/pipeline_expansion()
+ return list(node1)
+
+/obj/machinery/atmospherics/pipe/tank/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ add_underlay(T, node1, dir)
+
+/obj/machinery/atmospherics/pipe/tank/hide()
+ update_underlays()
+
+/obj/machinery/atmospherics/pipe/tank/atmos_init()
+ var/connect_direction = dir
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,connect_direction))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node1 = target
+ break
+
+ update_underlays()
+
+/obj/machinery/atmospherics/pipe/tank/disconnect(obj/machinery/atmospherics/reference)
+ if(reference == node1)
+ if(istype(node1, /obj/machinery/atmospherics/pipe))
+ QDEL_NULL(parent)
+ node1 = null
+
+ update_underlays()
+
+ return null
+
+/obj/machinery/atmospherics/pipe/tank/attackby(var/obj/item/W as obj, var/mob/user as mob)
+ if(istype(W, /obj/item/device/pipe_painter))
+ return
+
+ if(istype(W, /obj/item/device/analyzer) && in_range(user, src))
+ var/obj/item/device/analyzer/A = W
+ A.analyze_gases(src, user)
+
+/obj/machinery/atmospherics/pipe/tank/air
+ name = "Pressure Tank (Air)"
+ icon_state = "air_map"
+
+/obj/machinery/atmospherics/pipe/tank/air/Initialize()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T20C
+
+ air_temporary.adjust_multi("oxygen", (start_pressure*O2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature), \
+ "nitrogen",(start_pressure*N2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+
+ . = ..()
+ icon_state = "air"
+
+/obj/machinery/atmospherics/pipe/tank/oxygen
+ name = "Pressure Tank (Oxygen)"
+ icon_state = "o2_map"
+
+/obj/machinery/atmospherics/pipe/tank/oxygen/Initialize()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T20C
+
+ air_temporary.adjust_gas("oxygen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+ . = ..()
+ icon_state = "o2"
+
+/obj/machinery/atmospherics/pipe/tank/nitrogen
+ name = "Pressure Tank (Nitrogen)"
+ icon_state = "n2_map"
+
+/obj/machinery/atmospherics/pipe/tank/nitrogen/Initialize()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T20C
+
+ air_temporary.adjust_gas("nitrogen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+ . = ..()
+ icon_state = "n2"
+
+/obj/machinery/atmospherics/pipe/tank/carbon_dioxide
+ name = "Pressure Tank (Carbon Dioxide)"
+ icon_state = "co2_map"
+
+/obj/machinery/atmospherics/pipe/tank/carbon_dioxide/Initialize()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T20C
+
+ air_temporary.adjust_gas("carbon_dioxide", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+ . = ..()
+ icon_state = "co2"
+
+/obj/machinery/atmospherics/pipe/tank/phoron
+ name = "Pressure Tank (Phoron)"
+ icon_state = "phoron_map"
+
+/obj/machinery/atmospherics/pipe/tank/phoron/Initialize()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T20C
+
+ air_temporary.adjust_gas("phoron", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+ . = ..()
+ icon_state = "phoron"
+
+/obj/machinery/atmospherics/pipe/tank/nitrous_oxide
+ name = "Pressure Tank (Nitrous Oxide)"
+ icon_state = "n2o_map"
+
+/obj/machinery/atmospherics/pipe/tank/nitrous_oxide/Initialize()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T0C
+
+ air_temporary.adjust_gas("sleeping_agent", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+ . = ..()
+ icon_state = "n2o"
+
+/obj/machinery/atmospherics/pipe/vent
+ icon = 'icons/obj/atmospherics/pipe_vent.dmi'
+ icon_state = "intact"
+
+ name = "Vent"
+ desc = "A large air vent"
+
+ level = 1
+
+ volume = 250
+
+ dir = SOUTH
+ initialize_directions = SOUTH
+
+ var/build_killswitch = 1
+
+/obj/machinery/atmospherics/pipe/vent/Initialize()
+ initialize_directions = dir
+ . = ..()
+
+/obj/machinery/atmospherics/pipe/vent/high_volume
+ name = "Larger vent"
+ volume = 1000
+
+/obj/machinery/atmospherics/pipe/vent/machinery_process()
+ if(!parent)
+ if(build_killswitch <= 0)
+ . = PROCESS_KILL
+ else
+ build_killswitch--
+ ..()
+ return
+ else
+ parent.mingle_with_turf(loc, volume)
+
+/obj/machinery/atmospherics/pipe/vent/Destroy()
+ if(node1)
+ node1.disconnect(src)
+
+ node1 = null
+
+ return ..()
+
+/obj/machinery/atmospherics/pipe/vent/pipeline_expansion()
+ return list(node1)
+
+/obj/machinery/atmospherics/pipe/vent/update_icon()
+ if(node1)
+ icon_state = "intact"
+
+ set_dir(get_dir(src, node1))
+
+ else
+ icon_state = "exposed"
+
+/obj/machinery/atmospherics/pipe/vent/atmos_init()
+ var/connect_direction = dir
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,connect_direction))
+ if(target.initialize_directions & get_dir(target,src))
+ if (check_connect_types(target,src))
+ node1 = target
+ break
+
+ queue_icon_update()
+
+/obj/machinery/atmospherics/pipe/vent/disconnect(obj/machinery/atmospherics/reference)
+ if(reference == node1)
+ if(istype(node1, /obj/machinery/atmospherics/pipe))
+ QDEL_NULL(parent)
+ node1 = null
+
+ update_icon()
+
+ return null
+
+/obj/machinery/atmospherics/pipe/vent/hide(var/i) //to make the little pipe section invisible, the icon changes.
+ if(node1)
+ icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]intact"
+ set_dir(get_dir(src, node1))
+ else
+ icon_state = "exposed"
+
+
+/obj/machinery/atmospherics/pipe/simple/visible/universal
+ name="Universal pipe adapter"
+ desc = "An adapter for regular, supply and scrubbers pipes"
+ connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER
+ icon_state = "map_universal"
+ gfi_layer_rotation = GFI_ROTATION_OVERDIR
+
+/obj/machinery/atmospherics/pipe/simple/visible/universal/update_icon(var/safety = 0)
+ if(!check_icon_cache())
+ return
+
+ alpha = 255
+
+ cut_overlays()
+ add_overlay(icon_manager.get_atmos_icon("pipe", , pipe_color, "universal"))
+ underlays.Cut()
+
+ if (node1)
+ universal_underlays(node1)
+ if(node2)
+ universal_underlays(node2)
+ else
+ var/node1_dir = get_dir(node1,src)
+ universal_underlays(,node1_dir)
+ else if (node2)
+ universal_underlays(node2)
+ else
+ universal_underlays(,dir)
+ universal_underlays(,turn(dir, -180))
+
+/obj/machinery/atmospherics/pipe/simple/visible/universal/update_underlays()
+ ..()
+ queue_icon_update()
+
+
+
+/obj/machinery/atmospherics/pipe/simple/hidden/universal
+ name="Universal pipe adapter"
+ desc = "An adapter for regular, supply and scrubbers pipes"
+ connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER
+ icon_state = "map_universal"
+ gfi_layer_rotation = GFI_ROTATION_OVERDIR
+
+/obj/machinery/atmospherics/pipe/simple/hidden/universal/update_icon(var/safety = 0)
+ if(!check_icon_cache())
+ return
+
+ alpha = 255
+
+ cut_overlays()
+ add_overlay(icon_manager.get_atmos_icon("pipe", , pipe_color, "universal"))
+
+ underlays.Cut()
+
+ if (node1)
+ universal_underlays(node1)
+ if(node2)
+ universal_underlays(node2)
+ else
+ var/node2_dir = turn(get_dir(src,node1),-180)
+ universal_underlays(,node2_dir)
+ else if (node2)
+ universal_underlays(node2)
+ var/node1_dir = turn(get_dir(src,node2),-180)
+ universal_underlays(,node1_dir)
+ else
+ universal_underlays(,dir)
+ universal_underlays(,turn(dir, -180))
+
+/obj/machinery/atmospherics/pipe/simple/hidden/universal/update_underlays()
+ ..()
+ queue_icon_update()
+
+/obj/machinery/atmospherics/proc/universal_underlays(var/obj/machinery/atmospherics/node, var/direction)
+ var/turf/T = loc
+ if(node)
+ var/node_dir = get_dir(src,node)
+ if(node.icon_connect_type == "-supply")
+ add_underlay_adapter(T, , node_dir, "")
+ add_underlay_adapter(T, node, node_dir, "-supply")
+ add_underlay_adapter(T, , node_dir, "-scrubbers")
+ else if (node.icon_connect_type == "-scrubbers")
+ add_underlay_adapter(T, , node_dir, "")
+ add_underlay_adapter(T, , node_dir, "-supply")
+ add_underlay_adapter(T, node, node_dir, "-scrubbers")
+ else
+ add_underlay_adapter(T, node, node_dir, "")
+ add_underlay_adapter(T, , node_dir, "-supply")
+ add_underlay_adapter(T, , node_dir, "-scrubbers")
+ else
+ add_underlay_adapter(T, , direction, "-supply")
+ add_underlay_adapter(T, , direction, "-scrubbers")
+ add_underlay_adapter(T, , direction, "")
+
+/obj/machinery/atmospherics/proc/add_underlay_adapter(var/turf/T, var/obj/machinery/atmospherics/node, var/direction, var/icon_connect_type) //modified from add_underlay, does not make exposed underlays
+ if(node)
+ if(!T.is_plating() && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
+ underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "down" + icon_connect_type)
+ else
+ underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
+ else
+ underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "retracted" + icon_connect_type)
diff --git a/code/ZAS/Airflow.dm b/code/ZAS/Airflow.dm
index f849d2fd419..4fb32e22492 100644
--- a/code/ZAS/Airflow.dm
+++ b/code/ZAS/Airflow.dm
@@ -117,14 +117,14 @@ mob/living/carbon/human/airflow_hit(atom/A)
bloody_body(src)
var/b_loss = airflow_speed * vsc.airflow_damage
- var/blocked = run_armor_check("head","melee")
- apply_damage(b_loss/3, BRUTE, "head", blocked, 0, "Airflow")
+ var/blocked = run_armor_check(BP_HEAD,"melee")
+ apply_damage(b_loss/3, BRUTE, BP_HEAD, blocked, 0, "Airflow")
- blocked = run_armor_check("chest","melee")
- apply_damage(b_loss/3, BRUTE, "chest", blocked, 0, "Airflow")
+ blocked = run_armor_check(BP_CHEST,"melee")
+ apply_damage(b_loss/3, BRUTE, BP_CHEST, blocked, 0, "Airflow")
- blocked = run_armor_check("groin","melee")
- apply_damage(b_loss/3, BRUTE, "groin", blocked, 0, "Airflow")
+ blocked = run_armor_check(BP_GROIN,"melee")
+ apply_damage(b_loss/3, BRUTE, BP_GROIN, blocked, 0, "Airflow")
if(airflow_speed > 10)
Paralyse(round(airflow_speed * vsc.airflow_stun))
@@ -135,15 +135,17 @@ mob/living/carbon/human/airflow_hit(atom/A)
zone/proc/movables(list/origins)
. = list()
- if (!origins || !origins.len)
+ if (!origins?.len)
return
var/static/list/movables_tcache = typecacheof(list(/obj/effect, /mob/abstract))
var/atom/movable/AM
for (var/testing_turf in contents)
+ CHECK_TICK
for (var/am in testing_turf)
AM = am
+ CHECK_TICK
if (AM.simulated && !AM.anchored && !movables_tcache[AM.type])
for (var/source_turf in origins)
if (get_dist(testing_turf, source_turf) <= EDGE_KNOCKDOWN_MAX_DISTANCE)
diff --git a/code/ZAS/Fire.dm b/code/ZAS/Fire.dm
index 3ccb8a9baaf..80ac5068272 100644
--- a/code/ZAS/Fire.dm
+++ b/code/ZAS/Fire.dm
@@ -155,6 +155,8 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
else
icon_state = "1"
set_light(3, FIRE_LIGHT_1, no_update = TRUE)
+
+ air_contents.adjust_gas("carbon_dioxide", firelevel * 0.07)
for(var/mob/living/L in loc)
L.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure()) //Burn the mobs!
@@ -453,13 +455,13 @@ datum/gas_mixture/proc/check_recombustability(list/fuel_objs)
//Always check these damage procs first if fire damage isn't working. They're probably what's wrong.
- apply_damage(2.5*mx*head_exposure, BURN, "head", 0, 0, "Fire")
- apply_damage(2.5*mx*chest_exposure, BURN, "chest", 0, 0, "Fire")
- apply_damage(2.0*mx*groin_exposure, BURN, "groin", 0, 0, "Fire")
- apply_damage(0.6*mx*legs_exposure, BURN, "l_leg", 0, 0, "Fire")
- apply_damage(0.6*mx*legs_exposure, BURN, "r_leg", 0, 0, "Fire")
- apply_damage(0.4*mx*arms_exposure, BURN, "l_arm", 0, 0, "Fire")
- apply_damage(0.4*mx*arms_exposure, BURN, "r_arm", 0, 0, "Fire")
+ apply_damage(2.5*mx*head_exposure, BURN, BP_HEAD, 0, 0, "Fire")
+ apply_damage(2.5*mx*chest_exposure, BURN, BP_CHEST, 0, 0, "Fire")
+ apply_damage(2.0*mx*groin_exposure, BURN, BP_GROIN, 0, 0, "Fire")
+ apply_damage(0.6*mx*legs_exposure, BURN, BP_L_LEG, 0, 0, "Fire")
+ apply_damage(0.6*mx*legs_exposure, BURN, BP_R_LEG, 0, 0, "Fire")
+ apply_damage(0.4*mx*arms_exposure, BURN, BP_L_ARM, 0, 0, "Fire")
+ apply_damage(0.4*mx*arms_exposure, BURN, BP_R_ARM, 0, 0, "Fire")
#undef FIRE_LIGHT_1
diff --git a/code/ZAS/Phoron.dm b/code/ZAS/Phoron.dm
index 9be9a7099ae..8ba2fd3d6e6 100644
--- a/code/ZAS/Phoron.dm
+++ b/code/ZAS/Phoron.dm
@@ -44,7 +44,7 @@ obj/var/contaminated = 0
/obj/item/proc/can_contaminate()
//Clothing and backpacks can be contaminated.
if(flags & PHORONGUARD) return 0
- else if(istype(src,/obj/item/weapon/storage/backpack)) return 0 //Cannot be washed :(
+ else if(istype(src,/obj/item/storage/backpack)) return 0 //Cannot be washed :(
else if(istype(src,/obj/item/clothing)) return 1
/obj/item/proc/contaminate()
@@ -69,7 +69,7 @@ obj/var/contaminated = 0
if(prob(1)) suit_contamination() //Phoron can sometimes get through such an open suit.
//Cannot wash backpacks currently.
-// if(istype(back,/obj/item/weapon/storage/backpack))
+// if(istype(back,/obj/item/storage/backpack))
// back.contaminate()
/mob/proc/pl_effects()
@@ -126,7 +126,7 @@ obj/var/contaminated = 0
if (!has_eyes() || species.eyes_are_impermeable)
return
- var/obj/item/organ/eyes/E = get_eyes(no_synthetic = TRUE)
+ var/obj/item/organ/internal/eyes/E = get_eyes(no_synthetic = TRUE)
if(E)
if(prob(20)) to_chat(src, "Your eyes burn!")
E.damage += 2.5
diff --git a/code/__defines/_compile_options.dm b/code/__defines/_compile_options.dm
index c54c5376a22..74ed9385558 100644
--- a/code/__defines/_compile_options.dm
+++ b/code/__defines/_compile_options.dm
@@ -1,5 +1,5 @@
-#define BACKGROUND_ENABLED 0 // The default value for all uses of set background. Set background can cause gradual lag and is recommended you only turn this on if necessary.
- // 1 will enable set background. 0 will disable set background.
-
-// If defined, the sunlight system is enabled. Caution: this uses a LOT of memory.
-//#define ENABLE_SUNLIGHT
+#define BACKGROUND_ENABLED 0 // The default value for all uses of set background. Set background can cause gradual lag and is recommended you only turn this on if necessary.
+ // 1 will enable set background. 0 will disable set background.
+
+// If defined, the sunlight system is enabled. Caution: this uses a LOT of memory.
+//#define ENABLE_SUNLIGHT
diff --git a/code/__defines/_layers.dm b/code/__defines/_layers.dm
index ab1ffc669e3..60a3c1ee8b6 100644
--- a/code/__defines/_layers.dm
+++ b/code/__defines/_layers.dm
@@ -3,7 +3,6 @@
#define PLANE_SPACE_DUST (PLANE_SPACE_PARALLAX + 1) // -96
#define PLANE_ABOVE_PARALLAX (PLANE_SPACE_BACKGROUND + 3) // -95
-
#define LOWER_ON_TURF_LAYER (TURF_LAYER + 0.05) // under the below
#define ON_TURF_LAYER (TURF_LAYER + 0.1) // sitting on the turf - should be preferred over direct use of TURF_LAYER
#define AO_LAYER (ON_TURF_LAYER + 0.1)
@@ -16,6 +15,17 @@
#define BELOW_MOB_LAYER 3.7
#define ABOVE_MOB_LAYER 4.1
#define LIGHTING_LAYER 11
+#define EFFECTS_ABOVE_LIGHTING_LAYER 12 // For overlays you want to be above light.
#define HUD_LAYER 20 //Above lighting, but below obfuscation. For in-game HUD effects (whereas SCREEN_LAYER is for abstract/OOC things like inventory slots)
#define OBFUSCATION_LAYER 21 //Where images covering the view for eyes are put
#define SCREEN_LAYER 22 //Mob HUD/effects layer
+#define CINEMA_LAYER 23
+
+#define MECH_BASE_LAYER 4.01
+#define MECH_INTERMEDIATE_LAYER 4.02
+#define MECH_PILOT_LAYER 4.03
+#define MECH_LEG_LAYER 4.04
+#define MECH_COCKPIT_LAYER 4.05
+#define MECH_ARM_LAYER 4.06
+#define MECH_DECAL_LAYER 4.07
+#define MECH_GEAR_LAYER 4.08
\ No newline at end of file
diff --git a/code/__defines/_macros.dm b/code/__defines/_macros.dm
index 4150fea9b72..e97ef70ad61 100644
--- a/code/__defines/_macros.dm
+++ b/code/__defines/_macros.dm
@@ -1,7 +1,24 @@
#define Clamp(x, low, high) max(low, min(high, x))
#define CLAMP01(x) (Clamp(x, 0, 1))
-#define span(class, text) ("[text]")
+#define span(class, text) "[text]"
+#define SPAN_NOTICE(X) "[X]"
+#define SPAN_WARNING(X) "[X]"
+#define SPAN_DANGER(X) "[X]"
+#define SPAN_CULT(X) "[X]"
+#define SPAN_GOOD(X) "[X]"
+#define SPAN_BAD(X) "[X]"
+#define SPAN_ALIEN(X) "[X]"
+#define SPAN_ALERT(X) "[X]"
+#define SPAN_ITALIC(X) "[X]"
+#define SPAN_BOLD(X) "[X]"
+#define SPAN_SUBTLE(X) "[X]"
+
+#define FONT_SMALL(X) "[X]"
+#define FONT_NORMAL(X) "[X]"
+#define FONT_LARGE(X) "[X]"
+#define FONT_HUGE(X) "[X]"
+#define FONT_GIANT(X) "[X]"
#define isAI(A) istype(A, /mob/living/silicon/ai)
#define isDrone(A) istype(A, /mob/living/silicon/robot/drone)
@@ -22,9 +39,11 @@
#define ishuman(A) istype(A, /mob/living/carbon/human)
+#define ismech(A) istype(A, /mob/living/heavy_vehicle)
+
#define isliving(A) istype(A, /mob/living)
-#define ismouse(A) istype(A, /mob/living/simple_animal/mouse)
+#define israt(A) istype(A, /mob/living/simple_animal/rat)
#define isnewplayer(A) istype(A, /mob/abstract/new_player)
@@ -42,15 +61,15 @@
#define isslime(A) istype(A, /mob/living/carbon/slime)
-#define iscapacitor(A) istype(A, /obj/item/weapon/stock_parts/capacitor)
+#define iscapacitor(A) istype(A, /obj/item/stock_parts/capacitor)
-#define ismicrolaser(A) istype(A, /obj/item/weapon/stock_parts/micro_laser)
+#define ismicrolaser(A) istype(A, /obj/item/stock_parts/micro_laser)
-#define ismatterbin(A) istype(A, /obj/item/weapon/stock_parts/matter_bin)
+#define ismatterbin(A) istype(A, /obj/item/stock_parts/matter_bin)
-#define isscanner(A) istype(A, /obj/item/weapon/stock_parts/scanning_module)
+#define isscanner(A) istype(A, /obj/item/stock_parts/scanning_module)
-#define ismanipulator(A) istype(A, /obj/item/weapon/stock_parts/manipulator)
+#define ismanipulator(A) istype(A, /obj/item/stock_parts/manipulator)
#define isclient(A) istype(A, /client)
@@ -63,6 +82,7 @@
#define show_browser(target, browser_content, browser_name) target << browse(browser_content, browser_name)
#define send_rsc(target, rsc_content, rsc_name) target << browse_rsc(rsc_content, rsc_name)
#define send_output(target, msg, control) target << output(msg, control)
+#define send_link(target, url) target << link(url)
#define CanInteract(user, state) (CanUseTopic(user, state) == STATUS_INTERACTIVE)
diff --git a/code/__defines/admin.dm b/code/__defines/admin.dm
index 72a65bd58b5..ed1934fedac 100644
--- a/code/__defines/admin.dm
+++ b/code/__defines/admin.dm
@@ -41,6 +41,7 @@
#define R_CCIAA 0x8000 //higher than this will overflow
#define R_MAXPERMISSION 0x8000 // This holds the maximum value for a permission. It is used in iteration, so keep it updated.
+#define R_ALL 0x7FFF // All perms forever.
// ticket statuses
#define TICKET_CLOSED 0
@@ -51,3 +52,6 @@
#define NOT_ADMINHELPED 0
#define ADMINHELPED 1
#define ADMINHELPED_DISCORD 2
+
+#define STICKYBAN_DB_CACHE_TIME (10 SECONDS)
+#define STICKYBAN_ROGUE_CHECK_TIME 5
diff --git a/code/__defines/atmos.dm b/code/__defines/atmos.dm
index 7f1d870746d..7581f6897f1 100644
--- a/code/__defines/atmos.dm
+++ b/code/__defines/atmos.dm
@@ -24,8 +24,8 @@
#define SOUND_MINIMUM_PRESSURE 10
#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.
-#define MAX_HIGH_PRESSURE_DAMAGE 4 // This used to be 20... I got this much random rage for some retarded decision by polymorph?! Polymorph now lies in a pool of blood with a katana jammed in his spleen. ~Errorage --PS: The katana did less than 20 damage to him :(
-#define LOW_PRESSURE_DAMAGE 2 // The amount of damage someone takes when in a low pressure area. (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value).
+#define MAX_HIGH_PRESSURE_DAMAGE 4
+#define LOW_PRESSURE_DAMAGE 0.5 // 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 MINIMUM_PRESSURE_DIFFERENCE_TO_SUSPEND (MINIMUM_AIR_TO_SUSPEND*R_IDEAL_GAS_EQUATION*T20C)/CELL_VOLUME // Minimum pressure difference between zones to suspend
#define MINIMUM_AIR_RATIO_TO_SUSPEND 0.05 // Minimum ratio of air that must move to/from a tile to suspend group processing
@@ -40,11 +40,11 @@
#define MINIMUM_TEMPERATURE_START_SUPERCONDUCTION (T20C + 200)
// Must be between 0 and 1. Values closer to 1 equalize temperature faster. Should not exceed 0.4, else strange heat flow occurs.
-#define FLOOR_HEAT_TRANSFER_COEFFICIENT 0.4
-#define WALL_HEAT_TRANSFER_COEFFICIENT 0.0
-#define DOOR_HEAT_TRANSFER_COEFFICIENT 0.0
-#define SPACE_HEAT_TRANSFER_COEFFICIENT 0.2 // A hack to partly simulate radiative heat.
-#define OPEN_HEAT_TRANSFER_COEFFICIENT 0.4
+#define FLOOR_HEAT_TRANSFER_COEFFICIENT 0.4
+#define WALL_HEAT_TRANSFER_COEFFICIENT 0.0
+#define DOOR_HEAT_TRANSFER_COEFFICIENT 0.0
+#define SPACE_HEAT_TRANSFER_COEFFICIENT 0.2 // A hack to partly simulate radiative heat.
+#define OPEN_HEAT_TRANSFER_COEFFICIENT 0.4
#define WINDOW_HEAT_TRANSFER_COEFFICIENT 0.1 // A hack for now.
// Fire damage.
diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm
index 682e55b81b1..eb67daefd5b 100644
--- a/code/__defines/chemistry.dm
+++ b/code/__defines/chemistry.dm
@@ -15,6 +15,9 @@
#define LIQUID 2
#define GAS 3
+#define REAGENTS_PER_SHEET 20
+#define MAX_PILL_SPRITE 20 //max icon state of the pill sprites
+
#define REAGENTS_OVERDOSE 30
#define REAGENTS_BURNING_TEMP_HIGH T0C + 65 //Temperature at which high temperature burns occur
@@ -42,21 +45,43 @@
#define IS_VAURCA 128
#define IS_UNDEAD 256
-#define CE_STABLE "stable" // Inaprovaline
-#define CE_ANTIBIOTIC "antibiotic" // Spaceacilin
-#define CE_BLOODRESTORE "bloodrestore" // Iron/nutriment
-#define CE_PAINKILLER "painkiller"
-#define CE_ALCOHOL "alcohol" // Liver filtering
-#define CE_ALCOHOL_TOXIC "alcotoxic" // Liver damage
-#define CE_SPEEDBOOST "gofast" // Hyperzine
-#define CE_BERSERK "berserk"
-#define CE_PACIFIED "pacified"
-
-// Chemistry lists.
-var/list/tachycardics = list("coffee", "inaprovaline", "hyperzine", "nitroglycerin", "thirteenloko", "nicotine") // Increase heart rate.
-var/list/bradycardics = list("neurotoxin", "cryoxadone", "clonexadone", "space_drugs", "stoxin") // Decrease heart rate.
-var/list/heartstopper = list("potassium_chlorophoride", "zombie_powder") // This stops the heart.
-var/list/cheartstopper = list("potassium_chloride") // This stops the heart when overdose is met. -- c = conditional
+// Apply status effects
+#define CE_ALCOHOL "alcohol" // Liver filtering
+#define CE_ANTIEMETIC "antiemetic" // suppresses vomiting
+#define CE_BERSERK "berserk"
+#define CE_CLUMSY "clumsy" // Peridaxon side effects, etc
+#define CE_DROPITEM "dropitem" // keloderm side effect
+#define CE_EMETIC "emetic" // thetamycin side effect, ipecac
+#define CE_FEVER "fever" // causes fever
+#define CE_NOCOUGH "nocough" // suppresses coughing
+#define CE_NOFEVER "nofever" // suppresses fever
+#define CE_NOPULSE "heartstop" // Stops heartbeat
+#define CE_SEDATE "sedation"
+#define CE_SLOWDOWN "goslow"
+#define CE_SPEEDBOOST "gofast" // Hyperzine
+#define CE_STABLE "stable" // Epinephrine
+#define CE_PACIFIED "pacified"
+#define CE_PAINKILLER "painkiller"
+#define CE_PULSE "xcardic" // increases or decreases heartrate
+#define CE_UNDEXTROUS "undextrous" // arms no work right
+#define CE_HALLUCINATE "hallucinogen" //Makes hallucinations stronger or weaker
+
+// Apply healing effects
+#define CE_ANTIBIOTIC "antibiotic" // Thetamycin
+#define CE_ANTITOXIN "antitoxin" // Dylovene and stuff
+#define CE_ANTIVIRAL "antiviral" // Deltamivir
+#define CE_BLOODRESTORE "bloodrestore" // Iron/nutriment
+#define CE_BRAIN_REGEN "brainfix" // Alkysine
+#define CE_OXYGENATED "oxygen" // Dexalin
+
+// Deal damage
+#define CE_BREATHLOSS "breathloss"
+#define CE_TOXIN "toxins" // General toxins
+#define CE_NEUROTOXIC "braintoxic" // Brain damage
+#define CE_NEPHROTOXIC "kidneytoxic" // Kidney damage
+#define CE_HEPATOTOXIC "livertoxic" // Liver damage
+#define CE_CARDIOTOXIC "hearttoxic" // Heart damage
+#define CE_PNEUMOTOXIC "lungtoxic" // Lung damage
//Alcohol
#define INTOX_BUZZED 0.01
@@ -70,9 +95,9 @@ var/list/cheartstopper = list("potassium_chloride") // Thi
#define INTOX_DEATH 0.45
//How many units of intoxication to remove per second
-#define INTOX_FILTER_HEALTHY 0.035
-#define INTOX_FILTER_BRUISED 0.02
-#define INTOX_FILTER_DAMAGED 0.010
+#define INTOX_FILTER_HEALTHY 0.35
+#define INTOX_FILTER_BRUISED 0.2
+#define INTOX_FILTER_DAMAGED 0.10
#define BASE_DIZZY 50 //Base dizziness from getting drunk.
#define DIZZY_ADD_SCALE 15 //Amount added for every 0.01 percent over the JUDGEIMP limit
diff --git a/code/__defines/color.dm b/code/__defines/color.dm
new file mode 100644
index 00000000000..de84f58281c
--- /dev/null
+++ b/code/__defines/color.dm
@@ -0,0 +1,120 @@
+#define COLOR_BLACK "#000000"
+#define COLOR_NAVY_BLUE "#000080"
+#define COLOR_GREEN "#008000"
+#define COLOR_BRIGHT_GREEN "#13cf13"
+#define COLOR_DARK_GRAY "#404040"
+#define COLOR_MAROON "#800000"
+#define COLOR_PURPLE "#800080"
+#define COLOR_VIOLET "#9933ff"
+#define COLOR_OLIVE "#808000"
+#define COLOR_BROWN_ORANGE "#824b28"
+#define COLOR_DARK_ORANGE "#b95a00"
+#define COLOR_GRAY40 "#666666"
+#define COLOR_GRAY20 "#333333"
+#define COLOR_GRAY15 "#151515"
+#define COLOR_SEDONA "#cc6600"
+#define COLOR_DARK_BROWN "#917448"
+#define COLOR_BLUE "#0000ff"
+#define COLOR_DEEP_SKY_BLUE "#00e1ff"
+#define COLOR_LIME "#00ff00"
+#define COLOR_CYAN "#00ffff"
+#define COLOR_TEAL "#33cccc"
+#define COLOR_RED "#ff0000"
+#define COLOR_PINK "#ff00ff"
+#define COLOR_PALE_PINK "#bf89ba"
+#define COLOR_ORANGE "#ff9900"
+#define COLOR_YELLOW "#ffff00"
+#define COLOR_YELLOW_GRAY "#c9a344"
+#define COLOR_PALE_YELLOW "#c1bb7a"
+#define COLOR_WARM_YELLOW "#b3863c"
+#define COLOR_YELLOW_ENGI "#efbf2f"
+#define COLOR_GRAY "#808080"
+#define COLOR_RED_GRAY "#aa5f61"
+#define COLOR_BROWN "#b19664"
+#define COLOR_GREEN_GRAY "#8daf6a"
+#define COLOR_DARK_GREEN_GRAY "#54654c"
+#define COLOR_BLUE_GRAY "#6a97b0"
+#define COLOR_DARK_BLUE_GRAY "#3e4855"
+#define COLOR_SURGERY_BLUE "#e0f2f6"
+#define COLOR_SUN "#ec8b2f"
+#define COLOR_PURPLE_GRAY "#a2819e"
+#define COLOR_BLUE_LIGHT "#33ccff"
+#define COLOR_RED_LIGHT "#ff3333"
+#define COLOR_BEIGE "#ceb689"
+#define COLOR_BABY_BLUE "#89cff0"
+#define COLOR_PALE_GREEN_GRAY "#aed18b"
+#define COLOR_PALE_RED_GRAY "#cc9090"
+#define COLOR_PALE_PURPLE_GRAY "#bda2ba"
+#define COLOR_PALE_BLUE_GRAY "#8bbbd5"
+#define COLOR_LUMINOL "#66ffff"
+#define COLOR_SILVER "#c0c0c0"
+#define COLOR_GRAY80 "#cccccc"
+#define COLOR_OFF_WHITE "#eeeeee"
+#define COLOR_WHITE "#ffffff"
+#define COLOR_GOLD "#ffcc33"
+#define COLOR_CLOSET_GOLD "#6d6133"
+#define COLOR_DARK_RED "#9d2300"
+#define COLOR_BOTTLE_GREEN "#1f6b4f"
+#define COLOR_PALE_BTL_GREEN "#57967f"
+#define COLOR_GUNMETAL "#545c68"
+#define COLOR_WALL_GUNMETAL "#353a42"
+#define COLOR_STEEL "#a8b0b2"
+#define COLOR_MUZZLE_FLASH "#ffffb2"
+#define COLOR_CHESTNUT "#996633"
+#define COLOR_BEASTY_BROWN "#663300"
+#define COLOR_WHEAT "#ffff99"
+#define COLOR_CYAN_BLUE "#3366cc"
+#define COLOR_LIGHT_CYAN "#66ccff"
+#define COLOR_PAKISTAN_GREEN "#006600"
+#define COLOR_HULL "#436b8e"
+#define COLOR_AMBER "#ffbf00"
+#define COLOR_COMMAND_BLUE "#46698c"
+#define COLOR_SKY_BLUE "#5ca1cc"
+#define COLOR_PALE_ORANGE "#b88a3b"
+#define COLOR_CIVIE_GREEN "#b7f27d"
+#define COLOR_TITANIUM "#d1e6e3"
+#define COLOR_DARK_GUNMETAL "#4c535b"
+#define COLOR_BRONZE "#8c7853"
+#define COLOR_BRASS "#b99d71"
+#define COLOR_INDIGO "#4b0082"
+#define COLOR_ALUMINIUM "#bbbbbb"
+#define COLOR_CRYSTAL "#00c8a5"
+#define COLOR_ASTEROID_ROCK "#735555"
+#define COLOR_HOT_PINK "#ff6088"
+#define COLOR_DIAMOND "#d8d4ea"
+#define COLOR_TCFL "#849bc1"
+#define COLOR_IAC "#96bcde"
+#define COLOR_RIPLEY "#ffbc37"
+#define COLOR_CULT "#402821"
+#define COLOR_CULT_REINFORCED "#8f3329"
+#define COLOR_CULT_DOOR "#402821"
+#define COLOR_OIL "#030303"
+#define COLOR_ASH "#615C5B"
+#define COLOR_SNOW "#9CADAD"
+
+
+// Blood colors
+#define COLOR_HUMAN_BLOOD "#A10808"
+#define COLOR_DIONA_BLOOD "#97DD7C"
+#define COLOR_IPC_BLOOD "#1F181F"
+#define COLOR_SKRELL_BLOOD "#1D2CBF"
+#define COLOR_VAURCA_BLOOD "#E6E600"
+
+
+//Color defines used by the assembly detailer.
+#define COLOR_ASSEMBLY_BLACK "#545454"
+#define COLOR_ASSEMBLY_BGRAY "#9497AB"
+#define COLOR_ASSEMBLY_WHITE "#E2E2E2"
+#define COLOR_ASSEMBLY_RED "#CC4242"
+#define COLOR_ASSEMBLY_ORANGE "#E39751"
+#define COLOR_ASSEMBLY_BEIGE "#AF9366"
+#define COLOR_ASSEMBLY_BROWN "#97670E"
+#define COLOR_ASSEMBLY_GOLD "#AA9100"
+#define COLOR_ASSEMBLY_YELLOW "#CECA2B"
+#define COLOR_ASSEMBLY_GURKHA "#999875"
+#define COLOR_ASSEMBLY_LGREEN "#789876"
+#define COLOR_ASSEMBLY_GREEN "#44843C"
+#define COLOR_ASSEMBLY_LBLUE "#5D99BE"
+#define COLOR_ASSEMBLY_BLUE "#38559E"
+#define COLOR_ASSEMBLY_PURPLE "#6F6192"
+#define COLOR_ASSEMBLY_HOT_PINK "#FF69B4"
\ No newline at end of file
diff --git a/code/__defines/damage_organs.dm b/code/__defines/damage_organs.dm
index 2b535967927..d69a535cf50 100644
--- a/code/__defines/damage_organs.dm
+++ b/code/__defines/damage_organs.dm
@@ -5,17 +5,20 @@
#define TOX "tox"
#define OXY "oxy"
#define CLONE "clone"
-#define HALLOSS "halloss"
+#define PAIN "pain"
#define CUT "cut"
#define BRUISE "bruise"
#define PIERCE "pierce"
+#define LASER "laser"
+
+#define DAM_LASER 1
+#define DAM_BULLET 2
#define STUN "stun"
#define WEAKEN "weaken"
#define PARALYZE "paralize"
#define IRRADIATE "irradiate"
-#define AGONY "agony" // Added in PAIN!
#define SLUR "slur"
#define STUTTER "stutter"
#define EYE_BLUR "eye_blur"
@@ -25,7 +28,7 @@
#define FIRE_DAMAGE_MODIFIER 0.0215 // Higher values result in more external fire damage to the skin. (default 0.0215)
#define AIR_DAMAGE_MODIFIER 2.025 // More means less damage from hot air scalding lungs, less = more damage. (default 2.025)
-// Organ defines.
+// Organ status defines.
#define ORGAN_CUT_AWAY (1<<0)
#define ORGAN_BLEEDING (1<<1)
#define ORGAN_BROKEN (1<<2)
@@ -37,6 +40,16 @@
#define ORGAN_ASSISTED (1<<8)
#define ORGAN_ADV_ROBOT (1<<9)
#define ORGAN_PLANT (1<<10)
+#define ORGAN_ARTERY_CUT (1<<11)
+#define ORGAN_TENDON_CUT (1<<12)
+
+// Limb behaviour defines.
+#define ORGAN_CAN_AMPUTATE (1<<0) //Can this organ be amputated?
+#define ORGAN_CAN_BREAK (1<<1) //Can this organ break?
+#define ORGAN_CAN_GRASP (1<<2) //Can this organ grasp things?
+#define ORGAN_CAN_STAND (1<<3) //Can this organ allow you to stand?
+#define ORGAN_CAN_MAIM (1<<4) //Can this organ be maimed?
+#define ORGAN_HAS_TENDON (1<<5) //Does this organ have tendons?
#define DROPLIMB_EDGE 0
#define DROPLIMB_BLUNT 1
@@ -52,3 +65,16 @@
#define INFECTION_LEVEL_ONE 100
#define INFECTION_LEVEL_TWO 500
#define INFECTION_LEVEL_THREE 1000
+
+//Blood levels. These are percentages based on the species blood_volume var.
+#define BLOOD_VOLUME_SAFE 85
+#define BLOOD_VOLUME_OKAY 70
+#define BLOOD_VOLUME_BAD 60
+#define BLOOD_VOLUME_SURVIVE 30
+
+// These control the amount of blood lost from burns. The loss is calculated so
+// that dealing just enough burn damage to kill the player will cause the given
+// proportion of their max blood volume to be lost
+// (e.g. 0.6 == 60% lost if 200 burn damage is taken).
+#define FLUIDLOSS_WIDE_BURN 0.4 //for burns from heat applied over a wider area, like from fire
+#define FLUIDLOSS_CONC_BURN 0.2 //for concentrated burns, like from lasers
diff --git a/code/__defines/dna.dm b/code/__defines/dna.dm
index 1655659da68..27c8e95fa3a 100644
--- a/code/__defines/dna.dm
+++ b/code/__defines/dna.dm
@@ -3,16 +3,15 @@
#define UNIDNASIZE 13
// Generic mutations:
-#define TK 1
-#define COLD_RESISTANCE 2
-#define XRAY 3
-#define HULK 4
-#define CLUMSY 5
-#define FAT 6
-#define HUSK 7
-#define NOCLONE 8
-#define LASER 9 // Harm intent - click anywhere to shoot lasers from eyes.
-#define HEAL 10 // Healing people with hands.
+#define COLD_RESISTANCE 1
+#define XRAY 2
+#define HULK 3
+#define CLUMSY 4
+#define FAT 5
+#define HUSK 6
+#define NOCLONE 7
+#define LASER_EYES 8 // Harm intent - click anywhere to shoot lasers from eyes.
+#define HEAL 9 // Healing people with hands.
#define SKELETON 29
#define PLANT 30
@@ -35,7 +34,7 @@
#define EPILEPSY 2
#define COUGHING 4
#define TOURETTES 8
-#define STUTTER 16
+#define STUTTERING 16
#define DUMB 32
#define MONKEYLIKE 64 //sets IsAdvancedToolUser to FALSE
#define PACIFIST 128
diff --git a/code/__defines/flags.dm b/code/__defines/flags.dm
new file mode 100644
index 00000000000..8b5f85d04a6
--- /dev/null
+++ b/code/__defines/flags.dm
@@ -0,0 +1,3 @@
+// Movable flags.
+#define MOVABLE_FLAG_EFFECTMOVE 1 //Is this an effect that should move?
+#define MOVABLE_FLAG_DEL_SHUTTLE 2 //Shuttle transition will delete this.
\ No newline at end of file
diff --git a/code/__defines/gamemode.dm b/code/__defines/gamemode.dm
index 74b1baa53a1..f48002d1bc1 100644
--- a/code/__defines/gamemode.dm
+++ b/code/__defines/gamemode.dm
@@ -35,7 +35,6 @@
// Mode/antag template macros.
#define MODE_BORER "borer"
-#define MODE_XENOMORPH "xeno"
#define MODE_LOYALIST "loyalist"
#define MODE_MUTINEER "mutineer"
#define MODE_COMMANDO "commando"
@@ -55,7 +54,6 @@
#define MODE_TRAITOR "traitor"
#define MODE_VAMPIRE "vampire"
#define MODE_THRALL "thrall"
-#define MODE_LEGION "tau ceti foreign legion"
#define DEFAULT_TELECRYSTAL_AMOUNT 25
diff --git a/code/__defines/guns.dm b/code/__defines/guns.dm
new file mode 100644
index 00000000000..17c71c74e99
--- /dev/null
+++ b/code/__defines/guns.dm
@@ -0,0 +1,8 @@
+#define BULLET_IMPACT_NONE "none"
+#define BULLET_IMPACT_METAL "metal"
+#define BULLET_IMPACT_MEAT "meat"
+
+#define SOUNDS_BULLET_MEAT list('sound/effects/projectile_impact/bullet_meat1.ogg', 'sound/effects/projectile_impact/bullet_meat2.ogg', 'sound/effects/projectile_impact/bullet_meat3.ogg', 'sound/effects/projectile_impact/bullet_meat4.ogg')
+#define SOUNDS_BULLET_METAL list('sound/effects/projectile_impact/bullet_metal1.ogg', 'sound/effects/projectile_impact/bullet_metal2.ogg', 'sound/effects/projectile_impact/bullet_metal3.ogg')
+#define SOUNDS_LASER_MEAT list('sound/effects/projectile_impact/energy_meat1.ogg','sound/effects/projectile_impact/energy_meat2.ogg')
+#define SOUNDS_LASER_METAL list('sound/effects/projectile_impact/energy_metal1.ogg','sound/effects/projectile_impact/energy_metal2.ogg')
\ No newline at end of file
diff --git a/code/__defines/items_clothing.dm b/code/__defines/items_clothing.dm
index cb64b01e788..d8d4df06832 100644
--- a/code/__defines/items_clothing.dm
+++ b/code/__defines/items_clothing.dm
@@ -1,7 +1,5 @@
#define HUMAN_STRIP_DELAY 40 // Takes 40ds = 4s to strip someone.
-#define SHOES_SLOWDOWN -1.0 // How much shoes slow you down by default. Negative values speed you up.
-
#define CANDLE_LUM 3 // For how bright candles are.
// Item inventory slot bitmasks.
@@ -91,6 +89,7 @@
#define slot_r_ear 20
#define slot_legs 21
#define slot_tie 22
+#define slot_in_belt 23
// Inventory slot strings.
// since numbers cannot be used as associative list keys.
@@ -180,13 +179,13 @@
#define GLOVES_MIN_COLD_PROTECTION_TEMPERATURE 2.0 // For some gloves.
#define SHOE_MIN_COLD_PROTECTION_TEMPERATURE 2.0 // For shoes.
-#define SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE 5000 // These need better heat protect, but not as good heat protect as firesuits.
-#define FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE 30000 // What max_heat_protection_temperature is set to for firesuit quality headwear. MUST NOT BE 0.
-#define FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE 30000 // For fire-helmet quality items. (Red and white hardhats)
-#define HELMET_MAX_HEAT_PROTECTION_TEMPERATURE 600 // For normal helmets.
-#define ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE 600 // For armor.
-#define GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE 1500 // For some gloves.
-#define SHOE_MAX_HEAT_PROTECTION_TEMPERATURE 1500 // For shoes.
+#define SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE 5000 // These need better heat protect, but not as good heat protect as firesuits.
+#define FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE 30000 // What max_heat_protection_temperature is set to for firesuit quality headwear. MUST NOT BE 0.
+#define FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE 30000 // For fire-helmet quality items. (Red and white hardhats)
+#define HELMET_MAX_HEAT_PROTECTION_TEMPERATURE 600 // For normal helmets.
+#define ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE 600 // For armor.
+#define GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE 1500 // For some gloves.
+#define SHOE_MAX_HEAT_PROTECTION_TEMPERATURE 1500 // For shoes.
// Fire.
#define FIRE_MIN_STACKS -20
diff --git a/code/__defines/lighting.dm b/code/__defines/lighting.dm
index d4097da3e59..8ee5fbc5fae 100644
--- a/code/__defines/lighting.dm
+++ b/code/__defines/lighting.dm
@@ -1,141 +1,141 @@
-#define LIGHTING_INTERVAL 1 // Frequency, in 1/10ths of a second, of the lighting process.
-
-#define LIGHTING_HEIGHT 1 // height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone
-#define LIGHTING_Z_FACTOR 10 // Z diff is multiplied by this and LIGHTING_HEIGHT to get the final height of a light source. Affects how much darker A Z light gets with each level transitioned.
-#define LIGHTING_ROUND_VALUE 1 / 200 //Value used to round lumcounts, values smaller than 1/255 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_ICON 'icons/effects/lighting_overlay.dmi' // icon used for lighting shading effects
-#define LIGHTING_BASE_ICON_STATE "matrix" // icon_state used for normal color-matrix based lighting overlays.
-#define LIGHTING_STATION_ICON_STATE "tubedefault" // icon_state used for lighting overlays that are just displaying standard station lighting.
-#define LIGHTING_DARKNESS_ICON_STATE "black" // icon_state used for lighting overlays with no luminosity.
-#define LIGHTING_TRANSPARENT_ICON_STATE "blank"
-
-#define LIGHTING_SOFT_THRESHOLD 0.001 // If the max of the lighting lumcounts of each spectrum drops below this, disable luminosity on the lighting overlays.
-#define LIGHTING_BLOCKED_FACTOR 0.5 // How much the range of a directional light will be reduced while facing a wall.
-
-// If defined, instant updates will be used whenever server load permits. Otherwise queued updates are always used.
-#define USE_INTELLIGENT_LIGHTING_UPDATES
-
-// If defined, lighting corners will 'bleed' luminosity to corners above them to simulate cross-Z lighting upwards. Downwards Z-lighting will continue to work with this disabled.
-#define USE_CORNER_ZBLEED
-
-#define TURF_IS_DYNAMICALLY_LIT(T) (isturf(T) && T:dynamic_lighting && T:loc:dynamic_lighting)
-// mostly identical to above, but doesn't make sure T is valid first. Should only be used by lighting code.
-#define TURF_IS_DYNAMICALLY_LIT_UNSAFE(T) (T:dynamic_lighting && T:loc:dynamic_lighting)
-
-// If I were you I'd leave this alone.
-#define LIGHTING_BASE_MATRIX \
- list \
- ( \
- 1, 1, 1, 0, \
- 1, 1, 1, 0, \
- 1, 1, 1, 0, \
- 1, 1, 1, 0, \
- 0, 0, 0, 1 \
- ) \
-
-// Helpers so we can (more easily) control the colour matrices.
-#define CL_MATRIX_RR 1
-#define CL_MATRIX_RG 2
-#define CL_MATRIX_RB 3
-#define CL_MATRIX_RA 4
-#define CL_MATRIX_GR 5
-#define CL_MATRIX_GG 6
-#define CL_MATRIX_GB 7
-#define CL_MATRIX_GA 8
-#define CL_MATRIX_BR 9
-#define CL_MATRIX_BG 10
-#define CL_MATRIX_BB 11
-#define CL_MATRIX_BA 12
-#define CL_MATRIX_AR 13
-#define CL_MATRIX_AG 14
-#define CL_MATRIX_AB 15
-#define CL_MATRIX_AA 16
-#define CL_MATRIX_CR 17
-#define CL_MATRIX_CG 18
-#define CL_MATRIX_CB 19
-#define CL_MATRIX_CA 20
-
-// Higher numbers override lower.
-#define LIGHTING_NO_UPDATE 0
-#define LIGHTING_VIS_UPDATE 1
-#define LIGHTING_CHECK_UPDATE 2
-#define LIGHTING_FORCE_UPDATE 3
-
-// This color of overlay is very common - most of the station is this color when lit fully.
-// Tube lights are a bluish-white, so we can't just assume 1-1-1 is full-illumination.
-#define LIGHTING_DEFAULT_TUBE_R 0.96
-#define LIGHTING_DEFAULT_TUBE_G 1
-#define LIGHTING_DEFAULT_TUBE_B 1
-
-//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_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)
-
-#define LIGHT_COLOR_CYAN "#7DE1E1" //Diluted cyan. rgb(125, 225, 225)
-#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 "#A97FAA" //Soft purple. rgb(169, 127, 170)
-#define LIGHT_COLOR_VIOLET "#B43CB8" //Deep purple. rgb(180, 60, 184)
-#define LIGHT_COLOR_SCARLET "#E85656" //Light red. rgb(232, 86, 86)
-
-//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)
-#define LIGHT_COLOR_EMERGENCY "#FF3232" //Red color used by emergency lighting. rgb(255, 50, 50)
-
-//Defines for lighting status, see power/lighting.dm
-#define LIGHT_OK 0
-#define LIGHT_EMPTY 1
-#define LIGHT_BROKEN 2
-#define LIGHT_BURNED 3
-
-#define LIGHT_EMERGENCY_POWER_USE 0.2 //How much power emergency lights will consume per tick
-
-// Some angle presets for directional lighting.
-#define LIGHT_OMNI null
-#define LIGHT_SEMI 180
-#define LIGHT_WIDE 90
-#define LIGHT_NARROW 45
-
-// Night lighting controller times
-// The time (in hours based on worldtime2hours()) that various actions trigger
-#define MORNING_LIGHT_RESET 7 // 7am or 07:00 - lighting restores to normal in morning
-#define NIGHT_LIGHT_ACTIVE 18 // 6pm or 18:00 - night lighting mode activates
-
-// Some brightness/range defines for objects.
-#define L_WALLMOUNT_POWER 0.4
-#define L_WALLMOUNT_RANGE 2
-#define L_WALLMOUNT_HI_POWER 1 // For red/delta alert on fire alarms.
-#define L_WALLMOUNT_HI_RANGE 4
-// This controls by how much console sprites are dimmed before being overlayed.
-#define HOLOSCREEN_ADDITION_FACTOR 1
-#define HOLOSCREEN_MULTIPLICATION_FACTOR 0.5
-#define HOLOSCREEN_ADDITION_OPACITY 0.8
-#define HOLOSCREEN_MULTIPLICATION_OPACITY 1
-
-// Just so we can avoid unneeded proc calls when profiling is disabled.
-#define L_PROF(O,T) if (lighting_profiling) {lprof_write(O,T);}
-
-// -- Ambient Occlusion --
-
-// Not handled by the lighting engine, but related. Controls the alpha of the ambient occlusion effect on opaque atoms and openturfs.
-#define WALL_AO_ALPHA 80
-
-#define AO_UPDATE_NONE 0
-#define AO_UPDATE_OVERLAY 1
-#define AO_UPDATE_REBUILD 2
-
-// If ao_neighbors equals this, no AO shadows are present.
-#define AO_ALL_NEIGHBORS 1910
-
-// If defined, integrate with the lighting engine and use its opacity value. Otherwise a simple turf opacity check is used. This may cause visual artifacts with opaque non-square movables.
-//#define AO_USE_LIGHTING_OPACITY
+#define LIGHTING_INTERVAL 1 // Frequency, in 1/10ths of a second, of the lighting process.
+
+#define LIGHTING_HEIGHT 1 // height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone
+#define LIGHTING_Z_FACTOR 10 // Z diff is multiplied by this and LIGHTING_HEIGHT to get the final height of a light source. Affects how much darker A Z light gets with each level transitioned.
+#define LIGHTING_ROUND_VALUE 1 / 200 //Value used to round lumcounts, values smaller than 1/255 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_ICON 'icons/effects/lighting_overlay.dmi' // icon used for lighting shading effects
+#define LIGHTING_BASE_ICON_STATE "matrix" // icon_state used for normal color-matrix based lighting overlays.
+#define LIGHTING_STATION_ICON_STATE "tubedefault" // icon_state used for lighting overlays that are just displaying standard station lighting.
+#define LIGHTING_DARKNESS_ICON_STATE "black" // icon_state used for lighting overlays with no luminosity.
+#define LIGHTING_TRANSPARENT_ICON_STATE "blank"
+
+#define LIGHTING_SOFT_THRESHOLD 0.001 // If the max of the lighting lumcounts of each spectrum drops below this, disable luminosity on the lighting overlays.
+#define LIGHTING_BLOCKED_FACTOR 0.5 // How much the range of a directional light will be reduced while facing a wall.
+
+// If defined, instant updates will be used whenever server load permits. Otherwise queued updates are always used.
+#define USE_INTELLIGENT_LIGHTING_UPDATES
+
+// If defined, lighting corners will 'bleed' luminosity to corners above them to simulate cross-Z lighting upwards. Downwards Z-lighting will continue to work with this disabled.
+#define USE_CORNER_ZBLEED
+
+#define TURF_IS_DYNAMICALLY_LIT(T) (isturf(T) && T:dynamic_lighting && T:loc:dynamic_lighting)
+// mostly identical to above, but doesn't make sure T is valid first. Should only be used by lighting code.
+#define TURF_IS_DYNAMICALLY_LIT_UNSAFE(T) (T:dynamic_lighting && T:loc:dynamic_lighting)
+
+// If I were you I'd leave this alone.
+#define LIGHTING_BASE_MATRIX \
+ list \
+ ( \
+ 1, 1, 1, 0, \
+ 1, 1, 1, 0, \
+ 1, 1, 1, 0, \
+ 1, 1, 1, 0, \
+ 0, 0, 0, 1 \
+ ) \
+
+// Helpers so we can (more easily) control the colour matrices.
+#define CL_MATRIX_RR 1
+#define CL_MATRIX_RG 2
+#define CL_MATRIX_RB 3
+#define CL_MATRIX_RA 4
+#define CL_MATRIX_GR 5
+#define CL_MATRIX_GG 6
+#define CL_MATRIX_GB 7
+#define CL_MATRIX_GA 8
+#define CL_MATRIX_BR 9
+#define CL_MATRIX_BG 10
+#define CL_MATRIX_BB 11
+#define CL_MATRIX_BA 12
+#define CL_MATRIX_AR 13
+#define CL_MATRIX_AG 14
+#define CL_MATRIX_AB 15
+#define CL_MATRIX_AA 16
+#define CL_MATRIX_CR 17
+#define CL_MATRIX_CG 18
+#define CL_MATRIX_CB 19
+#define CL_MATRIX_CA 20
+
+// Higher numbers override lower.
+#define LIGHTING_NO_UPDATE 0
+#define LIGHTING_VIS_UPDATE 1
+#define LIGHTING_CHECK_UPDATE 2
+#define LIGHTING_FORCE_UPDATE 3
+
+// This color of overlay is very common - most of the station is this color when lit fully.
+// Tube lights are a bluish-white, so we can't just assume 1-1-1 is full-illumination.
+#define LIGHTING_DEFAULT_TUBE_R 0.96
+#define LIGHTING_DEFAULT_TUBE_G 1
+#define LIGHTING_DEFAULT_TUBE_B 1
+
+//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_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)
+
+#define LIGHT_COLOR_CYAN "#7DE1E1" //Diluted cyan. rgb(125, 225, 225)
+#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 "#A97FAA" //Soft purple. rgb(169, 127, 170)
+#define LIGHT_COLOR_VIOLET "#B43CB8" //Deep purple. rgb(180, 60, 184)
+#define LIGHT_COLOR_SCARLET "#E85656" //Light red. rgb(232, 86, 86)
+
+//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)
+#define LIGHT_COLOR_EMERGENCY "#FF3232" //Red color used by emergency lighting. rgb(255, 50, 50)
+
+//Defines for lighting status, see power/lighting.dm
+#define LIGHT_OK 0
+#define LIGHT_EMPTY 1
+#define LIGHT_BROKEN 2
+#define LIGHT_BURNED 3
+
+#define LIGHT_EMERGENCY_POWER_USE 0.2 //How much power emergency lights will consume per tick
+
+// Some angle presets for directional lighting.
+#define LIGHT_OMNI null
+#define LIGHT_SEMI 180
+#define LIGHT_WIDE 90
+#define LIGHT_NARROW 45
+
+// Night lighting controller times
+// The time (in hours based on worldtime2hours()) that various actions trigger
+#define MORNING_LIGHT_RESET 7 // 7am or 07:00 - lighting restores to normal in morning
+#define NIGHT_LIGHT_ACTIVE 18 // 6pm or 18:00 - night lighting mode activates
+
+// Some brightness/range defines for objects.
+#define L_WALLMOUNT_POWER 0.4
+#define L_WALLMOUNT_RANGE 2
+#define L_WALLMOUNT_HI_POWER 1 // For red/delta alert on fire alarms.
+#define L_WALLMOUNT_HI_RANGE 4
+// This controls by how much console sprites are dimmed before being overlayed.
+#define HOLOSCREEN_ADDITION_FACTOR 1
+#define HOLOSCREEN_MULTIPLICATION_FACTOR 0.5
+#define HOLOSCREEN_ADDITION_OPACITY 0.8
+#define HOLOSCREEN_MULTIPLICATION_OPACITY 1
+
+// Just so we can avoid unneeded proc calls when profiling is disabled.
+#define L_PROF(O,T) if (lighting_profiling) {lprof_write(O,T);}
+
+// -- Ambient Occlusion --
+
+// Not handled by the lighting engine, but related. Controls the alpha of the ambient occlusion effect on opaque atoms and openturfs.
+#define WALL_AO_ALPHA 80
+
+#define AO_UPDATE_NONE 0
+#define AO_UPDATE_OVERLAY 1
+#define AO_UPDATE_REBUILD 2
+
+// If ao_neighbors equals this, no AO shadows are present.
+#define AO_ALL_NEIGHBORS 1910
+
+// If defined, integrate with the lighting engine and use its opacity value. Otherwise a simple turf opacity check is used. This may cause visual artifacts with opaque non-square movables.
+//#define AO_USE_LIGHTING_OPACITY
diff --git a/code/__defines/lists.dm b/code/__defines/lists.dm
index 1b24a50bc19..b77cd7d6e21 100644
--- a/code/__defines/lists.dm
+++ b/code/__defines/lists.dm
@@ -8,9 +8,42 @@
#define LAZYCLEARLIST(L) if(L) L.Cut()
#define LAZYSET(L, K, V) if (!L) { L = list(); } L[K] = V;
#define LAZYPICK(L,DEFAULT) (LAZYLEN(L) ? pick(L) : DEFAULT)
+#define LAZYISIN(L, I) (L ? (I in L) : FALSE)
+#define LAZYDISTINCTADD(L, I) if(!L) { L = list(); } L |= I;
// Shims for some list procs in lists.dm.
-#define islist(L) istype(L,/list)
#define isemptylist(L) (!LAZYLEN(L))
#define safepick(L) LAZYPICK(L,null)
#define listgetindex(L,I) LAZYACCESS(L,I)
+
+#if DM_VERSION < 513
+#define islist(L) istype(L,/list)
+#endif
+
+// binary search sorted insert
+// IN: Object to be inserted
+// LIST: List to insert object into
+// TYPECONT: The typepath of the contents of the list
+// COMPARE: The variable on the objects to compare
+#define BINARY_INSERT(IN, LIST, TYPECONT, COMPARE) \
+ var/__BIN_CTTL = length(LIST);\
+ if(!__BIN_CTTL) {\
+ LIST += IN;\
+ } else {\
+ var/__BIN_LEFT = 1;\
+ var/__BIN_RIGHT = __BIN_CTTL;\
+ var/__BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\
+ var/##TYPECONT/__BIN_ITEM;\
+ while(__BIN_LEFT < __BIN_RIGHT) {\
+ __BIN_ITEM = LIST[__BIN_MID];\
+ if(__BIN_ITEM.##COMPARE <= IN.##COMPARE) {\
+ __BIN_LEFT = __BIN_MID + 1;\
+ } else {\
+ __BIN_RIGHT = __BIN_MID;\
+ };\
+ __BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\
+ };\
+ __BIN_ITEM = LIST[__BIN_MID];\
+ __BIN_MID = __BIN_ITEM.##COMPARE > IN.##COMPARE ? __BIN_MID : __BIN_MID + 1;\
+ LIST.Insert(__BIN_MID, IN);\
+ }
\ No newline at end of file
diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm
index c6005bf7dcd..3ccef65d0ef 100644
--- a/code/__defines/machinery.dm
+++ b/code/__defines/machinery.dm
@@ -28,6 +28,11 @@
#define AI_CAMERA_LUMINOSITY 6
+//Vending machines.
+#define CAT_NORMAL 1
+#define CAT_HIDDEN 2 // also used in corresponding wires/vending.dm
+#define CAT_COIN 4
+
// Camera networks
#define NETWORK_CRESCENT "Crescent"
#define NETWORK_CIVILIAN_EAST "Civilian East"
@@ -40,6 +45,7 @@
#define NETWORK_ENGINEERING_OUTPOST "Engineering Outpost"
#define NETWORK_ERT "ZeEmergencyResponseTeam"
#define NETWORK_STATION "Station"
+#define NETWORK_MECHS "Mechs"
#define NETWORK_MEDICAL "Medical"
#define NETWORK_MERCENARY "MercurialNet"
#define NETWORK_MINE "MINE"
diff --git a/code/__defines/materials.dm b/code/__defines/materials.dm
new file mode 100644
index 00000000000..11cf6d4a390
--- /dev/null
+++ b/code/__defines/materials.dm
@@ -0,0 +1,66 @@
+#define MATERIAL_PLASTIC "plastic"
+#define MATERIAL_PLASTIC_HOLO "holoplastic"
+#define MATERIAL_PLASTEEL "plasteel"
+#define MATERIAL_STEEL "steel"
+#define MATERIAL_GLASS "glass"
+#define MATERIAL_GLASS_REINFORCED "rglass"
+#define MATERIAL_GLASS_WIRED "wired glass"
+#define MATERIAL_GLASS_PHORON "borosilicate glass"
+#define MATERIAL_GLASS_REINFORCED_PHORON "reinforced borosilicate glass"
+#define MATERIAL_GOLD "gold"
+#define MATERIAL_SILVER "silver"
+#define MATERIAL_DIAMOND "diamond"
+#define MATERIAL_PHORON "phoron"
+#define MATERIAL_URANIUM "uranium"
+#define MATERIAL_SANDSTONE "sandstone"
+#define MATERIAL_CONCRETE "concrete"
+#define MATERIAL_IRON "iron"
+#define MATERIAL_PLATINUM "platinum"
+#define MATERIAL_BRONZE "bronze"
+#define MATERIAL_OSMIUM "osmium"
+#define MATERIAL_MARBLE "marble"
+#define MATERIAL_CULT "cult"
+#define MATERIAL_CULT_REINFORCED "cult_reinforced"
+#define MATERIAL_TITANIUM "titanium"
+#define MATERIAL_SAND "sand"
+#define MATERIAL_DIONA "biomass"
+#define MATERIAL_VAURCA "alien biomass"
+#define MATERIAL_TRITIUM "tritium"
+#define MATERIAL_HYDROGEN_METALLIC "mhydrogen"
+#define MATERIAL_ELEVATOR "elevatorium"
+#define MATERIAL_SHUTTLE "shuttle"
+#define MATERIAL_SHUTTLE_SKRELL "skrell"
+#define MATERIAL_RUST "rust"
+#define MATERIAL_CARDBOARD "cardboard"
+
+// Leathers and related.
+#define MATERIAL_RESIN "resin"
+#define MATERIAL_LEATHER "leather"
+#define MATERIAL_BONE "bone"
+#define MATERIAL_BONE_CURSED "cursed bone"
+#define MATERIAL_HIDE "hide"
+#define MATERIAL_HIDE_CORGI "corgi hide"
+#define MATERIAL_HIDE_CAT "cat hide"
+#define MATERIAL_HIDE_MONKEY "monkey hide"
+#define MATERIAL_HIDE_LIZARD "lizard hide"
+#define MATERIAL_HIDE_ALIEN "alien hide"
+#define MATERIAL_HIDE_HUMAN "human hide"
+
+// Wood.
+#define MATERIAL_WOOD "wood"
+#define MATERIAL_WOOD_HOLO "holowood"
+#define MATERIAL_WOOD_LOG "log"
+#define MATERIAL_WOOD_BRANCH "branch"
+
+// Cloth and related.
+#define MATERIAL_CLOTH "cloth"
+#define MATERIAL_COTTON "cotton"
+#define MATERIAL_CARPET "carpet"
+#define MATERIAL_CLOTH_TEAL "teal"
+#define MATERIAL_CLOTH_BLACK "black"
+#define MATERIAL_CLOTH_GREEN "green"
+#define MATERIAL_CLOTH_PURPLE "purple"
+#define MATERIAL_CLOTH_BLUE "blue"
+#define MATERIAL_CLOTH_BEIGE "beige"
+#define MATERIAL_CLOTH_LIME "lime"
+
diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index 44d4a1cb307..2a708ac4ba2 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -1,20 +1,5 @@
#define DEBUG
-//These get to go at the top, because they're special
-//You can use these defines to get the typepath of the currently running proc/verb (yes procs + verbs are objects)
-/* eg:
-/mob/living/carbon/human/death()
- world << THIS_PROC_TYPE_STR //You can only output the string versions
-Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a string with () (eg: the _WITH_ARGS defines) to make it look nicer)
-*/
-#define THIS_PROC_TYPE .....
-#define THIS_PROC_TYPE_STR "[THIS_PROC_TYPE]" //Because you can only obtain a string of THIS_PROC_TYPE using "[]", and it's nice to just +/+= strings
-#define THIS_PROC_TYPE_STR_WITH_ARGS "[THIS_PROC_TYPE]([args.Join(",")])"
-#define THIS_PROC_TYPE_WEIRD ...... //This one is WEIRD, in some cases (When used in certain defines? (eg: ASSERT)) THIS_PROC_TYPE will fail to work, but THIS_PROC_TYPE_WEIRD will work instead
-#define THIS_PROC_TYPE_WEIRD_STR "[THIS_PROC_TYPE_WEIRD]" //Included for completeness
-#define THIS_PROC_TYPE_WEIRD_STR_WITH_ARGS "[THIS_PROC_TYPE_WEIRD]([args.Join(",")])" //Ditto
-
-
// Turf-only flags.
#define NOJAUNT 1 // This is used in literally one place, turf.dm, to block ethereal jaunt.
#define MIMIC_BELOW 2 // If this turf should mimic the turf on the Z below.
@@ -49,7 +34,7 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define AGE_MIN 17
#define AGE_MAX 85
-#define MAX_GEAR_COST 10 // Used in chargen for accessory loadout limit.
+#define MAX_GEAR_COST 15 // Used in chargen for accessory loadout limit.
// Preference toggles.
#define SOUND_ADMINHELP 0x1
@@ -73,8 +58,6 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define PARALLAX_DUST 0x2
#define PROGRESS_BARS 0x4
#define PARALLAX_IS_STATIC 0x8
-//Gun safety check.
-#define SAFETY_CHECK 0x10
#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS|CHAT_LOOC)
@@ -83,11 +66,13 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define ASFX_FOOTSTEPS 2
#define ASFX_VOTE 4
#define ASFX_VOX 8
+#define ASFX_DROPSOUND 16
+#define ASFX_ARCADE 32
-#define ASFX_DEFAULT (ASFX_AMBIENCE|ASFX_FOOTSTEPS|ASFX_VOTE|ASFX_VOX)
+#define ASFX_DEFAULT (ASFX_AMBIENCE|ASFX_FOOTSTEPS|ASFX_VOTE|ASFX_VOX|ASFX_DROPSOUND|ASFX_ARCADE)
// For secHUDs and medHUDs and variants. The number is the location of the image on the list hud_list of humans.
-#define HEALTH_HUD 1 // A simple line rounding the mob's number health.
+#define HEALTH_HUD 1 // A simple line reading the pulse.
#define STATUS_HUD 2 // Alive, dead, diseased, etc.
#define ID_HUD 3 // The job asigned to your ID.
#define WANTED_HUD 4 // Wanted, released, paroled, security status.
@@ -98,46 +83,12 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define STATUS_HUD_OOC 9 // STATUS_HUD without virus DB check for someone being ill.
#define LIFE_HUD 10 // STATUS_HUD that only reports dead or alive
-//some colors
-#define COLOR_WHITE "#ffffff"
-#define COLOR_SILVER "#c0c0c0"
-#define COLOR_GRAY "#808080"
-#define COLOR_BLACK "#000000"
-#define COLOR_RED "#ff0000"
-#define COLOR_RED_LIGHT "#ff3333"
-#define COLOR_MAROON "#800000"
-#define COLOR_YELLOW "#ffff00"
-#define COLOR_OLIVE "#808000"
-#define COLOR_LIME "#00ff00"
-#define COLOR_GREEN "#008000"
-#define COLOR_CYAN "#00ffff"
-#define COLOR_TEAL "#008080"
-#define COLOR_BLUE "#0000ff"
-#define COLOR_BLUE_LIGHT "#33ccff"
-#define COLOR_NAVY "#000080"
-#define COLOR_PINK "#ff00ff"
-#define COLOR_PURPLE "#800080"
-#define COLOR_ORANGE "#ff9900"
-#define COLOR_LUMINOL "#66ffff"
-#define COLOR_BEIGE "#ceb689"
-#define COLOR_BLUE_GRAY "#6a97b0"
-#define COLOR_BROWN "#b19664"
-#define COLOR_DARK_BROWN "#917448"
-#define COLOR_DARK_ORANGE "#b95a00"
-#define COLOR_GREEN_GRAY "#8daf6a"
-#define COLOR_RED_GRAY "#aa5f61"
-#define COLOR_PALE_BLUE_GRAY "#8bbbd5"
-#define COLOR_PALE_GREEN_GRAY "#aed18b"
-#define COLOR_PALE_RED_GRAY "#cc9090"
-#define COLOR_PALE_PURPLE_GRAY "#bda2ba"
-#define COLOR_PURPLE_GRAY "#a2819e"
-#define COLOR_SUN "#ec8b2f"
-
// Shuttles.
// These define the time taken for the shuttle to get to the space station, and the time before it leaves again.
#define SHUTTLE_PREPTIME 300 // 5 minutes = 300 seconds - after this time, the shuttle departs centcom and cannot be recalled.
#define SHUTTLE_LEAVETIME 180 // 3 minutes = 180 seconds - the duration for which the shuttle will wait at the station after arriving.
+#define SHUTTLE_FORCETIME 300 // 5 minutes = 300 seconds - time after which the shuttle is automatically forced
#define SHUTTLE_TRANSIT_DURATION 300 // 5 minutes = 300 seconds - how long it takes for the shuttle to get to the station.
#define SHUTTLE_TRANSIT_DURATION_RETURN 120 // 2 minutes = 120 seconds - for some reason it takes less time to come back, go figure.
@@ -145,6 +96,7 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define SHUTTLE_IDLE 0
#define SHUTTLE_WARMUP 1
#define SHUTTLE_INTRANSIT 2
+#define SHUTTLE_HALT 3 // State of no recovery
// Ferry shuttle processing status.
#define IDLE_STATE 0
@@ -158,7 +110,7 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define MAX_PAPER_MESSAGE_LEN 3072
#define MAX_BOOK_MESSAGE_LEN 9216
#define MAX_LNAME_LEN 64
-#define MAX_NAME_LEN 26
+#define MAX_NAME_LEN 63
// Event defines.
#define EVENT_LEVEL_MUNDANE 1
@@ -191,6 +143,8 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define WALL_CAN_OPEN 1
#define WALL_OPENING 2
+#define MIN_DAMAGE_TO_HIT 15 //Minimum damage needed to dent walls and girders by hitting them with a weapon.
+
#define DEFAULT_TABLE_MATERIAL "plastic"
#define DEFAULT_WALL_MATERIAL "steel"
@@ -220,14 +174,18 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define NTNETSPEED_LOWSIGNAL 0.05 // GQ/s transfer speed when the device is wirelessly connected and on Low signal
#define NTNETSPEED_HIGHSIGNAL 0.25 // GQ/s transfer speed when the device is wirelessly connected and on High signal
#define NTNETSPEED_ETHERNET 1 // GQ/s transfer speed when the device is using wired connection
-#define NTNETSPEED_DOS_AMPLIFICATION 5 // Multiplier for Denial of Service program. Resulting load on NTNet relay is this multiplied by NTNETSPEED of the device
+#define NTNETSPEED_DOS_AMPLIFICATION 20 // Multiplier for Denial of Service program. Resulting load on NTNet relay is this multiplied by NTNETSPEED of the device
// Program bitflags
-#define PROGRAM_ALL 15
#define PROGRAM_CONSOLE 1
#define PROGRAM_LAPTOP 2
#define PROGRAM_TABLET 4
#define PROGRAM_TELESCREEN 8
+#define PROGRAM_SILICON 16
+#define PROGRAM_WRISTBOUND 32
+
+#define PROGRAM_ALL (PROGRAM_CONSOLE | PROGRAM_LAPTOP | PROGRAM_TABLET | PROGRAM_WRISTBOUND | PROGRAM_TELESCREEN | PROGRAM_SILICON)
+#define PROGRAM_ALL_REGULAR (PROGRAM_CONSOLE | PROGRAM_LAPTOP | PROGRAM_TABLET | PROGRAM_WRISTBOUND | PROGRAM_TELESCREEN)
#define PROGRAM_STATE_KILLED 0
#define PROGRAM_STATE_BACKGROUND 1
@@ -297,11 +255,6 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define DEBUG_REF(D) (D ? "\ref[D]|[D] ([D.type])" : "NULL")
-// These defines write to log_debug, prefixing the path to the current proc.
-// When using them, try PROCLOG first. If it does not compile, try PROCLOG_WEIRD.
-#define PROCLOG(thing) log_debug("[THIS_PROC_TYPE]: [thing]")
-#define PROCLOG_WEIRD(thing) log_debug("[THIS_PROC_TYPE_WEIRD]: [thing]")
-
//Recipe type defines. Used to determine what machine makes them
#define MICROWAVE 0x1
#define FRYER 0x2
@@ -325,10 +278,18 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
// Used for creating soft references to objects. A manner of storing an item reference
// as text so you don't necessarily fuck with an object's ability to be garbage collected.
+#if DM_VERSION < 513
+
#define SOFTREF(A) "\ref[A]"
+#else
+
+#define SOFTREF(A) ref(A)
+
+#endif
+
// This only works on 511 because it relies on 511's `var/something = foo = bar` syntax.
-#define WEAKREF(D) (istype(D, /datum) && !D:gcDestroyed ? (D:weakref || (D:weakref = new(D))) : null)
+#define WEAKREF(D) (istype(D, /datum) && !D:gcDestroyed ? (D:weakref || (D:weakref = new/datum/weakref(D))) : null)
#define ADD_VERB_IN(the_atom,time,verb) addtimer(CALLBACK(the_atom, /atom/.proc/add_verb, verb), time, TIMER_UNIQUE | TIMER_OVERRIDE | TIMER_NO_HASH_WAIT)
#define ADD_VERB_IN_IF(the_atom,time,verb,callback) addtimer(CALLBACK(the_atom, /atom/.proc/add_verb, verb, callback), time, TIMER_UNIQUE | TIMER_OVERRIDE | TIMER_NO_HASH_WAIT)
@@ -364,6 +325,15 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define isStationLevel(Z) ((Z) in current_map.station_levels)
#define isNotStationLevel(Z) !isStationLevel(Z)
+#define isPlayerLevel(Z) ((Z) in current_map.player_levels)
+#define isNotPlayerLevel(Z) !isPlayerLevel(Z)
+
+#define isAdminLevel(Z) ((Z) in current_map.admin_levels)
+#define isNotAdminLevel(Z) !isAdminLevel(Z)
+
+#define isContactLevel(Z) ((Z) in current_map.contact_levels)
+#define isNotContactLevel(Z) !isContactLevel(Z)
+
//Affects the chance that armour will block an attack. Should be between 0 and 1.
//If set to 0, then armor will always prevent the same amount of damage, always, with no randomness whatsoever.
//Of course, this will affect code that checks for blocked < 100, as blocked will be less likely to actually be 100.
@@ -459,3 +429,6 @@ Define for getting a bitfield of adjacent turfs that meet a condition.
#define GET_BELOW(A) (HAS_BELOW(A:z) ? get_step(A, DOWN) : null)
#define NULL_OR_EQUAL(self,other) (!(self) || (self) == (other))
+
+//Lying animation
+#define ANIM_LYING_TIME 2
diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index 6f6acc0c3aa..0f10a926b85 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -14,6 +14,7 @@
#define FAKEDEATH 0x2000 // Replaces stuff like changeling.changeling_fakedeath.
#define DISFIGURED 0x4000 // Set but never checked. Remove this sometime and replace occurences with the appropriate organ code
#define XENO_HOST 0x8000 // Tracks whether we're gonna be a baby alien's mummy.
+#define NO_ANTAG 0x10000 // Players are restricted from gaining antag roles when occupying this mob
// Grab levels.
#define GRAB_PASSIVE 1
@@ -45,6 +46,28 @@
#define PULSE_THREADY 5 // Occurs during hypovolemic shock
#define GETPULSE_HAND 0 // Less accurate. (hand)
#define GETPULSE_TOOL 1 // More accurate. (med scanner, sleeper, etc.)
+#define PULSE_MAX_BPM 250 // Highest, readable BPM by machines and humans.
+
+// Blood pressure levels, simplified
+#define BP_HIGH_SYSTOLIC 140
+#define BP_PRE_HIGH_SYSTOLIC 125
+#define BP_IDEAL_SYSTOLIC 80
+
+#define BP_HIGH_DIASTOLIC 100
+#define BP_PRE_HIGH_DIASTOLIC 85
+#define BP_IDEAL_DIASTOLIC 60
+
+#define BLOOD_PRESSURE_HIGH 4
+#define BLOOD_PRESSURE_PRE_HIGH 3
+#define BLOOD_PRESSURE_IDEAL 2
+#define BLOOD_PRESSURE_LOW 1
+
+// total_radiation levels (Note that total_radiation can be above RADS_MAX until handle_mutations_and_radiation() runs)
+#define RADS_NONE 0
+#define RADS_LOW 1
+#define RADS_MED 50
+#define RADS_HIGH 75
+#define RADS_MAX 100
//intent flags, why wasn't this done the first time?
#define I_HELP "help"
@@ -52,6 +75,62 @@
#define I_GRAB "grab"
#define I_HURT "harm"
+// Limbs and robotic stuff.
+#define BP_L_FOOT "l_foot"
+#define BP_R_FOOT "r_foot"
+#define BP_L_LEG "l_leg"
+#define BP_R_LEG "r_leg"
+#define BP_L_HAND "l_hand"
+#define BP_R_HAND "r_hand"
+#define BP_L_ARM "l_arm"
+#define BP_R_ARM "r_arm"
+#define BP_HEAD "head"
+#define BP_CHEST "chest"
+#define BP_GROIN "groin"
+#define BP_ALL_LIMBS list(BP_CHEST, BP_GROIN, BP_HEAD, BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND, BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT)
+#define BP_IS_ROBOTIC(org) (org.status & ORGAN_ROBOT)
+
+//Generic organs
+#define BP_MOUTH "mouth"
+#define BP_EYES "eyes"
+#define BP_HEART "heart"
+#define BP_LUNGS "lungs"
+#define BP_BRAIN "brain"
+#define BP_LIVER "liver"
+#define BP_KIDNEYS "kidneys"
+#define BP_STOMACH "stomach"
+#define BP_APPENDIX "appendix"
+
+//Aut'akh organs
+#define BP_ANCHOR "anchor"
+#define BP_HAEMO "haemodynamic"
+#define BP_ADRENAL "adrenal"
+
+//IPC organs
+#define BP_CELL "cell"
+#define BP_OPTICS "optics"
+#define BP_IPCTAG "ipc tag"
+
+//Augment organs
+#define BP_AUG_TIMEPIECE "integrated timepiece"
+#define BP_AUG_PDA "integrated pda"
+#define BP_AUG_TOOL "retractable combitool"
+#define BP_AUG_PEN "retractable combipen"
+#define BP_AUG_LIGHTER "retractable lighter"
+#define BP_AUG_HEALTHSCAN "integrated health scanner"
+#define BP_AUG_TESLA "tesla spine"
+#define BP_AUG_EYE_SENSORS "integrated eyes sensors"
+#define BP_AUG_HAIR "synthetic hair extensions"
+#define BP_AUG_SUSPENSION "calf suspension"
+#define BP_AUG_TASTE_BOOSTER "taste booster"
+#define BP_AUG_RADIO "integrated radio"
+#define BP_AUG_FUEL_CELL "integrated fuel cell"
+#define BP_AUG_AIR_ANALYZER "integrated air analyzer"
+
+//Organ defines
+#define PROCESS_ACCURACY 10
+#define DEFAULT_BLOOD_AMOUNT 560 //Default blood amount in units
+
//These are used Bump() code for living mobs, in the mob_bump_flag, mob_swap_flags, and mob_push_flags vars to determine whom can bump/swap with whom.
#define HUMAN 1
#define MONKEY 2
@@ -129,8 +208,8 @@
#define BASE_MAX_HYDRATION 800
#define THIRST_FACTOR 0.02 // Factor of how fast mob hydration decreases over time.
-#define CREW_MINIMUM_HYDRATION CREW_HYDRATION_SLIGHTLYTHIRSTY // The minimum amount of nutrition a crewmember will spawn with, represented as a percentage
-#define CREW_MAXIMUM_HYDRATION CREW_HYDRATION_HYDRATED // Same as above, but maximum.
+#define CREW_MINIMUM_HYDRATION CREW_HYDRATION_HYDRATED // The minimum amount of nutrition a crewmember will spawn with, represented as a percentage
+#define CREW_MAXIMUM_HYDRATION CREW_HYDRATION_OVERHYDRATED // Same as above, but maximum.
#define CREW_MINIMUM_NUTRITION CREW_NUTRITION_FULL // The minimum amount of nutrition a crewmember will spawn with, represented as a percentage.
#define CREW_MAXIMUM_NUTRITION CREW_NUTRITION_OVEREATEN // Same as above, but maximum.
@@ -164,6 +243,22 @@
#define ANIMAL_SPAWN_DELAY round(config.respawn_delay / 6)
#define DRONE_SPAWN_DELAY round(config.respawn_delay / 3)
+// Gluttony levels.
+#define GLUT_TINY 1 // Eat anything tiny and smaller
+#define GLUT_SMALLER 2 // Eat anything smaller than we are
+#define GLUT_ANYTHING 4 // Eat anything, ever
+#define GLUT_MESSY 8 // Only eat mobs, and eat them in chunks.
+
+#define GLUT_ITEM_TINY 16 // Eat items with a w_class of small or smaller
+#define GLUT_ITEM_NORMAL 32 // Eat items with a w_class of normal or smaller
+#define GLUT_ITEM_ANYTHING 64 // Eat any item
+#define GLUT_PROJECTILE_VOMIT 128 // When vomitting, does it fly out?
+
+
+// Devour speeds, returned by can_devour()
+#define DEVOUR_SLOW 1
+#define DEVOUR_FAST 2
+
// Incapacitation flags, used by the mob/proc/incapacitated() proc
#define INCAPACITATION_NONE 0
#define INCAPACITATION_RESTRAINED 1
@@ -186,7 +281,7 @@
//Time of Death constants
//Used with a list in preference datums to track times of death
#define CREW "crew" //Used for crewmembers, AI, cyborgs, nymphs, antags
-#define ANIMAL "animal" //Used for mice and any other simple animals
+#define ANIMAL "animal" //Used for rats and any other simple animals
#define MINISYNTH "minisynth"//Used for drones and pAIs
#define RESPAWN_ANIMAL 3000
@@ -225,6 +320,7 @@
#define PROSTHETIC_XMG "Xion Manufacturing Group"
#define PROSTHETIC_DIONA "Unknown Model"
#define PROSTHETIC_AUTAKH "Aut'akh Manufactured"
+#define PROSTHETIC_TESLA "Tesla Powered Prosthetics"
//Brain Damage defines
#define BRAIN_DAMAGE_MILD 10
@@ -239,3 +335,8 @@
#define CURE_HYPNOSIS "hypnosis"
#define CURE_SURGERY "surgery"
#define CURE_ADMIN "all"
+
+// Surgery Stuff
+#define SURGERY_SUCCESS 2 // Proceed with surgery
+#define SURGERY_FAIL 1 // Autofail surgery
+#define SURGERY_IGNORE 0 // Ignore surgery completely and just attack
\ No newline at end of file
diff --git a/code/__defines/obj.dm b/code/__defines/obj.dm
new file mode 100644
index 00000000000..1eeb63e214b
--- /dev/null
+++ b/code/__defines/obj.dm
@@ -0,0 +1,2 @@
+#define OBJ_FLAG_ROTATABLE (1<<1) //Can this object be rotated?
+#define OBJ_FLAG_ROTATABLE_ANCHORED (1<<2) // This object can be rotated even while anchored
\ No newline at end of file
diff --git a/code/__defines/psi.dm b/code/__defines/psi.dm
new file mode 100644
index 00000000000..70b14bf049a
--- /dev/null
+++ b/code/__defines/psi.dm
@@ -0,0 +1,11 @@
+#define PSI_COERCION "coercion"
+#define PSI_PSYCHOKINESIS "psychokinesis"
+#define PSI_REDACTION "redaction"
+#define PSI_ENERGISTICS "energistics"
+
+#define PSI_RANK_BLUNT 0
+#define PSI_RANK_LATENT 1
+#define PSI_RANK_OPERANT 2
+#define PSI_RANK_MASTER 3
+#define PSI_RANK_GRANDMASTER 4
+#define PSI_RANK_PARAMOUNT 5
\ No newline at end of file
diff --git a/code/__defines/qdel.dm b/code/__defines/qdel.dm
index b7cf56b65b0..ac86f23ef8a 100644
--- a/code/__defines/qdel.dm
+++ b/code/__defines/qdel.dm
@@ -20,3 +20,4 @@
#define QDEL_IN(item, time) addtimer(CALLBACK(GLOBAL_PROC, .proc/qdel, item), time, TIMER_STOPPABLE)
#define QDEL_NULL(item) qdel(item); item = null
+#define QDEL_NULL_LIST(x) if(x) { for(var/y in x) { qdel(y) }}; if(x) {x.Cut(); x = null } // Second x check to handle items that LAZYREMOVE on qdel.
diff --git a/code/__defines/radio.dm b/code/__defines/radio.dm
index 9224603bbc7..d634b6b23b1 100644
--- a/code/__defines/radio.dm
+++ b/code/__defines/radio.dm
@@ -9,6 +9,7 @@
#define AI_FREQ 1343
#define DTH_FREQ 1341
#define SYND_FREQ 1213
+#define NINJ_FREQ 1255
#define RAID_FREQ 1277
#define ENT_FREQ 1461 //entertainment frequency. This is not a diona exclusive frequency.
@@ -35,6 +36,7 @@ var/list/radiochannels = list(
"Response Team" = ERT_FREQ,
"Special Ops" = DTH_FREQ,
"Mercenary" = SYND_FREQ,
+ "Ninja" = NINJ_FREQ,
"Raider" = RAID_FREQ,
"Supply" = SUP_FREQ,
"Service" = SRV_FREQ,
@@ -60,12 +62,14 @@ var/list/CENT_FREQS_ASSOC = list(
// Antag channels, i.e. Syndicate
var/list/ANTAG_FREQS = list(
SYND_FREQ,
- RAID_FREQ
+ RAID_FREQ,
+ NINJ_FREQ
)
var/list/ANTAG_FREQS_ASSOC = list(
"[SYND_FREQ]" = TRUE,
- "[RAID_FREQ]" = TRUE
+ "[RAID_FREQ]" = TRUE,
+ "[NINJ_FREQ]" = TRUE
)
//Department channels, arranged lexically
diff --git a/code/__defines/rust_g.dm b/code/__defines/rust_g.dm
index a4998ef4630..7da00e019a0 100644
--- a/code/__defines/rust_g.dm
+++ b/code/__defines/rust_g.dm
@@ -1,3 +1,20 @@
// rust_g.dm - DM API for rust_g extension library
-#define RUST_G "rust_g"
-#define WRITE_LOG(log, text) call(RUST_G, "log_write")(log, text) // Using Rust g dll to log faster with less CPU usage.
\ No newline at end of file
+#define RUST_G "rust_g"
+#define WRITE_LOG(log, text) call(RUST_G, "log_write")(log, text) // Using Rust g dll to log faster with less CPU usage.
+
+#define RUSTG_JOB_NO_RESULTS_YET "NO RESULTS YET"
+#define RUSTG_JOB_NO_SUCH_JOB "NO SUCH JOB"
+#define RUSTG_JOB_ERROR "JOB PANICKED"
+
+#define rustg_udp_shipper_send(addr, text) call(RUST_G, "udp_shipper_send")(addr, text)
+
+#define RUSTG_HTTP_METHOD_GET "get"
+#define RUSTG_HTTP_METHOD_POST "post"
+#define RUSTG_HTTP_METHOD_PUT "put"
+#define RUSTG_HTTP_METHOD_DELETE "delete"
+#define RUSTG_HTTP_METHOD_PATCH "patch"
+#define RUSTG_HTTP_METHOD_HEAD "head"
+
+#define rustg_http_request_blocking(method, url, body, headers) call(RUST_G, "http_request_blocking")(method, url, body, headers)
+#define rustg_http_request_async(method, url, body, headers) call(RUST_G, "http_request_async")(method, url, body, headers)
+#define rustg_http_check_request(req_id) call(RUST_G, "http_check_request")(req_id)
diff --git a/code/__defines/shuttle.dm b/code/__defines/shuttle.dm
new file mode 100644
index 00000000000..a27b4e21d81
--- /dev/null
+++ b/code/__defines/shuttle.dm
@@ -0,0 +1,10 @@
+//Shuttles.
+#define SHUTTLE_FLAGS_NONE 0
+#define SHUTTLE_FLAGS_PROCESS 1
+#define SHUTTLE_FLAGS_SUPPLY 2
+#define SHUTTLE_FLAGS_ZERO_G 4
+#define SHUTTLE_FLAGS_ALL (~SHUTTLE_FLAGS_NONE)
+
+//Landmarks.
+#define SLANDMARK_FLAG_AUTOSET 1 // If set, will set base area and turf type to same as where it was spawned at
+#define SLANDMARK_FLAG_ZERO_G 2 // Zero-G shuttles moved here will lose gravity unless the area has ambient gravity.
diff --git a/code/__defines/spaceman_dmm.dm b/code/__defines/spaceman_dmm.dm
new file mode 100644
index 00000000000..e590a30ff99
--- /dev/null
+++ b/code/__defines/spaceman_dmm.dm
@@ -0,0 +1,13 @@
+// Interfaces for the SpacemanDMM linter, define'd to nothing when the linter
+// is not in use.
+
+// The SPACEMAN_DMM define is set by the linter and other tooling when it runs.
+#ifdef SPACEMAN_DMM
+ #define RETURN_TYPE(X) set SpacemanDMM_return_type = X
+ #define SHOULD_CALL_PARENT(X) set SpacemanDMM_should_call_parent = X
+ #define UNLINT(X) SpacemanDMM_unlint(X)
+#else
+ #define RETURN_TYPE(X)
+ #define SHOULD_CALL_PARENT(X)
+ #define UNLINT(X) X
+#endif
diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm
index ca5dcfa981e..d7e2728c825 100644
--- a/code/__defines/species_languages.dm
+++ b/code/__defines/species_languages.dm
@@ -10,6 +10,7 @@
#define IS_MECHANICAL 256 // Is a robot.
#define ACCEPTS_COOLER 512 // Can wear suit coolers and have them work without a suit.
#define NO_CHUBBY 1024 // Cannot be visibly fat from nutrition type.
+#define NO_ARTERIES 2048 // This species does not have arteries.
// unused: 0x8000(32768) - higher than this will overflow
// Base flags for IPCs.
@@ -19,6 +20,7 @@
#define IS_WHITELISTED 0x1 // Must be whitelisted to play.
#define CAN_JOIN 0x2 // Species is selectable in chargen.
#define IS_RESTRICTED 0x4 // Is not a core/normally playable species. (castes, mutantraces)
+#define NO_AGE_MINIMUM 0x8 // Doesn't respect minimum job age requirements.
// Species appearance flags
#define HAS_SKIN_TONE 0x1 // Skin tone selectable in chargen. (0-255)
@@ -29,6 +31,7 @@
#define HAS_HAIR_COLOR 0x20 // Hair colour selectable in chargen. (RGB)
#define HAS_SOCKS 0x40 // If this species can wear socks
#define HAS_FBP 0x80 // If for whatever ungodly reason we decide to ever have non-Shell FBPs.
+#define HAS_SKIN_PRESET 0x100 // Skin color presets selectable in character generation.
// Tau-Ceti basic, language common to all crew.
#define LANGUAGE_TCB "Ceti Basic"
@@ -41,9 +44,7 @@
#define LANGUAGE_SIGN_TAJARA "Nal'rasan"
#define LANGUAGE_YA_SSA "Ya'ssa"
#define LANGUAGE_DELVAHII "Delvahhi"
-#define LANGUAGE_SIIK_TAU "Siik'Tau"
#define LANGUAGE_SKRELLIAN "Nral'Malic"
-#define LANGUAGE_RESOMI "Resomi"
#define LANGUAGE_ROOTSONG "Rootsong"
#define LANGUAGE_TRADEBAND "Tradeband"
#define LANGUAGE_GUTTER "Freespeak"
@@ -52,11 +53,10 @@
#define LANGUAGE_SIGN "Sign Language"
// Antag Languages
-#define LANGUAGE_XENOMORPH "Xenomorph"
-#define LANGUAGE_HIVEMIND "Hivemind" // xeno hivemind
#define LANGUAGE_VOX "Vox-pidgin"
#define LANGUAGE_CHANGELING "Changeling"
#define LANGUAGE_BORER "Cortical Link"
+#define LANGUAGE_BORER_HIVEMIND "Cortical Hivemind"
#define LANGUAGE_CULT "Cult" // NOT CULTISTS!
#define LANGUAGE_OCCULT "Occult"
#define LANGUAGE_TERMINATOR "Hephaestus Darkcomms" // HKs.
@@ -84,4 +84,9 @@
#define INNATE 64 // All mobs can be assumed to speak and understand this language. (audible emotes)
#define NO_TALK_MSG 128 // Do not show the "\The [speaker] talks into \the [radio]" message
#define NO_STUTTER 256 // No stuttering, slurring, or other speech problems
-#define TCOMSSIM 512 // Can be synthesized in tcoms
\ No newline at end of file
+#define TCOMSSIM 512 // Can be synthesized in tcoms
+
+// Representative missions levels
+#define REPRESENTATIVE_MISSION_LOW 1
+#define REPRESENTATIVE_MISSION_MEDIUM 2
+#define REPRESENTATIVE_MISSION_HIGH 3
\ No newline at end of file
diff --git a/code/__defines/subsystem-defines.dm b/code/__defines/subsystem-defines.dm
index ca06062076b..cdfd591d40f 100644
--- a/code/__defines/subsystem-defines.dm
+++ b/code/__defines/subsystem-defines.dm
@@ -5,22 +5,26 @@
// -- SStimer stuff --
//Don't run if there is an identical unique timer active
-#define TIMER_UNIQUE 0x1
+#define TIMER_UNIQUE (1<<0)
//For unique timers: Replace the old timer rather then not start this one
-#define TIMER_OVERRIDE 0x2
+#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()
-#define TIMER_CLIENT_TIME 0x4
+#define TIMER_CLIENT_TIME (1<<2)
//Timer can be stopped using deltimer()
-#define TIMER_STOPPABLE 0x8
+#define TIMER_STOPPABLE (1<<3)
//To be used with TIMER_UNIQUE
//prevents distinguishing identical timers with the wait variable
-#define TIMER_NO_HASH_WAIT 0x10
+#define TIMER_NO_HASH_WAIT (1<<4)
+
+//Loops the timer repeatedly until qdeleted
+//In most cases you want a subsystem instead
+#define TIMER_LOOP (1<<5)
//number of byond ticks that are allowed to pass before the timer subsystem thinks it hung on something
#define TIMER_NO_INVOKE_WARNING 600
@@ -98,3 +102,12 @@
// -- SSmob_ai --
#define MOB_START_THINKING(mob) if (!mob.thinking_enabled) { SSmob_ai.processing += mob; mob.on_think_enabled(); mob.thinking_enabled = TRUE; }
#define MOB_STOP_THINKING(mob) SSmob_ai.processing -= mob; mob.on_think_disabled(); mob.thinking_enabled = FALSE;
+
+
+// - SSrecords --
+#define RECORD_GENERAL 1
+#define RECORD_MEDICAL 2
+#define RECORD_SECURITY 4
+#define RECORD_LOCKED 8
+#define RECORD_WARRANT 16
+#define RECORD_VIRUS 32
\ No newline at end of file
diff --git a/code/__defines/subsystem-priority.dm b/code/__defines/subsystem-priority.dm
index 7f3d2bb1b34..f64c42f1b81 100644
--- a/code/__defines/subsystem-priority.dm
+++ b/code/__defines/subsystem-priority.dm
@@ -4,7 +4,6 @@
#define SS_INIT_MAPLOAD 21 // DMM parsing and load. Unless you know what you're doing, make sure this remains first.
#define SS_INIT_JOBS 20
#define SS_INIT_MAPFINALIZE 19 // Asteroid generation.
-#define SS_INIT_SHUTTLE 18 // Shuttle setup.
#define SS_INIT_PARALLAX 17 // Parallax image cache generation. Must run before ghosts are able to join.
#define SS_INIT_HOLOMAP 16
#define SS_INIT_ATOMS 15 // World initialization. Will trigger lighting updates. Observers can join after this loads.
@@ -65,6 +64,7 @@
// SS_BACKGROUND
#define SS_PRIORITY_PROCESSING 50 // Generic datum processor. Replaces objects processor.
//#define SS_PRIORITY_DEFAULT 50 // This is defined somewhere else.
+#define SS_PRIORITY_PSYCHICS 30
#define SS_PRIORITY_ARRIVALS 30 // Centcomm arrivals shuttle auto-launch. Usually asleep.
#define SS_PRIORITY_EXPLOSIVES 20 // Explosion processor. Doesn't have much effect on explosion tick-checking.
#define SS_PRIORITY_DISPOSALS 20 // Disposal holder movement.
diff --git a/code/__defines/time.dm b/code/__defines/time.dm
index 5ec3ac984a6..73eb12b0f91 100644
--- a/code/__defines/time.dm
+++ b/code/__defines/time.dm
@@ -13,6 +13,6 @@
#define TICKS *world.tick_lag
-#define DS2TICKS(DS) (DS/world.tick_lag)
+#define DS2TICKS(DS) ((DS)/world.tick_lag)
-#define TICKS2DS(T) (T TICKS)
+#define TICKS2DS(T) ((T) TICKS)
diff --git a/code/__defines/vueui.dm b/code/__defines/vueui.dm
index 1fd83d02401..0c43f5b667d 100644
--- a/code/__defines/vueui.dm
+++ b/code/__defines/vueui.dm
@@ -1,10 +1,14 @@
#define VUEUI_SET_CHECK(a, b, c, d) if (a != b) { a = b; c = d; }
#define VUEUI_SET_CHECK_IFNOTSET(a, b, c, d) if (a == null && a != b) { a = b; c = d; }
+#define VUEUI_SET_IFNOTSET(a, b, c, d) if (a == null) { a = b; c = d; }
+#define VUEUI_SET_CHECK_LIST(a, b, c, d) if (!same_entries(a,b)) { a = b; c = d; } // Do not use for lists that contain lists
#define THEME_TYPE_DARK 1
#define THEME_TYPE_LIGHT 0
+#define FALLBACK_HTML_THEME "theme-nano dark-theme"
+
#define VUEUI_MONITOR_VARS(type, monitor_name) \
/datum/vueui_var_monitor/##monitor_name { subject_type = type; }; \
\
diff --git a/code/_helpers/_global_objects.dm b/code/_helpers/_global_objects.dm
new file mode 100644
index 00000000000..4a77edce5fb
--- /dev/null
+++ b/code/_helpers/_global_objects.dm
@@ -0,0 +1,3 @@
+//Gear tweaks and underwear.
+var/datum/gear_tweak/color/gear_tweak_free_color_choice = new()
+var/datum/category_collection/underwear/global_underwear = new()
diff --git a/code/_helpers/area_movement.dm b/code/_helpers/area_movement.dm
index 7070d30db8f..a2aa26d502d 100644
--- a/code/_helpers/area_movement.dm
+++ b/code/_helpers/area_movement.dm
@@ -45,28 +45,27 @@
// Turf matches, add it.
. += T
-// Moves the contents of this area to A. If turf_to_leave is defined, that type will be excluded from the area.
-/area/proc/move_contents_to(area/A, turf_to_leave = null)
- var/list/source_turfs = src.build_ordered_turf_list(turf_to_leave)
- var/list/target_turfs = A.build_ordered_turf_list()
+/area/proc/move_contents_to(var/area/A)
+ //Takes: Area.
+ //Returns: Nothing.
+ //Notes: Attempts to move the contents of one area to another area.
+ // Movement based on lower left corner.
- ASSERT(source_turfs.len == target_turfs.len)
+ if(!A || !src) return
- for (var/i = 1 to source_turfs.len)
- var/turf/ST = source_turfs[i]
- if (!ST) // Excluded turfs are null to keep the list ordered.
- continue
+ var/list/turfs_src = get_area_turfs("\ref[src]")
- var/turf/TT = ST.copy_turf(target_turfs[i])
+ if(!turfs_src.len)
+ return
- for (var/thing in ST)
- var/atom/movable/AM = thing
- AM.shuttle_move(TT)
+ //figure out a suitable origin - this assumes the shuttle areas are the exact same size and shape
+ //might be worth doing this with a shuttle core object instead of areas, in the future
+ var/src_origin = locate(src.x, src.y, src.z)
+ var/trg_origin = locate(A.x, A.y, A.z)
- ST.ChangeTurf(ST.baseturf)
-
- TT.update_icon()
- TT.update_above()
+ if(src_origin && trg_origin)
+ var/translation = get_turf_translation(src_origin, trg_origin, turfs_src)
+ translate_turfs(translation, null)
// Called when a movable area wants to move this object.
/atom/movable/proc/shuttle_move(turf/loc)
@@ -101,7 +100,13 @@
if (!ST || (plating_required && TTi.type == baseturf)) // Excluded turfs are null to keep the list ordered.
continue
- var/turf/TT = ST.copy_turf(TTi, ignore_air = TRUE)
+
+ var/turf/TT
+ if(istype(ST, /turf/simulated))
+ var/turf/simulated/ST_sim = ST
+ TT = ST_sim.copy_turf(TTi, ignore_air = TRUE)
+ else
+ TT = ST.copy_turf(TTi)
for (var/thing in ST)
var/atom/movable/AM = thing
diff --git a/code/_helpers/areas.dm b/code/_helpers/areas.dm
index cbaefbda25e..fb6a515d7fa 100644
--- a/code/_helpers/areas.dm
+++ b/code/_helpers/areas.dm
@@ -1,53 +1,108 @@
-//Takes: Area type as text string or as typepath OR an instance of the area.
-//Returns: A list of all turfs in areas of that type of that type in the world.
-/proc/get_area_turfs(areatype, var/list/predicates, target_z = 0, subtypes=TRUE)
- if(istext(areatype))
- areatype = text2path(areatype)
- else if(isarea(areatype))
- var/area/areatemp = areatype
- areatype = areatemp.type
- else if(!ispath(areatype))
- return null
-
- var/list/turfs = list()
- if(subtypes)
- var/list/cache = typecacheof(areatype)
- for(var/V in all_areas)
- var/area/A = V
- if(!cache[A.type])
- continue
- for(var/turf/T in A)
- if(target_z == 0 || target_z == T.z)
- if (predicates && predicates.len)
- var/predicates_true = TRUE
- for (var/predicate in predicates)
- if (!call(predicate)(T))
- predicates_true = FALSE
- break
- if (predicates_true)
- turfs += T
- else
- turfs += T
- else
- for(var/V in all_areas)
- var/area/A = V
- if(A.type != areatype)
- continue
- for(var/turf/T in A)
- if (target_z == 0 || target_z == T.z)
- if (predicates && predicates.len)
- var/predicates_true = TRUE
- for (var/predicate in predicates)
- if (!call(predicate)(T))
- predicates_true = FALSE
- break
- if (predicates_true)
- turfs += T
- else
- turfs += T
- return turfs
+/*
+ List generation helpers
+*/
+/proc/get_filtered_areas(var/list/predicates = list(/proc/is_area_with_turf))
+ . = list()
+ if(!predicates)
+ return
+ if(!islist(predicates))
+ predicates = list(predicates)
+ for(var/area/A)
+ if(all_predicates_true(list(A), predicates))
+ . += A
+
+/proc/get_area_turfs(var/area/A, var/list/predicates)
+ . = new/list()
+ A = istype(A) ? A : locate(A)
+ if(!A)
+ return
+ for(var/turf/T in A.contents)
+ if(!predicates || all_predicates_true(list(T), predicates))
+ . += T
+
+/proc/get_subarea_turfs(var/area/A, var/list/predicates)
+ . = new/list()
+ A = istype(A) ? A.type : A
+ if(!ispath(A))
+ return
+ for(var/sub_area_type in typesof(A))
+ var/area/sub_area = locate(sub_area_type)
+ for(var/turf/T in sub_area.contents)
+ if(!predicates || all_predicates_true(list(T), predicates))
+ . += T
+
+/proc/group_areas_by_name(var/list/predicates)
+ . = list()
+ for(var/area/A in get_filtered_areas(predicates))
+ group_by(., A.name, A)
+
+/proc/group_areas_by_z_level(var/list/predicates)
+ . = list()
+ var/enough_digits_to_contain_all_zlevels = 3
+ for(var/area/A in get_filtered_areas(predicates))
+ group_by(., add_zero(num2text(A.z), enough_digits_to_contain_all_zlevels), A)
+
+/*
+ Pick helpers
+*/
+/proc/pick_subarea_turf(var/areatype, var/list/predicates)
+ var/list/turfs = get_subarea_turfs(areatype, predicates)
+ if(LAZYLEN(turfs))
+ return pick(turfs)
+
+/proc/pick_area(var/list/predicates)
+ var/list/areas = get_filtered_areas(predicates)
+ if(LAZYLEN(areas))
+ . = pick(areas)
+
+/proc/pick_area_and_turf(var/list/area_predicates, var/list/turf_predicates)
+ var/list/areas = get_filtered_areas(area_predicates)
+ // We loop over all area candidates, until we finally get a valid turf or run out of areas
+ while(!. && length(areas))
+ var/area/A = pick_n_take(areas)
+ . = pick_area_turf(A, turf_predicates)
+
+/proc/pick_area_turf_in_connected_z_levels(var/list/area_predicates, var/list/turf_predicates, var/z_level)
+ area_predicates = area_predicates.Copy()
+
+ var/z_levels = GetConnectedZlevels(z_level)
+ area_predicates[/proc/area_belongs_to_zlevels] = z_levels
+ return pick_area_and_turf(area_predicates, turf_predicates)
/proc/pick_area_turf(var/areatype, var/list/predicates)
var/list/turfs = get_area_turfs(areatype, predicates)
if(turfs && turfs.len)
return pick(turfs)
+
+/*
+ Predicate Helpers
+*/
+/proc/area_belongs_to_zlevels(var/area/A, var/list/z_levels)
+ . = (A.z in z_levels)
+
+/proc/is_station_area(var/area/A)
+ . = isStationLevel(A.z)
+
+/proc/is_contact_area(var/area/A)
+ . = isContactLevel(A.z)
+
+/proc/is_player_area(var/area/A)
+ . = isPlayerLevel(A.z)
+
+/proc/is_not_space_area(var/area/A)
+ . = !istype(A,/area/space)
+
+/proc/is_not_shuttle_area(var/area/A)
+ . = !istype(A,/area/shuttle)
+
+/proc/is_area_with_turf(var/area/A)
+ . = isnum(A.x)
+
+/proc/is_area_without_turf(var/area/A)
+ . = !is_area_with_turf(A)
+
+/proc/is_maint_area(var/area/A)
+ . = istype(A,/area/maintenance)
+
+/proc/is_not_maint_area(var/area/A)
+ . = !is_maint_area(A)
\ No newline at end of file
diff --git a/code/_helpers/atmospherics.dm b/code/_helpers/atmospherics.dm
index 2b46052f5e7..9c4302cdbd2 100644
--- a/code/_helpers/atmospherics.dm
+++ b/code/_helpers/atmospherics.dm
@@ -1,47 +1,47 @@
-/obj/proc/analyze_gases(var/obj/A, var/mob/user)
- if(src != A)
- user.visible_message("\The [user] has used \an [src] on \the [A]")
-
- A.add_fingerprint(user)
- var/list/result = A.atmosanalyze(user)
- if(result && result.len)
- to_chat(user, "Results of the analysis[src == A ? "" : " of \the [A]"]")
- for(var/line in result)
- to_chat(user, "[line]")
- return 1
-
- to_chat(user, "Your [src] flashes a red light as it fails to analyze \the [A].")
- return 0
-
-/proc/atmosanalyzer_scan(var/obj/target, var/datum/gas_mixture/mixture, var/mob/user)
- var/pressure = mixture.return_pressure()
- var/total_moles = mixture.total_moles
-
- var/list/results = list()
- if (total_moles>0)
- results += "Pressure: [round(pressure,0.1)] kPa"
- for(var/mix in mixture.gas)
- results += "[gas_data.name[mix]]: [round((mixture.gas[mix] / total_moles) * 100)]%"
- results += "Temperature: [round(mixture.temperature-T0C)]°C"
- else
- results += "\The [target] is empty!"
-
- return results
-
-/obj/proc/atmosanalyze(var/mob/user)
- return
-
-/obj/item/weapon/tank/atmosanalyze(var/mob/user)
- return atmosanalyzer_scan(src, src.air_contents, user)
-
-/obj/machinery/portable_atmospherics/atmosanalyze(var/mob/user)
- return atmosanalyzer_scan(src, src.air_contents, user)
-
-/obj/machinery/atmospherics/pipe/atmosanalyze(var/mob/user)
- return atmosanalyzer_scan(src, src.parent.air, user)
-
-/obj/machinery/power/rad_collector/atmosanalyze(var/mob/user)
- if(P) return atmosanalyzer_scan(src, src.P.air_contents, user)
-
-/obj/item/weapon/flamethrower/atmosanalyze(var/mob/user)
- if(ptank) return atmosanalyzer_scan(src, ptank.air_contents, user)
+/obj/proc/analyze_gases(var/obj/A, var/mob/user)
+ if(src != A)
+ user.visible_message("\The [user] has used \an [src] on \the [A]")
+
+ A.add_fingerprint(user)
+ var/list/result = A.atmosanalyze(user)
+ if(result && result.len)
+ to_chat(user, "Results of the analysis[src == A ? "" : " of \the [A]"]")
+ for(var/line in result)
+ to_chat(user, "[line]")
+ return 1
+
+ to_chat(user, "Your [src] flashes a red light as it fails to analyze \the [A].")
+ return 0
+
+/proc/atmosanalyzer_scan(var/obj/target, var/datum/gas_mixture/mixture, var/mob/user)
+ var/pressure = mixture.return_pressure()
+ var/total_moles = mixture.total_moles
+
+ var/list/results = list()
+ if (total_moles>0)
+ results += "Pressure: [round(pressure,0.1)] kPa"
+ for(var/mix in mixture.gas)
+ results += "[gas_data.name[mix]]: [round((mixture.gas[mix] / total_moles) * 100)]%"
+ results += "Temperature: [round(mixture.temperature-T0C)]°C"
+ else
+ results += "\The [target] is empty!"
+
+ return results
+
+/obj/proc/atmosanalyze(var/mob/user)
+ return
+
+/obj/item/tank/atmosanalyze(var/mob/user)
+ return atmosanalyzer_scan(src, src.air_contents, user)
+
+/obj/machinery/portable_atmospherics/atmosanalyze(var/mob/user)
+ return atmosanalyzer_scan(src, src.air_contents, user)
+
+/obj/machinery/atmospherics/pipe/atmosanalyze(var/mob/user)
+ return atmosanalyzer_scan(src, src.parent.air, user)
+
+/obj/machinery/power/rad_collector/atmosanalyze(var/mob/user)
+ if(P) return atmosanalyzer_scan(src, src.P.air_contents, user)
+
+/obj/item/flamethrower/atmosanalyze(var/mob/user)
+ if(ptank) return atmosanalyzer_scan(src, ptank.air_contents, user)
diff --git a/code/_helpers/files.dm b/code/_helpers/files.dm
index 388b2db4ed3..7e91c61534c 100644
--- a/code/_helpers/files.dm
+++ b/code/_helpers/files.dm
@@ -1,60 +1,72 @@
-//checks if a file exists and contains text
-//returns text as a string if these conditions are met
-/proc/return_file_text(filename)
- if(fexists(filename) == 0)
- error("File not found ([filename])")
- return
-
- var/text = file2text(filename)
- if(!text)
- error("File empty ([filename])")
- return
-
- return text
-
-//Sends resource files to client cache
-/client/proc/getFiles()
- for(var/file in args)
- to_chat(src, browse_rsc(file))
-
-/client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list(".txt",".log",".htm"))
- var/path = root
-
- for(var/i=0, iError: browse_files(): File not found/Invalid file([path]).")
- return
-
- return path
-
-#define FTPDELAY 200 //200 tick delay to discourage spam
-/* This proc is a failsafe to prevent spamming of file requests.
- It is just a timer that only permits a download every [FTPDELAY] ticks.
- This can be changed by modifying FTPDELAY's value above.
-
- PLEASE USE RESPONSIBLY, Some log files canr each sizes of 4MB! */
-/client/proc/file_spam_check()
- var/time_to_wait = fileaccess_timer - world.time
- if(time_to_wait > 0)
- to_chat(src, "Error: file_spam_check(): Spam. Please wait [round(time_to_wait/10)] seconds.")
- return 1
- fileaccess_timer = world.time + FTPDELAY
- return 0
-#undef FTPDELAY
+//checks if a file exists and contains text
+//returns text as a string if these conditions are met
+/proc/return_file_text(filename)
+ if(fexists(filename) == 0)
+ error("File not found ([filename])")
+ return
+
+ var/text = file2text(filename)
+ if(!text)
+ error("File empty ([filename])")
+ return
+
+ return text
+
+/proc/get_subfolders(var/root)
+ var/list/folders = list()
+ var/list/contents = flist(root)
+
+ for(var/file in contents)
+ //Check if the filename ends with / to see if its a folder
+ if(copytext(file,-1,0) != "/")
+ continue
+ folders.Add("[root][file]")
+
+ return folders
+
+//Sends resource files to client cache
+/client/proc/getFiles()
+ for(var/file in args)
+ to_chat(src, browse_rsc(file))
+
+/client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list(".txt",".log",".htm"))
+ var/path = root
+
+ for(var/i=0, iError: browse_files(): File not found/Invalid file([path]).")
+ return
+
+ return path
+
+#define FTPDELAY 200 //200 tick delay to discourage spam
+/* This proc is a failsafe to prevent spamming of file requests.
+ It is just a timer that only permits a download every [FTPDELAY] ticks.
+ This can be changed by modifying FTPDELAY's value above.
+
+ PLEASE USE RESPONSIBLY, Some log files canr each sizes of 4MB! */
+/client/proc/file_spam_check()
+ var/time_to_wait = fileaccess_timer - world.time
+ if(time_to_wait > 0)
+ to_chat(src, "Error: file_spam_check(): Spam. Please wait [round(time_to_wait/10)] seconds.")
+ return 1
+ fileaccess_timer = world.time + FTPDELAY
+ return 0
+#undef FTPDELAY
diff --git a/code/_helpers/functional.dm b/code/_helpers/functional.dm
index 231b8a4d261..114913f7c3a 100644
--- a/code/_helpers/functional.dm
+++ b/code/_helpers/functional.dm
@@ -1,24 +1,24 @@
-/proc/all_predicates_true(var/list/input, var/list/predicates)
- functional_sanity(input, predicates)
-
- for(var/i = 1 to predicates.len)
- if(!call(predicates[i])(arglist(input)))
- return FALSE
- return TRUE
-
-/proc/any_predicate_true(var/list/input, var/list/predicates)
- functional_sanity(input, predicates)
-
- if(!predicates.len)
- return TRUE
-
- for(var/i = 1 to predicates.len)
- if(call(predicates[i])(arglist(input)))
- return TRUE
- return FALSE
-
-/proc/functional_sanity(var/list/input, var/list/predicates)
- if(!istype(input))
- CRASH("Expected list input. Was [input ? "[input.type]" : "null"]")
- if(!istype(predicates))
- CRASH("Expected predicate list. Was [predicates ? "[predicates.type]" : "null"]")
+/proc/all_predicates_true(var/list/input, var/list/predicates)
+ functional_sanity(input, predicates)
+
+ for(var/i = 1 to predicates.len)
+ if(!call(predicates[i])(arglist(input)))
+ return FALSE
+ return TRUE
+
+/proc/any_predicate_true(var/list/input, var/list/predicates)
+ functional_sanity(input, predicates)
+
+ if(!predicates.len)
+ return TRUE
+
+ for(var/i = 1 to predicates.len)
+ if(call(predicates[i])(arglist(input)))
+ return TRUE
+ return FALSE
+
+/proc/functional_sanity(var/list/input, var/list/predicates)
+ if(!istype(input))
+ CRASH("Expected list input. Was [input ? "[input.type]" : "null"]")
+ if(!istype(predicates))
+ CRASH("Expected predicate list. Was [predicates ? "[predicates.type]" : "null"]")
diff --git a/code/_helpers/game.dm b/code/_helpers/game.dm
index 1080eb5f078..f54f2f615da 100644
--- a/code/_helpers/game.dm
+++ b/code/_helpers/game.dm
@@ -1,564 +1,547 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
-
-/proc/dopage(src,target)
- var/href_list
- var/href
- href_list = params2list("src=\ref[src]&[target]=1")
- href = "src=\ref[src];[target]=1"
- src:temphtml = null
- src:Topic(href, href_list)
- return null
-
-/proc/is_on_same_plane_or_station(var/z1, var/z2)
- if(z1 == z2)
- return 1
- if((z1 in current_map.station_levels) && (z2 in current_map.station_levels))
- return 1
- return 0
-
-/proc/max_default_z_level()
- var/max_z = 0
- for(var/z in current_map.station_levels)
- max_z = max(z, max_z)
- for(var/z in current_map.admin_levels)
- max_z = max(z, max_z)
- for(var/z in current_map.player_levels)
- max_z = max(z, max_z)
- return max_z
-
-/proc/get_area(O)
- var/turf/loc = get_turf(O)
- if(loc)
- .= loc.loc
-
-/proc/get_area_name(N) //get area by its name
- for(var/area/A in all_areas)
- if(A.name == N)
- return A
- return 0
-
-/proc/get_area_master(const/O)
- var/area/A = get_area(O)
- if (isarea(A))
- return A
-
-/proc/in_range(source, user)
- if(get_dist(source, user) <= 1)
- return 1
-
- return 0 //not in range and not telekinetic
-
-// Like view but bypasses luminosity check
-
-/proc/hear(var/range, var/atom/source)
-
- var/lum = source.luminosity
- source.luminosity = 6
-
- var/list/heard = view(range, source)
- source.luminosity = lum
-
- return heard
-
-/proc/isPlayerLevel(var/level)
- return level in current_map.player_levels
-
-/proc/isAdminLevel(var/level)
- return level in current_map.admin_levels
-
-/proc/isNotAdminLevel(var/level)
- return !isAdminLevel(level)
-
-/proc/circlerange(center=usr,radius=3)
-
- var/turf/centerturf = get_turf(center)
- var/list/turfs = new/list()
- var/rsq = radius * (radius+0.5)
-
- for(var/atom/T in range(radius, centerturf))
- var/dx = T.x - centerturf.x
- var/dy = T.y - centerturf.y
- if(dx*dx + dy*dy <= rsq)
- turfs += T
-
- //turfs += centerturf
- return turfs
-
-/proc/circleview(center=usr,radius=3)
-
- var/turf/centerturf = get_turf(center)
- var/list/atoms = new/list()
- var/rsq = radius * (radius+0.5)
-
- for(var/atom/A in view(radius, centerturf))
- var/dx = A.x - centerturf.x
- var/dy = A.y - centerturf.y
- if(dx*dx + dy*dy <= rsq)
- atoms += A
-
- //turfs += centerturf
- return atoms
-
-/proc/get_dist_euclidian(atom/Loc1 as turf|mob|obj,atom/Loc2 as turf|mob|obj)
- var/dx = Loc1.x - Loc2.x
- var/dy = Loc1.y - Loc2.y
-
- var/dist = sqrt(dx**2 + dy**2)
-
- return dist
-
-/proc/circlerangeturfs(center=usr,radius=3)
-
- var/turf/centerturf = get_turf(center)
- var/list/turfs = new/list()
- var/rsq = radius * (radius+0.5)
-
- for(var/turf/T in range(radius, centerturf))
- var/dx = T.x - centerturf.x
- var/dy = T.y - centerturf.y
- if(dx*dx + dy*dy <= rsq)
- turfs += T
- return turfs
-
-/proc/circleviewturfs(center=usr,radius=3) //Is there even a diffrence between this proc and circlerangeturfs()?
-
- var/turf/centerturf = get_turf(center)
- var/list/turfs = new/list()
- var/rsq = radius * (radius+0.5)
-
- for(var/turf/T in view(radius, centerturf))
- var/dx = T.x - centerturf.x
- var/dy = T.y - centerturf.y
- if(dx*dx + dy*dy <= rsq)
- turfs += T
- return turfs
-
-
-
-//var/debug_mob = 0
-
-// Will recursively loop through an atom's contents and check for mobs, then it will loop through every atom in that atom's contents.
-// It will keep doing this until it checks every content possible. This will fix any problems with mobs, that are inside objects,
-// being unable to hear people due to being in a box within a bag.
-
-/proc/recursive_content_check(var/atom/O, var/list/L = list(), var/recursion_limit = 3, var/client_check = 1, var/sight_check = 1, var/include_mobs = 1, var/include_objects = 1)
-
- if(!recursion_limit)
- return L
-
- for(var/I in O.contents)
-
- if(ismob(I))
- if(!sight_check || isInSight(I, O))
- L |= recursive_content_check(I, L, recursion_limit - 1, client_check, sight_check, include_mobs, include_objects)
- if(include_mobs)
- if(client_check)
- var/mob/M = I
- if(M.client)
- L |= M
- else
- L |= I
-
- else if(istype(I,/obj/))
- if(!sight_check || isInSight(I, O))
- L |= recursive_content_check(I, L, recursion_limit - 1, client_check, sight_check, include_mobs, include_objects)
- if(include_objects)
- L |= I
-
- return L
-
-// Returns a list of mobs and/or objects in range of R from source. Used in radio and say code.
-
-/proc/get_mobs_or_objects_in_view(var/R, var/atom/source, var/include_mobs = 1, var/include_objects = 1)
-
- var/turf/T = get_turf(source)
- var/list/hear = list()
-
- if(!T)
- return hear
-
- var/list/range = hear(R, T)
-
- for(var/I in range)
- if(ismob(I))
- hear |= recursive_content_check(I, hear, 3, 1, 0, include_mobs, include_objects)
- if(include_mobs)
- var/mob/M = I
- if(M.client)
- hear += M
- else if(istype(I,/obj/))
- hear |= recursive_content_check(I, hear, 3, 1, 0, include_mobs, include_objects)
- if(include_objects)
- hear += I
-
- return hear
-
-
-/proc/get_mobs_in_radio_ranges(var/list/obj/item/device/radio/radios)
-
- set background = 1
-
- . = list()
- // Returns a list of mobs who can hear any of the radios given in @radios
- var/list/speaker_coverage = list()
- for(var/obj/item/device/radio/R in radios)
- if(R)
- //Cyborg checks. Receiving message uses a bit of cyborg's charge.
- var/obj/item/device/radio/borg/BR = R
- if(istype(BR) && BR.myborg)
- var/mob/living/silicon/robot/borg = BR.myborg
- var/datum/robot_component/CO = borg.get_component("radio")
- if(!CO)
- continue //No radio component (Shouldn't happen)
- if(!borg.is_component_functioning("radio") || !borg.cell_use_power(CO.active_usage))
- continue //No power.
-
- var/turf/speaker = get_turf(R)
- if(speaker)
- for(var/turf/T in hear(R.canhear_range,speaker))
- speaker_coverage[T] = T
-
-
- // Try to find all the players who can hear the message
- for(var/i = 1; i <= player_list.len; i++)
- var/mob/M = player_list[i]
- if(M)
- var/turf/ear = get_turf(M)
- if(ear)
- // Ghostship is magic: Ghosts can hear radio chatter from anywhere
- if(speaker_coverage[ear] || (istype(M, /mob/abstract/observer) && (M.client) && (M.client.prefs.toggles & CHAT_GHOSTRADIO)))
- . += M
- return .
-
-/proc/get_mobs_and_objs_in_view_fast(turf/T, range, list/mobs, list/objs, checkghosts = GHOSTS_ALL_HEAR)
- var/list/hear = list()
- DVIEW(hear, range, T, INVISIBILITY_MAXIMUM)
- var/list/hearturfs = list()
-
- for(var/am in hear)
- var/atom/movable/AM = am
- if (!AM.loc)
- continue
-
- if(ismob(AM))
- mobs[AM] = TRUE
- hearturfs[AM.locs[1]] = TRUE
- else if(isobj(AM))
- objs[AM] = TRUE
- hearturfs[AM.locs[1]] = TRUE
-
- for(var/m in player_list)
- var/mob/M = m
- if(checkghosts == GHOSTS_ALL_HEAR && M.stat == DEAD && !isnewplayer(M) && (M.client && M.client.prefs.toggles & CHAT_GHOSTEARS))
- if (!mobs[M])
- mobs[M] = TRUE
- continue
- if(M.loc && hearturfs[M.locs[1]])
- if (!mobs[M])
- mobs[M] = TRUE
-
- for(var/o in listening_objects)
- var/obj/O = o
- if(O && O.loc && hearturfs[O.locs[1]])
- if (!objs[O])
- objs[O] = TRUE
-
-#define SIGN(X) ((X<0)?-1:1)
-
-proc
- inLineOfSight(X1,Y1,X2,Y2,Z=1,PX1=16.5,PY1=16.5,PX2=16.5,PY2=16.5)
- var/turf/T
- if(X1==X2)
- if(Y1==Y2)
- return 1 //Light cannot be blocked on same tile
- else
- var/s = SIGN(Y2-Y1)
- Y1+=s
- while(Y1!=Y2)
- T=locate(X1,Y1,Z)
- if(T.opacity)
- return 0
- Y1+=s
- else
- var/m=(32*(Y2-Y1)+(PY2-PY1))/(32*(X2-X1)+(PX2-PX1))
- var/b=(Y1+PY1/32-0.015625)-m*(X1+PX1/32-0.015625) //In tiles
- var/signX = SIGN(X2-X1)
- var/signY = SIGN(Y2-Y1)
- if(X1 abs (dx)) //slope is above 1:1 (move horizontally in a tie)
- if(dy > 0)
- return get_step(start, SOUTH)
- else
- return get_step(start, NORTH)
- else
- if(dx > 0)
- return get_step(start, WEST)
- else
- return get_step(start, EAST)
-
-/proc/get_mob_by_key(var/key)
- for(var/mob/M in mob_list)
- if(M.ckey == lowertext(key))
- return M
- return null
-
-
-// Will return a list of active candidates. It increases the buffer 5 times until it finds a candidate which is active within the buffer.
-/proc/get_active_candidates(var/buffer = 1)
-
- var/list/candidates = list() //List of candidate KEYS to assume control of the new larva ~Carn
- var/i = 0
- while(candidates.len <= 0 && i < 5)
- for(var/mob/abstract/observer/G in player_list)
- if(((G.client.inactivity/10)/60) <= buffer + i) // the most active players are more likely to become an alien
- if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
- candidates += G.key
- i++
- return candidates
-
-// Same as above but for alien candidates.
-
-/proc/get_alien_candidates()
- var/list/candidates = list() //List of candidate KEYS to assume control of the new larva ~Carn
- var/i = 0
- while(candidates.len <= 0 && i < 5)
- for(var/mob/abstract/observer/G in player_list)
- if(MODE_XENOMORPH in G.client.prefs.be_special_role)
- if(((G.client.inactivity/10)/60) <= ALIEN_SELECT_AFK_BUFFER + i) // the most active players are more likely to become an alien
- if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
- candidates += G.key
- i++
- return candidates
-
-/proc/ScreenText(obj/O, maptext="", screen_loc="CENTER-7,CENTER-7", maptext_height=480, maptext_width=480)
- if(!isobj(O)) O = new /obj/screen/text()
- O.maptext = maptext
- O.maptext_height = maptext_height
- O.maptext_width = maptext_width
- O.screen_loc = screen_loc
- return O
-
-/proc/Show2Group4Delay(obj/O, list/group, delay=0)
- if(!isobj(O)) return
- if(!group) group = clients
- for(var/client/C in group)
- C.screen += O
- if(delay)
- spawn(delay)
- for(var/client/C in group)
- C.screen -= O
-
-datum/projectile_data
- var/src_x
- var/src_y
- var/time
- var/distance
- var/power_x
- var/power_y
- var/dest_x
- var/dest_y
-
-/datum/projectile_data/New(var/src_x, var/src_y, var/time, var/distance, \
- var/power_x, var/power_y, var/dest_x, var/dest_y)
- src.src_x = src_x
- src.src_y = src_y
- src.time = time
- src.distance = distance
- src.power_x = power_x
- src.power_y = power_y
- src.dest_x = dest_x
- src.dest_y = dest_y
-
-/proc/projectile_trajectory(var/src_x, var/src_y, var/rotation, var/angle, var/power)
-
- var/g = 9.81
- var/h = 10
- var/power_x = power * cos(angle)
- var/power_y = power * sin(angle)
- var/time = (power_y + sqrt((power_y*power_y)+(2*g*h)))/g
- var/distance = time * power_x
-
- var/dest_x = src_x + distance*sin(rotation);
- var/dest_y = src_y + distance*cos(rotation);
-
- return new /datum/projectile_data(src_x, src_y, time, distance, power_x, power_y, dest_x, dest_y)
-
-/proc/GetRedPart(const/hexa)
- return hex2num(copytext(hexa,2,4))
-
-/proc/GetGreenPart(const/hexa)
- return hex2num(copytext(hexa,4,6))
-
-/proc/GetBluePart(const/hexa)
- return hex2num(copytext(hexa,6,8))
-
-/proc/GetHexColors(const/hexa)
- return list(
- GetRedPart(hexa),
- GetGreenPart(hexa),
- GetBluePart(hexa)
- )
-
-/proc/MixColors(const/list/colors)
- var/list/reds = list()
- var/list/blues = list()
- var/list/greens = list()
- var/list/weights = list()
-
- for (var/i = 0, ++i <= colors.len)
- reds.Add(GetRedPart(colors[i]))
- blues.Add(GetBluePart(colors[i]))
- greens.Add(GetGreenPart(colors[i]))
- weights.Add(1)
-
- var/r = mixOneColor(weights, reds)
- var/g = mixOneColor(weights, greens)
- var/b = mixOneColor(weights, blues)
- return rgb(r,g,b)
-
-/proc/mixOneColor(var/list/weight, var/list/color)
- if (!weight || !color || length(weight)!=length(color))
- return 0
-
- var/contents = length(weight)
- var/i
-
- //normalize weights
- var/listsum = 0
- for(i=1; i<=contents; i++)
- listsum += weight[i]
- for(i=1; i<=contents; i++)
- weight[i] /= listsum
-
- //mix them
- var/mixedcolor = 0
- for(i=1; i<=contents; i++)
- mixedcolor += weight[i]*color[i]
- mixedcolor = round(mixedcolor)
-
- //until someone writes a formal proof for this algorithm, let's keep this in
-// if(mixedcolor<0x00 || mixedcolor>0xFF)
-// return 0
- //that's not the kind of operation we are running here, nerd
- mixedcolor=min(max(mixedcolor,0),255)
-
- return mixedcolor
-
-/**
-* Gets the highest and lowest pressures from the tiles in cardinal directions
-* around us, then checks the difference.
-*/
-/proc/getOPressureDifferential(var/turf/loc)
- var/minp=16777216;
- var/maxp=0;
- for(var/dir in cardinal)
- var/turf/simulated/T=get_turf(get_step(loc,dir))
- var/cp=0
- if(T && istype(T) && T.zone)
- var/datum/gas_mixture/environment = T.return_air()
- cp = environment.return_pressure()
- else
- if(istype(T,/turf/simulated))
- continue
- if(cpmaxp)maxp=cp
- return abs(minp-maxp)
-
-/proc/convert_k2c(var/temp)
- return ((temp - T0C))
-
-/proc/convert_c2k(var/temp)
- return ((temp + T0C))
-
-/proc/getCardinalAirInfo(var/turf/loc, var/list/stats=list("temperature"))
- var/list/temps = new/list(4)
- for(var/dir in cardinal)
- var/direction
- switch(dir)
- if(NORTH)
- direction = 1
- if(SOUTH)
- direction = 2
- if(EAST)
- direction = 3
- if(WEST)
- direction = 4
- var/turf/simulated/T=get_turf(get_step(loc,dir))
- var/list/rstats = new /list(stats.len)
- if(T && istype(T) && T.zone)
- var/datum/gas_mixture/environment = T.return_air()
- for(var/i=1;i<=stats.len;i++)
- if(stats[i] == "pressure")
- rstats[i] = environment.return_pressure()
- else
- rstats[i] = environment.vars[stats[i]]
- else if(istype(T, /turf/simulated))
- rstats = null // Exclude zone (wall, door, etc).
- else if(istype(T, /turf))
- // Should still work. (/turf/return_air())
- var/datum/gas_mixture/environment = T.return_air()
- for(var/i=1;i<=stats.len;i++)
- if(stats[i] == "pressure")
- rstats[i] = environment.return_pressure()
- else
- rstats[i] = environment.vars[stats[i]]
- temps[direction] = rstats
- return temps
-
-/proc/MinutesToTicks(var/minutes)
- return SecondsToTicks(60 * minutes)
-
-/proc/SecondsToTicks(var/seconds)
- return seconds * 10
-
-/proc/round_is_spooky(var/spookiness_threshold = config.cult_ghostwriter_req_cultists)
- if(enabled_spooking)
- return 1
- else
- return (cult.current_antagonists.len > spookiness_threshold)
-
-/proc/remove_images_from_clients(image/I, list/show_to)
- for(var/client/C in show_to)
- C.images -= I
-
-/proc/flick_overlay(image/I, list/show_to, duration)
- for(var/client/C in show_to)
- C.images += I
- addtimer(CALLBACK(GLOBAL_PROC, /.proc/remove_images_from_clients, I, show_to), duration)
-
-/proc/flick_overlay_view(image/I, atom/target, duration) //wrapper for the above, flicks to everyone who can see the target atom
- var/list/viewing = list()
- for(var/m in viewers(target))
- var/mob/M = m
- if(M.client)
- viewing += M.client
- flick_overlay(I, viewing, duration)
+//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
+
+/proc/dopage(src,target)
+ var/href_list
+ var/href
+ href_list = params2list("src=\ref[src]&[target]=1")
+ href = "src=\ref[src];[target]=1"
+ src:temphtml = null
+ src:Topic(href, href_list)
+ return null
+
+/proc/is_on_same_plane_or_station(var/z1, var/z2)
+ if(z1 == z2)
+ return 1
+ if(isStationLevel(z1) && isStationLevel(z2))
+ return 1
+ return 0
+
+/proc/max_default_z_level()
+ var/max_z = 0
+ for(var/z in current_map.station_levels)
+ max_z = max(z, max_z)
+ for(var/z in current_map.admin_levels)
+ max_z = max(z, max_z)
+ for(var/z in current_map.player_levels)
+ max_z = max(z, max_z)
+ return max_z
+
+/proc/get_area(O)
+ var/turf/loc = get_turf(O)
+ if(loc)
+ .= loc.loc
+
+/proc/get_area_name(N) //get area by its name
+ for(var/area/A in all_areas)
+ if(A.name == N)
+ return A
+ return 0
+
+/proc/get_area_master(const/O)
+ var/area/A = get_area(O)
+ if (isarea(A))
+ return A
+
+/proc/in_range(source, user)
+ if(get_dist(source, user) <= 1)
+ return 1
+
+ return 0 //not in range and not telekinetic
+
+// Like view but bypasses luminosity check
+
+/proc/hear(var/range, var/atom/source)
+
+ var/lum = source.luminosity
+ source.luminosity = 6
+
+ var/list/heard = view(range, source)
+ source.luminosity = lum
+
+ return heard
+
+/proc/circlerange(center=usr,radius=3)
+
+ var/turf/centerturf = get_turf(center)
+ var/list/turfs = new/list()
+ var/rsq = radius * (radius+0.5)
+
+ for(var/atom/T in range(radius, centerturf))
+ var/dx = T.x - centerturf.x
+ var/dy = T.y - centerturf.y
+ if(dx*dx + dy*dy <= rsq)
+ turfs += T
+
+ //turfs += centerturf
+ return turfs
+
+/proc/circleview(center=usr,radius=3)
+
+ var/turf/centerturf = get_turf(center)
+ var/list/atoms = new/list()
+ var/rsq = radius * (radius+0.5)
+
+ for(var/atom/A in view(radius, centerturf))
+ var/dx = A.x - centerturf.x
+ var/dy = A.y - centerturf.y
+ if(dx*dx + dy*dy <= rsq)
+ atoms += A
+
+ //turfs += centerturf
+ return atoms
+
+/proc/get_dist_euclidian(atom/Loc1 as turf|mob|obj,atom/Loc2 as turf|mob|obj)
+ var/dx = Loc1.x - Loc2.x
+ var/dy = Loc1.y - Loc2.y
+
+ var/dist = sqrt(dx**2 + dy**2)
+
+ return dist
+
+/proc/circlerangeturfs(center=usr,radius=3)
+
+ var/turf/centerturf = get_turf(center)
+ var/list/turfs = new/list()
+ var/rsq = radius * (radius+0.5)
+
+ for(var/turf/T in range(radius, centerturf))
+ var/dx = T.x - centerturf.x
+ var/dy = T.y - centerturf.y
+ if(dx*dx + dy*dy <= rsq)
+ turfs += T
+ return turfs
+
+/proc/circleviewturfs(center=usr,radius=3) //Is there even a diffrence between this proc and circlerangeturfs()?
+
+ var/turf/centerturf = get_turf(center)
+ var/list/turfs = new/list()
+ var/rsq = radius * (radius+0.5)
+
+ for(var/turf/T in view(radius, centerturf))
+ var/dx = T.x - centerturf.x
+ var/dy = T.y - centerturf.y
+ if(dx*dx + dy*dy <= rsq)
+ turfs += T
+ return turfs
+
+
+
+//var/debug_mob = 0
+
+// Will recursively loop through an atom's contents and check for mobs, then it will loop through every atom in that atom's contents.
+// It will keep doing this until it checks every content possible. This will fix any problems with mobs, that are inside objects,
+// being unable to hear people due to being in a box within a bag.
+
+/proc/recursive_content_check(var/atom/O, var/list/L = list(), var/recursion_limit = 3, var/client_check = 1, var/sight_check = 1, var/include_mobs = 1, var/include_objects = 1)
+
+ if(!recursion_limit)
+ return L
+
+ for(var/I in O.contents)
+
+ if(ismob(I))
+ if(!sight_check || isInSight(I, O))
+ L |= recursive_content_check(I, L, recursion_limit - 1, client_check, sight_check, include_mobs, include_objects)
+ if(include_mobs)
+ if(client_check)
+ var/mob/M = I
+ if(M.client)
+ L |= M
+ else
+ L |= I
+
+ else if(istype(I,/obj/))
+ if(!sight_check || isInSight(I, O))
+ L |= recursive_content_check(I, L, recursion_limit - 1, client_check, sight_check, include_mobs, include_objects)
+ if(include_objects)
+ L |= I
+
+ return L
+
+// Returns a list of mobs and/or objects in range of R from source. Used in radio and say code.
+
+/proc/get_mobs_or_objects_in_view(var/R, var/atom/source, var/include_mobs = 1, var/include_objects = 1)
+
+ var/turf/T = get_turf(source)
+ var/list/hear = list()
+
+ if(!T)
+ return hear
+
+ var/list/range = hear(R, T)
+
+ for(var/I in range)
+ if(ismob(I))
+ hear |= recursive_content_check(I, hear, 3, 1, 0, include_mobs, include_objects)
+ if(include_mobs)
+ var/mob/M = I
+ if(M.client)
+ hear += M
+ else if(istype(I,/obj/))
+ hear |= recursive_content_check(I, hear, 3, 1, 0, include_mobs, include_objects)
+ if(include_objects)
+ hear += I
+
+ return hear
+
+
+/proc/get_mobs_in_radio_ranges(var/list/obj/item/device/radio/radios)
+
+ set background = 1
+
+ . = list()
+ // Returns a list of mobs who can hear any of the radios given in @radios
+ var/list/speaker_coverage = list()
+ for(var/obj/item/device/radio/R in radios)
+ if(R)
+ //Cyborg checks. Receiving message uses a bit of cyborg's charge.
+ var/obj/item/device/radio/borg/BR = R
+ if(istype(BR) && BR.myborg)
+ var/mob/living/silicon/robot/borg = BR.myborg
+ var/datum/robot_component/CO = borg.get_component("radio")
+ if(!CO)
+ continue //No radio component (Shouldn't happen)
+ if(!borg.is_component_functioning("radio") || !borg.cell_use_power(CO.active_usage))
+ continue //No power.
+
+ var/turf/speaker = get_turf(R)
+ if(speaker)
+ for(var/turf/T in hear(R.canhear_range,speaker))
+ speaker_coverage[T] = T
+
+
+ // Try to find all the players who can hear the message
+ for(var/i = 1; i <= player_list.len; i++)
+ var/mob/M = player_list[i]
+ if(M)
+ var/turf/ear = get_turf(M)
+ if(ear)
+ // Ghostship is magic: Ghosts can hear radio chatter from anywhere
+ if(speaker_coverage[ear] || (istype(M, /mob/abstract/observer) && (M.client) && (M.client.prefs.toggles & CHAT_GHOSTRADIO)))
+ . += M
+ return .
+
+/proc/get_mobs_and_objs_in_view_fast(turf/T, range, list/mobs, list/objs, checkghosts = GHOSTS_ALL_HEAR)
+ var/list/hear = list()
+ DVIEW(hear, range, T, INVISIBILITY_MAXIMUM)
+ var/list/hearturfs = list()
+
+ for(var/am in hear)
+ var/atom/movable/AM = am
+ if (!AM.loc)
+ continue
+
+ if(ismob(AM))
+ mobs[AM] = TRUE
+ hearturfs[AM.locs[1]] = TRUE
+ else if(isobj(AM))
+ objs[AM] = TRUE
+ hearturfs[AM.locs[1]] = TRUE
+
+ for(var/m in player_list)
+ var/mob/M = m
+ if(istype(M, /mob/living/test))
+ if (!mobs[M])
+ mobs[M] = TRUE
+ continue
+ if(checkghosts == GHOSTS_ALL_HEAR && M.stat == DEAD && !isnewplayer(M) && (M.client && M.client.prefs.toggles & CHAT_GHOSTEARS))
+ if (!mobs[M])
+ mobs[M] = TRUE
+ continue
+ if(M.loc && hearturfs[M.locs[1]])
+ if (!mobs[M])
+ mobs[M] = TRUE
+
+ for(var/o in listening_objects)
+ var/obj/O = o
+ if(O && O.loc && hearturfs[O.locs[1]])
+ if (!objs[O])
+ objs[O] = TRUE
+
+#define SIGN(X) ((X<0)?-1:1)
+
+proc
+ inLineOfSight(X1,Y1,X2,Y2,Z=1,PX1=16.5,PY1=16.5,PX2=16.5,PY2=16.5)
+ var/turf/T
+ if(X1==X2)
+ if(Y1==Y2)
+ return 1 //Light cannot be blocked on same tile
+ else
+ var/s = SIGN(Y2-Y1)
+ Y1+=s
+ while(Y1!=Y2)
+ T=locate(X1,Y1,Z)
+ if(T.opacity)
+ return 0
+ Y1+=s
+ else
+ var/m=(32*(Y2-Y1)+(PY2-PY1))/(32*(X2-X1)+(PX2-PX1))
+ var/b=(Y1+PY1/32-0.015625)-m*(X1+PX1/32-0.015625) //In tiles
+ var/signX = SIGN(X2-X1)
+ var/signY = SIGN(Y2-Y1)
+ if(X1 abs (dx)) //slope is above 1:1 (move horizontally in a tie)
+ if(dy > 0)
+ return get_step(start, SOUTH)
+ else
+ return get_step(start, NORTH)
+ else
+ if(dx > 0)
+ return get_step(start, WEST)
+ else
+ return get_step(start, EAST)
+
+/proc/get_mob_by_key(var/key)
+ for(var/mob/M in mob_list)
+ if(M.ckey == lowertext(key))
+ return M
+ return null
+
+
+// Will return a list of active candidates. It increases the buffer 5 times until it finds a candidate which is active within the buffer.
+/proc/get_active_candidates(var/buffer = 1)
+
+ var/list/candidates = list() //List of candidate KEYS to assume control of the new larva ~Carn
+ var/i = 0
+ while(candidates.len <= 0 && i < 5)
+ for(var/mob/abstract/observer/G in player_list)
+ if(((G.client.inactivity/10)/60) <= buffer + i) // the most active players are more likely to become an alien
+ if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
+ candidates += G.key
+ i++
+ return candidates
+
+// Same as above but for alien candidates.
+
+/proc/ScreenText(obj/O, maptext="", screen_loc="CENTER-7,CENTER-7", maptext_height=480, maptext_width=480)
+ if(!isobj(O)) O = new /obj/screen/text()
+ O.maptext = maptext
+ O.maptext_height = maptext_height
+ O.maptext_width = maptext_width
+ O.screen_loc = screen_loc
+ return O
+
+/proc/Show2Group4Delay(obj/O, list/group, delay=0)
+ if(!isobj(O)) return
+ if(!group) group = clients
+ for(var/client/C in group)
+ C.screen += O
+ if(delay)
+ spawn(delay)
+ for(var/client/C in group)
+ C.screen -= O
+
+datum/projectile_data
+ var/src_x
+ var/src_y
+ var/time
+ var/distance
+ var/power_x
+ var/power_y
+ var/dest_x
+ var/dest_y
+
+/datum/projectile_data/New(var/src_x, var/src_y, var/time, var/distance, \
+ var/power_x, var/power_y, var/dest_x, var/dest_y)
+ src.src_x = src_x
+ src.src_y = src_y
+ src.time = time
+ src.distance = distance
+ src.power_x = power_x
+ src.power_y = power_y
+ src.dest_x = dest_x
+ src.dest_y = dest_y
+
+/proc/projectile_trajectory(var/src_x, var/src_y, var/rotation, var/angle, var/power)
+
+ var/g = 9.81
+ var/h = 10
+ var/power_x = power * cos(angle)
+ var/power_y = power * sin(angle)
+ var/time = (power_y + sqrt((power_y*power_y)+(2*g*h)))/g
+ var/distance = time * power_x
+
+ var/dest_x = src_x + distance*sin(rotation);
+ var/dest_y = src_y + distance*cos(rotation);
+
+ return new /datum/projectile_data(src_x, src_y, time, distance, power_x, power_y, dest_x, dest_y)
+
+/proc/GetRedPart(const/hexa)
+ return hex2num(copytext(hexa,2,4))
+
+/proc/GetGreenPart(const/hexa)
+ return hex2num(copytext(hexa,4,6))
+
+/proc/GetBluePart(const/hexa)
+ return hex2num(copytext(hexa,6,8))
+
+/proc/GetHexColors(const/hexa)
+ return list(
+ GetRedPart(hexa),
+ GetGreenPart(hexa),
+ GetBluePart(hexa)
+ )
+
+/proc/MixColors(const/list/colors)
+ var/list/reds = list()
+ var/list/blues = list()
+ var/list/greens = list()
+ var/list/weights = list()
+
+ for (var/i = 0, ++i <= colors.len)
+ reds.Add(GetRedPart(colors[i]))
+ blues.Add(GetBluePart(colors[i]))
+ greens.Add(GetGreenPart(colors[i]))
+ weights.Add(1)
+
+ var/r = mixOneColor(weights, reds)
+ var/g = mixOneColor(weights, greens)
+ var/b = mixOneColor(weights, blues)
+ return rgb(r,g,b)
+
+/proc/mixOneColor(var/list/weight, var/list/color)
+ if (!weight || !color || length(weight)!=length(color))
+ return 0
+
+ var/contents = length(weight)
+ var/i
+
+ //normalize weights
+ var/listsum = 0
+ for(i=1; i<=contents; i++)
+ listsum += weight[i]
+ for(i=1; i<=contents; i++)
+ weight[i] /= listsum
+
+ //mix them
+ var/mixedcolor = 0
+ for(i=1; i<=contents; i++)
+ mixedcolor += weight[i]*color[i]
+ mixedcolor = round(mixedcolor)
+
+ //until someone writes a formal proof for this algorithm, let's keep this in
+// if(mixedcolor<0x00 || mixedcolor>0xFF)
+// return 0
+ //that's not the kind of operation we are running here, nerd
+ mixedcolor=min(max(mixedcolor,0),255)
+
+ return mixedcolor
+
+/**
+* Gets the highest and lowest pressures from the tiles in cardinal directions
+* around us, then checks the difference.
+*/
+/proc/getOPressureDifferential(var/turf/loc)
+ var/minp=16777216;
+ var/maxp=0;
+ for(var/dir in cardinal)
+ var/turf/simulated/T=get_turf(get_step(loc,dir))
+ var/cp=0
+ if(T && istype(T) && T.zone)
+ var/datum/gas_mixture/environment = T.return_air()
+ cp = environment.return_pressure()
+ else
+ if(istype(T,/turf/simulated))
+ continue
+ if(cpmaxp)maxp=cp
+ return abs(minp-maxp)
+
+/proc/convert_k2c(var/temp)
+ return ((temp - T0C))
+
+/proc/convert_c2k(var/temp)
+ return ((temp + T0C))
+
+/proc/getCardinalAirInfo(var/turf/loc, var/list/stats=list("temperature"))
+ var/list/temps = new/list(4)
+ for(var/dir in cardinal)
+ var/direction
+ switch(dir)
+ if(NORTH)
+ direction = 1
+ if(SOUTH)
+ direction = 2
+ if(EAST)
+ direction = 3
+ if(WEST)
+ direction = 4
+ var/turf/simulated/T=get_turf(get_step(loc,dir))
+ var/list/rstats = new /list(stats.len)
+ if(T && istype(T) && T.zone)
+ var/datum/gas_mixture/environment = T.return_air()
+ for(var/i=1;i<=stats.len;i++)
+ if(stats[i] == "pressure")
+ rstats[i] = environment.return_pressure()
+ else
+ rstats[i] = environment.vars[stats[i]]
+ else if(istype(T, /turf/simulated))
+ rstats = null // Exclude zone (wall, door, etc).
+ else if(istype(T, /turf))
+ // Should still work. (/turf/return_air())
+ var/datum/gas_mixture/environment = T.return_air()
+ for(var/i=1;i<=stats.len;i++)
+ if(stats[i] == "pressure")
+ rstats[i] = environment.return_pressure()
+ else
+ rstats[i] = environment.vars[stats[i]]
+ temps[direction] = rstats
+ return temps
+
+/proc/MinutesToTicks(var/minutes)
+ return SecondsToTicks(60 * minutes)
+
+/proc/SecondsToTicks(var/seconds)
+ return seconds * 10
+
+/proc/round_is_spooky(var/spookiness_threshold = config.cult_ghostwriter_req_cultists)
+ if(enabled_spooking)
+ return 1
+ else
+ return (cult.current_antagonists.len > spookiness_threshold)
+
+/proc/remove_images_from_clients(image/I, list/show_to)
+ for(var/client/C in show_to)
+ C.images -= I
+
+/proc/flick_overlay(image/I, list/show_to, duration)
+ for(var/client/C in show_to)
+ C.images += I
+ addtimer(CALLBACK(GLOBAL_PROC, /.proc/remove_images_from_clients, I, show_to), duration)
+
+/proc/flick_overlay_view(image/I, atom/target, duration) //wrapper for the above, flicks to everyone who can see the target atom
+ var/list/viewing = list()
+ for(var/m in viewers(target))
+ var/mob/M = m
+ if(M.client)
+ viewing += M.client
+ flick_overlay(I, viewing, duration)
diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm
index d8b1c96acdb..b642bc8c198 100644
--- a/code/_helpers/global_lists.dm
+++ b/code/_helpers/global_lists.dm
@@ -1,226 +1,199 @@
-var/list/clients = list() //list of all clients
-var/list/admins = list() //list of all clients whom are admins
-var/list/directory = list() //list of all ckeys with associated client
-
-//Since it didn't really belong in any other category, I'm putting this here
-//This is for procs to replace all the goddamn 'in world's that are chilling around the code
-
-var/global/list/player_list = list() //List of all mobs **with clients attached**. Excludes /mob/abstract/new_player
-var/global/list/mob_list = list() //List of all mobs, including clientless
-var/global/list/human_mob_list = list() //List of all human mobs and sub-types, including clientless
-var/global/list/silicon_mob_list = list() //List of all silicon mobs, including clientless
-var/global/list/living_mob_list = list() //List of all alive mobs, including clientless. Excludes /mob/abstract/new_player
-var/global/list/dead_mob_list = list() //List of all dead mobs, including clientless. Excludes /mob/abstract/new_player
-var/global/list/topic_commands = list() //List of all API commands available
-var/global/list/topic_commands_names = list() //List of all API commands available
-
-var/global/list/landmarks_list = list() //list of all landmarks created
-var/global/list/surgery_steps = list() //list of all surgery steps |BS12
-var/global/list/side_effects = list() //list of all medical sideeffects types by thier names |BS12
-var/global/list/mechas_list = list() //list of all mechs. Used by hostile mobs target tracking.
-var/global/list/joblist = list() //list of all jobstypes, minus borg and AI
-var/global/list/brig_closets = list() //list of all brig secure_closets. Used by brig timers. Probably should be converted to use SSwireless eventually.
-
-var/global/list/teleportlocs = list()
-var/global/list/ghostteleportlocs = list()
-var/global/list/centcom_areas = list()
-var/global/list/the_station_areas = list()
-
-var/global/list/implants = list()
-
-var/global/list/turfs = list() //list of all turfs
-var/global/list/areas_by_type = list()
-var/global/list/all_areas = list()
-
-//Languages/species/whitelist.
-var/global/list/all_species = list()
-var/global/list/all_languages = list()
-var/global/list/language_keys = list() // Table of say codes for all languages
-var/global/list/whitelisted_species = list("Human") // Species that require a whitelist check.
-var/global/list/playable_species = list("Human") // A list of ALL playable species, whitelisted, latejoin or otherwise.
-
-// Posters
-var/global/list/poster_designs = list()
-
-// Uplinks
-var/list/obj/item/device/uplink/world_uplinks = list()
-
-//Preferences stuff
- //Hairstyles
-var/global/list/hair_styles_list = list() //stores /datum/sprite_accessory/hair indexed by name
-var/global/list/hair_styles_male_list = list()
-var/global/list/hair_styles_female_list = list()
-var/global/list/facial_hair_styles_list = list() //stores /datum/sprite_accessory/facial_hair indexed by name
-var/global/list/facial_hair_styles_male_list = list()
-var/global/list/facial_hair_styles_female_list = list()
-var/global/list/skin_styles_female_list = list() //unused
-var/global/list/body_marking_styles_list = list()
-var/global/list/chargen_disabilities_list = list()
- //Underwear
-var/global/list/underwear_m = list("White" = "m1", "Grey" = "m2", "Green" = "m3", "Blue" = "m4", "Black" = "m5", "Mankini" = "m6", "Boxers" = "boxers", "Green and blue boxers" = "boxers_green_and_blue","Loveheart boxers" = "boxers_loveheart","None") //Curse whoever made male/female underwear diffrent colours
-var/global/list/underwear_f = list("Red" = "f1", "White" = "f2", "Yellow" = "f3", "Blue" = "f4", "Black" = "f5", "Thong" = "f6", "Black Sports" = "f7","White Sports" = "f8","None")
- //undershirt
-var/global/list/undershirt_t = list(
- "White tank top" = "u1", "Black tank top" = "u2", "Black shirt" = "u3", "White shirt" = "u4",
- "Polo" = "polo", "Blue polo" = "bluepolo_s", "Red polo" = "redpolo_s", "Yellow polo" = "grayyellowpolo_s",
- "Striped shirt" = "shirt_stripes_s", "NanoTrasen shirt" = "shirt_nano_s", "Tiedye shirt" = "shirt_tiedye_s",
- "Green sport shirt" = "greenshirtsport_s", "Red sport shirt" = "redshirtsport_s", "Blue sport shirt" = "blueshirtsport_s",
- "Striped tank top " = "tank_stripes_s", "Rainbow tank top" = "tank_rainbow_s", "Longsleeve shirt" = "undershirt_long",
- "Striped longsleve shirt" = "longstripe", "Blue striped longsleve shirt" = "longstripe_blue", "None")
-
- //socks
-var/global/list/socks_f = list(
- "White normal" = "white_norm", "White short" = "white_short", "White knee" = "white_knee",
- "White thigh" = "white_thigh", "Black normal" = "black_norm", "Black short" = "black_short",
- "Black knee" = "black_knee", "Black thigh" = "black_thigh", "Striped normal" = "striped_norm",
- "Striped short" = "striped_short", "Striped knee" = "striped_knee", "Striped thigh" = "striped_thigh",
- "Rainbow normal" = "rainbow_norm", "Rainbow short" = "rainbow_short", "Rainbow knee" = "rainbow_knee",
- "Rainbow thigh" = "rainbow_thigh", "Pantyhose" = "pantyhose", "None")
-
-var/global/list/socks_m = list(
- "White normal" = "white_norm", "White short" = "white_short", "White knee" = "white_knee",
- "Black normal" = "black_norm", "Black short" = "black_short", "Black knee" = "black_knee",
- "Striped normal" = "striped_norm", "Striped short" = "striped_short", "Striped knee" = "striped_knee",
- "Rainbow normal" = "rainbow_norm", "Rainbow short" = "rainbow_short", "Rainbow knee" = "rainbow_knee", "None")
-
- //Backpacks
-var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt", "Duffel Bag", "Messenger Bag")
-var/global/list/backbagstyles = list("Job-specific", "Grey")
-var/global/list/exclude_jobs = list(/datum/job/ai,/datum/job/cyborg, /datum/job/merchant)
-
-// Visual nets
-var/list/datum/visualnet/visual_nets = list()
-var/datum/visualnet/camera/cameranet = new()
-var/datum/visualnet/cult/cultnet = new()
-
-// Runes
-var/global/list/rune_list = new()
-var/global/list/escape_list = list()
-var/global/list/endgame_exits = list()
-var/global/list/endgame_safespawns = list()
-
-var/global/list/syndicate_access = list(access_maint_tunnels, access_syndicate, access_external_airlocks)
-
-//Cloaking devices
-var/global/list/cloaking_devices = list()
-
-//////////////////////////
-/////Initial Building/////
-//////////////////////////
-
-/proc/makeDatumRefLists()
- var/list/paths
-
- //Hair - Initialise all /datum/sprite_accessory/hair into an list indexed by hair-style name
- paths = subtypesof(/datum/sprite_accessory/hair)
- for(var/path in paths)
- var/datum/sprite_accessory/hair/H = new path()
- hair_styles_list[H.name] = H
- switch(H.gender)
- if(MALE) hair_styles_male_list += H.name
- if(FEMALE) hair_styles_female_list += H.name
- else
- hair_styles_male_list += H.name
- hair_styles_female_list += H.name
-
- sortTim(hair_styles_list, /proc/cmp_text_asc)
- sortTim(hair_styles_male_list, /proc/cmp_text_asc)
- sortTim(hair_styles_female_list, /proc/cmp_text_asc)
-
- //Facial Hair - Initialise all /datum/sprite_accessory/facial_hair into an list indexed by facialhair-style name
- paths = subtypesof(/datum/sprite_accessory/facial_hair)
- for(var/path in paths)
- var/datum/sprite_accessory/facial_hair/H = new path()
- facial_hair_styles_list[H.name] = H
- switch(H.gender)
- if(MALE) facial_hair_styles_male_list += H.name
- if(FEMALE) facial_hair_styles_female_list += H.name
- else
- facial_hair_styles_male_list += H.name
- facial_hair_styles_female_list += H.name
-
- sortTim(facial_hair_styles_list, /proc/cmp_text_asc)
- sortTim(facial_hair_styles_male_list, /proc/cmp_text_asc)
- sortTim(facial_hair_styles_female_list, /proc/cmp_text_asc)
-
- //Body markings
- paths = subtypesof(/datum/sprite_accessory/marking)
- for(var/path in paths)
- var/datum/sprite_accessory/marking/M = new path()
- body_marking_styles_list[M.name] = M
-
- sortTim(body_marking_styles_list, /proc/cmp_text_asc)
-
- //Disability datums
- paths = subtypesof(/datum/character_disabilities)
- for(var/path in paths)
- var/datum/character_disabilities/T = new path()
- chargen_disabilities_list[T.name] = T
-
- sortTim(chargen_disabilities_list, /proc/cmp_text_asc)
-
- //Surgery Steps - Initialize all /datum/surgery_step into a list
- paths = subtypesof(/datum/surgery_step)
- for(var/T in paths)
- var/datum/surgery_step/S = new T
- surgery_steps += S
-
- sortTim(surgery_steps, /proc/cmp_surgery)
-
- //List of job. I can't believe this was calculated multiple times per tick!
- paths = subtypesof(/datum/job)
- paths -= exclude_jobs
- for(var/T in paths)
- var/datum/job/J = new T
- joblist[J.title] = J
-
- //Languages and species.
- paths = subtypesof(/datum/language)
- for(var/T in paths)
- var/datum/language/L = new T
- all_languages[L.name] = L
-
- for (var/language_name in all_languages)
- var/datum/language/L = all_languages[language_name]
- if(!(L.flags & NONGLOBAL))
- language_keys[lowertext(L.key)] = L
-
- var/rkey = 0
- paths = subtypesof(/datum/species)
- for(var/T in paths)
- rkey++
- var/datum/species/S = new T
- S.race_key = rkey //Used in mob icon caching.
- all_species[S.name] = S
-
- sortTim(all_species, /proc/cmp_text_asc)
-
- // The other lists are generated *after* we sort the main one so they don't need sorting too.
- for (var/thing in all_species)
- var/datum/species/S = all_species[thing]
-
- if (!(S.spawn_flags & IS_RESTRICTED))
- playable_species += S.name
- if(S.spawn_flags & IS_WHITELISTED)
- whitelisted_species += S.name
-
- //Posters
- paths = subtypesof(/datum/poster)
- for(var/T in paths)
- var/datum/poster/P = new T
- poster_designs += P
-
-
- return 1
-
-/* // Uncomment to debug chemical reaction list.
-/client/verb/debug_chemical_list()
-
- for (var/reaction in SSchemistry.chemical_reactions)
- . += "SSchemistry.chemical_reactions\[\"[reaction]\"\] = \"[SSchemistry.chemical_reactions[reaction]]\"\n"
- if(islist(SSchemistry.chemical_reactions[reaction]))
- var/list/L = SSchemistry.chemical_reactions[reaction]
- for(var/t in L)
- . += " has: [t]\n"
- world << .
-*/
+var/list/clients = list() //list of all clients
+var/list/staff = list() //list of all clients who have any permissions
+var/list/directory = list() //list of all ckeys with associated client
+
+//Since it didn't really belong in any other category, I'm putting this here
+//This is for procs to replace all the goddamn 'in world's that are chilling around the code
+
+var/global/list/player_list = list() //List of all mobs **with clients attached**. Excludes /mob/abstract/new_player
+var/global/list/mob_list = list() //List of all mobs, including clientless
+var/global/list/human_mob_list = list() //List of all human mobs and sub-types, including clientless
+var/global/list/silicon_mob_list = list() //List of all silicon mobs, including clientless
+var/global/list/living_mob_list = list() //List of all alive mobs, including clientless. Excludes /mob/abstract/new_player
+var/global/list/dead_mob_list = list() //List of all dead mobs, including clientless. Excludes /mob/abstract/new_player
+var/global/list/topic_commands = list() //List of all API commands available
+var/global/list/topic_commands_names = list() //List of all API commands available
+
+var/global/list/landmarks_list = list() //list of all landmarks created
+var/global/list/surgery_steps = list() //list of all surgery steps |BS12
+var/global/list/side_effects = list() //list of all medical sideeffects types by thier names |BS12
+var/global/list/mechas_list = list() //list of all mechs. Used by hostile mobs target tracking.
+var/global/list/joblist = list() //list of all jobstypes, minus borg and AI
+var/global/list/brig_closets = list() //list of all brig secure_closets. Used by brig timers. Probably should be converted to use SSwireless eventually.
+
+var/global/list/teleportlocs = list()
+var/global/list/ghostteleportlocs = list()
+var/global/list/centcom_areas = list()
+var/global/list/the_station_areas = list()
+
+var/global/list/implants = list()
+
+var/global/list/turfs = list() //list of all turfs
+var/global/list/areas_by_type = list()
+var/global/list/all_areas = list()
+
+//Languages/species/whitelist.
+var/global/list/datum/species/all_species = list()
+var/global/list/all_languages = list()
+var/global/list/language_keys = list() // Table of say codes for all languages
+var/global/list/whitelisted_species = list("Human") // Species that require a whitelist check.
+var/global/list/playable_species = list("Human") // A list of ALL playable species, whitelisted, latejoin or otherwise.
+
+// Posters
+var/global/list/poster_designs = list()
+
+// Uplinks
+var/list/obj/item/device/uplink/world_uplinks = list()
+
+//Preferences stuff
+//Hairstyles
+var/global/list/hair_styles_list = list() //stores /datum/sprite_accessory/hair indexed by name
+var/global/list/hair_styles_male_list = list()
+var/global/list/hair_styles_female_list = list()
+var/global/list/facial_hair_styles_list = list() //stores /datum/sprite_accessory/facial_hair indexed by name
+var/global/list/facial_hair_styles_male_list = list()
+var/global/list/facial_hair_styles_female_list = list()
+var/global/list/skin_styles_female_list = list() //unused
+var/global/list/body_marking_styles_list = list()
+var/global/list/chargen_disabilities_list = list()
+var/global/static/list/valid_player_genders = list(MALE, FEMALE, NEUTER)
+
+//Backpacks
+var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt", "Duffel Bag", "Messenger Bag")
+var/global/list/backbagstyles = list("Job-specific", "Grey")
+var/global/list/exclude_jobs = list(/datum/job/ai,/datum/job/cyborg, /datum/job/merchant)
+
+// Visual nets
+var/list/datum/visualnet/visual_nets = list()
+var/datum/visualnet/camera/cameranet = new()
+
+// Runes
+var/global/list/rune_list = new()
+var/global/list/escape_list = list()
+var/global/list/endgame_exits = list()
+var/global/list/endgame_safespawns = list()
+
+var/global/list/syndicate_access = list(access_maint_tunnels, access_syndicate, access_external_airlocks)
+
+//Cloaking devices
+var/global/list/cloaking_devices = list()
+
+//////////////////////////
+/////Initial Building/////
+//////////////////////////
+
+/proc/makeDatumRefLists()
+ var/list/paths
+
+ //Hair - Initialise all /datum/sprite_accessory/hair into an list indexed by hair-style name
+ paths = subtypesof(/datum/sprite_accessory/hair)
+ for(var/path in paths)
+ var/datum/sprite_accessory/hair/H = new path()
+ hair_styles_list[H.name] = H
+ switch(H.gender)
+ if(MALE) hair_styles_male_list += H.name
+ if(FEMALE) hair_styles_female_list += H.name
+ else
+ hair_styles_male_list += H.name
+ hair_styles_female_list += H.name
+
+ sortTim(hair_styles_list, /proc/cmp_text_asc)
+ sortTim(hair_styles_male_list, /proc/cmp_text_asc)
+ sortTim(hair_styles_female_list, /proc/cmp_text_asc)
+
+ //Facial Hair - Initialise all /datum/sprite_accessory/facial_hair into an list indexed by facialhair-style name
+ paths = subtypesof(/datum/sprite_accessory/facial_hair)
+ for(var/path in paths)
+ var/datum/sprite_accessory/facial_hair/H = new path()
+ facial_hair_styles_list[H.name] = H
+ switch(H.gender)
+ if(MALE) facial_hair_styles_male_list += H.name
+ if(FEMALE) facial_hair_styles_female_list += H.name
+ else
+ facial_hair_styles_male_list += H.name
+ facial_hair_styles_female_list += H.name
+
+ sortTim(facial_hair_styles_list, /proc/cmp_text_asc)
+ sortTim(facial_hair_styles_male_list, /proc/cmp_text_asc)
+ sortTim(facial_hair_styles_female_list, /proc/cmp_text_asc)
+
+ //Body markings
+ paths = subtypesof(/datum/sprite_accessory/marking)
+ for(var/path in paths)
+ var/datum/sprite_accessory/marking/M = new path()
+ body_marking_styles_list[M.name] = M
+
+ sortTim(body_marking_styles_list, /proc/cmp_text_asc)
+
+ //Disability datums
+ paths = subtypesof(/datum/character_disabilities)
+ for(var/path in paths)
+ var/datum/character_disabilities/T = new path()
+ chargen_disabilities_list[T.name] = T
+
+ sortTim(chargen_disabilities_list, /proc/cmp_text_asc)
+
+ //Surgery Steps - Initialize all /datum/surgery_step into a list
+ paths = subtypesof(/datum/surgery_step)
+ for(var/T in paths)
+ var/datum/surgery_step/S = new T
+ surgery_steps += S
+
+ sortTim(surgery_steps, /proc/cmp_surgery)
+
+ //List of job. I can't believe this was calculated multiple times per tick!
+ paths = subtypesof(/datum/job)
+ paths -= exclude_jobs
+ for(var/T in paths)
+ var/datum/job/J = new T
+ joblist[J.title] = J
+
+ //Languages and species.
+ paths = subtypesof(/datum/language)
+ for(var/T in paths)
+ var/datum/language/L = new T
+ all_languages[L.name] = L
+
+ for (var/language_name in all_languages)
+ var/datum/language/L = all_languages[language_name]
+ if(!(L.flags & NONGLOBAL))
+ language_keys[lowertext(L.key)] = L
+
+ var/rkey = 0
+ paths = subtypesof(/datum/species)
+ for(var/T in paths)
+ rkey++
+ var/datum/species/S = new T
+ S.race_key = rkey //Used in mob icon caching.
+ all_species[S.name] = S
+
+ sortTim(all_species, /proc/cmp_text_asc)
+
+ // The other lists are generated *after* we sort the main one so they don't need sorting too.
+ for (var/thing in all_species)
+ var/datum/species/S = all_species[thing]
+
+ if (!(S.spawn_flags & IS_RESTRICTED))
+ playable_species += S.name
+ if(S.spawn_flags & IS_WHITELISTED)
+ whitelisted_species += S.name
+
+ //Posters
+ paths = subtypesof(/datum/poster)
+ for(var/T in paths)
+ var/datum/poster/P = new T
+ poster_designs += P
+
+ return 1
+
+/* // Uncomment to debug chemical reaction list.
+/client/verb/debug_chemical_list()
+
+ for (var/reaction in SSchemistry.chemical_reactions)
+ . += "SSchemistry.chemical_reactions\[\"[reaction]\"\] = \"[SSchemistry.chemical_reactions[reaction]]\"\n"
+ if(islist(SSchemistry.chemical_reactions[reaction]))
+ var/list/L = SSchemistry.chemical_reactions[reaction]
+ for(var/t in L)
+ . += " has: [t]\n"
+ world << .
+*/
diff --git a/code/_helpers/icon_smoothing.dm b/code/_helpers/icon_smoothing.dm
index 1bbcb1749b7..0723a23995a 100644
--- a/code/_helpers/icon_smoothing.dm
+++ b/code/_helpers/icon_smoothing.dm
@@ -65,7 +65,7 @@
var/list/fixed_underlay
var/smooth_underlays // Determines if we should attempt to generate turf underlays for this type.
-/turf/simulated/shuttle/wall
+/turf/simulated/wall/shuttle
smooth_underlays = TRUE
/turf/simulated/wall
@@ -88,7 +88,7 @@
if (!tcache)
tcache = typecacheof(canSmoothWith || type, FALSE, !(smooth & SMOOTH_MORE))
SSicon_smooth.typecachecache[type] = tcache
- else
+ else
tcache = typecacheof(canSmoothWith || type, FALSE, !(smooth & SMOOTH_MORE))
if (smooth & SMOOTH_BORDER)
@@ -195,7 +195,7 @@
if (smooth_underlays && adjacencies)
// This should be a mutable_appearance, but we're still on 510.
// Alas.
- var/mutable_appearance/underlay_appearance = new(layer = TURF_LAYER)
+ var/mutable_appearance/underlay_appearance = mutable_appearance(null, layer = TURF_LAYER)
var/list/U = list(underlay_appearance)
if(fixed_underlay)
if(fixed_underlay["space"])
diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm
index 7d45d399186..df15e18a07b 100644
--- a/code/_helpers/icons.dm
+++ b/code/_helpers/icons.dm
@@ -1,960 +1,966 @@
-/*
-IconProcs README
-
-A BYOND library for manipulating icons and colors
-
-by Lummox JR
-
-version 1.0
-
-The IconProcs library was made to make a lot of common icon operations much easier. BYOND's icon manipulation
-routines are very capable but some of the advanced capabilities like using alpha transparency can be unintuitive to beginners.
-
-CHANGING ICONS
-
-Several new procs have been added to the /icon datum to simplify working with icons. To use them,
-remember you first need to setup an /icon var like so:
-
-var/icon/my_icon = new('iconfile.dmi')
-
-icon/ChangeOpacity(amount = 1)
- A very common operation in DM is to try to make an icon more or less transparent. Making an icon more
- transparent is usually much easier than making it less so, however. This proc basically is a frontend
- for MapColors() which can change opacity any way you like, in much the same way that SetIntensity()
- can make an icon lighter or darker. If amount is 0.5, the opacity of the icon will be cut in half.
- If amount is 2, opacity is doubled and anything more than half-opaque will become fully opaque.
-icon/GrayScale()
- Converts the icon to grayscale instead of a fully colored icon. Alpha values are left intact.
-icon/ColorTone(tone)
- Similar to GrayScale(), this proc converts the icon to a range of black -> tone -> white, where tone is an
- RGB color (its alpha is ignored). This can be used to create a sepia tone or similar effect.
- See also the global ColorTone() proc.
-icon/MinColors(icon)
- The icon is blended with a second icon where the minimum of each RGB pixel is the result.
- Transparency may increase, as if the icons were blended with ICON_ADD. You may supply a color in place of an icon.
-icon/MaxColors(icon)
- The icon is blended with a second icon where the maximum of each RGB pixel is the result.
- Opacity may increase, as if the icons were blended with ICON_OR. You may supply a color in place of an icon.
-icon/Opaque(background = "#000000")
- All alpha values are set to 255 throughout the icon. Transparent pixels become black, or whatever background color you specify.
-icon/BecomeAlphaMask()
- You can convert a simple grayscale icon into an alpha mask to use with other icons very easily with this proc.
- The black parts become transparent, the white parts stay white, and anything in between becomes a translucent shade of white.
-icon/AddAlphaMask(mask)
- The alpha values of the mask icon will be blended with the current icon. Anywhere the mask is opaque,
- the current icon is untouched. Anywhere the mask is transparent, the current icon becomes transparent.
- Where the mask is translucent, the current icon becomes more transparent.
-icon/UseAlphaMask(mask, mode)
- Sometimes you may want to take the alpha values from one icon and use them on a different icon.
- This proc will do that. Just supply the icon whose alpha mask you want to use, and src will change
- so it has the same colors as before but uses the mask for opacity.
-
-COLOR MANAGEMENT AND HSV
-
-RGB isn't the only way to represent color. Sometimes it's more useful to work with a model called HSV, which stands for hue, saturation, and value.
-
- * The hue of a color describes where it is along the color wheel. It goes from red to yellow to green to
- cyan to blue to magenta and back to red.
- * The saturation of a color is how much color is in it. A color with low saturation will be more gray,
- and with no saturation at all it is a shade of gray.
- * The value of a color determines how bright it is. A high-value color is vivid, moderate value is dark,
- and no value at all is black.
-
-Just as BYOND uses "#rrggbb" to represent RGB values, a similar format is used for HSV: "#hhhssvv". The hue is three
-hex digits because it ranges from 0 to 0x5FF.
-
- * 0 to 0xFF - red to yellow
- * 0x100 to 0x1FF - yellow to green
- * 0x200 to 0x2FF - green to cyan
- * 0x300 to 0x3FF - cyan to blue
- * 0x400 to 0x4FF - blue to magenta
- * 0x500 to 0x5FF - magenta to red
-
-Knowing this, you can figure out that red is "#000ffff" in HSV format, which is hue 0 (red), saturation 255 (as colorful as possible),
-value 255 (as bright as possible). Green is "#200ffff" and blue is "#400ffff".
-
-More than one HSV color can match the same RGB color.
-
-Here are some procs you can use for color management:
-
-ReadRGB(rgb)
- Takes an RGB string like "#ffaa55" and converts it to a list such as list(255,170,85). If an RGBA format is used
- that includes alpha, the list will have a fourth item for the alpha value.
-hsv(hue, sat, val, apha)
- Counterpart to rgb(), this takes the values you input and converts them to a string in "#hhhssvv" or "#hhhssvvaa"
- format. Alpha is not included in the result if null.
-ReadHSV(rgb)
- Takes an HSV string like "#100FF80" and converts it to a list such as list(256,255,128). If an HSVA format is used that
- includes alpha, the list will have a fourth item for the alpha value.
-RGBtoHSV(rgb)
- Takes an RGB or RGBA string like "#ffaa55" and converts it into an HSV or HSVA color such as "#080aaff".
-HSVtoRGB(hsv)
- Takes an HSV or HSVA string like "#080aaff" and converts it into an RGB or RGBA color such as "#ff55aa".
-BlendRGB(rgb1, rgb2, amount)
- Blends between two RGB or RGBA colors using regular RGB blending. If amount is 0, the first color is the result;
- if 1, the second color is the result. 0.5 produces an average of the two. Values outside the 0 to 1 range are allowed as well.
- The returned value is an RGB or RGBA color.
-BlendHSV(hsv1, hsv2, amount)
- Blends between two HSV or HSVA colors using HSV blending, which tends to produce nicer results than regular RGB
- blending because the brightness of the color is left intact. If amount is 0, the first color is the result; if 1,
- the second color is the result. 0.5 produces an average of the two. Values outside the 0 to 1 range are allowed as well.
- The returned value is an HSV or HSVA color.
-BlendRGBasHSV(rgb1, rgb2, amount)
- Like BlendHSV(), but the colors used and the return value are RGB or RGBA colors. The blending is done in HSV form.
-HueToAngle(hue)
- Converts a hue to an angle range of 0 to 360. Angle 0 is red, 120 is green, and 240 is blue.
-AngleToHue(hue)
- Converts an angle to a hue in the valid range.
-RotateHue(hsv, angle)
- Takes an HSV or HSVA value and rotates the hue forward through red, green, and blue by an angle from 0 to 360.
- (Rotating red by 60� produces yellow.) The result is another HSV or HSVA color with the same saturation and value
- as the original, but a different hue.
-GrayScale(rgb)
- Takes an RGB or RGBA color and converts it to grayscale. Returns an RGB or RGBA string.
-ColorTone(rgb, tone)
- Similar to GrayScale(), this proc converts an RGB or RGBA color to a range of black -> tone -> white instead of
- using strict shades of gray. The tone value is an RGB color; any alpha value is ignored.
-*/
-
-/*
-Get Flat Icon DEMO by DarkCampainger
-
-This is a test for the get flat icon proc, modified approprietly for icons and their states.
-Probably not a good idea to run this unless you want to see how the proc works in detail.
-mob
- icon = 'old_or_unused.dmi'
- icon_state = "green"
-
- Login()
- // Testing image underlays
- underlays += image(icon='old_or_unused.dmi',icon_state="red")
- underlays += image(icon='old_or_unused.dmi',icon_state="red", pixel_x = 32)
- underlays += image(icon='old_or_unused.dmi',icon_state="red", pixel_x = -32)
-
- // Testing image overlays
- overlays += image(icon='old_or_unused.dmi',icon_state="green", pixel_x = 32, pixel_y = -32)
- overlays += image(icon='old_or_unused.dmi',icon_state="green", pixel_x = 32, pixel_y = 32)
- overlays += image(icon='old_or_unused.dmi',icon_state="green", pixel_x = -32, pixel_y = -32)
-
- // Testing icon file overlays (defaults to mob's state)
- overlays += '_flat_demoIcons2.dmi'
-
- // Testing icon_state overlays (defaults to mob's icon)
- overlays += "white"
-
- // Testing dynamic icon overlays
- var/icon/I = icon('old_or_unused.dmi', icon_state="aqua")
- I.Shift(NORTH,16,1)
- overlays+=I
-
- // Testing dynamic image overlays
- I=image(icon=I,pixel_x = -32, pixel_y = 32)
- overlays+=I
-
- // Testing object types (and layers)
- overlays+=/obj/effect/overlayTest
-
- loc = locate (10,10,1)
- verb
- Browse_Icon()
- set name = "1. Browse Icon"
- // Give it a name for the cache
- var/iconName = "[ckey(src.name)]_flattened.dmi"
- // Send the icon to src's local cache
- src<