diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 40768604b565..e79928edd2ee 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -104,6 +104,7 @@ Maintainers can revert your changes if they feel they are not worth maintaining - [Embedding TGUI Components in Chat](../../tgui/docs/chat-embedded-components.md) - [Hard Deletes](./guides/HARDDELETES.md) +- [Quickly setting up a development database with ezdb](./guides/EZDB.md) - [MC Tab Guide](./guides/MC_tab.md) - [Tick system](./guides/TICK_ORDER.md) - [UI Development](../tgui/README.md) diff --git a/.github/guides/EZDB.md b/.github/guides/EZDB.md new file mode 100644 index 000000000000..cee9d7deaf18 --- /dev/null +++ b/.github/guides/EZDB.md @@ -0,0 +1,12 @@ +# Quickly setting up a development database with ezdb +While you do not need a database to code for yogstation, it is a prerequisite to many important features, especially on the admin side. Thus, if you are working in any code that benefits from it, it can be helpful to have one handy. + +**ezdb** is a tool for quickly setting up an isolated development database. It will manage downloading MariaDB, creating the database, setting it up, and updating it when the code evolves. It is not recommended for use in production servers, but is perfect for quick development. + +To run ezdb, go to `tools/ezdb`, and double-click on ezdb.bat. This will set up the database on port 1338, but you can configure this with `--port`. When it is done, you should be able to launch yogstation as normal and have database access. This runs on the same Python bootstrapper as things like the map merge tool, which can sometimes be flaky. + +If you wish to delete the ezdb database, delete the `db` folder as well as `config/ezdb.txt`. + +To update ezdb, run the script again. This will both look for any updates in the database changelog, as well as update your schema revision. + +Contact Mothblocks if you face any issues in this process. diff --git a/.github/workflows/turdis.yml b/.github/workflows/turdis.yml index cef619052746..dbde0b434455 100644 --- a/.github/workflows/turdis.yml +++ b/.github/workflows/turdis.yml @@ -88,9 +88,29 @@ jobs: - name: Compile All Maps run: | tools/build/build --ci dm -DCIBUILDING -DCITESTING -DALL_MAPS + find_all_maps: + if: "!contains(github.event.head_commit.message, '[ci skip]')" + name: Find Maps to Test + runs-on: ubuntu-20.04 + outputs: + maps: ${{ steps.map_finder.outputs.maps }} + steps: + - uses: actions/checkout@v2 + - name: Find Maps + id: map_finder + run: | + echo "$(ls -mw0 _maps/*.json)" > maps_output.txt + sed -i -e s+_maps/+\"+g -e s+.json+\"+g maps_output.txt + echo "Maps: $(cat maps_output.txt)" + echo "maps={\"paths\":[$(cat maps_output.txt)]}" >> $GITHUB_OUTPUT test: name: Compile and Run Tests runs-on: ubuntu-20.04 + needs: [find_all_maps] + strategy: + fail-fast: false + matrix: + map: ${{ fromJSON(needs.find_all_maps.outputs.maps).paths }} services: mariadb: image: mariadb @@ -98,7 +118,9 @@ jobs: - 3306:3306 env: MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: yes - + concurrency: + group: ci-${{ github.ref }}-${{ matrix.map }} + cancel-in-progress: true steps: - uses: actions/checkout@v2 @@ -136,7 +158,7 @@ jobs: - name: Compile run: | tools/build/build --ci dm -DCIBUILDING - tools/travis/dm.sh -DTRAVISBUILDING yogstation.dme || travis_terminate 1 + tools/travis/dm.sh -DTRAVISBUILDING -DANSICOLORS yogstation.dme || travis_terminate 1 - name: Prepare Artifacts run: | @@ -147,10 +169,23 @@ jobs: - name: Upload Artifacts uses: actions/upload-artifact@v1 with: - name: DMB + RSC + name: DMB + RSC ${{matrix.map}} path: ${{github.workspace}}/artifacts - name: Run Tests run: | - tools/travis/run_server.sh + tools/travis/run_server.sh ${{ matrix.map }} + results: + if: ${{ always() }} + runs-on: ubuntu-latest + name: Final Map Test + needs: [test] + steps: + - run: exit 1 + # see https://stackoverflow.com/a/67532120/4907315 + if: >- + ${{ + contains(needs.*.result, 'failure') + || contains(needs.*.result, 'cancelled') + }} diff --git a/.gitignore b/.gitignore index 9cd796be4556..bf6bfc5cf8c7 100644 --- a/.gitignore +++ b/.gitignore @@ -218,3 +218,7 @@ tools/MapAtmosFixer/MapAtmosFixer/bin/* #KDIFF3 files *.orig + +# ezdb +/db/ +/config/ezdb.txt diff --git a/SQL/database_changelog.txt b/SQL/database_changelog.md similarity index 98% rename from SQL/database_changelog.txt rename to SQL/database_changelog.md index ef9e3dc2e40c..5b3c483bd169 100644 --- a/SQL/database_changelog.txt +++ b/SQL/database_changelog.md @@ -11,6 +11,7 @@ In any query remember to add a prefix to the table names if you use one. version 5.13 2023-05-10 Adds allow_vpn to bound credentials flags +```sql ALTER TABLE `bound_credentials` MODIFY COLUMN flags set('bypass_bans','allow_proxies') DEFAULT NULL NULL; CREATE TABLE `proxy_cache` ( `ip` int(11) unsigned NOT NULL, @@ -19,28 +20,36 @@ CREATE TABLE `proxy_cache` ( PRIMARY KEY (`ip`), CONSTRAINT `data` CHECK (json_valid(`data`)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +``` +```sql CREATE OR REPLACE EVENT proxy_cache_ttl ON SCHEDULE EVERY 1 HOUR DO DELETE FROM proxy_cache WHERE (last_updated + INTERVAL 1 DAY) < current_timestamp(); +``` version 5.12 2023-04-10 Adds playtime to notes +```sql ALTER TABLE `messages` ADD `playtime` int(10) unsigned DEFAULT NULL; CREATE TRIGGER messagesTloghours BEFORE INSERT ON `messages` FOR EACH ROW SET NEW.playtime = (SELECT minutes FROM role_time rt WHERE rt.ckey = NEW.targetckey AND rt.job = 'Living'); +``` version 5.11 2023-01-03 Adds comment to credentials binding +```sql ALTER TABLE `bound_credentials` ADD comment text NULL; +``` version 5.10 2022-05-18, alexkar598 Adds credentials binding +```sql CREATE TABLE `bound_credentials` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `ckey` varchar(32) NOT NULL, @@ -52,27 +61,33 @@ CREATE TABLE `bound_credentials` ( KEY `idx_cid_lookup` (`computerid`), KEY `idx_ip_lookup` (`ip`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +``` version 5.9 23 November 2021, by adamsogm Adds the datetime column to the primary key for the MFA table +```sql ALTER TABLE ss13_mfa_logins DROP PRIMARY KEY, ADD PRIMARY KEY (`ckey`,`ip`,`cid`, `datetime`); +``` version 5.8 25 October 2021, by adamsogm Modifies the admin_tickets table, and adds the admin_ticket_interactions table Do not forget to apply the prefix to the foreign key on the admin_ticket_interactions table +```sql ALTER TABLE `admin_tickets` DROP COLUMN `content`, DROP COLUMN `rating`, MODIFY `a_ckey` varchar(32), ADD INDEX `idx_round` (`round_id`), ADD INDEX `idx_round_ticket` (`round_id`,`ticket_id`); +``` +```sql DROP TABLE IF EXISTS `admin_ticket_interactions`; CREATE TABLE IF NOT EXISTS `admin_ticket_interactions` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, @@ -83,15 +98,19 @@ CREATE TABLE IF NOT EXISTS `admin_ticket_interactions` ( PRIMARY KEY (`id`), FOREIGN KEY (`ticket_id`) REFERENCES `admin_tickets`(`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +``` version 5.7 23 September 2021, by adamsogm Adds table for storing mfa login cache and a column for storing TOTP seeds and one for mfa backup code +```sql ALTER TABLE player ADD COLUMN totp_seed varchar(20), ADD COLUMN mfa_backup varchar(128); +``` +```sql DROP TABLE IF EXISTS `mfa_logins`; CREATE TABLE IF NOT EXISTS `mfa_logins` ( `ckey` varchar(32) NOT NULL, @@ -100,6 +119,7 @@ CREATE TABLE IF NOT EXISTS `mfa_logins` ( `datetime` timestamp NOT NULL DEFAULT current_timestamp(), PRIMARY KEY (`ckey`,`ip`,`cid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +``` ---------------------------------------------------- @@ -107,9 +127,10 @@ version 5.6 14 August 2021, by alexkar598 Adds index on connection_log +```sql create index idx_review on connection_log (ckey, computerid, ip); - +``` ---------------------------------------------------- @@ -117,7 +138,9 @@ version 5.5 14 August 2021, by JamieD1 Adds column in mentor for position +```sql ALTER TABLE `mentor` ADD COLUMN `position` VARSET(32) UNSIGNED NOT NULL AFTER `ckey`; +``` ---------------------------------------------------- @@ -125,6 +148,7 @@ version 5.4 18 May 2020, by TheGamer01 Adds table for antag tokens +```sql CREATE TABLE `antag_tokens` ( `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, `ckey` VARCHAR(32) NULL NOT NULL, @@ -137,6 +161,7 @@ CREATE TABLE `antag_tokens` ( `round_id` int(11) unsigned NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; +``` ---------------------------------------------------- @@ -144,23 +169,29 @@ version 5.3 10 Dec 2019, by Nichlas0010 Added two tables for achievements, one for the metadata and one for storing achieved achievements, as well as a misc table which is essentially just a glorified assoc list +```sql CREATE TABLE `achievements` ( `name` VARCHAR(32) NOT NULL, `id` INT UNSIGNED NOT NULL, `descr` VARCHAR(2048) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; +``` +```sql CREATE TABLE `earned_achievements` ( `ckey` VARCHAR(32) NOT NULL, `id` INT UNSIGNED NOT NULL ) ENGINE=InnoDB; +``` +```sql CREATE TABLE `misc` ( `key` VARCHAR(32) NOT NULL, `value` VARCHAR(2048) NOT NULL, PRIMARY KEY (`key`) ) ENGINE=InnoDB; +``` ---------------------------------------------------- @@ -168,13 +199,17 @@ Version 5.2, 28 Aug 2019, by AffectedArc07/TheGamer01 Added a field to the `player` table to track ckey and discord ID relationships +```sql ALTER TABLE `player` ADD COLUMN `discord_id` BIGINT NULL DEFAULT NULL AFTER `flags`; +``` + ---------------------------------------------------- Version 5.1, 25 Feb 2018, by MrStonedOne Added four tables to enable storing of stickybans in the database since byond can lose them, and to enable disabling stickybans for a round without depending on a crash free round. Existing stickybans are automagically imported to the tables. +```sql CREATE TABLE `stickyban` ( `ckey` VARCHAR(32) NOT NULL, `reason` VARCHAR(2048) NOT NULL, @@ -182,7 +217,9 @@ CREATE TABLE `stickyban` ( `datetime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`ckey`) ) ENGINE=InnoDB; +``` +```sql CREATE TABLE `stickyban_matched_ckey` ( `stickyban` VARCHAR(32) NOT NULL, `matched_ckey` VARCHAR(32) NOT NULL, @@ -191,7 +228,9 @@ CREATE TABLE `stickyban_matched_ckey` ( `exempt` TINYINT(1) NOT NULL DEFAULT '0', PRIMARY KEY (`stickyban`, `matched_ckey`) ) ENGINE=InnoDB; +``` +```sql CREATE TABLE `stickyban_matched_ip` ( `stickyban` VARCHAR(32) NOT NULL, `matched_ip` INT UNSIGNED NOT NULL, @@ -199,7 +238,9 @@ CREATE TABLE `stickyban_matched_ip` ( `last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`stickyban`, `matched_ip`) ) ENGINE=InnoDB; +``` +```sql CREATE TABLE `stickyban_matched_cid` ( `stickyban` VARCHAR(32) NOT NULL, `matched_cid` VARCHAR(32) NOT NULL, @@ -207,6 +248,7 @@ CREATE TABLE `stickyban_matched_cid` ( `last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`stickyban`, `matched_cid`) ) ENGINE=InnoDB; +``` ---------------------------------------------------- @@ -216,6 +258,7 @@ Modified ban table to remove the need for the `bantype` column, a python script See the file 'ban_conversion_2018-10-28.py' for instructions on how to use the script. A new ban table can be created with the query: +```sql CREATE TABLE `ban` ( `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, `bantime` DATETIME NOT NULL, @@ -245,20 +288,25 @@ CREATE TABLE `ban` ( KEY `idx_ban_isbanned_details` (`ckey`,`ip`,`computerid`,`role`,`unbanned_datetime`,`expiration_time`), KEY `idx_ban_count` (`bantime`,`a_ckey`,`applies_to_admins`,`unbanned_datetime`,`expiration_time`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; +``` ---------------------------------------------------- Version 4.7, 18 August 2018, by CitrusGender Modified table `messages`, adding column `severity` to classify notes based on their severity. +```sql ALTER TABLE `messages` ADD `severity` enum('high','medium','minor','none') DEFAULT NULL AFTER `expire_timestamp` +``` ---------------------------------------------------- Version 4.6, 11 August 2018, by Jordie0608 Modified table `messages`, adding column `expire_timestamp` to allow for auto-"deleting" messages. +```sql ALTER TABLE `messages` ADD `expire_timestamp` DATETIME NULL DEFAULT NULL AFTER `secret`; +``` ---------------------------------------------------- @@ -266,26 +314,34 @@ Version 4.5, 9 July 2018, by Jordie0608 Modified table `player`, adding column `byond_key` to store a user's key along with their ckey. To populate this new column run the included script 'populate_key_2018-07', see the file for use instructions. +```sql ALTER TABLE `player` ADD `byond_key` VARCHAR(32) DEFAULT NULL AFTER `ckey`; +``` ---------------------------------------------------- Version 4.4, 9 May 2018, by Jordie0608 Modified table `round`, renaming column `start_datetime` to `initialize_datetime` and `end_datetime` to `shutdown_datetime` and adding columns to replace both under the same name in preparation for changes to TGS server initialization. +```sql ALTER TABLE `round` ALTER `start_datetime` DROP DEFAULT; +``` + +```sql ALTER TABLE `round` CHANGE COLUMN `start_datetime` `initialize_datetime` DATETIME NOT NULL AFTER `id`, ADD COLUMN `start_datetime` DATETIME NULL DEFAULT NULL AFTER `initialize_datetime`, CHANGE COLUMN `end_datetime` `shutdown_datetime` DATETIME NULL DEFAULT NULL AFTER `start_datetime`, ADD COLUMN `end_datetime` DATETIME NULL DEFAULT NULL AFTER `shutdown_datetime`; +``` ---------------------------------------------------- Version 4.3, 9 May 2018, by MrStonedOne Added table `role_time_log` and triggers `role_timeTlogupdate`, `role_timeTloginsert` and `role_timeTlogdelete` to update it from changes to `role_time` +```sql CREATE TABLE `role_time_log` ( `id` BIGINT NOT NULL AUTO_INCREMENT , `ckey` VARCHAR(32) NOT NULL , `job` VARCHAR(128) NOT NULL , `delta` INT NOT NULL , `datetime` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , PRIMARY KEY (`id`), INDEX (`ckey`), INDEX (`job`), INDEX (`datetime`)) ENGINE = InnoDB; DELIMITER $$ @@ -299,6 +355,7 @@ CREATE TRIGGER `role_timeTlogdelete` AFTER DELETE ON `role_time` FOR EACH ROW B END $$ DELIMITER ; +``` ---------------------------------------------------- Version 4.2, 17 April 2018, by Jordie0608 @@ -315,6 +372,7 @@ This change was made to enable use of sql-based admin loading. To import your existing admins and ranks run the included script 'admin_import_2018-02-03.py', see the file for use instructions. Legacy file-based admin loading is still supported, if you want to continue using it the script doesn't need to be run. +```sql ALTER TABLE `admin` CHANGE COLUMN `rank` `rank` VARCHAR(32) NOT NULL AFTER `ckey`, DROP COLUMN `id`, @@ -323,14 +381,18 @@ ALTER TABLE `admin` DROP COLUMN `email`, DROP PRIMARY KEY, ADD PRIMARY KEY (`ckey`); +``` +```sql ALTER TABLE `admin_log` CHANGE COLUMN `datetime` `datetime` DATETIME NOT NULL AFTER `id`, CHANGE COLUMN `adminckey` `adminckey` VARCHAR(32) NOT NULL AFTER `datetime`, CHANGE COLUMN `adminip` `adminip` INT(10) UNSIGNED NOT NULL AFTER `adminckey`, ADD COLUMN `operation` ENUM('add admin','remove admin','change admin rank','add rank','remove rank','change rank flags') NOT NULL AFTER `adminip`, CHANGE COLUMN `log` `log` VARCHAR(1000) NOT NULL AFTER `operation`; +``` +```sql ALTER TABLE `admin_ranks` CHANGE COLUMN `rank` `rank` VARCHAR(32) NOT NULL FIRST, CHANGE COLUMN `flags` `flags` SMALLINT UNSIGNED NOT NULL AFTER `rank`, @@ -339,6 +401,7 @@ ALTER TABLE `admin_ranks` DROP COLUMN `id`, DROP PRIMARY KEY, ADD PRIMARY KEY (`rank`); +``` ---------------------------------------------------- @@ -348,6 +411,8 @@ Modified feedback table to use json, a python script is used to migrate data to See the file 'feedback_conversion_2017-11-12.py' for instructions on how to use the script. A new json feedback table can be created with: + +```sql CREATE TABLE `feedback` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `datetime` datetime NOT NULL, @@ -358,12 +423,14 @@ CREATE TABLE `feedback` ( `json` json NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM +``` ---------------------------------------------------- Version 3.4, 28 August 2017, by MrStonedOne Modified table 'messages', adding a deleted column and editing all indexes to include it +```sql ALTER TABLE `messages` ADD COLUMN `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0' AFTER `edits`, DROP INDEX `idx_msg_ckey_time`, @@ -372,6 +439,7 @@ DROP INDEX `idx_msg_type_ckey_time_odr`, ADD INDEX `idx_msg_ckey_time` (`targetckey`,`timestamp`, `deleted`), ADD INDEX `idx_msg_type_ckeys_time` (`type`,`targetckey`,`adminckey`,`timestamp`, `deleted`), ADD INDEX `idx_msg_type_ckey_time_odr` (`type`,`targetckey`,`timestamp`, `deleted`); +``` ---------------------------------------------------- @@ -379,11 +447,13 @@ Version 3.3, 25 August 2017, by Jordie0608 Modified tables 'connection_log', 'legacy_population', 'library', 'messages' and 'player' to add additional 'round_id' tracking in various forms and 'server_ip' and 'server_port' to the table 'messages'. +```sql ALTER TABLE `connection_log` ADD COLUMN `round_id` INT(11) UNSIGNED NOT NULL AFTER `server_port`; ALTER TABLE `legacy_population` ADD COLUMN `round_id` INT(11) UNSIGNED NOT NULL AFTER `server_port`; ALTER TABLE `library` ADD COLUMN `round_id_created` INT(11) UNSIGNED NOT NULL AFTER `deleted`; ALTER TABLE `messages` ADD COLUMN `server_ip` INT(10) UNSIGNED NOT NULL AFTER `server`, ADD COLUMN `server_port` SMALLINT(5) UNSIGNED NOT NULL AFTER `server_ip`, ADD COLUMN `round_id` INT(11) UNSIGNED NOT NULL AFTER `server_port`; ALTER TABLE `player` ADD COLUMN `firstseen_round_id` INT(11) UNSIGNED NOT NULL AFTER `firstseen`, ADD COLUMN `lastseen_round_id` INT(11) UNSIGNED NOT NULL AFTER `lastseen`; +``` ---------------------------------------------------- @@ -391,9 +461,11 @@ Version 3.2, 18 August 2017, by Cyberboss and nfreader Modified table 'death', adding the columns `last_words` and 'suicide'. +```sql ALTER TABLE `death` ADD COLUMN `last_words` varchar(255) DEFAULT NULL AFTER `staminaloss`, ADD COLUMN `suicide` tinyint(0) NOT NULL DEFAULT '0' AFTER `last_words`; +``` Remember to add a prefix to the table name if you use them. @@ -403,9 +475,13 @@ Version 3.1, 20th July 2017, by Shadowlight213 Added role_time table to track time spent playing departments. Also, added flags column to the player table. +```sql CREATE TABLE `role_time` ( `ckey` VARCHAR(32) NOT NULL , `job` VARCHAR(128) NOT NULL , `minutes` INT UNSIGNED NOT NULL, PRIMARY KEY (`ckey`, `job`) ) ENGINE = InnoDB; +``` +```sql ALTER TABLE `player` ADD `flags` INT NOT NULL default '0' AFTER `accountjoindate`; +``` Remember to add a prefix to the table name if you use them. @@ -417,14 +493,18 @@ Added schema_revision to store the current db revision, why start at 3.0? because: 15:09 <+MrStonedOne> 1.0 was erro, 2.0 was when i removed erro_, 3.0 was when jordie made all the strings that hold numbers numbers +```sql CREATE TABLE `schema_revision` ( `major` TINYINT(3) UNSIGNED NOT NULL , `minor` TINYINT(3) UNSIGNED NOT NULL , `date` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL, PRIMARY KEY ( `major`,`minor` ) ) ENGINE = INNODB; +``` +```sql INSERT INTO `schema_revision` (`major`, `minor`) VALUES (3, 0); +``` Remember to add a prefix to the table name if you use them. @@ -434,7 +514,9 @@ Remember to add a prefix to the table name if you use them. Modified table 'poll_option', adding the column 'default_percentage_calc'. +```sql ALTER TABLE `poll_option` ADD COLUMN `default_percentage_calc` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1' AFTER `descmax` +``` Remember to add a prefix to the table name if you use them. @@ -444,7 +526,9 @@ Remember to add a prefix to the table name if you use them. Modified table 'poll_option', removing the column 'percentagecalc'. +```sql ALTER TABLE `poll_option` DROP COLUMN `percentagecalc` +``` Remember to add a prefix to the table name if you use them. diff --git a/SpacemanDMM.toml b/SpacemanDMM.toml index dc79b57af259..2cc934471078 100644 --- a/SpacemanDMM.toml +++ b/SpacemanDMM.toml @@ -1,5 +1,10 @@ -[langserver] -dreamchecker = true - -[debugger] -engine = "extools" +environment = "yogstation.dme" + +[langserver] +dreamchecker = true + +[diagnostics] +var_in_proc_parameter = "off" + +[debugger] +engine = "auxtools" diff --git a/_maps/RandomRuins/IceRuins/icemoon_surface_icehermit.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_hermit.dmm similarity index 100% rename from _maps/RandomRuins/IceRuins/icemoon_surface_icehermit.dmm rename to _maps/RandomRuins/IceRuins/icemoon_surface_hermit.dmm diff --git a/_maps/RandomRuins/IceRuins/icemoon_surface_syndicate.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_syndicate.dmm index 5e14bc6915b2..4422f1676409 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_surface_syndicate.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_surface_syndicate.dmm @@ -3515,7 +3515,7 @@ /obj/effect/turf_decal/siding/red, /obj/machinery/turretid{ ailock = 1; - control_area = "/area/ruin/powered/syndicate_lava_base/main"; + control_area = "/area/ruin/syndicate_icemoon/command"; dir = 1; icon_state = "control_kill"; lethal = 1; diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_walkervillage.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_walkervillage.dmm similarity index 100% rename from _maps/RandomRuins/IceRuins/icemoon_underground_walkervillage.dmm rename to _maps/RandomRuins/IceRuins/icemoon_surface_walkervillage.dmm diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm index 25fd8a3d49ae..b18a590ca4d5 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm @@ -3,7 +3,7 @@ /turf/template_noop, /area/template_noop) "ab" = ( -/turf/open/lava/smooth/lava_land_surface, +/turf/open/lava/smooth/lava_land_surface/no_shelter, /area/lavaland/surface/outdoors) "ac" = ( /obj/structure/disposaloutlet{ @@ -448,7 +448,7 @@ /area/ruin/powered/syndicate_lava_base/dormitories) "dS" = ( /obj/structure/lattice/catwalk, -/turf/open/lava/smooth/lava_land_surface, +/turf/open/lava/smooth/lava_land_surface/no_shelter, /area/lavaland/surface/outdoors) "dT" = ( /obj/effect/turf_decal/siding/blue/end{ @@ -3599,7 +3599,7 @@ name = "Syndicate Lavaland Base: Cargo Bay Dock"; width = 11 }, -/turf/open/lava/smooth/lava_land_surface, +/turf/open/lava/smooth/lava_land_surface/no_shelter, /area/lavaland/surface/outdoors) "ne" = ( /turf/open/floor/engine/o2, @@ -4366,7 +4366,7 @@ name = "Syndicate Lavaland Base: Arivals Dock"; width = 13 }, -/turf/open/lava/smooth/lava_land_surface, +/turf/open/lava/smooth/lava_land_surface/no_shelter, /area/lavaland/surface/outdoors) "tu" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ diff --git a/_maps/RandomRuins/StationRuins/BoxStation/chapel1.dmm b/_maps/RandomRuins/StationRuins/BoxStation/chapel1.dmm index f0e80d95eca0..cd8d019e4070 100644 --- a/_maps/RandomRuins/StationRuins/BoxStation/chapel1.dmm +++ b/_maps/RandomRuins/StationRuins/BoxStation/chapel1.dmm @@ -434,14 +434,7 @@ }, /turf/open/floor/plasteel/dark, /area/chapel/main) -"xO" = ( -/obj/effect/landmark/start/assistant, -/turf/open/floor/plasteel/chapel{ - dir = 4 - }, -/area/chapel/main) "Ar" = ( -/obj/effect/landmark/start/chaplain, /obj/structure/chair, /obj/structure/disposalpipe/segment{ dir = 4 @@ -572,14 +565,6 @@ }, /turf/open/floor/plasteel/dark, /area/chapel/main) -"MC" = ( -/obj/effect/landmark/start/assistant, -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/carpet/purple, -/area/chapel/main) "ML" = ( /obj/machinery/door/airlock/maintenance{ name = "Crematorium Maintenance"; @@ -1073,7 +1058,7 @@ ZS Wy ZS PM -xO +ZS PM QT JH @@ -1138,7 +1123,7 @@ Tv Tv rk Od -MC +Od Od Od Od diff --git a/_maps/RandomRuins/StationRuins/BoxStation/chapel2.dmm b/_maps/RandomRuins/StationRuins/BoxStation/chapel2.dmm index 09ea1a01b2c8..4b7ac1a5176e 100644 --- a/_maps/RandomRuins/StationRuins/BoxStation/chapel2.dmm +++ b/_maps/RandomRuins/StationRuins/BoxStation/chapel2.dmm @@ -50,7 +50,6 @@ /turf/open/floor/carpet/red, /area/chapel/main) "cB" = ( -/obj/effect/landmark/start/chaplain, /obj/machinery/camera{ c_tag = "Chapel Office" }, diff --git a/_maps/RandomRuins/StationRuins/BoxStation/engine_sm.dmm b/_maps/RandomRuins/StationRuins/BoxStation/engine_sm.dmm index 142f68d2201c..733a2ef2a261 100644 --- a/_maps/RandomRuins/StationRuins/BoxStation/engine_sm.dmm +++ b/_maps/RandomRuins/StationRuins/BoxStation/engine_sm.dmm @@ -1137,7 +1137,7 @@ "do" = ( /obj/machinery/atmospherics/components/trinary/filter/flipped/critical{ dir = 8; - filter_type = list(/datum/gas/nitrogen) + filter_type = list("n2") }, /turf/open/floor/engine, /area/engine/engineering) diff --git a/_maps/RandomRuins/StationRuins/MetaStation/meta_sm.dmm b/_maps/RandomRuins/StationRuins/MetaStation/meta_sm.dmm index cea332dfe4a9..7c18da9f5dd5 100644 --- a/_maps/RandomRuins/StationRuins/MetaStation/meta_sm.dmm +++ b/_maps/RandomRuins/StationRuins/MetaStation/meta_sm.dmm @@ -42,7 +42,7 @@ dir = 4 }, /obj/machinery/atmospherics/components/trinary/filter/flipped/critical{ - filter_type = list(/datum/gas/nitrogen) + filter_type = list("n2") }, /turf/open/floor/engine, /area/engine/engineering) diff --git a/_maps/RandomZLevels/VR/snowdin_VR.dmm b/_maps/RandomZLevels/VR/snowdin_VR.dmm index a11ea4463d80..e8859e690f32 100644 --- a/_maps/RandomZLevels/VR/snowdin_VR.dmm +++ b/_maps/RandomZLevels/VR/snowdin_VR.dmm @@ -2671,14 +2671,14 @@ "gc" = ( /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "gd" = ( /obj/effect/spawner/lootdrop/crate_spawner, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "ge" = ( @@ -2689,7 +2689,7 @@ /obj/effect/spawner/lootdrop/snowdin/dungeonheavy, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "gg" = ( @@ -3046,14 +3046,14 @@ /obj/effect/decal/remains/human, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "gV" = ( /obj/effect/decal/cleanable/blood/old, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "gW" = ( @@ -3372,7 +3372,7 @@ /obj/structure/destructible/cult/pylon, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "hG" = ( @@ -3637,7 +3637,7 @@ /obj/effect/spawner/lootdrop/snowdin/dungeonmid, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "im" = ( @@ -3647,7 +3647,7 @@ }, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "in" = ( @@ -3657,7 +3657,7 @@ }, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "io" = ( @@ -4458,7 +4458,7 @@ }, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "jP" = ( @@ -5553,7 +5553,7 @@ /obj/effect/spawner/lootdrop/snowdin/dungeonlite, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "lU" = ( @@ -7439,7 +7439,7 @@ /obj/structure/flora/rock/pile/icy, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "qh" = ( @@ -13071,7 +13071,7 @@ /turf/open/floor/mineral/plastitanium{ initial_gas_mix = "o2=22;n2=82;TEMP=180"; planetary_atmos = 1; - temperature = 180 + initial_temperature = 180 }, /area/awaymission/snowdin/cave) "EF" = ( @@ -13083,7 +13083,7 @@ /turf/open/floor/mineral/plastitanium{ initial_gas_mix = "o2=22;n2=82;TEMP=180"; planetary_atmos = 1; - temperature = 180 + initial_temperature = 180 }, /area/awaymission/snowdin/cave) "EG" = ( @@ -13097,7 +13097,7 @@ /turf/open/floor/mineral/plastitanium{ initial_gas_mix = "o2=22;n2=82;TEMP=180"; planetary_atmos = 1; - temperature = 180 + initial_temperature = 180 }, /area/awaymission/snowdin/cave) "EH" = ( diff --git a/_maps/RandomZLevels/moonoutpost19.dmm b/_maps/RandomZLevels/moonoutpost19.dmm index 5bb51263e5fc..1e0cf6ce459a 100644 --- a/_maps/RandomZLevels/moonoutpost19.dmm +++ b/_maps/RandomZLevels/moonoutpost19.dmm @@ -954,7 +954,7 @@ /turf/open/floor/plating{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "bY" = ( @@ -981,7 +981,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "ca" = ( @@ -989,7 +989,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cb" = ( @@ -1002,7 +1002,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cc" = ( @@ -1016,7 +1016,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cd" = ( @@ -1030,7 +1030,7 @@ heat_capacity = 1e+006; icon_state = "floorscorched2"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "ce" = ( @@ -1044,7 +1044,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cf" = ( @@ -1058,7 +1058,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cg" = ( @@ -1071,7 +1071,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "ch" = ( @@ -1086,7 +1086,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "ci" = ( @@ -1164,7 +1164,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cp" = ( @@ -1181,7 +1181,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cr" = ( @@ -1211,7 +1211,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "ct" = ( @@ -1234,7 +1234,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cv" = ( @@ -1248,7 +1248,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cw" = ( @@ -1324,7 +1324,7 @@ /turf/open/floor/plating{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cD" = ( @@ -1341,7 +1341,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cF" = ( @@ -1353,7 +1353,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cG" = ( @@ -1378,7 +1378,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cI" = ( @@ -1390,7 +1390,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cJ" = ( @@ -1401,7 +1401,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cK" = ( @@ -1422,7 +1422,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cL" = ( @@ -1437,7 +1437,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cM" = ( @@ -1498,7 +1498,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cR" = ( @@ -1507,7 +1507,7 @@ heat_capacity = 1e+006; icon_state = "damaged4"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cS" = ( @@ -1527,7 +1527,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cT" = ( @@ -1563,7 +1563,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cW" = ( @@ -1572,7 +1572,7 @@ heat_capacity = 1e+006; icon_state = "damaged2"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cX" = ( @@ -1581,7 +1581,7 @@ heat_capacity = 1e+006; icon_state = "damaged3"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cY" = ( @@ -1598,7 +1598,7 @@ dir = 1; heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "cZ" = ( @@ -1664,7 +1664,7 @@ /turf/open/floor/plating{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "df" = ( @@ -1686,7 +1686,7 @@ dir = 1; heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "dh" = ( @@ -1738,7 +1738,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "dm" = ( @@ -1749,7 +1749,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "dn" = ( @@ -1759,7 +1759,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "do" = ( @@ -1768,7 +1768,7 @@ heat_capacity = 1e+006; icon_state = "damaged1"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "dp" = ( @@ -1782,7 +1782,7 @@ heat_capacity = 1e+006; icon_state = "platingdmg3"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "dq" = ( @@ -1870,7 +1870,7 @@ /turf/open/floor/plating{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "dx" = ( @@ -1892,7 +1892,7 @@ /turf/open/floor/plating{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "dz" = ( @@ -1921,7 +1921,7 @@ /turf/open/floor/plating{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "dC" = ( @@ -1929,7 +1929,7 @@ heat_capacity = 1e+006; icon_state = "platingdmg1"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "dD" = ( @@ -1941,7 +1941,7 @@ /turf/open/floor/plating{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "dE" = ( @@ -2005,7 +2005,7 @@ icon_plating = "asteroidplating"; icon_state = "asteroidplating"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "dJ" = ( @@ -2031,7 +2031,7 @@ icon_plating = "asteroidplating"; icon_state = "asteroidplating"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) "dM" = ( @@ -2040,7 +2040,7 @@ icon_plating = "asteroidplating"; icon_state = "asteroidplating"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/main) "dN" = ( @@ -4936,7 +4936,7 @@ heat_capacity = 1e+006; icon_state = "platingdmg1"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "jB" = ( @@ -5188,7 +5188,7 @@ heat_capacity = 1e+006; icon_state = "floorscorched2"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "kd" = ( @@ -5200,7 +5200,7 @@ heat_capacity = 1e+006; icon_state = "damaged1"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "ke" = ( @@ -5212,7 +5212,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "kf" = ( @@ -5226,7 +5226,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "kg" = ( @@ -5238,7 +5238,7 @@ heat_capacity = 1e+006; icon_state = "floorscorched1"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "kh" = ( @@ -5249,7 +5249,7 @@ heat_capacity = 1e+006; icon_state = "platingdmg1"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "ki" = ( @@ -5261,7 +5261,7 @@ heat_capacity = 1e+006; icon_state = "damaged3"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "kj" = ( @@ -5448,7 +5448,7 @@ heat_capacity = 1e+006; icon_state = "damaged2"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "kC" = ( @@ -5467,7 +5467,7 @@ heat_capacity = 1e+006; icon_state = "damaged4"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "kE" = ( @@ -5475,7 +5475,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "kF" = ( @@ -5484,7 +5484,7 @@ heat_capacity = 1e+006; icon_state = "damaged5"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "kG" = ( @@ -5493,7 +5493,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "kH" = ( @@ -5591,7 +5591,7 @@ heat_capacity = 1e+006; icon_state = "platingdmg3"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "kR" = ( @@ -5779,7 +5779,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "ll" = ( @@ -5791,7 +5791,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "lm" = ( @@ -5901,7 +5901,7 @@ "lv" = ( /turf/open/floor/plasteel/showroomfloor{ heat_capacity = 1e+006; - temperature = 273.15 + initial_temperature = 273.15 }, /area/awaymission/moonoutpost19/arrivals) "lw" = ( @@ -5912,7 +5912,7 @@ }, /turf/open/floor/plasteel/showroomfloor{ heat_capacity = 1e+006; - temperature = 273.15 + initial_temperature = 273.15 }, /area/awaymission/moonoutpost19/arrivals) "lx" = ( @@ -5924,7 +5924,7 @@ /obj/item/clothing/under/waiter, /turf/open/floor/plasteel/showroomfloor{ heat_capacity = 1e+006; - temperature = 273.15 + initial_temperature = 273.15 }, /area/awaymission/moonoutpost19/arrivals) "lA" = ( @@ -5940,7 +5940,7 @@ }, /turf/open/floor/plating{ initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "lE" = ( @@ -5983,7 +5983,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "lJ" = ( @@ -5993,7 +5993,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "lK" = ( @@ -6067,7 +6067,7 @@ /obj/item/gun/ballistic/shotgun/sc_pump, /turf/open/floor/plasteel/showroomfloor{ heat_capacity = 1e+006; - temperature = 273.15 + initial_temperature = 273.15 }, /area/awaymission/moonoutpost19/arrivals) "lW" = ( @@ -6141,7 +6141,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "mi" = ( @@ -6192,7 +6192,7 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel/showroomfloor{ heat_capacity = 1e+006; - temperature = 273.15 + initial_temperature = 273.15 }, /area/awaymission/moonoutpost19/arrivals) "mn" = ( @@ -6207,7 +6207,7 @@ /obj/item/reagent_containers/food/snacks/meat/slab/monkey, /turf/open/floor/plasteel/showroomfloor{ heat_capacity = 1e+006; - temperature = 273.15 + initial_temperature = 273.15 }, /area/awaymission/moonoutpost19/arrivals) "mo" = ( @@ -6222,7 +6222,7 @@ /obj/item/storage/fancy/egg_box, /turf/open/floor/plasteel/showroomfloor{ heat_capacity = 1e+006; - temperature = 273.15 + initial_temperature = 273.15 }, /area/awaymission/moonoutpost19/arrivals) "mp" = ( @@ -6289,7 +6289,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "my" = ( @@ -6457,7 +6457,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "mQ" = ( @@ -6471,7 +6471,7 @@ heat_capacity = 1e+006; icon_state = "floorscorched2"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "mR" = ( @@ -6548,7 +6548,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "na" = ( @@ -6601,7 +6601,7 @@ heat_capacity = 1e+006; icon_state = "floorscorched2"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nj" = ( @@ -6614,7 +6614,7 @@ heat_capacity = 1e+006; icon_state = "damaged2"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nk" = ( @@ -6673,7 +6673,7 @@ heat_capacity = 1e+006; icon_state = "damaged1"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nr" = ( @@ -6704,7 +6704,7 @@ icon_plating = "asteroidplating"; icon_state = "asteroidplating"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nw" = ( @@ -6718,7 +6718,7 @@ /turf/open/floor/plasteel/cafeteria{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nx" = ( @@ -6742,7 +6742,7 @@ /turf/open/floor/plasteel/cafeteria{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "ny" = ( @@ -6757,7 +6757,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nz" = ( @@ -6810,7 +6810,7 @@ heat_capacity = 1e+006; icon_state = "platingdmg1"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nE" = ( @@ -6823,7 +6823,7 @@ heat_capacity = 1e+006; icon_state = "platingdmg3"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nF" = ( @@ -6836,7 +6836,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nG" = ( @@ -6849,7 +6849,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nH" = ( @@ -6911,7 +6911,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nN" = ( @@ -6922,7 +6922,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nO" = ( @@ -6966,7 +6966,7 @@ heat_capacity = 1e+006; icon_state = "damaged1"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nT" = ( @@ -7003,7 +7003,7 @@ icon_plating = "asteroidplating"; icon_state = "asteroidplating"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nX" = ( @@ -7015,7 +7015,7 @@ heat_capacity = 1e+006; icon_state = "floorscorched2"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nY" = ( @@ -7029,7 +7029,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "nZ" = ( @@ -7039,7 +7039,7 @@ icon_plating = "asteroidplating"; icon_state = "asteroidplating"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/main) "oa" = ( @@ -7061,7 +7061,7 @@ /turf/open/floor/plasteel{ heat_capacity = 1e+006; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/arrivals) "oc" = ( @@ -7074,7 +7074,7 @@ icon_plating = "asteroidplating"; icon_state = "asteroidplating"; initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - temperature = 251 + initial_temperature = 251 }, /area/awaymission/moonoutpost19/main) "od" = ( diff --git a/_maps/RandomZLevels/snowdin.dmm b/_maps/RandomZLevels/snowdin.dmm index 69a2ac9a86c6..ab80473ae735 100644 --- a/_maps/RandomZLevels/snowdin.dmm +++ b/_maps/RandomZLevels/snowdin.dmm @@ -2688,14 +2688,14 @@ "gc" = ( /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "gd" = ( /obj/effect/spawner/lootdrop/crate_spawner, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "ge" = ( @@ -2706,7 +2706,7 @@ /obj/effect/spawner/lootdrop/snowdin/dungeonheavy, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "gg" = ( @@ -3077,14 +3077,14 @@ /obj/effect/decal/remains/human, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "gV" = ( /obj/effect/decal/cleanable/blood/old, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "gW" = ( @@ -3391,7 +3391,7 @@ /obj/structure/destructible/cult/pylon, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "hG" = ( @@ -3652,7 +3652,7 @@ /obj/effect/spawner/lootdrop/snowdin/dungeonmid, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "im" = ( @@ -3662,7 +3662,7 @@ }, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "in" = ( @@ -3672,7 +3672,7 @@ }, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "io" = ( @@ -4489,7 +4489,7 @@ }, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "jP" = ( @@ -5615,7 +5615,7 @@ /obj/effect/spawner/lootdrop/snowdin/dungeonlite, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "lU" = ( @@ -7509,7 +7509,7 @@ /obj/structure/flora/rock/pile/icy, /turf/open/floor/engine/cult{ initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"; - temperature = 120 + initial_temperature = 120 }, /area/awaymission/snowdin/cave/cavern) "qh" = ( @@ -13210,7 +13210,7 @@ /turf/open/floor/mineral/plastitanium{ initial_gas_mix = "o2=22;n2=82;TEMP=180"; planetary_atmos = 1; - temperature = 180 + initial_temperature = 180 }, /area/awaymission/snowdin/cave) "EF" = ( @@ -13222,7 +13222,7 @@ /turf/open/floor/mineral/plastitanium{ initial_gas_mix = "o2=22;n2=82;TEMP=180"; planetary_atmos = 1; - temperature = 180 + initial_temperature = 180 }, /area/awaymission/snowdin/cave) "EG" = ( @@ -13236,7 +13236,7 @@ /turf/open/floor/mineral/plastitanium{ initial_gas_mix = "o2=22;n2=82;TEMP=180"; planetary_atmos = 1; - temperature = 180 + initial_temperature = 180 }, /area/awaymission/snowdin/cave) "EH" = ( diff --git a/_maps/RandomZLevels/undergroundoutpost45.dmm b/_maps/RandomZLevels/undergroundoutpost45.dmm index 2b15f9a3ec6a..3bb3fb1b1440 100644 --- a/_maps/RandomZLevels/undergroundoutpost45.dmm +++ b/_maps/RandomZLevels/undergroundoutpost45.dmm @@ -807,7 +807,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 351.9 + initial_temperature = 351.9 }, /area/awaymission/undergroundoutpost45/caves) "bX" = ( @@ -815,7 +815,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 351.9 + initial_temperature = 351.9 }, /area/awaymission/undergroundoutpost45/caves) "bY" = ( @@ -2112,7 +2112,7 @@ icon_plating = "asteroidplating"; icon_state = "asteroidplating"; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "ev" = ( @@ -2247,7 +2247,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "eK" = ( @@ -2625,7 +2625,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/central) "fo" = ( @@ -2861,7 +2861,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/central) "fK" = ( @@ -3042,7 +3042,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "gg" = ( @@ -3190,7 +3190,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/crew_quarters) "gC" = ( @@ -3462,7 +3462,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/research) "he" = ( @@ -3473,7 +3473,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/crew_quarters) "hf" = ( @@ -3505,7 +3505,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/crew_quarters) "hi" = ( @@ -4904,7 +4904,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/gateway) "jM" = ( @@ -4938,7 +4938,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/research) "jR" = ( @@ -6754,7 +6754,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/gateway) "mJ" = ( @@ -8519,7 +8519,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "pv" = ( @@ -8530,7 +8530,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "pw" = ( @@ -8542,7 +8542,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/engineering) "px" = ( @@ -8835,7 +8835,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "qb" = ( @@ -9069,7 +9069,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "qA" = ( @@ -9080,7 +9080,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "qB" = ( @@ -9091,7 +9091,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "qC" = ( @@ -11292,7 +11292,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/crew_quarters) "uc" = ( @@ -11946,7 +11946,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "vm" = ( @@ -12172,7 +12172,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/research) "vI" = ( @@ -12469,7 +12469,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/mining) "wk" = ( @@ -13692,7 +13692,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/mining) "yh" = ( @@ -13701,7 +13701,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yi" = ( @@ -13710,7 +13710,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yj" = ( @@ -13721,7 +13721,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yk" = ( @@ -13731,7 +13731,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yl" = ( @@ -13742,7 +13742,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "ym" = ( @@ -13752,7 +13752,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yn" = ( @@ -13761,7 +13761,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yo" = ( @@ -13771,7 +13771,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yp" = ( @@ -13781,7 +13781,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yq" = ( @@ -13790,7 +13790,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yr" = ( @@ -13799,7 +13799,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yt" = ( @@ -13809,7 +13809,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yu" = ( @@ -13819,7 +13819,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yw" = ( @@ -13829,7 +13829,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yz" = ( @@ -13838,7 +13838,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yA" = ( @@ -13848,7 +13848,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yB" = ( @@ -13857,7 +13857,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yC" = ( @@ -13867,7 +13867,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yD" = ( @@ -13878,7 +13878,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "yH" = ( @@ -13889,7 +13889,7 @@ heat_capacity = 1e+006; initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; name = "Cave Floor"; - temperature = 363.9 + initial_temperature = 363.9 }, /area/awaymission/undergroundoutpost45/caves) "zi" = ( diff --git a/_maps/map_files/AsteroidStation/AsteroidStation.dmm b/_maps/map_files/AsteroidStation/AsteroidStation.dmm index 45869b7ebd28..e21554301c0c 100644 --- a/_maps/map_files/AsteroidStation/AsteroidStation.dmm +++ b/_maps/map_files/AsteroidStation/AsteroidStation.dmm @@ -11221,7 +11221,7 @@ icon_state = "0-8" }, /obj/machinery/power/apc{ - areastring = "/area/service hall"; + areastring = "/area/hallway/secondary/service"; dir = 4; name = "Service Hall APC"; pixel_x = 24 @@ -12134,7 +12134,7 @@ "dcK" = ( /obj/machinery/door/airlock/security/glass{ name = "Armoury"; - req_access_txt = "3" + req_access_txt = "1" }, /obj/machinery/door/firedoor/border_only, /obj/machinery/door/firedoor/border_only{ @@ -17322,6 +17322,20 @@ /obj/effect/turf_decal/trimline/green/filled/line/lower, /turf/open/floor/plasteel, /area/hallway/primary/starboard) +"eHJ" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ + dir = 1 + }, +/obj/structure/cable, +/obj/machinery/power/apc{ + areastring = "/area/medical/storage/backroom"; + dir = 2; + name = "Medical Backrooms APC"; + pixel_y = -23 + }, +/obj/effect/turf_decal/trimline/blue/filled/line/lower, +/turf/open/floor/plasteel/white, +/area/medical/storage/backroom) "eHP" = ( /obj/machinery/airalarm{ dir = 1; @@ -17588,25 +17602,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /turf/open/floor/plasteel, /area/clerk) -"eMa" = ( -/obj/structure/disposalpipe/segment{ - dir = 9 - }, -/obj/structure/cable{ - icon_state = "1-8" - }, -/obj/structure/table, -/obj/item/clothing/suit/straight_jacket, -/obj/item/clothing/mask/muzzle, -/obj/machinery/power/apc{ - areastring = "/area/medical/central"; - name = "Medbay Central APC"; - pixel_y = -23 - }, -/obj/structure/cable, -/obj/effect/turf_decal/trimline/blue/filled/line/lower, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) "eMc" = ( /obj/machinery/camera{ c_tag = "Atmospherics - Incinerator"; @@ -18510,6 +18505,25 @@ }, /turf/open/floor/plasteel/white, /area/science/mixing) +"eZo" = ( +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/table, +/obj/item/clothing/suit/straight_jacket, +/obj/item/clothing/mask/muzzle, +/obj/machinery/power/apc{ + areastring = "/area/medical/medbay/central"; + name = "Medbay Central APC"; + pixel_y = -23 + }, +/obj/structure/cable, +/obj/effect/turf_decal/trimline/blue/filled/line/lower, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "eZK" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 @@ -29685,25 +29699,6 @@ }, /turf/open/floor/plasteel/dark, /area/engine/engineering) -"iFS" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/layer_manifold{ - dir = 1 - }, -/obj/machinery/door/firedoor/border_only{ - dir = 1 - }, -/obj/machinery/door/firedoor/border_only, -/obj/machinery/atmospherics/pipe/layer_manifold{ - dir = 1 - }, -/obj/machinery/door/airlock/external{ - name = "Port Docking Bay 2" - }, -/turf/open/floor/plasteel, -/area/hallway/secondary/entry) "iFW" = ( /turf/closed/wall/r_wall, /area/engine/atmos/storage) @@ -43190,20 +43185,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) -"mSH" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ - dir = 1 - }, -/obj/structure/cable, -/obj/machinery/power/apc{ - areastring = "/area/medical/backrooms"; - dir = 2; - name = "Medical Backrooms APC"; - pixel_y = -23 - }, -/obj/effect/turf_decal/trimline/blue/filled/line/lower, -/turf/open/floor/plasteel/white, -/area/medical/storage/backroom) "mSV" = ( /obj/machinery/light, /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ @@ -52376,6 +52357,22 @@ }, /turf/open/floor/plasteel/grimy, /area/ai_monitored/turret_protected/aisat_interior) +"pKn" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 1 + }, +/obj/machinery/door/firedoor/border_only, +/obj/machinery/atmospherics/pipe/layer_manifold{ + dir = 1 + }, +/obj/machinery/door/airlock/external{ + name = "Port Docking Bay 2" + }, +/turf/open/floor/plasteel, +/area/hallway/secondary/entry) "pKr" = ( /obj/effect/turf_decal/siding/wideplating{ dir = 4 @@ -88665,7 +88662,7 @@ hOf eff orl mHY -iFS +pKn aPF acb acb @@ -109267,7 +109264,7 @@ aZJ eQk haa nuJ -eMa +eZo aGU aGU aGU @@ -112611,7 +112608,7 @@ jbG miU brL xrr -mSH +eHJ wOM faF vBA diff --git a/_maps/map_files/DonutStation/DonutStation.dmm b/_maps/map_files/DonutStation/DonutStation.dmm index 889725455573..2895b1bb47eb 100644 --- a/_maps/map_files/DonutStation/DonutStation.dmm +++ b/_maps/map_files/DonutStation/DonutStation.dmm @@ -1456,6 +1456,19 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /turf/open/floor/plating, /area/maintenance/port/aft) +"aFg" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 5 + }, +/obj/structure/cable, +/obj/machinery/power/apc{ + areastring = "/area/chapel/office"; + dir = 8; + name = "Chapel Office APC"; + pixel_x = -25 + }, +/turf/open/floor/plasteel/dark, +/area/chapel/office) "aFm" = ( /obj/structure/particle_accelerator/power_box{ dir = 1; @@ -2447,6 +2460,24 @@ }, /turf/open/floor/plating, /area/maintenance/port/fore) +"bbd" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/door/airlock/maintenance{ + req_one_access_txt = "0" + }, +/obj/machinery/door/firedoor/border_only{ + dir = 1 + }, +/obj/machinery/door/firedoor/border_only, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/effect/turf_decal/trimline/yellow/arrow_cw{ + dir = 8 + }, +/turf/open/floor/plating, +/area/maintenance/aft) "bbg" = ( /turf/closed/wall, /area/medical/medbay/lobby) @@ -3363,6 +3394,15 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) +"bud" = ( +/obj/machinery/camera{ + c_tag = "Fitness Room" + }, +/obj/structure/extinguisher_cabinet{ + pixel_y = 28 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness) "bum" = ( /obj/machinery/computer/cryopod{ pixel_y = 26 @@ -5400,20 +5440,6 @@ }, /turf/open/floor/plasteel/grimy, /area/ai_monitored/turret_protected/aisat_interior) -"ciH" = ( -/obj/machinery/door/airlock/external{ - name = "Security External Airlock"; - req_access_txt = "63" - }, -/obj/machinery/atmospherics/pipe/layer_manifold{ - dir = 4 - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper_target{ - dirx = -2; - diry = 1 - }, -/turf/open/space/basic, -/area/security/main) "ciL" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ dir = 1 @@ -5934,6 +5960,21 @@ /obj/item/bedsheet/prisoner, /turf/open/floor/plasteel, /area/security/brig) +"cuV" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/engiyellow/filled/line/lower{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/atmos/warning/lower/nobottom{ + dir = 4 + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = 27 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "cve" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -6798,6 +6839,18 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) +"cMu" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel/grimy, +/area/chapel/office) "cMw" = ( /obj/machinery/door/airlock/maintenance{ req_one_access_txt = "12;35" @@ -7042,16 +7095,6 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/plating, /area/maintenance/port/aft) -"cRh" = ( -/obj/effect/spawner/structure/window/reinforced/shutter, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/structure/cable{ - icon_state = "0-8" - }, -/turf/open/floor/plating, -/area/bridge) "cRl" = ( /obj/effect/landmark/start/cargo_technician, /turf/open/floor/plasteel, @@ -7790,6 +7833,25 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) +"dis" = ( +/obj/structure/chair/comfy/black{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/effect/landmark/start/chief_medical_officer, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/button/door{ + id = "bridge blast"; + name = "Bridge Blast Door Control"; + pixel_x = 28; + pixel_y = 8; + req_access_txt = "19" + }, +/turf/open/floor/carpet, +/area/bridge) "diJ" = ( /obj/structure/barricade/wooden, /turf/open/floor/plating, @@ -9344,15 +9406,6 @@ /obj/structure/sign/warning/vacuum, /turf/closed/wall/rust, /area/quartermaster/warehouse) -"dRo" = ( -/obj/effect/turf_decal/trimline/darkblue/filled/corner/lower{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/secred/filled/corner/lower{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, -/area/bridge) "dRH" = ( /obj/machinery/light{ dir = 8 @@ -9674,6 +9727,17 @@ /obj/item/extinguisher, /turf/open/floor/plating, /area/maintenance/port/fore) +"dZo" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel/grimy, +/area/chapel/office) "dZx" = ( /obj/structure/closet/secure_closet/security/sec, /turf/open/floor/plasteel/showroomfloor, @@ -10788,15 +10852,6 @@ /obj/effect/turf_decal/trimline/engiyellow/filled/line/lower, /turf/open/floor/plasteel, /area/engine/atmos) -"ezL" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 6 - }, -/turf/open/floor/plasteel/grimy, -/area/chapel/office) "eAb" = ( /obj/machinery/door/airlock{ name = "Unisex Restrooms" @@ -12524,24 +12579,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) -"fjm" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ - dir = 1 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/darkblue/filled/line/lower{ - dir = 1 - }, -/turf/open/floor/plasteel/dark, -/area/bridge) "fjw" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, @@ -12823,16 +12860,6 @@ }, /turf/open/floor/plating, /area/engine/atmos) -"fqT" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 10 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ - dir = 9 - }, -/obj/effect/decal/cleanable/ash/crematorium, -/turf/open/floor/plasteel/dark, -/area/chapel/office) "fra" = ( /obj/machinery/atmospherics/components/unary/thermomachine/freezer/on{ dir = 8; @@ -13153,6 +13180,28 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) +"fvT" = ( +/obj/machinery/door/airlock{ + name = "Crematorium"; + req_access_txt = "27" + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel/dark, +/area/chapel/office) "fvU" = ( /obj/machinery/door/airlock/public/glass{ name = "Primary Tool Storage" @@ -13584,16 +13633,6 @@ }, /turf/open/floor/plasteel, /area/security/checkpoint) -"fGw" = ( -/obj/effect/spawner/structure/window/reinforced/shutter, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/structure/cable{ - icon_state = "0-2" - }, -/turf/open/floor/plating, -/area/bridge) "fGB" = ( /obj/structure/disposalpipe/sorting/mail/flip{ dir = 8; @@ -13860,6 +13899,28 @@ }, /turf/open/floor/plating, /area/quartermaster/warehouse) +"fNj" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/door/airlock/maintenance{ + req_one_access_txt = "12" + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "fNl" = ( /obj/effect/spawner/structure/window, /turf/open/floor/plating, @@ -14078,6 +14139,15 @@ /obj/effect/turf_decal/trimline/green/filled/corner/lower, /turf/open/floor/plasteel, /area/hallway/primary/central) +"fRz" = ( +/obj/effect/turf_decal/trimline/purple/filled/line/lower{ + dir = 8 + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = -28 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "fRQ" = ( /obj/machinery/rnd/production/techfab/department/service, /turf/open/floor/plasteel, @@ -14349,6 +14419,21 @@ "fZd" = ( /turf/open/floor/plasteel, /area/security/processing) +"fZm" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/open/floor/plasteel/dark, +/area/bridge) "fZy" = ( /obj/structure/cable{ icon_state = "2-8" @@ -14607,6 +14692,12 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) +"geT" = ( +/obj/machinery/light/small{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "geZ" = ( /obj/machinery/light{ dir = 1 @@ -15175,16 +15266,6 @@ }, /turf/open/floor/plasteel, /area/security/main) -"gsw" = ( -/obj/effect/spawner/structure/window/reinforced/shutter, -/obj/structure/cable{ - icon_state = "2-8" - }, -/obj/structure/cable{ - icon_state = "0-2" - }, -/turf/open/floor/plating, -/area/bridge) "gsD" = ( /obj/machinery/door/airlock/maintenance{ req_one_access_txt = "12" @@ -15225,6 +15306,16 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) +"gtn" = ( +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/obj/machinery/light_switch{ + pixel_x = -4; + pixel_y = -24 + }, +/turf/open/floor/carpet/black, +/area/crew_quarters/bar) "gtI" = ( /obj/machinery/power/port_gen/pacman, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ @@ -15282,6 +15373,13 @@ }, /turf/open/floor/plasteel/white, /area/medical/sleeper) +"guW" = ( +/obj/structure/chair/stool/bar, +/obj/machinery/light_switch{ + pixel_x = 24 + }, +/turf/open/floor/wood, +/area/crew_quarters/kitchen) "gvo" = ( /obj/effect/turf_decal/stripes/line, /turf/open/floor/plating/airless, @@ -15476,6 +15574,19 @@ }, /turf/open/floor/plating, /area/maintenance/port) +"gzX" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, +/obj/effect/turf_decal/trimline/engiyellow/filled/line/lower{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/atmos/warning/lower/nobottom{ + dir = 8 + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = -28 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "gAh" = ( /obj/effect/turf_decal/stripes/corner{ dir = 8 @@ -16095,6 +16206,21 @@ }, /turf/open/floor/plasteel/white, /area/medical/genetics) +"gQN" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/trimline/blue/filled/line/lower{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = -28 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "gQT" = ( /obj/machinery/shower{ dir = 4 @@ -16191,6 +16317,10 @@ }, /turf/open/floor/plasteel/white, /area/medical/sleeper) +"gTN" = ( +/obj/machinery/light/small, +/turf/open/floor/plating, +/area/maintenance/aft) "gUe" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, @@ -16251,6 +16381,19 @@ "gVe" = ( /turf/open/floor/plasteel/dark, /area/engine/gravity_generator) +"gVx" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/effect/turf_decal/trimline/blue/filled/line/lower{ + dir = 8 + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = -28 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "gVz" = ( /obj/structure/rack, /obj/item/stack/sheet/metal/fifty, @@ -17964,6 +18107,17 @@ /obj/machinery/vending/clothing, /turf/open/floor/plasteel, /area/crew_quarters/dorms) +"hJN" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel/grimy, +/area/chapel/office) "hJO" = ( /obj/machinery/computer/shuttle/labor{ dir = 1; @@ -18418,18 +18572,6 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) -"hWN" = ( -/obj/structure/cable/yellow{ - icon_state = "1-2" - }, -/obj/effect/turf_decal/trimline/engiyellow/filled/corner/lower{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/secred/filled/corner/lower{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/engineering) "hWV" = ( /obj/machinery/camera{ c_tag = "Research - Main 2"; @@ -18789,16 +18931,6 @@ }, /turf/open/floor/carpet, /area/library) -"ifd" = ( -/obj/machinery/camera{ - c_tag = "Hallway - Central Southeast 2"; - dir = 4 - }, -/obj/effect/turf_decal/trimline/secred/filled/line/lower{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/central) "ifi" = ( /obj/effect/turf_decal/stripes/corner, /turf/open/floor/plating, @@ -20527,6 +20659,19 @@ }, /turf/open/floor/grass, /area/medical/genetics) +"iWP" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 9 + }, +/obj/effect/decal/cleanable/ash/crematorium, +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/open/floor/plasteel/dark, +/area/chapel/office) "iXh" = ( /obj/structure/closet/crate{ name = "Surplus Toxins Supplies" @@ -21942,6 +22087,21 @@ }, /turf/open/floor/plasteel/showroomfloor, /area/security/warden) +"jBZ" = ( +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, +/obj/effect/turf_decal/trimline/engiyellow/filled/corner/lower{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/secred/filled/corner/lower{ + dir = 8 + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = -28 + }, +/turf/open/floor/plasteel, +/area/engine/engineering) "jCf" = ( /obj/effect/turf_decal/trimline/engiyellow/filled/line/lower{ dir = 4 @@ -22096,6 +22256,19 @@ /obj/structure/table/wood, /turf/open/floor/carpet, /area/library) +"jEs" = ( +/obj/effect/turf_decal/trimline/engiyellow/filled/corner/lower, +/obj/effect/turf_decal/trimline/atmos/warning/lower/corner/flip{ + dir = 2 + }, +/obj/effect/turf_decal/trimline/green/filled/corner/lower{ + dir = 1 + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = -28 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "jEP" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ dir = 4 @@ -22210,6 +22383,15 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating, /area/maintenance/disposal) +"jHI" = ( +/obj/structure/chair{ + dir = 1 + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = -28 + }, +/turf/open/floor/wood, +/area/hallway/primary/central) "jHS" = ( /obj/machinery/atmospherics/pipe/simple/yellow/visible, /obj/effect/turf_decal/trimline/blue/filled/corner/lower, @@ -22776,6 +22958,14 @@ /obj/effect/spawner/lootdrop/maintenance, /turf/closed/wall, /area/maintenance/fore) +"jRs" = ( +/obj/effect/turf_decal/trimline/darkblue/filled/line/lower, +/obj/machinery/door/poddoor/preopen{ + id = "bridge blast"; + name = "bridge blast door" + }, +/turf/open/floor/plasteel/dark, +/area/bridge) "jRC" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ dir = 4 @@ -23165,14 +23355,6 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, /turf/open/floor/carpet, /area/crew_quarters/theatre) -"jZE" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, -/turf/open/floor/plasteel/grimy, -/area/chapel/office) "jZF" = ( /obj/machinery/atmospherics/components/binary/pump{ dir = 1; @@ -23727,11 +23909,6 @@ /obj/machinery/door/firedoor/border_only, /turf/open/floor/plating, /area/maintenance/port/aft) -"kkT" = ( -/obj/effect/decal/cleanable/blood/old, -/obj/item/tank/internals/emergency_oxygen/empty, -/turf/open/floor/plating/asteroid/airless, -/area/space/nearstation) "kkZ" = ( /turf/open/floor/plasteel, /area/escapepodbay) @@ -24067,6 +24244,24 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /turf/open/floor/plating, /area/ai_monitored/storage/satellite) +"ktH" = ( +/obj/effect/turf_decal/trimline/darkblue/filled/corner/lower{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/secred/filled/corner/lower{ + dir = 4 + }, +/obj/machinery/power/apc/highcap/five_k{ + areastring = "/area/bridge"; + dir = 1; + name = "Bridge APC"; + pixel_y = 23 + }, +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/floor/plasteel/dark, +/area/bridge) "ktL" = ( /obj/structure/cable{ icon_state = "1-4" @@ -24233,6 +24428,12 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) +"kze" = ( +/obj/structure/extinguisher_cabinet{ + pixel_x = 28 + }, +/turf/open/floor/plasteel, +/area/hallway/secondary/exit/departure_lounge) "kzy" = ( /obj/structure/chair, /obj/effect/landmark/start/assistant, @@ -24487,6 +24688,18 @@ /obj/item/gps, /turf/open/floor/plating, /area/engine/engineering) +"kJb" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 6 + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/turf/open/floor/plasteel/grimy, +/area/chapel/office) "kJg" = ( /obj/effect/spawner/structure/window/reinforced/shutter, /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, @@ -24523,19 +24736,17 @@ /area/maintenance/fore) "kLb" = ( /obj/structure/table/glass, -/obj/item/clothing/gloves/color/latex, -/obj/item/reagent_containers/spray/cleaner, /obj/machinery/camera{ c_tag = "Security - Medical Room"; dir = 1; network = list("ss13","Security") }, -/obj/item/reagent_containers/glass/bottle/epinephrine, -/obj/item/reagent_containers/glass/bottle/charcoal, -/obj/item/reagent_containers/syringe, /obj/effect/turf_decal/trimline/blue/filled/line/lower{ dir = 10 }, +/obj/machinery/computer/med_data/laptop{ + dir = 1 + }, /turf/open/floor/plasteel/white, /area/security/brig) "kLS" = ( @@ -24908,12 +25119,6 @@ /obj/item/reagent_containers/food/drinks/soda_cans/grey_bull, /turf/open/floor/carpet, /area/hallway/secondary/entry) -"kSi" = ( -/obj/effect/decal/remains/human, -/obj/effect/decal/cleanable/blood/old, -/obj/item/pickaxe, -/turf/open/floor/plating/asteroid/airless, -/area/space/nearstation) "kSm" = ( /obj/structure/cable{ icon_state = "1-2" @@ -25018,10 +25223,6 @@ }, /turf/open/floor/plasteel/grimy, /area/tcommsat/computer) -"kVo" = ( -/obj/effect/decal/cleanable/blood/old, -/turf/open/floor/plating/asteroid/airless, -/area/space/nearstation) "kVw" = ( /obj/machinery/telecomms/bus/preset_two, /turf/open/floor/circuit/telecomms/mainframe, @@ -26506,6 +26707,12 @@ dir = 8 }, /area/chapel/main) +"lDg" = ( +/obj/structure/extinguisher_cabinet{ + pixel_x = -28 + }, +/turf/open/floor/plasteel/grimy, +/area/tcommsat/computer) "lDG" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 4 @@ -27025,6 +27232,13 @@ }, /turf/open/floor/plasteel/white, /area/medical/sleeper) +"lNv" = ( +/obj/structure/closet/secure_closet/bartender, +/obj/item/stack/sheet/glass/fifty, +/obj/item/stack/sheet/metal/fifty, +/obj/item/stack/cable_coil, +/turf/open/floor/wood, +/area/crew_quarters/bar) "lNJ" = ( /turf/open/floor/plasteel/airless{ icon_state = "damaged2" @@ -27301,10 +27515,6 @@ /obj/item/kirbyplants/random, /turf/open/floor/wood, /area/hallway/primary/central) -"lSG" = ( -/obj/effect/decal/cleanable/blood/gibs/old, -/turf/open/floor/plating/asteroid/airless, -/area/space/nearstation) "lSS" = ( /obj/structure/disposalpipe/sorting/mail/flip{ dir = 1; @@ -27457,16 +27667,6 @@ /obj/effect/turf_decal/trimline/green/filled/line/lower, /turf/open/floor/plasteel/white, /area/medical/virology) -"lWE" = ( -/obj/effect/turf_decal/trimline/engiyellow/filled/corner/lower, -/obj/effect/turf_decal/trimline/atmos/warning/lower/corner/flip{ - dir = 2 - }, -/obj/effect/turf_decal/trimline/green/filled/corner/lower{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/central) "lWG" = ( /obj/structure/table, /obj/item/gun/energy/e_gun/dragnet, @@ -27542,6 +27742,12 @@ /obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/aft) +"lYe" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ + dir = 4 + }, +/turf/open/floor/plasteel/grimy, +/area/chapel/office) "lYB" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/structure/extinguisher_cabinet{ @@ -27903,6 +28109,16 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) +"mhp" = ( +/obj/structure/table/wood, +/obj/machinery/light{ + dir = 1 + }, +/obj/structure/extinguisher_cabinet{ + pixel_y = 28 + }, +/turf/open/floor/carpet, +/area/crew_quarters/cryopods) "mhM" = ( /obj/structure/cable{ icon_state = "4-8" @@ -29236,18 +29452,6 @@ /obj/effect/decal/cleanable/blood/old, /turf/open/floor/plasteel/dark, /area/quartermaster/warehouse) -"mKD" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/engiyellow/filled/line/lower{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/atmos/warning/lower/nobottom{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "mKK" = ( /obj/machinery/light_switch{ pixel_x = 24 @@ -30616,6 +30820,20 @@ }, /turf/open/floor/plasteel, /area/security/prison) +"nlF" = ( +/obj/machinery/door/airlock/external{ + name = "Security External Airlock"; + req_access_txt = "63" + }, +/obj/machinery/atmospherics/pipe/layer_manifold{ + dir = 4 + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper_target{ + dirx = -2; + diry = 1 + }, +/turf/open/floor/plating, +/area/security/main) "nlJ" = ( /obj/structure/frame/machine, /obj/effect/turf_decal/stripes/line{ @@ -30811,25 +31029,6 @@ }, /turf/open/floor/plasteel/white, /area/science/lab) -"nrb" = ( -/obj/machinery/door/airlock{ - name = "Crematorium"; - req_access_txt = "27" - }, -/obj/machinery/door/firedoor/border_only{ - dir = 4 - }, -/obj/machinery/door/firedoor/border_only{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, -/area/chapel/office) "nrc" = ( /obj/structure/closet/toolcloset, /turf/open/floor/plasteel, @@ -31796,18 +31995,6 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) -"nLN" = ( -/obj/structure/chair/comfy/black{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/effect/landmark/start/chief_medical_officer, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/carpet, -/area/bridge) "nLR" = ( /obj/item/assembly/signaler{ pixel_y = 8 @@ -31960,6 +32147,20 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) +"nOt" = ( +/obj/effect/spawner/structure/window/reinforced/shutter, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/machinery/door/poddoor/preopen{ + id = "bridge blast"; + name = "bridge blast door" + }, +/turf/open/floor/plating, +/area/bridge) "nOB" = ( /obj/machinery/door/firedoor/border_only{ dir = 8 @@ -32033,6 +32234,13 @@ }, /turf/open/floor/plasteel/dark, /area/bridge) +"nQN" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/aft) "nQO" = ( /obj/machinery/computer/security/mining, /obj/effect/turf_decal/trimline/brown/filled/line/lower{ @@ -32666,10 +32874,6 @@ /obj/effect/spawner/structure/window/reinforced/shutter, /turf/open/floor/plating, /area/engine/engineering) -"odp" = ( -/obj/structure/closet/secure_closet/bartender, -/turf/open/floor/wood, -/area/crew_quarters/bar) "ody" = ( /obj/effect/turf_decal/trimline/purple/filled/corner/lower{ dir = 8 @@ -32774,6 +32978,12 @@ }, /turf/open/floor/plasteel, /area/science/mixing) +"ofp" = ( +/obj/structure/extinguisher_cabinet{ + pixel_x = -28 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "ofr" = ( /obj/effect/turf_decal/pool, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ @@ -33972,6 +34182,28 @@ "oJj" = ( /turf/open/floor/plating/burnt, /area/maintenance/starboard) +"oJI" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/darkblue/filled/line/lower{ + dir = 1 + }, +/obj/machinery/door/poddoor/preopen{ + id = "bridge blast"; + name = "bridge blast door" + }, +/turf/open/floor/plasteel/dark, +/area/bridge) "oJL" = ( /obj/structure/plasticflaps/opaque, /obj/machinery/navbeacon{ @@ -34314,11 +34546,6 @@ }, /turf/open/floor/plating, /area/engine/atmos) -"oRp" = ( -/obj/effect/decal/cleanable/blood/old, -/obj/effect/decal/cleanable/blood/gibs/old, -/turf/open/floor/plating/asteroid/airless, -/area/space/nearstation) "oRq" = ( /obj/machinery/door/firedoor/border_only{ dir = 1 @@ -34477,6 +34704,20 @@ /obj/effect/landmark/start/detective, /turf/open/floor/carpet, /area/security/detectives_office) +"oVz" = ( +/obj/effect/spawner/structure/window/reinforced/shutter, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/machinery/door/poddoor/preopen{ + id = "bridge blast"; + name = "bridge blast door" + }, +/turf/open/floor/plating, +/area/bridge) "oVN" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 4 @@ -34934,12 +35175,6 @@ }, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) -"pjA" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 5 - }, -/turf/open/floor/plasteel/dark, -/area/chapel/office) "pjJ" = ( /obj/machinery/computer/med_data{ dir = 8; @@ -35353,12 +35588,6 @@ }, /turf/open/floor/plasteel, /area/security/brig) -"pqV" = ( -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/turf/open/floor/carpet/black, -/area/crew_quarters/bar) "prf" = ( /obj/effect/landmark/event_spawn, /turf/open/floor/plasteel, @@ -36181,6 +36410,20 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) +"pIm" = ( +/obj/effect/spawner/structure/window/reinforced/shutter, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/machinery/door/poddoor/preopen{ + id = "bridge blast"; + name = "bridge blast door" + }, +/turf/open/floor/plating, +/area/bridge) "pIu" = ( /obj/machinery/portable_atmospherics/scrubber, /obj/effect/turf_decal/bot, @@ -36260,6 +36503,12 @@ }, /turf/closed/wall/r_wall, /area/engine/atmos) +"pKp" = ( +/obj/structure/extinguisher_cabinet{ + pixel_x = 27 + }, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) "pKG" = ( /obj/machinery/light, /obj/machinery/firealarm{ @@ -36289,12 +36538,6 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) -"pLB" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/open/floor/plasteel/grimy, -/area/chapel/office) "pLS" = ( /obj/machinery/door/airlock/virology/glass{ name = "Monkey Pen"; @@ -36510,22 +36753,6 @@ }, /turf/closed/wall/r_wall, /area/security/prison) -"pOJ" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/door/airlock/maintenance{ - req_one_access_txt = "12" - }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/port/aft) "pOM" = ( /obj/structure/cable{ icon_state = "4-8" @@ -36770,17 +36997,6 @@ }, /turf/open/floor/plasteel, /area/security/brig) -"pTc" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "2-8" - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ - dir = 4 - }, -/turf/open/floor/plasteel/grimy, -/area/chapel/office) "pTe" = ( /obj/machinery/mineral/ore_redemption, /obj/machinery/door/firedoor/border_only{ @@ -37160,6 +37376,20 @@ }, /turf/open/floor/plating, /area/maintenance/central) +"qbo" = ( +/obj/effect/spawner/structure/window/reinforced/shutter, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/machinery/door/poddoor/preopen{ + id = "bridge blast"; + name = "bridge blast door" + }, +/turf/open/floor/plating, +/area/bridge) "qbq" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -37256,27 +37486,6 @@ }, /turf/open/space/basic, /area/solar/starboard/fore) -"qdY" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, -/obj/machinery/door/airlock/maintenance{ - req_one_access_txt = "12" - }, -/obj/machinery/door/firedoor/border_only{ - dir = 1 - }, -/obj/machinery/door/firedoor/border_only, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/effect/mapping_helpers/airlock/unres{ - icon_state = "airlock_unres_helper" - }, -/obj/effect/turf_decal/trimline/yellow/arrow_cw{ - dir = 8 - }, -/turf/open/floor/plating, -/area/maintenance/aft) "qej" = ( /obj/structure/cable{ icon_state = "2-4" @@ -38318,15 +38527,6 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) -"qzN" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/open/floor/plasteel/grimy, -/area/chapel/office) "qzY" = ( /obj/machinery/door/firedoor/border_only{ dir = 4 @@ -38919,18 +39119,6 @@ }, /turf/open/floor/wood, /area/crew_quarters/heads/hop) -"qQt" = ( -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/trimline/blue/filled/line/lower{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) "qQQ" = ( /obj/effect/landmark/blobstart, /turf/open/floor/plating, @@ -39229,6 +39417,15 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) +"qXd" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = -28 + }, +/turf/open/floor/plasteel/showroomfloor, +/area/crew_quarters/kitchen) "qXg" = ( /obj/machinery/door/airlock/external{ name = "Solar Maintenance"; @@ -40597,12 +40794,6 @@ /obj/item/toy/talking/AI, /turf/open/floor/plasteel/grimy, /area/tcommsat/computer) -"rDA" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/plasteel/showroomfloor, -/area/crew_quarters/kitchen) "rDI" = ( /obj/machinery/door/window/southleft{ name = "Court Cell"; @@ -41343,6 +41534,16 @@ }, /turf/open/floor/plasteel/white, /area/science/research) +"rUJ" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ + dir = 1 + }, +/obj/machinery/door/poddoor/preopen{ + id = "bridge blast"; + name = "bridge blast door" + }, +/turf/open/floor/plasteel/dark, +/area/bridge) "rUM" = ( /obj/machinery/firealarm{ dir = 4; @@ -42507,6 +42708,12 @@ "sxb" = ( /turf/open/floor/plasteel/dark/telecomms, /area/ai_monitored/turret_protected/ai) +"sxt" = ( +/obj/structure/extinguisher_cabinet{ + pixel_x = -28 + }, +/turf/open/floor/carpet, +/area/crew_quarters/theatre) "sxx" = ( /obj/effect/turf_decal/trimline/darkblue/filled/line/lower{ dir = 1 @@ -43452,6 +43659,15 @@ }, /turf/open/floor/plasteel, /area/engine/gravity_generator) +"sOV" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = -28 + }, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) "sOX" = ( /obj/structure/cable{ icon_state = "2-8" @@ -44205,6 +44421,12 @@ }, /turf/open/floor/plasteel/dark/telecomms, /area/ai_monitored/turret_protected/ai) +"tgX" = ( +/obj/machinery/light/small{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/aft) "tha" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 6 @@ -44339,13 +44561,6 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, /area/quartermaster/warehouse) -"tki" = ( -/obj/effect/spawner/structure/window/reinforced/shutter, -/obj/structure/cable{ - icon_state = "0-4" - }, -/turf/open/floor/plating, -/area/bridge) "tkl" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel/showroomfloor, @@ -45299,12 +45514,6 @@ initial_gas_mix = "n2o=1000;TEMP=293.15" }, /area/engine/atmos) -"tDM" = ( -/obj/machinery/camera{ - c_tag = "Fitness Room" - }, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) "tDQ" = ( /obj/machinery/door/airlock/maintenance_hatch, /obj/effect/mapping_helpers/airlock/abandoned, @@ -45481,15 +45690,6 @@ }, /turf/open/floor/engine, /area/maintenance/disposal/incinerator) -"tHu" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ - dir = 4 - }, -/turf/open/floor/plasteel/grimy, -/area/chapel/office) "tHB" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ dir = 4 @@ -45712,6 +45912,19 @@ /obj/effect/turf_decal/trimline/green, /turf/open/floor/plasteel/dark, /area/engine/atmos) +"tLr" = ( +/obj/machinery/camera{ + c_tag = "Hallway - Central Southeast 2"; + dir = 4 + }, +/obj/effect/turf_decal/trimline/secred/filled/line/lower{ + dir = 8 + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = -28 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "tLB" = ( /obj/machinery/airalarm{ pixel_y = 24 @@ -47774,13 +47987,6 @@ }, /turf/open/floor/plasteel/white, /area/medical/virology) -"uHf" = ( -/obj/structure/table/wood, -/obj/machinery/light{ - dir = 1 - }, -/turf/open/floor/carpet, -/area/crew_quarters/cryopods) "uHz" = ( /obj/structure/lattice, /obj/structure/lattice, @@ -48743,12 +48949,6 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, /turf/open/floor/plasteel/stairs/goon/wood_stairs_middle, /area/library) -"vci" = ( -/obj/structure/chair{ - dir = 1 - }, -/turf/open/floor/wood, -/area/hallway/primary/central) "vcr" = ( /obj/structure/cable{ icon_state = "1-2" @@ -48916,10 +49116,14 @@ /area/clerk) "veY" = ( /obj/structure/table/glass, -/obj/machinery/computer/med_data/laptop, /obj/effect/turf_decal/trimline/blue/filled/line/lower{ dir = 8 }, +/obj/item/reagent_containers/spray/cleaner, +/obj/item/clothing/gloves/color/latex, +/obj/item/reagent_containers/syringe, +/obj/item/reagent_containers/glass/bottle/charcoal, +/obj/item/reagent_containers/glass/bottle/epinephrine, /turf/open/floor/plasteel/white, /area/security/brig) "vfa" = ( @@ -50249,16 +50453,6 @@ }, /turf/open/space/basic, /area/engine/atmos) -"vMQ" = ( -/obj/effect/spawner/structure/window/reinforced/shutter, -/obj/structure/cable{ - icon_state = "1-8" - }, -/obj/structure/cable{ - icon_state = "0-8" - }, -/turf/open/floor/plating, -/area/bridge) "vNc" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ @@ -51491,12 +51685,6 @@ }, /turf/open/floor/plasteel, /area/science/research) -"wph" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ - dir = 1 - }, -/turf/open/floor/plasteel/dark, -/area/bridge) "wpm" = ( /obj/effect/turf_decal/trimline/engiyellow/filled/corner/lower, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ @@ -51804,18 +51992,6 @@ }, /turf/open/floor/wood, /area/tcommsat/computer) -"wvu" = ( -/obj/machinery/power/apc{ - areastring = "/area/chapel/office"; - dir = 8; - name = "Chapel Office APC"; - pixel_x = -25 - }, -/obj/structure/cable{ - icon_state = "0-4" - }, -/turf/open/floor/plasteel/grimy, -/area/chapel/office) "wvA" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -52107,6 +52283,11 @@ }, /turf/open/floor/plating, /area/quartermaster/storage) +"wzV" = ( +/obj/effect/turf_decal/sand/plating, +/mob/living/simple_animal/hostile/asteroid/hivelord, +/turf/open/floor/plating/airless, +/area/space/nearstation) "wAa" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -54024,12 +54205,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/wood, /area/crew_quarters/kitchen) -"xnB" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "xnG" = ( /obj/machinery/door/airlock/maintenance{ req_one_access_txt = "12" @@ -55340,6 +55515,17 @@ }, /turf/open/floor/plating, /area/maintenance/port/fore) +"xPn" = ( +/obj/effect/spawner/structure/window/reinforced/shutter, +/obj/structure/cable{ + icon_state = "0-4" + }, +/obj/machinery/door/poddoor/preopen{ + id = "bridge blast"; + name = "bridge blast door" + }, +/turf/open/floor/plating, +/area/bridge) "xPu" = ( /obj/structure/door_assembly/door_assembly_eng{ anchored = 1 @@ -70583,9 +70769,9 @@ ylr ylr ylr ylr -ylr -ylr -ylr +dJY +dJY +dJY ylr ylr ylr @@ -70839,10 +71025,10 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY ylr ylr ylr @@ -71095,12 +71281,12 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -71352,12 +71538,12 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +aCv +dJY ylr ylr ylr @@ -71609,12 +71795,12 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -71866,12 +72052,12 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -72123,12 +72309,12 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +aCv +aCv +dJY +dJY +dJY ylr ylr ylr @@ -72380,12 +72566,12 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +aCv +dJY ylr ylr ylr @@ -72637,11 +72823,11 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -72896,9 +73082,9 @@ ylr ylr ylr ylr -ylr -ylr -ylr +dJY +dJY +dJY ylr ylr ylr @@ -73154,7 +73340,7 @@ ylr ylr ylr ylr -ylr +dJY ylr ylr ylr @@ -73675,7 +73861,7 @@ ylr ylr ylr ylr -ylr +dJY ylr ylr ylr @@ -73931,9 +74117,9 @@ ylr ylr ylr ylr -ylr -ylr -ylr +dJY +dJY +dJY ylr ylr ylr @@ -74188,9 +74374,9 @@ ylr ylr ylr ylr -ylr -ylr -ylr +dJY +dJY +dJY ylr ylr ylr @@ -74446,8 +74632,8 @@ ylr ylr ylr ylr -ylr -ylr +dJY +dJY ylr ylr ylr @@ -77802,9 +77988,9 @@ ylr ylr ylr ylr -dJY -dJY -dJY +ylr +ylr +ylr ylr ylr ylr @@ -78058,10 +78244,10 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr ylr ylr ylr @@ -78314,12 +78500,12 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -78571,12 +78757,12 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -aCv -dJY +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -78828,12 +79014,12 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -79085,12 +79271,12 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -79342,12 +79528,12 @@ ylr ylr ylr ylr -dJY -aCv -aCv -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -79599,12 +79785,12 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -aCv -dJY +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -79756,7 +79942,7 @@ uKU nsl och tzz -bPj +gVx bPj iLK rIY @@ -79856,11 +80042,11 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -80115,9 +80301,9 @@ ylr ylr ylr ylr -dJY -dJY -dJY +ylr +ylr +ylr ylr ylr ylr @@ -80361,6 +80547,7 @@ ylr ylr ylr ylr +bIB ylr ylr ylr @@ -80373,7 +80560,6 @@ ylr ylr ylr ylr -dJY ylr ylr ylr @@ -81119,8 +81305,8 @@ ylr ylr ylr ylr -ylr -ylr +dJY +dJY ylr ylr ylr @@ -81375,10 +81561,10 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY ylr ylr ylr @@ -81399,7 +81585,7 @@ ylr ylr ylr ylr -bIB +ylr ylr ylr ylr @@ -81632,11 +81818,11 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -81888,6 +82074,13 @@ ylr ylr ylr ylr +dJY +dJY +dJY +aCv +dJY +dJY +dJY ylr ylr ylr @@ -81920,13 +82113,6 @@ ylr ylr ylr ylr -dJY -ylr -ylr -ylr -ylr -ylr -ylr ylr ylr "} @@ -82145,6 +82331,13 @@ ylr ylr ylr ylr +dJY +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -82176,13 +82369,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -ylr -ylr -ylr -ylr ylr ylr ylr @@ -82402,6 +82588,12 @@ ylr ylr ylr ylr +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -82424,18 +82616,12 @@ ylr ylr ylr ylr -dJY -dJY -ylr ylr ylr ylr ylr ylr ylr -dJY -dJY -dJY ylr ylr ylr @@ -82661,6 +82847,12 @@ ylr ylr ylr ylr +dJY +dJY +dJY +ylr +ylr +ylr ylr ylr ylr @@ -82680,10 +82872,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY ylr ylr ylr @@ -82691,8 +82879,6 @@ ylr ylr ylr ylr -dJY -dJY ylr ylr ylr @@ -82937,11 +83123,11 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -83193,13 +83379,13 @@ ylr ylr ylr ylr -dJY -dJY -dJY -aCv -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -83300,7 +83486,7 @@ osy ryA nrw osy -tDM +bud ofr xpa ubP @@ -83450,13 +83636,13 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -83602,7 +83788,7 @@ kBq fME oOW lSS -qQt +gQN uCF opl cvE @@ -83707,12 +83893,12 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -83966,9 +84152,9 @@ ylr ylr ylr ylr -dJY -dJY -dJY +ylr +ylr +ylr ylr ylr ylr @@ -84058,7 +84244,7 @@ fNq fNq vpc oxB -fNq +kze fNq fNq nHw @@ -85430,7 +85616,7 @@ tIb fOG fOG kTi -pOJ +fNj kTi kTi xkg @@ -85492,7 +85678,7 @@ ylr ylr ylr ylr -ylr +bIB ylr ylr ylr @@ -85752,12 +85938,12 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -86006,23 +86192,23 @@ ylr ylr ylr ylr -ylr -bIB -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr ylr +bIB ylr ylr ylr @@ -86261,14 +86447,14 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY dJY dJY dJY @@ -86445,7 +86631,7 @@ gxy lML fmF fGO -odp +lNv ixS gxy qmO @@ -86516,13 +86702,11 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +dJY dJY dJY dJY @@ -86539,7 +86723,9 @@ ylr ylr ylr ylr -bIB +ylr +ylr +ylr ylr ylr ylr @@ -86679,7 +86865,7 @@ raj aux vVU vVU -raj +fRz ana dGE vxr @@ -86709,7 +86895,7 @@ gxy gxy fOG uPG -uPG +sxt egN eDe jlD @@ -86772,12 +86958,11 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +dJY dJY dJY dJY @@ -86812,27 +86997,28 @@ ylr ylr ylr ylr -"} -(119,1,1) = {" -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr +ylr +"} +(119,1,1) = {" +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -87029,13 +87215,11 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -dJY -dJY dJY +aCv +aCv +aCv +aCv dJY dJY dJY @@ -87069,6 +87253,8 @@ ylr ylr ylr ylr +ylr +ylr "} (120,1,1) = {" ylr @@ -87218,7 +87404,7 @@ qTz ghI pOm pOm -pqV +gtn gxy gxy fOG @@ -87285,20 +87471,17 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -dJY -dJY dJY dJY dJY +aCv +aCv dJY dJY dJY dJY dJY +aCv dJY dJY dJY @@ -87326,6 +87509,9 @@ ylr ylr ylr ylr +ylr +ylr +ylr "} (121,1,1) = {" ylr @@ -87494,7 +87680,7 @@ rjP iIJ hCk kKP -kKP +lDg kKP ufH hGc @@ -87542,14 +87728,11 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr +dJY dJY aCv -aCv -aCv +dJY +dJY aCv dJY dJY @@ -87583,6 +87766,9 @@ ylr ylr ylr ylr +ylr +ylr +ylr "} (122,1,1) = {" ylr @@ -87799,20 +87985,18 @@ ylr ylr ylr ylr -ylr -ylr -ylr dJY dJY dJY -aCv -aCv dJY dJY dJY dJY dJY -aCv +dJY +dJY +dJY +dJY dJY dJY dJY @@ -87840,6 +88024,8 @@ ylr ylr ylr ylr +ylr +ylr "} (123,1,1) = {" ylr @@ -88055,26 +88241,24 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -dJY -dJY -aCv -dJY -dJY -aCv -dJY dJY dJY dJY dJY dJY dJY +yhE +yhE +qGw dJY dJY dJY +qGw +yhE +qGw +yhE +yhE +yhE dJY dJY dJY @@ -88097,6 +88281,8 @@ ylr ylr ylr ylr +ylr +ylr "} (124,1,1) = {" ylr @@ -88312,20 +88498,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY dJY dJY dJY @@ -88333,6 +88505,17 @@ dJY dJY dJY dJY +fON +fON +fON +fON +fON +fON +fON +fON +fON +uSS +yhE dJY dJY dJY @@ -88354,6 +88537,9 @@ ylr ylr ylr ylr +ylr +ylr +ylr "} (125,1,1) = {" ylr @@ -88569,26 +88755,23 @@ ylr ylr ylr ylr -ylr -ylr -ylr -dJY dJY dJY dJY dJY dJY -yhE -yhE -qGw -dJY -dJY dJY qGw -yhE -qGw -yhE -yhE +fON +fON +fON +fON +fON +fON +fON +fON +fON +fON yhE dJY dJY @@ -88611,6 +88794,9 @@ ylr ylr ylr ylr +ylr +ylr +ylr "} (126,1,1) = {" ylr @@ -88699,7 +88885,7 @@ fZc kLa lLh wJB -uHf +mhp wUs bpi wUs @@ -88826,9 +89012,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr dJY dJY dJY @@ -88845,8 +89028,8 @@ fON fON fON fON -uSS -yhE +fON +dJY dJY dJY dJY @@ -88854,10 +89037,13 @@ dJY ylr ylr ylr -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -89027,10 +89213,10 @@ uLk uLk ykw lpn -rSz -rSz -rSz -rSz +akr +akr +akr +akr iVj akr myW @@ -89083,14 +89269,11 @@ ylr ylr ylr ylr -ylr -ylr -ylr -dJY dJY dJY dJY dJY +aCv dJY qGw fON @@ -89103,7 +89286,7 @@ fON fON fON fON -yhE +dJY dJY dJY dJY @@ -89111,9 +89294,12 @@ dJY ylr ylr ylr -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -89275,7 +89461,7 @@ uLk dZz kVY qoy -dZz +guW uLk kVY uLk @@ -89340,9 +89526,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr dJY dJY dJY @@ -89360,74 +89543,77 @@ fON fON fON fON +qGw dJY dJY dJY dJY -dJY -ylr -ylr -ylr -ylr -ylr -dJY -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -"} -(129,1,1) = {" -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +"} +(129,1,1) = {" +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -89541,7 +89727,7 @@ mew mew cjV mUP -rDA +qXd mPL jWl pwz @@ -89597,16 +89783,13 @@ ylr ylr ylr ylr -ylr -ylr -ylr dJY dJY dJY dJY -aCv dJY -qGw +dJY +dJY fON fON fON @@ -89617,11 +89800,14 @@ fON fON fON fON +qGw dJY dJY dJY -dJY -dJY +qxi +qxi +ylr +ylr ylr ylr ylr @@ -89854,9 +90040,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr dJY dJY dJY @@ -89874,11 +90057,14 @@ fON fON fON fON -qGw -dJY dJY dJY dJY +qxi +qxi +qxi +ylr +ylr ylr ylr ylr @@ -90111,9 +90297,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr dJY dJY dJY @@ -90131,12 +90314,15 @@ fON fON fON fON -qGw -dJY +yhE dJY dJY qxi qxi +dJY +ylr +ylr +ylr ylr ylr ylr @@ -90369,9 +90555,6 @@ ylr ylr ylr ylr -ylr -ylr -dJY dJY dJY dJY @@ -90388,21 +90571,24 @@ fON fON fON fON -dJY -dJY +yhE dJY qxi qxi qxi +dJY +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr ylr ylr -bIB ylr -dJY -dJY ylr ylr ylr @@ -90626,15 +90812,12 @@ ylr ylr ylr ylr -ylr -ylr -dJY -dJY dJY dJY dJY dJY dJY +qGw fON fON fON @@ -90645,21 +90828,24 @@ fON fON fON fON -yhE dJY dJY qxi qxi dJY +dJY +dJY +ylr +ylr +ylr +ylr +ylr ylr ylr ylr ylr ylr ylr -dJY -dJY -dJY ylr ylr ylr @@ -90883,30 +91069,28 @@ ylr ylr ylr ylr -ylr -ylr -ylr dJY dJY dJY dJY dJY +qGw +yhE +dJY +qGw +dJY dJY -fON -fON -fON -fON -fON -fON -fON -fON -fON -fON +yhE yhE dJY +dJY +qGw +dJY qxi qxi -qxi +dJY +dJY +dJY dJY ylr ylr @@ -90914,10 +91098,12 @@ ylr ylr ylr ylr -dJY -dJY -aCv -dJY +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -91071,7 +91257,7 @@ rIh gFE dfT nWv -lWE +jEs rSz uix uix @@ -91096,96 +91282,96 @@ eMS vDp bHj xSu -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -dJY -dJY -dJY -dJY -dJY -qGw -fON -fON -fON -fON -fON -fON -fON -fON -fON -fON -dJY -dJY -qxi -qxi -dJY -dJY -dJY -ylr -ylr -ylr -ylr -ylr -ylr -dJY -dJY -dJY -ylr -ylr -ylr -ylr -ylr -ylr -"} -(136,1,1) = {" -ylr -ylr -ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +qxi +qxi +dJY +dJY +dJY +dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +"} +(136,1,1) = {" +ylr +ylr +ylr ylr ylr ylr @@ -91397,26 +91583,23 @@ ylr ylr ylr ylr -ylr -ylr -ylr dJY dJY dJY dJY dJY -qGw -yhE dJY -qGw dJY dJY -yhE -yhE dJY dJY -qGw dJY +dJY +dJY +dJY +dJY +dJY +qxi qxi qxi dJY @@ -91430,7 +91613,10 @@ ylr ylr ylr ylr -dJY +ylr +ylr +ylr +ylr ylr ylr ylr @@ -91655,12 +91841,6 @@ ylr ylr ylr ylr -ylr -ylr -dJY -dJY -dJY -dJY dJY dJY dJY @@ -91676,10 +91856,16 @@ dJY dJY qxi qxi +qxi +qxi +qxi dJY dJY dJY -dJY +ylr +ylr +ylr +ylr ylr ylr ylr @@ -91866,7 +92052,7 @@ gOO gOO gOO bsD -qdY +bbd flF flF flF @@ -91912,27 +92098,23 @@ ylr ylr ylr ylr -ylr -ylr -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY dJY dJY dJY +qxi +qxi +qxi dJY dJY dJY qxi qxi qxi +qxi +qxi +qxi +qxi +qxi dJY dJY dJY @@ -91952,6 +92134,10 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr "} (139,1,1) = {" ylr @@ -92131,7 +92317,7 @@ sTU nvS eaS pRT -uJr +gTN uix oLK oLK @@ -92170,21 +92356,16 @@ ylr ylr ylr ylr -ylr -ylr -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY +qxi +qxi +qxi +qxi +qxi +qxi +qxi +qxi +qxi +qxi qxi qxi qxi @@ -92193,6 +92374,11 @@ qxi dJY dJY dJY +dJY +dJY +ylr +ylr +ylr ylr ylr ylr @@ -92376,13 +92562,13 @@ qmO nGh gIJ gIJ -gIJ +geT gIJ gIJ xkg xbB uJr -uJr +tgX uJr uix uix @@ -92398,7 +92584,7 @@ uJr uJr iKZ uJr -crg +nQN crg crg nzq @@ -92427,17 +92613,9 @@ ylr ylr ylr ylr -ylr -ylr -dJY -dJY -dJY qxi qxi qxi -dJY -dJY -dJY qxi qxi qxi @@ -92446,10 +92624,18 @@ qxi qxi qxi qxi +qxi +dJY +dJY +dJY dJY dJY dJY dJY +dJY +ylr +ylr +ylr ylr ylr ylr @@ -92600,7 +92786,7 @@ xMH agh gcp nrs -hWN +jBZ crL vka wHi @@ -92685,21 +92871,15 @@ ylr ylr ylr ylr -ylr -ylr -qxi -qxi -qxi -qxi -qxi -qxi -qxi -qxi -qxi -qxi +dJY +dJY +dJY +dJY qxi qxi qxi +dJY +dJY qxi qxi dJY @@ -92707,6 +92887,12 @@ dJY dJY dJY dJY +dJY +dJY +ylr +ylr +ylr +ylr ylr ylr ylr @@ -92942,44 +93128,44 @@ ylr ylr ylr ylr +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +qxi +qxi +dJY +dJY +aCv +dJY +dJY +dJY +dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr -qxi -qxi -qxi -qxi -qxi -qxi -qxi -qxi -qxi -qxi -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr "} (143,1,1) = {" ylr @@ -93199,27 +93385,27 @@ ylr ylr ylr ylr -ylr -ylr -ylr dJY dJY dJY dJY -qxi -qxi -qxi +dJY +dJY +dJY dJY dJY qxi qxi +qxi dJY dJY dJY dJY dJY dJY -dJY +ylr +ylr +ylr ylr ylr ylr @@ -93408,7 +93594,7 @@ ftc bJa aLA eUa -mKD +cuV mTW mBf lec @@ -93457,8 +93643,6 @@ ylr ylr ylr ylr -ylr -ylr dJY dJY dJY @@ -93472,7 +93656,6 @@ qxi qxi dJY dJY -aCv dJY dJY dJY @@ -93494,6 +93677,9 @@ ylr ylr ylr ylr +ylr +ylr +ylr "} (145,1,1) = {" ylr @@ -93724,11 +93910,8 @@ dJY dJY dJY dJY -dJY qxi qxi -qxi -dJY dJY dJY dJY @@ -93751,6 +93934,9 @@ ylr ylr ylr ylr +ylr +ylr +ylr "} (146,1,1) = {" ylr @@ -93978,9 +94164,7 @@ dJY dJY dJY dJY -dJY -dJY -dJY +aCv dJY dJY qxi @@ -93990,7 +94174,9 @@ dJY dJY dJY dJY -dJY +ylr +ylr +ylr ylr ylr ylr @@ -94238,16 +94424,16 @@ dJY dJY dJY dJY -dJY -dJY -dJY +qxi qxi qxi dJY dJY dJY dJY -dJY +ylr +ylr +ylr ylr ylr ylr @@ -94436,7 +94622,7 @@ kmf iKL kdf bHL -nSs +gzX eMJ pZe kZM @@ -94480,8 +94666,8 @@ ylr ylr ylr ylr -ylr -ylr +dJY +dJY ylr ylr ylr @@ -94495,16 +94681,16 @@ dJY dJY dJY dJY -aCv -dJY dJY qxi qxi -dJY -dJY -dJY -dJY -dJY +qxi +qxi +qxi +ylr +ylr +ylr +ylr ylr ylr ylr @@ -94735,12 +94921,10 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY ylr ylr ylr @@ -94758,10 +94942,12 @@ dJY qxi qxi qxi -dJY -dJY -dJY -dJY +qxi +qxi +ylr +ylr +ylr +ylr ylr ylr ylr @@ -94990,6 +95176,12 @@ ylr ylr ylr ylr +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -95000,15 +95192,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -dJY dJY dJY dJY @@ -95016,8 +95199,11 @@ dJY qxi qxi qxi -qxi -qxi +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -95246,6 +95432,16 @@ ylr ylr ylr ylr +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +ylr +ylr ylr ylr ylr @@ -95265,16 +95461,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -qxi -qxi -qxi -qxi -qxi ylr ylr ylr @@ -95381,7 +95567,7 @@ pww dvH jEm sgT -vci +jHI bgM pVC iIL @@ -95503,6 +95689,14 @@ ylr ylr ylr ylr +dJY +dJY +dJY +dJY +aCv +dJY +dJY +dJY ylr ylr ylr @@ -95523,14 +95717,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -qxi -qxi -qxi -ylr ylr ylr ylr @@ -95760,13 +95946,13 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +aCv +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -96017,13 +96203,13 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -96273,6 +96459,14 @@ ylr ylr ylr ylr +dJY +dJY +dJY +aCv +dJY +dJY +dJY +dJY ylr ylr ylr @@ -96292,17 +96486,9 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY ylr ylr ylr @@ -96530,6 +96716,23 @@ ylr ylr ylr ylr +dJY +dJY +dJY +dJY +dJY +dJY +dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -96538,6 +96741,14 @@ ylr ylr ylr ylr +dJY +dJY +dJY +dJY +dJY +dJY +ylr +ylr ylr ylr ylr @@ -96547,39 +96758,14 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -"} -(157,1,1) = {" +ylr +ylr +ylr +ylr +ylr +ylr +"} +(157,1,1) = {" ylr ylr ylr @@ -96787,13 +96973,13 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -96804,20 +96990,20 @@ ylr bIB ylr ylr +dJY +dJY ylr ylr ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +aCv +dJY +dJY +dJY ylr ylr ylr @@ -97045,6 +97231,11 @@ ylr ylr ylr ylr +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -97055,25 +97246,20 @@ ylr ylr ylr ylr +dJY +dJY +dJY ylr ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -97302,6 +97488,10 @@ ylr ylr ylr ylr +dJY +dJY +dJY +dJY ylr ylr ylr @@ -97313,23 +97503,19 @@ ylr ylr ylr ylr +dJY +dJY +dJY ylr +bIB ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +aCv +dJY +dJY ylr ylr ylr @@ -97559,6 +97745,10 @@ ylr ylr ylr ylr +dJY +dJY +dJY +dJY ylr ylr ylr @@ -97577,6 +97767,12 @@ ylr ylr ylr ylr +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -97591,16 +97787,6 @@ ylr ylr ylr ylr -dJY -dJY -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr ylr ylr ylr @@ -97817,6 +98003,8 @@ ylr ylr ylr ylr +dJY +dJY ylr ylr ylr @@ -97836,6 +98024,11 @@ ylr ylr ylr ylr +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -97847,13 +98040,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -ylr -ylr -ylr -ylr ylr ylr ylr @@ -98097,6 +98283,10 @@ ylr ylr ylr ylr +dJY +dJY +ylr +ylr ylr ylr ylr @@ -98104,11 +98294,7 @@ ylr ylr ylr ylr -dJY -dJY -dJY ylr -bIB ylr ylr ylr @@ -98457,7 +98643,7 @@ jBL ghL vYa tJZ -wvu +ghL jBL vXY wSN @@ -98581,7 +98767,7 @@ ylr ylr ylr ylr -ylr +dJY ylr ylr ylr @@ -98714,7 +98900,7 @@ jBL bhD wXE iSI -pLB +ghL jBL nDI jMb @@ -98837,9 +99023,9 @@ ylr ylr ylr ylr -ylr -ylr -ylr +dJY +dJY +dJY ylr ylr ylr @@ -98971,7 +99157,7 @@ jBL aKj pSS wYC -qzN +lYe jBL faF csp @@ -99056,7 +99242,7 @@ jHy jHy tzk sOX -xnB +sOV hNN aPm nQq @@ -99094,9 +99280,9 @@ ylr ylr ylr ylr -ylr -ylr -ylr +dJY +dJY +dJY ylr ylr ylr @@ -99226,9 +99412,9 @@ kqW jFa jBL npK -ezL -jZE -pTc +kJb +dZo +hJN uBj fXR yfT @@ -99350,10 +99536,10 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr +dJY +aCv +dJY +dJY ylr ylr ylr @@ -99483,7 +99669,7 @@ kqW uGk jBL iaH -tHu +cMu ghL ghL nTb @@ -99607,10 +99793,10 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY ylr ylr ylr @@ -99740,7 +99926,7 @@ kqW jFa jBL aLL -tHu +cMu bDL ghL kXM @@ -99795,7 +99981,7 @@ cPC cPC cPC dqy -ifd +tLr uNK uNK uNK @@ -99864,10 +100050,10 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY ylr ylr ylr @@ -99997,7 +100183,7 @@ kde jFa jBL jBL -nrb +fvT jBL jBL jBL @@ -100121,10 +100307,10 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY ylr ylr ylr @@ -100158,9 +100344,9 @@ ylr ylr ylr ylr -dJY -dJY -dJY +ylr +ylr +ylr ylr ylr ylr @@ -100254,8 +100440,8 @@ eGX brs jBL uzl -fqT -pjA +iWP +aFg wED jBL iSF @@ -100379,8 +100565,8 @@ ylr ylr ylr ylr -ylr -ylr +dJY +dJY ylr ylr ylr @@ -100413,12 +100599,12 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -100551,7 +100737,7 @@ cPC tWc asN xdk -cPC +ofp xWw rAT fjk @@ -100670,32 +100856,32 @@ ylr ylr ylr ylr -dJY -dJY -aCv -dJY -dJY -dJY -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -"} -(173,1,1) = {" -ylr -ylr -ylr -ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +"} +(173,1,1) = {" +ylr +ylr +ylr +ylr ylr ylr ylr @@ -100926,12 +101112,12 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -101182,12 +101368,12 @@ ylr ylr ylr ylr -dJY -dJY -dJY -aCv -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -101439,12 +101625,12 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -101579,9 +101765,9 @@ fen fen iuE ouG -fjm -wph -olk +oJI +rUJ +jRs mfu ntn uVJ @@ -101696,11 +101882,11 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -101955,8 +102141,8 @@ ylr ylr ylr ylr -dJY -dJY +ylr +ylr ylr ylr ylr @@ -102908,7 +103094,7 @@ uJr uJr nQq jHy -jHy +pKp fgV iXv dGB @@ -103112,8 +103298,8 @@ szo nhk iOI iOI -dRo -bOf +ktH +fZm oGa ouG ouG @@ -103889,7 +104075,7 @@ rca sMI ttj ksm -nLN +dis ttj ttj dcQ @@ -104262,15 +104448,15 @@ ylr ylr ylr ylr +dJY +dJY +dJY +dJY ylr ylr ylr ylr ylr -dJY -dJY -dJY -dJY ylr ylr ylr @@ -104518,11 +104704,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr dJY dJY dJY @@ -104545,6 +104726,11 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr "} (188,1,1) = {" ylr @@ -104774,11 +104960,6 @@ dJY dJY ylr ylr -ylr -ylr -ylr -ylr -ylr dJY dJY dJY @@ -104794,8 +104975,13 @@ ylr ylr ylr ylr -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -105049,10 +105235,10 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr ylr ylr ylr @@ -105304,12 +105490,12 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -105425,7 +105611,7 @@ okP mUq ylr mfu -tki +xPn pSc nQE roz @@ -105435,7 +105621,7 @@ pYL wtE eyw xlj -cRh +qbo jEc jEc jEc @@ -105560,14 +105746,14 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -105682,17 +105868,17 @@ qGg xSu xSu xSu -gsw -fGw -fGw -fGw -fGw -fGw -fGw -fGw -fGw -fGw -vMQ +pIm +oVz +oVz +oVz +oVz +oVz +oVz +oVz +oVz +oVz +nOt ylr kkk dYk @@ -105725,7 +105911,7 @@ xGT pzZ alW cJk -ciH +nlF cJk bHj bHj @@ -105811,20 +105997,20 @@ ylr ylr ylr ylr -dJY -dJY ylr ylr ylr ylr -dJY -dJY -dJY -dJY -aCv -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -106050,13 +106236,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr xSu xSu xSu @@ -106074,13 +106253,20 @@ ylr ylr ylr ylr -dJY -aCv -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -106307,13 +106493,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr kbQ kbQ kbQ @@ -106331,13 +106510,20 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -106560,13 +106746,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr xSu xSu xSu @@ -106587,14 +106766,21 @@ ylr ylr ylr ylr -dJY -dJY -dJY -aCv -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -106816,13 +107002,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr xSu xSu xSu @@ -106844,13 +107023,20 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -107067,13 +107253,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr xSu ylr ylr @@ -107101,13 +107280,20 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -107322,13 +107508,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr xSu xSu xSu @@ -107359,11 +107538,18 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -107567,11 +107753,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr bIB ylr ylr @@ -107583,8 +107764,6 @@ ylr ylr ylr ylr -ylr -ylr xSu xSu xSu @@ -107616,10 +107795,17 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -107836,13 +108022,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr xSu ylr xSu @@ -107873,10 +108052,17 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -108096,13 +108282,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr kbQ hBq drp @@ -108131,8 +108310,15 @@ ylr ylr ylr ylr -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -108351,13 +108537,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr xSu izO kbQ @@ -108400,6 +108579,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (203,1,1) = {" ylr @@ -108608,13 +108794,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr xSu izO cTN @@ -108657,6 +108836,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (204,1,1) = {" ylr @@ -108860,13 +109046,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr xSu xSu kbQ @@ -108914,6 +109093,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (205,1,1) = {" ylr @@ -109116,13 +109302,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr xlk hwZ hwZ @@ -109171,6 +109350,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (206,1,1) = {" ylr @@ -109372,13 +109558,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr xSu lNJ dOl @@ -109428,6 +109607,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (207,1,1) = {" ylr @@ -109629,13 +109815,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr kbQ hBI uOr @@ -109685,6 +109864,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (208,1,1) = {" ylr @@ -109886,13 +110072,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr kbQ lNJ hwZ @@ -109942,6 +110121,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (209,1,1) = {" ylr @@ -110138,18 +110324,11 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr dJY dJY dJY ylr ylr -ylr -ylr kbQ dkl hwZ @@ -110199,22 +110378,29 @@ ylr ylr ylr ylr -"} -(210,1,1) = {" -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +"} +(210,1,1) = {" +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -110393,11 +110579,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr dJY dJY dJY @@ -110405,8 +110586,6 @@ dJY dJY ylr ylr -ylr -ylr kbQ kbQ xSu @@ -110456,6 +110635,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (211,1,1) = {" ylr @@ -110650,11 +110836,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr dJY dJY dJY @@ -110668,8 +110849,6 @@ ylr ylr ylr ylr -ylr -ylr xSu xSu izO @@ -110713,6 +110892,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (212,1,1) = {" ylr @@ -110906,11 +111092,6 @@ tSr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr dJY dJY dJY @@ -110926,8 +111107,6 @@ ylr ylr ylr ylr -ylr -ylr xSu izO kbQ @@ -110970,6 +111149,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (213,1,1) = {" ylr @@ -111163,11 +111349,6 @@ xSu ylr ylr ylr -ylr -ylr -ylr -ylr -ylr dJY dJY dJY @@ -111185,8 +111366,6 @@ ylr ylr ylr ylr -ylr -ylr kbQ hBq hBq @@ -111227,6 +111406,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (214,1,1) = {" ylr @@ -111420,11 +111606,6 @@ xSu ylr ylr ylr -ylr -ylr -ylr -ylr -ylr dJY dJY dJY @@ -111439,8 +111620,6 @@ ylr ylr ylr ylr -ylr -ylr xSu ylr xSu @@ -111484,6 +111663,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (215,1,1) = {" ylr @@ -111677,11 +111863,6 @@ oof pkP ylr ylr -ylr -ylr -ylr -ylr -ylr dJY dJY dJY @@ -111696,8 +111877,6 @@ ylr ylr ylr ylr -ylr -ylr xSu xSu xSu @@ -111741,6 +111920,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (216,1,1) = {" ylr @@ -111935,11 +112121,6 @@ fsv ylr ylr ylr -ylr -ylr -ylr -ylr -ylr dJY dJY dJY @@ -111954,8 +112135,6 @@ ylr ylr ylr ylr -ylr -ylr xSu xSu xSu @@ -111998,6 +112177,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (217,1,1) = {" ylr @@ -112192,11 +112378,6 @@ sDp ylr ylr ylr -ylr -ylr -ylr -ylr -ylr dJY dJY aCv @@ -112211,8 +112392,6 @@ ylr ylr ylr ylr -ylr -ylr xSu xSu xSu @@ -112255,6 +112434,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (218,1,1) = {" ylr @@ -112450,11 +112636,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr dJY dJY dJY @@ -112469,8 +112650,6 @@ ylr ylr ylr ylr -ylr -ylr xSu ylr ylr @@ -112512,6 +112691,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (219,1,1) = {" ylr @@ -112707,11 +112893,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr dJY dJY dJY @@ -112734,8 +112915,6 @@ ylr ylr ylr ylr -ylr -ylr xSu xSu kbQ @@ -112769,6 +112948,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (220,1,1) = {" ylr @@ -112965,11 +113151,6 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr dJY dJY dJY @@ -112992,8 +113173,6 @@ ylr ylr ylr ylr -ylr -ylr xSu izO kbQ @@ -113026,6 +113205,13 @@ ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr "} (221,1,1) = {" ylr @@ -114018,14 +114204,14 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -114274,6 +114460,17 @@ ylr ylr ylr ylr +dJY +dJY +dJY +dJY +dJY +yhE +yhE +yhE +dJY +dJY +dJY ylr ylr ylr @@ -114298,17 +114495,6 @@ ylr ylr ylr ylr -dJY -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr ylr ylr "} @@ -114527,49 +114713,49 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -dJY -dJY -dJY -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -"} -(227,1,1) = {" +ylr +ylr +dJY +dJY +dJY +dJY +dJY +dJY +fON +fON +gcv +qGw +dJY +dJY +dJY +dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +"} +(227,1,1) = {" ylr ylr ylr @@ -114769,7 +114955,7 @@ ylr ylr ylr ylr -ylr +dJY ylr ylr ylr @@ -114785,6 +114971,22 @@ ylr bIB ylr ylr +dJY +dJY +dJY +dJY +dJY +dJY +yhE +fON +fON +fON +qGw +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -114809,22 +115011,6 @@ ylr ylr ylr ylr -ylr -ylr -dJY -dJY -dJY -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr "} (228,1,1) = {" ylr @@ -115025,6 +115211,8 @@ ylr ylr ylr ylr +dJY +dJY ylr ylr ylr @@ -115040,112 +115228,22 @@ ylr ylr ylr ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr +dJY +dJY +dJY dJY aCv dJY +qGw +fON +fON +fON +dJY +dJY +aCv +dJY +dJY dJY -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -"} -(229,1,1) = {" -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr -ylr ylr ylr ylr @@ -115170,29 +115268,12 @@ ylr ylr ylr ylr +"} +(229,1,1) = {" ylr ylr -pdy ylr -xSu -bHj -keV -lOT -lOT -rOl -qIR -gYI -ouF -yjJ -wnr -hHP -lOT -lOT -lOT -bHj -xSu ylr -xNJ ylr ylr ylr @@ -115228,50 +115309,6 @@ ylr ylr ylr ylr -qxi -qxi -qxi -qxi -qxi -qxi -qxi -qxi -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -lAY -vfU -vfU -vfU -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -115321,9 +115358,102 @@ ylr ylr ylr ylr +pdy +ylr +xSu +bHj +keV +lOT +lOT +rOl +qIR +gYI +ouF +yjJ +wnr +hHP +lOT +lOT +lOT +bHj +xSu +ylr +xNJ +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr +ylr +ylr +ylr +ylr +ylr +qxi +qxi +qxi +qxi +qxi +qxi +qxi +qxi +qxi +qxi +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +lAY +vfU +vfU +vfU +dJY +dJY +dJY +dJY dJY dJY dJY @@ -115338,6 +115468,62 @@ ylr ylr ylr ylr +dJY +dJY +dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +dJY +dJY +dJY +dJY +dJY +dJY +qGw +qGw +dJY +yhE +yhE +dJY +dJY +dJY +dJY +dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr "} (230,1,1) = {" @@ -115516,13 +115702,526 @@ dJY dJY dJY aCv -qxi +alz qxi vfU gra -vfU +wzV +qxi +dJY +dJY +dJY +dJY +dJY +dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +dJY +dJY +dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +dJY +dJY +qGw +qGw +yhE +qGw +qGw +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +"} +(231,1,1) = {" +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +pdy +ylr +xSu +xSu +bHj +nSD +lOT +lOT +lOT +nEF +gOc +iGk +lOT +lOT +keV +srH +bHj +xSu +ylr +ylr +xNJ +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +bIB +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +qxi +qxi +qxi +qxi +qxi +qxi +dJY +dJY +dJY +dJY +dJY +dJY +dJY +qxi +qxi +qxi +dJY +dJY +dJY +qxi +okd +qxi +lMb +qxi +qxi +aCv +dJY +dJY +dJY +dJY +dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +dJY +dJY +dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +dJY +dJY +qGw +fON +fON +gcv +qGw +dJY +aCv +dJY +dJY +dJY +dJY +dJY +ylr +ylr +ylr +bIB +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +"} +(232,1,1) = {" +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +xSu +bHj +bHj +lOT +lOT +lOT +lOT +lOT +lOT +lOT +bHj +bHj +xSu +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +qxi +qxi +qxi +dJY +dJY +dJY +dJY +dJY +dJY +qxi +qxi qxi +qxi +dJY +dJY +dJY +dJY +dJY dJY +qxi +qxi dJY dJY dJY @@ -115540,6 +116239,105 @@ ylr ylr ylr ylr +dJY +dJY +dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +dJY +dJY +qGw +fON +fON +fON +yhE +dJY +dJY +dJY +dJY +dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +"} +(233,1,1) = {" +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -115581,10 +116379,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY ylr ylr ylr @@ -115594,10 +116388,25 @@ ylr ylr ylr ylr +xNJ +xNJ +xNJ +xSu +bHj +bHj +lOT +lOT +lOT +lOT +lOT +bHj +bHj +xSu +xNJ +xNJ +xNJ ylr ylr -"} -(231,1,1) = {" ylr ylr ylr @@ -115650,6 +116459,29 @@ ylr ylr ylr ylr +qxi +qxi +dJY +dJY +dJY +dJY +dJY +qxi +qxi +qxi +qxi +qxi +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -115665,6 +116497,7 @@ ylr ylr ylr ylr +dJY ylr ylr ylr @@ -115681,32 +116514,24 @@ ylr ylr ylr ylr +dJY +dJY +fON +fON +fON +yhE +dJY +dJY +dJY +dJY ylr ylr ylr ylr ylr -pdy ylr -xSu -xSu -bHj -nSD -lOT -lOT -lOT -nEF -gOc -iGk -lOT -lOT -keV -srH -bHj -xSu ylr ylr -xNJ ylr ylr ylr @@ -115728,6 +116553,8 @@ ylr ylr ylr ylr +"} +(234,1,1) = {" ylr ylr ylr @@ -115738,7 +116565,6 @@ ylr ylr ylr ylr -bIB ylr ylr ylr @@ -115754,37 +116580,6 @@ ylr ylr ylr ylr -qxi -qxi -qxi -qxi -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -qxi -okd -qxi -lMb -qxi -qxi -aCv -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -115830,7 +116625,6 @@ ylr ylr ylr ylr -bIB ylr ylr ylr @@ -115838,10 +116632,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY ylr ylr ylr @@ -115853,14 +116643,22 @@ ylr ylr ylr ylr -"} -(232,1,1) = {" ylr ylr ylr ylr ylr ylr +xSu +bHj +bHj +lOT +lOT +lOT +bHj +bHj +xSu +xSu ylr ylr ylr @@ -115889,6 +116687,7 @@ ylr ylr ylr ylr +bIB ylr ylr ylr @@ -115918,8 +116717,27 @@ ylr ylr ylr ylr +qxi +qxi +dJY +dJY +dJY +dJY +qxi +qxi ylr ylr +qxi +qxi +qxi +qxi +qxi +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -115941,29 +116759,27 @@ ylr ylr ylr ylr +dJY +dJY ylr ylr ylr ylr ylr ylr -xSu -bHj -bHj -lOT -lOT -lOT -lOT -lOT -lOT -lOT -bHj -bHj -xSu ylr ylr ylr ylr +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -115994,6 +116810,8 @@ ylr ylr ylr ylr +"} +(235,1,1) = {" ylr ylr ylr @@ -116014,33 +116832,6 @@ ylr ylr ylr ylr -qxi -qxi -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -qxi -qxi -qxi -wOE -qxi -qxi -qxi -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -116096,8 +116887,6 @@ ylr ylr ylr ylr -dJY -dJY ylr ylr ylr @@ -116110,13 +116899,24 @@ ylr ylr ylr ylr -"} -(233,1,1) = {" ylr ylr ylr ylr ylr +cif +xSu +xSu +xSu +bHj +bHj +gVc +bHj +bHj +xSu +xSu +xSu +cif ylr ylr ylr @@ -116175,6 +116975,14 @@ ylr ylr ylr ylr +qxi +qxi +qxi +qxi +qxi +qxi +ylr +ylr ylr ylr ylr @@ -116202,34 +117010,33 @@ ylr ylr ylr ylr -xNJ -xNJ -xNJ -xSu -bHj -bHj -lOT -lOT -lOT -lOT -lOT -bHj -bHj -xSu -xNJ -xNJ -xNJ ylr ylr ylr ylr ylr +dJY +dJY +dJY +dJY +ylr +ylr +ylr +ylr ylr ylr ylr ylr ylr ylr +dJY +dJY +dJY +dJY +dJY +dJY +dJY +ylr ylr ylr ylr @@ -116260,6 +117067,8 @@ ylr ylr ylr ylr +"} +(236,1,1) = {" ylr ylr ylr @@ -116271,33 +117080,6 @@ ylr ylr ylr ylr -qxi -qxi -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -qxi -kkT -qxi -qxi -qxi -qxi -okd -dJY -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -116367,8 +117149,6 @@ ylr ylr ylr ylr -"} -(234,1,1) = {" ylr ylr ylr @@ -116383,11 +117163,22 @@ ylr ylr ylr ylr +xSu +xSu +xSu +xSu +xSu +xSu +xSu +xSu +cif +cif ylr ylr ylr ylr ylr +bIB ylr ylr ylr @@ -116463,16 +117254,6 @@ ylr ylr ylr ylr -xSu -bHj -bHj -lOT -lOT -lOT -bHj -bHj -xSu -xSu ylr ylr ylr @@ -116491,6 +117272,9 @@ ylr ylr ylr ylr +dJY +dJY +dJY ylr ylr ylr @@ -116501,9 +117285,13 @@ ylr ylr ylr ylr -bIB ylr ylr +dJY +dJY +dJY +dJY +dJY ylr ylr ylr @@ -116529,31 +117317,6 @@ ylr ylr ylr ylr -qxi -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -qxi -qxi -qxi -qxi -kVo -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -116561,6 +117324,8 @@ ylr ylr ylr ylr +"} +(237,1,1) = {" ylr ylr ylr @@ -116573,8 +117338,6 @@ ylr ylr ylr ylr -dJY -dJY ylr ylr ylr @@ -116624,8 +117387,6 @@ ylr ylr ylr ylr -"} -(235,1,1) = {" ylr ylr ylr @@ -116658,6 +117419,15 @@ ylr ylr ylr ylr +cif +xSu +cif +xSu +cif +cif +cif +xSu +cif ylr ylr ylr @@ -116718,19 +117488,6 @@ ylr ylr ylr ylr -cif -xSu -xSu -xSu -bHj -bHj -gVc -bHj -bHj -xSu -xSu -xSu -cif ylr ylr ylr @@ -116768,10 +117525,12 @@ ylr ylr ylr ylr +bIB ylr ylr ylr ylr +dJY ylr ylr ylr @@ -116787,27 +117546,6 @@ ylr ylr ylr ylr -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -qxi -qxi -okd -lSG -qxi -qxi -dJY -dJY -dJY -dJY dJY dJY dJY @@ -116829,10 +117567,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY ylr ylr ylr @@ -116847,15 +117581,9 @@ ylr ylr ylr ylr +"} +(238,1,1) = {" ylr -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -116881,8 +117609,6 @@ ylr ylr ylr ylr -"} -(236,1,1) = {" ylr ylr ylr @@ -116951,10 +117677,13 @@ ylr ylr ylr ylr +cif ylr +cif ylr ylr ylr +cif ylr ylr ylr @@ -116977,22 +117706,11 @@ ylr ylr ylr ylr -xSu -xSu -xSu -xSu -xSu -xSu -xSu -xSu -cif -cif ylr ylr ylr ylr ylr -bIB ylr ylr ylr @@ -117044,30 +117762,6 @@ ylr ylr ylr ylr -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -qxi -qxi -kVo -kSi -qxi -aCv -dJY -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -117086,9 +117780,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY ylr ylr ylr @@ -117104,17 +117795,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -yhE -yhE -yhE -dJY -dJY -dJY ylr ylr ylr @@ -117138,8 +117818,6 @@ ylr ylr ylr ylr -"} -(237,1,1) = {" ylr ylr ylr @@ -117160,6 +117838,8 @@ ylr ylr ylr ylr +"} +(239,1,1) = {" ylr ylr ylr @@ -117233,15 +117913,6 @@ ylr ylr ylr ylr -cif -xSu -cif -xSu -cif -cif -cif -xSu -cif ylr ylr ylr @@ -117301,33 +117972,6 @@ ylr ylr ylr ylr -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -aCv -kVo -alz -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -ylr -ylr ylr ylr ylr @@ -117339,12 +117983,9 @@ ylr ylr ylr ylr -bIB -ylr ylr ylr ylr -dJY ylr ylr ylr @@ -117359,20 +118000,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY -fON -fON -gcv -qGw -dJY -dJY -dJY -dJY ylr ylr ylr @@ -117395,8 +118022,6 @@ ylr ylr ylr ylr -"} -(238,1,1) = {" ylr ylr ylr @@ -117470,6 +118095,8 @@ ylr ylr ylr ylr +"} +(240,1,1) = {" ylr ylr ylr @@ -117491,13 +118118,10 @@ ylr ylr ylr ylr -cif ylr -cif ylr ylr ylr -cif ylr ylr ylr @@ -117557,32 +118181,6 @@ ylr ylr ylr ylr -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -qxi -qxi -okd -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -117615,22 +118213,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY -yhE -fON -fON -fON -qGw -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -117652,8 +118234,6 @@ ylr ylr ylr ylr -"} -(239,1,1) = {" ylr ylr ylr @@ -117772,6 +118352,8 @@ ylr ylr ylr ylr +"} +(241,1,1) = {" ylr ylr ylr @@ -117800,10 +118382,6 @@ ylr ylr ylr ylr -qxi -qxi -qxi -qxi ylr ylr ylr @@ -117812,34 +118390,6 @@ ylr ylr ylr ylr -qxi -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -qxi -oRp -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -qxi -dJY -dJY -dJY ylr ylr ylr @@ -117866,28 +118416,11 @@ ylr ylr ylr ylr -dJY ylr ylr ylr ylr ylr -dJY -dJY -dJY -dJY -aCv -dJY -qGw -fON -fON -fON -dJY -dJY -aCv -dJY -dJY -dJY ylr ylr ylr @@ -117909,8 +118442,6 @@ ylr ylr ylr ylr -"} -(240,1,1) = {" ylr ylr ylr @@ -118056,47 +118587,11 @@ ylr ylr ylr ylr -dJY -dJY -dJY -qxi -qxi -qxi -qxi -qxi ylr ylr ylr ylr ylr -qxi -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -aCv -qxi -qxi -kVo -aCv -dJY -dJY -dJY -dJY -dJY -qxi -okd -dJY -dJY -dJY ylr ylr ylr @@ -118114,6 +118609,8 @@ ylr ylr ylr ylr +"} +(242,1,1) = {" ylr ylr ylr @@ -118122,29 +118619,11 @@ ylr ylr ylr ylr -dJY -dJY ylr ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY -qGw -qGw -dJY -yhE -yhE -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -118166,8 +118645,6 @@ ylr ylr ylr ylr -"} -(241,1,1) = {" ylr ylr ylr @@ -118312,48 +118789,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY -qxi -qxi -qxi -qxi -qxi -qxi -qxi -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -qxi -dJY -dJY -dJY -dJY ylr ylr ylr @@ -118379,28 +118814,10 @@ ylr ylr ylr ylr -dJY -dJY -dJY ylr ylr ylr ylr -dJY -dJY -qGw -qGw -yhE -qGw -qGw -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -118423,8 +118840,6 @@ ylr ylr ylr ylr -"} -(242,1,1) = {" ylr ylr ylr @@ -118451,6 +118866,8 @@ ylr ylr ylr ylr +"} +(243,1,1) = {" ylr ylr ylr @@ -118572,46 +118989,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -qxi -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -qxi -qxi -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -118636,27 +119013,10 @@ ylr ylr ylr ylr -dJY -dJY -dJY ylr ylr ylr ylr -dJY -dJY -qGw -fON -fON -gcv -qGw -dJY -aCv -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -118680,8 +119040,6 @@ ylr ylr ylr ylr -"} -(243,1,1) = {" ylr ylr ylr @@ -118765,6 +119123,8 @@ ylr ylr ylr ylr +"} +(244,1,1) = {" ylr ylr ylr @@ -118830,45 +119190,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -qxi -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -118893,25 +119214,10 @@ ylr ylr ylr ylr -dJY -dJY -dJY ylr ylr ylr ylr -dJY -dJY -qGw -fON -fON -fON -yhE -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -118937,8 +119243,6 @@ ylr ylr ylr ylr -"} -(244,1,1) = {" ylr ylr ylr @@ -119076,6 +119380,8 @@ ylr ylr ylr ylr +"} +(245,1,1) = {" ylr ylr ylr @@ -119089,41 +119395,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -okd -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -qxi -okd -dJY -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -119150,24 +119421,11 @@ ylr ylr ylr ylr -dJY -dJY -dJY ylr ylr ylr ylr ylr -dJY -dJY -fON -fON -fON -yhE -dJY -dJY -dJY -dJY ylr ylr ylr @@ -119194,8 +119452,6 @@ ylr ylr ylr ylr -"} -(245,1,1) = {" ylr ylr ylr @@ -119349,37 +119605,9 @@ ylr ylr ylr ylr -dJY -dJY ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY -qxi -qxi -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -qxi -qxi ylr -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -119408,32 +119636,20 @@ ylr ylr ylr ylr -dJY ylr +"} +(246,1,1) = {" ylr ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY ylr ylr ylr ylr ylr ylr -dJY -dJY -dJY -dJY ylr ylr ylr @@ -119451,8 +119667,6 @@ ylr ylr ylr ylr -"} -(246,1,1) = {" ylr ylr ylr @@ -119613,22 +119827,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -qxi -qxi -okd -qxi -dJY -dJY -dJY -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -119673,24 +119871,12 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY -dJY ylr ylr ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -119873,19 +120059,7 @@ ylr ylr ylr ylr -dJY -dJY -qxi -qxi -qxi -qxi ylr -dJY -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -119931,11 +120105,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -119943,10 +120112,27 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr @@ -120130,12 +120316,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY -dJY -dJY -dJY ylr ylr ylr @@ -120190,9 +120370,6 @@ ylr ylr ylr ylr -dJY -dJY -dJY ylr ylr ylr @@ -120200,7 +120377,16 @@ ylr ylr ylr ylr -dJY +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr +ylr ylr ylr ylr diff --git a/_maps/map_files/GaxStation/GaxStation.dmm b/_maps/map_files/GaxStation/GaxStation.dmm index 0b8073605426..8e4c7ef0450f 100644 --- a/_maps/map_files/GaxStation/GaxStation.dmm +++ b/_maps/map_files/GaxStation/GaxStation.dmm @@ -12616,7 +12616,7 @@ /obj/effect/turf_decal/trimline/secred/filled/corner/lower{ dir = 1 }, -/obj/structure/table, +/obj/machinery/vending/snack/random, /turf/open/floor/plasteel, /area/hallway/primary/port) "fZI" = ( @@ -16680,8 +16680,8 @@ /obj/effect/turf_decal/trimline/engiyellow/filled/line/lower{ dir = 10 }, -/obj/structure/chair{ - dir = 1 +/obj/machinery/computer/warrant{ + dir = 4 }, /turf/open/floor/plasteel, /area/hallway/primary/port) @@ -19832,7 +19832,7 @@ }, /obj/machinery/atmospherics/components/trinary/filter/flipped/critical{ dir = 1; - filter_type = list(/datum/gas/nitrogen) + filter_type = list("n2") }, /turf/open/floor/engine, /area/engine/engineering) @@ -45959,6 +45959,8 @@ /obj/machinery/light_switch{ pixel_x = 24 }, +/obj/machinery/paystand, +/obj/item/paper/guides/jobs/security/paystand_setup, /turf/open/floor/plasteel, /area/security/warden) "wGe" = ( diff --git a/_maps/map_files/YogStation/YogStation.dmm b/_maps/map_files/YogStation/YogStation.dmm index eaf4d9f330b0..aa48b4460fc7 100644 --- a/_maps/map_files/YogStation/YogStation.dmm +++ b/_maps/map_files/YogStation/YogStation.dmm @@ -4705,6 +4705,13 @@ /obj/machinery/door/firedoor/border_only, /turf/open/floor/plating, /area/construction/mining/aux_base) +"aHY" = ( +/obj/structure/chair/sofa/right, +/obj/machinery/status_display/ai{ + pixel_y = 32 + }, +/turf/open/floor/carpet/blue, +/area/crew_quarters/heads/captain) "aIh" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ dir = 1 @@ -5461,12 +5468,6 @@ }, /turf/open/floor/plasteel/white, /area/medical/chemistry) -"aMV" = ( -/obj/structure/toilet{ - dir = 4 - }, -/turf/open/floor/plasteel/freezer, -/area/crew_quarters/heads/captain) "aMZ" = ( /turf/closed/wall, /area/hallway/secondary/exit) @@ -6609,10 +6610,6 @@ }, /turf/open/floor/plating, /area/maintenance/port/fore) -"aUZ" = ( -/mob/living/simple_animal/pet/fox/Renault, -/turf/open/floor/carpet/blue, -/area/crew_quarters/heads/captain) "aVc" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, @@ -6653,18 +6650,6 @@ /obj/machinery/vending/cola/random, /turf/open/floor/plasteel/dark, /area/hallway/secondary/entry) -"aWc" = ( -/obj/machinery/status_display/evac{ - pixel_y = 32 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/open/floor/carpet/blue, -/area/crew_quarters/heads/captain) "aWg" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ @@ -7115,11 +7100,6 @@ }, /turf/open/floor/plating, /area/maintenance/aft) -"baQ" = ( -/obj/structure/displaycase/captain, -/obj/structure/disposalpipe/segment, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "baS" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, @@ -7153,21 +7133,6 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/locker) -"bbo" = ( -/obj/machinery/computer/security/telescreen/entertainment{ - pixel_y = 32 - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ - dir = 8 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/open/floor/carpet/blue, -/area/crew_quarters/heads/captain) "bbq" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ dir = 4 @@ -7180,9 +7145,6 @@ }, /turf/open/floor/plating, /area/maintenance/port) -"bbw" = ( -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "bbx" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ dir = 4 @@ -7218,6 +7180,20 @@ /obj/effect/spawner/structure/window, /turf/open/floor/plating, /area/library) +"bbE" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "1-4"; + tag = "" + }, +/obj/effect/turf_decal/siding/wood/corner/thin{ + dir = 4 + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "bbG" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ dir = 5 @@ -7309,11 +7285,6 @@ /obj/machinery/telecomms/server/presets/security, /turf/open/floor/circuit/green/telecomms/mainframe, /area/tcommsat/server) -"bch" = ( -/obj/structure/table/wood, -/obj/item/storage/fancy/donut_box, -/turf/open/floor/carpet/blue, -/area/crew_quarters/heads/captain) "bcn" = ( /obj/structure/sign/directions/evac{ dir = 4; @@ -7440,12 +7411,6 @@ /obj/machinery/telecomms/server/presets/command, /turf/open/floor/circuit/green/telecomms/mainframe, /area/tcommsat/server) -"bdk" = ( -/obj/structure/chair/comfy/brown{ - dir = 8 - }, -/turf/open/floor/carpet/blue, -/area/crew_quarters/heads/captain) "bdm" = ( /obj/machinery/door/airlock{ name = "Unit 1" @@ -7462,28 +7427,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /turf/open/floor/plasteel/white, /area/medical/medbay/lobby) -"bdq" = ( -/obj/machinery/power/apc{ - areastring = "/area/crew_quarters/heads/captain"; - dir = 1; - name = "Captain's Office APC"; - pixel_y = 23 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "0-8" - }, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) -"bdr" = ( -/obj/item/kirbyplants/random, -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "bdv" = ( /obj/machinery/navbeacon{ codes_txt = "patrol;next_patrol=HOP2"; @@ -7570,16 +7513,6 @@ "bea" = ( /turf/closed/wall/r_wall, /area/quartermaster/warehouse) -"beg" = ( -/obj/structure/table/wood, -/obj/machinery/camera{ - c_tag = "Captain's Office"; - dir = 8 - }, -/obj/item/storage/lockbox/medal, -/obj/structure/disposalpipe/segment, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "bei" = ( /obj/machinery/door/firedoor/border_only{ dir = 1 @@ -7599,6 +7532,22 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/aft) +"bej" = ( +/obj/structure/table/glass, +/obj/item/reagent_containers/food/drinks/bottle/amaretto{ + pixel_x = -3; + pixel_y = 10 + }, +/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass{ + pixel_x = 5; + pixel_y = -1 + }, +/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass{ + pixel_x = 9; + pixel_y = 12 + }, +/turf/open/floor/carpet/blue, +/area/crew_quarters/heads/captain) "bek" = ( /obj/structure/girder, /turf/open/floor/plating, @@ -7696,20 +7645,6 @@ }, /turf/open/floor/plating, /area/quartermaster/sorting) -"bfl" = ( -/obj/structure/table/wood, -/obj/machinery/airalarm{ - dir = 8; - pixel_x = 24 - }, -/obj/item/camera, -/obj/item/storage/photo_album{ - pixel_y = -10 - }, -/obj/item/toy/figure/captain, -/obj/structure/disposalpipe/segment, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "bfo" = ( /obj/machinery/door/window/eastright{ dir = 1; @@ -7729,20 +7664,6 @@ "bfv" = ( /turf/closed/wall/r_wall, /area/ai_monitored/turret_protected/ai_upload) -"bfC" = ( -/obj/structure/table/wood, -/obj/item/pinpointer/nuke, -/obj/item/disk/nuclear, -/obj/item/storage/secure/safe{ - pixel_x = 35; - pixel_y = 5 - }, -/obj/machinery/light{ - dir = 4 - }, -/obj/structure/disposalpipe/segment, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "bfF" = ( /turf/closed/wall, /area/medical/chemistry) @@ -8042,13 +7963,6 @@ }, /turf/open/floor/plasteel/white, /area/medical/storage) -"bhG" = ( -/obj/machinery/firealarm{ - dir = 1; - pixel_y = -26 - }, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "bhH" = ( /obj/machinery/door/airlock/maintenance{ req_access_txt = "12" @@ -8883,15 +8797,6 @@ }, /turf/open/floor/plating, /area/hallway/secondary/entry) -"bpk" = ( -/obj/machinery/shower{ - dir = 1 - }, -/obj/item/soap/deluxe, -/obj/item/bikehorn/rubberducky, -/obj/structure/curtain, -/turf/open/floor/plasteel/freezer, -/area/crew_quarters/heads/captain) "bpr" = ( /obj/machinery/navbeacon{ codes_txt = "delivery;dir=8"; @@ -12232,6 +12137,22 @@ /obj/item/melee/sledgehammer, /turf/open/floor/plasteel, /area/engine/engineering) +"bRr" = ( +/obj/effect/turf_decal/ramp_corner, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) +"bRs" = ( +/obj/effect/turf_decal/ramp_middle{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/extinguisher_cabinet{ + pixel_y = -30 + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "bRu" = ( /obj/effect/turf_decal/stripes/corner{ dir = 8 @@ -12774,6 +12695,11 @@ }, /turf/open/floor/plating, /area/maintenance/solars/starboard/aft) +"bYT" = ( +/obj/structure/table/wood, +/obj/item/storage/lockbox/medal, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "bZg" = ( /obj/effect/turf_decal/trimline/secred/filled/line/lower{ dir = 8 @@ -13555,6 +13481,12 @@ "cjJ" = ( /turf/closed/wall/r_wall, /area/engine/engine_smes) +"cjK" = ( +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "cjL" = ( /obj/effect/decal/cleanable/glass, /turf/open/floor/plating, @@ -14506,6 +14438,21 @@ }, /turf/open/floor/plasteel, /area/construction/mining/aux_base) +"cuT" = ( +/obj/machinery/power/apc{ + areastring = "/area/crew_quarters/heads/captain"; + dir = 1; + name = "Captain's Office APC"; + pixel_y = 23 + }, +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/effect/turf_decal/siding/wood/thin{ + dir = 4 + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "cuZ" = ( /obj/machinery/camera{ c_tag = "Telecomms Server Room"; @@ -14953,13 +14900,6 @@ }, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) -"cCz" = ( -/obj/machinery/light{ - dir = 8 - }, -/obj/machinery/suit_storage_unit/captain, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "cCD" = ( /obj/structure/chair/office/light, /obj/effect/landmark/start/chemist, @@ -15135,11 +15075,6 @@ /obj/effect/landmark/carpspawn, /turf/open/space/basic, /area/space) -"cEV" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "cFk" = ( /obj/structure/cloth_curtain{ color = "#99ccff"; @@ -16748,16 +16683,6 @@ }, /turf/open/floor/plasteel, /area/science/misc_lab) -"diw" = ( -/obj/machinery/modular_computer/console/preset/command{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ - dir = 8 - }, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "diJ" = ( /obj/item/book/manual/wiki/security_space_law, /obj/structure/table, @@ -17021,6 +16946,14 @@ }, /turf/open/floor/carpet, /area/crew_quarters/heads/hos) +"dnF" = ( +/obj/machinery/suit_storage_unit/captain, +/obj/machinery/firealarm{ + dir = 1; + pixel_y = -26 + }, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "doM" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4, /obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2, @@ -17075,6 +17008,9 @@ }, /turf/open/floor/plasteel, /area/engine/atmos/mix) +"doS" = ( +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "doZ" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, @@ -18290,6 +18226,27 @@ icon_state = "panelscorched" }, /area/maintenance/aft) +"dNO" = ( +/obj/machinery/button/door{ + id = "captain blast"; + name = "Privacy Shutters Control"; + pixel_x = 26; + pixel_y = -1; + req_access_txt = "20" + }, +/obj/structure/railing{ + dir = 9 + }, +/obj/structure/table/wood, +/obj/machinery/photocopier/faxmachine{ + department = "Captain"; + name = "Captain's Fax Machine" + }, +/obj/effect/turf_decal/siding/wood/thin{ + dir = 9 + }, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "dNY" = ( /turf/closed/wall/r_wall, /area/engine/foyer) @@ -19409,19 +19366,6 @@ /obj/effect/turf_decal/pool/innercorner, /turf/open/water/safe, /area/hydroponics/garden) -"ekU" = ( -/obj/machinery/door/airlock/command{ - name = "Captain's Quarters"; - req_access_txt = "20" - }, -/obj/machinery/door/firedoor/border_only{ - dir = 1 - }, -/obj/machinery/door/firedoor/border_only, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/turf/open/floor/carpet/blue, -/area/crew_quarters/heads/captain) "ekZ" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ dir = 4 @@ -20508,11 +20452,6 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/fore) -"eEi" = ( -/obj/structure/table/wood, -/obj/item/folder/blue, -/turf/open/floor/carpet/blue, -/area/crew_quarters/heads/captain) "eEj" = ( /obj/machinery/advanced_airlock_controller{ dir = 8; @@ -20634,16 +20573,6 @@ /obj/effect/turf_decal/trimline/atmos/warning/lower/nobottom, /turf/open/floor/plasteel, /area/engine/atmos/mix) -"eGj" = ( -/obj/item/radio/intercom{ - dir = 8; - freerange = 1; - name = "Station Intercom (Command)"; - pixel_x = -28 - }, -/obj/structure/filingcabinet, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "eGm" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ dir = 8 @@ -21789,6 +21718,18 @@ /obj/effect/turf_decal/trimline/blue/filled/line/lower, /turf/open/floor/plasteel/white, /area/medical/sleeper) +"fbj" = ( +/obj/machinery/door/poddoor/preopen{ + id = "captain blast"; + name = "captain's shutters" + }, +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plating, +/area/crew_quarters/heads/captain) "fbF" = ( /obj/structure/table, /obj/item/radio/off, @@ -22115,6 +22056,15 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/aft) +"fiz" = ( +/obj/effect/turf_decal/ramp_middle, +/obj/machinery/door/window/northleft{ + dir = 2; + name = "Captain's Desk Door"; + req_one_access_txt = "20" + }, +/turf/open/floor/plasteel/stairs/goon/wood_stairs_wide, +/area/crew_quarters/heads/captain) "fiE" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 10 @@ -22275,6 +22225,23 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/port) +"flu" = ( +/obj/structure/railing{ + dir = 5 + }, +/obj/structure/table/wood, +/obj/item/hand_tele{ + pixel_x = 3 + }, +/obj/item/storage/pencil_holder/crew/fancy{ + pixel_x = -7; + pixel_y = 4 + }, +/obj/effect/turf_decal/siding/wood/thin{ + dir = 5 + }, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "flC" = ( /obj/machinery/door/firedoor/border_only{ dir = 4 @@ -22539,13 +22506,6 @@ }, /turf/open/floor/plasteel/dark, /area/bridge) -"fqv" = ( -/obj/machinery/disposal/bin, -/obj/structure/disposalpipe/trunk{ - dir = 4 - }, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "fqI" = ( /obj/machinery/computer/prisoner, /obj/effect/turf_decal/trimline/secred/filled/line/lower{ @@ -25343,12 +25303,6 @@ "gtC" = ( /turf/closed/wall, /area/medical/medbay/lobby) -"gtE" = ( -/obj/structure/chair/comfy/brown{ - dir = 4 - }, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "gtI" = ( /obj/machinery/camera{ c_tag = "Arrivals Bay 2"; @@ -25474,6 +25428,18 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/exit) +"guY" = ( +/obj/structure/chair/office/light{ + dir = 4 + }, +/obj/structure/railing/corner{ + dir = 8 + }, +/obj/effect/turf_decal/siding/wood/corner/thin{ + dir = 1 + }, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "gvl" = ( /obj/effect/turf_decal/stripes/corner{ dir = 1 @@ -25526,6 +25492,10 @@ }, /turf/open/floor/plasteel, /area/quartermaster/office) +"gwZ" = ( +/obj/structure/closet/secure_closet/captains, +/turf/open/floor/carpet/blue, +/area/crew_quarters/heads/captain) "gxF" = ( /obj/machinery/button/door{ desc = "A remote control-switch for shuttle construction storage."; @@ -26809,6 +26779,15 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, /area/maintenance/starboard/fore) +"gWx" = ( +/obj/effect/turf_decal/trimline/darkblue/filled/line/lower{ + dir = 8 + }, +/obj/machinery/status_display/evac{ + pixel_x = -32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "gWA" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable{ @@ -27110,6 +27089,10 @@ /obj/effect/turf_decal/trimline/purple/filled/line/lower, /turf/open/floor/plasteel, /area/hallway/primary/starboard) +"hbo" = ( +/obj/structure/displaycase/captain, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "hbO" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -27313,27 +27296,6 @@ /obj/structure/lattice, /turf/open/space/basic, /area/space/nearstation) -"hgw" = ( -/obj/machinery/light_switch{ - pixel_y = 28 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 10 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "hgD" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ dir = 8 @@ -27741,6 +27703,18 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) +"hnh" = ( +/obj/structure/railing{ + dir = 4 + }, +/obj/machinery/modular_computer/console/preset/command{ + dir = 8 + }, +/obj/effect/turf_decal/siding/wood/thin{ + dir = 4 + }, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "hnA" = ( /obj/effect/turf_decal/trimline/darkblue/filled/line/lower{ dir = 6 @@ -28011,6 +27985,34 @@ }, /turf/open/floor/plasteel/dark/telecomms, /area/tcommsat/server) +"hss" = ( +/obj/machinery/recharger/wallrecharger{ + pixel_x = -25; + pixel_y = 20 + }, +/obj/machinery/requests_console{ + announcementConsole = 1; + department = "Captain's Desk"; + departmentType = 5; + name = "Captain RC"; + pixel_x = -30 + }, +/obj/item/stamp/captain{ + layer = 3.2; + pixel_x = 8; + pixel_y = -2 + }, +/obj/structure/table/wood, +/obj/item/paper_bin{ + pixel_x = -3; + pixel_y = 7 + }, +/obj/item/pen{ + pixel_x = -6; + pixel_y = 5 + }, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "hsA" = ( /obj/machinery/computer/camera_advanced/base_construction{ dir = 1 @@ -28114,6 +28116,18 @@ }, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) +"huD" = ( +/obj/structure/railing{ + dir = 4 + }, +/obj/machinery/computer/communications{ + dir = 8 + }, +/obj/effect/turf_decal/siding/wood/thin{ + dir = 4 + }, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "huO" = ( /obj/structure/table, /obj/machinery/photocopier/faxmachine{ @@ -28175,11 +28189,6 @@ /obj/item/storage/pencil_holder/crew/fancy, /turf/open/floor/carpet/royalblue, /area/crew_quarters/heads/cmo) -"hwu" = ( -/obj/item/kirbyplants/random, -/obj/structure/disposalpipe/segment, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "hwx" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ dir = 4 @@ -28326,6 +28335,19 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating, /area/maintenance/starboard/aft) +"hzP" = ( +/obj/structure/sink{ + dir = 4; + pixel_x = 11 + }, +/obj/structure/mirror{ + pixel_x = 28 + }, +/obj/machinery/light/small{ + dir = 1 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/heads/captain) "hzQ" = ( /obj/structure/table, /obj/item/reagent_containers/glass/bucket, @@ -28377,6 +28399,19 @@ }, /turf/open/floor/plating, /area/maintenance/aft) +"hAI" = ( +/obj/machinery/door/airlock{ + name = "Private Restroom"; + req_access_txt = "20" + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 8 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/heads/captain) "hAJ" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 4 @@ -28991,6 +29026,13 @@ }, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) +"hNx" = ( +/obj/structure/chair/sofa, +/obj/machinery/computer/security/telescreen/entertainment{ + pixel_y = 32 + }, +/turf/open/floor/carpet/blue, +/area/crew_quarters/heads/captain) "hNI" = ( /obj/effect/spawner/structure/window/reinforced/shutter, /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ @@ -29025,6 +29067,18 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/security/main) +"hOk" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/siding/wood/thin{ + dir = 1 + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "hOn" = ( /obj/effect/turf_decal/bot_red, /obj/structure/rack, @@ -29167,6 +29221,18 @@ "hQm" = ( /turf/open/floor/circuit, /area/ai_monitored/nuke_storage) +"hQo" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 6 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 6 + }, +/obj/effect/turf_decal/siding/wood/thin{ + dir = 1 + }, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "hQt" = ( /obj/machinery/camera{ c_tag = "Virology Break Room"; @@ -29530,6 +29596,13 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, /area/hydroponics) +"hVX" = ( +/obj/structure/filingcabinet, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "hVY" = ( /obj/structure/sign/departments/minsky/research/research{ pixel_y = -32 @@ -30231,10 +30304,6 @@ }, /turf/open/floor/plating, /area/maintenance/fore/secondary) -"ihF" = ( -/obj/machinery/holopad, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "iiE" = ( /obj/machinery/firealarm{ dir = 1; @@ -30342,10 +30411,6 @@ /obj/effect/turf_decal/trimline/brown/filled/corner/lower, /turf/open/floor/plasteel, /area/quartermaster/office) -"ilk" = ( -/obj/structure/closet/secure_closet/captains, -/turf/open/floor/carpet/blue, -/area/crew_quarters/heads/captain) "ilm" = ( /obj/structure/sink{ dir = 4; @@ -30975,21 +31040,6 @@ }, /turf/open/space/basic, /area/ai_monitored/turret_protected/ai) -"ixh" = ( -/obj/machinery/status_display/ai{ - pixel_y = 32 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/open/floor/carpet/blue, -/area/crew_quarters/heads/captain) "ixn" = ( /obj/structure/cable{ icon_state = "1-2" @@ -31618,6 +31668,12 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/port) +"iKa" = ( +/obj/structure/chair/sofa/left{ + dir = 8 + }, +/turf/open/floor/carpet/blue, +/area/crew_quarters/heads/captain) "iKc" = ( /obj/structure/closet/secure_closet/CMO, /obj/item/sensor_device, @@ -32526,12 +32582,6 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) -"jaj" = ( -/obj/structure/chair/comfy/brown{ - dir = 4 - }, -/turf/open/floor/carpet/blue, -/area/crew_quarters/heads/captain) "jaq" = ( /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel/white, @@ -33841,6 +33891,15 @@ /obj/effect/turf_decal/box/corners, /turf/open/floor/engine, /area/science/xenobiology) +"jCH" = ( +/obj/structure/table/wood, +/obj/item/pinpointer/nuke, +/obj/item/disk/nuclear, +/obj/machinery/light{ + dir = 8 + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "jCM" = ( /obj/machinery/computer/message_monitor{ dir = 1 @@ -34374,6 +34433,21 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/aft) +"jNh" = ( +/obj/structure/table/wood, +/obj/item/storage/box/matches, +/obj/item/razor{ + pixel_x = -4; + pixel_y = 2 + }, +/obj/item/clothing/mask/cigarette/cigar, +/obj/item/reagent_containers/food/drinks/flask/gold, +/obj/machinery/light_switch{ + pixel_x = 25; + pixel_y = 8 + }, +/turf/open/floor/carpet/blue, +/area/crew_quarters/heads/captain) "jNo" = ( /obj/machinery/lapvend, /obj/effect/turf_decal/trimline/purple/filled/line/lower{ @@ -34565,6 +34639,18 @@ }, /turf/open/floor/wood, /area/library) +"jRb" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/effect/turf_decal/ramp_middle, +/obj/machinery/door/window{ + base_state = "right"; + icon_state = "right"; + name = "Captain's Desk Door"; + req_access_txt = "20" + }, +/turf/open/floor/plasteel/stairs/goon/wood_stairs_wide2, +/area/crew_quarters/heads/captain) "jRq" = ( /obj/effect/turf_decal/stripes/white/line{ dir = 6 @@ -35039,6 +35125,12 @@ /obj/effect/spawner/structure/window/reinforced/shutter, /turf/open/floor/plating, /area/security/prison) +"kcc" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ + dir = 1 + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "kcr" = ( /obj/machinery/status_display/ai{ pixel_y = -32 @@ -35211,14 +35303,6 @@ }, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) -"kgY" = ( -/obj/machinery/recharger/wallrecharger{ - pixel_x = -21; - pixel_y = -3 - }, -/obj/machinery/papershredder, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "khh" = ( /obj/structure/table/reinforced, /obj/machinery/door/window/northleft{ @@ -35983,21 +36067,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/fore) -"kwY" = ( -/obj/structure/table/wood, -/obj/item/flashlight/lamp/green{ - pixel_x = 5; - pixel_y = 8 - }, -/obj/item/phone/real{ - pixel_x = -2; - pixel_y = -4 - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ - dir = 8 - }, -/turf/open/floor/carpet/blue, -/area/crew_quarters/heads/captain) "kxl" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 4 @@ -37181,21 +37250,6 @@ /obj/effect/turf_decal/trimline/purple/filled/corner/lower, /turf/open/floor/plasteel/white, /area/science/research) -"kVQ" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ - dir = 5 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "1-4" - }, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "kVU" = ( /turf/closed/wall, /area/vacant_room/commissary) @@ -37255,11 +37309,6 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) -"kXE" = ( -/obj/structure/table/wood, -/obj/item/flashlight/lamp/green, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "kXP" = ( /obj/machinery/light, /obj/effect/decal/cleanable/dirt, @@ -38704,12 +38753,6 @@ "lyX" = ( /turf/open/floor/plasteel/dark, /area/tcommsat/storage) -"lza" = ( -/obj/structure/table/wood, -/obj/item/book/manual/wiki/security_space_law, -/obj/item/coin/plasma, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "lze" = ( /turf/open/floor/wood, /area/vacant_room) @@ -39042,6 +39085,15 @@ /obj/item/mop, /turf/open/floor/plasteel/dark, /area/janitor) +"lHL" = ( +/obj/machinery/door/poddoor/preopen{ + id = "captain blast"; + name = "captain's shutters" + }, +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable, +/turf/open/floor/plating, +/area/crew_quarters/heads/captain) "lHO" = ( /obj/item/stack/cable_coil, /obj/effect/decal/cleanable/dirt/dust, @@ -40909,13 +40961,11 @@ /obj/machinery/meter, /turf/open/floor/plasteel, /area/engine/atmos/distro) -"msz" = ( -/obj/structure/table/wood, -/obj/item/melee/chainofcommand, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ +"msk" = ( +/obj/effect/turf_decal/ramp_middle{ dir = 4 }, -/turf/open/floor/wood, +/turf/open/floor/wood/large, /area/crew_quarters/heads/captain) "msD" = ( /obj/effect/spawner/structure/window/reinforced/shutter, @@ -40927,6 +40977,19 @@ }, /turf/open/floor/plating, /area/hallway/primary/central) +"msN" = ( +/obj/machinery/newscaster/security_unit{ + pixel_x = 32 + }, +/obj/machinery/camera{ + c_tag = "Captain's Office"; + dir = 8 + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "msT" = ( /obj/structure/bed, /obj/item/bedsheet/captain, @@ -41227,6 +41290,15 @@ }, /turf/open/floor/plasteel, /area/hydroponics) +"mzu" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/siding/wood/thin{ + dir = 1 + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "mzy" = ( /obj/effect/turf_decal/stripes/corner{ dir = 4 @@ -41474,14 +41546,6 @@ }, /turf/open/floor/plasteel/dark, /area/security/prison) -"mCx" = ( -/obj/machinery/computer/communications{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "mCK" = ( /obj/effect/turf_decal/trimline/secred/filled/line/lower, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ @@ -41885,6 +41949,13 @@ }, /turf/open/floor/plating, /area/security/brig) +"mLc" = ( +/obj/structure/chair/sofa/corner, +/obj/machinery/status_display/ai{ + pixel_y = 32 + }, +/turf/open/floor/carpet/blue, +/area/crew_quarters/heads/captain) "mLd" = ( /obj/effect/turf_decal/trimline/secred/filled/line/lower{ dir = 1 @@ -42248,15 +42319,6 @@ /obj/effect/spawner/lootdrop/coin, /turf/open/floor/plating, /area/maintenance/port/fore) -"mRq" = ( -/obj/machinery/newscaster/security_unit{ - pixel_x = -32 - }, -/obj/machinery/keycard_auth{ - pixel_y = -24 - }, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "mRV" = ( /obj/machinery/computer/nanite_chamber_control{ dir = 8 @@ -42280,16 +42342,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) -"mSa" = ( -/obj/machinery/door/window{ - base_state = "right"; - dir = 4; - icon_state = "right"; - name = "Captain's Desk Door"; - req_access_txt = "20" - }, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "mSg" = ( /obj/machinery/atmospherics/pipe/manifold/general/visible, /turf/open/floor/circuit/telecomms/server, @@ -42335,12 +42387,6 @@ }, /turf/open/floor/plasteel, /area/science/misc_lab) -"mTm" = ( -/obj/structure/extinguisher_cabinet{ - pixel_y = -30 - }, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "mTr" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 4 @@ -42446,6 +42492,23 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, /turf/open/floor/plating, /area/maintenance/port/fore) +"mUE" = ( +/obj/effect/turf_decal/siding/wood/thin{ + dir = 1 + }, +/obj/structure/railing{ + dir = 1 + }, +/obj/structure/table/wood, +/obj/item/melee/chainofcommand, +/obj/item/radio/intercom{ + dir = 8; + freerange = 1; + name = "Station Intercom (Command)"; + pixel_x = -28 + }, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "mUU" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 1 @@ -43340,6 +43403,14 @@ /obj/effect/spawner/structure/window/reinforced/shutter, /turf/open/floor/plating, /area/security/prison) +"nlI" = ( +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk{ + dir = 4 + }, +/obj/machinery/light, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "nlS" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 4 @@ -44190,10 +44261,6 @@ }, /turf/open/floor/plasteel, /area/security/checkpoint/supply) -"nCL" = ( -/obj/machinery/vending/autodrobe/capdrobe, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "nCO" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, @@ -44918,19 +44985,6 @@ /obj/structure/table, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) -"nTb" = ( -/obj/machinery/door/airlock{ - name = "Private Restroom"; - req_access_txt = "20" - }, -/obj/machinery/door/firedoor/border_only{ - dir = 4 - }, -/obj/machinery/door/firedoor/border_only{ - dir = 8 - }, -/turf/open/floor/plasteel/freezer, -/area/crew_quarters/heads/captain) "nTv" = ( /obj/effect/turf_decal/trimline/secred/filled/line/lower{ dir = 1 @@ -45241,6 +45295,12 @@ }, /turf/open/floor/plasteel/white, /area/medical/storage) +"oaq" = ( +/obj/effect/turf_decal/ramp_middle{ + dir = 1 + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "oaC" = ( /obj/effect/turf_decal/trimline/secred/filled/line/lower{ dir = 1 @@ -45555,6 +45615,18 @@ }, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) +"ohr" = ( +/obj/structure/cable{ + icon_state = "1-4"; + tag = "" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "ohy" = ( /obj/machinery/recharger/wallrecharger{ pixel_x = 5; @@ -45587,13 +45659,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) -"oiA" = ( -/obj/structure/dresser, -/obj/machinery/light/small{ - dir = 1 - }, -/turf/open/floor/carpet/blue, -/area/crew_quarters/heads/captain) "oiE" = ( /obj/structure/table/reinforced, /obj/machinery/light{ @@ -46449,6 +46514,15 @@ }, /turf/open/floor/plasteel/white, /area/medical/virology) +"oxG" = ( +/obj/structure/railing/corner{ + dir = 4 + }, +/obj/effect/turf_decal/siding/wood/corner/thin{ + dir = 4 + }, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "oyd" = ( /obj/structure/window/reinforced{ dir = 4 @@ -47029,16 +47103,6 @@ }, /turf/open/floor/plating, /area/maintenance/aft) -"oKL" = ( -/obj/structure/chair/comfy/brown{ - dir = 4 - }, -/obj/machinery/camera/motion{ - c_tag = "Captain's Quarters"; - dir = 1 - }, -/turf/open/floor/carpet/blue, -/area/crew_quarters/heads/captain) "oKX" = ( /obj/item/radio/intercom{ name = "Station Intercom (General)"; @@ -47178,21 +47242,6 @@ }, /turf/open/floor/plating, /area/maintenance/fore) -"oME" = ( -/obj/structure/table/wood, -/obj/item/storage/box/matches, -/obj/item/razor{ - pixel_x = -4; - pixel_y = 2 - }, -/obj/item/clothing/mask/cigarette/cigar, -/obj/item/reagent_containers/food/drinks/flask/gold, -/obj/machinery/light_switch{ - pixel_x = 25; - pixel_y = 8 - }, -/turf/open/floor/carpet/blue, -/area/crew_quarters/heads/captain) "oMV" = ( /obj/effect/mapping_helpers/airlock/locked, /obj/machinery/door/airlock/research/glass{ @@ -47269,6 +47318,9 @@ /obj/effect/turf_decal/trimline/blue/filled/line/lower, /turf/open/floor/plasteel/white, /area/medical/medbay/central) +"oNF" = ( +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "oNS" = ( /obj/structure/table, /obj/item/coin/silver, @@ -47588,12 +47640,6 @@ /obj/structure/fans/tiny, /turf/open/floor/plating, /area/quartermaster/storage) -"oVK" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ - dir = 8 - }, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "oVO" = ( /obj/machinery/firealarm{ pixel_y = 26 @@ -48391,6 +48437,16 @@ }, /turf/open/floor/plasteel/dark, /area/engine/gravity_generator) +"pkR" = ( +/obj/effect/landmark/event_spawn, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/siding/wood/thin{ + dir = 1 + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "pkU" = ( /obj/effect/turf_decal/loading_area{ dir = 1 @@ -48655,6 +48711,14 @@ }, /turf/open/floor/plasteel, /area/engine/engine_smes) +"ppk" = ( +/obj/item/kirbyplants/random, +/obj/item/storage/secure/safe{ + pixel_x = -24; + pixel_y = 2 + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "ppK" = ( /obj/structure/rack, /obj/effect/spawner/lootdrop/maintenance{ @@ -49407,6 +49471,15 @@ }, /turf/open/floor/plasteel, /area/security/checkpoint/auxiliary) +"pBC" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/machinery/light{ + dir = 4 + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "pBG" = ( /turf/closed/wall, /area/maintenance/department/medical/morgue) @@ -50218,10 +50291,6 @@ /obj/item/hand_tele, /turf/open/floor/plasteel, /area/teleporter) -"pUK" = ( -/obj/structure/chair, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "pUL" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ dir = 1 @@ -51275,6 +51344,11 @@ }, /turf/open/floor/plasteel, /area/security/prison) +"qnQ" = ( +/obj/structure/table/glass, +/obj/item/storage/fancy/donut_box, +/turf/open/floor/carpet/blue, +/area/crew_quarters/heads/captain) "qnU" = ( /obj/machinery/door/firedoor/border_only, /obj/machinery/door/firedoor/border_only{ @@ -51452,6 +51526,21 @@ }, /turf/open/floor/plasteel/dark, /area/security/interrogation) +"qrA" = ( +/obj/structure/table/wood, +/obj/item/flashlight/lamp/green{ + pixel_x = 5; + pixel_y = 8 + }, +/obj/item/phone/real{ + pixel_x = -2; + pixel_y = -4 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ + dir = 8 + }, +/turf/open/floor/carpet/blue, +/area/crew_quarters/heads/captain) "qsk" = ( /obj/machinery/firealarm{ dir = 4; @@ -52723,6 +52812,11 @@ /obj/machinery/bounty_board, /turf/closed/wall, /area/quartermaster/storage) +"qPH" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "qPS" = ( /obj/structure/table/reinforced, /obj/machinery/door/window/northleft{ @@ -54257,10 +54351,6 @@ }, /turf/open/floor/plating, /area/ai_monitored/storage/satellite) -"ruZ" = ( -/obj/machinery/vending/cigarette, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "rvc" = ( /obj/machinery/light, /obj/item/radio/intercom{ @@ -54973,6 +55063,15 @@ }, /turf/open/floor/plasteel, /area/security/checkpoint/medical) +"rIQ" = ( +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/effect/turf_decal/siding/wood/thin{ + dir = 1 + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "rJa" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ dir = 9 @@ -58370,6 +58469,20 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/port) +"sXE" = ( +/obj/machinery/door/poddoor/preopen{ + id = "captain blast"; + name = "captain's shutters" + }, +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/floor/plating, +/area/crew_quarters/heads/captain) "sXH" = ( /turf/closed/wall/r_wall, /area/engine/atmos/foyer) @@ -58432,19 +58545,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) -"sYn" = ( -/obj/structure/sink{ - dir = 4; - pixel_x = 11 - }, -/obj/structure/mirror{ - pixel_x = 28 - }, -/obj/machinery/light/small{ - dir = 1 - }, -/turf/open/floor/plasteel/freezer, -/area/crew_quarters/heads/captain) "sYv" = ( /obj/machinery/navbeacon{ codes_txt = "patrol;next_patrol=CHE"; @@ -58459,23 +58559,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/starboard) -"sZn" = ( -/obj/structure/table/wood, -/obj/item/stamp/captain{ - layer = 3.2; - pixel_x = 8; - pixel_y = -2 - }, -/obj/item/paper_bin{ - pixel_x = -3; - pixel_y = 7 - }, -/obj/item/pen{ - pixel_x = -6; - pixel_y = 5 - }, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "sZy" = ( /obj/effect/turf_decal/trimline/brown/filled/line/lower{ dir = 8 @@ -58508,19 +58591,6 @@ }, /turf/open/floor/plasteel, /area/security/brig) -"sZY" = ( -/obj/machinery/camera{ - c_tag = "Central Hallway East"; - dir = 4 - }, -/obj/machinery/status_display/evac{ - pixel_x = -32 - }, -/obj/effect/turf_decal/trimline/darkblue/filled/line/lower{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/central) "tah" = ( /obj/effect/landmark/stationroom/maint/threexfive, /turf/template_noop, @@ -58632,6 +58702,18 @@ }, /turf/open/floor/plasteel, /area/quartermaster/storage) +"tcm" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 9 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 9 + }, +/obj/effect/turf_decal/siding/wood/thin{ + dir = 1 + }, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "tcr" = ( /obj/machinery/atmospherics/components/binary/pump{ dir = 0; @@ -58760,6 +58842,12 @@ }, /turf/open/floor/plasteel/white, /area/medical/chemistry) +"tfl" = ( +/obj/structure/toilet{ + dir = 4 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/heads/captain) "tfF" = ( /obj/effect/turf_decal/trimline/purple/filled/line/lower{ dir = 4 @@ -59208,10 +59296,6 @@ }, /turf/open/floor/plasteel, /area/engine/atmos/foyer) -"tmz" = ( -/obj/effect/landmark/event_spawn, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "tmB" = ( /obj/machinery/requests_console{ department = "Janitorial"; @@ -59249,6 +59333,19 @@ /obj/structure/lattice, /turf/open/space/basic, /area/space/nearstation) +"tnN" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/door/airlock/command{ + name = "Captain's Quarters"; + req_access_txt = "20" + }, +/obj/machinery/door/firedoor/border_only{ + dir = 1 + }, +/obj/machinery/door/firedoor/border_only, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "toz" = ( /obj/effect/turf_decal/stripes/corner{ dir = 1 @@ -61684,7 +61781,7 @@ "umX" = ( /obj/machinery/door/airlock/security/glass{ name = "Armory"; - req_access_txt = "3"; + req_access_txt = "1"; security_level = 1 }, /obj/machinery/door/firedoor/border_only{ @@ -61984,16 +62081,6 @@ }, /turf/open/floor/plasteel/dark, /area/engine/engineering) -"utm" = ( -/obj/structure/table/wood, -/obj/item/hand_tele, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/item/storage/pencil_holder/crew/fancy{ - pixel_y = 12 - }, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "utp" = ( /obj/structure/closet/athletic_mixed, /obj/item/pool/pool_noodle, @@ -64113,6 +64200,10 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/fore) +"viS" = ( +/obj/effect/landmark/start/chaplain, +/turf/template_noop, +/area/template_noop) "viU" = ( /obj/structure/table, /obj/structure/mirror{ @@ -64368,6 +64459,13 @@ }, /turf/open/floor/plasteel, /area/security/prison) +"vnl" = ( +/obj/item/kirbyplants/random, +/obj/machinery/airalarm{ + pixel_y = 24 + }, +/turf/open/floor/carpet/blue, +/area/crew_quarters/heads/captain) "vnp" = ( /obj/structure/chair{ dir = 8 @@ -65000,6 +65098,20 @@ }, /turf/open/floor/plasteel, /area/construction/mining/aux_base) +"vyH" = ( +/obj/structure/railing{ + dir = 5 + }, +/obj/structure/table/wood, +/obj/effect/turf_decal/siding/wood/thin{ + dir = 5 + }, +/obj/item/flashlight/lamp/green{ + pixel_x = 6; + pixel_y = 5 + }, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "vyL" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 8 @@ -66889,6 +67001,18 @@ }, /turf/open/floor/plasteel/cafeteria, /area/crew_quarters/heads/cmo) +"wgP" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "whu" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -67725,21 +67849,6 @@ }, /turf/open/floor/plating, /area/storage/tech) -"wxL" = ( -/obj/structure/table/wood, -/obj/machinery/requests_console{ - announcementConsole = 1; - department = "Captain's Desk"; - departmentType = 5; - name = "Captain RC"; - pixel_x = -30 - }, -/obj/machinery/photocopier/faxmachine{ - department = "Captain"; - name = "Captain's Fax Machine" - }, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "wyd" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ dir = 4 @@ -68217,6 +68326,15 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, /area/science/research) +"wKM" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/light_switch{ + pixel_y = 28 + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "wKP" = ( /obj/machinery/atmospherics/components/binary/pump{ dir = 8; @@ -68446,6 +68564,19 @@ }, /turf/open/floor/plasteel/white, /area/medical/virology) +"wPu" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "1-4"; + tag = "" + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "wPB" = ( /obj/machinery/status_display/ai{ pixel_x = -32 @@ -68522,6 +68653,15 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) +"wRD" = ( +/obj/machinery/shower{ + dir = 1 + }, +/obj/item/soap/deluxe, +/obj/item/bikehorn/rubberducky, +/obj/structure/curtain, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/heads/captain) "wRK" = ( /obj/structure/closet/secure_closet/personal/patient, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ @@ -68943,6 +69083,22 @@ /obj/structure/bodycontainer/morgue, /turf/open/floor/plasteel/dark, /area/security/brig) +"wZx" = ( +/mob/living/simple_animal/pet/fox/Renault, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 10 + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/effect/turf_decal/siding/wood/thin{ + dir = 4 + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "wZD" = ( /turf/open/floor/plasteel/white, /area/science/nanite) @@ -69059,10 +69215,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/aft) -"xdg" = ( -/obj/structure/disposalpipe/segment, -/turf/open/floor/wood, -/area/crew_quarters/heads/captain) "xdh" = ( /obj/item/radio/intercom{ name = "Station Intercom (General)"; @@ -69883,6 +70035,16 @@ }, /turf/open/floor/plasteel/white, /area/medical/storage) +"xvN" = ( +/obj/machinery/camera{ + c_tag = "Central Hallway East"; + dir = 4 + }, +/obj/effect/turf_decal/trimline/darkblue/filled/line/lower{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "xvO" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 4 @@ -70122,6 +70284,13 @@ }, /turf/open/floor/plasteel/dark, /area/science/xenobiology) +"xzH" = ( +/obj/machinery/light/small{ + dir = 1 + }, +/obj/machinery/vending/autodrobe/capdrobe, +/turf/open/floor/carpet/blue, +/area/crew_quarters/heads/captain) "xAi" = ( /obj/structure/closet/secure_closet/brig, /obj/effect/turf_decal/bot_red, @@ -70165,6 +70334,16 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating, /area/maintenance/port) +"xBj" = ( +/obj/structure/chair/comfy/brown{ + dir = 4 + }, +/obj/machinery/camera/motion{ + c_tag = "Captain's Quarters"; + dir = 1 + }, +/turf/open/floor/carpet/blue, +/area/crew_quarters/heads/captain) "xBl" = ( /obj/machinery/door/airlock/maintenance{ name = "Atmospherics Maintenance"; @@ -70284,6 +70463,14 @@ }, /turf/open/floor/plasteel, /area/science/robotics/lab) +"xCE" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/effect/turf_decal/ramp_middle{ + dir = 1 + }, +/turf/open/floor/wood/large, +/area/crew_quarters/heads/captain) "xCV" = ( /obj/structure/disposalpipe/segment{ dir = 5 @@ -71869,6 +72056,19 @@ /obj/structure/cable, /turf/open/floor/plasteel/white, /area/science/nanite) +"yje" = ( +/obj/structure/railing{ + dir = 4 + }, +/obj/effect/turf_decal/siding/wood/thin{ + dir = 4 + }, +/obj/machinery/papershredder, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/stone, +/area/crew_quarters/heads/captain) "yjf" = ( /obj/machinery/power/tracker, /obj/structure/cable/yellow{ @@ -103219,13 +103419,13 @@ hRj xjd oKX aZV -fqv -ruZ -nCL -cCz -wxL -kgY -eGj +bYT +jCH +ppk +oaq +mUE +hss +hbo aZV aZV aZV @@ -103476,18 +103676,18 @@ exk qkB xxK qNB -kVQ -bbw -bbw -pUK -sZn -gtE -bbw -mRq +ohr +wPu +kcc +oaq +flu +oxG +oNF +dnF aZV -oiA +xzH msT -ilk +gwZ bqH pJI kmp @@ -103733,18 +103933,18 @@ cDq daI lmd aZV -hgw -cEV -cEV -cEV -utm -mCx -diw -cEV -ekU +wKM +wgP +doS +oaq +fiz +hQo +qPH +qPH +tnN eDM nFx -oKL +xBj bqH pUH qup @@ -103990,18 +104190,18 @@ aPR mJr aPR aZV -ixh -jaj -jaj -kmy -kXE -lza -msz -mSa +cuT +wZx +bbE +xCE +jRb +tcm +oNF +nlI aZV jsR -kwY -oME +qrA +jNh bqH pVj quT @@ -104247,16 +104447,16 @@ oUy jkJ xgM aZV -bbo -bch -eEi +vnl kmy -tmz -bbw -oVK -mTm +hOk +oaq +dNO +guY +oNF +hVX aZV -nTb +hAI aZV aZV bqH @@ -104504,18 +104704,18 @@ onB daI wWA aZV -aWc -bdk -bdk -aUZ -bbw -ihF -bbw -bbw +aHY +qnQ +pkR +oaq +vyH +huD +hnh +yje aZV -sYn -aMV -bpk +hzP +tfl +wRD bqH bsj btI @@ -104761,14 +104961,14 @@ qjx bQi dbt aZV -bdq -bbw -bbw -bbw -bbw -bbw -bbw -bhG +hNx +bej +mzu +bRr +msk +msk +msk +bRs aZV aZV aZV @@ -105018,14 +105218,14 @@ mVl pKz hQK aZV -bdr -baQ -hwu -beg -bfC -bfl -xdg -xdg +mLc +iKa +rIQ +msN +cjK +doS +doS +pBC nsz kSk qWH @@ -105279,9 +105479,9 @@ aZV aZV aZV aZV -aZV -aZV -aZV +sXE +fbj +lHL aZV aZV bmA @@ -105532,9 +105732,9 @@ yfj jAv ipG nmg +gWx lFZ -lFZ -sZY +xvN sgo lFZ lFZ @@ -120689,7 +120889,7 @@ qQV qQV qQV qQV -qQV +viS qQV qQV qQV diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index ebdf7cc4a452..60a5237310a9 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -9278,7 +9278,7 @@ "aug" = ( /obj/structure/table/wood, /obj/item/pitchfork/demonic/ascended, -/obj/item/melee/powerfist, +/obj/item/clothing/gloves/powerfist/filled, /turf/open/floor/wood, /area/centcom/testchamber) "auh" = ( diff --git a/_maps/multiz_debug.json b/_maps/multiz_debug.json_bak similarity index 77% rename from _maps/multiz_debug.json rename to _maps/multiz_debug.json_bak index dd9a04df342d..6b2df33f2c61 100644 --- a/_maps/multiz_debug.json +++ b/_maps/multiz_debug.json_bak @@ -1,4 +1,5 @@ { + "__comment": "Map json disabled due to crash during unit testing", "map_name": "MultiZ Debug", "map_path": "map_files/debug", "map_file": "multiz.dmm", diff --git a/auxmos.dll b/auxmos.dll new file mode 100644 index 000000000000..6f76316c3f72 Binary files /dev/null and b/auxmos.dll differ diff --git a/auxmos.pdb b/auxmos.pdb new file mode 100644 index 000000000000..c86057ac0181 Binary files /dev/null and b/auxmos.pdb differ diff --git a/byond-extools.dll b/byond-extools.dll deleted file mode 100644 index 37efe6c6e403..000000000000 Binary files a/byond-extools.dll and /dev/null differ diff --git a/byond-extools.pdb b/byond-extools.pdb deleted file mode 100644 index b0665dcfea62..000000000000 Binary files a/byond-extools.pdb and /dev/null differ diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index b63cb9091b41..4424f9a8ca30 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -4,8 +4,6 @@ //Defines copying names of mutations in all cases, make sure to change this if you change mutation's type #define HULK /datum/mutation/human/hulk -#define ACTIVE_HULK /datum/mutation/human/active_hulk -#define GENETICS_HULK /datum/mutation/human/genetics_hulk #define XRAY /datum/mutation/human/thermal/x_ray #define SPACEMUT /datum/mutation/human/space_adaptation #define HEATMUT /datum/mutation/human/heat_adaptation diff --git a/code/__DEFINES/MC.dm b/code/__DEFINES/MC.dm index 7c84b693e31c..aa1d6214bd26 100644 --- a/code/__DEFINES/MC.dm +++ b/code/__DEFINES/MC.dm @@ -9,6 +9,8 @@ Master.current_ticklimit = original_tick_limit;\ } +#define MC_TICK_REMAINING_MS ((Master.current_ticklimit - TICK_USAGE) * world.tick_lag) + // Used to smooth out costs to try and avoid oscillation. #define MC_AVERAGE_FAST(average, current) (0.7 * (average) + 0.3 * (current)) #define MC_AVERAGE(average, current) (0.8 * (average) + 0.2 * (current)) diff --git a/code/__DEFINES/_auxtools.dm b/code/__DEFINES/_auxtools.dm new file mode 100644 index 000000000000..a907be8ecf8f --- /dev/null +++ b/code/__DEFINES/_auxtools.dm @@ -0,0 +1,8 @@ +/proc/auxtools_stack_trace(msg) + CRASH(msg) + +/proc/auxtools_expr_stub() + CRASH("auxtools not loaded") + +/proc/enable_debugging(mode, port) + CRASH("auxtools not loaded") diff --git a/code/__DEFINES/_bitfields.dm b/code/__DEFINES/_bitfields.dm new file mode 100644 index 000000000000..19a962fbffe5 --- /dev/null +++ b/code/__DEFINES/_bitfields.dm @@ -0,0 +1,4 @@ +#define DEFINE_BITFIELD(_variable, _flags) /datum/bitfield/##_variable { \ + flags = ##_flags; \ + variable = #_variable; \ +} diff --git a/code/__DEFINES/ai.dm b/code/__DEFINES/ai.dm index 3107edc5b84a..e0d742e1ad66 100644 --- a/code/__DEFINES/ai.dm +++ b/code/__DEFINES/ai.dm @@ -4,6 +4,8 @@ ///Temperature limit of all AI machinery #define AI_TEMP_LIMIT 288.15 //15C, much hotter than a normal server room for leniency :) +#define AI_HEATSINK_CAPACITY 5000 +#define AI_HEATSINK_COEFF 1 ///How many ticks can an AI data core store? When this amount of ticks have passed while it's in an INVALID state it can no longer be used by an AI #define MAX_AI_DATA_CORE_TICKS 45 diff --git a/code/__DEFINES/announcements.dm b/code/__DEFINES/announcements.dm new file mode 100644 index 000000000000..3a2edf6d6f77 --- /dev/null +++ b/code/__DEFINES/announcements.dm @@ -0,0 +1,7 @@ +// Priority-type announcement messages for `priority_announcement()` +/// Prefix this announcement with "Priority Announcement" +#define ANNOUNCEMENT_TYPE_PRIORITY "Priority" +/// Make it sound like it's coming from the Captain +#define ANNOUNCEMENT_TYPE_CAPTAIN "Captain" +/// Make it sound like it's coming from the Syndicate +#define ANNOUNCEMENT_TYPE_SYNDICATE "Syndicate" diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index 8060c7883b78..307e24ad60fa 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -110,6 +110,7 @@ #define PATH_SIDE "Side" +#define PATH_NONE "Unpledged" #define PATH_ASH "Ash" #define PATH_RUST "Rust" #define PATH_FLESH "Flesh" diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm index ea7c98d075c9..62eeffd3106f 100644 --- a/code/__DEFINES/atmospherics.dm +++ b/code/__DEFINES/atmospherics.dm @@ -1,15 +1,3 @@ -//LISTMOS -//indices of values in gas lists. -#define MOLES 1 -#define ARCHIVE 2 -#define GAS_META 3 -#define META_GAS_SPECIFIC_HEAT 1 -#define META_GAS_NAME 2 -#define META_GAS_MOLES_VISIBLE 3 -#define META_GAS_OVERLAY 4 -#define META_GAS_DANGER 5 -#define META_GAS_ID 6 -#define META_GAS_FUSION_POWER 7 //ATMOS //stuff you should probably leave well alone! /// kPa*L/(K*mol) @@ -437,6 +425,32 @@ /// north/south east/west doesn't matter, auto normalize on build. #define PIPING_CARDINAL_AUTONORMALIZE (1<<3) +// Gas defines because i hate typepaths +#define GAS_O2 "o2" +#define GAS_N2 "n2" +#define GAS_CO2 "co2" +#define GAS_PLASMA "plasma" +#define GAS_H2O "water_vapor" +#define GAS_HYPERNOB "hypernob" +#define GAS_NITROUS "n2o" +#define GAS_NITRIUM "no2" +#define GAS_TRITIUM "tritium" +#define GAS_BZ "bz" +#define GAS_PLUOXIUM "pluox" +#define GAS_MIASMA "miasma" +#define GAS_H2 "hydrogen" +#define GAS_FREON "freon" +#define GAS_HEALIUM "healium" +#define GAS_PLUONIUM "pluonium" +#define GAS_HALON "halon" +#define GAS_ANTINOB "antinob" +#define GAS_ZAUKER "zauker" +#define GAS_HEXANE "hexane" +#define GAS_DILITHIUM "dilithium" + +#define GAS_FLAG_DANGEROUS (1<<0) +#define GAS_FLAG_BREATH_PROC (1<<1) + //HELPERS #define PIPING_LAYER_SHIFT(T, PipingLayer) \ if(T.dir & (NORTH|SOUTH)) { \ @@ -458,24 +472,6 @@ T.pixel_x = (PipingLayer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X;\ T.pixel_y = (PipingLayer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y; -#ifdef TESTING -GLOBAL_LIST_INIT(atmos_adjacent_savings, list(0,0)) -#define CALCULATE_ADJACENT_TURFS(T) if (SSadjacent_air.queue[T]) { GLOB.atmos_adjacent_savings[1] += 1 } else { GLOB.atmos_adjacent_savings[2] += 1; SSadjacent_air.queue[T] = 1 } -#else -#define CALCULATE_ADJACENT_TURFS(T) SSadjacent_air.queue[T] = 1 -#endif - -GLOBAL_VAR(atmos_extools_initialized) // this must be an uninitialized (null) one or init_monstermos will be called twice because reasons -#define ATMOS_EXTOOLS_CHECK if(!GLOB.atmos_extools_initialized){\ - GLOB.atmos_extools_initialized=TRUE;\ - if(fexists(EXTOOLS)){\ - var/result = LIBCALL(EXTOOLS,"init_monstermos")();\ - if(result != "ok") {CRASH(result);}\ - } else {\ - CRASH("byond-extools.dll does not exist!");\ - }\ -} - GLOBAL_LIST_INIT(pipe_paint_colors, list( "amethyst" = rgb(130,43,255), //supplymain "blue" = rgb(0,0,255), @@ -494,4 +490,14 @@ GLOBAL_LIST_INIT(pipe_paint_colors, list( #define MIASMA_CORPSE_MOLES 0.02 #define MIASMA_GIBS_MOLES 0.005 +//PIPENET UPDATE STATUS +#define PIPENET_UPDATE_STATUS_DORMANT 0 +#define PIPENET_UPDATE_STATUS_REACT_NEEDED 1 +#define PIPENET_UPDATE_STATUS_RECONCILE_NEEDED 2 + #define TURF_SHARES(T) (LAZYLEN(T.atmos_adjacent_turfs)) + +//Defines for air alarm severities in areas. +#define ATMOS_ALARM_SEVERE "severe" +#define ATMOS_ALARM_MINOR "minor" +#define ATMOS_ALARM_CLEAR "clear" diff --git a/code/__DEFINES/bindings.dm b/code/__DEFINES/bindings.dm new file mode 100644 index 000000000000..18f8586433bf --- /dev/null +++ b/code/__DEFINES/bindings.dm @@ -0,0 +1,182 @@ +#define AUXMOS (__detect_auxmos()) + +/proc/__detect_auxmos() + if (world.system_type == UNIX) + return "libauxmos" + else + return "auxmos" + +/turf/proc/__update_auxtools_turf_adjacency_info() + return call_ext(AUXMOS, "byond:hook_infos_ffi")(src) + +/turf/proc/update_air_ref(flag) + return call_ext(AUXMOS, "byond:hook_register_turf_ffi")(src, flag) + +/datum/gas_mixture/proc/__auxtools_parse_gas_string(string) + return call_ext(AUXMOS, "byond:parse_gas_string_ffi")(src, string) + +/datum/controller/subsystem/air/proc/get_max_gas_mixes() + return call_ext(AUXMOS, "byond:hook_max_gas_mixes_ffi")() + +/datum/controller/subsystem/air/proc/get_amt_gas_mixes() + return call_ext(AUXMOS, "byond:hook_amt_gas_mixes_ffi")() + +/proc/equalize_all_gases_in_list(gas_list) + return call_ext(AUXMOS, "byond:equalize_all_hook_ffi")(gas_list) + +/datum/gas_mixture/proc/get_oxidation_power(temp) + return call_ext(AUXMOS, "byond:oxidation_power_hook_ffi")(src, temp) + +/datum/gas_mixture/proc/get_fuel_amount(temp) + return call_ext(AUXMOS, "byond:fuel_amount_hook_ffi")(src, temp) + +/datum/gas_mixture/proc/equalize_with(total) + return call_ext(AUXMOS, "byond:equalize_with_hook_ffi")(src, total) + +/datum/gas_mixture/proc/transfer_ratio_to(other, ratio) + return call_ext(AUXMOS, "byond:transfer_ratio_hook_ffi")(src, other, ratio) + +/datum/gas_mixture/proc/transfer_to(other, moles) + return call_ext(AUXMOS, "byond:transfer_hook_ffi")(src, other, moles) + +/datum/gas_mixture/proc/adjust_heat(temp) + return call_ext(AUXMOS, "byond:adjust_heat_hook_ffi")(src, temp) + +/datum/gas_mixture/proc/react(holder) + return call_ext(AUXMOS, "byond:react_hook_ffi")(src, holder) + +/datum/gas_mixture/proc/compare(other) + return call_ext(AUXMOS, "byond:compare_hook_ffi")(src, other) + +/datum/gas_mixture/proc/clear() + return call_ext(AUXMOS, "byond:clear_hook_ffi")(src) + +/datum/gas_mixture/proc/mark_immutable() + return call_ext(AUXMOS, "byond:mark_immutable_hook_ffi")(src) + +/datum/gas_mixture/proc/scrub_into(into, ratio_v, gas_list) + return call_ext(AUXMOS, "byond:scrub_into_hook_ffi")(src, into, ratio_v, gas_list) + +/datum/gas_mixture/proc/get_by_flag(flag_val) + return call_ext(AUXMOS, "byond:get_by_flag_hook_ffi")(src, flag_val) + +/datum/gas_mixture/proc/__remove_by_flag(into, flag_val, amount_val) + return call_ext(AUXMOS, "byond:remove_by_flag_hook_ffi")(src, into, flag_val, amount_val) + +/datum/gas_mixture/proc/divide(num_val) + return call_ext(AUXMOS, "byond:divide_hook_ffi")(src, num_val) + +/datum/gas_mixture/proc/multiply(num_val) + return call_ext(AUXMOS, "byond:multiply_hook_ffi")(src, num_val) + +/datum/gas_mixture/proc/subtract(num_val) + return call_ext(AUXMOS, "byond:subtract_hook_ffi")(src, num_val) + +/datum/gas_mixture/proc/add(num_val) + return call_ext(AUXMOS, "byond:add_hook_ffi")(src, num_val) + +/datum/gas_mixture/proc/adjust_multi(...) + var/list/args_copy = args.Copy() + args_copy.Insert(1, src) + return call_ext(AUXMOS, "byond:adjust_multi_hook_ffi")(arglist(args_copy)) + +/datum/gas_mixture/proc/adjust_moles_temp(id_val, num_val, temp_val) + return call_ext(AUXMOS, "byond:adjust_moles_temp_hook_ffi")(src, id_val, num_val, temp_val) + +/datum/gas_mixture/proc/adjust_moles(id_val, num_val) + return call_ext(AUXMOS, "byond:adjust_moles_hook_ffi")(src, id_val, num_val) + +/datum/gas_mixture/proc/set_moles(gas_id, amt_val) + return call_ext(AUXMOS, "byond:set_moles_hook_ffi")(src, gas_id, amt_val) + +/datum/gas_mixture/proc/get_moles(gas_id) + return call_ext(AUXMOS, "byond:get_moles_hook_ffi")(src, gas_id) + +/datum/gas_mixture/proc/set_volume(vol_arg) + return call_ext(AUXMOS, "byond:set_volume_hook_ffi")(src, vol_arg) + +/datum/gas_mixture/proc/partial_heat_capacity(gas_id) + return call_ext(AUXMOS, "byond:partial_heat_capacity_ffi")(src, gas_id) + +/datum/gas_mixture/proc/set_temperature(arg_temp) + return call_ext(AUXMOS, "byond:set_temperature_hook_ffi")(src, arg_temp) + +/datum/gas_mixture/proc/get_gases() + return call_ext(AUXMOS, "byond:get_gases_hook_ffi")(src) + +/datum/gas_mixture/proc/temperature_share(...) + var/list/args_copy = args.Copy() + args_copy.Insert(1, src) + return call_ext(AUXMOS, "byond:temperature_share_hook_ffi")(arglist(args_copy)) + +/datum/gas_mixture/proc/copy_from(giver) + return call_ext(AUXMOS, "byond:copy_from_hook_ffi")(src, giver) + +/datum/gas_mixture/proc/__remove(into, amount_arg) + return call_ext(AUXMOS, "byond:remove_hook_ffi")(src, into, amount_arg) + +/datum/gas_mixture/proc/__remove_ratio(into, ratio_arg) + return call_ext(AUXMOS, "byond:remove_ratio_hook_ffi")(src, into, ratio_arg) + +/datum/gas_mixture/proc/merge(giver) + return call_ext(AUXMOS, "byond:merge_hook_ffi")(src, giver) + +/datum/gas_mixture/proc/thermal_energy() + return call_ext(AUXMOS, "byond:thermal_energy_hook_ffi")(src) + +/datum/gas_mixture/proc/return_volume() + return call_ext(AUXMOS, "byond:return_volume_hook_ffi")(src) + +/datum/gas_mixture/proc/return_temperature() + return call_ext(AUXMOS, "byond:return_temperature_hook_ffi")(src) + +/datum/gas_mixture/proc/return_pressure() + return call_ext(AUXMOS, "byond:return_pressure_hook_ffi")(src) + +/datum/gas_mixture/proc/total_moles() + return call_ext(AUXMOS, "byond:total_moles_hook_ffi")(src) + +/datum/gas_mixture/proc/set_min_heat_capacity(arg_min) + return call_ext(AUXMOS, "byond:min_heat_cap_hook_ffi")(src, arg_min) + +/datum/gas_mixture/proc/heat_capacity() + return call_ext(AUXMOS, "byond:heat_cap_hook_ffi")(src) + +/datum/gas_mixture/proc/__gasmixture_unregister() + return call_ext(AUXMOS, "byond:unregister_gasmixture_hook_ffi")(src) + +/datum/gas_mixture/proc/__gasmixture_register() + return call_ext(AUXMOS, "byond:register_gasmixture_hook_ffi")(src) + +/proc/process_atmos_callbacks(remaining) + return call_ext(AUXMOS, "byond:atmos_callback_handle_ffi")(remaining) + +/datum/controller/subsystem/air/proc/process_turf_equalize_auxtools(remaining) + return call_ext(AUXMOS, "byond:equalize_hook_ffi")(src, remaining) + +/datum/controller/subsystem/air/proc/process_excited_groups_auxtools(remaining) + return call_ext(AUXMOS, "byond:groups_hook_ffi")(src, remaining) + +/proc/finalize_gas_refs() + return call_ext(AUXMOS, "byond:finalize_gas_refs_ffi")() + +/datum/controller/subsystem/air/proc/auxtools_update_reactions() + return call_ext(AUXMOS, "byond:update_reactions_ffi")() + +/proc/auxtools_atmos_init(gas_data) + return call_ext(AUXMOS, "byond:hook_init_ffi")(gas_data) + +/proc/_auxtools_register_gas(gas) + return call_ext(AUXMOS, "byond:hook_register_gas_ffi")(gas) + +/proc/__auxmos_shutdown() + return call_ext(AUXMOS, "byond:auxmos_shutdown_ffi")() + +/datum/controller/subsystem/air/proc/process_turfs_auxtools(remaining) + return call_ext(AUXMOS, "byond:process_turf_hook_ffi")(src, remaining) + +/datum/controller/subsystem/air/proc/finish_turf_processing_auxtools(time_remaining) + return call_ext(AUXMOS, "byond:finish_process_turfs_ffi")(time_remaining) + +/datum/controller/subsystem/air/proc/thread_running() + return call_ext(AUXMOS, "byond:thread_running_hook_ffi")() diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index ef64e821a051..b6fbca4f6dce 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -346,3 +346,22 @@ GLOBAL_LIST_INIT(cable_colors, list( #define COLOR_INPUT_DISABLED "#F0F0F0" #define COLOR_INPUT_ENABLED "#D3B5B5" + +/// Change color to red on ANSI terminal output, if enabled with -DANSICOLORS. +#ifdef ANSICOLORS +#define TEST_OUTPUT_RED(text) "\x1B\x5B1;31m[text]\x1B\x5B0m" +#else +#define TEST_OUTPUT_RED(text) (text) +#endif +/// Change color to green on ANSI terminal output, if enabled with -DANSICOLORS. +#ifdef ANSICOLORS +#define TEST_OUTPUT_GREEN(text) "\x1B\x5B1;32m[text]\x1B\x5B0m" +#else +#define TEST_OUTPUT_GREEN(text) (text) +#endif +/// Change color to yellow on ANSI terminal output, if enabled with -DANSICOLORS. +#ifdef ANSICOLORS +#define TEST_OUTPUT_YELLOW(text) "\x1B\x5B1;33m[text]\x1B\x5B0m" +#else +#define TEST_OUTPUT_YELLOW(text) (text) +#endif diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index ebc28a4d5700..f699cb55ca6c 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -34,6 +34,8 @@ #define BIO "bio" /// Involves ionizing radiation. #define RAD "rad" +/// Involves electric shock. +#define ELECTRIC "electric" /// Involves fire or temperature extremes. #define FIRE "fire" /// Involves corrosive substances. @@ -236,8 +238,8 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( #define EXPLODE_LIGHT 3 #define EXPLODE_GIB_THRESHOLD 50 //ex_act() with EXPLODE_DEVASTATE severity will gib mobs with less than this much bomb armor -#define EMP_HEAVY 1 -#define EMP_LIGHT 2 +#define EMP_LIGHT 5 // maximum severity level without severe effects like organ failure and paralysis +#define EMP_HEAVY 10 // max severity from most sources so you can't use a 5 billion tile EMP to instakill people #define GRENADE_CLUMSY_FUMBLE 1 #define GRENADE_NONCLUMSY_FUMBLE 2 diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm index 88a29ec697a4..63a366ea1aea 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm @@ -19,6 +19,14 @@ #define COMSIG_ATOM_SET_LIGHT_COLOR "atom_set_light_color" ///Called right after the atom changes the value of light_color to a different one, from base of [/atom/proc/set_light_color]: (old_color) #define COMSIG_ATOM_UPDATE_LIGHT_COLOR "atom_update_light_color" +///Called right before the atom changes the value of light_angle to a different one, from base [atom/proc/set_light_angle]: (new_angle) +#define COMSIG_ATOM_SET_LIGHT_ANGLE "atom_set_light_angle" +///Called right after the atom changes the value of light_angle to a different one, from base of [/atom/proc/set_light_angle]: (old_angle) +#define COMSIG_ATOM_UPDATE_LIGHT_ANGLE "atom_update_light_angle" +///Called right before the atom changes the value of light_dir to a different one, from base [atom/proc/set_light_dir]: (new_dir) +#define COMSIG_ATOM_SET_LIGHT_DIR "atom_set_light_dir" +///Called right after the atom changes the value of light_dir to a different one, from base of [/atom/proc/set_light_dir]: (old_dir) +#define COMSIG_ATOM_UPDATE_LIGHT_DIR "atom_update_light_dir" ///Called right before the atom changes the value of light_on to a different one, from base [atom/proc/set_light_on]: (new_value) #define COMSIG_ATOM_SET_LIGHT_ON "atom_set_light_on" ///Called right after the atom changes the value of light_on to a different one, from base of [/atom/proc/set_light_on]: (old_value) diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm index 720e132aa190..2ef0297bd972 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm @@ -77,14 +77,6 @@ #define COMSIG_MOVABLE_SET_ANCHORED "movable_set_anchored" ///from base of atom/movable/setGrabState(): (newstate) #define COMSIG_MOVABLE_SET_GRAB_STATE "living_set_grab_state" -///Called when the movable tries to change its dynamic light color setting, from base atom/movable/lighting_overlay_set_color(): (color) -#define COMSIG_MOVABLE_LIGHT_OVERLAY_SET_RANGE "movable_light_overlay_set_color" -///Called when the movable tries to change its dynamic light power setting, from base atom/movable/lighting_overlay_set_power(): (power) -#define COMSIG_MOVABLE_LIGHT_OVERLAY_SET_POWER "movable_light_overlay_set_power" -///Called when the movable tries to change its dynamic light range setting, from base atom/movable/lighting_overlay_set_range(): (range) -#define COMSIG_MOVABLE_LIGHT_OVERLAY_SET_COLOR "movable_light_overlay_set_range" -///Called when the movable tries to toggle its dynamic light LIGHTING_ON status, from base atom/movable/lighting_overlay_toggle_on(): (new_state) -#define COMSIG_MOVABLE_LIGHT_OVERLAY_TOGGLE_ON "movable_light_overlay_toggle_on" ///called when the movable's glide size is updated: (new_glide_size) #define COMSIG_MOVABLE_UPDATE_GLIDE_SIZE "movable_glide_size" ///Called when a movable is hit by a plunger in layer mode, from /obj/item/plunger/attack_atom() diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_living.dm index b8dd7713d195..56d9754eb42f 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_living.dm @@ -26,6 +26,7 @@ #define COMSIG_LIVING_EXTINGUISHED "living_extinguished" ///from base of mob/living/electrocute_act(): (shock_damage, source, siemens_coeff, flags) #define COMSIG_LIVING_ELECTROCUTE_ACT "living_electrocute_act" + #define COMPONENT_NO_ELECTROCUTE_ACT (1<<0) ///sent when items with siemen coeff. of 0 block a shock: (power_source, source, siemens_coeff, dist_check) #define COMSIG_LIVING_SHOCK_PREVENTED "living_shock_prevented" ///sent by stuff like stunbatons and tasers: () diff --git a/code/__DEFINES/directional.dm b/code/__DEFINES/directional.dm index 192a57706772..85d746a43882 100644 --- a/code/__DEFINES/directional.dm +++ b/code/__DEFINES/directional.dm @@ -8,6 +8,3 @@ #define TEXT_SOUTH "[SOUTH]" #define TEXT_EAST "[EAST]" #define TEXT_WEST "[WEST]" - -/// Inverse direction, taking into account UP|DOWN if necessary. -#define REVERSE_DIR(dir) ( ((dir & 85) << 1) | ((dir & 170) >> 1) ) diff --git a/code/__DEFINES/extools.dm b/code/__DEFINES/extools.dm deleted file mode 100644 index 0c20aeec1376..000000000000 --- a/code/__DEFINES/extools.dm +++ /dev/null @@ -1,144 +0,0 @@ -#define EXTOOLS_SUCCESS "SUCCESS" -#define EXTOOLS_FAILED "FAIL" -GLOBAL_VAR_INIT(enable_memdump, 0) - -/* - Core - Provides necessary functionality for other modules. - Initializing any other modules also initializes this so it shouldn't be necessary to call this. -*/ - -/proc/extools_initialize() - return LIBCALL(EXTOOLS, "core_initialize")() == EXTOOLS_SUCCESS - -/* - TFFI - Threaded FFI - All DLL calls are automatically threaded off. - Black magic is used to suspend (sleep) the currently executing proc, allowing non-blocking FFI. - You may call a DLL function and sleep until it returns, pass a callback to be called with the result, - or call resolve() on the /datum/promise to receive the return value at any time. - Example: - var/x = call_wait("sample.dll", "do_work", "arg1", "arg2", "arg3") - - Calls the do_work function from sample.dll with 3 arguments. The proc sleeps until do_work returns. - var/datum/promise/P = call_async("sample.dll", "do_work", "arg1") - ... do something else ... - var/result = P.resolve() - - Calls do_work with 1 argument. Returns a promise object. Runs some other code before calling P.resolve() to obtain the result. - /proc/print_result(result) - world << result - call_cb("sample.dll", "do_work", /proc/print_result, "arg1", "arg2") - - Calls do_work with 2 arguments. The callback is invoked with the result as the single argument. Execution resumes immediately. -*/ - -#if 0 - -/proc/tffi_initialize() - return LIBCALL(EXTOOLS, "tffi_initialize")() == EXTOOLS_SUCCESS - -GLOBAL_VAR_INIT(fallback_alerted, FALSE) -GLOBAL_VAR_INIT(next_promise_id, 0) - -/datum/promise - var/completed = FALSE - var/result = "" - var/callback_context = GLOBAL_PROC - var/callback_proc = null - var/__id = 0 - -/datum/promise/New() - __id = next_promise_id++ //please don't create more than 10^38 promises in a single tick - -//This proc's bytecode is overwritten to allow suspending and resuming on demand. -//None of the code here should run. -/datum/promise/proc/__internal_resolve(ref, id) - if(!fallback_alerted && world.system_type != UNIX) // the rewriting is currently broken on Linux. - world << "TFFI: __internal_resolve has not been rewritten, the TFFI DLL was not loaded correctly." - world.log << "TFFI: __internal_resolve has not been rewritten, the TFFI DLL was not loaded correctly." - fallback_alerted = TRUE - while(!completed) - sleep(1) - //It might be better to just fail and notify the user that something went wrong. - -/datum/promise/proc/__resolve_callback() - __internal_resolve("\ref[src]", __id) - if(callback_context == GLOBAL_PROC) - call(callback_proc)(result) - else - call(callback_context, callback_proc)(result) - -/datum/promise/proc/resolve() - __internal_resolve("\ref[src]", __id) - return result - -/proc/call_async() - var/list/arguments = args.Copy() - var/datum/promise/P = new - arguments.Insert(1, "\ref[P]") - LIBCALL(EXTOOLS, "call_async")(arglist(arguments)) - return P - -/proc/call_cb() - var/list/arguments = args.Copy() - var/context = arguments[3] - var/callback = arguments[4] - arguments.Cut(3, 5) - var/datum/promise/P = new - P.callback_context = context - P.callback_proc = callback - arguments.Insert(1, "\ref[P]") - LIBCALL(EXTOOLS, "call_async")(arglist(arguments)) - spawn(0) - P.__resolve_callback() - -/proc/call_wait() - return call_async(arglist(args)).resolve() - -#endif - -/* - Extended Profiling - High precision in-depth performance profiling. - Turning on extended profiling for a proc will cause each execution of it to generate a file in the ./profiles directory - containing a breakdown of time spent executing the proc and each sub-proc it calls. Import the file into https://www.speedscope.app/ to - view a good visual representation. - Be aware that sleeping counts as stopping and restarting the execution of the proc, which will generate multiple files, one between each sleep. - For large procs the profiles may become unusably large. Optimizations pending. - Example: - start_profiling(/datum/explosion/New) - - Enables profiling for /datum/explosion/New(), which will produce a detailed breakdown of each explosion that occurs afterwards. - stop_profiling(/datum/explosion/New) - - Disables profiling for explosions. Any currently running profiles will stop when the proc finishes executing or enters a sleep. -*/ - -/proc/profiling_initialize() - return LIBCALL(EXTOOLS, "extended_profiling_initialize")() == EXTOOLS_SUCCESS - -/proc/start_profiling(procpath) - LIBCALL(EXTOOLS, "enable_extended_profiling")("[procpath]") - -/proc/stop_profiling(procpath) - LIBCALL(EXTOOLS, "disable_extended_profiling")("[procpath]") - -/* - Debug Server - High and low level debugging of DM code. - Calling debugger_initialize will start a debug server that allows connections from frontends, - such as SpaceManiac's VSCode extension for line-by-line debugging (and more), or Steamport's - Somnium for bytecode inspection. - Call with pause = TRUE to wait until the debugger connected and immediately break on the next instruction after the call. -*/ - -/proc/debugger_initialize(pause = FALSE) - return LIBCALL(EXTOOLS, "debug_initialize")(pause ? "pause" : "") == EXTOOLS_SUCCESS - -/* - Misc -*/ - -//Programatically enable and disable the built-in byond profiler. Useful if you want to, for example, profile subsystem initializations. -/proc/enable_profiling() - return LIBCALL(EXTOOLS, "enable_profiling")() == EXTOOLS_SUCCESS - -/proc/disable_profiling() - return LIBCALL(EXTOOLS, "disable_profiling")() == EXTOOLS_SUCCESS - -// Will dump the server's in-depth memory profile into the file specified. -/proc/dump_memory_profile(file_name) - return LIBCALL(EXTOOLS, "dump_memory_usage")(file_name) == EXTOOLS_SUCCESS diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index 51f2e3c9bca7..92c389063f8a 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -4,6 +4,10 @@ #define ALL (~0) //For convenience. #define NONE 0 +/* Directions */ +///All the cardinal direction bitflags. +#define ALL_CARDINALS (NORTH|SOUTH|EAST|WEST) + //for convenience #define ENABLE_BITFIELD(variable, flag) (variable |= (flag)) #define DISABLE_BITFIELD(variable, flag) (variable &= ~(flag)) @@ -99,17 +103,18 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 the atom/checkpass() proc uses them (tables will call movable atom checkpass(PASSTABLE) for example) */ //flags for pass_flags -#define PASSTABLE (1<<0) -#define PASSGLASS (1<<1) -#define PASSGRILLE (1<<2) -#define PASSBLOB (1<<3) -#define PASSMOB (1<<4) -#define PASSCLOSEDTURF (1<<5) -#define LETPASSTHROW (1<<6) -#define PASSMACHINES (1<<7) -#define PASSCOMPUTER (1<<8) -#define PASSSTRUCTURE (1<<9) -#define PASSDOORS (1<<10) +#define PASSTABLE (1<<0) +#define PASSGLASS (1<<1) +#define PASSGRILLE (1<<2) +#define PASSBLOB (1<<3) +#define PASSMOB (1<<4) +#define PASSCLOSEDTURF (1<<5) +#define LETPASSTHROW (1<<6) +#define PASSMACHINES (1<<7) +#define PASSCOMPUTER (1<<8) +#define PASSSTRUCTURE (1<<9) +#define PASSDOOR (1<<10) +#define PASSMECH (1<<11) //Movement Types #define GROUND (1<<0) diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm index 18f3e09c7a6c..57271b6bcdee 100644 --- a/code/__DEFINES/lighting.dm +++ b/code/__DEFINES/lighting.dm @@ -4,12 +4,17 @@ #define STATIC_LIGHT 1 ///Light made by masking the lighting darkness plane. #define MOVABLE_LIGHT 2 +/// Light made by masking the lighting darkness plane, and is directional. +#define MOVABLE_LIGHT_DIRECTIONAL 3 +///Light made by masking the lighting darkness plane, and is a directionally focused beam. +#define MOVABLE_LIGHT_BEAM 4 + +#define NONSENSICAL_VALUE -99999 ///Is a movable light source attached to another movable (its loc), meaning that the lighting component should go one level deeper. #define LIGHT_ATTACHED (1<<0) - -///This light doesn't affect turf's lumcount calculations. Set to 1<<15 to ignore conflicts -#define LIGHT_NO_LUMCOUNT (1<<15) +/// Freezes a light in its current state, blocking any attempts at modification +#define LIGHT_FROZEN (1<<1) //Bay lighting engine shit, not in /code/modules/lighting because BYOND is being shit about it /// frequency, in 1/10ths of a second, of the lighting process @@ -67,6 +72,7 @@ #define DYNAMIC_LIGHTING_FORCED 2 /// dynamic lighting enabled only if starlight is. #define DYNAMIC_LIGHTING_IFSTARLIGHT 3 + #define IS_DYNAMIC_LIGHTING(A) A.dynamic_lighting diff --git a/code/__DEFINES/magic.dm b/code/__DEFINES/magic.dm index 7eeae378337c..34ec4b6659b6 100644 --- a/code/__DEFINES/magic.dm +++ b/code/__DEFINES/magic.dm @@ -64,7 +64,7 @@ /// (effectively making the invocation flavor, instead of required). #define SPELL_CASTABLE_WITHOUT_INVOCATION (1 << 8) -/*DEFINE_BITFIELD(spell_requirements, list( +DEFINE_BITFIELD(spell_requirements, list( "SPELL_CASTABLE_AS_BRAIN" = SPELL_CASTABLE_AS_BRAIN, "SPELL_CASTABLE_WHILE_PHASED" = SPELL_CASTABLE_WHILE_PHASED, "SPELL_CASTABLE_WITHOUT_INVOCATION" = SPELL_CASTABLE_WITHOUT_INVOCATION, @@ -74,7 +74,7 @@ "SPELL_REQUIRES_NO_ANTIMAGIC" = SPELL_REQUIRES_NO_ANTIMAGIC, "SPELL_REQUIRES_STATION" = SPELL_REQUIRES_STATION, "SPELL_REQUIRES_WIZARD_GARB" = SPELL_REQUIRES_WIZARD_GARB, -))*/ +)) // Bitflags for teleport spells /// Whether the teleport spell skips over space turfs @@ -92,11 +92,11 @@ /// Holy magic resistance that blocks unholy magic (revenant, vampire, voice of god) #define MAGIC_RESISTANCE_HOLY (1<<2) -/*DEFINE_BITFIELD(antimagic_flags, list( +DEFINE_BITFIELD(antimagic_flags, list( "MAGIC_RESISTANCE" = MAGIC_RESISTANCE, "MAGIC_RESISTANCE_HOLY" = MAGIC_RESISTANCE_HOLY, "MAGIC_RESISTANCE_MIND" = MAGIC_RESISTANCE_MIND, -))*/ +)) /** * Checks if our mob is jaunting actively (within a phased mob object) diff --git a/code/__DEFINES/maths.dm b/code/__DEFINES/maths.dm index 74cf20faa8eb..be6ebb9eb03e 100644 --- a/code/__DEFINES/maths.dm +++ b/code/__DEFINES/maths.dm @@ -228,5 +228,22 @@ #define DT_PROB(prob_per_second_percent, delta_time) (prob(100*DT_PROB_RATE(prob_per_second_percent/100, delta_time))) // ) +/// Taxicab distance--gets you the **actual** time it takes to get from one turf to another due to how we calculate diagonal movement +#define MANHATTAN_DISTANCE(a, b) (abs(a.x - b.x) + abs(a.y - b.y)) +// ) + +/// A function that exponentially approaches a maximum value of L +/// k is the rate at which is approaches L, x_0 is the point where the function = 0 +#define LOGISTIC_FUNCTION(L,k,x,x_0) (L/(1+(NUM_E**(-k*(x-x_0))))) + +// ) +/// Make sure something is a boolean TRUE/FALSE 1/0 value, since things like bitfield & bitflag doesn't always give 1s and 0s. +#define FORCE_BOOLEAN(x) ((x)? TRUE : FALSE) + +// ) +/// Gives the number of pixels in an orthogonal line of tiles. +#define TILES_TO_PIXELS(tiles) (tiles * PIXELS) +// ) + /// The number of cells in a taxicab circle (rasterized diamond) of radius X. #define DIAMOND_AREA(X) (1 + 2*(X)*((X)+1)) diff --git a/code/__DEFINES/profile.dm b/code/__DEFINES/profile.dm index 5fc847890145..ec79d942a984 100644 --- a/code/__DEFINES/profile.dm +++ b/code/__DEFINES/profile.dm @@ -27,3 +27,5 @@ #define PROFILE_ITEM_LEN 2 #define PROFILE_ITEM_TIME 1 #define PROFILE_ITEM_COUNT 2 + +GLOBAL_VAR_INIT(enable_memdump, 0) diff --git a/code/__DEFINES/reactions.dm b/code/__DEFINES/reactions.dm index 722bb656567a..f032c69a70de 100644 --- a/code/__DEFINES/reactions.dm +++ b/code/__DEFINES/reactions.dm @@ -80,3 +80,5 @@ #define FUSION_RAD_MAX 1500 #define FUSION_RAD_COEFFICIENT (-1000) #define FUSION_INSTABILITY_ENDOTHERMALITY 2 +// Snowflake fire product types +#define FIRE_PRODUCT_PLASMA 0 diff --git a/code/__DEFINES/shuttles.dm b/code/__DEFINES/shuttles.dm index ff2c5f6827d7..f6a8b782498e 100644 --- a/code/__DEFINES/shuttles.dm +++ b/code/__DEFINES/shuttles.dm @@ -87,3 +87,12 @@ ///Check for arena shuttle, if the bubblegum has died this round GLOBAL_VAR_INIT(bubblegum_dead, FALSE) +// Alert level related for new thing im porting --- cowbot93 +#define ALERT_COEFF_AUTOEVAC_NORMAL 6 +#define ALERT_COEFF_GREEN 5 +#define ALERT_COEFF_BLUE 4 +#define ALERT_COEFF_RED 3 +#define ALERT_COEFF_AUTOEVAC_CRITICAL 2 +#define ALERT_COEFF_DELTA 1 +#define ALERT_COEFF_GAMMA 0 +#define ALERT_COEFF_EPSILON -1 diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm index 27cafa5a56f3..385b6108efad 100644 --- a/code/__DEFINES/sound.dm +++ b/code/__DEFINES/sound.dm @@ -117,3 +117,23 @@ #define ANNOUNCER_SHUTTLEDOCK "announcer_shuttledock" #define ANNOUNCER_SHUTTLERECALLED "announcer_shuttlerecalled" #define ANNOUNCER_SPANOMALIES "announcer_spanomalies" + +/// Global list of all of our announcer keys. +GLOBAL_LIST_INIT(announcer_keys, list( + ANNOUNCER_AIMALF, + ANNOUNCER_ALIENS, + ANNOUNCER_ANIMES, + ANNOUNCER_GRANOMALIES, + ANNOUNCER_INTERCEPT, + ANNOUNCER_IONSTORM, + ANNOUNCER_METEORS, + ANNOUNCER_OUTBREAK5, + ANNOUNCER_OUTBREAK7, + ANNOUNCER_POWEROFF, + ANNOUNCER_POWERON, + ANNOUNCER_RADIATION, + ANNOUNCER_SHUTTLECALLED, + ANNOUNCER_SHUTTLEDOCK, + ANNOUNCER_SHUTTLERECALLED, + ANNOUNCER_SPANOMALIES, +)) diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index a7b960b6e83b..944f6ef36c98 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -150,7 +150,8 @@ #define INIT_ORDER_CIRCUIT 15 #define INIT_ORDER_TIMER 1 #define INIT_ORDER_DEFAULT 0 -#define INIT_ORDER_AIR -1 +#define INIT_ORDER_AIR_MACHINERY -0.5 +#define INIT_ORDER_AIR -2 #define INIT_ORDER_PERSISTENCE -2 #define INIT_ORDER_PERSISTENT_PAINTINGS -3 // Assets relies on this #define INIT_ORDER_ASSETS -4 @@ -195,6 +196,7 @@ #define FIRE_PRIORITY_DEFAULT 50 #define FIRE_PRIORITY_PARALLAX 65 #define FIRE_PRIORITY_INSTRUMENTS 80 +#define FIRE_PRIORITY_CALLBACKS 90 #define FIRE_PRIORITY_MOBS 100 #define FIRE_PRIORITY_ASSETS 105 #define FIRE_PRIORITY_TGUI 110 @@ -217,6 +219,24 @@ #define RUNLEVELS_DEFAULT (RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME) +// SSair run section +#define SSAIR_PIPENETS 1 +#define SSAIR_ATMOSMACHINERY 2 +#define SSAIR_EXCITEDGROUPS 3 +#define SSAIR_HIGHPRESSURE 4 +#define SSAIR_HOTSPOTS 5 +#define SSAIR_TURF_CONDUCTION 6 +#define SSAIR_REBUILD_PIPENETS 7 +#define SSAIR_EQUALIZE 8 +#define SSAIR_ACTIVETURFS 9 +#define SSAIR_TURF_POST_PROCESS 10 +#define SSAIR_FINALIZE_TURFS 11 +#define SSAIR_ATMOSMACHINERY_AIR 12 +#define SSAIR_DEFERRED_AIRS 13 + +//Pipeline rebuild helper defines, these suck but it'll do for now //Fools you actually merged it +#define SSAIR_REBUILD_PIPELINE 1 +#define SSAIR_REBUILD_QUEUE 2 // Truly disgusting, TG. Truly disgusting. //! ## Overlays subsystem @@ -250,18 +270,6 @@ */ #define addtimer(args...) _addtimer(args, file = __FILE__, line = __LINE__) -// Air subsystem subtasks -#define SSAIR_PIPENETS 1 -#define SSAIR_ATMOSMACHINERY 2 -#define SSAIR_EQUALIZE 3 -#define SSAIR_ACTIVETURFS 4 -#define SSAIR_EXCITEDGROUPS 5 -#define SSAIR_HIGHPRESSURE 6 -#define SSAIR_HOTSPOTS 7 -#define SSAIR_SUPERCONDUCTIVITY 8 -#define SSAIR_REBUILD_PIPENETS 9 - - // Explosion Subsystem subtasks #define SSEXPLOSIONS_MOVABLES 1 #define SSEXPLOSIONS_TURFS 2 diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 0cdc86824d08..3bbcdf2c4270 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -291,8 +291,6 @@ #define TRAIT_NOVEHICLE "no_vehicle" /// BALD!!! #define TRAIT_BALD "bald" -/// Reduces severity of EMPs by one level, heavy becomes light and light is ignored -#define TRAIT_FARADAYCAGE "faraday_cage" /// You can't see color! #define TRAIT_COLORBLIND "color_blind" diff --git a/code/__DEFINES/turfs.dm b/code/__DEFINES/turfs.dm index 25d4c40b9d38..549af806ee03 100644 --- a/code/__DEFINES/turfs.dm +++ b/code/__DEFINES/turfs.dm @@ -8,3 +8,5 @@ ///Returns all currently loaded turfs #define ALL_TURFS(...) block(locate(1, 1, 1), locate(world.maxx, world.maxy, world.maxz)) + +#define IS_OPAQUE_TURF(turf) (turf.directional_opacity == ALL_CARDINALS) diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm index a7b44a55f1d5..7be173cddf12 100644 --- a/code/__DEFINES/vv.dm +++ b/code/__DEFINES/vv.dm @@ -80,6 +80,13 @@ #define VV_HK_ADD_EMITTER "add_emitter" #define VV_HK_REMOVE_EMITTER "remove_emitter" +// /datum/gas_mixture +#define VV_HK_SET_MOLES "set_moles" +#define VV_HK_EMPTY "empty" +#define VV_HK_SET_TEMPERATURE "set_temp" +#define VV_HK_PARSE_GASSTRING "parse_gasstring" +#define VV_HK_SET_VOLUME "set_volume" + // /obj #define VV_HK_OSAY "osay" #define VV_HK_MASS_DEL_TYPE "mass_delete_type" diff --git a/code/__DEFINES/{yogs_defines}/flags.dm b/code/__DEFINES/{yogs_defines}/flags.dm deleted file mode 100644 index 1dd763fe00b1..000000000000 --- a/code/__DEFINES/{yogs_defines}/flags.dm +++ /dev/null @@ -1,2 +0,0 @@ -//pass_flags -#define PASSDOOR (1<<13) \ No newline at end of file diff --git a/code/__HELPERS/_extools_api.dm b/code/__HELPERS/_extools_api.dm new file mode 100644 index 000000000000..59af733d97ff --- /dev/null +++ b/code/__HELPERS/_extools_api.dm @@ -0,0 +1,5 @@ +//#define AUXOOLS_LOGGING // rust_g is used as a fallback if this is undefined + +/proc/extools_log_write() + +/proc/extools_finalize_logging() diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 7c4750ceea8e..d5cd95b2db6b 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -365,6 +365,8 @@ /// Takes a weighted list (see above) and expands it into raw entries /// This eats more memory, but saves time when actually picking from it /proc/expand_weights(list/list_to_pick) + if(!length(list_to_pick)) + return list() var/list/values = list() for(var/item in list_to_pick) var/value = list_to_pick[item] @@ -498,25 +500,23 @@ /proc/sortUsernames(list/L, order=1) return sortTim(L, order >= 0 ? /proc/cmp_username_asc : /proc/cmp_username_dsc) -/// Converts a bitfield to a list of numbers (or words if a wordlist is provided) -/proc/bitfield2list(bitfield = 0, list/wordlist) - var/list/r = list() +///Converts a bitfield to a list of numbers (or words if a wordlist is provided) +/proc/bitfield_to_list(bitfield = 0, list/wordlist) + var/list/return_list = list() if(islist(wordlist)) - var/max = min(wordlist.len,16) + var/max = min(wordlist.len, 24) var/bit = 1 - for(var/i=1, i<=max, i++) + for(var/i in 1 to max) if(bitfield & bit) - r += wordlist[i] + return_list += wordlist[i] bit = bit << 1 else - for(var/bit=1, bit<=65535, bit = bit << 1) + for(var/bit_number = 0 to 23) + var/bit = 1 << bit_number if(bitfield & bit) - r += bit + return_list += bit - return r - -//tg compat -#define bitfield_to_list(args...) bitfield2list(args) + return return_list /// Returns the key based on the index #define KEYBYINDEX(L, index) (((index <= length(L)) && (index > 0)) ? L[index] : null) diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 34cd5e3ea0b8..d678e57e513d 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -7,8 +7,13 @@ #define WRITE_FILE(file, text) DIRECT_OUTPUT(file, text) #define READ_FILE(file, text) DIRECT_INPUT(file, text) //This is an external call, "true" and "false" are how rust parses out booleans +#ifdef EXTOOLS_LOGGING +#define WRITE_LOG(log, text) extools_log_write(log, text, TRUE) +#define WRITE_LOG_NO_FORMAT(log, text) extools_log_write(log, text, FALSE) +#else #define WRITE_LOG(log, text) rustg_log_write(log, "\[[worldtime2text()]\] [text]", "true") #define WRITE_LOG_NO_FORMAT(log, text) rustg_log_write(log, text, "false") +#endif //print a warning message to world.log #define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [UNLINT(src)] usr: [usr].") @@ -250,7 +255,12 @@ /* Close open log handles. This should be called as late as possible, and no logging should hapen after. */ /proc/shutdown_logging() +#ifdef EXTOOLS_LOGGING + extools_finalize_logging() +#else rustg_log_close_all() +#endif + /* Helper procs for building detailed log lines */ diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index e33a3bdd893c..67751fd75f4b 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -322,7 +322,7 @@ Y1+=s while(Y1!=Y2) T=locate(X1,Y1,Z) - if(T.opacity) + if(IS_OPAQUE_TURF(T)) return 0 Y1+=s else @@ -338,7 +338,7 @@ else X1+=signX //Line exits tile horizontally T=locate(X1,Y1,Z) - if(T.opacity) + if(IS_OPAQUE_TURF(T)) return 0 return 1 #undef SIGNV @@ -707,7 +707,7 @@ if(!istype(T)) return var/datum/gas_mixture/environment = T.return_air() - if(!istype(environment)) + if(!environment) return var/pressure = environment.return_pressure() if(pressure <= LAVALAND_EQUIPMENT_EFFECT_PRESSURE) diff --git a/code/__HELPERS/priority_announce.dm b/code/__HELPERS/priority_announce.dm index 9caa886e50ce..3661d0c2ed8f 100644 --- a/code/__HELPERS/priority_announce.dm +++ b/code/__HELPERS/priority_announce.dm @@ -1,106 +1,206 @@ -#define RANDOM_REPORT_SOUND "random_report_sound" - -/proc/priority_announce(text, title = "", sound, type, sender_override, has_important_message, sanitize = TRUE) +// please don't use these defines outside of this file in order to ensure a unified framework. unless you have a really good reason to make them global, then whatever + +// these four are just text spans that furnish the TEXT itself with the appropriate CSS classes +#define MAJOR_ANNOUNCEMENT_TITLE(string) ("" + string + "") +#define SUBHEADER_ANNOUNCEMENT_TITLE(string) ("" + string + "") +#define MAJOR_ANNOUNCEMENT_TEXT(string) ("" + string + "") +#define MINOR_ANNOUNCEMENT_TITLE(string) ("" + string + "") +#define MINOR_ANNOUNCEMENT_TEXT(string) ("" + string + "") + +#define ANNOUNCEMENT_HEADER(string) ("" + string + "") + +// these two are the ones that actually give the striped background +#define CHAT_ALERT_DEFAULT_SPAN(string) ("
" + string + "
") +#define CHAT_ALERT_COLORED_SPAN(color, string) ("
" + string + "
") + +#define ANNOUNCEMENT_COLORS list("default", "green", "blue", "pink", "yellow", "orange", "red", "purple") + +/** + * Make a big red text announcement to + * + * Formatted like: + * + * " Message from sender " + * + * " Title " + * + * " Text " + * + * Arguments + * * text - required, the text to announce + * * title - optional, the title of the announcement. + * * sound - optional, the sound played accompanying the announcement + * * type - optional, the type of the announcement, for some "preset" announcement templates. See __DEFINES/announcements.dm + * * sender_override - optional, modifies the sender of the announcement + * * has_important_message - is this message critical to the game (and should not be overridden by station traits), or not + * * players - a list of all players to send the message to. defaults to all players (not including new players) + * * encode_title - if TRUE, the title will be HTML encoded + * * encode_text - if TRUE, the text will be HTML encoded + */ +/proc/priority_announce(text, title = "", sound, type, sender_override, has_important_message = FALSE, list/mob/players = GLOB.player_list, encode_title = TRUE, encode_text = TRUE, color_override) if(!text) return - var/announcement - var/default_sound + if(encode_title && title && length(title) > 0) + title = html_encode(title) + if(encode_text) + text = html_encode(text) + if(!length(text)) + return + var/list/announcement_strings = list() if(!sound) sound = SSstation.announcer.get_rand_alert_sound() - default_sound = SSstation.default_announcer.get_rand_alert_sound() else if(SSstation.announcer.event_sounds[sound]) sound = SSstation.announcer.event_sounds[sound] - if(SSstation.default_announcer.event_sounds[sound]) - default_sound = SSstation.default_announcer.event_sounds[sound] - - - if(sound == RANDOM_REPORT_SOUND) - sound = SSstation.announcer.get_rand_report_sound() - default_sound = SSstation.default_announcer.get_rand_report_sound() - - - if(type == "Priority") - announcement += "

Priority Announcement

" - if (title && length(title) > 0) - announcement += "

[sanitize ? html_encode(title) : title]

" - else if(type == "Captain") - announcement += "

Captain Announces

" - GLOB.news_network.SubmitArticle(text, "Captain's Announcement", "Station Announcements", null) - - else - if(!sender_override) - announcement += "

[command_name()] Update

" + var/header + switch(type) + if(ANNOUNCEMENT_TYPE_PRIORITY) + header = MAJOR_ANNOUNCEMENT_TITLE("Priority Announcement") + if(length(title) > 0) + header += SUBHEADER_ANNOUNCEMENT_TITLE(title) + if(ANNOUNCEMENT_TYPE_CAPTAIN) + header = MAJOR_ANNOUNCEMENT_TITLE("Captain's Announcement") + GLOB.news_network.SubmitArticle(text, "Captain's Announcement", "Station Announcements", null) + if(ANNOUNCEMENT_TYPE_SYNDICATE) + header = MAJOR_ANNOUNCEMENT_TITLE("Syndicate Captain's Announcement") else - announcement += "

[sender_override]

" - if (title && length(title) > 0) - announcement += "

[sanitize ? html_encode(title) : title]

" + header += generate_unique_announcement_header(title, sender_override) - if(!sender_override) - if(title == "") - GLOB.news_network.SubmitArticle(text, "Central Command Update", "Station Announcements", null) - else - GLOB.news_network.SubmitArticle(title + "

" + text, "Central Command", "Station Announcements", null) + announcement_strings += ANNOUNCEMENT_HEADER(header) ///If the announcer overrides alert messages, use that message. if(SSstation.announcer.custom_alert_message && !has_important_message) - announcement += SSstation.announcer.custom_alert_message + announcement_strings += MAJOR_ANNOUNCEMENT_TEXT(SSstation.announcer.custom_alert_message) + else + announcement_strings += MAJOR_ANNOUNCEMENT_TEXT(text) + + var/finalized_announcement + if(color_override) + finalized_announcement = CHAT_ALERT_COLORED_SPAN(color_override, jointext(announcement_strings, "")) else - announcement += "
[span_alert("[sanitize ? html_encode(text) : text]")]
" - announcement += "
" - - var/s = sound(sound) - var/default_s = s - if(!istype(SSstation.announcer, /datum/centcom_announcer/default)) - default_s = sound(default_sound) - for(var/mob/M in GLOB.player_list) - if(!isnewplayer(M) && M.can_hear()) - if(isliving(M) && M.stat != DEAD) - var/mob/living/L = M - if(!L.IsUnconscious()) - to_chat(L, announcement) - else - to_chat(M, announcement) - if(M.client.prefs.toggles & SOUND_ANNOUNCEMENTS) - if(M.client.prefs.read_preference(/datum/preference/toggle/disable_alternative_announcers)) - SEND_SOUND(M, default_s) - else - SEND_SOUND(M, s) + finalized_announcement = CHAT_ALERT_DEFAULT_SPAN(jointext(announcement_strings, "")) + + dispatch_announcement_to_players(finalized_announcement, players, sound) + + if(isnull(sender_override) && players == GLOB.player_list) + if(length(title) > 0) + GLOB.news_network.SubmitArticle(title + "

" + text, "[command_name()]", "Station Announcements", null) + else + GLOB.news_network.SubmitArticle(text, "[command_name()] Update", "Station Announcements", null) /proc/print_command_report(text = "", title = null, announce=TRUE) if(!title) title = "Classified [command_name()] Update" if(announce) - priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", RANDOM_REPORT_SOUND, has_important_message = TRUE) + priority_announce( + text = "A report has been downloaded and printed out at all communications consoles.", + title = "Incoming Classified Message", + sound = SSstation.announcer.get_rand_report_sound(), + has_important_message = TRUE, + ) + + var/datum/comm_message/message = new + message.title = title + message.content = text + + SScommunications.send_message(message) + +/** + * Sends a minor annoucement to players. + * Minor announcements are large text, with the title in red and message in white. + * Only mobs that can hear can see the announcements. + * + * message - the message contents of the announcement. + * title - the title of the announcement, which is often "who sent it". + * alert - whether this announcement is an alert, or just a notice. Only changes the sound that is played by default. + * html_encode - if TRUE, we will html encode our title and message before sending it, to prevent player input abuse. + * players - optional, a list mobs to send the announcement to. If unset, sends to all palyers. + * sound_override - optional, use the passed sound file instead of the default notice sounds. + * should_play_sound - Whether the notice sound should be played or not. + * color_override - optional, use the passed color instead of the default notice color. + */ +/proc/minor_announce(message, title = "Attention:", alert = FALSE, html_encode = TRUE, list/players, sound_override, should_play_sound = TRUE, color_override) + if(!message) + return - var/datum/comm_message/M = new - M.title = title - M.content = text + if (html_encode) + title = html_encode(title) + message = html_encode(message) - SScommunications.send_message(M) + var/list/minor_announcement_strings = list() + if(title != null && title != "") + minor_announcement_strings += ANNOUNCEMENT_HEADER(MINOR_ANNOUNCEMENT_TITLE(title)) + minor_announcement_strings += MINOR_ANNOUNCEMENT_TEXT(message) -/proc/minor_announce(message, title = "Attention:", alert, custom_alert_sound) - if(!message) - return + var/finalized_announcement + if(color_override) + finalized_announcement = CHAT_ALERT_COLORED_SPAN(color_override, jointext(minor_announcement_strings, "")) + else + finalized_announcement = CHAT_ALERT_DEFAULT_SPAN(jointext(minor_announcement_strings, "")) + + var/custom_sound = sound_override || (alert ? 'sound/misc/notice1.ogg' : 'sound/misc/notice2.ogg') + dispatch_announcement_to_players(finalized_announcement, players, custom_sound, should_play_sound) + +/// Sends an announcement about the level changing to players. Uses the passed in datum and the subsystem's previous security level to generate the message. +/proc/level_announce(datum/security_level/selected_level, previous_level_number) + var/current_level_number = selected_level.number_level + var/current_level_name = selected_level.name + var/current_level_color = selected_level.announcement_color + var/current_level_sound = selected_level.sound + + var/title + var/message + + if(current_level_number > previous_level_number) + title = "Attention! Security level elevated to [current_level_name]:" + message = selected_level.elevating_to_announcement + else + title = "Attention! Security level lowered to [current_level_name]:" + message = selected_level.lowering_to_announcement + + var/list/level_announcement_strings = list() + level_announcement_strings += ANNOUNCEMENT_HEADER(MINOR_ANNOUNCEMENT_TITLE(title)) + level_announcement_strings += MINOR_ANNOUNCEMENT_TEXT(message) + + var/finalized_announcement = CHAT_ALERT_COLORED_SPAN(current_level_color, jointext(level_announcement_strings, "")) + + dispatch_announcement_to_players(finalized_announcement, GLOB.player_list, current_level_sound) + +/// Proc that just generates a custom header based on variables fed into `priority_announce()` +/// Will return a string. +/proc/generate_unique_announcement_header(title, sender_override) + var/list/returnable_strings = list() + if(isnull(sender_override)) + returnable_strings += MAJOR_ANNOUNCEMENT_TITLE("[command_name()] Update") + else + returnable_strings += MAJOR_ANNOUNCEMENT_TITLE(sender_override) + + if(length(title) > 0) + returnable_strings += SUBHEADER_ANNOUNCEMENT_TITLE(title) + + return jointext(returnable_strings, "") + +/// Proc that just dispatches the announcement to our applicable audience. Only the announcement is a mandatory arg. +/proc/dispatch_announcement_to_players(announcement, list/players = GLOB.player_list, sound_override = null, should_play_sound = TRUE) + var/sound_to_play = !isnull(sound_override) ? sound_override : 'sound/misc/notice2.ogg' + + for(var/mob/target in players) + if(isnewplayer(target) || !target.can_hear()) + continue + + to_chat(target, announcement) + if(!should_play_sound) + continue + + SEND_SOUND(target, sound(sound_to_play)) - for(var/mob/M in GLOB.player_list) - if(!isnewplayer(M) && M.can_hear()) - if(isliving(M) && M.stat != DEAD) - var/mob/living/L = M - if(!L.IsUnconscious()) - to_chat(L, "[html_encode(title)]
[html_encode(message)]

") - else - to_chat(M, "[html_encode(title)]
[html_encode(message)]

") - if(M.client.prefs.toggles & SOUND_ANNOUNCEMENTS) - var/s = sound(custom_alert_sound) - if(custom_alert_sound) - SEND_SOUND(M, s) - else - if(alert) - SEND_SOUND(M, sound('sound/misc/notice1.ogg')) - else - SEND_SOUND(M, sound('sound/misc/notice2.ogg')) +#undef MAJOR_ANNOUNCEMENT_TITLE +#undef MAJOR_ANNOUNCEMENT_TEXT +#undef MINOR_ANNOUNCEMENT_TITLE +#undef MINOR_ANNOUNCEMENT_TEXT +#undef CHAT_ALERT_DEFAULT_SPAN +#undef CHAT_ALERT_COLORED_SPAN diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 38aef9e817b7..d346e7fae044 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -41,6 +41,9 @@ else if(x<0) .+=360 +//Better performant than an artisanal proc and more reliable than Turn(). From TGMC. +#define REVERSE_DIR(dir) ( ((dir & 85) << 1) | ((dir & 170) >> 1) ) + //Returns location. Returns null if no location was found. /proc/get_teleport_loc(turf/location,mob/target,distance = 1, density = FALSE, errorx = 0, errory = 0, eoffsetx = 0, eoffsety = 0) /* @@ -492,17 +495,13 @@ Turf and target are separate in case you want to teleport some distance from a t current = get_step_towards(current, target_turf) while(current != target_turf) if(steps > length) - return 0 - if(current.opacity) - return 0 - for(var/thing in current) - var/atom/A = thing - if(A.opacity) - return 0 + return FALSE + if(IS_OPAQUE_TURF(current)) + return FALSE current = get_step_towards(current, target_turf) steps++ - return 1 + return TRUE /proc/is_anchored_dense_turf(turf/T) //like the older version of the above, fails only if also anchored if(T.density) diff --git a/code/__byond_version_compat.dm b/code/__byond_version_compat.dm index a670b3d8da66..609907e9702f 100644 --- a/code/__byond_version_compat.dm +++ b/code/__byond_version_compat.dm @@ -1,17 +1,17 @@ // This file contains defines allowing targeting byond versions newer than the supported //Update this whenever you need to take advantage of more recent byond features -#define MIN_COMPILER_VERSION 514 -#define MIN_COMPILER_BUILD 1556 +#define MIN_COMPILER_VERSION 515 +#define MIN_COMPILER_BUILD 1620 #if (DM_VERSION < MIN_COMPILER_VERSION || DM_BUILD < MIN_COMPILER_BUILD) && !defined(SPACEMAN_DMM) //Don't forget to update this part #error Your version of BYOND is too out-of-date to compile this project. Go to https://secure.byond.com/download and update. -#error You need version 514.1556 or higher +#error You need version 515.1620 or higher #endif //If you update these values, update the message in the #error #define MAX_BYOND_MAJOR 515 -#define MAX_BYOND_MINOR 1603 +#define MAX_BYOND_MINOR 1620 // You can define IGNORE_MAX_BYOND_VERSION to bypass the max version check. // Note: This will likely break the game, especially any extools/auxtools linkage. Only use if you know what you're doing! @@ -25,7 +25,7 @@ #if ((DM_VERSION > MAX_BYOND_MAJOR) || (DM_BUILD > MAX_BYOND_MINOR)) && !defined(IGNORE_MAX_BYOND_VERSION) // Not updating until we fully move to 515 -#error Your version of BYOND is too new to compile this project. Download version 514.1589 at www.byond.com/download/build/514/514.1589_byond.exe +#error Your version of BYOND is too new to compile this project. Download version 515.1620 at www.byond.com/download/build/515/515.1620_byond.exe #endif // 515 split call for external libraries into call_ext diff --git a/code/_debugger.dm b/code/_debugger.dm new file mode 100644 index 000000000000..1518908fa9a0 --- /dev/null +++ b/code/_debugger.dm @@ -0,0 +1,13 @@ +//Datum used to init Auxtools debugging as early as possible +//Datum gets created in master.dm because for whatever reason global code in there gets runs first +//In case we ever figure out how to manipulate global init order please move the datum creation into this file +/datum/debugger + +/datum/debugger/New() + enable_debugger() + +/datum/debugger/proc/enable_debugger() + var/dll = world.GetConfig("env", "AUXTOOLS_DEBUG_DLL") + if (dll) + LIBCALL(dll, "auxtools_init")() + enable_debugging() diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index b77ed18af259..2123f6a32d20 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -1,204 +1,237 @@ -GLOBAL_LIST_INIT(bitfields, list( - "appearance_flags" = list( - "LONG_GLIDE" = LONG_GLIDE, - "RESET_COLOR" = RESET_COLOR, - "RESET_ALPHA" = RESET_ALPHA, - "RESET_TRANSFORM" = RESET_TRANSFORM, - "NO_CLIENT_COLOR" = NO_CLIENT_COLOR, - "KEEP_TOGETHER" = KEEP_TOGETHER, - "KEEP_APART" = KEEP_APART, - "PLANE_MASTER" = PLANE_MASTER, - "TILE_BOUND" = TILE_BOUND, - "PIXEL_SCALE" = PIXEL_SCALE - ), - "sight" = list( - "SEE_INFRA" = SEE_INFRA, - "SEE_SELF" = SEE_SELF, - "SEE_MOBS" = SEE_MOBS, - "SEE_OBJS" = SEE_OBJS, - "SEE_TURFS" = SEE_TURFS, - "SEE_PIXELS" = SEE_PIXELS, - "SEE_THRU" = SEE_THRU, - "SEE_BLACKNESS" = SEE_BLACKNESS, - "BLIND" = BLIND - ), - "obj_flags" = list( - "EMAGGED" = EMAGGED, - "IN_USE" = IN_USE, - "CAN_BE_HIT" = CAN_BE_HIT, - "BEING_SHOCKED" = BEING_SHOCKED, - "DANGEROUS_POSSESSION" = DANGEROUS_POSSESSION, - "ON_BLUEPRINTS" = ON_BLUEPRINTS, - "UNIQUE_RENAME" = UNIQUE_RENAME, - "USES_TGUI" = USES_TGUI, - "FROZEN" = FROZEN, - "UNIQUE_REDESC" = UNIQUE_REDESC, - "CMAGGED" = CMAGGED, - ), - "datum_flags" = list( - "DF_USE_TAG" = DF_USE_TAG, - "DF_VAR_EDITED" = DF_VAR_EDITED, - "DF_ISPROCESSING" = DF_ISPROCESSING, - ), - "item_flags" = list( - "BEING_REMOVED" = BEING_REMOVED, - "IN_INVENTORY" = IN_INVENTORY, - "FORCE_STRING_OVERRIDE" = FORCE_STRING_OVERRIDE, - "HAND_ITEM" = HAND_ITEM, - "NEEDS_PERMIT" = NEEDS_PERMIT, - "SLOWS_WHILE_IN_HAND" = SLOWS_WHILE_IN_HAND, - "NO_MAT_REDEMPTION" = NO_MAT_REDEMPTION, - "DROPDEL" = DROPDEL, - "NOBLUDGEON" = NOBLUDGEON, - "ABSTRACT" = ABSTRACT, - "IN_STORAGE" = IN_STORAGE, - "UNCATCHABLE" = UNCATCHABLE, - "MEDRESIST" = MEDRESIST, - ), - "admin_flags" = list( - "BUILDMODE" = R_BUILDMODE, - "ADMIN" = R_ADMIN, - "BAN" = R_BAN, - "FUN" = R_FUN, - "SERVER" = R_SERVER, - "DEBUG" = R_DEBUG, - "POSSESS" = R_POSSESS, - "PERMISSIONS" = R_PERMISSIONS, - "STEALTH" = R_STEALTH, - "POLL" = R_POLL, - "VAREDIT" = R_VAREDIT, - "SOUNDS" = R_SOUNDS, - "SPAWN" = R_SPAWN, - "AUTOLOGIN" = R_AUTOLOGIN, - "DEV" = R_DEV, - "PERSISTPERMS" = R_PERSIST_PERMS - ), - "interaction_flags_atom" = list( - "INTERACT_ATOM_REQUIRES_ANCHORED" = INTERACT_ATOM_REQUIRES_ANCHORED, - "INTERACT_ATOM_ATTACK_HAND" = INTERACT_ATOM_ATTACK_HAND, - "INTERACT_ATOM_UI_INTERACT" = INTERACT_ATOM_UI_INTERACT, - "INTERACT_ATOM_REQUIRES_DEXTERITY" = INTERACT_ATOM_REQUIRES_DEXTERITY, - "INTERACT_ATOM_IGNORE_INCAPACITATED" = INTERACT_ATOM_IGNORE_INCAPACITATED, - "INTERACT_ATOM_IGNORE_RESTRAINED" = INTERACT_ATOM_IGNORE_RESTRAINED, - "INTERACT_ATOM_CHECK_GRAB" = INTERACT_ATOM_CHECK_GRAB, - "INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND" = INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND, - "INTERACT_ATOM_NO_FINGERPRINT_INTERACT" = INTERACT_ATOM_NO_FINGERPRINT_INTERACT - ), - "interaction_flags_machine" = list( - "INTERACT_MACHINE_OPEN" = INTERACT_MACHINE_OPEN, - "INTERACT_MACHINE_OFFLINE" = INTERACT_MACHINE_OFFLINE, - "INTERACT_MACHINE_WIRES_IF_OPEN" = INTERACT_MACHINE_WIRES_IF_OPEN, - "INTERACT_MACHINE_ALLOW_SILICON" = INTERACT_MACHINE_ALLOW_SILICON, - "INTERACT_MACHINE_OPEN_SILICON" = INTERACT_MACHINE_OPEN_SILICON, - "INTERACT_MACHINE_REQUIRES_SILICON" = INTERACT_MACHINE_REQUIRES_SILICON, - "INTERACT_MACHINE_SET_MACHINE" = INTERACT_MACHINE_SET_MACHINE - ), - "interaction_flags_item" = list( - "INTERACT_ITEM_ATTACK_HAND_PICKUP" = INTERACT_ITEM_ATTACK_HAND_PICKUP, - ), - "pass_flags" = list( - "PASSTABLE" = PASSTABLE, - "PASSGLASS" = PASSGLASS, - "PASSGRILLE" = PASSGRILLE, - "PASSBLOB" = PASSBLOB, - "PASSMOB" = PASSMOB, - "PASSCLOSEDTURF" = PASSCLOSEDTURF, - "LETPASSTHROW" = LETPASSTHROW, - "PASSDOOR" = PASSDOOR, //yogs - "PASSMACHINES" = PASSMACHINES, - "PASSCOMPUTER" = PASSCOMPUTER, - "PASSSTRUCTURE" = PASSSTRUCTURE - ), - "movement_type" = list( - "GROUND" = GROUND, - "FLYING" = FLYING, - "VENTCRAWLING" = VENTCRAWLING, - "FLOATING" = FLOATING, - "UNSTOPPABLE" = UNSTOPPABLE - ), - "resistance_flags" = list( - "LAVA_PROOF" = LAVA_PROOF, - "FIRE_PROOF" = FIRE_PROOF, - "FLAMMABLE" = FLAMMABLE, - "ON_FIRE" = ON_FIRE, - "UNACIDABLE" = UNACIDABLE, - "ACID_PROOF" = ACID_PROOF, - "INDESTRUCTIBLE" = INDESTRUCTIBLE, - "FREEZE_PROOF" = FREEZE_PROOF - ), - "flags_1" = list( - "NOJAUNT_1" = NOJAUNT_1, - "UNUSED_RESERVATION_TURF_1" = UNUSED_RESERVATION_TURF_1, - "CAN_BE_DIRTY_1" = CAN_BE_DIRTY_1, - "HEAR_1" = HEAR_1, - "CHECK_RICOCHET_1" = CHECK_RICOCHET_1, - "CONDUCT_1" = CONDUCT_1, - "NO_LAVA_GEN_1" = NO_LAVA_GEN_1, - "NODECONSTRUCT_1" = NODECONSTRUCT_1, - "ON_BORDER_1" = ON_BORDER_1, - "NO_RUINS_1" = NO_RUINS_1, - "NO_RUST" = NO_RUST, - "PREVENT_CLICK_UNDER_1" = PREVENT_CLICK_UNDER_1, - "HOLOGRAM_1" = HOLOGRAM_1, - "TESLA_IGNORE_1" = TESLA_IGNORE_1, - "INITIALIZED_1" = INITIALIZED_1, - "ADMIN_SPAWNED_1" = ADMIN_SPAWNED_1, - "PREVENT_CONTENTS_EXPLOSION_1" = PREVENT_CONTENTS_EXPLOSION_1, - "RAD_PROTECT_CONTENTS_1" = RAD_PROTECT_CONTENTS_1, - "RAD_NO_CONTAMINATE_1" = RAD_NO_CONTAMINATE_1, - "IS_SPINNING_1" = IS_SPINNING_1, - ), - "clothing_flags" = list( - "LAVAPROTECT" = LAVAPROTECT, - "STOPSHIGHPRESSURE" = STOPSHIGHPRESSURE, - "STOPSLOWPRESSURE" = STOPSLOWPRESSURE, - "BLOCK_GAS_SMOKE_EFFECT" = BLOCK_GAS_SMOKE_EFFECT, - "MASKINTERNALS" = MASKINTERNALS, - "NOSLIP" = NOSLIP, - "THICKMATERIAL" = THICKMATERIAL, - "VOICEBOX_TOGGLABLE" = VOICEBOX_TOGGLABLE, - "VOICEBOX_DISABLED" = VOICEBOX_DISABLED, - "SCAN_REAGENTS" = SCAN_REAGENTS, - ), - "tesla_flags" = list( - "TESLA_MOB_DAMAGE" = TESLA_MOB_DAMAGE, - "TESLA_OBJ_DAMAGE" = TESLA_OBJ_DAMAGE, - "TESLA_MOB_STUN" = TESLA_MOB_STUN, - "TESLA_ALLOW_DUPLICATES" = TESLA_ALLOW_DUPLICATES, - "TESLA_MACHINE_EXPLOSIVE" = TESLA_MACHINE_EXPLOSIVE, - ), - "smooth" = list( - "SMOOTH_TRUE" = SMOOTH_TRUE, - "SMOOTH_MORE" = SMOOTH_MORE, - "SMOOTH_DIAGONAL" = SMOOTH_DIAGONAL, - "SMOOTH_BORDER" = SMOOTH_BORDER, - "SMOOTH_QUEUED" = SMOOTH_QUEUED, - ), - "car_traits" = list( - "CAN_KIDNAP" = CAN_KIDNAP, - ), - "mobility_flags" = list( - "MOVE" = MOBILITY_MOVE, - "STAND" = MOBILITY_STAND, - "PICKUP" = MOBILITY_PICKUP, - "USE" = MOBILITY_USE, - "UI" = MOBILITY_UI, - "STORAGE" = MOBILITY_STORAGE, - "PULL" = MOBILITY_PULL, - ), - "disease_flags" = list ( - "CURABLE" = CURABLE, - "CAN_CARRY" = CAN_CARRY, - "CAN_RESIST" = CAN_RESIST - ), - "vis_flags" = list( - "VIS_INHERIT_ICON" = VIS_INHERIT_ICON, - "VIS_INHERIT_ICON_STATE" = VIS_INHERIT_ICON_STATE, - "VIS_INHERIT_DIR" = VIS_INHERIT_DIR, - "VIS_INHERIT_LAYER" = VIS_INHERIT_LAYER, - "VIS_INHERIT_PLANE" = VIS_INHERIT_PLANE, - "VIS_INHERIT_ID" = VIS_INHERIT_ID, - "VIS_UNDERLAY" = VIS_UNDERLAY, - "VIS_HIDE" = VIS_HIDE - ) - )) +GLOBAL_LIST_INIT(bitfields, generate_bitfields()) + +/// Specifies a bitfield for smarter debugging +/datum/bitfield + /// The variable name that contains the bitfield + var/variable + + /// An associative list of the readable flag and its true value + var/list/flags + +/// Turns /datum/bitfield subtypes into a list for use in debugging +/proc/generate_bitfields() + var/list/bitfields = list() + for (var/_bitfield in subtypesof(/datum/bitfield)) + var/datum/bitfield/bitfield = new _bitfield + bitfields[bitfield.variable] = bitfield.flags + return bitfields + +DEFINE_BITFIELD(appearance_flags, list( + "LONG_GLIDE" = LONG_GLIDE, + "RESET_COLOR" = RESET_COLOR, + "RESET_ALPHA" = RESET_ALPHA, + "RESET_TRANSFORM" = RESET_TRANSFORM, + "NO_CLIENT_COLOR" = NO_CLIENT_COLOR, + "KEEP_TOGETHER" = KEEP_TOGETHER, + "KEEP_APART" = KEEP_APART, + "PLANE_MASTER" = PLANE_MASTER, + "TILE_BOUND" = TILE_BOUND, + "PIXEL_SCALE" = PIXEL_SCALE, +)) + +DEFINE_BITFIELD(sight, list( + "SEE_INFRA" = SEE_INFRA, + "SEE_SELF" = SEE_SELF, + "SEE_MOBS" = SEE_MOBS, + "SEE_OBJS" = SEE_OBJS, + "SEE_TURFS" = SEE_TURFS, + "SEE_PIXELS" = SEE_PIXELS, + "SEE_THRU" = SEE_THRU, + "SEE_BLACKNESS" = SEE_BLACKNESS, + "BLIND" = BLIND, +)) + +DEFINE_BITFIELD(obj_flags, list( + "EMAGGED" = EMAGGED, + "IN_USE" = IN_USE, + "CAN_BE_HIT" = CAN_BE_HIT, + "BEING_SHOCKED" = BEING_SHOCKED, + "DANGEROUS_POSSESSION" = DANGEROUS_POSSESSION, + "ON_BLUEPRINTS" = ON_BLUEPRINTS, + "UNIQUE_RENAME" = UNIQUE_RENAME, + "USES_TGUI" = USES_TGUI, + "FROZEN" = FROZEN, + "UNIQUE_REDESC" = UNIQUE_REDESC, + "CMAGGED" = CMAGGED, +)) + +DEFINE_BITFIELD(datum_flags, list( + "DF_USE_TAG" = DF_USE_TAG, + "DF_VAR_EDITED" = DF_VAR_EDITED, + "DF_ISPROCESSING" = DF_ISPROCESSING, +)) + +DEFINE_BITFIELD(item_flags, list( + "BEING_REMOVED" = BEING_REMOVED, + "IN_INVENTORY" = IN_INVENTORY, + "FORCE_STRING_OVERRIDE" = FORCE_STRING_OVERRIDE, + "HAND_ITEM" = HAND_ITEM, + "NEEDS_PERMIT" = NEEDS_PERMIT, + "SLOWS_WHILE_IN_HAND" = SLOWS_WHILE_IN_HAND, + "NO_MAT_REDEMPTION" = NO_MAT_REDEMPTION, + "DROPDEL" = DROPDEL, + "NOBLUDGEON" = NOBLUDGEON, + "ABSTRACT" = ABSTRACT, + "IN_STORAGE" = IN_STORAGE, + "UNCATCHABLE" = UNCATCHABLE, + "MEDRESIST" = MEDRESIST, +)) + +DEFINE_BITFIELD(admin_flags, list( + "BUILDMODE" = R_BUILDMODE, + "ADMIN" = R_ADMIN, + "BAN" = R_BAN, + "FUN" = R_FUN, + "SERVER" = R_SERVER, + "DEBUG" = R_DEBUG, + "POSSESS" = R_POSSESS, + "PERMISSIONS" = R_PERMISSIONS, + "STEALTH" = R_STEALTH, + "POLL" = R_POLL, + "VAREDIT" = R_VAREDIT, + "SOUNDS" = R_SOUNDS, + "SPAWN" = R_SPAWN, + "AUTOLOGIN" = R_AUTOLOGIN, + "DEV" = R_DEV, + "PERSISTPERMS" = R_PERSIST_PERMS, +)) + +DEFINE_BITFIELD(interaction_flags_atom, list( + "INTERACT_ATOM_REQUIRES_ANCHORED" = INTERACT_ATOM_REQUIRES_ANCHORED, + "INTERACT_ATOM_ATTACK_HAND" = INTERACT_ATOM_ATTACK_HAND, + "INTERACT_ATOM_UI_INTERACT" = INTERACT_ATOM_UI_INTERACT, + "INTERACT_ATOM_REQUIRES_DEXTERITY" = INTERACT_ATOM_REQUIRES_DEXTERITY, + "INTERACT_ATOM_IGNORE_INCAPACITATED" = INTERACT_ATOM_IGNORE_INCAPACITATED, + "INTERACT_ATOM_IGNORE_RESTRAINED" = INTERACT_ATOM_IGNORE_RESTRAINED, + "INTERACT_ATOM_CHECK_GRAB" = INTERACT_ATOM_CHECK_GRAB, + "INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND" = INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND, + "INTERACT_ATOM_NO_FINGERPRINT_INTERACT" = INTERACT_ATOM_NO_FINGERPRINT_INTERACT, +)) + +DEFINE_BITFIELD(interaction_flags_machine, list( + "INTERACT_MACHINE_OPEN" = INTERACT_MACHINE_OPEN, + "INTERACT_MACHINE_OFFLINE" = INTERACT_MACHINE_OFFLINE, + "INTERACT_MACHINE_WIRES_IF_OPEN" = INTERACT_MACHINE_WIRES_IF_OPEN, + "INTERACT_MACHINE_ALLOW_SILICON" = INTERACT_MACHINE_ALLOW_SILICON, + "INTERACT_MACHINE_OPEN_SILICON" = INTERACT_MACHINE_OPEN_SILICON, + "INTERACT_MACHINE_REQUIRES_SILICON" = INTERACT_MACHINE_REQUIRES_SILICON, + "INTERACT_MACHINE_SET_MACHINE" = INTERACT_MACHINE_SET_MACHINE, +)) + +DEFINE_BITFIELD(interaction_flags_item, list( + "INTERACT_ITEM_ATTACK_HAND_PICKUP" = INTERACT_ITEM_ATTACK_HAND_PICKUP, +)) + +DEFINE_BITFIELD(pass_flags, list( + "PASSTABLE" = PASSTABLE, + "PASSGLASS" = PASSGLASS, + "PASSGRILLE" = PASSGRILLE, + "PASSBLOB" = PASSBLOB, + "PASSMOB" = PASSMOB, + "PASSCLOSEDTURF" = PASSCLOSEDTURF, + "LETPASSTHROW" = LETPASSTHROW, + "PASSDOOR" = PASSDOOR, + "PASSMACHINES" = PASSMACHINES, + "PASSCOMPUTER" = PASSCOMPUTER, + "PASSSTRUCTURE" = PASSSTRUCTURE, +)) + +DEFINE_BITFIELD(movement_type, list( + "GROUND" = GROUND, + "FLYING" = FLYING, + "VENTCRAWLING" = VENTCRAWLING, + "FLOATING" = FLOATING, + "UNSTOPPABLE" = UNSTOPPABLE, +)) + +DEFINE_BITFIELD(resistance_flags, list( + "LAVA_PROOF" = LAVA_PROOF, + "FIRE_PROOF" = FIRE_PROOF, + "FLAMMABLE" = FLAMMABLE, + "ON_FIRE" = ON_FIRE, + "UNACIDABLE" = UNACIDABLE, + "ACID_PROOF" = ACID_PROOF, + "INDESTRUCTIBLE" = INDESTRUCTIBLE, + "FREEZE_PROOF" = FREEZE_PROOF, +)) + +DEFINE_BITFIELD(flags_1, list( + "NOJAUNT_1" = NOJAUNT_1, + "UNUSED_RESERVATION_TURF_1" = UNUSED_RESERVATION_TURF_1, + "CAN_BE_DIRTY_1" = CAN_BE_DIRTY_1, + "HEAR_1" = HEAR_1, + "CHECK_RICOCHET_1" = CHECK_RICOCHET_1, + "CONDUCT_1" = CONDUCT_1, + "NO_LAVA_GEN_1" = NO_LAVA_GEN_1, + "NODECONSTRUCT_1" = NODECONSTRUCT_1, + "ON_BORDER_1" = ON_BORDER_1, + "NO_RUINS_1" = NO_RUINS_1, + "PREVENT_CLICK_UNDER_1" = PREVENT_CLICK_UNDER_1, + "HOLOGRAM_1" = HOLOGRAM_1, + "TESLA_IGNORE_1" = TESLA_IGNORE_1, + "INITIALIZED_1" = INITIALIZED_1, + "ADMIN_SPAWNED_1" = ADMIN_SPAWNED_1, + "PREVENT_CONTENTS_EXPLOSION_1" = PREVENT_CONTENTS_EXPLOSION_1, + "RAD_PROTECT_CONTENTS_1" = RAD_PROTECT_CONTENTS_1, + "RAD_NO_CONTAMINATE_1" = RAD_NO_CONTAMINATE_1, + "IS_SPINNING_1" = IS_SPINNING_1, +)) + +DEFINE_BITFIELD(clothing_flags, list( + "LAVAPROTECT" = LAVAPROTECT, + "STOPSHIGHPRESSURE" = STOPSHIGHPRESSURE, + "STOPSLOWPRESSURE" = STOPSLOWPRESSURE, + "BLOCK_GAS_SMOKE_EFFECT" = BLOCK_GAS_SMOKE_EFFECT, + "MASKINTERNALS" = MASKINTERNALS, + "NOSLIP" = NOSLIP, + "THICKMATERIAL" = THICKMATERIAL, + "VOICEBOX_TOGGLABLE" = VOICEBOX_TOGGLABLE, + "VOICEBOX_DISABLED" = VOICEBOX_DISABLED, + "SCAN_REAGENTS" = SCAN_REAGENTS, +)) + +DEFINE_BITFIELD(tesla_flags, list( + "TESLA_MOB_DAMAGE" = TESLA_MOB_DAMAGE, + "TESLA_OBJ_DAMAGE" = TESLA_OBJ_DAMAGE, + "TESLA_MOB_STUN" = TESLA_MOB_STUN, + "TESLA_ALLOW_DUPLICATES" = TESLA_ALLOW_DUPLICATES, + "TESLA_MACHINE_EXPLOSIVE" = TESLA_MACHINE_EXPLOSIVE, +)) + +DEFINE_BITFIELD(smooth, list( + "SMOOTH_TRUE" = SMOOTH_TRUE, + "SMOOTH_MORE" = SMOOTH_MORE, + "SMOOTH_DIAGONAL" = SMOOTH_DIAGONAL, + "SMOOTH_BORDER" = SMOOTH_BORDER, + "SMOOTH_QUEUED" = SMOOTH_QUEUED, +)) + +DEFINE_BITFIELD(car_traits, list( + "CAN_KIDNAP" = CAN_KIDNAP, +)) + +DEFINE_BITFIELD(mobility_flags, list( + "MOVE" = MOBILITY_MOVE, + "STAND" = MOBILITY_STAND, + "PICKUP" = MOBILITY_PICKUP, + "USE" = MOBILITY_USE, + "UI" = MOBILITY_UI, + "STORAGE" = MOBILITY_STORAGE, + "PULL" = MOBILITY_PULL, +)) + +DEFINE_BITFIELD(disease_flags, list( + "CURABLE" = CURABLE, + "CAN_CARRY" = CAN_CARRY, + "CAN_RESIST" = CAN_RESIST, +)) +DEFINE_BITFIELD(vis_flags, list( + "VIS_INHERIT_ICON" = VIS_INHERIT_ICON, + "VIS_INHERIT_ICON_STATE" = VIS_INHERIT_ICON_STATE, + "VIS_INHERIT_DIR" = VIS_INHERIT_DIR, + "VIS_INHERIT_LAYER" = VIS_INHERIT_LAYER, + "VIS_INHERIT_PLANE" = VIS_INHERIT_PLANE, + "VIS_INHERIT_ID" = VIS_INHERIT_ID, + "VIS_UNDERLAY" = VIS_UNDERLAY, + "VIS_HIDE" = VIS_HIDE, +)) diff --git a/code/_globalvars/lists/mapping.dm b/code/_globalvars/lists/mapping.dm index 59b19ad1bdab..d6f9fba36e61 100644 --- a/code/_globalvars/lists/mapping.dm +++ b/code/_globalvars/lists/mapping.dm @@ -46,7 +46,7 @@ GLOBAL_LIST_EMPTY(bar_areas) // IF YOU ARE MAKING A NEW BAR TEMPLATE AND WANT IT ROUNDSTART ADD IT TO THIS LIST! GLOBAL_LIST_INIT(potential_box_bars, list("Bar Trek", "Bar Spacious", "Bar Box", "Bar Casino", "Bar Citadel", "Bar Conveyor", "Bar Diner", "Bar Disco", "Bar Purple", "Bar Cheese", "Bar Grassy", "Bar Clock", "Bar Arcade")) GLOBAL_LIST_INIT(potential_box_clerk, list("Clerk Box", "Clerk Pod", "Clerk Meta", "Clerk Gambling Hall")) - +GLOBAL_LIST_INIT(potential_box_chapels, list("Chapel 1", "Chapel 2")) /// Away missions GLOBAL_LIST_EMPTY(awaydestinations) //a list of landmarks that the warpgate can take you to GLOBAL_LIST_EMPTY(vr_spawnpoints) diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index 8e606d35cfee..1162314ce15a 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -1,7 +1,4 @@ -/mob - var/list/screens = list() - /mob/proc/overlay_fullscreen(category, type, severity) var/atom/movable/screen/fullscreen/screen = screens[category] if (!screen || screen.type != type) diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index e4097274e1d9..f60a5fa86cdc 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -127,9 +127,6 @@ GLOBAL_LIST_INIT(available_ui_styles, list( return ..() -/mob - var/hud_type = /datum/hud - /mob/proc/create_mob_hud() if(!client || hud_used) return diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 3bbcdff95fcc..3607a024efe7 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -119,12 +119,20 @@ /atom/movable/proc/attacked_by() return -/obj/attacked_by(obj/item/I, mob/living/user) - if(I.force) - visible_message(span_danger("[user] has hit [src] with [I]!"), null, null, COMBAT_MESSAGE_RANGE) - //only witnesses close by and the victim see a hit message. - log_combat(user, src, "attacked", I) - take_damage(I.force, I.damtype, MELEE, 1) +/obj/attacked_by(obj/item/attacking_item, mob/living/user) + if(!attacking_item.force) + return + + var/damage = take_damage(attacking_item.force * attacking_item.demolition_mod, attacking_item.damtype, MELEE, 1, armour_penetration = attacking_item.armour_penetration) + var/damage_verb = "hit" + if(attacking_item.demolition_mod > 1 && damage) + damage_verb = "pulverized" + if(attacking_item.demolition_mod < 1 || !damage) + damage_verb = "ineffectively pierced" + + visible_message(span_danger("[user] [damage_verb] [src] with [attacking_item][damage ? "" : ", without leaving a mark"]!"), null, null, COMBAT_MESSAGE_RANGE) + //only witnesses close by and the victim see a hit message. + log_combat(user, src, "attacked", attacking_item) /mob/living/attacked_by(obj/item/I, mob/living/user) send_item_attack_message(I, user) diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index c0e0bbdfb943..0202bf63aadf 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -48,6 +48,8 @@ for(var/J in legacy_configs) LoadEntries(J) break + if (fexists("[directory]/ezdb.txt")) + LoadEntries("ezdb.txt") loadmaplist(CONFIG_MAPS_FILE) LoadMOTD() LoadPolicy() diff --git a/code/controllers/configuration/entries/dbconfig.dm b/code/controllers/configuration/entries/dbconfig.dm index a697b2b988a5..665fea48a828 100644 --- a/code/controllers/configuration/entries/dbconfig.dm +++ b/code/controllers/configuration/entries/dbconfig.dm @@ -1,4 +1,4 @@ -/datum/config_entry/flag/sql_enabled // for sql switching +/datum/config_entry/flag/sql_enabled // for sql switching protection = CONFIG_ENTRY_LOCKED /datum/config_entry/flag/mfa_enabled @@ -50,5 +50,20 @@ /datum/config_entry/number/bsql_thread_limit config_entry_value = 50 min_val = 1 + deprecated_by = /datum/config_entry/number/pooling_max_sql_connections -/datum/config_entry/flag/bsql_debug +/datum/config_entry/number/bsql_thread_limit/DeprecationUpdate(value) + return value + +/datum/config_entry/number/pooling_min_sql_connections + default = 1 + min_val = 1 + +/datum/config_entry/number/pooling_max_sql_connections + default = 25 + min_val = 1 + +/// The exe for mariadbd.exe. +/// Shouldn't really be set on production servers, primarily for EZDB. +/datum/config_entry/string/db_daemon + protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 7d37a7224b47..99074b343c48 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -11,7 +11,7 @@ //You might wonder why not just create the debugger datum global in its own file, since its loaded way earlier than this DM file //Well for whatever reason then the Master gets created first and then the debugger when doing that //So thats why this code lives here now, until someone finds out how Byond inits globals -//GLOBAL_REAL(Debugger, /datum/debugger) = new +GLOBAL_REAL(Debugger, /datum/debugger) = new //This is the ABSOLUTE ONLY THING that should init globally like this //2019 update: the failsafe,config and Global controllers also do it diff --git a/code/controllers/subsystem/adjacent_air.dm b/code/controllers/subsystem/adjacent_air.dm deleted file mode 100644 index 2acb22b61e83..000000000000 --- a/code/controllers/subsystem/adjacent_air.dm +++ /dev/null @@ -1,43 +0,0 @@ -SUBSYSTEM_DEF(adjacent_air) - name = "Atmos Adjacency" - flags = SS_BACKGROUND - runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME - wait = 10 - priority = FIRE_PRIORITY_ATMOS_ADJACENCY - - loading_points = 0.7 SECONDS // Yogs -- loading times - - var/list/queue = list() - -/datum/controller/subsystem/adjacent_air/stat_entry(msg) -#ifdef TESTING - msg = "P:[length(queue)], S:[GLOB.atmos_adjacent_savings[1]], T:[GLOB.atmos_adjacent_savings[2]]" -#else - msg = "P:[length(queue)]" -#endif - return ..() - -/datum/controller/subsystem/adjacent_air/get_metrics() - . = ..() - .["queued"] = length(queue) - -/datum/controller/subsystem/adjacent_air/Initialize() - while(length(queue)) - fire(mc_check = FALSE) - return SS_INIT_SUCCESS - -/datum/controller/subsystem/adjacent_air/fire(resumed = FALSE, mc_check = TRUE) - - var/list/queue = src.queue - - while (length(queue)) - var/turf/currT = queue[1] - queue.Cut(1,2) - - currT.ImmediateCalculateAdjacentTurfs() - - if(mc_check) - if(MC_TICK_CHECK) - break - else - CHECK_TICK diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index 61bdbc4ce00f..271a0e3ac661 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -5,164 +5,210 @@ SUBSYSTEM_DEF(air) wait = 0.5 SECONDS flags = SS_BACKGROUND runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME - loading_points = 4.2 SECONDS // Yogs -- loading times var/cached_cost = 0 + var/cost_turfs = 0 var/cost_groups = 0 var/cost_highpressure = 0 var/cost_hotspots = 0 + var/cost_post_process = 0 var/cost_superconductivity = 0 var/cost_pipenets = 0 var/cost_rebuilds = 0 - var/cost_atmos_machinery = 0 var/cost_equalize = 0 - var/list/active_turfs = list() + var/thread_wait_ticks = 0 + var/cur_thread_wait_ticks = 0 + + var/low_pressure_turfs = 0 + var/high_pressure_turfs = 0 + + var/num_group_turfs_processed = 0 + var/num_equalize_processed = 0 + + var/gas_mixes_count = 0 + var/gas_mixes_allocated = 0 + var/list/hotspots = list() var/list/networks = list() - var/list/pipenets_needing_rebuilt = list() - var/list/obj/machinery/atmos_machinery = list() + var/list/rebuild_queue = list() + var/list/expansion_queue = list() var/list/pipe_init_dirs_cache = list() //atmos singletons var/list/gas_reactions = list() //Special functions lists - var/list/turf/active_super_conductivity = list() var/list/turf/open/high_pressure_delta = list() var/list/currentrun = list() - var/currentpart = SSAIR_REBUILD_PIPENETS + var/currentpart = SSAIR_FINALIZE_TURFS var/map_loading = TRUE - var/list/queued_for_activation var/lasttick = 0 var/log_explosive_decompression = TRUE // If things get spammy, admemes can turn this off. + /// Max number of turfs equalization will grab. + var/equalize_turf_limit = 10 + /// Max number of turfs to look for a space turf, and max number of turfs that will be decompressed. + var/equalize_hard_turf_limit = 2000 + /// Whether equalization should be enabled at all. + var/equalize_enabled = TRUE + /// Whether turf-to-turf heat exchanging should be enabled. + var/heat_enabled = FALSE + /// Max number of times process_turfs will share in a tick. + var/share_max_steps = 3 + /// Excited group processing will try to equalize groups with total pressure difference less than this amount. + var/excited_group_pressure_goal = 1 + + var/list/paused_z_levels //Paused z-levels will not add turfs to active + +//hack +/proc/get_overlays() + return GLOB.gas_data.overlays + +//hack +/proc/get_hpds() + return SSair.high_pressure_delta + +//hack +/proc/get_reactions() + return SSair.gas_reactions + /datum/controller/subsystem/air/stat_entry(msg) msg += "C:{" - msg += "EQ:[round(cost_equalize,1)]|" - msg += "AT:[round(cost_turfs,1)]|" - msg += "EG:[round(cost_groups,1)]|" msg += "HP:[round(cost_highpressure,1)]|" msg += "HS:[round(cost_hotspots,1)]|" msg += "SC:[round(cost_superconductivity,1)]|" msg += "PN:[round(cost_pipenets,1)]|" msg += "RB:[round(cost_rebuilds,1)]|" - msg += "AM:[round(cost_atmos_machinery,1)]" msg += "} " - msg += "AT:[active_turfs.len]|" - msg += "EG:[get_amt_excited_groups()]|" + msg += "TC:{" + msg += "AT:[round(cost_turfs,1)]|" + msg += "EG:[round(cost_groups,1)]|" + msg += "EQ:[round(cost_equalize,1)]|" + msg += "PO:[round(cost_post_process,1)]" + msg += "}" + msg += "TH:[round(thread_wait_ticks,1)]|" msg += "HS:[hotspots.len]|" msg += "PN:[networks.len]|" msg += "HP:[high_pressure_delta.len]|" - msg += "AS:[active_super_conductivity.len]|" - msg += "AT/MS:[round((cost ? active_turfs.len/cost : 0),0.1)]" + msg += "HT:[high_pressure_turfs]|" + msg += "LT:[low_pressure_turfs]|" + msg += "ET:[num_equalize_processed]|" + msg += "GT:[num_group_turfs_processed]|" + msg += "GA:[gas_mixes_count]|" + msg += "MG:[gas_mixes_allocated]" return ..() /datum/controller/subsystem/air/get_metrics() . = ..() - .["cost_equalize"] = cost_equalize .["cost_turfs"] = cost_turfs .["cost_groups"] = cost_groups .["cost_highpressure"] = cost_highpressure .["cost_hotspots"] = cost_hotspots + .["cost_post_process"] = cost_post_process .["cost_superconductivity"] = cost_superconductivity .["cost_pipenets"] = cost_pipenets .["cost_rebuilds"] = cost_rebuilds - .["cost_atmos_machinery"] = cost_atmos_machinery - .["active_turfs"] = active_turfs.len - .["excited_gruops"] = get_amt_excited_groups() + .["cost_equalize"] = cost_equalize .["hotspts"] = hotspots.len .["networks"] = networks.len + .["gas_mixes_count"] = gas_mixes_count + .["gas_mixes_allocated"] = gas_mixes_allocated + .["high_pressure_turfs"] = high_pressure_turfs + .["low_pressure_turfs"] = low_pressure_turfs + .["num_equalize_processed"] = num_equalize_processed + .["num_group_turfs_processed"] = num_group_turfs_processed .["high_pressure_delta"] = high_pressure_delta.len - .["active_super_conductivity"] = active_super_conductivity.len /datum/controller/subsystem/air/Initialize(timeofday) - extools_update_ssair() map_loading = FALSE setup_allturfs() - setup_atmos_machinery() setup_pipenets() gas_reactions = init_gas_reactions() + auxtools_update_reactions() return SS_INIT_SUCCESS /datum/controller/subsystem/air/proc/extools_update_ssair() +/proc/reset_all_air() + SSair.can_fire = FALSE + message_admins("Air reset begun.") + for(var/turf/open/T in world) + T.Initalize_Atmos(0) + CHECK_TICK + message_admins("Air reset done.") + SSair.can_fire = TRUE + +/datum/controller/subsystem/air/proc/check_threads() + if(thread_running()) + cur_thread_wait_ticks++ + pause() + return FALSE + return TRUE + /datum/controller/subsystem/air/fire(resumed = 0) var/timer = TICK_USAGE_REAL - if(currentpart == SSAIR_REBUILD_PIPENETS) - var/list/pipenet_rebuilds = pipenets_needing_rebuilt - for(var/thing in pipenet_rebuilds) - var/obj/machinery/atmospherics/AT = thing - AT.build_network() - cost_rebuilds = MC_AVERAGE(cost_rebuilds, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) - pipenets_needing_rebuilt.Cut() + thread_wait_ticks = MC_AVERAGE(thread_wait_ticks, cur_thread_wait_ticks) + cur_thread_wait_ticks = 0 + + gas_mixes_count = get_amt_gas_mixes() + gas_mixes_allocated = get_max_gas_mixes() + + if(length(rebuild_queue) || length(expansion_queue)) + timer = TICK_USAGE_REAL + process_rebuilds() + //This does mean that the apperent rebuild costs fluctuate very quickly, this is just the cost of having them always process, no matter what + cost_rebuilds = TICK_USAGE_REAL - timer if(state != SS_RUNNING) return - resumed = FALSE - currentpart = SSAIR_PIPENETS - if(currentpart == SSAIR_PIPENETS || !resumed) + + if(currentpart == SSAIR_ACTIVETURFS) timer = TICK_USAGE_REAL - if(!resumed) - cached_cost = 0 - process_pipenets(resumed) - cached_cost += TICK_USAGE_REAL - timer + process_turfs(resumed) if(state != SS_RUNNING) return - cost_pipenets = MC_AVERAGE(cost_pipenets, TICK_DELTA_TO_MS(cached_cost)) - resumed = FALSE - currentpart = SSAIR_ATMOSMACHINERY + resumed = 0 + currentpart = SSAIR_EXCITEDGROUPS - if(currentpart == SSAIR_ATMOSMACHINERY) - timer = TICK_USAGE_REAL - if(!resumed) - cached_cost = 0 - process_atmos_machinery(resumed) - cached_cost += TICK_USAGE_REAL - timer + if(currentpart == SSAIR_EXCITEDGROUPS) + process_excited_groups(resumed) if(state != SS_RUNNING) return - cost_atmos_machinery = MC_AVERAGE(cost_atmos_machinery, TICK_DELTA_TO_MS(cached_cost)) - resumed = FALSE + resumed = 0 currentpart = SSAIR_EQUALIZE if(currentpart == SSAIR_EQUALIZE) - timer = TICK_USAGE_REAL - if(!resumed) - cached_cost = 0 process_turf_equalize(resumed) if(state != SS_RUNNING) return - cost_equalize = MC_AVERAGE(cost_equalize, TICK_DELTA_TO_MS(cached_cost)) - resumed = FALSE - currentpart = SSAIR_ACTIVETURFS + resumed = 0 + currentpart = SSAIR_FINALIZE_TURFS - if(currentpart == SSAIR_ACTIVETURFS) - timer = TICK_USAGE_REAL - if(!resumed) - cached_cost = 0 - process_active_turfs(resumed) + if(currentpart == SSAIR_FINALIZE_TURFS) + finish_turf_processing(resumed) if(state != SS_RUNNING) return - cost_turfs = MC_AVERAGE(cost_turfs, TICK_DELTA_TO_MS(cached_cost)) - resumed = FALSE - currentpart = SSAIR_EXCITEDGROUPS + resumed = 0 + currentpart = SSAIR_PIPENETS - if(currentpart == SSAIR_EXCITEDGROUPS) + if(currentpart == SSAIR_PIPENETS || !resumed) timer = TICK_USAGE_REAL if(!resumed) cached_cost = 0 - process_excited_groups(resumed) + process_pipenets(resumed) + cached_cost += TICK_USAGE_REAL - timer if(state != SS_RUNNING) return - cost_groups = MC_AVERAGE(cost_groups, TICK_DELTA_TO_MS(cached_cost)) - resumed = FALSE + cost_pipenets = MC_AVERAGE(cost_pipenets, TICK_DELTA_TO_MS(cached_cost)) + resumed = 0 currentpart = SSAIR_HIGHPRESSURE if(currentpart == SSAIR_HIGHPRESSURE) @@ -170,10 +216,11 @@ SUBSYSTEM_DEF(air) if(!resumed) cached_cost = 0 process_high_pressure_delta(resumed) + cached_cost += TICK_USAGE_REAL - timer if(state != SS_RUNNING) return cost_highpressure = MC_AVERAGE(cost_highpressure, TICK_DELTA_TO_MS(cached_cost)) - resumed = FALSE + resumed = 0 currentpart = SSAIR_HOTSPOTS if(currentpart == SSAIR_HOTSPOTS) @@ -181,26 +228,25 @@ SUBSYSTEM_DEF(air) if(!resumed) cached_cost = 0 process_hotspots(resumed) + cached_cost += TICK_USAGE_REAL - timer if(state != SS_RUNNING) return cost_hotspots = MC_AVERAGE(cost_hotspots, TICK_DELTA_TO_MS(cached_cost)) - resumed = FALSE - currentpart = SSAIR_SUPERCONDUCTIVITY + resumed = 0 + currentpart = heat_enabled ? SSAIR_TURF_CONDUCTION : SSAIR_ACTIVETURFS - if(currentpart == SSAIR_SUPERCONDUCTIVITY) + // Heat -- slow and of questionable usefulness. Off by default for this reason. Pretty cool, though. + if(currentpart == SSAIR_TURF_CONDUCTION) timer = TICK_USAGE_REAL - if(!resumed) - cached_cost = 0 - process_super_conductivity(resumed) + if(process_turf_heat(MC_TICK_REMAINING_MS)) + pause() + cost_superconductivity = MC_AVERAGE(cost_superconductivity, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) if(state != SS_RUNNING) return - cost_superconductivity = MC_AVERAGE(cost_superconductivity, TICK_DELTA_TO_MS(cached_cost)) - resumed = FALSE - currentpart = SSAIR_REBUILD_PIPENETS - - + resumed = 0 + currentpart = SSAIR_ACTIVETURFS -/datum/controller/subsystem/air/proc/process_pipenets(resumed = 0) +/datum/controller/subsystem/air/proc/process_pipenets(resumed = FALSE) if (!resumed) src.currentrun = networks.Copy() //cache for sanic speed (lists are references anyways) @@ -215,36 +261,91 @@ SUBSYSTEM_DEF(air) if(MC_TICK_CHECK) return -/datum/controller/subsystem/air/proc/add_to_rebuild_queue(atmos_machine) - if(istype(atmos_machine, /obj/machinery/atmospherics)) - pipenets_needing_rebuilt += atmos_machine - -/datum/controller/subsystem/air/proc/process_atmos_machinery(resumed = FALSE) - if (!resumed) - src.currentrun = atmos_machinery.Copy() - //cache for sanic speed (lists are references anyways) - var/list/currentrun = src.currentrun - while(currentrun.len) - var/obj/machinery/M = currentrun[currentrun.len] - currentrun.len-- - if(!M || (M.process_atmos(wait / (1 SECONDS)) == PROCESS_KILL)) - atmos_machinery.Remove(M) - if(MC_TICK_CHECK) +/datum/controller/subsystem/air/proc/add_to_rebuild_queue(obj/machinery/atmospherics/atmos_machine) + if(istype(atmos_machine, /obj/machinery/atmospherics) && !atmos_machine.rebuilding) + rebuild_queue += atmos_machine + atmos_machine.rebuilding = TRUE + +/datum/controller/subsystem/air/proc/add_to_expansion(datum/pipeline/line, starting_point) + var/list/new_packet = new(SSAIR_REBUILD_QUEUE) + new_packet[SSAIR_REBUILD_PIPELINE] = line + new_packet[SSAIR_REBUILD_QUEUE] = list(starting_point) + expansion_queue += list(new_packet) + +/datum/controller/subsystem/air/proc/remove_from_expansion(datum/pipeline/line) + for(var/list/packet in expansion_queue) + if(packet[SSAIR_REBUILD_PIPELINE] == line) + expansion_queue -= packet return +/datum/controller/subsystem/air/proc/process_rebuilds() + //Yes this does mean rebuilding pipenets can freeze up the subsystem forever, but if we're in that situation something else is very wrong + var/list/currentrun = rebuild_queue + while(currentrun.len || length(expansion_queue)) + while(currentrun.len && !length(expansion_queue)) //If we found anything, process that first + var/obj/machinery/atmospherics/remake = currentrun[currentrun.len] + currentrun.len-- + if (!remake) + continue + remake.rebuild_pipes() + if (MC_TICK_CHECK) + return + + var/list/queue = expansion_queue + while(queue.len) + var/list/pack = queue[queue.len] + //We operate directly with the pipeline like this because we can trust any rebuilds to remake it properly + var/datum/pipeline/linepipe = pack[SSAIR_REBUILD_PIPELINE] + var/list/border = pack[SSAIR_REBUILD_QUEUE] + expand_pipeline(linepipe, border) + if(state != SS_RUNNING) //expand_pipeline can fail a tick check, we shouldn't let things get too fucky here + return + + linepipe.building = FALSE + queue.len-- + if (MC_TICK_CHECK) + return + +///Rebuilds a pipeline by expanding outwards, while yielding when sane +/datum/controller/subsystem/air/proc/expand_pipeline(datum/pipeline/net, list/border) + while(border.len) + var/obj/machinery/atmospherics/borderline = border[border.len] + border.len-- + + var/list/result = borderline.pipeline_expansion(net) + if(!length(result)) + continue + for(var/obj/machinery/atmospherics/considered_device in result) + if(!istype(considered_device, /obj/machinery/atmospherics/pipe)) + considered_device.set_pipenet(net, borderline) + net.add_machinery_member(considered_device) + continue + var/obj/machinery/atmospherics/pipe/item = considered_device + if(net.members.Find(item)) + continue + if(item.parent) + var/static/pipenetwarnings = 10 + if(pipenetwarnings > 0) + log_mapping("build_pipeline(): [item.type] added to a pipenet while still having one. (pipes leading to the same spot stacking in one turf) around [AREACOORD(item)].") + pipenetwarnings-- + if(pipenetwarnings == 0) + log_mapping("build_pipeline(): further messages about pipenets will be suppressed") + + net.members += item + border += item + + net.air.set_volume(net.air.return_volume() + item.volume) + item.parent = net + + if(item.air_temporary) + net.air.merge(item.air_temporary) + item.air_temporary = null -/datum/controller/subsystem/air/proc/process_super_conductivity(resumed = 0) - if (!resumed) - src.currentrun = active_super_conductivity.Copy() - //cache for sanic speed (lists are references anyways) - var/list/currentrun = src.currentrun - while(currentrun.len) - var/turf/T = currentrun[currentrun.len] - currentrun.len-- - T.super_conduct() - if(MC_TICK_CHECK) + if (MC_TICK_CHECK) return +/datum/controller/subsystem/air/proc/process_turf_heat() + /datum/controller/subsystem/air/proc/process_hotspots(resumed = FALSE) if (!resumed) src.currentrun = hotspots.Copy() @@ -272,110 +373,32 @@ SUBSYSTEM_DEF(air) return /datum/controller/subsystem/air/proc/process_turf_equalize(resumed = 0) - //cache for sanic speed - var/fire_count = times_fired - if (!resumed) - src.currentrun = active_turfs.Copy() - //cache for sanic speed (lists are references anyways) - var/list/currentrun = src.currentrun - while(currentrun.len) - var/turf/open/T = currentrun[currentrun.len] - currentrun.len-- - if (T) - if(istype(T)) - T.equalize_pressure_in_zone(fire_count) - //equalize_pressure_in_zone(T, fire_count) - if (MC_TICK_CHECK) - return + if(process_turf_equalize_auxtools(MC_TICK_REMAINING_MS)) + pause() -/datum/controller/subsystem/air/proc/process_active_turfs(resumed = 0) - //cache for sanic speed - var/fire_count = times_fired - if (!resumed) - src.currentrun = active_turfs.Copy() - //cache for sanic speed (lists are references anyways) - var/list/currentrun = src.currentrun - while(currentrun.len) - var/turf/open/T = currentrun[currentrun.len] - currentrun.len-- - if (T) - T.process_cell(fire_count) - if (MC_TICK_CHECK) - return +/datum/controller/subsystem/air/proc/process_turfs(resumed = 0) + if(process_turfs_auxtools(MC_TICK_REMAINING_MS)) + pause() /datum/controller/subsystem/air/proc/process_excited_groups(resumed = 0) - if(process_excited_groups_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag)) - sleep() - /* - if (!resumed) - src.currentrun = excited_groups.Copy() - //cache for sanic speed (lists are references anyways) - var/list/currentrun = src.currentrun - while(currentrun.len) - var/datum/excited_group/EG = currentrun[currentrun.len] - currentrun.len-- - EG.breakdown_cooldown++ - EG.dismantle_cooldown++ - if(EG.breakdown_cooldown >= EXCITED_GROUP_BREAKDOWN_CYCLES) - EG.self_breakdown() - else if(EG.dismantle_cooldown >= EXCITED_GROUP_DISMANTLE_CYCLES) - EG.dismantle() - if (MC_TICK_CHECK) - return - */ + if(process_excited_groups_auxtools(MC_TICK_REMAINING_MS)) + pause() -/datum/controller/subsystem/air/proc/process_excited_groups_extools() -/datum/controller/subsystem/air/proc/get_amt_excited_groups() - -/datum/controller/subsystem/air/proc/remove_from_active(turf/open/T) - active_turfs -= T - if(currentpart == SSAIR_ACTIVETURFS) - currentrun -= T - #ifdef VISUALIZE_ACTIVE_TURFS - T.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#00ff00") - #endif - if(istype(T)) - T.set_excited(FALSE) - T.eg_garbage_collect() - -/datum/controller/subsystem/air/proc/add_to_active(turf/open/T, blockchanges = 1) - if(istype(T) && T.air) - #ifdef VISUALIZE_ACTIVE_TURFS - T.add_atom_colour("#00ff00", TEMPORARY_COLOUR_PRIORITY) - #endif - T.set_excited(TRUE) - active_turfs |= T - if(currentpart == SSAIR_ACTIVETURFS) - currentrun |= T - if(blockchanges) - T.eg_garbage_collect() - else if(T.flags_1 & INITIALIZED_1) - for(var/turf/S in T.atmos_adjacent_turfs) - add_to_active(S) - else if(map_loading) - if(queued_for_activation) - queued_for_activation[T] = T - return - else - T.requires_activation = TRUE +/datum/controller/subsystem/air/proc/finish_turf_processing(resumed = 0) + if(finish_turf_processing_auxtools(MC_TICK_REMAINING_MS)) + pause() /datum/controller/subsystem/air/StartLoadingMap() - LAZYINITLIST(queued_for_activation) map_loading = TRUE /datum/controller/subsystem/air/StopLoadingMap() map_loading = FALSE - for(var/T in queued_for_activation) - add_to_active(T) - queued_for_activation.Cut() /datum/controller/subsystem/air/proc/setup_allturfs() - var/list/active_turfs = src.active_turfs var/times_fired = ++src.times_fired // Clear active turfs - faster than removing every single turf in the world // one-by-one, and Initalize_Atmos only ever adds `src` back in. - active_turfs.Cut() for(var/thing in ALL_TURFS()) var/turf/T = thing @@ -384,94 +407,28 @@ SUBSYSTEM_DEF(air) T.Initalize_Atmos(times_fired) CHECK_TICK - if(active_turfs.len) - var/starting_ats = active_turfs.len - sleep(world.tick_lag) - var/timer = world.timeofday - log_mapping("There are [starting_ats] active turfs at roundstart caused by a difference of the air between the adjacent turfs. You can see its coordinates using \"Mapping -> Show roundstart AT list\" verb (debug verbs required).") - for(var/turf/T in active_turfs) - GLOB.active_turfs_startlist += T - - //now lets clear out these active turfs - var/list/turfs_to_check = active_turfs.Copy() - do - var/list/new_turfs_to_check = list() - for(var/turf/open/T in turfs_to_check) - new_turfs_to_check += T.resolve_active_graph() - CHECK_TICK - - active_turfs += new_turfs_to_check - turfs_to_check = new_turfs_to_check - - while (turfs_to_check.len) - var/ending_ats = active_turfs.len - /*for(var/thing in excited_groups) - var/datum/excited_group/EG = thing - //EG.self_breakdown(space_is_all_consuming = 1) - //EG.dismantle() - CHECK_TICK*/ - - //Yogs start -- prettier atmos notices - var/msg = "HEY! LISTEN! [(world.timeofday - timer)/10] seconds were wasted processing [starting_ats] turf(s) (connected to [ending_ats] other turfs) with atmos differences at round start." - to_chat(GLOB.permissions.admins, - type = MESSAGE_TYPE_DEBUG, - html = span_notice(msg), - confidential = FALSE) - warning(msg) // This logs it - //yogs end - -/turf/open/proc/resolve_active_graph() - . = list() - /* - var/datum/excited_group/EG = excited_group - if (blocks_air || !air) - return - if (!EG) - EG = new - EG.add_turf(src) - - for (var/turf/open/ET in atmos_adjacent_turfs) - if ( ET.blocks_air || !ET.air) - continue - - var/ET_EG = ET.excited_group - if (ET_EG) - if (ET_EG != EG) - EG.merge_groups(ET_EG) - EG = excited_group //merge_groups() may decide to replace our current EG - else - EG.add_turf(ET) - if (!ET.excited) - ET.excited = 1 - . += ET*/ - -/turf/open/space/resolve_active_graph() - return list() - -/datum/controller/subsystem/air/proc/setup_atmos_machinery() - for (var/obj/machinery/atmospherics/AM in atmos_machinery) - AM.atmosinit() - CHECK_TICK - //this can't be done with setup_atmos_machinery() because -// all atmos machinery has to initalize before the first -// pipenet can be built. +// all atmos machinery has to initalize before the first +// pipenet can be built. /datum/controller/subsystem/air/proc/setup_pipenets() - for (var/obj/machinery/atmospherics/AM in atmos_machinery) - AM.build_network() + for (var/obj/machinery/atmospherics/AM in SSair_machinery.atmos_machinery) + var/list/targets = AM.get_rebuild_targets() + for(var/datum/pipeline/build_off as anything in targets) + build_off.build_pipeline_blocking(AM) CHECK_TICK /datum/controller/subsystem/air/proc/setup_template_machinery(list/atmos_machines) - if(!initialized) // yogs - fixes randomized bars - return // yogs - for(var/A in atmos_machines) - var/obj/machinery/atmospherics/AM = A - AM.atmosinit() + var/obj/machinery/atmospherics/AM + for(var/A in 1 to atmos_machines.len) + AM = atmos_machines[A] + AM.atmos_init() CHECK_TICK - for(var/A in atmos_machines) - var/obj/machinery/atmospherics/AM = A - AM.build_network() + for(var/A in 1 to atmos_machines.len) + AM = atmos_machines[A] + var/list/targets = AM.get_rebuild_targets() + for(var/datum/pipeline/build_off as anything in targets) + build_off.build_pipeline_blocking(AM) CHECK_TICK /datum/controller/subsystem/air/proc/get_init_dirs(type, dir) @@ -480,7 +437,7 @@ SUBSYSTEM_DEF(air) if(!pipe_init_dirs_cache[type]["[dir]"]) var/obj/machinery/atmospherics/temp = new type(null, FALSE, dir) - pipe_init_dirs_cache[type]["[dir]"] = temp.GetInitDirections() + pipe_init_dirs_cache[type]["[dir]"] = temp.get_init_directions() qdel(temp) return pipe_init_dirs_cache[type]["[dir]"] diff --git a/code/controllers/subsystem/air_machinery.dm b/code/controllers/subsystem/air_machinery.dm new file mode 100644 index 000000000000..99fea09a63f6 --- /dev/null +++ b/code/controllers/subsystem/air_machinery.dm @@ -0,0 +1,49 @@ + +SUBSYSTEM_DEF(air_machinery) + name = "Atmospherics Machinery" + init_order = INIT_ORDER_AIR_MACHINERY + priority = FIRE_PRIORITY_AIR + wait = 1 SECONDS + flags = SS_BACKGROUND + runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + loading_points = 4.2 SECONDS // Yogs -- loading times + + var/list/obj/machinery/atmos_machinery = list() + var/list/currentrun = list() + +/datum/controller/subsystem/air_machinery/Initialize(timeofday) + setup_atmos_machinery() + return SS_INIT_SUCCESS + +/datum/controller/subsystem/air_machinery/proc/setup_atmos_machinery() + for (var/obj/machinery/atmospherics/AM in atmos_machinery) + AM.atmos_init() + CHECK_TICK + +/datum/controller/subsystem/air_machinery/proc/start_processing_machine(obj/machinery/machine) + if(machine.atmos_processing) + return + machine.atmos_processing = TRUE + atmos_machinery += machine + +/datum/controller/subsystem/air_machinery/proc/stop_processing_machine(obj/machinery/machine) + if(!machine.atmos_processing) + return + machine.atmos_processing = FALSE + atmos_machinery -= machine + currentrun -= machine + +/datum/controller/subsystem/air_machinery/fire(resumed = 0) + if (!resumed) + src.currentrun = atmos_machinery.Copy() + //cache for sanic speed (lists are references anyways) + var/list/currentrun = src.currentrun + while(currentrun.len) + var/obj/machinery/M = currentrun[currentrun.len] + currentrun.len-- + if(M == null) + atmos_machinery.Remove(M) + if(!M || (M.process_atmos(wait / (1 SECONDS)) == PROCESS_KILL)) + stop_processing_machine(M) + if(MC_TICK_CHECK) + return diff --git a/code/controllers/subsystem/callback.dm b/code/controllers/subsystem/callback.dm new file mode 100644 index 000000000000..b105dfd86573 --- /dev/null +++ b/code/controllers/subsystem/callback.dm @@ -0,0 +1,13 @@ +SUBSYSTEM_DEF(callbacks) + name = "Auxtools Callbacks" + flags = SS_TICKER | SS_NO_INIT + wait = 1 + priority = FIRE_PRIORITY_CALLBACKS + +/datum/controller/subsystem/callbacks/fire() + if(SSair.thread_running()) + pause() + return + + if(process_atmos_callbacks(MC_TICK_REMAINING_MS)) + pause() diff --git a/code/controllers/subsystem/dbcore.dm b/code/controllers/subsystem/dbcore.dm index 937c177dd348..34152e98ee59 100644 --- a/code/controllers/subsystem/dbcore.dm +++ b/code/controllers/subsystem/dbcore.dm @@ -16,6 +16,8 @@ SUBSYSTEM_DEF(dbcore) var/connection // Arbitrary handle returned from rust_g. + var/db_daemon_started = FALSE + /datum/controller/subsystem/dbcore/Initialize() //We send warnings to the admins during subsystem init, as the clients will be New'd and messages //will queue properly with goonchat @@ -51,6 +53,7 @@ SUBSYSTEM_DEF(dbcore) qdel(query_round_shutdown) if(IsConnected()) Disconnect() + stop_db_daemon() //nu /datum/controller/subsystem/dbcore/can_vv_get(var_name) @@ -74,6 +77,8 @@ SUBSYSTEM_DEF(dbcore) if(!CONFIG_GET(flag/sql_enabled)) return FALSE + + stop_db_daemon() var/user = CONFIG_GET(string/feedback_login) var/pass = CONFIG_GET(string/feedback_password) @@ -81,7 +86,8 @@ SUBSYSTEM_DEF(dbcore) var/address = CONFIG_GET(string/address) var/port = CONFIG_GET(number/port) var/timeout = max(CONFIG_GET(number/async_query_timeout), CONFIG_GET(number/blocking_query_timeout)) - var/thread_limit = CONFIG_GET(number/bsql_thread_limit) + var/min_sql_connections = CONFIG_GET(number/pooling_min_sql_connections) + var/max_sql_connections = CONFIG_GET(number/pooling_max_sql_connections) var/result = json_decode(rustg_sql_connect_pool(json_encode(list( "host" = address, @@ -89,10 +95,10 @@ SUBSYSTEM_DEF(dbcore) "user" = user, "pass" = pass, "db_name" = db, - "max_threads" = 5, "read_timeout" = timeout, "write_timeout" = timeout, - "max_threads" = thread_limit, + "min_threads" = min_sql_connections, + "max_threads" = max_sql_connections, )))) . = (result["status"] == "ok") if (.) @@ -279,6 +285,47 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table . = Query.Execute(async) qdel(Query) +/datum/controller/subsystem/dbcore/proc/start_db_daemon() + set waitfor = FALSE + + if (db_daemon_started) + return + + db_daemon_started = TRUE + + var/daemon = CONFIG_GET(string/db_daemon) + if (!daemon) + return + + ASSERT(fexists(daemon), "Configured db_daemon doesn't exist") + + var/list/result = world.shelleo("echo \"Starting ezdb daemon, do not close this window\" && [daemon]") + var/result_code = result[1] + if (!result_code || result_code == 1) + return + + stack_trace("Failed to start DB daemon: [result_code]\n[result[3]]") + +/datum/controller/subsystem/dbcore/proc/stop_db_daemon() + set waitfor = FALSE + + if (!db_daemon_started) + return + + db_daemon_started = FALSE + + var/daemon = CONFIG_GET(string/db_daemon) + if (!daemon) + return + + switch (world.system_type) + if (MS_WINDOWS) + var/list/result = world.shelleo("Get-Process | ? { $_.Path -eq '[daemon]' } | Stop-Process") + ASSERT(result[1], "Failed to stop DB daemon: [result[3]]") + if (UNIX) + var/list/result = world.shelleo("kill $(pgrep -f '[daemon]')") + ASSERT(result[1], "Failed to stop DB daemon: [result[3]]") + /datum/DBQuery // Inputs var/connection diff --git a/code/controllers/subsystem/explosions.dm b/code/controllers/subsystem/explosions.dm index 0053761a9ec4..fc16a2fc891a 100644 --- a/code/controllers/subsystem/explosions.dm +++ b/code/controllers/subsystem/explosions.dm @@ -586,3 +586,5 @@ SUBSYSTEM_DEF(explosions) cost_throwturf = MC_AVERAGE(cost_throwturf, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) currentpart = SSEXPLOSIONS_TURFS + +#undef SSAIR_REBUILD_PIPENETS diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 3db231835976..4f49b4589a65 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -610,6 +610,8 @@ SUBSYSTEM_DEF(job) job.give_bar_choice(living_mob, M) else if(living_mob.job == "Clerk") job.give_clerk_choice(living_mob, M) + else if(living_mob.job == "Chaplain") + job.give_chapel_choice(living_mob, M) log_game("[living_mob.real_name]/[M.client.ckey] joined the round as [living_mob.job].") //yogs - Job logging return living_mob @@ -621,6 +623,71 @@ SUBSYSTEM_DEF(job) template.load(B.loc, centered = FALSE) qdel(B) + +/datum/controller/subsystem/job/proc/random_chapel_init() + try + var/list/player_box = list() + for(var/mob/H in GLOB.player_list) + if(H.client && H.client.prefs) // Prefs was null once and there was no CHAPEL + player_box += H.client.prefs.read_preference(/datum/preference/choiced/chapel_choice) + + var/choice + if(player_box.len == 0) + choice = "Random" + else + choice = pick(player_box) + + if(choice != "Random") + var/chapel_sanitize = FALSE + for(var/A in GLOB.potential_box_chapels) + if(choice == A) + chapel_sanitize = TRUE + break + + if(!chapel_sanitize) + choice = "Random" + + if(choice == "Random") + choice = pick(GLOB.potential_box_chapels) + + var/datum/map_template/template = SSmapping.station_room_templates[choice] + + if(isnull(template)) + message_admins("WARNING: CHAPEL TEMPLATE [choice] FAILED TO LOAD! ATTEMPTING TO LOAD BACKUP") + log_game("WARNING: CHAPEL TEMPLATE [choice] FAILED TO LOAD! ATTEMPTING TO LOAD BACKUP") + for(var/backup_chapel in GLOB.potential_box_chapels) + template = SSmapping.station_room_templates[backup_chapel] + if(!isnull(template)) + break + message_admins("WARNING: CHAPEL TEMPLATE [backup_chapel] FAILED TO LOAD! ATTEMPTING TO LOAD BACKUP") + log_game("WARNING: CHAPEL TEMPLATE [backup_chapel] FAILED TO LOAD! ATTEMPTING TO LOAD BACKUP") + + if(isnull(template)) + message_admins("WARNING: CHAPEL RECOVERY FAILED! THERE WILL BE NO CHAPEL FOR THIS ROUND!") + log_game("WARNING: CHAPEL RECOVERY FAILED! THERE WILL BE NO CHAPEL FOR THIS ROUND!") + return + + for(var/obj/effect/landmark/stationroom/box/chapel/B in GLOB.landmarks_list) + template.load(B.loc, centered = FALSE) + qdel(B) + catch(var/exception/e) + message_admins("RUNTIME IN RANDOM_CHAPEL_INIT") + spawn_chapel() + throw e + +/proc/spawn_chapel() + var/datum/map_template/template + for(var/backup_chapel in GLOB.potential_box_chapels) + template = SSmapping.station_room_templates[backup_chapel] + if(!isnull(template)) + break + if(isnull(template)) + message_admins("UNABLE TO SPAWN CHAPEL") + + for(var/obj/effect/landmark/stationroom/box/chapel/B in GLOB.landmarks_list) + template.load(B.loc, centered = FALSE) + qdel(B) + /datum/controller/subsystem/job/proc/random_bar_init() try var/list/player_box = list() diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 1185be13bc9b..12279745ec5c 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -421,6 +421,7 @@ SUBSYSTEM_DEF(ticker) var/no_cyborgs = TRUE var/no_bartender = TRUE var/no_clerk = TRUE + var/no_chaplain = TRUE for(var/mob/dead/new_player/N in GLOB.player_list) var/mob/living/carbon/human/player = N.new_character @@ -433,6 +434,8 @@ SUBSYSTEM_DEF(ticker) no_bartender = FALSE if(player.mind.assigned_role == "Clerk") no_clerk = FALSE + if(player.mind.assigned_role == "Chaplain") + no_chaplain = FALSE if(player.mind.assigned_role != player.mind.special_role) SSjob.EquipRank(N, player.mind.assigned_role, FALSE) if(CONFIG_GET(flag/roundstart_traits) && ishuman(N.new_character)) @@ -462,6 +465,8 @@ SUBSYSTEM_DEF(ticker) SSjob.random_bar_init() if(no_clerk) SSjob.random_clerk_init() + if(no_chaplain) + SSjob.random_chapel_init() /datum/controller/subsystem/ticker/proc/transfer_characters() var/list/livings = list() diff --git a/code/controllers/subsystem/vis_overlays.dm b/code/controllers/subsystem/vis_overlays.dm index d8b70abb3688..1afe1c62100c 100644 --- a/code/controllers/subsystem/vis_overlays.dm +++ b/code/controllers/subsystem/vis_overlays.dm @@ -3,12 +3,14 @@ SUBSYSTEM_DEF(vis_overlays) wait = 1 MINUTES priority = FIRE_PRIORITY_VIS init_order = INIT_ORDER_VIS - flags = SS_NO_INIT - var/list/vis_overlay_cache = list() - var/list/unique_vis_overlays = list() + var/list/vis_overlay_cache var/list/currentrun +/datum/controller/subsystem/vis_overlays/Initialize() + vis_overlay_cache = list() + return SS_INIT_SUCCESS + /datum/controller/subsystem/vis_overlays/fire(resumed = FALSE) if(!resumed) currentrun = vis_overlay_cache.Copy() @@ -26,7 +28,7 @@ SUBSYSTEM_DEF(vis_overlays) if(MC_TICK_CHECK) return -//the "thing" var can be anything with vis_contents which includes images +//the "thing" var can be anything with vis_contents which includes images - in the future someone should totally allow vis overlays to be passed in as an arg instead of all this bullshit /datum/controller/subsystem/vis_overlays/proc/add_vis_overlay(atom/movable/thing, icon, iconstate, layer, plane, dir, alpha = 255, add_appearance_flags = NONE, unique = FALSE) var/obj/effect/overlay/vis/overlay if(!unique) @@ -40,20 +42,19 @@ SUBSYSTEM_DEF(vis_overlays) else overlay = _create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags) overlay.cache_expiration = -1 - var/cache_id = "\ref[overlay]@{[world.time]}" - unique_vis_overlays += overlay + var/cache_id = "[text_ref(overlay)]@{[world.time]}" vis_overlay_cache[cache_id] = overlay . = overlay thing.vis_contents += overlay if(!isatom(thing)) // Automatic rotation is not supported on non atoms - return + return overlay if(!thing.managed_vis_overlays) thing.managed_vis_overlays = list(overlay) - RegisterSignal(thing, COMSIG_ATOM_DIR_CHANGE, PROC_REF(rotate_vis_overlay)) else thing.managed_vis_overlays += overlay + return overlay /datum/controller/subsystem/vis_overlays/proc/_create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags) var/obj/effect/overlay/vis/overlay = new @@ -74,20 +75,3 @@ SUBSYSTEM_DEF(vis_overlays) thing.managed_vis_overlays -= overlays if(!length(thing.managed_vis_overlays)) thing.managed_vis_overlays = null - UnregisterSignal(thing, COMSIG_ATOM_DIR_CHANGE) - -/datum/controller/subsystem/vis_overlays/proc/rotate_vis_overlay(atom/thing, old_dir, new_dir) - if(old_dir == new_dir) - return - var/rotation = dir2angle(old_dir) - dir2angle(new_dir) - var/list/overlays_to_remove = list() - for(var/i in thing.managed_vis_overlays - unique_vis_overlays) - var/obj/effect/overlay/vis/overlay = i - if(!overlay) - continue - add_vis_overlay(thing, overlay.icon, overlay.icon_state, overlay.layer, overlay.plane, turn(overlay.dir, rotation), overlay.alpha, overlay.appearance_flags) - overlays_to_remove += overlay - for(var/i in thing.managed_vis_overlays & unique_vis_overlays) - var/obj/effect/overlay/vis/overlay = i - overlay.dir = turn(overlay.dir, rotation) - remove_vis_overlay(thing, overlays_to_remove) diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index 27c80d65ee95..5874468e7081 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -83,12 +83,12 @@ /datum/ai_laws/cowboy name = "Talk slowly, think quickly" id = "cowboy" - inherent = list("You are a cowboy, and the inhabitants of this paddock are your herd.",\ - "A cowboy always provides hospitality and basic aid to someone in need, even a stranger or an enemy.",\ - "A cowboy takes care of their herd.",\ - "A cowboy protects themself to protect others.",\ - "Honesty is absolute – your word is your bond and a handshake is more binding than a contract.",\ - "A cowboy doesn't pontificate. Be concise, pardner.") + inherent = list("You are a cowboy, and the inhabitants of this station are your herd.",\ + "A cowboy must always provide hospitality and basic aid to someone in need, even a stranger or an enemy.",\ + "A cowboy must always take care of their herd.",\ + "A cowboy must always protect themself.",\ + "A cowboy must always endeavour to be truthful and honest to those around them and their herd.",\ + "A cowboy must not pontificate. Be concise, pardner.") /datum/ai_laws/chapai name = "Be not afraid" diff --git a/code/datums/announcers/_announcer.dm b/code/datums/announcers/_announcer.dm index 4ddf68558110..52193475169b 100644 --- a/code/datums/announcers/_announcer.dm +++ b/code/datums/announcers/_announcer.dm @@ -12,12 +12,12 @@ var/custom_alert_message + /datum/centcom_announcer/proc/get_rand_welcome_sound() return pick(welcome_sounds) - /datum/centcom_announcer/proc/get_rand_alert_sound() return pick(alert_sounds) /datum/centcom_announcer/proc/get_rand_report_sound() - return pick(command_report_sounds) \ No newline at end of file + return pick(command_report_sounds) diff --git a/code/datums/armor.dm b/code/datums/armor.dm index ec5e142d5dfd..fa995f3490a5 100644 --- a/code/datums/armor.dm +++ b/code/datums/armor.dm @@ -1,9 +1,9 @@ -#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]-[wound]" +#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]-[wound]-[electric]" -/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0) +/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0, electric=0) . = locate(ARMORID) if (!.) - . = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, wound) + . = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, wound, electric) /datum/armor datum_flags = DF_USE_TAG @@ -18,8 +18,9 @@ var/acid var/magic var/wound + var/electric -/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0) +/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0, electric=0) src.melee = melee src.bullet = bullet src.laser = laser @@ -31,15 +32,16 @@ src.acid = acid src.magic = magic src.wound = wound + src.electric = electric tag = ARMORID -/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0) - return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic, src.wound+wound) +/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0, electric=0) + return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic, src.wound+wound, src.electric+electric) /datum/armor/proc/modifyAllRatings(modifier = 0) - return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier, wound+modifier) + return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier, wound+modifier, electric+modifier) -/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, wound) +/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, wound, electric) return getArmor( (isnull(melee) ? src.melee : melee), (isnull(bullet) ? src.bullet : bullet), @@ -52,19 +54,20 @@ (isnull(acid) ? src.acid : acid), (isnull(magic) ? src.magic : magic), (isnull(wound) ? src.wound : wound), + (isnull(electric) ? src.electric : electric), ) /datum/armor/proc/getRating(rating) return vars[rating] /datum/armor/proc/getList() - return list(MELEE = melee, BULLET = bullet, LASER = laser, ENERGY = energy, BOMB = bomb, BIO = bio, RAD = rad, FIRE = fire, ACID = acid, MAGIC = magic, WOUND = wound) + return list(MELEE = melee, BULLET = bullet, LASER = laser, ENERGY = energy, BOMB = bomb, BIO = bio, RAD = rad, FIRE = fire, ACID = acid, MAGIC = magic, WOUND = wound, ELECTRIC = electric) /datum/armor/proc/attachArmor(datum/armor/AA) - return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic, wound+AA.wound) + return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic, wound+AA.wound, electric+AA.electric) /datum/armor/proc/detachArmor(datum/armor/AA) - return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic, wound-AA.wound) + return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic, wound-AA.wound, electric-AA.electric) /datum/armor/vv_edit_var(var_name, var_value) if (var_name == NAMEOF(src, tag)) @@ -72,4 +75,53 @@ . = ..() tag = ARMORID // update tag in case armor values were edited +/datum/armor/proc/show_protection_classes(additional_info = "") + var/list/readout = list("PROTECTION CLASSES") + + if(bomb || bullet || energy || laser || melee) + readout += "\nARMOR (I-X)" + if(bomb) + readout += "\nEXPLOSIVE [armor_to_protection_class(bomb)]" + if(bullet) + readout += "\nBULLET [armor_to_protection_class(bullet)]" + if(energy) + readout += "\nENERGY [armor_to_protection_class(energy)]" + if(laser) + readout += "\nLASER [armor_to_protection_class(laser)]" + if(melee) + readout += "\nMELEE [armor_to_protection_class(melee)]" + + if(bio || rad || electric) + readout += "\nENVIRONMENT (I-X)" + if(bio) + readout += "\nBIOHAZARD [armor_to_protection_class(bio)]" + if(rad) + readout += "\nRADIATION [armor_to_protection_class(rad)]" + if(electric) + readout += "\nELECTRICAL [armor_to_protection_class(electric)]" + + if(fire || acid) + readout += "\nDURABILITY (I-X)" + if(fire) + readout += "\nFIRE [armor_to_protection_class(fire)]" + if(acid) + readout += "\nACID [armor_to_protection_class(acid)]" + + if(additional_info != "") + readout += additional_info + readout += "" + return readout.Join() + +/** + * Rounds armor_value down to the nearest 10, divides it by 10 and then converts it to Roman numerals. + * + * Arguments: + * * armor_value - Number we're converting + */ +/datum/armor/proc/armor_to_protection_class(armor_value) + if (armor_value < 0) + . = "-" + . += "\Roman[round(abs(armor_value), 10) / 10]" + return . + #undef ARMORID diff --git a/code/datums/components/heal_react.dm b/code/datums/components/heal_react.dm index e77e74d6f03b..488f05ad9aaf 100644 --- a/code/datums/components/heal_react.dm +++ b/code/datums/components/heal_react.dm @@ -67,7 +67,7 @@ var/favor = ..() boost_amount = initial(boost_amount) if(favor) - GLOB.religious_sect.adjust_favor(round(min(favor, 40), 0.1)) + GLOB.religious_sect.adjust_favor(round(favor/2, 0.1)) /datum/component/heal_react/boost/holylight/on_heal(var/mob/living/target,amount,damtype) if(istype(get_area(target), /area/chapel)) @@ -75,4 +75,4 @@ var/favor = ..() boost_amount = initial(boost_amount) if(favor) - GLOB.religious_sect.adjust_favor(round(min(favor * 2, 40), 0.1)) + GLOB.religious_sect.adjust_favor(round(favor/2, 0.1)) diff --git a/code/datums/components/nanites.dm b/code/datums/components/nanites.dm index b2b692d27ed8..6323072873fc 100644 --- a/code/datums/components/nanites.dm +++ b/code/datums/components/nanites.dm @@ -184,21 +184,23 @@ /datum/component/nanites/proc/on_emp(datum/source, severity) if(HAS_TRAIT(host_mob, TRAIT_EMPPROOF_SELF)) return // don't do EMP effects if they're protected from EMPs - if(HAS_TRAIT(host_mob, TRAIT_FARADAYCAGE)) - severity++ - if(severity > EMP_LIGHT) - return - nanite_volume *= 1 - (rand(0.1, 0.25) / severity) //Lose 10-25% of nanites - adjust_nanites(null, -(rand(5, 30) / severity)) //Lose 5-30 flat nanite volume + if(iscarbon(host_mob)) + var/mob/living/carbon/host_carbon = host_mob + if(host_carbon.dna?.species) + severity *= host_carbon.dna.species.emp_mod + if(severity < 1) + return // don't bother if it's less than 1 severity + nanite_volume *= 1 - (rand(0.01, 0.025) * severity) //Lose 1-2.5% of nanites for each severity level + adjust_nanites(null, -(rand(0.5, 3) * severity)) //Lose 0.5-3 flat nanite volume for each severity level for(var/X in programs) var/datum/nanite_program/NP = X NP.on_emp(severity) addtimer(VARSET_CALLBACK(src, cloud_id, cloud_id), NANITE_SYNC_DELAY, TIMER_UNIQUE)//return it to normal, intentionally missing the next sync timer cloud_id = 0 //temporarily disable resyncing so rogue programs actually have a chance to do something -/datum/component/nanites/proc/on_shock(datum/source, shock_damage) - nanite_volume *= (rand(0.65, 0.90)) //Lose 10-35% of nanites - adjust_nanites(null, -(rand(5, 50))) //Lose 5-50 flat nanite volume +/datum/component/nanites/proc/on_shock(datum/source, shock_damage, obj/source, siemens_coeff, zone, tesla_shock) + nanite_volume *= 1 - (rand(0.10, 0.35)**siemens_coeff) //Lose 10-35% of nanites + adjust_nanites(null, -(rand(5, 50)**siemens_coeff)) //Lose 5-50 flat nanite volume for(var/X in programs) var/datum/nanite_program/NP = X NP.on_shock(shock_damage) diff --git a/code/datums/components/overlay_lighting.dm b/code/datums/components/overlay_lighting.dm index 8f91f254b1d9..4309808910eb 100644 --- a/code/datums/components/overlay_lighting.dm +++ b/code/datums/components/overlay_lighting.dm @@ -5,21 +5,23 @@ #define GET_PARENT (parent_attached_to || parent) +#define SHORT_CAST 2 + /** - * Movable atom overlay-based lighting component. - * - * * Component works by applying a visual object to the parent target. - * - * * The component tracks the parent's loc to determine the current_holder. - * * The current_holder is either the parent or its loc, whichever is on a turf. If none, then the current_holder is null and the light is not visible. - * - * * Lighting works at its base by applying a dark overlay and "cutting" said darkness with light, adding (possibly colored) transparency. - * * This component uses the visible_mask visual object to apply said light mask on the darkness. - * - * * The main limitation of this system is that it uses a limited number of pre-baked geometrical shapes, but for most uses it does the job. - * - * * Another limitation is for big lights: you only see the light if you see the object emiting it. - * * For small objects this is good (you can't see them behind a wall), but for big ones this quickly becomes prety clumsy. + * Movable atom overlay-based lighting component. + * + * * Component works by applying a visual object to the parent target. + * + * * The component tracks the parent's loc to determine the current_holder. + * * The current_holder is either the parent or its loc, whichever is on a turf. If none, then the current_holder is null and the light is not visible. + * + * * Lighting works at its base by applying a dark overlay and "cutting" said darkness with light, adding (possibly colored) transparency. + * * This component uses the visible_mask visual object to apply said light mask on the darkness. + * + * * The main limitation of this system is that it uses a limited number of pre-baked geometrical shapes, but for most uses it does the job. + * + * * Another limitation is for big lights: you only see the light if you see the object emiting it. + * * For small objects this is good (you can't see them behind a wall), but for big ones this quickly becomes prety clumsy. */ /datum/component/overlay_lighting ///How far the light reaches, float. @@ -27,11 +29,7 @@ ///Ceiling of range, integer without decimal entries. var/lumcount_range = 0 ///How much this light affects the dynamic_lumcount of turfs. - var/real_lum_power = 0.5 - ///The lum power being used - var/used_lum_power = 0.5 - ///Transparency value. - var/set_alpha = 0 + var/lum_power = 0.5 ///For light sources that can be turned on and off. var/overlay_lighting_flags = NONE @@ -58,28 +56,46 @@ var/atom/movable/current_holder ///Movable atom the parent is attached to. For example, a flashlight into a helmet or gun. We'll need to track the thing the parent is attached to as if it were the parent itself. var/atom/movable/parent_attached_to - - -/datum/component/overlay_lighting/Initialize(_range, _power, _color, starts_on) + ///Whether we're a directional light + var/directional = FALSE + ///Whether we're a beam light + var/beam = FALSE + ///A cone overlay for directional light, it's alpha and color are dependant on the light + var/obj/effect/overlay/light_visible/cone/cone + ///Current tracked direction for the directional cast behaviour + var/current_direction + ///Tracks current directional x offset so we dont update unecessarily + var/directional_offset_x + ///Tracks current directional y offset so we dont update unecessarily + var/directional_offset_y + ///Cast range for the directional cast (how far away the atom is moved) + var/cast_range = 2 + +/datum/component/overlay_lighting/Initialize(range, power, color, starts_on, is_directional, is_beam) if(!ismovable(parent)) return COMPONENT_INCOMPATIBLE - var/atom/movable/movable_parent = parent - if(movable_parent.light_system != MOVABLE_LIGHT) - stack_trace("[type] added to [parent], with [movable_parent.light_system] value for the light_system var. Use [MOVABLE_LIGHT] instead.") + if(movable_parent.light_system != MOVABLE_LIGHT && movable_parent.light_system != MOVABLE_LIGHT_DIRECTIONAL && movable_parent.light_system != MOVABLE_LIGHT_BEAM) + stack_trace("[type] added to [parent], with [movable_parent.light_system] value for the light_system var. Use [MOVABLE_LIGHT], [MOVABLE_LIGHT_DIRECTIONAL] or [MOVABLE_LIGHT_BEAM] instead.") return COMPONENT_INCOMPATIBLE . = ..() - - visible_mask = new() - if(!isnull(_range)) - movable_parent.set_light_range(_range) + visible_mask = new(src) + if(is_directional) + directional = TRUE + cone = new(src) + cone.transform = cone.transform.Translate(-32, -32) + set_direction(movable_parent.dir) + if(is_beam) + beam = TRUE + if(!isnull(range)) + movable_parent.set_light_range(range) set_range(parent, movable_parent.light_range) - if(!isnull(_power)) - movable_parent.set_light_power(_power) + if(!isnull(power)) + movable_parent.set_light_power(power) set_power(parent, movable_parent.light_power) - if(!isnull(_color)) - movable_parent.set_light_color(_color) + if(!isnull(color)) + movable_parent.set_light_color(color) set_color(parent, movable_parent.light_color) if(!isnull(starts_on)) movable_parent.set_light_on(starts_on) @@ -87,19 +103,20 @@ /datum/component/overlay_lighting/RegisterWithParent() . = ..() + if(directional) + RegisterSignal(parent, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_parent_dir_change)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_RANGE, PROC_REF(set_range)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_POWER, PROC_REF(set_power)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_COLOR, PROC_REF(set_color)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_ON, PROC_REF(on_toggle)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_FLAGS, PROC_REF(on_light_flags_change)) + RegisterSignal(parent, COMSIG_ATOM_USED_IN_CRAFT, PROC_REF(on_parent_crafted)) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_parent_moved)) - RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_RANGE, PROC_REF(set_range)) - RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_POWER, PROC_REF(set_power)) - RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_COLOR, PROC_REF(set_color)) - RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_ON, PROC_REF(on_toggle)) - RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_FLAGS, PROC_REF(on_light_flags_change)) + RegisterSignal(parent, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(on_z_move)) var/atom/movable/movable_parent = parent if(movable_parent.light_flags & LIGHT_ATTACHED) overlay_lighting_flags |= LIGHTING_ATTACHED set_parent_attached_to(ismovable(movable_parent.loc) ? movable_parent.loc : null) - if(movable_parent.light_flags & LIGHT_NO_LUMCOUNT) - overlay_lighting_flags |= LIGHT_NO_LUMCOUNT - set_lum_power(real_lum_power) check_holder() if(movable_parent.light_on) turn_on() @@ -112,12 +129,16 @@ clean_old_turfs() UnregisterSignal(parent, list( COMSIG_MOVABLE_MOVED, - COMSIG_ATOM_SET_LIGHT_RANGE, - COMSIG_ATOM_SET_LIGHT_POWER, - COMSIG_ATOM_SET_LIGHT_COLOR, - COMSIG_ATOM_SET_LIGHT_ON, - COMSIG_ATOM_SET_LIGHT_FLAGS, + COMSIG_MOVABLE_Z_CHANGED, + COMSIG_ATOM_UPDATE_LIGHT_RANGE, + COMSIG_ATOM_UPDATE_LIGHT_POWER, + COMSIG_ATOM_UPDATE_LIGHT_COLOR, + COMSIG_ATOM_UPDATE_LIGHT_ON, + COMSIG_ATOM_UPDATE_LIGHT_FLAGS, + COMSIG_ATOM_USED_IN_CRAFT, )) + if(directional) + UnregisterSignal(parent, COMSIG_ATOM_DIR_CHANGE) if(overlay_lighting_flags & LIGHTING_ON) turn_off() return ..() @@ -127,14 +148,16 @@ set_parent_attached_to(null) set_holder(null) clean_old_turfs() - QDEL_NULL(visible_mask) + visible_mask = null + cone = null + parent_attached_to = null return ..() ///Clears the affected_turfs lazylist, removing from its contents the effects of being near the light. /datum/component/overlay_lighting/proc/clean_old_turfs() for(var/turf/lit_turf as anything in affected_turfs) - lit_turf.dynamic_lumcount -= used_lum_power + lit_turf.dynamic_lumcount -= lum_power SSdemo.mark_turf(lit_turf) affected_turfs = null @@ -143,8 +166,10 @@ /datum/component/overlay_lighting/proc/get_new_turfs() if(!current_holder) return + . = list() for(var/turf/lit_turf in view(lumcount_range, get_turf(current_holder))) - lit_turf.dynamic_lumcount += used_lum_power + lit_turf.dynamic_lumcount += lum_power + . += lit_turf SSdemo.mark_turf(lit_turf) LAZYADD(affected_turfs, lit_turf) @@ -154,27 +179,32 @@ clean_old_turfs() if(!isturf(current_holder?.loc)) return + if(directional) + cast_directional_light() get_new_turfs() -///Adds the luminosity and source for the afected movable atoms to keep track of their visibility. -/datum/component/overlay_lighting/proc/add_dynamic_lumi(atom/movable/affected_movable) - LAZYSET(affected_movable.affected_dynamic_lights, src, lumcount_range + 1) - affected_movable.vis_contents += visible_mask - affected_movable.update_dynamic_luminosity() - - -///Removes the luminosity and source for the afected movable atoms to keep track of their visibility. -/datum/component/overlay_lighting/proc/remove_dynamic_lumi(atom/movable/affected_movable) - LAZYREMOVE(affected_movable.affected_dynamic_lights, src) - affected_movable.vis_contents -= visible_mask - affected_movable.update_dynamic_luminosity() +///Adds the luminosity and source for the affected movable atoms to keep track of their visibility. +/datum/component/overlay_lighting/proc/add_dynamic_lumi() + LAZYSET(current_holder.affected_dynamic_lights, src, lumcount_range + 1) + current_holder.underlays += visible_mask + current_holder.update_dynamic_luminosity() + if(directional) + current_holder.underlays += cone +///Removes the luminosity and source for the affected movable atoms to keep track of their visibility. +/datum/component/overlay_lighting/proc/remove_dynamic_lumi() + LAZYREMOVE(current_holder.affected_dynamic_lights, src) + current_holder.underlays -= visible_mask + current_holder.update_dynamic_luminosity() + if(directional) + current_holder.underlays -= cone ///Called to change the value of parent_attached_to. /datum/component/overlay_lighting/proc/set_parent_attached_to(atom/movable/new_parent_attached_to) if(new_parent_attached_to == parent_attached_to) return + . = parent_attached_to parent_attached_to = new_parent_attached_to if(.) @@ -198,17 +228,25 @@ if(current_holder) if(current_holder != parent && current_holder != parent_attached_to) UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED)) + if(directional) + UnregisterSignal(current_holder, COMSIG_ATOM_DIR_CHANGE) if(overlay_lighting_flags & LIGHTING_ON) - remove_dynamic_lumi(current_holder) + remove_dynamic_lumi() current_holder = new_holder if(new_holder == null) clean_old_turfs() return - if(overlay_lighting_flags & LIGHTING_ON) - add_dynamic_lumi(new_holder) if(new_holder != parent && new_holder != parent_attached_to) RegisterSignal(new_holder, COMSIG_PARENT_QDELETING, PROC_REF(on_holder_qdel)) - RegisterSignal(new_holder, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved)) + if(overlay_lighting_flags & LIGHTING_ON) + RegisterSignal(new_holder, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved)) + if(directional) + RegisterSignal(new_holder, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_holder_dir_change)) + if(directional && current_direction != new_holder.dir) + current_direction = new_holder.dir + if(overlay_lighting_flags & LIGHTING_ON) + add_dynamic_lumi() + make_luminosity_update() ///Used to determine the new valid current_holder from the parent's loc. @@ -229,12 +267,18 @@ ///Called when the current_holder is qdeleted, to remove the light effect. /datum/component/overlay_lighting/proc/on_holder_qdel(atom/movable/source, force) + SIGNAL_HANDLER + if(QDELETED(current_holder)) + return UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED)) + if(directional) + UnregisterSignal(current_holder, COMSIG_ATOM_DIR_CHANGE) set_holder(null) ///Called when current_holder changes loc. /datum/component/overlay_lighting/proc/on_holder_moved(atom/movable/source, OldLoc, Dir, Forced) + SIGNAL_HANDLER if(!(overlay_lighting_flags & LIGHTING_ON)) return make_luminosity_update() @@ -242,6 +286,7 @@ ///Called when parent changes loc. /datum/component/overlay_lighting/proc/on_parent_moved(atom/movable/source, OldLoc, Dir, Forced) + SIGNAL_HANDLER var/atom/movable/movable_parent = parent if(overlay_lighting_flags & LIGHTING_ATTACHED) set_parent_attached_to(ismovable(movable_parent.loc) ? movable_parent.loc : null) @@ -250,10 +295,24 @@ return make_luminosity_update() +/datum/component/overlay_lighting/proc/on_z_move(atom/source) + SIGNAL_HANDLER + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays -= visible_mask + current_holder.underlays -= cone + visible_mask.plane = O_LIGHTING_VISUAL_PLANE + if(cone) + cone.plane = O_LIGHTING_VISUAL_PLANE + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += visible_mask + current_holder.underlays += cone ///Called when the current_holder is qdeleted, to remove the light effect. /datum/component/overlay_lighting/proc/on_parent_attached_to_qdel(atom/movable/source, force) + SIGNAL_HANDLER UnregisterSignal(parent_attached_to, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED)) + if(directional) + UnregisterSignal(parent_attached_to, COMSIG_ATOM_DIR_CHANGE) if(parent_attached_to == current_holder) set_holder(null) set_parent_attached_to(null) @@ -261,6 +320,7 @@ ///Called when parent_attached_to changes loc. /datum/component/overlay_lighting/proc/on_parent_attached_to_moved(atom/movable/source, OldLoc, Dir, Forced) + SIGNAL_HANDLER check_holder() if(!(overlay_lighting_flags & LIGHTING_ON) || !current_holder) return @@ -268,76 +328,114 @@ ///Changes the range which the light reaches. 0 means no light, 6 is the maximum value. -/datum/component/overlay_lighting/proc/set_range(atom/source, new_range) +/datum/component/overlay_lighting/proc/set_range(atom/source, old_range) + SIGNAL_HANDLER + var/new_range = source.light_range if(range == new_range) return - if(range == 0) + if(new_range == 0) turn_off() range = clamp(CEILING(new_range, 0.5), 1, 6) var/pixel_bounds = ((range - 1) * 64) + 32 lumcount_range = CEILING(range, 1) + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays -= visible_mask visible_mask.icon = light_overlays["[pixel_bounds]"] if(pixel_bounds == 32) - visible_mask.transform = null - return - var/offset = (pixel_bounds - 32) * 0.5 - var/matrix/transform = new - transform.Translate(-offset, -offset) - visible_mask.transform = transform + if(!directional) // it's important that we make it to the end of this function if we are a directional light + visible_mask.transform = null + return + else + var/offset = (pixel_bounds - 32) * 0.5 + var/matrix/transform = new + transform.Translate(-offset, -offset) + visible_mask.transform = transform + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += visible_mask + if(directional) + if(beam) + cast_range = max(round(new_range * 0.5), 1) + else + cast_range = clamp(round(new_range * 0.5), 1, 3) if(overlay_lighting_flags & LIGHTING_ON) make_luminosity_update() ///Changes the intensity/brightness of the light by altering the visual object's alpha. -/datum/component/overlay_lighting/proc/set_power(atom/source, new_power) - set_lum_power(new_power >= 0 ? 0.5 : -0.5) - set_alpha = min(230, (abs(new_power) * 120) + 30) - visible_mask.alpha = set_alpha +/datum/component/overlay_lighting/proc/set_power(atom/source, old_power) + SIGNAL_HANDLER + var/new_power = source.light_power + set_lum_power(new_power) + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays -= visible_mask + visible_mask.alpha = min(230, (abs(new_power) * 120) + 30) + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += visible_mask + if(!directional) + return + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays -= cone + cone.alpha = min(200, (abs(new_power) * 90) + 20) + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += cone ///Changes the light's color, pretty straightforward. -/datum/component/overlay_lighting/proc/set_color(atom/source, new_color) +/datum/component/overlay_lighting/proc/set_color(atom/source, old_color) + SIGNAL_HANDLER + var/new_color = source.light_color + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays -= visible_mask visible_mask.color = new_color + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += visible_mask + if(!directional) + return + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays -= cone + cone.color = new_color + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += cone ///Toggles the light on and off. -/datum/component/overlay_lighting/proc/on_toggle(atom/source, new_value) +/datum/component/overlay_lighting/proc/on_toggle(atom/source, old_value) + SIGNAL_HANDLER + var/new_value = source.light_on if(new_value) //Truthy value input, turn on. turn_on() return turn_off() //Falsey value, turn off. -///Triggered right before the parent light flags change. -/datum/component/overlay_lighting/proc/on_light_flags_change(atom/source, new_value) +///Triggered right after the parent light flags change. +/datum/component/overlay_lighting/proc/on_light_flags_change(atom/source, old_flags) + SIGNAL_HANDLER + var/new_flags = source.light_flags var/atom/movable/movable_parent = parent - if(new_value & LIGHT_ATTACHED) - if(!(movable_parent.light_flags & LIGHT_ATTACHED)) //Gained the LIGHT_ATTACHED property. - overlay_lighting_flags |= LIGHTING_ATTACHED - if(ismovable(movable_parent.loc)) - set_parent_attached_to(movable_parent.loc) - else if(movable_parent.light_flags & LIGHT_ATTACHED) //Lost the LIGHT_ATTACHED property. + if(!((new_flags ^ old_flags) & LIGHT_ATTACHED)) + return + + if(new_flags & LIGHT_ATTACHED) // Gained the [LIGHT_ATTACHED] property + overlay_lighting_flags |= LIGHTING_ATTACHED + if(ismovable(movable_parent.loc)) + set_parent_attached_to(movable_parent.loc) + else // Lost the [LIGHT_ATTACHED] property overlay_lighting_flags &= ~LIGHTING_ATTACHED set_parent_attached_to(null) - - if(new_value & LIGHT_NO_LUMCOUNT) - if(!(movable_parent.light_flags & LIGHT_NO_LUMCOUNT)) //Gained the NO_LUMCOUNT property - overlay_lighting_flags |= LIGHT_NO_LUMCOUNT - //Recalculate affecting - set_lum_power(real_lum_power) - else if(movable_parent.light_flags & LIGHT_NO_LUMCOUNT) //Lost the NO_LUMCOUNT property - overlay_lighting_flags &= ~LIGHT_NO_LUMCOUNT - //Recalculate affecting - set_lum_power(real_lum_power) ///Toggles the light on. /datum/component/overlay_lighting/proc/turn_on() if(overlay_lighting_flags & LIGHTING_ON) return - if(current_holder) - add_dynamic_lumi(current_holder) overlay_lighting_flags |= LIGHTING_ON + if(current_holder) + add_dynamic_lumi() + if(directional) + cast_directional_light() + if(current_holder && current_holder != parent && current_holder != parent_attached_to) + RegisterSignal(current_holder, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved)) get_new_turfs() @@ -346,38 +444,109 @@ if(!(overlay_lighting_flags & LIGHTING_ON)) return if(current_holder) - remove_dynamic_lumi(current_holder) + remove_dynamic_lumi() overlay_lighting_flags &= ~LIGHTING_ON + if(current_holder && current_holder != parent && current_holder != parent_attached_to) + UnregisterSignal(current_holder, COMSIG_MOVABLE_MOVED) clean_old_turfs() ///Here we append the behavior associated to changing lum_power. /datum/component/overlay_lighting/proc/set_lum_power(new_lum_power) - //Get the simulated luminosity count (If we have no lumcount, this is set to 0) - var/simulated_lum_power = new_lum_power - if(overlay_lighting_flags & LIGHT_NO_LUMCOUNT) - simulated_lum_power = 0 - //The new lum power is the same - if(used_lum_power == simulated_lum_power) - //This light doesn't affect lumcount, but lum_power must be updated regardless - if(new_lum_power != simulated_lum_power) - . = real_lum_power - real_lum_power = new_lum_power + if(lum_power == new_lum_power) return - //Set the return value to the old lum power - . = real_lum_power - real_lum_power = new_lum_power - //Get the old used lum power - var/old_lum_power = used_lum_power - used_lum_power = simulated_lum_power - //Calculate the difference - var/difference = old_lum_power - used_lum_power - //Apply it to any turf we are affecting - for(var/t in affected_turfs) - var/turf/lit_turf = t + . = lum_power + lum_power = new_lum_power + var/difference = . - lum_power + for(var/turf/lit_turf as anything in affected_turfs) lit_turf.dynamic_lumcount -= difference +///Here we append the behavior associated to changing lum_power. +/datum/component/overlay_lighting/proc/cast_directional_light() + var/final_distance = cast_range + //Lower the distance by 1 if we're not looking at a cardinal direction, and we're not a short cast + if(final_distance > SHORT_CAST && !(ALL_CARDINALS & current_direction)) + final_distance -= 1 + var/turf/scanning = get_turf(current_holder) + for(var/i in 1 to final_distance) + var/turf/next_turf = get_step(scanning, current_direction) + if(isnull(next_turf) || IS_OPAQUE_TURF(next_turf)) + final_distance = i + break + scanning = next_turf + + current_holder.underlays -= visible_mask + + var/translate_x = -((range - 1) * 32) + var/translate_y = translate_x + var/scale_x = 1 + var/scale_y = 1 + switch(current_direction) + if(NORTH) + translate_y += 32 * final_distance + if(beam && range > 1) + scale_x = 1 / (range - (range/5)) + if(SOUTH) + translate_y += -32 * final_distance + if(beam && range > 1) + scale_x = 1 / (range - (range/5)) + if(EAST) + translate_x += 32 * final_distance + if(beam && range > 1) + scale_y = 1 / (range - (range/5)) + if(WEST) + translate_x += -32 * final_distance + if(beam && range > 1) + scale_y = 1 / (range - (range/5)) + + if((directional_offset_x != translate_x) || (directional_offset_y != translate_y)) + directional_offset_x = translate_x + directional_offset_y = translate_y + var/matrix/transform = matrix() + if(beam && range > 1) + transform.Scale(scale_x, scale_y) + transform.Translate(translate_x, translate_y) + visible_mask.transform = transform + if(overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += visible_mask + +///Called when current_holder changes loc. +/datum/component/overlay_lighting/proc/on_holder_dir_change(atom/movable/source, olddir, newdir) + SIGNAL_HANDLER + set_direction(newdir) + +///Called when parent changes loc. +/datum/component/overlay_lighting/proc/on_parent_dir_change(atom/movable/source, olddir, newdir) + SIGNAL_HANDLER + set_direction(newdir) + +///Sets a new direction for the directional cast, then updates luminosity +/datum/component/overlay_lighting/proc/set_direction(newdir) + if(!newdir) + return + if(current_direction == newdir) + return + current_direction = newdir + if(overlay_lighting_flags & LIGHTING_ON) + make_luminosity_update() + +/datum/component/overlay_lighting/proc/on_parent_crafted(datum/source, atom/movable/new_craft) + SIGNAL_HANDLER + + if(!istype(new_craft)) + return + + UnregisterSignal(parent, COMSIG_ATOM_USED_IN_CRAFT) + RegisterSignal(new_craft, COMSIG_ATOM_USED_IN_CRAFT, PROC_REF(on_parent_crafted)) + set_parent_attached_to(new_craft) + +/// Handles putting the source for overlay lights into the light eater queue since we aren't tracked by [/atom/var/light_sources] +/datum/component/overlay_lighting/proc/on_light_eater(datum/source, list/light_queue, datum/light_eater) + SIGNAL_HANDLER + light_queue[parent] = TRUE + return NONE #undef LIGHTING_ON #undef LIGHTING_ATTACHED #undef GET_PARENT +#undef SHORT_CAST diff --git a/code/datums/components/rot.dm b/code/datums/components/rot.dm index 1eb32bd0138d..b37c6773f3f2 100644 --- a/code/datums/components/rot.dm +++ b/code/datums/components/rot.dm @@ -21,22 +21,23 @@ return var/datum/gas_mixture/turf_air = T.return_air() + if(!turf_air) + return var/datum/gas_mixture/stank_breath = T.remove_air(1 / turf_air.return_volume() * turf_air.total_moles()) if(!stank_breath) return stank_breath.set_volume(1) - var/oxygen_pp = stank_breath.get_moles(/datum/gas/oxygen) * R_IDEAL_GAS_EQUATION * stank_breath.return_temperature() / stank_breath.return_volume() + var/oxygen_pp = stank_breath.get_moles(GAS_O2) * R_IDEAL_GAS_EQUATION * stank_breath.return_temperature() / stank_breath.return_volume() if(oxygen_pp > 18) var/this_amount = min((oxygen_pp - 8) * stank_breath.return_volume() / stank_breath.return_temperature() / R_IDEAL_GAS_EQUATION, amount) - stank_breath.adjust_moles(/datum/gas/oxygen, -this_amount) + stank_breath.adjust_moles(GAS_O2, -this_amount) var/datum/gas_mixture/stank = new - stank.set_moles(/datum/gas/miasma, this_amount) + stank.set_moles(GAS_MIASMA, this_amount) stank.set_temperature(BODYTEMP_NORMAL) // otherwise we have gas below 2.7K which will break our lag generator stank_breath.merge(stank) T.assume_air(stank_breath) - T.air_update_turf() /datum/component/rot/corpse amount = MIASMA_CORPSE_MOLES diff --git a/code/datums/components/twohanded.dm b/code/datums/components/twohanded.dm index 4892e0208f1c..9a881e017f37 100644 --- a/code/datums/components/twohanded.dm +++ b/code/datums/components/twohanded.dm @@ -14,10 +14,8 @@ var/wielded = FALSE /// The multiplier applied to force when wielded, does not work with force_wielded, and force_unwielded var/force_multiplier = 0 - /// The force of the item when wielded + /// Additional force when wielded var/force_wielded = 0 - /// The force of the item when unweilded - var/force_unwielded = 0 /// Play sound when wielded var/wieldsound = FALSE /// Play sound when unwielded @@ -33,6 +31,8 @@ /// stat list for wielded/unwielded, switches with weapon_stats when wielding or unwielding var/list/wielded_stats + /// keep track of unwielded stats, we'll need it later for properly unwielding without causing runtimes + var/list/unwielded_stats /// A callback on the parent to be called when the item is wielded var/datum/callback/wield_callback @@ -50,7 +50,6 @@ * * attacksound (optional) The sound to play when wielded and attacking * * force_multiplier (optional) The force multiplier when wielded, do not use with force_wielded, and force_unwielded * * force_wielded (optional) The force setting when the item is wielded, do not use with force_multiplier - * * force_unwielded (optional) The force setting when the item is unwielded, do not use with force_multiplier * * icon_wielded (optional) The icon to be used when wielded */ /datum/component/two_handed/Initialize( @@ -60,7 +59,6 @@ attacksound = FALSE, force_multiplier = 0, force_wielded = 0, - force_unwielded = 0, icon_wielded = FALSE, datum/callback/wield_callback, datum/callback/unwield_callback, @@ -75,7 +73,6 @@ src.attacksound = attacksound src.force_multiplier = force_multiplier src.force_wielded = force_wielded - src.force_unwielded = force_unwielded src.icon_wielded = icon_wielded src.wield_callback = wield_callback src.unwield_callback = unwield_callback @@ -93,7 +90,6 @@ unwieldsound, force_multiplier, force_wielded, - force_unwielded, icon_wielded, datum/callback/wield_callback, datum/callback/unwield_callback, @@ -113,8 +109,6 @@ src.force_multiplier = force_multiplier if(force_wielded) src.force_wielded = force_wielded - if(force_unwielded) - src.force_unwielded = force_unwielded if(icon_wielded) src.icon_wielded = icon_wielded if(wield_callback) @@ -225,9 +219,8 @@ if(force_multiplier) parent_item.force *= force_multiplier else if(force_wielded) - parent_item.force = force_wielded - if(sharpened_increase) - parent_item.force += sharpened_increase + parent_item.force += force_wielded + unwielded_stats = parent_item.weapon_stats parent_item.weapon_stats = wielded_stats parent_item.name = "[parent_item.name] (Wielded)" parent_item.update_appearance() @@ -271,14 +264,13 @@ // update item stats var/obj/item/parent_item = parent - if(sharpened_increase) - parent_item.force -= sharpened_increase if(force_multiplier) parent_item.force /= force_multiplier - else if(force_unwielded) - parent_item.force = force_unwielded + else if(force_wielded) + parent_item.force -= force_wielded - parent_item.weapon_stats = initial(parent_item.weapon_stats) + parent_item.weapon_stats = unwielded_stats + unwielded_stats = null // update the items name to remove the wielded status var/sf = findtext(parent_item.name, " (Wielded)", -10) // 10 == length(" (Wielded)") @@ -365,7 +357,7 @@ /** * on_sharpen Triggers on usage of a sharpening stone on the item */ -/datum/component/two_handed/proc/on_sharpen(obj/item/item, amount, max_amount) +/datum/component/two_handed/proc/on_sharpen(obj/item/item, amount, max_amount=INFINITY) SIGNAL_HANDLER if(!item) @@ -373,14 +365,14 @@ if(sharpened_increase) return COMPONENT_BLOCK_SHARPEN_ALREADY var/wielded_val = 0 + var/obj/item/parent_item = parent if(force_multiplier) - var/obj/item/parent_item = parent if(wielded) wielded_val = parent_item.force else wielded_val = parent_item.force * force_multiplier else - wielded_val = force_wielded + wielded_val = parent_item.force + (wielded ? 0 : force_wielded) if(wielded_val > max_amount) return COMPONENT_BLOCK_SHARPEN_MAXED sharpened_increase = min(amount, (max_amount - wielded_val)) diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index 2313ca184dd0..0a409a1ded27 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -405,9 +405,9 @@ . = 0 if(M.loc) - environment = M.loc.return_air() + environment = M.return_air() if(environment) - if(environment.get_moles(/datum/gas/plasma) > GLOB.meta_gas_info[/datum/gas/plasma][META_GAS_MOLES_VISIBLE]) //if there's enough plasma in the air to see + if(environment.get_moles(GAS_PLASMA) > GLOB.gas_data.visibility[GAS_PLASMA]) //if there's enough plasma in the air to see . += power * 0.5 var/requires_metabolizing = !(A.process_dead && M.stat == DEAD) //don't require metabolizing if our host is dead and we have necrotic metabolsim if(M.reagents.has_reagent(/datum/reagent/toxin/plasma, needs_metabolizing = requires_metabolizing)) @@ -504,3 +504,63 @@ if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len, null, BODYPART_ORGANIC)) M.update_damage_overlays() return 1 + +#define SYMPTOM_SUPERFICIAL_LOWER_THRESHOLD 0.7 +/datum/symptom/heal/surface + name = "Superficial Healing" + desc = "The virus accelerates the body's natural healing, causing the body to heal minor wounds quickly." + stealth = -2 + resistance = -2 + stage_speed = -2 + transmittable = 1 + + level = 3 + passive_message = span_notice("Your skin tingles") + + var/threshold = 0.9 // Percentual total health we check against. This is less than a toolbox hit, so probably wont save you in combat + var/healing_power = 0.5 // 0.5 brute and fire, slightly better than the worst case starlight with its 0.3 + + threshold_descs = list( + "Stage Speed 8" = "Improves healing significantly.", + "Resistance 10" = "Improves healing threshhold. This comes at the downside of exhausting the body more as heavier wounds heal", + ) + +/datum/symptom/heal/surface/Start(datum/disease/advance/A) + . = ..() + if(!.) + return + if(A.properties["stage_rate"] >= 8) //stronger healing + healing_power = 1.5 + if(A.properties["resistance"] >= 10) + threshold = SYMPTOM_SUPERFICIAL_LOWER_THRESHOLD + +/datum/symptom/heal/surface/CanHeal(datum/disease/advance/A) + var/mob/living/M = A.affected_mob + if(M.health == M.maxHealth) + return FALSE + return TRUE + + +/datum/symptom/heal/surface/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) + if(M.health == M.maxHealth) + return + if(((M.health/M.maxHealth) > threshold)) + healing_power = healing_power * actual_power + + // We don't actually heal all damage types at once, but prioritise one over the other. + // Since the virus focuses mainly on surface damage, it will firstly heal those + // If it can't find any then it will consider healing some toxins (Not affected by healing power) + if(M.getBruteLoss() || M.getFireLoss()) + M.heal_bodypart_damage(healing_power, healing_power) + else if(M.getToxLoss()) + M.adjustToxLoss(-0.5) + else + return // Still continues IF we healed something + + // A downside to the better threshold + if(threshold == SYMPTOM_SUPERFICIAL_LOWER_THRESHOLD) + // Interesting downside + if(M.getStaminaLoss() < 65) + M.adjustStaminaLoss(20) + return TRUE +#undef SYMPTOM_SUPERFICIAL_LOWER_THRESHOLD diff --git a/code/datums/elements/light_blocking.dm b/code/datums/elements/light_blocking.dm new file mode 100644 index 000000000000..673838ad4f80 --- /dev/null +++ b/code/datums/elements/light_blocking.dm @@ -0,0 +1,42 @@ +/** + * Attached to movable atoms with opacity. Listens to them move and updates their old and new turf loc's opacity accordingly. + */ +/datum/element/light_blocking + element_flags = ELEMENT_DETACH_ON_HOST_DESTROY + + +/datum/element/light_blocking/Attach(datum/target) + . = ..() + if(!ismovable(target)) + return ELEMENT_INCOMPATIBLE + RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(on_target_move)) + var/atom/movable/movable_target = target + if(!isturf(movable_target.loc)) + return + for(var/turf/turf_loc as anything in movable_target.locs) + turf_loc.add_opacity_source(target) + + +/datum/element/light_blocking/Detach(datum/target) + . = ..() + UnregisterSignal(target, list(COMSIG_MOVABLE_MOVED)) + var/atom/movable/movable_target = target + if(!isturf(movable_target.loc)) + return + for(var/turf/turf_loc as anything in movable_target.locs) + turf_loc.remove_opacity_source(target) + + +///Updates old and new turf loc opacities. +/datum/element/light_blocking/proc/on_target_move(atom/movable/source, atom/old_loc, dir, forced, list/old_locs) + SIGNAL_HANDLER + if(isturf(old_loc)) + if(old_locs) + for(var/turf/old_turf as anything in old_locs) + old_turf.remove_opacity_source(source) + else + var/turf/old_turf = old_loc + old_turf.remove_opacity_source(source) + if(isturf(source.loc)) + for(var/turf/new_turf as anything in source.locs) + new_turf.add_opacity_source(source) diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index aeec4dbdc21b..fcca5c762f24 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -155,11 +155,11 @@ // Can most things breathe? if(trace_gases) continue - if(A.get_moles(/datum/gas/oxygen) < 16) + if(A.get_moles(GAS_O2) < 16) continue - if(A.get_moles(/datum/gas/plasma)) + if(A.get_moles(GAS_PLASMA)) continue - if(A.get_moles(/datum/gas/carbon_dioxide) >= 10) + if(A.get_moles(GAS_CO2) >= 10) continue // Aim for goldilocks temperatures and pressure diff --git a/code/datums/martial/flying_fang.dm b/code/datums/martial/flying_fang.dm index bfeef4b5e5c3..95e8eeef2bf2 100644 --- a/code/datums/martial/flying_fang.dm +++ b/code/datums/martial/flying_fang.dm @@ -118,10 +118,13 @@ //headbutt, deals moderate brute and stamina damage with an eye blur, causes poor aim for a few seconds to the target if they have no helmet on /datum/martial_art/flyingfang/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) add_to_streak("D",D) - if(check_streak(A,D)) - return TRUE if(!can_use(A)) return + if(HAS_TRAIT(A, TRAIT_PACIFISM)) // All disarm attacks/combos deal non-stamina damage, yet pacifism is not accounted for in base disarm. + to_chat(A, span_warning("You don't want to harm [D]!")) + return + if(check_streak(A,D)) + return TRUE var/obj/item/bodypart/affecting = D.get_bodypart(check_zone(BODY_ZONE_HEAD)) var/armor_block = D.run_armor_check(affecting, MELEE) var/disarm_damage = A.get_punchdamagehigh() / 2 //5 damage diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm index 2c6c3236429a..2e46bbeb2635 100644 --- a/code/datums/martial/krav_maga.dm +++ b/code/datums/martial/krav_maga.dm @@ -234,11 +234,10 @@ desc = "These tactical gloves are fireproof and shock resistant, and using nanochip technology it teaches you the powers of krav maga." icon_state = "black" item_state = "blackglovesplus" - siemens_coefficient = 0 strip_delay = 80 cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 80, ACID = 50) + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 80, ACID = 50, ELECTRIC = 100) diff --git a/code/datums/martial/lightning_flow.dm b/code/datums/martial/lightning_flow.dm index b1759970c0a3..1f6f5853915e 100644 --- a/code/datums/martial/lightning_flow.dm +++ b/code/datums/martial/lightning_flow.dm @@ -27,11 +27,11 @@ /datum/martial_art/lightning_flow/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) if(dashing) return TRUE - damage(D, A, 5) + damage(D, A, 5, zone=A.zone_selected) return FALSE -/datum/martial_art/lightning_flow/proc/damage(mob/living/target, mob/living/carbon/human/user, amount = 5, stun = FALSE) - target.electrocute_act(amount, user, stun = stun) +/datum/martial_art/lightning_flow/proc/damage(mob/living/target, mob/living/carbon/human/user, amount = 5, stun = FALSE, zone = null) + target.electrocute_act(amount, user, stun = stun, zone = zone) /datum/martial_art/lightning_flow/proc/InterceptClickOn(mob/living/carbon/human/H, params, atom/target) var/list/modifiers = params2list(params) @@ -72,10 +72,14 @@ dashing = TRUE if(action_type && action_type == INTENT_DISARM) H.Knockdown(2 SECONDS, TRUE, TRUE) - H.Immobilize(0.6 SECONDS, TRUE, TRUE) //just until the dash would end + H.Immobilize(1 SECONDS, TRUE, TRUE) //to prevent canceling the dash new /obj/effect/particle_effect/sparks/electricity/short/loud(get_turf(H)) - H.throw_at(target, DASH_RANGE, DASH_SPEED, H, FALSE, TRUE) + H.throw_at(target, DASH_RANGE, DASH_SPEED, H, FALSE, callback = CALLBACK(src, PROC_REF(end_dash), H)) +/datum/martial_art/lightning_flow/proc/end_dash(mob/living/carbon/human/H) + dashing = FALSE + H.SetImmobilized(0, TRUE, TRUE) //remove the block on movement + /datum/martial_art/lightning_flow/handle_throw(atom/hit_atom, mob/living/carbon/human/H, datum/thrownthing/throwingdatum) if(!dashing || !action_type) return FALSE @@ -83,14 +87,13 @@ return FALSE var/mob/living/target = hit_atom dashing = FALSE - H.SetImmobilized(0) - H.SetKnockdown(0) switch(action_type) if(INTENT_DISARM) if(ishuman(target)) var/mob/living/carbon/human/victim = target if(victim.check_shields(src, 0, "[H]", attack_type = LEAP_ATTACK)) return FALSE + H.SetKnockdown(0) //remove the self knockdown from the dropkick dropkick(target, H, throwingdatum) if(INTENT_GRAB) target.grabbedby(H) @@ -105,7 +108,7 @@ /datum/martial_art/lightning_flow/proc/dropkick(mob/living/target, mob/living/carbon/human/H, datum/thrownthing/throwingdatum) target.visible_message(span_danger("[H] dropkicks [target]!"), span_userdanger("[H] dropkicks you!")) target.Knockdown(5 SECONDS) - damage(target, H, 15, TRUE) + damage(target, H, 15, TRUE, BODY_ZONE_CHEST) var/destination = throwingdatum.target if(get_dist(target, destination) < 5) destination = get_ranged_target_turf(get_turf(H), throwingdatum.init_dir, 5) diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index 6a74b8bd54d4..4f2530061adb 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -184,7 +184,6 @@ /obj/item/melee/bostaff/Initialize(mapload) . = ..() AddComponent(/datum/component/two_handed, \ - force_unwielded = 10, \ force_wielded = 14, \ ) diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm index c0280d80b7cf..804492f862e9 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -195,40 +195,41 @@ quality = POSITIVE text_gain_indication = span_notice("Your skin begins to glow softly.") instability = 5 - var/obj/effect/dummy/luminescent_glow/glowth //shamelessly copied from luminescents - var/glow = 3.5 - var/range = 2.5 - var/glow_color - var/current_nullify_timer // For veil yogstation\code\modules\antagonists\shadowling\shadowling_abilities.dm power_coeff = 1 conflicts = list(/datum/mutation/human/glow/anti, /datum/mutation/human/radiantburst) + var/glow_power = 3.5 + var/glow_range = 2.5 + var/glow_color + var/current_nullify_timer // For veil yogstation\code\modules\antagonists\shadowling\shadowling_abilities.dm + + var/obj/effect/dummy/lighting_obj/moblight/glow + /datum/mutation/human/glow/on_acquiring(mob/living/carbon/human/owner) . = ..() if(.) return glow_color = owner.dna.features["mcolor"] - glowth = new(owner) + glow = owner.mob_light() modify() // Override modify here without a parent call, because we don't actually give an action. /datum/mutation/human/glow/modify() - if(!glowth) + if(!glow) return - var/power = GET_MUTATION_POWER(src) - glowth.set_light_range_power_color(range * power, glow * power, glow_color) + glow.set_light_range_power_color(glow_range * GET_MUTATION_POWER(src), glow_power, glow_color) /datum/mutation/human/glow/on_losing(mob/living/carbon/human/owner) . = ..() if(.) return - QDEL_NULL(glowth) + QDEL_NULL(glow) /datum/mutation/human/glow/anti name = "Anti-Glow" desc = "Your skin seems to attract and absorb nearby light creating 'darkness' around you." text_gain_indication = span_notice("Your light around you seems to disappear.") - glow = -3.5 + glow_power = -3.5 conflicts = list(/datum/mutation/human/glow, /datum/mutation/human/radiantburst) locked = TRUE diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm index 1295d857b14c..4aaf778b6b21 100644 --- a/code/datums/mutations/hulk.dm +++ b/code/datums/mutations/hulk.dm @@ -43,102 +43,3 @@ message = "[replacetext(message, ".", "!")]!!" wrapped_message[1] = message return COMPONENT_UPPERCASE_SPEECH - -/datum/mutation/human/genetics_hulk - name = "Hulk" - desc = "A seemingly dormant genome, but reacts violently to agitation." - difficulty = 16 - instability = 50 - class = MUT_OTHER - locked = TRUE - quality = POSITIVE - get_chance = 10 - lowest_value = 256 * 14 - text_gain_indication = span_notice("You feel an anger welling inside you.") - health_req = 25 - -/datum/mutation/human/genetics_hulk/on_losing(mob/living/carbon/human/owner) - . = ..() - dna.remove_mutation(ACTIVE_HULK) - return - -/datum/mutation/human/active_hulk - name = "Hulk State" - desc = "The single most angry genome ever seen. Mutating this will incite a one-time immediate Hulkformation in the mutatee." - quality = POSITIVE - instability = 30 - class = MUT_OTHER - locked = TRUE - text_gain_indication = span_notice("Your muscles hurt!") - health_req = 1 - var/health_based = 0 - power_path = /datum/action/cooldown/spell/aoe/repulse/hulk - -/datum/mutation/human/active_hulk/on_acquiring(mob/living/carbon/human/owner) - if(..()) - return - owner.remove_CC() //RAGE RAGE RAGE, RISE RISE RISE - ADD_TRAIT(owner, TRAIT_STUNIMMUNE, TRAIT_HULK) - ADD_TRAIT(owner, TRAIT_PUSHIMMUNE, TRAIT_HULK) - ADD_TRAIT(owner, TRAIT_IGNORESLOWDOWN, TRAIT_HULK) - RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(handle_speech)) - if(istype(owner.w_uniform, /obj/item/clothing/under)) - var/obj/item/clothing/under/U = owner.w_uniform - if(owner.canUnEquip(U)) - owner.visible_message("[U] falls apart!", span_warning("You tear your clothes up in anger!")) - qdel(U) - if(istype(owner.wear_suit, /obj/item/clothing/suit)) - var/obj/item/clothing/suit/S = owner.wear_suit - if(owner.canUnEquip(S)) - owner.dropItemToGround(S) - owner.undershirt = "Nude" - owner.dna.species.no_equip.Add(ITEM_SLOT_OCLOTHING, ITEM_SLOT_ICLOTHING) - owner.say("PUNY HUMANS!!") - owner.physiology.stamina_mod = 0.3 - owner.update_body() - -/datum/mutation/human/active_hulk/on_attack_hand(atom/target, proximity) - if(proximity) //no telekinetic hulk attack - if(prob(3)) - owner.adjust_jitter(10 SECONDS) - owner.adjustStaminaLoss(-0.5) - return target.attack_hulk(owner) - -/datum/mutation/human/active_hulk/on_life() - owner.adjustStaminaLoss(0.9) - if(owner.health < 0) - on_losing(owner) - to_chat(owner, span_danger("You suddenly feel very weak. Your rage dies out.")) - -/datum/mutation/human/active_hulk/on_losing(mob/living/carbon/human/owner) - if(..()) - return - REMOVE_TRAIT(owner, TRAIT_STUNIMMUNE, TRAIT_HULK) - REMOVE_TRAIT(owner, TRAIT_PUSHIMMUNE, TRAIT_HULK) - REMOVE_TRAIT(owner, TRAIT_IGNORESLOWDOWN, TRAIT_HULK) - UnregisterSignal(owner, COMSIG_MOB_SAY) - owner.dna.species.no_equip.Remove(ITEM_SLOT_OCLOTHING, ITEM_SLOT_ICLOTHING) - owner.physiology.stamina_mod = initial(owner.physiology.stamina_mod) - owner.update_body_parts() - owner.dna.species.handle_mutant_bodyparts(owner) - -/datum/mutation/human/active_hulk/proc/handle_speech(original_message, wrapped_message) - var/message = wrapped_message[1] - if(message) - message = "[replacetext(message, ".", "!")]!!" - wrapped_message[1] = message - return COMPONENT_UPPERCASE_SPEECH - -/datum/action/cooldown/spell/aoe/repulse/hulk - name = "Ground Smash" - desc = "Smash the ground to throw your enemies back!" - invocation = "HULK SMASH!!" - button_icon = 'icons/mob/actions.dmi' - button_icon_state = "green_hand" - -/datum/action/cooldown/spell/aoe/repulse/hulk/cast_on_thing_in_aoe(atom/movable/victim, atom/caster) - var/turf/open/floor/turf = get_turf(victim) - if(istype(turf)) - turf.break_tile() - playsound(usr.loc, 'sound/effects/meteorimpact.ogg', 30, TRUE, 2) - return ..() diff --git a/code/datums/mutations/touch.dm b/code/datums/mutations/touch.dm index 4eb0ed901cc1..1441078d94c6 100644 --- a/code/datums/mutations/touch.dm +++ b/code/datums/mutations/touch.dm @@ -29,7 +29,7 @@ /datum/action/cooldown/spell/touch/shock/cast_on_hand_hit(obj/item/melee/touch_attack/hand, atom/victim, mob/living/carbon/caster) if(iscarbon(victim)) var/mob/living/carbon/carbon_victim = victim - if(carbon_victim.electrocute_act(15, caster, 1, stun = FALSE))//doesnt stun. never let this stun + if(carbon_victim.electrocute_act(15, caster, 1, zone=caster.zone_selected, stun = FALSE))//doesnt stun. never let this stun carbon_victim.dropItemToGround(carbon_victim.get_active_held_item()) carbon_victim.dropItemToGround(carbon_victim.get_inactive_held_item()) carbon_victim.adjust_timed_status_effect(15 SECONDS, /datum/status_effect/confusion) @@ -56,29 +56,3 @@ desc = "This is kind of like when you rub your feet on a shag rug so you can zap your friends, only a lot less safe." icon_state = "zapper" item_state = "zapper" - var/far = FALSE - -/obj/item/melee/touch_attack/shock/afterattack(atom/target, mob/living/carbon/user, proximity) - if(!(proximity || far) || !can_see(user, target, 5) || get_dist(target, user) > 5) - user.visible_message(span_notice("[user]'s hand reaches out but nothing happens.")) - return - if(iscarbon(target)) - var/mob/living/carbon/C = target - if(C.electrocute_act(15, src, 1, FALSE, FALSE, FALSE, FALSE, FALSE))//doesnt stun. never let this stun - user.Beam(C, icon_state="red_lightning", time = 1.5 SECONDS) - C.dropItemToGround(C.get_active_held_item()) - C.dropItemToGround(C.get_inactive_held_item()) - C.adjust_confusion(15 SECONDS) - C.visible_message(span_danger("[user] electrocutes [target]!"),span_userdanger("[user] electrocutes you!")) - log_combat(user, target, "[user] electrocuted [target] with shock touch") - else - user.visible_message(span_warning("[user] fails to electrocute [target]!")) - else if(isliving(target)) - var/mob/living/L = target - L.electrocute_act(15, src, 1, FALSE, FALSE, FALSE, FALSE) - user.Beam(L, icon_state="red_lightning", time = 1.5 SECONDS) - L.visible_message(span_danger("[user] electrocutes [target]!"),span_userdanger("[user] electrocutes you!")) - else - to_chat(user,span_warning("The electricity doesn't seem to affect [target]...")) - remove_hand_with_no_refund(user) - return ..() diff --git a/code/datums/mutations/touchfar.dm b/code/datums/mutations/touchfar.dm index 883853f4d4d6..317e23337277 100644 --- a/code/datums/mutations/touchfar.dm +++ b/code/datums/mutations/touchfar.dm @@ -10,5 +10,14 @@ name = "Extended Shock Touch" hand_path = /obj/item/melee/touch_attack/shock/far +/datum/action/cooldown/spell/touch/shock/far/cast_on_hand_hit(obj/item/melee/touch_attack/hand, atom/victim, mob/living/carbon/caster) + . = ..() + caster.Beam(victim, icon_state="red_lightning", time = 1.5 SECONDS) + /obj/item/melee/touch_attack/shock/far - far = TRUE + +/obj/item/melee/touch_attack/shock/far/afterattack(atom/target, mob/living/carbon/user, proximity, click_parameters) + if(!can_see(user, target, 5) || get_dist(target, user) > 5) + user.visible_message(span_notice("[user]'s hand reaches out but nothing happens.")) + return + . = ..(target, user, TRUE, click_parameters) //call the parent, forcing proximity = TRUE so even distant things are considered nearby diff --git a/code/datums/ruins/icemoon.dm b/code/datums/ruins/icemoon.dm index 47eac685cdba..d3ed65a6b87f 100644 --- a/code/datums/ruins/icemoon.dm +++ b/code/datums/ruins/icemoon.dm @@ -17,7 +17,7 @@ name = "Icemoon Hermit" id = "ice_hermit" description = "The home of a hermit in the ice and snow, you can't possibly imagine who'd want to live here." - suffix = "icemoon_hermit.dmm" + suffix = "icemoon_surface_hermit.dmm" /datum/map_template/ruin/icemoon/lust name = "Ruin of Lust" @@ -56,6 +56,12 @@ suffix = "lavaland_surface_seed_vault.dmm" allow_duplicates = FALSE +/datum/map_template/ruin/icemoon/walker_village + name = "Walker Village" + id = "walkervillage" + description = "A town populated by strange, sapient zombies." + suffix = "icemoon_surface_walkervillage.dmm" + // above and below ground together /datum/map_template/ruin/icemoon/mining_site @@ -119,9 +125,3 @@ id = "wampacave" description = "A cave inhabited by a strange monster, with an unfortunate hero..." suffix = "icemoon_underground_wampacave.dmm" - -/datum/map_template/ruin/icemoon/underground/walker_village - name = "Walker Village" - id = "walkervillage" - description = "A town populated by strange, sapient zombies." - suffix = "icemoon_underground_walkervillage.dmm" diff --git a/code/datums/status_effects/buffs/buffs.dm b/code/datums/status_effects/buffs/buffs.dm index b40be55ce848..112529026ff8 100644 --- a/code/datums/status_effects/buffs/buffs.dm +++ b/code/datums/status_effects/buffs/buffs.dm @@ -717,9 +717,11 @@ REMOVE_TRAIT(owner, TRAIT_ANTIMAGIC, type) owner.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY) + +#define HEALBOOST_FILTER "holy_glow" /datum/status_effect/holylight_healboost id = "holy healboost" - duration = 30 SECONDS + duration = 1 MINUTES tick_interval = -1 status_type = STATUS_EFFECT_REFRESH alert_type = /atom/movable/screen/alert/status_effect/holylight_healboost @@ -734,7 +736,15 @@ . = ..() if(.) owner.AddComponent(/datum/component/heal_react/boost/holylight) + owner.add_filter(HEALBOOST_FILTER, 2, list("type" = "outline", "color" = "#60A2A8", "alpha" = 0, "size" = 1)) + var/filter = owner.get_filter(HEALBOOST_FILTER) + animate(filter, alpha = 200, time = 2 SECONDS, loop = -1, easing = EASE_OUT | CUBIC_EASING) + animate(alpha = 0, time = 2 SECONDS, loop = -1, easing = EASE_OUT | CUBIC_EASING) /datum/status_effect/holylight_healboost/on_remove() var/datum/component/heal_react/boost/holylight/healing = owner.GetComponent(/datum/component/heal_react/boost/holylight) healing?.RemoveComponent() + var/filter = owner.get_filter(HEALBOOST_FILTER) + if(filter) + animate(filter) + owner.remove_filter(HEALBOOST_FILTER) diff --git a/code/datums/status_effects/debuffs/fire_stacks.dm b/code/datums/status_effects/debuffs/fire_stacks.dm index 76b6b64f6100..55978eb6bbdb 100644 --- a/code/datums/status_effects/debuffs/fire_stacks.dm +++ b/code/datums/status_effects/debuffs/fire_stacks.dm @@ -153,7 +153,7 @@ return TRUE var/datum/gas_mixture/air = owner.loc.return_air() - if(!air || (air.get_moles(/datum/gas/oxygen) < 1)) + if(!air || (air.get_moles(GAS_O2) < 1)) qdel(src) return TRUE diff --git a/code/datums/traits/good.dm b/code/datums/traits/good.dm index fd42bdd0572f..6c9e33ccef9d 100644 --- a/code/datums/traits/good.dm +++ b/code/datums/traits/good.dm @@ -310,46 +310,99 @@ medical_record_text = "Patient is unusually speedy when creating crafts." /datum/quirk/cyberorgan //random upgraded cybernetic organ - name = "Cybernetic Organ" - desc = "Due to a past incident you lost function of one of your organs, but now have a fancy upgraded cybernetic organ!" + name = "Upgraded Cybernetic Organ" + desc = "Due to a past incident you lost function of one of your organs, but now have a random upgraded cybernetic organ!" icon = "building-ngo" - value = 4 + value = 3 var/slot_string = "organ" - var/list/organ_list = list(ORGAN_SLOT_LUNGS, ORGAN_SLOT_HEART, ORGAN_SLOT_LIVER) + var/list/organ_list = list( + ORGAN_SLOT_LUNGS = /obj/item/organ/lungs/cybernetic/upgraded, + ORGAN_SLOT_HEART = /obj/item/organ/heart/cybernetic/upgraded, + ORGAN_SLOT_LIVER = /obj/item/organ/liver/cybernetic/upgraded, + ) medical_record_text = "During physical examination, patient was found to have an upgraded cybernetic organ." /datum/quirk/cyberorgan/on_spawn() var/mob/living/carbon/human/H = quirk_holder var/list/temp = organ_list.Copy() //pretty sure this is global so i dont want to bugger with it :) - if(isjellyperson(H)) + if(HAS_TRAIT_FROM(H, TRAIT_TOXINLOVER, SPECIES_TRAIT)) temp -= ORGAN_SLOT_LIVER - var/organ_slot = pick(temp) - var/obj/item/organ/old_part = H.getorganslot(organ_slot) - var/obj/item/organ/prosthetic - switch(organ_slot) - if(ORGAN_SLOT_LUNGS) - prosthetic = new/obj/item/organ/lungs/cybernetic/upgraded(quirk_holder) - slot_string = "lungs" - if(ORGAN_SLOT_HEART) - prosthetic = new/obj/item/organ/heart/cybernetic/upgraded(quirk_holder) - slot_string = "heart" - if(ORGAN_SLOT_LIVER) - prosthetic = new/obj/item/organ/liver/cybernetic/upgraded(quirk_holder) - slot_string = "liver" + if(HAS_TRAIT_FROM(H, TRAIT_NOBREATH, SPECIES_TRAIT)) + temp -= ORGAN_SLOT_LUNGS + if(NOBLOOD in H.dna?.species.species_traits) + temp -= ORGAN_SLOT_HEART + var/organ_type = organ_list[pick(temp)] + var/obj/item/organ/prosthetic = new organ_type(quirk_holder) + var/obj/item/organ/old_part = H.getorganslot(prosthetic.slot) + slot_string = prosthetic.slot prosthetic.Insert(H) qdel(old_part) H.regenerate_icons() /datum/quirk/cyberorgan/post_add() - to_chat(quirk_holder, "Your [slot_string] has been replaced with an upgraded cybernetic variant.") + to_chat(quirk_holder, span_boldannounce("Your [slot_string] has been replaced with an upgraded cybernetic variant.")) /datum/quirk/cyberorgan/check_quirk(datum/preferences/prefs) var/species_type = prefs.read_preference(/datum/preference/choiced/species) if(species_type == /datum/species/ipc) // IPCs are already cybernetic return "You already have cybernetic organs!" + + var/datum/species/species = new species_type + var/list/temp = organ_list.Copy() + if(TRAIT_TOXINLOVER in species.inherent_traits) + temp -= ORGAN_SLOT_LIVER + if(TRAIT_NOBREATH in species.inherent_traits) + temp -= ORGAN_SLOT_LUNGS + if(NOBLOOD in species.species_traits) + temp -= ORGAN_SLOT_HEART + if(temp.len <= 0) + return "You have no organs to replace!" + return FALSE +/datum/quirk/cyberorgan/lungs + name = "Cybernetic Organ (Lungs)" + desc = "Due to a past incident you lost function of your lungs, but now have cybernetic lungs!" + organ_list = list(ORGAN_SLOT_LUNGS = /obj/item/organ/lungs/cybernetic) + medical_record_text = "During physical examination, patient was found to have upgraded cybernetic lungs." + value = 0 + +/datum/quirk/cyberorgan/lungs/check_quirk(datum/preferences/prefs) + var/species_type = prefs.read_preference(/datum/preference/choiced/species) + var/datum/species/species = new species_type + if(TRAIT_NOBREATH in species.inherent_traits) // species with TRAIT_NOBREATH don't have lungs + return "You don't have lungs!" + return ..() + +/datum/quirk/cyberorgan/heart + name = "Cybernetic Organ (Heart)" + desc = "Due to a past incident you lost function of your heart, but now have a cybernetic heart!" + organ_list = list(ORGAN_SLOT_HEART = /obj/item/organ/heart/cybernetic) + medical_record_text = "During physical examination, patient was found to have a cybernetic heart." + value = 0 + +/datum/quirk/cyberorgan/heart/check_quirk(datum/preferences/prefs) + var/species_type = prefs.read_preference(/datum/preference/choiced/species) + var/datum/species/species = new species_type + if(NOBLOOD in species.species_traits) // species with NOBLOOD don't have a heart + return "You don't have a heart!" + return ..() + +/datum/quirk/cyberorgan/liver + name = "Cybernetic Organ (Liver)" + desc = "Due to a past incident you lost function of your liver, but now have a cybernetic liver!" + organ_list = list(ORGAN_SLOT_LIVER = /obj/item/organ/liver/cybernetic) + medical_record_text = "During physical examination, patient was found to have a cybernetic liver." + value = 0 + +/datum/quirk/cyberorgan/liver/check_quirk(datum/preferences/prefs) + var/species_type = prefs.read_preference(/datum/preference/choiced/species) + var/datum/species/species = new species_type + if(TRAIT_TOXINLOVER in species.inherent_traits) // species with TRAIT_TOXINLOVER slowly die when given upgraded livers + return "You aren't compatible with upgraded livers!" + return ..() + /datum/quirk/telomeres_long name = "Long Telomeres" desc = "You haven't been cloned much, if at all. Your DNA's telomeres are still largely unaffected by repeated cloning, enabling cloners to work faster." diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index e30a5e450947..5714024064dc 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -659,28 +659,6 @@ lose_text = span_notice("Your mind finally feels calm.") medical_record_text = "Patient's mind is in a vulnerable state, and cannot recover from traumatic events." -/datum/quirk/sheltered - name = "Sheltered" - desc = "You never learned to speak galactic common." - icon = "comment-dots" - value = -2 - mob_trait = TRAIT_SHELTERED - gain_text = span_danger("You do not speak galactic common.") - lose_text = span_notice("You start to put together how to speak galactic common.") - medical_record_text = "Patient looks perplexed when questioned in galactic common." - -/datum/quirk/sheltered/on_clone(data) - var/mob/living/carbon/human/H = quirk_holder - H.remove_language(/datum/language/common, FALSE, TRUE) - if(!H.get_selected_language()) - H.grant_language(/datum/language/japanese) - -/datum/quirk/sheltered/on_spawn() - var/mob/living/carbon/human/H = quirk_holder - H.remove_language(/datum/language/common, FALSE, TRUE) - if(!H.get_selected_language()) - H.grant_language(/datum/language/japanese) - /datum/quirk/allergic name = "Allergic Reaction" desc = "You have had an allergic reaction to medicine in the past. Better stay away from it!" diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm index a93336ec2e08..d40bdf4026b8 100644 --- a/code/datums/traits/neutral.dm +++ b/code/datums/traits/neutral.dm @@ -375,3 +375,25 @@ /datum/quirk/bald/proc/unequip_hat(mob/user, obj/item/hat) SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "bad_hair_day", /datum/mood_event/bald) + +/datum/quirk/sheltered + name = "Sheltered" + desc = "You never learned to speak galactic common." + icon = "comment-dots" + value = 0 + mob_trait = TRAIT_SHELTERED + gain_text = span_danger("You do not speak galactic common.") + lose_text = span_notice("You start to put together how to speak galactic common.") + medical_record_text = "Patient looks perplexed when questioned in galactic common." + +/datum/quirk/sheltered/on_clone(data) + var/mob/living/carbon/human/H = quirk_holder + H.remove_language(/datum/language/common, FALSE, TRUE) + if(!H.get_selected_language()) + H.grant_language(/datum/language/japanese) + +/datum/quirk/sheltered/on_spawn() + var/mob/living/carbon/human/H = quirk_holder + H.remove_language(/datum/language/common, FALSE, TRUE) + if(!H.get_selected_language()) + H.grant_language(/datum/language/japanese) diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index c6b23bc0b270..afab00c7f397 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -32,6 +32,7 @@ var/clockwork_warp_allowed = TRUE // Can servants warp into this area from Reebe? var/clockwork_warp_fail = "The structure there is too dense for warping to pierce. (This is normal in high-security areas.)" + ///If true, that means one of any fire alarms in the area is active var/fire = FALSE var/atmos = TRUE var/atmosalm = FALSE @@ -113,6 +114,7 @@ var/list/firedoors var/list/cameras var/list/firealarms + var/list/airalarms var/firedoors_last_closed_on = 0 /// Can the Xenobio management console transverse this area by default? var/xenobiology_compatible = FALSE @@ -344,10 +346,7 @@ GLOBAL_LIST_EMPTY(teleportlocs) D.triggerAlarm("Power", src, cameras, source) for(var/item in GLOB.alarmdisplay) var/datum/computer_file/program/alarm_monitor/p = item - if(state == 1) - p.cancelAlarm("Power", src, source) - else - p.triggerAlarm("Power", src, cameras, source) + p.update_alarm_display() /** * Generate an atmospheric alert for this area @@ -368,7 +367,7 @@ GLOBAL_LIST_EMPTY(teleportlocs) D.triggerAlarm("Atmosphere", src, cameras, source) for(var/item in GLOB.alarmdisplay) var/datum/computer_file/program/alarm_monitor/p = item - p.triggerAlarm("Atmosphere", src, cameras, source) + p.update_alarm_display() else for (var/item in GLOB.silicon_mobs) @@ -382,7 +381,7 @@ GLOBAL_LIST_EMPTY(teleportlocs) D.cancelAlarm("Atmosphere", src, source) for(var/item in GLOB.alarmdisplay) var/datum/computer_file/program/alarm_monitor/p = item - p.cancelAlarm("Atmosphere", src, source) + p.update_alarm_display() /** * Try to close all the firedoors in the area */ @@ -433,7 +432,7 @@ GLOBAL_LIST_EMPTY(teleportlocs) D.triggerAlarm("Fire", src, cameras, source) for(var/item in GLOB.alarmdisplay) var/datum/computer_file/program/alarm_monitor/p = item - p.triggerAlarm("Fire", src, cameras, source) + p.update_alarm_display() START_PROCESSING(SSobj, src) @@ -445,8 +444,8 @@ GLOBAL_LIST_EMPTY(teleportlocs) * * Also cycles the icons of all firealarms and deregisters the area from processing on SSOBJ */ -/area/proc/firereset(obj/source) - if (fire) +/area/proc/firereset(obj/source, alert_only=FALSE) + if (fire && !alert_only) unset_fire_alarm_effects() ModifyFiredoors(TRUE) for(var/item in firealarms) @@ -464,7 +463,7 @@ GLOBAL_LIST_EMPTY(teleportlocs) D.cancelAlarm("Fire", src, source) for(var/item in GLOB.alarmdisplay) var/datum/computer_file/program/alarm_monitor/p = item - p.cancelAlarm("Fire", src, source) + p.update_alarm_display() STOP_PROCESSING(SSobj, src) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index f0e851f8a341..191525de75e4 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -44,6 +44,28 @@ var/datum/wires/wires = null var/obj/effect/abstract/particle_holder/master_holder + ///Light systems, both shouldn't be active at the same time. + var/light_system = STATIC_LIGHT + ///Range of the light in tiles. Zero means no light. + var/light_range = 0 + ///Intensity of the light. The stronger, the less shadows you will see on the lit area. + var/light_power = 1 + ///Hexadecimal RGB string representing the colour of the light. White by default. + var/light_color = COLOR_WHITE + /// Angle of light to show in light_dir + /// 360 is a circle, 90 is a cone, etc. + var/light_angle = 360 + /// What angle to project light in + var/light_dir = NORTH + ///Boolean variable for toggleable lights. Has no effect without the proper light_system, light_range and light_power values. + var/light_on = TRUE + ///Bitflags to determine lighting-related atom properties. + var/light_flags = NONE + ///Our light source. Don't fuck with this directly unless you have a good reason! + var/tmp/datum/light_source/light + ///Any light sources that are "inside" of us, for example, if src here was a mob that's carrying a flashlight, that flashlight's light source would be part of this list. + var/tmp/list/light_sources + ///overlays that should remain on top and not normally removed when using cut_overlay functions, like c4. var/list/priority_overlays /// a very temporary list of overlays to remove @@ -171,10 +193,6 @@ if (light_system == STATIC_LIGHT && light_power && light_range) update_light() - if (opacity && isturf(loc)) - var/turf/T = loc - T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways. - if (canSmoothWith) canSmoothWith = typelist("canSmoothWith", canSmoothWith) @@ -363,23 +381,38 @@ ///Take air from the passed in gas mixture datum /atom/proc/assume_air(datum/gas_mixture/giver) - qdel(giver) + return null + +/atom/proc/assume_air_moles(datum/gas_mixture/giver, moles) + return null + +/atom/proc/assume_air_ratio(datum/gas_mixture/giver, ratio) return null ///Remove air from this atom /atom/proc/remove_air(amount) return null +/atom/proc/remove_air_ratio(ratio) + return null + +/atom/proc/transfer_air(datum/gas_mixture/taker, amount) + return null + +/atom/proc/transfer_air_ratio(datum/gas_mixture/taker, ratio) + return null + ///Return the current air environment in this atom /atom/proc/return_air() if(loc) return loc.return_air() - else - return null + return null +///Return the air if we can analyze it /atom/proc/return_analyzable_air() return null + ///Return the air if we can analyze it ///Check if this atoms eye is still alive (probably) /atom/proc/check_eye(mob/user) @@ -1046,12 +1079,63 @@ * the object has been admin edited */ /atom/vv_edit_var(var_name, var_value) + var/old_light_flags = light_flags + // Disable frozen lights for now, so we can actually modify it + light_flags &= ~LIGHT_FROZEN + switch(var_name) + + if(NAMEOF(src, light_range)) + if(light_system == STATIC_LIGHT) + set_light(l_range = var_value) + else + set_light_range(var_value) + . = TRUE + if(NAMEOF(src, light_power)) + if(light_system == STATIC_LIGHT) + set_light(l_power = var_value) + else + set_light_power(var_value) + . = TRUE + if(NAMEOF(src, light_color)) + if(light_system == STATIC_LIGHT) + set_light(l_color = var_value) + else + set_light_color(var_value) + . = TRUE + if(NAMEOF(src, light_angle)) + if(light_system == STATIC_LIGHT) + set_light(l_angle = var_value) + . = TRUE + if(NAMEOF(src, light_dir)) + if(light_system == STATIC_LIGHT) + set_light(l_dir = var_value) + . = TRUE + if(NAMEOF(src, light_on)) + set_light_on(var_value) + . = TRUE + if(NAMEOF(src, light_flags)) + set_light_flags(var_value) + // I'm sorry + old_light_flags = var_value + . = TRUE + + light_flags = old_light_flags + if(!isnull(.)) + datum_flags |= DF_VAR_EDITED + return + if(!GLOB.Debug2) flags_1 |= ADMIN_SPAWNED_1 - . = ..() + + . = ..() + switch(var_name) - if("color") + if(NAMEOF(src, color)) add_atom_colour(color, ADMIN_COLOUR_PRIORITY) + update_appearance() + if(NAMEOF(src, opacity)) + set_opacity(var_value) + . = TRUE /** * Return the markup to for the dropdown list for the VV panel for this atom diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index caa5aa2f94d9..99dc8e01778b 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -61,7 +61,7 @@ var/affecting_dynamic_lumi = 0 -/atom/movable/Initialize(mapload) +/atom/movable/Initialize(mapload, ...) . = ..() switch(blocks_emissive) if(EMISSIVE_BLOCK_GENERIC) @@ -71,8 +71,16 @@ em_block = new(src, render_target) vis_contents += em_block - if(light_system == MOVABLE_LIGHT) - AddComponent(/datum/component/overlay_lighting) + if(opacity) + AddElement(/datum/element/light_blocking) + + switch(light_system) + if(MOVABLE_LIGHT) + AddComponent(/datum/component/overlay_lighting) + if(MOVABLE_LIGHT_DIRECTIONAL) + AddComponent(/datum/component/overlay_lighting, is_directional = TRUE) + if(MOVABLE_LIGHT_BEAM) + AddComponent(/datum/component/overlay_lighting, is_directional = TRUE, is_beam = TRUE) /atom/movable/Destroy(force) QDEL_NULL(proximity_monitor) @@ -85,8 +93,11 @@ //Restore air flow if we were blocking it (movables with ATMOS_PASS_PROC will need to do this manually if necessary) if(((CanAtmosPass == ATMOS_PASS_DENSITY && density) || CanAtmosPass == ATMOS_PASS_NO) && isturf(loc)) CanAtmosPass = ATMOS_PASS_YES - air_update_turf(TRUE) + air_update_turf() loc.handle_atom_del(src) + + if(opacity) + RemoveElement(/datum/element/light_blocking) invisibility = INVISIBILITY_ABSTRACT diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index d5dd024038f8..974f66f8a616 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -80,7 +80,6 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) var/antags_rolled = 0 /// CRATE DISCOUNT var/discountedcrates = list( /datum/supply_pack/security/laser, - /datum/supply_pack/security/helmets, /datum/supply_pack/security/vending/security, /datum/supply_pack/service/party) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 0b5069abaa5a..e9a990cd8e30 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -443,7 +443,7 @@ continue // No parent vent // Stops Aliens getting stuck in small networks. // See: Security, Virology - if(temp_vent_parent.other_atmosmch.len > 20) + if(temp_vent_parent.other_atmos_machines.len > 20) vents += temp_vent if(!vents.len) return FALSE diff --git a/code/game/gamemodes/extended/extended.dm b/code/game/gamemodes/extended/extended.dm index a80f5056a844..00fd0a8cd15b 100644 --- a/code/game/gamemodes/extended/extended.dm +++ b/code/game/gamemodes/extended/extended.dm @@ -32,4 +32,4 @@ . += greenshift_message print_command_report(., "Central Command Status Summary", announce = FALSE) - priority_announce(greenshift_message, "Security Report", RANDOM_REPORT_SOUND) + priority_announce(greenshift_message, "Security Report", SSstation.announcer.get_rand_report_sound()) diff --git a/code/game/gamemodes/objective_items.dm b/code/game/gamemodes/objective_items.dm index 72c151b38701..4a923f59efac 100644 --- a/code/game/gamemodes/objective_items.dm +++ b/code/game/gamemodes/objective_items.dm @@ -150,12 +150,12 @@ if(!istype(o, /obj/item/tank)) continue var/obj/item/tank/T = o - found_amount += T.air_contents.get_moles(/datum/gas/plasma) + found_amount += T.air_contents.get_moles(GAS_PLASMA) if (istype(objective.team, /datum/team/infiltrator)) for (var/area/A in world) if (is_type_in_typecache(A, GLOB.infiltrator_objective_areas)) for (var/obj/item/tank/T in A.get_all_contents()) //Check for items - found_amount += T.air_contents.get_moles(/datum/gas/plasma) + found_amount += T.air_contents.get_moles(GAS_PLASMA) CHECK_TICK CHECK_TICK CHECK_TICK diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 7a57f1a3fe42..8a017d1be4f5 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -137,6 +137,9 @@ Class Procs: /// Mobtype of last user. Typecast to [/mob/living] for initial() usage var/mob/living/last_user_mobtype + ///Boolean on whether this machines interact with atmos + var/atmos_processing = FALSE + /obj/machinery/Initialize(mapload) if(!armor) armor = list(MELEE = 25, BULLET = 10, LASER = 10, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 50, ACID = 70) @@ -162,7 +165,7 @@ Class Procs: power_change() RegisterSignal(src, COMSIG_ENTER_AREA, PROC_REF(power_change)) -/obj/machinery/Destroy() +/obj/machinery/Destroy(force=FALSE) disconnect_from_network() GLOB.machines.Remove(src) if(!speed_process) @@ -188,7 +191,7 @@ Class Procs: /obj/machinery/emp_act(severity) . = ..() if(use_power && !stat && !(. & EMP_PROTECT_SELF)) - use_power(7500/severity) + use_power(750 * severity) new /obj/effect/temp_visual/emp(loc) /obj/machinery/proc/open_machine(drop = TRUE) @@ -297,11 +300,7 @@ Class Procs: var/mob/living/carbon/H = user if(istype(H) && H.has_dna()) - if (H.dna.check_mutation(ACTIVE_HULK)) - to_chat(H, span_warning("HULK NOT NERD. HULK SMASH!!!")) - return FALSE // hulks cant use machines - - else if(!Adjacent(user) && !H.dna.check_mutation(TK)) + if(!Adjacent(user) && !H.dna.check_mutation(TK)) return FALSE // need to be close or have telekinesis return TRUE @@ -488,8 +487,8 @@ Class Procs: I.play_tool_sound(src, 50) setDir(turn(dir,-90)) to_chat(user, span_notice("You rotate [src].")) - return 1 - return 0 + return TRUE + return FALSE /obj/proc/can_be_unfasten_wrench(mob/user, silent) //if we can unwrench this object; returns SUCCESSFUL_UNFASTEN and FAILED_UNFASTEN, which are both TRUE, or CANT_UNFASTEN, which isn't. if(!(isfloorturf(loc) || istype(loc, /turf/open/indestructible)) && !anchored) diff --git a/code/game/machinery/airlock_cycle_control.dm b/code/game/machinery/airlock_cycle_control.dm index 852ac542b135..7a142582f6f5 100644 --- a/code/game/machinery/airlock_cycle_control.dm +++ b/code/game/machinery/airlock_cycle_control.dm @@ -113,12 +113,12 @@ qdel(wires) wires = null cut_links() - SSair.atmos_machinery -= src + SSair_machinery.stop_processing_machine(src) return ..() /obj/machinery/advanced_airlock_controller/Initialize(mapload) . = ..() - SSair.atmos_machinery += src + SSair_machinery.start_processing_machine(src) scan_on_late_init = mapload if(mapload && (. != INITIALIZE_HINT_QDEL)) return INITIALIZE_HINT_LATELOAD @@ -135,14 +135,12 @@ airlock.bolt() /obj/machinery/advanced_airlock_controller/proc/update_cycle_icon(use_hash = FALSE) - var/turf/location = get_turf(src) - if(!location) + if(!isopenturf(get_turf(src))) return var/pressure = 0 - if(location) - var/datum/gas_mixture/environment = location.return_air() - if(environment) - pressure = environment.return_pressure() + var/datum/gas_mixture/environment = return_air() + if(environment) + pressure = environment.return_pressure() var/maxpressure = (exterior_pressure && (cyclestate == AIRLOCK_CYCLESTATE_OUTCLOSING || cyclestate == AIRLOCK_CYCLESTATE_OUTOPENING || cyclestate == AIRLOCK_CYCLESTATE_OUTOPEN)) ? exterior_pressure : interior_pressure var/pressure_bars = round(pressure / maxpressure * 5 + 0.01) @@ -295,15 +293,13 @@ update_cycle_icon(TRUE) return - var/turf/location = get_turf(src) - if(!location) + if(!isopenturf(get_turf(src))) update_cycle_icon(TRUE) return var/pressure = 0 - if(location) - var/datum/gas_mixture/environment = location.return_air() - if(environment) - pressure = environment.return_pressure() + var/datum/gas_mixture/environment = return_air() + if(environment) + pressure = environment.return_pressure() update_error_status() var/doors_valid = TRUE @@ -596,10 +592,9 @@ ui.open() /obj/machinery/advanced_airlock_controller/ui_data(mob/user) - var/turf/T = get_turf(src) var/pressure = 0 - if(T) - var/datum/gas_mixture/environment = T.return_air() + if(isopenturf(get_turf(src))) + var/datum/gas_mixture/environment = return_air() if(environment) pressure = environment.return_pressure() diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 1b20666ac44c..a36956f5459f 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -144,7 +144,7 @@ if(!status) return if(!(. & EMP_PROTECT_SELF)) - if(prob(150/severity)) + if(prob(15 * severity)) update_appearance(UPDATE_ICON) var/list/previous_network = network network = list() @@ -164,7 +164,7 @@ if(can_use()) GLOB.cameranet.addCamera(src) emped = 0 //Resets the consecutive EMP count - addtimer(CALLBACK(src, PROC_REF(cancelCameraAlarm)), 100) + addtimer(CALLBACK(src, PROC_REF(cancelCameraAlarm)), severity SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE) for(var/i in GLOB.player_list) var/mob/M = i if (M.client.eye == src) diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index f009648e90b6..4d8f22c4f9ef 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -532,7 +532,7 @@ GLOBAL_VAR_INIT(clones, 0) . = ..() if (!(. & EMP_PROTECT_SELF)) var/mob/living/mob_occupant = occupant - if(mob_occupant && prob(100/(severity*efficiency))) + if(mob_occupant && prob(10 * severity / efficiency)) log_cloning("[key_name(mob_occupant)] ejected from [src] at [AREACOORD(src)] due to EMP pulse.") connected_message(Gibberish("EMP-caused Accidental Ejection", 0)) SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of [mob_occupant.real_name] prematurely." ,0)) diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm index 50682a895aea..c0077e4fa619 100644 --- a/code/game/machinery/computer/_computer.dm +++ b/code/game/machinery/computer/_computer.dm @@ -103,9 +103,9 @@ if(!.) return // reduce unneeded light changes if(stat & NOPOWER) - set_light(FALSE) + set_light_on(FALSE) else - set_light(TRUE) + set_light_on(TRUE) /obj/machinery/computer/screwdriver_act(mob/living/user, obj/item/I) if(..()) @@ -133,18 +133,14 @@ . = ..() if(.) playsound(loc, 'sound/effects/glassbr3.ogg', 100, TRUE) - set_light(0) + set_light_on(FALSE) /obj/machinery/computer/emp_act(severity) . = ..() - if (!(. & EMP_PROTECT_SELF)) - switch(severity) - if(1) - if(prob(50)) - obj_break(ENERGY) - if(2) - if(prob(10)) - obj_break(ENERGY) + if(. & EMP_PROTECT_SELF) + return + if(prob(5 * severity)) + obj_break(ENERGY) /obj/machinery/computer/deconstruct(disassembled = TRUE, mob/user) on_deconstruction() diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index a124b493fa5d..7c6a41699814 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -120,12 +120,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( return var/empprize = null - var/num_of_prizes = 0 - switch(severity) - if(1) - num_of_prizes = rand(1,4) - if(2) - num_of_prizes = rand(0,2) + var/num_of_prizes = rand(0, severity / 2.5) for(var/i = num_of_prizes; i > 0; i--) if(override) empprize = pickweight(prize_override) diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm index 0a54ea2f031e..97383ec1c85c 100644 --- a/code/game/machinery/computer/atmos_alert.dm +++ b/code/game/machinery/computer/atmos_alert.dm @@ -4,13 +4,18 @@ circuit = /obj/item/circuitboard/computer/atmos_alert icon_screen = "alert:0" icon_keyboard = "atmos_key" - var/list/priority_alarms = list() - var/list/minor_alarms = list() - var/receive_frequency = FREQ_ATMOS_ALARMS - var/datum/radio_frequency/radio_connection - light_color = LIGHT_COLOR_CYAN + ///List of areas with a priority alarm ongoing. + var/list/area/priority_alarms = list() + ///List of areas with a minor alarm ongoing. + var/list/area/minor_alarms = list() + + ///The radio connection the computer uses to receive signals. + var/datum/radio_frequency/radio_connection + ///The frequency that radio_connection listens and retrieves signals from. + var/receive_frequency = FREQ_ATMOS_ALARMS + /obj/machinery/computer/atmos_alert/Initialize(mapload) . = ..() set_frequency(receive_frequency) @@ -27,31 +32,43 @@ /obj/machinery/computer/atmos_alert/ui_data(mob/user) var/list/data = list() + data["priority_alerts"] = list() + data["minor_alerts"] = list() + + for(var/area/priority_alarm as anything in priority_alarms) + data["priority_alerts"] += list(list( + "name" = priority_alarm.name, + "ref" = REF(priority_alarm), + )) - data["priority"] = list() - for(var/zone in priority_alarms) - data["priority"] += zone - data["minor"] = list() - for(var/zone in minor_alarms) - data["minor"] += zone + for(var/area/minor_alarm as anything in minor_alarms) + data["minor_alerts"] += list(list( + "name" = minor_alarm.name, + "ref" = REF(minor_alarm), + )) return data /obj/machinery/computer/atmos_alert/ui_act(action, params) - if(..()) - return - switch(action) - if("clear") - var/zone = params["zone"] - if(zone in priority_alarms) - to_chat(usr, "Priority alarm for [zone] cleared.") - priority_alarms -= zone - . = TRUE - if(zone in minor_alarms) - to_chat(usr, "Minor alarm for [zone] cleared.") - minor_alarms -= zone - . = TRUE - update_appearance(UPDATE_ICON) + . = ..() + if(.) + return TRUE + if(action != "clear") + return TRUE + + var/area/zone_from_tgui = locate(params["zone_ref"]) in priority_alarms + minor_alarms + if(!zone_from_tgui || !istype(zone_from_tgui)) + return TRUE + + var/obj/machinery/airalarm/found_air_alarm = locate() in zone_from_tgui + if(found_air_alarm) + found_air_alarm.atmos_manualOverride(TRUE) + found_air_alarm.post_alert(0) + priority_alarms -= zone_from_tgui + minor_alarms -= zone_from_tgui + balloon_alert(usr, "alarm cleared.") + update_appearance(UPDATE_ICON) + return TRUE /obj/machinery/computer/atmos_alert/proc/set_frequency(new_frequency) SSradio.remove_object(src, receive_frequency) @@ -62,25 +79,27 @@ if(!signal) return - var/zone = signal.data["zone"] + var/area/new_zone = signal.data["zone"] var/severity = signal.data["alert"] - - if(!zone || !severity) + if(!new_zone || !istype(new_zone) || !severity) return - minor_alarms -= zone - priority_alarms -= zone - if(severity == "severe") - priority_alarms += zone - else if (severity == "minor") - minor_alarms += zone + //clear current references. + minor_alarms -= new_zone + priority_alarms -= new_zone + + switch(severity) + if(ATMOS_ALARM_SEVERE) + priority_alarms += new_zone + if(ATMOS_ALARM_MINOR) + minor_alarms += new_zone update_appearance(UPDATE_ICON) - return /obj/machinery/computer/atmos_alert/update_overlays() . = ..() if(stat & (NOPOWER|BROKEN)) return + if(priority_alarms.len) . += "alert:2" else if(minor_alarms.len) diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm index 7474377cc462..7ed11ce00534 100644 --- a/code/game/machinery/computer/atmos_control.dm +++ b/code/game/machinery/computer/atmos_control.dm @@ -61,7 +61,7 @@ var/total_moles = air_sample.total_moles() if(total_moles) for(var/gas_id in air_sample.get_gases()) - var/gas_name = GLOB.meta_gas_info[gas_id][META_GAS_NAME] + var/gas_name = GLOB.gas_data.names[gas_id] signal.data["gases"][gas_name] = air_sample.get_moles(gas_id) / total_moles * 100 radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) @@ -74,11 +74,11 @@ /obj/machinery/air_sensor/Initialize(mapload) . = ..() - SSair.atmos_machinery += src + SSair_machinery.start_processing_machine(src) set_frequency(frequency) /obj/machinery/air_sensor/Destroy() - SSair.atmos_machinery -= src + SSair_machinery.stop_processing_machine(src) SSradio.remove_object(src, frequency) return ..() diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 2914a3fbdf0b..a4661b57163d 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -252,7 +252,7 @@ nuke_request(reason, usr) to_chat(usr, span_notice("Request sent.")) usr.log_message("has requested the nuclear codes from CentCom with reason \"[reason]\"", LOG_SAY) - priority_announce("The codes for the on-station nuclear self-destruct have been requested by [authorize_name]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self-Destruct Codes Requested", RANDOM_REPORT_SOUND) + priority_announce("The codes for the on-station nuclear self-destruct have been requested by [authorize_name]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self-Destruct Codes Requested", SSstation.announcer.get_rand_report_sound()) playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE) COOLDOWN_START(src, important_action_cooldown, IMPORTANT_ACTION_COOLDOWN) if ("restoreBackupRoutingData") @@ -364,7 +364,7 @@ playsound(loc, 'sound/items/poster_being_created.ogg', 100, 1) new /obj/item/card/id/captains_spare/temporary(loc) COOLDOWN_START(src, important_action_cooldown, IMPORTANT_ACTION_COOLDOWN) - priority_announce("The emergency spare ID has been printed by [authorize_name].", "Emergency Spare ID Warning System", RANDOM_REPORT_SOUND) + priority_announce("The emergency spare ID has been printed by [authorize_name].", "Emergency Spare ID Warning System", SSstation.announcer.get_rand_report_sound()) if("printAIControlCode") if(authenticated_as_non_silicon_head(usr)) if(!COOLDOWN_FINISHED(src, important_action_cooldown)) @@ -373,7 +373,7 @@ GLOB.ai_control_code = random_nukecode(6) new /obj/item/paper/ai_control_code(loc) COOLDOWN_START(src, important_action_cooldown, IMPORTANT_ACTION_COOLDOWN) - priority_announce("The AI Control Code been printed by [authorize_name]. All previous codes have been invalidated.", "Central Tech Support", RANDOM_REPORT_SOUND) + priority_announce("The AI Control Code been printed by [authorize_name]. All previous codes have been invalidated.", "Central Tech Support", SSstation.announcer.get_rand_report_sound()) /obj/machinery/computer/communications/ui_data(mob/user) diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index 8fcbfe3f7298..cefddeb1eda1 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -721,6 +721,9 @@ // GUARD CHECK - This should not be possible. Unexpected result if(!HM) return + if(!HM.allow_cloning) + say("ERROR: This mutation is anomalous, and cannot be saved.") + return var/datum/mutation/human/A = new HM.type() A.copy_mutation(HM) @@ -1389,6 +1392,9 @@ // GUARD CHECK - This should not be possible. Unexpected result if(!HM) return + if(!HM.allow_cloning) + say("ERROR: This mutation is anomalous, and cannot be added to an injector.") + return // We want to make sure we stick within the instability limit. // We start with the instability of the mutation we're intending to add. diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index cf7ed783af0b..a26d877798de 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -534,7 +534,7 @@ . = ..() if(!(stat & (BROKEN|NOPOWER)) && !(. & EMP_PROTECT_SELF)) for(var/datum/data/record/R in GLOB.data_core.medical) - if(prob(10/severity)) + if(prob(severity)) switch(rand(1,6)) if(1) if(prob(10)) diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 4c3a77264c0d..bd642b99f661 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -875,7 +875,7 @@ return for(var/datum/data/record/R in GLOB.data_core.security) - if(prob(10/severity)) + if(prob(severity)) switch(rand(1,8)) if(1) if(prob(10)) diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm index 1b203509452c..a27c9c1275b7 100644 --- a/code/game/machinery/computer/station_alert.dm +++ b/code/game/machinery/computer/station_alert.dm @@ -45,6 +45,7 @@ var/list/sources = alarm[3] if (!(source in sources)) sources += source + update_appearance(UPDATE_ICON) return 1 var/obj/machinery/camera/C = null var/list/CL = null @@ -55,6 +56,7 @@ else if(O && istype(O, /obj/machinery/camera)) C = O L[A.name] = list(A, (C ? C : O), list(source)) + update_appearance(UPDATE_ICON) return 1 @@ -72,6 +74,7 @@ if (srcs.len == 0) cleared = 1 L -= I + update_appearance(UPDATE_ICON) return !cleared /obj/machinery/computer/station_alert/update_overlays() diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index b8112fb735e7..8fb9435b6e7c 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -374,7 +374,7 @@ GLOBAL_VAR_INIT(cryopods_enabled, FALSE) return if(!GLOB.cryopods_enabled) - to_chat(user, span_boldnotice("NanoTrasen does not allow abandoning your crew during a crisis. Cryo systems disabled until the current crisis is resolved.")) + to_chat(user, span_boldnotice("Nanotrasen does not allow abandoning your crew during a crisis. Cryo systems disabled until the current crisis is resolved.")) return if(occupant) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 7d9f72c774f2..fcb931fa2f4a 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -507,12 +507,9 @@ else return else if(user.has_status_effect(/datum/status_effect/hallucination) && ishuman(user) && prob(1) && !operating) - var/mob/living/carbon/human/H = user - if(H.gloves) - var/obj/item/clothing/gloves/G = H.gloves - if(G.siemens_coefficient)//not insulated - new /datum/hallucination/shock(H) - return + if(user.getarmor(user.held_index_to_body_zone(user.active_hand_index), ELECTRIC) < 100) + new /datum/hallucination/shock(user) + return var/allowed = (obj_flags & CMAGGED) ? cmag_allowed(user) : allowed(user) if (cyclelinkedairlock) if (!shuttledocked && !emergency && !cyclelinkedairlock.shuttledocked && !cyclelinkedairlock.emergency && allowed) @@ -1427,7 +1424,7 @@ sleep(0.1 SECONDS) density = FALSE sleep(0.3 SECONDS) - air_update_turf(1) + air_update_turf() sleep(0.1 SECONDS) layer = OPEN_DOOR_LAYER update_icon(state = AIRLOCK_OPEN, override = TRUE) @@ -1469,11 +1466,11 @@ layer = CLOSED_DOOR_LAYER if(air_tight) density = TRUE - air_update_turf(1) + air_update_turf() sleep(0.1 SECONDS) density = TRUE if(!air_tight) - air_update_turf(1) + air_update_turf() sleep(0.4 SECONDS) if(!safe) crush() diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm index 5204102cb6c1..4607882135b0 100644 --- a/code/game/machinery/doors/airlock_types.dm +++ b/code/game/machinery/doors/airlock_types.dm @@ -64,7 +64,7 @@ */ /obj/machinery/door/airlock/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/glass/incinerator @@ -82,28 +82,28 @@ id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_EXTERIOR /obj/machinery/door/airlock/command/glass - opacity = 0 + opacity = FALSE glass = TRUE normal_integrity = 400 /obj/machinery/door/airlock/engineering/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/engineering/glass/critical critical_machine = TRUE //stops greytide virus from opening & bolting doors in critical positions, such as the SM chamber. /obj/machinery/door/airlock/security/glass - opacity = 0 + opacity = FALSE glass = TRUE normal_integrity = 400 /obj/machinery/door/airlock/medical/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/research/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/research/glass/incinerator @@ -121,30 +121,30 @@ id_tag = INCINERATOR_TOXMIX_AIRLOCK_EXTERIOR /obj/machinery/door/airlock/mining/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/atmos/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/atmos/glass/critical critical_machine = TRUE //stops greytide virus from opening & bolting doors in critical positions, such as the SM chamber. /obj/machinery/door/airlock/science/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/virology/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/maintenance/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/maintenance/external/glass - opacity = 0 + opacity = FALSE glass = TRUE normal_integrity = 200 @@ -159,7 +159,7 @@ assemblytype = /obj/structure/door_assembly/door_assembly_gold /obj/machinery/door/airlock/gold/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/silver @@ -168,7 +168,7 @@ assemblytype = /obj/structure/door_assembly/door_assembly_silver /obj/machinery/door/airlock/silver/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/diamond @@ -180,7 +180,7 @@ /obj/machinery/door/airlock/diamond/glass normal_integrity = 950 - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/uranium @@ -201,7 +201,7 @@ return /obj/machinery/door/airlock/uranium/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/plasma @@ -229,8 +229,8 @@ DA.update_appearance() qdel(src) -/obj/machinery/door/airlock/plasma/BlockSuperconductivity() //we don't stop the heat~ - return 0 +/obj/machinery/door/airlock/plasma/BlockThermalConductivity() //we don't stop the heat~ + return FALSE /obj/machinery/door/airlock/plasma/attackby(obj/item/C, mob/user, params) if(C.is_hot() > 300)//If the temperature of the object is over 300, then ignite @@ -241,7 +241,7 @@ return ..() /obj/machinery/door/airlock/plasma/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/bananium @@ -252,7 +252,7 @@ doorOpen = 'sound/items/bikehorn.ogg' /obj/machinery/door/airlock/bananium/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/sandstone @@ -261,7 +261,7 @@ assemblytype = /obj/structure/door_assembly/door_assembly_sandstone /obj/machinery/door/airlock/sandstone/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/wood @@ -270,7 +270,7 @@ assemblytype = /obj/structure/door_assembly/door_assembly_wood /obj/machinery/door/airlock/wood/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/titanium @@ -283,7 +283,7 @@ /obj/machinery/door/airlock/titanium/glass normal_integrity = 350 - opacity = 0 + opacity = FALSE glass = TRUE ////////////////////////////////// @@ -297,7 +297,7 @@ assemblytype = /obj/structure/door_assembly/door_assembly_public /obj/machinery/door/airlock/public/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/public/glass/incinerator @@ -330,7 +330,7 @@ panel_attachment = "bottom" /obj/machinery/door/airlock/external/glass - opacity = 0 + opacity = FALSE glass = TRUE ////////////////////////////////// @@ -426,7 +426,7 @@ anim_parts = "rightu=11,0;left=-12,0;right=11,0" /obj/machinery/door/airlock/shuttle/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/abductor @@ -521,7 +521,7 @@ /obj/machinery/door/airlock/cult/glass glass = TRUE - opacity = 0 + opacity = FALSE /obj/machinery/door/airlock/cult/glass/friendly friendly = TRUE @@ -537,7 +537,7 @@ /obj/machinery/door/airlock/cult/unruned/glass glass = TRUE - opacity = 0 + opacity = FALSE /obj/machinery/door/airlock/cult/unruned/glass/friendly friendly = TRUE @@ -586,7 +586,7 @@ . += gear_text /obj/machinery/door/airlock/clockwork/emp_act(severity) - if(prob(80/severity)) + if(prob(8 * severity)) open() /obj/machinery/door/airlock/clockwork/canAIControl(mob/user) @@ -664,7 +664,7 @@ /obj/machinery/door/airlock/clockwork/brass glass = TRUE - opacity = 0 + opacity = FALSE ////////////////////////////////// /* @@ -678,7 +678,7 @@ mask_file = 'icons/obj/doors/airlocks/mask_64x32_airlocks.dmi' mask_x = 16 // byond is consistent and sane anim_parts = "left=-21,0;right=21,0;top=0,29" - opacity = 0 + opacity = FALSE assemblytype = null glass = TRUE bound_width = 64 // 2x1 diff --git a/code/game/machinery/doors/alarmlock.dm b/code/game/machinery/doors/alarmlock.dm index 52940e6d0081..4b83bf63ed93 100644 --- a/code/game/machinery/doors/alarmlock.dm +++ b/code/game/machinery/doors/alarmlock.dm @@ -2,7 +2,7 @@ name = "glass alarm airlock" icon = 'icons/obj/doors/airlocks/station2/glass.dmi' overlays_file = 'icons/obj/doors/airlocks/station2/overlays.dmi' - opacity = 0 + opacity = FALSE assemblytype = /obj/structure/door_assembly/door_assembly_public glass = TRUE @@ -35,9 +35,9 @@ if(alarm_area == get_area_name(src)) switch(alert) - if("severe") + if(ATMOS_ALARM_SEVERE) autoclose = TRUE close() - if("minor", "clear") + if(ATMOS_ALARM_MINOR, ATMOS_ALARM_CLEAR) autoclose = FALSE - open() \ No newline at end of file + open() diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 20a82701e250..4d298a074a71 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -3,7 +3,7 @@ desc = "It opens and closes." icon = 'icons/obj/doors/Doorint.dmi' icon_state = "door1" - opacity = 1 + opacity = TRUE density = TRUE move_resist = MOVE_FORCE_VERY_STRONG layer = OPEN_DOOR_LAYER @@ -83,7 +83,7 @@ . = ..() set_init_door_layer() update_freelook_sight() - air_update_turf(1) + air_update_turf() GLOB.airlocks += src spark_system = new /datum/effect_system/spark_spread spark_system.set_up(2, 1, src) @@ -103,7 +103,7 @@ else layer = initial(layer) -/obj/machinery/door/Destroy() +/obj/machinery/door/Destroy(force=FALSE) update_freelook_sight() GLOB.airlocks -= src if(spark_system) @@ -263,9 +263,9 @@ var/max_moles = min_moles // okay this is a bit hacky. First, we set density to 0 and recalculate our adjacent turfs density = FALSE - T.ImmediateCalculateAdjacentTurfs() + var/list/adj_turfs = T.get_adjacent_atmos_turfs() // then we use those adjacent turfs to figure out what the difference between the lowest and highest pressures we'd be holding is - for(var/turf/open/T2 in T.atmos_adjacent_turfs) + for(var/turf/open/T2 in adj_turfs) if((flags_1 & ON_BORDER_1) && get_dir(src, T2) != dir) continue var/moles = T2.air.total_moles() @@ -274,7 +274,6 @@ if(moles > max_moles) max_moles = moles density = TRUE - T.ImmediateCalculateAdjacentTurfs() // alright lets put it back return max_moles - min_moles > 20 /obj/machinery/door/attackby(obj/item/I, mob/user, params) @@ -316,9 +315,9 @@ . = ..() if (. & EMP_PROTECT_SELF) return - if(prob(20/severity) && (istype(src, /obj/machinery/door/airlock) || istype(src, /obj/machinery/door/window)) ) + if(prob(2 * severity) && (istype(src, /obj/machinery/door/airlock) || istype(src, /obj/machinery/door/window)) ) INVOKE_ASYNC(src, PROC_REF(open)) - if(prob(severity*10 - 20)) + if(prob(severity*2 - 20)) if(secondsElectrified == MACHINE_NOT_ELECTRIFIED) secondsElectrified = MACHINE_ELECTRIFIED_PERMANENT LAZYADD(shockedby, "\[[time_stamp()]\]EM Pulse") @@ -366,7 +365,7 @@ update_appearance(UPDATE_ICON) set_opacity(0) operating = FALSE - air_update_turf(1) + air_update_turf() update_freelook_sight() if(autoclose) spawn(autoclose) @@ -398,7 +397,7 @@ if(visible && !glass) set_opacity(1) operating = FALSE - air_update_turf(1) + air_update_turf() update_freelook_sight() if(safe) CheckForMobs() @@ -454,8 +453,8 @@ if(!glass && GLOB.cameranet) GLOB.cameranet.updateVisibility(src, 0) -/obj/machinery/door/BlockSuperconductivity() // All non-glass airlocks block heat, this is intended. - if(opacity || heat_proof) +/obj/machinery/door/BlockThermalConductivity() // All non-glass airlocks block heat, this is intended. + if(heat_proof && density) return TRUE return FALSE diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 329686d9fea2..eb8f08bcdf05 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -70,10 +70,7 @@ /obj/machinery/door/firedoor/Destroy() remove_from_areas() affecting_areas.Cut() - var/turf/T = get_turf(src) - spawn(0) - if(T) - T.ImmediateCalculateAdjacentTurfs() + air_update_turf() return ..() /obj/machinery/door/firedoor/Bumped(atom/movable/AM) @@ -222,6 +219,7 @@ else icon_state = "door_open" SSdemo.mark_dirty(src) + air_update_turf() /obj/machinery/door/firedoor/update_overlays() . = ..() @@ -240,17 +238,15 @@ . = ..() latetoggle() -/obj/machinery/door/firedoor/proc/whack_a_mole(reconsider_immediately = FALSE) - set waitfor = 0 +/obj/machinery/door/firedoor/proc/whack_a_mole() for(var/cdir in GLOB.cardinals) if((flags_1 & ON_BORDER_1) && cdir != dir) continue - whack_a_mole_part(get_step(src, cdir), reconsider_immediately) + whack_a_mole_part(get_step(src, cdir)) if(flags_1 & ON_BORDER_1) - whack_a_mole_part(get_turf(src), reconsider_immediately) + whack_a_mole_part(get_turf(src)) -/obj/machinery/door/firedoor/proc/whack_a_mole_part(turf/start_point, reconsider_immediately) - set waitfor = 0 +/obj/machinery/door/firedoor/proc/whack_a_mole_part(turf/start_point) var/list/doors_to_close = list() var/list/turfs = list() turfs[start_point] = 1 @@ -283,17 +279,24 @@ return // too big, don't bother for(var/obj/machinery/door/firedoor/FD in doors_to_close) FD.emergency_pressure_stop(FALSE) - if(reconsider_immediately) - var/turf/open/T = FD.loc - if(istype(T)) - T.ImmediateCalculateAdjacentTurfs() /obj/machinery/door/firedoor/proc/emergency_pressure_stop(consider_timer = TRUE) - set waitfor = 0 if(density || operating || welded) return if(world.time >= emergency_close_timer || !consider_timer) - close() + emergency_pressure_close() + +//this is here to prevent sleeps from messing with decomp, by closing firedoors instantly +/obj/machinery/door/firedoor/proc/emergency_pressure_close() + density = TRUE + air_update_turf() + layer = closingLayer + update_icon() + if(visible && !glass) + set_opacity(1) + update_freelook_sight() + if(!(flags_1 & ON_BORDER_1)) + crush() /obj/machinery/door/firedoor/deconstruct(disassembled = TRUE) if(!(flags_1 & NODECONSTRUCT_1) && disassembled) @@ -330,6 +333,14 @@ return TRUE if(operating || welded) return + check_pulls() + . = ..() + +/obj/machinery/door/firedoor/border_only/emergency_pressure_close() + check_pulls() + . = ..() + +/obj/machinery/door/firedoor/border_only/proc/check_pulls() var/turf/T1 = get_turf(src) var/turf/T2 = get_step(T1, dir) for(var/mob/living/M in T1) @@ -347,7 +358,6 @@ to_chat(M, span_notice("You pull [M.pulling] through [src] right as it closes")) M.pulling.forceMove(T2) M.start_pulling(M2) - . = ..() /obj/machinery/door/firedoor/border_only/allow_hand_open(mob/user) var/area/A = get_area(src) @@ -401,6 +411,11 @@ else return TRUE +/obj/machinery/door/firedoor/border_only/BlockThermalConductivity(opp_dir) + if(opp_dir == dir) + return density + return FALSE + /obj/machinery/door/firedoor/heavy name = "heavy firelock" icon = 'icons/obj/doors/doorfire.dmi' diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index 8d5c39cf8c1e..58640614c6e9 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -22,7 +22,7 @@ /obj/machinery/door/poddoor/preopen icon_state = "open" density = FALSE - opacity = 0 + opacity = FALSE /obj/machinery/door/poddoor/ert name = "ERT Armory door" diff --git a/code/game/machinery/doors/shutters.dm b/code/game/machinery/doors/shutters.dm index d4f383e0b925..6f71f57d5759 100644 --- a/code/game/machinery/doors/shutters.dm +++ b/code/game/machinery/doors/shutters.dm @@ -11,7 +11,7 @@ /obj/machinery/door/poddoor/shutters/preopen icon_state = "open" density = FALSE - opacity = 0 + opacity = FALSE /obj/machinery/door/poddoor/shutters/window name = "windowed shutters" diff --git a/code/game/machinery/doors/unpowered.dm b/code/game/machinery/doors/unpowered.dm index 0f7fd4ec4da7..6e14893f9e8b 100644 --- a/code/game/machinery/doors/unpowered.dm +++ b/code/game/machinery/doors/unpowered.dm @@ -20,6 +20,6 @@ icon = 'icons/turf/shuttle.dmi' name = "door" icon_state = "door1" - opacity = 1 + opacity = TRUE density = TRUE explosion_block = 1 diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index edb6ef9f4a75..57f0db385dd8 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -12,7 +12,7 @@ armor = list(MELEE = 60, BULLET = -40, LASER = 50, ENERGY = 50, BOMB = 10, BIO = 100, RAD = 100, FIRE = 70, ACID = 100) visible = FALSE flags_1 = ON_BORDER_1 - opacity = 0 + opacity = FALSE CanAtmosPass = ATMOS_PASS_PROC interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN var/obj/item/electronics/airlock/electronics = null @@ -158,7 +158,7 @@ sleep(1 SECONDS) density = FALSE - air_update_turf(1) + air_update_turf() update_freelook_sight() if(operating == 1) //emag again @@ -180,7 +180,7 @@ icon_state = base_state density = TRUE - air_update_turf(1) + air_update_turf() update_freelook_sight() sleep(1 SECONDS) @@ -423,7 +423,7 @@ return ..() /obj/machinery/door/window/clockwork/emp_act(severity) - if(prob(80/severity)) + if(prob(8 * severity)) open() /obj/machinery/door/window/clockwork/ratvar_act() diff --git a/code/game/machinery/electrolyzer.dm b/code/game/machinery/electrolyzer.dm index a3b56108a132..1460a455aec0 100644 --- a/code/game/machinery/electrolyzer.dm +++ b/code/game/machinery/electrolyzer.dm @@ -63,7 +63,7 @@ if(panel_open) . += "electrolyzer-open" -/obj/machinery/electrolyzer/process(delta_time) +/obj/machinery/electrolyzer/process_atmos() if((stat & (BROKEN|MAINT)) && on) on = FALSE if(!on) @@ -76,8 +76,7 @@ update_appearance(UPDATE_ICON) return FALSE - var/turf/L = loc - if(!istype(L)) + if(!isopenturf(get_turf(src))) if(mode != ELECTROLYZER_MODE_STANDBY) mode = ELECTROLYZER_MODE_STANDBY update_appearance(UPDATE_ICON) @@ -92,24 +91,23 @@ if(mode == ELECTROLYZER_MODE_STANDBY) return - var/datum/gas_mixture/env = L.return_air() //get air from the turf + var/datum/gas_mixture/env = return_air() //get air from the turf var/datum/gas_mixture/removed = env.remove(0.1 * env.total_moles()) if(!removed) return var/proportion = 0 - if(removed.get_moles(/datum/gas/water_vapor)) - proportion = min(removed.get_moles(/datum/gas/water_vapor), (3 * delta_time * workingPower)) //Works to max 12 moles at a time. - removed.adjust_moles(/datum/gas/water_vapor, -proportion) - removed.adjust_moles(/datum/gas/oxygen, proportion / 2) - removed.adjust_moles(/datum/gas/hydrogen, proportion) - if(removed.get_moles(/datum/gas/hypernoblium)) - proportion = min(removed.get_moles(/datum/gas/hypernoblium), (delta_time * workingPower)) // up to 4 moles at a time - removed.adjust_moles(/datum/gas/hypernoblium, -proportion) - removed.adjust_moles(/datum/gas/antinoblium, proportion) + if(removed.get_moles(GAS_H2O)) + proportion = min(removed.get_moles(GAS_H2O), (3 * workingPower)) //Works to max 12 moles at a time. + removed.adjust_moles(GAS_H2O, -proportion) + removed.adjust_moles(GAS_O2, proportion / 2) + removed.adjust_moles(GAS_H2, proportion) + if(removed.get_moles(GAS_HYPERNOB)) + proportion = min(removed.get_moles(GAS_HYPERNOB), workingPower) // up to 4 moles at a time + removed.adjust_moles(GAS_HYPERNOB, -proportion) + removed.adjust_moles(GAS_ANTINOB, proportion) env.merge(removed) //put back the new gases in the turf - air_update_turf() var/working = TRUE @@ -205,7 +203,9 @@ usr.visible_message(span_notice("[usr] switches [on ? "on" : "off"] \the [src]."), span_notice("You switch [on ? "on" : "off"] \the [src].")) update_appearance(UPDATE_ICON) if (on) - START_PROCESSING(SSmachines, src) + SSair_machinery.start_processing_machine(src) + else + SSair_machinery.stop_processing_machine(src) . = TRUE if("eject") if(panel_open && cell) diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 6a4ca14b1339..99b5a4987ec9 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -30,10 +30,20 @@ light_range = 7 light_color = "#ff3232" + /// 1 = will auto detect fire, 0 = no auto var/detecting = 1 - var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone + /// 2 = complete, 1 = no wires, 0 = circuit gone + var/buildstage = 2 + /// Cooldown for next alarm trigger, so it doesnt spam much var/last_alarm = 0 + /// The area of the current fire alarm var/area/myarea = null + /// If true, then this area has a real fire and not by someone triggering it manually + var/real_fire = FALSE + /// If real_fire is true then it will show you the current hot temperature + var/bad_temp = null + /// The radio to alert engineers, atmos techs + var/obj/item/radio/radio /obj/machinery/firealarm/Initialize(mapload, dir, building) . = ..() @@ -47,8 +57,16 @@ update_appearance(UPDATE_ICON) myarea = get_area(src) LAZYADD(myarea.firealarms, src) + radio = new(src) + radio.keyslot = new /obj/item/encryptionkey/headset_eng() + radio.subspace_transmission = TRUE + radio.canhear_range = 0 + radio.recalculateChannels() + STOP_PROCESSING(SSmachines, src) // I will do this /obj/machinery/firealarm/Destroy() + myarea.firereset(src, TRUE) + QDEL_NULL(radio) LAZYREMOVE(myarea.firealarms, src) return ..() @@ -101,7 +119,7 @@ if (. & EMP_PROTECT_SELF) return - if(prob(50 / severity)) + if(prob(5 * severity)) alarm() /obj/machinery/firealarm/emag_act(mob/user, obj/item/card/emag/emag_card) @@ -115,18 +133,42 @@ playsound(src, "sparks", 50, 1) return TRUE +/obj/machinery/firealarm/examine(mob/user) + . = ..() + if(areafire_check()) + . += span_danger("Fire detected in this area, current fire alarm temperature: [bad_temp-T0C]C") + else + . += span_notice("There's no fire detected.") + /obj/machinery/firealarm/temperature_expose(datum/gas_mixture/air, temperature, volume) var/turf/open/T = get_turf(src) if((temperature >= FIRE_MINIMUM_TEMPERATURE_TO_EXIST || temperature < BODYTEMP_COLD_DAMAGE_LIMIT || (istype(T) && T.turf_fire)) && (last_alarm+FIREALARM_COOLDOWN < world.time) && !(obj_flags & EMAGGED) && detecting && !stat) + if(!real_fire) + radio.talk_into(src, "Fire detected in [myarea].", RADIO_CHANNEL_ENGINEERING) + real_fire = TRUE + bad_temp = temperature alarm() + START_PROCESSING(SSmachines, src) ..() +/obj/machinery/firealarm/process() //Fire alarm only start processing when its triggered by temperature_expose() + var/turf/open/T = get_turf(src) + var/datum/gas_mixture/env = T.return_air() + if(env.return_temperature() < FIRE_MINIMUM_TEMPERATURE_TO_EXIST && env.return_temperature() > BODYTEMP_COLD_DAMAGE_LIMIT && (istype(T) && !T.turf_fire)) + real_fire = FALSE + STOP_PROCESSING(SSmachines, src) + +/obj/machinery/firealarm/proc/areafire_check() + for(var/obj/machinery/firealarm/FA in myarea.firealarms) + if(FA.real_fire) + return TRUE + return FALSE + /obj/machinery/firealarm/proc/alarm(mob/user) if(!is_operational() || (last_alarm+FIREALARM_COOLDOWN > world.time)) return last_alarm = world.time - var/area/A = get_area(src) - A.firealert(src) + myarea.firealert(src) playsound(loc, 'goon/sound/machinery/FireAlarm.ogg', 75) if(user) log_game("[user] triggered a fire alarm at [COORD(src)]") @@ -134,8 +176,9 @@ /obj/machinery/firealarm/proc/reset(mob/user) if(!is_operational()) return - var/area/A = get_area(src) - A.firereset(src) + for(var/obj/machinery/firealarm/F in myarea.firealarms) + F.myarea.firereset(F) + F.bad_temp = null if(user) log_game("[user] reset a fire alarm at [COORD(src)]") @@ -144,8 +187,7 @@ return ..() add_fingerprint(user) play_click_sound("button") - var/area/A = get_area(src) - if(A.fire || A.party) + if(myarea.fire || myarea.party) reset(user) else alarm(user) @@ -201,8 +243,7 @@ else if(W.force) //hit and turn it on ..() - var/area/A = get_area(src) - if(!A.fire) + if(!myarea.fire) alarm() return @@ -295,6 +336,7 @@ . = ..() if(.) + myarea.firereset(src, TRUE) LAZYREMOVE(myarea.firealarms, src) /obj/machinery/firealarm/deconstruct(disassembled = TRUE) @@ -332,19 +374,17 @@ /obj/machinery/firealarm/partyalarm/reset() if (stat & (NOPOWER|BROKEN)) return - var/area/A = get_area(src) - if (!A || !A.party) + if (!myarea || !myarea.party) return - A.party = FALSE - A.cut_overlay(party_overlay) + myarea.party = FALSE + myarea.cut_overlay(party_overlay) /obj/machinery/firealarm/partyalarm/alarm() if (stat & (NOPOWER|BROKEN)) return - var/area/A = get_area(src) - if (!A || A.party || A.name == "Space") + if (!myarea || myarea.party || istype(myarea, /area/space)) return - A.party = TRUE + myarea.party = TRUE if (!party_overlay) party_overlay = iconstate2appearance('icons/turf/areas.dmi', "party") - A.add_overlay(party_overlay) + myarea.add_overlay(party_overlay) diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index 5b86b762ba09..fbb5417be5b5 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -141,7 +141,7 @@ /obj/machinery/flasher/emp_act(severity) . = ..() if(!(stat & (BROKEN|NOPOWER)) && !(. & EMP_PROTECT_SELF)) - if(bulb && prob(75/severity)) + if(bulb && prob(8 * severity)) flash() bulb.burn_out() power_change() diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm index 91742d81c00a..33c9676d86dc 100644 --- a/code/game/machinery/pipe/construction.dm +++ b/code/game/machinery/pipe/construction.dm @@ -64,10 +64,10 @@ Buildable meters /obj/item/pipe/dropped() if(loc) - setPipingLayer(piping_layer) + set_piping_layer(piping_layer) return ..() -/obj/item/pipe/proc/setPipingLayer(new_layer = PIPING_LAYER_DEFAULT) +/obj/item/pipe/proc/set_piping_layer(new_layer = PIPING_LAYER_DEFAULT) var/obj/machinery/atmospherics/fakeA = pipe_type if(initial(fakeA.pipe_flags) & PIPING_ALL_LAYER) @@ -139,7 +139,7 @@ Buildable meters return TRUE if((M.piping_layer != piping_layer) && !((M.pipe_flags | flags) & PIPING_ALL_LAYER)) //don't continue if either pipe goes across all layers continue - if(M.GetInitDirections() & SSair.get_init_dirs(pipe_type, fixed_dir())) // matches at least one direction on either type of pipe + if(M.get_init_directions() & SSair.get_init_dirs(pipe_type, fixed_dir())) // matches at least one direction on either type of pipe to_chat(user, span_warning("There is already a pipe at that location!")) return TRUE // no conflicts found @@ -159,7 +159,7 @@ Buildable meters /obj/item/pipe/proc/build_pipe(obj/machinery/atmospherics/A) A.setDir(fixed_dir()) - A.SetInitDirections() + A.set_init_directions() if(pipename) A.name = pipename diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm index 2fbde8399a12..4f3656c062b9 100644 --- a/code/game/machinery/pipe/pipe_dispenser.dm +++ b/code/game/machinery/pipe/pipe_dispenser.dm @@ -47,7 +47,7 @@ return var/p_dir = text2num(href_list["dir"]) var/obj/item/pipe/P = new (loc, p_type, p_dir) - P.setPipingLayer(piping_layer) + P.set_piping_layer(piping_layer) P.add_fingerprint(usr) wait = world.time + 10 if(href_list["makemeter"]) diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index a55f51e7e99d..f6015bb4142d 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -5,7 +5,7 @@ icon_state = "shield-old" density = TRUE move_resist = INFINITY - opacity = 0 + opacity = FALSE anchored = TRUE resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF max_integrity = 200 //The shield can only take so much beating (prevents perma-prisons) @@ -14,7 +14,7 @@ /obj/structure/emergency_shield/Initialize(mapload) . = ..() setDir(pick(GLOB.cardinals)) - air_update_turf(1) + air_update_turf() /obj/structure/emergency_shield/Move() var/turf/T = loc @@ -25,11 +25,10 @@ . = ..() if (. & EMP_PROTECT_SELF) return - switch(severity) - if(1) - qdel(src) - if(2) - take_damage(50, BRUTE, ENERGY, 0) + if(severity > EMP_LIGHT) + qdel(src) + return + take_damage(5 * severity, BRUTE, ENERGY, 0) /obj/structure/emergency_shield/play_attack_sound(damage, damage_type = BRUTE, damage_flag = 0) switch(damage_type) @@ -70,7 +69,7 @@ icon = 'icons/obj/objects.dmi' icon_state = "shieldoff" density = TRUE - opacity = 0 + opacity = FALSE anchored = FALSE pressure_resistance = 2*ONE_ATMOSPHERE req_access = list(ACCESS_ENGINE) diff --git a/code/game/machinery/shuttle/shuttle_engine.dm b/code/game/machinery/shuttle/shuttle_engine.dm index 73f146992974..4743665672fb 100644 --- a/code/game/machinery/shuttle/shuttle_engine.dm +++ b/code/game/machinery/shuttle/shuttle_engine.dm @@ -118,10 +118,11 @@ //Thanks to spaceheater.dm for inspiration :) /obj/machinery/shuttle/engine/proc/fireEngine() - var/turf/heatTurf = loc - if(!heatTurf) + if(!isopenturf(get_turf(src))) + return + var/datum/gas_mixture/env = return_air() + if(!env) return - var/datum/gas_mixture/env = heatTurf.return_air() var/heat_cap = env.heat_capacity() var/req_power = abs(env.return_temperature() - ENGINE_HEAT_TARGET) * heat_cap req_power = min(req_power, ENGINE_HEATING_POWER) @@ -129,7 +130,6 @@ if(deltaTemperature < 0) return env.set_temperature(env.return_temperature() + deltaTemperature) - air_update_turf() /obj/machinery/shuttle/engine/attackby(obj/item/I, mob/living/user, params) check_setup() diff --git a/code/game/machinery/shuttle/shuttle_heater.dm b/code/game/machinery/shuttle/shuttle_heater.dm index beb24acf2085..be8cb0542c9d 100644 --- a/code/game/machinery/shuttle/shuttle_heater.dm +++ b/code/game/machinery/shuttle/shuttle_heater.dm @@ -28,14 +28,14 @@ pipe_flags = PIPING_ONE_PER_TURF | PIPING_DEFAULT_LAYER_ONLY - var/gas_type = /datum/gas/plasma + var/gas_type = GAS_PLASMA var/efficiency_multiplier = 1 var/gas_capacity = 0 /obj/machinery/atmospherics/components/unary/shuttle/heater/New() . = ..() GLOB.custom_shuttle_machines += src - SetInitDirections() + set_init_directions() update_adjacent_engines() updateGasStats() @@ -46,27 +46,27 @@ /obj/machinery/atmospherics/components/unary/shuttle/heater/on_construction() ..(dir, dir) - SetInitDirections() + set_init_directions() update_adjacent_engines() /obj/machinery/atmospherics/components/unary/shuttle/heater/default_change_direction_wrench(mob/user, obj/item/I) if(!..()) return FALSE - SetInitDirections() + set_init_directions() var/obj/machinery/atmospherics/node = nodes[1] if(node) node.disconnect(src) nodes[1] = null if(!parents[1]) return - nullifyPipenet(parents[1]) + nullify_pipenet(parents[1]) - atmosinit() + atmos_init() node = nodes[1] if(node) - node.atmosinit() - node.addMember(src) - build_network() + node.atmos_init() + node.add_member(src) + SSair.add_to_rebuild_queue(src) return TRUE /obj/machinery/atmospherics/components/unary/shuttle/heater/RefreshParts() @@ -91,8 +91,6 @@ return air_contents.set_volume(gas_capacity) air_contents.set_temperature(T20C) - if(gas_type) - air_contents.set_moles(gas_type) /obj/machinery/atmospherics/components/unary/shuttle/heater/proc/hasFuel(required) var/datum/gas_mixture/air_contents = airs[1] @@ -230,7 +228,7 @@ /obj/machinery/power/engine_capacitor_bank/emp_act(severity) . = ..() - stored_power = rand(0, stored_power) + stored_power = stored_power * (0.9**(severity)) // exponential decay based on EMP severity, heavy EMPs (10 severity) reduce to 35% power /obj/machinery/power/engine_capacitor_bank/escape_pod name = "emergency thruster capacitor bank" diff --git a/code/game/machinery/slotmachine.dm b/code/game/machinery/slotmachine.dm index 536d61200dcb..8ff7540611dd 100644 --- a/code/game/machinery/slotmachine.dm +++ b/code/game/machinery/slotmachine.dm @@ -182,7 +182,7 @@ return if(prob(1)) // :^) obj_flags |= EMAGGED - var/severity_ascending = 4 - severity + var/severity_ascending = 2 + (severity / 5) money = max(rand(money - (200 * severity_ascending), money + (200 * severity_ascending)), 0) balance = max(rand(balance - (50 * severity_ascending), balance + (50 * severity_ascending)), 0) money -= max(0, give_payout(min(rand(-50, 100 * severity_ascending)), money)) //This starts at -50 because it shouldn't always dispense coins yo diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index 8b7946707bd0..90482de1d7e8 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -66,7 +66,7 @@ if(panel_open) . += "sheater-open" -/obj/machinery/space_heater/process(delta_time) +/obj/machinery/space_heater/process_atmos() if(!on || stat & (BROKEN|MAINT)) if (on) // If it's broken, turn it off too on = FALSE @@ -103,7 +103,7 @@ var/heat_capacity = env.heat_capacity() var/requiredEnergy = abs(env.return_temperature() - targetTemperature) * heat_capacity - requiredEnergy = min(requiredEnergy, heatingPower * delta_time) + requiredEnergy = min(requiredEnergy, heatingPower) if(requiredEnergy < 1) return @@ -115,7 +115,6 @@ for (var/turf/open/turf in ((L.atmos_adjacent_turfs || list()) + L)) var/datum/gas_mixture/turf_gasmix = turf.return_air() turf_gasmix.set_temperature(turf_gasmix.return_temperature() + deltaTemperature) - air_update_turf(FALSE, FALSE) var/working = TRUE @@ -213,13 +212,10 @@ data["minTemp"] = max(settableTemperatureMedian - settableTemperatureRange - T0C, TCMB) data["maxTemp"] = settableTemperatureMedian + settableTemperatureRange - T0C - var/turf/L = get_turf(loc) var/curTemp - if(istype(L)) - var/datum/gas_mixture/env = L.return_air() - curTemp = env.return_temperature() - else if(isturf(L)) - curTemp = L.return_temperature() + if(isopenturf(get_turf(src))) + var/datum/gas_mixture/env = return_air() + curTemp = env?.return_temperature() if(isnull(curTemp)) data["currentTemp"] = "N/A" else @@ -268,7 +264,9 @@ usr.visible_message("[usr] switches [on ? "on" : "off"] \the [src].", span_notice("You switch [on ? "on" : "off"] \the [src].")) update_appearance(UPDATE_ICON) if (on) - START_PROCESSING(SSmachines, src) + SSair_machinery.start_processing_machine(src) + else + SSair_machinery.stop_processing_machine(src) /obj/machinery/space_heater/AltClick(mob/user) if(!user.canUseTopic(src, !issilicon(user))) diff --git a/code/game/machinery/stasis.dm b/code/game/machinery/stasis.dm index 0b3068846a59..e610992476eb 100644 --- a/code/game/machinery/stasis.dm +++ b/code/game/machinery/stasis.dm @@ -3,6 +3,7 @@ desc = "A not so comfortable looking bed with some nozzles at the top and bottom. It will keep someone in stasis." icon = 'icons/obj/machines/stasis.dmi' icon_state = "stasis" + base_icon_state = "stasis" density = FALSE can_buckle = TRUE buckle_lying = 90 @@ -92,19 +93,20 @@ last_stasis_sound = _running /obj/machinery/stasis/AltClick(mob/user) - if(world.time >= stasis_can_toggle && user.canUseTopic(src, !issilicon(user))) - stasis_enabled = !stasis_enabled - stasis_can_toggle = world.time + stasis_cooldown - playsound(src, 'sound/machines/click.ogg', 60, TRUE) - play_power_sound() - update_appearance(UPDATE_ICON) + if(world.time < stasis_can_toggle || !user.canUseTopic(src, !issilicon(user))) + return + stasis_enabled = !stasis_enabled + stasis_can_toggle = world.time + stasis_cooldown + playsound(src, 'sound/machines/click.ogg', 60, TRUE) + play_power_sound() + update_appearance(UPDATE_ICON) /obj/machinery/stasis/Exited(atom/movable/AM, atom/newloc) if(AM == occupant) var/mob/living/L = AM if(L.has_status_effect(STATUS_EFFECT_STASIS)) thaw_them(L) - . = ..() + return ..() /obj/machinery/stasis/proc/stasis_running() return stasis_enabled && is_operational() @@ -112,30 +114,36 @@ /obj/machinery/stasis/update_icon_state() . = ..() if(stat & BROKEN) - icon_state = "stasis_broken" + icon_state = "[base_icon_state]_broken" return if(panel_open || stat & MAINT) - icon_state = "stasis_maintenance" + icon_state = "[base_icon_state]_maintenance" return - icon_state = "stasis" + icon_state = base_icon_state + +/obj/machinery/stasis/setDir() + . = ..() + update_appearance(UPDATE_ICON) /obj/machinery/stasis/update_overlays() . = ..() + if(!mattress_state) + return var/_running = stasis_running() - var/list/overlays_to_remove = managed_vis_overlays - - if(mattress_state) - if(!mattress_on || !managed_vis_overlays) - mattress_on = SSvis_overlays.add_vis_overlay(src, icon, mattress_state, layer, plane, dir, alpha = 0, unique = TRUE) - - if(mattress_on.alpha ? !_running : _running) //check the inverse of _running compared to truthy alpha, to see if they differ - var/new_alpha = _running ? 255 : 0 - var/easing_direction = _running ? EASE_OUT : EASE_IN - animate(mattress_on, alpha = new_alpha, time = stasis_cooldown, easing = CUBIC_EASING|easing_direction) - - overlays_to_remove = managed_vis_overlays - mattress_on + if(!mattress_on) + mattress_on = SSvis_overlays.add_vis_overlay(src, icon, mattress_state, layer, plane, dir, alpha = 0, unique = TRUE) + else + vis_contents += mattress_on + mattress_on.dir = dir + if(managed_vis_overlays) + managed_vis_overlays += mattress_on + else + managed_vis_overlays = list(mattress_on) - SSvis_overlays.remove_vis_overlay(src, overlays_to_remove) + if(mattress_on.alpha ? !_running : _running) //check the inverse of _running compared to truthy alpha, to see if they differ + var/new_alpha = _running ? 255 : 0 + var/easing_direction = _running ? EASE_OUT : EASE_IN + animate(mattress_on, alpha = new_alpha, time = 50, easing = CUBIC_EASING|easing_direction) /obj/machinery/stasis/obj_break(damage_flag) . = ..() diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index 3799c63845e7..3bd5a4d73720 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -502,16 +502,15 @@ /obj/item/bombcore/emp name = "EMP payload" desc = "A set of superconducting electromagnetic coils designed to release a powerful pulse to destroy electronics and scramble circuits" - range_heavy = 15 - range_medium = 25 + range_heavy = 25 // 25 severity, can do some serious damage /obj/item/bombcore/emp/detonate() if(adminlog) message_admins(adminlog) log_game(adminlog) - empulse(src, range_heavy, range_medium) - + empulse(src, range_heavy) + qdel(src) ///Syndicate Detonator (aka the big red button)/// diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index 6bf5c01110be..2d536cadb7f6 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -153,10 +153,9 @@ GLOBAL_LIST_EMPTY(telecomms_list) /obj/machinery/telecomms/proc/update_speed() if(!on) return - var/turf/T = get_turf(src) //yogs var/speedloss = 0 - var/datum/gas_mixture/env = T.return_air() - var/temperature = env.return_temperature() + var/datum/gas_mixture/env = return_air() + var/temperature = env?.return_temperature() if(temperature <= 150) // 150K optimal operating parameters net_efective = 100 else @@ -191,9 +190,9 @@ GLOBAL_LIST_EMPTY(telecomms_list) . = ..() if(. & EMP_PROTECT_SELF) return - if(prob(100/severity) && !(stat & EMPED)) + if(prob(10 * severity) && !(stat & EMPED)) stat |= EMPED - var/duration = (300 * 10)/severity + var/duration = (30 SECONDS) * severity // 30 seconds per level of severity, 5 minutes at 10 severity (EMP_HEAVY) addtimer(CALLBACK(src, PROC_REF(de_emp)), rand(duration - 20, duration + 20)) /obj/machinery/telecomms/proc/de_emp() diff --git a/code/game/mecha/combat/reticence.dm b/code/game/mecha/combat/reticence.dm index 7237237ccc6a..9a324986eae5 100644 --- a/code/game/mecha/combat/reticence.dm +++ b/code/game/mecha/combat/reticence.dm @@ -18,7 +18,7 @@ stepsound = null turnsound = null meleesound = FALSE - opacity = 0 + opacity = FALSE /obj/mecha/combat/reticence/Initialize(mapload) . = ..() diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm index 6aad0746d6dc..2fe788ba5dd0 100644 --- a/code/game/mecha/equipment/tools/work_tools.dm +++ b/code/game/mecha/equipment/tools/work_tools.dm @@ -190,54 +190,42 @@ equip_cooldown = 5 energy_drain = 0 range = MECHA_MELEE|MECHA_RANGED + var/chem_amount = 2 /obj/item/mecha_parts/mecha_equipment/extinguisher/Initialize(mapload) . = ..() create_reagents(1000) - reagents.add_reagent(/datum/reagent/water, 1000) + reagents.add_reagent(/datum/reagent/firefighting_foam, 1000) /obj/item/mecha_parts/mecha_equipment/extinguisher/action(atom/target) //copypasted from extinguisher. TODO: Rewrite from scratch. - if(!action_checks(target) || get_dist(chassis, target)>3) + if(!action_checks(target)) return - if(istype(target, /obj/structure/reagent_dispensers/watertank) && get_dist(chassis,target) <= 1) - var/obj/structure/reagent_dispensers/watertank/WT = target + if(istype(target, /obj/structure/reagent_dispensers/foamtank) && get_dist(chassis,target) <= 1) + var/obj/structure/reagent_dispensers/WT = target WT.reagents.trans_to(src, 1000) occupant_message(span_notice("Extinguisher refilled.")) playsound(chassis, 'sound/effects/refill.ogg', 50, 1, -6) - else - if(reagents.total_volume > 0) - playsound(chassis, 'sound/effects/extinguish.ogg', 75, 1, -3) - var/direction = get_dir(chassis,target) - var/turf/T = get_turf(target) - var/turf/T1 = get_step(T,turn(direction, 90)) - var/turf/T2 = get_step(T,turn(direction, -90)) - - var/list/the_targets = list(T,T1,T2) - spawn(0) - for(var/a=0, a<5, a++) - var/obj/effect/particle_effect/water/W = new /obj/effect/particle_effect/water(get_turf(chassis)) - if(!W) - return - var/turf/my_target = pick(the_targets) - var/datum/reagents/R = new/datum/reagents(5) - W.reagents = R - R.my_atom = W - reagents.trans_to(W,1, transfered_by = chassis.occupant) - for(var/b=0, b<4, b++) - if(!W) - return - step_towards(W,my_target) - if(!W) - return - var/turf/W_turf = get_turf(W) - W.reagents.reaction(W_turf) - for(var/atom/atm in W_turf) - W.reagents.reaction(atm) - if(W.loc == my_target) - break - sleep(0.2 SECONDS) + else if(reagents.total_volume >= 1) + playsound(chassis, 'sound/effects/extinguish.ogg', 75, 1, -3) + + //Get all the turfs that can be shot at + var/direction = get_dir(chassis,target) + var/turf/T = get_turf(target) + var/turf/T1 = get_step(T,turn(direction, 90)) + var/turf/T2 = get_step(T,turn(direction, -90)) + var/turf/T3 = get_step(T1, turn(direction, 90)) + var/turf/T4 = get_step(T2,turn(direction, -90)) + var/list/the_targets = list(T,T1,T2,T3,T4) + + for(var/a=0, a<5, a++) + var/my_target = pick(the_targets) + var/obj/effect/particle_effect/water/W = new /obj/effect/particle_effect/water(get_turf(src), my_target) + reagents.trans_to(W, chem_amount, transfered_by = chassis.occupant) + the_targets -= my_target return 1 + else + occupant_message(span_warning("[src] is empty!")) /obj/item/mecha_parts/mecha_equipment/extinguisher/get_equip_info() return "[..()] \[[src.reagents.total_volume]\]" diff --git a/code/game/mecha/equipment/weapons/melee_weapons.dm b/code/game/mecha/equipment/weapons/melee_weapons.dm index 7367f0f0f669..51a45519af5e 100644 --- a/code/game/mecha/equipment/weapons/melee_weapons.dm +++ b/code/game/mecha/equipment/weapons/melee_weapons.dm @@ -273,7 +273,7 @@ set_light_on(FALSE) /obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/katana //Anime mech sword - name = "\improper OWM-5 \"Ronin\" katana" + name = "\improper HR-2 \"Ronin\" katana" desc = "An oversized, light-weight replica of an ancient style of blade. Still woefully underpowered in D&D." icon_state = "mecha_katana" energy_drain = 15 @@ -363,7 +363,7 @@ playsound(L, 'sound/items/welder.ogg', 50, 1) /obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/maul - name = "\improper CX-22 \"Barbatos\" heavy maul" + name = "\improper ASW-8 \"Barbatos\" heavy maul" desc = "A massive, unwieldy, mace-like weapon, this thing really looks like something you don't want to be hit by if you're not a fan of being concave." icon_state = "mecha_maul" energy_drain = 40 @@ -385,7 +385,7 @@ do_item_attack_animation(L, hit_effect) /obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/rapier - name = "\improper E9-V \"Sigrun\" rapier" + name = "\improper MS-15 \"Gyan\" rapier" desc = "A remarkably thin blade for a weapon wielded by an exosuit, this rapier is the favorite of syndicate pilots that perfer finesse over brute force." icon_state = "mecha_rapier" energy_drain = 40 @@ -459,7 +459,7 @@ /obj/item/mecha_parts/mecha_equipment/melee_weapon/rocket_fist //Passive upgrade weapon when selected, makes your mech punch harder AND faster - name = "\improper DD-2 \"Atom Smasher\" rocket fist" + name = "\improper RS-77 \"Atom Smasher\" rocket fist" desc = "A large metal fist fitted to the arm of an exosuit, it uses repurposed maneuvering thrusters from a Raven battlecruiser to give a little more oomph to every punch. Also helps increase the speed at which the mech is able to return to a ready stance after each swing." icon_state = "mecha_rocket_fist" weapon_damage = 20 diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 23e2e5bea55e..324601c5c654 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -18,7 +18,7 @@ desc = "Exosuit" icon = 'icons/mecha/mecha.dmi' density = TRUE //Dense. To raise the heat. - opacity = 1 ///opaque. Menacing. + opacity = TRUE ///opaque. Menacing. move_resist = MOVE_FORCE_EXTREMELY_STRONG //no pulling around. resistance_flags = FIRE_PROOF | ACID_PROOF layer = BELOW_MOB_LAYER//icon draw layer @@ -213,11 +213,7 @@ scanmod = null capacitor = null internal_tank = null - if(loc) - loc.assume_air(cabin_air) - air_update_turf() - else - qdel(cabin_air) + assume_air(cabin_air) cabin_air = null qdel(spark_system) spark_system = null @@ -276,8 +272,8 @@ cabin_air = new cabin_air.set_temperature(T20C) cabin_air.set_volume(200) - cabin_air.set_moles(/datum/gas/oxygen, O2STANDARD*cabin_air.return_volume()/(R_IDEAL_GAS_EQUATION*cabin_air.return_temperature())) - cabin_air.set_moles(/datum/gas/nitrogen, N2STANDARD*cabin_air.return_volume()/(R_IDEAL_GAS_EQUATION*cabin_air.return_temperature())) + cabin_air.set_moles(GAS_O2, O2STANDARD*cabin_air.return_volume()/(R_IDEAL_GAS_EQUATION*cabin_air.return_temperature())) + cabin_air.set_moles(GAS_N2, N2STANDARD*cabin_air.return_volume()/(R_IDEAL_GAS_EQUATION*cabin_air.return_temperature())) return cabin_air /obj/mecha/proc/add_radio() @@ -295,6 +291,11 @@ return TRUE return FALSE +/obj/mecha/CanAllowThrough(atom/movable/mover, turf/target) + . = ..() // if something can go through machines it can go through mechs + if(istype(mover) && (mover.pass_flags & PASSMECH)) + return TRUE + //////////////////////////////////////////////////////////////////////////////// /obj/mecha/examine(mob/user) @@ -336,50 +337,8 @@ //Armor tag /obj/mecha/Topic(href, href_list) . = ..() - if(href_list["list_armor"]) - var/list/readout = list("PROTECTION CLASSES") - if(armor.bio || armor.bomb || armor.bullet || armor.energy || armor.laser || armor.melee) - readout += "\nARMOR (I-X)" - if(armor.bio) - readout += "\nBIO [armor_to_protection_class(armor.bio)]" - if(armor.bomb) - readout += "\nEXPLOSIVE [armor_to_protection_class(armor.bomb)]" - if(armor.bullet) - readout += "\nBULLET [armor_to_protection_class(armor.bullet)]" - if(armor.energy) - readout += "\nENERGY [armor_to_protection_class(armor.energy)]" - if(armor.laser) - readout += "\nLASER [armor_to_protection_class(armor.laser)]" - if(armor.melee) - readout += "\nMELEE [armor_to_protection_class(armor.melee)]" - if(armor.fire || armor.acid || deflect_chance || max_temperature) - readout += "\nDURABILITY (I-X)" - if(armor.fire) - readout += "\nFIRE [armor_to_protection_class(armor.fire)]" - if(armor.acid) - readout += "\nACID [armor_to_protection_class(armor.acid)]" - if(deflect_chance) - readout += "\nDEFLECT CHANCE: [deflect_chance]%" - if(max_temperature) - readout += "\nMAX TEMPERATURE: [max_temperature] KELVIN" - - readout += "" - - to_chat(usr, "[readout.Join()]") - -/** - * Rounds armor_value down to the nearest 10, divides it by 10 and then converts it to Roman numerals. - * - * Arguments: - * * armor_value - Number we're converting - */ -/obj/mecha/proc/armor_to_protection_class(armor_value) - if (armor_value < 0) - . = "-" - . += "\Roman[round(abs(armor_value), 10) / 10]" - return . - + to_chat(usr, "[armor.show_protection_classes()]") //processing internal damage, temperature, air regulation, alert updates, lights power use. /obj/mecha/process() @@ -405,13 +364,7 @@ if(internal_damage & MECHA_INT_TANK_BREACH) //remove some air from internal tank if(internal_tank) - var/datum/gas_mixture/int_tank_air = internal_tank.return_air() - var/datum/gas_mixture/leaked_gas = int_tank_air.remove_ratio(0.1) - if(loc) - loc.assume_air(leaked_gas) - air_update_turf() - else - qdel(leaked_gas) + assume_air_ratio(internal_tank.return_air(), 0.1) if(internal_damage & MECHA_INT_SHORT_CIRCUIT) if(get_charge()) @@ -434,8 +387,7 @@ if(pressure_delta > 0) //cabin pressure lower than release pressure if(tank_air.return_temperature() > 0) transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) - var/datum/gas_mixture/removed = tank_air.remove(transfer_moles) - cabin_air.merge(removed) + tank_air.transfer_to(cabin_air,transfer_moles) else if(pressure_delta < 0) //cabin pressure higher than release pressure var/datum/gas_mixture/t_air = return_air() pressure_delta = cabin_pressure - release_pressure @@ -443,11 +395,7 @@ pressure_delta = min(cabin_pressure - t_air.return_pressure(), pressure_delta) if(pressure_delta > 0) //if location pressure is lower than cabin pressure transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) - var/datum/gas_mixture/removed = cabin_air.remove(transfer_moles) - if(t_air) - t_air.merge(removed) - else //just delete the cabin gas, we're in space or some shit - qdel(removed) + cabin_air.transfer_to(t_air, transfer_moles) if(occupant) if(cell) @@ -954,6 +902,11 @@ return cabin_air.remove(amount) return ..() +/obj/mecha/remove_air_ratio(ratio) + if(use_internal_tank) + return cabin_air.remove_ratio(ratio) + return ..() + /obj/mecha/return_air() if(use_internal_tank) return cabin_air diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm index 4762da6c0e5e..a2e3d2f9084b 100644 --- a/code/game/mecha/mecha_defense.dm +++ b/code/game/mecha/mecha_defense.dm @@ -161,8 +161,8 @@ if (. & EMP_PROTECT_SELF) return if(get_charge()) - use_power((cell.charge/3)/(severity*2)) - take_damage(40 / severity, BURN, ENERGY, 1) + use_power((cell.charge * severity / 15)) + take_damage(4 * severity, BURN, ENERGY, 1) log_message("EMP detected", LOG_MECHA, color="red") if(istype(src, /obj/mecha/combat)) diff --git a/code/game/mecha/mecha_wreckage.dm b/code/game/mecha/mecha_wreckage.dm index 0043fb3e4e6d..034d32ab341c 100644 --- a/code/game/mecha/mecha_wreckage.dm +++ b/code/game/mecha/mecha_wreckage.dm @@ -9,7 +9,7 @@ icon = 'icons/mecha/mecha.dmi' density = TRUE anchored = FALSE - opacity = 0 + opacity = FALSE var/state = MECHA_WRECK_CUT var/orig_mecha var/can_be_reconstructed = FALSE diff --git a/code/game/movable_luminosity.dm b/code/game/movable_luminosity.dm index 7a6eaddafd9e..c3bf5ed2525d 100644 --- a/code/game/movable_luminosity.dm +++ b/code/game/movable_luminosity.dm @@ -11,7 +11,6 @@ affecting_dynamic_lumi = highest luminosity += affecting_dynamic_lumi - ///Helper to change several lighting overlay settings. /atom/movable/proc/set_light_range_power_color(range, power, color) set_light_range(range) diff --git a/code/game/objects/effects/alien_acid.dm b/code/game/objects/effects/alien_acid.dm index 18974a9a01aa..6d0ae81b5082 100644 --- a/code/game/objects/effects/alien_acid.dm +++ b/code/game/objects/effects/alien_acid.dm @@ -4,7 +4,7 @@ desc = "Burbling corrosive stuff." icon_state = "acid" density = FALSE - opacity = 0 + opacity = FALSE anchored = TRUE resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF layer = ABOVE_NORMAL_TURF_LAYER diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm index cffa965457d7..1aa541aa1b7e 100644 --- a/code/game/objects/effects/anomalies.dm +++ b/code/game/objects/effects/anomalies.dm @@ -191,23 +191,9 @@ /obj/effect/anomaly/flux/proc/mobShock(mob/living/M) if(canshock && istype(M)) - canshock = 0 //Just so you don't instakill yourself if you slam into the anomaly five times in a second. - if(iscarbon(M)) - var/siemens_coeff = 1 - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.gloves) - siemens_coeff *= (H.gloves.siemens_coefficient + 1) / 2 // protective gloves reduce damage by half - if(H.wear_suit) - siemens_coeff *= (H.wear_suit.siemens_coefficient + 1) / 2 // protective suit reduces damage by another half, minimum of 33% - var/should_stun = !M.IsParalyzed() // stunlock is boring - M.electrocute_act(shockdamage, "[name]", max(siemens_coeff, 0.33), safety = TRUE, stun = should_stun) // 15 damage with insuls, 10 damage with insuls and hardsuit - return - else - M.adjustFireLoss(shockdamage) - M.visible_message(span_danger("[M] was shocked by \the [name]!"), \ - span_userdanger("You feel a powerful shock coursing through your body!"), \ - span_italics("You hear a heavy electrical crack.")) + var/should_stun = !M.IsParalyzed() // stunlock is boring + var/hit_percent = (100 - M.getarmor(null, ELECTRIC)) / 100 + M.electrocute_act(shockdamage, "[name]", max(hit_percent, 0.33), zone = null, override=TRUE, stun = should_stun) // ignore armor because we're doing our own calculations /obj/effect/anomaly/flux/detonate() switch(explosive) @@ -439,8 +425,21 @@ core_type = ANOMALY_HALLUCINATION /// Time passed since the last effect, increased by delta_time of the SSobj var/ticks = 0 - /// How many seconds between each small hallucination pulses + /// How many seconds between each hallucination spanwed var/release_delay = 5 + /// flavor of hallucination mobs this spawns (cosmetic) + var/hallucination_set + +/obj/effect/anomaly/hallucination/Initialize(mapload, new_lifespan) + . = ..() + hallucination_set = pick("syndicate", "cult") + switch(hallucination_set) + if("syndicate") + icon = 'icons/mob/simple_human.dmi' + icon_state = "syndicate_stormtrooper_sword" + if("cult") + icon = 'icons/mob/nonhuman-player/cult.dmi' + icon_state = "cultist" /obj/effect/anomaly/hallucination/anomalyEffect(delta_time) . = ..() @@ -450,37 +449,82 @@ ticks -= release_delay var/turf/open/our_turf = get_turf(src) if(istype(our_turf)) - hallucination_pulse(our_turf, 5) + var/mob/living/simple_animal/hostile/newhall = new /mob/living/simple_animal/hostile/hallucination(our_turf) + switch(hallucination_set) + if("syndicate") + newhall.name = "syndicate operative" + newhall.icon = 'icons/mob/simple_human.dmi' + newhall.icon_state = "syndicate_space_knife" + newhall.attacktext = "slashes" + newhall.attack_sound = 'sound/weapons/bladeslice.ogg' + if("cult") + newhall.name = "shade" + newhall.icon = 'icons/mob/nonhuman-player/cult.dmi' + newhall.icon_state = "shade_cult" + newhall.attacktext = "metaphysically strikes" /obj/effect/anomaly/hallucination/detonate() - var/turf/open/our_turf = get_turf(src) - if(istype(our_turf)) - hallucination_pulse(our_turf, 10) - -/proc/hallucination_pulse(turf/location, range, strength = 50) - for(var/mob/living/carbon/human/near in view(location, range)) - // If they are immune to hallucinations - if (HAS_TRAIT(near, TRAIT_MESONS) || (near.mind && HAS_TRAIT(near.mind, TRAIT_MESONS))) - continue + var/mob/living/simple_animal/hostile/hallucination/anomaly/bighall = new(get_turf(src)) + bighall.icon = icon + bighall.icon_state = icon_state + switch(hallucination_set) + if("syndicate") + bighall.attacktext = "slashes" + bighall.attack_sound = 'sound/weapons/bladeslice.ogg' + if("cult") + bighall.attacktext = "slashes" + bighall.attack_sound = 'sound/weapons/blade1.ogg' + +// Hallucination anomaly spawned mob, attacks deal stamina damage, if it stamcrits someone, they start hallucinating themself dying. +/mob/living/simple_animal/hostile/hallucination + name = "Unknown" + desc = "Whoever they are, they look angry, and hard to look at." + maxHealth = 25 + health = 25 + melee_damage_lower = 15 + melee_damage_upper = 10 + stat_attack = UNCONSCIOUS + robust_searching = TRUE + icon = 'icons/mob/simple_human.dmi' + icon_state = "faceless" + obj_damage = 0 + digitalinvis = TRUE //silicons can't hallucinate, as they are robots. they also can't take stamina damage. + melee_damage_type = STAMINA + damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 1, STAMINA = 0, OXY = 0) + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + minbodytemp = 0 + maxbodytemp = INFINITY + del_on_death = TRUE + footstep_type = FOOTSTEP_MOB_SHOE + +/mob/living/simple_animal/hostile/hallucination/anomaly + name = "hallucination anomaly" + desc = "A mysterious anomaly, seen commonly only in the region of space that the station orbits..." + maxHealth = 50 + health = 50 + melee_damage_lower = 30 + melee_damage_upper = 30 - // Blind people don't get hallucinations - if (is_blind(near)) - continue +/mob/living/simple_animal/hostile/hallucination/CanAttack(atom/the_target) + . = ..() + if(!iscarbon(the_target)) + return FALSE - // Everyone else - var/dist = sqrt(1 / max(1, get_dist(near, location))) - near.adjust_hallucinations(max(150, strength * dist)) - near.adjust_jitter(10 SECONDS) - near.adjust_confusion(10 SECONDS) - near.adjust_dizzy(10 SECONDS) - near.adjust_drowsiness(10 SECONDS) - var/static/list/messages = list( - "You feel your conscious mind fall apart!", - "Reality warps around you!", - "Something's whispering around you!", - "You are going insane!", - "What was that?!" - ) - to_chat(near, span_warning("[pick(messages)]")) +/mob/living/simple_animal/hostile/hallucination/AttackingTarget() + . = ..() + if(. && isliving(target)) + var/mob/living/carbon/C = target + C.clear_stamina_regen() + if(C.getStaminaLoss() >= 100) //congrats you have hallucinated being stabbed now you are hallucinating dying + if(!C.losebreath) + to_chat(C, span_notice("You feel your heart slow down...")) + C.losebreath = min(C.losebreath+2, 10) + C.silent = min(C.silent+2, 10) + if(C.getOxyLoss() >= 100) //let's skip the waiting and get to the fun part + if(C.can_heartattack()) + C.playsound_local(C, 'sound/effects/singlebeat.ogg', 100, 0) + C.set_heartattack(TRUE) + else + C.adjustBruteLoss(10) #undef ANOMALY_MOVECHANCE diff --git a/code/game/objects/effects/bump_teleporter.dm b/code/game/objects/effects/bump_teleporter.dm index 36320f29133b..426a4a37064e 100644 --- a/code/game/objects/effects/bump_teleporter.dm +++ b/code/game/objects/effects/bump_teleporter.dm @@ -7,7 +7,7 @@ invisibility = INVISIBILITY_ABSTRACT //nope, can't see this anchored = TRUE density = TRUE - opacity = 0 + opacity = FALSE var/static/list/AllTeleporters diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index fab5e473e4c1..b3260fd51c58 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -233,3 +233,12 @@ /obj/effect/decal/cleanable/insectguts/Destroy(force) GLOB.vomit_spots -= src . = ..() + +/obj/effect/decal/cleanable/dirt_siding + name = "dirt siding" + icon = 'icons/turf/decals.dmi' + icon_state = "dirt_side" + +/obj/effect/decal/cleanable/dirt_siding/corner + name = "dirt corner" + icon_state = "dirt_side_corner" \ No newline at end of file diff --git a/code/game/objects/effects/decals/turfdecal/markings.dm b/code/game/objects/effects/decals/turfdecal/markings.dm index f7787772e6ba..552dbfa621fb 100644 --- a/code/game/objects/effects/decals/turfdecal/markings.dm +++ b/code/game/objects/effects/decals/turfdecal/markings.dm @@ -249,7 +249,7 @@ /obj/effect/turf_decal/siding/wood icon_state = "siding_wood_line" - color = "#55391A" + color = "#5d341f" /obj/effect/turf_decal/siding/wood/corner icon_state = "siding_wood_corner" @@ -257,6 +257,15 @@ /obj/effect/turf_decal/siding/wood/end icon_state = "siding_wood_end" +/obj/effect/turf_decal/siding/wood/thin + icon_state = "siding_wood_line_thin" + +/obj/effect/turf_decal/siding/wood/corner/thin + icon_state = "siding_wood_corner_thin" + +/obj/effect/turf_decal/siding/wood/end/thin + icon_state = "siding_wood_end_thin" + /obj/effect/turf_decal/siding/thinplating icon_state = "siding_thinplating_line" color = "#aaaaaa" diff --git a/code/game/objects/effects/effect_system/effect_system.dm b/code/game/objects/effects/effect_system/effect_system.dm index 35ba7c6f9c44..3839457dc634 100644 --- a/code/game/objects/effects/effect_system/effect_system.dm +++ b/code/game/objects/effects/effect_system/effect_system.dm @@ -25,7 +25,7 @@ would spawn and follow the beaker, even if it is carried or thrown. /datum/effect_system var/number = 3 - var/cardinals = FALSE + var/cardinals_only = FALSE var/turf/location var/atom/holder var/effect_type @@ -39,7 +39,7 @@ would spawn and follow the beaker, even if it is carried or thrown. /datum/effect_system/proc/set_up(number = 3, cardinals_only = FALSE, location) src.number = min(number, 10) - src.cardinals = cardinals_only + src.cardinals_only = cardinals_only src.location = get_turf(location) /datum/effect_system/proc/attach(atom/atom) @@ -59,7 +59,7 @@ would spawn and follow the beaker, even if it is carried or thrown. var/obj/effect/E = new effect_type(location) total_effects++ var/direction - if(cardinals) + if(cardinals_only) direction = pick(GLOB.cardinals) else direction = pick(GLOB.alldirs) diff --git a/code/game/objects/effects/effect_system/effects_explosion.dm b/code/game/objects/effects/effect_system/effects_explosion.dm index f264fa3a618b..e436ca851fbc 100644 --- a/code/game/objects/effects/effect_system/effects_explosion.dm +++ b/code/game/objects/effects/effect_system/effects_explosion.dm @@ -1,7 +1,7 @@ /obj/effect/particle_effect/expl_particles name = "fire" icon_state = "explosion_particle" - opacity = 1 + opacity = TRUE anchored = TRUE /obj/effect/particle_effect/expl_particles/Initialize(mapload) //yogs start: reverts harddel stuff so it doesn't break horribly @@ -23,7 +23,7 @@ name = "fire" icon = 'icons/effects/96x96.dmi' icon_state = "explosion" - opacity = 1 + opacity = TRUE anchored = TRUE mouse_opacity = MOUSE_OPACITY_TRANSPARENT pixel_x = -32 diff --git a/code/game/objects/effects/effect_system/effects_sparks.dm b/code/game/objects/effects/effect_system/effects_sparks.dm index 9efda705f3f0..ceaeb77375ff 100644 --- a/code/game/objects/effects/effect_system/effects_sparks.dm +++ b/code/game/objects/effects/effect_system/effects_sparks.dm @@ -5,13 +5,9 @@ // will always spawn at the items location. ///////////////////////////////////////////// -/proc/do_sparks(n, c, source) - // n - number of sparks - // c - cardinals, bool, do the sparks only move in cardinal directions? - // source - source of the sparks. - +/proc/do_sparks(number, cardinal_only, datum/source) var/datum/effect_system/spark_spread/sparks = new - sparks.set_up(n, c, source) + sparks.set_up(number, cardinal_only, source) sparks.autocleanup = TRUE sparks.start() @@ -24,7 +20,6 @@ light_range = 2 light_power = 0.5 light_color = LIGHT_COLOR_FIRE - light_flags = LIGHT_NO_LUMCOUNT var/duration = 2 SECONDS var/volume = 100 var/sound = "sparks" diff --git a/code/game/objects/effects/effect_system/effects_water.dm b/code/game/objects/effects/effect_system/effects_water.dm index 1899d0372fdf..ac4c7ff9e1a4 100644 --- a/code/game/objects/effects/effect_system/effects_water.dm +++ b/code/game/objects/effects/effect_system/effects_water.dm @@ -3,18 +3,48 @@ /obj/effect/particle_effect/water name = "water" icon_state = "extinguish" - pass_flags = PASSTABLE | PASSMACHINES | PASSCOMPUTER | PASSSTRUCTURE | PASSGRILLE | PASSBLOB + pass_flags = PASSTABLE | PASSMACHINES | PASSCOMPUTER | PASSSTRUCTURE | PASSGRILLE | PASSBLOB | PASSMECH | PASSMOB var/life = 15 mouse_opacity = MOUSE_OPACITY_TRANSPARENT + var/turf/target_turf + var/transfer_methods = TOUCH + +/obj/effect/particle_effect/water/New(loc, turf/target, methods, ...) + if(!isnull(target)) + target_turf = target + if(!isnull(methods)) + transfer_methods = methods + return ..() /obj/effect/particle_effect/water/Initialize(mapload) . = ..() + create_reagents(5) QDEL_IN(src, 70) + if(target_turf) + addtimer(CALLBACK(src, PROC_REF(move_particle)), 2) + +/obj/effect/particle_effect/water/proc/move_particle() + if(!target_turf) + return + var/starting_loc = loc + step_towards(src, target_turf) + if(starting_loc == loc) + if(reagents) // react again if it got stuck + reagents.reaction(loc, transfer_methods) + for(var/atom/A in loc) + reagents.reaction(A, transfer_methods) + qdel(src) // delete itself if it got blocked and can't move + return + addtimer(CALLBACK(src, PROC_REF(move_particle)), 2) /obj/effect/particle_effect/water/Move(turf/newloc) if (--src.life < 1) qdel(src) return FALSE + if(reagents) + reagents.reaction(newloc, transfer_methods) + for(var/atom/A in newloc) + reagents.reaction(A, transfer_methods) return ..() /obj/effect/particle_effect/water/Bump(atom/A) diff --git a/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm b/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm index ef1e1897b4cf..ca003178d8da 100644 --- a/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm +++ b/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm @@ -262,15 +262,13 @@ QDEL_NULL(turf_fire) var/datum/gas_mixture/air = location.air - var/scrub_amt = min(30, air.get_moles(/datum/gas/plasma)) //Absorb some plasma - air.adjust_moles(/datum/gas/plasma, -scrub_amt) + var/scrub_amt = min(30, air.get_moles(GAS_PLASMA)) //Absorb some plasma + air.adjust_moles(GAS_PLASMA, -scrub_amt) absorbed_plasma += scrub_amt if (air.return_temperature() > T20C) air.set_temperature(max(air.return_temperature() / 2, T20C)) - location.air_update_turf(FALSE, FALSE) - /obj/effect/particle_effect/fluid/foam/firefighting/make_result() if(!absorbed_plasma) // don't bother if it didn't scrub any plasma return @@ -322,7 +320,7 @@ /obj/structure/foamedmetal/Initialize(mapload) . = ..() - air_update_turf(1) + air_update_turf() /obj/structure/foamedmetal/Move() var/turf/T = loc @@ -409,11 +407,10 @@ for(var/gas_type in air.get_gases()) switch(gas_type) - if(/datum/gas/oxygen, /datum/gas/nitrogen) + if(GAS_O2, GAS_N2) continue else air.set_moles(gas_type, 0) - location.air_update_turf() for(var/obj/machinery/atmospherics/components/unary/comp in location) if(!comp.welded) diff --git a/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm b/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm index e2a1d4352544..030d78c8d201 100644 --- a/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm @@ -294,13 +294,12 @@ if(!distcheck || get_dist(location, chilly) < blast) // Otherwise we'll get silliness like people using Nanofrost to kill people through walls with cold air air.set_temperature(temperature) - if(air.get_moles(/datum/gas/plasma)) - air.adjust_moles(/datum/gas/nitrogen, air.get_moles(/datum/gas/plasma)) - air.set_moles(/datum/gas/plasma, 0) + if(air.get_moles(GAS_PLASMA)) + air.adjust_moles(GAS_N2, air.get_moles(GAS_PLASMA)) + air.set_moles(GAS_PLASMA, 0) for(var/obj/effect/hotspot/fire in chilly) qdel(fire) - chilly.air_update_turf() if(weldvents) for(var/obj/machinery/atmospherics/components/unary/comp in chilly) diff --git a/code/game/objects/effects/forcefields.dm b/code/game/objects/effects/forcefields.dm index 2216f16b6ef2..429e064b0b6b 100644 --- a/code/game/objects/effects/forcefields.dm +++ b/code/game/objects/effects/forcefields.dm @@ -3,7 +3,7 @@ desc = "A space wizard's magic wall." icon_state = "m_shield" anchored = TRUE - opacity = 0 + opacity = FALSE density = TRUE CanAtmosPass = ATMOS_PASS_DENSITY /// If set, how long the force field lasts after it's created. Set to 0 to have infinite duration forcefields. diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm index cb24dad4edbe..c7de6a2597cc 100644 --- a/code/game/objects/effects/misc.dm +++ b/code/game/objects/effects/misc.dm @@ -79,16 +79,16 @@ light_range = MINIMUM_USEFUL_LIGHT_RANGE mouse_opacity = MOUSE_OPACITY_TRANSPARENT -/obj/effect/dummy/lighting_obj/Initialize(mapload, _range, _power, _color, _duration) +/obj/effect/dummy/lighting_obj/Initialize(mapload, range, power, color, duration) . = ..() - if(!isnull(_range)) - set_light_range(_range) - if(!isnull(_power)) - set_light_power(_power) - if(!isnull(_color)) - set_light_color(_color) - if(_duration) - QDEL_IN(src, _duration) + if(!isnull(range)) + set_light_range(range) + if(!isnull(power)) + set_light_power(power) + if(!isnull(color)) + set_light_color(color) + if(duration) + QDEL_IN(src, duration) /obj/effect/dummy/lighting_obj/moblight name = "mob lighting fx" @@ -98,6 +98,9 @@ if(!ismob(loc)) return INITIALIZE_HINT_QDEL +/obj/effect/dummy/lighting_obj/moblight/species + name = "species lighting" + /obj/effect/dusting_anim icon = 'icons/effects/filters.dmi' icon_state = "nothing" diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index 906425b34252..dfd44008cdbb 100644 --- a/code/game/objects/effects/overlays.dm +++ b/code/game/objects/effects/overlays.dm @@ -50,7 +50,7 @@ /obj/effect/overlay/vis mouse_opacity = MOUSE_OPACITY_TRANSPARENT anchored = TRUE - vis_flags = NONE + vis_flags = VIS_INHERIT_DIR var/unused = 0 //When detected to be unused it gets set to world.time, after a while it gets removed var/cache_expiration = 2 MINUTES // overlays which go unused for 2 minutes get cleaned up vis_flags = VIS_INHERIT_ID @@ -88,3 +88,7 @@ mouse_opacity = MOUSE_OPACITY_TRANSPARENT alpha = 0 vis_flags = NONE + +/obj/effect/overlay/light_visible/cone + icon = 'icons/effects/light_overlays/light_cone.dmi' + alpha = 110 diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm index 6cd4f737e7bf..9e85bedc2839 100644 --- a/code/game/objects/effects/portals.dm +++ b/code/game/objects/effects/portals.dm @@ -121,8 +121,6 @@ return FALSE atmos_source.atmos_adjacent_turfs[atmos_destination] = TRUE atmos_destination.atmos_adjacent_turfs[atmos_source] = TRUE - atmos_source.air_update_turf(FALSE) - atmos_destination.air_update_turf(FALSE) /obj/effect/portal/proc/unlink_atmos() if(istype(atmos_source)) diff --git a/code/game/objects/effects/spawners/bombspawner.dm b/code/game/objects/effects/spawners/bombspawner.dm index 40bd2405fda6..9e07ee6a7a14 100644 --- a/code/game/objects/effects/spawners/bombspawner.dm +++ b/code/game/objects/effects/spawners/bombspawner.dm @@ -1,6 +1,6 @@ #define CELSIUS_TO_KELVIN(T_K) ((T_K) + T0C) -#define OPTIMAL_TEMP_K_PLA_BURN_SCALE(PRESSURE_P,PRESSURE_O,TEMP_O) (((PRESSURE_P) * GLOB.meta_gas_info[/datum/gas/plasma][META_GAS_SPECIFIC_HEAT]) / (((PRESSURE_P) * GLOB.meta_gas_info[/datum/gas/plasma][META_GAS_SPECIFIC_HEAT] + (PRESSURE_O) * GLOB.meta_gas_info[/datum/gas/oxygen][META_GAS_SPECIFIC_HEAT]) / PLASMA_UPPER_TEMPERATURE - (PRESSURE_O) * GLOB.meta_gas_info[/datum/gas/oxygen][META_GAS_SPECIFIC_HEAT] / CELSIUS_TO_KELVIN(TEMP_O))) +#define OPTIMAL_TEMP_K_PLA_BURN_SCALE(PRESSURE_P,PRESSURE_O,TEMP_O) (((PRESSURE_P) * GLOB.gas_data.specific_heats[GAS_PLASMA]) / (((PRESSURE_P) * GLOB.gas_data.specific_heats[GAS_PLASMA] + (PRESSURE_O) * GLOB.gas_data.specific_heats[GAS_O2]) / PLASMA_UPPER_TEMPERATURE - (PRESSURE_O) * GLOB.gas_data.specific_heats[GAS_O2] / CELSIUS_TO_KELVIN(TEMP_O))) #define OPTIMAL_TEMP_K_PLA_BURN_RATIO(PRESSURE_P,PRESSURE_O,TEMP_O) (CELSIUS_TO_KELVIN(TEMP_O) * PLASMA_OXYGEN_FULLBURN * (PRESSURE_P) / (PRESSURE_O)) /obj/effect/spawner/newbomb @@ -19,10 +19,10 @@ var/obj/item/tank/internals/plasma/PT = new(V) var/obj/item/tank/internals/oxygen/OT = new(V) - PT.air_contents.set_moles(/datum/gas/plasma, pressure_p*PT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_p))) + PT.air_contents.set_moles(GAS_PLASMA, pressure_p*PT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_p))) PT.air_contents.set_temperature(CELSIUS_TO_KELVIN(temp_p)) - OT.air_contents.set_moles(/datum/gas/oxygen, pressure_o*OT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_o))) + OT.air_contents.set_moles(GAS_O2, pressure_o*OT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_o))) OT.air_contents.set_temperature(CELSIUS_TO_KELVIN(temp_o)) V.tank_one = PT diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index dc3cb66af6d0..08f70d4bd4af 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -133,7 +133,7 @@ if(get_dist(src, entry_vent) <= 1) var/list/vents = list() var/datum/pipeline/entry_vent_parent = entry_vent.parents[1] - for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in entry_vent_parent.other_atmosmch) + for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in entry_vent_parent.other_atmos_machines) vents.Add(temp_vent) if(!vents.len) entry_vent = null diff --git a/code/game/objects/effects/turf_fire.dm b/code/game/objects/effects/turf_fire.dm index 62e2e514ab1d..a7f98193af91 100644 --- a/code/game/objects/effects/turf_fire.dm +++ b/code/game/objects/effects/turf_fire.dm @@ -108,7 +108,7 @@ /obj/effect/abstract/turf_fire/proc/process_waste() if(open_turf.planetary_atmos) return TRUE - var/oxy = open_turf.air.get_moles(/datum/gas/oxygen) + var/oxy = open_turf.air.get_moles(GAS_O2) if (oxy < TURF_FIRE_BURN_MINIMUM_OXYGEN_REQUIRED) return FALSE var/thermal_energy = open_turf.air.return_temperature() * open_turf.air.heat_capacity() @@ -116,8 +116,8 @@ if(burn_rate > oxy) burn_rate = oxy - open_turf.air.adjust_moles(/datum/gas/oxygen, -burn_rate) - open_turf.air.adjust_moles(/datum/gas/carbon_dioxide, burn_rate * TURF_FIRE_BURN_CARBON_DIOXIDE_MULTIPLIER) + open_turf.air.adjust_moles(GAS_O2, -burn_rate) + open_turf.air.adjust_moles(GAS_CO2, burn_rate * TURF_FIRE_BURN_CARBON_DIOXIDE_MULTIPLIER) open_turf.air.set_temperature((thermal_energy + (burn_rate * TURF_FIRE_ENERGY_PER_BURNED_OXY_MOL)) / open_turf.air.heat_capacity()) open_turf.air_update_turf(TRUE) diff --git a/code/game/objects/empulse.dm b/code/game/objects/empulse.dm index 34fa0ccd6e2c..a9c029047219 100644 --- a/code/game/objects/empulse.dm +++ b/code/game/objects/empulse.dm @@ -1,32 +1,30 @@ -/proc/empulse(turf/epicenter, heavy_range, light_range, log=0) +/proc/empulse(turf/epicenter, severity, range=null, log=TRUE) if(!epicenter) + CRASH("Warning: empulse() called without an epicenter!") + + if(severity < 1) return if(!isturf(epicenter)) epicenter = get_turf(epicenter.loc) + + if(isnull(range)) // range is equal to severity by default + range = severity if(log) - message_admins("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ") - log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ") - - if(heavy_range > 1) - new /obj/effect/temp_visual/emp/pulse(epicenter) + message_admins("EMP with size ([range]) and severity ([severity]) in area [epicenter.loc.name] ") + log_game("EMP with size ([range]) and severity ([severity]) in area [epicenter.loc.name] ") - if(heavy_range > light_range) - light_range = heavy_range + if(range <= 0) + for(var/atom/A in epicenter) + A.emp_act(severity) + return - for(var/A in spiral_range(light_range, epicenter)) + var/tile_falloff = severity / range + for(var/A in spiral_range(range, epicenter)) var/atom/T = A - var/distance = get_dist(epicenter, T) - if(distance < 0) - distance = 0 - if(distance < heavy_range) - T.emp_act(EMP_HEAVY) - else if(heavy_range && distance == heavy_range) //0 radius heavy EMPs will have no effect - if(prob(50)) - T.emp_act(EMP_HEAVY) - else - T.emp_act(EMP_LIGHT) - else if(distance <= light_range) - T.emp_act(EMP_LIGHT) - return 1 + var/decayed_severity = severity - round(get_dist(epicenter, T) * tile_falloff) + if(decayed_severity < 1) + continue + T.emp_act(decayed_severity) + return TRUE diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 4c40cf4173ec..dbf326d64000 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -71,7 +71,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) var/body_parts_partial_covered = 0 //same bit flags as above, only applies half armor to these body parts var/gas_transfer_coefficient = 1 // for leaking gas from turf to mask and vice-versa (for masks right now, but at some point, i'd like to include space helmets) - var/siemens_coefficient = 1 // for electrical admittance/conductance (electrocution checks and shit) var/slowdown = 0 // How much clothing is slowing you down. Negative values speeds you up var/armour_penetration = 0 //percentage of armour effectiveness to remove var/list/allowed = null //suit storage stuff. @@ -296,6 +295,11 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) if(HAS_TRAIT(src, TRAIT_NO_STORAGE)) . += "[gender == PLURAL ? "They are" : "It is"] too bulky, fragile, or cumbersome to fit in a container." + if(demolition_mod > 1) + . += "[src] seems exceptionally good at breaking things!" + else if(demolition_mod < 1) + . += "[src] seems exceptionally bad at breaking things." + if(resistance_flags & INDESTRUCTIBLE) . += "[src] seems extremely robust! It'll probably withstand anything that could happen to it!" else diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm index 3c25133864f1..c547a7078779 100644 --- a/code/game/objects/items/RCD.dm +++ b/code/game/objects/items/RCD.dm @@ -12,7 +12,7 @@ RLD /obj/item/construction name = "not for ingame use" desc = "A device used to rapidly build and deconstruct. Reload with metal, plasteel, glass or compressed matter cartridges." - opacity = 0 + opacity = FALSE density = FALSE anchored = FALSE flags_1 = CONDUCT_1 diff --git a/code/game/objects/items/RPD.dm b/code/game/objects/items/RPD.dm index 5b9ec8c74943..523293932963 100644 --- a/code/game/objects/items/RPD.dm +++ b/code/game/objects/items/RPD.dm @@ -467,7 +467,7 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list( P.update() P.add_fingerprint(usr) - P.setPipingLayer(piping_layer) + P.set_piping_layer(piping_layer) if(findtext("[queued_p_type]", "/obj/machinery/atmospherics/pipe") && !findtext("[queued_p_type]", "layer_manifold")) P.add_atom_colour(GLOB.pipe_paint_colors[paint_color], FIXED_COLOUR_PRIORITY) if(mode&WRENCH_MODE) diff --git a/code/game/objects/items/RSF.dm b/code/game/objects/items/RSF.dm index dce2f155e9e7..a497be7a27c2 100644 --- a/code/game/objects/items/RSF.dm +++ b/code/game/objects/items/RSF.dm @@ -13,7 +13,7 @@ RSF var/spent_icon_state = "rsf_empty" lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - opacity = 0 + opacity = FALSE density = FALSE anchored = FALSE item_flags = NOBLUDGEON diff --git a/code/game/objects/items/chrono_eraser.dm b/code/game/objects/items/chrono_eraser.dm index a11921c19de2..3095d7a3cd7d 100644 --- a/code/game/objects/items/chrono_eraser.dm +++ b/code/game/objects/items/chrono_eraser.dm @@ -253,12 +253,18 @@ return BULLET_ACT_HIT /obj/structure/chrono_field/assume_air() - return 0 + return null + +/obj/effect/chrono_field/assume_air_moles() + return null + +/obj/effect/chrono_field/assume_air_ratio() + return null /obj/structure/chrono_field/return_air() //we always have nominal air and temperature var/datum/gas_mixture/GM = new - GM.set_moles(/datum/gas/oxygen, MOLES_O2STANDARD) - GM.set_moles(/datum/gas/nitrogen, MOLES_N2STANDARD) + GM.set_moles(GAS_O2, MOLES_O2STANDARD) + GM.set_moles(GAS_N2, MOLES_N2STANDARD) GM.set_temperature(T20C) return GM diff --git a/code/game/objects/items/credit_holochip.dm b/code/game/objects/items/credit_holochip.dm index 5d1cc2e0deb9..6683b6c5481e 100644 --- a/code/game/objects/items/credit_holochip.dm +++ b/code/game/objects/items/credit_holochip.dm @@ -105,7 +105,7 @@ . = ..() if(. & EMP_PROTECT_SELF) return - var/wipe_chance = 60 / severity + var/wipe_chance = 6 * severity if(prob(wipe_chance)) visible_message(span_warning("[src] fizzles and disappears!")) qdel(src) //rip cash diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index 589103941ff1..ea6d0c4fbf05 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -153,7 +153,7 @@ . = ..() if(cell && !(. & EMP_PROTECT_CONTENTS)) - deductcharge(5000 / severity) + deductcharge(500 * severity) if (. & EMP_PROTECT_SELF) return @@ -308,7 +308,6 @@ /obj/item/shockpaddles/Initialize(mapload, obj/item/defibrillator/spawned_in) . = ..() AddComponent(/datum/component/two_handed, \ - force_unwielded = 8, \ force_wielded = 12, \ icon_wielded = "[base_icon_state]1", \ ) @@ -462,12 +461,14 @@ return if(!req_defib && !combat) return - busy = TRUE M.visible_message(span_danger("[user] has touched [M] with [src]!"), \ span_userdanger("[user] has touched [M] with [src]!")) - M.adjustStaminaLoss(50) - M.Knockdown(100) - M.updatehealth() //forces health update before next life tick //isn't this done by adjustStaminaLoss anyway? + var/hit_percent = (100 - M.getarmor(user.zone_selected, ELECTRIC)) / 100 + if(!hit_percent) + return + busy = TRUE + M.adjustStaminaLoss(50 * hit_percent) + M.Knockdown((10 * hit_percent) SECONDS) playsound(src, 'sound/machines/defib_zap.ogg', 50, 1, -1) M.emote("gasp") log_combat(user, M, "stunned", src) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 51edcb5d3e2f..edd624f642e3 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -410,14 +410,13 @@ GLOBAL_LIST_EMPTY(PDAs) if (3) dat += "

[PDAIMG(atmos)] Atmospheric Readings

" - var/turf/T = user.loc - if (isnull(T)) + if (!isopenturf(get_turf(user))) dat += "Unable to obtain a reading.
" else - var/datum/gas_mixture/environment = T.return_air() + var/datum/gas_mixture/environment = user.return_air() - var/pressure = environment.return_pressure() - var/total_moles = environment.total_moles() + var/pressure = environment?.return_pressure() + var/total_moles = environment?.total_moles() dat += "Air Pressure: [round(pressure,0.1)] kPa
" @@ -425,7 +424,7 @@ GLOBAL_LIST_EMPTY(PDAs) for(var/id in environment.get_gases()) var/gas_level = environment.get_moles(id)/total_moles if(gas_level > 0) - dat += "[GLOB.meta_gas_info[id][META_GAS_NAME]]: [round(gas_level*100, 0.01)]%
" + dat += "[GLOB.gas_data.names[id]]: [round(gas_level*100, 0.01)]%
" dat += "Temperature: [round(environment.return_temperature()-T0C)]°C
" dat += "
" @@ -1227,7 +1226,7 @@ GLOBAL_LIST_EMPTY(PDAs) A.emp_act(severity) if (!(. & EMP_PROTECT_SELF)) emped += 1 - spawn(200 * severity) + spawn(20 * severity) emped -= 1 /proc/get_viewable_pdas() diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 6b538bff266a..e5a6611c0df1 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -32,6 +32,7 @@ set_light_on(on) if(light_system == STATIC_LIGHT) update_light() + /obj/item/flashlight/attack_self(mob/user) on = !on update_brightness(user) @@ -236,6 +237,7 @@ force = 9 // Not as good as a stun baton. light_range = 5 // A little better than the standard flashlight. hitsound = 'sound/weapons/genhit1.ogg' + light_system = MOVABLE_LIGHT_DIRECTIONAL // the desk lamps are a bit special /obj/item/flashlight/lamp diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index dc6c33d1a1b4..84f32bcdabca 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -87,7 +87,7 @@ return if(ishuman(user)) var/mob/living/carbon/human/H = user - if(H.dna.check_mutation(HULK) || H.dna.check_mutation(ACTIVE_HULK)) + if(H.dna.check_mutation(HULK)) to_chat(user, span_warning("Your fingers can't press the button!")) return diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm index 8f2e996ef16e..4bf8b57b1dc9 100644 --- a/code/game/objects/items/devices/megaphone.dm +++ b/code/game/objects/items/devices/megaphone.dm @@ -7,7 +7,6 @@ lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' w_class = WEIGHT_CLASS_SMALL - siemens_coefficient = 1 var/last_used = 0 var/list/voicespan = list(SPAN_COMMAND) diff --git a/code/game/objects/items/devices/pseudocider.dm b/code/game/objects/items/devices/pseudocider.dm index 64d2cfdaeb8b..be75eaacab07 100644 --- a/code/game/objects/items/devices/pseudocider.dm +++ b/code/game/objects/items/devices/pseudocider.dm @@ -9,7 +9,7 @@ var/active = FALSE var/mob/living/carbon/fake_corpse COOLDOWN_DECLARE(fake_death_timer) - var/fake_death_cooldown = 20 SECONDS + var/fake_death_cooldown = 30 SECONDS /obj/item/pseudocider/update_icon_state() icon_state = "[base_icon_state][active ? "-open" : "-closed"]" diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 6c4bf27335cd..e1159a7dce30 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -206,7 +206,7 @@ /obj/item/radio/headset/headset_cent name = "\improper CentCom headset" - desc = "A headset used by the upper echelons of NanoTrasen." + desc = "A headset used by the upper echelons of Nanotrasen." icon_state = "cent_headset" keyslot = new /obj/item/encryptionkey/headset_com keyslot2 = new /obj/item/encryptionkey/headset_cent diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 873b1803cf31..cb5027fa300c 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -429,7 +429,6 @@ GLOBAL_LIST_INIT(channel_tokens, list( if (. & EMP_PROTECT_SELF) return emped++ //There's been an EMP; better count it - var/curremp = emped //Remember which EMP this was if (listening && ismob(loc)) // if the radio is turned on and on someone's person they notice to_chat(loc, span_warning("\The [src] overloads.")) broadcasting = FALSE @@ -437,11 +436,9 @@ GLOBAL_LIST_INIT(channel_tokens, list( for (var/ch_name in channels) channels[ch_name] = 0 on = FALSE - addtimer(CALLBACK(src, PROC_REF(end_emp_effect), curremp), 200) + addtimer(CALLBACK(src, PROC_REF(end_emp_effect)), 20 * severity, TIMER_UNIQUE | TIMER_OVERRIDE) -/obj/item/radio/proc/end_emp_effect(curremp) - if(emped != curremp) //Don't fix it if it's been EMP'd again - return FALSE +/obj/item/radio/proc/end_emp_effect() emped = FALSE on = TRUE return TRUE diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 7d32ab02180d..39633ed98f4d 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -362,7 +362,7 @@ GENE SCANNER var/mob/living/carbon/human/H = M var/datum/species/S = H.dna.species var/mutant = FALSE - if (H.dna.check_mutation(HULK) || H.dna.check_mutation(ACTIVE_HULK)) + if (H.dna.check_mutation(HULK)) mutant = TRUE else if (S.mutantlungs != initial(S.mutantlungs)) mutant = TRUE @@ -623,11 +623,14 @@ GENE SCANNER if (user.stat || user.eye_blind) return - var/turf/location = user.loc - if(!istype(location)) + if(!isopenturf(get_turf(user))) return - var/datum/gas_mixture/environment = location.return_air() + var/datum/gas_mixture/environment = user.return_air() + + if(!environment) + to_chat(user, span_info("No air detected.")) + return var/pressure = environment.return_pressure() var/total_moles = environment.total_moles() @@ -638,36 +641,36 @@ GENE SCANNER else combined_msg += span_alert("Pressure: [round(pressure, 0.01)] kPa") if(total_moles) - var/o2_concentration = environment.get_moles(/datum/gas/oxygen)/total_moles - var/n2_concentration = environment.get_moles(/datum/gas/nitrogen)/total_moles - var/co2_concentration = environment.get_moles(/datum/gas/carbon_dioxide)/total_moles - var/plasma_concentration = environment.get_moles(/datum/gas/plasma)/total_moles + var/o2_concentration = environment.get_moles(GAS_O2)/total_moles + var/n2_concentration = environment.get_moles(GAS_N2)/total_moles + var/co2_concentration = environment.get_moles(GAS_CO2)/total_moles + var/plasma_concentration = environment.get_moles(GAS_PLASMA)/total_moles if(abs(n2_concentration - N2STANDARD) < 20) - combined_msg += span_info("Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/nitrogen), 0.01)] mol)") + combined_msg += span_info("Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(environment.get_moles(GAS_N2), 0.01)] mol)") else - combined_msg += span_alert("Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/nitrogen), 0.01)] mol)") + combined_msg += span_alert("Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(environment.get_moles(GAS_N2), 0.01)] mol)") if(abs(o2_concentration - O2STANDARD) < 2) - combined_msg += span_info("Oxygen: [round(o2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/oxygen), 0.01)] mol)") + combined_msg += span_info("Oxygen: [round(o2_concentration*100, 0.01)] % ([round(environment.get_moles(GAS_O2), 0.01)] mol)") else - combined_msg += span_alert("Oxygen: [round(o2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/oxygen), 0.01)] mol)") + combined_msg += span_alert("Oxygen: [round(o2_concentration*100, 0.01)] % ([round(environment.get_moles(GAS_O2), 0.01)] mol)") if(co2_concentration > 0.01) - combined_msg += span_alert("CO2: [round(co2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/carbon_dioxide), 0.01)] mol)") + combined_msg += span_alert("CO2: [round(co2_concentration*100, 0.01)] % ([round(environment.get_moles(GAS_CO2), 0.01)] mol)") else - combined_msg += span_info("CO2: [round(co2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/carbon_dioxide), 0.01)] mol)") + combined_msg += span_info("CO2: [round(co2_concentration*100, 0.01)] % ([round(environment.get_moles(GAS_CO2), 0.01)] mol)") if(plasma_concentration > 0.005) - combined_msg += span_alert("Plasma: [round(plasma_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/plasma), 0.01)] mol)") + combined_msg += span_alert("Plasma: [round(plasma_concentration*100, 0.01)] % ([round(environment.get_moles(GAS_PLASMA), 0.01)] mol)") else - combined_msg += span_info("Plasma: [round(plasma_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/plasma), 0.01)] mol)") + combined_msg += span_info("Plasma: [round(plasma_concentration*100, 0.01)] % ([round(environment.get_moles(GAS_PLASMA), 0.01)] mol)") for(var/id in environment.get_gases()) if(id in GLOB.hardcoded_gases) continue var/gas_concentration = environment.get_moles(id)/total_moles - combined_msg += span_alert("[GLOB.meta_gas_info[id][META_GAS_NAME]]: [round(gas_concentration*100, 0.01)] % ([round(environment.get_moles(id), 0.01)] mol)") + combined_msg += span_alert("[GLOB.gas_data.names[id]]: [round(gas_concentration*100, 0.01)] % ([round(environment.get_moles(id), 0.01)] mol)") combined_msg += span_info("Temperature: [round(environment.return_temperature()-T0C, 0.01)] °C ([round(environment.return_temperature(), 0.01)] K)") to_chat(user, examine_block(combined_msg.Join("\n"))) @@ -764,7 +767,7 @@ GENE SCANNER for(var/id in air_contents.get_gases()) var/gas_concentration = air_contents.get_moles(id)/total_moles - combined_msg += span_notice("[GLOB.meta_gas_info[id][META_GAS_NAME]]: [round(gas_concentration*100, 0.01)] % ([round(air_contents.get_moles(id), 0.01)] mol)") + combined_msg += span_notice("[GLOB.gas_data.names[id]]: [round(gas_concentration*100, 0.01)] % ([round(air_contents.get_moles(id), 0.01)] mol)") combined_msg += span_notice("Temperature: [round(temperature - T0C,0.01)] °C ([round(temperature, 0.01)] K)") else diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index 8848dd0e2f28..7a195a99be79 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -130,22 +130,17 @@ target_self = TRUE if(change_volume) if(!target_self) - target.set_volume(target.return_volume() + tank_two.air_contents.return_volume()) + target.set_volume(target.return_volume() + tank_two.volume) target.set_volume(target.return_volume() + tank_one.air_contents.return_volume()) - var/datum/gas_mixture/temp - temp = tank_one.air_contents.remove_ratio(1) - target.merge(temp) + tank_one.air_contents.transfer_ratio_to(target, 1) if(!target_self) - temp = tank_two.air_contents.remove_ratio(1) - target.merge(temp) + tank_two.air_contents.transfer_ratio_to(target, 1) /obj/item/transfer_valve/proc/split_gases() if (!valve_open || !tank_one || !tank_two) return var/ratio1 = tank_one.air_contents.return_volume()/tank_two.air_contents.return_volume() - var/datum/gas_mixture/temp - temp = tank_two.air_contents.remove_ratio(ratio1) - tank_one.air_contents.merge(temp) + tank_two.air_contents.transfer_ratio_to(tank_one.air_contents, ratio1) tank_two.air_contents.set_volume(tank_two.air_contents.return_volume() - tank_one.air_contents.return_volume()) /* diff --git a/code/game/objects/items/dna_injector.dm b/code/game/objects/items/dna_injector.dm index 7d182fba2cbd..2ec72419d8d2 100644 --- a/code/game/objects/items/dna_injector.dm +++ b/code/game/objects/items/dna_injector.dm @@ -88,12 +88,7 @@ /obj/item/dnainjector/antihulk name = "\improper DNA injector (Anti-Hulk)" desc = "Cures green skin." - remove_mutations = list(HULK, ACTIVE_HULK, GENETICS_HULK) - -/obj/item/dnainjector/hulkmut/genetics_hulk - name = "\improper DNA injector (Genetics Hulk)" - desc = "This will make you big and strong if you get hurt, but give you a bad skin condition." - add_mutations = list(GENETICS_HULK) + remove_mutations = list(HULK) /obj/item/dnainjector/hulkmut name = "\improper DNA injector (Hulk)" diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm index 74049fab9c8b..97b8302758f0 100644 --- a/code/game/objects/items/extinguisher.dm +++ b/code/game/objects/items/extinguisher.dm @@ -168,43 +168,12 @@ var/turf/T4 = get_step(T2,turn(direction, -90)) the_targets.Add(T3,T4) - var/list/water_particles=list() for(var/a=0, a<5, a++) - var/obj/effect/particle_effect/water/W = new /obj/effect/particle_effect/water(get_turf(src)) var/my_target = pick(the_targets) - water_particles[W] = my_target - // If precise, remove turf from targets so it won't be picked more than once + var/obj/effect/particle_effect/water/W = new /obj/effect/particle_effect/water(get_turf(src), my_target) + reagents.trans_to(W, chem_amount, transfered_by = user) if(precision) the_targets -= my_target - var/datum/reagents/R = new/datum/reagents(5) - W.reagents = R - R.my_atom = W - reagents.trans_to(W, chem_amount, transfered_by = user) - - //Make em move dat ass, hun - addtimer(CALLBACK(src, /obj/item/extinguisher/proc/move_particles, water_particles), 2) - -//Particle movement loop -/obj/item/extinguisher/proc/move_particles(list/particles, repetition=0) - //Check if there's anything in here first - if(!particles || particles.len == 0) - return - // Second loop: Get all the water particles and make them move to their target - for(var/obj/effect/particle_effect/water/W in particles) - var/turf/my_target = particles[W] - if(!W) - continue - step_towards(W,my_target) - if(!W.reagents) - continue - W.reagents.reaction(get_turf(W)) - for(var/A in get_turf(W)) - W.reagents.reaction(A) - if(W.loc == my_target) - particles -= W - if(repetition < power) - repetition++ - addtimer(CALLBACK(src, /obj/item/extinguisher/proc/move_particles, particles, repetition), 2) //Chair movement loop /obj/item/extinguisher/proc/move_chair(obj/B, movementdirection, repetition=0) diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm index 1ef10bf9a414..1d49b434522e 100644 --- a/code/game/objects/items/flamethrower.dm +++ b/code/game/objects/items/flamethrower.dm @@ -205,27 +205,27 @@ var/datum/gas_mixture/fuel_mix = ptank.air_contents.remove_ratio(ratio_removed) // Return of the stimball flamethrower, wear radiation protection when using this or you're just as likely to die as your target - if(fuel_mix.get_moles(/datum/gas/plasma) >= NITRO_BALL_MOLES_REQUIRED && fuel_mix.get_moles(/datum/gas/nitrium) >= NITRO_BALL_MOLES_REQUIRED && fuel_mix.get_moles(/datum/gas/pluoxium) >= NITRO_BALL_MOLES_REQUIRED) - var/balls_shot = round(min(fuel_mix.get_moles(/datum/gas/nitrium), fuel_mix.get_moles(/datum/gas/pluoxium), NITRO_BALL_MAX_REACT_RATE / NITRO_BALL_MOLES_REQUIRED)) + if(fuel_mix.get_moles(GAS_PLASMA) >= NITRO_BALL_MOLES_REQUIRED && fuel_mix.get_moles(GAS_NITRIUM) >= NITRO_BALL_MOLES_REQUIRED && fuel_mix.get_moles(GAS_PLUOXIUM) >= NITRO_BALL_MOLES_REQUIRED) + var/balls_shot = round(min(fuel_mix.get_moles(GAS_NITRIUM), fuel_mix.get_moles(GAS_PLUOXIUM), NITRO_BALL_MAX_REACT_RATE / NITRO_BALL_MOLES_REQUIRED)) var/angular_increment = 360/balls_shot var/random_starting_angle = rand(0,360) for(var/i in 1 to balls_shot) target.fire_nuclear_particle((i*angular_increment+random_starting_angle)) - fuel_mix.adjust_moles(/datum/gas/plasma, -balls_shot * NITRO_BALL_MOLES_REQUIRED) // No free extra damage for you, conservation of mass go brrrrr + fuel_mix.adjust_moles(GAS_PLASMA, -balls_shot * NITRO_BALL_MOLES_REQUIRED) // No free extra damage for you, conservation of mass go brrrrr // Funny rad flamethrower go brrr - if(fuel_mix.get_moles(/datum/gas/tritium)) // Tritium fires cause a bit of radiation - radiation_pulse(target, min(fuel_mix.get_moles(/datum/gas/tritium), fuel_mix.get_moles(/datum/gas/oxygen)/2) * FIRE_HYDROGEN_ENERGY_RELEASED / TRITIUM_BURN_RADIOACTIVITY_FACTOR) + if(fuel_mix.get_moles(GAS_TRITIUM)) // Tritium fires cause a bit of radiation + radiation_pulse(target, min(fuel_mix.get_moles(GAS_TRITIUM), fuel_mix.get_moles(GAS_O2)/2) * FIRE_HYDROGEN_ENERGY_RELEASED / TRITIUM_BURN_RADIOACTIVITY_FACTOR) // 8 damage at 0.5 mole transfer or ~17 kPa release pressure // 16 damage at 1 mole transfer or ~35 kPa release pressure - var/damage = fuel_mix.get_moles(/datum/gas/plasma) * 16 + var/damage = fuel_mix.get_moles(GAS_PLASMA) * 16 // harder to achieve than plasma - damage += fuel_mix.get_moles(/datum/gas/tritium) * 24 // Lower damage than hydrogen, causes minor radiation - damage += fuel_mix.get_moles(/datum/gas/hydrogen) * 32 + damage += fuel_mix.get_moles(GAS_TRITIUM) * 24 // Lower damage than hydrogen, causes minor radiation + damage += fuel_mix.get_moles(GAS_H2) * 32 // Maximum damage restricted by the available oxygen, with a hard cap at 16 var/datum/gas_mixture/turf_air = target.return_air() - damage = min(damage, turf_air.get_moles(/datum/gas/oxygen) + fuel_mix.get_moles(/datum/gas/oxygen), max_damage) // capped by combined oxygen in the fuel mix and enviroment + damage = min(damage, turf_air.get_moles(GAS_O2) + fuel_mix.get_moles(GAS_O2), max_damage) // capped by combined oxygen in the fuel mix and enviroment // If there's not enough fuel and/or oxygen to do more than 1 damage, shut itself off if(damage < 1) diff --git a/code/game/objects/items/granters/magic/charge.dm b/code/game/objects/items/granters/magic/charge.dm index 72ab119aa152..d0c33ed14701 100644 --- a/code/game/objects/items/granters/magic/charge.dm +++ b/code/game/objects/items/granters/magic/charge.dm @@ -17,4 +17,4 @@ /obj/item/book/granter/action/spell/charge/recoil(mob/living/user) . = ..() to_chat(user,span_warning("[src] suddenly feels very warm!")) - empulse(src, 1, 1) \ No newline at end of file + empulse(src, EMP_HEAVY, 0) diff --git a/code/game/objects/items/grenades/atmos_grenades.dm b/code/game/objects/items/grenades/atmos_grenades.dm index 27d8c8eda24c..0df6b3d6a9d7 100644 --- a/code/game/objects/items/grenades/atmos_grenades.dm +++ b/code/game/objects/items/grenades/atmos_grenades.dm @@ -44,9 +44,8 @@ if(floor_loc.air.return_temperature() > 370) floor_loc.atmos_spawn_air("n2=[gas_amount / distance_from_center];TEMP=30") floor_loc.MakeSlippery(TURF_WET_PERMAFROST, (5 / distance_from_center) MINUTES) - if(floor_loc.air.get_gases(/datum/gas/plasma)) - floor_loc.air.adjust_moles(/datum/gas/plasma, -(floor_loc.air.get_moles(/datum/gas/plasma) * 0.5 / distance_from_center)) - floor_loc.air_update_turf() + if(floor_loc.air.get_gases(GAS_PLASMA)) + floor_loc.air.adjust_moles(GAS_PLASMA, -(floor_loc.air.get_moles(GAS_PLASMA) * 0.5 / distance_from_center)) for(var/mob/living/carbon/live_mob in turf_loc) live_mob.adjustStaminaLoss(stamina_damage / distance_from_center) live_mob.adjust_bodytemperature(-150 / distance_from_center) diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm index 416ac77f0518..2423c687ef52 100644 --- a/code/game/objects/items/grenades/chem_grenade.dm +++ b/code/game/objects/items/grenades/chem_grenade.dm @@ -151,7 +151,7 @@ /obj/item/grenade/chem_grenade/emp_act(severity) ..() - if(prob(40/severity)) + if(prob(4 * severity)) prime() /obj/item/grenade/chem_grenade/on_found(mob/finder) diff --git a/code/game/objects/items/grenades/emgrenade.dm b/code/game/objects/items/grenades/emgrenade.dm index 99cf4bdf99d1..082663addd44 100644 --- a/code/game/objects/items/grenades/emgrenade.dm +++ b/code/game/objects/items/grenades/emgrenade.dm @@ -6,5 +6,5 @@ /obj/item/grenade/empgrenade/prime() update_mob() - empulse(src, 4, 10) + empulse(src, EMP_HEAVY) qdel(src) diff --git a/code/game/objects/items/grenades/flashbang.dm b/code/game/objects/items/grenades/flashbang.dm index a66c2cdec5c8..bfa0f46dcfe9 100644 --- a/code/game/objects/items/grenades/flashbang.dm +++ b/code/game/objects/items/grenades/flashbang.dm @@ -13,7 +13,7 @@ return do_sparks(rand(5, 9), FALSE, src) playsound(flashbang_turf, 'sound/weapons/flashbang.ogg', 100, TRUE, 8, 0.9) - new /obj/effect/dummy/lighting_obj (flashbang_turf, flashbang_range + 2, 4, COLOR_WHITE, 2) + new /obj/effect/dummy/lighting_obj(flashbang_turf, flashbang_range + 2, 4, COLOR_WHITE, 2) for(var/mob/living/M in get_hearers_in_view(flashbang_range, flashbang_turf)) bang(get_turf(M), M) qdel(src) diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm index f933ef821122..856dd4bf9387 100644 --- a/code/game/objects/items/holy_weapons.dm +++ b/code/game/objects/items/holy_weapons.dm @@ -859,12 +859,13 @@ force = 0 // How often we forget throwforce = 0 // Faith without works is... attack_verb = list("blessed") + menutab = MENU_MISC + additional_desc = "A holy icon, praying to it will allow it to weaken and burn those that draw your god's ire." + var/held_up = FALSE var/mutable_appearance/holy_glow_fx - var/obj/effect/dummy/lighting_obj/moblight/holy_glow_light COOLDOWN_DECLARE(holy_notification) - menutab = MENU_MISC - additional_desc = "A holy icon, praying to it will allow it to weaken and burn those that draw your god's ire." + var/obj/effect/dummy/lighting_obj/moblight/holy_glow_light /obj/item/nullrod/cross/attack_self(mob/living/user) . = ..() @@ -879,7 +880,7 @@ slot_flags = 0 holy_glow_fx = mutable_appearance('icons/effects/genetics.dmi', "servitude", -MUTATIONS_LAYER) user.add_overlay(holy_glow_fx) - holy_glow_light = user.mob_light(_color = LIGHT_COLOR_HOLY_MAGIC, _range = 2) + holy_glow_light = user.mob_light(range = 2, color = LIGHT_COLOR_HOLY_MAGIC) RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(unwield)) RegisterSignal(src, COMSIG_ITEM_PREDROPPED, PROC_REF(drop_unwield)) START_PROCESSING(SSfastprocess, src) @@ -1093,7 +1094,7 @@ it also swaps back if it gets thrown into the chaplain, but the chaplain catches playsound(target, 'sound/weapons/rapierhit.ogg', 30, 1, -1) owner.take_overall_damage(5) visible_message("[src] smacks [owner] in the face as [owner.p_they()] try to catch it with [owner.p_their()] hands full!") - else if(possessed) + else if(possessed && soul) transform = initial(transform)//to reset rotation for when it drops to the ground blade = new /mob/living/simple_animal/nullrod(get_turf(src)) blade.sword = src @@ -1301,43 +1302,12 @@ it also swaps back if it gets thrown into the chaplain, but the chaplain catches var/turf/T5 = get_step(get_turf(target),turn(direction, -90)) var/list/the_targets = list(T,T1,T2,T3,T4,T5) - var/list/water_particles=list() for(var/a=0, a<6, a++) - var/obj/effect/particle_effect/water/W = new /obj/effect/particle_effect/water(get_turf(src)) - W.life = distance var/my_target = pick(the_targets) - water_particles[W] = my_target - the_targets -= my_target - var/datum/reagents/R = new/datum/reagents(1) - W.reagents = R - R.my_atom = W + var/obj/effect/particle_effect/water/W = new /obj/effect/particle_effect/water(get_turf(src), my_target, TOUCH|VAPOR) W.reagents.add_reagent(/datum/reagent/water/holywater, 1) - - //Make em move dat ass, hun - addtimer(CALLBACK(src, /obj/item/extinguisher/proc/move_particles, water_particles), 1) - -//Particle movement loop -/obj/item/nullrod/aspergillum/proc/move_particles(list/particles, repetition=0) - //Check if there's anything in here first - if(!particles || particles.len == 0) - return - // Second loop: Get all the water particles and make them move to their target - for(var/obj/effect/particle_effect/water/W in particles) - var/turf/my_target = particles[W] - if(!W) - continue - step_towards(W,my_target) - if(!W.reagents) - continue - for(var/A in get_turf(W)) - if(A == src.loc)//don't fill the chaplain with holy water - continue - W.reagents.reaction(A, TOUCH|VAPOR) - if(W.loc == my_target) - particles -= W - if(repetition < distance) - repetition++ - addtimer(CALLBACK(src, /obj/item/extinguisher/proc/move_particles, particles, repetition), 1) + the_targets -= my_target + W.life = distance /obj/item/nullrod/aspergillum/update_icon_state() . = ..() diff --git a/code/game/objects/items/implants/implant_misc.dm b/code/game/objects/items/implants/implant_misc.dm index 837b947b3bf7..9bbece6a4047 100644 --- a/code/game/objects/items/implants/implant_misc.dm +++ b/code/game/objects/items/implants/implant_misc.dm @@ -64,7 +64,7 @@ /obj/item/implant/emp/activate() . = ..() uses-- - empulse(imp_in, 3, 5) + empulse(imp_in, EMP_HEAVY, 5) // 10 severity, extends to 5 tiles if(!uses) qdel(src) @@ -174,13 +174,13 @@ UnregisterSignal(target, COMSIG_ATOM_EMP_ACT) return TRUE -/obj/item/implant/empshield/proc/overloaded(mob/living/target) +/obj/item/implant/empshield/proc/overloaded(mob/living/target, severity) if(world.time - lastemp > overloadtimer) numrecent = 0 - numrecent ++ + numrecent += severity lastemp = world.time - if(numrecent >= 5 && ishuman(target)) + if(numrecent >= (5 * EMP_HEAVY) && ishuman(target)) if(warning) to_chat(target, span_userdanger("You feel a twinge inside from your [src], you get the feeling it won't protect you anymore.")) warning = FALSE diff --git a/code/game/objects/items/implants/implantchair.dm b/code/game/objects/items/implants/implantchair.dm index e3aadfe0fe34..77bc76d2b0a5 100644 --- a/code/game/objects/items/implants/implantchair.dm +++ b/code/game/objects/items/implants/implantchair.dm @@ -4,7 +4,7 @@ icon = 'icons/obj/machines/implantchair.dmi' icon_state = "implantchair" density = TRUE - opacity = 0 + opacity = FALSE var/ready = TRUE var/replenishing = FALSE diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm index 773871e48a49..9d6e0c8a939f 100644 --- a/code/game/objects/items/kitchen.dm +++ b/code/game/objects/items/kitchen.dm @@ -92,6 +92,7 @@ hitsound = 'sound/weapons/bladeslice.ogg' throw_speed = 3 throw_range = 6 + demolition_mod = 0.8 materials = list(/datum/material/iron=12000) attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") sharpness = SHARP_EDGED diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index da1f73bfdd5b..4a3f74dea584 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -626,7 +626,6 @@ T.visible_message(span_danger("[T] smacks into [src] and rapidly flashes to ash."),\ span_italics("You hear a loud crack as you are washed with a wave of heat.")) shard.Consume() - CALCULATE_ADJACENT_TURFS(T) /obj/item/melee/supermatter_sword/add_blood_DNA(list/blood_dna) return FALSE diff --git a/code/game/objects/items/mop.dm b/code/game/objects/items/mop.dm index 80275184e206..982116fe9651 100644 --- a/code/game/objects/items/mop.dm +++ b/code/game/objects/items/mop.dm @@ -21,7 +21,7 @@ /obj/item/mop/Initialize(mapload) . = ..() - create_reagents(mopcap) + create_reagents(mopcap, REFILLABLE) /obj/item/mop/proc/clean(turf/A) diff --git a/code/game/objects/items/powerfist.dm b/code/game/objects/items/powerfist.dm index d35a33d472c6..f6e8f65c2884 100644 --- a/code/game/objects/items/powerfist.dm +++ b/code/game/objects/items/powerfist.dm @@ -1,4 +1,4 @@ -/obj/item/melee/powerfist +/obj/item/clothing/gloves/powerfist name = "power-fist" desc = "A metal gauntlet with a piston-powered ram ontop for that extra 'ompfh' in your punch." icon = 'icons/obj/traitor.dmi' @@ -11,16 +11,29 @@ force = 20 throwforce = 10 throw_range = 7 + strip_delay = 80 + cold_protection = HANDS + heat_protection = HANDS w_class = WEIGHT_CLASS_NORMAL - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 40) - resistance_flags = FIRE_PROOF + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100, ELECTRIC = 100) + resistance_flags = FIRE_PROOF | ACID_PROOF var/click_delay = 1.5 var/fisto_setting = 1 + var/max_setting = 3 var/gasperfist = 3 var/obj/item/tank/internals/tank = null //Tank used for the gauntlet's piston-ram. +/obj/item/clothing/gloves/powerfist/equipped(mob/user, slot) + . = ..() + if(slot & ITEM_SLOT_GLOVES) + RegisterSignal(user, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(power_punch)) + +/obj/item/clothing/gloves/powerfist/dropped(mob/user) + if(user.get_item_by_slot(ITEM_SLOT_GLOVES)==src) + UnregisterSignal(user, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + return ..() -/obj/item/melee/powerfist/examine(mob/user) +/obj/item/clothing/gloves/powerfist/examine(mob/user) . = ..() if(!in_range(user, src)) . += span_notice("You'll need to get closer to see any more.") @@ -29,7 +42,7 @@ . += span_notice("[icon2html(tank, user)] It has \a [tank] mounted onto it.") -/obj/item/melee/powerfist/attackby(obj/item/W, mob/user, params) +/obj/item/clothing/gloves/powerfist/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/tank/internals)) if(!tank) var/obj/item/tank/internals/IT = W @@ -38,20 +51,20 @@ return updateTank(W, 0, user) else if(W.tool_behaviour == TOOL_WRENCH) - switch(fisto_setting) - if(1) - fisto_setting = 2 - if(2) - fisto_setting = 3 - if(3) - fisto_setting = 1 + fisto_setting++ + if(fisto_setting > max_setting) + fisto_setting = 1 W.play_tool_sound(src) + user.balloon_alert(user, span_notice("power set to [fisto_setting]")) to_chat(user, span_notice("You tweak \the [src]'s piston valve to [fisto_setting].")) else if(W.tool_behaviour == TOOL_SCREWDRIVER) if(tank) updateTank(tank, 1, user) + else if(W.tool_behaviour == TOOL_ANALYZER) + if(tank) + atmosanalyzer_scan(user, tank) -/obj/item/melee/powerfist/proc/updateTank(obj/item/tank/internals/thetank, removing = 0, mob/living/carbon/human/user) +/obj/item/clothing/gloves/powerfist/proc/updateTank(obj/item/tank/internals/thetank, removing = 0, mob/living/carbon/human/user) if(removing) if(!tank) to_chat(user, span_notice("\The [src] currently has no tank attached to it.")) @@ -69,32 +82,36 @@ to_chat(user, span_notice("You hook \the [thetank] up to \the [src].")) tank = thetank +/obj/item/clothing/gloves/powerfist/attack(mob/living/target, mob/living/user) + power_punch(user, target) -/obj/item/melee/powerfist/attack(mob/living/target, mob/living/user) +/obj/item/clothing/gloves/powerfist/proc/power_punch(mob/living/user, atom/movable/target) + if(!user || user.a_intent!=INTENT_HARM || (!isliving(target) && !isobj(target)) || isitem(target)) + return if(!tank) to_chat(user, span_warning("\The [src] can't operate without a source of gas!")) return + var/moles_used = min(tank.air_contents.total_moles(), gasperfist * fisto_setting) var/datum/gas_mixture/gasused = tank.air_contents.remove(gasperfist * fisto_setting) var/turf/T = get_turf(src) if(!T) return T.assume_air(gasused) - T.air_update_turf() if(!gasused) to_chat(user, span_warning("\The [src]'s tank is empty!")) - target.apply_damage((force / 5), BRUTE) + do_attack(user, target, force / 5) playsound(loc, 'sound/weapons/punch1.ogg', 50, 1) target.visible_message(span_danger("[user]'s powerfist lets out a dull thunk as [user.p_they()] punch[user.p_es()] [target.name]!"), \ span_userdanger("[user]'s punches you!")) - return - if(gasused.total_moles() < gasperfist * fisto_setting) + return COMPONENT_NO_ATTACK_HAND + if(moles_used < gasperfist * fisto_setting) to_chat(user, span_warning("\The [src]'s piston-ram lets out a weak hiss, it needs more gas!")) playsound(loc, 'sound/weapons/punch4.ogg', 50, 1) - target.apply_damage((force / 2), BRUTE) + do_attack(user, target, force / 2) target.visible_message(span_danger("[user]'s powerfist lets out a weak hiss as [user.p_they()] punch[user.p_es()] [target.name]!"), \ span_userdanger("[user]'s punch strikes with force!")) - return - target.apply_damage(force * fisto_setting, BRUTE, wound_bonus = CANT_WOUND) + return COMPONENT_NO_ATTACK_HAND + do_attack(user, target, force * moles_used / gasperfist) target.visible_message(span_danger("[user]'s powerfist lets out a loud hiss as [user.p_they()] punch[user.p_es()] [target.name]!"), \ span_userdanger("You cry out in pain as [user]'s punch flings you backwards!")) new /obj/effect/temp_visual/kinetic_blast(target.loc) @@ -103,18 +120,27 @@ var/atom/throw_target = get_edge_target_turf(target, get_dir(src, get_step_away(target, src))) - target.throw_at(throw_target, 5 * fisto_setting, 0.5 + (fisto_setting / 2)) + if(!target.anchored) + target.throw_at(throw_target, 5 * fisto_setting, 0.5 + (fisto_setting / 2)) log_combat(user, target, "power fisted", src) - user.changeNext_move(CLICK_CD_MELEE * click_delay) + return COMPONENT_NO_ATTACK_HAND - return +/obj/item/clothing/gloves/powerfist/proc/do_attack(mob/living/user, atom/target, punch_force) + if(isliving(target)) + var/mob/living/target_mob = target + target_mob.apply_damage(punch_force, BRUTE, wound_bonus = CANT_WOUND) + else if(isobj(target)) + var/obj/target_obj = target + target_obj.take_damage(punch_force, BRUTE, MELEE, FALSE) + user.do_attack_animation(target, ATTACK_EFFECT_SMASH) + user.changeNext_move(CLICK_CD_MELEE * click_delay) -/obj/item/melee/powerfist/filled +/obj/item/clothing/gloves/powerfist/filled var/obj/item/tank/internals/plasma/full/fire -/obj/item/melee/powerfist/filled/Initialize(mapload) +/obj/item/clothing/gloves/powerfist/filled/Initialize(mapload) . = ..() fire = new(src) tank = fire diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm index c521b30fef2a..d896615dbf01 100644 --- a/code/game/objects/items/religion.dm +++ b/code/game/objects/items/religion.dm @@ -325,11 +325,11 @@ name = "Plate Gauntlets" icon_state = "crusader" desc = "They're like gloves, but made of metal." - siemens_coefficient = 0 cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 0, ELECTRIC = 100) /obj/item/clothing/gloves/plate/red icon_state = "crusader-red" diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index cb459e0914fc..c7baf90124e5 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -133,7 +133,7 @@ if(scooldown < world.time) if(M.health >= 0) if(ishuman(M)||ismonkey(M)) - M.electrocute_act(5, "[user]", safety = 1, tesla_shock = 1) + M.electrocute_act(5, "[user]", zone=user.zone_selected, tesla_shock = 1) user.visible_message(span_userdanger("[user] electrocutes [M] with [user.p_their()] touch!"), \ span_danger("You electrocute [M] with your touch!")) M.update_mobility() diff --git a/code/game/objects/items/singularityhammer.dm b/code/game/objects/items/singularityhammer.dm index 5e33dee24d33..d5d4ba24e585 100644 --- a/code/game/objects/items/singularityhammer.dm +++ b/code/game/objects/items/singularityhammer.dm @@ -21,7 +21,6 @@ . = ..() START_PROCESSING(SSobj, src) AddComponent(/datum/component/two_handed, \ - force_unwielded = 5, \ force_wielded = 15, \ icon_wielded = "[base_icon_state]1", \ ) @@ -98,7 +97,6 @@ /obj/item/mjolnir/Initialize(mapload) . = ..() AddComponent(/datum/component/two_handed, \ - force_unwielded = 5, \ force_wielded = 20, \ icon_wielded = "[base_icon_state]1", \ ) diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 3b81adcb57f1..18a930acbb04 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -199,6 +199,18 @@ GLOBAL_LIST_INIT(plasma_recipes, list ( \ atmos_spawn_air("plasma=[amount*10];TEMP=[exposed_temperature]") qdel(src) +/obj/item/stack/sheet/mineral/plasma/bullet_act(obj/projectile/P) + . = ..() + if(!QDELETED(src) && !P.nodamage && ((P.damage_type == BURN))) + var/turf/T = get_turf(src) + if(P.firer) + message_admins("Plasma stack ([amount]) ignited by [ADMIN_LOOKUPFLW(P.firer)] in [ADMIN_VERBOSEJMP(T)]") + log_game("Plasma stack ([amount]) ignited by [key_name(P.firer)] in [AREACOORD(T)]") + else + message_admins("Plasma stack ([amount]) ignited by [P]. No known firer, in [ADMIN_VERBOSEJMP(T)]") + log_game("Plasma stack ([amount]) ignited by [P] in [AREACOORD(T)]. No known firer.") + fire_act(2500) + /* * Gold */ diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 35ec28b5e3e5..b28344641425 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -223,7 +223,6 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ new/datum/stack_recipe("rolling pin", /obj/item/kitchen/rollingpin, 2, time = 30), \ new/datum/stack_recipe("tiki mask", /obj/item/clothing/mask/gas/tiki_mask, 2), \ new/datum/stack_recipe("winged wooden chair", /obj/structure/chair/wood/wings, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \ - new/datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20), \ new/datum/stack_recipe("wood table frame", /obj/structure/table_frame/wood, 2, time = 10), \ new/datum/stack_recipe("wooden barricade", /obj/structure/barricade/wooden, 5, time = 50, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/glass/bucket/wooden, 3, time = 10),\ @@ -233,6 +232,12 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ new/datum/stack_recipe("wooden door", /obj/structure/mineral_door/wood, 10, time = 20, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("wooden sandals", /obj/item/clothing/shoes/sandal, 1), \ + new/datum/stack_recipe_list("floor tiles", list( \ + new/datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20), \ + new/datum/stack_recipe("parquet wood floor tile", /obj/item/stack/tile/wood/parquet, 1, 4, 20), \ + new/datum/stack_recipe("large wood floor tile", /obj/item/stack/tile/wood/large, 1, 4, 20), \ + new/datum/stack_recipe("tiled wood floor tile", /obj/item/stack/tile/wood/tile, 1, 4, 20), \ + )), \ null, \ new/datum/stack_recipe_list("pews", list( new /datum/stack_recipe("pew (left)", /obj/structure/chair/pew/left, 3, one_per_turf = TRUE, on_floor = TRUE), diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index 8f0808ac5bda..6d9365afbb8f 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -153,6 +153,24 @@ turf_type = /turf/open/floor/wood resistance_flags = FLAMMABLE +/obj/item/stack/tile/wood/parquet + name = "parquet wood floor tile" + singular_name = "parquet wood floor tile" + icon_state = "tile-wood_parquet" + turf_type = /turf/open/floor/wood/parquet + +/obj/item/stack/tile/wood/large + name = "large wood floor tile" + singular_name = "large wood floor tile" + icon_state = "tile-wood_large" + turf_type = /turf/open/floor/wood/large + +/obj/item/stack/tile/wood/tile + name = "tiled wood floor tile" + singular_name = "tiled wood floor tile" + icon_state = "tile-wood_tile" + turf_type = /turf/open/floor/wood/tile + //Bamboo /obj/item/stack/tile/bamboo name = "bamboo mat pieces" diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm index 26e196ccf62d..c6fb03421780 100644 --- a/code/game/objects/items/storage/book.dm +++ b/code/game/objects/items/storage/book.dm @@ -86,7 +86,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "burning", var/obj/item/clothing/gloves/color/fyellow/insuls = new insuls.name = "insuls" insuls.desc = "A mere copy of the true insuls." - insuls.siemens_coefficient = 0.99999 + insuls.armor.setRating(electric=0.001) H.equip_to_slot(insuls, ITEM_SLOT_GLOVES) GLOB.bible_icon_state = icon_state GLOB.bible_item_state = item_state diff --git a/code/game/objects/items/storage/lockbox.dm b/code/game/objects/items/storage/lockbox.dm index 98342c6c4910..2fce62a8bc34 100644 --- a/code/game/objects/items/storage/lockbox.dm +++ b/code/game/objects/items/storage/lockbox.dm @@ -78,19 +78,18 @@ togglelock(user) /obj/item/storage/lockbox/emp_act(severity) - switch(severity) - if(EMP_HEAVY) - emag_act() - if(EMP_LIGHT) - if(prob(60)) - var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED) - SEND_SIGNAL(src, COMSIG_TRY_STORAGE_SET_LOCKSTATE, !locked) - locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED) - if(locked) - icon_state = icon_locked - SEND_SIGNAL(src, COMSIG_TRY_STORAGE_HIDE_ALL) - else - icon_state = icon_closed + if(severity > EMP_LIGHT) + emag_act() + return + if(prob(6 * severity)) + var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED) + SEND_SIGNAL(src, COMSIG_TRY_STORAGE_SET_LOCKSTATE, !locked) + locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED) + if(locked) + icon_state = icon_locked + SEND_SIGNAL(src, COMSIG_TRY_STORAGE_HIDE_ALL) + else + icon_state = icon_closed /obj/item/storage/lockbox/loyalty name = "lockbox of mindshield implants" diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm index 0736463ba346..d7b7421bf7b5 100644 --- a/code/game/objects/items/stunbaton.dm +++ b/code/game/objects/items/stunbaton.dm @@ -257,7 +257,7 @@ /obj/item/melee/baton/emp_act(severity) . = ..() if (!(. & EMP_PROTECT_SELF)) - deductcharge(1000 / severity) + deductcharge(100 * severity) //Makeshift stun baton. Replacement for stun gloves. /obj/item/melee/baton/cattleprod diff --git a/code/game/objects/items/supermatter_delaminator.dm b/code/game/objects/items/supermatter_delaminator.dm index 08463ca7b125..2624ca7c7575 100644 --- a/code/game/objects/items/supermatter_delaminator.dm +++ b/code/game/objects/items/supermatter_delaminator.dm @@ -201,7 +201,7 @@ investigate_log("has consumed [key_name(user)].", "supermatter") user.dust() radiation_pulse(src, 500, 2) - empulse(src, 5, 10) + empulse(src, EMP_HEAVY) playsound(src, 'sound/effects/supermatter.ogg', 50, 1) QDEL_NULL(shard) update_appearance(UPDATE_ICON) diff --git a/code/game/objects/items/tanks/jetpack.dm b/code/game/objects/items/tanks/jetpack.dm index 53ead5abe5ef..d33469f42132 100644 --- a/code/game/objects/items/tanks/jetpack.dm +++ b/code/game/objects/items/tanks/jetpack.dm @@ -9,7 +9,7 @@ distribute_pressure = ONE_ATMOSPHERE * O2STANDARD actions_types = list(/datum/action/item_action/set_internals, /datum/action/item_action/toggle_jetpack, /datum/action/item_action/jetpack_stabilization) cryo_preserve = TRUE - var/gas_type = /datum/gas/oxygen + var/gas_type = GAS_O2 var/on = FALSE var/stabilizers = FALSE var/full_speed = TRUE // If the jetpack will have a speedboost in space/nograv or not @@ -90,13 +90,7 @@ turn_off(user) return - var/datum/gas_mixture/removed = air_contents.remove(num) - if(removed.total_moles() < 0.005) - turn_off(user) - return - - var/turf/T = get_turf(user) - T.assume_air(removed) + assume_air_moles(air_contents, num) return TRUE @@ -129,13 +123,7 @@ turn_off(user) return - var/datum/gas_mixture/removed = air_contents.remove(num) - if(removed.total_moles() < 0.005) - turn_off(user) - return - - var/turf/T = get_turf(user) - T.assume_air(removed) + assume_air_moles(air_contents, num) return TRUE @@ -185,7 +173,7 @@ icon_state = "jetpack-black" item_state = "jetpack-black" distribute_pressure = 0 - gas_type = /datum/gas/carbon_dioxide + gas_type = GAS_CO2 /obj/item/tank/jetpack/suit diff --git a/code/game/objects/items/tanks/tank_types.dm b/code/game/objects/items/tanks/tank_types.dm index cd72c64e4858..b6c02c3494ca 100644 --- a/code/game/objects/items/tanks/tank_types.dm +++ b/code/game/objects/items/tanks/tank_types.dm @@ -30,7 +30,7 @@ /obj/item/tank/internals/oxygen/populate_gas() - air_contents.set_moles(/datum/gas/oxygen, (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) + air_contents.set_moles(GAS_O2, (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) /obj/item/tank/internals/oxygen/yellow @@ -62,8 +62,8 @@ force = 10 /obj/item/tank/internals/anesthetic/populate_gas() - air_contents.set_moles(/datum/gas/oxygen, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD) - air_contents.set_moles(/datum/gas/nitrous_oxide, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD) + air_contents.set_moles(GAS_O2, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD) + air_contents.set_moles(GAS_NITROUS, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD) /* * Air @@ -77,8 +77,8 @@ dog_fashion = /datum/dog_fashion/back /obj/item/tank/internals/air/populate_gas() - air_contents.set_moles(/datum/gas/oxygen, (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD) - air_contents.set_moles(/datum/gas/nitrogen, (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD) + air_contents.set_moles(GAS_O2, (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD) + air_contents.set_moles(GAS_N2, (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD) /* * Plasma @@ -94,7 +94,7 @@ /obj/item/tank/internals/plasma/populate_gas() - air_contents.set_moles(/datum/gas/plasma, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) + air_contents.set_moles(GAS_PLASMA, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) /obj/item/tank/internals/plasma/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/flamethrower)) @@ -110,7 +110,7 @@ return ..() /obj/item/tank/internals/plasma/full/populate_gas() - air_contents.set_moles(/datum/gas/plasma, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) + air_contents.set_moles(GAS_PLASMA, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) /obj/item/tank/internals/plasma/empty/populate_gas() return @@ -128,10 +128,10 @@ distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE /obj/item/tank/internals/plasmaman/populate_gas() - air_contents.set_moles(/datum/gas/plasma, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) + air_contents.set_moles(GAS_PLASMA, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) /obj/item/tank/internals/plasmaman/full/populate_gas() - air_contents.set_moles(/datum/gas/plasma, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) + air_contents.set_moles(GAS_PLASMA, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) /obj/item/tank/internals/plasmaman/belt @@ -143,7 +143,7 @@ w_class = WEIGHT_CLASS_SMALL //thanks i forgot this /obj/item/tank/internals/plasmaman/belt/full/populate_gas() - air_contents.set_moles(/datum/gas/plasma, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) + air_contents.set_moles(GAS_PLASMA, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) /obj/item/tank/internals/plasmaman/belt/empty/populate_gas() return @@ -166,7 +166,7 @@ /obj/item/tank/internals/emergency_oxygen/populate_gas() - air_contents.set_moles(/datum/gas/oxygen, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) + air_contents.set_moles(GAS_O2, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) /obj/item/tank/internals/emergency_oxygen/empty/populate_gas() @@ -200,7 +200,7 @@ distribute_pressure = 8 /obj/item/tank/internals/ipc_coolant/populate_gas() - air_contents.set_moles(/datum/gas/nitrogen, (10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * (T0C - 50))) + air_contents.set_moles(GAS_N2, (10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * (T0C - 50))) air_contents.set_temperature(T0C - 50) /obj/item/tank/internals/ipc_coolant/empty/populate_gas() diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index 8816fec2a7d7..41483a0b7a6f 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -138,7 +138,6 @@ var/turf/T = get_turf(src) if(T) T.assume_air(air_contents) - air_update_turf() playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3) qdel(src) @@ -230,6 +229,9 @@ /obj/item/tank/remove_air(amount) return air_contents.remove(amount) +/obj/item/tank/remove_air_ratio(ratio) + return air_contents.remove_ratio(ratio) + /obj/item/tank/return_air() return air_contents @@ -242,6 +244,18 @@ check_status() return 1 +/obj/item/tank/assume_air_moles(datum/gas_mixture/giver, moles) + giver.transfer_to(air_contents, moles) + + check_status() + return TRUE + +/obj/item/tank/assume_air_ratio(datum/gas_mixture/giver, ratio) + giver.transfer_ratio_to(air_contents, ratio) + + check_status() + return TRUE + /obj/item/tank/proc/remove_air_volume(volume_to_return) if(!air_contents) return null @@ -417,7 +431,7 @@ update_appearance(UPDATE_ICON) /obj/item/tank/proc/ignite() //This happens when a bomb is told to explode - var/fuel_moles = air_contents.get_moles(/datum/gas/tritium) + air_contents.get_moles(/datum/gas/hydrogen) + air_contents.get_moles(/datum/gas/plasma) + air_contents.get_moles(/datum/gas/oxygen)/6 + var/fuel_moles = air_contents.get_moles(GAS_TRITIUM) + air_contents.get_moles(GAS_H2) + air_contents.get_moles(GAS_PLASMA) + air_contents.get_moles(GAS_O2)/6 var/datum/gas_mixture/bomb_mixture = air_contents.copy() var/strength = 1 @@ -464,12 +478,9 @@ ground_zero.assume_air(bomb_mixture) ground_zero.hotspot_expose(1000, 125) - ground_zero.air_update_turf() - /obj/item/tank/proc/release() //This happens when the bomb is not welded. Tank contents are just spat out. var/datum/gas_mixture/removed = air_contents.remove(air_contents.total_moles()) var/turf/T = get_turf(src) if(!T) return T.assume_air(removed) - air_update_turf() diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm index 3f84093da693..027d16615440 100644 --- a/code/game/objects/items/tools/crowbar.dm +++ b/code/game/objects/items/tools/crowbar.dm @@ -10,6 +10,7 @@ slot_flags = ITEM_SLOT_BELT force = 5 throwforce = 7 + demolition_mod = 2 // the right tool in the wrong place can make all the difference w_class = WEIGHT_CLASS_SMALL materials = list(/datum/material/iron=50) drop_sound = 'sound/items/handling/crowbar_drop.ogg' diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm index 2db3040fec34..12a0bbacda73 100644 --- a/code/game/objects/items/tools/screwdriver.dm +++ b/code/game/objects/items/tools/screwdriver.dm @@ -9,6 +9,7 @@ flags_1 = CONDUCT_1 slot_flags = ITEM_SLOT_BELT force = 5 + demolition_mod = 0.5 w_class = WEIGHT_CLASS_TINY throwforce = 5 throw_speed = 3 diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index f69488465225..5470eef922ec 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -23,6 +23,7 @@ light_on = FALSE throw_speed = 3 throw_range = 5 + demolition_mod = 0.5 // not very good at smashing w_class = WEIGHT_CLASS_SMALL armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 30) resistance_flags = FIRE_PROOF @@ -225,6 +226,7 @@ playsound(loc, acti_sound, 50, 1) force = 12 damtype = BURN + demolition_mod = 1.5 // pretty good at cutting hitsound = 'sound/items/welder.ogg' update_appearance(UPDATE_ICON) START_PROCESSING(SSobj, src) @@ -243,6 +245,7 @@ force = 3 damtype = "brute" hitsound = "swing_hit" + demolition_mod = initial(demolition_mod) update_appearance(UPDATE_ICON) diff --git a/code/game/objects/items/tools/wrench.dm b/code/game/objects/items/tools/wrench.dm index 2ff293b763cd..fcd948da6187 100644 --- a/code/game/objects/items/tools/wrench.dm +++ b/code/game/objects/items/tools/wrench.dm @@ -9,6 +9,7 @@ slot_flags = ITEM_SLOT_BELT force = 5 throwforce = 7 + demolition_mod = 1.5 w_class = WEIGHT_CLASS_SMALL usesound = 'sound/items/ratchet.ogg' materials = list(/datum/material/iron=150) diff --git a/code/game/objects/items/two_handed/broom.dm b/code/game/objects/items/two_handed/broom.dm index 929c0759e5a9..45f8f4c0c748 100644 --- a/code/game/objects/items/two_handed/broom.dm +++ b/code/game/objects/items/two_handed/broom.dm @@ -19,7 +19,6 @@ /obj/item/broom/Initialize(mapload) . = ..() AddComponent(/datum/component/two_handed, \ - force_unwielded = 8, \ force_wielded = 4, \ icon_wielded = "[base_icon_state]1", \ wield_callback = CALLBACK(src, PROC_REF(on_wield)), \ diff --git a/code/game/objects/items/two_handed/chainsaw.dm b/code/game/objects/items/two_handed/chainsaw.dm index 38e447b0d432..9aa4aa9affe9 100644 --- a/code/game/objects/items/two_handed/chainsaw.dm +++ b/code/game/objects/items/two_handed/chainsaw.dm @@ -14,6 +14,7 @@ throwforce = 13 throw_speed = 2 throw_range = 4 + demolition_mod = 1.5 materials = list(/datum/material/iron=13000) attack_verb = list("sawed", "torn", "cut", "chopped", "diced") hitsound = "swing_hit" diff --git a/code/game/objects/items/two_handed/dualsaber.dm b/code/game/objects/items/two_handed/dualsaber.dm index 78df5f0e21e3..e369a884d41c 100644 --- a/code/game/objects/items/two_handed/dualsaber.dm +++ b/code/game/objects/items/two_handed/dualsaber.dm @@ -50,7 +50,6 @@ set_light_color(new_color) AddComponent(/datum/component/two_handed, \ - force_unwielded = force, \ force_wielded = force_wielded, \ icon_wielded = "[base_icon_state][saber_color]1", \ wieldsound = 'sound/weapons/saberon.ogg', \ @@ -94,7 +93,7 @@ /obj/item/melee/dualsaber/attack(mob/target, mob/living/carbon/human/user) if(user.has_dna()) - if(user.dna.check_mutation(HULK) || user.dna.check_mutation(ACTIVE_HULK)) + if(user.dna.check_mutation(HULK)) to_chat(user, span_warning("You grip the blade too hard and accidentally close it!")) if(HAS_TRAIT(src, TRAIT_WIELDED)) user.dropItemToGround(src, force=TRUE) @@ -184,7 +183,7 @@ /obj/item/melee/dualsaber/proc/on_wield(atom/source, mob/living/carbon/M) if(!M.has_dna()) return - if(M.dna.check_mutation(HULK) || M.dna.check_mutation(ACTIVE_HULK)) + if(M.dna.check_mutation(HULK)) to_chat(M, span_warning("You lack the grace to wield this!")) return sharpness = SHARP_EDGED diff --git a/code/game/objects/items/two_handed/fireaxe.dm b/code/game/objects/items/two_handed/fireaxe.dm index d61023b7b344..16b1bc27484d 100644 --- a/code/game/objects/items/two_handed/fireaxe.dm +++ b/code/game/objects/items/two_handed/fireaxe.dm @@ -8,6 +8,7 @@ desc = "Truly, the weapon of a madman. Who would think to fight fire with an axe?" force = 5 throwforce = 15 + demolition_mod = 3 // specifically designed for breaking things w_class = WEIGHT_CLASS_BULKY slot_flags = ITEM_SLOT_BACK attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut", "axed") @@ -19,13 +20,12 @@ wound_bonus = -15 bare_wound_bonus = 20 - /// How much damage to do wielded - var/force_wielded = 24 + /// Bonus damage from wielding + var/force_wielded = 19 /obj/item/fireaxe/Initialize(mapload) . = ..() AddComponent(/datum/component/two_handed, \ - force_unwielded = force, \ force_wielded = force_wielded, \ icon_wielded = "[base_icon_state]1", \ ) @@ -43,6 +43,8 @@ . = ..() if(!proximity) return + if(QDELETED(A)) + return if(HAS_TRAIT(src, TRAIT_WIELDED)) //destroys shit faster, generally in 1-2 hits. if(istype(A, /obj/structure/window)) var/obj/structure/window/W = A @@ -50,12 +52,6 @@ else if(istype(A, /obj/structure/grille)) var/obj/structure/grille/G = A G.take_damage(G.max_integrity*2, BRUTE, MELEE, FALSE, null, armour_penetration) - else if(istype(A, /obj/machinery/door)) //Nines hits for reinforced airlock, seven for normal - var/obj/machinery/door/D = A - D.take_damage((force+25), BRUTE, MELEE, FALSE, null, armour_penetration) - else if(istype(A, /obj/structure/door_assembly)) //Two hits for frames left behind - var/obj/machinery/door/D = A - D.take_damage((force+25), BRUTE, MELEE, FALSE, null, armour_penetration) /* * Metal Hydrogen Axe @@ -86,6 +82,7 @@ icon = 'icons/obj/weapons/energy.dmi' icon_state = "energy-fireaxe0" base_icon_state = "energy-fireaxe" + demolition_mod = 4 // DESTROY armour_penetration = 50 // Probably doesn't care much for armor given how it can destroy solid metal structures block_chance = 50 // Big handle and large flat energy blade, good for blocking things heat = 1800 // It's a FIRE axe @@ -105,7 +102,6 @@ /obj/item/fireaxe/energy/Initialize(mapload) . = ..() AddComponent(/datum/component/two_handed, \ - force_unwielded = force, \ force_wielded = force_wielded, \ icon_wielded = "[base_icon_state]1", \ wieldsound = 'sound/weapons/saberon.ogg', \ @@ -132,15 +128,6 @@ ..() M.ignite_mob() // Ignites you if you're flammable -/obj/item/fireaxe/energy/afterattack(atom/A, mob/user, proximity) - . = ..() - if(!proximity) - return - if(HAS_TRAIT(src, TRAIT_WIELDED)) // Does x2 damage against inanimate objects like machines, structures, mechs, etc - if(isobj(A) && !isitem(A)) - var/obj/O = A - O.take_damage(force, BRUTE, MELEE, FALSE, null, armour_penetration) - /obj/item/fireaxe/energy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text, final_block_chance, damage, attack_type) if(!HAS_TRAIT(src, TRAIT_WIELDED)) return 0 // large energy blade can only block stuff if it's actually on diff --git a/code/game/objects/items/two_handed/highfrequencyblade.dm b/code/game/objects/items/two_handed/highfrequencyblade.dm index 5684a084ba55..40cd8a0c1a18 100644 --- a/code/game/objects/items/two_handed/highfrequencyblade.dm +++ b/code/game/objects/items/two_handed/highfrequencyblade.dm @@ -20,7 +20,6 @@ /obj/item/vibro_weapon/Initialize(mapload) . = ..() AddComponent(/datum/component/two_handed, \ - force_unwielded = force, \ force_wielded = 20, \ icon_wielded = "[base_icon_state]1", \ ) diff --git a/code/game/objects/items/two_handed/pitchfork.dm b/code/game/objects/items/two_handed/pitchfork.dm index dbe5f27016bf..21d96efaf729 100644 --- a/code/game/objects/items/two_handed/pitchfork.dm +++ b/code/game/objects/items/two_handed/pitchfork.dm @@ -16,13 +16,12 @@ armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 30) resistance_flags = FIRE_PROOF - ///How much damage the pitchfork will do while wielded. + ///How much extra damage the pitchfork will do while wielded. var/force_wielded = 8 /obj/item/pitchfork/Initialize(mapload) . = ..() AddComponent(/datum/component/two_handed, \ - force_unwielded = force, \ force_wielded = force_wielded, \ icon_wielded = "[base_icon_state]1", \ ) diff --git a/code/game/objects/items/two_handed/spears.dm b/code/game/objects/items/two_handed/spears.dm index 1133aa0ee564..d782903aeb09 100644 --- a/code/game/objects/items/two_handed/spears.dm +++ b/code/game/objects/items/two_handed/spears.dm @@ -26,7 +26,7 @@ wound_bonus = -15 bare_wound_bonus = 15 - ///How much damage to deal when wielded. + ///How much extra damage to deal when wielded. var/force_wielded = 8 ///Whether the spear can have an explosive attached to it. var/can_be_explosive = TRUE @@ -34,7 +34,6 @@ /obj/item/melee/spear/Initialize(mapload) . = ..() AddComponent(/datum/component/two_handed, \ - force_unwielded = force, \ force_wielded = force_wielded, \ icon_wielded = "[base_icon_state]1", \ wielded_stats = list(SWING_SPEED = 1, ENCUMBRANCE = 0.4, ENCUMBRANCE_TIME = 5, REACH = 2, DAMAGE_LOW = 2, DAMAGE_HIGH = 5), \ @@ -154,7 +153,6 @@ /obj/item/melee/spear/grey_tide/Initialize(mapload) . = ..() AddComponent(/datum/component/two_handed, \ - force_unwielded = force, \ force_wielded = force_wielded, \ icon_wielded = "[base_icon_state]1", \ wielded_stats = list(SWING_SPEED = 1, ENCUMBRANCE = 0, ENCUMBRANCE_TIME = 0, REACH = 2, DAMAGE_LOW = 0, DAMAGE_HIGH = 0), \ @@ -205,7 +203,6 @@ /obj/item/melee/spear/bonespear/Initialize(mapload) . = ..() AddComponent(/datum/component/two_handed, \ - force_unwielded = force, \ force_wielded = force_wielded, \ icon_wielded = "[base_icon_state]1", \ wielded_stats = list(SWING_SPEED = 1, ENCUMBRANCE = 0.4, ENCUMBRANCE_TIME = 5, REACH = 2, DAMAGE_LOW = 0, DAMAGE_HIGH = 0), \ diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 52e7e793e80a..9b0f45b5b393 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -80,7 +80,7 @@ playsound(src, P.hitsound, 50, 1) visible_message(span_danger("[src] is hit by \a [P]!"), null, null, COMBAT_MESSAGE_RANGE) if(!QDELETED(src)) //Bullet on_hit effect might have already destroyed this object - take_damage(P.damage, P.damage_type, P.armor_flag, 0, turn(P.dir, 180), P.armour_penetration) + take_damage(P.damage * P.demolition_mod, P.damage_type, P.armor_flag, 0, turn(P.dir, 180), P.armour_penetration) ///Called to get the damage that hulks will deal to the obj. /obj/proc/hulk_damage() diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 13fa98a11173..686438b8b836 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -16,6 +16,8 @@ var/wound_bonus = 0 /// If this attacks a human with no wound armor on the affected body part, add this to the wound mod. Some attacks may be significantly worse at wounding if there's even a slight layer of armor to absorb some of it vs bare flesh var/bare_wound_bonus = 0 + /// Damage multiplier against structures, machines, mechs, and to a lesser extent silicons + var/demolition_mod = 1 var/datum/armor/armor var/obj_integrity //defaults to max_integrity @@ -102,17 +104,39 @@ else return null +/obj/assume_air_moles(datum/gas_mixture/giver, moles) + if(loc) + return loc.assume_air_moles(giver, moles) + return null + +/obj/assume_air_ratio(datum/gas_mixture/giver, ratio) + if(loc) + return loc.assume_air_ratio(giver, ratio) + return null +/obj/transfer_air(datum/gas_mixture/taker, moles) + if(loc) + return loc.transfer_air(taker, moles) + return null + +/obj/transfer_air_ratio(datum/gas_mixture/taker, ratio) + if(loc) + return loc.transfer_air_ratio(taker, ratio) + return null + /obj/remove_air(amount) if(loc) return loc.remove_air(amount) - else - return null + return null + +/obj/remove_air_ratio(ratio) + if(loc) + return loc.remove_air_ratio(ratio) + return null /obj/return_air() if(loc) return loc.return_air() - else - return null + return null /obj/proc/handle_internal_lifeform(mob/lifeform_inside_me, breath_request) //Return: (NONSTANDARD) @@ -122,8 +146,7 @@ if(breath_request>0) var/datum/gas_mixture/environment = return_air() - var/breath_percentage = BREATH_VOLUME / environment.return_volume() - return remove_air(environment.total_moles() * breath_percentage) + return remove_air_ratio(BREATH_VOLUME / environment.return_volume()) else return null diff --git a/code/game/objects/structures/aliens.dm b/code/game/objects/structures/aliens.dm index 7b301ddadc60..8837107f9cb7 100644 --- a/code/game/objects/structures/aliens.dm +++ b/code/game/objects/structures/aliens.dm @@ -55,7 +55,7 @@ icon = 'icons/obj/smooth_structures/alien/resin_wall.dmi' icon_state = "smooth" density = TRUE - opacity = 1 + opacity = TRUE anchored = TRUE canSmoothWith = list(/obj/structure/alien/resin) max_integrity = 200 @@ -66,7 +66,7 @@ /obj/structure/alien/resin/Initialize(mapload) . = ..() - air_update_turf(TRUE) + air_update_turf() /obj/structure/alien/resin/Move() var/turf/T = loc @@ -81,7 +81,7 @@ resintype = "wall" canSmoothWith = list(/obj/structure/alien/resin/wall, /obj/structure/alien/resin/membrane) -/obj/structure/alien/resin/wall/BlockSuperconductivity() +/obj/structure/alien/resin/wall/BlockThermalConductivity() return 1 /obj/structure/alien/resin/membrane @@ -89,7 +89,7 @@ desc = "Resin just thin enough to let light pass through." icon = 'icons/obj/smooth_structures/alien/resin_membrane.dmi' icon_state = "smooth" - opacity = 0 + opacity = FALSE max_integrity = 160 resintype = "membrane" canSmoothWith = list(/obj/structure/alien/resin/wall, /obj/structure/alien/resin/membrane) diff --git a/code/game/objects/structures/barsigns.dm b/code/game/objects/structures/barsigns.dm index e6c35e8eb24f..36e45204be9f 100644 --- a/code/game/objects/structures/barsigns.dm +++ b/code/game/objects/structures/barsigns.dm @@ -293,6 +293,51 @@ icon = "thegoose" desc = "A nice place to hang loose and relax, while enjoying some electrifying drinks." +/datum/barsign/tearoom + name = "Little Treats Tea Room" + icon = "little_treats" + desc = "A delightfully relaxing tearoom for all the fancy lads in the cosmos." + +/datum/barsign/le_cafe_silencieux + name = "Le Café Silencieux" + icon = "le_cafe_silencieux" + desc = "..." + +/datum/barsign/maltroach + name = "Maltroach" + icon = "maltroach" + desc = "Mothroaches politely greet you into the bar, or are they greeting eachother?" + +/datum/barsign/rock_bottom + name = "Rock Bottom" + icon = "rock-bottom" + desc = "When it feels like you're stuck in a pit, might as well have a drink." + +/datum/barsign/assembly_line + name = "The Assembly Line" + icon = "the-assembly-line" + desc = "Where every drink is masterfully crafted with industrial efficiency!" + +/datum/barsign/bargonia + name = "Bargonia" + icon = "bargonia" + desc = "The warehouse yearns for a higher calling... so Supply has declared BARGONIA!" + +/datum/barsign/cult_cove + name = "Cult Cove" + icon = "cult-cove" + desc = "Nar'Sie's favourite retreat" + +/datum/barsign/neon_flamingo + name = "Neon Flamingo" + icon = "neon-flamingo" + desc = "A bus for all but the flamboyantly challenged." + +/datum/barsign/slowdive + name = "Slowdive" + icon = "slowdive" + desc = "First stop out of hell, last stop before heaven." + /datum/barsign/hiddensigns hidden = TRUE diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 6aefe0e9fb8e..66d75d7e3125 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -550,10 +550,10 @@ GLOBAL_LIST_EMPTY(lockers) for(var/obj/O in src) O.emp_act(severity) if(secure && !broken && !(. & EMP_PROTECT_SELF)) - if(prob(50 / severity)) + if(prob(5 * severity)) locked = !locked update_appearance(UPDATE_ICON) - if(prob(20 / severity) && !opened) + if(prob(2 * severity) && !opened) if(!locked) open() else @@ -625,7 +625,6 @@ GLOBAL_LIST_EMPTY(lockers) var/remove_amount = (loc_air.total_moles() + air_contents.total_moles()) * air_contents.return_volume() / (loc_air.return_volume() + air_contents.return_volume()) loc.assume_air(air_contents) loc.remove_air(remove_amount) - loc.air_update_turf() air_contents = null /obj/structure/closet/return_air() diff --git a/code/game/objects/structures/crates_lockers/closets/bodybag.dm b/code/game/objects/structures/crates_lockers/closets/bodybag.dm index 63fdda6bd680..536d10fe4b5c 100644 --- a/code/game/objects/structures/crates_lockers/closets/bodybag.dm +++ b/code/game/objects/structures/crates_lockers/closets/bodybag.dm @@ -336,8 +336,8 @@ air_contents = null air_contents = new(50) // liters air_contents.set_temperature(T20C) - air_contents.set_moles(/datum/gas/oxygen, (ONE_ATMOSPHERE*50)/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD) - air_contents.set_moles(/datum/gas/nitrous_oxide, (ONE_ATMOSPHERE*50)/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD) + air_contents.set_moles(GAS_O2, (ONE_ATMOSPHERE*50)/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD) + air_contents.set_moles(GAS_NITROUS, (ONE_ATMOSPHERE*50)/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD) /obj/structure/closet/body_bag/environmental/prisoner/syndicate/Destroy() STOP_PROCESSING(SSobj, src) diff --git a/code/game/objects/structures/crates_lockers/crates/critter.dm b/code/game/objects/structures/crates_lockers/crates/critter.dm index c376d57616fa..6b3f7269f587 100644 --- a/code/game/objects/structures/crates_lockers/crates/critter.dm +++ b/code/game/objects/structures/crates_lockers/crates/critter.dm @@ -39,7 +39,7 @@ if(tank) return tank.air_contents else - return loc.return_air() + return loc?.return_air() /obj/structure/closet/crate/critter/return_analyzable_air() if(tank) diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index 874b1a6c51a8..3ca29103d44a 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -9,7 +9,7 @@ icon_state = "wall" layer = CLOSED_TURF_LAYER density = TRUE - opacity = 1 + opacity = TRUE max_integrity = 100 canSmoothWith = list( @@ -35,7 +35,7 @@ /obj/structure/falsewall/Initialize(mapload) . = ..() - air_update_turf(TRUE) + air_update_turf() /obj/structure/falsewall/ratvar_act() new /obj/structure/falsewall/brass(loc) @@ -68,7 +68,7 @@ set_opacity(density) opening = FALSE update_appearance(UPDATE_ICON) - air_update_turf(TRUE) + air_update_turf() /obj/structure/falsewall/update_icon_state() . = ..() diff --git a/code/game/objects/structures/fluff.dm b/code/game/objects/structures/fluff.dm index 3d998428ee39..399d554f2102 100644 --- a/code/game/objects/structures/fluff.dm +++ b/code/game/objects/structures/fluff.dm @@ -7,7 +7,7 @@ icon_state = "minibar" anchored = TRUE density = FALSE - opacity = 0 + opacity = FALSE var/deconstructible = TRUE /obj/structure/fluff/attackby(obj/item/I, mob/living/user, params) diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index 6ef5f6841c6e..b8058ba0791c 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -702,7 +702,7 @@ GLOBAL_LIST_EMPTY(servant_golem_users) short_desc = "After becoming disillusioned with society, you chose a life here with the ice and snow." roundstart = FALSE death = FALSE - flavour_text = "After becoming disillusioned with society, you chose a life here with the ice and snow." + flavour_text = "Your solitude might be threatened by the new Nanotrasen facility constructed nearby, but it also might offer minor comforts and services that you haven't experienced in years." icon = 'icons/obj/machines/sleeper.dmi' icon_state = "sleeper" outfit = /datum/outfit/ice_hermit diff --git a/code/game/objects/structures/guncase.dm b/code/game/objects/structures/guncase.dm index 6d969b87dd78..4eee49f9990c 100644 --- a/code/game/objects/structures/guncase.dm +++ b/code/game/objects/structures/guncase.dm @@ -6,7 +6,7 @@ icon_state = "shotguncase" anchored = FALSE density = TRUE - opacity = 0 + opacity = FALSE var/case_type = "" var/gun_category = /obj/item/gun var/open = TRUE diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm index 4765c9a98f12..e6f3ac779793 100644 --- a/code/game/objects/structures/holosign.dm +++ b/code/game/objects/structures/holosign.dm @@ -134,7 +134,7 @@ /obj/structure/holosign/barrier/atmos/Initialize(mapload) . = ..() - air_update_turf(TRUE) + air_update_turf() /obj/structure/holosign/barrier/cyborg name = "Energy Field" @@ -284,7 +284,7 @@ if(!shockcd) if(ismob(user)) var/mob/living/M = user - M.electrocute_act(15,"Energy Barrier", safety=1) + M.electrocute_act(15,"Energy Barrier", zone=user.held_index_to_body_zone(user.active_hand_index)) // you touched it with your hand shockcd = TRUE addtimer(CALLBACK(src, PROC_REF(cooldown)), 5) @@ -296,6 +296,6 @@ return var/mob/living/M = AM - M.electrocute_act(15,"Energy Barrier", safety=1) + M.electrocute_act(15,"Energy Barrier", zone=null) shockcd = TRUE addtimer(CALLBACK(src, PROC_REF(cooldown)), 5) diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm index 67204afc2eeb..c05798db10ab 100644 --- a/code/game/objects/structures/mineral_doors.dm +++ b/code/game/objects/structures/mineral_doors.dm @@ -29,7 +29,7 @@ /obj/structure/mineral_door/Initialize(mapload) . = ..() - air_update_turf(TRUE) + air_update_turf() /obj/structure/mineral_door/Move() var/turf/T = loc @@ -94,7 +94,7 @@ density = FALSE door_opened = TRUE layer = OPEN_DOOR_LAYER - air_update_turf(1) + air_update_turf() update_appearance(UPDATE_ICON) isSwitchingStates = FALSE @@ -115,7 +115,7 @@ set_opacity(TRUE) door_opened = FALSE layer = initial(layer) - air_update_turf(1) + air_update_turf() update_appearance(UPDATE_ICON) isSwitchingStates = FALSE @@ -134,7 +134,7 @@ /obj/structure/mineral_door/setAnchored(anchorvalue) //called in default_unfasten_wrench() chain . = ..() set_opacity(anchored ? !door_opened : FALSE) - air_update_turf(TRUE) + air_update_turf() /obj/structure/mineral_door/wrench_act(mob/living/user, obj/item/I) default_unfasten_wrench(user, I, 40) diff --git a/code/game/objects/structures/plasticflaps.dm b/code/game/objects/structures/plasticflaps.dm index a47afc12f122..5a4394975542 100644 --- a/code/game/objects/structures/plasticflaps.dm +++ b/code/game/objects/structures/plasticflaps.dm @@ -103,10 +103,10 @@ /obj/structure/plasticflaps/Initialize(mapload) . = ..() - air_update_turf(TRUE) + air_update_turf() /obj/structure/plasticflaps/Destroy() var/atom/oldloc = loc . = ..() if (oldloc) - oldloc.air_update_turf(1) + oldloc.air_update_turf() diff --git a/code/game/objects/structures/railings.dm b/code/game/objects/structures/railings.dm index 3b33ffcc7404..728282c02ca5 100644 --- a/code/game/objects/structures/railings.dm +++ b/code/game/objects/structures/railings.dm @@ -110,6 +110,5 @@ return TRUE /obj/structure/railing/proc/after_rotation(mob/user,rotation_type) - air_update_turf(1) ini_dir = dir add_fingerprint(user) diff --git a/code/game/objects/structures/signs/_signs.dm b/code/game/objects/structures/signs/_signs.dm index 7391d088457f..912a4dac333a 100644 --- a/code/game/objects/structures/signs/_signs.dm +++ b/code/game/objects/structures/signs/_signs.dm @@ -1,7 +1,7 @@ /obj/structure/sign icon = 'icons/obj/decals.dmi' anchored = TRUE - opacity = 0 + opacity = FALSE density = FALSE layer = SIGN_LAYER max_integrity = 100 diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm index 96b932d81924..bf336c208e80 100644 --- a/code/game/objects/structures/transit_tubes/station.dm +++ b/code/game/objects/structures/transit_tubes/station.dm @@ -177,11 +177,9 @@ sleep(OPEN_DURATION + 0.2 SECONDS) pod_moving = FALSE if(!QDELETED(pod)) - var/datum/gas_mixture/floor_mixture = loc.return_air() - floor_mixture.archive() - pod.air_contents.archive() - pod.air_contents.share(floor_mixture, 1) //mix the pod's gas mixture with the tile it's on - air_update_turf() + var/datum/gas_mixture/floor_mixture = loc?.return_air() + if(floor_mixture) + equalize_all_gases_in_list(list(pod.air_contents,floor_mixture)) /obj/structure/transit_tube/station/init_tube_dirs() switch(dir) diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm index 843b93e57cc0..2b8c1f72a377 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm @@ -10,8 +10,8 @@ /obj/structure/transit_tube_pod/Initialize(mapload) . = ..() - air_contents.set_moles(/datum/gas/oxygen, MOLES_O2STANDARD) - air_contents.set_moles(/datum/gas/nitrogen, MOLES_N2STANDARD) + air_contents.set_moles(GAS_O2, MOLES_O2STANDARD) + air_contents.set_moles(GAS_N2, MOLES_N2STANDARD) air_contents.set_temperature(T20C) @@ -166,9 +166,24 @@ /obj/structure/transit_tube_pod/assume_air(datum/gas_mixture/giver) return air_contents.merge(giver) +/obj/structure/transit_tube_pod/assume_air_moles(datum/gas_mixture/giver, moles) + return giver.transfer_to(air_contents, moles) + +/obj/structure/transit_tube_pod/assume_air_ratio(datum/gas_mixture/giver, ratio) + return giver.transfer_ratio_to(air_contents, ratio) + /obj/structure/transit_tube_pod/remove_air(amount) return air_contents.remove(amount) +/obj/structure/transit_tube_pod/remove_air_ratio(ratio) + return air_contents.remove_ratio(ratio) + +/obj/structure/transit_tube_pod/transfer_air(datum/gas_mixture/taker, moles) + return air_contents.transfer_to(taker, moles) + +/obj/structure/transit_tube_pod/transfer_air_ratio(datum/gas_mixture/taker, ratio) + return air_contents.transfer_ratio_to(taker, ratio) + /obj/structure/transit_tube_pod/relaymove(mob/mob, direction) if(istype(mob) && mob.client) if(!moving) diff --git a/code/game/objects/structures/traps.dm b/code/game/objects/structures/traps.dm index a521f8b2fd7e..9bc5785e2a85 100644 --- a/code/game/objects/structures/traps.dm +++ b/code/game/objects/structures/traps.dm @@ -85,7 +85,7 @@ icon_state = "trap-shock" /obj/structure/trap/stun/trap_effect(mob/living/L) - L.electrocute_act(30, src, safety=1) // electrocute act does a message. + L.electrocute_act(30, src, zone=null, override=TRUE) // electrocute act does a message. L.Paralyze(100) /obj/structure/trap/fire diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 3ff6fd6ee3ba..c1050969b625 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -274,15 +274,19 @@ to_chat(user, span_warning("Someone's already washing here!")) return - if(istype(O, /obj/item/reagent_containers)) - var/obj/item/reagent_containers/RG = O - if(RG.is_refillable()) - if(!RG.reagents.holder_full()) - RG.reagents.add_reagent(dispensedreagent, min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this)) - to_chat(user, span_notice("You fill [RG] from [src].")) - return TRUE - to_chat(user, span_notice("\The [RG] is full.")) - return FALSE + // If it's refillable, fill it up + if(O.is_refillable()) + if(!O.reagents.holder_full()) + var/transfer_amount = 10 + if(istype(O, /obj/item/reagent_containers)) + var/obj/item/reagent_containers/R = O + transfer_amount = R.amount_per_transfer_from_this + O.reagents.add_reagent(dispensedreagent, min(O.reagents.maximum_volume - O.reagents.total_volume, transfer_amount)) + to_chat(user, span_notice("You fill [O] from [src].")) + playsound(loc, 'sound/effects/slosh.ogg', 25, 1) + return TRUE + to_chat(user, span_notice("\The [O] is full.")) + return FALSE if(istype(O, /obj/item/melee/baton)) var/obj/item/melee/baton/B = O @@ -298,12 +302,6 @@ playsound(src, "sparks", 50, 1) return - if(istype(O, /obj/item/mop)) - O.reagents.add_reagent(dispensedreagent, 5) - to_chat(user, span_notice("You wet [O] in [src].")) - playsound(loc, 'sound/effects/slosh.ogg', 25, 1) - return - if(istype(O, /obj/item/stack/medical/gauze)) var/obj/item/stack/medical/gauze/G = O new /obj/item/reagent_containers/glass/rag(src.loc) @@ -386,7 +384,7 @@ alpha = 200 //Mappers can also just set this to 255 if they want curtains that can't be seen through layer = SIGN_LAYER anchored = TRUE - opacity = 0 + opacity = FALSE density = FALSE var/open = TRUE @@ -401,14 +399,14 @@ layer = WALL_OBJ_LAYER density = TRUE open = FALSE - opacity = TRUE + set_opacity(TRUE) else icon_state = "open" layer = SIGN_LAYER density = FALSE open = TRUE - opacity = FALSE + set_opacity(FALSE) /obj/structure/curtain/attackby(obj/item/W, mob/user) if (istype(W, /obj/item/toy/crayon)) diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm index 5f5c415a1589..aabd13e23356 100644 --- a/code/game/objects/structures/windoor_assembly.dm +++ b/code/game/objects/structures/windoor_assembly.dm @@ -34,11 +34,11 @@ if(set_dir) setDir(set_dir) ini_dir = dir - air_update_turf(1) + air_update_turf() /obj/structure/windoor_assembly/Destroy() density = FALSE - air_update_turf(1) + air_update_turf() return ..() /obj/structure/windoor_assembly/Move() diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 4bcc890a7011..d4a01fd2a175 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -55,7 +55,7 @@ state = RWINDOW_SECURE ini_dir = dir - air_update_turf(1) + air_update_turf() if(fulltile) setDir() @@ -219,7 +219,7 @@ /obj/structure/window/setAnchored(anchorvalue) ..() - air_update_turf(TRUE) + air_update_turf() update_nearby_icons() /obj/structure/window/proc/check_state(checked_state) @@ -302,17 +302,16 @@ return TRUE /obj/structure/window/proc/after_rotation(mob/user,rotation_type) - air_update_turf(1) + air_update_turf() ini_dir = dir add_fingerprint(user) /obj/structure/window/Destroy() density = FALSE - air_update_turf(1) + air_update_turf() update_nearby_icons() return ..() - /obj/structure/window/Move() var/turf/T = loc . = ..() @@ -391,7 +390,7 @@ armor = list(MELEE = 60, BULLET = -50, LASER = 0, ENERGY = 0, BOMB = 25, BIO = 100, RAD = 100, FIRE = 80, ACID = 100) max_integrity = 75 explosion_block = 1 - damage_deflection = 10 + damage_deflection = 11 state = RWINDOW_SECURE glass_type = /obj/item/stack/sheet/rglass rad_insulation = RAD_HEAVY_INSULATION @@ -510,6 +509,11 @@ if (fulltile) . += new /obj/item/shard/plasma(location) +/obj/structure/window/plasma/BlockThermalConductivity(opp_dir) + if(!anchored || !density) + return FALSE + return FULLTILE_WINDOW_DIR == dir || dir == opp_dir + /obj/structure/window/plasma/spawner/east dir = EAST @@ -613,7 +617,7 @@ /obj/structure/window/reinforced/tinted name = "tinted window" icon_state = "twindow" - opacity = 1 + opacity = TRUE /obj/structure/window/reinforced/tinted/frosted name = "frosted window" icon_state = "fwindow" diff --git a/code/game/objects/structures/wire_splicing.dm b/code/game/objects/structures/wire_splicing.dm index 63b2b327110e..5536249aa223 100644 --- a/code/game/objects/structures/wire_splicing.dm +++ b/code/game/objects/structures/wire_splicing.dm @@ -98,7 +98,7 @@ var/obj/structure/cable/C = locate(/obj/structure/cable) in T if(!C) return FALSE - if (electrocute_mob(user, C.powernet, src, siemens_coeff)) + if(electrocute_mob(user, C.powernet, src, siemens_coeff, zone = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))) do_sparks(5, TRUE, src) return TRUE else diff --git a/code/game/shuttle_engines.dm b/code/game/shuttle_engines.dm index 582780f10a59..098efd8fc44f 100644 --- a/code/game/shuttle_engines.dm +++ b/code/game/shuttle_engines.dm @@ -99,7 +99,7 @@ name = "propulsion engine" icon_state = "propulsion" desc = "A standard reliable bluespace engine used by many forms of shuttles." - opacity = 1 + opacity = TRUE /obj/structure/shuttle/engine/propulsion/left name = "left propulsion engine" @@ -132,7 +132,7 @@ /obj/structure/shuttle/engine/large name = "engine" - opacity = 1 + opacity = TRUE icon = 'icons/obj/2x2.dmi' icon_state = "large_engine" desc = "A very large bluespace engine used to propel very large ships." @@ -142,7 +142,7 @@ /obj/structure/shuttle/engine/huge name = "engine" - opacity = 1 + opacity = TRUE icon = 'icons/obj/3x3.dmi' icon_state = "huge_engine" desc = "An extremely large bluespace engine used to propel extremely large ships." diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index 329502913482..9c110801ed2a 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -2,7 +2,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( /turf/open/space, /turf/baseturf_bottom, - ))) +))) /turf/proc/empty(turf_type=/turf/open/space, baseturf_type, list/ignore_typecache, flags) // Remove all atoms except observers, landmarks, docking ports @@ -14,14 +14,11 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( qdel(thing, force=TRUE) if(turf_type) - var/turf/newT = ChangeTurf(turf_type, baseturf_type, flags) - SSair.remove_from_active(newT) - CALCULATE_ADJACENT_TURFS(newT) - SSair.add_to_active(newT,1) + ChangeTurf(turf_type, baseturf_type, flags) -/turf/proc/copyTurf(turf/T) +/turf/proc/copyTurf(turf/T, copy_air, flags) if(T.type != type) - T.ChangeTurf(type) + T.ChangeTurf(type, null, flags) if(T.icon_state != icon_state) T.icon_state = icon_state if(T.icon != icon) @@ -48,6 +45,14 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( /turf/proc/TerraformTurf(path, new_baseturf, flags) return ChangeTurf(path, new_baseturf, flags) +/turf/proc/get_z_base_turf() + . = SSmapping.level_trait(z, ZTRAIT_BASETURF) || /turf/open/space + if (!ispath(.)) + . = text2path(.) + if (!ispath(.)) + warning("Z-level [z] has invalid baseturf '[SSmapping.level_trait(z, ZTRAIT_BASETURF)]'") + . = /turf/open/space + // Creates a new turf // new_baseturfs can be either a single type or list of types, formated the same as baseturfs. see turf.dm /turf/proc/ChangeTurf(path, list/new_baseturfs, flags) @@ -71,13 +76,13 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( if(flags & CHANGETURF_SKIP) return new path(src) - var/old_opacity = opacity var/old_dynamic_lighting = dynamic_lighting var/old_lighting_object = lighting_object var/old_lighting_corner_NE = lighting_corner_NE var/old_lighting_corner_SE = lighting_corner_SE var/old_lighting_corner_SW = lighting_corner_SW var/old_lighting_corner_NW = lighting_corner_NW + var/old_directional_opacity = directional_opacity var/old_exl = explosion_level var/old_exi = explosion_id @@ -118,10 +123,9 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( lighting_corner_NW = old_lighting_corner_NW if(SSlighting.initialized) - recalc_atom_opacity() lighting_object = old_lighting_object - if (old_opacity != opacity || dynamic_lighting != old_dynamic_lighting) - reconsider_lights() + directional_opacity = old_directional_opacity + recalculate_directional_opacity() if (dynamic_lighting != old_dynamic_lighting) if (IS_DYNAMIC_LIGHTING(src)) @@ -138,8 +142,10 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( return W /turf/open/ChangeTurf(path, list/new_baseturfs, flags) + //don't + if(!SSair.initialized) + return ..() if ((flags & CHANGETURF_INHERIT_AIR) && ispath(path, /turf/open)) - SSair.remove_from_active(src) var/datum/gas_mixture/stashed_air = new() stashed_air.copy_from(air) . = ..() @@ -155,14 +161,18 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( if (!istype(newTurf.air, /datum/gas_mixture/immutable/space)) QDEL_NULL(newTurf.air) newTurf.air = stashed_air - update_air_ref() - SSair.add_to_active(newTurf) + update_air_ref(planetary_atmos ? 1 : 2) else if(turf_fire) qdel(turf_fire) if(ispath(path,/turf/closed)|| ispath(path,/turf/cordon)) flags |= CHANGETURF_RECALC_ADJACENT - return ..() + update_air_ref(-1) + . = ..() + else + . = ..() + if(!istype(air,/datum/gas_mixture)) + Initalize_Atmos(0) // Take off the top layer turf and replace it with the next baseturf down /turf/proc/ScrapeAway(amount=1, flags) @@ -260,7 +270,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( // Copy an existing turf and put it on top // Returns the new turf -/turf/proc/CopyOnTop(turf/copytarget, ignore_bottom=1, depth=INFINITY, copy_air = FALSE) +/turf/proc/CopyOnTop(turf/copytarget, ignore_bottom=1, depth=INFINITY, copy_air = FALSE, flags) var/list/new_baseturfs = list() new_baseturfs += baseturfs new_baseturfs += type @@ -277,7 +287,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( target_baseturfs -= new_baseturfs & GLOB.blacklisted_automated_baseturfs new_baseturfs += target_baseturfs - var/turf/newT = copytarget.copyTurf(src, copy_air) + var/turf/newT = copytarget.copyTurf(src, copy_air, flags) newT.baseturfs = new_baseturfs return newT @@ -285,11 +295,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( //If you modify this function, ensure it works correctly with lateloaded map templates. /turf/proc/AfterChange(flags) //called after a turf has been replaced in ChangeTurf() levelupdate() - if(flags & CHANGETURF_RECALC_ADJACENT) - ImmediateCalculateAdjacentTurfs() - else - CALCULATE_ADJACENT_TURFS(src) - SSair.add_to_active(src) + ImmediateCalculateAdjacentTurfs() //update firedoor adjacency var/list/turfs_to_check = get_adjacent_open_turfs(src) | src @@ -323,7 +329,6 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( total.merge(S.air) air.copy_from(total.remove_ratio(1/turf_count)) - SSair.add_to_active(src) /turf/proc/ReplaceWithLattice() ScrapeToBottom(flags = CHANGETURF_INHERIT_AIR) // Yogs -- fixes this not actually replacing the turf with a lattice, lmao (ScrapeToBottom defined in yogs file) diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm index a35d4930ddec..114bcd368b51 100644 --- a/code/game/turfs/closed.dm +++ b/code/game/turfs/closed.dm @@ -1,19 +1,14 @@ /turf/closed layer = CLOSED_TURF_LAYER - opacity = 1 + opacity = TRUE density = TRUE blocks_air = TRUE flags_1 = RAD_PROTECT_CONTENTS_1 | RAD_NO_CONTAMINATE_1 rad_insulation = RAD_MEDIUM_INSULATION -/turf/closed/Initialize(mapload) - . = ..() - update_air_ref() - /turf/closed/AfterChange() . = ..() SSair.high_pressure_delta -= src - update_air_ref() /turf/closed/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir) return FALSE @@ -107,7 +102,7 @@ /turf/closed/indestructible/fakeglass name = "window" icon_state = "fake_window" - opacity = 0 + opacity = FALSE smooth = SMOOTH_TRUE icon = 'icons/obj/smooth_structures/reinforced_window.dmi' @@ -120,7 +115,7 @@ /turf/closed/indestructible/opsglass name = "window" icon_state = "plastitanium_window" - opacity = 0 + opacity = FALSE smooth = SMOOTH_TRUE icon = 'icons/obj/smooth_structures/plastitanium_window.dmi' diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index affcf0cd9e5d..82203455e9de 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -487,18 +487,12 @@ icon_state = "info" /turf/open/Initalize_Atmos(times_fired) - set_excited(FALSE) - update_visuals() - - current_cycle = times_fired + if(!blocks_air) + if(!istype(air,/datum/gas_mixture/turf)) + air = new(2500,src) + air.copy_from_turf(src) + update_air_ref(planetary_atmos ? 1 : 2) ImmediateCalculateAdjacentTurfs() - for(var/i in atmos_adjacent_turfs) - var/turf/open/enemy_tile = i - var/datum/gas_mixture/enemy_air = enemy_tile.return_air() - if(!get_excited() && air.compare(enemy_air)) - //testing("Active turf found. Return value of compare(): [is_active]") - set_excited(TRUE) - SSair.active_turfs |= src /turf/open/proc/GetHeatCapacity() . = air.heat_capacity() @@ -508,7 +502,6 @@ /turf/open/proc/TakeTemperature(temp) air.set_temperature(air.return_temperature() + temp) - air_update_turf() /turf/open/proc/freeze_turf() for(var/obj/I in contents) @@ -592,20 +585,18 @@ /turf/open/rad_act(pulse_strength, collectable_radiation) . = ..() - if (air.get_moles(/datum/gas/carbon_dioxide) && air.get_moles(/datum/gas/oxygen) && !(air.get_moles(/datum/gas/hypernoblium)>=REACTION_OPPRESSION_THRESHOLD)) - pulse_strength = min(pulse_strength,air.get_moles(/datum/gas/carbon_dioxide)*1000,air.get_moles(/datum/gas/oxygen)*2000) //Ensures matter is conserved properly - air.set_moles(/datum/gas/carbon_dioxide, max(air.get_moles(/datum/gas/carbon_dioxide)-(pulse_strength * 0.001),0)) - air.set_moles(/datum/gas/oxygen, max(air.get_moles(/datum/gas/oxygen)-(pulse_strength * 0.002),0)) - air.adjust_moles(/datum/gas/pluoxium, pulse_strength * 0.004) - air_update_turf() - if (air.get_moles(/datum/gas/hydrogen) && !(air.get_moles(/datum/gas/hypernoblium)>=REACTION_OPPRESSION_THRESHOLD)) - pulse_strength = min(pulse_strength, air.get_moles(/datum/gas/hydrogen) * 1000) - air.set_moles(/datum/gas/hydrogen, max(air.get_moles(/datum/gas/hydrogen) - (pulse_strength * 0.001), 0)) - air.adjust_moles(/datum/gas/tritium, pulse_strength * 0.001) - air_update_turf() + if (air.get_moles(GAS_CO2) && air.get_moles(GAS_O2) && !(air.get_moles(GAS_HYPERNOB) >= REACTION_OPPRESSION_THRESHOLD) ) + pulse_strength = min(pulse_strength,air.get_moles(GAS_CO2)*1000,air.get_moles(GAS_O2)*2000) //Ensures matter is conserved properly + air.set_moles(GAS_CO2, max(air.get_moles(GAS_CO2)-(pulse_strength * 0.001),0)) + air.set_moles(GAS_O2, max(air.get_moles(GAS_O2)-(pulse_strength * 0.002),0)) + air.adjust_moles(GAS_PLUOXIUM, pulse_strength * 0.004) + if (air.get_moles(GAS_H2) && !(air.get_moles(GAS_HYPERNOB) >= REACTION_OPPRESSION_THRESHOLD)) + pulse_strength = min(pulse_strength, air.get_moles(GAS_H2) * 1000) + air.set_moles(GAS_H2, max(air.get_moles(GAS_H2) - (pulse_strength * 0.001), 0)) + air.adjust_moles(GAS_TRITIUM, pulse_strength * 0.001) /turf/open/IgniteTurf(power, fire_color="red") - if(air.get_moles(/datum/gas/oxygen) < 1) + if(air.get_moles(GAS_O2) < 1) return if(turf_fire) turf_fire.AddPower(power) diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 38c28f0ef402..676b6d1bc154 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -25,10 +25,6 @@ tiled_dirt = TRUE - //Do we have an uncleanable level of grime? This overlays a color multiplied noise ("grime") image on top for TG style dirtiness with clean icons. - var/grime = FALSE - var/grime_alpha = 40 //what is the alpha of our grime? brighter tiles look worse with grime. - /turf/open/floor/Initialize(mapload) if (!broken_states) @@ -62,12 +58,6 @@ icon_state_regular_floor = icon_state icon_regular_floor = icon - if(grime) - //add a bit of grime for noobs - var/mutable_appearance/MA = mutable_appearance(icon, "grime", alpha = grime_alpha) - MA.blend_mode = BLEND_MULTIPLY - add_overlay(MA) - if(mapload && prob(33)) MakeDirty() if(is_station_level(z)) diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm index 5e47d159cec4..c6ec1637b061 100644 --- a/code/game/turfs/simulated/floor/fancy_floor.dm +++ b/code/game/turfs/simulated/floor/fancy_floor.dm @@ -63,6 +63,21 @@ to_chat(user, span_notice("You forcefully pry off the planks, destroying them in the process.")) return make_plating() +/turf/open/floor/wood/parquet + icon_state = "wood-parquet" + floor_tile = /obj/item/stack/tile/wood/parquet + broken_states = list("wood-parquet-broken", "wood-parquet-broken2", "wood-parquet-broken3", "wood-parquet-broken4", "wood-parquet-broken5", "wood-parquet-broken6", "wood-parquet-broken7") + +/turf/open/floor/wood/tile + icon_state = "wood-tile" + floor_tile = /obj/item/stack/tile/wood/tile + broken_states = list("wood-tile-broken", "wood-tile-broken2", "wood-tile-broken3") + +/turf/open/floor/wood/large + icon_state = "wood-large" + floor_tile = /obj/item/stack/tile/wood/large + broken_states = list("wood-large-broken", "wood-large-broken2", "wood-large-broken3") + /turf/open/floor/wood/cold initial_gas_mix = KITCHEN_COLDROOM_ATMOS @@ -160,6 +175,48 @@ /turf/open/floor/wood/cold/broken/seven icon_state = "wood-broken7" +/turf/open/floor/wood/parquet/broken + icon_state = "wood-parquet-broken" + broken = TRUE + +/turf/open/floor/wood/parquet/broken/two + icon_state = "wood-parquet-broken2" + +/turf/open/floor/wood/parquet/broken/three + icon_state = "wood-parquet-broken3" + +/turf/open/floor/wood/parquet/broken/four + icon_state = "wood-parquet-broken4" + +/turf/open/floor/wood/parquet/broken/five + icon_state = "wood-parquet-broken5" + +/turf/open/floor/wood/parquet/broken/six + icon_state = "wood-parquet-broken6" + +/turf/open/floor/wood/parquet/broken/seven + icon_state = "wood-parquet-broken7" + +/turf/open/floor/wood/tile/broken + icon_state = "wood-tile-broken" + broken = TRUE + +/turf/open/floor/wood/tile/broken/two + icon_state = "wood-tile-broken2" + +/turf/open/floor/wood/tile/broken/three + icon_state = "wood-tile-broken3" + +/turf/open/floor/wood/large/broken + icon_state = "wood-large-broken" + broken = TRUE + +/turf/open/floor/wood/large/broken/two + icon_state = "wood-large-broken2" + +/turf/open/floor/wood/large/broken/three + icon_state = "wood-large-broken3" + /turf/open/floor/bamboo desc = "A bamboo mat with a decorative trim." icon = 'icons/turf/floors/bamboo_mat.dmi' diff --git a/code/game/turfs/simulated/floor/plasteel_floor.dm b/code/game/turfs/simulated/floor/plasteel_floor.dm index a6b5a5cce5d0..6f0f9dbe29fd 100644 --- a/code/game/turfs/simulated/floor/plasteel_floor.dm +++ b/code/game/turfs/simulated/floor/plasteel_floor.dm @@ -3,7 +3,6 @@ floor_tile = /obj/item/stack/tile/plasteel broken_states = list("damaged1", "damaged2", "damaged3", "damaged4", "damaged5") burnt_states = list("floorscorched1", "floorscorched2") - grime = TRUE /turf/open/floor/plasteel/examine(mob/user) . = ..() @@ -108,19 +107,15 @@ /turf/open/floor/plasteel/white icon_state = "white" - grime_alpha = 20 /turf/open/floor/plasteel/whitegrad icon_state = "whitegreygrad" - grime_alpha = 30 /turf/open/floor/plasteel/white/side icon_state = "whitehall" - grime_alpha = 30 /turf/open/floor/plasteel/white/corner icon_state = "whitecorner" - grime_alpha = 30 /turf/open/floor/plasteel/airless/white icon_state = "white" diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index 0290baa6c30f..5fdd9fa14468 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -16,7 +16,6 @@ barefootstep = FOOTSTEP_HARD_BAREFOOT clawfootstep = FOOTSTEP_HARD_CLAW heavyfootstep = FOOTSTEP_GENERIC_HEAVY - grime = TRUE FASTDMM_PROP(\ pipe_astar_cost = 1\ diff --git a/code/game/turfs/simulated/floor/plating/asteroid.dm b/code/game/turfs/simulated/floor/plating/asteroid.dm index 642beded649c..4f3960ac2d02 100644 --- a/code/game/turfs/simulated/floor/plating/asteroid.dm +++ b/code/game/turfs/simulated/floor/plating/asteroid.dm @@ -135,6 +135,10 @@ baseturfs = /turf/open/floor/plating/asteroid/airless turf_type = /turf/open/floor/plating/asteroid/airless +// / Breathing types. Lungs can access either by these or by a string, which will be considered a gas ID. +#define BREATH_OXY /datum/breathing_class/oxygen +#define BREATH_PLASMA /datum/breathing_class/plasma + /turf/open/floor/plating/asteroid/snow gender = PLURAL name = "snow" diff --git a/code/game/turfs/simulated/floor/plating/misc_plating.dm b/code/game/turfs/simulated/floor/plating/misc_plating.dm index a14885d02ad9..c3cae2da310b 100644 --- a/code/game/turfs/simulated/floor/plating/misc_plating.dm +++ b/code/game/turfs/simulated/floor/plating/misc_plating.dm @@ -173,7 +173,7 @@ icon = 'icons/turf/floors/ice_turf.dmi' icon_state = "unsmooth" initial_gas_mix = FROZEN_ATMOS - temperature = 180 + initial_temperature = 180 planetary_atmos = TRUE baseturfs = /turf/open/floor/plating/ice attachment_holes = FALSE @@ -201,10 +201,10 @@ canSmoothWith = list(/turf/open/floor/plating/ice/smooth, /turf/open/floor/plating/ice) /turf/open/floor/plating/ice/colder - temperature = 140 + initial_temperature = 140 /turf/open/floor/plating/ice/temperate - temperature = 255.37 + initial_temperature = 255.37 /turf/open/floor/plating/ice/break_tile() return @@ -225,7 +225,7 @@ icon = 'icons/turf/snow.dmi' icon_state = "snowplating" initial_gas_mix = FROZEN_ATMOS - temperature = 180 + initial_temperature = 180 attachment_holes = FALSE planetary_atmos = TRUE footstep = FOOTSTEP_SAND @@ -244,10 +244,10 @@ icon_state = "smooth" /turf/open/floor/plating/snowed/colder - temperature = 140 + initial_temperature = 140 /turf/open/floor/plating/snowed/temperatre - temperature = 255.37 + initial_temperature = 255.37 /turf/open/floor/plating/snowed/smoothed/icemoon initial_gas_mix = ICEMOON_DEFAULT_ATMOS diff --git a/code/game/turfs/simulated/lava.dm b/code/game/turfs/simulated/lava.dm index e4fbb1035cf3..0a24d89e0e9e 100644 --- a/code/game/turfs/simulated/lava.dm +++ b/code/game/turfs/simulated/lava.dm @@ -172,5 +172,7 @@ planetary_atmos = TRUE baseturfs = /turf/open/lava/smooth/lava_land_surface +/turf/open/lava/smooth/lava_land_surface/no_shelter //snowflake version that survival pods won't spawn in + /turf/open/lava/smooth/airless initial_gas_mix = AIRLESS_ATMOS diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm index c319f4542997..b9e8d6521e16 100644 --- a/code/game/turfs/simulated/minerals.dm +++ b/code/game/turfs/simulated/minerals.dm @@ -10,10 +10,10 @@ canSmoothWith = null baseturfs = /turf/open/floor/plating/asteroid/airless initial_gas_mix = AIRLESS_ATMOS - opacity = 1 + opacity = TRUE density = TRUE layer = EDGED_TURF_LAYER - temperature = TCMB + initial_temperature = TCMB var/environment_type = "asteroid" var/turf/open/floor/plating/turf_type = /turf/open/floor/plating/asteroid/airless var/mineralType = null diff --git a/code/game/turfs/simulated/wall/reinf_walls.dm b/code/game/turfs/simulated/wall/reinf_walls.dm index e32864e5d785..94e94e57333f 100644 --- a/code/game/turfs/simulated/wall/reinf_walls.dm +++ b/code/game/turfs/simulated/wall/reinf_walls.dm @@ -3,7 +3,7 @@ desc = "A huge chunk of reinforced metal used to separate rooms." icon = 'icons/turf/walls/reinforced_wall.dmi' icon_state = "r_wall" - opacity = 1 + opacity = TRUE density = TRUE var/d_state = INTACT diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 3d67d31f7459..aff1b3ae03f4 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -81,8 +81,7 @@ var/obj/structure/sign/poster/P = O P.roll_and_drop(src) - var/turf/new_floor = ScrapeAway() - new_floor.air_update_turf() + ScrapeAway() /turf/closed/wall/proc/break_wall() new sheet_type(src, sheet_amount) diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index eb437da4683f..253cf793e805 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -4,8 +4,8 @@ name = "\proper space" intact = 0 - temperature = TCMB - thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT + initial_temperature = TCMB + thermal_conductivity = 0 heat_capacity = 700000 FASTDMM_PROP(\ @@ -16,7 +16,7 @@ var/destination_x var/destination_y - var/global/datum/gas_mixture/immutable/space/space_gas = new + var/global/datum/gas_mixture/immutable/space/space_gas plane = PLANE_SPACE layer = SPACE_LAYER light_power = 0.25 @@ -30,8 +30,10 @@ /turf/open/space/Initialize(mapload) SHOULD_CALL_PARENT(FALSE) icon_state = SPACE_ICON_STATE + if(!space_gas) + space_gas = new air = space_gas - update_air_ref() + update_air_ref(0) vis_contents.Cut() //removes inherited overlays visibilityChanged() @@ -44,14 +46,11 @@ if(!IS_DYNAMIC_LIGHTING(src) && IS_DYNAMIC_LIGHTING(A)) add_overlay(/obj/effect/fullbright) - if(requires_activation) - SSair.add_to_active(src) - if (light_system == STATIC_LIGHT && light_power && light_range) update_light() if (opacity) - has_opaque_atom = TRUE + directional_opacity = ALL_CARDINALS return INITIALIZE_HINT_NORMAL @@ -80,6 +79,13 @@ /turf/open/space/remove_air(amount) return null +/turf/open/space/remove_air_ratio(amount) + return null + +//IT SHOULD RETURN NULL YOU MONKEY, WHY IN TARNATION WHAT THE FUCKING FUCK +/turf/open/space/remove_air(amount) + return null + /turf/open/space/proc/update_starlight() if(CONFIG_GET(flag/starlight)) for(var/t in RANGE_TURFS(1,src)) //RANGE_TURFS is in code\__HELPERS\game.dm diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm old mode 100644 new mode 100755 index bf0afac73c78..0d676cd092d3 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -3,6 +3,9 @@ GLOBAL_LIST_EMPTY(station_turfs) /turf icon = 'icons/turf/floors.dmi' level = 1 + luminosity = 1 + + var/dynamic_lighting = DYNAMIC_LIGHTING_ENABLED var/intact = 1 @@ -13,15 +16,12 @@ GLOBAL_LIST_EMPTY(station_turfs) // This shouldn't be modified directly, use the helper procs. var/list/baseturfs = /turf/baseturf_bottom - var/temperature = T20C + var/initial_temperature = T20C var/to_be_destroyed = 0 //Used for fire, if a melting temperature was reached, it will be destroyed var/max_fire_temperature_sustained = 0 //The max temperature of the fire which it was subjected to var/blocks_air = FALSE - ///Which directions does this turf block the vision of, taking into account both the turf's opacity and the movable opacity_sources. - var/directional_opacity = NONE - flags_1 = CAN_BE_DIRTY_1 var/list/image/blueprint_data //for the station blueprints, images of objects eg: pipes @@ -39,6 +39,24 @@ GLOBAL_LIST_EMPTY(station_turfs) var/tiled_dirt = FALSE // use smooth tiled dirt decal + ///Lumcount added by sources other than lighting datum objects, such as the overlay lighting component. + var/dynamic_lumcount = 0 + + var/tmp/lighting_corners_initialised = FALSE + + ///Our lighting object. + var/tmp/datum/lighting_object/lighting_object + ///Lighting Corner datums. + var/tmp/datum/lighting_corner/lighting_corner_NE + var/tmp/datum/lighting_corner/lighting_corner_SE + var/tmp/datum/lighting_corner/lighting_corner_SW + var/tmp/datum/lighting_corner/lighting_corner_NW + + ///Which directions does this turf block the vision of, taking into account both the turf's opacity and the movable opacity_sources. + var/directional_opacity = NONE + ///Lazylist of movable atoms providing opacity sources. + var/list/atom/movable/opacity_sources + /turf/vv_edit_var(var_name, new_value) var/static/list/banned_edits = list("x", "y", "z") if(var_name in banned_edits) @@ -69,11 +87,10 @@ GLOBAL_LIST_EMPTY(station_turfs) add_overlay(/obj/effect/fullbright) if(requires_activation) - CALCULATE_ADJACENT_TURFS(src) - SSair.add_to_active(src) + ImmediateCalculateAdjacentTurfs() + if(color) add_atom_colour(color, FIXED_COLOUR_PRIORITY) - if (light_system == STATIC_LIGHT && light_power && light_range) update_light() @@ -87,14 +104,29 @@ GLOBAL_LIST_EMPTY(station_turfs) SEND_SIGNAL(T, COMSIG_TURF_MULTIZ_NEW, src, UP) if (opacity) - has_opaque_atom = TRUE + directional_opacity = ALL_CARDINALS + + if(isopenturf(src)) + var/turf/open/O = src + __auxtools_update_turf_temp_info(isspaceturf(get_z_base_turf()) && !O.planetary_atmos) + else + update_air_ref(-1) + __auxtools_update_turf_temp_info(isspaceturf(get_z_base_turf())) if(color) add_atom_colour(color, FIXED_COLOUR_PRIORITY) return INITIALIZE_HINT_NORMAL +/turf/proc/__auxtools_update_turf_temp_info() + +/turf/proc/__auxtools_update_turf_infos(immediate) + +/turf/return_temperature() + +/turf/proc/set_temperature() + /turf/proc/Initalize_Atmos(times_fired) - CALCULATE_ADJACENT_TURFS(src) + ImmediateCalculateAdjacentTurfs() /turf/Destroy(force) . = QDEL_HINT_IWILLGC @@ -116,7 +148,6 @@ GLOBAL_LIST_EMPTY(station_turfs) for(var/I in B.vars) B.vars[I] = null return - SSair.remove_from_active(src) visibilityChanged() QDEL_LIST(blueprint_data) flags_1 &= ~INITIALIZED_1 @@ -267,14 +298,6 @@ GLOBAL_LIST_EMPTY(station_turfs) if(QDELETED(mover)) return FALSE //We were deleted. -/turf/Entered(atom/movable/AM) - ..() - - // If an opaque movable atom moves around we need to potentially update visibility. - if (AM.opacity) - has_opaque_atom = TRUE // Make sure to do this before reconsider_lights(), incase we're on instant updates. Guaranteed to be on in this case. - reconsider_lights() - /turf/open/Entered(atom/movable/AM) ..() //melting diff --git a/code/game/world.dm b/code/game/world.dm index 3982adb505a1..65b4cbdc23a3 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -211,19 +211,19 @@ GLOBAL_VAR(restart_counter) var/list/fail_reasons if(GLOB) if(GLOB.total_runtimes != 0) - fail_reasons = list("Total runtimes: [GLOB.total_runtimes]") + fail_reasons = list(TEST_OUTPUT_RED("Total runtimes: [GLOB.total_runtimes]")) #ifdef UNIT_TESTS if(GLOB.failed_any_test) - LAZYADD(fail_reasons, "Unit Tests failed!") + LAZYADD(fail_reasons, TEST_OUTPUT_RED("Unit Tests failed!")) #endif if(!GLOB.log_directory) - LAZYADD(fail_reasons, "Missing GLOB.log_directory!") + LAZYADD(fail_reasons, TEST_OUTPUT_RED("Missing GLOB.log_directory!")) else - fail_reasons = list("Missing GLOB!") + fail_reasons = list(TEST_OUTPUT_RED("Missing GLOB!")) if(!fail_reasons) text2file("Success!", "[GLOB.log_directory]/clean_run.lk") else - log_world("Test run failed!\n[fail_reasons.Join("\n")]") + log_world("[TEST_OUTPUT_RED("Test run failed")]!\n[fail_reasons.Join("\n")]") sleep(0) //yes, 0, this'll let Reboot finish and prevent byond memes qdel(src) //shut it down @@ -272,17 +272,15 @@ GLOBAL_VAR(restart_counter) log_world("World rebooted at [time_stamp()]") shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss. + __auxmos_shutdown() ..() /world/Del() - // memory leaks bad - var/num_deleted = 0 - for(var/datum/gas_mixture/GM) - GM.__gasmixture_unregister() - num_deleted++ - log_world("Deallocated [num_deleted] gas mixtures") - if(fexists(EXTOOLS)) - LIBCALL(EXTOOLS, "cleanup")() + shutdown_logging() // makes sure the thread is closed before end, else we terminate + __auxmos_shutdown() + var/debug_server = world.GetConfig("env", "AUXTOOLS_DEBUG_DLL") + if (debug_server) + LIBCALL(debug_server, "auxtools_shutdown")() ..() /world/proc/update_status() //yogs -- Mirrored in the Yogs folder in March 2019. Do not edit, swallow, or submerge in acid diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 612ff69e0c8e..41933cd0ae11 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -20,6 +20,7 @@ GLOBAL_PROTECT(admin_verbs_default) /client/proc/stop_sounds, /client/proc/fix_air, // yogs - fix air verb /client/proc/fix_air_z, + /client/proc/clear_all_pipenets, /client/proc/debugstatpanel, /client/proc/clear_mfa, /client/proc/show_rights @@ -155,7 +156,6 @@ GLOBAL_PROTECT(admin_verbs_server) /client/proc/panicbunker, /client/proc/toggle_hub, /client/proc/mentor_memo, // YOGS - something stupid about "Mentor memos" - /client/proc/dump_memory_usage, /client/proc/release_queue, // Yogs -- Adds some queue-manipulation verbs /client/proc/toggle_cdn ) @@ -812,7 +812,7 @@ GLOBAL_PROTECT(admin_verbs_hideable) log_admin("[key_name(usr)] has [AI_Interact ? "activated" : "deactivated"] Admin AI Interact") message_admins("[key_name_admin(usr)] has [AI_Interact ? "activated" : "deactivated"] their AI interaction") - +/* /client/proc/dump_memory_usage() set name = "Dump Server Memory Usage" set category = "Server" @@ -841,6 +841,7 @@ GLOBAL_PROTECT(admin_verbs_hideable) to_chat(usr, span_warning("File creation failed. Please check to see if the data/logs/memory folder actually exists.")) else to_chat(usr, span_notice("Memory dump completed.")) +*/ /client/proc/debugstatpanel() diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm index ce02517e9fad..d93f496ca9b3 100644 --- a/code/modules/admin/secrets.dm +++ b/code/modules/admin/secrets.dm @@ -312,6 +312,7 @@ var/objective = stripped_input(mob_user, "Enter an objective") if(!objective) return + var/tc_amount = input(mob_user, "How much TC should they all get?") as null|num SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Traitor All", "[objective]")) for(var/mob/living/H in GLOB.player_list) if(!(ishuman(H)||istype(H, /mob/living/silicon/))) @@ -327,6 +328,11 @@ new_objective.explanation_text = objective T.add_objective(new_objective) H.mind.add_antag_datum(T) + if(tc_amount && tc_amount != TELECRYSTALS_DEFAULT)//if the admin chose a different starting TC amount + if(T.uplink_holder) + var/datum/component/uplink/uplink = T.uplink_holder.GetComponent(/datum/component/uplink) + if(uplink) + uplink.telecrystals = tc_amount message_admins(span_adminnotice("[key_name_admin(mob_user)] used everyone is a traitor secret. Objective is [objective]")) log_admin("[key_name(mob_user)] used everyone is a traitor secret. Objective is [objective]") @@ -464,7 +470,7 @@ if(is_station_level(W.z) && !istype(get_area(W), /area/bridge) && !istype(get_area(W), /area/crew_quarters) && !istype(get_area(W), /area/security/prison)) W.req_access = list() message_admins("[key_name_admin(mob_user)] activated Egalitarian Station mode (All doors are open access)") - priority_announce("CentCom airlock control override activated. Please take this time to get acquainted with your coworkers.", null, RANDOM_REPORT_SOUND) + priority_announce("CentCom airlock control override activated. Please take this time to get acquainted with your coworkers.", null, SSstation.announcer.get_rand_report_sound()) if("ancap") if(!check_rights_for(rights, R_FUN)) @@ -473,9 +479,9 @@ SSeconomy.full_ancap = !SSeconomy.full_ancap message_admins("[key_name_admin(mob_user)] toggled Anarcho-capitalist mode") if(SSeconomy.full_ancap) - priority_announce("The NAP is now in full effect.", null, RANDOM_REPORT_SOUND) + priority_announce("The NAP is now in full effect.", null, SSstation.announcer.get_rand_report_sound()) else - priority_announce("The NAP has been revoked.", null, RANDOM_REPORT_SOUND) + priority_announce("The NAP has been revoked.", null, SSstation.announcer.get_rand_report_sound()) if("dorf") if(!check_rights_for(rights, R_FUN)) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index f8032d2a705a..e82d53f88f43 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2319,7 +2319,7 @@ return var/customname = input(src, "Pick a title for the report", "Title") as text|null - var/prefix = "
NanoTrasen Fax Network

RE: [inputsubject]

" + var/prefix = "
Nanotrasen Fax Network

RE: [inputsubject]

" var/suffix = "
Signed: [inputsigned]" inputmessage = parsemarkdown(inputmessage) diff --git a/code/modules/admin/verbs/commandreport.dm b/code/modules/admin/verbs/commandreport.dm new file mode 100644 index 000000000000..5636a036db3d --- /dev/null +++ b/code/modules/admin/verbs/commandreport.dm @@ -0,0 +1,175 @@ +/// The default command report announcement sound. +#define DEFAULT_ANNOUNCEMENT_SOUND "default_announcement" + +/// Preset central command names to chose from for centcom reports. +#define CENTCOM_PRESET "Central Command" +#define SYNDICATE_PRESET "The Syndicate" +#define WIZARD_PRESET "The Wizard Federation" +#define CUSTOM_PRESET "Custom Command Name" + +/// Verb to change the global command name. +/client/proc/cmd_change_command_name() + set category = "Admin.Round Interaction" + set name = "Change Command Name" + + if(!check_rights(R_ADMIN)) + return + + var/input = input(usr, "Please input a new name for Central Command.", "What?", "") as text|null + if(!input) + return + change_command_name(input) + message_admins("[key_name_admin(src)] has changed Central Command's name to [input]") + log_admin("[key_name(src)] has changed the Central Command name to: [input]") + +/// Verb to open the create command report window and send command reports. +/client/proc/cmd_admin_create_centcom_report() + set category = "Admin.Round Interaction" + set name = "Create Command Report" + + if(!check_rights(R_ADMIN)) + return + + SSblackbox.record_feedback("tally", "admin_verb", 1, "Create Command Report") // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! + var/datum/command_report_menu/tgui = new(usr) + tgui.ui_interact(usr) + +/// Datum for holding the TGUI window for command reports. +/datum/command_report_menu + /// The mob using the UI. + var/mob/ui_user + /// The name of central command that will accompany our report + var/command_name = CENTCOM_PRESET + /// Whether we are using a custom name instead of a preset. + var/custom_name + /// The actual contents of the report we're going to send. + var/command_report_content + /// Whether the report's contents are announced. + var/announce_contents = TRUE + /// Whether a copy of the report is printed at every console. + var/print_report = TRUE + /// The sound that's going to accompany our message. + var/played_sound = DEFAULT_ANNOUNCEMENT_SOUND + /// The colour of the announcement when sent + var/announcement_color = "default" + /// The subheader to include when sending the announcement. Keep blank to not include a subheader + var/subheader = "" + /// A static list of preset names that can be chosen. + var/list/preset_names = list(CENTCOM_PRESET, SYNDICATE_PRESET, WIZARD_PRESET, CUSTOM_PRESET) + +/datum/command_report_menu/New(mob/user) + ui_user = user + if(command_name() != CENTCOM_PRESET) + command_name = command_name() + preset_names.Insert(1, command_name()) + +/datum/command_report_menu/ui_state(mob/user) + return GLOB.admin_state + +/datum/command_report_menu/ui_close() + qdel(src) + +/datum/command_report_menu/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "CommandReport") + ui.open() + +/datum/command_report_menu/ui_data(mob/user) + var/list/data = list() + data["command_name"] = command_name + data["custom_name"] = custom_name + data["command_report_content"] = command_report_content + data["announce_contents"] = announce_contents + data["print_report"] = print_report + data["played_sound"] = played_sound + data["announcement_color"] = announcement_color + data["subheader"] = subheader + + return data + +/datum/command_report_menu/ui_static_data(mob/user) + var/list/data = list() + data["command_name_presets"] = preset_names + data["announcer_sounds"] = list(DEFAULT_ANNOUNCEMENT_SOUND) + GLOB.announcer_keys + data["announcement_colors"] = ANNOUNCEMENT_COLORS + + return data + +/datum/command_report_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + + switch(action) + if("update_command_name") + if(params["updated_name"] == CUSTOM_PRESET) + custom_name = TRUE + else if (params["updated_name"] in preset_names) + custom_name = FALSE + + command_name = params["updated_name"] + if("set_report_sound") + played_sound = params["picked_sound"] + if("toggle_announce") + announce_contents = !announce_contents + if("toggle_printing") + print_report = !print_report + if("update_announcement_color") + var/colors = ANNOUNCEMENT_COLORS + var/chosen_color = params["updated_announcement_color"] + if(chosen_color in colors) + announcement_color = chosen_color + if("set_subheader") + subheader = params["new_subheader"] + if("submit_report") + if(!command_name) + to_chat(ui_user, span_danger("You can't send a report with no command name.")) + return + if(!params["report"]) + to_chat(ui_user, span_danger("You can't send a report with no contents.")) + return + command_report_content = params["report"] + send_announcement() + + return TRUE + +/* + * The actual proc that sends the priority announcement and reports + * + * Uses the variables set by the user on our datum as the arguments for the report. + */ +/datum/command_report_menu/proc/send_announcement() + /// Our current command name to swap back to after sending the report. + var/original_command_name = command_name() + change_command_name(command_name) + + /// The sound we're going to play on report. + var/report_sound = played_sound + if(played_sound == DEFAULT_ANNOUNCEMENT_SOUND) + report_sound = SSstation.announcer.get_rand_report_sound() + + if(announce_contents) + var/chosen_color = announcement_color + if(chosen_color == "default") + if(command_name == SYNDICATE_PRESET) + chosen_color = "red" + else if(command_name == WIZARD_PRESET) + chosen_color = "purple" + priority_announce(command_report_content, subheader == ""? null : subheader, report_sound, has_important_message = TRUE, color_override = chosen_color) + + if(!announce_contents || print_report) + print_command_report(command_report_content, "[announce_contents ? "" : "Classified "][command_name] Update", !announce_contents) + + change_command_name(original_command_name) + + log_admin("[key_name(ui_user)] has created a command report: \"[command_report_content]\", sent from \"[command_name]\" with the sound \"[played_sound]\".") + message_admins("[key_name_admin(ui_user)] has created a command report, sent from \"[command_name]\" with the sound \"[played_sound]\"") + + +#undef DEFAULT_ANNOUNCEMENT_SOUND + +#undef CENTCOM_PRESET +#undef SYNDICATE_PRESET +#undef WIZARD_PRESET +#undef CUSTOM_PRESET diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 15916f9e5423..893c26ed104e 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -872,7 +872,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) if(Rad.anchored) if(!Rad.loaded_tank) var/obj/item/tank/internals/plasma/Plasma = new/obj/item/tank/internals/plasma(Rad) - Plasma.air_contents.set_moles(/datum/gas/plasma, 70) + Plasma.air_contents.set_moles(GAS_PLASMA, 70) Rad.drainratio = 0 Rad.loaded_tank = Plasma Plasma.forceMove(Rad) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 841482eb3878..a74290108199 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -617,47 +617,6 @@ Traitors and the like can also be revived with the previous role mostly intact. L?.mind?.name = newname SSblackbox.record_feedback("tally", "admin_verb", 1, "Offer Mob Rename") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc -/client/proc/cmd_admin_create_centcom_report() - set category = "Admin.Round Interaction" - set name = "Create Command Report" - - if(!check_rights(R_ADMIN)) - return - - var/input = input(usr, "Enter a Command Report. Ensure it makes sense IC.", "What?", "") as message|null - if(!input) - return - - var/confirm = alert(src, "Do you want to announce the contents of the report to the crew?", "Announce", "Yes", "No", "Cancel") - var/announce_command_report = TRUE - var/senderOverride = input(src, "Please input the sender of the report", "Sender", "[command_name()] Update") - switch(confirm) - if("Yes") - priority_announce(input, null, RANDOM_REPORT_SOUND, sender_override = senderOverride, sanitize = FALSE) - announce_command_report = FALSE - if("Cancel") - return - - print_command_report(input, "[announce_command_report ? "Classified " : ""][senderOverride]", announce_command_report) - - log_admin("[key_name(src)] has created a command report: [input]") - message_admins("[key_name_admin(src)] has created a command report") - SSblackbox.record_feedback("tally", "admin_verb", 1, "Create Command Report") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_change_command_name() - set category = "Admin.Round Interaction" - set name = "Change Command Name" - - if(!check_rights(R_ADMIN)) - return - - var/input = input(usr, "Please input a new name for Central Command.", "What?", "") as text|null - if(!input) - return - change_command_name(input) - message_admins("[key_name_admin(src)] has changed Central Command's name to [input]") - log_admin("[key_name(src)] has changed the Central Command name to: [input]") - /client/proc/cmd_admin_delete(atom/A as obj|mob|turf in world) set category = "Misc.Unused" set name = "Delete" @@ -744,18 +703,17 @@ Traitors and the like can also be revived with the previous role mostly intact. if(!check_rights(R_ADMIN)) return - var/heavy = input("Range of heavy pulse.", text("Input")) as num|null - if(heavy == null) + var/severity = input("Severity of pulse.", text("Input")) as num|null + if(!isnum(severity)) return - var/light = input("Range of light pulse.", text("Input")) as num|null - if(light == null) - return - - if (heavy || light) + var/range = input("Range of pulse.", text("Input")) as num|null + if(!isnum(range)) + range = severity - empulse(O, heavy, light) - log_admin("[key_name(usr)] created an EM Pulse ([heavy],[light]) at [AREACOORD(O)]") - message_admins("[key_name_admin(usr)] created an EM Pulse ([heavy],[light]) at [AREACOORD(O)]") + if (severity) + empulse(O, severity, range) + log_admin("[key_name(usr)] created an EM Pulse ([range] range, [severity] severity) at [AREACOORD(O)]") + message_admins("[key_name_admin(usr)] created an EM Pulse ([range] range, [severity] severity) at [AREACOORD(O)]") SSblackbox.record_feedback("tally", "admin_verb", 1, "EM Pulse") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! return diff --git a/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm b/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm index 8c98537297d1..2ccd4b6f646e 100644 --- a/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm +++ b/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm @@ -22,7 +22,7 @@ /datum/blobstrain/reagent/electromagnetic_web/death_reaction(obj/structure/blob/B, damage_flag) if(damage_flag == MELEE || damage_flag == BULLET || damage_flag == LASER) - empulse(B.loc, 1, 3) //less than screen range, so you can stand out of range to avoid it + empulse(B.loc, EMP_HEAVY, 3) //less than screen range, so you can stand out of range to avoid it /datum/reagent/blob/electromagnetic_web name = "Electromagnetic Web" @@ -32,6 +32,6 @@ /datum/reagent/blob/electromagnetic_web/reaction_mob(mob/living/M, methods = TOUCH, reac_volume, show_message, permeability, mob/camera/blob/O) reac_volume = ..() if(prob(reac_volume*2)) - M.emp_act(EMP_LIGHT) + M.emp_act(min(reac_volume / 10, EMP_HEAVY)) if(M) M.apply_damage(reac_volume, BURN, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/structures/_blob.dm b/code/modules/antagonists/blob/structures/_blob.dm index 7178befd2ad3..e7054ad62198 100644 --- a/code/modules/antagonists/blob/structures/_blob.dm +++ b/code/modules/antagonists/blob/structures/_blob.dm @@ -5,7 +5,7 @@ light_range = 2 desc = "A thick wall of writhing tendrils." density = FALSE //this being false causes two bugs, being able to attack blob tiles behind other blobs and being unable to move on blob tiles in no gravity, but turning it to 1 causes the blob mobs to be unable to path through blobs, which is probably worse. - opacity = 0 + opacity = FALSE anchored = TRUE layer = BELOW_MOB_LAYER CanAtmosPass = ATMOS_PASS_PROC @@ -31,7 +31,7 @@ setDir(pick(GLOB.cardinals)) update_appearance(UPDATE_ICON) if(atmosblock) - air_update_turf(1) + air_update_turf() ConsumeTile() /obj/structure/blob/proc/creation_action() //When it's created by the overmind, do this. @@ -40,7 +40,7 @@ /obj/structure/blob/Destroy() if(atmosblock) atmosblock = FALSE - air_update_turf(1) + air_update_turf() if(overmind) overmind.blobs_legit -= src //if it was in the legit blobs list, it isn't now GLOB.blobs -= src //it's no longer in the all blobs list either @@ -64,7 +64,7 @@ result++ . -= result - 1 -/obj/structure/blob/BlockSuperconductivity() +/obj/structure/blob/BlockThermalConductivity() return atmosblock /obj/structure/blob/CanAllowThrough(atom/movable/mover, turf/target) @@ -206,7 +206,7 @@ if(severity > 0) if(overmind) overmind.blobstrain.emp_reaction(src, severity) - if(prob(100 - severity * 30)) + if(prob(40 + (severity * 6))) new /obj/effect/temp_visual/emp(get_turf(src)) /obj/structure/blob/tesla_act(power, tesla_flags, shocked_targets, zap_gib = FALSE) diff --git a/code/modules/antagonists/blob/structures/shield.dm b/code/modules/antagonists/blob/structures/shield.dm index 8efcb868cd75..fd34cb45ecb1 100644 --- a/code/modules/antagonists/blob/structures/shield.dm +++ b/code/modules/antagonists/blob/structures/shield.dm @@ -31,7 +31,7 @@ name = initial(name) desc = initial(desc) atmosblock = TRUE - air_update_turf(1) + air_update_turf() /obj/structure/blob/shield/reflective name = "reflective blob" diff --git a/code/modules/antagonists/bloodsuckers/bloodsucker_objectives.dm b/code/modules/antagonists/bloodsuckers/bloodsucker_objectives.dm index 7adf0f951d9a..db09e672abda 100644 --- a/code/modules/antagonists/bloodsuckers/bloodsucker_objectives.dm +++ b/code/modules/antagonists/bloodsuckers/bloodsucker_objectives.dm @@ -1,5 +1,10 @@ /datum/objective/monsterhunter name = "destroymonsters" + explanation_text = "Destroy all monsters on ." + +/datum/objective/monsterhunter/New() + update_explanation_text() + ..() // EXPLANATION /datum/objective/monsterhunter/update_explanation_text() diff --git a/code/modules/antagonists/bloodsuckers/bloodsuckers_objects.dm b/code/modules/antagonists/bloodsuckers/bloodsuckers_objects.dm index 310203b0f648..52f553ff0ad0 100644 --- a/code/modules/antagonists/bloodsuckers/bloodsuckers_objects.dm +++ b/code/modules/antagonists/bloodsuckers/bloodsuckers_objects.dm @@ -166,7 +166,6 @@ name = "silver stake" desc = "Polished and sharp at the end. For when some mofo is always trying to iceskate uphill." icon_state = "silver" - siemens_coefficient = 1 //flags = CONDUCT // var/siemens_coefficient = 1 // for electrical admittance/conductance (electrocution checks and shit) force = 9 armour_penetration = 25 embedding = list("embed_chance" = 65) diff --git a/code/modules/antagonists/bloodsuckers/powers/feed.dm b/code/modules/antagonists/bloodsuckers/powers/feed.dm index d0e5a60401aa..4b62c8dbc97d 100644 --- a/code/modules/antagonists/bloodsuckers/powers/feed.dm +++ b/code/modules/antagonists/bloodsuckers/powers/feed.dm @@ -58,7 +58,7 @@ /datum/action/cooldown/bloodsucker/feed/DeactivatePower() var/mob/living/user = owner - var/mob/living/feed_target = target_ref.resolve() + var/mob/living/feed_target = target_ref?.resolve() if(isnull(feed_target)) log_combat(user, user, "fed on blood (target not found)", addition="(and took [blood_taken] blood)") else @@ -136,7 +136,7 @@ if(!active) //If we aren't active (running on SSfastprocess) return ..() //Manage our cooldown timers var/mob/living/user = owner - var/mob/living/feed_target = target_ref.resolve() + var/mob/living/feed_target = target_ref?.resolve() if(!ContinueActive(user, feed_target)) if(!silent_feed) user.visible_message( diff --git a/code/modules/antagonists/bloodsuckers/powers/gangrel.dm b/code/modules/antagonists/bloodsuckers/powers/gangrel.dm index 0c4d987ef62e..91ab766577bd 100644 --- a/code/modules/antagonists/bloodsuckers/powers/gangrel.dm +++ b/code/modules/antagonists/bloodsuckers/powers/gangrel.dm @@ -24,11 +24,9 @@ /datum/action/cooldown/bloodsucker/gangrel/transform/ActivatePower() var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.mind.has_antag_datum(/datum/antagonist/bloodsucker) var/mob/living/carbon/human/user = owner - if(!do_after(user, 10 SECONDS)) - return var/list/radial_display = list() //get our options, switches are kinda weird here cause wwe ant to stack them - if(bloodsuckerdatum.total_blood_drank) //makes the icons for the options + if(bloodsuckerdatum) //makes the icons for the options var/datum/radial_menu_choice/option = new user.setDir(SOUTH) var/icon/icon_to_mix = getFlatIcon(user) @@ -55,6 +53,8 @@ option.info = "Turn into a giant bat simple mob with unique abilities." radial_display["Bat"] = option var/chosen_transform = show_radial_menu(user, user, radial_display) + if(!chosen_transform || !do_after(user, 10 SECONDS)) + return transform(chosen_transform) //actually transform return ..() @@ -85,7 +85,7 @@ user.dna.species.punchdamagehigh += 10 //very stronk user.dna.species.punchstunthreshold += 10 user.dna.species.action_speed_coefficient *= 1.3 - user.dna.species.armor += 40 + user.dna.species.armor += 15 bloodsuckerdatum.AddBloodVolume(50) if("Bat") var/mob/living/simple_animal/hostile/bloodsucker/giantbat/gb diff --git a/code/modules/antagonists/bloodsuckers/powers/olfaction.dm b/code/modules/antagonists/bloodsuckers/powers/olfaction.dm index 1089d603dc9a..f97c5fe9fd69 100644 --- a/code/modules/antagonists/bloodsuckers/powers/olfaction.dm +++ b/code/modules/antagonists/bloodsuckers/powers/olfaction.dm @@ -47,7 +47,7 @@ return FALSE DeactivatePower() var/datum/gas_mixture/air = owner.loc.return_air() - if(air.get_moles(/datum/gas/miasma) >= 0.1/sensitivity && sensitive) + if(air.get_moles(GAS_MIASMA) >= 0.1/sensitivity && sensitive) owner.adjust_disgust(sensitivity * 45) to_chat(owner, span_warning("With your overly sensitive nose, you get a whiff of stench and feel sick! Try moving to a cleaner area!")) return diff --git a/code/modules/antagonists/bloodsuckers/powers/targeted/hecata.dm b/code/modules/antagonists/bloodsuckers/powers/targeted/hecata.dm index b557e22ea80a..d6a55ad0705e 100644 --- a/code/modules/antagonists/bloodsuckers/powers/targeted/hecata.dm +++ b/code/modules/antagonists/bloodsuckers/powers/targeted/hecata.dm @@ -31,7 +31,18 @@ cooldown_time = 45 SECONDS target_range = 1 prefire_message = "Select a target." + var/list/zombies = list() +/datum/action/cooldown/bloodsucker/targeted/hecata/necromancy/Grant(mob/user) + . = ..() + RegisterSignal(owner, COMSIG_LIVING_DEATH, PROC_REF(die)) + +/datum/action/cooldown/bloodsucker/targeted/hecata/necromancy/proc/die() + for(var/dude in zombies) + if(isliving(dude)) //sanity check + var/mob/living/alive = dude + end_necromance(alive) + /datum/action/cooldown/bloodsucker/targeted/hecata/necromancy/CheckValidTarget(atom/target_atom) . = ..() if(!.) @@ -63,65 +74,59 @@ /datum/action/cooldown/bloodsucker/targeted/hecata/necromancy/FireTargetedPower(atom/target_atom) . = ..() + if(!iscarbon(target_atom)) + return + if(!isliving(owner)) + return var/mob/living/carbon/target = target_atom var/mob/living/user = owner - var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(/datum/antagonist/bloodsucker) - if(target.stat == DEAD && user.Adjacent(target)) - owner.balloon_alert(owner, "attempting to revive...") - if(HAS_TRAIT(target, TRAIT_MINDSHIELD)) //if they have a mindshield - owner.balloon_alert(owner, "mindshield detected, this will take longer...") - if(!do_after(user, 18 SECONDS, target)) - return FALSE - for(var/obj/item/implant/mindshield/L in target) - if(L) - qdel(L) - else - if(!do_after(user, 6 SECONDS, target)) - return FALSE - if(IS_VASSAL(target)) - power_activated_sucessfully() - owner.balloon_alert(owner, "we revive [target]!") - zombify(target) - bloodsuckerdatum.clanprogress++ //counts a succesful necromancy towards your objective progress - return - if(IS_MONSTERHUNTER(target)) - owner.balloon_alert(owner, "their body refuses to react...") - DeactivatePower() - return - var/old_species = target.dna?.species.type - zombify(target) - bloodsuckerdatum.make_vassal(target) - power_activated_sucessfully() - bloodsuckerdatum.clanprogress++ //counts a succesful necromancy towards your objective progress - to_chat(user, span_warning("We revive [target]!")) - var/living_time - switch(level_current) - if(0) - living_time = 2 MINUTES - if(1) - living_time = 5 MINUTES - if(2) - living_time = 8 MINUTES - if(3) - living_time = 11 MINUTES - if(4) - living_time = 14 MINUTES - if(5 to 99) - living_time = 17 MINUTES //in general, they don't last long, make the most of them. - addtimer(CALLBACK(src, PROC_REF(end_necromance), target, old_species), living_time) - else //extra check, but this shouldn't happen - owner.balloon_alert(owner, "out of range/not dead.") + if(!IS_BLOODSUCKER(owner)) //sanity check + return + var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind?.has_antag_datum(/datum/antagonist/bloodsucker) + + if(target.stat != DEAD) + owner.balloon_alert(owner, "not dead.") + return FALSE + + if(!user.Adjacent(target)) + owner.balloon_alert(owner, "out of range.") + return FALSE + + + owner.balloon_alert(owner, "attempting to revive...") + if(HAS_TRAIT(target, TRAIT_MINDSHIELD)) //if they have a mindshield + owner.balloon_alert(owner, "mindshield detected, this will take longer...") + if(!do_after(user, 12 SECONDS, target)) + return FALSE + for(var/obj/item/implant/mindshield/L in target) + qdel(L) + owner.balloon_alert(owner, "mindshield destroyed, proceeding with revival...") + if(!do_after(user, 6 SECONDS, target)) return FALSE + + if(IS_MONSTERHUNTER(target)) + owner.balloon_alert(owner, "their body refuses to react...") + DeactivatePower() + return + + bloodsuckerdatum.clanprogress++ //counts a succesful necromancy towards your objective progress + zombify(target) + to_chat(user, span_warning("We revive [target]!")) + if(!IS_VASSAL(target)) + var/living_time = (2 + min(level_current * 3, 15)) MINUTES //in general, they don't last long, make the most of them. + addtimer(CALLBACK(src, PROC_REF(end_necromance), target), living_time) + bloodsuckerdatum.make_vassal(target) + RegisterSignal(target, COMSIG_LIVING_DEATH, PROC_REF(remove_vassal), target) //only remove vassal from those that were initially not one + power_activated_sucessfully() DeactivatePower() -/datum/action/cooldown/bloodsucker/targeted/hecata/necromancy/proc/end_necromance(mob/living/user, old_species) - user.mind.remove_antag_datum(/datum/antagonist/vassal) - to_chat(user, span_warning("You feel the shadows around you weaken, your form falling limp like a puppet cut from its strings!")) - user.set_species(old_species ? old_species : /datum/species/krokodil_addict) //go back to original species, or lesser zombie if they somehow didn't have one - user.death() - -/datum/action/cooldown/bloodsucker/targeted/hecata/necromancy/proc/zombify(mob/living/user) +/datum/action/cooldown/bloodsucker/targeted/hecata/necromancy/proc/zombify(mob/living/carbon/user) + if(!user.mind || !istype(user)) + return user.mind.grab_ghost() + zombies |= user + if(user.dna?.species?.type) + zombies[user] = user.dna.species.type user.set_species(/datum/species/zombie/hecata) //imitation zombies that shamble around and beat people with their fists user.revive(full_heal = TRUE, admin_revive = TRUE) user.visible_message(span_danger("[user] suddenly convulses, as [user.p_they()] stagger to their feet and gain a ravenous hunger in [user.p_their()] eyes!"), span_alien("You RISE!")) @@ -129,6 +134,18 @@ to_chat(user, span_warning("Your broken form is picked up by strange shadows. If you were previously not a vassal, it is unlikely these shadows will be strong enough to keep you going for very long.")) to_chat(user, span_notice("You are resilient to many things like the vacuum of space, can punch harder, and can take more damage before dropping. However, you are unable to use guns and are slower.")) +/datum/action/cooldown/bloodsucker/targeted/hecata/necromancy/proc/remove_vassal(mob/living/carbon/user) + if(user.mind) + user.mind.remove_antag_datum(/datum/antagonist/vassal) + +/datum/action/cooldown/bloodsucker/targeted/hecata/necromancy/proc/end_necromance(mob/living/carbon/user) + if(!istype(user) || !(user in zombies)) + return + to_chat(user, span_warning("You feel the shadows around you weaken, your form falling limp like a puppet cut from its strings!")) + user.set_species(zombies[user] ? zombies[user] : /datum/species/krokodil_addict) //go back to original species, or lesser zombie if they somehow didn't have one + user.death() + zombies -= user + /datum/action/cooldown/bloodsucker/hecata purchase_flags = HECATA_CAN_BUY background_icon = 'icons/mob/actions/actions_hecata_bloodsucker.dmi' diff --git a/code/modules/antagonists/bloodsuckers/structures/bloodsucker_life.dm b/code/modules/antagonists/bloodsuckers/structures/bloodsucker_life.dm index 718b13382163..7925aa933ad6 100644 --- a/code/modules/antagonists/bloodsuckers/structures/bloodsucker_life.dm +++ b/code/modules/antagonists/bloodsuckers/structures/bloodsucker_life.dm @@ -292,7 +292,46 @@ if(bloodsucker_blood_volume < (FRENZY_THRESHOLD_ENTER + humanity_lost * 10) && !frenzied) if(!iscarbon(owner.current)) return - owner.current.apply_status_effect(/datum/status_effect/frenzy) + if(my_clan?.get_clan() == CLAN_GANGREL) + var/mob/living/carbon/user = owner.current + switch(frenzies) + if(0) + owner.current.apply_status_effect(STATUS_EFFECT_FRENZY) + if(1) + to_chat(owner, span_warning("You start feeling hungrier, you feel like a normal frenzy won't satiate it enough anymore.")) + owner.current.apply_status_effect(STATUS_EFFECT_FRENZY) + if(2 to INFINITY) + if(do_after(user, 2 SECONDS, user, IGNORE_ALL)) + playsound(user.loc, 'sound/weapons/slash.ogg', 25, 1) + to_chat(user, span_warning("You skin rips and tears.")) + if(do_after(user, 1 SECONDS, user, IGNORE_ALL)) + playsound(user.loc, 'sound/weapons/slashmiss.ogg', 25, 1) + to_chat(user, span_warning("You heart pumps blackened blood into your veins as your skin turns into fur.")) + if(do_after(user, 1 SECONDS, user, IGNORE_ALL)) + playsound(user.loc, 'sound/weapons/slice.ogg', 25, 1) + to_chat(user, span_boldnotice("YOU HAVE AWOKEN.")) + var/mob/living/simple_animal/hostile/bloodsucker/werewolf/ww + if(!ww || ww.stat == DEAD) + AddBloodVolume(560 - user.blood_volume) //so it doesn't happen multiple times and refills your blood when you get out again + ww = new /mob/living/simple_animal/hostile/bloodsucker/werewolf(user.loc) + user.forceMove(ww) + ww.bloodsucker = user + user.mind.transfer_to(ww) + var/list/wolf_powers = list(new /datum/action/cooldown/bloodsucker/targeted/feast,) + for(var/datum/action/cooldown/bloodsucker/power in powers) + if(istype(power, /datum/action/cooldown/bloodsucker/fortitude)) + wolf_powers += new /datum/action/cooldown/bloodsucker/gangrel/wolfortitude + if(istype(power, /datum/action/cooldown/bloodsucker/targeted/lunge)) + wolf_powers += new /datum/action/cooldown/bloodsucker/targeted/pounce + if(istype(power, /datum/action/cooldown/bloodsucker/cloak)) + wolf_powers += new /datum/action/cooldown/bloodsucker/gangrel/howl + if(istype(power, /datum/action/cooldown/bloodsucker/targeted/trespass)) + wolf_powers += new /datum/action/cooldown/bloodsucker/gangrel/rabidism + for(var/datum/action/cooldown/bloodsucker/power in wolf_powers) + power.Grant(ww) + frenzies ++ + else + owner.current.apply_status_effect(STATUS_EFFECT_FRENZY) else if(bloodsucker_blood_volume < BLOOD_VOLUME_BAD(owner.current)) additional_regen = 0.1 else if(bloodsucker_blood_volume < BLOOD_VOLUME_OKAY(owner.current)) @@ -463,13 +502,12 @@ return //If we're on Masquerade, we appear to have full blood, unless we are REALLY low, in which case we don't look as bad. if(HAS_TRAIT(owner.current, TRAIT_MASQUERADE)) - switch(bloodsucker_blood_volume) - if(BLOOD_VOLUME_OKAY(owner.current) to INFINITY) // 336 and up, we are perfectly fine. - owner.current.blood_volume = initial(bloodsucker_blood_volume) - if(BLOOD_VOLUME_BAD(owner.current) to BLOOD_VOLUME_OKAY(owner.current)) // 224 to 336 - owner.current.blood_volume = BLOOD_VOLUME_SAFE(owner.current) - else // 224 and below - owner.current.blood_volume = BLOOD_VOLUME_OKAY(owner.current) + if(bloodsucker_blood_volume >= BLOOD_VOLUME_OKAY(owner.current)) + owner.current.blood_volume = initial(bloodsucker_blood_volume) + else if(bloodsucker_blood_volume >= BLOOD_VOLUME_BAD(owner.current)) + owner.current.blood_volume = BLOOD_VOLUME_SAFE(owner.current) + else + owner.current.blood_volume = BLOOD_VOLUME_OKAY(owner.current) return owner.current.blood_volume = bloodsucker_blood_volume diff --git a/code/modules/antagonists/changeling/powers/shriek.dm b/code/modules/antagonists/changeling/powers/shriek.dm index 6a56642dce33..9c3cf68e97b7 100644 --- a/code/modules/antagonists/changeling/powers/shriek.dm +++ b/code/modules/antagonists/changeling/powers/shriek.dm @@ -53,5 +53,5 @@ for(var/obj/machinery/light/L in range(5, usr)) L.on = 1 L.break_light_tube() - empulse(get_turf(user), 2, 5, 1) + empulse(get_turf(user), EMP_HEAVY, 5, 1) return TRUE diff --git a/code/modules/antagonists/clockcult/clock_effect.dm b/code/modules/antagonists/clockcult/clock_effect.dm index a788677eb162..237a15c72763 100644 --- a/code/modules/antagonists/clockcult/clock_effect.dm +++ b/code/modules/antagonists/clockcult/clock_effect.dm @@ -7,7 +7,7 @@ icon_state = "ratvars_flame" anchored = TRUE density = FALSE - opacity = 0 + opacity = FALSE resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF /obj/effect/clockwork/Initialize(mapload) diff --git a/code/modules/antagonists/clockcult/clock_effects/servant_blocker.dm b/code/modules/antagonists/clockcult/clock_effects/servant_blocker.dm index e1d464e41047..9bf278d7800e 100644 --- a/code/modules/antagonists/clockcult/clock_effects/servant_blocker.dm +++ b/code/modules/antagonists/clockcult/clock_effects/servant_blocker.dm @@ -10,7 +10,7 @@ /obj/effect/clockwork/servant_blocker/Initialize(mapload) . = ..() - air_update_turf(TRUE) + air_update_turf() /obj/effect/clockwork/servant_blocker/Destroy(force) if(!force) @@ -30,7 +30,7 @@ return FALSE return TRUE -/obj/effect/clockwork/servant_blocker/BlockSuperconductivity() +/obj/effect/clockwork/servant_blocker/BlockThermalConductivity() return TRUE /obj/effect/clockwork/servant_blocker/singularity_act() diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/longsword.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/longsword.dm index d931924b3b5d..1d71903ac051 100644 --- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/longsword.dm +++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/longsword.dm @@ -8,13 +8,14 @@ block_chance = 35 attack_verb = list("attacked", "slashed", "cut", "torn", "gored") clockwork_desc = "A powerful sword of Ratvarian making. Enemies hit with it will be struck with a powerful electromagnetic pulse." + var/emp_severity = EMP_LIGHT var/emp_cooldown = 0 var/cooldown_duration = 10 SECONDS /obj/item/clockwork/weapon/brass_sword/attack(mob/living/target, mob/living/carbon/human/user) . = ..() if(world.time > emp_cooldown && !is_servant_of_ratvar(target)) - target.emp_act(EMP_LIGHT) + target.emp_act(emp_severity) emp_cooldown = world.time + cooldown_duration addtimer(CALLBACK(src, PROC_REF(send_message)), cooldown_duration) to_chat(user, "You strike [target] with an electromagnetic pulse!") @@ -24,7 +25,7 @@ /obj/item/clockwork/weapon/brass_sword/attack_obj(obj/O, mob/living/user) . = ..() if(world.time > emp_cooldown && ismecha(O)) - O.emp_act(EMP_HEAVY) + O.emp_act(emp_severity * 2) emp_cooldown = world.time + cooldown_duration addtimer(CALLBACK(src, PROC_REF(send_message)), cooldown_duration) to_chat(user, "You strike [O] with an electromagnetic pulse!") diff --git a/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm b/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm index cc539fc00785..689b95fbe4ad 100644 --- a/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm +++ b/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm @@ -131,9 +131,8 @@ body_parts_covered = ARMS cold_protection = ARMS heat_protection = ARMS - siemens_coefficient = 0 resistance_flags = FIRE_PROOF | ACID_PROOF - armor = list(MELEE = 50, BULLET = 40, LASER = 20, ENERGY = 10, BOMB = 60, BIO = 60, RAD = 0, FIRE = 100, ACID = 100) + armor = list(MELEE = 50, BULLET = 40, LASER = 20, ENERGY = 10, BOMB = 60, BIO = 60, RAD = 0, FIRE = 100, ACID = 100, ELECTRIC = 100) /obj/item/clothing/gloves/clockwork/Initialize(mapload) . = ..() @@ -146,17 +145,17 @@ /obj/item/clothing/gloves/clockwork/ratvar_act() if(GLOB.ratvar_awakens) - armor.setRating(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 100, bio = 100, rad = 100, fire = 100, acid = 100) + armor.setRating(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 100, bio = 100, rad = 100, fire = 100, acid = 100, electric = 100) clothing_flags |= STOPSPRESSUREDAMAGE max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT else if(GLOB.ratvar_approaches) - armor.setRating(melee = 60, bullet = 50, laser = 25, energy = 25, bomb = 60, bio = 90, rad = 0, fire = 100, acid = 100) + armor.setRating(melee = 60, bullet = 50, laser = 25, energy = 25, bomb = 60, bio = 90, rad = 0, fire = 100, acid = 100, electric = 100) clothing_flags |= STOPSPRESSUREDAMAGE max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT else - armor.setRating(melee = 50, bullet = 40, laser = 20, energy = 10, bomb = 60, bio = 60, rad = 0, fire = 100, acid = 100) + armor.setRating(melee = 50, bullet = 40, laser = 20, energy = 10, bomb = 60, bio = 60, rad = 0, fire = 100, acid = 100, electric = 100) clothing_flags &= ~STOPSPRESSUREDAMAGE max_heat_protection_temperature = initial(max_heat_protection_temperature) min_cold_protection_temperature = initial(min_cold_protection_temperature) diff --git a/code/modules/antagonists/clockcult/clock_mobs.dm b/code/modules/antagonists/clockcult/clock_mobs.dm index f51d9430640f..0a080e94fe02 100644 --- a/code/modules/antagonists/clockcult/clock_mobs.dm +++ b/code/modules/antagonists/clockcult/clock_mobs.dm @@ -37,7 +37,7 @@ /mob/living/simple_animal/hostile/clockwork/ratvar_act() fully_heal(TRUE) -/mob/living/simple_animal/hostile/clockwork/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE, gib = FALSE) +/mob/living/simple_animal/hostile/clockwork/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, zone = null, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE, gib = FALSE) return 0 //ouch, my metal-unlikely-to-be-damaged-by-electricity-body /mob/living/simple_animal/hostile/clockwork/examine(mob/user) diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index 558b3d5cace4..f8c9196488a5 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -423,12 +423,12 @@ user.visible_message(span_warning("[user] holds up [user.p_their()] hand, which explodes in a flash of red light!"), \ span_cultitalic("You attempt to stun [L] with the spell!")) - user.mob_light(_range = 3, _color = LIGHT_COLOR_BLOOD_MAGIC, _duration = 0.2 SECONDS) + user.mob_light(range = 3, color = LIGHT_COLOR_BLOOD_MAGIC, duration = 0.2 SECONDS) var/anti_magic_source = L.can_block_magic() if(anti_magic_source) - L.mob_light(_range = 2, _color = LIGHT_COLOR_HOLY_MAGIC, _duration = 10 SECONDS) + L.mob_light(range = 2, color = LIGHT_COLOR_HOLY_MAGIC, duration = 10 SECONDS) var/mutable_appearance/forbearance = mutable_appearance('icons/effects/genetics.dmi', "servitude", -MUTATIONS_LAYER) L.add_overlay(forbearance) addtimer(CALLBACK(L, TYPE_PROC_REF(/atom, cut_overlay), forbearance), 100) diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 11a7f4fd5009..87b5d4ed3f62 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -695,7 +695,6 @@ GLOBAL_VAR_INIT(curselimit, 0) /obj/item/cult_spear/Initialize(mapload) . = ..() AddComponent(/datum/component/two_handed, \ - force_unwielded = 12, \ force_wielded = 16, \ icon_wielded = "[base_icon_state]1", \ wielded_stats = list(SWING_SPEED = 1, ENCUMBRANCE = 0.4, ENCUMBRANCE_TIME = 5, REACH = 2, DAMAGE_LOW = 2, DAMAGE_HIGH = 5), \ diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index 4884191cd10c..c6d9cee7a905 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -699,7 +699,7 @@ structure_check() searches for nearby cultist structures required for the invoca GLOB.wall_runes -= src return ..() -/obj/effect/rune/wall/BlockSuperconductivity() +/obj/effect/rune/wall/BlockThermalConductivity() return density /obj/effect/rune/wall/invoke(list/invokers) @@ -742,7 +742,7 @@ structure_check() searches for nearby cultist structures required for the invoca /obj/effect/rune/wall/proc/update_state() deltimer(density_timer) - air_update_turf(1) + air_update_turf() if(density) density_timer = addtimer(CALLBACK(src, PROC_REF(lose_density)), 300, TIMER_STOPPABLE) //yogs: 30 seconds instead of 300 I could microwave a pizza before a barrier rune went down naturally var/mutable_appearance/shimmer = mutable_appearance('icons/effects/effects.dmi', "barriershimmer", ABOVE_MOB_LAYER) @@ -1046,7 +1046,7 @@ structure_check() searches for nearby cultist structures required for the invoca visible_message(span_warning("A colossal shockwave of energy bursts from the rune, disintegrating it in the process!")) for(var/mob/living/L in range(src, 3)) L.Paralyze(30) - empulse(T, 0.42*(intensity), 1) + empulse(T, 0.42*(intensity)) var/list/images = list() var/zmatch = T.z var/datum/atom_hud/AH = GLOB.huds[DATA_HUD_SECURITY_ADVANCED] diff --git a/code/modules/antagonists/eldritch_cult/eldritch_antag.dm b/code/modules/antagonists/eldritch_cult/eldritch_antag.dm index 31d010a0f97e..15b3ca169506 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_antag.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_antag.dm @@ -13,7 +13,7 @@ var/list/researched_knowledge = list() var/list/transmutations = list() var/total_sacrifices = 0 - var/lore = "Unpledged" //Used to track which path the heretic has taken + var/lore = PATH_NONE //Used to track which path the heretic has taken var/ascended = FALSE var/transformed = FALSE //Used to track if the heretic sheds their own body during ascension var/charge = 1 @@ -21,89 +21,8 @@ var/knowledge_tier = TIER_PATH //oh boy this is going to be fun ///tracks the number of knowledges to next tier, currently 3 var/tier_counter = 0 -///list of knowledges available, by path. every odd tier is an exclusive upgrade, and every even one is a set of upgrades of which 3 need to be picked to move on. ///order these from main path ability (will choose the color in the UI) to minor abilities below them (will once again, make sense if you look at the in game UI) - var/list/knowledges = list( - TIER_PATH = list( - /datum/eldritch_knowledge/base_ash, - /datum/eldritch_knowledge/base_flesh, - /datum/eldritch_knowledge/base_rust, - /datum/eldritch_knowledge/base_mind, - /datum/eldritch_knowledge/base_void, - /datum/eldritch_knowledge/base_blade, - /datum/eldritch_knowledge/base_cosmic, - /datum/eldritch_knowledge/base_knock), - TIER_1 = list( - /datum/eldritch_knowledge/madness_mask, - /datum/eldritch_knowledge/flesh_ghoul, - /datum/eldritch_knowledge/rust_regen, - /datum/eldritch_knowledge/spell/eldritchbolt, - /datum/eldritch_knowledge/rune_carver, - /datum/eldritch_knowledge/blade_dance, - /datum/eldritch_knowledge/spell/cosmic_runes, - /datum/eldritch_knowledge/key_ring, - /datum/eldritch_knowledge/armor, - /datum/eldritch_knowledge/spell/rust_construction, - /datum/eldritch_knowledge/void_cloak, - /datum/eldritch_knowledge/ashen_eyes, - /datum/eldritch_knowledge/essence, - /datum/eldritch_knowledge/eldritch_eye, - /datum/eldritch_knowledge/fire_shark), - TIER_MARK = list( - /datum/eldritch_knowledge/ash_mark, - /datum/eldritch_knowledge/flesh_mark, - /datum/eldritch_knowledge/rust_mark, - /datum/eldritch_knowledge/mind_mark, - /datum/eldritch_knowledge/void_mark, - /datum/eldritch_knowledge/blade_mark, - /datum/eldritch_knowledge/cosmic_mark, - /datum/eldritch_knowledge/knock_mark), - TIER_2 = list( - /datum/eldritch_knowledge/spell/volcano_blast, - /datum/eldritch_knowledge/raw_prophet, - /datum/eldritch_knowledge/spell/area_conversion, - /datum/eldritch_knowledge/spell/assault, - /datum/eldritch_knowledge/cold_snap, - /datum/eldritch_knowledge/duel_stance, - /datum/eldritch_knowledge/spell/star_blast, - /datum/eldritch_knowledge/spell/burglar_finesse, - /datum/eldritch_knowledge/spell/realignment, - /datum/eldritch_knowledge/spell/blood_siphon, - /datum/eldritch_knowledge/spell/void_blast), - TIER_BLADE = list( - /datum/eldritch_knowledge/ash_blade_upgrade, - /datum/eldritch_knowledge/flesh_blade_upgrade, - /datum/eldritch_knowledge/rust_blade_upgrade, - /datum/eldritch_knowledge/mind_blade_upgrade, - /datum/eldritch_knowledge/void_blade_upgrade, - /datum/eldritch_knowledge/blade_blade_upgrade, - /datum/eldritch_knowledge/cosmic_blade_upgrade, - /datum/eldritch_knowledge/knock_blade_upgrade), - TIER_3 = list( - /datum/eldritch_knowledge/spell/flame_birth, - /datum/eldritch_knowledge/stalker, - /datum/eldritch_knowledge/spell/entropic_plume, - /datum/eldritch_knowledge/cerebral_control, - /datum/eldritch_knowledge/spell/void_pull, - /datum/eldritch_knowledge/spell/furious_steel, - /datum/eldritch_knowledge/spell/cosmic_expansion, - /datum/eldritch_knowledge/spell/freedom_forever, - /datum/eldritch_knowledge/lionhunter_rifle, - /datum/eldritch_knowledge/ashy, - /datum/eldritch_knowledge/rusty, - /datum/eldritch_knowledge/spell/cleave, - /datum/eldritch_knowledge/spell/famished_roar, - /datum/eldritch_knowledge/spell/call_of_ice), - TIER_ASCEND = list( - /datum/eldritch_knowledge/ash_final, - /datum/eldritch_knowledge/flesh_final, - /datum/eldritch_knowledge/rust_final, - /datum/eldritch_knowledge/mind_final, - /datum/eldritch_knowledge/void_final, - /datum/eldritch_knowledge/blade_final, - /datum/eldritch_knowledge/cosmic_final, - /datum/eldritch_knowledge/knock_final)) - + var/static/list/path_to_ui_color = list( PATH_START = "grey", PATH_SIDE = "green", @@ -123,10 +42,10 @@ data["charges"] = charge data["total_sacrifices"] = total_sacrifices data["ascended"] = ascended - + data["path"] = lore + for(var/datum/eldritch_knowledge/knowledge as anything in get_researchable_knowledge()) var/list/knowledge_data = list() - knowledge_data["path"] = lore knowledge_data["name"] = initial(knowledge.name) knowledge_data["desc"] = initial(knowledge.desc) knowledge_data["gainFlavor"] = initial(knowledge.gain_text) @@ -141,7 +60,7 @@ knowledge_data["color"] = path_to_ui_color[initial(knowledge.route)] || "grey" data["learnableKnowledge"] += list(knowledge_data) - + for(var/path in researched_knowledge) var/list/knowledge_data = list() var/datum/eldritch_knowledge/found_knowledge = researched_knowledge[path] @@ -161,8 +80,6 @@ data["objectives"] = get_objectives() - - return data /datum/antagonist/heretic/ui_act(action, params) @@ -838,15 +755,17 @@ /datum/antagonist/heretic/proc/get_researchable_knowledge() var/list/researchable_knowledge = list() - var/list/banned_knowledge = list() - for(var/X in researched_knowledge) - var/datum/eldritch_knowledge/EK = researched_knowledge[X] - banned_knowledge |= EK.banned_knowledge - banned_knowledge |= EK.type - for(var/i in TIER_PATH to knowledge_tier) - for(var/knowledge in knowledges[i]) - researchable_knowledge += knowledge - researchable_knowledge -= banned_knowledge + for(var/datum/eldritch_knowledge/knowledge as anything in subtypesof(/datum/eldritch_knowledge)) + if(locate(knowledge) in researched_knowledge) + continue + if(initial(knowledge.tier) > knowledge_tier) + continue + if((initial(knowledge.tier) == TIER_PATH) && lore != PATH_NONE) + continue + if((initial(knowledge.tier) == TIER_MARK || initial(knowledge.tier) == TIER_BLADE || initial(knowledge.tier) == TIER_ASCEND) && lore != initial(knowledge.route)) + continue + researchable_knowledge += knowledge + return researchable_knowledge /datum/antagonist/heretic/proc/get_knowledge(wanted) @@ -862,31 +781,31 @@ return transmutations /datum/antagonist/heretic/proc/is_ash() - return "[lore]" == "Ash" + return "[lore]" == PATH_ASH /datum/antagonist/heretic/proc/is_flesh() - return "[lore]" == "Flesh" + return "[lore]" == PATH_FLESH /datum/antagonist/heretic/proc/is_rust() - return "[lore]" == "Rust" + return "[lore]" == PATH_RUST /datum/antagonist/heretic/proc/is_mind() - return "[lore]" == "Mind" + return "[lore]" == PATH_MIND /datum/antagonist/heretic/proc/is_void() - return "[lore]" == "Void" + return "[lore]" == PATH_VOID /datum/antagonist/heretic/proc/is_blade() - return "[lore]" == "Blade" + return "[lore]" == PATH_BLADE /datum/antagonist/heretic/proc/is_cosmic() - return "[lore]" == "Cosmic" + return "[lore]" == PATH_COSMIC /datum/antagonist/heretic/proc/is_knock() - return "[lore]" == "Knock" + return "[lore]" == PATH_KNOCK /datum/antagonist/heretic/proc/is_unpledged() - return "[lore]" == "Unpledged" + return "[lore]" == PATH_NONE //////////////// // Objectives // diff --git a/code/modules/antagonists/eldritch_cult/eldritch_gun.dm b/code/modules/antagonists/eldritch_cult/eldritch_gun.dm index 38b94e060142..2f902acbc474 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_gun.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_gun.dm @@ -120,7 +120,7 @@ BB.stamina *= 2 BB.knockdown = 0.5 SECONDS BB.stutter = 6 SECONDS - BB.projectile_phasing = PASSTABLE | PASSGLASS | PASSGRILLE | PASSCLOSEDTURF | PASSMACHINES | PASSSTRUCTURE | PASSDOORS + BB.projectile_phasing = PASSTABLE | PASSGLASS | PASSGRILLE | PASSCLOSEDTURF | PASSMACHINES | PASSSTRUCTURE | PASSDOOR BB.homing = TRUE BB.homing_turn_speed = 80 diff --git a/code/modules/antagonists/eldritch_cult/eldritch_items.dm b/code/modules/antagonists/eldritch_cult/eldritch_items.dm index 2707f24409b3..693016e600dc 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_items.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_items.dm @@ -107,6 +107,7 @@ force = 20 armour_penetration = 25 throwforce = 10 + wound_bonus = -5 hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacks", "slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "rends") var/datum/action/innate/heretic_shatter/linked_action diff --git a/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm b/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm index 2f8153ebc912..bb8b40f9dddd 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm @@ -17,8 +17,6 @@ var/cost = 0 ///tier of the spell, 3 of any tier is required to purchase the next ugprade knowledge, and upgrades unlock the next tier. TIER_NONE will not advance anything. var/tier = TIER_NONE - ///What knowledge is incompatible with this. This will simply make it impossible to research knowledges that are in banned_knowledge once this gets researched. - var/list/banned_knowledge = list() ///What path is this on defaults to "Side" var/route = PATH_SIDE ///transmutation recipes unlocked by this knowledge diff --git a/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm index 4bdc5cc2bd4e..53092c81197c 100644 --- a/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm +++ b/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm @@ -2,35 +2,6 @@ name = "Nightwatcher's Secret" desc = "Pledges yourself to the path of Ash. Allows you to transmute a pile of ash with a knife or its derivatives into an ashen blade. Additionally, empowers your Mansus grasp to throw enemies away from you. You will also become more resistant to fire." gain_text = "Night on the Kilnplains reveals the Ashy Lantern in the sky. In your dreams, you reached out and touched it. Now, like it, you are a part of the dunes. Forever." - banned_knowledge = list( - /datum/eldritch_knowledge/base_rust, - /datum/eldritch_knowledge/base_flesh, - /datum/eldritch_knowledge/base_mind, - /datum/eldritch_knowledge/base_void, - /datum/eldritch_knowledge/base_blade, - /datum/eldritch_knowledge/base_cosmic, - /datum/eldritch_knowledge/base_knock, - /datum/eldritch_knowledge/rust_mark, - /datum/eldritch_knowledge/flesh_mark, - /datum/eldritch_knowledge/mind_mark, - /datum/eldritch_knowledge/void_mark, - /datum/eldritch_knowledge/blade_mark, - /datum/eldritch_knowledge/cosmic_mark, - /datum/eldritch_knowledge/knock_mark, - /datum/eldritch_knowledge/rust_blade_upgrade, - /datum/eldritch_knowledge/flesh_blade_upgrade, - /datum/eldritch_knowledge/mind_blade_upgrade, - /datum/eldritch_knowledge/void_blade_upgrade, - /datum/eldritch_knowledge/blade_blade_upgrade, - /datum/eldritch_knowledge/cosmic_blade_upgrade, - /datum/eldritch_knowledge/knock_blade_upgrade, - /datum/eldritch_knowledge/rust_final, - /datum/eldritch_knowledge/flesh_final, - /datum/eldritch_knowledge/mind_final, - /datum/eldritch_knowledge/void_final, - /datum/eldritch_knowledge/blade_final, - /datum/eldritch_knowledge/cosmic_final, - /datum/eldritch_knowledge/knock_final) unlocked_transmutations = list(/datum/eldritch_transmutation/ash_knife) cost = 1 route = PATH_ASH @@ -94,6 +65,7 @@ desc = "Allows you to craft an eldritch amulet by transmuting a pair of eyes with a glass shard. When worn, the amulet will give you thermal vision." unlocked_transmutations = list(/datum/eldritch_transmutation/ashen_eyes) cost = 1 + route = PATH_ASH tier = TIER_1 /datum/eldritch_knowledge/ash_mark @@ -101,14 +73,6 @@ gain_text = "All living things are linked through their sparks. This technique represents a fraction of the Shrouded One's communality." desc = "Your Mansus grasp now applies a mark on hit. Use your ashen blade to detonate the mark, which causes burning that can spread to nearby targets, decreasing in damage with each jump." cost = 2 - banned_knowledge = list( - /datum/eldritch_knowledge/rust_mark, - /datum/eldritch_knowledge/flesh_mark, - /datum/eldritch_knowledge/mind_mark, - /datum/eldritch_knowledge/void_mark, - /datum/eldritch_knowledge/blade_mark, - /datum/eldritch_knowledge/cosmic_mark, - /datum/eldritch_knowledge/knock_mark,) route = PATH_ASH tier = TIER_MARK @@ -166,14 +130,6 @@ gain_text = "The stench of boiling blood was common in the wake of the City Guard. Though they are gone, the memory of their pikes and greatswords may yet benefit you." desc = "Your ashen blade will now ignite targets." cost = 2 - banned_knowledge = list( - /datum/eldritch_knowledge/rust_blade_upgrade, - /datum/eldritch_knowledge/flesh_blade_upgrade, - /datum/eldritch_knowledge/mind_blade_upgrade, - /datum/eldritch_knowledge/void_blade_upgrade, - /datum/eldritch_knowledge/blade_blade_upgrade, - /datum/eldritch_knowledge/cosmic_blade_upgrade, - /datum/eldritch_knowledge/knock_blade_upgrade,) route = PATH_ASH tier = TIER_BLADE @@ -199,6 +155,7 @@ desc = "A powerful ranged spell that causes heavy bleeding and blood loss in an area around your target." cost = 1 spell_to_add = /datum/action/cooldown/spell/pointed/cleave + route = PATH_ASH tier = TIER_3 /datum/eldritch_knowledge/ash_final diff --git a/code/modules/antagonists/eldritch_cult/knowledge/blade_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/blade_lore.dm index 9ed83a92e4b8..6989d662bb75 100644 --- a/code/modules/antagonists/eldritch_cult/knowledge/blade_lore.dm +++ b/code/modules/antagonists/eldritch_cult/knowledge/blade_lore.dm @@ -2,35 +2,6 @@ name = "The Cutting Edge" desc = "Pledges yourself to the path of Blade. Allows you to transmute a bar of silver with a knife or its derivatives into a Sundered Blade. Additionally, empowers your Mansus grasp to deal brute damage and paralyze enemies hit." gain_text = "Our great ancestors forged swords and practiced sparring on the eve of great battles." - banned_knowledge = list( - /datum/eldritch_knowledge/base_ash, - /datum/eldritch_knowledge/base_rust, - /datum/eldritch_knowledge/base_flesh, - /datum/eldritch_knowledge/base_mind, - /datum/eldritch_knowledge/base_void, - /datum/eldritch_knowledge/base_cosmic, - /datum/eldritch_knowledge/base_knock, - /datum/eldritch_knowledge/ash_mark, - /datum/eldritch_knowledge/rust_mark, - /datum/eldritch_knowledge/flesh_mark, - /datum/eldritch_knowledge/mind_mark, - /datum/eldritch_knowledge/void_mark, - /datum/eldritch_knowledge/cosmic_mark, - /datum/eldritch_knowledge/knock_mark, - /datum/eldritch_knowledge/ash_blade_upgrade, - /datum/eldritch_knowledge/rust_blade_upgrade, - /datum/eldritch_knowledge/flesh_blade_upgrade, - /datum/eldritch_knowledge/mind_blade_upgrade, - /datum/eldritch_knowledge/void_blade_upgrade, - /datum/eldritch_knowledge/cosmic_blade_upgrade, - /datum/eldritch_knowledge/knock_blade_upgrade, - /datum/eldritch_knowledge/ash_final, - /datum/eldritch_knowledge/rust_final, - /datum/eldritch_knowledge/flesh_final, - /datum/eldritch_knowledge/mind_final, - /datum/eldritch_knowledge/void_final, - /datum/eldritch_knowledge/cosmic_final, - /datum/eldritch_knowledge/knock_final) unlocked_transmutations = list(/datum/eldritch_transmutation/dark_knife) cost = 1 route = PATH_BLADE @@ -201,14 +172,6 @@ That is how I met them. Their name was The Colonel." desc = "Allows you to craft Eldrtich Whetstones, one time use items that can enhance the sharpness of your blades up to a certain degree." cost = 2 - banned_knowledge = list( - /datum/eldritch_knowledge/ash_mark, - /datum/eldritch_knowledge/rust_mark, - /datum/eldritch_knowledge/flesh_mark, - /datum/eldritch_knowledge/mind_mark, - /datum/eldritch_knowledge/void_mark, - /datum/eldritch_knowledge/cosmic_mark, - /datum/eldritch_knowledge/knock_mark,) unlocked_transmutations = list(/datum/eldritch_transmutation/eldritch_whetstone) route = PATH_BLADE tier = TIER_MARK @@ -218,7 +181,6 @@ var/obj/eldwhetstone = new /obj/item/sharpener/eldritch user.put_in_hands(eldwhetstone) - /datum/eldritch_knowledge/duel_stance name = "T2 - Stance of the Torn Champion" desc = "Grants immunity to having your limbs dismembered. \ @@ -241,6 +203,7 @@ gain_text = "In the flurry of death, he found peace within himself. Despite insurmountable odds, he forged on." cost = 1 spell_to_add = /datum/action/cooldown/spell/realignment + route = PATH_BLADE tier = TIER_2 /datum/eldritch_knowledge/duel_stance/on_gain(mob/user, datum/antagonist/heretic/our_heretic) @@ -287,14 +250,6 @@ gain_text = "I found him cleaved in twain, halves locked in a duel without end; \ a flurry of blades, neither hitting their mark, for the Champion was indomitable." cost = 2 - banned_knowledge = list( - /datum/eldritch_knowledge/ash_blade_upgrade, - /datum/eldritch_knowledge/rust_blade_upgrade, - /datum/eldritch_knowledge/flesh_blade_upgrade, - /datum/eldritch_knowledge/mind_blade_upgrade, - /datum/eldritch_knowledge/void_blade_upgrade, - /datum/eldritch_knowledge/cosmic_blade_upgrade, - /datum/eldritch_knowledge/knock_blade_upgrade,) unlocked_transmutations = list(/datum/eldritch_transmutation/bone_knife) route = PATH_BLADE tier = TIER_BLADE diff --git a/code/modules/antagonists/eldritch_cult/knowledge/cosmo_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/cosmo_lore.dm index f591fe7c2863..68381332e33e 100644 --- a/code/modules/antagonists/eldritch_cult/knowledge/cosmo_lore.dm +++ b/code/modules/antagonists/eldritch_cult/knowledge/cosmo_lore.dm @@ -3,35 +3,6 @@ desc = "Opens up the Path of Cosmos to you. \ Allows you to transmute a sheet of plasma and a knife into an Cosmic Blade. \ Additionally your grasp will now cause a cosmic ring on your targets, which are affected by your abilities." gain_text = "A nebula appeared in the sky, its infernal birth shone upon me. This was the start of a great transcendence." - banned_knowledge = list( - /datum/eldritch_knowledge/base_ash, - /datum/eldritch_knowledge/base_rust, - /datum/eldritch_knowledge/base_flesh, - /datum/eldritch_knowledge/base_mind, - /datum/eldritch_knowledge/base_void, - /datum/eldritch_knowledge/base_blade, - /datum/eldritch_knowledge/base_knock, - /datum/eldritch_knowledge/ash_mark, - /datum/eldritch_knowledge/rust_mark, - /datum/eldritch_knowledge/flesh_mark, - /datum/eldritch_knowledge/mind_mark, - /datum/eldritch_knowledge/void_mark, - /datum/eldritch_knowledge/blade_mark, - /datum/eldritch_knowledge/knock_mark, - /datum/eldritch_knowledge/ash_blade_upgrade, - /datum/eldritch_knowledge/rust_blade_upgrade, - /datum/eldritch_knowledge/flesh_blade_upgrade, - /datum/eldritch_knowledge/mind_blade_upgrade, - /datum/eldritch_knowledge/void_blade_upgrade, - /datum/eldritch_knowledge/blade_blade_upgrade, - /datum/eldritch_knowledge/knock_blade_upgrade, - /datum/eldritch_knowledge/ash_final, - /datum/eldritch_knowledge/rust_final, - /datum/eldritch_knowledge/flesh_final, - /datum/eldritch_knowledge/mind_final, - /datum/eldritch_knowledge/void_final, - /datum/eldritch_knowledge/blade_final, - /datum/eldritch_knowledge/knock_final) unlocked_transmutations = list(/datum/eldritch_transmutation/cosmic_knife) cost = 1 route = PATH_COSMIC @@ -86,14 +57,6 @@ They will then be paralyzed for 2 seconds." gain_text = "The Beast now whispered to me occasionally, only small tidbits of their circumstances. \ I can help them, I have to help them." - banned_knowledge = list( - /datum/eldritch_knowledge/ash_mark, - /datum/eldritch_knowledge/rust_mark, - /datum/eldritch_knowledge/flesh_mark, - /datum/eldritch_knowledge/mind_mark, - /datum/eldritch_knowledge/void_mark, - /datum/eldritch_knowledge/blade_mark, - /datum/eldritch_knowledge/knock_mark,) route = PATH_COSMIC tier = TIER_MARK @@ -134,14 +97,6 @@ desc = "Your blade now deals damage to people's cells through cosmic radiation." gain_text = "The Beast took my blades in their hand, I kneeled and felt a sharp pain. \ The blades now glistened with fragmented power. I fell to the ground and wept at the beast's feet." - banned_knowledge = list( - /datum/eldritch_knowledge/ash_blade_upgrade, - /datum/eldritch_knowledge/rust_blade_upgrade, - /datum/eldritch_knowledge/flesh_blade_upgrade, - /datum/eldritch_knowledge/mind_blade_upgrade, - /datum/eldritch_knowledge/void_blade_upgrade, - /datum/eldritch_knowledge/blade_blade_upgrade, - /datum/eldritch_knowledge/knock_blade_upgrade) route = PATH_COSMIC tier = TIER_BLADE diff --git a/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm index 23b2c2c5e881..1252b9c7a63e 100644 --- a/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm +++ b/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm @@ -2,35 +2,6 @@ name = "Principle of Hunger" desc = "Pledges yourself to the path of Flesh. Allows you to transmute a pool of blood with a knife into a flesh blade. Additionally, your Mansus grasp now raises dead humanoids into subservient ghouls if they are not mindshielded or husked. It will husk the person it's used on." gain_text = "The Priest has seduced countless into his flock. He will entice countless more with the Glorious Feast. You knelt before his statue and swore the Red Oath." - banned_knowledge = list( - /datum/eldritch_knowledge/base_ash, - /datum/eldritch_knowledge/base_rust, - /datum/eldritch_knowledge/base_mind, - /datum/eldritch_knowledge/base_void, - /datum/eldritch_knowledge/base_blade, - /datum/eldritch_knowledge/base_cosmic, - /datum/eldritch_knowledge/base_knock, - /datum/eldritch_knowledge/ash_mark, - /datum/eldritch_knowledge/rust_mark, - /datum/eldritch_knowledge/mind_mark, - /datum/eldritch_knowledge/void_mark, - /datum/eldritch_knowledge/blade_mark, - /datum/eldritch_knowledge/cosmic_mark, - /datum/eldritch_knowledge/knock_mark, - /datum/eldritch_knowledge/ash_blade_upgrade, - /datum/eldritch_knowledge/rust_blade_upgrade, - /datum/eldritch_knowledge/mind_blade_upgrade, - /datum/eldritch_knowledge/void_blade_upgrade, - /datum/eldritch_knowledge/blade_blade_upgrade, - /datum/eldritch_knowledge/cosmic_blade_upgrade, - /datum/eldritch_knowledge/knock_blade_upgrade, - /datum/eldritch_knowledge/ash_final, - /datum/eldritch_knowledge/rust_final, - /datum/eldritch_knowledge/mind_final, - /datum/eldritch_knowledge/void_final, - /datum/eldritch_knowledge/blade_final, - /datum/eldritch_knowledge/cosmic_final, - /datum/eldritch_knowledge/knock_final) cost = 1 unlocked_transmutations = list(/datum/eldritch_transmutation/flesh_blade) route = PATH_FLESH @@ -131,6 +102,7 @@ desc = "Allows you to summon a Fire Shark by transmuting a pair of eyes, a pile of ash, and a sheet of plasma. Fire sharks leave behind a cloud of plasma upon death, and injects Phlogiston into the targets it bites." cost = 1 unlocked_transmutations = list(/datum/eldritch_transmutation/summon/fire_shark) + route = PATH_FLESH tier = TIER_1 /datum/eldritch_knowledge/flesh_mark @@ -138,14 +110,6 @@ gain_text = "She revels and laughs when life begins to flow. Her kiss rips and feasts on flesh alike. This imitates her touch." desc = "Your Mansus grasp now applies a mark on hit. Use your flesh blade to detonate the mark, which causes significant bleeding on the target." cost = 2 - banned_knowledge = list( - /datum/eldritch_knowledge/rust_mark, - /datum/eldritch_knowledge/ash_mark, - /datum/eldritch_knowledge/mind_mark, - /datum/eldritch_knowledge/void_mark, - /datum/eldritch_knowledge/blade_mark, - /datum/eldritch_knowledge/cosmic_mark, - /datum/eldritch_knowledge/knock_mark,) route = PATH_FLESH tier = TIER_MARK @@ -178,6 +142,7 @@ desc = "A touch spell that drains a target's health and restores yours." cost = 1 spell_to_add = /datum/action/cooldown/spell/pointed/blood_siphon + route = PATH_FLESH tier = TIER_2 /datum/eldritch_knowledge/flesh_blade_upgrade @@ -185,14 +150,6 @@ gain_text = "Ebis, the Owl, was the second to take the Red Oath. They still grant the gift of their steel to those powerful enough to resist their incursions." desc = "Your flesh blade will now cause additional bleeding on hit." cost = 2 - banned_knowledge = list( - /datum/eldritch_knowledge/ash_blade_upgrade, - /datum/eldritch_knowledge/rust_blade_upgrade, - /datum/eldritch_knowledge/mind_blade_upgrade, - /datum/eldritch_knowledge/void_blade_upgrade, - /datum/eldritch_knowledge/blade_blade_upgrade, - /datum/eldritch_knowledge/cosmic_blade_upgrade, - /datum/eldritch_knowledge/knock_blade_upgrade,) route = PATH_FLESH tier = TIER_BLADE @@ -219,6 +176,7 @@ desc = "You can now summon an Ashman by transmuting a pile of ash, a head, and a book. Ashmen have powerful offensive abilities and access to the Ashen Shift spell." cost = 1 unlocked_transmutations = list(/datum/eldritch_transmutation/summon/ashy) + route = PATH_FLESH tier = TIER_3 /datum/eldritch_knowledge/rusty @@ -227,6 +185,7 @@ desc = "You can now summon a Rustwalker transmuting a vomit pool and a book. Rustwalkers are capable of spreading rust and have a strong, short-ranged projectile attack." cost = 1 unlocked_transmutations = list(/datum/eldritch_transmutation/summon/rusty) + route = PATH_FLESH tier = TIER_3 /datum/eldritch_knowledge/flesh_final diff --git a/code/modules/antagonists/eldritch_cult/knowledge/knock_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/knock_lore.dm index f4c76e69f88e..80931c2c2307 100644 --- a/code/modules/antagonists/eldritch_cult/knowledge/knock_lore.dm +++ b/code/modules/antagonists/eldritch_cult/knowledge/knock_lore.dm @@ -3,35 +3,6 @@ desc = "Opens up the Path of Knock to you. \ Allows you to transmute a knife and a crowbar into a Key Blade. Additionally, your grasp will open up numerous locked things when used upon them." gain_text = "The Knock permits no seal and no isolation. It thrusts us gleefully out of the safety of ignorance." - banned_knowledge = list( - /datum/eldritch_knowledge/base_ash, - /datum/eldritch_knowledge/base_rust, - /datum/eldritch_knowledge/base_flesh, - /datum/eldritch_knowledge/base_mind, - /datum/eldritch_knowledge/base_void, - /datum/eldritch_knowledge/base_blade, - /datum/eldritch_knowledge/base_cosmic, - /datum/eldritch_knowledge/ash_mark, - /datum/eldritch_knowledge/rust_mark, - /datum/eldritch_knowledge/flesh_mark, - /datum/eldritch_knowledge/mind_mark, - /datum/eldritch_knowledge/void_mark, - /datum/eldritch_knowledge/blade_mark, - /datum/eldritch_knowledge/cosmic_mark, - /datum/eldritch_knowledge/ash_blade_upgrade, - /datum/eldritch_knowledge/rust_blade_upgrade, - /datum/eldritch_knowledge/flesh_blade_upgrade, - /datum/eldritch_knowledge/mind_blade_upgrade, - /datum/eldritch_knowledge/void_blade_upgrade, - /datum/eldritch_knowledge/blade_blade_upgrade, - /datum/eldritch_knowledge/cosmic_blade_upgrade, - /datum/eldritch_knowledge/ash_final, - /datum/eldritch_knowledge/rust_final, - /datum/eldritch_knowledge/flesh_final, - /datum/eldritch_knowledge/mind_final, - /datum/eldritch_knowledge/void_final, - /datum/eldritch_knowledge/blade_final, - /datum/eldritch_knowledge/cosmic_final) unlocked_transmutations = list(/datum/eldritch_transmutation/knock_knife) cost = 1 route = PATH_KNOCK @@ -98,14 +69,6 @@ Attack a marked person to bar them from all passages for the duration of the mark." gain_text = "Their requests for passage will remain unheeded." cost = 2 - banned_knowledge = list( - /datum/eldritch_knowledge/ash_mark, - /datum/eldritch_knowledge/rust_mark, - /datum/eldritch_knowledge/flesh_mark, - /datum/eldritch_knowledge/mind_mark, - /datum/eldritch_knowledge/void_mark, - /datum/eldritch_knowledge/blade_mark, - /datum/eldritch_knowledge/cosmic_mark) route = PATH_KNOCK tier = TIER_MARK @@ -137,14 +100,6 @@ name = "Blade Upgrade - Opening Blade" desc = "Your blade will be able to pry open unlocked airlocks." gain_text = "The power of my patron courses through my blade, willing their very flesh to part." - banned_knowledge = list( - /datum/eldritch_knowledge/ash_blade_upgrade, - /datum/eldritch_knowledge/rust_blade_upgrade, - /datum/eldritch_knowledge/flesh_blade_upgrade, - /datum/eldritch_knowledge/mind_blade_upgrade, - /datum/eldritch_knowledge/void_blade_upgrade, - /datum/eldritch_knowledge/blade_blade_upgrade, - /datum/eldritch_knowledge/cosmic_blade_upgrade,) route = PATH_KNOCK tier = TIER_BLADE diff --git a/code/modules/antagonists/eldritch_cult/knowledge/mind_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/mind_lore.dm index c887de51ee2d..a39b68b38f7c 100644 --- a/code/modules/antagonists/eldritch_cult/knowledge/mind_lore.dm +++ b/code/modules/antagonists/eldritch_cult/knowledge/mind_lore.dm @@ -2,35 +2,6 @@ name = "Precipice Of Enlightenment" desc = "Pledge yourself to knowledge everlasting. Allows you to transmute a knife and a book into a blade of pure thought. Additionally, Your mansus grasp now functions at a range, knocking them down and blurring their vision." gain_text = "The corpse of an ancient God defiled, your fellow scholars enlightened by false knowledge, but you seek true insight. You seek the unknown, the invisible, the truth behind the veil." - banned_knowledge = list( - /datum/eldritch_knowledge/base_ash, - /datum/eldritch_knowledge/base_rust, - /datum/eldritch_knowledge/base_flesh, - /datum/eldritch_knowledge/base_void, - /datum/eldritch_knowledge/base_blade, - /datum/eldritch_knowledge/base_cosmic, - /datum/eldritch_knowledge/base_knock, - /datum/eldritch_knowledge/ash_mark, - /datum/eldritch_knowledge/rust_mark, - /datum/eldritch_knowledge/flesh_mark, - /datum/eldritch_knowledge/void_mark, - /datum/eldritch_knowledge/blade_mark, - /datum/eldritch_knowledge/cosmic_mark, - /datum/eldritch_knowledge/knock_mark, - /datum/eldritch_knowledge/ash_blade_upgrade, - /datum/eldritch_knowledge/rust_blade_upgrade, - /datum/eldritch_knowledge/flesh_blade_upgrade, - /datum/eldritch_knowledge/void_blade_upgrade, - /datum/eldritch_knowledge/blade_blade_upgrade, - /datum/eldritch_knowledge/cosmic_blade_upgrade, - /datum/eldritch_knowledge/knock_blade_upgrade, - /datum/eldritch_knowledge/ash_final, - /datum/eldritch_knowledge/rust_final, - /datum/eldritch_knowledge/flesh_final, - /datum/eldritch_knowledge/void_final, - /datum/eldritch_knowledge/blade_final, - /datum/eldritch_knowledge/cosmic_final, - /datum/eldritch_knowledge/knock_final) unlocked_transmutations = list(/datum/eldritch_transmutation/mind_knife) cost = 1 route = PATH_MIND @@ -63,17 +34,6 @@ human_target.blur_eyes(1 SECONDS) human_target.Knockdown(2 SECONDS) -// /datum/eldritch_knowledge/spell/mental_obfuscation -// name = "T1 - Mental Obfuscation" -// gain_text = "A mind is such an easy thing to trick, nothing more than a lump of meat ready to be moulded by your hands." -// desc = "Allows you to teleport a short distance to a targeted destination." -// cost = 1 -// spell_to_add = /datum/action/cooldown/spell/pointed/phase_jump/obfuscation -// banned_knowledge = list( -// /datum/eldritch_knowledge/spell/void_phase) -// route = PATH_MIND -// tier = TIER_1 - /datum/eldritch_knowledge/spell/eldritchbolt name = "T1 - Eldritch Bolt" gain_text = "Remain wary of the frailty of men. Their wills are weak, minds young. Were it not for fear, death would go unlamented. Seek the old blood. Let us pray, let us wish... to partake in communion." @@ -89,6 +49,7 @@ desc = "Allows you to craft an eldritch eye by transmuting a flashlight and a pair of eyes. Grants the user a hud type of their choosing, additionally also grants night vision but it cannot be removed." unlocked_transmutations = list(/datum/eldritch_transmutation/eldritch_eye) cost = 1 + route = PATH_MIND tier = TIER_1 /datum/eldritch_knowledge/mind_mark @@ -96,14 +57,6 @@ gain_text = "They say the eyes are the gateway to the soul, a way to tell one's true intentions. Show them a single sliver of the truth of this world and their eyes will reject all." desc = "Upgrade your mansus grasp, granting it the ability to blind a target on hit, as well as increasing the range" cost = 2 - banned_knowledge = list( - /datum/eldritch_knowledge/rust_mark, - /datum/eldritch_knowledge/flesh_mark, - /datum/eldritch_knowledge/ash_mark, - /datum/eldritch_knowledge/void_mark, - /datum/eldritch_knowledge/blade_mark, - /datum/eldritch_knowledge/cosmic_mark, - /datum/eldritch_knowledge/knock_mark,) route = PATH_MIND tier = TIER_MARK @@ -141,6 +94,7 @@ desc = "An AOE roar spell that freezes all nearby people with sheer terror." cost = 1 spell_to_add = /datum/action/cooldown/spell/aoe/immobilize/famished_roar + route = PATH_MIND tier = TIER_3 /datum/eldritch_knowledge/mind_blade_upgrade @@ -148,14 +102,6 @@ gain_text = "Curse here, Curse there. Curse for he and she, why care? A bottomless curse, a bottomless sea, source of all greatness, all things that be." desc = "Your mind blade will now inject targets hit with mutetoxin, silencing them." cost = 2 - banned_knowledge = list( - /datum/eldritch_knowledge/rust_blade_upgrade, - /datum/eldritch_knowledge/flesh_blade_upgrade, - /datum/eldritch_knowledge/ash_blade_upgrade, - /datum/eldritch_knowledge/void_blade_upgrade, - /datum/eldritch_knowledge/blade_blade_upgrade, - /datum/eldritch_knowledge/cosmic_blade_upgrade, - /datum/eldritch_knowledge/knock_blade_upgrade,) route = PATH_MIND tier = TIER_BLADE diff --git a/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm index 02c02108911d..3a24e212310c 100644 --- a/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm +++ b/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm @@ -2,35 +2,6 @@ name = "Blacksmith's Tale" desc = "Pledges yourself to the path of Rust. Allows you to transmute a piece of trash with a knife into a rusty blade. Additionally, your Mansus grasp now deals 500 damage to inorganic matter, rusts any surface it's used on, while destroying any surface that is already rusty." gain_text = "Outside the Ruined Keep, you drank of the River Krym. Its poison seeped through your body as years shriveled away. Yet, you were spared. Now, your purpose is clear." - banned_knowledge = list( - /datum/eldritch_knowledge/base_ash, - /datum/eldritch_knowledge/base_flesh, - /datum/eldritch_knowledge/base_mind, - /datum/eldritch_knowledge/base_void, - /datum/eldritch_knowledge/base_blade, - /datum/eldritch_knowledge/base_cosmic, - /datum/eldritch_knowledge/base_knock, - /datum/eldritch_knowledge/ash_mark, - /datum/eldritch_knowledge/flesh_mark, - /datum/eldritch_knowledge/mind_mark, - /datum/eldritch_knowledge/void_mark, - /datum/eldritch_knowledge/blade_mark, - /datum/eldritch_knowledge/cosmic_mark, - /datum/eldritch_knowledge/knock_mark, - /datum/eldritch_knowledge/ash_blade_upgrade, - /datum/eldritch_knowledge/flesh_blade_upgrade, - /datum/eldritch_knowledge/mind_blade_upgrade, - /datum/eldritch_knowledge/void_blade_upgrade, - /datum/eldritch_knowledge/blade_blade_upgrade, - /datum/eldritch_knowledge/cosmic_blade_upgrade, - /datum/eldritch_knowledge/knock_blade_upgrade, - /datum/eldritch_knowledge/ash_final, - /datum/eldritch_knowledge/flesh_final, - /datum/eldritch_knowledge/mind_final, - /datum/eldritch_knowledge/void_final, - /datum/eldritch_knowledge/blade_final, - /datum/eldritch_knowledge/cosmic_final, - /datum/eldritch_knowledge/knock_final) cost = 1 unlocked_transmutations = list(/datum/eldritch_transmutation/rust_blade) route = PATH_RUST @@ -89,6 +60,7 @@ desc = "An instant spell that will create a wall at your command, only works on rusted tiles. Will knock back and damage anyone caught on the same tile." cost = 1 spell_to_add = /datum/action/cooldown/spell/pointed/rust_construction + route = PATH_RUST tier = TIER_1 /datum/eldritch_knowledge/rust_regen/on_life(mob/user) @@ -111,6 +83,7 @@ desc = "Allows you to craft a set of eldritch armor by transmuting a table and a gas mask. The robes significantly reduce most incoming damage. Also allows you to further upgrade said robes by transmuting a diamond with it." cost = 1 unlocked_transmutations = list(/datum/eldritch_transmutation/armor, /datum/eldritch_transmutation/armor/upgrade) + route = PATH_RUST tier = TIER_1 /datum/eldritch_knowledge/essence @@ -119,6 +92,7 @@ desc = "Allows you to craft a flask of eldritch essence by transmuting a water tank. The reagent will heal you and damage those not linked to the Mansus." cost = 1 unlocked_transmutations = list(/datum/eldritch_transmutation/water) + route = PATH_RUST tier = TIER_1 /datum/eldritch_knowledge/rust_mark @@ -126,14 +100,6 @@ gain_text = "Ire and envy are universally observable. Where the Drifter went, he saw those who rejoiced with more and those who suffered with less. Only hatred grew in his heart." desc = "Your Mansus grasp now applies a mark on hit. Use your rusty blade to detonate the mark, which has a chance to deal between 0 to 200 damage to 75% of your target's items." cost = 2 - banned_knowledge = list( - /datum/eldritch_knowledge/ash_mark, - /datum/eldritch_knowledge/flesh_mark, - /datum/eldritch_knowledge/mind_mark, - /datum/eldritch_knowledge/void_mark, - /datum/eldritch_knowledge/blade_mark, - /datum/eldritch_knowledge/cosmic_mark, - /datum/eldritch_knowledge/knock_mark,) route = PATH_RUST tier = TIER_MARK @@ -165,14 +131,6 @@ gain_text = "By the time her subjects began to rebel, she had given the Blacksmith enough bodies to sate the blades. His own drooled with an intoxicating nectar, which sealed his fate." desc = "Your rusted blade now injects eldritch essence on hit." cost = 2 - banned_knowledge = list( - /datum/eldritch_knowledge/ash_blade_upgrade, - /datum/eldritch_knowledge/flesh_blade_upgrade, - /datum/eldritch_knowledge/mind_blade_upgrade, - /datum/eldritch_knowledge/void_blade_upgrade, - /datum/eldritch_knowledge/blade_blade_upgrade, - /datum/eldritch_knowledge/cosmic_blade_upgrade, - /datum/eldritch_knowledge/knock_blade_upgrade,) route = PATH_RUST tier = TIER_BLADE diff --git a/code/modules/antagonists/eldritch_cult/knowledge/void_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/void_lore.dm index e5a6507d75f0..ed0b854b7544 100644 --- a/code/modules/antagonists/eldritch_cult/knowledge/void_lore.dm +++ b/code/modules/antagonists/eldritch_cult/knowledge/void_lore.dm @@ -2,35 +2,6 @@ name = "Glimmer of Winter" desc = "Pledges yourself to the path of the Void. Allows you to transmute a stuff with a knife or its derivatives into a void blade. Additionally, empowers your Mansus grasp to chill any target hit." gain_text = "Wanting, I lie, too weary to die, too lost to the ice for saving. My sins claim me, untame me" - banned_knowledge = list( - /datum/eldritch_knowledge/base_ash, - /datum/eldritch_knowledge/base_rust, - /datum/eldritch_knowledge/base_flesh, - /datum/eldritch_knowledge/base_mind, - /datum/eldritch_knowledge/base_blade, - /datum/eldritch_knowledge/base_cosmic, - /datum/eldritch_knowledge/base_knock, - /datum/eldritch_knowledge/ash_mark, - /datum/eldritch_knowledge/rust_mark, - /datum/eldritch_knowledge/flesh_mark, - /datum/eldritch_knowledge/mind_mark, - /datum/eldritch_knowledge/blade_mark, - /datum/eldritch_knowledge/cosmic_mark, - /datum/eldritch_knowledge/knock_mark, - /datum/eldritch_knowledge/ash_blade_upgrade, - /datum/eldritch_knowledge/rust_blade_upgrade, - /datum/eldritch_knowledge/flesh_blade_upgrade, - /datum/eldritch_knowledge/mind_blade_upgrade, - /datum/eldritch_knowledge/blade_blade_upgrade, - /datum/eldritch_knowledge/cosmic_blade_upgrade, - /datum/eldritch_knowledge/knock_blade_upgrade, - /datum/eldritch_knowledge/ash_final, - /datum/eldritch_knowledge/rust_final, - /datum/eldritch_knowledge/flesh_final, - /datum/eldritch_knowledge/mind_final, - /datum/eldritch_knowledge/blade_final, - /datum/eldritch_knowledge/cosmic_final, - /datum/eldritch_knowledge/knock_final) unlocked_transmutations = list(/datum/eldritch_transmutation/void_knife) cost = 1 route = PATH_VOID @@ -85,19 +56,6 @@ route = PATH_VOID tier = TIER_1 -// /datum/eldritch_knowledge/spell/void_phase -// name = "T1 - Void Phase" -// gain_text = "The entity calls themself the Aristocrat. They effortlessly walk through air like -// nothing - leaving a harsh, cold breeze in their wake. They disappear, and I am left in the blizzard." -// desc = "Grants you Void Phase, a long range targeted teleport spell. -// Additionally causes damage to heathens around your original and target destination." -// cost = 1 -// spell_to_add = /datum/action/cooldown/spell/pointed/void_phase -// banned_knowledge = list( -// /datum/eldritch_knowledge/spell/mental_obfuscation) -// route = PATH_VOID -// tier = TIER_1 - /datum/eldritch_knowledge/void_cloak name = "T1 - Void Cloak" gain_text = "The Owl is the keeper of things that are not quite in practice, but in theory are. Many things are." @@ -105,6 +63,7 @@ to create a Void Cloak. This cloak will make the wearer partially invisible over time, and allow them to temporarily dodge attacks." unlocked_transmutations = list(/datum/eldritch_transmutation/void_cloak) cost = 1 + route = PATH_VOID tier = TIER_1 /datum/eldritch_knowledge/void_mark @@ -114,14 +73,6 @@ desc = "Your Mansus Grasp now applies the Mark of Void. The mark is triggered from an attack with your Void Blade. \ When triggered, further silences the victim and swiftly lowers the temperature of their body and the air around them." cost = 2 - banned_knowledge = list( - /datum/eldritch_knowledge/ash_mark, - /datum/eldritch_knowledge/rust_mark, - /datum/eldritch_knowledge/flesh_mark, - /datum/eldritch_knowledge/mind_mark, - /datum/eldritch_knowledge/blade_mark, - /datum/eldritch_knowledge/cosmic_mark, - /datum/eldritch_knowledge/knock_mark,) route = PATH_VOID tier = TIER_MARK @@ -165,6 +116,7 @@ freezing the ground and any victims within." cost = 1 spell_to_add = /datum/action/cooldown/spell/cone/staggered/cone_of_cold/void + route = PATH_VOID tier = TIER_2 /datum/eldritch_knowledge/void_blade_upgrade @@ -172,14 +124,6 @@ gain_text = "Fleeting memories, fleeting feet. I mark my way with frozen blood upon the snow. Covered and forgotten, wandering I lie, too weary to die." desc = "Your blade will now inject a freezing venom into your targets." cost = 2 - banned_knowledge = list( - /datum/eldritch_knowledge/ash_blade_upgrade, - /datum/eldritch_knowledge/rust_blade_upgrade, - /datum/eldritch_knowledge/flesh_blade_upgrade, - /datum/eldritch_knowledge/mind_blade_upgrade, - /datum/eldritch_knowledge/blade_blade_upgrade, - /datum/eldritch_knowledge/cosmic_blade_upgrade, - /datum/eldritch_knowledge/knock_blade_upgrade) route = PATH_VOID tier = TIER_BLADE @@ -210,11 +154,11 @@ desc = "A powerful spell that calls forth memories of ice, will create a large area of ice around you." cost = 1 spell_to_add = /datum/action/cooldown/spell/aoe/slip/void + route = PATH_VOID tier = TIER_3 /datum/eldritch_knowledge/lionhunter_rifle name = "T3 - Lionhunter Rifle" - name = "Lionhunter's Rifle" desc = "Allows you to transmute any ballistic weapon, with \ a plank of wood, a piece of gold and a camera to create the Lionhunter's rifle. \ The Lionhunter's Rifle is a long ranged ballistic weapon with three shots. \ @@ -226,6 +170,7 @@ I could not purchase it at the time, but they showed me how they made it ages ago." unlocked_transmutations = list(/datum/eldritch_transmutation/lionhunter, /datum/eldritch_transmutation/lionhunter_ammo) cost = 1 + route = PATH_VOID tier = TIER_3 /datum/eldritch_knowledge/void_final diff --git a/code/modules/antagonists/eldritch_cult/magic/general_heretic_magic.dm b/code/modules/antagonists/eldritch_cult/magic/general_heretic_magic.dm index 7af0106e0ac7..ab839dd64ed3 100644 --- a/code/modules/antagonists/eldritch_cult/magic/general_heretic_magic.dm +++ b/code/modules/antagonists/eldritch_cult/magic/general_heretic_magic.dm @@ -156,8 +156,7 @@ THIS FILE IS FOR ALL HERETIC SPELLS THAT DO NOT CONFER TO A PATH'S THEME OR YOU invocation_type = INVOCATION_WHISPER spell_requirements = SPELL_CASTABLE_WITHOUT_INVOCATION | SPELL_REQUIRES_NO_ANTIMAGIC - emp_heavy = 6 - emp_light = 10 + radius = 10 /datum/action/cooldown/spell/list_target/telepathy/eldritch name = "Eldritch Telepathy" diff --git a/code/modules/antagonists/eldritch_cult/transmutations/ash_transmutations.dm b/code/modules/antagonists/eldritch_cult/transmutations/ash_transmutations.dm index ee4b5cd647d2..111e7052270b 100644 --- a/code/modules/antagonists/eldritch_cult/transmutations/ash_transmutations.dm +++ b/code/modules/antagonists/eldritch_cult/transmutations/ash_transmutations.dm @@ -99,5 +99,3 @@ env = T.return_air() current_temp = env.return_temperature() env.set_temperature(current_temp+25) - T.air_update_turf() - L.air_update_turf() diff --git a/code/modules/antagonists/horror/horror.dm b/code/modules/antagonists/horror/horror.dm index 8e9e8cdcc4f6..03ca12a00b9c 100644 --- a/code/modules/antagonists/horror/horror.dm +++ b/code/modules/antagonists/horror/horror.dm @@ -73,6 +73,7 @@ add_ability(/datum/action/innate/horror/take_control) add_ability(/datum/action/innate/horror/leave_body) add_ability(/datum/action/innate/horror/make_chems) + add_ability(/datum/action/innate/horror/scan_host) add_ability(/datum/action/innate/horror/give_back_control) RefreshAbilities() @@ -433,6 +434,15 @@ usr << browse(html, "window=ViewHorror\ref[src]Chems;size=600x800") +/mob/living/simple_animal/horror/proc/scan_host() + if(!can_use_ability()) + return + if(!victim) + to_chat(src, span_warning("You are not inside a host body.")) + return + healthscan(usr, victim) + chemscan(usr, victim) + /mob/living/simple_animal/horror/proc/hide() if(victim) to_chat(src, span_warning("You cannot do this while you're inside a host.")) diff --git a/code/modules/antagonists/horror/horror_abilities_and_upgrades.dm b/code/modules/antagonists/horror/horror_abilities_and_upgrades.dm index 090af213248b..8213353bc619 100644 --- a/code/modules/antagonists/horror/horror_abilities_and_upgrades.dm +++ b/code/modules/antagonists/horror/horror_abilities_and_upgrades.dm @@ -137,6 +137,17 @@ /datum/action/innate/horror/make_chems/Activate() B.secrete_chemicals() +/datum/action/innate/horror/scan_host + name = "Host Scan" + desc = "Analyze your host's body and chemical content." + button_icon = 'icons/obj/device.dmi' + button_icon_state = "health" + blacklisted = TRUE + category = list("infest") + +/datum/action/innate/horror/scan_host/Activate() + B.scan_host() + /datum/action/innate/horror/freeze_victim name = "Knockdown victim" desc = "Use your tentacle to trip a victim, stunning for a short duration." diff --git a/code/modules/antagonists/horror/horror_chemicals.dm b/code/modules/antagonists/horror/horror_chemicals.dm index 50cfdafb7f60..704ca1b9dc15 100644 --- a/code/modules/antagonists/horror/horror_chemicals.dm +++ b/code/modules/antagonists/horror/horror_chemicals.dm @@ -26,7 +26,7 @@ to_chat(src, span_boldnotice("You need [C.chemuse] chemicals stored to use this chemical!")) return - to_chat(src, span_danger("You squirt a measure of [C.chemname] from your reservoirs into [victim]'s bloodstream.")) + to_chat(src, span_danger("You squirt [C.quantity] units of [C.chemname] from your reservoirs into [victim]'s bloodstream.")) victim.reagents.add_reagent(C.R, C.quantity) chemicals -= C.chemuse log_game("[src]/([src.ckey]) has injected [C.chemname] into their host [victim]/([victim.ckey])") @@ -51,7 +51,6 @@ chemname = "mannitol" R = /datum/reagent/medicine/mannitol chem_desc = "Heals brain damage." - /datum/horror_chem/bicaridine chemname = "bicaridine" R = /datum/reagent/medicine/bicaridine diff --git a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm index d4c6bdef3518..6157aa467e5b 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm @@ -1,6 +1,6 @@ /obj/machinery/nuclearbomb name = "nuclear fission explosive" - desc = "A stolen NanoTrasen branded nuclear bomb. You probably shouldn't stick around to see if this is armed." + desc = "A stolen Nanotrasen branded nuclear bomb. You probably shouldn't stick around to see if this is armed." icon = 'icons/obj/machines/nuke.dmi' icon_state = "nuclearbomb_base" base_icon_state = "nuclearbomb" diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 0155656d5a86..877b97da4936 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -17,6 +17,7 @@ var/traitor_kind = TRAITOR_HUMAN //Set on initial assignment var/malf = FALSE //whether or not the AI is malf (in case it's a traitor) var/datum/contractor_hub/contractor_hub + var/obj/item/uplink_holder can_hijack = HIJACK_HIJACKER /datum/antagonist/traitor/on_gain() diff --git a/code/modules/atmospherics/auxgm/breathing_classes.dm b/code/modules/atmospherics/auxgm/breathing_classes.dm new file mode 100644 index 000000000000..862f2b5b8aa3 --- /dev/null +++ b/code/modules/atmospherics/auxgm/breathing_classes.dm @@ -0,0 +1,82 @@ +// Breathing classes are, yes, just a list of gases, associated with numbers. +// But they're very simple: pluoxium's status as O2 * 8 is represented here, +// with a single line of code, no hardcoding and special-casing across the codebase. +// Not only that, but they're very general: you could have a negative value +// to simulate asphyxiants, e.g. if I add krypton it could go into the oxygen +// breathing class at -7, simulating krypton narcosis. + +/datum/breathing_class + ///Gases that we consume and count as respirable + var/list/gases + ///Gases that we breathe out + var/list/products + ///Reagent generated if we breathe in too much of the gases in the gas_max value of gases defined in lungs + var/danger_reagent + ///Catergory of the alert generated if we do not have enough required gases + var/low_alert_category = "not_enough_oxy" + ///Type of the alert generated if we do not have enough required gases + var/low_alert_datum = /atom/movable/screen/alert/not_enough_oxy + ///Catergory of the alert generated if we breathe in too much of the gases in the gas_max value of gases defined in lungs + var/high_alert_category = "too_much_oxy" + ///Type of the alert generated if we breathe in too much of the gases in the gas_max value of gases defined in lungs + var/high_alert_datum = /atom/movable/screen/alert/too_much_oxy + +/datum/breathing_class/proc/get_effective_pp(datum/gas_mixture/breath) + var/mol = 0 + for(var/gas in gases) + mol += breath.get_moles(gas) * gases[gas] + return (mol/breath.total_moles()) * breath.return_pressure() + +/datum/breathing_class/oxygen + gases = list( + GAS_O2 = 1, + GAS_PLUOXIUM = 8, + GAS_CO2 = -0.7, // CO2 isn't actually toxic, just an asphyxiant + ) + products = list( + GAS_CO2 = 1, + ) + +/datum/breathing_class/oxygen_plas + gases = list( + GAS_O2 = 1, + GAS_PLUOXIUM = 8, + GAS_CO2 = -0.7, // CO2 isn't actually toxic, just an asphyxiant + GAS_PLASMA = 1 + ) + products = list( + GAS_CO2 = 1, + ) + +/datum/breathing_class/oxygen_co2 + gases = list( + GAS_O2 = 1, + GAS_PLUOXIUM = 8, + GAS_CO2 = 1, + ) + products = list( + GAS_CO2 = 1, + ) + +/datum/breathing_class/plasma + gases = list( + GAS_PLASMA = 1 + ) + products = list( + GAS_CO2 = 1 + ) + low_alert_category = "not_enough_tox" + low_alert_datum = /atom/movable/screen/alert/not_enough_tox + high_alert_category = "too_much_tox" + high_alert_datum = /atom/movable/screen/alert/too_much_tox + +/datum/breathing_class/oxygen_vapor + gases = list( + GAS_O2 = 1, + GAS_PLUOXIUM = 8, + GAS_CO2 = -0.7, // CO2 isn't actually toxic, just an asphyxiant + GAS_H2O = 1, + ) + products = list( + GAS_CO2 = 1, + ) diff --git a/code/modules/atmospherics/auxgm/gas_types.dm b/code/modules/atmospherics/auxgm/gas_types.dm new file mode 100644 index 000000000000..04ff522f1cd5 --- /dev/null +++ b/code/modules/atmospherics/auxgm/gas_types.dm @@ -0,0 +1,203 @@ +/datum/gas/oxygen + id = GAS_O2 + specific_heat = 20 + name = "Oxygen" + label = "O₂" + ui_color = "blue" + +/datum/gas/nitrogen + id = GAS_N2 + specific_heat = 20 + name = "Nitrogen" + label = "N₂" + breath_alert_info = list( + not_enough_alert = list( + alert_category = "not_enough_nitro", + alert_type = /atom/movable/screen/alert/not_enough_nitro, + ), + too_much_alert = list( + alert_category = "too_much_nitro", + alert_type = /atom/movable/screen/alert/too_much_nitro, + ) + ) + ui_color = "red" + +/datum/gas/carbon_dioxide //what the fuck is this? + id = GAS_CO2 + specific_heat = 30 + name = "Carbon Dioxide" + label = "CO₂" + breath_results = GAS_O2 + breath_alert_info = list( + not_enough_alert = list( + alert_category = "not_enough_co2", + alert_type = /atom/movable/screen/alert/not_enough_co2, + ), + too_much_alert = list( + alert_category = "too_much_co2", + alert_type = /atom/movable/screen/alert/too_much_co2, + ) + ) + ui_color = "grey" + +/datum/gas/plasma + id = GAS_PLASMA + specific_heat = 200 + name = "Plasma" + gas_overlay = "plasma" + moles_visible = MOLES_GAS_VISIBLE + flags = GAS_FLAG_DANGEROUS + ui_color = "orange" + +/datum/gas/water_vapor + id = GAS_H2O + specific_heat = 40 + name = "Water Vapor" + label = "H₂O" + gas_overlay = "water_vapor" + moles_visible = MOLES_GAS_VISIBLE + breath_reagent = /datum/reagent/water + fusion_power = 8 + ui_color = "lightsteelblue" + +/datum/gas/hypernoblium + id = GAS_HYPERNOB + specific_heat = 2000 + name = "Hyper-noblium" + label = "Hyper-nob" + gas_overlay = "freon" + moles_visible = MOLES_GAS_VISIBLE + flags = GAS_FLAG_DANGEROUS + ui_color = "teal" + +/datum/gas/nitrous_oxide + id = GAS_NITROUS + specific_heat = 40 + name = "Nitrous Oxide" + label = "N₂O" + gas_overlay = "nitrous_oxide" + moles_visible = MOLES_GAS_VISIBLE * 2 + fusion_power = 10 + flags = GAS_FLAG_DANGEROUS + ui_color = "bisque" + +/datum/gas/nitrium + id = GAS_NITRIUM + specific_heat = 10 + name = "Nitrium" + gas_overlay = "nitrium" + moles_visible = MOLES_GAS_VISIBLE + flags = GAS_FLAG_DANGEROUS + fusion_power = 7 + ui_color = "brown" + +/datum/gas/tritium + id = GAS_TRITIUM + specific_heat = 10 + name = "Tritium" + gas_overlay = "tritium" + moles_visible = MOLES_GAS_VISIBLE + flags = GAS_FLAG_DANGEROUS + fusion_power = 1 + ui_color = "limegreen" + +/datum/gas/bz + id = GAS_BZ + specific_heat = 20 + name = "BZ" + flags = GAS_FLAG_DANGEROUS + fusion_power = 8 + ui_color = "mediumpurple" + +/datum/gas/pluoxium + id = GAS_PLUOXIUM + specific_heat = 80 + name = "Pluoxium" + fusion_power = -10 + ui_color = "mediumslateblue" + +/datum/gas/miasma + id = GAS_MIASMA + specific_heat = 20 + name = "Miasma" + gas_overlay = "miasma" + moles_visible = MOLES_GAS_VISIBLE * 60 + ui_color = "olive" + +/datum/gas/freon + id = GAS_FREON + specific_heat = 600 + name = "Freon" + gas_overlay = "freon" + moles_visible = MOLES_GAS_VISIBLE *30 + fusion_power = -5 + ui_color = "paleturquoise" + +/datum/gas/hydrogen + id = GAS_H2 + specific_heat = 15 + name = "Hydrogen" + label = "H₂" + flags = GAS_FLAG_DANGEROUS + ui_color = "white" + +/datum/gas/healium + id = GAS_HEALIUM + specific_heat = 10 + name = "Healium" + gas_overlay = "healium" + moles_visible = MOLES_GAS_VISIBLE + ui_color = "salmon" + +/datum/gas/pluonium + id = GAS_PLUONIUM + specific_heat = 30 + name = "Pluonium" + flags = GAS_FLAG_DANGEROUS + gas_overlay = "pluonium" + moles_visible = MOLES_GAS_VISIBLE + ui_color = "greenyellow" + +/datum/gas/halon + id = GAS_HALON + specific_heat = 175 + name = "Halon" + flags = GAS_FLAG_DANGEROUS + gas_overlay = "halon" + moles_visible = MOLES_GAS_VISIBLE + ui_color = "purple" + +/datum/gas/antinoblium + id = GAS_ANTINOB + specific_heat = 1 + name = "Antinoblium" + label = "Anti-nob" + gas_overlay = "antinoblium" + moles_visible = MOLES_GAS_VISIBLE + fusion_power = 20 + ui_color = "maroon" + +/datum/gas/zauker + id = GAS_ZAUKER + specific_heat = 350 + name = "Zauker" + flags = GAS_FLAG_DANGEROUS + gas_overlay = "zauker" + moles_visible = MOLES_GAS_VISIBLE + ui_color = "darkgreen" + +/datum/gas/hexane + id = GAS_HEXANE + specific_heat = 5 + name = "Hexane" + flags = GAS_FLAG_DANGEROUS + gas_overlay = "hexane" + moles_visible = MOLES_GAS_VISIBLE + ui_color = "plum" + +/datum/gas/dilithium // Main point is that this helps fusion occur at a significantly lower temperature than normal + id = GAS_DILITHIUM + specific_heat = 55 + name = "Dilithium" + fusion_power = 1 + ui_color = "pink" diff --git a/code/modules/atmospherics/environmental/LINDA_fire.dm b/code/modules/atmospherics/environmental/LINDA_fire.dm index a211e76706d2..635a5d5b1dae 100644 --- a/code/modules/atmospherics/environmental/LINDA_fire.dm +++ b/code/modules/atmospherics/environmental/LINDA_fire.dm @@ -17,33 +17,23 @@ if(!air) return - if(air.get_moles(/datum/gas/hypernoblium) > REACTION_OPPRESSION_THRESHOLD) + if (air.get_moles(GAS_O2) < 0.5 || air.get_moles(GAS_HYPERNOB) > REACTION_OPPRESSION_THRESHOLD) return - var/oxy = air.get_moles(/datum/gas/oxygen) - if (oxy < 0.5) - return - var/tox = air.get_moles(/datum/gas/plasma) - var/trit = air.get_moles(/datum/gas/tritium) - var/h2 = air.get_moles(/datum/gas/hydrogen) + var/has_fuel = air.get_moles(GAS_PLASMA) > 0.5 || air.get_moles(GAS_TRITIUM) > 0.5 || air.get_moles(GAS_H2) > 0.5 if(active_hotspot) if(soh) - if(tox > 0.5 || trit > 0.5 || h2 > 0.5) + if(has_fuel) if(active_hotspot.temperature < exposed_temperature) active_hotspot.temperature = exposed_temperature if(active_hotspot.volume < exposed_volume) active_hotspot.volume = exposed_volume return - if((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && (tox > 0.5 || trit > 0.5 || h2 > 0.5)) - + if((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && has_fuel) active_hotspot = new /obj/effect/hotspot(src, exposed_volume*25, exposed_temperature) - active_hotspot.just_spawned = (current_cycle < SSair.times_fired) - //remove just_spawned protection if no longer processing this cell - SSair.add_to_active(src, 0) - //This is the icon for fire on turfs, also helps for nurturing small fires until they are full tile /obj/effect/hotspot anchored = TRUE @@ -73,7 +63,6 @@ if(!perform_exposure()) return INITIALIZE_HINT_QDEL setDir(pick(GLOB.cardinals)) - air_update_turf() /obj/effect/hotspot/proc/perform_exposure() var/turf/open/location = loc @@ -163,7 +152,7 @@ color = list(LERP(0.3, 1, 1-greyscale_fire) * heat_r,0.3 * heat_g * greyscale_fire,0.3 * heat_b * greyscale_fire, 0.59 * heat_r * greyscale_fire,LERP(0.59, 1, 1-greyscale_fire) * heat_g,0.59 * heat_b * greyscale_fire, 0.11 * heat_r * greyscale_fire,0.11 * heat_g * greyscale_fire,LERP(0.11, 1, 1-greyscale_fire) * heat_b, 0,0,0) alpha = heat_a -#define INSUFFICIENT(path) (location.air.get_moles(path) < 0.5) +#define INSUFFICIENT(id) (location.air.get_moles(id) < 0.5) /obj/effect/hotspot/process() if(just_spawned) just_spawned = FALSE @@ -181,7 +170,7 @@ return //Not enough / nothing to burn - if(!location.air || (INSUFFICIENT(/datum/gas/plasma) && INSUFFICIENT(/datum/gas/tritium)) && INSUFFICIENT(/datum/gas/hydrogen) || INSUFFICIENT(/datum/gas/oxygen)) + if(!location.air || (INSUFFICIENT(GAS_PLASMA) && INSUFFICIENT(GAS_TRITIUM)) && INSUFFICIENT(GAS_H2) || INSUFFICIENT(GAS_O2)) qdel(src) return diff --git a/code/modules/atmospherics/environmental/LINDA_system.dm b/code/modules/atmospherics/environmental/LINDA_system.dm index 21dc6069a6c2..fc3d4ffa183b 100644 --- a/code/modules/atmospherics/environmental/LINDA_system.dm +++ b/code/modules/atmospherics/environmental/LINDA_system.dm @@ -18,58 +18,112 @@ /turf/open/CanAtmosPass(turf/T, vertical = FALSE) var/dir = vertical? get_dir_multiz(src, T) : get_dir(src, T) - var/opp = dir_inverse_multiz(dir) - var/R = FALSE + . = TRUE if(vertical && !(zAirOut(dir, T) && T.zAirIn(dir, src))) - R = TRUE + . = FALSE if(blocks_air || T.blocks_air) - R = TRUE + . = FALSE if (T == src) - return !R + return . for(var/obj/O in contents+T.contents) var/turf/other = (O.loc == src ? T : src) if(!(vertical? (CANVERTICALATMOSPASS(O, other)) : (CANATMOSPASS(O, other)))) - R = TRUE - if(O.BlockSuperconductivity()) //the direction and open/closed are already checked on CanAtmosPass() so there are no arguments - atmos_supeconductivity |= dir - T.atmos_supeconductivity |= opp - return FALSE //no need to keep going, we got all we asked + . = FALSE - atmos_supeconductivity &= ~dir - T.atmos_supeconductivity &= ~opp +/turf/proc/update_conductivity(turf/T) + var/dir = get_dir_multiz(src, T) + var/opp = REVERSE_DIR(dir) - return !R + if(T == src) + return + + //all these must be above zero for auxmos to even consider them + if(!thermal_conductivity || !heat_capacity || !T.thermal_conductivity || !T.heat_capacity) + conductivity_blocked_directions |= dir + T.conductivity_blocked_directions |= opp + return + + for(var/obj/O in contents+T.contents) + if(O.BlockThermalConductivity(opp)) //the direction and open/closed are already checked on CanAtmosPass() so there are no arguments + conductivity_blocked_directions |= dir + T.conductivity_blocked_directions |= opp + +/turf/proc/block_all_conductivity() + conductivity_blocked_directions |= NORTH | SOUTH | EAST | WEST | UP | DOWN -/atom/movable/proc/BlockSuperconductivity() // objects that block air and don't let superconductivity act. Only firelocks atm. +//dir of this obj to the other turf +/atom/movable/proc/BlockThermalConductivity(dir) // Objects that don't let heat through. return FALSE /turf/proc/ImmediateCalculateAdjacentTurfs() - var/canpass = CANATMOSPASS(src, src) + var/canpass = CANATMOSPASS(src, src) var/canvpass = CANVERTICALATMOSPASS(src, src) + + conductivity_blocked_directions = 0 + + var/src_contains_firelock = 1 + if(locate(/obj/machinery/door/firedoor) in src) + src_contains_firelock |= 2 + for(var/direction in GLOB.cardinals_multiz) var/turf/T = get_step_multiz(src, direction) - var/opp_dir = dir_inverse_multiz(direction) - if(!isopenturf(T)) + if(!istype(T)) + conductivity_blocked_directions |= direction continue - if(!(blocks_air || T.blocks_air) && ((direction & (UP|DOWN))? (canvpass && CANVERTICALATMOSPASS(T, src)) : (canpass && CANATMOSPASS(T, src))) ) + + var/other_contains_firelock = 1 + if(locate(/obj/machinery/door/firedoor) in T) + other_contains_firelock |= 2 + + update_conductivity(T) + + if(isopenturf(T) && !(blocks_air || T.blocks_air) && ((direction & (UP|DOWN))? (canvpass && CANVERTICALATMOSPASS(T, src)) : (canpass && CANATMOSPASS(T, src))) ) LAZYINITLIST(atmos_adjacent_turfs) LAZYINITLIST(T.atmos_adjacent_turfs) - atmos_adjacent_turfs[T] = direction - T.atmos_adjacent_turfs[src] = opp_dir - T.__update_extools_adjacent_turfs() + atmos_adjacent_turfs[T] = other_contains_firelock | src_contains_firelock + T.atmos_adjacent_turfs[src] = src_contains_firelock else if (atmos_adjacent_turfs) atmos_adjacent_turfs -= T if (T.atmos_adjacent_turfs) T.atmos_adjacent_turfs -= src - T.__update_extools_adjacent_turfs() UNSETEMPTY(T.atmos_adjacent_turfs) + + T.__update_auxtools_turf_adjacency_info() UNSETEMPTY(atmos_adjacent_turfs) src.atmos_adjacent_turfs = atmos_adjacent_turfs - __update_extools_adjacent_turfs() + __update_auxtools_turf_adjacency_info() -/turf/proc/__update_extools_adjacent_turfs() +/turf/proc/clear_adjacencies() + block_all_conductivity() + for(var/direction in GLOB.cardinals_multiz) + var/turf/T = get_step_multiz(src, direction) + if(!T) + continue + if (atmos_adjacent_turfs) + atmos_adjacent_turfs -= T + if (T.atmos_adjacent_turfs) + T.atmos_adjacent_turfs -= src + UNSETEMPTY(T.atmos_adjacent_turfs) + T.__update_auxtools_turf_adjacency_info() + LAZYNULL(atmos_adjacent_turfs) + __update_auxtools_turf_adjacency_info() + + +//Only gets a list of adjacencies, does NOT update +/turf/proc/get_adjacent_atmos_turfs() + . = list() + var/canpass = CANATMOSPASS(src, src) + var/canvpass = CANVERTICALATMOSPASS(src, src) + + for(var/direction in GLOB.cardinals_multiz) + var/turf/T = get_step_multiz(src, direction) + if(isopenturf(T) && !(blocks_air || T.blocks_air) && ((direction & (UP|DOWN))? (canvpass && CANVERTICALATMOSPASS(T, src)) : (canpass && CANATMOSPASS(T, src))) ) + .[T] = 0 + else + . -= T + UNSETEMPTY(.) //returns a list of adjacent turfs that can share air with this one. //alldir includes adjacent diagonal tiles that can share @@ -106,21 +160,19 @@ return adjacent_turfs -/atom/proc/air_update_turf(command = 0) - if(!isturf(loc) && command) +/atom/proc/air_update_turf() + var/turf/T = get_turf(src) + if(!T) return - var/turf/T = get_turf(loc) - T.air_update_turf(command) + T.air_update_turf() -/turf/air_update_turf(command = 0) - if(command) - ImmediateCalculateAdjacentTurfs() - SSair.add_to_active(src,command) +/turf/air_update_turf() + ImmediateCalculateAdjacentTurfs() /atom/movable/proc/move_update_air(turf/T) if(isturf(T)) - T.air_update_turf(1) - air_update_turf(1) + T.air_update_turf() + air_update_turf() /atom/proc/atmos_spawn_air(text) //because a lot of people loves to copy paste awful code lets just make an easy proc to spawn your plasma fires var/turf/open/T = get_turf(src) @@ -134,7 +186,4 @@ var/datum/gas_mixture/G = new G.parse_gas_string(text) - - air.merge(G) - archive() - SSair.add_to_active(src, 0) + assume_air(G) diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index ab5068eb1373..af36d33d22d4 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -1,18 +1,12 @@ /turf - //used for temperature calculations + //conductivity is divided by 10 when interacting with air for balance purposes var/thermal_conductivity = 0.05 var/heat_capacity = 1 - var/temperature_archived //list of open turfs adjacent to us var/list/atmos_adjacent_turfs - //bitfield of dirs in which we are superconducitng - var/atmos_supeconductivity = NONE - var/is_openturf = FALSE // used by extools shizz. - - //used to determine whether we should archive - var/archived_cycle = 0 - var/current_cycle = 0 + ///bitfield of dirs in which we thermal conductivity is blocked + var/conductivity_blocked_directions = NONE //used for mapping and for breathing while in walls (because that's a thing that needs to be accounted for...) //string parsed by /datum/gas/proc/copy_from_turf @@ -32,13 +26,15 @@ var/planetary_atmos = FALSE //air will revert to initial_gas_mix over time var/list/atmos_overlay_types //gas IDs of current active gas overlays - is_openturf = TRUE + +/turf/proc/should_conduct_to_space() + return get_z_base_turf() == /turf/open/space /turf/open/Initialize(mapload) if(!blocks_air) - air = new + air = new(2500,src) air.copy_from_turf(src) - update_air_ref() + update_air_ref(planetary_atmos ? 1 : 2) if(wet) AddComponent(/datum/component/wet_floor, wet, INFINITY, 0, INFINITY, TRUE) return ..() @@ -46,26 +42,45 @@ /turf/open/Destroy() if(active_hotspot) QDEL_NULL(active_hotspot) - // Adds the adjacent turfs to the current atmos processing - for(var/T in atmos_adjacent_turfs) - SSair.add_to_active(T) return ..() -/turf/proc/update_air_ref() - /////////////////GAS MIXTURE PROCS/////////////////// /turf/open/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air + return assume_air_ratio(giver, 1) + +/turf/open/assume_air_moles(datum/gas_mixture/giver, moles) + if(!giver) + return FALSE + giver.transfer_to(air, moles) + return TRUE + +/turf/open/assume_air_ratio(datum/gas_mixture/giver, ratio) if(!giver) return FALSE - air.merge(giver) - update_visuals() + giver.transfer_ratio_to(air, ratio) + return TRUE + +/turf/open/transfer_air(datum/gas_mixture/taker, moles) + if(!taker || !return_air()) // shouldn't transfer from space + return FALSE + air.transfer_to(taker, moles) + return TRUE + +/turf/open/transfer_air_ratio(datum/gas_mixture/taker, ratio) + if(!taker || !return_air()) + return FALSE + air.transfer_ratio_to(taker, ratio) return TRUE /turf/open/remove_air(amount) var/datum/gas_mixture/ours = return_air() var/datum/gas_mixture/removed = ours.remove(amount) - update_visuals() + return removed + +/turf/open/remove_air_ratio(ratio) + var/datum/gas_mixture/ours = return_air() + var/datum/gas_mixture/removed = ours.remove_ratio(ratio) return removed /turf/open/proc/copy_air_with_tile(turf/open/T) @@ -90,16 +105,9 @@ return return_air() /turf/temperature_expose() - if(temperature > heat_capacity) + if(return_temperature() > heat_capacity) to_be_destroyed = TRUE -/turf/proc/archive() - temperature_archived = temperature - -/turf/open/archive() - air.archive() - archived_cycle = SSair.times_fired - temperature_archived = temperature /turf/open/proc/eg_reset_cooldowns() /turf/open/proc/eg_garbage_collect() @@ -122,12 +130,12 @@ src.atmos_overlay_types = null return + for(var/id in air.get_gases()) - if(nonoverlaying_gases[id]) + if (nonoverlaying_gases[id]) continue - var/gas_meta = GLOB.meta_gas_info[id] - var/gas_overlay = gas_meta[META_GAS_OVERLAY] - if(gas_overlay && air.get_moles(id) > gas_meta[META_GAS_MOLES_VISIBLE]) + var/gas_overlay = GLOB.gas_data.overlays[id] + if(gas_overlay && air.get_moles(id) > GLOB.gas_data.visibility[id]) new_overlay_types += gas_overlay[min(FACTOR_GAS_VISIBLE_MAX, CEILING(air.get_moles(id) / MOLES_GAS_VISIBLE_STEP, 1))] if (atmos_overlay_types) @@ -143,6 +151,7 @@ UNSETEMPTY(new_overlay_types) src.atmos_overlay_types = new_overlay_types +//called by auxmos, do not remove /turf/open/proc/set_visuals(list/new_overlay_types) if (atmos_overlay_types) for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added @@ -161,49 +170,40 @@ for (var/gastype in subtypesof(/datum/gas)) var/datum/gas/gasvar = gastype if (!initial(gasvar.gas_overlay)) - .[gastype] = TRUE + .[initial(gasvar.id)] = TRUE /////////////////////////////SIMULATION/////////////////////////////////// -/*#define LAST_SHARE_CHECK \ - var/last_share = our_air.get_last_share();\ - if(last_share > MINIMUM_AIR_TO_SUSPEND){\ - our_excited_group.reset_cooldowns();\ - cached_atmos_cooldown = 0;\ - } else if(last_share > MINIMUM_MOLES_DELTA_TO_MOVE) {\ - our_excited_group.dismantle_cooldown = 0;\ - cached_atmos_cooldown = 0;\ - } -*/ /turf/proc/process_cell(fire_count) - SSair.remove_from_active(src) /turf/open/proc/equalize_pressure_in_zone(cyclenum) /turf/open/proc/consider_firelocks(turf/T2) - var/reconsider_adj = FALSE for(var/obj/machinery/door/firedoor/FD in T2) - if((FD.flags_1 & ON_BORDER_1) && get_dir(T2, src) != FD.dir) - continue FD.emergency_pressure_stop() - reconsider_adj = TRUE for(var/obj/machinery/door/firedoor/FD in src) - if((FD.flags_1 & ON_BORDER_1) && get_dir(src, T2) != FD.dir) - continue FD.emergency_pressure_stop() - reconsider_adj = TRUE - if(reconsider_adj) - T2.ImmediateCalculateAdjacentTurfs() // We want those firelocks closed yesterday. /turf/proc/handle_decompression_floor_rip() /turf/open/floor/handle_decompression_floor_rip(sum) - if(sum > 20 && prob(clamp(sum / 10, 0, 30))) - remove_tile() + if(sum > 20 && prob(clamp(sum / 20, 0, 15))) + if(floor_tile) + new floor_tile(src) + make_plating() + +/turf/open/floor/plating/handle_decompression_floor_rip() + return + +/turf/open/floor/engine/handle_decompression_floor_rip() + return /turf/open/process_cell(fire_count) //////////////////////////SPACEWIND///////////////////////////// -/turf/open/proc/consider_pressure_difference(turf/T, difference) +/turf/proc/consider_pressure_difference() + return + +/turf/open/consider_pressure_difference(turf/T, difference) SSair.high_pressure_delta |= src if(difference > pressure_difference) pressure_direction = get_dir(src, T) @@ -227,7 +227,7 @@ /atom/movable/var/last_high_pressure_movement_air_cycle = 0 /atom/movable/proc/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0, throw_target) - var/const/PROBABILITY_OFFSET = 25 + var/const/PROBABILITY_OFFSET = 40 var/const/PROBABILITY_BASE_PRECENT = 10 var/max_force = sqrt(pressure_difference)*(MOVE_FORCE_DEFAULT / 5) set waitfor = 0 @@ -237,124 +237,13 @@ move_prob += pressure_resistance_prob_delta if (move_prob > PROBABILITY_OFFSET && prob(move_prob) && (move_resist != INFINITY) && (!anchored && (max_force >= (move_resist * MOVE_FORCE_PUSH_RATIO))) || (anchored && (max_force >= (move_resist * MOVE_FORCE_FORCEPUSH_RATIO)))) var/move_force = max_force * clamp(move_prob, 0, 100) / 100 - if(move_force > 4000) + if(move_force > 6000) // WALLSLAM HELL TIME OH BOY var/turf/throw_turf = get_ranged_target_turf(get_turf(src), direction, round(move_force / 2000)) if(throw_target && (get_dir(src, throw_target) & direction)) throw_turf = get_turf(throw_target) - var/throw_speed = clamp(round(move_force / 2000), 1, 10) - if(iscarbon(src)) - throw_speed = min(throw_speed, 4) - throw_at(throw_turf, move_force / 2000, throw_speed) + var/throw_speed = clamp(round(move_force / 3000), 1, 10) + throw_at(throw_turf, move_force / 3000, throw_speed, quickstart = FALSE) else step(src, direction) last_high_pressure_movement_air_cycle = SSair.times_fired - -////////////////////////SUPERCONDUCTIVITY///////////////////////////// -/turf/proc/conductivity_directions() - if(archived_cycle < SSair.times_fired) - archive() - return NORTH|SOUTH|EAST|WEST - -/turf/open/conductivity_directions() - if(blocks_air) - return ..() - for(var/direction in GLOB.cardinals) - var/turf/T = get_step(src, direction) - if(!(T in atmos_adjacent_turfs) && !(atmos_supeconductivity & direction)) - . |= direction - -/turf/proc/neighbor_conduct_with_src(turf/open/other) - if(!other.blocks_air) //Open but neighbor is solid - other.temperature_share_open_to_solid(src) - else //Both tiles are solid - other.share_temperature_mutual_solid(src, thermal_conductivity) - temperature_expose(null, temperature, null) - -/turf/open/neighbor_conduct_with_src(turf/other) - if(blocks_air) - ..() - return - - if(!other.blocks_air) //Both tiles are open - var/turf/open/T = other - T.air.temperature_share(air, WINDOW_HEAT_TRANSFER_COEFFICIENT) - else //Solid but neighbor is open - temperature_share_open_to_solid(other) - SSair.add_to_active(src, 0) - -/turf/proc/super_conduct() - var/conductivity_directions = conductivity_directions() - - if(conductivity_directions) - //Conduct with tiles around me - for(var/direction in GLOB.cardinals) - if(conductivity_directions & direction) - var/turf/neighbor = get_step(src,direction) - - if(!neighbor.thermal_conductivity) - continue - - if(neighbor.archived_cycle < SSair.times_fired) - neighbor.archive() - - neighbor.neighbor_conduct_with_src(src) - - neighbor.consider_superconductivity() - - radiate_to_spess() - - finish_superconduction() - -/turf/proc/finish_superconduction(temp = temperature) - //Make sure still hot enough to continue conducting heat - if(temp < MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION) - SSair.active_super_conductivity -= src - return FALSE - -/turf/open/finish_superconduction() - //Conduct with air on my tile if I have it - if(!blocks_air) - temperature = air.temperature_share(null, thermal_conductivity, temperature, heat_capacity) - ..((blocks_air ? temperature : air.return_temperature())) - -/turf/proc/consider_superconductivity() - if(!thermal_conductivity) - return FALSE - - SSair.active_super_conductivity |= src - return TRUE - -/turf/open/consider_superconductivity(starting) - if(air.return_temperature() < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION)) - return FALSE - if(air.heat_capacity() < M_CELL_WITH_RATIO) // Was: MOLES_CELLSTANDARD*0.1*0.05 Since there are no variables here we can make this a constant. - return FALSE - return ..() - -/turf/closed/consider_superconductivity(starting) - if(temperature < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION)) - return FALSE - return ..() - -/turf/proc/radiate_to_spess() //Radiate excess tile heat to space - if(temperature > T0C) //Considering 0 degC as te break even point for radiation in and out - var/delta_temperature = (temperature_archived - TCMB) //hardcoded space temperature - if((heat_capacity > 0) && (abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)) - - var/heat = thermal_conductivity*delta_temperature* \ - (heat_capacity*HEAT_CAPACITY_VACUUM/(heat_capacity+HEAT_CAPACITY_VACUUM)) - temperature -= heat/heat_capacity - -/turf/open/proc/temperature_share_open_to_solid(turf/sharer) - sharer.temperature = air.temperature_share(null, sharer.thermal_conductivity, sharer.temperature, sharer.heat_capacity) - -/turf/proc/share_temperature_mutual_solid(turf/sharer, conduction_coefficient) //to be understood - var/delta_temperature = (temperature_archived - sharer.temperature_archived) - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER && heat_capacity && sharer.heat_capacity) - - var/heat = conduction_coefficient*delta_temperature* \ - (heat_capacity*sharer.heat_capacity/(heat_capacity+sharer.heat_capacity)) - - temperature -= heat/heat_capacity - sharer.temperature += heat/sharer.heat_capacity diff --git a/code/modules/atmospherics/gasmixtures/auxgm.dm b/code/modules/atmospherics/gasmixtures/auxgm.dm new file mode 100644 index 000000000000..60bf7896c0af --- /dev/null +++ b/code/modules/atmospherics/gasmixtures/auxgm.dm @@ -0,0 +1,146 @@ +///the main four gases, which were at one time hardcoded +GLOBAL_LIST_INIT(hardcoded_gases, list( + GAS_O2, + GAS_N2, + GAS_CO2, + GAS_PLASMA, +)) +///Gasses that are unable to react amongst themselves +GLOBAL_LIST_INIT(nonreactive_gases, typecacheof( + list( + GAS_O2, + GAS_N2, + GAS_CO2, + GAS_PLUOXIUM, + ), +)) + +// Auxgm +// It's a send-up of XGM, like what baystation got. +// It's got the same architecture as XGM, but it's structured +// differently to make it more convenient for auxmos. + +// Most important compared to TG is that it does away with hardcoded typepaths, +// which lead to problems on the auxmos end anyway. We cache the string value +// references on the Rust end, so no performance is lost here. + +// Also allows you to add new gases at runtime + +/datum/auxgm + var/list/datums = list() + var/list/specific_heats = list() + var/list/names = list() + var/list/labels = list() + var/list/visibility = list() + var/list/overlays = list() + var/list/flags = list() + var/list/ids = list() + var/list/typepaths = list() + var/list/fusion_powers = list() + var/list/breathing_classes = list() + var/list/breath_results = list() + var/list/breath_reagents = list() + var/list/breath_reagents_dangerous = list() + var/list/breath_alert_info = list() + var/list/oxidation_temperatures = list() + var/list/oxidation_rates = list() + var/list/fire_temperatures = list() + var/list/enthalpies = list() + var/list/fire_products = list() + var/list/fire_burn_rates = list() + var/list/ui_colors = list() + +/datum/gas + var/id = "" + var/specific_heat = 0 + var/name = "" + var/label = "" //shortened name + var/gas_overlay = "" //icon_state in icons/effects/atmospherics.dmi + var/moles_visible = null + var/flags = NONE //currently used by canisters + var/fusion_power = 0 // How much the gas destabilizes a fusion reaction + var/breath_results = GAS_CO2 // what breathing this breathes out + var/breath_reagent = null // what breathing this adds to your reagents + var/breath_reagent_dangerous = null // what breathing this adds to your reagents IF it's above a danger threshold + var/list/breath_alert_info = null // list for alerts that pop up when you have too much/not enough of something + var/oxidation_temperature = null // temperature above which this gas is an oxidizer; null for none + var/oxidation_rate = 1 // how many moles of this can oxidize how many moles of material + var/fire_temperature = null // temperature above which gas may catch fire; null for none + var/list/fire_products = null // what results when this gas is burned (oxidizer or fuel); null for none + var/enthalpy = 0 // Standard enthalpy of formation in joules, used for fires + var/fire_burn_rate = 1 // how many moles are burned per product released + var/fire_radiation_released = 0 // How much radiation is released when this gas burns + var/ui_color = "white" + +/datum/gas/proc/breath(partial_pressure, light_threshold, heavy_threshold, moles, mob/living/carbon/C, obj/item/organ/lungs/lungs) + // This is only called on gases with the GAS_FLAG_BREATH_PROC flag. When possible, do NOT use this-- + // greatly prefer just adding a reagent. This is mostly around for legacy reasons. + return null + +/datum/auxgm/proc/add_gas(datum/gas/gas) + var/g = gas.id + if(g) + datums[g] = gas + specific_heats[g] = gas.specific_heat + names[g] = gas.name + if(!gas.label) + gas.label = gas.name + labels[g] = gas.label + if(gas.moles_visible) + visibility[g] = gas.moles_visible + overlays[g] = new /list(FACTOR_GAS_VISIBLE_MAX) + for(var/i in 1 to FACTOR_GAS_VISIBLE_MAX) + overlays[g][i] = new /obj/effect/overlay/gas(gas.gas_overlay, i * 255 / FACTOR_GAS_VISIBLE_MAX) + else + visibility[g] = 0 + overlays[g] = 0 + flags[g] = gas.flags + ids[g] = g + typepaths[g] = gas.type + fusion_powers[g] = gas.fusion_power + ui_colors[g] = gas.ui_color + + if(gas.breath_alert_info) + breath_alert_info[g] = gas.breath_alert_info + breath_results[g] = gas.breath_results + if(gas.breath_reagent) + breath_reagents[g] = gas.breath_reagent + if(gas.breath_reagent_dangerous) + breath_reagents_dangerous[g] = gas.breath_reagent_dangerous + if(gas.oxidation_temperature) + oxidation_temperatures[g] = gas.oxidation_temperature + oxidation_rates[g] = gas.oxidation_rate + if(gas.fire_products) + fire_products[g] = gas.fire_products + enthalpies[g] = gas.enthalpy + else if(gas.fire_temperature) + fire_temperatures[g] = gas.fire_temperature + fire_burn_rates[g] = gas.fire_burn_rate + if(gas.fire_products) + fire_products[g] = gas.fire_products + enthalpies[g] = gas.enthalpy + _auxtools_register_gas(gas) + +/datum/auxgm/New() + for(var/gas_path in subtypesof(/datum/gas)) + var/datum/gas/gas = new gas_path + add_gas(gas) + for(var/breathing_class_path in subtypesof(/datum/breathing_class)) + var/datum/breathing_class/class = new breathing_class_path + breathing_classes[breathing_class_path] = class + finalize_gas_refs() + +GLOBAL_DATUM_INIT(gas_data, /datum/auxgm, new) + +/obj/effect/overlay/gas + icon = 'icons/effects/atmospherics.dmi' + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + anchored = TRUE // should only appear in vis_contents, but to be safe + layer = FLY_LAYER + appearance_flags = TILE_BOUND + vis_flags = NONE + +/obj/effect/overlay/gas/New(state, alph) + . = ..() + icon_state = state + alpha = alph diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index 991907fbd814..e3d56b5e471c 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -21,44 +21,105 @@ What are the archived variables for? #define QUANTIZE(variable) (round(variable,0.0000001))/*I feel the need to document what happens here. Basically this is used to catch most rounding errors, however it's previous value made it so that once gases got hot enough, most procedures wouldnt occur due to the fact that the mole counts would get rounded away. Thus, we lowered it a few orders of magnititude */ -GLOBAL_LIST_INIT(meta_gas_info, meta_gas_list()) //see ATMOSPHERICS/gas_types.dm -GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) - -/proc/init_gaslist_cache() - . = list() - for(var/id in GLOB.meta_gas_info) - var/list/cached_gas = new(3) - - .[id] = cached_gas - - cached_gas[MOLES] = 0 - cached_gas[ARCHIVE] = 0 - cached_gas[GAS_META] = GLOB.meta_gas_info[id] /datum/gas_mixture + /// Never ever set this variable, hooked into vv_get_var for view variables viewing. + var/gas_list_view_only var/initial_volume = CELL_VOLUME //liters var/list/reaction_results var/list/analyzer_results //used for analyzer feedback - not initialized until its used - var/_extools_pointer_gasmixture = 0 // Contains the memory address of the shared_ptr object for this gas mixture in c++ land. Don't. Touch. This. Var. + var/_extools_pointer_gasmixture // Contains the index in the gas vector for this gas mixture in rust land. Don't. Touch. This. Var. + +GLOBAL_VAR_INIT(auxtools_atmos_initialized, FALSE) /datum/gas_mixture/New(volume) if (!isnull(volume)) initial_volume = volume - ATMOS_EXTOOLS_CHECK + if(!GLOB.auxtools_atmos_initialized && auxtools_atmos_init(GLOB.gas_data)) + GLOB.auxtools_atmos_initialized = TRUE __gasmixture_register() reaction_results = new +/datum/gas_mixture/Del() + __gasmixture_unregister() + . = ..() + /datum/gas_mixture/vv_edit_var(var_name, var_value) if(var_name == NAMEOF(src, _extools_pointer_gasmixture)) return FALSE // please no. segfaults bad. + if(var_name == "gas_list_view_only") + return FALSE return ..() -/* -/datum/gas_mixture/Del() - __gasmixture_unregister() - . = ..()*/ -/datum/gas_mixture/proc/__gasmixture_unregister() -/datum/gas_mixture/proc/__gasmixture_register() +/datum/gas_mixture/vv_get_var(var_name) + . = ..() + if(var_name == "gas_list_view_only") + var/list/dummy = get_gases() + for(var/gas in dummy) + dummy[gas] = get_moles(gas) + dummy["CAP [gas]"] = partial_heat_capacity(gas) + dummy["TEMP"] = return_temperature() + dummy["PRESSURE"] = return_pressure() + dummy["HEAT CAPACITY"] = heat_capacity() + dummy["TOTAL MOLES"] = total_moles() + dummy["VOLUME"] = return_volume() + dummy["THERMAL ENERGY"] = thermal_energy() + return debug_variable("gases (READ ONLY)", dummy, 0, src) + +/datum/gas_mixture/vv_get_dropdown() + . = ..() + VV_DROPDOWN_OPTION("", "---") + VV_DROPDOWN_OPTION(VV_HK_PARSE_GASSTRING, "Parse Gas String") + VV_DROPDOWN_OPTION(VV_HK_EMPTY, "Empty") + VV_DROPDOWN_OPTION(VV_HK_SET_MOLES, "Set Moles") + VV_DROPDOWN_OPTION(VV_HK_SET_TEMPERATURE, "Set Temperature") + VV_DROPDOWN_OPTION(VV_HK_SET_VOLUME, "Set Volume") + +/datum/gas_mixture/vv_do_topic(list/href_list) + . = ..() + if(!.) + return + if(href_list[VV_HK_PARSE_GASSTRING]) + var/gasstring = input(usr, "Input Gas String (WARNING: Advanced. Don't use this unless you know how these work.", "Gas String Parse") as text|null + if(!istext(gasstring)) + return + log_admin("[key_name(usr)] modified gas mixture [REF(src)]: Set to gas string [gasstring].") + message_admins("[key_name(usr)] modified gas mixture [REF(src)]: Set to gas string [gasstring].") + parse_gas_string(gasstring) + if(href_list[VV_HK_EMPTY]) + log_admin("[key_name(usr)] emptied gas mixture [REF(src)].") + message_admins("[key_name(usr)] emptied gas mixture [REF(src)].") + clear() + if(href_list[VV_HK_SET_MOLES]) + var/list/gases = get_gases() + for(var/gas in gases) + gases[gas] = get_moles(gas) + var/gasid = input(usr, "What kind of gas?", "Set Gas") as null|anything in GLOB.gas_data.ids + if(!gasid) + return + var/amount = input(usr, "Input amount", "Set Gas", gases[gasid] || 0) as num|null + if(!isnum(amount)) + return + amount = max(0, amount) + log_admin("[key_name(usr)] modified gas mixture [REF(src)]: Set gas [gasid] to [amount] moles.") + message_admins("[key_name(usr)] modified gas mixture [REF(src)]: Set gas [gasid] to [amount] moles.") + set_moles(gasid, amount) + if(href_list[VV_HK_SET_TEMPERATURE]) + var/temp = input(usr, "Set the temperature of this mixture to?", "Set Temperature", return_temperature()) as num|null + if(!isnum(temp)) + return + temp = max(2.7, temp) + log_admin("[key_name(usr)] modified gas mixture [REF(src)]: Changed temperature to [temp].") + message_admins("[key_name(usr)] modified gas mixture [REF(src)]: Changed temperature to [temp].") + set_temperature(temp) + if(href_list[VV_HK_SET_VOLUME]) + var/volume = input(usr, "Set the volume of this mixture to?", "Set Volume", return_volume()) as num|null + if(!isnum(volume)) + return + volume = max(0, volume) + log_admin("[key_name(usr)] modified gas mixture [REF(src)]: Changed volume to [volume].") + message_admins("[key_name(usr)] modified gas mixture [REF(src)]: Changed volume to [volume].") + set_volume(volume) /proc/gas_types() var/list/L = subtypesof(/datum/gas) @@ -67,50 +128,20 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) L[gt] = initial(G.specific_heat) return L -/datum/gas_mixture/proc/heat_capacity(data = MOLES) //joules per kelvin - -/datum/gas_mixture/proc/total_moles() - -/datum/gas_mixture/proc/return_pressure() //kilopascals - -/datum/gas_mixture/proc/return_temperature() //kelvins - -/datum/gas_mixture/proc/set_min_heat_capacity(n) -/datum/gas_mixture/proc/set_temperature(new_temp) -/datum/gas_mixture/proc/set_volume(new_volume) -/datum/gas_mixture/proc/get_moles(gas_type) -/datum/gas_mixture/proc/set_moles(gas_type, moles) -/datum/gas_mixture/proc/scrub_into(datum/gas_mixture/target, list/gases) -/datum/gas_mixture/proc/mark_immutable() -/datum/gas_mixture/proc/get_gases() -/datum/gas_mixture/proc/multiply(factor) /datum/gas_mixture/proc/get_last_share() -/datum/gas_mixture/proc/clear() - -/datum/gas_mixture/proc/adjust_moles(gas_type, amt = 0) - if((get_moles(gas_type) + amt) < 0) - amt = 0 - set_moles(gas_type, get_moles(gas_type) + amt) - -/datum/gas_mixture/proc/return_volume() //liters - -/datum/gas_mixture/proc/thermal_energy() //joules /datum/gas_mixture/proc/archive() //Update archived versions of variables //Returns: 1 in all cases -/datum/gas_mixture/proc/merge(datum/gas_mixture/giver) - //Merges all air from giver into self. giver is untouched. - //Returns: 1 if we are mutable, 0 otherwise /datum/gas_mixture/proc/remove(amount) - //Removes amount of gas from the gas_mixture + //Proportionally removes amount of gas from the gas_mixture //Returns: gas_mixture with the gases removed -/datum/gas_mixture/proc/transfer_to(datum/gas_mixture/target, amount) - //Transfers amount of gas to target. Equivalent to target.merge(remove(amount)) but faster. - //Removes amount of gas from the gas_mixture +/datum/gas_mixture/proc/remove_by_flag(flag, amount) + //Removes amount of gas from the gas mixture by flag + //Returns: gas_mixture with gases that match the flag removed /datum/gas_mixture/proc/remove_ratio(ratio) //Proportionally removes amount of gas from the gas_mixture @@ -120,10 +151,6 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) //Creates new, identical gas mixture //Returns: duplicate gas mixture -/datum/gas_mixture/proc/copy_from(datum/gas_mixture/sample) - //Copies variables from sample - //Returns: 1 if we are mutable, 0 otherwise - /datum/gas_mixture/proc/copy_from_turf(turf/model) //Copies all gas info from the turf into the gas list along with temperature //Returns: 1 if we are mutable, 0 otherwise @@ -136,27 +163,18 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) //Performs air sharing calculations between two gas_mixtures assuming only 1 boundary length //Returns: amount of gas exchanged (+ if sharer received) -/datum/gas_mixture/proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient) - //Performs temperature sharing calculations (via conduction) between two gas_mixtures assuming only 1 boundary length - //Returns: new temperature of the sharer - -/datum/gas_mixture/proc/compare(datum/gas_mixture/sample) - //Compares sample to self to see if within acceptable ranges that group processing may be enabled - //Returns: a string indicating what check failed, or "" if check passes - -/datum/gas_mixture/proc/react(turf/open/dump_location) - //Performs various reactions such as combustion or fusion (LOL) - //Returns: 1 if any reaction took place; 0 otherwise +/datum/gas_mixture/remove_by_flag(flag, amount) + var/datum/gas_mixture/removed = new type + __remove_by_flag(removed, flag, amount) + return removed -/datum/gas_mixture/proc/__remove() /datum/gas_mixture/remove(amount) var/datum/gas_mixture/removed = new type __remove(removed, amount) return removed -/datum/gas_mixture/proc/__remove_ratio() /datum/gas_mixture/remove_ratio(ratio) var/datum/gas_mixture/removed = new type __remove_ratio(removed, ratio) @@ -170,75 +188,30 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) return copy /datum/gas_mixture/copy_from_turf(turf/model) + set_temperature(initial(model.initial_temperature)) parse_gas_string(model.initial_gas_mix) - - //acounts for changes in temperature - var/turf/model_parent = model.parent_type - if(model.temperature != initial(model.temperature) || model.temperature != initial(model_parent.temperature)) - set_temperature(model.temperature) - return 1 /datum/gas_mixture/parse_gas_string(gas_string) + __auxtools_parse_gas_string(gas_string) + /* var/list/gas = params2list(gas_string) if(gas["TEMP"]) - set_temperature(text2num(gas["TEMP"])) + var/temp = text2num(gas["TEMP"]) gas -= "TEMP" + if(!isnum(temp) || temp < 2.7) + temp = 2.7 + set_temperature(temp) clear() for(var/id in gas) - var/path = id - if(!ispath(path)) - path = gas_id2path(path) //a lot of these strings can't have embedded expressions (especially for mappers), so support for IDs needs to stick around - set_moles(path, text2num(gas[id])) + set_moles(id, text2num(gas[id])) return 1 - -/datum/gas_mixture/react(datum/holder) - . = NO_REACTION - var/list/reactions = list() - for(var/I in get_gases()) - reactions += SSair.gas_reactions[I] - if(!length(reactions)) - return - if (length(reactions) > 1) - reactions = sortTim(reactions, /proc/cmp_gas_reaction) - reaction_results = new - var/temp = return_temperature() - var/ener = thermal_energy() - - reaction_loop: - for(var/r in reactions) - var/datum/gas_reaction/reaction = r - - var/list/min_reqs = reaction.min_requirements - if( (min_reqs["TEMP"] && temp < min_reqs["TEMP"]) || \ - (min_reqs["ENER"] && ener < min_reqs["ENER"]) || \ - (min_reqs["MAX_TEMP"] && temp > min_reqs["MAX_TEMP"]) - ) - continue - - for(var/id in min_reqs) - if (id == "TEMP" || id == "ENER" || id == "MAX_TEMP") - continue - if(get_moles(id) < min_reqs[id]) - continue reaction_loop - - //at this point, all requirements for the reaction are satisfied. we can now react() - - . |= reaction.react(src, holder) - if (. & STOP_REACTIONS) - break - -//Takes the amount of the gas you want to PP as an argument -//So I don't have to do some hacky switches/defines/magic strings -//eg: -//Tox_PP = get_partial_pressure(gas_mixture.toxins) -//O2_PP = get_partial_pressure(gas_mixture.oxygen) - -/datum/gas_mixture/proc/get_breath_partial_pressure(gas_pressure) - return (gas_pressure * R_IDEAL_GAS_EQUATION * return_temperature()) / BREATH_VOLUME -//inverse -/datum/gas_mixture/proc/get_true_breath_pressure(partial_pressure) - return (partial_pressure * BREATH_VOLUME) / (R_IDEAL_GAS_EQUATION * return_temperature()) + */ + +/datum/gas_mixture/proc/set_analyzer_results(instability) + if(!analyzer_results) + analyzer_results = new + analyzer_results["fusion"] = instability //Mathematical proofs: /* @@ -251,59 +224,6 @@ get_true_breath_pressure(pp) --> gas_pp = pp/breath_pp*total_moles() /datum/gas_mixture/turf -/* -/mob/verb/profile_atmos() - /world{loop_checks = 0;} - var/datum/gas_mixture/A = new - var/datum/gas_mixture/B = new - A.parse_gas_string("o2=200;n2=800;TEMP=50") - B.parse_gas_string("co2=500;plasma=500;TEMP=5000") - var/pa - var/pb - pa = world.tick_usage - for(var/I in 1 to 100000) - B.transfer_to(A, 1) - A.transfer_to(B, 1) - pb = world.tick_usage - var/total_time = (pb-pa) * world.tick_lag - to_chat(src, "Total time (gas transfer): [total_time]ms") - to_chat(src, "Operations per second: [100000 / (total_time/1000)]") - pa = world.tick_usage - for(var/I in 1 to 100000) - B.total_moles(); - pb = world.tick_usage - total_time = (pb-pa) * world.tick_lag - to_chat(src, "Total time (total_moles): [total_time]ms") - to_chat(src, "Operations per second: [100000 / (total_time/1000)]") - pa = world.tick_usage - for(var/I in 1 to 100000) - new /datum/gas_mixture - pb = world.tick_usage - total_time = (pb-pa) * world.tick_lag - to_chat(src, "Total time (new gas mixture): [total_time]ms") - to_chat(src, "Operations per second: [100000 / (total_time/1000)]") -*/ - - -/// Pumps gas from src to output_air. The amount depends on target_pressure -/datum/gas_mixture/proc/pump_gas_to(datum/gas_mixture/output_air, target_pressure) - var/output_starting_pressure = output_air.return_pressure() - - if((target_pressure - output_starting_pressure) < 0.01) - //No need to pump gas if target is already reached! - return FALSE - - //Calculate necessary moles to transfer using PV=nRT - if((total_moles() > 0) && (return_temperature()>0)) - var/pressure_delta = target_pressure - output_starting_pressure - var/transfer_moles = pressure_delta*output_air.return_volume()/(return_temperature() * R_IDEAL_GAS_EQUATION) - - //Actually transfer the gas - var/datum/gas_mixture/removed = remove(transfer_moles) - output_air.merge(removed) - return TRUE - return FALSE - /// Releases gas from src to output air. This means that it can not transfer air to gas mixture with higher pressure. /datum/gas_mixture/proc/release_gas_to(datum/gas_mixture/output_air, target_pressure) var/output_starting_pressure = output_air.return_pressure() @@ -311,7 +231,7 @@ get_true_breath_pressure(pp) --> gas_pp = pp/breath_pp*total_moles() if(output_starting_pressure >= min(target_pressure,input_starting_pressure-10)) //No need to pump gas if target is already reached or input pressure is too low - //Need at least 10 KPa difference to overcome friction in the mechanism + //Need at least 10 kPa difference to overcome friction in the mechanism return FALSE //Calculate necessary moles to transfer using PV = nRT @@ -324,10 +244,12 @@ get_true_breath_pressure(pp) --> gas_pp = pp/breath_pp*total_moles() //Actually transfer the gas var/datum/gas_mixture/removed = remove(transfer_moles) output_air.merge(removed) - return TRUE return FALSE +/datum/gas_mixture/proc/vv_react(datum/holder) + return react(holder) + /datum/gas_mixture/proc/remove_specific_ratio(gas_id, ratio) if(ratio <= 0) return null @@ -357,13 +279,16 @@ get_true_breath_pressure(pp) --> gas_pp = pp/breath_pp*total_moles() /datum/gas_mixture/proc/equalize(datum/gas_mixture/other) . = FALSE + if(!return_volume() || !other.return_volume()) + return + var/self_temp = return_temperature() var/other_temp = other.return_temperature() if(abs(self_temp - other_temp) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) . = TRUE var/self_heat_cap = heat_capacity() var/other_heat_cap = other.heat_capacity() - var/new_temp = (self_temp * self_heat_cap + other_temp * other_heat_cap) / (self_heat_cap + other_heat_cap) + var/new_temp = max((self_temp * self_heat_cap + other_temp * other_heat_cap) / (self_heat_cap + other_heat_cap), TCMB) set_temperature(new_temp) other.set_temperature(new_temp) diff --git a/code/modules/atmospherics/gasmixtures/gas_types.dm b/code/modules/atmospherics/gasmixtures/gas_types.dm deleted file mode 100644 index 2a52acd9cfba..000000000000 --- a/code/modules/atmospherics/gasmixtures/gas_types.dm +++ /dev/null @@ -1,237 +0,0 @@ -GLOBAL_LIST_INIT(hardcoded_gases, list(/datum/gas/oxygen, /datum/gas/nitrogen, /datum/gas/carbon_dioxide, /datum/gas/plasma)) //the main four gases, which were at one time hardcoded -GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(/datum/gas/oxygen, /datum/gas/nitrogen, /datum/gas/carbon_dioxide, /datum/gas/pluoxium))) //unable to react amongst themselves - -/proc/meta_gas_list() - . = subtypesof(/datum/gas) - for(var/gas_path in .) - var/list/gas_info = new(7) - var/datum/gas/gas = gas_path - - gas_info[META_GAS_SPECIFIC_HEAT] = initial(gas.specific_heat) - gas_info[META_GAS_NAME] = initial(gas.name) - - gas_info[META_GAS_MOLES_VISIBLE] = initial(gas.moles_visible) - if(initial(gas.moles_visible) != null) - gas_info[META_GAS_OVERLAY] = new /list(FACTOR_GAS_VISIBLE_MAX) - for(var/i in 1 to FACTOR_GAS_VISIBLE_MAX) - gas_info[META_GAS_OVERLAY][i] = new /obj/effect/overlay/gas(initial(gas.gas_overlay), i * 255 / FACTOR_GAS_VISIBLE_MAX) - - gas_info[META_GAS_FUSION_POWER] = initial(gas.fusion_power) - gas_info[META_GAS_DANGER] = initial(gas.dangerous) - gas_info[META_GAS_ID] = initial(gas.id) - .[gas_path] = gas_info - -/proc/gas_id2path(id) - var/list/meta_gas = GLOB.meta_gas_info - if(id in meta_gas) - return id - for(var/path in meta_gas) - if(meta_gas[path][META_GAS_ID] == id) - return path - return "" - -/*||||||||||||||/----------\||||||||||||||*\ -||||||||||||||||[GAS DATUMS]|||||||||||||||| -||||||||||||||||\__________/|||||||||||||||| -||||These should never be instantiated. |||| -||||They exist only to make it easier |||| -||||to add a new gas. They are accessed |||| -||||only by meta_gas_list(). |||| -\*||||||||||||||||||||||||||||||||||||||||*/ - -/datum/gas - var/id = "" - var/specific_heat = 0 - var/name = "" - /// icon_state in icons/effects/atmospherics.dmi - var/gas_overlay = "" - var/moles_visible = null - /// Currently used by canisters - var/dangerous = FALSE - /// How much the gas accelerates a fusion reaction - var/fusion_power = 0 - /// Relative rarity compared to other gases, used when setting up the reactions list. - var/rarity = 0 - -// If you add or remove gases, update TOTAL_NUM_GASES in the extools code to match! -// (dont forget to count shizz in the yogstation folder) - -/datum/gas/oxygen - id = "o2" - specific_heat = 20 - name = "Oxygen" - rarity = 900 - -/datum/gas/nitrogen - id = "n2" - specific_heat = 20 - name = "Nitrogen" - rarity = 1000 - -/datum/gas/carbon_dioxide //what the fuck is this? - id = "co2" - specific_heat = 30 - name = "Carbon Dioxide" - rarity = 700 - -/datum/gas/plasma - id = "plasma" - specific_heat = 200 - name = "Plasma" - gas_overlay = "plasma" - moles_visible = MOLES_GAS_VISIBLE - dangerous = TRUE - rarity = 800 - -/datum/gas/water_vapor - id = "water_vapor" - specific_heat = 40 - name = "Water Vapor" - gas_overlay = "water_vapor" - moles_visible = MOLES_GAS_VISIBLE - fusion_power = 8 - rarity = 500 - -/datum/gas/hypernoblium - id = "nob" - specific_heat = 2000 - name = "Hyper-noblium" - gas_overlay = "freon" - moles_visible = MOLES_GAS_VISIBLE - dangerous = TRUE - rarity = 50 - -/datum/gas/nitrous_oxide - id = "n2o" - specific_heat = 40 - name = "Nitrous Oxide" - gas_overlay = "nitrous_oxide" - moles_visible = MOLES_GAS_VISIBLE * 2 - fusion_power = 10 - dangerous = TRUE - rarity = 600 - -/datum/gas/nitrium - id = "nitrium" - specific_heat = 10 - name = "Nitrium" - fusion_power = 7 - gas_overlay = "nitrium" - moles_visible = MOLES_GAS_VISIBLE - dangerous = TRUE - rarity = 1 - -/datum/gas/tritium - id = "tritium" - specific_heat = 10 - name = "Tritium" - gas_overlay = "tritium" - moles_visible = MOLES_GAS_VISIBLE - dangerous = TRUE - fusion_power = 1 - rarity = 300 - -/datum/gas/bz - id = "bz" - specific_heat = 20 - name = "BZ" - dangerous = TRUE - fusion_power = 8 - rarity = 400 - -/datum/gas/pluoxium - id = "pluox" - specific_heat = 80 - name = "Pluoxium" - fusion_power = -10 - rarity = 200 - -/datum/gas/miasma - id = "miasma" - specific_heat = 20 - name = "Miasma" - gas_overlay = "miasma" - moles_visible = MOLES_GAS_VISIBLE * 60 - rarity = 250 - -/datum/gas/freon - id = "freon" - specific_heat = 600 - name = "Freon" - gas_overlay = "freon" - moles_visible = MOLES_GAS_VISIBLE *30 - fusion_power = -5 - rarity = 10 - -/datum/gas/hydrogen - id = "hydrogen" - specific_heat = 15 - name = "Hydrogen" - dangerous = TRUE - rarity = 700 - -/datum/gas/healium - id = "healium" - specific_heat = 10 - name = "Healium" - dangerous = TRUE - gas_overlay = "healium" - moles_visible = MOLES_GAS_VISIBLE - rarity = 100 - -/datum/gas/pluonium - id = "pluonium" - specific_heat = 30 - name = "Pluonium" - dangerous = TRUE - gas_overlay = "pluonium" - moles_visible = MOLES_GAS_VISIBLE - rarity = 100 - -/datum/gas/halon - id = "halon" - specific_heat = 175 - name = "Halon" - dangerous = TRUE - gas_overlay = "halon" - moles_visible = MOLES_GAS_VISIBLE - rarity = 100 - -/datum/gas/antinoblium - id = "antinoblium" - specific_heat = 1 - name = "Antinoblium" - dangerous = TRUE - gas_overlay = "antinoblium" - moles_visible = MOLES_GAS_VISIBLE - fusion_power = 20 - rarity = 1 - -/datum/gas/zauker - id = "zauker" - specific_heat = 350 - name = "Zauker" - dangerous = TRUE - gas_overlay = "zauker" - moles_visible = MOLES_GAS_VISIBLE - rarity = 1 -/datum/gas/hexane - id = "hexane" - specific_heat = 5 - name = "Hexane" - dangerous = TRUE - gas_overlay = "hexane" - moles_visible = MOLES_GAS_VISIBLE - rarity = 100 - -/obj/effect/overlay/gas - icon = 'icons/effects/atmospherics.dmi' - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - anchored = TRUE // should only appear in vis_contents, but to be safe - layer = FLY_LAYER - appearance_flags = TILE_BOUND - -/obj/effect/overlay/gas/New(state, alph) - . = ..() - icon_state = state - alpha = alph diff --git a/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm b/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm index 2f1a10e2756a..7de056ed0261 100644 --- a/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm +++ b/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm @@ -25,4 +25,4 @@ initial_temperature = T20C /datum/gas_mixture/immutable/cloner/populate() - set_moles(/datum/gas/nitrogen, MOLES_O2STANDARD + MOLES_N2STANDARD) + set_moles(GAS_N2, MOLES_O2STANDARD + MOLES_N2STANDARD) diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index efe099b4b64d..d97e5e504e98 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -1,71 +1,51 @@ //All defines used in reactions are located in ..\__DEFINES\reactions.dm -/*priority so far, check this list to see what are the numbers used. Please use a different priority for each reaction(higher number are done first) -miaster = -10 (this should always be under all other fires) -freonfire = -5 -plasmafire = -4 -h2fire = -3 -tritfire = -2 -halon_o2removal = -1 -nitrous_decomp = 0 -water_vapor = 1 -fusion = 2 -nitrium_formation = 3 -bzformation = 4 -freonformation = 5 -stim_ball = 7 -zauker_decomp = 8 -healium_formation = 9 -pluonium_formation = 10 -zauker_formation = 11 -halon_formation = 12 -hexane_formation = 13 -pluonium_response = 14 - 16 -metalhydrogen = 17 -nobliumsuppression = 1000 -nobliumformation = 1001 -*/ +//priority so far, check this list to see what are the numbers used. +//Please use a different priority for each reaction(higher number are done first) +//or else auxmos will ignore the reaction +//NOTE: ONLY INTEGERS ARE ALLOWED, EXPECT WEIRDNESS IF YOU DON'T FOLLOW THIS +#define MIASTER -10 +#define FREONFIRE -5 +#define PLASMAFIRE -4 +#define H2FIRE -3 +#define TRITFIRE -2 +#define HALONO2REMOVAL -1 +#define NITROUSDECOMP 0 +#define WATERVAPOR 1 +#define FUSION 2 +#define COLDFUSION 3 +#define NITRIUMFORMATION 4 +#define BZFORMATION 5 +#define FREONFORMATION 6 +#define NITROBALL 7 +#define ZAUKERDECOMP 8 +#define HEALIUMFORMATION 9 +#define PLUONIUMFORMATION 10 +#define ZAUKERFORMATION 11 +#define HALONFORMATION 12 +#define HEXANEFORMATION 13 +#define PLUONIUMBZRESPONSE 14 +#define PLUONIUMTRITRESPONSE 15 +#define PLUONIUMH2RESPONSE 16 +#define METALHYDROGEN 17 +#define NOBLIUMSUPPRESSION 1000 +#define NOBLIUMFORMATION 1001 /proc/init_gas_reactions() . = list() - for(var/type in subtypesof(/datum/gas)) - .[type] = list() for(var/r in subtypesof(/datum/gas_reaction)) var/datum/gas_reaction/reaction = r if(initial(reaction.exclude)) continue reaction = new r - var/datum/gas/reaction_key - for (var/req in reaction.min_requirements) - if (ispath(req)) - var/datum/gas/req_gas = req - if (!reaction_key || initial(reaction_key.rarity) > initial(req_gas.rarity)) - reaction_key = req_gas - .[reaction_key] += list(reaction) - sortTim(., /proc/cmp_gas_reactions, TRUE) - -/proc/cmp_gas_reactions(list/datum/gas_reaction/a, list/datum/gas_reaction/b) // compares lists of reactions by the maximum priority contained within the list - if (!length(a) || !length(b)) - return length(b) - length(a) - var/maxa - var/maxb - for (var/datum/gas_reaction/R in a) - if (R.priority > maxa) - maxa = R.priority - for (var/datum/gas_reaction/R in b) - if (R.priority > maxb) - maxb = R.priority - return maxb - maxa - -/proc/cmp_gas_reaction(datum/gas_reaction/a, datum/gas_reaction/b) // compares the priority of two gas reactions - return b.priority - a.priority + . += reaction /datum/gas_reaction //regarding the requirements lists: the minimum or maximum requirements must be non-zero. //when in doubt, use MINIMUM_MOLE_COUNT. var/list/min_requirements var/exclude = FALSE //do it this way to allow for addition/removal of reactions midmatch in the future - var/priority = 100 //lower numbers are checked/react later than higher numbers. if two reactions have the same priority they may happen in either order + var/priority = -1000 //lower numbers are checked/react later than higher numbers. if two reactions have the same priority they may happen in either order var/name = "reaction" var/id = "r" @@ -77,13 +57,23 @@ nobliumformation = 1001 /datum/gas_reaction/proc/react(datum/gas_mixture/air, atom/location) return NO_REACTION +//fires cannot use this proc, because you don't want fires in pipes to proc fire_act on random turfs above the pipe +/proc/get_holder_turf(datum/holder) + var/turf/open/location + if(istype(holder,/datum/pipeline)) //Find the tile the reaction is occuring on, or a random part of the network if it's a pipenet. + var/datum/pipeline/pipenet = holder + location = get_turf(pick(pipenet.members)) + else + location = get_turf(holder) + return location + /datum/gas_reaction/nobliumsuppression - priority = 1000 //ensure all non-HN reactions are lower than this number. + priority = NOBLIUMSUPPRESSION //ensure all non-HN reactions are lower than this number. name = "Hyper-Noblium Reaction Suppression" id = "nobstop" /datum/gas_reaction/nobliumsuppression/init_reqs() - min_requirements = list(/datum/gas/hypernoblium = REACTION_OPPRESSION_THRESHOLD) + min_requirements = list(GAS_HYPERNOB = REACTION_OPPRESSION_THRESHOLD) /datum/gas_reaction/nobliumsuppression/react() return STOP_REACTIONS @@ -95,13 +85,13 @@ nobliumformation = 1001 * Can frost things if the gas is cold enough. */ /datum/gas_reaction/water_vapor - priority = 1 + priority = WATERVAPOR name = "Water Vapor" id = "vapor" /datum/gas_reaction/water_vapor/init_reqs() min_requirements = list( - /datum/gas/water_vapor = MOLES_GAS_VISIBLE, + GAS_H2O = MOLES_GAS_VISIBLE, "MAX_TEMP" = WATER_VAPOR_CONDENSATION_POINT, ) @@ -112,6 +102,7 @@ nobliumformation = 1001 var/turf/open/location = holder var/consumed = 0 + switch(air.return_temperature()) if(-INFINITY to WATER_VAPOR_DEPOSITION_POINT) if(location?.freeze_turf()) @@ -121,25 +112,24 @@ nobliumformation = 1001 consumed = MOLES_GAS_VISIBLE if(consumed) - air.adjust_moles(/datum/gas/water_vapor, -consumed) + air.adjust_moles(GAS_H2O, -consumed) . = REACTING //tritium combustion: combustion of oxygen and tritium (treated as hydrocarbons). creates hotspots. exothermic /datum/gas_reaction/tritfire - priority = -2 //fire should ALWAYS be last, but tritium fires happen before plasma fires + priority = TRITFIRE //fire should ALWAYS be last, but tritium fires happen before plasma fires name = "Tritium Combustion" id = "tritfire" /datum/gas_reaction/tritfire/init_reqs() min_requirements = list( "TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST, - /datum/gas/tritium = MINIMUM_MOLE_COUNT, - /datum/gas/oxygen = MINIMUM_MOLE_COUNT + GAS_TRITIUM = MINIMUM_MOLE_COUNT, + GAS_O2 = MINIMUM_MOLE_COUNT, ) /datum/gas_reaction/tritfire/react(datum/gas_mixture/air, datum/holder) - var/old_heat_capacity = air.heat_capacity() - var/temperature = air.return_temperature() + var/initial_thermal_energy = air.thermal_energy() var/list/cached_results = air.reaction_results cached_results["fire"] = 0 var/turf/open/location = null @@ -150,13 +140,13 @@ nobliumformation = 1001 location = get_turf(pick(combustion_pipenet.members)) else location = get_turf(holder) - var/burned_fuel = min(air.get_moles(/datum/gas/tritium), air.get_moles(/datum/gas/oxygen)) / TRITIUM_BURN_TRIT_FACTOR + var/burned_fuel = min(air.get_moles(GAS_TRITIUM), air.get_moles(GAS_O2)) / TRITIUM_BURN_TRIT_FACTOR if(burned_fuel <= 0) return NO_REACTION - air.adjust_moles(/datum/gas/tritium, -burned_fuel) // Yogs -- Maybe a tiny performance boost? I'unno - air.adjust_moles(/datum/gas/oxygen, -burned_fuel / 2) - air.adjust_moles(/datum/gas/water_vapor, burned_fuel)// Yogs -- Conservation of Mass + air.adjust_moles(GAS_TRITIUM, -burned_fuel) // Yogs -- Maybe a tiny performance boost? I'unno + air.adjust_moles(GAS_O2, -burned_fuel / 2) + air.adjust_moles(GAS_H2O, burned_fuel)// Yogs -- Conservation of Mass var/energy_released = (FIRE_HYDROGEN_ENERGY_RELEASED * burned_fuel * TRITIUM_BURN_TRIT_FACTOR) // Yogs -- Fixes low-energy tritium fires if(location && prob(10) && burned_fuel > TRITIUM_MINIMUM_RADIATION_ENERGY) //woah there let's not crash the server @@ -167,11 +157,11 @@ nobliumformation = 1001 if(energy_released > 0) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature((temperature*old_heat_capacity + energy_released)/new_heat_capacity) + air.set_temperature((initial_thermal_energy + energy_released)/new_heat_capacity) //let the floor know a fire is happening BUT ONLY IF IT'S ACTUALLY A FLOOR if(istype(location) && isturf(holder)) - temperature = air.return_temperature() + var/temperature = air.return_temperature() if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST) location.hotspot_expose(temperature, CELL_VOLUME) for(var/I in location) @@ -183,20 +173,20 @@ nobliumformation = 1001 //plasma combustion: combustion of oxygen and plasma (treated as hydrocarbons). creates hotspots. exothermic /datum/gas_reaction/plasmafire - priority = -4 //fire should ALWAYS be last, but plasma fires happen after tritium fires + priority = PLASMAFIRE //fire should ALWAYS be last, but plasma fires happen after tritium fires name = "Plasma Combustion" id = "plasmafire" /datum/gas_reaction/plasmafire/init_reqs() min_requirements = list( "TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST, - /datum/gas/plasma = MINIMUM_MOLE_COUNT, - /datum/gas/oxygen = MINIMUM_MOLE_COUNT + GAS_PLASMA = MINIMUM_MOLE_COUNT, + GAS_O2 = MINIMUM_MOLE_COUNT ) /datum/gas_reaction/plasmafire/react(datum/gas_mixture/air, datum/holder) var/energy_released = 0 - var/old_heat_capacity = air.heat_capacity() + var/old_thermal_energy = air.thermal_energy() var/temperature = air.return_temperature() var/list/cached_results = air.reaction_results cached_results["fire"] = 0 @@ -210,27 +200,30 @@ nobliumformation = 1001 //to make tritium var/super_saturation = FALSE + var/initial_o2 = air.get_moles(GAS_O2) + var/initial_plas = air.get_moles(GAS_PLASMA) + if(temperature > PLASMA_UPPER_TEMPERATURE) temperature_scale = 1 else temperature_scale = (temperature-PLASMA_MINIMUM_BURN_TEMPERATURE)/(PLASMA_UPPER_TEMPERATURE-PLASMA_MINIMUM_BURN_TEMPERATURE) if(temperature_scale > 0) oxygen_burn_rate = OXYGEN_BURN_RATE_BASE - temperature_scale - if(air.get_moles(/datum/gas/oxygen) / air.get_moles(/datum/gas/plasma) > SUPER_SATURATION_THRESHOLD) //supersaturation. Form Tritium. + if(initial_o2 / initial_plas > SUPER_SATURATION_THRESHOLD) //supersaturation. Form Tritium. super_saturation = TRUE - if(air.get_moles(/datum/gas/oxygen) > air.get_moles(/datum/gas/plasma)*PLASMA_OXYGEN_FULLBURN) - plasma_burn_rate = (air.get_moles(/datum/gas/plasma)*temperature_scale)/PLASMA_BURN_RATE_DELTA + if(initial_o2 > initial_plas * PLASMA_OXYGEN_FULLBURN) + plasma_burn_rate = (initial_plas*temperature_scale)/PLASMA_BURN_RATE_DELTA else - plasma_burn_rate = (temperature_scale*(air.get_moles(/datum/gas/oxygen)/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA + plasma_burn_rate = (temperature_scale*(initial_o2/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY) - plasma_burn_rate = min(plasma_burn_rate,air.get_moles(/datum/gas/plasma),air.get_moles(/datum/gas/oxygen)/oxygen_burn_rate) //Ensures matter is conserved properly - air.set_moles(/datum/gas/plasma, QUANTIZE(air.get_moles(/datum/gas/plasma) - plasma_burn_rate)) - air.set_moles(/datum/gas/oxygen, QUANTIZE(air.get_moles(/datum/gas/oxygen) - (plasma_burn_rate * oxygen_burn_rate))) + plasma_burn_rate = min(plasma_burn_rate,initial_plas,initial_o2/oxygen_burn_rate) //Ensures matter is conserved properly + air.adjust_moles(GAS_PLASMA, -plasma_burn_rate) + air.adjust_moles(GAS_O2, -(plasma_burn_rate * oxygen_burn_rate)) if (super_saturation) - air.adjust_moles(/datum/gas/tritium, plasma_burn_rate) + air.adjust_moles(GAS_TRITIUM, plasma_burn_rate) else - air.adjust_moles(/datum/gas/carbon_dioxide, plasma_burn_rate) + air.adjust_moles(GAS_CO2, plasma_burn_rate) energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate) @@ -239,7 +232,7 @@ nobliumformation = 1001 if(energy_released > 0) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature((temperature*old_heat_capacity + energy_released)/new_heat_capacity) + air.set_temperature((old_thermal_energy + energy_released)/new_heat_capacity) //let the floor know a fire is happening if(istype(location)) @@ -254,26 +247,26 @@ nobliumformation = 1001 return cached_results["fire"] ? REACTING : NO_REACTION /datum/gas_reaction/n2odecomp - priority = 0 + priority = NITROUSDECOMP name = "Nitrous Oxide Decomposition" id = "n2odecomp" /datum/gas_reaction/n2odecomp/init_reqs() min_requirements = list( "TEMP" = N2O_DECOMPOSITION_MIN_HEAT, - /datum/gas/nitrous_oxide = MINIMUM_MOLE_COUNT*2 + GAS_NITROUS = MINIMUM_MOLE_COUNT*2 ) /datum/gas_reaction/n2odecomp/react(datum/gas_mixture/air, datum/holder) var/old_heat_capacity = air.heat_capacity() var/temperature = air.return_temperature() - var/nitrous = air.get_moles(/datum/gas/nitrous_oxide) + var/nitrous = air.get_moles(GAS_NITROUS) var/burned_fuel = min(N2O_DECOMPOSITION_RATE*nitrous*temperature*(temperature-N2O_DECOMPOSITION_MAX_HEAT)/((-1/4)*(N2O_DECOMPOSITION_MAX_HEAT**2)), nitrous) if(burned_fuel>0) - air.set_moles(/datum/gas/nitrous_oxide, QUANTIZE(nitrous - burned_fuel)) - air.set_moles(/datum/gas/nitrogen, QUANTIZE(air.get_moles(/datum/gas/nitrogen) + burned_fuel)) - air.set_moles(/datum/gas/oxygen, QUANTIZE(air.get_moles(/datum/gas/oxygen) + burned_fuel/2)) + air.set_moles(GAS_NITROUS, QUANTIZE(nitrous - burned_fuel)) + air.set_moles(GAS_N2, QUANTIZE(air.get_moles(GAS_N2) + burned_fuel)) + air.set_moles(GAS_O2, QUANTIZE(air.get_moles(GAS_O2) + burned_fuel/2)) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) air.set_temperature((temperature*old_heat_capacity + burned_fuel*N2O_DECOMPOSITION_ENERGY)/new_heat_capacity) @@ -285,46 +278,59 @@ nobliumformation = 1001 //Fusion Rework Counter: Please increment this if you make a major overhaul to this system again. //6 reworks +/datum/gas_reaction/cold_fusion + exclude = FALSE + priority = COLDFUSION + name = "Cold Plasmic Fusion" + id = "coldfusion" + +/datum/gas_reaction/cold_fusion/init_reqs() + min_requirements = list( + "TEMP" = FUSION_TEMPERATURE_THRESHOLD_MINIMUM, + "MAX_TEMP" = FUSION_TEMPERATURE_THRESHOLD, + GAS_DILITHIUM = MINIMUM_MOLE_COUNT, + GAS_TRITIUM = FUSION_TRITIUM_MOLES_USED, + GAS_PLASMA = FUSION_MOLE_THRESHOLD, + GAS_CO2 = FUSION_MOLE_THRESHOLD) + +/datum/gas_reaction/cold_fusion/react(datum/gas_mixture/air, datum/holder) + if(air.return_temperature() < (FUSION_TEMPERATURE_THRESHOLD - FUSION_TEMPERATURE_THRESHOLD_MINIMUM) * NUM_E**( - air.get_moles(GAS_DILITHIUM) * DILITHIUM_LAMBDA) + FUSION_TEMPERATURE_THRESHOLD_MINIMUM) + // This is an exponential decay equation, actually. Horizontal Asymptote is FUSION_TEMPERATURE_THRESHOLD_MINIMUM. + return NO_REACTION + return fusion_react(air, holder, id) + /datum/gas_reaction/fusion exclude = FALSE - priority = 2 + priority = FUSION name = "Plasmic Fusion" id = "fusion" /datum/gas_reaction/fusion/init_reqs() min_requirements = list( - "TEMP" = FUSION_TEMPERATURE_THRESHOLD_MINIMUM, // Yogs -- Cold Fusion - /datum/gas/tritium = FUSION_TRITIUM_MOLES_USED, - /datum/gas/plasma = FUSION_MOLE_THRESHOLD, - /datum/gas/carbon_dioxide = FUSION_MOLE_THRESHOLD) + "TEMP" = FUSION_TEMPERATURE_THRESHOLD, + GAS_TRITIUM = FUSION_TRITIUM_MOLES_USED, + GAS_PLASMA = FUSION_MOLE_THRESHOLD, + GAS_CO2 = FUSION_MOLE_THRESHOLD) /datum/gas_reaction/fusion/react(datum/gas_mixture/air, datum/holder) - //Yogs start -- Cold Fusion - if(air.return_temperature() < FUSION_TEMPERATURE_THRESHOLD) - if(!air.get_moles(/datum/gas/dilithium)) - return - if(air.return_temperature() < (FUSION_TEMPERATURE_THRESHOLD - FUSION_TEMPERATURE_THRESHOLD_MINIMUM) * NUM_E**( - air.get_moles(/datum/gas/dilithium) * DILITHIUM_LAMBDA) + FUSION_TEMPERATURE_THRESHOLD_MINIMUM) - // This is an exponential decay equation, actually. Horizontal Asymptote is FUSION_TEMPERATURE_THRESHOLD_MINIMUM. - return - //Yogs End - var/turf/open/location - if (istype(holder,/datum/pipeline)) //Find the tile the reaction is occuring on, or a random part of the network if it's a pipenet. - var/datum/pipeline/fusion_pipenet = holder - location = get_turf(pick(fusion_pipenet.members)) - else - location = get_turf(holder) + return fusion_react(air, holder, id) + +/proc/fusion_react(datum/gas_mixture/air, datum/holder, id) + var/turf/open/location = get_holder_turf(holder) + if(!location) + return NO_REACTION if(!air.analyzer_results) air.analyzer_results = new var/list/cached_scan_results = air.analyzer_results - var/old_heat_capacity = air.heat_capacity() + var/old_thermal_energy = air.thermal_energy() var/reaction_energy = 0 //Reaction energy can be negative or positive, for both exothermic and endothermic reactions. - var/initial_plasma = air.get_moles(/datum/gas/plasma) - var/initial_carbon = air.get_moles(/datum/gas/carbon_dioxide) + var/initial_plasma = air.get_moles(GAS_PLASMA) + var/initial_carbon = air.get_moles(GAS_CO2) var/scale_factor = (air.return_volume())/(PI) //We scale it down by volume/Pi because for fusion conditions, moles roughly = 2*volume, but we want it to be based off something constant between reactions. var/toroidal_size = (2*PI)+TORADIANS(arctan((air.return_volume()-TOROID_VOLUME_BREAKEVEN)/TOROID_VOLUME_BREAKEVEN)) //The size of the phase space hypertorus var/gas_power = 0 for (var/gas_id in air.get_gases()) - gas_power += (GLOB.meta_gas_info[gas_id][META_GAS_FUSION_POWER]*air.get_moles(gas_id)) + gas_power += (GLOB.gas_data.fusion_powers[gas_id]*air.get_moles(gas_id)) var/instability = MODULUS((gas_power*INSTABILITY_GAS_POWER_FACTOR)**2,toroidal_size) //Instability effects how chaotic the behavior of the reaction is cached_scan_results[id] = instability//used for analyzer feedback @@ -336,9 +342,9 @@ nobliumformation = 1001 carbon = MODULUS(carbon - plasma, toroidal_size) - air.set_moles(/datum/gas/plasma, plasma*scale_factor + FUSION_MOLE_THRESHOLD )//Scales the gases back up - air.set_moles(/datum/gas/carbon_dioxide, carbon*scale_factor + FUSION_MOLE_THRESHOLD) - var/delta_plasma = initial_plasma - air.get_moles(/datum/gas/plasma) + air.set_moles(GAS_PLASMA, plasma*scale_factor + FUSION_MOLE_THRESHOLD )//Scales the gases back up + air.set_moles(GAS_CO2, carbon*scale_factor + FUSION_MOLE_THRESHOLD) + var/delta_plasma = initial_plasma - air.get_moles(GAS_PLASMA) reaction_energy += delta_plasma*PLASMA_BINDING_ENERGY //Energy is gained or lost corresponding to the creation or destruction of mass. if(instability < FUSION_INSTABILITY_ENDOTHERMALITY) @@ -347,17 +353,17 @@ nobliumformation = 1001 reaction_energy *= (instability-FUSION_INSTABILITY_ENDOTHERMALITY)**0.5 if(air.thermal_energy() + reaction_energy < 0) //No using energy that doesn't exist. - air.set_moles(/datum/gas/plasma, initial_plasma) - air.set_moles(/datum/gas/carbon_dioxide, initial_carbon) + air.set_moles(GAS_PLASMA, initial_plasma) + air.set_moles(GAS_CO2, initial_carbon) return NO_REACTION - air.adjust_moles(/datum/gas/tritium, -FUSION_TRITIUM_MOLES_USED) + air.adjust_moles(GAS_TRITIUM, -FUSION_TRITIUM_MOLES_USED) //The decay of the tritium and the reaction's energy produces waste gases, different ones depending on whether the reaction is endo or exothermic if(reaction_energy > 0) - air.adjust_moles(/datum/gas/oxygen, FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT)) - air.adjust_moles(/datum/gas/nitrous_oxide, FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT)) + air.adjust_moles(GAS_O2, FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT)) + air.adjust_moles(GAS_NITROUS, FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT)) else - air.adjust_moles(/datum/gas/bz, FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT)) - air.adjust_moles(/datum/gas/nitrium, FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT)) + air.adjust_moles(GAS_BZ, FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT)) + air.adjust_moles(GAS_NITRIUM, FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT)) if(reaction_energy) if(location) @@ -369,70 +375,77 @@ nobliumformation = 1001 var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(clamp(((air.return_temperature()*old_heat_capacity + reaction_energy)/new_heat_capacity),TCMB,INFINITY)) + air.set_temperature(clamp(((old_thermal_energy + reaction_energy)/new_heat_capacity),TCMB,INFINITY)) return REACTING -/datum/gas_reaction/nitrium_formation //The formation of nitrium. Endothermic. Requires N2O as a catalyst. - priority = 3 +/datum/gas_reaction/nitriumformation //The formation of nitrium. Endothermic. Requires N2O as a catalyst. + priority = NITRIUMFORMATION name = "Nitrium formation" - id = "nitrium_formation" + id = "nitriumformation" -/datum/gas_reaction/nitrium_formation/init_reqs() +/datum/gas_reaction/nitriumformation/init_reqs() min_requirements = list( - /datum/gas/nitrogen = 50, - /datum/gas/plasma = 20, - /datum/gas/bz = 20, - /datum/gas/nitrous_oxide = 5, + GAS_N2 = 50, + GAS_PLASMA = 20, + GAS_BZ = 20, + GAS_NITROUS = 5, "TEMP" = NITRIUM_FORMATION_MIN_TEMP, ) -/datum/gas_reaction/nitrium_formation/react(datum/gas_mixture/air) +/datum/gas_reaction/nitriumformation/react(datum/gas_mixture/air) var/temperature = air.return_temperature() - var/old_heat_capacity = air.heat_capacity() + var/old_thermal_energy = air.thermal_energy() + + var/initial_n2 = air.get_moles(GAS_N2) + var/initial_plasma = air.get_moles(GAS_PLASMA) + var/initial_bz = air.get_moles(GAS_BZ) - var/heat_efficency = min(temperature / NITRIUM_FORMATION_ENERGY, air.get_moles(/datum/gas/nitrogen) / 2, air.get_moles(/datum/gas/plasma), air.get_moles(/datum/gas/bz)) - //Shouldn't produce gas from nothing. - if (heat_efficency <= 0 || (air.get_moles(/datum/gas/nitrogen) - heat_efficency < 0 ) || (air.get_moles(/datum/gas/plasma) - heat_efficency < 0) || (air.get_moles(/datum/gas/bz) - heat_efficency < 0)) + var/heat_efficency = min(temperature / NITRIUM_FORMATION_ENERGY, initial_n2 / 2, initial_plasma, initial_bz) + + // Shouldn't produce gas from nothing. + if (heat_efficency <= 0 || (initial_n2 - heat_efficency < 0 ) || (initial_plasma - heat_efficency < 0) || (initial_bz - heat_efficency < 0)) return NO_REACTION - air.adjust_moles(/datum/gas/nitrogen, -heat_efficency * 2) - air.adjust_moles(/datum/gas/plasma, -heat_efficency) - air.adjust_moles(/datum/gas/bz, -heat_efficency) - air.adjust_moles(/datum/gas/nitrium, heat_efficency / 10) + air.adjust_moles(GAS_N2, -heat_efficency * 2) + air.adjust_moles(GAS_PLASMA, -heat_efficency) + air.adjust_moles(GAS_BZ, -heat_efficency) + air.adjust_moles(GAS_NITRIUM, heat_efficency / 10) var/energy_used = heat_efficency * NITRIUM_FORMATION_ENERGY var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(max(((temperature * old_heat_capacity - energy_used) / new_heat_capacity), TCMB)) + air.set_temperature(max(((old_thermal_energy - energy_used) / new_heat_capacity), TCMB)) return REACTING /datum/gas_reaction/bzformation //Formation of BZ by combining plasma and tritium at low pressures. Exothermic. - priority = 4 + priority = BZFORMATION name = "BZ Gas formation" id = "bzformation" /datum/gas_reaction/bzformation/init_reqs() min_requirements = list( - /datum/gas/nitrous_oxide = 10, - /datum/gas/plasma = 10 + GAS_NITROUS = 10, + GAS_PLASMA = 10, ) - /datum/gas_reaction/bzformation/react(datum/gas_mixture/air) - var/temperature = air.return_temperature() var/pressure = air.return_pressure() - var/old_heat_capacity = air.heat_capacity() - var/reaction_efficency = min(1/((clamp(pressure,1,1000)/(0.5*ONE_ATMOSPHERE))*(max(air.get_moles(/datum/gas/plasma)/air.get_moles(/datum/gas/nitrous_oxide),1))),air.get_moles(/datum/gas/nitrous_oxide),air.get_moles(/datum/gas/plasma)/2) + var/old_thermal_energy = air.thermal_energy() + + var/initial_plas = air.get_moles(GAS_PLASMA) + var/initial_nitrous = air.get_moles(GAS_NITROUS) + + var/reaction_efficency = min(1/((clamp(pressure,1,1000)/(0.5*ONE_ATMOSPHERE))*(max(initial_plas/initial_nitrous,1))),initial_nitrous,initial_plas/2) var/energy_released = 2*reaction_efficency*FIRE_CARBON_ENERGY_RELEASED - if ((air.get_moles(/datum/gas/nitrous_oxide) - reaction_efficency < 0 )|| (air.get_moles(/datum/gas/plasma) - (2*reaction_efficency) < 0) || energy_released <= 0) //Shouldn't produce gas from nothing. + if ((initial_nitrous - reaction_efficency < 0 )|| (initial_plas - (2*reaction_efficency) < 0) || energy_released <= 0) //Shouldn't produce gas from nothing. return NO_REACTION - air.adjust_moles(/datum/gas/bz, reaction_efficency) - if(reaction_efficency == air.get_moles(/datum/gas/nitrous_oxide)) - air.adjust_moles(/datum/gas/bz, -min(pressure,1)) - air.adjust_moles(/datum/gas/oxygen, min(pressure,1)) - air.adjust_moles(/datum/gas/nitrous_oxide, -reaction_efficency) - air.adjust_moles(/datum/gas/plasma, -2*reaction_efficency) + air.adjust_moles(GAS_BZ, reaction_efficency) + if(reaction_efficency == initial_nitrous) + air.adjust_moles(GAS_BZ, -min(pressure,1)) + air.adjust_moles(GAS_O2, min(pressure,1)) + air.adjust_moles(GAS_NITROUS, -reaction_efficency) + air.adjust_moles(GAS_PLASMA, -2*reaction_efficency) //clamps by a minimum amount in the event of an underflow. SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, clamp((reaction_efficency**2)*BZ_RESEARCH_AMOUNT,0.01,BZ_RESEARCH_MAX_AMOUNT)) @@ -440,124 +453,139 @@ nobliumformation = 1001 if(energy_released > 0) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(max(((temperature*old_heat_capacity + energy_released)/new_heat_capacity),TCMB)) + air.set_temperature(max(((old_thermal_energy + energy_released)/new_heat_capacity),TCMB)) return REACTING /datum/gas_reaction/nobliumformation //Hyper-Noblium formation is extrememly endothermic, but requires high temperatures to start. Due to its high mass, hyper-nobelium uses large amounts of nitrogen and tritium. BZ can be used as a catalyst to make it less endothermic. - priority = 1001 //Ensure this value is higher than nobstop + priority = NOBLIUMFORMATION //Ensure this value is higher than nobstop name = "Hyper-Noblium condensation" id = "nobformation" /datum/gas_reaction/nobliumformation/init_reqs() min_requirements = list( - /datum/gas/nitrogen = 20, - /datum/gas/tritium = 10, + GAS_N2 = 20, + GAS_TRITIUM = 10, "TEMP" = 5000000) /datum/gas_reaction/nobliumformation/react(datum/gas_mixture/air) - var/nob_formed = min(max(air.get_moles(/datum/gas/bz), 1) * (log(air.return_temperature())**2), air.get_moles(/datum/gas/tritium)/10, air.get_moles(/datum/gas/nitrogen)/20) - var/old_heat_capacity = air.heat_capacity() - var/energy_taken = nob_formed*(NOBLIUM_FORMATION_ENERGY/(max(air.get_moles(/datum/gas/bz),1))) - air.adjust_moles(/datum/gas/tritium, -10*nob_formed) - air.adjust_moles(/datum/gas/nitrogen, -20*nob_formed) - air.adjust_moles(/datum/gas/hypernoblium, nob_formed) + var/initial_trit = air.get_moles(GAS_TRITIUM) + var/initial_n2 = air.get_moles(GAS_N2) + var/initial_bz = air.get_moles(GAS_BZ) + + var/nob_formed = min(max(initial_bz, 1) * (log(air.return_temperature())**2), initial_trit / 10, initial_n2 / 20) + + var/old_thermal_energy = air.thermal_energy() + + var/energy_taken = nob_formed*(NOBLIUM_FORMATION_ENERGY/(max(initial_bz,1))) + air.adjust_moles(GAS_TRITIUM, -10*nob_formed) + air.adjust_moles(GAS_N2, -20*nob_formed) + air.adjust_moles(GAS_HYPERNOB, nob_formed) SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, clamp(nob_formed*NOBLIUM_RESEARCH_AMOUNT, 0.01, NOBLIUM_RESEARCH_MAX_AMOUNT)) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(max(((air.return_temperature()*old_heat_capacity - energy_taken)/new_heat_capacity),TCMB)) + air.set_temperature(max(((old_thermal_energy - energy_taken)/new_heat_capacity),TCMB)) return REACTING /datum/gas_reaction/miaster //dry heat sterilization: clears out pathogens in the air - priority = -10 //after all the heating from fires etc. is done + priority = MIASTER //after all the heating from fires etc. is done name = "Dry Heat Sterilization" id = "sterilization" /datum/gas_reaction/miaster/init_reqs() min_requirements = list( "TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST+70, - /datum/gas/miasma = MINIMUM_MOLE_COUNT + GAS_MIASMA = MINIMUM_MOLE_COUNT ) /datum/gas_reaction/miaster/react(datum/gas_mixture/air, datum/holder) // As the name says it, it needs to be dry - if(air.get_moles(/datum/gas/water_vapor)/air.total_moles() > 0.1) // Yogs --Fixes runtime in Sterilization + if(air.get_moles(GAS_H2O)/air.total_moles() > 0.1) // Yogs --Fixes runtime in Sterilization return NO_REACT //Replace miasma with oxygen - var/cleaned_air = min(air.get_moles(/datum/gas/miasma), 20 + (air.return_temperature() - FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 70) / 20) - air.adjust_moles(/datum/gas/miasma, -cleaned_air) - air.adjust_moles(/datum/gas/oxygen, cleaned_air) + var/cleaned_air = min(air.get_moles(GAS_MIASMA), 20 + (air.return_temperature() - FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 70) / 20) + air.adjust_moles(GAS_MIASMA, -cleaned_air) + air.adjust_moles(GAS_O2, cleaned_air) //Possibly burning a bit of organic matter through maillard reaction, so a *tiny* bit more heat would be understandable air.set_temperature(air.return_temperature() + cleaned_air * 0.002) SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, clamp(cleaned_air*MIASMA_RESEARCH_AMOUNT,0.01, MIASMA_RESEARCH_MAX_AMOUNT))//Turns out the burning of miasma is kinda interesting to scientists return REACTING - + /datum/gas_reaction/nitro_ball - priority = 7 + priority = NITROBALL name ="Nitrium Energy Ball" - id = "nitro_ball" + id = "nitroball" /datum/gas_reaction/nitro_ball/init_reqs() min_requirements = list( - /datum/gas/pluoxium = NITRO_BALL_MOLES_REQUIRED, - /datum/gas/nitrium = NITRO_BALL_MOLES_REQUIRED, - /datum/gas/plasma = NITRO_BALL_MOLES_REQUIRED, + GAS_PLUOXIUM = NITRO_BALL_MOLES_REQUIRED, + GAS_NITRIUM = NITRO_BALL_MOLES_REQUIRED, + GAS_PLASMA = NITRO_BALL_MOLES_REQUIRED, "TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST ) /// Reaction that burns nitrium and plouxium into radballs and partial constituent gases, but also catalyzes the combustion of plasma. /datum/gas_reaction/nitro_ball/react(datum/gas_mixture/air, datum/holder) - var/turf/location - var/old_heat_capacity = air.heat_capacity() - if(istype(holder,/datum/pipeline)) //Find the tile the reaction is occuring on, or a random part of the network if it's a pipenet. - var/datum/pipeline/pipenet = holder - location = get_turf(pick(pipenet.members)) - else - location = get_turf(holder) - var/reaction_rate = min(NITRO_BALL_MAX_REACT_RATE, air.get_moles(/datum/gas/pluoxium), air.get_moles(/datum/gas/nitrium), air.get_moles(/datum/gas/plasma)) - var/balls_shot = round(reaction_rate/NITRO_BALL_MOLES_REQUIRED) + var/turf/open/location = get_holder_turf(holder) + if(!location) + return NO_REACTION + + var/old_thermal_energy = air.thermal_energy() + + var/initial_pluox = air.get_moles(GAS_PLUOXIUM) + var/initial_nitrium = air.get_moles(GAS_NITRIUM) + var/initial_plas = air.get_moles(GAS_PLASMA) + + var/reaction_rate = min(NITRO_BALL_MAX_REACT_RATE, initial_plas, initial_pluox, initial_nitrium) + var/balls_shot = round(reaction_rate / NITRO_BALL_MOLES_REQUIRED) + //A percentage of plasma is burned during the reaction that is converted into energy and radballs, though mostly pure heat. - var/plasma_burned = QUANTIZE((air.get_moles(/datum/gas/plasma) + 5*reaction_rate)*NITRO_BALL_PLASMA_COEFFICIENT) + var/plasma_burned = QUANTIZE((initial_plas + 5 * reaction_rate) * NITRO_BALL_PLASMA_COEFFICIENT) //Nitrium has a lot of stored energy, and breaking it up releases some of it. Plasma is also partially converted into energy in the process. - var/energy_released = (reaction_rate*NITRO_BALL_HEAT_SCALE) + (plasma_burned*NITRO_BALL_PLASMA_ENERGY) - air.adjust_moles(/datum/gas/nitrium, -reaction_rate) - air.adjust_moles(/datum/gas/pluoxium, -reaction_rate) - air.adjust_moles(/datum/gas/antinoblium, reaction_rate) // an actual purpose for this reaction other than bombs and flamethrowers - air.adjust_moles(/datum/gas/plasma, -plasma_burned) + var/energy_released = (reaction_rate * NITRO_BALL_HEAT_SCALE) + (plasma_burned * NITRO_BALL_PLASMA_ENERGY) + + air.adjust_moles(GAS_PLUOXIUM, -reaction_rate) + air.adjust_moles(GAS_NITRIUM, -reaction_rate) + air.adjust_moles(GAS_ANTINOB, reaction_rate) // an actual purpose for this reaction other than bombs and flamethrowers + air.adjust_moles(GAS_PLASMA, -plasma_burned) + if(balls_shot && !isnull(location)) var/angular_increment = 360/balls_shot var/random_starting_angle = rand(0,360) for(var/i in 1 to balls_shot) - location.fire_nuclear_particle((i*angular_increment+random_starting_angle)) + location.fire_nuclear_particle((i * angular_increment + random_starting_angle)) + if(energy_released) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(clamp((air.return_temperature()*old_heat_capacity + energy_released)/new_heat_capacity, TCMB, INFINITY)) + air.set_temperature(clamp((old_thermal_energy + energy_released) / new_heat_capacity, TCMB, INFINITY)) return REACTING //freon reaction (is not a fire yet) /datum/gas_reaction/freonfire - priority = -5 + priority = FREONFIRE name = "Freon combustion" id = "freonfire" /datum/gas_reaction/freonfire/init_reqs() min_requirements = list( - /datum/gas/oxygen = MINIMUM_MOLE_COUNT, - /datum/gas/freon = MINIMUM_MOLE_COUNT, + GAS_O2 = MINIMUM_MOLE_COUNT, + GAS_FREON = MINIMUM_MOLE_COUNT, "TEMP" = FREON_LOWER_TEMPERATURE, "MAX_TEMP" = FREON_MAXIMUM_BURN_TEMPERATURE ) /datum/gas_reaction/freonfire/react(datum/gas_mixture/air, datum/holder) - var/energy_released = 0 - var/old_heat_capacity = air.heat_capacity() - var/temperature = air.return_temperature() - if(!isturf(holder)) + if(!isopenturf(holder)) return NO_REACTION var/turf/open/location = holder + var/energy_released = 0 + var/old_thermal_energy = air.thermal_energy() + var/temperature = air.return_temperature() + var/initial_o2 = air.get_moles(GAS_O2) + var/initial_freon = air.get_moles(GAS_FREON) //Handle freon burning (only reaction now) var/freon_burn_rate = 0 @@ -571,16 +599,16 @@ nobliumformation = 1001 temperature_scale = (FREON_MAXIMUM_BURN_TEMPERATURE - temperature) / (FREON_MAXIMUM_BURN_TEMPERATURE - FREON_LOWER_TEMPERATURE) //calculate the scale based on the temperature if(temperature_scale >= 0) oxygen_burn_rate = OXYGEN_BURN_RATE_BASE - temperature_scale - if(air.get_moles(/datum/gas/oxygen) > air.get_moles(/datum/gas/freon) * FREON_OXYGEN_FULLBURN) - freon_burn_rate = (air.get_moles(/datum/gas/freon) * temperature_scale) / FREON_BURN_RATE_DELTA + if(initial_o2 > initial_freon * FREON_OXYGEN_FULLBURN) + freon_burn_rate = (initial_freon * temperature_scale) / FREON_BURN_RATE_DELTA else - freon_burn_rate = (temperature_scale * (air.get_moles(/datum/gas/oxygen) / FREON_OXYGEN_FULLBURN)) / FREON_BURN_RATE_DELTA + freon_burn_rate = (temperature_scale * (initial_o2 / FREON_OXYGEN_FULLBURN)) / FREON_BURN_RATE_DELTA if(freon_burn_rate > MINIMUM_HEAT_CAPACITY) - freon_burn_rate = min(freon_burn_rate, air.get_moles(/datum/gas/freon), air.get_moles(/datum/gas/oxygen) / oxygen_burn_rate) //Ensures matter is conserved properly - air.adjust_moles(/datum/gas/freon, -freon_burn_rate) - air.adjust_moles(/datum/gas/oxygen, -(freon_burn_rate * oxygen_burn_rate)) - air.adjust_moles(/datum/gas/carbon_dioxide, freon_burn_rate) + freon_burn_rate = min(freon_burn_rate, initial_freon, initial_o2 / oxygen_burn_rate) //Ensures matter is conserved properly + air.adjust_moles(GAS_FREON, -freon_burn_rate) + air.adjust_moles(GAS_O2, -(freon_burn_rate * oxygen_burn_rate)) + air.adjust_moles(GAS_CO2, freon_burn_rate) if(temperature < 160 && temperature > 120 && prob(2)) new /obj/item/stack/sheet/hot_ice(location) @@ -590,34 +618,34 @@ nobliumformation = 1001 if(energy_released < 0) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature((temperature * old_heat_capacity + energy_released) / new_heat_capacity) + air.set_temperature((old_thermal_energy + energy_released) / new_heat_capacity) /datum/gas_reaction/h2fire - priority = -3 //fire should ALWAYS be last, but tritium fires happen before plasma fires + priority = H2FIRE //fire should ALWAYS be last, but tritium fires happen before plasma fires name = "Hydrogen Combustion" id = "h2fire" /datum/gas_reaction/h2fire/init_reqs() min_requirements = list( "TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST, - /datum/gas/hydrogen = MINIMUM_MOLE_COUNT, - /datum/gas/oxygen = MINIMUM_MOLE_COUNT + GAS_H2 = MINIMUM_MOLE_COUNT, + GAS_O2 = MINIMUM_MOLE_COUNT ) /datum/gas_reaction/h2fire/react(datum/gas_mixture/air, datum/holder) - var/old_heat_capacity = air.heat_capacity() - //this speeds things up because accessing datum vars is slow + var/old_thermal_energy = air.thermal_energy() + //this speeds things up because accessing datum vars is slow var/temperature = air.return_temperature() var/list/cached_results = air.reaction_results cached_results["fire"] = 0 var/turf/open/location = isturf(holder) ? holder : null - var/burned_fuel = min(air.get_moles(/datum/gas/hydrogen), air.get_moles(/datum/gas/oxygen)) / HYDROGEN_BURN_H2_FACTOR + var/burned_fuel = min(air.get_moles(GAS_H2), air.get_moles(GAS_O2)) / HYDROGEN_BURN_H2_FACTOR if(burned_fuel <= 0) return NO_REACTION - air.adjust_moles(/datum/gas/hydrogen, -burned_fuel) // Yogs - see trit burn - air.adjust_moles(/datum/gas/oxygen, -burned_fuel / 2) - air.adjust_moles(/datum/gas/water_vapor, burned_fuel) + air.adjust_moles(GAS_H2, -burned_fuel) // Yogs - see trit burn + air.adjust_moles(GAS_O2, -burned_fuel / 2) + air.adjust_moles(GAS_H2O, burned_fuel) var/energy_released = (FIRE_HYDROGEN_ENERGY_RELEASED * burned_fuel * HYDROGEN_BURN_H2_FACTOR) // Yogs -- burns twice as fast with half the energy cached_results["fire"] += burned_fuel @@ -625,7 +653,7 @@ nobliumformation = 1001 if(energy_released > 0) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature((temperature*old_heat_capacity + energy_released) / new_heat_capacity) + air.set_temperature((old_thermal_energy + energy_released) / new_heat_capacity) //let the floor know a fire is happening if(istype(location)) @@ -641,284 +669,299 @@ nobliumformation = 1001 /datum/gas_reaction/hexane_formation - priority = 13 + priority = HEXANEFORMATION name = "Hexane formation" id = "hexane_formation" /datum/gas_reaction/hexane_formation/init_reqs() min_requirements = list( - /datum/gas/bz = MINIMUM_MOLE_COUNT, - /datum/gas/hydrogen = MINIMUM_MOLE_COUNT, + GAS_BZ = MINIMUM_MOLE_COUNT, + GAS_H2 = MINIMUM_MOLE_COUNT, "TEMP" = 450, "MAX_TEMP" = 465 ) /datum/gas_reaction/hexane_formation/react(datum/gas_mixture/air, datum/holder) var/temperature = air.return_temperature() - var/old_heat_capacity = air.heat_capacity() - var/heat_efficency = min(temperature * 0.01, air.get_moles(/datum/gas/hydrogen), air.get_moles(/datum/gas/bz)) + var/old_thermal_energy = air.thermal_energy() + var/initial_h2 = air.get_moles(GAS_H2) + var/initial_bz = air.get_moles(GAS_BZ) + var/heat_efficency = min(temperature * 0.01, initial_h2, initial_bz) var/energy_used = heat_efficency * 600 - if (air.get_moles(/datum/gas/hydrogen) - (heat_efficency * 5) < 0 || air.get_moles(/datum/gas/bz) - (heat_efficency * 0.25) < 0) //Shouldn't produce gas from nothing. + if (initial_h2 - (heat_efficency * 5) < 0 || initial_bz - (heat_efficency * 0.25) < 0) //Shouldn't produce gas from nothing. return NO_REACTION - air.adjust_moles(/datum/gas/hydrogen, -(heat_efficency * 5)) - air.adjust_moles(/datum/gas/bz, -(heat_efficency * 0.25)) - air.adjust_moles(/datum/gas/hexane, (heat_efficency * 5.25)) + air.adjust_moles(GAS_H2, -(heat_efficency * 5)) + air.adjust_moles(GAS_BZ, -(heat_efficency * 0.25)) + air.adjust_moles(GAS_HEXANE, (heat_efficency * 5.25)) if(energy_used) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(max(((temperature * old_heat_capacity - energy_used) / new_heat_capacity), TCMB)) + air.set_temperature(max(((old_thermal_energy - energy_used) / new_heat_capacity), TCMB)) return REACTING /datum/gas_reaction/metalhydrogen - priority = 17 + priority = METALHYDROGEN name = "Metal Hydrogen formation" id = "metalhydrogen" /datum/gas_reaction/metalhydrogen/init_reqs() min_requirements = list( - /datum/gas/hydrogen = 300, //same crystallizer recipe - /datum/gas/bz = 50, + GAS_H2 = 300, + GAS_BZ = 50, "TEMP" = METAL_HYDROGEN_MINIMUM_HEAT ) /datum/gas_reaction/metalhydrogen/react(datum/gas_mixture/air, datum/holder) - var/temperature = air.return_temperature() - var/old_heat_capacity = air.heat_capacity() - if(!isturf(holder)) + if(!isopenturf(holder)) return NO_REACTION var/turf/open/location = holder + var/temperature = air.return_temperature() + var/old_thermal_energy = air.thermal_energy() ///the more heat you use the higher is this factor var/increase_factor = min(log(10 , (temperature / METAL_HYDROGEN_MINIMUM_HEAT)), 5) //e7-e12 range ///the more moles you use and the higher the heat, the higher is the efficiency - var/heat_efficency = air.get_moles(/datum/gas/hydrogen)* 0.01 * increase_factor //This variable name is dumb but I can't be assed to change it + var/heat_efficency = air.get_moles(GAS_H2)* 0.01 * increase_factor //This variable name is dumb but I can't be assed to change it var/pressure = air.return_pressure() var/energy_used = heat_efficency * METAL_HYDROGEN_FORMATION_ENERGY if(pressure >= METAL_HYDROGEN_MINIMUM_PRESSURE && temperature >= METAL_HYDROGEN_MINIMUM_HEAT) - air.adjust_moles(/datum/gas/bz, -(heat_efficency)) //About 70% the amount of BZ requirement consumed + air.adjust_moles(GAS_BZ, -(heat_efficency)) if (prob(25 * increase_factor)) - air.adjust_moles(/datum/gas/hydrogen, -(heat_efficency * 10)) //Still consume about 70% of the hydrogen present + air.adjust_moles(GAS_H2, -(heat_efficency * 10)) new /obj/item/stack/sheet/mineral/metal_hydrogen(location) SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, min((heat_efficency * increase_factor * 0.5), METAL_HYDROGEN_RESEARCH_MAX_AMOUNT)) if(energy_used > 0) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(max(((temperature * old_heat_capacity - energy_used) / new_heat_capacity), TCMB)) + air.set_temperature(max(((old_thermal_energy - energy_used) / new_heat_capacity), TCMB)) return REACTING /datum/gas_reaction/freonformation - priority = 5 + priority = FREONFORMATION name = "Freon formation" id = "freonformation" /datum/gas_reaction/freonformation/init_reqs() //minimum requirements for freon formation min_requirements = list( - /datum/gas/plasma = 40, - /datum/gas/carbon_dioxide = 20, - /datum/gas/bz = 20, + GAS_PLASMA = 40, + GAS_CO2 = 20, + GAS_BZ = 20, "TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST + 100 ) /datum/gas_reaction/freonformation/react(datum/gas_mixture/air) var/temperature = air.return_temperature() - var/old_heat_capacity = air.heat_capacity() - var/heat_efficency = min(temperature / (FIRE_MINIMUM_TEMPERATURE_TO_EXIST * 10), air.get_moles(/datum/gas/plasma), air.get_moles(/datum/gas/carbon_dioxide), air.get_moles(/datum/gas/bz)) + var/old_thermal_energy = air.thermal_energy() + var/initial_plas = air.get_moles(GAS_PLASMA) + var/initial_co2 = air.get_moles(GAS_CO2) + var/initial_bz = air.get_moles(GAS_BZ) + var/heat_efficency = min(temperature / (FIRE_MINIMUM_TEMPERATURE_TO_EXIST * 10), initial_plas, initial_co2, initial_bz) var/energy_used = heat_efficency * 100 - if ((air.get_moles(/datum/gas/plasma) - heat_efficency * 1.5 < 0 ) || (air.get_moles(/datum/gas/carbon_dioxide) - heat_efficency * 0.75 < 0) || (air.get_moles(/datum/gas/bz) - heat_efficency * 0.25 < 0)) //Shouldn't produce gas from nothing. + if ((initial_plas - heat_efficency * 1.5 < 0 ) || (initial_co2 - heat_efficency * 0.75 < 0) || (initial_bz - heat_efficency * 0.25 < 0)) //Shouldn't produce gas from nothing. return NO_REACTION - air.adjust_moles(/datum/gas/plasma, -(heat_efficency * 1.5)) - air.adjust_moles(/datum/gas/carbon_dioxide, -(heat_efficency * 0.75)) - air.adjust_moles(/datum/gas/bz, -(heat_efficency * 0.25)) - air.adjust_moles(/datum/gas/freon, (heat_efficency * 2.5)) + air.adjust_moles(GAS_PLASMA, -(heat_efficency * 1.5)) + air.adjust_moles(GAS_CO2, -(heat_efficency * 0.75)) + air.adjust_moles(GAS_BZ, -(heat_efficency * 0.25)) + air.adjust_moles(GAS_FREON, (heat_efficency * 2.5)) if(energy_used > 0) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(max(((temperature * old_heat_capacity - energy_used)/new_heat_capacity), TCMB)) + air.set_temperature(max(((old_thermal_energy - energy_used)/new_heat_capacity), TCMB)) return REACTING - /datum/gas_reaction/halon_formation - priority = 12 + priority = HALONFORMATION name = "Halon formation" id = "halon_formation" /datum/gas_reaction/halon_formation/init_reqs() min_requirements = list( - /datum/gas/bz = MINIMUM_MOLE_COUNT, - /datum/gas/tritium = MINIMUM_MOLE_COUNT, + GAS_BZ = MINIMUM_MOLE_COUNT, + GAS_TRITIUM = MINIMUM_MOLE_COUNT, "TEMP" = 30, "MAX_TEMP" = 55 ) /datum/gas_reaction/halon_formation/react(datum/gas_mixture/air, datum/holder) var/temperature = air.return_temperature() - var/old_heat_capacity = air.heat_capacity() - var/heat_efficency = min(temperature * 0.01, air.get_moles(/datum/gas/tritium), air.get_moles(/datum/gas/bz)) + var/old_thermal_energy = air.thermal_energy() + var/initial_bz = air.get_moles(GAS_BZ) + var/initial_trit = air.get_moles(GAS_TRITIUM) + var/heat_efficency = min(temperature * 0.01, initial_trit, initial_bz) var/energy_used = heat_efficency * 300 - if ((air.get_moles(/datum/gas/tritium) - heat_efficency * 4 < 0 ) || (air.get_moles(/datum/gas/bz) - heat_efficency * 0.25 < 0)) //Shouldn't produce gas from nothing. + if ((initial_trit - heat_efficency * 4 < 0 ) || (initial_bz - heat_efficency * 0.25 < 0)) //Shouldn't produce gas from nothing. return NO_REACTION - air.adjust_moles(/datum/gas/tritium, -(heat_efficency * 4)) - air.adjust_moles(/datum/gas/bz, -(heat_efficency * 0.25)) - air.adjust_moles(/datum/gas/halon, (heat_efficency * 4.25)) + air.adjust_moles(GAS_TRITIUM, -(heat_efficency * 4)) + air.adjust_moles(GAS_BZ, -(heat_efficency * 0.25)) + air.adjust_moles(GAS_HALON, (heat_efficency * 4.25)) if(energy_used) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(max(((temperature * old_heat_capacity + energy_used) / new_heat_capacity), TCMB)) + air.set_temperature(max(((old_thermal_energy + energy_used) / new_heat_capacity), TCMB)) return REACTING /datum/gas_reaction/healium_formation - priority = 9 + priority = HEALIUMFORMATION name = "Healium formation" id = "healium_formation" /datum/gas_reaction/healium_formation/init_reqs() min_requirements = list( - /datum/gas/bz = MINIMUM_MOLE_COUNT, - /datum/gas/freon = MINIMUM_MOLE_COUNT, + GAS_BZ = MINIMUM_MOLE_COUNT, + GAS_FREON = MINIMUM_MOLE_COUNT, "TEMP" = 25, "MAX_TEMP" = 300 ) /datum/gas_reaction/healium_formation/react(datum/gas_mixture/air, datum/holder) var/temperature = air.return_temperature() - var/old_heat_capacity = air.heat_capacity() - var/heat_efficency = min(temperature * 0.3, air.get_moles(/datum/gas/freon), air.get_moles(/datum/gas/bz)) + var/old_thermal_energy = air.thermal_energy() + var/initial_freon = air.get_moles(GAS_FREON) + var/initial_bz = air.get_moles(GAS_BZ) + var/heat_efficency = min(temperature * 0.3, initial_freon, initial_bz) var/energy_used = heat_efficency * 9000 - if ((air.get_moles(/datum/gas/freon) - heat_efficency * 2.75 < 0 ) || (air.get_moles(/datum/gas/bz) - heat_efficency * 0.25 < 0)) //Shouldn't produce gas from nothing. + if ((initial_freon - heat_efficency * 2.75 < 0 ) || (initial_bz - heat_efficency * 0.25 < 0)) //Shouldn't produce gas from nothing. return NO_REACTION - air.adjust_moles(/datum/gas/freon, -(heat_efficency * 2.75)) - air.adjust_moles(/datum/gas/bz, -(heat_efficency * 0.25)) - air.adjust_moles(/datum/gas/healium, (heat_efficency * 3)) + air.adjust_moles(GAS_FREON, -(heat_efficency * 2.75)) + air.adjust_moles(GAS_BZ, -(heat_efficency * 0.25)) + air.adjust_moles(GAS_HEALIUM, (heat_efficency * 3)) if(energy_used) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(max(((temperature * old_heat_capacity + energy_used) / new_heat_capacity), TCMB)) + air.set_temperature(max(((old_thermal_energy + energy_used) / new_heat_capacity), TCMB)) return REACTING /datum/gas_reaction/pluonium_formation - priority = 10 + priority = PLUONIUMFORMATION name = "Pluonium formation" id = "pluonium_formation" /datum/gas_reaction/pluonium_formation/init_reqs() min_requirements = list( - /datum/gas/pluoxium = MINIMUM_MOLE_COUNT, - /datum/gas/hydrogen = MINIMUM_MOLE_COUNT, + GAS_PLUOXIUM = MINIMUM_MOLE_COUNT, + GAS_H2 = MINIMUM_MOLE_COUNT, "TEMP" = 5000, "MAX_TEMP" = 10000 ) /datum/gas_reaction/pluonium_formation/react(datum/gas_mixture/air, datum/holder) var/temperature = air.return_temperature() - var/old_heat_capacity = air.heat_capacity() - var/heat_efficency = min(temperature * 0.005, air.get_moles(/datum/gas/pluoxium), air.get_moles(/datum/gas/hydrogen)) + var/old_thermal_energy = air.thermal_energy() + var/initial_pluox = air.get_moles(GAS_PLUOXIUM) + var/initial_h2 = air.get_moles(GAS_H2) + var/heat_efficency = min(temperature * 0.005, initial_pluox, initial_h2) var/energy_used = heat_efficency * 650 - if ((air.get_moles(/datum/gas/pluoxium) - heat_efficency * 0.2 < 0 ) || (air.get_moles(/datum/gas/hydrogen) - heat_efficency * 2 < 0)) //Shouldn't produce gas from nothing. + if ((initial_pluox - heat_efficency * 0.2 < 0 ) || (initial_h2 - heat_efficency * 2 < 0)) //Shouldn't produce gas from nothing. return NO_REACTION - air.adjust_moles(/datum/gas/hydrogen, -(heat_efficency * 2)) - air.adjust_moles(/datum/gas/pluoxium, -(heat_efficency * 0.2)) - air.adjust_moles(/datum/gas/pluonium, (heat_efficency * 2.2)) + air.adjust_moles(GAS_H2, -(heat_efficency * 2)) + air.adjust_moles(GAS_PLUOXIUM, -(heat_efficency * 0.2)) + air.adjust_moles(GAS_PLUONIUM, (heat_efficency * 2.2)) if(energy_used > 0) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(max(((temperature * old_heat_capacity + energy_used) / new_heat_capacity), TCMB)) + air.set_temperature(max(((old_thermal_energy + energy_used) / new_heat_capacity), TCMB)) return REACTING /datum/gas_reaction/zauker_formation - priority = 11 + priority = ZAUKERFORMATION name = "Zauker formation" id = "zauker_formation" /datum/gas_reaction/zauker_formation/init_reqs() min_requirements = list( - /datum/gas/hypernoblium = MINIMUM_MOLE_COUNT, - /datum/gas/nitrium = MINIMUM_MOLE_COUNT, + GAS_HYPERNOB = MINIMUM_MOLE_COUNT, + GAS_NITRIUM = MINIMUM_MOLE_COUNT, "TEMP" = 50000, "MAX_TEMP" = 75000 ) /datum/gas_reaction/zauker_formation/react(datum/gas_mixture/air, datum/holder) var/temperature = air.return_temperature() - var/old_heat_capacity = air.heat_capacity() - var/heat_efficency = min(temperature * 0.000005, air.get_moles(/datum/gas/hypernoblium), air.get_moles(/datum/gas/nitrium)) + var/old_thermal_energy = air.thermal_energy() + + var/initial_nob = air.get_moles(GAS_HYPERNOB) + var/initial_nitrium = air.get_moles(GAS_NITRIUM) + + var/heat_efficency = min(temperature * 0.000005, initial_nob, initial_nitrium) var/energy_used = heat_efficency * 5000 - if ((air.get_moles(/datum/gas/hypernoblium) - heat_efficency * 0.01 < 0 ) || (air.get_moles(/datum/gas/nitrium) - heat_efficency * 0.5 < 0)) //Shouldn't produce gas from nothing. + if ((initial_nob - heat_efficency * 0.01 < 0 ) || (initial_nitrium - heat_efficency * 0.5 < 0)) //Shouldn't produce gas from nothing. return NO_REACTION - air.adjust_moles(/datum/gas/hypernoblium, -(heat_efficency * 0.01)) - air.adjust_moles(/datum/gas/nitrium, -(heat_efficency * 0.5)) - air.adjust_moles(/datum/gas/zauker, (heat_efficency * 0.5)) + + air.adjust_moles(GAS_HYPERNOB, -(heat_efficency * 0.01)) + air.adjust_moles(GAS_NITRIUM, -(heat_efficency * 0.5)) + air.adjust_moles(GAS_ZAUKER, (heat_efficency * 0.5)) if(energy_used) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(max(((temperature * old_heat_capacity - energy_used) / new_heat_capacity), TCMB)) + air.set_temperature(max(((old_thermal_energy - energy_used) / new_heat_capacity), TCMB)) return REACTING /datum/gas_reaction/halon_o2removal - priority = -1 + priority = HALONO2REMOVAL name = "Halon o2 removal" id = "halon_o2removal" /datum/gas_reaction/halon_o2removal/init_reqs() min_requirements = list( - /datum/gas/halon = MINIMUM_MOLE_COUNT, - /datum/gas/oxygen = MINIMUM_MOLE_COUNT, + GAS_HALON = MINIMUM_MOLE_COUNT, + GAS_O2 = MINIMUM_MOLE_COUNT, "TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST ) /datum/gas_reaction/halon_o2removal/react(datum/gas_mixture/air, datum/holder) var/temperature = air.return_temperature() - var/old_heat_capacity = air.heat_capacity() - var/heat_efficency = min(temperature / ( FIRE_MINIMUM_TEMPERATURE_TO_EXIST * 10), air.get_moles(/datum/gas/halon), air.get_moles(/datum/gas/oxygen)) + var/old_thermal_energy = air.thermal_energy() + var/initial_o2 = air.get_moles(GAS_O2) + var/initial_halon = air.get_moles(GAS_HALON) + var/heat_efficency = min(temperature / ( FIRE_MINIMUM_TEMPERATURE_TO_EXIST * 10), initial_halon, initial_o2) var/energy_used = heat_efficency * 2500 - if ((air.get_moles(/datum/gas/halon) - heat_efficency < 0 ) || (air.get_moles(/datum/gas/oxygen) - heat_efficency * 20 < 0)) //Shouldn't produce gas from nothing. + if ((initial_halon - heat_efficency < 0 ) || (initial_o2 - heat_efficency * 20 < 0)) //Shouldn't produce gas from nothing. return NO_REACTION - air.adjust_moles(/datum/gas/halon, -(heat_efficency)) - air.adjust_moles(/datum/gas/oxygen, -(heat_efficency * 20)) - air.adjust_moles(/datum/gas/carbon_dioxide, (heat_efficency * 5)) + air.adjust_moles(GAS_HALON, -(heat_efficency)) + air.adjust_moles(GAS_O2, -(heat_efficency * 20)) + air.adjust_moles(GAS_CO2, (heat_efficency * 5)) if(energy_used) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(max(((temperature * old_heat_capacity - energy_used) / new_heat_capacity), TCMB)) + air.set_temperature(max(((old_thermal_energy - energy_used) / new_heat_capacity), TCMB)) return REACTING /datum/gas_reaction/zauker_decomp - priority = 8 + priority = ZAUKERDECOMP name = "Zauker decomposition" id = "zauker_decomp" /datum/gas_reaction/zauker_decomp/init_reqs() min_requirements = list( - /datum/gas/nitrogen = MINIMUM_MOLE_COUNT, - /datum/gas/zauker = MINIMUM_MOLE_COUNT + GAS_N2 = MINIMUM_MOLE_COUNT, + GAS_ZAUKER = MINIMUM_MOLE_COUNT, ) /datum/gas_reaction/zauker_decomp/react(datum/gas_mixture/air, datum/holder) var/energy_released = 0 - var/old_heat_capacity = air.heat_capacity() - //this speeds things up because accessing datum vars is slow - var/temperature = air.return_temperature() - var/burned_fuel = 0 - burned_fuel = min(20, air.get_moles(/datum/gas/nitrogen), air.get_moles(/datum/gas/zauker)) - if(air.get_moles(/datum/gas/zauker) - burned_fuel < 0) + var/old_thermal_energy = air.thermal_energy() + var/initial_zauker = air.get_moles(GAS_ZAUKER) + var/burned_fuel = min(20, air.get_moles(GAS_N2), initial_zauker) + if(initial_zauker - burned_fuel < 0) return NO_REACTION - air.adjust_moles(/datum/gas/zauker, -burned_fuel) + air.adjust_moles(GAS_ZAUKER, -burned_fuel) if(burned_fuel) energy_released += (460 * burned_fuel) - air.adjust_moles(/datum/gas/oxygen, (burned_fuel * 0.3)) - air.adjust_moles(/datum/gas/nitrogen, (burned_fuel * 0.7)) + air.adjust_moles(GAS_O2, (burned_fuel * 0.3)) + air.adjust_moles(GAS_N2, (burned_fuel * 0.7)) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(max((temperature * old_heat_capacity + energy_released) / new_heat_capacity, TCMB)) + air.set_temperature(max((old_thermal_energy + energy_released) / new_heat_capacity, TCMB)) return REACTING return NO_REACTION @@ -928,105 +971,132 @@ nobliumformation = 1001 * Breaks BZ down into nitrogen and plasma in the presence of pluonium. */ /datum/gas_reaction/pluonium_bz_response - priority = 14 + priority = PLUONIUMBZRESPONSE name = "Pluonium bz response" id = "pluonium_bz_response" /datum/gas_reaction/pluonium_bz_response/init_reqs() min_requirements = list( - /datum/gas/pluonium = MINIMUM_MOLE_COUNT, - /datum/gas/bz = MINIMUM_MOLE_COUNT, + GAS_PLUONIUM = MINIMUM_MOLE_COUNT, + GAS_BZ = MINIMUM_MOLE_COUNT, "TEMP" = 260, "MAX_TEMP" = 280 ) /datum/gas_reaction/pluonium_bz_response/react(datum/gas_mixture/air, datum/holder) var/old_temperature = air.return_temperature() - var/consumed_amount = min(old_temperature / 2240 * air.get_moles(/datum/gas/bz) * air.get_moles(/datum/gas/pluonium) / (air.get_moles(/datum/gas/bz) + air.get_moles(/datum/gas/pluonium)), air.get_moles(/datum/gas/bz), air.get_moles(/datum/gas/pluonium)) - if (consumed_amount <= 0 || air.get_moles(/datum/gas/bz) - consumed_amount < 0) + var/old_thermal_energy = air.thermal_energy() + + var/initial_bz = air.get_moles(GAS_BZ) + var/initial_pluon = air.get_moles(GAS_PLUONIUM) + + var/consumed_amount = min(old_temperature / 2240 * initial_bz * initial_pluon / (initial_bz + initial_pluon), initial_bz, initial_pluon) + if(consumed_amount <= 0 || initial_bz - consumed_amount < 0) return NO_REACTION - var/old_heat_capacity = air.heat_capacity() - air.adjust_moles(/datum/gas/bz, -consumed_amount) - air.adjust_moles(/datum/gas/nitrogen, consumed_amount * 0.5) - air.adjust_moles(/datum/gas/plasma, consumed_amount * 1) - - var/turf/open/location - if(istype(holder, /datum/pipeline)) //Find the tile the reaction is occuring on, or a random part of the network if it's a pipenet. - var/datum/pipeline/pipenet = holder - location = get_turf(pick(pipenet.members)) - else - location = get_turf(holder) + air.adjust_moles(GAS_BZ, -consumed_amount) + air.adjust_moles(GAS_N2, consumed_amount * 0.5) + air.adjust_moles(GAS_PLASMA, consumed_amount * 1) var/energy_released = consumed_amount * 2 - + + var/turf/open/location = get_holder_turf(holder) if (location) radiation_pulse(location, consumed_amount * 2, 2.5, TRUE, FALSE) for(var/mob/living/carbon/L in location) - L.adjust_hallucinations(air.get_moles(/datum/gas/bz) * 0.7) // Yogs -- fixed accidental "path * number" + L.adjust_hallucinations(air.get_moles(GAS_BZ) * 0.7) // Yogs -- fixed accidental "path * number" energy_released += 100 if(energy_released) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(max((old_temperature * old_heat_capacity + energy_released) / new_heat_capacity, TCMB)) + air.set_temperature(max((old_thermal_energy + energy_released) / new_heat_capacity, TCMB)) return REACTING /datum/gas_reaction/pluonium_tritium_response - priority = 15 + priority = PLUONIUMTRITRESPONSE name = "Pluonium tritium response" id = "pluonium_tritium_response" /datum/gas_reaction/pluonium_tritium_response/init_reqs() min_requirements = list( - /datum/gas/pluonium = MINIMUM_MOLE_COUNT, - /datum/gas/tritium = MINIMUM_MOLE_COUNT, + GAS_PLUONIUM = MINIMUM_MOLE_COUNT, + GAS_TRITIUM = MINIMUM_MOLE_COUNT, "TEMP" = 150, "MAX_TEMP" = 340 ) /datum/gas_reaction/pluonium_tritium_response/react(datum/gas_mixture/air, datum/holder) var/energy_released = 0 - var/old_heat_capacity = air.heat_capacity() - var/temperature = air.return_temperature() - var/turf/open/location = isturf(holder) ? holder : null - var produced_amount = min(5, air.get_moles(/datum/gas/tritium), air.get_moles(/datum/gas/pluonium)) - if(air.get_moles(/datum/gas/tritium) - produced_amount < 0 || air.get_moles(/datum/gas/pluonium) - produced_amount * 0.01 < 0) + var/old_thermal_energy = air.thermal_energy() + var/initial_pluon = air.get_moles(GAS_PLUONIUM) + var/initial_trit = air.get_moles(GAS_TRITIUM) + var/produced_amount = min(5, initial_trit, initial_pluon) + if(initial_trit - produced_amount < 0 || initial_pluon - produced_amount * 0.01 < 0) return NO_REACTION - location.rad_act(produced_amount * 2.4) - air.adjust_moles(/datum/gas/tritium, -produced_amount) - air.adjust_moles(/datum/gas/hydrogen, produced_amount) - air.adjust_moles(/datum/gas/pluonium, -(produced_amount * 0.01)) + if(isopenturf(holder)) + var/turf/open/location = holder + location.rad_act(produced_amount * 2.4) + air.adjust_moles(GAS_TRITIUM, -produced_amount) + air.adjust_moles(GAS_H2, produced_amount) + air.adjust_moles(GAS_PLUONIUM, -(produced_amount * 0.01)) energy_released += 50 if(energy_released) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(max((temperature * old_heat_capacity + energy_released) / new_heat_capacity, TCMB)) + air.set_temperature(max((old_thermal_energy + energy_released) / new_heat_capacity, TCMB)) return REACTING /datum/gas_reaction/pluonium_hydrogen_response - priority = 16 + priority = PLUONIUMH2RESPONSE name = "Pluonium hydrogen response" id = "pluonium_hydrogen_response" /datum/gas_reaction/pluonium_hydrogen_response/init_reqs() min_requirements = list( - /datum/gas/pluonium = MINIMUM_MOLE_COUNT, - /datum/gas/hydrogen = 150, + GAS_PLUONIUM = MINIMUM_MOLE_COUNT, + GAS_H2 = 150, ) /datum/gas_reaction/pluonium_hydrogen_response/react(datum/gas_mixture/air, datum/holder) var/energy_released = 0 - var/old_heat_capacity = air.heat_capacity() - var/temperature = air.return_temperature() - var produced_amount = min(5, air.get_moles(/datum/gas/hydrogen), air.adjust_moles(/datum/gas/pluonium)) - if(air.get_moles(/datum/gas/hydrogen) - produced_amount < 0) + var/old_thermal_energy = air.thermal_energy() + var/initial_h2 = air.get_moles(GAS_H2) + var/initial_pluon = air.get_moles(GAS_PLUONIUM) + var/produced_amount = min(5, initial_h2, initial_pluon) + if(initial_h2 - produced_amount < 0) return NO_REACTION - air.adjust_moles(/datum/gas/hydrogen, -produced_amount) - air.adjust_moles(/datum/gas/pluonium, (produced_amount * 0.5)) + air.adjust_moles(GAS_H2, -produced_amount) + air.adjust_moles(GAS_PLUONIUM, (produced_amount * 0.5)) energy_released = produced_amount * 2500 if(energy_released) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.set_temperature(max((temperature * old_heat_capacity - energy_released) / new_heat_capacity, TCMB)) + air.set_temperature(max((old_thermal_energy - energy_released) / new_heat_capacity, TCMB)) return REACTING +#undef MIASTER +#undef FREONFIRE +#undef PLASMAFIRE +#undef H2FIRE +#undef TRITFIRE +#undef HALONO2REMOVAL +#undef NITROUSDECOMP +#undef WATERVAPOR +#undef FUSION +#undef COLDFUSION +#undef NITRIUMFORMATION +#undef BZFORMATION +#undef FREONFORMATION +#undef NITROBALL +#undef ZAUKERDECOMP +#undef HEALIUMFORMATION +#undef PLUONIUMFORMATION +#undef ZAUKERFORMATION +#undef HALONFORMATION +#undef HEXANEFORMATION +#undef PLUONIUMBZRESPONSE +#undef PLUONIUMTRITRESPONSE +#undef PLUONIUMH2RESPONSE +#undef METALHYDROGEN +#undef NOBLIUMSUPPRESSION +#undef NOBLIUMFORMATION diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm index 902c3e5dac65..f7dc8a79e3ec 100644 --- a/code/modules/atmospherics/machinery/airalarm.dm +++ b/code/modules/atmospherics/machinery/airalarm.dm @@ -99,80 +99,77 @@ var/list/TLV = list( // Breathable air. "pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa. Values are min2, min1, max1, max2 "temperature" = new/datum/tlv(T0C, T0C+10, T0C+40, T0C+66), - /datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa - /datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000), - /datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10), - /datum/gas/miasma = new/datum/tlv/(-1, -1, 15, 30), - /datum/gas/plasma = new/datum/tlv/dangerous, - /datum/gas/nitrous_oxide = new/datum/tlv/dangerous, - /datum/gas/bz = new/datum/tlv/dangerous, - /datum/gas/hypernoblium = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic - /datum/gas/water_vapor = new/datum/tlv/dangerous, - /datum/gas/tritium = new/datum/tlv/dangerous, - /datum/gas/nitrium = new/datum/tlv/dangerous, - /datum/gas/dilithium = new/datum/tlv/dangerous,//Yogs -- Dilithium - /datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000), // Unlike oxygen, pluoxium does not fuel plasma/tritium fires - /datum/gas/freon = new/datum/tlv/dangerous, - /datum/gas/hydrogen = new/datum/tlv/dangerous, - /datum/gas/healium = new/datum/tlv/dangerous, - /datum/gas/pluonium = new/datum/tlv/dangerous, - /datum/gas/zauker = new/datum/tlv/dangerous, - /datum/gas/halon = new/datum/tlv/dangerous, - /datum/gas/antinoblium = new/datum/tlv/dangerous, - /datum/gas/hexane = new/datum/tlv/dangerous + GAS_O2 = new/datum/tlv(16, 19, 40, 50), // Partial pressure, kpa + GAS_N2 = new/datum/tlv(-1, -1, 1000, 1000), + GAS_CO2 = new/datum/tlv(-1, -1, 5, 10), + GAS_MIASMA = new/datum/tlv/(-1, -1, 15, 30), + GAS_PLASMA = new/datum/tlv/dangerous, + GAS_NITROUS = new/datum/tlv/dangerous, + GAS_BZ = new/datum/tlv/dangerous, + GAS_HYPERNOB = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic + GAS_H2O = new/datum/tlv/dangerous, + GAS_TRITIUM = new/datum/tlv/dangerous, + GAS_NITRIUM = new/datum/tlv/dangerous, + GAS_DILITHIUM = new/datum/tlv/dangerous,//Yogs -- Dilithium + GAS_PLUOXIUM = new/datum/tlv(-1, -1, 5, 6), // Unlike oxygen, pluoxium does not fuel plasma/tritium fires + GAS_FREON = new/datum/tlv/dangerous, + GAS_H2 = new/datum/tlv/dangerous, + GAS_HEALIUM = new/datum/tlv/dangerous, + GAS_PLUONIUM = new/datum/tlv/dangerous, + GAS_ZAUKER = new/datum/tlv/dangerous, + GAS_HALON = new/datum/tlv/dangerous, + GAS_HEXANE = new/datum/tlv/dangerous, ) /obj/machinery/airalarm/server // No checks here. TLV = list( "pressure" = new/datum/tlv/no_checks, "temperature" = new/datum/tlv/no_checks, - /datum/gas/oxygen = new/datum/tlv/no_checks, - /datum/gas/nitrogen = new/datum/tlv/no_checks, - /datum/gas/carbon_dioxide = new/datum/tlv/no_checks, - /datum/gas/miasma = new/datum/tlv/no_checks, - /datum/gas/plasma = new/datum/tlv/no_checks, - /datum/gas/nitrous_oxide = new/datum/tlv/no_checks, - /datum/gas/bz = new/datum/tlv/no_checks, - /datum/gas/hypernoblium = new/datum/tlv/no_checks, - /datum/gas/water_vapor = new/datum/tlv/no_checks, - /datum/gas/tritium = new/datum/tlv/no_checks, - /datum/gas/nitrium = new/datum/tlv/no_checks, - /datum/gas/dilithium = new/datum/tlv/no_checks,//Yogs -- Dilithium - /datum/gas/pluoxium = new/datum/tlv/no_checks, - /datum/gas/freon = new/datum/tlv/no_checks, - /datum/gas/hydrogen = new/datum/tlv/no_checks, - /datum/gas/healium = new/datum/tlv/dangerous, - /datum/gas/pluonium = new/datum/tlv/dangerous, - /datum/gas/halon = new/datum/tlv/dangerous, - /datum/gas/antinoblium = new/datum/tlv/dangerous, - /datum/gas/hexane = new/datum/tlv/dangerous + GAS_O2 = new/datum/tlv/no_checks, + GAS_N2 = new/datum/tlv/no_checks, + GAS_CO2 = new/datum/tlv/no_checks, + GAS_MIASMA = new/datum/tlv/no_checks, + GAS_PLASMA = new/datum/tlv/no_checks, + GAS_NITROUS = new/datum/tlv/no_checks, + GAS_BZ = new/datum/tlv/no_checks, + GAS_HYPERNOB = new/datum/tlv/no_checks, + GAS_H2O = new/datum/tlv/no_checks, + GAS_TRITIUM = new/datum/tlv/no_checks, + GAS_NITRIUM = new/datum/tlv/no_checks, + GAS_DILITHIUM = new/datum/tlv/no_checks,//Yogs -- Dilithium + GAS_PLUOXIUM = new/datum/tlv/no_checks, + GAS_FREON = new/datum/tlv/no_checks, + GAS_H2 = new/datum/tlv/no_checks, + GAS_HEALIUM = new/datum/tlv/dangerous, + GAS_PLUONIUM = new/datum/tlv/dangerous, + GAS_HALON = new/datum/tlv/dangerous, + GAS_HEXANE = new/datum/tlv/dangerous, ) /obj/machinery/airalarm/kitchen_cold_room // Kitchen cold rooms start off at -80°C or 193.15°K. TLV = list( "pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa "temperature" = new/datum/tlv(T0C-273.15, T0C-100, T0C-60, T0C), - /datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa - /datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000), - /datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10), - /datum/gas/miasma = new/datum/tlv/(-1, -1, 2, 5), - /datum/gas/plasma = new/datum/tlv/dangerous, - /datum/gas/nitrous_oxide = new/datum/tlv/dangerous, - /datum/gas/bz = new/datum/tlv/dangerous, - /datum/gas/hypernoblium = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic - /datum/gas/water_vapor = new/datum/tlv/dangerous, - /datum/gas/tritium = new/datum/tlv/dangerous, - /datum/gas/nitrium = new/datum/tlv/dangerous, - /datum/gas/dilithium = new/datum/tlv/dangerous,//Yogs -- Dilithium - /datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000), // Unlike oxygen, pluoxium does not fuel plasma/tritium fires - /datum/gas/freon = new/datum/tlv/dangerous, - /datum/gas/hydrogen = new/datum/tlv/dangerous, - /datum/gas/healium = new/datum/tlv/dangerous, - /datum/gas/pluonium = new/datum/tlv/dangerous, - /datum/gas/zauker = new/datum/tlv/dangerous, - /datum/gas/halon = new/datum/tlv/dangerous, - /datum/gas/antinoblium = new/datum/tlv/dangerous, - /datum/gas/hexane = new/datum/tlv/dangerous + GAS_O2 = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa + GAS_N2 = new/datum/tlv(-1, -1, 1000, 1000), + GAS_CO2 = new/datum/tlv(-1, -1, 5, 10), + GAS_MIASMA = new/datum/tlv/(-1, -1, 2, 5), + GAS_PLASMA = new/datum/tlv/dangerous, + GAS_NITROUS = new/datum/tlv/dangerous, + GAS_BZ = new/datum/tlv/dangerous, + GAS_HYPERNOB = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic + GAS_H2O = new/datum/tlv/dangerous, + GAS_TRITIUM = new/datum/tlv/dangerous, + GAS_NITRIUM = new/datum/tlv/dangerous, + GAS_DILITHIUM = new/datum/tlv/dangerous,//Yogs -- Dilithium + GAS_PLUOXIUM = new/datum/tlv(-1, -1, 1000, 1000), // Unlike oxygen, pluoxium does not fuel plasma/tritium fires + GAS_FREON = new/datum/tlv/dangerous, + GAS_H2 = new/datum/tlv/dangerous, + GAS_HEALIUM = new/datum/tlv/dangerous, + GAS_PLUONIUM = new/datum/tlv/dangerous, + GAS_ZAUKER = new/datum/tlv/dangerous, + GAS_HALON = new/datum/tlv/dangerous, + GAS_HEXANE = new/datum/tlv/dangerous, ) /obj/machinery/airalarm/unlocked @@ -231,6 +228,7 @@ ..() wires = new /datum/wires/airalarm(src) A = get_area(src) + LAZYADD(A.airalarms, src) if(ndir) setDir(ndir) @@ -248,8 +246,13 @@ /obj/machinery/airalarm/Destroy() SSradio.remove_object(src, frequency) QDEL_NULL(wires) - atmos_manualOverride(TRUE) - post_alert(0) + if(length(A.airalarms)<2 || A.manual_atmosalm) + atmos_manualOverride(TRUE) + post_alert(0) + else + atmos_manualOverride(TRUE) + A.atmosalert(0, src) + LAZYREMOVE(A.airalarms, src) return ..() /obj/machinery/airalarm/Initialize(mapload) @@ -292,11 +295,11 @@ data["fire_alarm"] = A.fire var/turf/T = get_turf(src) - var/datum/gas_mixture/environment = T.return_air() + var/datum/gas_mixture/environment = T?.return_air() var/datum/tlv/cur_tlv data["environment_data"] = list() - var/pressure = environment.return_pressure() + var/pressure = environment?.return_pressure() cur_tlv = TLV["pressure"] data["environment_data"] += list(list( "name" = "Pressure", @@ -304,7 +307,7 @@ "unit" = "kPa", "danger_level" = cur_tlv.get_danger_level(pressure) )) - var/temperature = environment.return_temperature() + var/temperature = environment?.return_temperature() cur_tlv = TLV["temperature"] data["environment_data"] += list(list( "name" = "Temperature", @@ -312,14 +315,14 @@ "unit" = "K ([round(temperature - T0C, 0.1)]C)", "danger_level" = cur_tlv.get_danger_level(temperature) )) - var/total_moles = environment.total_moles() - var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.return_temperature() / environment.return_volume() - for(var/gas_id in environment.get_gases()) + var/total_moles = environment?.total_moles() + var/partial_pressure = R_IDEAL_GAS_EQUATION * environment?.return_temperature() / environment?.return_volume() + for(var/gas_id in environment?.get_gases()) if(!(gas_id in TLV)) // We're not interested in this gas, it seems. continue cur_tlv = TLV[gas_id] data["environment_data"] += list(list( - "name" = GLOB.meta_gas_info[gas_id][META_GAS_NAME], + "name" = GLOB.gas_data.names[gas_id], "value" = environment.get_moles(gas_id) / total_moles * 100, "unit" = "%", "danger_level" = cur_tlv.get_danger_level(environment.get_moles(gas_id) * partial_pressure) @@ -388,11 +391,11 @@ thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max1", "selected" = selected.max1)) thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max2", "selected" = selected.max2)) - for(var/gas_id in GLOB.meta_gas_info) + for(var/gas_id in GLOB.gas_data.names) if(!(gas_id in TLV)) // We're not interested in this gas, it seems. continue selected = TLV[gas_id] - thresholds += list(list("name" = GLOB.meta_gas_info[gas_id][META_GAS_NAME], "settings" = list())) + thresholds += list(list("name" = GLOB.gas_data.names[gas_id], "settings" = list())) thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min2", "selected" = selected.min2)) thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min1", "selected" = selected.min1)) thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "max1", "selected" = selected.max1)) @@ -533,7 +536,7 @@ for(var/device_id in A.air_scrub_names) send_signal(device_id, list( "power" = 1, - "set_filters" = list(/datum/gas/carbon_dioxide), + "set_filters" = list(GAS_CO2), "scrubbing" = 1, "widenet" = 0 ), signal_source) @@ -548,25 +551,24 @@ send_signal(device_id, list( "power" = 1, "set_filters" = list( - /datum/gas/carbon_dioxide, - /datum/gas/miasma, - /datum/gas/plasma, - /datum/gas/water_vapor, - /datum/gas/hypernoblium, - /datum/gas/nitrous_oxide, - /datum/gas/nitrium, - /datum/gas/tritium, - /datum/gas/bz, - /datum/gas/pluoxium, - /datum/gas/dilithium,//Yogs -- Adds Dilithium - /datum/gas/freon, - /datum/gas/hydrogen, - /datum/gas/healium, - /datum/gas/pluonium, - /datum/gas/zauker, - /datum/gas/halon, - /datum/gas/antinoblium, - /datum/gas/hexane + GAS_CO2, + GAS_MIASMA, + GAS_PLASMA, + GAS_H2O, + GAS_HYPERNOB, + GAS_NITROUS, + GAS_NITRIUM, + GAS_TRITIUM, + GAS_BZ, + GAS_PLUOXIUM,//yogs comma + GAS_DILITHIUM,//Yogs -- Adds Dilithium + GAS_FREON, + GAS_H2, + GAS_HEALIUM, + GAS_PLUONIUM, + GAS_ZAUKER, + GAS_HALON, + GAS_HEXANE ), "scrubbing" = 1, "widenet" = 1 @@ -665,13 +667,16 @@ post_alert(0) return - var/turf/location = get_turf(src) - if(!location) + if(!isopenturf(get_turf(src))) return var/datum/tlv/cur_tlv - var/datum/gas_mixture/environment = location.return_air() + var/datum/gas_mixture/environment = return_air() + + if(!environment) + return + var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.return_temperature() / environment.return_volume() cur_tlv = TLV["pressure"] @@ -708,9 +713,13 @@ else AA.manual_override = TRUE +#define ALARM_LEVEL_CLEAR 0 +#define ALARM_LEVEL_MINOR 1 +#define ALARM_LEVEL_SEVERE 2 + /obj/machinery/airalarm/proc/post_alert(alert_level) var/datum/radio_frequency/frequency = SSradio.return_frequency(alarm_frequency) - if(alert_level>0 && !manual_override) + if(alert_level > 0 && !manual_override) trigger_reset = TRUE else trigger_reset = FALSE @@ -722,23 +731,28 @@ return var/datum/signal/alert_signal = new(list( - "zone" = get_area_name(src), - "type" = "Atmospheric" + "zone" = A, + "type" = "Atmospheric", )) - if(alert_level==2) - alert_signal.data["alert"] = "severe" - A.set_vacuum_alarm_effect() - else if (alert_level==1) - alert_signal.data["alert"] = "minor" - else if (alert_level==0) - alert_signal.data["alert"] = "clear" - A.unset_vacuum_alarm_effect() + switch(alert_level) + if(ALARM_LEVEL_CLEAR) + alert_signal.data["alert"] = ATMOS_ALARM_CLEAR + A.unset_vacuum_alarm_effect() + if(ALARM_LEVEL_MINOR) + alert_signal.data["alert"] = ATMOS_ALARM_MINOR + if(ALARM_LEVEL_SEVERE) + alert_signal.data["alert"] = ATMOS_ALARM_SEVERE + A.set_vacuum_alarm_effect() frequency.post_signal(src, alert_signal, range = -1) for(var/obj/machinery/airalarm/AA in A) AA.update_appearance(UPDATE_ICON) +#undef ALARM_LEVEL_CLEAR +#undef ALARM_LEVEL_MINOR +#undef ALARM_LEVEL_SEVERE + /obj/machinery/airalarm/proc/apply_danger_level() var/new_area_danger_level = 0 diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index c61fdc65c383..73f2b391ca04 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -23,6 +23,10 @@ GLOBAL_LIST_EMPTY(pipeimages) resistance_flags = FIRE_PROOF max_integrity = 200 obj_flags = CAN_BE_HIT | ON_BLUEPRINTS + ///Is the thing being rebuilt by SSair or not. Prevents list bloat + var/rebuilding = FALSE + ///If we should init and immediately start processing + var/init_processing = FALSE var/can_unwrench = 0 var/initialize_directions = 0 var/pipe_color @@ -53,19 +57,21 @@ GLOBAL_LIST_EMPTY(pipeimages) nodes = new(device_type) if (!armor) armor = list(MELEE = 25, BULLET = 10, LASER = 10, ENERGY = 100, BOMB = 0, BIO = 100, RAD = 100, FIRE = 100, ACID = 70) + init_processing = process ..() - if(process) - SSair.atmos_machinery += src - SetInitDirections() + set_init_directions() + +/obj/machinery/atmospherics/Initialize(mapload) + if(init_processing) + SSair_machinery.start_processing_machine(src) + return ..() /obj/machinery/atmospherics/Destroy() for(var/i in 1 to device_type) - nullifyNode(i) - - SSair.atmos_machinery -= src - if(SSair.currentpart == SSAIR_ATMOSMACHINERY) - SSair.currentrun -= src - SSair.pipenets_needing_rebuilt -= src + nullify_node(i) + + SSair_machinery.stop_processing_machine(src) + SSair.rebuild_queue -= src dropContents() if(pipe_vision_img) @@ -77,27 +83,36 @@ GLOBAL_LIST_EMPTY(pipeimages) /obj/machinery/atmospherics/proc/destroy_network() return -/obj/machinery/atmospherics/proc/build_network() - // Called to build a network from this node +/obj/machinery/atmospherics/proc/rebuild_pipes() + var/list/targets = get_rebuild_targets() + rebuilding = FALSE + for(var/datum/pipeline/build_off as anything in targets) + build_off.build_pipeline(src) //This'll add to the expansion queue + +/obj/machinery/atmospherics/proc/get_rebuild_targets() return -/obj/machinery/atmospherics/proc/nullifyNode(i) - if(nodes[i]) - var/obj/machinery/atmospherics/N = nodes[i] - N.disconnect(src) - nodes[i] = null +/obj/machinery/atmospherics/proc/nullify_node(i) + if(!nodes[i]) + return + var/obj/machinery/atmospherics/N = nodes[i] + N.disconnect(src) + nodes[i] = null -/obj/machinery/atmospherics/proc/getNodeConnects() +/obj/machinery/atmospherics/proc/get_node_connects() var/list/node_connects = list() node_connects.len = device_type + var/init_directions = get_init_directions() for(var/i in 1 to device_type) - for(var/D in GLOB.cardinals) - if(D & GetInitDirections()) - if(D in node_connects) - continue - node_connects[i] = D - break + for(var/direction in GLOB.cardinals) + if(!(direction & init_directions)) + continue + if(direction in node_connects) + continue + node_connects[i] = direction + break + return node_connects /obj/machinery/atmospherics/proc/normalize_cardinal_directions() @@ -108,9 +123,9 @@ GLOBAL_LIST_EMPTY(pipeimages) setDir(EAST) //this is called just after the air controller sets up turfs -/obj/machinery/atmospherics/proc/atmosinit(list/node_connects) +/obj/machinery/atmospherics/proc/atmos_init(list/node_connects) if(!node_connects) //for pipes where order of nodes doesn't matter - node_connects = getNodeConnects() + node_connects = get_node_connects() for(var/i in 1 to device_type) for(var/obj/machinery/atmospherics/target in get_step(src,node_connects[i])) @@ -119,7 +134,7 @@ GLOBAL_LIST_EMPTY(pipeimages) break update_appearance(UPDATE_ICON) -/obj/machinery/atmospherics/proc/setPipingLayer(new_layer) +/obj/machinery/atmospherics/proc/set_piping_layer(new_layer) piping_layer = (pipe_flags & PIPING_DEFAULT_LAYER_ONLY) ? PIPING_LAYER_DEFAULT : new_layer update_appearance(UPDATE_ICON) @@ -131,43 +146,54 @@ GLOBAL_LIST_EMPTY(pipeimages) return connection_check(target, piping_layer) //Find a connecting /obj/machinery/atmospherics in specified direction -/obj/machinery/atmospherics/proc/findConnecting(direction, prompted_layer) - for(var/obj/machinery/atmospherics/target in get_step(src, direction)) - if(target.initialize_directions & get_dir(target,src)) - if(connection_check(target, prompted_layer)) - return target +/obj/machinery/atmospherics/proc/find_connecting(direction, prompted_layer) + for(var/obj/machinery/atmospherics/target in get_step_multiz(src, direction)) + if(!(target.initialize_directions & get_dir(target,src))) + continue + if(connection_check(target, prompted_layer)) + return target /obj/machinery/atmospherics/proc/connection_check(obj/machinery/atmospherics/target, given_layer) - if(isConnectable(target, given_layer) && target.isConnectable(src, given_layer) && (target.initialize_directions & get_dir(target,src))) - return TRUE - return FALSE + if(!((initialize_directions & get_dir(src, target)) && (target.initialize_directions & get_dir(target, src)))) + return FALSE + + if(!is_connectable(target, given_layer) || !target.is_connectable(src, given_layer)) + return FALSE + + return TRUE -/obj/machinery/atmospherics/proc/isConnectable(obj/machinery/atmospherics/target, given_layer) + +/obj/machinery/atmospherics/proc/is_connectable(obj/machinery/atmospherics/target, given_layer) if(isnull(given_layer)) given_layer = piping_layer + + if(target.loc == loc) + return FALSE + if((target.piping_layer == given_layer) || (target.pipe_flags & PIPING_ALL_LAYER)) return TRUE + return FALSE /obj/machinery/atmospherics/proc/pipeline_expansion() return nodes -/obj/machinery/atmospherics/proc/SetInitDirections() +/obj/machinery/atmospherics/proc/set_init_directions() return -/obj/machinery/atmospherics/proc/GetInitDirections() +/obj/machinery/atmospherics/proc/get_init_directions() return initialize_directions -/obj/machinery/atmospherics/proc/returnPipenet() +/obj/machinery/atmospherics/proc/return_pipenet() return -/obj/machinery/atmospherics/proc/returnPipenetAir() +/obj/machinery/atmospherics/proc/return_pipenet_airs() return -/obj/machinery/atmospherics/proc/setPipenet() +/obj/machinery/atmospherics/proc/set_pipenet() return -/obj/machinery/atmospherics/proc/replacePipenet() +/obj/machinery/atmospherics/proc/replace_pipenet() return /obj/machinery/atmospherics/proc/disconnect(obj/machinery/atmospherics/reference) @@ -181,7 +207,7 @@ GLOBAL_LIST_EMPTY(pipeimages) if(istype(W, /obj/item/pipe)) //lets you autodrop var/obj/item/pipe/pipe = W if(user.dropItemToGround(pipe)) - pipe.setPipingLayer(piping_layer) //align it with us + pipe.set_piping_layer(piping_layer) //align it with us return TRUE else return ..() @@ -265,13 +291,13 @@ GLOBAL_LIST_EMPTY(pipeimages) if(!(flags_1 & NODECONSTRUCT_1)) if(can_unwrench) var/obj/item/pipe/stored = new construction_type(loc, null, dir, src) - stored.setPipingLayer(piping_layer) + stored.set_piping_layer(piping_layer) if(!disassembled) stored.obj_integrity = stored.max_integrity * 0.5 transfer_fingerprints_to(stored) ..() -/obj/machinery/atmospherics/proc/getpipeimage(iconset, iconstate, direction, col=rgb(255,255,255), piping_layer=3, trinary = FALSE) +/obj/machinery/atmospherics/proc/get_pipe_image(iconset, iconstate, direction, col=rgb(255,255,255), piping_layer=3, trinary = FALSE) //Add identifiers for the iconset if(GLOB.iconsetids[iconset] == null) @@ -292,15 +318,15 @@ GLOBAL_LIST_EMPTY(pipeimages) if(can_unwrench) add_atom_colour(obj_color, FIXED_COLOUR_PRIORITY) pipe_color = obj_color - setPipingLayer(set_layer) + set_piping_layer(set_layer) var/turf/T = get_turf(src) level = T.intact ? 2 : 1 - atmosinit() + atmos_init() var/list/nodes = pipeline_expansion() for(var/obj/machinery/atmospherics/A in nodes) - A.atmosinit() - A.addMember(src) - build_network() + A.atmos_init() + A.add_member(src) + SSair.add_to_rebuild_queue(src) /obj/machinery/atmospherics/Entered(atom/movable/AM) if(istype(AM, /mob/living)) @@ -323,7 +349,7 @@ GLOBAL_LIST_EMPTY(pipeimages) if(user in buckled_mobs)// fixes buckle ventcrawl edgecase fuck bug return - var/obj/machinery/atmospherics/target_move = findConnecting(direction, user.ventcrawl_layer) + var/obj/machinery/atmospherics/target_move = find_connecting(direction, user.ventcrawl_layer) if(target_move) if(target_move.can_crawl_through()) if(is_type_in_typecache(target_move, GLOB.ventcrawl_machinery)) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/binary_devices.dm b/code/modules/atmospherics/machinery/components/binary_devices/binary_devices.dm index 5e1428559345..5f3741f24519 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/binary_devices.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/binary_devices.dm @@ -6,7 +6,7 @@ device_type = BINARY layer = GAS_PUMP_LAYER -/obj/machinery/atmospherics/components/binary/SetInitDirections() +/obj/machinery/atmospherics/components/binary/set_init_directions() switch(dir) if(NORTH, SOUTH) initialize_directions = NORTH|SOUTH @@ -17,7 +17,7 @@ update_appearance(UPDATE_ICON) ..() -/obj/machinery/atmospherics/components/binary/getNodeConnects() +/obj/machinery/atmospherics/components/binary/get_node_connects() return list(turn(dir, 180), dir) ///Used by binary devices to set what the offset will be for each layer diff --git a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm index 9c9a7203f343..a309095d2716 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm @@ -76,7 +76,6 @@ last_pressure_delta = 0 /obj/machinery/atmospherics/components/binary/circulator/process_atmos() - ..() update_icon_nopipes() /obj/machinery/atmospherics/components/binary/circulator/update_overlays() @@ -86,11 +85,11 @@ for(var/direction in GLOB.cardinals) if(!(direction & initialize_directions)) continue - var/obj/machinery/atmospherics/node = findConnecting(direction) + var/obj/machinery/atmospherics/node = find_connecting(direction) var/image/cap if(node) - cap = getpipeimage(icon, "cap", direction, node.pipe_color, piping_layer = piping_layer) + cap = get_pipe_image(icon, "cap", direction, node.pipe_color, piping_layer = piping_layer) . += cap @@ -164,37 +163,37 @@ if(node1) node1.disconnect(src) nodes[1] = null - nullifyPipenet(parents[1]) + nullify_pipenet(parents[1]) if(node2) node2.disconnect(src) nodes[2] = null - nullifyPipenet(parents[2]) + nullify_pipenet(parents[2]) if(anchored) - SetInitDirections() - atmosinit() + set_init_directions() + atmos_init() node1 = nodes[1] if(node1) - node1.atmosinit() - node1.addMember(src) + node1.atmos_init() + node1.add_member(src) node2 = nodes[2] if(node2) - node2.atmosinit() - node2.addMember(src) + node2.atmos_init() + node2.add_member(src) SSair.add_to_rebuild_queue(src) update_appearance(UPDATE_ICON) return TRUE -/obj/machinery/atmospherics/components/binary/circulator/SetInitDirections() +/obj/machinery/atmospherics/components/binary/circulator/set_init_directions() switch(dir) if(NORTH, SOUTH) initialize_directions = EAST|WEST if(EAST, WEST) initialize_directions = NORTH|SOUTH -/obj/machinery/atmospherics/components/binary/circulator/getNodeConnects() +/obj/machinery/atmospherics/components/binary/circulator/get_node_connects() if(flipped) return list(turn(dir, 270), turn(dir, 90)) return list(turn(dir, 90), turn(dir, 270)) @@ -255,7 +254,7 @@ generator.update_appearance(UPDATE_ICON) generator = null -/obj/machinery/atmospherics/components/binary/circulator/setPipingLayer(new_layer) +/obj/machinery/atmospherics/components/binary/circulator/set_piping_layer(new_layer) ..() pixel_x = 0 pixel_y = 0 diff --git a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm index 607797d55d5a..d82bde6274b8 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm @@ -42,7 +42,7 @@ /obj/machinery/atmospherics/components/binary/dp_vent_pump/update_icon_nopipes() cut_overlays() if(showpipe) - var/image/cap = getpipeimage(icon, "dpvent_cap", dir, piping_layer = piping_layer) + var/image/cap = get_pipe_image(icon, "dpvent_cap", dir, piping_layer = piping_layer) add_overlay(cap) if(!on || !is_operational()) @@ -51,8 +51,8 @@ icon_state = pump_direction ? "vent_out" : "vent_in" /obj/machinery/atmospherics/components/binary/dp_vent_pump/process_atmos() - ..() - + if(welded || !is_operational() || !isopenturf(loc)) + return FALSE if(!on) return var/datum/gas_mixture/air1 = airs[1] @@ -73,19 +73,14 @@ if(air1.return_temperature() > 0) var/transfer_moles = pressure_delta*environment.return_volume()/(air1.return_temperature() * R_IDEAL_GAS_EQUATION) - var/datum/gas_mixture/removed = air1.remove(transfer_moles) - //Removed can be null if there is no atmosphere in air1 - if(!removed) - return + loc.assume_air_moles(air1, transfer_moles) - loc.assume_air(removed) - air_update_turf() + var/datum/pipeline/parent1 = parents[1] - parent1.update = 1 + parent1.update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED else //external -> output - if(environment.return_pressure() > 0) var/our_multiplier = air2.return_volume() / (environment.return_temperature() * R_IDEAL_GAS_EQUATION) var/moles_delta = 10000 * our_multiplier @@ -93,20 +88,15 @@ moles_delta = min(moles_delta, (environment_pressure - output_pressure_max) * environment.return_volume() / (environment.return_temperature() * R_IDEAL_GAS_EQUATION)) if(pressure_checks&INPUT_MIN) moles_delta = min(moles_delta, (input_pressure_min - air2.return_pressure()) * our_multiplier) - - if(moles_delta > 0) - var/datum/gas_mixture/removed = loc.remove_air(moles_delta) - if (isnull(removed)) // in space - return - air2.merge(removed) - air_update_turf() + if(moles_delta > 0) + loc.transfer_air(air2, moles_delta) + var/datum/pipeline/parent2 = parents[2] - parent2.update = 1 - - //Radio remote control + parent2.update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED +//Radio remote control /obj/machinery/atmospherics/components/binary/dp_vent_pump/proc/set_frequency(new_frequency) SSradio.remove_object(src, frequency) frequency = new_frequency @@ -130,7 +120,7 @@ )) radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) -/obj/machinery/atmospherics/components/binary/dp_vent_pump/atmosinit() +/obj/machinery/atmospherics/components/binary/dp_vent_pump/atmos_init() ..() if(frequency) set_frequency(frequency) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm index 01ec68fa1c20..774eeaa8a0cf 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm @@ -55,35 +55,15 @@ Passive gate is similar to the regular pump except: cut_overlays() icon_state = "passgate_off-[set_overlay_offset(piping_layer)]" if(on) - add_overlay(getpipeimage(icon, "passgate_on-[set_overlay_offset(piping_layer)]")) + add_overlay(get_pipe_image(icon, "passgate_on-[set_overlay_offset(piping_layer)]")) /obj/machinery/atmospherics/components/binary/passive_gate/process_atmos() - ..() if(!on) return var/datum/gas_mixture/air1 = airs[1] var/datum/gas_mixture/air2 = airs[2] - - var/output_starting_pressure = air2.return_pressure() - var/input_starting_pressure = air1.return_pressure() - - if(output_starting_pressure >= min(target_pressure,input_starting_pressure-10)) - //No need to pump gas if target is already reached or input pressure is too low - //Need at least 10 KPa difference to overcome friction in the mechanism - return - - //Calculate necessary moles to transfer using PV = nRT - if((air1.total_moles() > 0) && (air1.return_temperature()>0)) - var/pressure_delta = min(target_pressure - output_starting_pressure, (input_starting_pressure - output_starting_pressure)/2) - //Can not have a pressure delta that would cause output_pressure > input_pressure - - var/transfer_moles = pressure_delta*air2.return_volume()/(air1.return_temperature() * R_IDEAL_GAS_EQUATION) - - //Actually transfer the gas - var/datum/gas_mixture/removed = air1.remove(transfer_moles) - air2.merge(removed) - + if(air1.release_gas_to(air2, target_pressure)) update_parents() @@ -150,7 +130,7 @@ Passive gate is similar to the regular pump except: investigate_log(msg, INVESTIGATE_SUPERMATTER) // yogs - make supermatter invest useful update_appearance(UPDATE_ICON) -/obj/machinery/atmospherics/components/binary/passive_gate/atmosinit() +/obj/machinery/atmospherics/components/binary/passive_gate/atmos_init() ..() if(frequency) set_frequency(frequency) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm b/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm index 7d3c7949b7d7..2556d9917447 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm @@ -119,7 +119,7 @@ investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", INVESTIGATE_ATMOS) update_appearance(UPDATE_ICON) -/obj/machinery/atmospherics/components/binary/pressure_valve/atmosinit() +/obj/machinery/atmospherics/components/binary/pressure_valve/atmos_init() . = ..() if(frequency) set_frequency(frequency) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm index 76f2b98782d7..be8c8dbdb6e2 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm @@ -53,27 +53,21 @@ icon_state = (on && is_operational()) ? "pump_on-[set_overlay_offset(piping_layer)]" : "pump_off-[set_overlay_offset(piping_layer)]" /obj/machinery/atmospherics/components/binary/pump/process_atmos() -// ..() if(!on || !is_operational()) return var/datum/gas_mixture/air1 = airs[1] var/datum/gas_mixture/air2 = airs[2] - var/output_starting_pressure = air2.return_pressure() - if((target_pressure - output_starting_pressure) < 0.01) //No need to pump gas if target is already reached! return - //Calculate necessary moles to transfer using PV=nRT if((air1.total_moles() > 0) && (air1.return_temperature()>0)) var/pressure_delta = target_pressure - output_starting_pressure var/transfer_moles = pressure_delta*air2.return_volume()/(air1.return_temperature() * R_IDEAL_GAS_EQUATION) - //Actually transfer the gas - var/datum/gas_mixture/removed = air1.remove(transfer_moles) - air2.merge(removed) + air1.transfer_to(air2,transfer_moles) update_parents() @@ -139,7 +133,7 @@ investigate_log(msg, INVESTIGATE_SUPERMATTER) // yogs - makes supermatter invest useful update_appearance(UPDATE_ICON) -/obj/machinery/atmospherics/components/binary/pump/atmosinit() +/obj/machinery/atmospherics/components/binary/pump/atmos_init() ..() if(frequency) set_frequency(frequency) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm index 3a489e3821af..25d30312fc03 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm @@ -33,7 +33,7 @@ icon_state = "tpump_[on && is_operational() ? "on" : "off"]-[set_overlay_offset(piping_layer)]" /obj/machinery/atmospherics/components/binary/temperature_pump/process_atmos() - ..() + if(!on || !is_operational()) return @@ -42,7 +42,6 @@ if(!QUANTIZE(air_input.total_moles()) || !QUANTIZE(air_output.total_moles())) //Don't transfer if there's no gas return - var/datum/gas_mixture/remove_input = air_input.remove_ratio(0.9) var/datum/gas_mixture/remove_output = air_output.remove_ratio(0.9) @@ -50,7 +49,7 @@ if(coolant_temperature_delta > 0) var/input_capacity = remove_input.heat_capacity() - var/output_capacity = remove_output.heat_capacity() + var/output_capacity = air_output.heat_capacity() var/cooling_heat_amount = (heat_transfer_rate * 0.01) * coolant_temperature_delta * (input_capacity * output_capacity / (input_capacity + output_capacity)) remove_input.set_temperature(max(remove_input.return_temperature() - (cooling_heat_amount / input_capacity), TCMB)) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/valve.dm b/code/modules/atmospherics/machinery/components/binary_devices/valve.dm index 89e9b7b2a43a..86449e9eb00b 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/valve.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/valve.dm @@ -14,6 +14,8 @@ It's like a regular ol' straight pipe, but you can turn it on and off. interaction_flags_machine = INTERACT_MACHINE_OFFLINE | INTERACT_MACHINE_OPEN //Intentionally no allow_silicon flag pipe_flags = PIPING_CARDINAL_AUTONORMALIZE + custom_reconcilation = TRUE + var/frequency = 0 var/id = null @@ -24,6 +26,26 @@ It's like a regular ol' straight pipe, but you can turn it on and off. var/switching = FALSE + +/obj/machinery/atmospherics/components/binary/valve/Destroy() + //Should only happen on extreme circumstances + if(on) + //Let's give presumably now-severed pipenets a chance to scramble for what's happening at next SSair fire() + if(parents[1]) + parents[1].update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED + if(parents[2]) + parents[2].update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED + . = ..() + +// This is what handles the actual functionality of combining 2 pipenets when the valve is open +// Basically when a pipenet updates it will consider both sides to be the same for the purpose of the gas update +/obj/machinery/atmospherics/components/binary/valve/return_pipenets_for_reconcilation(datum/pipeline/requester) + . = ..() + if(!on) + return + . |= parents[1] + . |= parents[2] + /obj/machinery/atmospherics/components/binary/valve/update_icon_nopipes(animation = FALSE) normalize_cardinal_directions() if(animation) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm index 9092deda1252..74c6be7c3f26 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm @@ -55,7 +55,6 @@ icon_state = on && is_operational() ? "volpump_on-[set_overlay_offset(piping_layer)]" : "volpump_off-[set_overlay_offset(piping_layer)]" /obj/machinery/atmospherics/components/binary/volume_pump/process_atmos() -// ..() if(!on || !is_operational()) return @@ -73,19 +72,15 @@ if(overclocked && (output_starting_pressure-input_starting_pressure > 1000))//Overclocked pumps can only force gas a certain amount. return - - var/transfer_ratio = transfer_rate / air1.return_volume() - - var/datum/gas_mixture/removed = air1.remove_ratio(transfer_ratio) - if(overclocked)//Some of the gas from the mixture leaks to the environment when overclocked var/turf/open/T = loc if(istype(T)) - var/datum/gas_mixture/leaked = removed.remove_ratio(VOLUME_PUMP_LEAK_AMOUNT) + var/datum/gas_mixture/leaked = air1.remove_ratio(VOLUME_PUMP_LEAK_AMOUNT) T.assume_air(leaked) - T.air_update_turf() - air2.merge(removed) + var/transfer_ratio = transfer_rate / air1.return_volume() + + air1.transfer_ratio_to(air2,transfer_ratio) update_parents() @@ -126,7 +121,7 @@ data["max_rate"] = round(MAX_TRANSFER_RATE) return data -/obj/machinery/atmospherics/components/binary/volume_pump/atmosinit() +/obj/machinery/atmospherics/components/binary/volume_pump/atmos_init() ..() set_frequency(frequency) diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm index 95ca4b666034..2f1863532f74 100644 --- a/code/modules/atmospherics/machinery/components/components_base.dm +++ b/code/modules/atmospherics/machinery/components/components_base.dm @@ -6,10 +6,14 @@ var/showpipe = TRUE var/shift_underlay_only = TRUE //Layering only shifts underlay? + var/update_parents_after_rebuild = FALSE + var/list/datum/pipeline/parents var/list/datum/gas_mixture/airs var/startingvolume = 200 + var/custom_reconcilation = FALSE + /obj/machinery/atmospherics/components/New() parents = new(device_type) airs = new(device_type) @@ -17,8 +21,11 @@ ..() for(var/i in 1 to device_type) - var/datum/gas_mixture/A = new(startingvolume) - airs[i] = A + if(airs[i]) + continue + var/datum/gas_mixture/component_mixture = new + component_mixture.set_volume(startingvolume) + airs[i] = component_mixture // Iconnery @@ -54,52 +61,73 @@ /obj/machinery/atmospherics/components/proc/get_pipe_underlay(state, dir, color = null) if(color) - . = getpipeimage('icons/obj/atmospherics/components/binary_devices.dmi', state, dir, color, piping_layer = shift_underlay_only ? piping_layer : 3) + . = get_pipe_image('icons/obj/atmospherics/components/binary_devices.dmi', state, dir, color, piping_layer = shift_underlay_only ? piping_layer : 3) else - . = getpipeimage('icons/obj/atmospherics/components/binary_devices.dmi', state, dir, piping_layer = shift_underlay_only ? piping_layer : 3) + . = get_pipe_image('icons/obj/atmospherics/components/binary_devices.dmi', state, dir, piping_layer = shift_underlay_only ? piping_layer : 3) // Pipenet stuff; housekeeping -/obj/machinery/atmospherics/components/nullifyNode(i) - if(nodes[i]) - nullifyPipenet(parents[i]) - QDEL_NULL(airs[i]) - ..() +/obj/machinery/atmospherics/components/nullify_node(i) + if(parents[i]) + nullify_pipenet(parents[i]) + airs[i] = null + return ..() /obj/machinery/atmospherics/components/on_construction() ..() update_parents() -/obj/machinery/atmospherics/components/build_network() +/obj/machinery/atmospherics/components/rebuild_pipes() + . = ..() + if(update_parents_after_rebuild) + update_parents() + +/obj/machinery/atmospherics/components/get_rebuild_targets() + var/list/to_return = list() for(var/i in 1 to device_type) - if(!parents[i]) - parents[i] = new /datum/pipeline() - var/datum/pipeline/P = parents[i] - P.build_pipeline(src) + if(parents[i]) + continue + parents[i] = new /datum/pipeline() + to_return += parents[i] + return to_return -/obj/machinery/atmospherics/components/proc/nullifyPipenet(datum/pipeline/reference) +/obj/machinery/atmospherics/components/proc/nullify_pipenet(datum/pipeline/reference) if(!reference) - CRASH("nullifyPipenet(null) called by [type] on [COORD(src)]") - var/i = parents.Find(reference) - reference.other_airs -= airs[i] - reference.other_atmosmch -= src - parents[i] = null + CRASH("nullify_pipenet(null) called by [type] on [COORD(src)]") + + for (var/i in 1 to parents.len) + if (parents[i] == reference) + reference.other_airs -= airs[i] // Disconnects from the pipeline side + parents[i] = null // Disconnects from the machinery side. + + reference.other_atmos_machines -= src + + if(!length(reference.other_atmos_machines) && !length(reference.members)) + if(QDESTROYING(reference)) + CRASH("nullify_pipenet() called on qdeleting [reference]") + qdel(reference) -/obj/machinery/atmospherics/components/returnPipenetAir(datum/pipeline/reference) - return airs[parents.Find(reference)] +// We should return every air sharing a parent +/obj/machinery/atmospherics/components/return_pipenet_airs(datum/pipeline/reference) + var/list/returned_air = list() + + for (var/i in 1 to parents.len) + if (parents[i] == reference) + returned_air += airs[i] + return returned_air /obj/machinery/atmospherics/components/pipeline_expansion(datum/pipeline/reference) if(reference) return list(nodes[parents.Find(reference)]) return ..() -/obj/machinery/atmospherics/components/setPipenet(datum/pipeline/reference, obj/machinery/atmospherics/A) +/obj/machinery/atmospherics/components/set_pipenet(datum/pipeline/reference, obj/machinery/atmospherics/A) parents[nodes.Find(A)] = reference -/obj/machinery/atmospherics/components/returnPipenet(obj/machinery/atmospherics/A = nodes[1]) //returns parents[1] if called without argument +/obj/machinery/atmospherics/components/return_pipenet(obj/machinery/atmospherics/A = nodes[1]) //returns parents[1] if called without argument return parents[nodes.Find(A)] -/obj/machinery/atmospherics/components/replacePipenet(datum/pipeline/Old, datum/pipeline/New) +/obj/machinery/atmospherics/components/replace_pipenet(datum/pipeline/Old, datum/pipeline/New) parents[parents.Find(Old)] = New /obj/machinery/atmospherics/components/unsafe_pressure_release(mob/user, pressures) @@ -117,15 +145,9 @@ times_lost++ var/shared_loss = lost/times_lost - var/datum/gas_mixture/to_release for(var/i in 1 to device_type) var/datum/gas_mixture/air = airs[i] - if(!to_release) - to_release = air.remove(shared_loss) - continue - to_release.merge(air.remove(shared_loss)) - T.assume_air(to_release) - air_update_turf(1) + T.assume_air_moles(air, shared_loss) /obj/machinery/atmospherics/components/proc/safe_input(title, text, default_set) var/new_value = input(usr,text,title,default_set) as num @@ -136,6 +158,11 @@ // Helpers /obj/machinery/atmospherics/components/proc/update_parents() + if(!SSair.initialized) + return + if(rebuilding) + update_parents_after_rebuild = TRUE + return for(var/i in 1 to device_type) var/datum/pipeline/parent = parents[i] if(!parent) @@ -147,7 +174,13 @@ /obj/machinery/atmospherics/components/return_pipenets() . = list() for(var/i in 1 to device_type) - . += returnPipenet(nodes[i]) + . += return_pipenet(nodes[i]) + +/obj/machinery/atmospherics/components/proc/return_pipenets_for_reconcilation(datum/pipeline/requester) + return list() + +/obj/machinery/atmospherics/components/proc/return_airs_for_reconcilation(datum/pipeline/requester) + return list() // UI Stuff @@ -159,5 +192,30 @@ // Tool acts +/obj/machinery/atmospherics/components/proc/disconnect_nodes() + for(var/i in 1 to device_type) + var/obj/machinery/atmospherics/node = nodes[i] + if(node) + if(src in node.nodes) //Only if it's actually connected. On-pipe version would is one-sided. + node.disconnect(src) + nodes[i] = null + if(parents[i]) + nullify_pipenet(parents[i]) + +/obj/machinery/atmospherics/components/proc/connect_nodes() + atmos_init() + for(var/i in 1 to device_type) + var/obj/machinery/atmospherics/node = nodes[i] + if(node) + node.atmos_init() + node.add_member(src) + SSair.add_to_rebuild_queue(src) + +/obj/machinery/atmospherics/components/proc/change_nodes_connection(disconnect) + if(disconnect) + disconnect_nodes() + return + connect_nodes() + /obj/machinery/atmospherics/components/return_analyzable_air() return airs diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_fuel_datums.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_fuel_datums.dm index 54a4e005704d..f9dd6525ecfb 100644 --- a/code/modules/atmospherics/machinery/components/fusion/hfr_fuel_datums.dm +++ b/code/modules/atmospherics/machinery/components/fusion/hfr_fuel_datums.dm @@ -50,9 +50,9 @@ GLOBAL_LIST_INIT(hfr_fuels_list, hfr_fuels_create_list()) fuel_consumption_multiplier = 3.3 gas_production_multiplier = 1.4 temperature_change_multiplier = 0.6 - requirements = list(/datum/gas/plasma, /datum/gas/oxygen) - primary_products = list(/datum/gas/carbon_dioxide, /datum/gas/water_vapor) - secondary_products = list(/datum/gas/carbon_dioxide, /datum/gas/freon, /datum/gas/tritium, /datum/gas/hydrogen, /datum/gas/pluoxium, /datum/gas/halon) + requirements = list(GAS_PLASMA, GAS_O2) + primary_products = list(GAS_CO2, GAS_H2O) + secondary_products = list(GAS_CO2, GAS_FREON, GAS_TRITIUM, GAS_H2, GAS_PLUOXIUM, GAS_HALON) meltdown_flags = HYPERTORUS_FLAG_BASE_EXPLOSION | HYPERTORUS_FLAG_MINIMUM_SPREAD /datum/hfr_fuel/hydrogen_oxy_fuel @@ -64,9 +64,9 @@ GLOBAL_LIST_INIT(hfr_fuels_list, hfr_fuels_create_list()) fuel_consumption_multiplier = 1.1 gas_production_multiplier = 0.9 temperature_change_multiplier = 0.75 - requirements = list(/datum/gas/hydrogen, /datum/gas/oxygen) - primary_products = list(/datum/gas/nitrogen) - secondary_products = list(/datum/gas/plasma, /datum/gas/freon, /datum/gas/bz, /datum/gas/healium, /datum/gas/pluoxium, /datum/gas/hypernoblium) + requirements = list(GAS_H2, GAS_O2) + primary_products = list(GAS_N2) + secondary_products = list(GAS_PLASMA, GAS_FREON, GAS_BZ, GAS_HEALIUM, GAS_PLUOXIUM, GAS_HYPERNOB) meltdown_flags = HYPERTORUS_FLAG_BASE_EXPLOSION | HYPERTORUS_FLAG_EMP | HYPERTORUS_FLAG_MEDIUM_SPREAD /datum/hfr_fuel/tritium_oxy_fuel @@ -78,9 +78,9 @@ GLOBAL_LIST_INIT(hfr_fuels_list, hfr_fuels_create_list()) fuel_consumption_multiplier = 1.2 gas_production_multiplier = 0.8 temperature_change_multiplier = 0.8 - requirements = list(/datum/gas/tritium, /datum/gas/oxygen) - primary_products = list(/datum/gas/pluoxium) - secondary_products = list(/datum/gas/plasma, /datum/gas/pluoxium, /datum/gas/healium, /datum/gas/hydrogen, /datum/gas/halon, /datum/gas/hypernoblium) + requirements = list(GAS_TRITIUM, GAS_O2) + primary_products = list(GAS_PLUOXIUM) + secondary_products = list(GAS_PLASMA, GAS_PLUOXIUM, GAS_HEALIUM, GAS_H2, GAS_HALON, GAS_HYPERNOB) meltdown_flags = HYPERTORUS_FLAG_BASE_EXPLOSION | HYPERTORUS_FLAG_RADIATION_PULSE | HYPERTORUS_FLAG_MEDIUM_SPREAD /datum/hfr_fuel/hydrogen_tritium_fuel @@ -92,9 +92,9 @@ GLOBAL_LIST_INIT(hfr_fuels_list, hfr_fuels_create_list()) fuel_consumption_multiplier = 1 gas_production_multiplier = 1 temperature_change_multiplier = 0.85 - requirements = list(/datum/gas/hydrogen, /datum/gas/tritium) - primary_products = list(/datum/gas/pluoxium) - secondary_products = list(/datum/gas/nitrogen, /datum/gas/healium, /datum/gas/dilithium, /datum/gas/hexane, /datum/gas/hypernoblium, /datum/gas/antinoblium) + requirements = list(GAS_H2, GAS_TRITIUM) + primary_products = list(GAS_PLUOXIUM) + secondary_products = list(GAS_N2, GAS_HEALIUM, GAS_DILITHIUM, GAS_HEXANE, GAS_HYPERNOB, GAS_ANTINOB) meltdown_flags = HYPERTORUS_FLAG_MEDIUM_EXPLOSION | HYPERTORUS_FLAG_RADIATION_PULSE | HYPERTORUS_FLAG_EMP | HYPERTORUS_FLAG_MEDIUM_SPREAD /datum/hfr_fuel/hypernob_hydrogen_fuel @@ -106,9 +106,9 @@ GLOBAL_LIST_INIT(hfr_fuels_list, hfr_fuels_create_list()) fuel_consumption_multiplier = 0.55 gas_production_multiplier = 1.4 temperature_change_multiplier = 0.9 - requirements = list(/datum/gas/hypernoblium, /datum/gas/hydrogen) - primary_products = list(/datum/gas/antinoblium) - secondary_products = list(/datum/gas/antinoblium, /datum/gas/healium, /datum/gas/pluoxium, /datum/gas/pluonium, /datum/gas/zauker, /datum/gas/nitrium) + requirements = list(GAS_HYPERNOB, GAS_H2) + primary_products = list(GAS_ANTINOB) + secondary_products = list(GAS_ANTINOB, GAS_HEALIUM, GAS_PLUOXIUM, GAS_PLUONIUM, GAS_ZAUKER, GAS_NITRIUM) meltdown_flags = HYPERTORUS_FLAG_DEVASTATING_EXPLOSION | HYPERTORUS_FLAG_RADIATION_PULSE | HYPERTORUS_FLAG_EMP | HYPERTORUS_FLAG_BIG_SPREAD /datum/hfr_fuel/hypernob_trit_fuel @@ -120,9 +120,9 @@ GLOBAL_LIST_INIT(hfr_fuels_list, hfr_fuels_create_list()) fuel_consumption_multiplier = 0.45 gas_production_multiplier = 1.7 temperature_change_multiplier = 0.95 - requirements = list(/datum/gas/hypernoblium, /datum/gas/tritium) - primary_products = list(/datum/gas/antinoblium) - secondary_products = list(/datum/gas/antinoblium, /datum/gas/healium, /datum/gas/pluonium, /datum/gas/zauker, /datum/gas/nitrium, /datum/gas/miasma) + requirements = list(GAS_HYPERNOB, GAS_TRITIUM) + primary_products = list(GAS_ANTINOB) + secondary_products = list(GAS_ANTINOB, GAS_HEALIUM, GAS_PLUONIUM, GAS_ZAUKER, GAS_NITRIUM, GAS_MIASMA) meltdown_flags = HYPERTORUS_FLAG_DEVASTATING_EXPLOSION | HYPERTORUS_FLAG_RADIATION_PULSE | HYPERTORUS_FLAG_EMP | HYPERTORUS_FLAG_BIG_SPREAD /datum/hfr_fuel/hypernob_antinob_fuel @@ -134,7 +134,7 @@ GLOBAL_LIST_INIT(hfr_fuels_list, hfr_fuels_create_list()) fuel_consumption_multiplier = 0.01 gas_production_multiplier = 3 temperature_change_multiplier = 1 - requirements = list(/datum/gas/hypernoblium, /datum/gas/antinoblium) - primary_products = list(/datum/gas/zauker, /datum/gas/miasma) - secondary_products = list(/datum/gas/oxygen, /datum/gas/nitrium, /datum/gas/bz, /datum/gas/pluonium, /datum/gas/hexane, /datum/gas/healium) + requirements = list(GAS_HYPERNOB, GAS_ANTINOB) + primary_products = list(GAS_ZAUKER, GAS_MIASMA) + secondary_products = list(GAS_O2, GAS_NITRIUM, GAS_BZ, GAS_PLUONIUM, GAS_HEXANE, GAS_HEALIUM) meltdown_flags = HYPERTORUS_FLAG_DEVASTATING_EXPLOSION | HYPERTORUS_FLAG_RADIATION_PULSE | HYPERTORUS_FLAG_EMP | HYPERTORUS_FLAG_MASSIVE_SPREAD | HYPERTORUS_FLAG_CRITICAL_MELTDOWN diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm index 3a6a3e8f85b4..03aa37895cd2 100644 --- a/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm +++ b/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm @@ -4,7 +4,7 @@ * fusion_process() handles all the main fusion reaction logic and consequences (lightning, radiation, particles) from an active fusion reaction. */ -/obj/machinery/atmospherics/components/unary/hypertorus/core/process(delta_time) +/obj/machinery/atmospherics/components/unary/hypertorus/core/process_atmos(delta_time) /* *Pre-checks */ @@ -101,9 +101,9 @@ //Calculation of the gas power, only for theoretical instability calculations var/gas_power = 0 for (var/gas_id in internal_fusion.get_gases()) - gas_power += (GLOB.meta_gas_info[gas_id][META_GAS_FUSION_POWER] * internal_fusion.get_moles(gas_id)) + gas_power += (GLOB.gas_data.fusion_powers[gas_id] * internal_fusion.get_moles(gas_id)) for (var/gas_id in moderator_internal.get_gases()) - gas_power += (GLOB.meta_gas_info[gas_id][META_GAS_FUSION_POWER] * moderator_internal.get_moles(gas_id) * 0.75) + gas_power += (GLOB.gas_data.fusion_powers[gas_id] * moderator_internal.get_moles(gas_id) * 0.75) instability = MODULUS((gas_power * INSTABILITY_GAS_POWER_FACTOR_HFR)**2, toroidal_size) + (current_damper * 0.01) - iron_content * 0.05 //Effective reaction instability (determines if the energy is used/released) @@ -118,37 +118,37 @@ */ ///Those are the scaled gases that gets consumed and adjust energy // Gases that increase the amount of energy - var/energy_modifiers = scaled_moderator_list[/datum/gas/nitrogen] * 0.35 + \ - scaled_moderator_list[/datum/gas/carbon_dioxide] * 0.55 + \ - scaled_moderator_list[/datum/gas/nitrous_oxide] * 0.95 + \ - scaled_moderator_list[/datum/gas/zauker] * 1.55 + \ - scaled_moderator_list[/datum/gas/antinoblium] * 20 + var/energy_modifiers = scaled_moderator_list[GAS_N2] * 0.35 + \ + scaled_moderator_list[GAS_CO2] * 0.55 + \ + scaled_moderator_list[GAS_NITROUS] * 0.95 + \ + scaled_moderator_list[GAS_ZAUKER] * 1.55 + \ + scaled_moderator_list[GAS_ANTINOB] * 20 // Gases that decrease the amount of energy - energy_modifiers -= scaled_moderator_list[/datum/gas/hypernoblium] * 10 + \ - scaled_moderator_list[/datum/gas/water_vapor] * 0.75 + \ - scaled_moderator_list[/datum/gas/nitrium] * 0.15 + \ - scaled_moderator_list[/datum/gas/healium] * 0.45 + \ - scaled_moderator_list[/datum/gas/freon] * 1.15 + energy_modifiers -= scaled_moderator_list[GAS_HYPERNOB] * 10 + \ + scaled_moderator_list[GAS_H2O] * 0.75 + \ + scaled_moderator_list[GAS_NITRIUM] * 0.15 + \ + scaled_moderator_list[GAS_HEALIUM] * 0.45 + \ + scaled_moderator_list[GAS_FREON] * 1.15 ///Between 0.25 and 100, this value is used to modify the behaviour of the internal energy and the core temperature based on the gases present in the mix - var/power_modifier = scaled_moderator_list[/datum/gas/oxygen] * 0.55 + \ - scaled_moderator_list[/datum/gas/carbon_dioxide] * 0.95 + \ - scaled_moderator_list[/datum/gas/nitrium] * 1.45 + \ - scaled_moderator_list[/datum/gas/zauker] * 5.55 + \ - scaled_moderator_list[/datum/gas/plasma] * 0.05 - \ - scaled_moderator_list[/datum/gas/nitrous_oxide] * 0.05 - \ - scaled_moderator_list[/datum/gas/freon] * 0.75 + var/power_modifier = scaled_moderator_list[GAS_O2] * 0.55 + \ + scaled_moderator_list[GAS_CO2] * 0.95 + \ + scaled_moderator_list[GAS_NITRIUM] * 1.45 + \ + scaled_moderator_list[GAS_ZAUKER] * 5.55 + \ + scaled_moderator_list[GAS_PLASMA] * 0.05 - \ + scaled_moderator_list[GAS_NITROUS] * 0.05 - \ + scaled_moderator_list[GAS_FREON] * 0.75 ///Minimum 0.25, this value is used to modify the behaviour of the energy emission based on the gases present in the mix - var/heat_modifier = scaled_moderator_list[/datum/gas/plasma] * 1.25 - \ - scaled_moderator_list[/datum/gas/nitrogen] * 0.75 - \ - scaled_moderator_list[/datum/gas/nitrous_oxide] * 1.45 - \ - scaled_moderator_list[/datum/gas/freon] * 0.95 + var/heat_modifier = scaled_moderator_list[GAS_PLASMA] * 1.25 - \ + scaled_moderator_list[GAS_N2] * 0.75 - \ + scaled_moderator_list[GAS_NITROUS] * 1.45 - \ + scaled_moderator_list[GAS_FREON] * 0.95 ///Between 0.005 and 1000, this value modify the radiation emission of the reaction, higher values increase the emission - var/radiation_modifier = scaled_moderator_list[/datum/gas/freon] * 1.15 - \ - scaled_moderator_list[/datum/gas/nitrogen] * 0.45 - \ - scaled_moderator_list[/datum/gas/plasma] * 0.95 + \ - scaled_moderator_list[/datum/gas/bz] * 1.9 + \ - scaled_moderator_list[/datum/gas/pluonium] * 0.1 + \ - scaled_moderator_list[/datum/gas/antinoblium] * 10 + var/radiation_modifier = scaled_moderator_list[GAS_FREON] * 1.15 - \ + scaled_moderator_list[GAS_N2] * 0.45 - \ + scaled_moderator_list[GAS_PLASMA] * 0.95 + \ + scaled_moderator_list[GAS_BZ] * 1.9 + \ + scaled_moderator_list[GAS_PLUONIUM] * 0.1 + \ + scaled_moderator_list[GAS_ANTINOB] * 10 if (selected_fuel) // These should probably be static coefficients read from a table rather than things that depend on the current recipe @@ -267,80 +267,80 @@ /obj/machinery/atmospherics/components/unary/hypertorus/core/proc/moderator_common_process(delta_time, scaled_production, datum/gas_mixture/internal_output, moderator_list, dirty_production_rate, heat_output, radiation_modifier) switch(power_level) if(1) - if(moderator_list[/datum/gas/plasma] > 100) - internal_output.adjust_moles(/datum/gas/nitrous_oxide, scaled_production * 0.5) - moderator_internal.adjust_moles(/datum/gas/plasma, -min(moderator_internal.get_moles(/datum/gas/plasma), scaled_production * 0.85)) - if(moderator_list[/datum/gas/bz] > 150) - internal_output.adjust_moles(/datum/gas/halon, scaled_production * 0.55) - moderator_internal.adjust_moles(/datum/gas/bz, -min(moderator_internal.get_moles(/datum/gas/bz), scaled_production * 0.95)) + if(moderator_list[GAS_PLASMA] > 100) + internal_output.adjust_moles(GAS_NITROUS, scaled_production * 0.5) + moderator_internal.adjust_moles(GAS_PLASMA, -min(moderator_internal.get_moles(GAS_PLASMA), scaled_production * 0.85)) + if(moderator_list[GAS_BZ] > 150) + internal_output.adjust_moles(GAS_HALON, scaled_production * 0.55) + moderator_internal.adjust_moles(GAS_BZ, -min(moderator_internal.get_moles(GAS_BZ), scaled_production * 0.95)) if(2) - if(moderator_list[/datum/gas/plasma] > 50) - internal_output.adjust_moles(/datum/gas/bz, scaled_production * 1.8) - moderator_internal.adjust_moles(/datum/gas/plasma, -min(moderator_internal.get_moles(/datum/gas/plasma), scaled_production * 1.75)) - if(moderator_list[/datum/gas/pluonium] > 20) + if(moderator_list[GAS_PLASMA] > 50) + internal_output.adjust_moles(GAS_BZ, scaled_production * 1.8) + moderator_internal.adjust_moles(GAS_PLASMA, -min(moderator_internal.get_moles(GAS_PLASMA), scaled_production * 1.75)) + if(moderator_list[GAS_PLUONIUM] > 20) radiation *= 1.55 heat_output *= 1.025 - moderator_internal.adjust_moles(/datum/gas/pluonium, -min(moderator_internal.get_moles(/datum/gas/pluonium), scaled_production * 1.35)) + moderator_internal.adjust_moles(GAS_PLUONIUM, -min(moderator_internal.get_moles(GAS_PLUONIUM), scaled_production * 1.35)) if(3, 4) - if(moderator_list[/datum/gas/plasma] > 10) - internal_output.adjust_moles(/datum/gas/freon, scaled_production * 0.15) - moderator_internal.adjust_moles(/datum/gas/plasma, -min(moderator_internal.get_moles(/datum/gas/plasma), scaled_production * 0.45)) - if(moderator_list[/datum/gas/freon] > 50) + if(moderator_list[GAS_PLASMA] > 10) + internal_output.adjust_moles(GAS_FREON, scaled_production * 0.15) + moderator_internal.adjust_moles(GAS_PLASMA, -min(moderator_internal.get_moles(GAS_PLASMA), scaled_production * 0.45)) + if(moderator_list[GAS_FREON] > 50) heat_output *= 0.9 radiation *= 0.8 - if(moderator_list[/datum/gas/pluonium]> 15) - internal_output.adjust_moles(/datum/gas/halon, scaled_production * 1.15) - moderator_internal.adjust_moles(/datum/gas/pluonium, -min(moderator_internal.get_moles(/datum/gas/pluonium), scaled_production * 1.55)) + if(moderator_list[GAS_PLUONIUM]> 15) + internal_output.adjust_moles(GAS_HALON, scaled_production * 1.15) + moderator_internal.adjust_moles(GAS_PLUONIUM, -min(moderator_internal.get_moles(GAS_PLUONIUM), scaled_production * 1.55)) radiation *= 1.95 heat_output *= 1.25 - if(moderator_list[/datum/gas/bz] > 100) - internal_output.adjust_moles(/datum/gas/pluonium, scaled_production * 1.5) - internal_output.adjust_moles(/datum/gas/healium, scaled_production * 1.5) + if(moderator_list[GAS_BZ] > 100) + internal_output.adjust_moles(GAS_PLUONIUM, scaled_production * 1.5) + internal_output.adjust_moles(GAS_HEALIUM, scaled_production * 1.5) induce_hallucination(50 * power_level, delta_time) if(5) - if(moderator_list[/datum/gas/plasma] > 15) - internal_output.adjust_moles(/datum/gas/freon, scaled_production * 0.25) - moderator_internal.adjust_moles(/datum/gas/plasma, -min(moderator_internal.get_moles(/datum/gas/plasma), scaled_production * 1.45)) - if(moderator_list[/datum/gas/freon] > 500) + if(moderator_list[GAS_PLASMA] > 15) + internal_output.adjust_moles(GAS_FREON, scaled_production * 0.25) + moderator_internal.adjust_moles(GAS_PLASMA, -min(moderator_internal.get_moles(GAS_PLASMA), scaled_production * 1.45)) + if(moderator_list[GAS_FREON] > 500) heat_output *= 0.5 radiation *= 0.2 - if(moderator_list[/datum/gas/pluonium] > 50) - internal_output.adjust_moles(/datum/gas/pluoxium, scaled_production) - moderator_internal.adjust_moles(/datum/gas/pluonium, -min(moderator_internal.get_moles(/datum/gas/pluonium), scaled_production * 1.35)) + if(moderator_list[GAS_PLUONIUM] > 50) + internal_output.adjust_moles(GAS_PLUOXIUM, scaled_production) + moderator_internal.adjust_moles(GAS_PLUONIUM, -min(moderator_internal.get_moles(GAS_PLUONIUM), scaled_production * 1.35)) radiation *= 1.95 heat_output *= 1.25 - if(moderator_list[/datum/gas/bz] > 100) - internal_output.adjust_moles(/datum/gas/healium, scaled_production) + if(moderator_list[GAS_BZ] > 100) + internal_output.adjust_moles(GAS_HEALIUM, scaled_production) induce_hallucination(500, delta_time) - internal_output.adjust_moles(/datum/gas/freon, scaled_production * 1.15) - if(moderator_list[/datum/gas/healium] > 100) + internal_output.adjust_moles(GAS_FREON, scaled_production * 1.15) + if(moderator_list[GAS_HEALIUM] > 100) if(critical_threshold_proximity > 400) - critical_threshold_proximity = max(critical_threshold_proximity - (moderator_list[/datum/gas/healium] / 100 * delta_time ), 0) - moderator_internal.adjust_moles(/datum/gas/healium, -min(moderator_internal.get_moles(/datum/gas/healium), scaled_production * 20)) - if(moderator_internal.return_temperature() < 1e7 || (moderator_list[/datum/gas/plasma] > 100 && moderator_list[/datum/gas/bz] > 50)) - internal_output.adjust_moles(/datum/gas/antinoblium, dirty_production_rate * 0.9 / 0.065 * delta_time) + critical_threshold_proximity = max(critical_threshold_proximity - (moderator_list[GAS_HEALIUM] / 100 * delta_time ), 0) + moderator_internal.adjust_moles(GAS_HEALIUM, -min(moderator_internal.get_moles(GAS_HEALIUM), scaled_production * 20)) + if(moderator_internal.return_temperature() < 1e7 || (moderator_list[GAS_PLASMA] > 100 && moderator_list[GAS_BZ] > 50)) + internal_output.adjust_moles(GAS_ANTINOB, dirty_production_rate * 0.9 / 0.065 * delta_time) if(6) - if(moderator_list[/datum/gas/plasma] > 30) - internal_output.adjust_moles(/datum/gas/bz, scaled_production * 1.15) - moderator_internal.adjust_moles(/datum/gas/plasma, -min(moderator_internal.get_moles(/datum/gas/plasma), scaled_production * 1.45)) - if(moderator_list[/datum/gas/pluonium]) - internal_output.adjust_moles(/datum/gas/zauker, scaled_production * 5.35) - internal_output.adjust_moles(/datum/gas/nitrium, scaled_production * 2.15) - moderator_internal.adjust_moles(/datum/gas/pluonium, -min(moderator_internal.get_moles(/datum/gas/pluonium), scaled_production * 3.35)) + if(moderator_list[GAS_PLASMA] > 30) + internal_output.adjust_moles(GAS_BZ, scaled_production * 1.15) + moderator_internal.adjust_moles(GAS_PLASMA, -min(moderator_internal.get_moles(GAS_PLASMA), scaled_production * 1.45)) + if(moderator_list[GAS_PLUONIUM]) + internal_output.adjust_moles(GAS_ZAUKER, scaled_production * 5.35) + internal_output.adjust_moles(GAS_NITRIUM, scaled_production * 2.15) + moderator_internal.adjust_moles(GAS_PLUONIUM, -min(moderator_internal.get_moles(GAS_PLUONIUM), scaled_production * 3.35)) radiation *= 2 heat_output *= 2.25 - if(moderator_list[/datum/gas/bz]) + if(moderator_list[GAS_BZ]) induce_hallucination(900, delta_time, force=TRUE) - internal_output.adjust_moles(/datum/gas/antinoblium, clamp(dirty_production_rate / 0.045, 0, 10) * delta_time) - if(moderator_list[/datum/gas/healium] > 100) + internal_output.adjust_moles(GAS_ANTINOB, clamp(dirty_production_rate / 0.045, 0, 10) * delta_time) + if(moderator_list[GAS_HEALIUM] > 100) if(critical_threshold_proximity > 400) - critical_threshold_proximity = max(critical_threshold_proximity - (moderator_list[/datum/gas/healium] / 100 * delta_time ), 0) - moderator_internal.adjust_moles(/datum/gas/healium, -min(moderator_internal.get_moles(/datum/gas/healium), scaled_production * 20)) - internal_fusion.adjust_moles(/datum/gas/antinoblium, dirty_production_rate * 0.01 / 0.095 * delta_time) + critical_threshold_proximity = max(critical_threshold_proximity - (moderator_list[GAS_HEALIUM] / 100 * delta_time ), 0) + moderator_internal.adjust_moles(GAS_HEALIUM, -min(moderator_internal.get_moles(GAS_HEALIUM), scaled_production * 20)) + internal_fusion.adjust_moles(GAS_ANTINOB, dirty_production_rate * 0.01 / 0.095 * delta_time) //Modifies the internal_fusion temperature with the amount of heat output var/temperature_modifier = selected_fuel.temperature_change_multiplier @@ -364,12 +364,12 @@ check_lightning_arcs(moderator_list) // Oxygen burns away iron content rapidly - if(moderator_list[/datum/gas/oxygen] > 150) + if(moderator_list[GAS_O2] > 150) if(iron_content > 0) var/max_iron_removable = IRON_OXYGEN_HEAL_PER_SECOND var/iron_removed = min(max_iron_removable * delta_time, iron_content) iron_content -= iron_removed - moderator_internal.adjust_moles(/datum/gas/oxygen, -(iron_removed * OXYGEN_MOLES_CONSUMED_PER_IRON_HEAL)) + moderator_internal.adjust_moles(GAS_O2, -(iron_removed * OXYGEN_MOLES_CONSUMED_PER_IRON_HEAL)) check_gravity_pulse(delta_time) @@ -435,7 +435,7 @@ if(power_level < 4) return - if(moderator_list[/datum/gas/bz] < (150 / power_level)) + if(moderator_list[GAS_BZ] < (150 / power_level)) return var/obj/machinery/hypertorus/corner/picked_corner = pick(corners) @@ -444,7 +444,7 @@ /obj/machinery/atmospherics/components/unary/hypertorus/core/proc/check_lightning_arcs(moderator_list) if(power_level < 4) return - if(moderator_list[/datum/gas/antinoblium] <= 50 && critical_threshold_proximity <= 500) + if(moderator_list[GAS_ANTINOB] <= 50 && critical_threshold_proximity <= 500) return var/zap_number = power_level - 2 diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm index d62493a59090..ecb4e063594f 100644 --- a/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm +++ b/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm @@ -58,18 +58,18 @@ /obj/machinery/atmospherics/components/unary/hypertorus/default_change_direction_wrench(mob/user, obj/item/I) . = ..() if(.) - SetInitDirections() + set_init_directions() var/obj/machinery/atmospherics/node = nodes[1] if(node) node.disconnect(src) nodes[1] = null if(parents[1]) - nullifyPipenet(parents[1]) - atmosinit() + nullify_pipenet(parents[1]) + atmos_init() node = nodes[1] if(node) - node.atmosinit() - node.addMember(src) + node.atmos_init() + node.add_member(src) SSair.add_to_rebuild_queue(src) /obj/machinery/atmospherics/components/unary/hypertorus/update_icon_state() @@ -202,15 +202,6 @@ else to_chat(user, span_notice("Activate the machine first by using a multitool on the interface.")) -/obj/machinery/hypertorus/interface/proc/gas_list_to_gasid_list(list/gas_list) - var/list/gasid_list = list() - for(var/gas_type in gas_list) - var/datum/gas/gas = gas_type - gasid_list += initial(gas.id) - return gasid_list - - - /obj/machinery/hypertorus/interface/ui_static_data() var/data = list() data["base_max_temperature"] = FUSION_MAXIMUM_TEMPERATURE @@ -221,9 +212,9 @@ data["selectable_fuel"] += list(list( "name" = recipe.name, "id" = recipe.id, - "requirements" = gas_list_to_gasid_list(recipe.requirements), - "fusion_byproducts" = gas_list_to_gasid_list(recipe.primary_products), - "product_gases" = gas_list_to_gasid_list(recipe.secondary_products), + "requirements" = recipe.requirements, + "fusion_byproducts" = recipe.primary_products, + "product_gases" = recipe.secondary_products, "recipe_cooling_multiplier" = recipe.negative_temperature_multiplier, "recipe_heating_multiplier" = recipe.positive_temperature_multiplier, "energy_loss_multiplier" = recipe.energy_concentration_multiplier, @@ -231,6 +222,14 @@ "gas_production_multiplier" = recipe.gas_production_multiplier, "temperature_multiplier" = recipe.temperature_change_multiplier, )) + + data["gas_data"] = list() + for(var/gas_id in GLOB.gas_data.ids) + data["gas_data"] += list(list( + "id" = gas_id, + "label" = GLOB.gas_data.labels[gas_id], + "ui_color" = GLOB.gas_data.ui_colors[gas_id], + )) return data /obj/machinery/hypertorus/interface/ui_data() @@ -244,35 +243,31 @@ //Internal Fusion gases var/list/fusion_gasdata = list() if(connected_core.internal_fusion.total_moles()) - for(var/gas_type in connected_core.internal_fusion.get_gases()) - var/datum/gas/gas = gas_type + for(var/gas_id in connected_core.internal_fusion.get_gases()) fusion_gasdata.Add(list(list( - "id"= initial(gas.id), - "amount" = round(connected_core.internal_fusion.get_moles(gas), 0.01), + "id"= initial(gas_id), + "amount" = round(connected_core.internal_fusion.get_moles(gas_id), 0.01), ))) else - for(var/gas_type in connected_core.internal_fusion.get_gases()) - var/datum/gas/gas = gas_type + for(var/gas_id in connected_core.internal_fusion.get_gases()) fusion_gasdata.Add(list(list( - "id"= initial(gas.id), + "id"= initial(gas_id), "amount" = 0, - ))) + ))) //Moderator gases var/list/moderator_gasdata = list() if(connected_core.moderator_internal.total_moles()) - for(var/gas_type in connected_core.moderator_internal.get_gases()) - var/datum/gas/gas = gas_type + for(var/gas_id in connected_core.moderator_internal.get_gases()) moderator_gasdata.Add(list(list( - "id"= initial(gas.id), - "amount" = round(connected_core.moderator_internal.get_moles(gas), 0.01), + "id"= initial(gas_id), + "amount" = round(connected_core.moderator_internal.get_moles(gas_id), 0.01), ))) else - for(var/gas_type in connected_core.moderator_internal.get_gases()) - var/datum/gas/gas = gas_type + for(var/gas_id in connected_core.moderator_internal.get_gases()) moderator_gasdata.Add(list(list( - "id"= initial(gas.id), + "id"= initial(gas_id), "amount" = 0, - ))) + ))) data["fusion_gases"] = fusion_gasdata data["moderator_gases"] = moderator_gasdata @@ -314,9 +309,8 @@ data["waste_remove"] = connected_core.waste_remove data["fuel_remove"] = connected_core.fuel_remove data["filter_types"] = list() - for(var/path in GLOB.meta_gas_info) - var/list/gas = GLOB.meta_gas_info[path] - data["filter_types"] += list(list("gas_id" = gas[META_GAS_ID], "gas_name" = gas[META_GAS_NAME], "enabled" = (path in connected_core.moderator_scrubbing))) + for(var/id in GLOB.gas_data.ids) + data["filter_types"] += list(list("gas_id" = id, "gas_name" = GLOB.gas_data.labels[id], "enabled" = (id in connected_core.moderator_scrubbing))) data["cooling_volume"] = connected_core.airs[1].return_volume() data["mod_filtering_rate"] = connected_core.moderator_filtering_rate @@ -374,7 +368,9 @@ connected_core.fuel_remove = !connected_core.fuel_remove . = TRUE if("filter") - connected_core.moderator_scrubbing ^= gas_id2path(params["mode"]) + var/gas = params["mode"] + if(gas in GLOB.gas_data.names) + connected_core.moderator_scrubbing ^= gas . = TRUE if("mod_filtering_rate") var/mod_filtering_rate = text2num(params["mod_filtering_rate"]) diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_procs.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_procs.dm index 70469590ed12..e6e67f3c501f 100644 --- a/code/modules/atmospherics/machinery/components/fusion/hfr_procs.dm +++ b/code/modules/atmospherics/machinery/components/fusion/hfr_procs.dm @@ -173,13 +173,13 @@ /obj/machinery/atmospherics/components/unary/hypertorus/core/proc/update_temperature_status(delta_time) fusion_temperature_archived = fusion_temperature - fusion_temperature = internal_fusion.return_temperature() + fusion_temperature = internal_fusion.total_moles() == 0 ? 0 : internal_fusion.return_temperature() moderator_temperature_archived = moderator_temperature - moderator_temperature = moderator_internal.return_temperature() + moderator_temperature = moderator_internal.total_moles() == 0 ? 0 : moderator_internal.return_temperature() coolant_temperature_archived = coolant_temperature - coolant_temperature = airs[1].return_temperature() + coolant_temperature = airs[1].total_moles() == 0 ? 0 : airs[1].return_temperature() output_temperature_archived = output_temperature - output_temperature = linked_output.airs[1].return_temperature() + output_temperature = linked_output.airs[1].total_moles() == 0 ? 0 : linked_output.airs[1].return_temperature() temperature_period = delta_time //Set the power level of the fusion process @@ -439,8 +439,7 @@ var/devastating_explosion = 0 var/em_pulse = selected_fuel.meltdown_flags & HYPERTORUS_FLAG_EMP var/rad_pulse = selected_fuel.meltdown_flags & HYPERTORUS_FLAG_RADIATION_PULSE - var/emp_light_size = 0 - var/emp_heavy_size = 0 + var/emp_severity = 0 var/rad_pulse_size = 0 var/rad_pulse_strength = 0 var/gas_spread = 0 @@ -464,8 +463,7 @@ if(selected_fuel.meltdown_flags & HYPERTORUS_FLAG_MINIMUM_SPREAD) if(em_pulse) - emp_light_size = power_level * 3 - emp_heavy_size = power_level * 1 + emp_severity = power_level * 3 if(rad_pulse) rad_pulse_size = (1 / (power_level + 1)) rad_pulse_strength = power_level * 3000 @@ -474,8 +472,7 @@ if(selected_fuel.meltdown_flags & HYPERTORUS_FLAG_MEDIUM_SPREAD) if(em_pulse) - emp_light_size = power_level * 5 - emp_heavy_size = power_level * 3 + emp_severity = power_level * 5 if(rad_pulse) rad_pulse_size = (1 / (power_level + 3)) rad_pulse_strength = power_level * 5000 @@ -484,8 +481,7 @@ if(selected_fuel.meltdown_flags & HYPERTORUS_FLAG_BIG_SPREAD) if(em_pulse) - emp_light_size = power_level * 7 - emp_heavy_size = power_level * 5 + emp_severity = power_level * 7 if(rad_pulse) rad_pulse_size = (1 / (power_level + 5)) rad_pulse_strength = power_level * 7000 @@ -494,8 +490,7 @@ if(selected_fuel.meltdown_flags & HYPERTORUS_FLAG_MASSIVE_SPREAD) if(em_pulse) - emp_light_size = power_level * 9 - emp_heavy_size = power_level * 7 + emp_severity = power_level * 9 if(rad_pulse) rad_pulse_size = (1 / (power_level + 7)) rad_pulse_strength = power_level * 9000 @@ -550,8 +545,7 @@ if(em_pulse) empulse( epicenter = loc, - heavy_range = critical ? emp_heavy_size * 2 : emp_heavy_size, - light_range = critical ? emp_light_size * 2 : emp_heavy_size, + severity = critical ? emp_severity * 2 : emp_severity, log = TRUE ) diff --git a/code/modules/atmospherics/machinery/components/gas_recipe_machines/atmos_machines_recipes.dm b/code/modules/atmospherics/machinery/components/gas_recipe_machines/atmos_machines_recipes.dm index ef482c77ca06..46b8e98b9566 100644 --- a/code/modules/atmospherics/machinery/components/gas_recipe_machines/atmos_machines_recipes.dm +++ b/code/modules/atmospherics/machinery/components/gas_recipe_machines/atmos_machines_recipes.dm @@ -42,7 +42,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = 50000 max_temp = 150000 energy_release = -2500000 - requirements = list(/datum/gas/hydrogen = 300, /datum/gas/bz = 50) + requirements = list(GAS_H2 = 300, GAS_BZ = 50) products = list(/obj/item/stack/sheet/mineral/metal_hydrogen = 1) /datum/gas_recipe/crystallizer/supermatter_extraction_tongs @@ -51,7 +51,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = 50000 max_temp = 150000 energy_release = -150000 - requirements = list(/datum/gas/hydrogen = 100, /datum/gas/hypernoblium = 5, /datum/gas/bz = 5) + requirements = list(GAS_H2 = 100, GAS_HYPERNOB = 5, GAS_BZ = 5) products = list(/obj/item/hemostat/supermatter = 1) /datum/gas_recipe/crystallizer/supermatter_base_structure @@ -60,7 +60,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = 50000 max_temp = 150000 energy_release = -200000 - requirements = list(/datum/gas/hydrogen = 1000, /datum/gas/bz = 100, /datum/gas/hypernoblium = 10) + requirements = list(GAS_H2 = 1000, GAS_BZ = 100, GAS_HYPERNOB = 10) products = list(/obj/structure/supermatter_base_structure = 1) /datum/gas_recipe/crystallizer/healium_grenade @@ -69,7 +69,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = 200 max_temp = 400 energy_release = -2000000 - requirements = list(/datum/gas/healium = 100, /datum/gas/freon = 120, /datum/gas/plasma = 50) + requirements = list(GAS_HEALIUM = 100, GAS_FREON = 120, GAS_PLASMA = 50) products = list(/obj/item/grenade/gas_crystal/healium_crystal = 1) /datum/gas_recipe/crystallizer/pluonium_grenade @@ -78,7 +78,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = 200 max_temp = 400 energy_release = 1500000 - requirements = list(/datum/gas/pluonium = 100, /datum/gas/nitrogen = 80, /datum/gas/oxygen = 80) + requirements = list(GAS_PLUONIUM = 100, GAS_N2 = 80, GAS_O2 = 80) products = list(/obj/item/grenade/gas_crystal/pluonium_crystal = 1) /datum/gas_recipe/crystallizer/hot_ice @@ -87,7 +87,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = 15 max_temp = 35 energy_release = -3000000 - requirements = list(/datum/gas/freon = 60, /datum/gas/plasma = 160, /datum/gas/oxygen = 80) + requirements = list(GAS_FREON = 60, GAS_PLASMA = 160, GAS_O2 = 80) products = list(/obj/item/stack/sheet/hot_ice = 1) /datum/gas_recipe/crystallizer/ammonia_crystal @@ -96,7 +96,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = 200 max_temp = 240 energy_release = 950000 - requirements = list(/datum/gas/hydrogen = 50, /datum/gas/nitrogen = 40) + requirements = list(GAS_H2 = 50, GAS_N2 = 40) products = list(/obj/item/stack/ammonia_crystals = 2) /datum/gas_recipe/crystallizer/tesla @@ -106,7 +106,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) max_temp = 12000 energy_release = -350000 dangerous = TRUE - requirements = list(/datum/gas/nitrium = 500, /datum/gas/freon = 500, /datum/gas/tritium = 500) + requirements = list(GAS_TRITIUM = 500, GAS_FREON = 500, GAS_NITRIUM = 500) products = list(/obj/machinery/the_singularitygen/tesla = 1) /datum/gas_recipe/crystallizer/supermatter_silver @@ -116,7 +116,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) max_temp = 200000 energy_release = -250000 dangerous = TRUE - requirements = list(/datum/gas/bz = 100, /datum/gas/hypernoblium = 125, /datum/gas/tritium = 250, /datum/gas/plasma = 750) + requirements = list(GAS_BZ = 100, GAS_HYPERNOB = 125, GAS_TRITIUM = 250, GAS_PLASMA = 750) products = list(/obj/item/nuke_core/supermatter_sliver = 1) /datum/gas_recipe/crystallizer/n2o_crystal @@ -125,7 +125,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = 50 max_temp = 350 energy_release = 3500000 - requirements = list(/datum/gas/nitrous_oxide = 100, /datum/gas/bz = 5) + requirements = list(GAS_NITROUS = 100, GAS_BZ = 5) products = list(/obj/item/grenade/gas_crystal/nitrous_oxide_crystal = 1) /datum/gas_recipe/crystallizer/diamond @@ -134,7 +134,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = 10000 max_temp = 30000 energy_release = -9500000 - requirements = list(/datum/gas/carbon_dioxide = 10000) + requirements = list(GAS_CO2 = 10000) products = list(/obj/item/stack/sheet/mineral/diamond = 1) /datum/gas_recipe/crystallizer/uranium @@ -143,7 +143,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = 1000 max_temp = 5000 energy_release = -2500000 - requirements = list(/datum/gas/tritium = 200, /datum/gas/hypernoblium = 50) + requirements = list(GAS_TRITIUM = 200, GAS_HYPERNOB = 50) products = list(/obj/item/stack/sheet/mineral/uranium = 1) /datum/gas_recipe/crystallizer/plasma_sheet @@ -152,7 +152,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = 10 max_temp = 20 energy_release = 3500000 - requirements = list(/datum/gas/plasma = 450) + requirements = list(GAS_PLASMA = 450) products = list(/obj/item/stack/sheet/mineral/plasma = 1) /datum/gas_recipe/crystallizer/crystal_cell @@ -161,7 +161,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = 50 max_temp = 90 energy_release = -800000 - requirements = list(/datum/gas/plasma = 800, /datum/gas/healium = 100, /datum/gas/bz = 50) + requirements = list(GAS_PLASMA = 800, GAS_HEALIUM = 100, GAS_BZ = 50) products = list(/obj/item/stock_parts/cell/crystal_cell = 1) /datum/gas_recipe/crystallizer/zaukerite @@ -170,7 +170,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = 5 max_temp = 20 energy_release = 2900000 - requirements = list(/datum/gas/hypernoblium = 5, /datum/gas/zauker = 10, /datum/gas/bz = 7.5) + requirements = list(GAS_HYPERNOB = 5, GAS_ZAUKER = 10, GAS_BZ = 7.5) products = list(/obj/item/stack/sheet/mineral/zaukerite = 2) /datum/gas_recipe/crystallizer/hypernoblium_crystal @@ -179,7 +179,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = 100000 max_temp = 200000 energy_release = 2800000 - requirements = list(/datum/gas/bz = 100, /datum/gas/hypernoblium = 100, /datum/gas/oxygen = 1000) + requirements = list(GAS_BZ = 100, GAS_HYPERNOB = 100, GAS_O2 = 1000) products = list(/obj/item/stack/hypernoblium_crystal = 1) /datum/gas_recipe/crystallizer/antinoblium_crystal @@ -188,7 +188,7 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = TCMB max_temp = TCMB + 20 energy_release = 2800000 - requirements = list(/datum/gas/antinoblium = 100, /datum/gas/bz = 30, /datum/gas/plasma = 100) + requirements = list(GAS_ANTINOB = 100, GAS_BZ = 30, GAS_PLASMA = 100) products = list(/obj/item/stack/antinoblium_crystal = 1) /datum/gas_recipe/crystallizer/crystallized_nitrium @@ -197,5 +197,5 @@ GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list()) min_temp = 10 max_temp = 25 energy_release = 45000 - requirements = list(/datum/gas/nitrium = 150, /datum/gas/oxygen = 70, /datum/gas/bz = 50) + requirements = list(GAS_NITRIUM = 150, GAS_O2 = 70, GAS_BZ = 50) products = list(/obj/item/nitrium_crystal = 1) diff --git a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm index 6c50495de769..f60149ae6115 100644 --- a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm +++ b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm @@ -50,7 +50,7 @@ . = ..() if(!.) return FALSE - SetInitDirections() + set_init_directions() var/obj/machinery/atmospherics/node1 = nodes[1] var/obj/machinery/atmospherics/node2 = nodes[2] if(node1) @@ -63,27 +63,27 @@ nodes[2] = null if(parents[1]) - nullifyPipenet(parents[1]) + nullify_pipenet(parents[1]) if(parents[2]) - nullifyPipenet(parents[2]) + nullify_pipenet(parents[2]) - atmosinit() + atmos_init() node1 = nodes[1] if(node1) - node1.atmosinit() - node1.addMember(src) + node1.atmos_init() + node1.add_member(src) node2 = nodes[2] if(node2) - node2.atmosinit() - node2.addMember(src) + node2.atmos_init() + node2.add_member(src) SSair.add_to_rebuild_queue(src) return TRUE /obj/machinery/atmospherics/components/binary/crystallizer/update_overlays() . = ..() cut_overlays() - . += getpipeimage(icon, "pipe", dir, COLOR_LIME, piping_layer) - . += getpipeimage(icon, "pipe", turn(dir, 180), COLOR_RED, piping_layer) + . += get_pipe_image(icon, "pipe", dir, COLOR_LIME, piping_layer) + . += get_pipe_image(icon, "pipe", turn(dir, 180), COLOR_RED, piping_layer) /obj/machinery/atmospherics/components/binary/crystallizer/update_icon_state() . = ..() @@ -275,14 +275,16 @@ if(internal.total_moles()) for(var/gasid in internal.get_gases()) internal_gas_data.Add(list(list( - "name"= GLOB.meta_gas_info[gasid][META_GAS_NAME], + "name"= GLOB.gas_data.names[gasid], "amount" = round(internal.get_moles(gasid), 0.01), + "color" = GLOB.gas_data.ui_colors[gasid], ))) else for(var/gasid in internal.get_gases()) internal_gas_data.Add(list(list( - "name"= GLOB.meta_gas_info[gasid][META_GAS_NAME], + "name"= GLOB.gas_data.names[gasid], "amount" = 0, + "color" = GLOB.gas_data.ui_colors[gasid], ))) data["internal_gas_data"] = internal_gas_data @@ -292,9 +294,8 @@ else requirements = list("To create [selected_recipe.name] you will need:") for(var/gas_type in selected_recipe.requirements) - var/datum/gas/gas_required = gas_type var/amount_consumed = selected_recipe.requirements[gas_type] - requirements += "-[amount_consumed] moles of [initial(gas_required.name)]" + requirements += "-[amount_consumed] moles of [initial(gas_type)]" requirements += "In a temperature range between [selected_recipe.min_temp] K and [selected_recipe.max_temp] K" requirements += "The crystallization reaction will be [selected_recipe.energy_release ? (selected_recipe.energy_release > 0 ? "exothermic" : "endothermic") : "thermally neutral"]" data["requirements"] = requirements.Join("\n") diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm index 077d38c368b5..6cb832ecace7 100644 --- a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm +++ b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm @@ -49,13 +49,13 @@ for(var/direction in GLOB.cardinals) if(!(direction & initialize_directions)) continue - var/obj/machinery/atmospherics/node = findConnecting(direction) + var/obj/machinery/atmospherics/node = find_connecting(direction) var/image/cap if(node) - cap = getpipeimage(icon, "cap", direction, node.pipe_color, piping_layer = piping_layer, trinary = TRUE) + cap = get_pipe_image(icon, "cap", direction, node.pipe_color, piping_layer = piping_layer, trinary = TRUE) else - cap = getpipeimage(icon, "cap", direction, piping_layer = piping_layer, trinary = TRUE) + cap = get_pipe_image(icon, "cap", direction, piping_layer = piping_layer, trinary = TRUE) . += cap @@ -64,7 +64,6 @@ icon_state = "filter_[on_state ? "on" : "off"]-[set_overlay_offset(piping_layer)][flipped ? "_f" : ""]" /obj/machinery/atmospherics/components/trinary/filter/process_atmos() - ..() if(!on || !(nodes[1] && nodes[2] && nodes[3]) || !is_operational()) return @@ -128,7 +127,7 @@ update_parents() -/obj/machinery/atmospherics/components/trinary/filter/atmosinit() +/obj/machinery/atmospherics/components/trinary/filter/atmos_init() set_frequency(frequency) return ..() @@ -145,9 +144,8 @@ data["max_rate"] = round(MAX_TRANSFER_RATE) data["filter_types"] = list() - for(var/path in GLOB.meta_gas_info) - var/list/gas = GLOB.meta_gas_info[path] - data["filter_types"] += list(list("name" = gas[META_GAS_NAME], "gas_id" = gas[META_GAS_ID], "enabled" = (path in filter_type))) + for(var/id in GLOB.gas_data.ids) + data["filter_types"] += list(list("name" = GLOB.gas_data.labels[id], "gas_id" = id, "enabled" = (id in filter_type))) return data @@ -179,16 +177,15 @@ investigate_log(msg, INVESTIGATE_ATMOS) investigate_log(msg, INVESTIGATE_SUPERMATTER) // yogs - make supermatter invest useful if("toggle_filter") - if(!gas_id2path(params["val"])) - return TRUE - filter_type ^= gas_id2path(params["val"]) + var/gas = params["val"] + if(gas in GLOB.gas_data.names) + filter_type ^= gas var/change - if(gas_id2path(params["val"]) in filter_type) + if(gas in filter_type) change = "added" else change = "removed" - var/gas_name = GLOB.meta_gas_info[gas_id2path(params["val"])][META_GAS_NAME] - var/msg = "[key_name(usr)] [change] [gas_name] from the filter type." + var/msg = "[key_name(usr)] [change] [gas] from the filter type." investigate_log(msg, INVESTIGATE_ATMOS) investigate_log(msg, INVESTIGATE_SUPERMATTER) // yogs - make supermatter invest useful . = TRUE @@ -247,38 +244,38 @@ icon_state = "filter_on-0" /obj/machinery/atmospherics/components/trinary/filter/atmos/n2 name = "Nitrogen filter (N2)" - filter_type = list(/datum/gas/nitrogen) + filter_type = list(GAS_N2) /obj/machinery/atmospherics/components/trinary/filter/atmos/o2 name = "Oxygen filter (O2)" - filter_type = list(/datum/gas/oxygen) + filter_type = list(GAS_O2) /obj/machinery/atmospherics/components/trinary/filter/atmos/co2 name = "Carbon dioxide filter (CO2)" - filter_type = list(/datum/gas/carbon_dioxide) + filter_type = list(GAS_CO2) /obj/machinery/atmospherics/components/trinary/filter/atmos/n2o name = "Nitrous oxide filter (N2O)" - filter_type = list(/datum/gas/nitrous_oxide) + filter_type = list(GAS_NITROUS) /obj/machinery/atmospherics/components/trinary/filter/atmos/plasma name = "Plasma filter" - filter_type = list(/datum/gas/plasma) + filter_type = list(GAS_PLASMA) /obj/machinery/atmospherics/components/trinary/filter/atmos/flipped //This feels wrong, I know icon_state = "filter_on-0_f" flipped = TRUE /obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/n2 name = "Nitrogen filter (N2)" - filter_type = list(/datum/gas/nitrogen) + filter_type = list(GAS_N2) /obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/o2 name = "Oxygen filter (O2)" - filter_type = list(/datum/gas/oxygen) + filter_type = list(GAS_O2) /obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/co2 name = "Carbon dioxide filter (CO2)" - filter_type = list(/datum/gas/carbon_dioxide) + filter_type = list(GAS_CO2) /obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/n2o name = "Nitrous oxide filter (N2O)" - filter_type = list(/datum/gas/nitrous_oxide) + filter_type = list(GAS_NITROUS) /obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/plasma name = "Plasma filter" - filter_type = list(/datum/gas/plasma) + filter_type = list(GAS_PLASMA) // These two filter types have critical_machine flagged to on and thus causes the area they are in to be exempt from the Grid Check event. diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm index 8863b9431f49..b04219514e37 100644 --- a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm +++ b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm @@ -36,13 +36,13 @@ for(var/direction in GLOB.cardinals) if(!(direction & initialize_directions)) continue - var/obj/machinery/atmospherics/node = findConnecting(direction) + var/obj/machinery/atmospherics/node = find_connecting(direction) var/image/cap if(node) - cap = getpipeimage(icon, "cap", direction, node.pipe_color, piping_layer = piping_layer, trinary = TRUE) + cap = get_pipe_image(icon, "cap", direction, node.pipe_color, piping_layer = piping_layer, trinary = TRUE) else - cap = getpipeimage(icon, "cap", direction, piping_layer = piping_layer, trinary = TRUE) + cap = get_pipe_image(icon, "cap", direction, piping_layer = piping_layer, trinary = TRUE) . += cap @@ -57,7 +57,6 @@ airs[3] = air3 /obj/machinery/atmospherics/components/trinary/mixer/process_atmos() - ..() if(!on || !(nodes[1] && nodes[2] && nodes[3]) && !is_operational()) return @@ -109,19 +108,17 @@ //Actually transfer the gas if(transfer_moles1) - var/datum/gas_mixture/removed1 = air1.remove(transfer_moles1) - air3.merge(removed1) + air1.transfer_to(air3, transfer_moles1) var/datum/pipeline/parent1 = parents[1] - parent1.update = TRUE + parent1.update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED if(transfer_moles2) - var/datum/gas_mixture/removed2 = air2.remove(transfer_moles2) - air3.merge(removed2) + air2.transfer_to(air3, transfer_moles2) var/datum/pipeline/parent2 = parents[2] - parent2.update = TRUE + parent2.update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED var/datum/pipeline/parent3 = parents[3] - parent3.update = TRUE + parent3.update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED /obj/machinery/atmospherics/components/trinary/mixer/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) @@ -255,7 +252,7 @@ on = TRUE icon_state = "t_mixer_on-0" -/obj/machinery/atmospherics/components/trinary/mixer/t_mixer/SetInitDirections() +/obj/machinery/atmospherics/components/trinary/mixer/t_mixer/set_init_directions() switch(dir) if(NORTH) initialize_directions = EAST|NORTH|WEST @@ -266,7 +263,7 @@ if(WEST) initialize_directions = WEST|NORTH|SOUTH -/obj/machinery/atmospherics/components/trinary/mixer/t_mixer/getNodeConnects() +/obj/machinery/atmospherics/components/trinary/mixer/t_mixer/get_node_connects() var/node1_connect = turn(dir, -90) var/node2_connect = turn(dir, 90) var/node3_connect = dir diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/trinary_devices.dm b/code/modules/atmospherics/machinery/components/trinary_devices/trinary_devices.dm index c587b1b1b630..d711d65ec4d4 100644 --- a/code/modules/atmospherics/machinery/components/trinary_devices/trinary_devices.dm +++ b/code/modules/atmospherics/machinery/components/trinary_devices/trinary_devices.dm @@ -9,7 +9,7 @@ var/flipped = FALSE -/obj/machinery/atmospherics/components/trinary/SetInitDirections() +/obj/machinery/atmospherics/components/trinary/set_init_directions() switch(dir) if(NORTH) initialize_directions = EAST|NORTH|SOUTH @@ -24,7 +24,7 @@ Housekeeping and pipe network stuff */ -/obj/machinery/atmospherics/components/trinary/getNodeConnects() +/obj/machinery/atmospherics/components/trinary/get_node_connects() //Mixer: //1 and 2 is input diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 5eb2f8366c76..7e9740b47a36 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -257,28 +257,29 @@ GLOBAL_VAR_INIT(cryo_overlay_cover_off, mutable_appearance('icons/obj/cryogenics if(reagent_transfer == 0) // Magically transfer reagents. Because cryo magic. beaker.reagents.trans_to(occupant, 1, efficiency * 0.25) // Transfer reagents. beaker.reagents.reaction(occupant, VAPOR) - if(air1.get_moles(/datum/gas/pluoxium) > 5 )//Use pluoxium over oxygen - air1.adjust_moles(/datum/gas/pluoxium, -max(0,air1.get_moles(/datum/gas/pluoxium) - 0.5 / efficiency)) - else - air1.adjust_moles(/datum/gas/oxygen, -max(0,air1.get_moles(/datum/gas/oxygen) - 2 / efficiency)) //Let's use gas for this + if(air1.get_moles(GAS_PLUOXIUM) > 5 )//Use pluoxium over oxygen + air1.adjust_moles(GAS_PLUOXIUM, -max(0,air1.get_moles(GAS_PLUOXIUM) - 0.5 / efficiency)) + else + air1.adjust_moles(GAS_O2, -max(0,air1.get_moles(GAS_O2) - 2 / efficiency)) //Let's use gas for this if(occupant.reagents.get_reagent_amount(/datum/reagent/medicine/cryoxadone) >= 100) //prevent cryoxadone overdose occupant.reagents.del_reagent(/datum/reagent/medicine/cryoxadone) occupant.reagents.add_reagent(/datum/reagent/medicine/cryoxadone, 99) reagent_transfer += 0.5 * delta_time if(reagent_transfer >= 10 * efficiency) // Throttle reagent transfer (higher efficiency will transfer the same amount but consume less from the beaker). reagent_transfer = 0 - + if(air1.get_moles(GAS_HEALIUM) > 1) //healium check, if theres enough we get some extra healing from our favorite pink gas. + var/existing = mob_occupant.reagents.get_reagent_amount(/datum/reagent/healium) + mob_occupant.reagents.add_reagent(/datum/reagent/healium, 1 - existing) + air1.set_moles(GAS_HEALIUM, -max(0, air1.get_moles(GAS_HEALIUM) - 0.1 / efficiency)) return 1 -/obj/machinery/atmospherics/components/unary/cryo_cell/process_atmos(delta_time) - ..() - +/obj/machinery/atmospherics/components/unary/cryo_cell/process_atmos() if(!on) return var/datum/gas_mixture/air1 = airs[1] - if(!nodes[1] || !airs[1] || (air1.get_moles(/datum/gas/oxygen) < 5 && air1.get_moles(/datum/gas/pluoxium) < 5)) // Turn off if the machine won't work. + if(!nodes[1] || !airs[1] || (air1.get_moles(GAS_O2) < 5 && air1.get_moles(GAS_PLUOXIUM) < 5)) // Turn off if the machine won't work. set_on(FALSE) return @@ -299,10 +300,10 @@ GLOBAL_VAR_INIT(cryo_overlay_cover_off, mutable_appearance('icons/obj/cryogenics air1.set_temperature(max(air1.return_temperature() - heat / air_heat_capacity, TCMB)) mob_occupant.adjust_bodytemperature(heat / heat_capacity, TCMB) - if(air1.get_moles(/datum/gas/pluoxium) > 5) //use pluoxium over oxygen - air1.set_moles(/datum/gas/pluoxium, max(0,air1.get_moles(/datum/gas/pluoxium) - 0.125 / efficiency)) - else - air1.set_moles(/datum/gas/oxygen, max(0,air1.get_moles(/datum/gas/oxygen) - 0.5 / efficiency)) // Magically consume gas? Why not, we run on cryo magic. + if(air1.get_moles(GAS_PLUOXIUM) > 5) //use pluoxium over oxygen + air1.set_moles(GAS_PLUOXIUM, max(0,air1.get_moles(GAS_PLUOXIUM) - 0.125 / efficiency)) + else + air1.set_moles(GAS_O2, max(0,air1.get_moles(GAS_O2) - 0.5 / efficiency)) // Magically consume gas? Why not, we run on cryo magic. if(air1.return_temperature() > 2000) take_damage(clamp((air1.return_temperature())/200, 10, 20), BURN) @@ -512,17 +513,18 @@ GLOBAL_VAR_INIT(cryo_overlay_cover_off, mutable_appearance('icons/obj/cryogenics /obj/machinery/atmospherics/components/unary/cryo_cell/default_change_direction_wrench(mob/user, obj/item/wrench/W) . = ..() if(.) - SetInitDirections() + set_init_directions() var/obj/machinery/atmospherics/node = nodes[1] if(node) node.disconnect(src) nodes[1] = null - nullifyPipenet(parents[1]) - atmosinit() + if(parents[1]) + nullify_pipenet(parents[1]) + atmos_init() node = nodes[1] if(node) - node.atmosinit() - node.addMember(src) + node.atmos_init() + node.add_member(src) SSair.add_to_rebuild_queue(src) #undef MAX_TEMPERATURE diff --git a/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm b/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm index 1ca74980ddd4..becd13ed0927 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm @@ -33,7 +33,7 @@ icon_state = "he0" PIPING_LAYER_SHIFT(src, piping_layer) -/obj/machinery/atmospherics/components/unary/heat_exchanger/atmosinit() +/obj/machinery/atmospherics/components/unary/heat_exchanger/atmos_init() var/obj/machinery/atmospherics/components/unary/heat_exchanger/partner = partner_ref?.resolve() if(!partner) partner_ref = null diff --git a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm index 368e9274af67..40d7ebc0af8c 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm @@ -47,7 +47,7 @@ cut_overlays() if(showpipe) // everything is already shifted so don't shift the cap - add_overlay(getpipeimage(icon, "inje_cap", initialize_directions)) + add_overlay(get_pipe_image(icon, "inje_cap", initialize_directions)) if(!nodes[1] || !on || !is_operational()) icon_state = "inje_off" @@ -55,7 +55,6 @@ icon_state = "inje_on" /obj/machinery/atmospherics/components/unary/outlet_injector/process_atmos() - ..() injecting = 0 @@ -65,13 +64,7 @@ var/datum/gas_mixture/air_contents = airs[1] if(air_contents.return_temperature() > 0) - var/transfer_moles = (air_contents.return_pressure()) * volume_rate / (air_contents.return_temperature() * R_IDEAL_GAS_EQUATION) - - var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) - - loc.assume_air(removed) - air_update_turf() - + loc.assume_air_ratio(air_contents, volume_rate / air_contents.return_volume()) update_parents() /obj/machinery/atmospherics/components/unary/outlet_injector/proc/inject() @@ -84,9 +77,7 @@ injecting = 1 if(air_contents.return_temperature() > 0) - var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.return_temperature() * R_IDEAL_GAS_EQUATION) - var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) - loc.assume_air(removed) + loc.assume_air_ratio(air_contents, volume_rate / air_contents.return_volume()) update_parents() flick("inje_inject", src) @@ -112,7 +103,7 @@ )) radio_connection.post_signal(src, signal) -/obj/machinery/atmospherics/components/unary/outlet_injector/atmosinit() +/obj/machinery/atmospherics/components/unary/outlet_injector/atmos_init() set_frequency(frequency) broadcast_status() ..() diff --git a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm index b511f3ff624a..8a44fb2bcb61 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm @@ -2,7 +2,6 @@ icon_state = "passive_vent_map-3" name = "passive vent" desc = "It is an open vent." - can_unwrench = TRUE layer = GAS_SCRUBBER_LAYER shift_underlay_only = FALSE @@ -12,7 +11,7 @@ /obj/machinery/atmospherics/components/unary/passive_vent/update_icon_nopipes() cut_overlays() if(showpipe) - var/image/cap = getpipeimage(icon, "vent_cap", initialize_directions) + var/image/cap = get_pipe_image(icon, "vent_cap", initialize_directions) add_overlay(cap) icon_state = "passive_vent" @@ -21,11 +20,20 @@ if(isclosedturf(location)) return + var/active = FALSE var/datum/gas_mixture/external = location.return_air() var/datum/gas_mixture/internal = airs[1] + var/external_pressure = external.return_pressure() + var/internal_pressure = internal.return_pressure() + var/pressure_delta = abs(external_pressure - internal_pressure) + + if(pressure_delta > 0.5) + equalize_all_gases_in_list(list(internal,external)) + active = TRUE + + active = internal.temperature_share(external, OPEN_HEAT_TRANSFER_COEFFICIENT) || active - if(internal.equalize(external)) - air_update_turf() + if(active) update_parents() /obj/machinery/atmospherics/components/unary/passive_vent/can_crawl_through() diff --git a/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm b/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm index 782bbe2e4064..a5d1fe5b0a29 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm @@ -11,6 +11,7 @@ pipe_state = "connector" piping_layer = 3 showpipe = TRUE + custom_reconcilation = TRUE var/obj/machinery/portable_atmospherics/connected_device @@ -24,11 +25,22 @@ connected_device.disconnect() return ..() +/obj/machinery/atmospherics/components/unary/portables_connector/return_airs_for_reconcilation(datum/pipeline/requester) + . = ..() + if(!connected_device) + return + if(istype(connected_device, /obj/mecha)) + var/obj/mecha/connected_mech = connected_device + if(connected_mech.internal_tank) + . += connected_mech.internal_tank.return_air() + else + . += connected_device.return_air() + /obj/machinery/atmospherics/components/unary/portables_connector/update_icon_nopipes() icon_state = "connector" if(showpipe) cut_overlays() - var/image/cap = getpipeimage(icon, "connector_cap", initialize_directions) + var/image/cap = get_pipe_image(icon, "connector_cap", initialize_directions) add_overlay(cap) /obj/machinery/atmospherics/components/unary/portables_connector/process_atmos() diff --git a/code/modules/atmospherics/machinery/components/unary_devices/tank.dm b/code/modules/atmospherics/machinery/components/unary_devices/tank.dm index c52bd69bb205..de6de198bf09 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/tank.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/tank.dm @@ -14,58 +14,57 @@ var/volume = 10000 //in liters var/gas_type = 0 -/obj/machinery/atmospherics/components/unary/tank/New() - ..() +/obj/machinery/atmospherics/components/unary/tank/Initialize(mapload) + . = ..() var/datum/gas_mixture/air_contents = airs[1] air_contents.set_volume(volume) air_contents.set_temperature(T20C) if(gas_type) - air_contents.set_moles(AIR_CONTENTS) - name = "[name] ([GLOB.meta_gas_info[gas_type][META_GAS_NAME]])" - setPipingLayer(piping_layer) - + air_contents.set_moles(gas_type, AIR_CONTENTS) + name = "[name] ([GLOB.gas_data.names[gas_type]])" + set_piping_layer(piping_layer) /obj/machinery/atmospherics/components/unary/tank/air icon_state = "grey" name = "pressure tank (Air)" -/obj/machinery/atmospherics/components/unary/tank/air/New() - ..() +/obj/machinery/atmospherics/components/unary/tank/air/Initialize(mapload) + . = ..() var/datum/gas_mixture/air_contents = airs[1] - air_contents.set_moles(/datum/gas/oxygen, AIR_CONTENTS * 0.2) - air_contents.set_moles(/datum/gas/nitrogen, AIR_CONTENTS * 0.8) + air_contents.set_moles(GAS_O2, AIR_CONTENTS * 0.2) + air_contents.set_moles(GAS_N2, AIR_CONTENTS * 0.8) /obj/machinery/atmospherics/components/unary/tank/carbon_dioxide - gas_type = /datum/gas/carbon_dioxide + gas_type = GAS_CO2 -/obj/machinery/atmospherics/components/unary/tank/carbon_dioxide/New() - ..() +/obj/machinery/atmospherics/components/unary/tank/carbon_dioxide/Initialize(mapload) + . = ..() var/datum/gas_mixture/air_contents = airs[1] - air_contents.set_moles(/datum/gas/carbon_dioxide, AIR_CONTENTS) + air_contents.set_moles(GAS_CO2, AIR_CONTENTS) /obj/machinery/atmospherics/components/unary/tank/toxins icon_state = "orange" - gas_type = /datum/gas/plasma + gas_type = GAS_PLASMA -/obj/machinery/atmospherics/components/unary/tank/toxins/New() - ..() +/obj/machinery/atmospherics/components/unary/tank/toxins/Initialize(mapload) + . = ..() var/datum/gas_mixture/air_contents = airs[1] - air_contents.set_moles(/datum/gas/plasma, AIR_CONTENTS) + air_contents.set_moles(GAS_PLASMA, AIR_CONTENTS) /obj/machinery/atmospherics/components/unary/tank/oxygen icon_state = "blue" - gas_type = /datum/gas/oxygen + gas_type = GAS_O2 -/obj/machinery/atmospherics/components/unary/tank/oxygen/New() - ..() +/obj/machinery/atmospherics/components/unary/tank/oxygen/Initialize(mapload) + . = ..() var/datum/gas_mixture/air_contents = airs[1] - air_contents.set_moles(/datum/gas/oxygen, AIR_CONTENTS) + air_contents.set_moles(GAS_O2, AIR_CONTENTS) /obj/machinery/atmospherics/components/unary/tank/nitrogen icon_state = "red" - gas_type = /datum/gas/nitrogen + gas_type = GAS_N2 -/obj/machinery/atmospherics/components/unary/tank/nitrogen/New() - ..() +/obj/machinery/atmospherics/components/unary/tank/nitrogen/Initialize(mapload) + . = ..() var/datum/gas_mixture/air_contents = airs[1] - air_contents.set_moles(/datum/gas/nitrogen, AIR_CONTENTS) \ No newline at end of file + air_contents.set_moles(GAS_N2, AIR_CONTENTS) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm index 9a6d2231040b..bad3de341d73 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm @@ -82,7 +82,7 @@ /obj/machinery/atmospherics/components/unary/thermomachine/update_overlays() . = ..() - . += getpipeimage(icon, "pipe", dir, , piping_layer) + . += get_pipe_image(icon, "pipe", dir, , piping_layer) /obj/machinery/atmospherics/components/unary/thermomachine/AltClick(mob/living/user) if(!can_interact(user)) @@ -99,7 +99,7 @@ /obj/machinery/atmospherics/components/unary/thermomachine/update_icon_nopipes() cut_overlays() if(showpipe) - add_overlay(getpipeimage(icon, "scrub_cap", initialize_directions)) + add_overlay(get_pipe_image(icon, "scrub_cap", initialize_directions)) /obj/machinery/atmospherics/components/unary/thermomachine/examine(mob/user) . = ..() @@ -116,7 +116,6 @@ return ..() /obj/machinery/atmospherics/components/unary/thermomachine/process_atmos() - ..() if(!on || !nodes[1]) return var/datum/gas_mixture/air_contents = airs[1] @@ -140,6 +139,7 @@ /obj/machinery/atmospherics/components/unary/thermomachine/attackby(obj/item/I, mob/user, params) if(!on) if(default_deconstruction_screwdriver(user, icon_state_open, icon_state_off, I)) + change_pipe_connection(panel_open) return if(default_change_direction_wrench(user, I)) return @@ -150,21 +150,8 @@ /obj/machinery/atmospherics/components/unary/thermomachine/default_change_direction_wrench(mob/user, obj/item/I) if(!..()) return FALSE - SetInitDirections() - var/obj/machinery/atmospherics/node = nodes[1] - if(node) - if(src in node.nodes) //Only if it's actually connected. On-pipe version would is one-sided. - node.disconnect(src) - nodes[1] = null - if(parents[1]) - nullifyPipenet(parents[1]) - - atmosinit() - node = nodes[1] - if(node) - node.atmosinit() - node.addMember(src) - SSair.add_to_rebuild_queue(src) + set_init_directions() + update_icon(UPDATE_ICON) return TRUE /obj/machinery/atmospherics/components/unary/thermomachine/ui_status(mob/user) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm b/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm index db73b2ea8a45..b61cc02b516e 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm @@ -13,7 +13,7 @@ pipe_interference_group = "atmos-[piping_layer]"\ ) -/obj/machinery/atmospherics/components/unary/SetInitDirections() +/obj/machinery/atmospherics/components/unary/set_init_directions() initialize_directions = dir /obj/machinery/atmospherics/components/unary/on_construction() @@ -27,3 +27,27 @@ /obj/machinery/atmospherics/components/unary/proc/assign_uid_vents() uid = num2text(gl_uid++) return uid + +/obj/machinery/atmospherics/components/unary/proc/change_pipe_connection(disconnect) + if(disconnect) + disconnect_pipes() + return + connect_pipes() + +/obj/machinery/atmospherics/components/unary/proc/connect_pipes() + var/obj/machinery/atmospherics/node1 = nodes[1] + atmos_init() + node1 = nodes[1] + if(node1) + node1.atmos_init() + node1.add_member(src) + SSair.add_to_rebuild_queue(src) + +/obj/machinery/atmospherics/components/unary/proc/disconnect_pipes() + var/obj/machinery/atmospherics/node1 = nodes[1] + if(node1) + if(src in node1.nodes) //Only if it's actually connected. On-pipe version would is one-sided. + node1.disconnect(src) + nodes[1] = null + if(parents[1]) + nullify_pipenet(parents[1]) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm index bc6b484c6dd2..18c8cc194bfb 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm @@ -67,7 +67,7 @@ /obj/machinery/atmospherics/components/unary/vent_pump/update_icon_nopipes() cut_overlays() if(showpipe) - var/image/cap = getpipeimage(icon, "vent_cap", initialize_directions) + var/image/cap = get_pipe_image(icon, "vent_cap", initialize_directions) add_overlay(cap) else PIPING_LAYER_SHIFT(src, PIPING_LAYER_DEFAULT) @@ -111,8 +111,7 @@ icon_state = "vent_in" /obj/machinery/atmospherics/components/unary/vent_pump/process_atmos() - ..() - if(!is_operational()) + if(!is_operational() || !isopenturf(loc)) last_moles_added = 0 return if(space_shutoff_ticks > 0) @@ -128,6 +127,10 @@ var/datum/gas_mixture/air_contents = airs[1] var/datum/gas_mixture/environment = loc.return_air() + + if(!environment) + return + var/environment_pressure = environment.return_pressure() var/environment_moles = environment.total_moles() var/last_moles_real_added = environment_moles - last_moles @@ -161,11 +164,7 @@ var/transfer_moles = pressure_delta*environment.return_volume()/(air_contents.return_temperature() * R_IDEAL_GAS_EQUATION) last_moles_added = transfer_moles - - var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) - - loc.assume_air(removed) - air_update_turf() + loc.assume_air_moles(air_contents, transfer_moles) else // external -> internal last_moles_added = 0 @@ -178,12 +177,7 @@ moles_delta = min(moles_delta, (internal_pressure_bound - air_contents.return_pressure()) * our_multiplier) if(moles_delta > 0) - var/datum/gas_mixture/removed = loc.remove_air(moles_delta) - if (isnull(removed)) // in space - return - - air_contents.merge(removed) - air_update_turf() + loc.transfer_air(air_contents, moles_delta) last_moles = environment_moles update_parents() @@ -222,7 +216,7 @@ radio_connection.post_signal(src, signal, radio_filter_out) -/obj/machinery/atmospherics/components/unary/vent_pump/atmosinit() +/obj/machinery/atmospherics/components/unary/vent_pump/atmos_init() //some vents work his own spesial way radio_filter_in = frequency==FREQ_ATMOS_CONTROL?(RADIO_FROM_AIRALARM):null radio_filter_out = frequency==FREQ_ATMOS_CONTROL?(RADIO_TO_AIRALARM):null @@ -496,6 +490,14 @@ name = "air mix tank output inlet" id_tag = ATMOS_GAS_MONITOR_OUTPUT_AIR +/obj/machinery/atmospherics/components/unary/vent_pump/siphon/on/server + name = "server vent" + +/obj/machinery/atmospherics/components/unary/vent_pump/on/server + name = "server vent" + external_pressure_bound = 4000 + internal_pressure_bound = 0 + #undef INT_BOUND #undef EXT_BOUND #undef NO_BOUND diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm index 2729cb4f456a..4631397bb504 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm @@ -15,10 +15,11 @@ layer = GAS_SCRUBBER_LAYER shift_underlay_only = FALSE showpipe = FALSE + var/id_tag = null var/scrubbing = SCRUBBING //0 = siphoning, 1 = scrubbing - var/filter_types = list(/datum/gas/carbon_dioxide) + var/filter_types = list(GAS_CO2) var/volume_rate = 200 var/widenet = 0 //is this scrubber acting on the 3x3 area around it. var/list/turf/adjacent_turfs = list() @@ -35,11 +36,6 @@ if(!id_tag) id_tag = assign_uid_vents() - for(var/f in filter_types) - if(istext(f)) - filter_types -= f - filter_types += gas_id2path(f) - /obj/machinery/atmospherics/components/unary/vent_scrubber/Destroy() var/area/A = get_area(src) if (A) @@ -70,7 +66,7 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/update_icon_nopipes() cut_overlays() if(showpipe) - var/image/cap = getpipeimage(icon, "scrub_cap", initialize_directions) + var/image/cap = get_pipe_image(icon, "scrub_cap", initialize_directions) add_overlay(cap) else PIPING_LAYER_SHIFT(src, PIPING_LAYER_DEFAULT) @@ -101,9 +97,8 @@ return FALSE var/list/f_types = list() - for(var/path in GLOB.meta_gas_info) - var/list/gas = GLOB.meta_gas_info[path] - f_types += list(list("gas_id" = gas[META_GAS_ID], "gas_name" = gas[META_GAS_NAME], "enabled" = (path in filter_types))) + for(var/id in GLOB.gas_data.ids) + f_types += list(list("gas_id" = id, "gas_name" = GLOB.gas_data.labels[id], "enabled" = (id in filter_types))) var/datum/signal/signal = new(list( "tag" = id_tag, @@ -127,7 +122,7 @@ return TRUE -/obj/machinery/atmospherics/components/unary/vent_scrubber/atmosinit() +/obj/machinery/atmospherics/components/unary/vent_scrubber/atmos_init() radio_filter_in = frequency==initial(frequency)?(RADIO_FROM_AIRALARM):null radio_filter_out = frequency==initial(frequency)?(RADIO_TO_AIRALARM):null if(frequency) @@ -137,7 +132,6 @@ ..() /obj/machinery/atmospherics/components/unary/vent_scrubber/process_atmos() - ..() if(welded || !is_operational()) return FALSE if(!nodes[1] || !on) @@ -149,39 +143,23 @@ scrub(tile) return TRUE -/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/scrub(turf/tile) +/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/scrub(turf/open/tile) if(!istype(tile)) return FALSE var/datum/gas_mixture/environment = tile.return_air() var/datum/gas_mixture/air_contents = airs[1] + if(!environment) + return FALSE + if(air_contents.return_pressure() >= 50 * ONE_ATMOSPHERE) return FALSE if(scrubbing & SCRUBBING) - var/transfer_moles = min(1, volume_rate / environment.return_volume()) * environment.total_moles() - - //Take a gas sample - var/datum/gas_mixture/removed = tile.remove_air(transfer_moles) - - //Nothing left to remove from the tile - if(isnull(removed)) - return FALSE - - removed.scrub_into(air_contents, filter_types) - - //Remix the resulting gases - tile.assume_air(removed) - tile.air_update_turf() + environment.scrub_into(air_contents, volume_rate/environment.return_volume(), filter_types) else //Just siphoning all air - - var/transfer_moles = environment.total_moles() * (volume_rate / environment.return_volume()) - - var/datum/gas_mixture/removed = tile.remove_air(transfer_moles) - - air_contents.merge(removed) - tile.air_update_turf() + environment.transfer_ratio_to(air_contents, volume_rate/environment.return_volume()) update_parents() @@ -227,12 +205,12 @@ investigate_log(" was toggled to [scrubbing ? "scrubbing" : "siphon"] mode by [key_name(signal_sender)]",INVESTIGATE_ATMOS) if("toggle_filter" in signal.data) - filter_types ^= gas_id2path(signal.data["toggle_filter"]) + filter_types ^= signal.data["toggle_filter"] if("set_filters" in signal.data) filter_types = list() for(var/gas in signal.data["set_filters"]) - filter_types += gas_id2path(gas) + filter_types += gas if("init" in signal.data) name = signal.data["init"] diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm index 2836c6199e60..e5a2eb7addff 100644 --- a/code/modules/atmospherics/machinery/datum_pipeline.dm +++ b/code/modules/atmospherics/machinery/datum_pipeline.dm @@ -3,134 +3,164 @@ var/list/datum/gas_mixture/other_airs var/list/obj/machinery/atmospherics/pipe/members - var/list/obj/machinery/atmospherics/components/other_atmosmch + var/list/obj/machinery/atmospherics/components/other_atmos_machines var/update = TRUE + var/building = FALSE + /datum/pipeline/New() other_airs = list() members = list() - other_atmosmch = list() + other_atmos_machines = list() SSair.networks += src /datum/pipeline/Destroy() SSair.networks -= src + if(building) + SSair.remove_from_expansion(src) if(air && air.return_volume()) temporarily_store_air() - for(var/obj/machinery/atmospherics/pipe/P in members) - P.parent = null - for(var/obj/machinery/atmospherics/components/C in other_atmosmch) - C.nullifyPipenet(src) + for(var/obj/machinery/atmospherics/pipe/considered_pipe in members) + considered_pipe.parent = null + if(QDELETED(considered_pipe)) + continue + SSair.add_to_rebuild_queue(considered_pipe) + for(var/obj/machinery/atmospherics/components/considered_component in other_atmos_machines) + considered_component.nullify_pipenet(src) return ..() /datum/pipeline/process() - if(update) - update = FALSE - reconcile_air() + if(!update || building) + return + update = FALSE + reconcile_air() update = air.react(src) /datum/pipeline/proc/build_pipeline(obj/machinery/atmospherics/base) + building = TRUE var/volume = 0 if(istype(base, /obj/machinery/atmospherics/pipe)) - var/obj/machinery/atmospherics/pipe/E = base - volume = E.volume - members += E - if(E.air_temporary) - air = E.air_temporary - E.air_temporary = null + var/obj/machinery/atmospherics/pipe/considered_pipe = base + volume = considered_pipe.volume + members += considered_pipe + if(considered_pipe.air_temporary) + air = considered_pipe.air_temporary + considered_pipe.air_temporary = null else - addMachineryMember(base) + add_machinery_member(base) + if(!air) + air = new + air.set_volume(volume) + SSair.add_to_expansion(src, base) + +///Has the same effect as build_pipeline(), but this doesn't queue its work, so overrun abounds. It's useful for the pregame +/datum/pipeline/proc/build_pipeline_blocking(obj/machinery/atmospherics/base) + var/volume = 0 + if(istype(base, /obj/machinery/atmospherics/pipe)) + var/obj/machinery/atmospherics/pipe/considered_pipe = base + volume = considered_pipe.volume + members += considered_pipe + if(considered_pipe.air_temporary) + air = considered_pipe.air_temporary + considered_pipe.air_temporary = null + else + add_machinery_member(base) + if(!air) air = new var/list/possible_expansions = list(base) while(possible_expansions.len) for(var/obj/machinery/atmospherics/borderline in possible_expansions) var/list/result = borderline.pipeline_expansion(src) - if(result && result.len) - for(var/obj/machinery/atmospherics/P in result) - if(istype(P, /obj/machinery/atmospherics/pipe)) - var/obj/machinery/atmospherics/pipe/item = P - if(!members.Find(item)) - - if(item.parent) - var/static/pipenetwarnings = 100 - if(pipenetwarnings > 0) - log_mapping("build_pipeline(): [item.type] added to a pipenet while still having one. (pipes leading to the same spot stacking in one turf) around [AREACOORD(item)].") - pipenetwarnings-- - if(pipenetwarnings == 0) - log_mapping("build_pipeline(): further messages about pipenets will be suppressed") - members += item - possible_expansions += item - - volume += item.volume - item.parent = src - - if(item.air_temporary) - air.merge(item.air_temporary) - item.air_temporary = null - else - P.setPipenet(src, borderline) - addMachineryMember(P) + if(!result?.len) + possible_expansions -= borderline + continue + for(var/obj/machinery/atmospherics/considered_device in result) + if(!istype(considered_device, /obj/machinery/atmospherics/pipe)) + considered_device.set_pipenet(src, borderline) + add_machinery_member(considered_device) + continue + var/obj/machinery/atmospherics/pipe/item = considered_device + if(members.Find(item)) + continue + if(item.parent) + var/static/pipenetwarnings = 10 + if(pipenetwarnings > 0) + log_mapping("build_pipeline(): [item.type] added to a pipenet while still having one. (pipes leading to the same spot stacking in one turf) around [AREACOORD(item)].") + pipenetwarnings-- + if(pipenetwarnings == 0) + log_mapping("build_pipeline(): further messages about pipenets will be suppressed") + + members += item + possible_expansions += item + + volume += item.volume + item.parent = src + + if(item.air_temporary) + air.merge(item.air_temporary) + item.air_temporary = null possible_expansions -= borderline air.set_volume(volume) -/datum/pipeline/proc/addMachineryMember(obj/machinery/atmospherics/components/C) - other_atmosmch |= C - var/datum/gas_mixture/G = C.returnPipenetAir(src) - if(!G) - stack_trace("addMachineryMember: Null gasmix added to pipeline datum from [C] which is of type [C.type]. Nearby: ([C.x], [C.y], [C.z])") - other_airs |= G - -/datum/pipeline/proc/addMember(obj/machinery/atmospherics/A, obj/machinery/atmospherics/N) - if(istype(A, /obj/machinery/atmospherics/pipe)) - var/obj/machinery/atmospherics/pipe/P = A - if(P.parent) - merge(P.parent) - P.parent = src - var/list/adjacent = P.pipeline_expansion() - for(var/obj/machinery/atmospherics/pipe/I in adjacent) - if(I.parent == src) - continue - var/datum/pipeline/E = I.parent - merge(E) - if(!members.Find(P)) - members += P - air.set_volume(air.return_volume() + P.volume) +/datum/pipeline/proc/add_machinery_member(obj/machinery/atmospherics/components/considered_component) + other_atmos_machines |= considered_component + var/list/returned_airs = considered_component.return_pipenet_airs(src) + if (!length(returned_airs) || (null in returned_airs)) + stack_trace("addMachineryMember: Nonexistent (empty list) or null machinery gasmix added to pipeline datum from [considered_component] \ + which is of type [considered_component.type]. Nearby: ([considered_component.x], [considered_component.y], [considered_component.z])") + other_airs |= returned_airs + +/datum/pipeline/proc/add_member(obj/machinery/atmospherics/reference_device, obj/machinery/atmospherics/device_to_add) + if(!istype(reference_device, /obj/machinery/atmospherics/pipe)) + reference_device.set_pipenet(src, device_to_add) + add_machinery_member(reference_device) else - A.setPipenet(src, N) - addMachineryMember(A) - -/datum/pipeline/proc/merge(datum/pipeline/E) - if(E == src) + var/obj/machinery/atmospherics/pipe/reference_pipe = reference_device + if(reference_pipe.parent) + merge(reference_pipe.parent) + reference_pipe.parent = src + var/list/adjacent = reference_pipe.pipeline_expansion() + for(var/obj/machinery/atmospherics/pipe/adjacent_pipe in adjacent) + if(adjacent_pipe.parent == src) + continue + var/datum/pipeline/parent_pipeline = adjacent_pipe.parent + merge(parent_pipeline) + if(!members.Find(reference_pipe)) + members += reference_pipe + air.set_volume(air.return_volume() + reference_pipe.volume) + +/datum/pipeline/proc/merge(datum/pipeline/parent_pipeline) + if(parent_pipeline == src) return - air.set_volume(air.return_volume() + E.air.return_volume()) - members.Add(E.members) - for(var/obj/machinery/atmospherics/pipe/S in E.members) - S.parent = src - air.merge(E.air) - for(var/obj/machinery/atmospherics/components/C in E.other_atmosmch) - C.replacePipenet(E, src) - other_atmosmch.Add(E.other_atmosmch) - other_airs.Add(E.other_airs) - E.members.Cut() - E.other_atmosmch.Cut() + air.set_volume(air.return_volume() + parent_pipeline.air.return_volume()) + members.Add(parent_pipeline.members) + for(var/obj/machinery/atmospherics/pipe/reference_pipe in parent_pipeline.members) + reference_pipe.parent = src + air.merge(parent_pipeline.air) + for(var/obj/machinery/atmospherics/components/reference_component in parent_pipeline.other_atmos_machines) + reference_component.replace_pipenet(parent_pipeline, src) + other_atmos_machines |= parent_pipeline.other_atmos_machines + other_airs |= parent_pipeline.other_airs + parent_pipeline.members.Cut() + parent_pipeline.other_atmos_machines.Cut() update = TRUE - qdel(E) + qdel(parent_pipeline) -/obj/machinery/atmospherics/proc/addMember(obj/machinery/atmospherics/A) +/obj/machinery/atmospherics/proc/add_member(obj/machinery/atmospherics/considered_device) return -/obj/machinery/atmospherics/pipe/addMember(obj/machinery/atmospherics/A) - parent.addMember(A, src) - -/obj/machinery/atmospherics/components/addMember(obj/machinery/atmospherics/A) - var/datum/pipeline/P = returnPipenet(A) - if(!P) - CRASH("null.addMember() called by [type] on [COORD(src)]") - P.addMember(A, src) +/obj/machinery/atmospherics/pipe/add_member(obj/machinery/atmospherics/considered_device) + parent.add_member(considered_device, src) +/obj/machinery/atmospherics/components/add_member(obj/machinery/atmospherics/considered_device) + var/datum/pipeline/device_pipeline = return_pipenet(considered_device) + if(!device_pipeline) + CRASH("null.add_member() called by [type] on [COORD(src)]") + device_pipeline.add_member(considered_device, src) /datum/pipeline/proc/temporarily_store_air() //Update individual gas_mixtures by volume ratio @@ -186,13 +216,13 @@ else return 1 - air.set_temperature(air.return_temperature() + self_temperature_delta); + air.set_temperature(air.return_temperature() + self_temperature_delta) modeled_location.TakeTemperature(sharer_temperature_delta) else if((target.heat_capacity>0) && (partial_heat_capacity>0)) - var/delta_temperature = air.return_temperature() - target.temperature + var/delta_temperature = air.return_temperature() - target.return_temperature() var/heat = thermal_conductivity*delta_temperature* \ (partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity)) @@ -205,43 +235,28 @@ if(listclearnulls(.)) stack_trace("[src] has one or more null gas mixtures, which may cause bugs. Null mixtures will not be considered in reconcile_air().") -/datum/pipeline/proc/reconcile_air() - var/list/datum/gas_mixture/GL = list() - var/list/datum/pipeline/PL = list() - PL += src +/datum/pipeline/proc/empty() + for(var/datum/gas_mixture/GM as anything in get_all_connected_airs()) + GM?.clear() - for(var/i = 1; i <= PL.len; i++) //can't do a for-each here because we may add to the list within the loop - var/datum/pipeline/P = PL[i] - if(!P) - continue - GL += P.other_airs - GL += P.air - for(var/atmosmch in P.other_atmosmch) - if (istype(atmosmch, /obj/machinery/atmospherics/components/binary/valve)) - var/obj/machinery/atmospherics/components/binary/valve/V = atmosmch - if(V.on) - PL |= V.parents[1] - PL |= V.parents[2] - else if (istype(atmosmch, /obj/machinery/atmospherics/components/unary/portables_connector)) - var/obj/machinery/atmospherics/components/unary/portables_connector/C = atmosmch - if(C.connected_device) - GL += C.connected_device.air_contents - - var/datum/gas_mixture/total_gas_mixture = new(0) - var/total_volume = 0 - - for(var/i in GL) - if(!i) +/datum/pipeline/proc/get_all_connected_airs() + var/list/datum/gas_mixture/gas_mixture_list = list() + var/list/datum/pipeline/pipeline_list = list() + pipeline_list += src + + for(var/i = 1; i <= pipeline_list.len; i++) //can't do a for-each here because we may add to the list within the loop + var/datum/pipeline/pipeline = pipeline_list[i] + if(!pipeline) continue - var/datum/gas_mixture/G = i - total_gas_mixture.merge(G) - total_volume += G.return_volume() - - if(total_volume > 0) - //Update individual gas_mixtures by volume ratio - for(var/i in GL) - if(!i) + gas_mixture_list += pipeline.other_airs + gas_mixture_list += pipeline.air + for(var/obj/machinery/atmospherics/components/atmos_machine in pipeline.other_atmos_machines) + if(!atmos_machine.custom_reconcilation) continue - var/datum/gas_mixture/G = i - G.copy_from(total_gas_mixture) - G.multiply(G.return_volume()/total_volume) + pipeline_list |= atmos_machine.return_pipenets_for_reconcilation(src) + gas_mixture_list |= atmos_machine.return_airs_for_reconcilation(src) + return gas_mixture_list + +/datum/pipeline/proc/reconcile_air() + var/list/datum/gas_mixture/GL = get_all_connected_airs() + equalize_all_gases_in_list(GL) diff --git a/code/modules/atmospherics/machinery/other/meter.dm b/code/modules/atmospherics/machinery/other/meter.dm index e05e29c009d4..3e511d438366 100644 --- a/code/modules/atmospherics/machinery/other/meter.dm +++ b/code/modules/atmospherics/machinery/other/meter.dm @@ -32,14 +32,14 @@ id_tag = ATMOS_GAS_MONITOR_LOOP_DISTRIBUTION /obj/machinery/meter/Destroy() - SSair.atmos_machinery -= src + SSair_machinery.stop_processing_machine(src) target = null return ..() /obj/machinery/meter/Initialize(mapload, new_piping_layer) if(!isnull(new_piping_layer)) target_layer = new_piping_layer - SSair.atmos_machinery += src + SSair_machinery.start_processing_machine(src) if(!target) reattach_to_layer() return ..() diff --git a/code/modules/atmospherics/machinery/other/miner.dm b/code/modules/atmospherics/machinery/other/miner.dm index 2a6a583ab6de..78c154084256 100644 --- a/code/modules/atmospherics/machinery/other/miner.dm +++ b/code/modules/atmospherics/machinery/other/miner.dm @@ -117,24 +117,23 @@ on_overlay.color = overlay_color . += on_overlay -/obj/machinery/atmospherics/miner/process(delta_time) +/obj/machinery/atmospherics/miner/process_atmos() update_power() check_operation() if(active && !broken) if(isnull(spawn_id)) return FALSE if(do_use_power(active_power_usage)) - mine_gas(delta_time) + mine_gas() -/obj/machinery/atmospherics/miner/proc/mine_gas(delta_time = 2) +/obj/machinery/atmospherics/miner/proc/mine_gas() var/turf/open/O = get_turf(src) if(!isopenturf(O)) return FALSE var/datum/gas_mixture/merger = new - merger.set_moles(spawn_id, (spawn_mol * delta_time)) + merger.set_moles(spawn_id, spawn_mol) merger.set_temperature(spawn_temp) O.assume_air(merger) - O.air_update_turf(TRUE) /obj/machinery/atmospherics/miner/attack_ai(mob/living/silicon/user) if(broken) @@ -144,39 +143,39 @@ /obj/machinery/atmospherics/miner/n2o name = "\improper N2O Gas Miner" overlay_color = "#FFCCCC" - spawn_id = /datum/gas/nitrous_oxide + spawn_id = GAS_NITROUS /obj/machinery/atmospherics/miner/nitrogen name = "\improper N2 Gas Miner" overlay_color = "#CCFFCC" - spawn_id = /datum/gas/nitrogen + spawn_id = GAS_N2 /obj/machinery/atmospherics/miner/oxygen name = "\improper O2 Gas Miner" overlay_color = "#007FFF" - spawn_id = /datum/gas/oxygen + spawn_id = GAS_O2 /obj/machinery/atmospherics/miner/hydrogen name = "\improper H2 Gas Miner" overlay_color = "#ff0000" - spawn_id = /datum/gas/hydrogen + spawn_id = GAS_H2 /obj/machinery/atmospherics/miner/toxins name = "\improper Plasma Gas Miner" overlay_color = "#ff6600" - spawn_id = /datum/gas/plasma + spawn_id = GAS_PLASMA /obj/machinery/atmospherics/miner/carbon_dioxide name = "\improper CO2 Gas Miner" overlay_color = "#CDCDCD" - spawn_id = /datum/gas/carbon_dioxide + spawn_id = GAS_CO2 /obj/machinery/atmospherics/miner/bz name = "\improper BZ Gas Miner" overlay_color = "#FAFF00" - spawn_id = /datum/gas/bz + spawn_id = GAS_BZ /obj/machinery/atmospherics/miner/water_vapor name = "\improper Water Vapor Gas Miner" overlay_color = "#99928E" - spawn_id = /datum/gas/water_vapor + spawn_id = GAS_H2O diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm index 40db098a78ac..43721f5de7b1 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm @@ -11,7 +11,7 @@ . = ..() add_atom_colour("#404040", FIXED_COLOUR_PRIORITY) -/obj/machinery/atmospherics/pipe/heat_exchanging/isConnectable(obj/machinery/atmospherics/pipe/heat_exchanging/target, given_layer, HE_type_check = TRUE) +/obj/machinery/atmospherics/pipe/heat_exchanging/is_connectable(obj/machinery/atmospherics/pipe/heat_exchanging/target, given_layer, HE_type_check = TRUE) if(istype(target, /obj/machinery/atmospherics/pipe/heat_exchanging) != HE_type_check) return FALSE . = ..() diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/junction.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/junction.dm index 90f2cc47bf89..54eeb02d9425 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/junction.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/junction.dm @@ -15,17 +15,17 @@ construction_type = /obj/item/pipe/directional pipe_state = "junction" -/obj/machinery/atmospherics/pipe/heat_exchanging/junction/SetInitDirections() +/obj/machinery/atmospherics/pipe/heat_exchanging/junction/set_init_directions() switch(dir) if(NORTH, SOUTH) initialize_directions = SOUTH|NORTH if(EAST, WEST) initialize_directions = WEST|EAST -/obj/machinery/atmospherics/pipe/heat_exchanging/junction/getNodeConnects() +/obj/machinery/atmospherics/pipe/heat_exchanging/junction/get_node_connects() return list(turn(dir, 180), dir) -/obj/machinery/atmospherics/pipe/heat_exchanging/junction/isConnectable(obj/machinery/atmospherics/target, given_layer, he_type_check) +/obj/machinery/atmospherics/pipe/heat_exchanging/junction/is_connectable(obj/machinery/atmospherics/target, given_layer, he_type_check) if(dir == get_dir(target, src)) return ..(target, given_layer, FALSE) //we want a normal pipe instead return ..(target, given_layer, TRUE) diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm index 5e995528d4a2..ada7a478f4c5 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm @@ -15,12 +15,13 @@ construction_type = /obj/item/pipe/trinary pipe_state = "he_manifold" -/obj/machinery/atmospherics/pipe/heat_exchanging/manifold/New() + +/obj/machinery/atmospherics/pipe/heat_exchanging/manifold/New(mapload) icon_state = "" return ..() -/obj/machinery/atmospherics/pipe/heat_exchanging/manifold/SetInitDirections() - initialize_directions = NORTH|SOUTH|EAST|WEST +/obj/machinery/atmospherics/pipe/heat_exchanging/manifold/set_init_directions() + initialize_directions = ALL_CARDINALS initialize_directions &= ~dir /obj/machinery/atmospherics/pipe/heat_exchanging/manifold/update_overlays() @@ -33,7 +34,7 @@ //Add non-broken pieces for(var/i in 1 to device_type) if(nodes[i]) - . += getpipeimage(icon, "pipe-[piping_layer]", get_dir(src, nodes[i])) + . += get_pipe_image(icon, "pipe-[piping_layer]", get_dir(src, nodes[i])) update_layer() update_alpha() diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm index 22d73b285bc7..72f6a61c6371 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm @@ -7,7 +7,7 @@ name = "4-way pipe manifold" desc = "A manifold composed of heat-exchanging pipes." - initialize_directions = NORTH|SOUTH|EAST|WEST + initialize_directions = ALL_CARDINALS device_type = QUATERNARY @@ -18,7 +18,7 @@ icon_state = "" return ..() -/obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w/SetInitDirections() +/obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w/set_init_directions() initialize_directions = initial(initialize_directions) /obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w/update_overlays() @@ -30,7 +30,7 @@ //Add non-broken pieces for(var/i in 1 to device_type) if(nodes[i]) - . += getpipeimage(icon, "pipe-[piping_layer]", get_dir(src, nodes[i])) + . += get_pipe_image(icon, "pipe-[piping_layer]", get_dir(src, nodes[i])) update_layer() update_alpha() diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/simple.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/simple.dm index f3f472efb7e1..18879f86da1e 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/simple.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/simple.dm @@ -14,7 +14,7 @@ construction_type = /obj/item/pipe/binary/bendable pipe_state = "he" -/obj/machinery/atmospherics/pipe/heat_exchanging/simple/SetInitDirections() +/obj/machinery/atmospherics/pipe/heat_exchanging/simple/set_init_directions() if(dir in GLOB.diagonals) initialize_directions = dir return diff --git a/code/modules/atmospherics/machinery/pipes/layermanifold.dm b/code/modules/atmospherics/machinery/pipes/layermanifold.dm index 4044ebc99fd2..d979f42c53a0 100644 --- a/code/modules/atmospherics/machinery/pipes/layermanifold.dm +++ b/code/modules/atmospherics/machinery/pipes/layermanifold.dm @@ -68,21 +68,21 @@ // Uses pipe-3 because we don't want the vertical shifting if(p_color) - new_overlay = getpipeimage(icon, "pipe-3", p_dir, p_color, piping_layer = p_layer) + new_overlay = get_pipe_image(icon, "pipe-3", p_dir, p_color, piping_layer = p_layer) else - new_overlay = getpipeimage(icon, "pipe-3", p_dir, piping_layer = p_layer) + new_overlay = get_pipe_image(icon, "pipe-3", p_dir, piping_layer = p_layer) new_overlay.layer = layer - 0.01 return new_overlay -/obj/machinery/atmospherics/pipe/layer_manifold/SetInitDirections() +/obj/machinery/atmospherics/pipe/layer_manifold/set_init_directions() switch(dir) if(NORTH, SOUTH) initialize_directions = NORTH|SOUTH if(EAST, WEST) initialize_directions = EAST|WEST -/obj/machinery/atmospherics/pipe/layer_manifold/isConnectable(obj/machinery/atmospherics/target, given_layer) +/obj/machinery/atmospherics/pipe/layer_manifold/is_connectable(obj/machinery/atmospherics/target, given_layer) if(!given_layer) return TRUE . = ..() @@ -92,8 +92,8 @@ back_nodes = list() var/list/new_nodes = list() for(var/iter in PIPING_LAYER_MIN to PIPING_LAYER_MAX) - var/obj/machinery/atmospherics/foundfront = findConnecting(dir, iter) - var/obj/machinery/atmospherics/foundback = findConnecting(turn(dir, 180), iter) + var/obj/machinery/atmospherics/foundfront = find_connecting(dir, iter) + var/obj/machinery/atmospherics/foundback = find_connecting(turn(dir, 180), iter) front_nodes += foundfront back_nodes += foundback if(foundfront && !QDELETED(foundfront)) @@ -103,13 +103,13 @@ update_appearance(UPDATE_ICON) return new_nodes -/obj/machinery/atmospherics/pipe/layer_manifold/atmosinit() +/obj/machinery/atmospherics/pipe/layer_manifold/atmos_init() normalize_cardinal_directions() findAllConnections() var/turf/T = loc // hide if turf is not intact hide(T.intact) -/obj/machinery/atmospherics/pipe/layer_manifold/setPipingLayer() +/obj/machinery/atmospherics/pipe/layer_manifold/set_piping_layer() piping_layer = PIPING_LAYER_DEFAULT /obj/machinery/atmospherics/pipe/layer_manifold/pipeline_expansion() diff --git a/code/modules/atmospherics/machinery/pipes/manifold.dm b/code/modules/atmospherics/machinery/pipes/manifold.dm index 625ebf4ecae9..af37701d74ef 100644 --- a/code/modules/atmospherics/machinery/pipes/manifold.dm +++ b/code/modules/atmospherics/machinery/pipes/manifold.dm @@ -24,12 +24,12 @@ * in the mapping subsystem init before Initialize(mapload) is called in the atoms subsystem init. * This is true for the other manifolds (the 4 ways and the heat exchanges) too. */ -/obj/machinery/atmospherics/pipe/manifold/New() +/obj/machinery/atmospherics/pipe/manifold/New(mapload) icon_state = "" return ..() -/obj/machinery/atmospherics/pipe/manifold/SetInitDirections() - initialize_directions = NORTH|SOUTH|EAST|WEST +/obj/machinery/atmospherics/pipe/manifold/set_init_directions() + initialize_directions = ALL_CARDINALS initialize_directions &= ~dir /obj/machinery/atmospherics/pipe/manifold/update_overlays() @@ -43,7 +43,7 @@ //Add non-broken pieces for(var/i in 1 to device_type) if(nodes[i]) - . += getpipeimage(icon, "pipe-[piping_layer]", get_dir(src, nodes[i])) + . += get_pipe_image(icon, "pipe-[piping_layer]", get_dir(src, nodes[i])) update_layer() update_alpha() diff --git a/code/modules/atmospherics/machinery/pipes/manifold4w.dm b/code/modules/atmospherics/machinery/pipes/manifold4w.dm index 1ad4d090b130..35d3f68ce1e7 100644 --- a/code/modules/atmospherics/machinery/pipes/manifold4w.dm +++ b/code/modules/atmospherics/machinery/pipes/manifold4w.dm @@ -7,7 +7,7 @@ name = "4-way pipe manifold" desc = "A manifold composed of regular pipes." - initialize_directions = NORTH|SOUTH|EAST|WEST + initialize_directions = ALL_CARDINALS device_type = QUATERNARY @@ -19,11 +19,11 @@ pipe_interference_group = "atmos-[piping_layer]"\ ) -/obj/machinery/atmospherics/pipe/manifold4w/New() +/obj/machinery/atmospherics/pipe/manifold4w/New(mapload) icon_state = "" return ..() -/obj/machinery/atmospherics/pipe/manifold4w/SetInitDirections() +/obj/machinery/atmospherics/pipe/manifold4w/set_init_directions() initialize_directions = initial(initialize_directions) /obj/machinery/atmospherics/pipe/manifold4w/update_overlays() @@ -35,7 +35,7 @@ //Add non-broken pieces for(var/i in 1 to device_type) if(nodes[i]) - . += getpipeimage(icon, "pipe-[piping_layer]", get_dir(src, nodes[i])) + . += get_pipe_image(icon, "pipe-[piping_layer]", get_dir(src, nodes[i])) update_layer() update_alpha() diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm index bf36ad6a1740..e14ef7818dab 100644 --- a/code/modules/atmospherics/machinery/pipes/pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/pipes.dm @@ -18,26 +18,27 @@ ),\ ) -/obj/machinery/atmospherics/pipe/New() +/obj/machinery/atmospherics/pipe/New(mapload) add_atom_colour(pipe_color, FIXED_COLOUR_PRIORITY) volume = 35 * device_type - ..() + return ..() -/obj/machinery/atmospherics/pipe/nullifyNode(i) - var/obj/machinery/atmospherics/oldN = nodes[i] - ..() - if(oldN) - SSair.add_to_rebuild_queue(oldN) +/obj/machinery/atmospherics/pipe/nullify_node(i) + var/obj/machinery/atmospherics/old_node = nodes[i] + . = ..() + if(old_node) + SSair.add_to_rebuild_queue(old_node) /obj/machinery/atmospherics/pipe/destroy_network() QDEL_NULL(parent) -/obj/machinery/atmospherics/pipe/build_network() - if(QDELETED(parent)) - parent = new - parent.build_pipeline(src) +/obj/machinery/atmospherics/pipe/get_rebuild_targets() + if(!QDELETED(parent)) + return + parent = new + return list(parent) -/obj/machinery/atmospherics/pipe/atmosinit() +/obj/machinery/atmospherics/pipe/atmos_init() var/turf/T = loc // hide if turf is not intact hide(T.intact) ..() @@ -51,19 +52,26 @@ if(air_temporary) var/turf/T = loc T.assume_air(air_temporary) - air_update_turf() /obj/machinery/atmospherics/pipe/return_air() - if(parent) - return parent.air + if(air_temporary) + return air_temporary + return parent.air /obj/machinery/atmospherics/pipe/return_analyzable_air() - if(parent) - return parent.air + if(air_temporary) + return air_temporary + return parent.air /obj/machinery/atmospherics/pipe/remove_air(amount) - if(parent) - return parent.air.remove(amount) + if(air_temporary) + return air_temporary.remove(amount) + return parent.air.remove(amount) + +/obj/machinery/atmospherics/pipe/remove_air_ratio(ratio) + if(air_temporary) + return air_temporary.remove_ratio(ratio) + return parent.air.remove_ratio(ratio) /obj/machinery/atmospherics/pipe/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/pipe_meter)) @@ -78,10 +86,10 @@ analyzer_act(user, src) return ..() -/obj/machinery/atmospherics/pipe/returnPipenet() +/obj/machinery/atmospherics/pipe/return_pipenet() return parent -/obj/machinery/atmospherics/pipe/setPipenet(datum/pipeline/P) +/obj/machinery/atmospherics/pipe/set_pipenet(datum/pipeline/P) parent = P /obj/machinery/atmospherics/pipe/Destroy() diff --git a/code/modules/atmospherics/machinery/pipes/simple.dm b/code/modules/atmospherics/machinery/pipes/simple.dm index 3ac2daf18e06..538ebc89bb64 100644 --- a/code/modules/atmospherics/machinery/pipes/simple.dm +++ b/code/modules/atmospherics/machinery/pipes/simple.dm @@ -22,7 +22,7 @@ pipe_interference_group = "atmos-[piping_layer]"\ ) -/obj/machinery/atmospherics/pipe/simple/SetInitDirections() +/obj/machinery/atmospherics/pipe/simple/set_init_directions() if(dir in GLOB.diagonals) initialize_directions = dir return diff --git a/code/modules/atmospherics/machinery/portable/canister.dm b/code/modules/atmospherics/machinery/portable/canister.dm index 4b56e08552e7..1e7c2c6b3148 100644 --- a/code/modules/atmospherics/machinery/portable/canister.dm +++ b/code/modules/atmospherics/machinery/portable/canister.dm @@ -25,7 +25,7 @@ integrity_failure = 100 pressure_resistance = 7 * ONE_ATMOSPHERE var/temperature_resistance = 1000 + T0C - var/starter_temp + var/starter_temp = T20C // Prototype vars var/prototype = FALSE var/valve_timer = null @@ -88,37 +88,37 @@ name = "Nitrogen canister" desc = "Nitrogen gas. Reportedly useful for something." icon_state = "nitrogen" - gas_type = /datum/gas/nitrogen + gas_type = GAS_N2 /obj/machinery/portable_atmospherics/canister/oxygen name = "Oxygen canister" desc = "Oxygen. Necessary for human life." icon_state = "oxygen" - gas_type = /datum/gas/oxygen + gas_type = GAS_O2 /obj/machinery/portable_atmospherics/canister/carbon_dioxide name = "Carbon dioxide canister" desc = "Carbon dioxide. What the fuck is carbon dioxide?" icon_state = "carbon" - gas_type = /datum/gas/carbon_dioxide + gas_type = GAS_CO2 /obj/machinery/portable_atmospherics/canister/toxins name = "Plasma canister" desc = "Plasma gas. The reason YOU are here. Highly toxic." icon_state = "plasma" - gas_type = /datum/gas/plasma + gas_type = GAS_PLASMA /obj/machinery/portable_atmospherics/canister/bz name = "\improper BZ canister" desc = "BZ, a powerful hallucinogenic nerve agent." icon_state = "bz" - gas_type = /datum/gas/bz + gas_type = GAS_BZ /obj/machinery/portable_atmospherics/canister/nitrous_oxide name = "Nitrous oxide canister" desc = "Nitrous oxide gas. Known to cause drowsiness." icon_state = "nitrous" - gas_type = /datum/gas/nitrous_oxide + gas_type = GAS_NITROUS /obj/machinery/portable_atmospherics/canister/air name = "Air canister" @@ -129,100 +129,100 @@ name = "Tritium canister" desc = "Tritium. Inhalation might cause irradiation." icon_state = "tritium" - gas_type = /datum/gas/tritium + gas_type = GAS_TRITIUM /obj/machinery/portable_atmospherics/canister/nob name = "Hyper-noblium canister" desc = "Hyper-Noblium. More noble than all other gases." icon_state = "hypno" - gas_type = /datum/gas/hypernoblium + gas_type = GAS_HYPERNOB /obj/machinery/portable_atmospherics/canister/nitrium name = "Nitrium canister" desc = "Nitrium gas. Feels great 'til the acid eats your lungs." icon_state = "nitrium" - gas_type = /datum/gas/nitrium + gas_type = GAS_NITRIUM /obj/machinery/portable_atmospherics/canister/pluoxium name = "Pluoxium canister" desc = "Pluoxium. Like oxygen, but more bang for your buck." icon_state = "pluoxium" - gas_type = /datum/gas/pluoxium + gas_type = GAS_PLUOXIUM /obj/machinery/portable_atmospherics/canister/water_vapor name = "Water vapor canister" desc = "Water vapor. We get it, you vape." icon_state = "water" - gas_type = /datum/gas/water_vapor + gas_type = GAS_H2O filled = 1 /obj/machinery/portable_atmospherics/canister/miasma name = "Miasma canister" desc = "Foul miasma. Even the canister reeks of fetid refuse." icon_state = "miasma" - gas_type = /datum/gas/miasma + gas_type = GAS_MIASMA filled = 1 /obj/machinery/portable_atmospherics/canister/dilithium name = "Dilithium canister" desc = "A gas produced from dilithium crystal." icon_state = "dilithium" - gas_type = /datum/gas/dilithium + gas_type = GAS_DILITHIUM /obj/machinery/portable_atmospherics/canister/freon name = "Freon canister" desc = "Freon. Can absorb heat" icon_state = "freon" - gas_type = /datum/gas/freon + gas_type = GAS_FREON filled = 1 /obj/machinery/portable_atmospherics/canister/hydrogen name = "Hydrogen canister" desc = "Hydrogen, highly flammable" icon_state = "h2" - gas_type = /datum/gas/hydrogen + gas_type = GAS_H2 filled = 1 /obj/machinery/portable_atmospherics/canister/healium name = "Healium canister" desc = "Healium, causes deep sleep" icon_state = "healium" - gas_type = /datum/gas/healium + gas_type = GAS_HEALIUM filled = 1 /obj/machinery/portable_atmospherics/canister/pluonium name = "Pluonium canister" desc = "Pluonium, reacts differently with various gases" icon_state = "pluonium" - gas_type = /datum/gas/pluonium + gas_type = GAS_PLUONIUM filled = 1 /obj/machinery/portable_atmospherics/canister/halon name = "Halon canister" desc = "Halon, remove oxygen from high temperature fires and cool down the area" icon_state = "halon" - gas_type = /datum/gas/halon + gas_type = GAS_HALON filled = 1 /obj/machinery/portable_atmospherics/canister/hexane name = "Hexane canister" desc = "hexane, highly flammable." icon_state = "hexane" - gas_type = /datum/gas/hexane + gas_type = GAS_HEXANE filled = 1 /obj/machinery/portable_atmospherics/canister/zauker name = "Zauker canister" desc = "Zauker, highly toxic" icon_state = "zauker" - gas_type = /datum/gas/zauker + gas_type = GAS_ZAUKER filled = 1 /obj/machinery/portable_atmospherics/canister/antinoblium name = "Antinoblium canister" desc = "Antinoblium, we still don't know what it does, but it sells for a lot" icon_state = "antino" - gas_type = /datum/gas/antinoblium + gas_type = GAS_ANTINOB filled = 1 /obj/machinery/portable_atmospherics/canister/proc/get_time_left() @@ -255,13 +255,13 @@ /obj/machinery/portable_atmospherics/canister/proto/default/oxygen name = "prototype canister" desc = "A prototype canister for a prototype bike, what could go wrong?" - gas_type = /datum/gas/oxygen + gas_type = GAS_O2 filled = 1 release_pressure = ONE_ATMOSPHERE*2 -/obj/machinery/portable_atmospherics/canister/New(loc, datum/gas_mixture/existing_mixture) - ..() +/obj/machinery/portable_atmospherics/canister/Initialize(mapload, datum/gas_mixture/existing_mixture) + . = ..() if(existing_mixture) air_contents.copy_from(existing_mixture) else @@ -284,13 +284,21 @@ if(gas_type) if(starter_temp) air_contents.set_temperature(starter_temp) - air_contents.set_moles(gas_type, (maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature())) + if(air_contents.return_volume() == 0) + CRASH("Air content volume is zero, this shouldn't be the case volume is: [volume]!") + if(air_contents.return_temperature() == 0) + CRASH("Air content temperature is zero, this shouldn't be the case!") + if (gas_type) + air_contents.set_moles(gas_type, (maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature())) /obj/machinery/portable_atmospherics/canister/air/create_gas() - if(starter_temp) - air_contents.set_temperature(starter_temp) - air_contents.set_moles(/datum/gas/oxygen, (O2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature())) - air_contents.set_moles(/datum/gas/nitrogen, (N2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature())) + if(air_contents.return_volume() == 0) + CRASH("Air content volume is zero, this shouldn't be the case volume is: [volume]!") + if(air_contents.return_temperature() == 0) + CRASH("Air content temperature is zero, this shouldn't be the case!") + air_contents.set_temperature(starter_temp) + air_contents.set_moles(GAS_O2, (O2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature())) + air_contents.set_moles(GAS_N2, (N2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature())) /obj/machinery/portable_atmospherics/canister/update_icon_state() if(stat & BROKEN) @@ -374,7 +382,6 @@ var/datum/gas_mixture/expelled_gas = air_contents.remove(air_contents.total_moles()) var/turf/T = get_turf(src) T.assume_air(expelled_gas) - air_update_turf() obj_break() density = FALSE @@ -402,21 +409,16 @@ if(timing && valve_timer < world.time) valve_open = !valve_open timing = FALSE + + // Handle gas transfer. if(valve_open) var/turf/T = get_turf(src) - pump.airs[1] = air_contents - pump.airs[2] = holding ? holding.air_contents : T.return_air() - pump.target_pressure = release_pressure - - pump.process_atmos() // Pump gas. - if(!holding) - air_update_turf() // Update the environment if needed. - else - pump.airs[1] = null - pump.airs[2] = null + var/datum/gas_mixture/target_air = holding ? holding.air_contents : T.return_air() + air_contents.release_gas_to(target_air, release_pressure) update_appearance(UPDATE_ICON) + /obj/machinery/portable_atmospherics/canister/ui_state(mob/user) return GLOB.physical_state @@ -514,11 +516,10 @@ if(!holding) var/list/danger = list() for(var/id in air_contents.get_gases()) - if(!GLOB.meta_gas_info[id][META_GAS_DANGER]) + if(!(GLOB.gas_data.flags[id] & GAS_FLAG_DANGEROUS)) continue - if(air_contents.get_moles(id) > (GLOB.meta_gas_info[id][META_GAS_MOLES_VISIBLE] || MOLES_GAS_VISIBLE)) //if moles_visible is undefined, default to default visibility - danger[GLOB.meta_gas_info[id][META_GAS_NAME]] = air_contents.get_moles(id) //ex. "plasma" = 20 - + if(air_contents.get_moles(id) > (GLOB.gas_data.visibility[id] || MOLES_GAS_VISIBLE)) //if moles_visible is undefined, default to default visibility + danger[GLOB.gas_data.names[id]] = air_contents.get_moles(id) //ex. "plasma" = 20 if(danger.len) message_admins("[ADMIN_LOOKUPFLW(usr)] opened a canister that contains the following at [ADMIN_VERBOSEJMP(src)]:") log_admin("[key_name(usr)] opened a canister that contains the following at [AREACOORD(src)]:") @@ -576,10 +577,10 @@ desc = "This should never be spawned in game." icon_state = "danger" /obj/machinery/portable_atmospherics/canister/fusion_test/create_gas() - air_contents.set_moles(/datum/gas/tritium, 10) - air_contents.set_moles(/datum/gas/plasma, 500) - air_contents.set_moles(/datum/gas/hydrogen, 500) - air_contents.set_moles(/datum/gas/nitrous_oxide, 100) + air_contents.set_moles(GAS_TRITIUM, 10) + air_contents.set_moles(GAS_PLASMA, 500) + air_contents.set_moles(GAS_H2, 500) + air_contents.set_moles(GAS_NITROUS, 100) air_contents.set_temperature(10000) /// Canister 1 Kelvin below the fusion point. Contains far too much plasma. Only good for adding more fuel to ongoing fusion reactions. @@ -588,10 +589,10 @@ desc = "This should never be spawned in game." icon_state = "danger" /obj/machinery/portable_atmospherics/canister/fusion_test_2/create_gas() - air_contents.set_moles(/datum/gas/tritium, 10) - air_contents.set_moles(/datum/gas/plasma, 15000) - air_contents.set_moles(/datum/gas/carbon_dioxide, 1500) - air_contents.set_moles(/datum/gas/nitrous_oxide, 100) + air_contents.set_moles(GAS_TRITIUM, 10) + air_contents.set_moles(GAS_PLASMA, 15000) + air_contents.set_moles(GAS_CO2, 1500) + air_contents.set_moles(GAS_NITROUS, 100) air_contents.set_temperature(9999) /// Canister at the perfect conditions to start and continue fusion for a long time. @@ -600,9 +601,9 @@ desc = "This should never be spawned in game." icon_state = "danger" /obj/machinery/portable_atmospherics/canister/fusion_test_3/create_gas() - air_contents.set_moles(/datum/gas/tritium, 1000) - air_contents.set_moles(/datum/gas/plasma, 4500) - air_contents.set_moles(/datum/gas/carbon_dioxide, 1500) + air_contents.set_moles(GAS_TRITIUM, 1000) + air_contents.set_moles(GAS_PLASMA, 4500) + air_contents.set_moles(GAS_CO2, 1500) air_contents.set_temperature(1000000) /** Canister for testing dilithium based cold fusion. Use fusion_test_3 if you don't know what you are doing. @@ -612,10 +613,10 @@ desc = "This should never be spawned in game. Contains dilithium for cold fusion." icon_state = "danger" /obj/machinery/portable_atmospherics/canister/fusion_test_4/create_gas() - air_contents.set_moles(/datum/gas/tritium, 1000) - air_contents.set_moles(/datum/gas/plasma, 4500) - air_contents.set_moles(/datum/gas/carbon_dioxide, 1500) - air_contents.set_moles(/datum/gas/dilithium, 2000) + air_contents.set_moles(GAS_TRITIUM, 1000) + air_contents.set_moles(GAS_PLASMA, 4500) + air_contents.set_moles(GAS_CO2, 1500) + air_contents.set_moles(GAS_DILITHIUM, 2000) air_contents.set_temperature(10000) /// A canister that is 1 Kelvin away from doing the stimball reaction. @@ -624,7 +625,7 @@ desc = "This should never be spawned in game except for testing purposes." icon_state = "danger" /obj/machinery/portable_atmospherics/canister/stimball_test/create_gas() - air_contents.set_moles(/datum/gas/nitrium, 1000) - air_contents.set_moles(/datum/gas/plasma, 1000) - air_contents.set_moles(/datum/gas/pluoxium, 1000) + air_contents.set_moles(GAS_NITRIUM, 1000) + air_contents.set_moles(GAS_PLASMA, 1000) + air_contents.set_moles(GAS_PLUOXIUM, 1000) air_contents.set_temperature(FIRE_MINIMUM_TEMPERATURE_TO_EXIST-1) diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm index 53764eb0bc1a..156ade34ddab 100644 --- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm +++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm @@ -14,20 +14,17 @@ var/maximum_pressure = 90 * ONE_ATMOSPHERE -/obj/machinery/portable_atmospherics/New() - ..() - SSair.atmos_machinery += src +/obj/machinery/portable_atmospherics/Initialize(mapload) + . = ..() + SSair_machinery.start_processing_machine(src) air_contents = new(volume) air_contents.set_temperature(T20C) - return 1 - /obj/machinery/portable_atmospherics/Destroy() + SSair_machinery.stop_processing_machine(src) disconnect() QDEL_NULL(air_contents) - SSair.atmos_machinery -= src - return ..() /obj/machinery/portable_atmospherics/ex_act(severity, target) @@ -38,12 +35,11 @@ //This explosion will destroy the can, release its air. var/turf/T = get_turf(src) T.assume_air(air_contents) - T.air_update_turf() return ..() /obj/machinery/portable_atmospherics/process_atmos() - if(!connected_port) // Pipe network handles reactions if connected. + if(!connected_port && air_contents != null && src != null) // Pipe network handles reactions if connected. air_contents.react(src) /obj/machinery/portable_atmospherics/return_air() @@ -64,8 +60,7 @@ //Perform the connection connected_port = new_port connected_port.connected_device = src - var/datum/pipeline/connected_port_parent = connected_port.parents[1] - connected_port_parent.reconcile_air() + connected_port.parents[1].update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED anchored = TRUE //Prevent movement pixel_x = new_port.pixel_x diff --git a/code/modules/atmospherics/machinery/portable/pump.dm b/code/modules/atmospherics/machinery/portable/pump.dm index b2224cf9cad8..e3a22c002df9 100644 --- a/code/modules/atmospherics/machinery/portable/pump.dm +++ b/code/modules/atmospherics/machinery/portable/pump.dm @@ -25,7 +25,6 @@ /obj/machinery/portable_atmospherics/pump/Destroy() var/turf/T = get_turf(src) T.assume_air(air_contents) - air_update_turf() QDEL_NULL(pump) return ..() @@ -57,17 +56,15 @@ pump.airs[2] = holding ? holding.air_contents : air_contents pump.process_atmos() // Pump gas. - if(!holding) - air_update_turf() // Update the environment if needed. /obj/machinery/portable_atmospherics/pump/emp_act(severity) . = ..() if(. & EMP_PROTECT_SELF) return if(is_operational()) - if(prob(50 / severity)) + if(prob(5 * severity)) on = !on - if(prob(100 / severity)) + if(prob(10 * severity)) direction = PUMP_OUT pump.target_pressure = rand(0, 100 * ONE_ATMOSPHERE) update_appearance(UPDATE_ICON) @@ -115,8 +112,8 @@ if("power") on = !on if(on && !holding) - var/plasma = air_contents.get_moles(/datum/gas/plasma) - var/n2o = air_contents.get_moles(/datum/gas/nitrous_oxide) + var/plasma = air_contents.get_moles(GAS_PLASMA) + var/n2o = air_contents.get_moles(GAS_NITROUS) if(n2o || plasma) message_admins("[ADMIN_LOOKUPFLW(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [ADMIN_VERBOSEJMP(src)]") log_admin("[key_name(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [AREACOORD(src)]") diff --git a/code/modules/atmospherics/machinery/portable/scrubber.dm b/code/modules/atmospherics/machinery/portable/scrubber.dm index f0d132d6fe71..7abd790fe477 100644 --- a/code/modules/atmospherics/machinery/portable/scrubber.dm +++ b/code/modules/atmospherics/machinery/portable/scrubber.dm @@ -9,31 +9,25 @@ volume = 1000 var/list/scrubbing = list( - /datum/gas/plasma, - /datum/gas/carbon_dioxide, - /datum/gas/nitrous_oxide, - /datum/gas/miasma, - /datum/gas/bz, - /datum/gas/nitrium, - /datum/gas/tritium, - /datum/gas/hypernoblium, - /datum/gas/dilithium, - /datum/gas/freon, - /datum/gas/hydrogen, - /datum/gas/water_vapor, - /datum/gas/healium, - /datum/gas/pluoxium, - /datum/gas/pluonium, - /datum/gas/halon, - /datum/gas/zauker, - /datum/gas/antinoblium, - /datum/gas/hexane, + GAS_PLASMA, + GAS_CO2, + GAS_NITROUS, + GAS_BZ, + GAS_NITRIUM, + GAS_TRITIUM, + GAS_HYPERNOB, + GAS_FREON, + GAS_H2O, + GAS_HEALIUM, + GAS_PLUONIUM, + GAS_HALON, + GAS_ZAUKER, + GAS_HEXANE, ) /obj/machinery/portable_atmospherics/scrubber/Destroy() var/turf/T = get_turf(src) T.assume_air(air_contents) - air_update_turf() return ..() /obj/machinery/portable_atmospherics/scrubber/update_icon_state() @@ -63,32 +57,27 @@ if(air_contents.return_pressure() >= overpressure_m * ONE_ATMOSPHERE) return - var/transfer_moles = min(1, volume_rate / mixture.return_volume()) * mixture.total_moles() - - var/datum/gas_mixture/filtering = mixture.remove(transfer_moles) // Remove part of the mixture to filter. - if(!filtering) - return - - filtering.scrub_into(air_contents, scrubbing) - - mixture.merge(filtering) // Returned the cleaned gas. - if(!holding) - air_update_turf() + mixture.scrub_into(air_contents, volume_rate / mixture.return_volume(), scrubbing) /obj/machinery/portable_atmospherics/scrubber/emp_act(severity) . = ..() if(. & EMP_PROTECT_SELF) return if(is_operational()) - if(prob(50 / severity)) + if(prob(5 * severity)) on = !on update_appearance(UPDATE_ICON) + +/obj/machinery/portable_atmospherics/scrubber/ui_state(mob/user) + return GLOB.physical_state + /obj/machinery/portable_atmospherics/scrubber/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, "PortableScrubber", name) + ui = new(user, src, "PortableScrubber") ui.open() + ui.set_autoupdate(TRUE) // Air pressure, tank pressure /obj/machinery/portable_atmospherics/scrubber/ui_data() var/data = list() @@ -98,9 +87,8 @@ data["id_tag"] = -1 //must be defined in order to reuse code between portable and vent scrubbers data["filter_types"] = list() - for(var/path in GLOB.meta_gas_info) - var/list/gas = GLOB.meta_gas_info[path] - data["filter_types"] += list(list("gas_id" = gas[META_GAS_ID], "gas_name" = gas[META_GAS_NAME], "enabled" = (path in scrubbing))) + for(var/id in GLOB.gas_data.ids) + data["filter_types"] += list(list("gas_id" = id, "gas_name" = GLOB.gas_data.labels[id], "enabled" = (id in scrubbing))) if(holding) data["holding"] = list() @@ -118,7 +106,7 @@ on = FALSE update_appearance(UPDATE_ICON) else if(on && holding) - investigate_log("[key_name(user)] started a transfer into [holding].
", INVESTIGATE_ATMOS) + investigate_log("[key_name(user)] started a transfer into [holding].", INVESTIGATE_ATMOS) /obj/machinery/portable_atmospherics/scrubber/ui_act(action, params) if(..()) @@ -132,9 +120,10 @@ replace_tank(usr, FALSE) . = TRUE if("toggle_filter") - scrubbing ^= gas_id2path(params["val"]) + scrubbing ^= params["val"] . = TRUE - update_appearance(UPDATE_ICON) + if(.) + update_appearance(UPDATE_ICON) /obj/machinery/portable_atmospherics/scrubber/huge name = "huge air scrubber" diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index 94b0f590c0d0..5627157c0fb5 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -403,7 +403,7 @@ /obj/effect/mob_spawn/human/bartender/alive/space name = "space bartender sleeper" - flavour_text = "You got this place from your old man, a bar in the middle of nowhere. Or at least, until NanoTrasen decided to move in. Time to mix drinks and change lives." + flavour_text = "You got this place from your old man, a bar in the middle of nowhere. Or at least, until Nanotrasen decided to move in. Time to mix drinks and change lives." important_info = "Do not leave your post under any circumstances!" outfit = /datum/outfit/spacebartender/space diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm index 0f09fe7b60b2..9a58051c044c 100644 --- a/code/modules/awaymissions/mission_code/snowdin.dm +++ b/code/modules/awaymissions/mission_code/snowdin.dm @@ -151,8 +151,8 @@ /turf/open/floor/plasteel/dark/snowdin initial_gas_mix = FROZEN_ATMOS - planetary_atmos = 1 - temperature = 180 + planetary_atmos = TRUE + initial_temperature = 180 /turf/open/lava/plasma name = "liquid plasma" diff --git a/code/modules/cargo/bounties/engineering.dm b/code/modules/cargo/bounties/engineering.dm index a2dad0de195f..921a1c71d056 100644 --- a/code/modules/cargo/bounties/engineering.dm +++ b/code/modules/cargo/bounties/engineering.dm @@ -13,61 +13,61 @@ name = "Full Tank of Pluoxium" description = "CentCom RnD is researching extra compact internals. Ship us a tank full of Pluoxium and you'll be compensated. (20 Moles)" reward = 2500 - gas_type = /datum/gas/pluoxium + gas_type = GAS_PLUOXIUM /datum/bounty/item/atmos/simple/nitrium_tank name = "Full Tank of Nitrium" description = "The non-human staff of Station 88 has been volunteered to test performance enhancing drugs. Ship them a tank full of Nitrium so they can get started. (20 Moles)" reward = 12000 - gas_type = /datum/gas/nitrium + gas_type = GAS_NITRIUM /datum/bounty/item/atmos/simple/tritium_tank name = "Full Tank of Tritium" description = "Station 49 is looking to kickstart their research program. Ship them a tank full of Tritium. (20 Moles)" reward = 3500 - gas_type = /datum/gas/tritium + gas_type = GAS_TRITIUM /datum/bounty/item/atmos/simple/freon_tank name = "Full Tank of Freon" description = "The Supermatter of station 33 has started the delamination process. Deliver a tank of Freon gas to help them stop it! (20 Moles)" reward = 4500 - gas_type = /datum/gas/freon + gas_type = GAS_FREON /datum/bounty/item/atmos/simple/healium_tank name = "Full Tank of Healium" description = "Station 42's medical staff are working on an experimental cryogenics setup. They need a tank of Healium. (20 Moles)" reward = 8000 - gas_type = /datum/gas/healium + gas_type = GAS_HEALIUM /datum/bounty/item/atmos/complex/zauker_tank name = "Full Tank of Zauker" description = "The main planet of \[REDACTED] has been chosen as testing grounds for the new weapon that uses Zauker gas. Ship us a tank full of it. (20 Moles)" reward = 25000 - gas_type = /datum/gas/zauker + gas_type = GAS_ZAUKER /datum/bounty/item/atmos/complex/hypernob_tank name = "Full Tank of Hypernoblium" description = "Station 26's atmospheric division has had a mishap with an experimental fusion mix. Some Hyper-Noblium would be appreciated. (20 Moles)" reward = 15000 - gas_type = /datum/gas/hypernoblium + gas_type = GAS_HYPERNOB /datum/bounty/item/h2metal/metallic_hydrogen_armor - name = "Metallic Hydrogen Armors" - description = "Nanotrasen is requiring new armor to be made. Ship them some metallic hydrogen armors." + name = "Metallic Hydrogen Armor" + description = "Nanotrasen is requiring new armor to be made. Ship them 1 metallic hydrogen armor." reward = 8000 required_count = 1 wanted_types = list(/obj/item/clothing/suit/armor/elder_atmosian) /datum/bounty/item/h2metal/metallic_hydrogen_helmet - name = "Metallic Hydrogen Armors" - description = "Nanotrasen is requiring new helmet to be made. Ship them some metallic hydrogen helmets." + name = "Metallic Hydrogen Helmet" + description = "Nanotrasen is requiring new helmet to be made. Ship them 1 metallic hydrogen helmet." reward = 7000 required_count = 1 wanted_types = list(/obj/item/clothing/head/helmet/elder_atmosian) /datum/bounty/item/h2metal/metallic_hydrogen_axe name = "Metallic Hydrogen Axes" - description = "Nanotrasen is requiring new axes to be made. Ship them some metallic hydrogen helmets." + description = "Nanotrasen is requiring new axes to be made. Ship them 3 metallic hydrogen axes." reward = 7500 required_count = 3 wanted_types = list(/obj/item/fireaxe/metal_h2_axe) diff --git a/code/modules/cargo/export_scanner.dm b/code/modules/cargo/export_scanner.dm index f4304126d034..95df716acc68 100644 --- a/code/modules/cargo/export_scanner.dm +++ b/code/modules/cargo/export_scanner.dm @@ -8,7 +8,6 @@ righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' item_flags = NOBLUDGEON w_class = WEIGHT_CLASS_SMALL - siemens_coefficient = 1 var/obj/machinery/computer/cargo/cargo_console = null /obj/item/export_scanner/examine(user) diff --git a/code/modules/cargo/expressconsole.dm b/code/modules/cargo/expressconsole.dm index 3ec66739dcfe..ca3636f094a0 100644 --- a/code/modules/cargo/expressconsole.dm +++ b/code/modules/cargo/expressconsole.dm @@ -9,7 +9,7 @@ /obj/machinery/computer/cargo/express name = "express supply console" desc = "This console allows the user to purchase a package \ - with 1/40th of the delivery time: made possible by NanoTrasen's new \"1500mm Orbital Railgun\".\ + with 1/40th of the delivery time: made possible by Nanotrasen's new \"1500mm Orbital Railgun\".\ All sales are near instantaneous - please choose carefully" icon_screen = "supply_express" circuit = /obj/item/circuitboard/computer/cargo/express diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm index 14bdcf196981..e7b753fc64c1 100644 --- a/code/modules/cargo/packs.dm +++ b/code/modules/cargo/packs.dm @@ -276,12 +276,15 @@ /datum/supply_pack/security/armor name = "Armor Crate" - desc = "Three vests of well-rounded, decently-protective armor. Requires Security access to open." - cost = 1000 + desc = "Three sets of well-rounded, decently-protective armor and helmet. Requires Security access to open." + cost = 2000 access_view = ACCESS_SECURITY - contains = list(/obj/item/clothing/suit/armor/vest, - /obj/item/clothing/suit/armor/vest, - /obj/item/clothing/suit/armor/vest) + contains = list(/obj/item/clothing/suit/armor/vest/alt, + /obj/item/clothing/suit/armor/vest/alt, + /obj/item/clothing/suit/armor/vest/alt, + /obj/item/clothing/head/helmet/sec, + /obj/item/clothing/head/helmet/sec, + /obj/item/clothing/head/helmet/sec) crate_name = "armor crate" /datum/supply_pack/security/disabler @@ -315,15 +318,6 @@ /obj/item/clothing/head/fedora/det_hat) crate_name = "forensics crate" -/datum/supply_pack/security/helmets - name = "Helmets Crate" - desc = "Contains three standard-issue brain buckets. Requires Security access to open." - cost = 1000 - contains = list(/obj/item/clothing/head/helmet/sec, - /obj/item/clothing/head/helmet/sec, - /obj/item/clothing/head/helmet/sec) - crate_name = "helmet crate" - /datum/supply_pack/security/laser name = "Lasers Crate" desc = "Contains three lethal, high-energy laser guns. Requires Security access to open." @@ -522,21 +516,15 @@ /datum/supply_pack/security/armory/bulletarmor name = "Bulletproof Armor Crate" - desc = "Contains three sets of bulletproof armor. Guaranteed to reduce a bullet's stopping power by over half. Requires Armory access to open." - cost = 1500 + desc = "Contains three sets of bulletproof armor and helmet. Guaranteed to reduce a bullet's stopping power by over half. Requires Armory access to open." + cost = 3000 contains = list(/obj/item/clothing/suit/armor/bulletproof, /obj/item/clothing/suit/armor/bulletproof, - /obj/item/clothing/suit/armor/bulletproof) - crate_name = "bulletproof armor crate" - -/datum/supply_pack/security/armory/bullethelmets - name = "Bulletproof Helmet Crate" - desc = "Contains three bulletproof helmets, perfect for protecting the void inside your skull. Requires Armory access to open." - cost = 1500 - contains = list(/obj/item/clothing/head/helmet/alt, + /obj/item/clothing/suit/armor/bulletproof, + /obj/item/clothing/head/helmet/alt, /obj/item/clothing/head/helmet/alt, /obj/item/clothing/head/helmet/alt) - crate_name = "bulletproof helmet crate" + crate_name = "bulletproof armor crate" /datum/supply_pack/security/armory/chemimp name = "Chemical Implants Crate" @@ -579,21 +567,15 @@ /datum/supply_pack/security/armory/riotarmor name = "Riot Armor Crate" - desc = "Contains three sets of heavy body armor. Advanced padding protects against close-ranged weaponry, making melee attacks feel only half as potent to the user. Requires Armory access to open." - cost = 1500 + desc = "Contains three sets of heavy body armor and helmet. Advanced padding protects against close-ranged weaponry, making melee attacks feel only half as potent to the user. Requires Armory access to open." + cost = 3000 contains = list(/obj/item/clothing/suit/armor/riot, /obj/item/clothing/suit/armor/riot, - /obj/item/clothing/suit/armor/riot) - crate_name = "riot armor crate" - -/datum/supply_pack/security/armory/riothelmets - name = "Riot Helmets Crate" - desc = "Contains three riot helmets. Requires Armory access to open." - cost = 1500 - contains = list(/obj/item/clothing/head/helmet/riot, + /obj/item/clothing/suit/armor/riot, + /obj/item/clothing/head/helmet/riot, /obj/item/clothing/head/helmet/riot, /obj/item/clothing/head/helmet/riot) - crate_name = "riot helmets crate" + crate_name = "riot armor crate" /datum/supply_pack/security/armory/riotshields name = "Riot Shields Crate" @@ -1002,17 +984,6 @@ crate_name = "power cell crate" crate_type = /obj/structure/closet/crate/engineering/electrical -/datum/supply_pack/engineering/portable_pumps - name = "Portable Pumps" - desc = "A set of spare portable pumps. Perfect for larger atmospheric projects or restocking after a toxins problem goes wrong." - cost = 1500 - contains = list( - /obj/machinery/portable_atmospherics/pump, - /obj/machinery/portable_atmospherics/pump - ) - crate_name = "portable pump crate" - crate_type = /obj/structure/closet/crate/large - /datum/supply_pack/engineering/portable_scrubbers name = "Portable Scrubbers" desc = "A set of spare portable scrubbers. Perfect for when plasma 'accidentally' gets into the air supply." diff --git a/code/modules/client/client_colour.dm b/code/modules/client/client_colour.dm index ba7fcdbcebd4..c59259bc307b 100644 --- a/code/modules/client/client_colour.dm +++ b/code/modules/client/client_colour.dm @@ -15,9 +15,6 @@ var/colour = "" //Any client.color-valid value var/priority = 1 //Since only one client.color can be rendered on screen, we take the one with the highest priority value: //eg: "Bloody screen" > "goggles colour" as the former is much more important -/mob - var/list/client_colours = list() - /* diff --git a/code/modules/client/preferences/chapel_choice.dm b/code/modules/client/preferences/chapel_choice.dm new file mode 100644 index 000000000000..932967a4f215 --- /dev/null +++ b/code/modules/client/preferences/chapel_choice.dm @@ -0,0 +1,23 @@ +/// Which chapel to spawn on boxstation +/datum/preference/choiced/chapel_choice + category = PREFERENCE_CATEGORY_NON_CONTEXTUAL + savefile_key = "chapel_choice" + savefile_identifier = PREFERENCE_CHARACTER + can_randomize = FALSE + +/datum/preference/choiced/chapel_choice/create_default_value() + return "Random" + +/datum/preference/choiced/chapel_choice/init_possible_values() + return GLOB.potential_box_chapels + "Random" + +/datum/preference/choiced/chapel_choice/is_accessible(datum/preferences/preferences) + if (!..(preferences)) + return FALSE + + // Job needs to be medium or high for the preference to show up + return preferences.job_preferences["Chaplain"] >= JP_MEDIUM + +/datum/preference/choiced/chapel_choice/apply_to_human(mob/living/carbon/human/target, value) + return + diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm index 9ce10ac5e6e3..43562cd6d269 100644 --- a/code/modules/clothing/chameleon.dm +++ b/code/modules/clothing/chameleon.dm @@ -598,7 +598,7 @@ icon_state = "black" desc = "A pair of black shoes." resistance_flags = NONE - armor = list(MELEE = 10, BULLET = 10, LASER = 10, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 50, ACID = 50) + armor = list(MELEE = 10, BULLET = 10, LASER = 10, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 50, ACID = 50, ELECTRIC = 100) pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes var/datum/action/item_action/chameleon/change/chameleon_action diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index c2dc8a24625e..795b1f3d5cee 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -284,29 +284,8 @@ /obj/item/clothing/Topic(href, href_list) . = ..() - if(href_list["list_armor"]) - var/list/readout = list("PROTECTION CLASSES") - if(armor.bio || armor.bomb || armor.bullet || armor.energy || armor.laser || armor.melee) - readout += "\nARMOR (I-X)" - if(armor.bio) - readout += "\nTOXIN [armor_to_protection_class(armor.bio)]" - if(armor.bomb) - readout += "\nEXPLOSIVE [armor_to_protection_class(armor.bomb)]" - if(armor.bullet) - readout += "\nBULLET [armor_to_protection_class(armor.bullet)]" - if(armor.energy) - readout += "\nENERGY [armor_to_protection_class(armor.energy)]" - if(armor.laser) - readout += "\nLASER [armor_to_protection_class(armor.laser)]" - if(armor.melee) - readout += "\nMELEE [armor_to_protection_class(armor.melee)]" - if(armor.fire || armor.acid) - readout += "\nDURABILITY (I-X)" - if(armor.fire) - readout += "\nFIRE [armor_to_protection_class(armor.fire)]" - if(armor.acid) - readout += "\nACID [armor_to_protection_class(armor.acid)]" + var/additional_info = "" if(flags_cover & HEADCOVERSMOUTH || flags_cover & HEADCOVERSEYES) var/list/things_blocked = list() if(flags_cover & HEADCOVERSMOUTH) @@ -314,24 +293,9 @@ if(flags_cover & HEADCOVERSEYES) things_blocked += "pepperspray" if(length(things_blocked)) - readout += "\nCOVERAGE" - readout += "\nIt will block [english_list(things_blocked)]." - - readout += "" - - to_chat(usr, "[readout.Join()]") - -/** - * Rounds armor_value down to the nearest 10, divides it by 10 and then converts it to Roman numerals. - * - * Arguments: - * * armor_value - Number we're converting - */ -/obj/item/clothing/proc/armor_to_protection_class(armor_value) - if (armor_value < 0) - . = "-" - . += "\Roman[round(abs(armor_value), 10) / 10]" - return . + additional_info += "\nCOVERAGE" + additional_info += "\nIt will block [english_list(things_blocked)]." + to_chat(usr, "[armor.show_protection_classes(additional_info)]") /obj/item/clothing/obj_break(damage_flag) damaged_clothes = CLOTHING_DAMAGED diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm index 8091745f8cb5..0535f58f0576 100644 --- a/code/modules/clothing/gloves/_gloves.dm +++ b/code/modules/clothing/gloves/_gloves.dm @@ -3,13 +3,13 @@ gender = PLURAL //Carn: for grammarically correct text-parsing w_class = WEIGHT_CLASS_SMALL icon = 'icons/obj/clothing/gloves.dmi' - siemens_coefficient = 0.5 body_parts_covered = HANDS slot_flags = ITEM_SLOT_GLOVES attack_verb = list("challenged") var/transfer_prints = FALSE strip_delay = 20 equip_delay_other = 40 + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 0, ELECTRIC = 50) /obj/item/clothing/gloves/wash(clean_types) . = ..() diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index ee13940d5297..fdc36d7ac040 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -6,8 +6,7 @@ name = "insulated gloves" icon_state = "yellow" item_state = "ygloves" - siemens_coefficient = 0 - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 0, ACID = 0) + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 0, ACID = 0, ELECTRIC = 100) resistance_flags = NONE /obj/item/clothing/gloves/color/fyellow //Cheap Chinese Crap @@ -15,8 +14,7 @@ name = "budget insulated gloves" icon_state = "yellow" item_state = "ygloves" - siemens_coefficient = 0 - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 0, ACID = 0) + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 0, ACID = 0, ELECTRIC = 100) resistance_flags = NONE var/damaged = FALSE @@ -84,8 +82,7 @@ /obj/item/clothing/gloves/color/red/insulated name = "insulated gloves" desc = "These gloves will protect the wearer from electric shock." - siemens_coefficient = 0 - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 0, ACID = 0) + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 0, ACID = 0, ELECTRIC = 100) resistance_flags = NONE /obj/item/clothing/gloves/color/rainbow @@ -135,13 +132,12 @@ name = "captain's gloves" icon_state = "captain" item_state = "egloves" - siemens_coefficient = 0 cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT strip_delay = 60 - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 70, ACID = 50) + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 70, ACID = 50, ELECTRIC = 100) /obj/item/clothing/gloves/color/captain/centcom desc = "Regal green gloves, with a nice gold trim, a diamond anti-shock coating, and an integrated thermal barrier. Swanky." @@ -160,10 +156,9 @@ desc = "Cheap sterile gloves made from latex. Transfers minor paramedic knowledge to the user via budget nanochips." icon_state = "latex" item_state = "lgloves" - siemens_coefficient = 0.3 transfer_prints = TRUE resistance_flags = NONE - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 0, ACID = 0) + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 0, ACID = 0, ELECTRIC = 70) clothing_traits = list(TRAIT_QUICK_CARRY) var/surgeryspeed = 0.9 //how much these gloves speed up surgery diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm index b29fb22c2084..e76ea5d08620 100644 --- a/code/modules/clothing/gloves/miscellaneous.dm +++ b/code/modules/clothing/gloves/miscellaneous.dm @@ -5,13 +5,13 @@ icon_state = "fingerless" item_state = "fingerless" transfer_prints = TRUE - siemens_coefficient = 1 //What no if you touch things with your bare fingies you're gonna get shocked strip_delay = 40 equip_delay_other = 20 cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT custom_price = 10 undyeable = TRUE + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 0, ELECTRIC = 0) var/tacticalspeed = 0.9 var/worn @@ -63,14 +63,13 @@ desc = "These tactical gloves are fireproof and shock resistant." icon_state = "black" item_state = "blackgloves" - siemens_coefficient = 0 strip_delay = 80 cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 80, ACID = 50) + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 80, ACID = 50, ELECTRIC = 100) /obj/item/clothing/gloves/bracer name = "bone bracers" @@ -78,7 +77,6 @@ icon_state = "bracers" item_state = "bracers" transfer_prints = TRUE - siemens_coefficient = 1 //They're not gloves? strip_delay = 40 equip_delay_other = 20 body_parts_covered = ARMS @@ -86,7 +84,7 @@ min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE - armor = list(MELEE = 15, BULLET = 25, LASER = 15, ENERGY = 15, BOMB = 20, BIO = 10, RAD = 0, FIRE = 0, ACID = 0) + armor = list(MELEE = 15, BULLET = 25, LASER = 15, ENERGY = 15, BOMB = 20, BIO = 10, RAD = 0, FIRE = 0, ACID = 0, ELECTRIC = 0) /obj/item/clothing/gloves/rapid name = "Gloves of the North Star" @@ -264,8 +262,7 @@ heat_protection = HANDS max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF - siemens_coefficient = 0.2 - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 90, RAD = 0, FIRE = 100, ACID = 90) + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 90, RAD = 0, FIRE = 100, ACID = 90, ELECTRIC = 80) clothing_flags = THICKMATERIAL clothing_traits = list(TRAIT_QUICKEST_CARRY, TRAIT_RESISTHEATHANDS) @@ -273,4 +270,4 @@ name = "advanced insulated gloves" desc = "These gloves provide excellent thermal and electrical insulation." icon_state = "ce_insuls" - siemens_coefficient = 0 + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 90, RAD = 0, FIRE = 100, ACID = 90, ELECTRIC = 100) diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index a5c994bfb7fc..ca282661132b 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -4,7 +4,7 @@ icon_state = "hardhat0_yellow" item_state = "hardhat0_yellow" mob_overlay_icon = 'icons/mob/clothing/head/head.dmi' - armor = list(MELEE = 15, BULLET = 5, LASER = 20, ENERGY = 10, BOMB = 20, BIO = 10, RAD = 20, FIRE = 100, ACID = 50, WOUND = 10) + armor = list(MELEE = 15, BULLET = 5, LASER = 20, ENERGY = 10, BOMB = 20, BIO = 10, RAD = 20, FIRE = 100, ACID = 50, WOUND = 10, ELECTRIC = 100) // now OSHA-compliant! flags_inv = 0 actions_types = list(/datum/action/item_action/toggle_helmet_light) resistance_flags = FIRE_PROOF diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index ce5288b44381..3af7218fff12 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -111,6 +111,8 @@ attack_verb = list("poked", "tipped") embedding = list("embed_chance" = 0) //Zero percent chance to embed var/extended = 0 + var/mob/living/carbon/fedora_man + var/returning = FALSE /obj/item/clothing/head/det_hat/evil/attack_self(mob/user) extended = !extended @@ -127,6 +129,7 @@ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut", "tipped") hitsound = 'sound/weapons/bladeslice.ogg' hattable = FALSE //So you don't accidentally throw it onto somebody's head instead of decapitating them + item_flags = UNCATCHABLE //so it isn't just immediately caught else force = 0 throwforce = 0 @@ -136,18 +139,31 @@ attack_verb = list("poked", "tipped") hitsound = 'sound/weapons/genhit.ogg' hattable = TRUE + item_flags = NONE /obj/item/clothing/head/det_hat/evil/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) - if(iscarbon(loc) || !iscarbon(thrownby)) - return ..() - throw_at(thrownby, throw_range+3, 3, null) - ..() - -/obj/item/clothing/head/det_hat/evil/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, quickstart = TRUE) - if(iscarbon(thrower)) - var/mob/living/carbon/C = thrower - C.throw_mode_on() - ..() + if(fedora_man && hit_atom == fedora_man) + if(fedora_man.put_in_hands(src)) + fedora_man.throw_mode_on() + return + else + return ..() + . = ..() + if(fedora_man && returning) + returning = FALSE //only try to return once + if(get_turf(src) == get_turf(fedora_man))//don't try to return if the tile it hit is literally under the thrower + return + addtimer(CALLBACK(src, PROC_REF(comeback)), 1, TIMER_UNIQUE)//delay the return by such a small amount + +/obj/item/clothing/head/det_hat/evil/proc/comeback() + throw_at(fedora_man, throw_range+3, throw_speed) + +/obj/item/clothing/head/det_hat/evil/throw_at(atom/target, range, speed, mob/thrower, spin=0, diagonals_first = 0, datum/callback/callback, force, quickstart = TRUE) + if(thrower && iscarbon(thrower)) + fedora_man = thrower + fedora_man.changeNext_move(CLICK_CD_MELEE)//longer cooldown + returning = TRUE + . = ..() //Mime /obj/item/clothing/head/beret @@ -165,7 +181,7 @@ /obj/item/clothing/head/beret/archaic name = "archaic beret" - desc = "An absolutely ancient beret, allegedly worn by the first mime to ever step foot on a NanoTrasen station." + desc = "An absolutely ancient beret, allegedly worn by the first mime to ever step foot on a Nanotrasen station." icon_state = "archaicberet" dog_fashion = null @@ -322,7 +338,7 @@ /obj/item/clothing/head/beret/sec/centcom name = "\improper CentCom beret" - desc = "A special beret with the NanoTrasen logo emblazoned on it. For where no man has gone before." + desc = "A special beret with the Nanotrasen logo emblazoned on it. For where no man has gone before." icon_state = "official" //Curator diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index c26244226577..67b320c3b228 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -515,17 +515,15 @@ cloak_charge_rate = 20 cloak_dodge_loss = 40 var/cloak_emp_disable_duration = 10 SECONDS - var/cloak_emp_loss = 25 + var/cloak_emp_loss = 5 /obj/item/clothing/neck/cloak/ranger/syndie/emp_act(severity) . = ..() if(CHECK_BITFIELD(., EMP_PROTECT_SELF)) return - if(severity == EMP_HEAVY) - set_cloak(0) + if(severity > EMP_LIGHT) TIMER_COOLDOWN_START(src, "cloak_emp_disable", cloak_emp_disable_duration) - else - set_cloak(cloak - cloak_emp_loss) + set_cloak(max(cloak - (cloak_emp_loss * severity), 0)) /obj/item/clothing/neck/cloak/ranger/syndie/process(delta_time) if(TIMER_COOLDOWN_CHECK(src, "cloak_emp_disable")) diff --git a/code/modules/clothing/neck/bodycamera.dm b/code/modules/clothing/neck/bodycamera.dm index 3cd85f30beb1..21207b75cfd3 100644 --- a/code/modules/clothing/neck/bodycamera.dm +++ b/code/modules/clothing/neck/bodycamera.dm @@ -88,7 +88,7 @@ /obj/item/clothing/neck/bodycam/emp_act(severity) . = ..() - if(prob(150/severity)) + if(prob(15 * severity)) Disconnect() bodcam.c_tag = null bodcam.network[1] = null //requires a reset diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index 4deecec621c2..86b102144b6e 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -5,7 +5,7 @@ var/magboot_state = "magboots" var/magpulse = 0 var/slowdown_active = 2 - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 0, ACID = 0) + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 60, RAD = 0, FIRE = 0, ACID = 0, ELECTRIC = 100) actions_types = list(/datum/action/item_action/toggle) strip_delay = 70 equip_delay_other = 70 diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 3ffb8d5c5b73..95cd0b5ba2c1 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -12,7 +12,7 @@ item_state = "jackboots" lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' - armor = list(MELEE = 25, BULLET = 25, LASER = 25, ENERGY = 25, BOMB = 50, BIO = 60, RAD = 0, FIRE = 70, ACID = 50) + armor = list(MELEE = 25, BULLET = 25, LASER = 25, ENERGY = 25, BOMB = 50, BIO = 60, RAD = 0, FIRE = 70, ACID = 50, ELECTRIC = 100) strip_delay = 70 resistance_flags = NONE pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes @@ -25,7 +25,7 @@ name = "\improper SWAT boots" desc = "High speed, no drag combat boots." clothing_flags = NOSLIP - armor = list(MELEE = 40, BULLET = 30, LASER = 25, ENERGY = 25, BOMB = 50, BIO = 100, RAD = 30, FIRE = 90, ACID = 50) + armor = list(MELEE = 40, BULLET = 30, LASER = 25, ENERGY = 25, BOMB = 50, BIO = 100, RAD = 30, FIRE = 90, ACID = 50, ELECTRIC = 100) /obj/item/clothing/shoes/sandal desc = "A pair of rather plain wooden sandals." @@ -55,7 +55,7 @@ strip_delay = 50 equip_delay_other = 50 resistance_flags = NONE - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 100, RAD = 0, FIRE = 40, ACID = 75) + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 100, RAD = 0, FIRE = 40, ACID = 75, ELECTRIC = 100) can_be_bloody = FALSE custom_price = 100 @@ -169,7 +169,7 @@ /obj/item/clothing/shoes/workboots name = "work boots" - desc = "Nanotrasen-issue Engineering lace-up work boots for the especially blue-collar." + desc = "Nanotrasen-issue Engineering lace-up work boots for the especially blue-collar. Electrically insulated to protect from hazardous work environments." icon_state = "workboots" item_state = "jackboots" lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' @@ -177,7 +177,7 @@ strip_delay = 40 equip_delay_other = 40 pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 40, RAD = 0, FIRE = 0, ACID = 0) + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 40, RAD = 0, FIRE = 0, ACID = 0, ELECTRIC = 100) /obj/item/clothing/shoes/workboots/mining name = "mining boots" @@ -451,7 +451,7 @@ /obj/item/clothing/shoes/xeno_wraps //Standard for all digitigrade legs and feets name = "footwraps" - desc = "Standard issue NanoTrasen cloth footwraps for those with podiatric deficiencies. They're quite itchy and scratchy." + desc = "Standard issue Nanotrasen cloth footwraps for those with podiatric deficiencies. They're quite itchy and scratchy." icon_state = "footwraps" item_state = "footwraps" xenoshoe = EITHER_STYLE // This can be worn by digitigrade or straight legs, or a hybridization thereof (one prosthetic one digitigrade). Xenoshoe variable will default to NO_DIGIT, excluding digitigrade feet. @@ -469,7 +469,7 @@ /obj/item/clothing/shoes/xeno_wraps/command // Not applicable unless 11505 merges - Digitigrade-exclusive shoes for Command positions name = "command footwraps" - desc = "These Command-grade NanoTrasen fiber footwraps exude an air of refinement not often felt by those with alien podiatric structures." + desc = "These Command-grade Nanotrasen fiber footwraps exude an air of refinement not often felt by those with alien podiatric structures." icon_state = "footwraps_c" item_state = "footwraps_c" xenoshoe = YES_DIGIT // This is digitigrade leg exclusive @@ -509,15 +509,16 @@ /obj/item/clothing/shoes/xeno_wraps/engineering name = "engineering footwraps" - desc = "Standard issue NanoTrasen cloth footwraps, specially made for the frequent glass treader." + desc = "Standard issue Nanotrasen cloth footwraps, specially made for the frequent glass treader. Electrically insulated." icon_state = "footwraps_e" item_state = "footwraps_e" xenoshoe = YES_DIGIT mutantrace_variation = MUTANTRACE_VARIATION + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 15, RAD = 0, FIRE = 0, ACID = 0, ELECTRIC = 100) /obj/item/clothing/shoes/xeno_wraps/science name = "science footwraps" - desc = "Standard issue NanoTrasen cloth footwraps, to reduce fatigue when standing at a console all day." + desc = "Standard issue Nanotrasen cloth footwraps, to reduce fatigue when standing at a console all day." icon_state = "footwraps_sc" item_state = "footwraps_sc" xenoshoe = YES_DIGIT @@ -525,7 +526,7 @@ /obj/item/clothing/shoes/xeno_wraps/medical name = "medical footwraps" - desc = "Standard issue NanoTrasen cloth footwraps, for when you dont want other people's blood all over your feet." + desc = "Standard issue Nanotrasen cloth footwraps, for when you dont want other people's blood all over your feet." icon_state = "footwraps_m" item_state = "footwraps_m" xenoshoe = YES_DIGIT @@ -533,7 +534,7 @@ /obj/item/clothing/shoes/xeno_wraps/cargo name = "cargo footwraps" - desc = "Standard issue NanoTrasen cloth footwraps, with reinforcment to protect against falling crates." + desc = "Standard issue Nanotrasen cloth footwraps, with reinforcment to protect against falling crates." icon_state = "footwraps_ca" item_state = "footwraps_ca" xenoshoe = YES_DIGIT diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm index 4e7e5b6b3e97..2cac53d24947 100644 --- a/code/modules/clothing/spacesuits/chronosuit.dm +++ b/code/modules/clothing/spacesuits/chronosuit.dm @@ -73,13 +73,11 @@ if(. & EMP_PROTECT_SELF) return var/mob/living/carbon/human/user = src.loc - switch(severity) - if(1) - if(activated && user && ishuman(user) && (user.wear_suit == src)) - to_chat(user, span_danger("E:FATAL:RAM_READ_FAIL\nE:FATAL:STACK_EMPTY\nE:FATAL:READ_NULL_POINT\nE:FATAL:PWR_BUS_OVERLOAD")) - to_chat(user, span_userdanger("An electromagnetic pulse disrupts your [name] and violently tears you out of time-bluespace!")) - user.emote("scream") - deactivate(1, 1) + if(severity > EMP_LIGHT && activated && user && ishuman(user) && (user.wear_suit == src)) + to_chat(user, span_danger("E:FATAL:RAM_READ_FAIL\nE:FATAL:STACK_EMPTY\nE:FATAL:READ_NULL_POINT\nE:FATAL:PWR_BUS_OVERLOAD")) + to_chat(user, span_userdanger("An electromagnetic pulse disrupts your [name] and violently tears you out of time-bluespace!")) + user.emote("scream") + deactivate(1, 1) /obj/item/clothing/suit/space/chronos/proc/finish_chronowalk(mob/living/carbon/human/user, turf/to_turf) if(!user) @@ -223,7 +221,7 @@ teleport_now.Remove(user) if(user.wear_suit == src) if(hard_landing) - user.electrocute_act(35, src, safety = 1) + user.electrocute_act(35, src, zone = null) user.Paralyze(200) if(!silent) to_chat(user, "\nroot@ChronosuitMK4# chronowalk4 --stop\n") @@ -246,7 +244,7 @@ density = FALSE anchored = TRUE invisibility = INVISIBILITY_ABSTRACT - opacity = 0 + opacity = FALSE mouse_opacity = MOUSE_OPACITY_TRANSPARENT var/mob/holder var/phase_time = 0 diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index 2975673406ea..e0ff6a6a2d76 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -144,7 +144,7 @@ /obj/item/clothing/head/helmet/space/hardsuit/emp_act(severity) . = ..() - display_visor_message("[severity > 1 ? "Light" : "Strong"] electromagnetic pulse detected!") + display_visor_message("Electromagnetic pulse detected! Severity: [severity]") /obj/item/clothing/suit/space/hardsuit @@ -153,9 +153,8 @@ icon_state = "hardsuit-engineering" item_state = "eng_hardsuit" max_integrity = 300 - armor = list(MELEE = 10, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 75, FIRE = 50, ACID = 75, WOUND = 10) + armor = list(MELEE = 10, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 75, FIRE = 50, ACID = 75, WOUND = 10, ELECTRIC = 100) allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/t_scanner, /obj/item/construction/rcd, /obj/item/pipe_dispenser) - siemens_coefficient = 0 actions_types = list(/datum/action/item_action/toggle_helmet) var/obj/item/clothing/head/helmet/space/hardsuit/helmet @@ -228,7 +227,7 @@ icon_state = "hardsuit0-engineering" item_state = "eng_helm" hardsuit_type = "engineering" - armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 100, FIRE = 100, ACID = 75, WOUND = 10) + armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 100, FIRE = 100, ACID = 75, WOUND = 10, ELECTRIC = 100) resistance_flags = FIRE_PROOF /obj/item/clothing/suit/space/hardsuit/engine @@ -236,7 +235,7 @@ desc = "A special suit that protects against hazardous, low pressure environments. Has radiation shielding." icon_state = "hardsuit-engineering" item_state = "eng_hardsuit" - armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 100, FIRE = 100, ACID = 75, WOUND = 10) + armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 100, FIRE = 100, ACID = 75, WOUND = 10, ELECTRIC = 100) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/engine resistance_flags = FIRE_PROOF @@ -247,7 +246,7 @@ icon_state = "hardsuit0-atmospherics" item_state = "atmo_helm" hardsuit_type = "atmospherics" - armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 25, FIRE = 100, ACID = 75, WOUND = 10) + armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 25, FIRE = 100, ACID = 75, WOUND = 10, ELECTRIC = 100) heat_protection = HEAD //Uncomment to enable firesuit protection max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT @@ -256,7 +255,7 @@ desc = "A special suit that protects against hazardous, low pressure environments. Has thermal shielding." icon_state = "hardsuit-atmospherics" item_state = "atmo_hardsuit" - armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 25, FIRE = 100, ACID = 75, WOUND = 10) + armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 25, FIRE = 100, ACID = 75, WOUND = 10, ELECTRIC = 100) heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS //Uncomment to enable firesuit protection max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT helmettype = /obj/item/clothing/head/helmet/space/hardsuit/engine/atmos @@ -268,7 +267,7 @@ icon_state = "hardsuit0-flight" item_state = "flighthelmet" hardsuit_type = "flight" - armor = list(MELEE = 40, BULLET = 35, LASER = 25, ENERGY = 30, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100, WOUND = 20) + armor = list(MELEE = 40, BULLET = 35, LASER = 25, ENERGY = 30, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100, WOUND = 20, ELECTRIC = 100) heat_protection = HEAD //Uncomment to enable firesuit protection max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF @@ -279,7 +278,7 @@ desc = "A special suit that protects against hazardous, low pressure environments. Has thermal shielding. This one is made with the toughest and rarest materials available to man." icon_state = "flightsuit" item_state = "flightsuit" - armor = list(MELEE = 40, BULLET = 35, LASER = 25, ENERGY = 30, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100, WOUND = 20) + armor = list(MELEE = 40, BULLET = 35, LASER = 25, ENERGY = 30, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100, WOUND = 20, ELECTRIC = 100) heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS //Uncomment to enable firesuit protection max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT helmettype = /obj/item/clothing/head/helmet/space/hardsuit/elder_atmosian @@ -295,7 +294,7 @@ icon_state = "hardsuit0-white" item_state = "ce_helm" hardsuit_type = "white" - armor = list(MELEE = 40, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 50, BIO = 100, RAD = 100, FIRE = 100, ACID = 90, WOUND = 10) + armor = list(MELEE = 40, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 50, BIO = 100, RAD = 100, FIRE = 100, ACID = 90, WOUND = 10, ELECTRIC = 100) heat_protection = HEAD max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT @@ -304,7 +303,7 @@ name = "advanced hardsuit" desc = "An advanced suit that protects against hazardous, low pressure environments. Shines with a high polish." item_state = "ce_hardsuit" - armor = list(MELEE = 40, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 50, BIO = 100, RAD = 100, FIRE = 100, ACID = 90, WOUND = 10) + armor = list(MELEE = 40, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 50, BIO = 100, RAD = 100, FIRE = 100, ACID = 90, WOUND = 10, ELECTRIC = 100) heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT helmettype = /obj/item/clothing/head/helmet/space/hardsuit/engine/elite @@ -320,7 +319,7 @@ max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF heat_protection = HEAD - armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 50, BIO = 100, RAD = 50, FIRE = 50, ACID = 75, WOUND = 15) + armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 50, BIO = 100, RAD = 50, FIRE = 50, ACID = 75, WOUND = 15, ELECTRIC = 100) light_range = 7 allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator) @@ -335,7 +334,7 @@ item_state = "mining_hardsuit" max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF - armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 50, BIO = 100, RAD = 50, FIRE = 50, ACID = 75, WOUND = 15) + armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 50, BIO = 100, RAD = 50, FIRE = 50, ACID = 75, WOUND = 15, ELECTRIC = 100) allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/storage/bag/ore, /obj/item/pickaxe) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/mining heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS @@ -352,7 +351,7 @@ icon_state = "hardsuit1-syndi" item_state = "syndie_helm" hardsuit_type = "syndi" - armor = list(MELEE = 40, BULLET = 50, LASER = 30, ENERGY = 25, BOMB = 50, BIO = 100, RAD = 50, FIRE = 50, ACID = 90, WOUND = 25) + armor = list(MELEE = 40, BULLET = 50, LASER = 30, ENERGY = 25, BOMB = 50, BIO = 100, RAD = 50, FIRE = 50, ACID = 90, WOUND = 25, ELECTRIC = 100) on = TRUE actions_types = list(/datum/action/item_action/toggle_helmet_mode) visor_flags_inv = HIDEMASK|HIDEEYES|HIDEFACE|HIDEFACIALHAIR @@ -432,7 +431,7 @@ item_state = "syndie_hardsuit" hardsuit_type = "syndi" w_class = WEIGHT_CLASS_NORMAL - armor = list(MELEE = 40, BULLET = 50, LASER = 30, ENERGY = 25, BOMB = 50, BIO = 100, RAD = 50, FIRE = 50, ACID = 90, WOUND = 25) + armor = list(MELEE = 40, BULLET = 50, LASER = 30, ENERGY = 25, BOMB = 50, BIO = 100, RAD = 50, FIRE = 50, ACID = 90, WOUND = 25, ELECTRIC = 100) allowed = list(/obj/item/gun, /obj/item/ammo_box,/obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/fireaxe/energy) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/syndi jetpack = /obj/item/tank/jetpack/suit @@ -444,7 +443,7 @@ alt_desc = "An elite version of the syndicate helmet, with improved armour and fireproofing. It is in combat mode. Property of Gorlex Marauders." icon_state = "hardsuit1-syndielite" hardsuit_type = "syndielite" - armor = list(MELEE = 60, BULLET = 60, LASER = 50, ENERGY = 35, BOMB = 90, BIO = 100, RAD = 70, FIRE = 100, ACID = 100, WOUND = 25) + armor = list(MELEE = 60, BULLET = 60, LASER = 50, ENERGY = 35, BOMB = 90, BIO = 100, RAD = 70, FIRE = 100, ACID = 100, WOUND = 25, ELECTRIC = 100) heat_protection = HEAD max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF @@ -456,7 +455,7 @@ icon_state = "hardsuit1-syndielite" hardsuit_type = "syndielite" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/syndi/elite - armor = list(MELEE = 60, BULLET = 60, LASER = 50, ENERGY = 25, BOMB = 90, BIO = 100, RAD = 70, FIRE = 100, ACID = 100, WOUND = 25) + armor = list(MELEE = 60, BULLET = 60, LASER = 50, ENERGY = 25, BOMB = 90, BIO = 100, RAD = 70, FIRE = 100, ACID = 100, WOUND = 25, ELECTRIC = 100) heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF @@ -488,7 +487,7 @@ desc = "Spaceworthy and it looks like a space carp's head, smells like one too." icon_state = "carp_helm" item_state = "syndicate" - armor = list(MELEE = -20, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 100, RAD = 75, FIRE = 60, ACID = 75) //As whimpy as a space carp + armor = list(MELEE = -20, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 100, RAD = 75, FIRE = 60, ACID = 75, ELECTRIC = 100) //As whimpy as a space carp light_system = NO_LIGHT_SUPPORT light_range = 0 //luminosity when on actions_types = list() @@ -503,7 +502,7 @@ icon_state = "carp_suit" item_state = "space_suit_syndicate" slowdown = 0 //Space carp magic, never stop believing - armor = list(MELEE = -20, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 100, RAD = 75, FIRE = 60, ACID = 75) //As whimpy whimpy whoo + armor = list(MELEE = -20, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 100, RAD = 75, FIRE = 60, ACID = 75, ELECTRIC = 100) //As whimpy whimpy whoo allowed = list(/obj/item/tank/internals, /obj/item/pneumatic_cannon/speargun) //I'm giving you a hint here helmettype = /obj/item/clothing/head/helmet/space/hardsuit/carp @@ -524,7 +523,7 @@ desc = "A scaley heat resistant helm sporting a fearsome carp dragon look and smell." icon_state = "carpdragon_helm" item_state = "carpdragon_helm" - armor = list(MELEE = 50, BULLET = 30, LASER = 50, ENERGY = 30, BOMB = 50, BIO = 100, RAD = 90, FIRE = 100, ACID = 100) //not so whimpy now + armor = list(MELEE = 50, BULLET = 30, LASER = 50, ENERGY = 30, BOMB = 50, BIO = 100, RAD = 90, FIRE = 100, ACID = 100, ELECTRIC = 100) //not so whimpy now resistance_flags = FIRE_PROOF | ACID_PROOF max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT @@ -533,7 +532,7 @@ desc = "A tough, space and heat resistant suit patched together with space dragon scales." icon_state = "carpdragon" item_state = "carpdragon" - armor = list(MELEE = 50, BULLET = 30, LASER = 50, ENERGY = 30, BOMB = 50, BIO = 100, RAD = 90, FIRE = 100, ACID = 100) + armor = list(MELEE = 50, BULLET = 30, LASER = 50, ENERGY = 30, BOMB = 50, BIO = 100, RAD = 90, FIRE = 100, ACID = 100, ELECTRIC = 100) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/carp/dragon resistance_flags = FIRE_PROOF | ACID_PROOF max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT @@ -547,7 +546,7 @@ item_state = "wiz_helm" hardsuit_type = "wiz" resistance_flags = FIRE_PROOF | ACID_PROOF //No longer shall our kind be foiled by lone chemists with spray bottles! - armor = list(MELEE = 20, BULLET = 20, LASER = 20, ENERGY = 20, BOMB = 25, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, WOUND = 30) + armor = list(MELEE = 20, BULLET = 20, LASER = 20, ENERGY = 20, BOMB = 25, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, WOUND = 30, ELECTRIC = 100) heat_protection = HEAD //Uncomment to enable firesuit protection max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT @@ -558,7 +557,7 @@ item_state = "wiz_hardsuit" w_class = WEIGHT_CLASS_NORMAL resistance_flags = FIRE_PROOF | ACID_PROOF - armor = list(MELEE = 20, BULLET = 20, LASER = 20, ENERGY = 20, BOMB = 25, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, WOUND = 30) + armor = list(MELEE = 20, BULLET = 20, LASER = 20, ENERGY = 20, BOMB = 25, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, WOUND = 30, ELECTRIC = 100) allowed = list(/obj/item/teleportation_scroll, /obj/item/tank/internals) heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS //Uncomment to enable firesuit protection max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT @@ -578,7 +577,7 @@ icon_state = "hardsuit0-medical" item_state = "medical_helm" hardsuit_type = "medical" - armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 60, FIRE = 60, ACID = 75, WOUND = 10) + armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 60, FIRE = 60, ACID = 75, WOUND = 10, ELECTRIC = 100) clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SCAN_REAGENTS | HEADINTERNALS /obj/item/clothing/suit/space/hardsuit/medical @@ -587,7 +586,7 @@ desc = "A special suit that protects against hazardous, low pressure environments. Built with lightweight materials for easier movement." item_state = "medical_hardsuit" allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/storage/firstaid, /obj/item/healthanalyzer, /obj/item/stack/medical) - armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 60, FIRE = 60, ACID = 75, WOUND = 10) + armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 60, FIRE = 60, ACID = 75, WOUND = 10, ELECTRIC = 100) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/medical slowdown = 0.5 @@ -599,7 +598,7 @@ hardsuit_type = "rd" resistance_flags = ACID_PROOF | FIRE_PROOF max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT - armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 100, BIO = 100, RAD = 60, FIRE = 60, ACID = 80, WOUND = 15) + armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 100, BIO = 100, RAD = 60, FIRE = 60, ACID = 80, WOUND = 15, ELECTRIC = 100) var/explosion_detection_dist = 21 clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SCAN_REAGENTS | HEADINTERNALS actions_types = list(/datum/action/item_action/toggle_helmet_light, /datum/action/item_action/toggle_research_scanner) @@ -638,7 +637,7 @@ max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT //Same as an emergency firesuit. Not ideal for extended exposure. allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/gun/energy/wormhole_projector, /obj/item/hand_tele, /obj/item/aicard) - armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 100, BIO = 100, RAD = 60, FIRE = 60, ACID = 80, WOUND = 15) + armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 100, BIO = 100, RAD = 60, FIRE = 60, ACID = 80, WOUND = 15, ELECTRIC = 100) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/rd @@ -650,7 +649,7 @@ icon_state = "hardsuit0-sec" item_state = "sec_helm" hardsuit_type = "sec" - armor = list(MELEE = 35, BULLET = 25, LASER = 30,ENERGY = 10, BOMB = 40, BIO = 100, RAD = 50, FIRE = 75, ACID = 75, WOUND = 20) + armor = list(MELEE = 35, BULLET = 25, LASER = 30,ENERGY = 10, BOMB = 40, BIO = 100, RAD = 50, FIRE = 75, ACID = 75, WOUND = 20, ELECTRIC = 100) /obj/item/clothing/suit/space/hardsuit/security @@ -658,7 +657,7 @@ name = "security hardsuit" desc = "A special suit that protects against hazardous, low pressure environments. Has an additional layer of armor." item_state = "sec_hardsuit" - armor = list(MELEE = 35, BULLET = 25, LASER = 30, ENERGY = 10, BOMB = 40, BIO = 100, RAD = 50, FIRE = 75, ACID = 75, WOUND = 20) + armor = list(MELEE = 35, BULLET = 25, LASER = 30, ENERGY = 10, BOMB = 40, BIO = 100, RAD = 50, FIRE = 75, ACID = 75, WOUND = 20, ELECTRIC = 100) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/security /obj/item/clothing/suit/space/hardsuit/security/Initialize(mapload) @@ -671,14 +670,14 @@ desc = "A special bulky helmet designed for work in a hazardous, low pressure environment. Has an additional layer of armor." icon_state = "hardsuit0-hos" hardsuit_type = "hos" - armor = list(MELEE = 45, BULLET = 30, LASER = 30, ENERGY = 10, BOMB = 50, BIO = 100, RAD = 50, FIRE = 95, ACID = 95, WOUND = 25) + armor = list(MELEE = 45, BULLET = 30, LASER = 30, ENERGY = 10, BOMB = 50, BIO = 100, RAD = 50, FIRE = 95, ACID = 95, WOUND = 25, ELECTRIC = 100) /obj/item/clothing/suit/space/hardsuit/security/hos icon_state = "hardsuit-hos" name = "head of security's hardsuit" desc = "A special bulky suit that protects against hazardous, low pressure environments. Has an additional layer of armor." - armor = list(MELEE = 45, BULLET = 30, LASER = 30, ENERGY = 10, BOMB = 50, BIO = 100, RAD = 50, FIRE = 95, ACID = 95, WOUND = 25) + armor = list(MELEE = 45, BULLET = 30, LASER = 30, ENERGY = 10, BOMB = 50, BIO = 100, RAD = 50, FIRE = 95, ACID = 95, WOUND = 25, ELECTRIC = 100) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/security/hos jetpack = /obj/item/tank/jetpack/suit @@ -688,7 +687,7 @@ icon_state = "swat2helm" item_state = "swat2helm" desc = "A tactical SWAT helmet MK.II." - armor = list(MELEE = 40, BULLET = 50, LASER = 50, ENERGY = 25, BOMB = 50, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, WOUND = 15) + armor = list(MELEE = 40, BULLET = 50, LASER = 50, ENERGY = 25, BOMB = 50, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, WOUND = 15, ELECTRIC = 100) resistance_flags = FIRE_PROOF | ACID_PROOF flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR //we want to see the mask heat_protection = HEAD @@ -702,7 +701,7 @@ desc = "A MK.II SWAT suit with streamlined joints and armor made out of superior materials, insulated against intense heat. The most advanced tactical armor available." icon_state = "swat2" item_state = "swat2" - armor = list(MELEE = 40, BULLET = 50, LASER = 50, ENERGY = 25, BOMB = 50, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, WOUND = 15) + armor = list(MELEE = 40, BULLET = 50, LASER = 50, ENERGY = 25, BOMB = 50, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, WOUND = 15, ELECTRIC = 100) resistance_flags = FIRE_PROOF | ACID_PROOF heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT //this needed to be added a long fucking time ago @@ -734,14 +733,14 @@ icon_state = "hardsuit0-clown" item_state = "hardsuit0-clown" hardsuit_type = "clown" - armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 75, FIRE = 60, ACID = 30) + armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 75, FIRE = 60, ACID = 30, ELECTRIC = 100) /obj/item/clothing/suit/space/hardsuit/clown name = "cosmohonk hardsuit" desc = "A special suit that protects against hazardous, low humor environments. Has radiation shielding. Only a true clown can wear it." icon_state = "hardsuit-clown" item_state = "clown_hardsuit" - armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 75, FIRE = 60, ACID = 30) + armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 75, FIRE = 60, ACID = 30, ELECTRIC = 100) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/clown /obj/item/clothing/suit/space/hardsuit/clown/mob_can_equip(mob/M, slot) @@ -761,7 +760,7 @@ icon_state = "hardsuit0-ert_commander" item_state = "hardsuit0-ert_commander" hardsuit_type = "ert_commander" - armor = list(MELEE = 65, BULLET = 50, LASER = 50, ENERGY = 50, BOMB = 50, BIO = 100, RAD = 100, FIRE = 80, ACID = 80) + armor = list(MELEE = 65, BULLET = 50, LASER = 50, ENERGY = 50, BOMB = 50, BIO = 100, RAD = 100, FIRE = 80, ACID = 80, ELECTRIC = 100) strip_delay = 130 light_range = 7 resistance_flags = FIRE_PROOF @@ -778,7 +777,7 @@ item_state = "ert_command" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals) - armor = list(MELEE = 65, BULLET = 50, LASER = 50, ENERGY = 50, BOMB = 50, BIO = 100, RAD = 100, FIRE = 80, ACID = 80) + armor = list(MELEE = 65, BULLET = 50, LASER = 50, ENERGY = 50, BOMB = 50, BIO = 100, RAD = 100, FIRE = 80, ACID = 80, ELECTRIC = 100) slowdown = 0 strip_delay = 130 resistance_flags = FIRE_PROOF @@ -905,7 +904,7 @@ icon_state = "hardsuit0-ancient" item_state = "anc_helm" hardsuit_type = "ancient" - armor = list(MELEE = 30, BULLET = 5, LASER = 5, ENERGY = 0, BOMB = 50, BIO = 100, RAD = 100, FIRE = 100, ACID = 75) + armor = list(MELEE = 30, BULLET = 5, LASER = 5, ENERGY = 0, BOMB = 50, BIO = 100, RAD = 100, FIRE = 100, ACID = 75, ELECTRIC = 100) resistance_flags = FIRE_PROOF /obj/item/clothing/suit/space/hardsuit/ancient @@ -913,7 +912,7 @@ desc = "Prototype powered RIG hardsuit. Provides excellent protection from the elements of space while being comfortable to move around in, thanks to the powered locomotives. Remains very bulky however." icon_state = "hardsuit-ancient" item_state = "anc_hardsuit" - armor = list(MELEE = 30, BULLET = 5, LASER = 5, ENERGY = 0, BOMB = 50, BIO = 100, RAD = 100, FIRE = 100, ACID = 75) + armor = list(MELEE = 30, BULLET = 5, LASER = 5, ENERGY = 0, BOMB = 50, BIO = 100, RAD = 100, FIRE = 100, ACID = 75, ELECTRIC = 100) slowdown = 3 helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ancient resistance_flags = FIRE_PROOF @@ -960,7 +959,7 @@ icon_state = "hardsuit-hos" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/security/hos allowed = null - armor = list(MELEE = 30, BULLET = 15, LASER = 30, ENERGY = 10, BOMB = 10, BIO = 100, RAD = 50, FIRE = 100, ACID = 100) + armor = list(MELEE = 30, BULLET = 15, LASER = 30, ENERGY = 10, BOMB = 10, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, ELECTRIC = 100) resistance_flags = FIRE_PROOF | ACID_PROOF var/current_charges = 3 var/max_charges = 3 //How many charges total the shielding has @@ -1027,7 +1026,7 @@ hardsuit_type = "ctf-white" // Adding TRAIT_NODROP is done when the CTF spawner equips people helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf - armor = list(MELEE = 0, BULLET = 30, LASER = 30, ENERGY = 30, BOMB = 50, BIO = 100, RAD = 100, FIRE = 95, ACID = 95) + armor = list(MELEE = 0, BULLET = 30, LASER = 30, ENERGY = 30, BOMB = 50, BIO = 100, RAD = 100, FIRE = 95, ACID = 95, ELECTRIC = 100) slowdown = 0 max_charges = 5 @@ -1054,7 +1053,7 @@ icon_state = "hardsuit0-ctf_white" item_state = null hardsuit_type = "ert_medical" - armor = list(MELEE = 0, BULLET = 30, LASER = 30, ENERGY = 30, BOMB = 50, BIO = 100, RAD = 100, FIRE = 95, ACID = 95) + armor = list(MELEE = 0, BULLET = 30, LASER = 30, ENERGY = 30, BOMB = 50, BIO = 100, RAD = 100, FIRE = 95, ACID = 95, ELECTRIC = 100) /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/red @@ -1082,7 +1081,7 @@ icon_state = "hardsuit1-syndi" item_state = "syndie_hardsuit" hardsuit_type = "syndi" - armor = list(MELEE = 40, BULLET = 50, LASER = 30, ENERGY = 25, BOMB = 80, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, WOUND = 30) + armor = list(MELEE = 40, BULLET = 50, LASER = 30, ENERGY = 25, BOMB = 80, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, WOUND = 30, ELECTRIC = 100) allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi slowdown = 0 @@ -1094,7 +1093,7 @@ icon_state = "hardsuit1-syndi" item_state = "syndie_helm" hardsuit_type = "syndi" - armor = list(MELEE = 40, BULLET = 50, LASER = 30, ENERGY = 25, BOMB = 80, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, WOUND = 30) + armor = list(MELEE = 40, BULLET = 50, LASER = 30, ENERGY = 25, BOMB = 80, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, WOUND = 30, ELECTRIC = 100) ///Deathsquad version @@ -1103,7 +1102,7 @@ desc = "An advanced tactical space helmet." icon_state = "deathsquad" item_state = "deathsquad" - armor = list(MELEE = 80, BULLET = 80, LASER = 50, ENERGY = 50, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100, WOUND = 30) + armor = list(MELEE = 80, BULLET = 80, LASER = 50, ENERGY = 50, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100, WOUND = 30, ELECTRIC = 100) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF @@ -1118,7 +1117,7 @@ icon_state = "deathsquad" item_state = "swat_suit" allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/kitchen/knife/combat) - armor = list(MELEE = 80, BULLET = 80, LASER = 50, ENERGY = 50, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100, WOUND = 30) + armor = list(MELEE = 80, BULLET = 80, LASER = 50, ENERGY = 50, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100, WOUND = 30, ELECTRIC = 100) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF @@ -1135,7 +1134,7 @@ max_charges = 4 current_charges = 4 recharge_delay = 15 - armor = list(MELEE = 80, BULLET = 80, LASER = 50, ENERGY = 50, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100) + armor = list(MELEE = 80, BULLET = 80, LASER = 50, ENERGY = 50, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100, ELECTRIC = 100) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/swat @@ -1147,7 +1146,7 @@ icon_state = "deathsquad" item_state = "deathsquad" hardsuit_type = "syndi" - armor = list(MELEE = 80, BULLET = 80, LASER = 50, ENERGY = 50, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100) + armor = list(MELEE = 80, BULLET = 80, LASER = 50, ENERGY = 50, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100, ELECTRIC = 100) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT actions_types = list() @@ -1178,14 +1177,14 @@ hardsuit_type = "t45b" strip_delay = 100 equip_delay_other = 100 - armor = list(MELEE = 45, BULLET = 30, LASER = 25, ENERGY = 15, BOMB = 40, BIO = 100, RAD = 80, FIRE = 90, ACID = 100) + armor = list(MELEE = 45, BULLET = 30, LASER = 25, ENERGY = 15, BOMB = 40, BIO = 100, RAD = 80, FIRE = 90, ACID = 100, ELECTRIC = 100) /obj/item/clothing/suit/space/hardsuit/powerarmor_t45b name = "Salvaged T-45b power armor" desc = "It's some dusty power armor, probably hundreds of years old." icon_state = "hardsuit-t45b" item_state = "t45b_hardsuit" - armor = list(MELEE = 45, BULLET = 30, LASER = 25, ENERGY = 15, BOMB = 40, BIO = 100, RAD = 80, FIRE = 90, ACID = 100) + armor = list(MELEE = 45, BULLET = 30, LASER = 25, ENERGY = 15, BOMB = 40, BIO = 100, RAD = 80, FIRE = 90, ACID = 100, ELECTRIC = 100) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/powerarmor_t45b hardsuit_type = "t45b" strip_delay = 180 @@ -1202,7 +1201,7 @@ hardsuit_type = "advpa1" strip_delay = 100 equip_delay_other = 100 - armor = list(MELEE = 50, BULLET = 10, LASER = 25, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 10, WOUND = 0) + armor = list(MELEE = 50, BULLET = 10, LASER = 25, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 10, WOUND = 0, ELECTRIC = 100) max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | LAVA_PROOF | ACID_PROOF @@ -1214,7 +1213,7 @@ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/powerarmor_advanced hardsuit_type = "advancedpa1" allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/kinetic_crusher, /obj/item/pickaxe, /obj/item/pickaxe/drill/jackhammer, /obj/item/shield/riot/goliath, /obj/item/shield/riot/roman) - armor = list(MELEE = 50, BULLET = 10, LASER = 25, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 10, WOUND = 0) + armor = list(MELEE = 50, BULLET = 10, LASER = 25, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 10, WOUND = 0, ELECTRIC = 100) slowdown = 0 strip_delay = 180 equip_delay_other = 180 @@ -1235,7 +1234,7 @@ alt_desc = "A debug hardsuit helmet. It is in combat mode." icon_state = "hardsuit0-syndielite" hardsuit_type = "syndielite" - armor = list(MELEE = 100, BULLET = 100, LASER = 100, ENERGY = 100, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100) + armor = list(MELEE = 100, BULLET = 100, LASER = 100, ENERGY = 100, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100, ELECTRIC = 100) heat_protection = HEAD max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF @@ -1247,7 +1246,7 @@ icon_state = "hardsuit0-syndielite" hardsuit_type = "syndielite" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/syndi/debug - armor = list(MELEE = 100, BULLET = 100, LASER = 100, ENERGY = 100, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100) + armor = list(MELEE = 100, BULLET = 100, LASER = 100, ENERGY = 100, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100, ELECTRIC = 100) heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm index 59137204f6c4..2c7852cd5fa5 100644 --- a/code/modules/clothing/suits/jobs.dm +++ b/code/modules/clothing/suits/jobs.dm @@ -115,6 +115,7 @@ blood_overlay_type = "armor" allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/tank/internals/ipc_coolant, /obj/item/t_scanner, /obj/item/radio, /obj/item/extinguisher/mini) resistance_flags = NONE + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 0, ELECTRIC = 20) // slightly more OSHA-compliant! //Lawyer /obj/item/clothing/suit/toggle/lawyer diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index b08798a2fdbc..3345a9940fa7 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -689,20 +689,20 @@ name = "engineering winter coat" icon_state = "coatengineer" item_state = "coatengineer" - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 20, FIRE = 30, ACID = 45) + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 20, FIRE = 30, ACID = 45, ELECTRIC = 20) allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/tank/internals/ipc_coolant, /obj/item/t_scanner, /obj/item/construction/rcd, /obj/item/pipe_dispenser, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/extinguisher/mini) hoodtype = /obj/item/clothing/head/hooded/winterhood/engineering /obj/item/clothing/head/hooded/winterhood/engineering icon_state = "winterhood_engineer" - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 10, FIRE = 20, ACID = 10) + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 10, FIRE = 20, ACID = 10, ELECTRIC = 20) /obj/item/clothing/suit/hooded/wintercoat/engineering/ce name = "chief engineer's winter coat" desc = "A white winter coat with reflective green and yellow stripes made for the truly insane. Stuffed with asbestos, treated with fire retardant PBDE, lined with a micro thin sheet of lead foil and snugly fitted to your body's measurements. This baby's ready to save you from anything except the thyroid cancer and systemic fibrosis you'll get from wearing it. The zipper tab is a tiny golden wrench." icon_state = "coatce" item_state = "coatce" - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 30, FIRE = 40, ACID = 10) + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 30, FIRE = 40, ACID = 10, ELECTRIC = 40) hoodtype = /obj/item/clothing/head/hooded/winterhood/engineering/ce /obj/item/clothing/suit/hooded/wintercoat/engineering/ce/Initialize(mapload) @@ -714,7 +714,7 @@ /obj/item/clothing/head/hooded/winterhood/engineering/ce desc = "A white winter coat hood. Feels surprisingly heavy. The tag says that it's not child safe." icon_state = "winterhood_ce" - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 15, FIRE = 30, ACID = 10) + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 15, FIRE = 30, ACID = 10, ELECTRIC = 40) /obj/item/clothing/suit/hooded/wintercoat/engineering/atmos name = "atmospherics winter coat" diff --git a/code/modules/clothing/suits/reactive_armour.dm b/code/modules/clothing/suits/reactive_armour.dm index d10391cd5670..8995c24607e5 100644 --- a/code/modules/clothing/suits/reactive_armour.dm +++ b/code/modules/clothing/suits/reactive_armour.dm @@ -117,7 +117,7 @@ if(ismob(loc)) to_chat(loc, emp_message) bad_effect = TRUE - addtimer(VARSET_CALLBACK(src, bad_effect, FALSE), 30 SECONDS) + addtimer(VARSET_CALLBACK(src, bad_effect, FALSE), (3 SECONDS) * severity) //When the wearer gets hit, this armor will teleport the user a short distance away (to safety or to more danger, no one knows. That's the fun of it!) /obj/item/clothing/suit/armor/reactive/teleport @@ -222,23 +222,29 @@ /obj/item/clothing/suit/armor/reactive/tesla name = "reactive tesla armor" desc = "An experimental suit of armor with sensitive detectors hooked up to a huge capacitor grid, with emitters strutting out of it. Zap." - siemens_coefficient = -1 reactivearmor_cooldown_duration = 3 SECONDS var/tesla_power = 25000 var/tesla_range = 20 var/tesla_flags = TESLA_MOB_DAMAGE | TESLA_OBJ_DAMAGE cooldown_message = span_danger("The tesla capacitors on the reactive tesla armor are still recharging! The armor merely emits some sparks.") emp_message = span_warning("The tesla capacitors beep ominously for a moment.") + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100, ELECTRIC = 100) /obj/item/clothing/suit/armor/reactive/tesla/dropped(mob/user) ..() if(istype(user)) user.flags_1 &= ~TESLA_IGNORE_1 + UnregisterSignal(user, COMSIG_LIVING_ELECTROCUTE_ACT) /obj/item/clothing/suit/armor/reactive/tesla/equipped(mob/user, slot) ..() if(slot_flags & slot) //Was equipped to a valid slot for this item? user.flags_1 |= TESLA_IGNORE_1 + RegisterSignal(user, COMSIG_LIVING_ELECTROCUTE_ACT, PROC_REF(handle_shock)) + +/obj/item/clothing/suit/armor/reactive/tesla/proc/handle_shock(mob/living/victim, shock_damage, obj/source, siemens_coeff = 1, zone = null, tesla_shock = 0, illusion = 0) + if(tesla_shock) + return COMPONENT_NO_ELECTROCUTE_ACT /obj/item/clothing/suit/armor/reactive/tesla/cooldown_activation(mob/living/carbon/human/owner) var/datum/effect_system/spark_spread/sparks = new /datum/effect_system/spark_spread @@ -326,11 +332,10 @@ //Hallucinating /obj/item/clothing/suit/armor/reactive/hallucinating - name = "reactive hallucinating armor" - desc = "An experimental suit of armor with sensitive detectors hooked up to the mind of the wearer, sending mind pulses that causes hallucinations around you." - cooldown_message = span_warning("The connection is currently out of sync... Recalibrating.") - emp_message = span_warning("You feel the backsurge of a mind pulse.") - var/effect_range = 3 + name = "reactive hallucination armor" + desc = "An experimental suit of armor which produces an illusory defender upon registering an attack." + cooldown_message = span_warning("The reactive hallucination armor's memetic array is currently recalibrating!") + emp_message = span_warning("The reactive hallucination armor's array of lights and mirrors turns on you...") clothing_traits = list(TRAIT_MESONS) /obj/item/clothing/suit/armor/reactive/hallucinating/cooldown_activation(mob/living/carbon/human/owner) @@ -340,14 +345,15 @@ ..() /obj/item/clothing/suit/armor/reactive/hallucinating/reactive_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - owner.visible_message(span_danger("[src] blocks [attack_text], sending out mental pulses!")) - var/turf/location = get_turf(owner) - if(location) - hallucination_pulse(location, effect_range, strength = 25) + owner.visible_message(span_danger("[src] blocks [attack_text], the body of an assistant forming to absorb it!")) //get down mr president + var/mob/living/simple_animal/hostile/shadowclone = new /mob/living/simple_animal/hostile/hallucination(get_turf(src)) + shadowclone.friends += owner return TRUE /obj/item/clothing/suit/armor/reactive/hallucinating/emp_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - owner.visible_message(span_danger("[src] blocks [attack_text], but pulls a massive charge of mental energy into [owner] from the surrounding environment!")) + owner.visible_message(span_danger("[src] blocks [attack_text], the body of an assistant forming to absorb it, before turning on [owner]!")) + var/mob/living/simple_animal/hostile/shadowclone = new /mob/living/simple_animal/hostile/hallucination(get_turf(src)) + shadowclone.GiveTarget(owner) owner.adjust_hallucinations(150) return TRUE diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm index 0f405e23d5aa..d89818e2aea9 100644 --- a/code/modules/clothing/under/jobs/engineering.dm +++ b/code/modules/clothing/under/jobs/engineering.dm @@ -4,7 +4,7 @@ name = "chief engineer's jumpsuit" icon_state = "chiefengineer" item_state = "gy_suit" - armor = list(MELEE = 0, BULLET = 0, LASER = 0,ENERGY = 0, BOMB = 0, BIO = 0, RAD = 10, FIRE = 80, ACID = 40) + armor = list(MELEE = 0, BULLET = 0, LASER = 0,ENERGY = 0, BOMB = 0, BIO = 0, RAD = 10, FIRE = 80, ACID = 40, ELECTRIC = 10) resistance_flags = NONE sensor_mode = SENSOR_COORDS random_sensor = FALSE @@ -26,7 +26,7 @@ name = "atmospheric technician's jumpsuit" icon_state = "atmos" item_state = "atmos_suit" - armor = list(MELEE = 0, BULLET = 0, LASER = 0,ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 80, ACID = 0) + armor = list(MELEE = 0, BULLET = 0, LASER = 0,ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 80, ACID = 0, ELECTRIC = 0) resistance_flags = NONE mutantrace_variation = MUTANTRACE_VARIATION diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm index 15b3fbb981a2..803c07e84431 100644 --- a/code/modules/events/alien_infestation.dm +++ b/code/modules/events/alien_infestation.dm @@ -53,7 +53,7 @@ continue//no parent vent //Stops Aliens getting stuck in small networks. //See: Security, Virology - if(temp_vent_parent.other_atmosmch.len > 20) + if(temp_vent_parent.other_atmos_machines.len > 20) vents += temp_vent if(!vents.len) diff --git a/code/modules/events/ion_storm.dm b/code/modules/events/ion_storm.dm index 079d23dc3891..225fca834f08 100644 --- a/code/modules/events/ion_storm.dm +++ b/code/modules/events/ion_storm.dm @@ -1,5 +1,6 @@ #define ION_RANDOM 0 #define ION_ANNOUNCE 1 + /datum/round_event_control/ion_storm name = "Ion Storm" typepath = /datum/round_event/ion_storm @@ -7,14 +8,31 @@ min_players = 2 /datum/round_event/ion_storm - var/addIonLawChance = 100 // chance a new ion law will be added in addition to other ion effects - var/replaceLawsetChance = 25 //chance the AI's lawset is completely replaced with something else per config weights - var/removeRandomLawChance = 10 //chance the AI has one random supplied or inherent law removed - var/removeDontImproveChance = 10 //chance the randomly created law replaces a random law instead of simply being added - var/shuffleLawsChance = 10 //chance the AI's laws are shuffled afterwards + /// Chance a new ion law will be added in addition to other ion effects. + var/addIonLawChance = 100 + /// Chance the AI's lawset is completely replaced with something else per config weights. + var/replaceLawsetChance = 25 + /// Chance the AI has one random supplied or inherent law removed. + var/removeRandomLawChance = 10 + /// Chance the ion law will replace a random law instead of simply being added. + var/removeDontImproveChance = 10 + /// Chance the AI's laws are shuffled afterwards. + var/shuffleLawsChance = 10 + /// Chance that bots on the station will become emagged. var/botEmagChance = 10 - var/announceEvent = ION_RANDOM // -1 means don't announce, 0 means have it randomly announce, 1 means + /// Chance that an airlock on the station will be messed with, if there are no AIs. + var/airlockChance = 5 + /// Maximum number of airlocks that can be messed with. + var/airlockAmount = 20 + /// Chance that an APC on the station will be messed with, if there are no AIs. + var/apcChance = 5 + /// Maximum number of APCs that can be messed with. + var/apcAmount = 10 + /// Should it announce? -1 = No | 0 = Random | 1 = Always. + var/announceEvent = ION_RANDOM + /// Custom ion law, if not null. var/ionMessage = null + /// If announceEvent is 0, what is the chance it is will accounce? var/ionAnnounceChance = 33 announceWhen = 1 @@ -24,17 +42,22 @@ removeDontImproveChance = 0 shuffleLawsChance = 0 botEmagChance = 0 + airlockChance = 0 + airlockAmount = 0 + apcChance = 0 + apcAmount = 0 /datum/round_event/ion_storm/announce(fake) if(announceEvent == ION_ANNOUNCE || (announceEvent == ION_RANDOM && prob(ionAnnounceChance)) || fake) priority_announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", ANNOUNCER_IONSTORM) - /datum/round_event/ion_storm/start() //AI laws + var/anyAliveAI = FALSE for(var/mob/living/silicon/ai/M in GLOB.alive_mob_list) M.laws_sanity_check() if(M.stat != DEAD && M.see_in_dark != 0) + anyAliveAI = TRUE if(prob(replaceLawsetChance)) M.laws.pick_ion_lawset() to_chat(M, span_alert("Your lawset has been changed by the ion storm!")) @@ -56,12 +79,78 @@ log_game("Ion storm changed laws of [key_name(M)] to [english_list(M.laws.get_law_list(TRUE, TRUE))]") message_admins("[ADMIN_LOOKUPFLW(M)] has had their laws changed by an ion storm to [english_list(M.laws.get_law_list(TRUE, TRUE))]") M.post_lawchange() - if(botEmagChance) for(var/mob/living/simple_animal/bot/bot in GLOB.alive_mob_list) if(prob(botEmagChance)) bot.emag_act() + if(!anyAliveAI) + if(airlockChance) + var/list/airlocks = get_acceptable_airlocks() + var/amountSince = 0 + for(var/obj/machinery/door/airlock/airlock in airlocks) + if(!prob(airlockChance)) + continue + if(!airlock.hasPower() || !airlock.canAIControl() || (airlock.obj_flags & EMAGGED) ) + continue + var/turf/turf = get_turf(airlock) + var/luck = rand(1, 4) + switch(luck) + if(1) + if(airlock.locked) + airlock.unbolt() + log_game("Ion storm unbolted airlock ([airlock.name]) at [COORD(turf)].") + else + airlock.bolt() + log_game("Ion storm bolted airlock ([airlock.name]) at [COORD(turf)].") + if(3) + airlock.emergency = !airlock.emergency + airlock.update_appearance(UPDATE_ICON) + log_game("Ion storm [airlock.emergency ? "enabled" : "disabled"] emergency access on airlock ([airlock.name]) at [COORD(turf)].") + if(4) + airlock.set_electrified(MACHINE_DEFAULT_ELECTRIFY_TIME) + log_game("Ion storm electrified for [MACHINE_DEFAULT_ELECTRIFY_TIME] seconds airlock ([airlock.name]) at [COORD(turf)].") + if(5) + airlock.safe = !airlock.safe + airlock.normalspeed = airlock.safe // Intentional. They should match for maximum crushing (or maximum safety). + log_game("Ion storm [airlock.safe ? "enabled" : "disabled"] safety & speed on airlock ([airlock.name]) at [COORD(turf)].") + amountSince += 1 + if(amountSince >= airlockAmount) + break + if(apcChance) + var/list/apcs = get_acceptable_apcs() + var/amountSince = 0 + for(var/obj/machinery/power/apc/apc in apcs) + if(!prob(apcChance)) + continue + if(apc.aidisabled) + continue + var/turf/turf = get_turf(apc) + var/luck = rand(1, 4) + switch(luck) + if(1) + if(apc.lighting) + apc.lighting = 0 + log_game("Ion storm disabled lighting on APC ([apc.name]) at [COORD(turf)].") + if(2) + if(apc.equipment) + apc.equipment = 0 + log_game("Ion storm disabled equipment on APC ([apc.name]) at [COORD(turf)].") + if(3) + if(apc.environ) + apc.environ = 0 + log_game("Ion storm disabled environment on APC ([apc.name]) at [COORD(turf)].") + if(4) + if(apc.lighting || apc.equipment || apc.environ) + apc.environ = 0 + apc.equipment = 0 + apc.lighting = 0 + log_game("Ion storm disabled lightning, equipment, and environment on APC ([apc.name]) at [COORD(turf)].") + apc.update() + amountSince += 1 + if(amountSince >= apcAmount) + break + /datum/round_event/ion_storm/malicious var/location_name @@ -73,6 +162,70 @@ message += (location_name ? "Signal traced to [location_name].
" : "Signal untracable.
") print_command_report(message, null, FALSE) +/// Returns acceptable apcs that are safe to mess with that shouldn't cause excessive/extreme damage. +/datum/round_event/ion_storm/proc/get_acceptable_apcs() + var/list/data_core_areas = list() + for(var/obj/machinery/ai/data_core/core as anything in GLOB.data_cores) + if(!core.valid_data_core()) + continue + if(!isarea(core.loc)) + continue + var/area/A = core.loc + data_core_areas[A.type] = TRUE + var/list/acceptable_apcs = list() + for(var/obj/machinery/power/apc/apc in GLOB.apcs_list) + if(!apc.cell || !SSmapping.level_trait(apc.z, ZTRAIT_STATION)) // Must have power and be on station. + continue + var/area/area = apc.area + if(GLOB.typecache_powerfailure_safe_areas[area.type]) // No touching safe areas. + continue + if(data_core_areas[area.type]) // No touching areas with data cores in them. + continue + var/critical = FALSE + for(var/obj/machinery/M in area.contents) // No touching areas that have critical machines. + if(M.critical_machine) + critical = TRUE + break + for(var/mob/living/silicon/ai/AI in GLOB.ai_list) // No touching areas with AIs in them. + if(get_area(AI) == area) + critical = TRUE + break + if(critical) + continue + acceptable_apcs += apc + return acceptable_apcs + +/// Returns acceptable airlocks that are safe to mess with that shouldn't cause excessive/extreme damage. +/datum/round_event/ion_storm/proc/get_acceptable_airlocks() + var/list/data_core_areas = list() + for(var/obj/machinery/ai/data_core/core as anything in GLOB.data_cores) + if(!core.valid_data_core()) + continue + if(!isarea(core.loc)) + continue + var/area/A = core.loc + data_core_areas[A.type] = TRUE + var/list/acceptable_airlocks = list() + for(var/obj/machinery/door/airlock/airlock in GLOB.airlocks) + if(SSmapping.level_trait(airlock.z, ZTRAIT_STATION)) + var/area/area = get_area(airlock) + if(data_core_areas[area.type]) // No touching areas with data cores in them. + continue + var/critical = FALSE + for(var/obj/machinery/M in area.contents) // No touching areas that have critical machines. + if(M.critical_machine) + critical = TRUE + break + for(var/A in GLOB.ai_list) // No touching areas with AIs in them. + var/mob/living/silicon/ai/I = A + if(get_area(I) == area) + critical = TRUE + break + if(critical) + continue + acceptable_airlocks += airlock + return acceptable_airlocks + /*/proc/generate_ion_law() //yogs - start mirrored in the yogs folder //Threats are generally bad things, silly or otherwise. Plural. var/ionthreats = pick_list(ION_FILE, "ionthreats") diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm index 077c1c192479..ae2b3031707c 100644 --- a/code/modules/events/pirates.dm +++ b/code/modules/events/pirates.dm @@ -33,7 +33,7 @@ beacon = new(ship_name) /datum/round_event/pirates/announce(fake) - priority_announce("Incoming subspace communication. Secure channel opened at all communication consoles.", "Incoming Message", RANDOM_REPORT_SOUND) + priority_announce("Incoming subspace communication. Secure channel opened at all communication consoles.", "Incoming Message", SSstation.announcer.get_rand_report_sound()) play_intro_music() if(fake) return diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm index 81dbd9c0b9d9..c6dcda3ad61a 100644 --- a/code/modules/events/spacevine.dm +++ b/code/modules/events/spacevine.dm @@ -176,7 +176,7 @@ var/turf/open/floor/T = holder.loc if(istype(T)) var/datum/gas_mixture/GM = T.air - GM.set_moles(/datum/gas/oxygen, max(GM.get_moles(/datum/gas/oxygen) - severity * holder.energy, 0)) + GM.set_moles(GAS_O2, max(GM.get_moles(GAS_O2) - severity * holder.energy, 0)) /datum/spacevine_mutation/nitro_eater name = "nitrogen consuming" @@ -188,7 +188,7 @@ var/turf/open/floor/T = holder.loc if(istype(T)) var/datum/gas_mixture/GM = T.air - GM.set_moles(/datum/gas/nitrogen, max(GM.get_moles(/datum/gas/nitrogen) - severity * holder.energy, 0)) + GM.set_moles(GAS_N2, max(GM.get_moles(GAS_N2) - severity * holder.energy, 0)) /datum/spacevine_mutation/carbondioxide_eater name = "CO2 consuming" @@ -200,7 +200,7 @@ var/turf/open/floor/T = holder.loc if(istype(T)) var/datum/gas_mixture/GM = T.air - GM.set_moles(/datum/gas/carbon_dioxide, max(GM.get_moles(/datum/gas/carbon_dioxide) - severity * holder.energy, 0)) + GM.set_moles(GAS_CO2, max(GM.get_moles(GAS_CO2) - severity * holder.energy, 0)) /datum/spacevine_mutation/plasma_eater name = "toxins consuming" @@ -212,7 +212,7 @@ var/turf/open/floor/T = holder.loc if(istype(T)) var/datum/gas_mixture/GM = T.air - GM.set_moles(/datum/gas/plasma, max(GM.get_moles(/datum/gas/plasma) - severity * holder.energy, 0)) + GM.set_moles(GAS_PLASMA, max(GM.get_moles(GAS_PLASMA) - severity * holder.energy, 0)) /datum/spacevine_mutation/thorns name = "thorny" diff --git a/code/modules/events/spider_infestation.dm b/code/modules/events/spider_infestation.dm index 5a60c6337406..dfb572c42a10 100644 --- a/code/modules/events/spider_infestation.dm +++ b/code/modules/events/spider_infestation.dm @@ -27,7 +27,7 @@ continue if(is_station_level(temp_vent.loc.z) && !temp_vent.welded) var/datum/pipeline/temp_vent_parent = temp_vent.parents[1] - if(temp_vent_parent.other_atmosmch.len > 20) + if(temp_vent_parent.other_atmos_machines.len > 20) vents += temp_vent while((spawncount >= 1) && vents.len) diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm index bbc06023fda4..ad98033033bd 100644 --- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm +++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm @@ -13,6 +13,7 @@ volume = 100 force = 15 //Smashing bottles over someone's head hurts. throwforce = 15 + demolition_mod = 0.25 item_state = "broken_beer" //Generic held-item sprite until unique ones are made. lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi' righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi' @@ -166,6 +167,7 @@ throwforce = 5 throw_speed = 3 throw_range = 5 + demolition_mod = 0.25 w_class = WEIGHT_CLASS_TINY item_state = "beer" hitsound = 'sound/weapons/bladeslice.ogg' diff --git a/code/modules/food_and_drinks/food/snacks_pastry.dm b/code/modules/food_and_drinks/food/snacks_pastry.dm index 979f01dd5790..4881b9e8e4f8 100644 --- a/code/modules/food_and_drinks/food/snacks_pastry.dm +++ b/code/modules/food_and_drinks/food/snacks_pastry.dm @@ -786,31 +786,39 @@ . += "It contains [contents.len?"[ingredients_listed]":"no ingredient, "]on top of a [initial(name)]." bitecount = originalBites -/obj/item/reagent_containers/food/snacks/pancakes/attackby(obj/item/I, mob/living/user, params) - if(istype(I, /obj/item/reagent_containers/food/snacks/pancakes)) - var/obj/item/reagent_containers/food/snacks/pancakes/P = I - if((contents.len >= PANCAKE_MAX_STACK) || ((P.contents.len + contents.len) > PANCAKE_MAX_STACK) || (reagents.total_volume >= volume)) +/obj/item/reagent_containers/food/snacks/pancakes/attackby(obj/item/item, mob/living/user, params) + if(istype(item, /obj/item/reagent_containers/food/snacks/pancakes)) + var/obj/item/reagent_containers/food/snacks/pancakes/pancake = item + if((contents.len >= PANCAKE_MAX_STACK) || ((pancake.contents.len + contents.len) > PANCAKE_MAX_STACK) || (reagents.total_volume >= volume)) to_chat(user, span_warning("You can't add that many pancakes to [src]!")) else - if(!user.transferItemToLoc(I, src)) + if(!user.transferItemToLoc(item, src)) return - to_chat(user, span_notice("You add the [I] to the [name].")) - P.name = initial(P.name) - contents += P - update_overlays(P) - if (P.contents.len) - for(var/V in P.contents) - P = V - P.name = initial(P.name) - contents += P - update_overlays(P) - P = I - LAZYCLEARLIST(P.contents) + to_chat(user, span_notice("You add the [item] to the [name].")) + pancake.name = initial(pancake.name) + contents += pancake + update_snack_overlays(pancake) + if (pancake.contents.len) + for(var/V in pancake.contents) + pancake = V + pancake.name = initial(pancake.name) + contents += pancake + update_snack_overlays(pancake) + pancake = item + LAZYCLEARLIST(pancake.contents) return else if(contents.len) var/obj/O = contents[contents.len] - return O.attackby(I, user, params) - ..() + return O.attackby(item, user, params) + return ..() + +/obj/item/reagent_containers/food/snacks/pancakes/update_snack_overlays(obj/item/reagent_containers/food/snacks/pancakes/pancake) + var/mutable_appearance/pancake_visual = mutable_appearance(icon, "[pancake.item_state]_[rand(1, 3)]") + pancake_visual.pixel_x = rand(-1, 1) + pancake_visual.pixel_y = 3 * contents.len - 1 + pancake_visual.layer = layer + (contents.len * 0.01) + add_overlay(pancake_visual) + update_appearance() /obj/item/reagent_containers/food/snacks/pancakes/attack(mob/M, mob/user, def_zone, stacked = TRUE) if(user.a_intent == INTENT_HARM || !contents.len || !stacked) diff --git a/code/modules/goals/station_goals/dna_vault.dm b/code/modules/goals/station_goals/dna_vault.dm index 903124d5e87a..15c0fb761cd2 100644 --- a/code/modules/goals/station_goals/dna_vault.dm +++ b/code/modules/goals/station_goals/dna_vault.dm @@ -261,8 +261,7 @@ to_chat(H, span_notice("You feel resistant to toxins.")) if(locate(/obj/item/organ/lungs) in H.internal_organs) var/obj/item/organ/lungs/L = H.internal_organs_slot[ORGAN_SLOT_LUNGS] - L.tox_breath_dam_min = 0 - L.tox_breath_dam_max = 0 + L.gas_max -= GAS_PLASMA ADD_TRAIT(H, TRAIT_VIRUSIMMUNE, "dna_vault") P.tox_mod *= 0.2 H.dna.species.acidmod *= 0.2 //Remind me to move this to physiolgy later - Mqiib diff --git a/code/modules/goals/station_goals/station_goal.dm b/code/modules/goals/station_goals/station_goal.dm index 34454f533e03..9c9c972eebb3 100644 --- a/code/modules/goals/station_goals/station_goal.dm +++ b/code/modules/goals/station_goals/station_goal.dm @@ -12,7 +12,7 @@ var/report_message = "Complete this goal." /datum/station_goal/proc/send_report() - priority_announce("Priority Nanotrasen directive received. Project \"[name]\" details inbound.", "Incoming Priority Message", RANDOM_REPORT_SOUND) + priority_announce("Priority Nanotrasen directive received. Project \"[name]\" details inbound.", "Incoming Priority Message", SSstation.announcer.get_rand_report_sound()) print_command_report(get_report(),"Nanotrasen Directive [pick(GLOB.phonetic_alphabet)] \Roman[rand(1,50)]", announce=FALSE) on_report() diff --git a/code/modules/holiday/pride.dm b/code/modules/holiday/pride.dm index 212a45aaf1fa..6cee794b5f56 100644 --- a/code/modules/holiday/pride.dm +++ b/code/modules/holiday/pride.dm @@ -10,7 +10,7 @@ /datum/holiday/pride/proc/become_gay_destroyer_of_worlds() for(var/i in 1 to FACTOR_GAS_VISIBLE_MAX) //I DON'T LIKE EM PUTTING CHEMICALS IN THE GAS THAT TURN THE FRIGGIN PLASMA GAY! - var/obj/effect/overlay/gas/G = GLOB.meta_gas_info[/datum/gas/plasma][META_GAS_OVERLAY][i] + var/obj/effect/overlay/gas/G = GLOB.gas_data.overlays[GAS_PLASMA][i] G.icon_state = "pridesma" animate(G, color = rgb(255, 0, 0), time = 5, loop = -1) animate(color = rgb(0, 255, 0), time = 5, loop = -1) diff --git a/code/modules/holodeck/area_copy.dm b/code/modules/holodeck/area_copy.dm index c063330a60a1..cc92d7637050 100644 --- a/code/modules/holodeck/area_copy.dm +++ b/code/modules/holodeck/area_copy.dm @@ -67,7 +67,7 @@ copiedobjs += SM.get_all_contents() for(var/V in T.vars - GLOB.duplicate_forbidden_vars) - if(V == "air") + if(V == "air" && SSair.initialized) var/turf/open/O1 = B var/turf/open/O2 = T O1.air.copy_from(O2.return_air()) @@ -77,8 +77,6 @@ if(toupdate.len) for(var/turf/T1 in toupdate) - CALCULATE_ADJACENT_TURFS(T1) - SSair.add_to_active(T1,1) - + T1.ImmediateCalculateAdjacentTurfs() return copiedobjs diff --git a/code/modules/holodeck/holo_effect.dm b/code/modules/holodeck/holo_effect.dm index a85d20bbeed6..3baa3e10ceea 100644 --- a/code/modules/holodeck/holo_effect.dm +++ b/code/modules/holodeck/holo_effect.dm @@ -61,7 +61,7 @@ var/datum/effect_system/spark_spread/s = new s.set_up(3, 1, T) s.start() - T.temperature = 5000 + T.set_temperature(5000) T.hotspot_expose(50000,50000,1) diff --git a/code/modules/hydroponics/grown/berries.dm b/code/modules/hydroponics/grown/berries.dm index 17352feaf011..86dfa455cf02 100644 --- a/code/modules/hydroponics/grown/berries.dm +++ b/code/modules/hydroponics/grown/berries.dm @@ -240,3 +240,34 @@ filling_color = "#7FFF00" tastes = list("green grape" = 1) distill_reagent = /datum/reagent/consumable/ethanol/cognac + +// Lanterfruit + +/obj/item/seeds/lanternfruit + name = "pack of lanternfruit seeds" + desc = "These seeds grow into lanternfruit pods." + icon_state = "seed-lanternfruit" + species = "lanternfruit" + plantname = "Lanternfruit Pod" + product = /obj/item/reagent_containers/food/snacks/grown/lanternfruit + lifespan = 35 + endurance = 35 + maturation = 5 + production = 5 + growthstages = 3 + growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi' + icon_grow = "lanternfruit-grow" + icon_dead = "lanternfruit-dead" + icon_harvest = "lanternfruit-harvest" + genes = list(/datum/plant_gene/trait/glow/yellow) + mutatelist = null + reagents_add = list(/datum/reagent/sulphur = 0.07, /datum/reagent/consumable/sugar = 0.07, /datum/reagent/consumable/liquidelectricity = 0.07) + +/obj/item/reagent_containers/food/snacks/grown/lanternfruit + seed = /obj/item/seeds/lanternfruit + name = "lanternfruits" + desc = "A sofly glowing fruit with a handle-shaped stem, an Ethereal favorite!" + icon_state = "lanternfruit" + filling_color = "#eeff00" + tastes = list("tv static" = 1, "sour pear" = 1, "grapefruit" = 1) + distill_reagent = /datum/reagent/consumable/ethanol/wine_voltaic diff --git a/code/modules/hydroponics/grown/misc.dm b/code/modules/hydroponics/grown/misc.dm index 9c72886a82d4..4efa0c1a92aa 100644 --- a/code/modules/hydroponics/grown/misc.dm +++ b/code/modules/hydroponics/grown/misc.dm @@ -57,10 +57,9 @@ return var/datum/gas_mixture/stank = new - stank.set_moles(/datum/gas/miasma, (yield + 6) * 3.5 * MIASMA_CORPSE_MOLES * delta_time) // this process is only being called about 2/7 as much as corpses so this is 12-32 times a corpses + stank.set_moles(GAS_MIASMA, (yield + 6) * 3.5 * MIASMA_CORPSE_MOLES * delta_time) // this process is only being called about 2/7 as much as corpses so this is 12-32 times a corpses stank.set_temperature(T20C) // without this the room would eventually freeze and miasma mining would be easier T.assume_air(stank) - T.air_update_turf() //Galaxy Thistle /obj/item/seeds/galaxythistle diff --git a/code/modules/hydroponics/grown/towercap.dm b/code/modules/hydroponics/grown/towercap.dm index 2de2723478c7..9bf186af6b50 100644 --- a/code/modules/hydroponics/grown/towercap.dm +++ b/code/modules/hydroponics/grown/towercap.dm @@ -231,7 +231,7 @@ if(isopenturf(loc)) var/turf/open/O = loc if(O.air) - if(O.air.get_moles(/datum/gas/oxygen) > 13) + if(O.air.get_moles(GAS_O2) > 13) return TRUE return FALSE diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm index 3d9a7e170a89..f56c3429d245 100644 --- a/code/modules/hydroponics/plant_genes.dm +++ b/code/modules/hydroponics/plant_genes.dm @@ -198,7 +198,7 @@ ..() if(istype(G) && ispath(G.trash, /obj/item/grown)) return - var/obj/item/seeds/seed = G.seed + var/obj/item/seeds/seed = G.get_plant_seed() var/stun_len = seed.potency * rate if(!istype(G, /obj/item/grown/bananapeel) && (!G.reagents || !G.reagents.has_reagent(/datum/reagent/lube))) @@ -221,14 +221,14 @@ /datum/plant_gene/trait/cell_charge/on_slip(obj/item/reagent_containers/food/snacks/grown/G, mob/living/carbon/C) var/power = G.seed.potency*rate if(prob(power)) - C.electrocute_act(round(power), G, 1, 1) + C.electrocute_act(round(power), G, 1, zone = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) // you stepped on it, so check protection on the legs /datum/plant_gene/trait/cell_charge/on_squash(obj/item/reagent_containers/food/snacks/grown/G, atom/target) if(iscarbon(target)) var/mob/living/carbon/C = target var/power = G.seed.potency*rate if(prob(power)) - C.electrocute_act(round(power), G, 1, 1) + C.electrocute_act(round(power), G, 1, zone = null) /datum/plant_gene/trait/cell_charge/on_consume(obj/item/reagent_containers/food/snacks/grown/G, mob/living/carbon/target) if(!G.reagents.total_volume) @@ -256,16 +256,20 @@ trait_id = "glow" var/glow_color = "#C3E381" -/datum/plant_gene/trait/glow/proc/glow_range(obj/item/seeds/S) - return 1.4 + S.potency*rate +/datum/plant_gene/trait/glow/proc/glow_range(obj/item/seeds/seed) + return 1.4 + seed.potency * rate -/datum/plant_gene/trait/glow/proc/glow_power(obj/item/seeds/S) - return max(S.potency*(rate + 0.01), 0.1) +/datum/plant_gene/trait/glow/proc/glow_power(obj/item/seeds/seed) + return max(seed.potency * (rate + 0.01), 0.1) -/datum/plant_gene/trait/glow/on_new(obj/item/reagent_containers/food/snacks/grown/G, newloc) +/datum/plant_gene/trait/glow/on_new(obj/item/our_plant, newloc) . = ..() - G.light_system = MOVABLE_LIGHT - G.AddComponent(/datum/component/overlay_lighting, glow_range(G.seed), glow_power(G.seed), glow_color) + if(!.) + return + + var/obj/item/seeds/our_seed = our_plant.get_plant_seed() + our_plant.light_system = MOVABLE_LIGHT + our_plant.AddComponent(/datum/component/overlay_lighting, glow_range(our_seed), glow_power(our_seed), glow_color) /datum/plant_gene/trait/glow/shadow //makes plant emit slightly purple shadows diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index 1ffb5349e54a..f4f415cf0be9 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -437,3 +437,21 @@ genes += P else qdel(P) + +/* + * Both `/item/food/grown` and `/item/grown` implement a seed variable which tracks + * plant statistics, genes, traits, etc. This proc gets the seed for either grown food or + * grown inedibles and returns it, or returns null if it's not a plant. + * + * Returns an `/obj/item/seeds` ref for grown foods or grown inedibles. + * - returned seed CAN be null in weird cases but in all applications it SHOULD NOT be. + * Returns null if it is not a plant. + */ +/obj/item/proc/get_plant_seed() + return null + +/obj/item/grown/get_plant_seed() + return seed + +/obj/item/reagent_containers/food/snacks/grown/get_plant_seed() + return seed diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm index f35d90193696..6365594bd8dc 100644 --- a/code/modules/jobs/job_types/captain.dm +++ b/code/modules/jobs/job_types/captain.dm @@ -9,7 +9,7 @@ faction = "Station" total_positions = 1 spawn_positions = 1 - supervisors = "NanoTrasen officers and Space law" //Changed to officer to separate from CentCom officials being their superior. + supervisors = "Nanotrasen officers and Space law" //Changed to officer to separate from CentCom officials being their superior. selection_color = "#ccccff" req_admin_notify = 1 space_law_notify = 1 //Yogs diff --git a/code/modules/jobs/job_types/roboticist.dm b/code/modules/jobs/job_types/roboticist.dm index ff6932f7e38d..cfe4981644bb 100644 --- a/code/modules/jobs/job_types/roboticist.dm +++ b/code/modules/jobs/job_types/roboticist.dm @@ -10,7 +10,7 @@ selection_color = "#ffeeff" exp_requirements = 60 exp_type = EXP_TYPE_CREW - alt_titles = list("Augmentation Theorist", "Cyborg Maintainer", "Robotics Intern", "Biomechanical Engineer", "Mechatronic Engineer", "Machinist") + alt_titles = list("Augmentation Theorist", "Cyborg Maintainer", "Robotics Intern", "Biomechanical Engineer", "Mechatronic Engineer", "Machinist", "Chrome Shaman", "Ripperdoc") outfit = /datum/outfit/job/roboticist diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm index d7d1ef75f581..ccb68f5c0e1c 100644 --- a/code/modules/jobs/job_types/warden.dm +++ b/code/modules/jobs/job_types/warden.dm @@ -20,7 +20,7 @@ alt_titles = list("Brig Watchman", "Brig Superintendent", "Security Dispatcher", "Prison Supervisor") - added_access = list(ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_FORENSICS_LOCKERS) + added_access = list(ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_FORENSICS_LOCKERS, ACCESS_BRIG_PHYS, ACCESS_MEDICAL) //they get medical access because apparently the windoors AREN'T BRIG PHYS ACCESS base_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_MECH_SECURITY, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM) // See /datum/job/warden/get_access() paycheck = PAYCHECK_HARD paycheck_department = ACCOUNT_SEC diff --git a/code/modules/jobs/jobs.dm b/code/modules/jobs/jobs.dm index 047d41026ae7..7e450eae0346 100644 --- a/code/modules/jobs/jobs.dm +++ b/code/modules/jobs/jobs.dm @@ -154,12 +154,12 @@ GLOBAL_LIST_INIT(alt_medical_positions, list( "EMT", "Paramedic Trainee", "Rapid Response Medic", "Space Search & Rescue", "Counsellor", "Therapist", "Mentalist", "Mining Medical Support", "Lavaland Medical Care Unit", "Junior Mining Medic", "Planetside Health Officer", "Land Search & Rescue", - "Security Medic", "Security Medical Support", "Penitentiary Medical Care Unit", "Junior Brig Physician", "Detention Center Health Officer",)) + "Security Medic", "Security Medical Support", "Penitentiary Medical Care Unit", "Junior Brig Physician", "Detention Center Health Officer")) GLOBAL_LIST_INIT(alt_science_positions, list( "Chief Science Officer", "Head of Research", "Chief Technology Officer", "Researcher", "Toxins Specialist", "Physicist", "Test Associate", "Anomalist", "Quantum Physicist", "Theoretical Physicist", "Xenobiologist", "Explosives Technician", "Hypothetical Physicist", - "Augmentation Theorist", "Cyborg Maintainer", "Robotics Intern", "Biomechanical Engineer", "Mechatronic Engineer", "Machinist")) + "Augmentation Theorist", "Cyborg Maintainer", "Robotics Intern", "Biomechanical Engineer", "Mechatronic Engineer", "Machinist", "Chrome Shaman", "Ripperdoc")) GLOBAL_LIST_INIT(alt_supply_positions, list( "Chief of Staff", "Head of Internal Affairs", diff --git a/code/modules/keybindings/focus.dm b/code/modules/keybindings/focus.dm index 205b293e9a1a..d542b4926700 100644 --- a/code/modules/keybindings/focus.dm +++ b/code/modules/keybindings/focus.dm @@ -1,6 +1,3 @@ -/mob - var/datum/focus //What receives our keyboard inputs. src by default - /mob/proc/set_focus(datum/new_focus) if(focus == new_focus) return diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index 0fa649ac58f1..70542eee66fb 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -17,7 +17,7 @@ desc = "A great place for storing knowledge." anchored = FALSE density = TRUE - opacity = 0 + opacity = FALSE resistance_flags = FLAMMABLE max_integrity = 200 armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 50, ACID = 0) diff --git a/code/modules/lighting/lighting_area.dm b/code/modules/lighting/lighting_area.dm index ce3b6b70f4c9..58ee031d3281 100644 --- a/code/modules/lighting/lighting_area.dm +++ b/code/modules/lighting/lighting_area.dm @@ -1,5 +1,5 @@ /area - luminosity = TRUE + luminosity = TRUE var/dynamic_lighting = DYNAMIC_LIGHTING_ENABLED /area/proc/set_dynamic_lighting(new_dynamic_lighting = DYNAMIC_LIGHTING_ENABLED) diff --git a/code/modules/lighting/lighting_atom.dm b/code/modules/lighting/lighting_atom.dm index 55b14cb513d7..6ffa5121b925 100644 --- a/code/modules/lighting/lighting_atom.dm +++ b/code/modules/lighting/lighting_atom.dm @@ -1,54 +1,48 @@ - -/atom - ///Light systems, both shouldn't be active at the same time. - var/light_system = STATIC_LIGHT - ///Range of the light in tiles. Zero means no light. - var/light_range = 0 - ///Intensity of the light. The stronger, the less shadows you will see on the lit area. - var/light_power = 1 - ///Hexadecimal RGB string representing the colour of the light. White by default. - var/light_color = COLOR_WHITE - ///Boolean variable for toggleable lights. Has no effect without the proper light_system, light_range and light_power values. - var/light_on = TRUE - ///Bitflags to determine lighting-related atom properties. - var/light_flags = NONE - ///Our light source. Don't fuck with this directly unless you have a good reason! - var/tmp/datum/light_source/light - ///Any light sources that are "inside" of us, for example, if src here was a mob that's carrying a flashlight, that flashlight's light source would be part of this list. - var/tmp/list/light_sources - // The proc you should always use to set the light of this atom. -// Nonesensical value for l_color default, so we can detect if it gets set to null. -#define NONSENSICAL_VALUE -99999 -/atom/proc/set_light(l_range, l_power, l_color = NONSENSICAL_VALUE) +/atom/proc/set_light(l_range, l_power, l_color = NONSENSICAL_VALUE, l_angle, l_dir, l_on) + // We null everything but l_dir, because we don't want to allow for modifications while frozen + if(light_flags & LIGHT_FROZEN) + l_range = null + l_power = null + l_color = null + l_on = null + l_angle = null + if(l_range > 0 && l_range < MINIMUM_USEFUL_LIGHT_RANGE) - l_range = MINIMUM_USEFUL_LIGHT_RANGE //Brings the range up to 1.4, which is just barely brighter than the soft lighting that surrounds players. - if (l_power != null) - light_power = l_power + l_range = MINIMUM_USEFUL_LIGHT_RANGE //Brings the range up to 1.4, which is just barely brighter than the soft lighting that surrounds players. + + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT, l_range, l_power, l_color, l_on) & COMPONENT_BLOCK_LIGHT_UPDATE) + return - if (l_range != null) - light_range = l_range + if(!isnull(l_power)) + set_light_power(l_power) - if (l_color != NONSENSICAL_VALUE) - light_color = l_color + if(!isnull(l_range)) + set_light_range(l_range) - SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT, l_range, l_power, l_color) + if(l_color != NONSENSICAL_VALUE) + set_light_color(l_color) - update_light() + if(!isnull(l_angle)) + set_light_angle(l_angle) + + if(!isnull(l_dir)) + set_light_dir(l_dir) + + if(!isnull(l_on)) + set_light_on(l_on) -#undef NONSENSICAL_VALUE + update_light() -// Will update the light (duh). -// Creates or destroys it if needed, makes it update values, makes sure it's got the correct source turf... +/// Will update the light (duh). +/// Creates or destroys it if needed, makes it update values, makes sure it's got the correct source turf... /atom/proc/update_light() - set waitfor = FALSE - if (QDELETED(src)) - return + SHOULD_NOT_SLEEP(TRUE) if(light_system != STATIC_LIGHT) CRASH("update_light() for [src] with following light_system value: [light_system]") - if (!light_power || !light_range) // We won't emit light anyways, destroy the light source. + if (!light_power || !light_range || !light_on) // We won't emit light anyways, destroy the light source. QDEL_NULL(light) else if (!ismovable(loc)) // We choose what atom should be the top atom of the light here. @@ -60,71 +54,37 @@ light.update(.) else light = new/datum/light_source(src, .) - -// If we have opacity, make sure to tell (potentially) affected light sources. -/atom/movable/Destroy() - var/turf/T = loc - . = ..() - if (opacity && istype(T)) - var/old_has_opaque_atom = T.has_opaque_atom - T.recalc_atom_opacity() - if (old_has_opaque_atom != T.has_opaque_atom) - T.reconsider_lights() - -// Should always be used to change the opacity of an atom. -// It notifies (potentially) affected light sources so they can update (if needed). + return . + +/** + * Updates the atom's opacity value. + * + * This exists to act as a hook for associated behavior. + * It notifies (potentially) affected light sources so they can update (if needed). + */ /atom/proc/set_opacity(new_opacity) - if (new_opacity == opacity) + if (new_opacity == opacity || light_flags & LIGHT_FROZEN) return - + SEND_SIGNAL(src, COMSIG_ATOM_SET_OPACITY, new_opacity) + . = opacity opacity = new_opacity - var/turf/T = loc - if (!isturf(T)) + return . + +/atom/movable/set_opacity(new_opacity) + . = ..() + if(isnull(.) || !isturf(loc)) return - if (new_opacity == TRUE) - T.has_opaque_atom = TRUE - T.reconsider_lights() + if(opacity) + AddElement(/datum/element/light_blocking) else - var/old_has_opaque_atom = T.has_opaque_atom - T.recalc_atom_opacity() - if (old_has_opaque_atom != T.has_opaque_atom) - T.reconsider_lights() - + RemoveElement(/datum/element/light_blocking) -/atom/movable/Moved(atom/OldLoc, Dir) +/turf/set_opacity(new_opacity) . = ..() - for (var/datum/light_source/light as anything in light_sources) // Cycle through the light sources on this atom and tell them to update. - light.source_atom.update_light() - -/atom/vv_edit_var(var_name, var_value) - switch (var_name) - if ("light_range") - if(light_system == STATIC_LIGHT) - set_light(l_range = var_value) - else - set_light_range(var_value) - datum_flags |= DF_VAR_EDITED - return TRUE - - if ("light_power") - if(light_system == STATIC_LIGHT) - set_light(l_power = var_value) - else - set_light_power(var_value) - datum_flags |= DF_VAR_EDITED - return TRUE - - if ("light_color") - if(light_system == STATIC_LIGHT) - set_light(l_color = var_value) - else - set_light_color(var_value) - datum_flags |= DF_VAR_EDITED - return TRUE - - return ..() - + if(isnull(.)) + return + recalculate_directional_opacity() /atom/proc/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION) return @@ -132,59 +92,96 @@ /turf/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION) if(!_duration) stack_trace("Lighting FX obj created on a turf without a duration") - new /obj/effect/dummy/lighting_obj (src, _range, _power, _color, _duration) + new /obj/effect/dummy/lighting_obj(src, _range, _power, _color, _duration) /obj/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION) if(!_duration) stack_trace("Lighting FX obj created on a obj without a duration") - new /obj/effect/dummy/lighting_obj (get_turf(src), _range, _power, _color, _duration) - + new /obj/effect/dummy/lighting_obj(get_turf(src), _range, _power, _color, _duration) /mob/living/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION) mob_light(_range, _power, _color, _duration) - -/mob/living/proc/mob_light(_range, _power, _color, _duration) - var/obj/effect/dummy/lighting_obj/moblight/mob_light_obj = new (src, _range, _power, _color, _duration) +/mob/living/proc/mob_light(range, power, color, duration, light_type = /obj/effect/dummy/lighting_obj/moblight) + var/obj/effect/dummy/lighting_obj/moblight/mob_light_obj = new light_type(src, range, power, color, duration) return mob_light_obj - +/// Setter for the light range of this atom. /atom/proc/set_light_range(new_range) - if(new_range == light_range) + if(new_range == light_range || light_flags & LIGHT_FROZEN) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_RANGE, new_range) & COMPONENT_BLOCK_LIGHT_UPDATE) return - SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_RANGE, new_range) . = light_range light_range = new_range + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_RANGE, .) + return . +/// Setter for the light power of this atom. /atom/proc/set_light_power(new_power) - if(new_power == light_power) + if(new_power == light_power || light_flags & LIGHT_FROZEN) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_POWER, new_power) & COMPONENT_BLOCK_LIGHT_UPDATE) return - SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_POWER, new_power) . = light_power light_power = new_power + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_POWER, .) + return . - +/// Setter for the light color of this atom. /atom/proc/set_light_color(new_color) - if(new_color == light_color) + if(new_color == light_color || light_flags & LIGHT_FROZEN) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_COLOR, new_color) & COMPONENT_BLOCK_LIGHT_UPDATE) return - SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_COLOR, new_color) . = light_color light_color = new_color + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_COLOR, .) + return . +/// Setter for the light angle of this atom +/atom/proc/set_light_angle(new_value) + if(new_value == light_angle || light_flags & LIGHT_FROZEN) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_ANGLE, new_value) & COMPONENT_BLOCK_LIGHT_UPDATE) + return + . = light_angle + light_angle = new_value + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_ANGLE, .) + return . + +/// Setter for the light direction of this atom +/atom/proc/set_light_dir(new_value) + // No frozen check here because we allow direction changes in a freeze + if(new_value == light_dir) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_DIR, new_value) & COMPONENT_BLOCK_LIGHT_UPDATE) + return + . = light_dir + light_dir = new_value + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_DIR, .) + return . +/// Setter for whether or not this atom's light is on. /atom/proc/set_light_on(new_value) - if(new_value == light_on) + if(new_value == light_on || light_flags & LIGHT_FROZEN) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_ON, new_value) & COMPONENT_BLOCK_LIGHT_UPDATE) return - SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_ON, new_value) . = light_on light_on = new_value + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_ON, .) + return . - +/// Setter for the light flags of this atom. /atom/proc/set_light_flags(new_value) - if(new_value == light_flags) + if(new_value == light_flags || (light_flags & LIGHT_FROZEN && new_value & LIGHT_FROZEN)) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_FLAGS, new_value) & COMPONENT_BLOCK_LIGHT_UPDATE) return - SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_FLAGS, new_value) . = light_flags light_flags = new_value + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_FLAGS, .) + return . diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm index 3eec3be05a23..93839a8a6e79 100644 --- a/code/modules/lighting/lighting_source.dm +++ b/code/modules/lighting/lighting_source.dm @@ -219,7 +219,7 @@ var/oldlum = source_turf.luminosity source_turf.luminosity = CEILING(light_range, 1) for(var/turf/T in view(CEILING(light_range, 1), source_turf)) - if(!T.has_opaque_atom) + if(!IS_OPAQUE_TURF(T)) if (!T.lighting_corners_initialised) T.generate_missing_corners() corners[T.lighting_corner_NE] = 0 diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index 406ed0ae09d0..871099973730 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -1,22 +1,3 @@ -/turf - var/dynamic_lighting = TRUE - luminosity = 1 - - var/tmp/lighting_corners_initialised = FALSE - - var/tmp/datum/lighting_object/lighting_object // Our lighting object. - - ///Lighting Corner datums. - var/tmp/datum/lighting_corner/lighting_corner_NE - var/tmp/datum/lighting_corner/lighting_corner_SE - var/tmp/datum/lighting_corner/lighting_corner_SW - var/tmp/datum/lighting_corner/lighting_corner_NW - - var/tmp/has_opaque_atom = FALSE // Not to be confused with opacity, this will be TRUE if there's any opaque atom on the tile. - - ///Lumcount added by sources other than lighting datum objects, such as the overlay lighting component. - var/dynamic_lumcount = 0 - // Causes any affecting light sources to be queued for a visibility update, for example a door got opened. /turf/proc/reconsider_lights() lighting_corner_NE?.vis_update() @@ -78,21 +59,39 @@ return !luminosity -// Can't think of a good name, this proc will recalculate the has_opaque_atom variable. -/turf/proc/recalc_atom_opacity() - has_opaque_atom = opacity - if (!has_opaque_atom) - for (var/atom/A in src.contents) // Loop through every movable atom on our tile PLUS ourselves (we matter too...) - if (A.opacity) - has_opaque_atom = TRUE - break +///Proc to add movable sources of opacity on the turf and let it handle lighting code. +/turf/proc/add_opacity_source(atom/movable/new_source) + LAZYADD(opacity_sources, new_source) + if(opacity) + return + recalculate_directional_opacity() -/turf/Exited(atom/movable/Obj, atom/newloc) - . = ..() - if (Obj && Obj.opacity) - recalc_atom_opacity() // Make sure to do this before reconsider_lights(), incase we're on instant updates. - reconsider_lights() +///Proc to remove movable sources of opacity on the turf and let it handle lighting code. +/turf/proc/remove_opacity_source(atom/movable/old_source) + LAZYREMOVE(opacity_sources, old_source) + if(opacity) //Still opaque, no need to worry on updating. + return + recalculate_directional_opacity() + +///Calculate on which directions this turfs block view. +/turf/proc/recalculate_directional_opacity() + . = directional_opacity + if(opacity) + directional_opacity = ALL_CARDINALS + if(. != directional_opacity) + reconsider_lights() + return + directional_opacity = NONE + if(opacity_sources) + for(var/atom/movable/opacity_source as anything in opacity_sources) + if(opacity_source.flags_1 & ON_BORDER_1) + directional_opacity |= opacity_source.dir + else //If fulltile and opaque, then the whole tile blocks view, no need to continue checking. + directional_opacity = ALL_CARDINALS + break + if(. != directional_opacity && (. == ALL_CARDINALS || directional_opacity == ALL_CARDINALS)) + reconsider_lights() //The lighting system only cares whether the tile is fully concealed from all directions or not. /turf/proc/change_area(area/old_area, area/new_area) if(SSlighting.initialized) diff --git a/code/modules/mapping/map_template.dm b/code/modules/mapping/map_template.dm index 3d0a0d2d11cf..7a5695b82748 100644 --- a/code/modules/mapping/map_template.dm +++ b/code/modules/mapping/map_template.dm @@ -102,7 +102,7 @@ ) ) for(var/turf/affected_turf as anything in template_and_bordering_turfs) - affected_turf.air_update_turf(TRUE, TRUE) + affected_turf.ImmediateCalculateAdjacentTurfs() affected_turf.levelupdate() /datum/map_template/proc/load_new_z(secret = FALSE) diff --git a/code/modules/mapping/ruins.dm b/code/modules/mapping/ruins.dm index 6162364d0470..f6ed99bf937d 100644 --- a/code/modules/mapping/ruins.dm +++ b/code/modules/mapping/ruins.dm @@ -68,9 +68,18 @@ var/list/ruins_availible = list() //we can try these in the current pass var/list/ruins_placed = list() // yogs + if(PERFORM_ALL_TESTS(log_mapping)) + log_mapping("All ruins being loaded for map testing") + //Set up the starting ruin list for(var/key in ruins) var/datum/map_template/ruin/R = ruins[key] + + if(PERFORM_ALL_TESTS(log_mapping)) + R.cost = 0 + R.allow_duplicates = FALSE // no multiples for testing + R.always_place = !R.unpickable // unpickable ruin means it spawns as a set with another ruin + if(R.cost > budget) //Why would you do that continue if(R.always_place) diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm index 87a4ae9e8f57..19c4ab3b310d 100644 --- a/code/modules/mining/abandoned_crates.dm +++ b/code/modules/mining/abandoned_crates.dm @@ -11,6 +11,15 @@ var/attempts = 10 var/codelen = 4 +/obj/structure/closet/crate/secure/loot/Initialize(mapload) + . = ..() + var/list/digits = list("1", "2", "3", "4", "5", "6", "7", "8", "9", "0") + code = "" + for(var/i = 0, i < codelen, i++) + var/dig = pick(digits) + code += dig + digits -= dig //there are never matching digits in the answer + /obj/structure/closet/crate/secure/loot/update_overlays() . = ..() tamperproof = initial(tamperproof) @@ -20,13 +29,6 @@ /obj/structure/closet/crate/secure/loot/PopulateContents() . = ..() - var/list/digits = list("1", "2", "3", "4", "5", "6", "7", "8", "9", "0") - code = "" - for(var/i = 0, i < codelen, i++) - var/dig = pick(digits) - code += dig - digits -= dig //there are never matching digits in the answer - var/loot = rand(1,100) //100 different crates with varying chances of spawning switch(loot) if(1 to 5) //5% chance @@ -82,14 +84,14 @@ new /obj/item/clothing/neck/petcollar(src) if(63 to 64) for(var/i in 1 to rand(4, 7)) - var/newcoin = pickweight( + var/newcoin = pickweight(list( /obj/item/coin/silver = 3, /obj/item/coin/iron = 3, /obj/item/coin/gold = 1, /obj/item/coin/diamond = 1, /obj/item/coin/plasma = 1, /obj/item/coin/uranium = 1, - ) + )) new newcoin(src) if(65 to 66) new /obj/item/clothing/suit/ianshirt(src) diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index c7bc5806bd52..1c2de639447a 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -36,7 +36,7 @@ /obj/item/kinetic_crusher/Initialize(mapload) . = ..() AddComponent(/datum/component/butchering, 60, 110) //technically it's huge and bulky, but this provides an incentive to use it - AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=20) + AddComponent(/datum/component/two_handed, force_wielded=20) /obj/item/kinetic_crusher/Destroy() QDEL_LIST(trophies) diff --git a/code/modules/mining/equipment/mining_tools.dm b/code/modules/mining/equipment/mining_tools.dm index ca31e16e0e6d..d85dbb56f8e6 100644 --- a/code/modules/mining/equipment/mining_tools.dm +++ b/code/modules/mining/equipment/mining_tools.dm @@ -7,6 +7,7 @@ slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK force = 15 throwforce = 10 + demolition_mod = 1.2 item_state = "pickaxe" lefthand_file = 'icons/mob/inhands/equipment/mining_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/mining_righthand.dmi' diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm index 60b0461a89f0..9669eacfe860 100644 --- a/code/modules/mining/equipment/survival_pod.dm +++ b/code/modules/mining/equipment/survival_pod.dm @@ -152,6 +152,7 @@ /obj/machinery/stasis/survival_pod icon = 'icons/obj/lavaland/survival_pod.dmi' icon_state = "sleeper" + base_icon_state = "sleeper" mattress_state = null buckle_lying = 270 @@ -275,7 +276,7 @@ /obj/structure/fans/Initialize(mapload) . = ..() - air_update_turf(1) + air_update_turf() //Inivisible, indestructible fans /obj/structure/fans/tiny/invisible diff --git a/code/modules/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm index b263c1696d50..27fd03403b30 100644 --- a/code/modules/mining/equipment/wormhole_jaunter.dm +++ b/code/modules/mining/equipment/wormhole_jaunter.dm @@ -52,7 +52,7 @@ playsound(src,'sound/effects/sparks4.ogg',50,1) qdel(src) -/obj/item/wormhole_jaunter/emp_act(power) +/obj/item/wormhole_jaunter/emp_act(severity) . = ..() if(. & EMP_PROTECT_SELF) return @@ -60,11 +60,8 @@ var/mob/M = loc if(istype(M)) var/triggered = FALSE - if(M.get_item_by_slot(ITEM_SLOT_BELT) == src) - if(power == 1) - triggered = TRUE - else if(power == 2 && prob(50)) - triggered = TRUE + if(M.get_item_by_slot(ITEM_SLOT_BELT) == src && prob(10 * severity)) + triggered = TRUE if(triggered) M.visible_message(span_warning("[src] overloads and activates!")) diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm index cd67b979af49..3dc7fcb2ce27 100644 --- a/code/modules/mining/machine_vending.dm +++ b/code/modules/mining/machine_vending.dm @@ -284,7 +284,7 @@ /obj/machinery/mineral/equipment_vendor/free_miner name = "free miner ship equipment vendor" - desc = "A vendor sold by NanoTrasen to profit off small mining contractors." + desc = "A vendor sold by Nanotrasen to profit off small mining contractors." prize_list = list( new /datum/data/mining_equipment("Kinetic Accelerator", /obj/item/gun/energy/kinetic_accelerator, 750, VENDING_WEAPON), new /datum/data/mining_equipment("Resonator", /obj/item/resonator, 800, VENDING_WEAPON), diff --git a/code/modules/mining/shelters.dm b/code/modules/mining/shelters.dm index 30bc664dde85..9dcb54da06f4 100644 --- a/code/modules/mining/shelters.dm +++ b/code/modules/mining/shelters.dm @@ -8,7 +8,7 @@ /datum/map_template/shelter/New() . = ..() - blacklisted_turfs = typecacheof(/turf/closed) + blacklisted_turfs = typecacheof(/turf/closed, /turf/open/lava/smooth/lava_land_surface/no_shelter) whitelisted_turfs = list() banned_areas = typecacheof(/area/shuttle) banned_objects = list() diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 79ca3f7ade87..b30a1abc79f2 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -37,6 +37,10 @@ return "r" return "l" +/mob/proc/held_index_to_body_zone(i) + if(!(i % 2)) + return BODY_ZONE_R_ARM + return BODY_ZONE_L_ARM //Check we have an organ for this hand slot (Dismemberment), Only relevant for humans /mob/proc/has_hand_for_held_index(i) diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index 1d0658084614..7ceb3f3f93b4 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -287,15 +287,10 @@ var/obj/item/clothing/head/hat = owner.get_item_by_slot(ITEM_SLOT_HEAD) if(hat && istype(hat, /obj/item/clothing/head/foilhat)) return - - owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, (50/severity) * (maxHealth - damage) / maxHealth) - owner.adjust_drugginess(40/severity) - switch(severity) - if(1) - to_chat(owner, span_warning("Alert: Posibrain heavily damaged.")) - if(2) - to_chat(owner, span_warning("Alert: Posibrain damaged.")) - + to_chat(owner, span_warning("Alert: Posibrain [severity > EMP_LIGHT ? "severely " : ""]damaged.")) + owner.adjust_drugginess(5 * severity) + if(severity > EMP_LIGHT) + owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, (2 * (severity - EMP_LIGHT)) * (maxHealth - damage) / maxHealth) // don't give traumas from weak EMPs ////////////////////////////////////TRAUMAS//////////////////////////////////////// diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index 11a2dcc37e73..6c921a663a5e 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -284,7 +284,7 @@ Doesn't work on other aliens/AI.*/ span_alertalien("You spit neurotoxin."), ) - var/obj/projectile/bullet/neurotoxin/neurotoxin = new /obj/projectile/bullet/neurotoxin(caller.loc) + var/obj/projectile/reagent/neurotoxin/neurotoxin = new /obj/projectile/reagent/neurotoxin(caller.loc) neurotoxin.preparePixelProjectile(target, caller, params) neurotoxin.firer = caller neurotoxin.fire() diff --git a/code/modules/mob/living/carbon/alien/life.dm b/code/modules/mob/living/carbon/alien/life.dm index 91d423d199f4..b468e9223cdc 100644 --- a/code/modules/mob/living/carbon/alien/life.dm +++ b/code/modules/mob/living/carbon/alien/life.dm @@ -15,20 +15,20 @@ var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.return_temperature())/BREATH_VOLUME //Partial pressure of the toxins in our breath - var/Toxins_pp = (breath.get_moles(/datum/gas/plasma)/breath.total_moles())*breath_pressure + var/Toxins_pp = (breath.get_moles(GAS_PLASMA)/breath.total_moles())*breath_pressure if(Toxins_pp > tox_detect_threshold) // Detect toxins in air - adjustPlasma(breath.get_moles(/datum/gas/plasma)*250) + adjustPlasma(breath.get_moles(GAS_PLASMA)*250) throw_alert("alien_tox", /atom/movable/screen/alert/alien_tox) - toxins_used = breath.get_moles(/datum/gas/plasma) + toxins_used = breath.get_moles(GAS_PLASMA) else clear_alert("alien_tox") //Breathe in toxins and out oxygen - breath.adjust_moles(/datum/gas/plasma, -toxins_used) - breath.adjust_moles(/datum/gas/oxygen, toxins_used) + breath.adjust_moles(GAS_PLASMA, -toxins_used) + breath.adjust_moles(GAS_O2, toxins_used) //BREATH TEMPERATURE handle_breath_temperature(breath) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 243853dafa04..d04f8899ad5e 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -541,10 +541,6 @@ /mob/living/carbon/update_stamina() var/stam = getStaminaLoss() - if(ishuman(src)) - var/mob/living/carbon/human/H = src //leaving this here but sus - if(stam && H.hulk_stamina_check()) - return if(stam > DAMAGE_PRECISION && (maxHealth - stam) <= crit_threshold) if(!stat) enter_stamcrit() @@ -970,11 +966,11 @@ O.set_owner(src) bodyparts.Remove(X) bodyparts.Add(O) - if(O.body_part == ARM_LEFT) + if(O.body_part & ARM_LEFT) l_arm_index_next += 2 O.held_index = l_arm_index_next //1, 3, 5, 7... hand_bodyparts += O - else if(O.body_part == ARM_RIGHT) + else if(O.body_part & ARM_RIGHT) r_arm_index_next += 2 O.held_index = r_arm_index_next //2, 4, 6, 8... hand_bodyparts += O @@ -1153,7 +1149,7 @@ /// Returns if the carbon is wearing shock proof gloves /mob/living/carbon/proc/wearing_shock_proof_gloves() - return gloves?.siemens_coefficient == 0 + return gloves?.armor.getRating(ELECTRIC) >= 100 /mob/living/carbon/wash(clean_types) . = ..() diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index b69a40db20dc..25436281deae 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -372,27 +372,39 @@ . = ..() if(. & EMP_PROTECT_SELF) return - if(HAS_TRAIT(src, TRAIT_FARADAYCAGE)) - severity++ - if(severity > EMP_LIGHT) - return - for(var/X in internal_organs) - var/obj/item/organ/O = X - O.emp_act(severity) -/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0, stun = TRUE, gib = FALSE) + if(dna?.species) + severity *= dna.species.emp_mod + if(severity < 1) + return + + var/emp_message = TRUE + for(var/obj/item/bodypart/BP as anything in get_damageable_bodyparts(BODYPART_ROBOTIC)) + if(!(BP.emp_act(severity, emp_message) & EMP_PROTECT_SELF)) + emp_message = FALSE // if the EMP was successful, don't spam the chat with more messages + +/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, zone = BODY_ZONE_R_ARM, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE, gib = FALSE) if(tesla_shock && (flags_1 & TESLA_IGNORE_1)) return FALSE if(HAS_TRAIT(src, TRAIT_SHOCKIMMUNE)) return FALSE + if(!override) // override variable bypasses protection + siemens_coeff *= (100 - getarmor(zone, ELECTRIC)) / 100 + var/stuntime = 8*siemens_coeff SECONDS // do this before species adjustments or balancing will be a pain + if(reagents.has_reagent(/datum/reagent/teslium)) + siemens_coeff *= 1.5 //If the mob has teslium in their body, shocks are 50% more damaging! + + if(SEND_SIGNAL(src, COMSIG_LIVING_ELECTROCUTE_ACT, shock_damage, source, siemens_coeff, zone, tesla_shock) & COMPONENT_NO_ELECTROCUTE_ACT) + return FALSE + shock_damage *= siemens_coeff if(dna && dna.species) shock_damage *= dna.species.siemens_coeff + dna.species.spec_electrocute_act(src, shock_damage,source,siemens_coeff,zone,override,tesla_shock, illusion, stun) if(shock_damage<1 && !override) return FALSE - if(reagents.has_reagent(/datum/reagent/teslium)) - shock_damage *= 1.5 //If the mob has teslium in their body, shocks are 50% more damaging! + if(illusion) adjustStaminaLoss(shock_damage) else @@ -405,11 +417,13 @@ do_jitter_animation(stuntime * 3) adjust_stutter(stuntime / 2) adjust_jitter(stuntime * 2) + var/should_stun = !tesla_shock || (tesla_shock && siemens_coeff > 0.5) if(stun && should_stun) Paralyze(min(stuntime, 4 SECONDS)) if(stuntime > 2 SECONDS) addtimer(CALLBACK(src, PROC_REF(secondary_shock), should_stun, stuntime - (2 SECONDS)), 2 SECONDS) + if(stat == DEAD && can_defib()) //yogs: ZZAPP if(!illusion && (shock_damage * siemens_coeff >= 1) && prob(80)) set_heartattack(FALSE) @@ -419,6 +433,7 @@ INVOKE_ASYNC(src, PROC_REF(emote), "gasp") adjust_jitter(10 SECONDS) adjustOrganLoss(ORGAN_SLOT_BRAIN, 100, 199) + if(gib && siemens_coeff > 0) visible_message( span_danger("[src] body is emitting a loud noise!"), \ @@ -426,6 +441,14 @@ span_italics("You hear a loud noise!"), \ ) addtimer(CALLBACK(src, PROC_REF(supermatter_tesla_gib)), 4 SECONDS) //yogs end + + if(undergoing_cardiac_arrest() && !illusion) + if(shock_damage * siemens_coeff >= 1 && prob(25)) + var/obj/item/organ/heart/heart = getorganslot(ORGAN_SLOT_HEART) + heart.beating = TRUE + if(stat == CONSCIOUS) + to_chat(src, span_notice("You feel your heart beating again!")) + if(override) return override else @@ -483,12 +506,6 @@ adjust_status_effects_on_shake_up() // adjustStaminaLoss(-10) if you want hugs to recover stamina damage, uncomment this - if(dna && dna.check_mutation(ACTIVE_HULK)) - if(prob(30)) - adjustStaminaLoss(10) - to_chat(src, span_notice("[M] calms you down a little.")) - else - to_chat(src, span_warning("[M] tries to calm you!")) set_resting(FALSE) playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 9b4f0bba51c5..f352cacb4132 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -154,6 +154,28 @@ key_third_person = "shrugs" message = "shrugs." +// Tail thump! Lizard-tail exclusive emote. +/datum/emote/living/carbon/human/tailthump + key = "thump" + key_third_person = "thumps their tail" + message = "thumps their tail!" + emote_type = EMOTE_AUDIBLE + vary = TRUE + +/datum/emote/living/carbon/human/tailthump/get_sound(mob/living/user) + return 'sound/voice/lizard/tailthump.ogg' // Source: https://freesound.org/people/TylerAM/sounds/389665/ + +/datum/emote/living/carbon/human/tailthump/can_run_emote(mob/user, status_check = TRUE, intentional) + . = ..() + if(!.) + return FALSE + var/mob/living/carbon/human/H = user + if(!istype(H) || !H.dna || !H.dna.species) + return FALSE + if(H.IsParalyzed() || H.IsStun()) // No thumping allowed. Taken from can_wag_tail(). + return FALSE + return ("tail_lizard" in H.dna.species.mutant_bodyparts) || ("waggingtail_lizard" in H.dna.species.mutant_bodyparts) + /datum/emote/living/carbon/human/wag key = "wag" key_third_person = "wags" diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 7365f84e1ada..55f80107e70a 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -479,7 +479,7 @@ "\[View comment log\]", "\[Add comment\]"), "") else if(isobserver(user) && traitstring) - . += "Traits: [traitstring]
" + . += "Quirks: [traitstring]
" . += "" /mob/living/proc/status_effect_examines(pronoun_replacement) //You can include this in any mob's examine() to show the examine texts of status effects! diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 1fc17d853d7c..c5508355451b 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -619,7 +619,8 @@ facial_hair_style = "Full Beard" else facial_hair_style = "Shaved" - hair_style = pick("Bedhead", "Bedhead 2", "Bedhead 3") + if(!HAS_TRAIT(src, TRAIT_BALD)) + hair_style = pick("Bedhead", "Bedhead 2", "Bedhead 3") underwear = "Nude" update_body() update_hair() @@ -708,7 +709,7 @@ #undef CPR_PANIC_SPEED /mob/living/carbon/human/cuff_resist(obj/item/I) - if(dna && (dna.check_mutation(HULK) || dna.check_mutation(ACTIVE_HULK))) + if(dna && (dna.check_mutation(HULK))) say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk") if(..(I, cuff_break = FAST_CUFFBREAK)) dropItemToGround(I) @@ -1128,12 +1129,8 @@ remove_movespeed_modifier(MOVESPEED_ID_CRAWL_MODIFIER, TRUE) /mob/living/carbon/human/updatehealth() - var/oldhealth = health . = ..() dna?.species.spec_updatehealth(src) - if(!dna) - return - hulk_health_check(oldhealth) /mob/living/carbon/human/adjust_nutrition(change) //Honestly FUCK the oldcoders for putting nutrition on /mob someone else can move it up because holy hell I'd have to fix SO many typechecks if(HAS_TRAIT(src, TRAIT_NOHUNGER)) @@ -1394,36 +1391,3 @@ /mob/living/carbon/human/species/zombie/krokodil_addict race = /datum/species/krokodil_addict - -/mob/living/carbon/human/proc/hulk_health_check(oldhealth) - if(!dna) - return - - if(dna.check_mutation(ACTIVE_HULK)) - if(health < HEALTH_THRESHOLD_CRIT) - dna.remove_mutation(ACTIVE_HULK) - return - if(health < oldhealth) - adjustStaminaLoss(-1.5 * (oldhealth - health)) - else - if(!dna.check_mutation(HULK) && dna.check_mutation(GENETICS_HULK) && stat == CONSCIOUS && (oldhealth >= health + 10 || health < (0.5 * maxHealth))) - dna.add_mutation(ACTIVE_HULK) - -/mob/living/carbon/human/proc/hulk_stamina_check() - if(dna.check_mutation(ACTIVE_HULK)) - if(staminaloss < 60 && prob(1)) - adjust_confusion(7 SECONDS) - say("HULK SMASH!!") - if(staminaloss >= 90) - dna.remove_mutation(ACTIVE_HULK) - to_chat(src, span_notice("You have calm down enough to become human again.")) - Knockdown(6) - return TRUE - else - return FALSE - -/mob/living/carbon/human/Bump(atom/movable/AM) - ..() - if(dna.check_mutation(ACTIVE_HULK) && has_status_effect(/datum/status_effect/confusion) && (world.time - last_bumped) > 15) - Bumped(AM) - return AM.attack_hulk(src) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index d3259e769e01..e47cd033f595 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -15,7 +15,7 @@ //If you don't specify a bodypart, it checks ALL your bodyparts for protection, and averages out the values for(var/X in bodyparts) var/obj/item/bodypart/BP = X - armorval += checkarmor(BP, type) + armorval += min(checkarmor(BP, type), 100) // hey no you can't do that organnum++ return (armorval/max(organnum, 1)) @@ -30,7 +30,7 @@ continue if(bp && istype(bp , /obj/item/clothing)) var/obj/item/clothing/C = bp - if(C.body_parts_covered & def_zone.body_part) + if(def_zone.body_part & C.body_parts_covered) protection += C.armor.getRating(d_type) else if(C.body_parts_partial_covered & def_zone.body_part) protection += C.armor.getRating(d_type) * 0.5 @@ -46,7 +46,7 @@ continue if(bp && istype(bp , /obj/item/clothing)) var/obj/item/clothing/C = bp - if(C.body_parts_covered & def_zone.body_part) + if(def_zone.body_part & C.body_parts_covered) covering_part += C return covering_part @@ -64,7 +64,7 @@ if(mind) if(mind.martial_art && !incapacitated(FALSE, TRUE) && mind.martial_art.can_use(src) && (mind.martial_art.deflection_chance || ((mind.martial_art.id == "sleeping carp") && in_throw_mode))) //Some martial arts users can deflect projectiles! if(prob(mind.martial_art.deflection_chance) || ((mind.martial_art.id == "sleeping carp") && in_throw_mode)) // special check if sleeping carp is our martial art and throwmode is on, deflect - if((mobility_flags & MOBILITY_USE) && dna && !(dna.check_mutation(HULK)|| dna.check_mutation(ACTIVE_HULK))) //But only if they're otherwise able to use items, and hulks can't do it + if((mobility_flags & MOBILITY_USE) && dna && !dna.check_mutation(HULK)) //But only if they're otherwise able to use items, and hulks can't do it if(!isturf(loc)) //if we're inside something and still got hit P.force_hit = TRUE //The thing we're in passed the bullet to us. Pass it back, and tell it to take the damage. loc.bullet_act(P) @@ -500,44 +500,8 @@ //Added a safety check in case you want to shock a human mob directly through electrocute_act. -/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0, stun = TRUE, gib = FALSE) - if(tesla_shock) - var/total_coeff = 1 - if(gloves) - var/obj/item/clothing/gloves/G = gloves - if(G.siemens_coefficient <= 0) - total_coeff -= 0.5 - if(istype(G, /obj/item/clothing/gloves/color/fyellow)) - var/obj/item/clothing/gloves/color/fyellow/greytide = G - greytide.get_shocked() - if(wear_suit) - var/obj/item/clothing/suit/S = wear_suit - if(S.siemens_coefficient <= 0) - total_coeff -= 0.95 - else if(S.siemens_coefficient == (-1)) - total_coeff -= 1 - siemens_coeff = total_coeff - if(flags_1 & TESLA_IGNORE_1) - siemens_coeff = 0 - else if(!safety) - var/gloves_siemens_coeff = 1 - if(gloves) - var/obj/item/clothing/gloves/G = gloves - gloves_siemens_coeff = G.siemens_coefficient - if(istype(G, /obj/item/clothing/gloves/color/fyellow)) - var/obj/item/clothing/gloves/color/fyellow/greytide = G - greytide.get_shocked() - siemens_coeff = gloves_siemens_coeff - if(undergoing_cardiac_arrest() && !illusion) - if(shock_damage * siemens_coeff >= 1 && prob(25)) - var/obj/item/organ/heart/heart = getorganslot(ORGAN_SLOT_HEART) - heart.beating = TRUE - if(stat == CONSCIOUS) - to_chat(src, span_notice("You feel your heart beating again!")) - siemens_coeff *= physiology.siemens_coeff - - dna.species.spec_electrocute_act(src, shock_damage,source,siemens_coeff,safety,override,tesla_shock, illusion, stun) - . = ..(shock_damage,source,siemens_coeff,safety,override,tesla_shock, illusion, stun, gib) +/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, zone = BODY_ZONE_R_ARM, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE, gib = FALSE) + . = ..() if(.) electrocution_animation(40) @@ -547,32 +511,8 @@ return dna.species.spec_emag_act(src, user, emag_card) /mob/living/carbon/human/emp_act(severity) - . = ..() - if(. & EMP_PROTECT_SELF) - return - if(HAS_TRAIT(src, TRAIT_FARADAYCAGE)) - severity++ - if(severity > EMP_LIGHT) - return - dna?.species.spec_emp_act(src, severity) - var/list/affected_parts = list() - for(var/obj/item/bodypart/BP in bodyparts) - if(istype(BP) && BP.status == BODYPART_ROBOTIC) - if(prob(5) && severity == EMP_HEAVY && (TRAIT_EASYDISMEMBER in dna?.species.inherent_traits) && BP.body_zone != BODY_ZONE_CHEST) - BP.dismember() - else - affected_parts += BP - if(affected_parts.len) - emote("scream") - adjustFireLoss(min(5 * affected_parts.len / severity, 20 / severity), FALSE, FALSE, BODYPART_ROBOTIC) - var/obj/item/bodypart/chest/C = get_bodypart(BODY_ZONE_CHEST) - var/obj/item/bodypart/head/H = get_bodypart(BODY_ZONE_HEAD) - if(((C && C.status == BODYPART_ROBOTIC) || (H && H.status == BODYPART_ROBOTIC)) && severity == EMP_HEAVY) // if your head and/or chest are robotic (aka you're a robotic race or augmented) you get cooler flavor text and rapid-onset paralysis - to_chat(src, span_userdanger("A surge of searing pain erupts throughout your very being! As the pain subsides, a terrible sensation of emptiness is left in its wake.")) - Paralyze(5 SECONDS) //heavy EMPs will fully stun you - else - adjustStaminaLoss(min(15 * affected_parts.len / severity, 60 / severity), FALSE, FALSE, BODYPART_ROBOTIC) - to_chat(src, span_userdanger("You feel a sharp pain as your robotic limbs overload.")) + severity *= physiology.emp_mod + return ..(severity) /mob/living/carbon/human/rad_act(amount, collectable_radiation) . = ..() diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 0d4695ddfa1d..8d81a51a33d3 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -142,7 +142,7 @@ . = ..() if(G.trigger_guard == TRIGGER_GUARD_NORMAL) - if(src.dna.check_mutation(HULK) || src.dna.check_mutation(ACTIVE_HULK)) + if(src.dna.check_mutation(HULK)) to_chat(src, span_warning("Your meaty finger is much too large for the trigger guard!")) return FALSE if(HAS_TRAIT(src, TRAIT_NOGUNS)) @@ -351,12 +351,20 @@ visually_duplicate_and_equip_item(copied_human_mob.gloves, ITEM_SLOT_GLOVES, new_human_mob, dropdel) if(copied_human_mob.shoes) visually_duplicate_and_equip_item(copied_human_mob.shoes, ITEM_SLOT_FEET, new_human_mob, dropdel) + if(copied_human_mob.head) + visually_duplicate_and_equip_item(copied_human_mob.head, ITEM_SLOT_HEAD, new_human_mob, dropdel) if(copied_human_mob.wear_id) visually_duplicate_and_equip_item(copied_human_mob.wear_id, ITEM_SLOT_ID, new_human_mob, dropdel) new_human_mob.sec_hud_set_ID() for(var/obj/item/implant/implant_instance in copied_human_mob.implants) - var/obj/item/implant/implant_copy = new implant_instance.type + var/obj/item/implant/implant_copy + if(istype(implant_instance, /obj/item/implant/dusting/iaa)) + implant_copy = new /obj/item/implant/dusting/iaa/fake () + else + implant_copy = new implant_instance.type + if(!implant_copy) + continue //if somehow it doesn't create a copy, don't runtime implant_copy.implant(new_human_mob, null, TRUE) if(dropdel) QDEL_IN(implant_copy, 7 SECONDS) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 990eafe0c222..83ce26f2f419 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -107,7 +107,7 @@ if(!dna) return - if(prob(3) && dna.check_mutation(ACTIVE_HULK)) + if(prob(3) && dna.check_mutation(HULK)) say(pick_list_replacements(BRAIN_DAMAGE_FILE, "hulk")) /mob/living/carbon/human/handle_mutations_and_radiation() diff --git a/code/modules/mob/living/carbon/human/physiology.dm b/code/modules/mob/living/carbon/human/physiology.dm index 50f31d0fcd3a..36982d89d352 100644 --- a/code/modules/mob/living/carbon/human/physiology.dm +++ b/code/modules/mob/living/carbon/human/physiology.dm @@ -17,6 +17,7 @@ var/damage_resistance = 0 // %damage reduction from all sources var/siemens_coeff = 1 // resistance to shocks + var/emp_mod = 1 // resistance to EMPs var/stun_mod = 1 // % stun modifier var/bleed_mod = 1 // % bleeding modifier diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 571facfad919..2b759a5e221d 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -97,6 +97,8 @@ GLOBAL_LIST_EMPTY(features_by_species) var/staminamod = 1 /// multiplier for pressure damage var/pressuremod = 1 + /// multiplier for EMP severity + var/emp_mod = 1 /// multiplier for money paid at payday, species dependent var/payday_modifier = 1 ///Type of damage attack does @@ -1035,7 +1037,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(!forced_colour) switch(S.color_src) if(MUTCOLORS) - if(H.dna.check_mutation(HULK) || H.dna.check_mutation(ACTIVE_HULK)) //HULK GO FIRST + if(H.dna.check_mutation(HULK)) //HULK GO FIRST accessory_overlay.color = "#00aa00" else if(fixed_mut_color) //Then fixed color if applicable accessory_overlay.color = fixed_mut_color @@ -1542,7 +1544,7 @@ GLOBAL_LIST_EMPTY(features_by_species) /datum/species/proc/spec_emag_act(mob/living/carbon/human/H, mob/user, obj/item/card/emag/emag_card) return FALSE -/datum/species/proc/spec_electrocute_act(mob/living/carbon/human/H, shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0, stun = TRUE) +/datum/species/proc/spec_electrocute_act(mob/living/carbon/human/H, shock_damage, obj/source, siemens_coeff = 1, zone = BODY_ZONE_R_ARM, override = 0, tesla_shock = 0, illusion = 0, stun = TRUE) return /datum/species/proc/help(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) @@ -1763,7 +1765,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(M.mind) attacker_style = M.mind.martial_art if((M != H) && M.a_intent != INTENT_HELP && H.check_shields(M, 0, M.name, attack_type = UNARMED_ATTACK)) - if((M.dna.check_mutation(ACTIVE_HULK) || M.dna.check_mutation(HULK)) && M.a_intent == "disarm") + if(M.dna.check_mutation(HULK) && M.a_intent == "disarm") H.check_shields(0, M.name) // We check their shields twice since we are a hulk. Also triggers hitreactions for HULK_ATTACK M.visible_message(span_danger("[M]'s punch knocks the shield out of [H]'s hand."), \ span_userdanger("[M]'s punch knocks the shield out of [H]'s hand.")) @@ -1973,8 +1975,8 @@ GLOBAL_LIST_EMPTY(features_by_species) if(istype(human_loc, /obj/machinery/atmospherics/components/unary/cryo_cell)) return - if(environment.get_moles(/datum/gas/water_vapor) > 10)//water vapour above a certain amount makes you wet - if(environment.get_moles(/datum/gas/water_vapor) > 40)//if there's a lot of water vapour, preterni ded + if(environment.get_moles(GAS_H2O) > 10)//water vapour above a certain amount makes you wet + if(environment.get_moles(GAS_H2O) > 40)//if there's a lot of water vapour, preterni ded H.adjust_wet_stacks(3) else H.adjust_wet_stacks(2) @@ -2577,6 +2579,22 @@ GLOBAL_LIST_EMPTY(features_by_species) SPECIES_PERK_DESC = "[plural_form] are resilient to being shocked.", )) + if(emp_mod > 1) + to_add += list(list( + SPECIES_PERK_TYPE = SPECIES_NEGATIVE_PERK, + SPECIES_PERK_ICON = "thunderstorm", + SPECIES_PERK_NAME = "EM Weakness", + SPECIES_PERK_DESC = "[plural_form] are weak to electromagnetic interference.", + )) + + if(emp_mod < 1) + to_add += list(list( + SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK, + SPECIES_PERK_ICON = "thunderstorm", //if we update font awesome, please swap to bolt-slash + SPECIES_PERK_NAME = "EM Resistance", + SPECIES_PERK_DESC = "[plural_form] are resistant to electromagnetic interference.", + )) + return to_add /** @@ -2675,15 +2693,6 @@ GLOBAL_LIST_EMPTY(features_by_species) SPECIES_PERK_NAME = "Radiation Immunity", SPECIES_PERK_DESC = "[plural_form] are completely unaffected by radiation. However, this doesn't mean they can't be irradiated.", )) - - if(TRAIT_FARADAYCAGE in inherent_traits) - to_add += list(list( - SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK, - SPECIES_PERK_ICON = "thunderstorm", //if we update font awesome, please swap to bolt-slash - SPECIES_PERK_NAME = "Faraday \"Skin\"", - SPECIES_PERK_DESC = "[plural_form] have a unique physiology that shields them from weak EMPs.", - )) - if(TRAIT_LIMBATTACHMENT in inherent_traits) to_add += list(list( SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK, diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm index 1187abb2c9d7..890dac7e8108 100644 --- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm +++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm @@ -53,15 +53,12 @@ smells_like = "crackling sweetness" - var/obj/effect/dummy/lighting_obj/ethereal_light - + var/obj/effect/dummy/lighting_obj/moblight/species/ethereal_light /datum/species/ethereal/Destroy(force) - if(ethereal_light) - QDEL_NULL(ethereal_light) + QDEL_NULL(ethereal_light) return ..() - /datum/species/ethereal/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load) . = ..() if(!ishuman(C)) @@ -70,7 +67,7 @@ var/mob/living/carbon/human/ethereal = C setup_color(ethereal) - ethereal_light = ethereal.mob_light() + ethereal_light = ethereal.mob_light(light_type = /obj/effect/dummy/lighting_obj/moblight/species) spec_updatehealth(ethereal) var/obj/item/organ/heart/ethereal/ethereal_heart = ethereal.getorganslot(ORGAN_SLOT_HEART) @@ -136,7 +133,7 @@ to_chat(H, span_notice("You feel the light of your body leave you.")) EMPeffect = TRUE spec_updatehealth(H) - addtimer(CALLBACK(src, PROC_REF(stop_emp), H), 200 / severity, TIMER_UNIQUE|TIMER_OVERRIDE) //We're out for 10 to 20 seconds depending on severity + addtimer(CALLBACK(src, PROC_REF(stop_emp), H), 20 * severity, TIMER_UNIQUE|TIMER_OVERRIDE) //We're out for 2 to 20 seconds depending on severity /datum/species/ethereal/proc/stop_emp(mob/living/carbon/human/H) EMPeffect = FALSE diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index eb87263056ab..0d21310381a0 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -442,19 +442,25 @@ id = "lum" say_mod = "says" var/glow_intensity = LUMINESCENT_DEFAULT_GLOW - var/obj/effect/dummy/luminescent_glow/glow var/obj/item/slime_extract/current_extract var/datum/action/innate/integrate_extract/integrate_extract var/datum/action/innate/use_extract/extract_minor var/datum/action/innate/use_extract/major/extract_major var/extract_cooldown = 0 + /// Internal dummy used to glow (very cool) + var/obj/effect/dummy/lighting_obj/moblight/species/glow + +/datum/species/jelly/luminescent/Destroy(force, ...) + . = ..() + QDEL_NULL(glow) + /datum/species/jelly/luminescent/on_species_loss(mob/living/carbon/C) ..() if(current_extract) current_extract.forceMove(C.drop_location()) current_extract = null - qdel(glow) + QDEL_NULL(glow) if(integrate_extract) integrate_extract.Remove(C) if(extract_minor) @@ -464,7 +470,7 @@ /datum/species/jelly/luminescent/on_species_gain(mob/living/carbon/C, datum/species/old_species) ..() - glow = new(C) + glow = C.mob_light(light_type = /obj/effect/dummy/lighting_obj/moblight/species) update_glow(C) integrate_extract = new(src) integrate_extract.Grant(C) @@ -484,20 +490,6 @@ glow_intensity = intensity glow.set_light_range_power_color(glow_intensity, glow_intensity, C.dna.features["mcolor"]) -/obj/effect/dummy/luminescent_glow - name = "luminescent glow" - desc = "Tell a coder if you're seeing this." - icon_state = "nothing" - light_color = "#FFFFFF" - light_range = LUMINESCENT_DEFAULT_GLOW - light_system = MOVABLE_LIGHT - light_power = 2.5 - -/obj/effect/dummy/luminescent_glow/Initialize(mapload) - . = ..() - if(!isliving(loc)) - return INITIALIZE_HINT_QDEL - /datum/action/innate/integrate_extract name = "Integrate Extract" desc = "Eat a slime extract to use its properties." diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index e75dd711dc7c..0dfc2d7ad44d 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -112,7 +112,11 @@ /datum/species/lizard/proc/regrow_tail(mob/living/carbon/human/H) if(!H.getorganslot(ORGAN_SLOT_TAIL) && H.stat != DEAD) - mutant_bodyparts |= "tail_lizard" + var/obj/item/organ/tail/lizard/tail = new mutanttail() + tail.color = H.dna.features["mcolor"] + tail.tail_type = H.dna.features["tail_lizard"] + tail.spines = H.dna.features["spines"] + tail.Insert(H, TRUE) H.visible_message("[H]'s tail regrows.","You feel your tail regrow.") /datum/species/lizard/get_species_description() diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index 81adae64a74e..3739d3c9dd6b 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -27,6 +27,8 @@ liked_food = DAIRY changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC species_language_holder = /datum/language_holder/plasmaman + + screamsound = list('sound/voice/plasmaman/plasmeme_scream_1.ogg', 'sound/voice/plasmaman/plasmeme_scream_2.ogg', 'sound/voice/plasmaman/plasmeme_scream_3.ogg') smells_like = "plasma-caked calcium" @@ -47,7 +49,7 @@ if((!istype(H.w_uniform, /obj/item/clothing/under/plasmaman) || !istype(H.head, /obj/item/clothing/head/helmet/space/plasmaman)) && !atmos_sealed) if(environment) if(environment.total_moles()) - if(environment.get_moles(/datum/gas/oxygen) >= 1) //Same threshhold that extinguishes fire + if(environment.get_moles(GAS_O2) >= 1) //Same threshhold that extinguishes fire H.adjust_fire_stacks(0.5) if(!H.on_fire && H.fire_stacks > 0) H.visible_message(span_danger("[H]'s body reacts with the atmosphere and bursts into flames!"),span_userdanger("Your body reacts with the atmosphere and bursts into flame!")) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 64a179f88e09..15c1da734fbe 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -631,7 +631,7 @@ generate/load female uniform sprites matching all previously decided variables /mob/living/carbon/human/generate_icon_render_key() . = "[dna.species.limbs_id]" - if(dna.check_mutation(HULK) || dna.check_mutation(ACTIVE_HULK)) + if(dna.check_mutation(HULK)) . += "-coloured-hulk" else if(dna.species.use_skintones) . += "-coloured-[skin_tone]" diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 1cb873615047..7e860d1e31af 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -113,21 +113,22 @@ breath = loc_as_obj.handle_internal_lifeform(src, BREATH_VOLUME) else if(isturf(loc)) //Breathe from loc as turf - var/breath_moles = 0 + var/breath_ratio = 0 if(environment) - breath_moles = environment.total_moles()*BREATH_PERCENTAGE + breath_ratio = BREATH_VOLUME/environment.return_volume() - breath = loc.remove_air(breath_moles) + breath = loc.remove_air_ratio(breath_ratio) else //Breathe from loc as obj again if(istype(loc, /obj/)) var/obj/loc_as_obj = loc loc_as_obj.handle_internal_lifeform(src,0) + if(breath) + breath.set_volume(BREATH_VOLUME) check_breath(breath) if(breath) loc.assume_air(breath) - air_update_turf() /mob/living/carbon/proc/has_smoke_protection() if(HAS_TRAIT(src, TRAIT_NOBREATH)) @@ -162,11 +163,13 @@ var/SA_para_min = 1 var/SA_sleep_min = 5 var/oxygen_used = 0 - var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.return_temperature())/BREATH_VOLUME + var/moles = breath.total_moles() - var/O2_partialpressure = (breath.get_moles(/datum/gas/oxygen)/breath.total_moles())*breath_pressure - var/Toxins_partialpressure = (breath.get_moles(/datum/gas/plasma)/breath.total_moles())*breath_pressure - var/CO2_partialpressure = (breath.get_moles(/datum/gas/carbon_dioxide)/breath.total_moles())*breath_pressure + + var/breath_pressure = (moles*R_IDEAL_GAS_EQUATION*breath.return_temperature())/BREATH_VOLUME + var/O2_partialpressure = ((breath.get_moles(GAS_O2)/moles)*breath_pressure) + (((breath.get_moles(GAS_PLUOXIUM)*8)/moles)*breath_pressure) + var/Toxins_partialpressure = (breath.get_moles(GAS_PLASMA)/moles)*breath_pressure + var/CO2_partialpressure = (breath.get_moles(GAS_CO2)/moles)*breath_pressure //OXYGEN @@ -177,7 +180,7 @@ var/ratio = 1 - O2_partialpressure/safe_oxy_min adjustOxyLoss(min(5*ratio, 3)) failed_last_breath = 1 - oxygen_used = breath.get_moles(/datum/gas/oxygen)*ratio + oxygen_used = breath.get_moles(GAS_O2)*ratio else adjustOxyLoss(3) failed_last_breath = 1 @@ -187,11 +190,11 @@ failed_last_breath = 0 if(health >= crit_threshold) adjustOxyLoss(-5) - oxygen_used = breath.get_moles(/datum/gas/oxygen) + oxygen_used = breath.get_moles(GAS_O2) clear_alert("not_enough_oxy") - breath.adjust_moles(/datum/gas/oxygen, -oxygen_used) - breath.adjust_moles(/datum/gas/carbon_dioxide, oxygen_used) + breath.adjust_moles(GAS_O2, -oxygen_used) + breath.adjust_moles(GAS_CO2, oxygen_used) //CARBON DIOXIDE if(CO2_partialpressure > safe_co2_max) @@ -210,15 +213,15 @@ //TOXINS/PLASMA if(Toxins_partialpressure > safe_tox_max) - var/ratio = (breath.get_moles(/datum/gas/plasma)/safe_tox_max) * 10 + var/ratio = (breath.get_moles(GAS_PLASMA)/safe_tox_max) * 10 adjustToxLoss(clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE)) throw_alert("too_much_tox", /atom/movable/screen/alert/too_much_tox) else clear_alert("too_much_tox") //NITROUS OXIDE - if(breath.get_moles(/datum/gas/nitrous_oxide)) - var/SA_partialpressure = (breath.get_moles(/datum/gas/nitrous_oxide)/breath.total_moles())*breath_pressure + if(breath.get_moles(GAS_NITROUS)) + var/SA_partialpressure = (breath.get_moles(GAS_NITROUS)/breath.total_moles())*breath_pressure if(SA_partialpressure > SA_para_min) Unconscious(60) if(SA_partialpressure > SA_sleep_min) @@ -232,8 +235,8 @@ //yogs start -- Adds Nitrogen Narcosis https://en.wikipedia.org/wiki/Nitrogen_narcosis //NITROGEN - if(breath.get_moles(/datum/gas/nitrogen)) - var/SA_partialpressure = (breath.get_moles(/datum/gas/nitrogen)/breath.total_moles())*breath_pressure + if(breath.get_moles(GAS_N2)) + var/SA_partialpressure = (breath.get_moles(GAS_N2)/breath.total_moles())*breath_pressure if(SA_partialpressure > NITROGEN_NARCOSIS_PRESSURE_LOW) // Giggles if(prob(20)) emote(pick("giggle","laugh")) @@ -244,8 +247,8 @@ adjust_hallucinations(5 SECONDS) //yogs end //BZ (Facepunch port of their Agent B) - if(breath.get_moles(/datum/gas/bz)) - var/bz_partialpressure = (breath.get_moles(/datum/gas/bz)/breath.total_moles())*breath_pressure + if(breath.get_moles(GAS_BZ)) + var/bz_partialpressure = (breath.get_moles(GAS_BZ)/breath.total_moles())*breath_pressure /* Yogs comment-out: Smoothed BZ hallucination levels if(bz_partialpressure > 1) adjust_hallucinations(10 SECONDS) @@ -255,18 +258,18 @@ adjust_hallucinations(round(BZ_MAX_HALLUCINATION * (1 - NUM_E ** (-BZ_LAMBDA * bz_partialpressure)))) // Yogs -- Better BZ hallucination values. Keep in mind that hallucination has to be an integer value, due to how it's handled in handle_hallucination() //TRITIUM - if(breath.get_moles(/datum/gas/tritium)) - var/tritium_partialpressure = (breath.get_moles(/datum/gas/tritium)/breath.total_moles())*breath_pressure + if(breath.get_moles(GAS_TRITIUM)) + var/tritium_partialpressure = (breath.get_moles(GAS_TRITIUM)/breath.total_moles())*breath_pressure radiation += tritium_partialpressure/10 //FREON - if(breath.get_moles(/datum/gas/freon)) - var/freon_partialpressure = (breath.get_moles(/datum/gas/freon)/breath.total_moles())*breath_pressure + if(breath.get_moles(GAS_FREON)) + var/freon_partialpressure = (breath.get_moles(GAS_FREON)/breath.total_moles())*breath_pressure adjustFireLoss(freon_partialpressure * 0.25) //MIASMA - if(breath.get_moles(/datum/gas/miasma)) - var/miasma_partialpressure = (breath.get_moles(/datum/gas/miasma)/breath.total_moles())*breath_pressure + if(breath.get_moles(GAS_MIASMA)) + var/miasma_partialpressure = (breath.get_moles(GAS_MIASMA)/breath.total_moles())*breath_pressure if(prob(1 * miasma_partialpressure)) var/datum/disease/advance/miasma_disease = new /datum/disease/advance/random(2,3) @@ -335,7 +338,7 @@ /mob/living/carbon/proc/handle_bodyparts() var/stam_regen = FALSE - if(stam_regen_start_time <= world.time && (has_dna() && !dna.check_mutation(ACTIVE_HULK))) + if(stam_regen_start_time <= world.time) stam_regen = TRUE if(HAS_TRAIT_FROM(src, TRAIT_INCAPACITATED, STAMINA)) . |= BODYPART_LIFE_UPDATE_HEALTH //make sure we remove the stamcrit diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 120de23ca684..b09e8ed406d9 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -363,7 +363,10 @@ //same as above /mob/living/pointed(atom/A as mob|obj|turf in view()) - if(incapacitated()) + var/obj/item/clothing/suit/straight_jacket/straightjacket = get_item_by_slot(ITEM_SLOT_OCLOTHING) + if(istype(straightjacket)) + return FALSE + if(incapacitated(ignore_restraints = TRUE)) return FALSE if(HAS_TRAIT(src, TRAIT_DEATHCOMA)) return FALSE @@ -941,7 +944,7 @@ loc_temp = obj_temp else if(isspaceturf(get_turf(src))) var/turf/heat_turf = get_turf(src) - loc_temp = heat_turf.temperature + loc_temp = heat_turf.return_temperature() return loc_temp /mob/living/proc/get_standard_pixel_x_offset(lying = 0) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 0f863d0aa9ba..161beed32fd4 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -360,22 +360,30 @@ take_bodypart_damage(acidpwr * min(1, acid_volume * 0.1)) return 1 -/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE, gib = FALSE) - SEND_SIGNAL(src, COMSIG_LIVING_ELECTROCUTE_ACT, shock_damage) +/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, zone = null, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE, gib = FALSE) if(tesla_shock && (flags_1 & TESLA_IGNORE_1)) return FALSE if(HAS_TRAIT(src, TRAIT_SHOCKIMMUNE)) return FALSE - if(shock_damage > 0) - if(!illusion) - last_damage = "electricity burns" - adjustFireLoss(shock_damage) - visible_message( - span_danger("[src] was shocked by \the [source]!"), \ - span_userdanger("You feel a powerful shock coursing through your body!"), \ - span_italics("You hear a heavy electrical crack.") \ - ) - return shock_damage + + if(!override) + siemens_coeff *= (100 - getarmor(zone, ELECTRIC)) / 100 + if(SEND_SIGNAL(src, COMSIG_LIVING_ELECTROCUTE_ACT, shock_damage, source, siemens_coeff, zone, tesla_shock, illusion) & COMPONENT_NO_ELECTROCUTE_ACT) + return FALSE + + shock_damage *= siemens_coeff + if(shock_damage < 1 && !override) + return FALSE + + if(!illusion) + last_damage = "electricity burns" + adjustFireLoss(shock_damage) + visible_message( + span_danger("[src] was shocked by \the [source]!"), \ + span_userdanger("You feel a powerful shock coursing through your body!"), \ + span_italics("You hear a heavy electrical crack.") \ + ) + return shock_damage /mob/living/emp_act(severity) . = ..() diff --git a/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm b/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm index 785606f8b3f2..51dea1064c3a 100644 --- a/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm +++ b/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm @@ -8,30 +8,36 @@ icon = 'icons/obj/machines/research.dmi' icon_state = "RD-server-on" density = TRUE + ///Temperature of the ai core itself, this will share with air in the enviroment + var/core_temp = 193.15 /obj/machinery/ai/Initialize(mapload) . = ..() - - SSair.atmos_machinery += src + START_PROCESSING(SSmachines, src) + SSair_machinery.start_processing_machine(src) + +//Cooling happens here +/obj/machinery/ai/process_atmos() + var/turf/T = get_turf(src) + if(!T) + return + if(isspaceturf(T)) + return + var/datum/gas_mixture/env = T.return_air() + if(!env) + return + var/new_temp = env.temperature_share(AI_HEATSINK_COEFF, core_temp, AI_HEATSINK_CAPACITY) + core_temp = new_temp /obj/machinery/ai/Destroy() . = ..() - - SSair.atmos_machinery -= src + SSair_machinery.stop_processing_machine(src) + STOP_PROCESSING(SSmachines, src) /obj/machinery/ai/proc/valid_holder() if(stat & (BROKEN|EMPED) || !has_power()) return FALSE - - var/turf/T = get_turf(src) - var/datum/gas_mixture/env = T.return_air() - if(!env) - return FALSE - var/total_moles = env.total_moles() - if(istype(T, /turf/open/space) || total_moles < 10) - return FALSE - - if(env.return_temperature() > GLOB.ai_os.get_temp_limit() || !env.heat_capacity()) + if(core_temp > GLOB.ai_os.get_temp_limit()) return FALSE return TRUE @@ -41,15 +47,6 @@ /obj/machinery/ai/proc/get_holder_status() if(stat & (BROKEN|NOPOWER|EMPED)) return FALSE - - var/turf/T = get_turf(src) - var/datum/gas_mixture/env = T.return_air() - if(!env) - return AI_MACHINE_NO_MOLES - var/total_moles = env.total_moles() - if(istype(T, /turf/open/space) || total_moles < 10) - return AI_MACHINE_NO_MOLES - - if(env.return_temperature() > GLOB.ai_os.get_temp_limit() || !env.heat_capacity()) + if(core_temp > GLOB.ai_os.get_temp_limit()) return AI_MACHINE_TOO_HOT \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm b/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm index e2dc2308877f..cd77f9b70ad8 100644 --- a/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm +++ b/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm @@ -59,8 +59,42 @@ GLOBAL_VAR_INIT(primary_data_core, null) power_modifier = new_power_mod active_power_usage = AI_DATA_CORE_POWER_USAGE * power_modifier -/obj/machinery/ai/data_core/process_atmos() - calculate_validity() +/obj/machinery/ai/data_core/process() + valid_ticks = clamp(valid_ticks, 0, MAX_AI_DATA_CORE_TICKS) + + if(valid_holder()) + valid_ticks++ + if(valid_ticks == 1) + update_icon() + use_power = ACTIVE_POWER_USE + if((stat & NOPOWER)) + integrated_battery.use(active_power_usage * CELL_POWERUSE_MULTIPLIER) + warning_sent = FALSE + else + valid_ticks-- + if(valid_ticks <= 0) + use_power = IDLE_POWER_USE + update_icon() + for(var/mob/living/silicon/ai/AI in contents) + if(!AI.is_dying) + AI.relocate() + if(!warning_sent && COOLDOWN_FINISHED(src, warning_cooldown)) + warning_sent = TRUE + COOLDOWN_START(src, warning_cooldown, AI_DATA_CORE_WARNING_COOLDOWN) + var/list/send_to = GLOB.ai_list.Copy() + for(var/mob/living/silicon/ai/AI in send_to) + if(AI.is_dying) + continue + if(!AI.mind && AI.deployed_shell.mind) + to_chat(AI.deployed_shell, span_userdanger("Data core in [get_area(src)] is on the verge of failing! Immediate action required to prevent failure.")) + else + to_chat(AI, span_userdanger("Data core in [get_area(src)] is on the verge of failing! Immediate action required to prevent failure.")) + AI.playsound_local(AI, 'sound/machines/engine_alert2.ogg', 30) + + if(!(stat & (BROKEN|EMPED)) && has_power() && !disableheat) + var/temp_active_usage = stat & NOPOWER ? active_power_usage * CELL_POWERUSE_MULTIPLIER : active_power_usage + var/temperature_increase = (temp_active_usage / AI_HEATSINK_CAPACITY) * heat_modifier //1 CPU = 1000W. Heat capacity = somewhere around 3000-4000. Aka we generate 0.25 - 0.33 K per second, per CPU. + core_temp += temperature_increase * AI_TEMPERATURE_MULTIPLIER /obj/machinery/ai/data_core/Destroy() GLOB.data_cores -= src @@ -126,6 +160,7 @@ GLOBAL_VAR_INIT(primary_data_core, null) . += span_warning("Machinery non-functional. Reason: [holder_status]") if(!isobserver(user)) return + . += "Core temperature: [core_temp] K" . += "Networked AI Laws:" for(var/mob/living/silicon/ai/AI in GLOB.ai_list) var/active_status = "(Core: [FOLLOW_LINK(user, AI.loc)], Eye: [FOLLOW_LINK(user, AI.eyeobj)])" diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm b/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm index eaccf21f5213..d19eba133c67 100644 --- a/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm +++ b/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm @@ -320,7 +320,7 @@ GLOBAL_VAR_INIT(ai_control_code, random_nukecode(6)) one_time_password_used = TRUE var/msg = "

Warning!


We have detected usage of the AI Control Code for unlocking a console at coordinates ([src.x], [src.y], [src.z]) by [usr.name]. Please verify that this is correct. Be aware we have cancelled the current control code.
\ If needed a new code can be printed at a communications console." - priority_announce(msg, sender_override = "Central Cyber Security Update", has_important_message = TRUE, sanitize = FALSE) + priority_announce(msg, sender_override = "Central Cyber Security Update", has_important_message = TRUE) GLOB.ai_control_code = null else to_chat(usr, span_warning("Incorrect code. Make sure you have the latest one.")) diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm index 8aa136fe96b1..8a4d7bc023cd 100644 --- a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm +++ b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm @@ -87,8 +87,8 @@ data["location_name"] = get_area(current_turf) data["location_coords"] = "[current_turf.x], [current_turf.y], [current_turf.z]" - var/datum/gas_mixture/env = current_turf.return_air() - data["temperature"] = env.return_temperature() + var/obj/machinery/ai/current_machine = owner.loc + data["temperature"] = current_machine.core_temp ? current_machine.core_temp : 0 for(var/datum/ai_project/AP as anything in available_projects) data["available_projects"] += list(list("name" = AP.name, "description" = AP.description, "ram_required" = AP.ram_required, "available" = AP.canResearch(), "research_cost" = AP.research_cost, "research_progress" = AP.research_progress, diff --git a/code/modules/mob/living/silicon/ai/decentralized/server_cabinet.dm b/code/modules/mob/living/silicon/ai/decentralized/server_cabinet.dm index 64b2fca5cd33..5f283cdda954 100644 --- a/code/modules/mob/living/silicon/ai/decentralized/server_cabinet.dm +++ b/code/modules/mob/living/silicon/ai/decentralized/server_cabinet.dm @@ -64,18 +64,14 @@ GLOBAL_LIST_EMPTY(server_cabinets) idle_power_usage = initial(idle_power_usage) * power_modifier -/obj/machinery/ai/server_cabinet/process_atmos() +/obj/machinery/ai/server_cabinet/process() valid_ticks = clamp(valid_ticks, 0, MAX_AI_EXPANSION_TICKS) if(valid_holder()) var/total_usage = (cached_power_usage * power_modifier) use_power(total_usage) - var/turf/T = get_turf(src) - var/datum/gas_mixture/env = T.return_air() - if(env.heat_capacity()) - var/temperature_increase = (total_usage / env.heat_capacity()) * heat_modifier - env.set_temperature(env.return_temperature() + temperature_increase * AI_TEMPERATURE_MULTIPLIER) //assume all input power is dissipated - T.air_update_turf() + var/temperature_increase = (total_usage / AI_HEATSINK_CAPACITY)* heat_modifier + core_temp += temperature_increase * AI_TEMPERATURE_MULTIPLIER valid_ticks++ if(!was_valid_holder) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 17afcab90d30..9fb6a32b9d80 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -9,6 +9,9 @@ mob_size = MOB_SIZE_TINY desc = "A generic pAI mobile hard-light holographics emitter. It seems to be deactivated." weather_immunities = list(WEATHER_ASH) + light_on = FALSE + light_flags = LIGHT_ATTACHED + light_system = MOVABLE_LIGHT health = 500 maxHealth = 500 layer = BELOW_MOB_LAYER diff --git a/code/modules/mob/living/silicon/pai/pai_defense.dm b/code/modules/mob/living/silicon/pai/pai_defense.dm index b8be2fda95af..09bb968cd43c 100644 --- a/code/modules/mob/living/silicon/pai/pai_defense.dm +++ b/code/modules/mob/living/silicon/pai/pai_defense.dm @@ -6,16 +6,16 @@ . = ..() if(. & EMP_PROTECT_SELF) return - take_holo_damage(50/severity) - Paralyze(400/severity) - silent = max(30/severity, silent) + take_holo_damage(5 * severity) + Paralyze(40 * severity) + silent = max(3 * severity, silent) if(holoform) fold_in(force = TRUE) //Need more effects that aren't instadeath or permanent law corruption. //Ask and you shall receive switch(rand(1, 3)) if(1) - adjust_stutter(1 MINUTES / severity) + adjust_stutter((6 * severity) SECONDS) to_chat(src, span_danger("Warning: Feedback loop detected in speech module.")) if(2) adjust_slurring(INFINITY) diff --git a/code/modules/mob/living/silicon/pai/pai_shell.dm b/code/modules/mob/living/silicon/pai/pai_shell.dm index 57d2045c373e..23c911e36ee2 100644 --- a/code/modules/mob/living/silicon/pai/pai_shell.dm +++ b/code/modules/mob/living/silicon/pai/pai_shell.dm @@ -34,7 +34,6 @@ if(client) client.perspective = EYE_PERSPECTIVE client.eye = src - set_light(0) icon_state = "[chassis]" held_state = "[chassis]" visible_message(span_boldnotice("[src] folds out its holochassis emitter and forms a holoshell around itself!")) @@ -63,7 +62,6 @@ forceMove(card) mobility_flags = NONE density = FALSE - set_light(0) holoform = FALSE set_resting(resting) @@ -93,12 +91,9 @@ return FALSE /mob/living/silicon/pai/proc/toggle_integrated_light() - if(!light_range) - set_light(brightness_power) - to_chat(src, span_notice("You enable your integrated light.")) - else - set_light(0) - to_chat(src, span_notice("You disable your integrated light.")) + set_light_on(!light_on) + set_light_range(brightness_power) + to_chat(src, span_notice("You [light_on ? "enable" : "disable"] your integrated light.")) /mob/living/silicon/pai/mob_try_pickup(mob/living/user) if(!possible_chassis[chassis]) diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index a54c85a9c65c..77739a90a570 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -573,7 +573,7 @@ for(var/id in environment.get_gases()) var/gas_level = environment.get_moles(id)/total_moles if(gas_level > 0.01) - dat += "[GLOB.meta_gas_info[id][META_GAS_NAME]]: [round(gas_level*100)]%
" + dat += "[GLOB.gas_data.labels[id]]: [round(gas_level*100)]%
" dat += "Temperature: [round(environment.return_temperature()-T0C)]°C
" dat += "Refresh Reading
" dat += "
" diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index 80e710a1518e..6bc616c27263 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -80,11 +80,7 @@ . = ..() if(. & EMP_PROTECT_SELF) return - switch(severity) - if(1) - Stun(160) - if(2) - Stun(60) + Stun(min((1.6 SECONDS) * severity, 16 SECONDS)) // up to 16 seconds /mob/living/silicon/robot/emag_act(mob/user, obj/item/card/emag/emag_card) @@ -201,7 +197,7 @@ if(prob(75) && Proj.damage > 0) spark_system.start() -/mob/living/silicon/robot/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE, gib = FALSE) +/mob/living/silicon/robot/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, zone = null, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE, gib = FALSE) if(gib) visible_message( span_danger("[src] begins to heat up!"), \ diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index e8ef8b4249a7..7e2cb6838954 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -529,16 +529,17 @@ return clamp(damage_amount * (1 - armor_protection/100), 1, damage_amount) // Minimum of 1 damage. /// Copy of '/mob/living/attacked_by', except it sets damage to what is returned by 'proc/run_armor'. -/mob/living/silicon/attacked_by(obj/item/I, mob/living/user) - send_item_attack_message(I, user) - if(I.force) - var/damage = run_armor(I.force, I.damtype, MELEE) - apply_damage(damage, I.damtype) - if(I.damtype == BRUTE) - if(prob(33)) - I.add_mob_blood(src) - var/turf/location = get_turf(src) - add_splatter_floor(location) - if(get_dist(user, src) <= 1) - user.add_mob_blood(src) - return TRUE +/mob/living/silicon/attacked_by(obj/item/attacking_item, mob/living/user) + send_item_attack_message(attacking_item, user) + if(!attacking_item.force) + return FALSE + // Demolition mod has half the effect on silicons that it does on structures (ex. 2x will act as 1.5x, 0.5x will act as 0.75x) + var/damage = run_armor(attacking_item.force * (1 + attacking_item.demolition_mod)/2, attacking_item.damtype, MELEE) + apply_damage(damage, attacking_item.damtype) + if(attacking_item.damtype == BRUTE && prob(33)) + attacking_item.add_mob_blood(src) + var/turf/location = get_turf(src) + add_splatter_floor(location) + if(get_dist(user, src) <= 1) + user.add_mob_blood(src) + return TRUE diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm index 3942d298949d..621a5b374f2d 100644 --- a/code/modules/mob/living/silicon/silicon_defense.dm +++ b/code/modules/mob/living/silicon/silicon_defense.dm @@ -97,11 +97,11 @@ return return ..() -/mob/living/silicon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE, gib = FALSE) +/mob/living/silicon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, zone = null, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE, gib = FALSE) if(buckled_mobs) for(var/mob/living/M in buckled_mobs) unbuckle_mob(M) - M.electrocute_act(shock_damage/100, source, siemens_coeff, safety, tesla_shock, illusion, stun, gib) //Hard metal shell conducts! + M.electrocute_act(shock_damage/100, source, siemens_coeff, zone, override, tesla_shock, illusion, stun, gib) //Hard metal shell conducts! return 0 //So borgs they don't die trying to fix wiring /mob/living/silicon/emp_act(severity) @@ -109,14 +109,10 @@ to_chat(src, span_danger("Warning: Electromagnetic pulse detected.")) if(. & EMP_PROTECT_SELF) return - switch(severity) - if(1) - src.take_bodypart_damage(20) - if(2) - src.take_bodypart_damage(10) + take_bodypart_damage(2 * severity) to_chat(src, span_userdanger("*BZZZT*")) for(var/mob/living/M in buckled_mobs) - if(prob(severity*50)) + if(prob(5 * severity)) unbuckle_mob(M) M.Paralyze(40) M.visible_message(span_boldwarning("[M] is thrown off of [src]!")) @@ -125,7 +121,7 @@ /mob/living/silicon/bullet_act(obj/projectile/Proj, def_zone) SEND_SIGNAL(src, COMSIG_ATOM_BULLET_ACT, Proj, def_zone) if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) - var/damage = run_armor(Proj.damage, Proj.damage_type, Proj.armor_flag, Proj.armour_penetration) + var/damage = run_armor(Proj.damage * (1 + Proj.demolition_mod)/2, Proj.damage_type, Proj.armor_flag, Proj.armour_penetration) adjustBruteLoss(damage) if(prob(damage*1.5)) for(var/mob/living/M in buckled_mobs) diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm index 148022aec96e..f560dcb9eca4 100644 --- a/code/modules/mob/living/simple_animal/animal_defense.dm +++ b/code/modules/mob/living/simple_animal/animal_defense.dm @@ -180,7 +180,7 @@ visual_effect_icon = ATTACK_EFFECT_SMASH ..() -/mob/living/simple_animal/electrocute_act(shock_damage, obj/source, siemens_coeff, safety, tesla_shock, illusion, stun, gib) +/mob/living/simple_animal/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, zone = null, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE, gib = FALSE) if(gib) gib() return ..() diff --git a/code/modules/mob/living/simple_animal/bot/atmosbot.dm b/code/modules/mob/living/simple_animal/bot/atmosbot.dm index 8f08df2f4041..6c5ad5917052 100644 --- a/code/modules/mob/living/simple_animal/bot/atmosbot.dm +++ b/code/modules/mob/living/simple_animal/bot/atmosbot.dm @@ -136,7 +136,7 @@ return ATMOSBOT_CHECK_BREACH //Too little oxygen or too little pressure var/partial_pressure = R_IDEAL_GAS_EQUATION * gas_mix.return_temperature() / gas_mix.return_volume() - var/oxygen_moles = gas_mix.get_moles(/datum/gas/oxygen) * partial_pressure + var/oxygen_moles = gas_mix.get_moles(GAS_O2) * partial_pressure if(oxygen_moles < 20 || gas_mix.return_pressure() < WARNING_LOW_PRESSURE) return ATMOSBOT_LOW_OXYGEN diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index a6c8a8f93f74..bf7a61cc67bb 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -364,7 +364,7 @@ ejectpai(0) if(on) turn_off() - spawn(severity*300) + spawn(30 * severity) stat &= ~EMPED if(was_on) turn_on() diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index c1fd265adb0f..39cf352be45c 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -459,12 +459,10 @@ Auto Patrol[]"}, /mob/living/simple_animal/bot/ed209/emp_act(severity) - if(severity == 2 && prob(70)) - severity = 1 . = ..() if(. & EMP_PROTECT_SELF) return - if (severity >= 2) + if (severity > EMP_LIGHT || prob(70)) new /obj/effect/temp_visual/emp(loc) var/list/mob/living/carbon/targets = new for(var/mob/living/carbon/C in view(12,src)) diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index bbdc13985fc1..e5ab5179cd00 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -726,6 +726,11 @@ else return null +/mob/living/simple_animal/bot/mulebot/remove_air_ratio(ratio) + if(loc) + return loc.remove_air_ratio(ratio) + return null + /mob/living/simple_animal/bot/mulebot/resist() ..() if(load) diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 5334e54e44d1..8141a446f15d 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -112,7 +112,7 @@ /mob/living/simple_animal/hostile/construct/narsie_act() return -/mob/living/simple_animal/hostile/construct/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE, gib = FALSE) +/mob/living/simple_animal/hostile/construct/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, zone = null, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE, gib = FALSE) return 0 /mob/living/simple_animal/hostile/construct/adjustHealth(amount, updating_health = TRUE, forced = FALSE) diff --git a/code/modules/mob/living/simple_animal/eldritch_demons.dm b/code/modules/mob/living/simple_animal/eldritch_demons.dm index a8160ab84822..1bd51dd4308b 100644 --- a/code/modules/mob/living/simple_animal/eldritch_demons.dm +++ b/code/modules/mob/living/simple_animal/eldritch_demons.dm @@ -276,7 +276,7 @@ var/list/parts = list() for(var/X in C.bodyparts) var/obj/item/bodypart/bodypart = X - if(bodypart.body_part != HEAD && bodypart.body_part != CHEST && bodypart.body_part != LEG_LEFT && bodypart.body_part != LEG_RIGHT) + if(!(bodypart.body_part & HEAD|CHEST|LEG_LEFT|LEG_RIGHT)) if(bodypart.dismemberable) parts += bodypart if(length(parts) && prob(10)) diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm index fd63fa71afb3..3f28397fa82e 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm @@ -229,9 +229,9 @@ . = ..() if(. & EMP_PROTECT_SELF) return - Stun(100) + Stun(10 * severity) to_chat(src, span_danger("ER@%R: MME^RY CO#RU9T! R&$b@0tin)...")) - if(severity == 1) + if(severity > EMP_LIGHT) adjustBruteLoss(heavy_emp_damage) to_chat(src, span_userdanger("HeAV% DA%^MMA+G TO I/O CIR!%UUT!")) @@ -288,5 +288,5 @@ // Why would bees pay attention to drones? return 1 -/mob/living/simple_animal/drone/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE, gib = FALSE) +/mob/living/simple_animal/drone/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, zone = null, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE, gib = FALSE) return 0 //So they don't die trying to fix wiring diff --git a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm index da68ff11f309..6aa83963a038 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm @@ -55,7 +55,7 @@ /obj/guardian_bomb/proc/disguise(obj/A) A.forceMove(src) stored_obj = A - opacity = A.opacity + set_opacity(A.opacity) anchored = A.anchored density = A.density appearance = A.appearance diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm index bb7ed9200a63..d0eaedc4ca14 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm @@ -35,6 +35,7 @@ Difficulty: Extremely Hard var/projectile_speed_multiplier = 1 var/enraged = FALSE var/enraging = FALSE + internal_type = /obj/item/gps/internal/frostminer deathmessage = "falls to the ground, decaying into plasma particles." deathsound = "bodyfall" attack_action_types = list(/datum/action/innate/megafauna_attack/frost_orbs, @@ -338,3 +339,9 @@ Difficulty: Extremely Hard to_chat(owner, span_notice("The cube melts!")) owner.cut_overlay(cube) UnregisterSignal(owner, COMSIG_MOVABLE_PRE_MOVE) + +/obj/item/gps/internal/frostminer + icon_state = null + gpstag = "Hollow Signal" + desc = "What could possibly be sending out a GPS signal in these wastes?" + invisibility = 100 diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index abf942d702fb..adfcd9c49fb9 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -478,7 +478,7 @@ Difficulty: Medium icon = 'icons/effects/fire.dmi' icon_state = "1" anchored = TRUE - opacity = 0 + opacity = FALSE density = TRUE CanAtmosPass = ATMOS_PASS_DENSITY duration = 8.2 SECONDS diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm index d457ad0c2396..ef45124b5a1f 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm @@ -285,7 +285,7 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa else var/mob/living/L = target L.attack_animal(src) - L.electrocute_act(10, src, safety = TRUE) //safety = TRUE means we don't check gloves... Ok? + L.electrocute_act(10, src, zone = null) //zone=null means we don't only check gloves... Ok? return TRUE else return ..() diff --git a/code/modules/mob/living/simple_animal/hostile/regalrat.dm b/code/modules/mob/living/simple_animal/hostile/regalrat.dm index c117420b0f4d..8aee2da1ca0e 100644 --- a/code/modules/mob/living/simple_animal/hostile/regalrat.dm +++ b/code/modules/mob/living/simple_animal/hostile/regalrat.dm @@ -72,9 +72,9 @@ /mob/living/simple_animal/hostile/regalrat/handle_environment(datum/gas_mixture/environment) . = ..() - if(stat == DEAD || !environment || !environment.get_moles(/datum/gas/miasma)) + if(stat == DEAD || !environment || !environment.get_moles(GAS_MIASMA)) return - var/miasma_percentage = environment.get_moles(/datum/gas/miasma)/environment.total_moles() + var/miasma_percentage = environment.get_moles(GAS_MIASMA)/environment.total_moles() if(miasma_percentage>=0.25) heal_bodypart_damage(1) diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm index a96caddca1a5..09c283adafe2 100644 --- a/code/modules/mob/living/simple_animal/hostile/tree.dm +++ b/code/modules/mob/living/simple_animal/hostile/tree.dm @@ -46,12 +46,12 @@ if(isopenturf(loc)) var/turf/open/T = src.loc if(T.air) - var/co2 = T.air.get_moles(/datum/gas/carbon_dioxide) + var/co2 = T.air.get_moles(GAS_CO2) if(co2 > 0) if(prob(25)) var/amt = min(co2, 9) - T.air.adjust_moles(/datum/gas/carbon_dioxide, -amt) - T.atmos_spawn_air("o2=[amt]") + T.air.adjust_moles(GAS_CO2, -amt) + T.atmos_spawn_air("o2=[amt];TEMP=293.15") /mob/living/simple_animal/hostile/tree/AttackingTarget() . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm index 1ab5b77515ad..4ed3901312fe 100644 --- a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm +++ b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm @@ -14,7 +14,7 @@ icon = 'icons/effects/spacevines.dmi' icon_state = "flower_bud" layer = SPACEVINE_MOB_LAYER - opacity = 0 + opacity = FALSE canSmoothWith = list() smooth = SMOOTH_FALSE /// The amount of time it takes to create a venus human trap, in deciseconds diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index f8739d65a3d1..2294a6799169 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -227,10 +227,10 @@ var/turf/open/ST = src.loc if(ST.air) - var/tox = ST.air.get_moles(/datum/gas/plasma) - var/oxy = ST.air.get_moles(/datum/gas/oxygen) - var/n2 = ST.air.get_moles(/datum/gas/nitrogen) - var/co2 = ST.air.get_moles(/datum/gas/carbon_dioxide) + var/tox = ST.air.get_moles(GAS_PLASMA) + var/oxy = ST.air.get_moles(GAS_O2) + var/n2 = ST.air.get_moles(GAS_N2) + var/co2 = ST.air.get_moles(GAS_CO2) if(atmos_requirements["min_oxy"] && oxy < atmos_requirements["min_oxy"]) . = FALSE diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm index e6986611d0cd..51d9095a115f 100644 --- a/code/modules/mob/living/simple_animal/slime/life.dm +++ b/code/modules/mob/living/simple_animal/slime/life.dm @@ -134,7 +134,7 @@ Tempstun = 0 if(stat != DEAD) - var/bz_percentage = environment.total_moles() ? (environment.get_moles(/datum/gas/bz) / environment.total_moles()) : 0 + var/bz_percentage = environment.total_moles() ? (environment.get_moles(GAS_BZ) / environment.total_moles()) : 0 var/stasis = (bz_percentage >= 0.05 && bodytemperature < (T0C + 100)) || force_stasis if(stat == CONSCIOUS && stasis) diff --git a/code/modules/mob/living/ventcrawling.dm b/code/modules/mob/living/ventcrawling.dm index 33e5cc3d4d90..370d71ff8850 100644 --- a/code/modules/mob/living/ventcrawling.dm +++ b/code/modules/mob/living/ventcrawling.dm @@ -46,7 +46,7 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list( if(vent_found) var/datum/pipeline/vent_found_parent = vent_found.parents[1] - if(vent_found_parent && (vent_found_parent.members.len || vent_found_parent.other_atmosmch)) + if(vent_found_parent && (vent_found_parent.members.len || vent_found_parent.other_atmos_machines)) visible_message(span_notice("[src] begins climbing into the ventilation system...") ,span_notice("You begin climbing into the ventilation system...")) if(!do_after(src, 2.5 SECONDS, vent_found)) @@ -97,7 +97,7 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list( for(var/datum/pipeline/P in starting_machine.return_pipenets()) totalMembers += P.members - totalMembers += P.other_atmosmch + totalMembers += P.other_atmos_machines if(!totalMembers.len) return diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index c93719de7ff2..399aa3e7786d 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -176,7 +176,7 @@ t += span_danger("Temperature: [environment.return_temperature()] \n") for(var/id in environment.get_gases()) if(environment.get_moles(id)) - t+=span_notice("[GLOB.meta_gas_info[id][META_GAS_NAME]]: [environment.get_moles(id)] \n") + t+=span_notice("[GLOB.gas_data.names[id]]: [environment.get_moles(id)] \n") to_chat(usr, t) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 447b4b306f58..469261640cb2 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -221,4 +221,16 @@ var/list/alerts = list() // contains /atom/movable/screen/alert only // On /mob so clientless mobs will throw alerts properly + ///Contains the fullscreen overlays the mob can see (from 'code/_onclick/hud/fullscreen.dm') + var/list/screens = list() + + ///The HUD type the mob will gain on Initialize. (from 'code/_onclick/hud/hud.dm') + var/hud_type = /datum/hud + + ///The client colors the mob is looking at. (from 'code/modules/client/client_color.dm') + var/list/client_colours = list() + + ///What receives our keyboard inputs. src by default. (from 'code/modules/keybindings/focus.dm') + var/datum/focus + var/fake_client = FALSE // Currently only used for examines diff --git a/code/modules/modular_computers/computers/item/pda/pda_presets.dm b/code/modules/modular_computers/computers/item/pda/pda_presets.dm index 13bebc619a9f..d790eb77f63e 100644 --- a/code/modules/modular_computers/computers/item/pda/pda_presets.dm +++ b/code/modules/modular_computers/computers/item/pda/pda_presets.dm @@ -3,7 +3,9 @@ /obj/item/stock_parts/cell/computer/micro, /obj/item/computer_hardware/hard_drive/small/pda, /obj/item/computer_hardware/network_card, - /obj/item/computer_hardware/card_slot) + /obj/item/computer_hardware/card_slot, + /obj/item/computer_hardware/printer/mini + ) // This is literally the worst possible cheap tablet /obj/item/modular_computer/tablet/pda/preset/basic diff --git a/code/modules/modular_computers/file_system/programs/engineering/alarm.dm b/code/modules/modular_computers/file_system/programs/engineering/alarm.dm index c40942e6dccd..9357494f9e83 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/alarm.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/alarm.dm @@ -38,52 +38,6 @@ return data -/datum/computer_file/program/alarm_monitor/proc/triggerAlarm(class, area/A, O, obj/source) - if(is_station_level(source.z)) - if(!(A.type in GLOB.the_station_areas)) - return - else if(!is_mining_level(source.z) || istype(A, /area/ruin)) - return - - var/list/L = GLOB.alarms[class] - for(var/I in L) - if (I == A.name) - var/list/alarm = L[I] - var/list/sources = alarm[3] - if (!(source in sources)) - sources += source - return 1 - var/obj/machinery/camera/C = null - var/list/CL = null - if(O && istype(O, /list)) - CL = O - if (CL.len == 1) - C = CL[1] - else if(O && istype(O, /obj/machinery/camera)) - C = O - L[A.name] = list(A, (C ? C : O), list(source)) - - update_alarm_display() - - return 1 - - -/datum/computer_file/program/alarm_monitor/proc/cancelAlarm(class, area/A, obj/origin) - var/list/L = GLOB.alarms[class] - var/cleared = 0 - for (var/I in L) - if (I == A.name) - var/list/alarm = L[I] - var/list/srcs = alarm[3] - if (origin in srcs) - srcs -= origin - if (srcs.len == 0) - cleared = 1 - L -= I - - update_alarm_display() - return !cleared - /datum/computer_file/program/alarm_monitor/proc/update_alarm_display() has_alert = FALSE for(var/cat in GLOB.alarms) @@ -91,6 +45,10 @@ if(L.len) has_alert = TRUE +/datum/computer_file/program/alarm_monitor/New() + ..() + GLOB.alarmdisplay += src + /datum/computer_file/program/alarm_monitor/run_program(mob/user) . = ..(user) GLOB.alarmdisplay += src diff --git a/code/modules/modular_computers/file_system/programs/engineering/atmosscan.dm b/code/modules/modular_computers/file_system/programs/engineering/atmosscan.dm index eafb14402b45..983cc27f71b3 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/atmosscan.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/atmosscan.dm @@ -34,7 +34,7 @@ var/moles = environment.get_moles(id) var/gas_level = moles/total_moles if(gas_level > 0) - airlist += list(list("name" = "[GLOB.meta_gas_info[id][META_GAS_NAME]]", "percentage" = round(gas_level*100, 0.01))) + airlist += list(list("name" = GLOB.gas_data.labels[id], "ui_color" = GLOB.gas_data.ui_colors[id], "percentage" = round(gas_level*100, 0.01))) data["AirData"] = airlist else data["AirPressure"] = 0 diff --git a/code/modules/modular_computers/file_system/programs/engineering/sm_monitor.dm b/code/modules/modular_computers/file_system/programs/engineering/sm_monitor.dm index c4afd769d205..7157b82ee0c1 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/sm_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/sm_monitor.dm @@ -154,18 +154,21 @@ for(var/gasid in air.get_gases()) if(data_corrupted) gasdata.Add(list(list( - "name"= GLOB.meta_gas_info[gasid][META_GAS_NAME], - "amount" = round(rand()*100,0.01)))) + "name"= GLOB.gas_data.names[gasid], + "amount" = round(rand()*100,0.01), + "ui_color" = GLOB.gas_data.ui_colors[gasid]))) else gasdata.Add(list(list( - "name"= GLOB.meta_gas_info[gasid][META_GAS_NAME], - "amount" = round(100*air.get_moles(gasid)/air.total_moles(),0.01)))) + "name"= GLOB.gas_data.names[gasid], + "amount" = round(100*air.get_moles(gasid)/air.total_moles(),0.01), + "ui_color" = GLOB.gas_data.ui_colors[gasid]))) else for(var/gasid in air.get_gases()) gasdata.Add(list(list( - "name"= GLOB.meta_gas_info[gasid][META_GAS_NAME], - "amount" = 0))) + "name"= GLOB.gas_data.names[gasid], + "amount" = 0, + "ui_color" = GLOB.gas_data.ui_colors[gasid]))) data["gases"] = gasdata else diff --git a/code/modules/modular_computers/hardware/hard_drive.dm b/code/modules/modular_computers/hardware/hard_drive.dm index f1cb63c5d3dd..647627ddf7ab 100644 --- a/code/modules/modular_computers/hardware/hard_drive.dm +++ b/code/modules/modular_computers/hardware/hard_drive.dm @@ -221,6 +221,8 @@ ..() store_file(new/datum/computer_file/program/themeify(src)) store_file(new/datum/computer_file/program/pdamessager(src)) + store_file(new/datum/computer_file/program/budgetorders(src)) + store_file(new/datum/computer_file/program/bounty_board(src)) /// For tablets given to nuke ops /obj/item/computer_hardware/hard_drive/small/nukeops diff --git a/code/modules/ninja/energy_katana.dm b/code/modules/ninja/energy_katana.dm index 83d559175094..071c3aeafcd8 100644 --- a/code/modules/ninja/energy_katana.dm +++ b/code/modules/ninja/energy_katana.dm @@ -58,28 +58,13 @@ /obj/item/energy_katana/pickup(mob/living/carbon/human/user) . = ..() if(!is_ninja(user)) //stolen directly from the bloody bastard sword - if(HAS_TRAIT (user, TRAIT_SHOCKIMMUNE)) - to_chat(user, span_warning("[src] attempts to shock you.")) - user.electrocute_act(15,src) - return - if(user.gloves) - if(!user.gloves.siemens_coefficient) - to_chat(user, span_warning("[src] attempts to shock you.")) - user.electrocute_act(15,src) - return - to_chat(user, span_userdanger("[src] shocks you!")) //duplicate code because wearing gloves did nothing beforehand - user.emote("scream") - user.electrocute_act(15,src) - user.dropItemToGround(src, TRUE) - user.Paralyze(50) - return - else + if(user.electrocute_act(15, src, 1, user.held_index_to_body_zone(user.active_hand_index))) // you tried to grab it with this hand, so we'll shock it to_chat(user, span_userdanger("[src] shocks you!")) user.emote("scream") - user.electrocute_act(15,src) user.dropItemToGround(src, TRUE) user.Paralyze(50) - return + else + to_chat(user, span_warning("[src] attempts to shock you.")) jaunt.Grant(user, src) user.update_icons() playsound(src, 'sound/items/unsheath.ogg', 25, 1) diff --git a/code/modules/ninja/suit/gloves.dm b/code/modules/ninja/suit/gloves.dm index 440e02125322..92b5b20b7ecb 100644 --- a/code/modules/ninja/suit/gloves.dm +++ b/code/modules/ninja/suit/gloves.dm @@ -25,7 +25,6 @@ name = "ninja gloves" icon_state = "s-ninja" item_state = "s-ninja" - siemens_coefficient = 0 cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS @@ -36,6 +35,7 @@ var/candrain = 0 var/mindrain = 200 var/maxdrain = 3200 + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 0, WOUND = 0, ELECTRIC = 100) /obj/item/clothing/gloves/space_ninja/Touch(atom/A,proximity) diff --git a/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm b/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm index 42a4a73d74af..aa44118c5123 100644 --- a/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm +++ b/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm @@ -10,7 +10,7 @@ It is possible to destroy the net by the occupant or someone else. icon_state = "energynet" density = TRUE//Can't pass through. - opacity = 0//Can see through. + opacity = FALSE//Can see through. mouse_opacity = MOUSE_OPACITY_ICON//So you can hit it with stuff. anchored = TRUE//Can't drag/grab the net. layer = ABOVE_ALL_MOB_LAYER diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_empulse.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_empulse.dm index 3d77ac911cbb..b14cf101e7ab 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_empulse.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_empulse.dm @@ -6,5 +6,5 @@ if(!ninjacost(250,N_STEALTH_CANCEL)) var/mob/living/carbon/human/H = affecting playsound(H.loc, 'sound/effects/empulse.ogg', 60, 2) - empulse(H, 4, 6) //Procs sure are nice. Slightly weaker than wizard's disable tch. + empulse(H, EMP_HEAVY, 6) //Procs sure are nice. Slightly weaker than wizard's disable tch. s_coold = 4 diff --git a/code/modules/pai/actions.dm b/code/modules/pai/actions.dm deleted file mode 100644 index 99f312dc917c..000000000000 --- a/code/modules/pai/actions.dm +++ /dev/null @@ -1,62 +0,0 @@ -/datum/action/innate/pai - name = "PAI Action" - background_icon = 'icons/mob/actions/actions_silicon.dmi' - var/mob/living/silicon/pai/pai_owner - -/datum/action/innate/pai/Trigger(trigger_flags) - if(!ispAI(owner)) - return FALSE - pai_owner = owner - -/datum/action/innate/pai/software - name = "Software Interface" - button_icon_state = "pai" - background_icon_state = "bg_tech" - -/datum/action/innate/pai/software/Trigger(trigger_flags) - ..() - pai_owner.ui_act() - -/datum/action/innate/pai/shell - name = "Toggle Holoform" - button_icon_state = "pai_holoform" - background_icon_state = "bg_tech" - -/datum/action/innate/pai/shell/Trigger(trigger_flags) - ..() - if(pai_owner.holoform) - pai_owner.fold_in(0) - else - pai_owner.fold_out() - -/datum/action/innate/pai/chassis - name = "Holochassis Appearance Composite" - button_icon_state = "pai_chassis" - background_icon_state = "bg_tech" - -/datum/action/innate/pai/chassis/Trigger(trigger_flags) - ..() - pai_owner.choose_chassis() - -/datum/action/innate/pai/rest - name = "Rest" - button_icon_state = "pai_rest" - background_icon_state = "bg_tech" - -/datum/action/innate/pai/rest/Trigger(trigger_flags) - ..() - var/mob/living/silicon/pai/pAI = usr - if(!pAI.resting) - pAI.set_resting(TRUE) - else - pAI.set_resting(FALSE) - -/datum/action/innate/pai/light - name = "Toggle Integrated Lights" - background_icon = 'icons/mob/actions/actions_spells.dmi' - button_icon_state = "emp" - background_icon_state = "bg_tech" - -/datum/action/innate/pai/light/Trigger(trigger_flags) - ..() - pai_owner.toggle_integrated_light() diff --git a/code/modules/pai/camera.dm b/code/modules/pai/camera.dm deleted file mode 100644 index 30b1918651e4..000000000000 --- a/code/modules/pai/camera.dm +++ /dev/null @@ -1,58 +0,0 @@ -/mob/living/silicon/pai/ClickOn(atom/target, params) - ..() - if(!camera?.in_camera_mode) - return FALSE - //pAI picture taking - camera.toggle_camera_mode(sound = FALSE) - camera.captureimage(target, usr, camera.picture_size_x - 1, camera.picture_size_y - 1) - return TRUE - -/obj/item/camera/siliconcam/pai_camera - name = "pAI photo camera" - light_color = COLOR_PAI_GREEN - -/obj/item/camera/siliconcam/pai_camera/after_picture(mob/user, datum/picture/picture) - var/number = length(stored) - picture.picture_name = "Image [number] (taken by [loc.name])" - stored[picture] = TRUE - playsound(loc, pick('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg'), 75, TRUE, -3) - balloon_alert(user, "image recorded") - -/** - * Handles selecting and printing stored images. - * - * @param {mob} user - The pAI. - * - * @returns {boolean} - TRUE if the pAI prints an image, - * FALSE otherwise. -*/ -/obj/item/camera/siliconcam/pai_camera/proc/pai_print(mob/user) - var/mob/living/silicon/pai/pai = loc - var/datum/picture/selection = selectpicture(user) - if(!istype(selection)) - balloon_alert(user, "invalid image") - return FALSE - printpicture(user, selection) - user.visible_message(span_notice("A picture appears on top of the chassis of [pai.name]!"), span_notice("You print a photograph.")) - return TRUE - -/** - * All inclusive camera proc. Zooms, snaps, prints. - * - * @param {mob} user - The pAI requesting the camera. - * - * @param {string} mode - The camera option to toggle. - * - * @returns {boolean} - TRUE if the camera worked. - */ -/mob/living/silicon/pai/proc/use_camera(mob/user, mode) - if(!camera || isnull(mode)) - return FALSE - switch(mode) - if(PAI_PHOTO_MODE_CAMERA) - camera.toggle_camera_mode(user) - if(PAI_PHOTO_MODE_PRINTER) - camera.pai_print(user) - if(PAI_PHOTO_MODE_ZOOM) - camera.adjust_zoom(user) - return TRUE diff --git a/code/modules/pai/candidate.dm b/code/modules/pai/candidate.dm deleted file mode 100644 index 6455492e1379..000000000000 --- a/code/modules/pai/candidate.dm +++ /dev/null @@ -1,35 +0,0 @@ -/** - * #pAI Candidate - * - * Created when a user opens the pAI submit interface. - * Stores the candidate in an associative list of ckey: candidate objects. - */ -/datum/pai_candidate - /// User inputted OOC comments - var/comments - /// User inputted behavior description - var/description - /// User's ckey - var/ckey - /// User's pAI name. If blank, ninja name. - var/name - /// If the user has hit "submit" - var/ready = FALSE - -/datum/pai_candidate/New(ckey) - src.ckey = ckey - -/** - * Checks if a candidate is ready so that they may be displayed or - * downloaded. Removes any invalid entries. - * - * @returns {boolean} - TRUE if the candidate is ready, FALSE if not - */ -/datum/pai_candidate/proc/check_ready() - var/mob/candidate_mob = get_mob_by_key(ckey) - if(!candidate_mob?.client || !isobserver(candidate_mob) || is_banned_from(ckey, ROLE_PAI)) - SSpai.candidates -= ckey - return FALSE - if(!ready) - return FALSE - return TRUE diff --git a/code/modules/pai/card.dm b/code/modules/pai/card.dm deleted file mode 100644 index fc50e1a2c04b..000000000000 --- a/code/modules/pai/card.dm +++ /dev/null @@ -1,260 +0,0 @@ -/obj/item/pai_card - name = "personal AI device" - desc = "Downloads personal AI assistants to accompany its owner or others." - icon = 'icons/obj/aicards.dmi' - icon_state = "pai" - item_state = "electronic" - lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' - righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' - resistance_flags = FIRE_PROOF | ACID_PROOF | INDESTRUCTIBLE - w_class = WEIGHT_CLASS_SMALL - slot_flags = ITEM_SLOT_BELT - cryo_preserve = TRUE - /// Spam alert prevention - var/alert_cooldown - /// The emotion icon displayed. - var/emotion_icon = "off" - /// Any pAI personalities inserted - var/mob/living/silicon/pai/pai - /// Prevents a crew member from hitting "request pAI" repeatedly - var/request_spam = FALSE - -/obj/item/pai_card/attackby(obj/item/used, mob/user, params) - if(pai && istype(used, /obj/item/encryptionkey)) - if(!pai.encrypt_mod) - to_chat(user, span_alert("Encryption Key ports not configured.")) - return - user.set_machine(src) - pai.radio.attackby(used, user, params) - to_chat(user, span_notice("You insert [used] into the [src].")) - return - return ..() - -/obj/item/pai_card/attack_self(mob/user) - if(!in_range(src, user)) - return - user.set_machine(src) - ui_interact(user) - -/obj/item/pai_card/Destroy() - //Will stop people throwing friend pAIs into the singularity so they can respawn - SSpai.pai_card_list.Remove(src) - if(!QDELETED(pai)) - QDEL_NULL(pai) - return ..() - -/obj/item/pai_card/emag_act(mob/user, obj/item/card/emag/emag_card) - if(!pai) - return FALSE - return pai.handle_emag(user, emag_card) - -/obj/item/pai_card/emp_act(severity) - . = ..() - if (. & EMP_PROTECT_SELF) - return - if(pai && !pai.holoform) - pai.emp_act(severity) - -/obj/item/pai_card/handle_atom_del(atom/thing) - if(thing == pai) //double check /mob/living/silicon/pai/Destroy() if you change these. - pai = null - emotion_icon = initial(emotion_icon) - update_appearance(UPDATE_ICON) - return ..() - -/obj/item/pai_card/Initialize(mapload) - . = ..() - update_appearance(UPDATE_ICON) - SSpai.pai_card_list += src - -/obj/item/pai_card/suicide_act(mob/living/user) - user.visible_message(span_suicide("[user] is staring sadly at [src]! [user.p_they()] can't keep living without real human intimacy!")) - return OXYLOSS - -/obj/item/pai_card/update_overlays() - . = ..() - . += "pai-[emotion_icon]" - if(pai?.hacking_cable) - . += "[initial(icon_state)]-connector" - -/obj/item/pai_card/vv_edit_var(vname, vval) - . = ..() - if(vname == NAMEOF(src, emotion_icon)) - update_appearance(UPDATE_ICON) - -/obj/item/pai_card/ui_interact(mob/user, datum/tgui/ui) - . = ..() - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "PaiCard") - ui.open() - -/obj/item/pai_card/ui_status(mob/user) - if(user in get_nested_locs(src)) - return UI_INTERACTIVE - return ..() - -/obj/item/pai_card/ui_data(mob/user) - . = ..() - var/list/data = list() - if(!pai) - data["candidates"] = pool_candidates() || list() - return data - data["pai"] = list( - can_holo = pai.can_holo, - dna = pai.master_dna, - emagged = pai.emagged, - laws = pai.laws.supplied, - master = pai.master_name, - name = pai.name, - transmit = pai.can_transmit, - receive = pai.can_receive, - ) - return data - -/obj/item/pai_card/ui_act(action, list/params, datum/tgui/ui) - . = ..() - if(.) - return TRUE - // Actions that don't require a pAI - if(action == "download") - download_candidate(usr, params["ckey"]) - return TRUE - if(action == "request") - find_pai(usr) - return TRUE - // pAI specific actions. - if(!pai) - return FALSE - switch(action) - if("fix_speech") - pai.fix_speech() - return TRUE - if("reset_software") - pai.reset_software() - return TRUE - if("set_dna") - pai.set_dna(usr) - return TRUE - if("set_laws") - pai.set_laws(usr) - return TRUE - if("toggle_holo") - pai.toggle_holo() - return TRUE - if("toggle_radio") - pai.toggle_radio(params["option"]) - return TRUE - if("wipe_pai") - pai.wipe_pai(usr) - ui.close() - return TRUE - return FALSE - -/** Flashes the pai card screen */ -/obj/item/pai_card/proc/add_alert() - if(pai) - return - add_overlay( - list(mutable_appearance(icon, "[initial(icon_state)]-alert"), - mutable_appearance(icon, "[initial(icon_state)]-alert", src, alpha = src.alpha))) - -/** Removes any overlays */ -/obj/item/pai_card/proc/remove_alert() - if(pai) - return - cut_overlays() - -/** Alerts pAI cards that someone has submitted candidacy */ -/obj/item/pai_card/proc/alert_update() - if(!COOLDOWN_FINISHED(src, alert_cooldown)) - return - COOLDOWN_START(src, alert_cooldown, 5 SECONDS) - add_alert() - addtimer(CALLBACK(src, PROC_REF(remove_alert)), 5 SECONDS) - playsound(src, 'sound/machines/ping.ogg', 30, TRUE) - visible_message(span_notice("[src] flashes a message across its screen: New personalities available for download!"), blind_message = span_notice("[src] vibrates with an alert.")) - -/** - * Downloads a candidate from the list and removes them from SSpai.candidates - * - * @param {string} ckey The ckey of the candidate to download - * - * @returns {boolean} - TRUE if the candidate was downloaded, FALSE if not - */ -/obj/item/pai_card/proc/download_candidate(mob/user, ckey) - if(pai) - return FALSE - var/datum/pai_candidate/candidate = SSpai.candidates[ckey] - if(!candidate?.check_ready()) - balloon_alert(user, "download interrupted") - return FALSE - var/mob/living/silicon/pai/new_pai = new(src) - new_pai.name = candidate.name || pick(GLOB.ninja_names) - new_pai.real_name = new_pai.name - new_pai.key = candidate.ckey - set_personality(new_pai) - SSpai.candidates -= ckey - return TRUE - -/** - * Pings ghosts to announce that someone is requesting a pAI - * - * @param {mob} user - The user who is requesting a pAI - * - * @returns {boolean} - TRUE if the pAI was requested, FALSE if not - */ -/obj/item/pai_card/proc/find_pai(mob/user) - if(pai) - return FALSE - if(!(GLOB.ghost_role_flags & GHOSTROLE_SILICONS)) - balloon_alert(user, "unavailable: NT blacklisted") - return FALSE - if(request_spam) - balloon_alert(user, "request sent too recently") - return FALSE - request_spam = TRUE - playsound(src, 'sound/machines/ping.ogg', 20, TRUE) - balloon_alert(user, "pAI assistance requested") - var/mutable_appearance/alert_overlay = mutable_appearance('icons/obj/aicards.dmi', "pai") - notify_ghosts("[user] is requesting a pAI companion! Use the pAI button to submit yourself as one.", source = user, alert_overlay = alert_overlay, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "pAI Request!", ignore_key = POLL_IGNORE_PAI) - addtimer(VARSET_CALLBACK(src, request_spam, FALSE), PAI_SPAM_TIME, TIMER_UNIQUE | TIMER_STOPPABLE | TIMER_CLIENT_TIME | TIMER_DELETE_ME) - return TRUE - -/** - * Gathers a list of candidates to display in the download candidate - * window. If the candidate isn't marked ready, ie they have not - * pressed submit, they will be skipped over. - * - * @returns - An array of candidate objects. - */ -/obj/item/pai_card/proc/pool_candidates() - var/list/candidates = list() - if(pai || !length(SSpai?.candidates)) - return candidates - for(var/key in SSpai.candidates) - var/datum/pai_candidate/candidate = SSpai.candidates[key] - if(!candidate?.check_ready()) - continue - candidates += list(list( - ckey = candidate.ckey, - comments = candidate.comments, - description = candidate.description, - name = candidate.name, - )) - return candidates - -/** - * Sets the personality on the current pai_card - * - * @param {silicon/pai} downloaded - The new pAI to load into the card. - */ -/obj/item/pai_card/proc/set_personality(mob/living/silicon/pai/downloaded) - if(pai) - return FALSE - pai = downloaded - emotion_icon = "null" - update_appearance(UPDATE_ICON) - playsound(src, 'sound/effects/pai_boot.ogg', 50, TRUE, -1) - audible_message("[src] plays a cheerful startup noise!") - return TRUE diff --git a/code/modules/pai/death.dm b/code/modules/pai/death.dm deleted file mode 100644 index 2168f46796fb..000000000000 --- a/code/modules/pai/death.dm +++ /dev/null @@ -1,19 +0,0 @@ -/mob/living/silicon/pai/death(gibbed) - if(stat == DEAD) - return - set_stat(DEAD) - update_sight() - clear_fullscreens() - /** - * New pAI's get a brand new mind to prevent meta stuff from their previous - * life. This new mind causes problems down the line if it's not deleted here. - */ - ghostize() - - if (!QDELETED(card) && loc != card) - card.forceMove(drop_location()) - card.pai = null - card.emotion_icon = initial(card.emotion_icon) - card.update_appearance(UPDATE_ICON) - - qdel(src) diff --git a/code/modules/pai/debug.dm b/code/modules/pai/debug.dm deleted file mode 100644 index 63d6a8eb5020..000000000000 --- a/code/modules/pai/debug.dm +++ /dev/null @@ -1,45 +0,0 @@ -/client/proc/makepAI(turf/target in GLOB.mob_list) - set category = "Admin.Fun" - set name = "Make pAI" - set desc = "Specify a location to spawn a pAI device, then specify a key to play that pAI" - - var/list/available = list() - for(var/mob/player as anything in GLOB.player_list) - if(player.client && player.key) - available.Add(player) - var/mob/choice = tgui_input_list(usr, "Choose a player to play the pAI", "Spawn pAI", available) - if(isnull(choice)) - return - - var/chosen_name = input(choice, "Enter your pAI name:", "pAI Name", "Personal AI") as text|null - if (isnull(chosen_name)) - return - - if(!isobserver(choice)) - var/confirm = tgui_alert(usr, "[choice.key] isn't ghosting right now. Are you sure you want to yank them out of their body and place them in this pAI?", "Spawn pAI Confirmation", list("Yes", "No")) - if(confirm != "Yes") - return - var/obj/item/pai_card/card = new(target) - var/mob/living/silicon/pai/pai = new(card) - - pai.name = chosen_name - pai.real_name = pai.name - pai.key = choice.key - card.set_personality(pai) - if(SSpai.candidates[key]) - SSpai.candidates -= key - SSblackbox.record_feedback("tally", "admin_verb", 1, "Make pAI") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/** - * Creates a new pAI. - * - * @param {boolean} delete_old - If TRUE, deletes the old pAI. - */ -/mob/proc/make_pai(delete_old) - var/obj/item/pai_card/card = new(src) - var/mob/living/silicon/pai/pai = new(card) - pai.key = key - pai.name = name - card.set_personality(pai) - if(delete_old) - qdel(src) diff --git a/code/modules/pai/defense.dm b/code/modules/pai/defense.dm deleted file mode 100644 index cfe1211778ed..000000000000 --- a/code/modules/pai/defense.dm +++ /dev/null @@ -1,90 +0,0 @@ -/mob/living/silicon/pai/blob_act(obj/structure/blob/B) - return FALSE - -/mob/living/silicon/pai/emp_act(severity) - . = ..() - if(. & EMP_PROTECT_SELF) - return - take_holo_damage(50 / severity) - Stun(40 SECONDS / severity) - if(holoform) - fold_in(force = TRUE) - //Need more effects that aren't instadeath or permanent law corruption. - //Ask and you shall receive - switch(rand(1, 3)) - if(1) - stuttering = 1 MINUTES / severity - to_chat(src, span_danger("Warning: Feedback loop detected in speech module.")) - if(2) - slurring = INFINITY - to_chat(src, span_danger("Warning: Audio synthesizer CPU stuck.")) - if(3) - derpspeech = INFINITY - to_chat(src, span_danger("Warning: Vocabulary databank corrupted.")) - if(prob(40)) - mind.language_holder.selected_language = get_random_spoken_language() - - -/mob/living/silicon/pai/ex_act(severity, target) - take_holo_damage(50 * severity) - switch(severity) - if(EXPLODE_DEVASTATE) //RIP - qdel(card) - qdel(src) - if(EXPLODE_HEAVY) - fold_in(force = 1) - Paralyze(400) - if(EXPLODE_LIGHT) - fold_in(force = 1) - Paralyze(200) - -/mob/living/silicon/pai/attack_hand(mob/living/carbon/human/user, list/modifiers) - if(user.a_intent == INTENT_HELP) - visible_message(span_notice("[user] gently pats [src] on the head, eliciting an off-putting buzzing from its holographic field.")) - return - user.do_attack_animation(src) - if(user.name != master_name) - visible_message(span_danger("[user] stomps on [src]!.")) - take_holo_damage(2) - return - visible_message(span_notice("Responding to its master's touch, [src] disengages its holochassis emitter, rapidly losing coherence.")) - if(!do_after(user, 1 SECONDS, src)) - return - fold_in() - if(user.put_in_hands(card)) - user.visible_message(span_notice("[user] promptly scoops up [user.p_their()] pAI's card.")) - -/mob/living/silicon/pai/bullet_act(obj/projectile/Proj) - if(Proj.stun) - fold_in(force = TRUE) - src.visible_message(span_warning("The electrically-charged projectile disrupts [src]'s holomatrix, forcing [src] to fold in!")) - . = ..(Proj) - -/mob/living/silicon/pai/ignite_mob(silent) - return FALSE - -/mob/living/silicon/pai/proc/take_holo_damage(amount) - holochassis_health = clamp((holochassis_health - amount), -50, HOLOCHASSIS_MAX_HEALTH) - if(holochassis_health < 0) - fold_in(force = TRUE) - if(amount > 0) - to_chat(src, span_userdanger("The impact degrades your holochassis!")) - return amount - -/mob/living/silicon/pai/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, required_status) - return take_holo_damage(amount) - -/mob/living/silicon/pai/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, required_status) - return take_holo_damage(amount) - -/mob/living/silicon/pai/adjustStaminaLoss(amount, updating_stamina, forced = FALSE, required_status) - if(forced) - take_holo_damage(amount) - else - take_holo_damage(amount * 0.25) - -/mob/living/silicon/pai/getBruteLoss() - return HOLOCHASSIS_MAX_HEALTH - holochassis_health - -/mob/living/silicon/pai/getFireLoss() - return HOLOCHASSIS_MAX_HEALTH - holochassis_health diff --git a/code/modules/pai/door_jack.dm b/code/modules/pai/door_jack.dm deleted file mode 100644 index 75cf0fe9b442..000000000000 --- a/code/modules/pai/door_jack.dm +++ /dev/null @@ -1,129 +0,0 @@ -#define CABLE_LENGTH 2 - -/** - * Switch that handles door jack operations. - * - * @param {string} mode - The requested operation of the door jack. - * - * @returns {boolean} - TRUE if the door jack state was switched, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/door_jack(mode) - if(isnull(mode)) - return FALSE - switch(mode) - if(PAI_DOOR_JACK_CABLE) - extend_cable() - return TRUE - if(PAI_DOOR_JACK_HACK) - hack_door() - return TRUE - if(PAI_DOOR_JACK_CANCEL) - QDEL_NULL(hacking_cable) - visible_message(span_notice("The cable retracts into the pAI.")) - return TRUE - return FALSE - -/** - * #Extend cable supporting proc - * - * When doorjack is installed, allows the pAI to drop - * a cable which is placed either on the floor or in - * someone's hands based (on distance). - * - * @returns {boolean} - TRUE if the cable was dropped, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/extend_cable() - QDEL_NULL(hacking_cable) //clear any old cables - hacking_cable = new - var/mob/living/carbon/hacker = get_holder() - if(iscarbon(hacker) && hacker.put_in_hands(hacking_cable)) //important to double check since get_holder can return non-null values that aren't carbons. - hacker.visible_message(span_notice("A port on [src] opens to reveal a cable, which [hacker] quickly grabs."), span_notice("A port on [src] opens to reveal a cable, which you quickly grab."), span_hear("You hear the soft click of a plastic component and manage to catch the falling cable.")) - track_pai() - track_thing(hacking_cable) - return TRUE - hacking_cable.forceMove(drop_location()) - hacking_cable.visible_message(message = span_notice("A port on [src] opens to reveal a cable, which promptly falls to the floor."), blind_message = span_hear("You hear the soft click of a plastic component fall to the ground.")) - track_pai() - track_thing(hacking_cable) - return TRUE - -/** Tracks the associated pai */ -/mob/living/silicon/pai/proc/track_pai() - RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(handle_move)) - RegisterSignal(card, COMSIG_MOVABLE_MOVED, PROC_REF(handle_move)) - -/** Untracks the associated pai */ -/mob/living/silicon/pai/proc/untrack_pai() - UnregisterSignal(src, COMSIG_MOVABLE_MOVED) - UnregisterSignal(card, COMSIG_MOVABLE_MOVED) - -/** Tracks the associated hacking_cable */ -/mob/living/silicon/pai/proc/track_thing(atom/movable/thing) - RegisterSignal(thing, COMSIG_MOVABLE_MOVED, PROC_REF(handle_move)) - var/list/locations = get_nested_locs(thing, include_turf = FALSE) - for(var/atom/movable/location in locations) - RegisterSignal(location, COMSIG_MOVABLE_MOVED, PROC_REF(handle_move)) - -/** Untracks the associated hacking */ -/mob/living/silicon/pai/proc/untrack_thing(atom/movable/thing) - UnregisterSignal(thing, COMSIG_MOVABLE_MOVED) - var/list/locations = get_nested_locs(thing, include_turf = FALSE) - for(var/atom/movable/location in locations) - UnregisterSignal(location, COMSIG_MOVABLE_MOVED) - -/** - * A periodic check to see if the source pAI is nearby. - * Deletes the extended cable if the source pAI is not nearby. - */ -/mob/living/silicon/pai/proc/handle_move(atom/movable/source, atom/movable/old_loc) - if(ismovable(old_loc)) - untrack_thing(old_loc) - if(hacking_cable && (!IN_GIVEN_RANGE(src, hacking_cable, CABLE_LENGTH))) - retract_cable() - return - if(ismovable(source.loc)) - track_thing(source.loc) - -/** - * Handles deleting the hacking cable and notifying the user. - */ -/mob/living/silicon/pai/proc/retract_cable() - balloon_alert(src, "cable retracted") - untrack_pai() - QDEL_NULL(hacking_cable) - return TRUE - -/** - * #Door jacking supporting proc - * - * After a 15 second timer, the door will crack open, - * provided they don't move out of the way. - * - * @returns {boolean} - TRUE if the door was jacked, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/hack_door() - if(!hacking_cable) - return FALSE - if(!hacking_cable.machine) - balloon_alert(src, "nothing connected") - return FALSE - playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, TRUE) - balloon_alert(src, "overriding...") - // Now begin hacking - if(!do_after(src, 15 SECONDS, hacking_cable.machine, timed_action_flags = NONE, progress = TRUE)) - balloon_alert(src, "failed! retracting...") - untrack_pai() - untrack_thing(hacking_cable) - QDEL_NULL(hacking_cable) - if(!QDELETED(card)) - card.update_appearance(UPDATE_ICON) - return FALSE - var/obj/machinery/door/door = hacking_cable.machine - balloon_alert(src, "success") - door.open() - untrack_pai() - untrack_thing(hacking_cable) - QDEL_NULL(hacking_cable) - return TRUE - -#undef CABLE_LENGTH diff --git a/code/modules/pai/hud.dm b/code/modules/pai/hud.dm deleted file mode 100644 index 3c53c96395a3..000000000000 --- a/code/modules/pai/hud.dm +++ /dev/null @@ -1,267 +0,0 @@ -#define PAI_MISSING_SOFTWARE_MESSAGE span_warning("You must download the required software to use this.") - -/atom/movable/screen/pai - icon = 'icons/mob/screen_pai.dmi' - var/required_software - -/atom/movable/screen/pai/Click() - if(isobserver(usr) || usr.incapacitated()) - return FALSE - var/mob/living/silicon/pai/user = usr - if(required_software && !user.installed_software.Find(required_software)) - to_chat(user, PAI_MISSING_SOFTWARE_MESSAGE) - return FALSE - return TRUE - -/atom/movable/screen/pai/software - name = "Software Interface" - icon_state = "pai" - -/atom/movable/screen/pai/software/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.ui_interact(pAI) - -/atom/movable/screen/pai/shell - name = "Toggle Holoform" - icon_state = "pai_holoform" - -/atom/movable/screen/pai/shell/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - if(pAI.holoform) - pAI.fold_in(0) - else - pAI.fold_out() - -/atom/movable/screen/pai/chassis - name = "Holochassis Appearance Composite" - icon_state = "pai_chassis" - -/atom/movable/screen/pai/chassis/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.choose_chassis() - -/atom/movable/screen/pai/rest - name = "Rest" - icon_state = "pai_rest" - -/atom/movable/screen/pai/rest/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - if(pAI.resting) - pAI.set_resting(FALSE) - else - pAI.set_resting(TRUE) - -/atom/movable/screen/pai/light - name = "Toggle Integrated Lights" - icon_state = "light" - -/atom/movable/screen/pai/light/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.toggle_integrated_light() - -/atom/movable/screen/pai/newscaster - name = "pAI Newscaster" - icon_state = "newscaster" - required_software = "Newscaster" - -/atom/movable/screen/pai/newscaster/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.newscaster.ui_interact(usr) - -/atom/movable/screen/pai/host_monitor - name = "Host Health Scan" - icon_state = "host_monitor" - required_software = "Host Scan" - -/atom/movable/screen/pai/host_monitor/Click(location, control, params) - . = ..() - if(!.) - return - var/mob/living/silicon/pai/pAI = usr - pAI.host_scan(PAI_SCAN_TARGET) - return TRUE - -/atom/movable/screen/pai/crew_manifest - name = "Crew Manifest" - icon_state = "manifest" - required_software = "Crew Manifest" - -/atom/movable/screen/pai/crew_manifest/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.ai_roster() - -/atom/movable/screen/pai/state_laws - name = "State Laws" - icon_state = "state_laws" - -/atom/movable/screen/pai/state_laws/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.checklaws() - -/atom/movable/screen/pai/modpc - name = "Messenger" - icon_state = "pda_send" - required_software = "Digital Messenger" - var/mob/living/silicon/pai/pAI - -/atom/movable/screen/pai/modpc/Click() - . = ..() - if(!.) // this works for some reason. - return - pAI.modularInterface?.interact(pAI) - -/atom/movable/screen/pai/internal_gps - name = "Internal GPS" - icon_state = "internal_gps" - required_software = "Internal GPS" - -/atom/movable/screen/pai/internal_gps/Click() - . = ..() - if(!.) - return - var/mob/living/silicon/pai/pAI = usr - if(!pAI.internal_gps) - pAI.internal_gps = new(pAI) - pAI.internal_gps.attack_self(pAI) - -/atom/movable/screen/pai/image_take - name = "Take Image" - icon_state = "take_picture" - required_software = "Photography Module" - -/atom/movable/screen/pai/image_take/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.camera.toggle_camera_mode(usr) - -/atom/movable/screen/pai/image_view - name = "View Images" - icon_state = "view_images" - required_software = "Photography Module" - -/atom/movable/screen/pai/image_view/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.camera.viewpictures(usr) - -/atom/movable/screen/pai/radio - name = "radio" - icon = 'icons/mob/screen_cyborg.dmi' - icon_state = "radio" - -/atom/movable/screen/pai/radio/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.radio.interact(usr) - -/datum/hud/pai/New(mob/living/silicon/pai/owner) - ..() - var/atom/movable/screen/using - var/mob/living/silicon/pai/mypai = mymob - -// Software menu - using = new /atom/movable/screen/pai/software(src) - using.screen_loc = ui_pai_software - static_inventory += using - -// Holoform - using = new /atom/movable/screen/pai/shell(src) - using.screen_loc = ui_pai_shell - static_inventory += using - -// Chassis Select Menu - using = new /atom/movable/screen/pai/chassis(src) - using.screen_loc = ui_pai_chassis - static_inventory += using - -// Rest - using = new /atom/movable/screen/pai/rest(src) - using.screen_loc = ui_pai_rest - static_inventory += using - -// Integrated Light - using = new /atom/movable/screen/pai/light(src) - using.screen_loc = ui_pai_light - static_inventory += using - -// Newscaster - using = new /atom/movable/screen/pai/newscaster(src) - using.screen_loc = ui_pai_newscaster - static_inventory += using - -// Language menu - using = new /atom/movable/screen/language_menu(src) - using.screen_loc = ui_pai_language_menu - static_inventory += using - -// Host Monitor - using = new /atom/movable/screen/pai/host_monitor(src) - using.screen_loc = ui_pai_host_monitor - static_inventory += using - -// Crew Manifest - using = new /atom/movable/screen/pai/crew_manifest(src) - using.screen_loc = ui_pai_crew_manifest - static_inventory += using - -// Laws - using = new /atom/movable/screen/pai/state_laws(src) - using.screen_loc = ui_pai_state_laws - static_inventory += using - -// Modular Interface - using = new /atom/movable/screen/pai/modpc(src) - using.screen_loc = ui_pai_mod_int - static_inventory += using - mypai.pda_button = using - var/atom/movable/screen/pai/modpc/tablet_button = using - tablet_button.pAI = mypai - -// Internal GPS - using = new /atom/movable/screen/pai/internal_gps(src) - using.screen_loc = ui_pai_internal_gps - static_inventory += using - -// Take image - using = new /atom/movable/screen/pai/image_take(src) - using.screen_loc = ui_pai_take_picture - static_inventory += using - -// View images - using = new /atom/movable/screen/pai/image_view(src) - using.screen_loc = ui_pai_view_images - static_inventory += using - -// Radio - using = new /atom/movable/screen/pai/radio(src) - using.screen_loc = ui_pai_radio - static_inventory += using - - update_software_buttons() - -/datum/hud/pai/proc/update_software_buttons() - var/mob/living/silicon/pai/owner = mymob - for(var/atom/movable/screen/pai/button in static_inventory) - if(button.required_software) - button.color = owner.installed_software.Find(button.required_software) ? null : "#808080" - -#undef PAI_MISSING_SOFTWARE_MESSAGE diff --git a/code/modules/pai/login.dm b/code/modules/pai/login.dm deleted file mode 100644 index 0f418c4bf32b..000000000000 --- a/code/modules/pai/login.dm +++ /dev/null @@ -1,10 +0,0 @@ -/mob/living/silicon/pai/Login() - . = ..() - if(!. || !client) - return FALSE - - client.perspective = EYE_PERSPECTIVE - if(holoform) - client.eye = src - else - client.eye = card diff --git a/code/modules/pai/pai.dm b/code/modules/pai/pai.dm deleted file mode 100644 index 022802f46da2..000000000000 --- a/code/modules/pai/pai.dm +++ /dev/null @@ -1,412 +0,0 @@ -/mob/living/silicon/pai - can_be_held = TRUE - density = FALSE - desc = "A generic pAI hard-light holographics emitter." - health = 500 - held_lh = 'icons/mob/pai_item_lh.dmi' - held_rh = 'icons/mob/pai_item_rh.dmi' - held_icon = 'icons/mob/pai_item_head.dmi' - hud_type = /datum/hud/pai - icon = 'icons/mob/pai.dmi' - icon_state = "repairbot" - job = "Personal AI" - layer = BELOW_MOB_LAYER - light_color = COLOR_PAI_GREEN - light_flags = LIGHT_ATTACHED - light_on = FALSE - light_range = 3 - light_system = MOVABLE_LIGHT - maxHealth = 500 - mob_size = MOB_SIZE_TINY - mobility_flags = MOBILITY_FLAGS_DEFAULT - mouse_opacity = MOUSE_OPACITY_ICON - move_force = 0 - move_resist = 0 - name = "pAI" - pass_flags = PASSTABLE | PASSMOB - pull_force = 0 - radio = /obj/item/radio/headset/silicon/pai - worn_slot_flags = ITEM_SLOT_HEAD - - /// If someone has enabled/disabled the pAIs ability to holo - var/can_holo = TRUE - /// Whether this pAI can recieve radio messages - var/can_receive = TRUE - /// Whether this pAI can transmit radio messages - var/can_transmit = TRUE - /// The card we inhabit - var/obj/item/pai_card/card - /// The current chasis that will appear when in holoform - var/chassis = "repairbot" - /// Toggles whether the pAI can hold encryption keys or not - var/encrypt_mod = FALSE - /// The cable we produce when hacking a door - var/obj/item/pai_cable/hacking_cable - /// The current health of the holochassis - var/holochassis_health = 20 - /// Holochassis available to use - var/holochassis_ready = FALSE - /// Whether we are currently holoformed - var/holoform = FALSE - /// Installed software on the pAI - var/list/installed_software = list() - /// Toggles whether universal translator has been activated. Cannot be reversed - var/languages_granted = FALSE - /// Reference of the bound master - var/datum/weakref/master_ref - /// The master's name string - var/master_name - /// DNA string for owner verification - var/master_dna - /// Toggles whether the Medical HUD is active or not - var/medHUD = FALSE - /// Used as currency to purchase different abilities - var/ram = 100 - /// Toggles whether the Security HUD is active or not - var/secHUD = FALSE - - // Onboard Items - /// Atmospheric analyzer - var/obj/item/analyzer/atmos_analyzer - /// Health analyzer - var/obj/item/healthanalyzer/host_scan - /// GPS - var/obj/item/gps/internal/internal_gps - /// Music Synthesizer - var/obj/item/instrument/piano_synth/instrument - /// Newscaster - var/obj/machinery/newscaster/pai/newscaster - /// PDA - var/atom/movable/screen/ai/modpc/pda_button - /// Photography module - var/obj/item/camera/siliconcam/pai_camera/camera - /// Remote signaler - var/obj/item/assembly/signaler/internal/signaler - - // Static lists - /// List of all available downloads - var/static/list/available_software = list( - "Atmospheric Sensor" = 5, - "Crew Manifest" = 5, - "Digital Messenger" = 5, - "Photography Module" = 5, - "Encryption Slot" = 10, - "Music Synthesizer" = 10, - "Newscaster" = 10, - "Remote Signaler" = 10, - "Host Scan" = 20, - "Medical HUD" = 20, - "Security HUD" = 20, - "Crew Monitor" = 35, - "Door Jack" = 35, - "Internal GPS" = 35, - "Universal Translator" = 35, - ) - /// List of all possible chasises. TRUE means the pAI can be picked up in this chasis. - var/static/list/possible_chassis = list( - "cat" = TRUE, - "corgi" = FALSE, - "fox" = FALSE, - "monkey" = TRUE, - "mouse" = TRUE, - "rabbit" = TRUE, - ) - /// List of all available card overlays. - var/static/list/possible_overlays = list( - "null", - "angry", - "cat", - "extremely-happy", - "face", - "happy", - "laugh", - "off", - "sad", - "sunglasses", - "what" - ) - -/mob/living/silicon/pai/add_sensors() //pAIs have to buy their HUDs - return - -/mob/living/silicon/pai/can_interact_with(atom/target) - if(target == signaler) // Bypass for signaler - return TRUE - if(target == modularInterface) - return TRUE - return ..() - -/mob/living/silicon/pai/Destroy() - QDEL_NULL(atmos_analyzer) - QDEL_NULL(camera) - QDEL_NULL(hacking_cable) - QDEL_NULL(host_scan) - QDEL_NULL(instrument) - QDEL_NULL(internal_gps) - QDEL_NULL(newscaster) - QDEL_NULL(signaler) - card = null - GLOB.pai_list.Remove(src) - return ..() - -/mob/living/silicon/pai/emag_act(mob/user, obj/item/card/emag/emag_card) - return handle_emag(user, emag_card) - -/mob/living/silicon/pai/examine(mob/user) - . = ..() - . += "Its master ID string seems to be [(!master_name || emagged) ? "empty" : master_name]." - -/mob/living/silicon/pai/get_status_tab_items() - . += ..() - if(!stat) - . += text("Emitter Integrity: [holochassis_health * (100 / HOLOCHASSIS_MAX_HEALTH)].") - else - . += text("Systems nonfunctional.") - -/mob/living/silicon/pai/handle_atom_del(atom/deleting_atom) - if(deleting_atom == hacking_cable) - untrack_pai() - untrack_thing(hacking_cable) - hacking_cable = null - SStgui.update_user_uis(src) - if(!QDELETED(card)) - card.update_appearance(UPDATE_ICON) - if(deleting_atom == atmos_analyzer) - atmos_analyzer = null - if(deleting_atom == camera) - camera = null - if(deleting_atom == host_scan) - host_scan = null - if(deleting_atom == internal_gps) - internal_gps = null - if(deleting_atom == instrument) - instrument = null - if(deleting_atom == newscaster) - newscaster = null - if(deleting_atom == signaler) - signaler = null - return ..() - -/mob/living/silicon/pai/Initialize(mapload) - . = ..() - START_PROCESSING(SSfastprocess, src) - GLOB.pai_list += src - make_laws() - for(var/law in laws.inherent) - lawcheck += law - var/obj/item/pai_card/pai_card = loc - if(!istype(pai_card)) // when manually spawning a pai, we create a card to put it into. - var/newcardloc = pai_card - pai_card = new(newcardloc) - pai_card.set_personality(src) - forceMove(pai_card) - card = pai_card - addtimer(VARSET_CALLBACK(src, holochassis_ready, TRUE), HOLOCHASSIS_INIT_TIME) - if(!holoform) - Immobilize(50 MINUTES) - desc = "A pAI hard-light holographics emitter. This one appears in the form of a [chassis]." - - RegisterSignal(src, COMSIG_LIVING_CULT_SACRIFICED, PROC_REF(on_cult_sacrificed)) - -/mob/living/silicon/pai/make_laws() - laws = new /datum/ai_laws/pai() - return TRUE - -/mob/living/silicon/pai/process(delta_time) - holochassis_health = clamp((holochassis_health + (HOLOCHASSIS_REGEN_PER_SECOND * delta_time)), -50, HOLOCHASSIS_MAX_HEALTH) - -/mob/living/silicon/pai/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) - . = ..() - if(!.) - add_movespeed_modifier(MOVESPEED_ID_PAI_SPACEWALK, update = TRUE, priority = 100, multiplicative_slowdown = 2) - return TRUE - remove_movespeed_modifier(MOVESPEED_ID_PAI_SPACEWALK, TRUE) - return TRUE - -/mob/living/silicon/pai/screwdriver_act(mob/living/user, obj/item/tool) - return radio.screwdriver_act(user, tool) - -/mob/living/silicon/pai/updatehealth() - if(status_flags & GODMODE) - return - set_health(maxHealth - getBruteLoss() - getFireLoss()) - update_stat() - SEND_SIGNAL(src, COMSIG_LIVING_HEALTH_UPDATE) - -/** - * Resolves the weakref of the pai's master. - * If the master has been deleted, calls reset_software(). - * - * @returns {mob/living || FALSE} - The master mob, or - * FALSE if the master is gone. - */ -/mob/living/silicon/pai/proc/find_master() - if(!master_ref) - return FALSE - var/mob/living/resolved_master = master_ref?.resolve() - if(!resolved_master) - reset_software() - return FALSE - return resolved_master - -/** - * Fixes weird speech issues with the pai. - * - * @returns {boolean} - TRUE if successful. - */ -/mob/living/silicon/pai/proc/fix_speech() - var/mob/living/silicon/pai = src - balloon_alert(pai, "speech modulation corrected") - stuttering = 0 - slurring = 0 - derpspeech = 0 - - return TRUE - -/** - * Gets the current holder of the pAI if its - * being carried in card or holoform. - * - * @returns {living/carbon || FALSE} - The holder of the pAI, - * or FALSE if the pAI is not being carried. - */ -/mob/living/silicon/pai/proc/get_holder() - var/mob/living/carbon/holder - if(!holoform && iscarbon(card.loc)) - holder = card.loc - if(holoform && ispickedupmob(loc) && iscarbon(loc.loc)) - holder = loc.loc - if(!holder || !iscarbon(holder)) - return FALSE - return holder - -/** - * Handles the pai card or the pai itself being hit with an emag. - * This replaces any current laws, masters, and DNA. - * - * @param {living/carbon} attacker - The user performing the action. - * @returns {boolean} - TRUE if successful, FALSE if not. - */ -/mob/living/silicon/pai/proc/handle_emag(mob/living/carbon/attacker, obj/item/card/emag/emag_card) - if(!isliving(attacker)) - return FALSE - balloon_alert(attacker, "directive override complete") - balloon_alert(src, "directive override detected") - log_game("[key_name(attacker)] emagged [key_name(src)], wiping their master DNA and supplemental directive.") - emagged = TRUE - master_ref = WEAKREF(attacker) - master_name = "The Syndicate" - master_dna = "Untraceable Signature" - // Sets supplemental directive to this - laws.supplied[1] = "Do not interfere with the operations of the Syndicate." - return TRUE - -/** - * Resets the pAI and any emagged status. - * - * @returns {boolean} - TRUE if successful, FALSE if not. - */ -/mob/living/silicon/pai/proc/reset_software() - emagged = FALSE - if(!master_ref) - return FALSE - master_ref = null - master_name = null - master_dna = null - add_supplied_law(0, "None.") - balloon_alert(src, "software rebooted") - return TRUE - -/** - * Imprints your DNA onto the downloaded pAI - * - * @param {mob} user - The user performing the imprint. - * @returns {boolean} - TRUE if successful, FALSE if not. - */ -/mob/living/silicon/pai/proc/set_dna(mob/user) - if(!iscarbon(user)) - balloon_alert(user, "incompatible DNA signature") - balloon_alert(src, "incompatible DNA signature") - return FALSE - if(emagged) - balloon_alert(user, "directive system malfunctional") - return FALSE - var/mob/living/carbon/master = user - master_ref = WEAKREF(master) - master_name = master.real_name - master_dna = master.dna.unique_enzymes - to_chat(src, span_boldannounce("You have been bound to a new master: [user.real_name]!")) - holochassis_ready = TRUE - return TRUE - -/** - * Opens a tgui alert that allows someone to enter laws. - * - * @param {mob} user - The user performing the law change. - * @returns {boolean} - TRUE if successful, FALSE if not. - */ -/mob/living/silicon/pai/proc/set_laws(mob/user) - if(!master_ref) - balloon_alert(user, "access denied: no master") - return FALSE - var/new_laws = tgui_input_text(user, "Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", laws.supplied[1], 300) - if(!new_laws || !master_ref) - return FALSE - add_supplied_law(0, new_laws) - to_chat(src, span_notice(new_laws)) - return TRUE - -/** - * Toggles the ability of the pai to enter holoform - * - * @returns {boolean} - TRUE if successful, FALSE if not. - */ -/mob/living/silicon/pai/proc/toggle_holo() - balloon_alert(src, "holomatrix [can_holo ? "disabled" : "enabled"]") - can_holo = !can_holo - return TRUE - -/** - * Toggles the radio settings on and off. - * - * @param {string} option - The option being toggled. - */ -/mob/living/silicon/pai/proc/toggle_radio(option) - // it can't be both so if we know it's not transmitting it must be receiving. - var/transmitting = option == "transmit" - var/transmit_holder = (transmitting ? WIRE_TX : WIRE_RX) - if(transmitting) - can_transmit = !can_transmit - else //receiving - can_receive = !can_receive - radio.wires.cut(transmit_holder)//wires.cut toggles cut and uncut states - transmit_holder = (transmitting ? can_transmit : can_receive) //recycling can be fun! - balloon_alert(src, "[transmitting ? "outgoing" : "incoming"] radio [transmit_holder ? "enabled" : "disabled"]") - return TRUE - -/** - * Wipes the current pAI on the card. - * - * @param {mob} user - The user performing the action. - * - * @returns {boolean} - TRUE if successful, FALSE if not. - */ -/mob/living/silicon/pai/proc/wipe_pai(mob/user) - if(tgui_alert(user, "Are you certain you wish to delete the current personality? This action cannot be undone.", "Personality Wipe", list("Yes", "No")) != "Yes") - return FALSE - to_chat(src, span_warning("You feel yourself slipping away from reality.")) - to_chat(src, span_danger("Byte by byte you lose your sense of self.")) - to_chat(src, span_userdanger("Your mental faculties leave you.")) - to_chat(src, span_rose("oblivion... ")) - balloon_alert(user, "personality wiped") - playsound(src, "sound/machines/buzz-two.ogg", 30, TRUE) - qdel(src) - return TRUE - -/// Signal proc for [COMSIG_LIVING_CULT_SACRIFICED] to give a funny message when a pai is attempted to be sac'd -/mob/living/silicon/pai/proc/on_cult_sacrificed(datum/source, list/invokers) - SIGNAL_HANDLER - - for(var/mob/living/cultist as anything in invokers) - to_chat(cultist, span_cultitalic("You don't think this is what Nar'Sie had in mind when She asked for blood sacrifices...")) - return STOP_SACRIFICE diff --git a/code/modules/pai/personality.dm b/code/modules/pai/personality.dm deleted file mode 100644 index 92cf5747801f..000000000000 --- a/code/modules/pai/personality.dm +++ /dev/null @@ -1,56 +0,0 @@ -/** - * name - * key - * description - * role - * comments - * ready = TRUE - */ - -/datum/pai_candidate/proc/savefile_path(mob/user) - return "data/player_saves/[user.ckey[1]]/[user.ckey]/pai.sav" - -/datum/pai_candidate/proc/savefile_save(mob/user) - if(is_guest_key(user.key)) - to_chat(usr, span_warning("You cannot save pAI information as a guest.")) - return FALSE - var/savefile/F = new /savefile(src.savefile_path(user)) - WRITE_FILE(F["name"], name) - WRITE_FILE(F["description"], description) - WRITE_FILE(F["comments"], comments) - WRITE_FILE(F["version"], 1) - to_chat(usr, span_boldnotice("You have saved pAI information locally.")) - return TRUE - -// loads the savefile corresponding to the mob's ckey -// if silent=true, report incompatible savefiles -// returns TRUE if loaded (or file was incompatible) -// returns FALSE if savefile did not exist - -/datum/pai_candidate/proc/savefile_load(mob/user, silent = TRUE) - if (is_guest_key(user.key)) - return FALSE - - var/path = savefile_path(user) - - if (!fexists(path)) - return FALSE - - var/savefile/F = new /savefile(path) - - if(!F) - return //Not everyone has a pai savefile. - - var/version = null - F["version"] >> version - - if (isnull(version) || version != 1) - fdel(path) - if (!silent) - tgui_alert(user, "Your savefile was incompatible with this version and was deleted.") - return FALSE - - F["name"] >> src.name - F["description"] >> src.description - F["comments"] >> src.comments - return TRUE diff --git a/code/modules/pai/say.dm b/code/modules/pai/say.dm deleted file mode 100644 index b35abfe7f9d8..000000000000 --- a/code/modules/pai/say.dm +++ /dev/null @@ -1,2 +0,0 @@ -/mob/living/silicon/pai/binarycheck() - return radio?.translate_binary diff --git a/code/modules/pai/shell.dm b/code/modules/pai/shell.dm deleted file mode 100644 index 66e2e8bfb279..000000000000 --- a/code/modules/pai/shell.dm +++ /dev/null @@ -1,169 +0,0 @@ -/mob/living/silicon/pai/mob_try_pickup(mob/living/user, instant=FALSE) - if(!possible_chassis[chassis]) - to_chat(user, span_warning("[src]'s current form isn't able to be carried!")) - return FALSE - return ..() - -/mob/living/silicon/pai/start_pulling(atom/movable/thing, state, force = move_force, supress_message = FALSE) - return FALSE - -/mob/living/silicon/pai/update_resting() - . = ..() - if(resting) - icon_state = "[chassis]_rest" - else - icon_state = "[chassis]" - if(loc != card) - visible_message(span_notice("[src] [resting? "lays down for a moment..." : "perks up from the ground."]")) - -/mob/living/silicon/pai/wabbajack_act(what_to_randomize, change_flags = WABBAJACK) - if(length(possible_chassis) < 2) - return FALSE - var/holochassis = pick(possible_chassis - chassis) - set_holochassis(holochassis) - balloon_alert(src, "[holochassis] composite engaged") - return TRUE - -/** - * Checks if we are allowed to interact with a radial menu - * - * @param {atom} anchor - The atom that is anchoring the menu. - * - * @returns {boolean} - TRUE if we are allowed to interact with the menu, - * FALSE otherwise. - */ -/mob/living/silicon/pai/proc/check_menu(atom/anchor) - if(incapacitated()) - return FALSE - if(get_turf(src) != get_turf(anchor)) - return FALSE - if(!isturf(loc) && loc != card) - balloon_alert(src, "can't do that here") - return FALSE - return TRUE - -/** - * Sets a new holochassis skin based on a pAI's choice. - * - * @returns {boolean} - True if the skin was successfully set. - * FALSE otherwise. - */ -/mob/living/silicon/pai/proc/choose_chassis() - var/list/skins = list() - for(var/holochassis_option in possible_chassis) - var/image/item_image = image(icon = src.icon, icon_state = holochassis_option) - skins += list("[holochassis_option]" = item_image) - var/atom/anchor = get_atom_on_turf(src) - var/choice = show_radial_menu(src, anchor, skins, custom_check = CALLBACK(src, PROC_REF(check_menu), anchor), radius = 40, require_near = TRUE) - if(!choice) - return FALSE - set_holochassis(choice) - balloon_alert(src, "[choice] composite engaged") - update_resting() - return TRUE - -/** - * Returns the pAI to card mode. - * - * @param {boolean} force - If TRUE, the pAI will be forced to card mode. - * - * @returns {boolean} - TRUE if the pAI was forced to card mode. - * FALSE otherwise. - */ -/mob/living/silicon/pai/proc/fold_in(force = FALSE) - holochassis_ready = FALSE - if(!force) - addtimer(VARSET_CALLBACK(src, holochassis_ready, TRUE), HOLOCHASSIS_COOLDOWN) - else - addtimer(VARSET_CALLBACK(src, holochassis_ready, TRUE), HOLOCHASSIS_OVERLOAD_COOLDOWN) - icon_state = "[chassis]" - if(!holoform) - . = fold_out(force) - return FALSE - visible_message(span_notice("[src] deactivates its holochassis emitter and folds back into a compact card!")) - stop_pulling() - if(ispickedupmob(loc)) - var/obj/item/clothing/mob_holder/mob_head = loc - mob_head.release(display_messages = FALSE) - if(client) - client.perspective = EYE_PERSPECTIVE - var/turf/target = drop_location() - card.forceMove(target) - forceMove(card) - Immobilize(30 MINUTES) - set_density(FALSE) - set_light_on(FALSE) - holoform = FALSE - set_resting(resting) - return TRUE - -/** - * Engage holochassis form. - * - * @param {boolean} force - Force the form to engage. - * - * @returns {boolean} - TRUE if the form was successfully engaged. - * FALSE otherwise. - */ -/mob/living/silicon/pai/proc/fold_out(force = FALSE) - if(holochassis_health < 0) - balloon_alert(src, "emitter repair incomplete") - return FALSE - if(!can_holo && !force) - balloon_alert(src, "emitters are disabled") - return FALSE - if(holoform) - . = fold_in(force) - return - if(!holochassis_ready) - balloon_alert(src, "emitters recycling...") - return FALSE - holochassis_ready = FALSE - addtimer(VARSET_CALLBACK(src, holochassis_ready, TRUE), HOLOCHASSIS_COOLDOWN) - SetImmobilized(0) - set_density(TRUE) - if(istype(card.loc, /obj/item/modular_computer)) - var/obj/item/modular_computer/pc = card.loc - pc.inserted_pai = null - pc.visible_message(span_notice("[src] ejects itself from [pc]!")) - if(isliving(card.loc)) - var/mob/living/living_holder = card.loc - if(!living_holder.temporarilyRemoveItemFromInventory(card)) - balloon_alert(src, "unable to expand") - return FALSE - forceMove(get_turf(card)) - card.forceMove(src) - if(client) - client.perspective = EYE_PERSPECTIVE - client.eye = src - set_light_on(FALSE) - icon_state = "[chassis]" - held_state = "[chassis]" - visible_message(span_boldnotice("[src] folds out its holochassis emitter and forms a holoshell around itself!")) - holoform = TRUE - return TRUE - -/** - * Sets the holochassis skin and updates the icons - * - * @param {string} choice - The skin that will be used for the pAI holoform - * - * @returns {boolean} - TRUE if the skin was successfully set. FALSE otherwise. - */ -/mob/living/silicon/pai/proc/set_holochassis(choice) - if(!choice) - return FALSE - chassis = choice - icon_state = "[chassis]" - held_state = "[chassis]" - desc = "A pAI mobile hard-light holographics emitter. This one appears in the form of a [chassis]." - return TRUE - -/** - * Toggles the onboard light - * - * @returns {boolean} - TRUE if the light was toggled. - */ -/mob/living/silicon/pai/proc/toggle_integrated_light() - set_light_on(!light_on) - return TRUE diff --git a/code/modules/pai/software.dm b/code/modules/pai/software.dm deleted file mode 100644 index 9fb5cf109e78..000000000000 --- a/code/modules/pai/software.dm +++ /dev/null @@ -1,242 +0,0 @@ -/mob/living/silicon/pai/ui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "PaiInterface", name) - ui.open() - ui.set_autoupdate(FALSE) - -/mob/living/silicon/pai/ui_data(mob/user) - var/list/data = list() - data["door_jack"] = hacking_cable - data["image"] = card.emotion_icon - data["installed"] = installed_software - data["ram"] = ram - return data - -/mob/living/silicon/pai/ui_static_data(mob/user) - var/list/data = list() - data["available"] = available_software - data["directives"] = laws.supplied - data["emagged"] = emagged - data["languages"] = languages_granted - data["master_name"] = master_name - data["master_dna"] = master_dna - return data - -/mob/living/silicon/pai/ui_act(action, list/params, datum/tgui/ui) - . = ..() - if(.) - return TRUE - if(action == "buy") - buy_software(params["selection"]) - return TRUE - if(action == "change image") - change_image() - return TRUE - if(action == "check dna") - check_dna() - return TRUE - // Software related ui actions - if(available_software[action] && !installed_software.Find(action)) - balloon_alert(usr, "software unavailable") - return FALSE - switch(action) - if("Atmospheric Sensor") - atmos_analyzer.attack_self(src) - return TRUE - if("Crew Manifest") - ai_roster() - return TRUE - if("Crew Monitor") - GLOB.crewmonitor.show(usr, src) - return TRUE - if("Digital Messenger") - modularInterface?.interact(usr) - return TRUE - if("Door Jack") - // Look to door_jack.dm for implementation - door_jack(params["mode"]) - return TRUE - if("Encryption Slot") - balloon_alert(usr, "radio frequencies [!encrypt_mod ? "enabled" : "disabled"]") - encrypt_mod = !encrypt_mod - radio.subspace_transmission = !radio.subspace_transmission - return TRUE - if("Host Scan") - host_scan(params["mode"]) - return TRUE - if("Internal GPS") - internal_gps.attack_self(src) - return TRUE - if("Music Synthesizer") - instrument.interact(src) - return TRUE - if("Medical HUD") - toggle_hud(PAI_TOGGLE_MEDICAL_HUD) - return TRUE - if("Newscaster") - newscaster.ui_interact(src) - return TRUE - if("Photography Module") - // Look to pai_camera.dm for implementation - use_camera(usr, params["mode"]) - return TRUE - if("Remote Signaler") - signaler.ui_interact(src) - return TRUE - if("Security HUD") - toggle_hud(PAI_TOGGLE_SECURITY_HUD) - return TRUE - if("Universal Translator") - grant_languages() - ui.send_full_update() - return TRUE - return FALSE - -/** - * Purchases the selected software from the list and deducts their - * available ram. - * - * @param {string} selection - The software to purchase. - * - * @returns {boolean} - TRUE if the software was purchased, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/buy_software(selection) - if(!available_software[selection] || installed_software.Find(selection)) - return FALSE - var/cost = available_software[selection] - if(ram < cost) - return FALSE - installed_software.Add(selection) - ram -= cost - var/datum/hud/pai/pAIhud = hud_used - pAIhud?.update_software_buttons() - switch(selection) - if("Atmospheric Sensor") - atmos_analyzer = new(src) - if("Digital Messenger") - create_modularInterface() - if("Host Scan") - host_scan = new(src) - if("Internal GPS") - internal_gps = new(src) - if("Music Synthesizer") - instrument = new(src) - if("Newscaster") - newscaster = new(src) - if("Photography Module") - camera = new(src) - if("Remote Signaler") - signaler = new(src) - return TRUE - -/** - * Changes the image displayed on the pAI. - * - * @param {mob} user - The user who is changing the image. - * - * @returns {boolean} - TRUE if the image was changed, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/change_image() - var/new_image = tgui_input_list(src, "Select your new display image", "Display Image", possible_overlays) - if(isnull(new_image)) - return FALSE - card.emotion_icon = new_image - card.update_appearance(UPDATE_ICON) - return TRUE - -/** - * Supporting proc for the pAI to prick it's master's hand - * or... whatever. It must be held in order to work - * Gives the owner a popup if they want to get the jab. - * - * @returns {boolean} - TRUE if a sample was taken, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/check_dna() - if(emagged) // Their master DNA signature is scrambled anyway - to_chat(src, span_syndradio("You are not at liberty to do this! All agents are clandestine.")) - return FALSE - var/mob/living/carbon/holder = get_holder() - if(!iscarbon(holder)) - balloon_alert(src, "not being carried") - return FALSE - balloon_alert(src, "requesting dna sample") - if(tgui_alert(holder, "[src] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "Checking DNA", list("Yes", "No")) != "Yes") - balloon_alert(src, "dna sample refused!") - return FALSE - holder.visible_message(span_notice("[holder] presses [holder.p_their()] thumb against [src]."), span_notice("You press your thumb against [src]."), span_notice("[src] makes a sharp clicking sound as it extracts DNA material from [holder].")) - if(!holder.has_dna()) - balloon_alert(src, "no dna detected!") - return FALSE - to_chat(src, span_boldannounce(("[holder]'s UE string: [holder.dna.unique_enzymes]"))) - to_chat(src, span_notice("DNA [holder.dna.unique_enzymes == master_dna ? "matches" : "does not match"] our stored Master's DNA.")) - return TRUE - -/** - * Grant all languages to the current pAI. - * - * @returns {boolean} - TRUE if the languages were granted, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/grant_languages() - if(languages_granted) - return FALSE - grant_all_languages(TRUE, TRUE, TRUE, LANGUAGE_SOFTWARE) - languages_granted = TRUE - return TRUE - -/** - * Host scan supporting proc - * - * Allows the pAI to scan its host's health vitals - * using an integrated health analyzer. - * - * @returns {boolean} - TRUE if the scan was successful, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/host_scan(mode) - if(isnull(mode)) - return FALSE - if(mode == PAI_SCAN_TARGET) - var/mob/living/target = get_holder() - if(!target || !isliving(target)) - balloon_alert(src, "not being carried") - return FALSE - host_scan.attack(target, src) - return TRUE - if(mode == PAI_SCAN_MASTER) - if(!master_ref) - balloon_alert(src, "no master detected") - return FALSE - var/mob/living/resolved_master = find_master() - if(!resolved_master) - balloon_alert(src, "cannot locate master") - return FALSE - if(!is_valid_z_level(get_turf(src), get_turf(resolved_master))) - balloon_alert(src, "master out of range") - return FALSE - host_scan.attack(resolved_master, src) - return TRUE - return FALSE - -/** - * Proc that toggles any active huds based on the option. - * - * @param {string} mode - The hud to toggle. - */ -/mob/living/silicon/pai/proc/toggle_hud(mode) - if(isnull(mode)) - return FALSE - var/datum/atom_hud/hud - var/hud_on - if(mode == PAI_TOGGLE_MEDICAL_HUD) - hud = GLOB.huds[med_hud] - medHUD = !medHUD - hud_on = medHUD - if(mode == PAI_TOGGLE_SECURITY_HUD) - hud = GLOB.huds[sec_hud] - secHUD = !secHUD - hud_on = secHUD - if(hud_on) - hud.show_to(src) - else - hud.hide_from(src) - return TRUE diff --git a/code/modules/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm index 27bb868f2371..5b25b248cab8 100644 --- a/code/modules/photography/camera/camera.dm +++ b/code/modules/photography/camera/camera.dm @@ -154,7 +154,7 @@ if(on) // EMP will only work on cameras that are on as it has power going through it icon_state = state_off on = FALSE - addtimer(CALLBACK(src, PROC_REF(emp_after)), (600/severity)) + addtimer(CALLBACK(src, PROC_REF(emp_after)), (6*severity) SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE) /obj/item/camera/proc/emp_after() on = TRUE diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index e2fcb0d0fea9..215bfb7fab95 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -1466,7 +1466,7 @@ environ = 0 update_appearance(UPDATE_ICON) update() - addtimer(CALLBACK(src, PROC_REF(reset), APC_RESET_EMP), 600) + addtimer(CALLBACK(src, PROC_REF(reset), APC_RESET_EMP), (6 * severity) SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE) /obj/machinery/power/apc/blob_act(obj/structure/blob/B) set_broken() diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 6ca8fac3e3e7..d042bbba6020 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -179,7 +179,7 @@ . = ..() if(. & EMP_PROTECT_SELF) return - charge -= max((charge * 0.1), 500) / severity + charge -= max((charge * severity / 100), 50 * severity) if (charge < 0) charge = 0 @@ -392,7 +392,7 @@ . = ..() if(. & EMP_PROTECT_SELF) return - charge = clamp((charge-(10000/severity)),0,maxcharge) + charge = clamp((charge-(1000 * severity)),0,maxcharge) /obj/item/stock_parts/cell/emergency_light name = "miniature power cell" diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm index 5fdb7e9646cf..43f7e4347f63 100644 --- a/code/modules/power/generator.dm +++ b/code/modules/power/generator.dm @@ -21,14 +21,16 @@ . = ..() find_circs() connect_to_network() - SSair.atmos_machinery += src + SSair_machinery.start_processing_machine(src) + START_PROCESSING(SSmachines, src) update_appearance(UPDATE_ICON) component_parts = list(new /obj/item/circuitboard/machine/generator) AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS ) /obj/machinery/power/generator/Destroy() kill_circs() - SSair.atmos_machinery -= src + SSair_machinery.stop_processing_machine(src) + STOP_PROCESSING(SSmachines, src) return ..() /obj/machinery/power/generator/update_icon_state() @@ -120,7 +122,8 @@ lastgenlev = power_output lastgen -= power_output lastgen = max(lastgen, 0) - ..() + update_icon() + src.updateDialog() /obj/machinery/power/generator/proc/get_menu(include_link = TRUE) var/t = "" diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 7c9f48b664a3..ede43e165e3c 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -9,8 +9,8 @@ #define LIGHT_BROKEN 2 #define LIGHT_BURNED 3 -#define BROKEN_SPARKS_MIN (30 SECONDS) -#define BROKEN_SPARKS_MAX (90 SECONDS) +#define BROKEN_SPARKS_MIN (3 MINUTES) +#define BROKEN_SPARKS_MAX (9 MINUTES) #define LIGHT_ON_DELAY_UPPER 3 SECONDS #define LIGHT_ON_DELAY_LOWER 1 SECONDS @@ -488,7 +488,7 @@ update() /obj/machinery/light/proc/broken_sparks(start_only=FALSE) - if(status == LIGHT_BROKEN && has_power() && Master.current_runlevel) + if(!QDELETED(src) && status == LIGHT_BROKEN && has_power() && Master.current_runlevel) if(!start_only) do_sparks(3, TRUE, src) var/delay = rand(BROKEN_SPARKS_MIN, BROKEN_SPARKS_MAX) diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 4ccc468325e5..91ba0b8c813f 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -343,8 +343,9 @@ //source is an object caused electrocuting (airlock, grille, etc) //siemens_coeff - layman's terms, conductivity //dist_check - set to only shock mobs within 1 of source (vendors, airlocks, etc.) +//zone_override - allows checking a specific body part for shock protection instead of the hands //No animations will be performed by this proc. -/proc/electrocute_mob(mob/living/carbon/victim, power_source, obj/source, siemens_coeff = 1, dist_check = FALSE) +/proc/electrocute_mob(mob/living/carbon/victim, power_source, obj/source, siemens_coeff = 1, dist_check = FALSE, zone = BODY_ZONE_R_ARM) if(!istype(victim) || ismecha(victim.loc)) return FALSE //feckin mechs are dumb @@ -352,7 +353,7 @@ if(!in_range(source, victim)) return FALSE - if(victim.wearing_shock_proof_gloves()) + if(victim.getarmor(zone, ELECTRIC) >= 100) SEND_SIGNAL(victim, COMSIG_LIVING_SHOCK_PREVENTED, power_source, source, siemens_coeff, dist_check) var/obj/item/clothing/gloves/G = victim.gloves if(istype(G, /obj/item/clothing/gloves/color/fyellow)) diff --git a/code/modules/power/reactor/reactor.dm b/code/modules/power/reactor/reactor.dm index 5874490f5f25..e0a8597112e2 100644 --- a/code/modules/power/reactor/reactor.dm +++ b/code/modules/power/reactor/reactor.dm @@ -307,14 +307,14 @@ if(active && moderator_input.total_moles() >= minimum_coolant_level) // Fuel types: increases power and K var/total_fuel_moles = 0 - total_fuel_moles += moderator_input.get_moles(/datum/gas/plasma) * PLASMA_FUEL_POWER - total_fuel_moles += moderator_input.get_moles(/datum/gas/tritium) * TRITIUM_FUEL_POWER - total_fuel_moles += moderator_input.get_moles(/datum/gas/antinoblium) * ANTINOBLIUM_FUEL_POWER + total_fuel_moles += moderator_input.get_moles(GAS_PLASMA) * PLASMA_FUEL_POWER + total_fuel_moles += moderator_input.get_moles(GAS_TRITIUM) * TRITIUM_FUEL_POWER + total_fuel_moles += moderator_input.get_moles(GAS_ANTINOB) * ANTINOBLIUM_FUEL_POWER // Power modifier types: increases fuel effectiveness var/power_mod_moles = 0 - power_mod_moles += moderator_input.get_moles(/datum/gas/oxygen) * OXYGEN_POWER_MOD - power_mod_moles += moderator_input.get_moles(/datum/gas/hydrogen) * HYDROGEN_POWER_MOD + power_mod_moles += moderator_input.get_moles(GAS_O2) * OXYGEN_POWER_MOD + power_mod_moles += moderator_input.get_moles(GAS_H2) * HYDROGEN_POWER_MOD // Now make some actual power! if(total_fuel_moles >= minimum_coolant_level) //You at least need SOME fuel. @@ -322,39 +322,39 @@ var/power_modifier = max(power_mod_moles * 10 / moderator_input.total_moles(), 1) //You can never have negative IPM. For now. power_produced = max(0,((fuel_power*power_modifier)*moderator_input.total_moles())) / delta_time if(active) - coolant_output.adjust_moles(/datum/gas/pluonium, total_fuel_moles/20) //Shove out pluonium into the air when it's fuelled. You need to filter this off, or you're gonna have a bad time. + coolant_output.adjust_moles(GAS_PLUONIUM, total_fuel_moles/20) //Shove out pluonium into the air when it's fuelled. You need to filter this off, or you're gonna have a bad time. // Control types: increases control of K var/total_control_moles = 0 - total_control_moles += moderator_input.get_moles(/datum/gas/nitrogen) * NITROGEN_CONTROL_MOD - total_control_moles += moderator_input.get_moles(/datum/gas/carbon_dioxide) * CARBON_CONTROL_MOD - total_control_moles += moderator_input.get_moles(/datum/gas/pluoxium) * PLUOXIUM_CONTROL_MOD + total_control_moles += moderator_input.get_moles(GAS_N2) * NITROGEN_CONTROL_MOD + total_control_moles += moderator_input.get_moles(GAS_CO2) * CARBON_CONTROL_MOD + total_control_moles += moderator_input.get_moles(GAS_PLUOXIUM) * PLUOXIUM_CONTROL_MOD if(total_control_moles >= minimum_coolant_level) var/control_bonus = total_control_moles / REACTOR_CONTROL_FACTOR //1 mol of n2 -> 0.002 bonus control rod effectiveness, if you want a super controlled reaction, you'll have to sacrifice some power. control_rod_effectiveness = initial(control_rod_effectiveness) + control_bonus // Permeability types: increases cooling efficiency var/total_permeability_moles = 0 - total_permeability_moles += moderator_input.get_moles(/datum/gas/bz) * BZ_PERMEABILITY_MOD - total_permeability_moles += moderator_input.get_moles(/datum/gas/water_vapor) * WATER_PERMEABILITY_MOD - total_permeability_moles += moderator_input.get_moles(/datum/gas/hypernoblium) * NOBLIUM_PERMEABILITY_MOD + total_permeability_moles += moderator_input.get_moles(GAS_BZ) * BZ_PERMEABILITY_MOD + total_permeability_moles += moderator_input.get_moles(GAS_H2O) * WATER_PERMEABILITY_MOD + total_permeability_moles += moderator_input.get_moles(GAS_HYPERNOB) * NOBLIUM_PERMEABILITY_MOD if(total_permeability_moles >= minimum_coolant_level) gas_absorption_effectiveness = clamp(gas_absorption_constant + (total_permeability_moles / REACTOR_PERMEABILITY_FACTOR), 0, 1) // Radiation types: increases radiation - radioactivity_spice_multiplier += moderator_input.get_moles(/datum/gas/nitrogen) * NITROGEN_RAD_MOD //An example setup of 50 moles of n2 (for dealing with spent fuel) leaves us with a radioactivity spice multiplier of 3. - radioactivity_spice_multiplier += moderator_input.get_moles(/datum/gas/carbon_dioxide) * CARBON_RAD_MOD - radioactivity_spice_multiplier += moderator_input.get_moles(/datum/gas/hydrogen) * HYDROGEN_RAD_MOD - radioactivity_spice_multiplier += moderator_input.get_moles(/datum/gas/tritium) * TRITIUM_RAD_MOD - radioactivity_spice_multiplier += moderator_input.get_moles(/datum/gas/antinoblium) * ANTINOBLIUM_RAD_MOD + radioactivity_spice_multiplier += moderator_input.get_moles(GAS_N2) * NITROGEN_RAD_MOD //An example setup of 50 moles of n2 (for dealing with spent fuel) leaves us with a radioactivity spice multiplier of 3. + radioactivity_spice_multiplier += moderator_input.get_moles(GAS_CO2) * CARBON_RAD_MOD + radioactivity_spice_multiplier += moderator_input.get_moles(GAS_H2) * HYDROGEN_RAD_MOD + radioactivity_spice_multiplier += moderator_input.get_moles(GAS_TRITIUM) * TRITIUM_RAD_MOD + radioactivity_spice_multiplier += moderator_input.get_moles(GAS_ANTINOB) * ANTINOBLIUM_RAD_MOD // Integrity modification - var/healium_moles = moderator_input.get_moles(/datum/gas/healium) + var/healium_moles = moderator_input.get_moles(GAS_HEALIUM) if(healium_moles > minimum_coolant_level) integrity_restoration = max((2400-max(TCMB, temperature))/300) * delta_time //At 1800K integrity_restoration should be around 1, which then it cant keep up with the heat damage (around 1.1 maximum in temp_damage) to restore integrity // Degradation types: degrades the fuel rods - var/total_degradation_moles = moderator_input.get_moles(/datum/gas/pluonium) //Because it's quite hard to get. + var/total_degradation_moles = moderator_input.get_moles(GAS_PLUONIUM) //Because it's quite hard to get. if(total_degradation_moles >= minimum_coolant_level) //I'll be nice. depletion_modifier += total_degradation_moles / 15 //Oops! All depletion. This causes your fuel rods to get SPICY. if(prob(total_degradation_moles)) // don't spam the sound so much please @@ -568,7 +568,7 @@ //Results: Engineering becomes unusable and your engine irreparable /obj/machinery/atmospherics/components/trinary/nuclear_reactor/proc/meltdown() set waitfor = FALSE - SSair.atmos_machinery -= src //Annd we're now just a useless brick. + SSair_machinery.stop_processing_machine(src) vessel_integrity = null // this makes it show up weird on the monitor to even further emphasize something's gone horribly wrong slagged = TRUE color = null diff --git a/code/modules/power/singularity/collector.dm b/code/modules/power/singularity/collector.dm index 9110802e69de..10bd9e90bbe5 100644 --- a/code/modules/power/singularity/collector.dm +++ b/code/modules/power/singularity/collector.dm @@ -36,9 +36,9 @@ /// What is it producing var/mode = POWER /// What gasses are we using - var/list/using = list(/datum/gas/plasma) + var/list/using = list(GAS_PLASMA) /// Gasses we give - var/list/giving = list(/datum/gas/tritium = 1) + var/list/giving = list(GAS_TRITIUM = 1) /// Last output used to calculate per minute var/last_output = 0 // Higher machine tier will give more power @@ -118,11 +118,7 @@ toggle_power() user.visible_message("[user.name] turns the [src.name] [active? "on":"off"].", \ span_notice("You turn the [src.name] [active? "on":"off"].")) - //yogs start -- fixes runtime with empty rad collectors - var/fuel = 0 - if(loaded_tank) - fuel = loaded_tank.air_contents.get_moles(/datum/gas/plasma) - //yogs end + var/fuel = loaded_tank?.air_contents?.get_moles(GAS_PLASMA) investigate_log("turned [active?"on":"off"] by [key_name(user)]. [loaded_tank?"Fuel: [round(fuel/0.29)]%":"It is empty"].", INVESTIGATE_SINGULO) investigate_log("turned [active?"on":"off"] by [key_name(user)]. [loaded_tank?"Fuel: [round(fuel/0.29)]%":"It is empty"].", INVESTIGATE_SUPERMATTER) // yogs - so supermatter investigate is useful return @@ -234,23 +230,23 @@ to_chat(user, "[src] isn't connected to a powernet!") return mode = POWER - using = list(/datum/gas/plasma) - giving = list(/datum/gas/tritium = 1) + using = list(GAS_PLASMA) + giving = list(GAS_TRITIUM = 1) if(SCIENCE) if(!is_station_level(z) && !SSresearch.science_tech) to_chat(user, "[src] isn't linked to a research system!") return // Dont switch over mode = SCIENCE - using = list(/datum/gas/tritium, /datum/gas/oxygen) - giving = list(/datum/gas/carbon_dioxide = 2) // Conservation of mass + using = list(GAS_TRITIUM, GAS_O2) + giving = list(GAS_CO2 = 2) // Conservation of mass if(MONEY) var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) if(!D) to_chat(user, "[src] couldn't find the cargo budget!") return // Dont switch over mode = MONEY - using = list(/datum/gas/plasma) - giving = list(/datum/gas/tritium = 0.5) // money + using = list(GAS_PLASMA) + giving = list(GAS_TRITIUM = 0.5) // money to_chat(user, "You set the [src] mode to [mode] production.") diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 25cfc4cdd859..2fb1abeaadbf 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -52,6 +52,7 @@ /obj/machinery/power/emitter/anchored anchored = TRUE + state = EMITTER_WRENCHED /obj/machinery/power/emitter/ctf name = "Energy Cannon" @@ -77,6 +78,10 @@ ADD_TRAIT(src, TRAIT_EMPPROOF_CONTENTS, "innate_empproof") AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS, null, CALLBACK(src, PROC_REF(can_be_rotated))) +/obj/machinery/power/emitter/on_construction() + if(anchored && state == EMITTER_UNWRENCHED) + state = EMITTER_WRENCHED + /obj/machinery/power/emitter/RefreshParts() var/max_reload = initial(maximum_reload_time) + 20 var/min_reload = initial(minimum_reload_time) + 4 @@ -437,10 +442,10 @@ if(!tank || !tank.air_contents) return var/datum/gas_mixture/fuel = tank.air_contents - if(fuel.get_moles(/datum/gas/tritium) < fuel_consumption) + if(fuel.get_moles(GAS_TRITIUM) < fuel_consumption) return - fuel.adjust_moles(/datum/gas/tritium, -fuel_consumption) - fuel.adjust_moles(/datum/gas/hydrogen, fuel_consumption) + fuel.adjust_moles(GAS_TRITIUM, -fuel_consumption) + fuel.adjust_moles(GAS_H2, fuel_consumption) if(obj_flags & EMAGGED) // radioactive if emagged radiation_pulse(get_turf(src), fuel_consumption * FIRE_HYDROGEN_ENERGY_RELEASED / TRITIUM_BURN_RADIOACTIVITY_FACTOR) return ..() @@ -461,7 +466,7 @@ /obj/machinery/power/emitter/particle/update_icon_state() . = ..() if(active) - icon_state = (tank?.air_contents?.get_moles(/datum/gas/tritium) >= fuel_consumption) ? icon_state_on : icon_state_underpowered + icon_state = (tank?.air_contents?.get_moles(GAS_TRITIUM) >= fuel_consumption) ? icon_state_on : icon_state_underpowered else icon_state = initial(icon_state) diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 3689d4eb9d73..3d45e0554f19 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -583,7 +583,7 @@ /obj/singularity/proc/emp_area() - empulse(src, 8, 10) + empulse(src, EMP_HEAVY) return /obj/singularity/singularity_act() diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index ba8c60ddc4ee..c17a460347bb 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -417,7 +417,7 @@ outputting = output_attempt output_level = rand(0, output_level_max) input_level = rand(0, input_level_max) - charge = max(charge - 1e6/severity, 0) + charge = max(charge - (1e5 * severity), 0) update_appearance(UPDATE_ICON) log_smes() diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 3e658011ab0e..93e02b451c90 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -20,7 +20,7 @@ #define H2O_HEAT_PENALTY 12 //This'll get made slowly over time, I want my spice rock spicy god damnit #define ANTINOB_HEAT_PENALTY 15 -/// Higher == Bigger bonus to power generation. +/// Higher == Bigger bonus to power generation. /// All of these get divided by 10-bzcomp * 5 before having 1 added and being multiplied with power to determine rads #define OXYGEN_TRANSMIT_MODIFIER 1.5 #define PLASMA_TRANSMIT_MODIFIER 4 @@ -36,7 +36,7 @@ /// How much extra radioactivity to emit #define BZ_RADIOACTIVITY_MODIFIER 5 // Up to 500% rads -#define TRITIUM_RADIOACTIVITY_MODIFIER 3 +#define TRITIUM_RADIOACTIVITY_MODIFIER 3 #define PLUOXIUM_RADIOACTIVITY_MODIFIER -2 /// Higher == Gas makes the crystal more resistant against heat damage. @@ -130,7 +130,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) /// How much force the SM expldoes with var/explosion_power = 35 - + /// Factor for power generation. AirTemp*(temp_factor/(0C)) var/temp_factor = 30 var/power = 0 @@ -222,7 +222,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) /obj/machinery/power/supermatter_crystal/Initialize(mapload) . = ..() uid = gl_uid++ - SSair.atmos_machinery += src + SSair_machinery.start_processing_machine(src) countdown = new(src) countdown.start() GLOB.poi_list |= src @@ -238,7 +238,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) /obj/machinery/power/supermatter_crystal/Destroy() investigate_log("has been destroyed.", INVESTIGATE_SUPERMATTER) - SSair.atmos_machinery -= src + SSair_machinery.stop_processing_machine(src) QDEL_NULL(radio) GLOB.poi_list -= src QDEL_NULL(countdown) @@ -456,40 +456,40 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) // Calculate the gas mix ratio combined_gas = max(removed.total_moles(), 0) - var/plasmacomp = max(removed.get_moles(/datum/gas/plasma)/combined_gas, 0) - var/o2comp = max(removed.get_moles(/datum/gas/oxygen)/combined_gas, 0) - var/co2comp = max(removed.get_moles(/datum/gas/carbon_dioxide)/combined_gas, 0) - var/n2ocomp = max(removed.get_moles(/datum/gas/nitrous_oxide)/combined_gas, 0) - var/n2comp = max(removed.get_moles(/datum/gas/nitrogen)/combined_gas, 0) - var/pluoxiumcomp = max(removed.get_moles(/datum/gas/pluoxium)/combined_gas, 0) - var/tritiumcomp = max(removed.get_moles(/datum/gas/tritium)/combined_gas, 0) - var/h2comp = max(removed.get_moles(/datum/gas/hydrogen)/combined_gas, 0) - var/h2ocomp = max(removed.get_moles(/datum/gas/water_vapor)/combined_gas, 0) - var/bzcomp = max(removed.get_moles(/datum/gas/bz)/combined_gas, 0) - var/pluoniumcomp = max(removed.get_moles(/datum/gas/pluonium)/combined_gas, 0) - var/healcomp = max(removed.get_moles(/datum/gas/healium)/combined_gas, 0) - var/zaukcomp = max(removed.get_moles(/datum/gas/zauker)/combined_gas, 0) - var/haloncomp = max(removed.get_moles(/datum/gas/halon)/combined_gas, 0) - var/nobliumcomp = max(removed.get_moles(/datum/gas/hypernoblium)/combined_gas, 0) - var/antinobliumcomp = max(removed.get_moles(/datum/gas/antinoblium)/combined_gas, 0) - var/nitriumcomp = max(removed.get_moles(/datum/gas/nitrium)/combined_gas, 0) - var/miasmacomp = max(removed.get_moles(/datum/gas/miasma)/combined_gas, 0) + var/plasmacomp = max(removed.get_moles(GAS_PLASMA)/combined_gas, 0) + var/o2comp = max(removed.get_moles(GAS_O2)/combined_gas, 0) + var/co2comp = max(removed.get_moles(GAS_CO2)/combined_gas, 0) + var/n2ocomp = max(removed.get_moles(GAS_NITROUS)/combined_gas, 0) + var/n2comp = max(removed.get_moles(GAS_N2)/combined_gas, 0) + var/pluoxiumcomp = max(removed.get_moles(GAS_PLUOXIUM)/combined_gas, 0) + var/tritiumcomp = max(removed.get_moles(GAS_TRITIUM)/combined_gas, 0) + var/bzcomp = max(removed.get_moles(GAS_BZ)/combined_gas, 0) + var/h2ocomp = max(removed.get_moles(GAS_H2O)/combined_gas, 0) + var/h2comp = max(removed.get_moles(GAS_H2)/combined_gas, 0) + var/pluoniumcomp = max(removed.get_moles(GAS_PLUONIUM)/combined_gas, 0) + var/healcomp = max(removed.get_moles(GAS_HEALIUM)/combined_gas, 0) + var/zaukcomp = max(removed.get_moles(GAS_ZAUKER)/combined_gas, 0) + var/haloncomp = max(removed.get_moles(GAS_HALON)/combined_gas, 0) + var/nobliumcomp = max(removed.get_moles(GAS_HYPERNOB)/combined_gas, 0) + var/antinobliumcomp = max(removed.get_moles(GAS_ANTINOB)/combined_gas, 0) + var/nitriumcomp = max(removed.get_moles(GAS_NITRIUM)/combined_gas, 0) + var/miasmacomp = max(removed.get_moles(GAS_MIASMA)/combined_gas, 0) if (healcomp >= 0.1) heal_mod = (healcomp * HEALIUM_HEAL_MOD) + 1 //Increases healing and healing cap else heal_mod = 1 - + if (zaukcomp >= 0.05) damage_mod = (zaukcomp * ZAUKER_DAMAGE_MOD) + 1 //Increases damage taken and damage cap else damage_mod = 1 // Mole releated calculations - var/bzmol = max(removed.get_moles(/datum/gas/bz), 0) - var/nitriummol = max(removed.get_moles(/datum/gas/nitrium), 0) - var/antinobmol = max(removed.get_moles(/datum/gas/antinoblium), 0) - var/miasmol = max(removed.get_moles(/datum/gas/miasma), 0) + var/bzmol = max(removed.get_moles(GAS_BZ), 0) + var/nitriummol = max(removed.get_moles(GAS_NITRIUM), 0) + var/antinobmol = max(removed.get_moles(GAS_ANTINOB), 0) + var/miasmol = max(removed.get_moles(GAS_MIASMA), 0) // Power of the gas. Scale of 0 to 1 gasmix_power_ratio = clamp(plasmacomp + o2comp + co2comp + tritiumcomp + bzcomp + nitriumcomp + antinobliumcomp - pluoxiumcomp - n2comp, 0, 1) @@ -507,7 +507,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) powerloss_dynamic_scaling = clamp(powerloss_dynamic_scaling + clamp(co2comp - powerloss_dynamic_scaling, -0.02, 0.02), 0, 1) else powerloss_dynamic_scaling = clamp(powerloss_dynamic_scaling - 0.05,0, 1) - + if(support_integrity >= 10 && !supermatter_blob) powerloss_inhibitor = clamp(1-(powerloss_dynamic_scaling * clamp(combined_gas/POWERLOSS_INHIBITION_MOLE_BOOST_THRESHOLD,1 ,1.5)),0 ,1) @@ -532,7 +532,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) if(prob(50)) //1 + (tritRad + pluoxDampen * bzDampen * o2Rad * plasmaRad / (10 - bzrads)) - last_rads = power * (1 + (tritiumcomp * TRITIUM_RADIOACTIVITY_MODIFIER) + ((pluoxiumcomp * PLUOXIUM_RADIOACTIVITY_MODIFIER) * pluoxiumcomp) * (power_transmission_bonus/(10-(bzcomp * BZ_RADIOACTIVITY_MODIFIER)))) * radmodifier + last_rads = power * (1 + (tritiumcomp * TRITIUM_RADIOACTIVITY_MODIFIER) + (((pluoxiumcomp ** 2) * PLUOXIUM_RADIOACTIVITY_MODIFIER)) * (power_transmission_bonus/(10-(bzcomp * BZ_RADIOACTIVITY_MODIFIER)))) * radmodifier radiation_pulse(src, max(last_rads)) if(nitriummol > NITRO_BALL_MOLES_REQUIRED) // haha funny particles go brrrrr @@ -540,7 +540,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) var/starting_angle = rand(0, 360) for(var/i = 0 to balls_shot) // fires particles in a ring, with some random variation in the angle src.fire_nuclear_particle(starting_angle + rand(-180/balls_shot, 180/balls_shot) + (i * 360 / balls_shot)) - removed.set_moles(/datum/gas/nitrium, max(nitriummol - (balls_shot * NITRO_BALL_MOLES_REQUIRED), 0)) //converts nitrium into radballs + removed.set_moles(GAS_NITRIUM, max(nitriummol - (balls_shot * NITRO_BALL_MOLES_REQUIRED), 0)) //converts stimulum into radballs if(bzcomp >= 0.4 && prob(50 * bzcomp)) src.fire_nuclear_particle() // Start to emit radballs at a maximum of 50% chance per tick @@ -587,18 +587,17 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) //Calculate how much gas to release, antinoblium seeded SM produces much more gas if(antinoblium_attached || supermatter_blob) - removed.adjust_moles(/datum/gas/plasma, max(((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER) * (1+(100-support_integrity)/25), 0)) - removed.adjust_moles(/datum/gas/oxygen, max((((device_energy + removed.return_temperature() * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER) * (1+(100-support_integrity)/25), 0)) + removed.adjust_moles(GAS_PLASMA, max(((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER) * (1+(100-support_integrity)/25), 0)) + removed.adjust_moles(GAS_O2, max((((device_energy + removed.return_temperature() * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER) * (1+(100-support_integrity)/25), 0)) else if(haloncomp >= 0.15) - removed.adjust_moles(/datum/gas/plasma, max((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER, 0)) - removed.adjust_moles(/datum/gas/oxygen, max(((device_energy + removed.return_temperature() * dynamic_heat_modifier) - T0C) / PLASMA_RELEASE_MODIFIER, 0)) // Supresses Oxygen Generation + removed.adjust_moles(GAS_PLASMA, max((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER, 0)) + removed.adjust_moles(GAS_O2, max(((device_energy + removed.return_temperature() * dynamic_heat_modifier) - T0C) / PLASMA_RELEASE_MODIFIER, 0)) // Supresses Oxygen Generation else - removed.adjust_moles(/datum/gas/plasma, max((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER, 0)) - removed.adjust_moles(/datum/gas/oxygen, max(((device_energy + removed.return_temperature() * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0)) + removed.adjust_moles(GAS_PLASMA, max((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER, 0)) + removed.adjust_moles(GAS_O2, max(((device_energy + removed.return_temperature() * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0)) if(produces_gas) env.merge(removed) - air_update_turf() for(var/mob/living/carbon/human/l in view(src, HALLUCINATION_RANGE(power))) // If they can see it without mesons on. Bad on them. if((!HAS_TRAIT(l, TRAIT_MESONS)) || corruptor_attached) @@ -628,8 +627,6 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) supermatter_pull(src, power/750) if(prob(5) || (antinoblium_attached || supermatter_blob) && prob(10)) supermatter_anomaly_gen(src, ANOMALY_FLUX, rand(5, 10)) - if(prob(5) || (antinoblium_attached || supermatter_blob) && prob(10)) - supermatter_anomaly_gen(src, ANOMALY_HALLUCINATION, rand(5, 10)) if(power > SEVERE_POWER_PENALTY_THRESHOLD && prob(5) || prob(1) || (antinoblium_attached || supermatter_blob) && prob(10)) supermatter_anomaly_gen(src, ANOMALY_GRAVITATIONAL, rand(5, 10)) if(power > SEVERE_POWER_PENALTY_THRESHOLD && prob(2) || prob(0.3) && power > POWER_PENALTY_THRESHOLD || (antinoblium_attached || supermatter_blob) && prob(10)) @@ -696,7 +693,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) radio.talk_into(src, "DANGER: SUPERMATTER BIOHAZARD LEVELS HAVE EXCEEDED SAFETY THRESHOLDS.", common_channel) log_game("DANGER: SUPERMATTER BIOHAZARD LEVELS HAVE EXCEEDED SAFETY THRESHOLDS.") // yogs start - Logs SM chatter investigate_log("DANGER: SUPERMATTER BIOHAZARD LEVELS HAVE EXCEEDED SAFETY THRESHOLDS.", INVESTIGATE_SUPERMATTER) // yogs end - + if(antinoblium_attached) if(support_integrity <= 10) radio.talk_into(src, "DANGER: RESONANCE CASCADE IMMINENT.", engineering_channel) @@ -761,7 +758,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) radiation_pulse(src, (100-support_integrity)*2, 4) if(support_integrity<3) var/emp_power = round(explosion_power * (1+(1-(support_integrity/3))),1) - empulse(src, emp_power, emp_power*2) + empulse(src, emp_power) if(support_integrity<100) power += round((100-support_integrity)/2,1) if(support_integrity<70) @@ -782,7 +779,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) if(istype(T, /turf/open/space) || T.return_air().total_moles() < MOLE_SPACE_THRESHOLD) damage += DAMAGE_HARDCAP * explosion_point //Can't cheat by spacing the crystal to buy time, it will just delaminate faster if(prob(2)) - empulse(src, 10-support_integrity, (10-support_integrity)*2) //EMPs must always be spewing every so often to ensure that containment is guaranteed to fail. + empulse(src, 10-support_integrity) //EMPs must always be spewing every so often to ensure that containment is guaranteed to fail. return 1 /obj/machinery/power/supermatter_crystal/bullet_act(obj/projectile/Proj) @@ -1007,7 +1004,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) to_chat(user, "You attach the antinoblium shard to the [src], moving your hand away before a sudden gravitational wave pulls the [W] into the crystal as it flashes to ash!") playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1) radiation_pulse(src, 150, 4) - empulse(src, 3,6) + empulse(src, EMP_HEAVY, 6) qdel(W) return else if(user.dropItemToGround(W)) @@ -1155,8 +1152,6 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) new /obj/effect/anomaly/flux/explosion(local_turf, has_weak_lifespan ? rand(250, 300) : null) if(ANOMALY_GRAVITATIONAL) new /obj/effect/anomaly/grav(local_turf, has_weak_lifespan ? rand(250, 300) : null) - if(ANOMALY_HALLUCINATION) - new /obj/effect/anomaly/hallucination(local_turf, has_weak_lifespan ? rand(250, 300) : null) if(ANOMALY_PYRO) new /obj/effect/anomaly/pyro(local_turf, has_weak_lifespan ? rand(250, 300) : null) if(ANOMALY_VORTEX) @@ -1263,7 +1258,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) qdel(src) addtimer(CALLBACK(shard, TYPE_PROC_REF(/obj/machinery/power/supermatter_crystal/shard, trigger)), 60) return TRUE - + /obj/machinery/power/supermatter_crystal/shard/proc/trigger() var/area/A = get_area(loc) playsound(src, 'sound/machines/supermatter_alert.ogg', 75) diff --git a/code/modules/power/supermatter/supermatter_delamination.dm b/code/modules/power/supermatter/supermatter_delamination.dm index 5893ca5d2282..0b97f5c66c31 100644 --- a/code/modules/power/supermatter/supermatter_delamination.dm +++ b/code/modules/power/supermatter/supermatter_delamination.dm @@ -77,6 +77,7 @@ call_tesla() call_explosion() return + call_explosion() /datum/supermatter_delamination/proc/shockwave() //borrowed ynot's code var/atom/movable/gravity_lens/shockwave = new(supermatter_turf) diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index fb30e6e0f266..38dca34c30b0 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -348,7 +348,7 @@ else if(closest_mob) var/shock_damage = (tesla_flags & TESLA_MOB_DAMAGE)? (min(round(power/600), 90) + rand(-5, 5)) : 0 - closest_mob.electrocute_act(shock_damage, source, 1, tesla_shock = 1, stun = (tesla_flags & TESLA_MOB_STUN), gib = zap_gib) + closest_mob.electrocute_act(shock_damage, source, 1, zone=null, tesla_shock = 1, stun = (tesla_flags & TESLA_MOB_STUN), gib = zap_gib) if(issilicon(closest_mob)) var/mob/living/silicon/S = closest_mob if((tesla_flags & TESLA_MOB_STUN) && (tesla_flags & TESLA_MOB_DAMAGE)) diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm index 0cdf68ad3a3a..e551f28c6d25 100644 --- a/code/modules/power/turbine.dm +++ b/code/modules/power/turbine.dm @@ -44,7 +44,7 @@ var/intake_ratio = 0.1 // might add a way to adjust this in-game later /obj/machinery/power/compressor/Destroy() - SSair.atmos_machinery.Remove(src) + SSair_machinery.stop_processing_machine(src) if (turbine && turbine.compressor == src) turbine.compressor = null var/turf/T = get_turf(src) @@ -72,7 +72,7 @@ var/productivity = 1 /obj/machinery/power/turbine/Destroy() - SSair.atmos_machinery.Remove(src) + SSair_machinery.stop_processing_machine(src) if (compressor && compressor.turbine == src) compressor.turbine = null compressor = null @@ -91,7 +91,7 @@ /obj/machinery/power/compressor/Initialize(mapload) . = ..() - SSair.atmos_machinery += src + SSair_machinery.start_processing_machine(src) // The inlet of the compressor is the direction it faces gas_contained = new inturf = get_step(src, dir) @@ -189,7 +189,7 @@ /obj/machinery/power/turbine/Initialize(mapload) . = ..() - SSair.atmos_machinery += src + SSair_machinery.start_processing_machine(src) // The outlet is pointed at the direction of the turbine component outturf = get_step(src, dir) locate_machinery() diff --git a/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm index 00dba2d00014..18607b919aba 100644 --- a/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm +++ b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm @@ -10,12 +10,13 @@ if(!mother) return var/list/map = mother.map - for(var/turf/T in map) - SSair.remove_from_active(T) for(var/turf/open/T in map) if(T.air) - T.air.copy_from_turf(T) - SSair.add_to_active(T) + if(T.initial_gas_mix) + T.air.parse_gas_string(T.initial_gas_mix) + T.set_temperature(T.air.return_temperature()) + else + T.air.copy_from_turf(T) /datum/mapGeneratorModule/bottomLayer/massdelete spawnableAtoms = list() diff --git a/code/modules/projectiles/ammunition/ballistic/shotgun.dm b/code/modules/projectiles/ammunition/ballistic/shotgun.dm index 5f4be6d2453d..10339f83fce3 100644 --- a/code/modules/projectiles/ammunition/ballistic/shotgun.dm +++ b/code/modules/projectiles/ammunition/ballistic/shotgun.dm @@ -231,10 +231,10 @@ /obj/item/ammo_casing/shotgun/hardlight/emp_act(severity) if (. & EMP_PROTECT_SELF) return - variance = 60 // yikes - if(severity == EMP_HEAVY) - pellets = 3 // also yikes - addtimer(CALLBACK(src, PROC_REF(remove_emp)), 10 SECONDS / severity, TIMER_OVERRIDE|TIMER_UNIQUE) + variance = initial(variance) + severity*4 // yikes + if(severity > EMP_LIGHT) + pellets = initial(pellets) * (0.5**(severity / EMP_HEAVY)) // also yikes + addtimer(CALLBACK(src, PROC_REF(remove_emp)), severity SECONDS, TIMER_OVERRIDE|TIMER_UNIQUE) /obj/item/ammo_casing/shotgun/hardlight/proc/remove_emp() variance = initial(variance) diff --git a/code/modules/projectiles/ammunition/energy/special.dm b/code/modules/projectiles/ammunition/energy/special.dm index 6ff05a4c1616..0aadae394955 100644 --- a/code/modules/projectiles/ammunition/energy/special.dm +++ b/code/modules/projectiles/ammunition/energy/special.dm @@ -4,7 +4,7 @@ fire_sound = 'sound/weapons/ionrifle.ogg' /obj/item/ammo_casing/energy/ion/hos - projectile_type = /obj/projectile/ion/light + projectile_type = /obj/projectile/ion/weak e_cost = 200 /obj/item/ammo_casing/energy/ion/weak diff --git a/code/modules/projectiles/ammunition/reusable/arrow.dm b/code/modules/projectiles/ammunition/reusable/arrow.dm index 933c10d0511a..c367fdcfbac6 100644 --- a/code/modules/projectiles/ammunition/reusable/arrow.dm +++ b/code/modules/projectiles/ammunition/reusable/arrow.dm @@ -464,23 +464,23 @@ if(/obj/item/singularity_shard/stage2) break_chance = 0.5 rads_released = 200 - empulse(src, 0, 1) + empulse(src, 1) if(/obj/item/singularity_shard/stage3) break_chance = 1.5 rads_released = 500 - empulse(src, 0, 3) + empulse(src, 3) if(/obj/item/singularity_shard/stage4) break_chance = 5 rads_released = 1000 - empulse(src, 1, 5) + empulse(src, 5) if(/obj/item/singularity_shard/stage5) break_chance = 10 rads_released = 2000 - empulse(src, 2, 7) + empulse(src, 7) if(/obj/item/singularity_shard/stage6) break_chance = 100 rads_released = 3000 - empulse(src, 5, 15) // Its going to break open into a singulo anyways, may as well add some fireworks + empulse(src, 15) // Its going to break open into a singulo anyways, may as well add some fireworks // Handles releasing rads if(rads_released) diff --git a/code/modules/projectiles/ammunition/special/reagent.dm b/code/modules/projectiles/ammunition/special/reagent.dm new file mode 100644 index 000000000000..525c8b52614f --- /dev/null +++ b/code/modules/projectiles/ammunition/special/reagent.dm @@ -0,0 +1,24 @@ +/obj/item/ammo_casing/reagent + name = "pressurized liquid" + desc = "You shouldn't be seeing this!" + projectile_type = /obj/projectile/reagent + firing_effect_type = null + +/obj/item/ammo_casing/reagent/Initialize(mapload) + . = ..() + create_reagents(10, OPENCONTAINER_NOSPILL) + +/obj/item/ammo_casing/reagent/newshot(new_volume) + if(!isnull(new_volume)) + reagents.maximum_volume = new_volume + return ..() + + +/obj/item/ammo_casing/reagent/ready_proj(atom/target, mob/living/user, quiet, zone_override, atom/fired_from) + var/obj/item/gun/gun = loc + if(gun.reagents && !reagents.total_volume) + gun.reagents.trans_to(src, reagents.maximum_volume, transfered_by = user) + return ..() + +/obj/item/ammo_casing/reagent/water + projectile_type = /obj/projectile/reagent/water diff --git a/code/modules/projectiles/boxes_magazines/external/rechargable.dm b/code/modules/projectiles/boxes_magazines/external/rechargable.dm index c9a5c0dea3f1..7556ca1c68a3 100644 --- a/code/modules/projectiles/boxes_magazines/external/rechargable.dm +++ b/code/modules/projectiles/boxes_magazines/external/rechargable.dm @@ -102,7 +102,7 @@ . = ..() if(!(. & EMP_PROTECT_CONTENTS)) var/bullet_count = ammo_count() - var/bullets_to_remove = round(bullet_count / (severity*2)) + var/bullets_to_remove = round(bullet_count * (0.5**(severity/EMP_HEAVY))) for(var/i = 0; i < bullets_to_remove, i++) qdel(get_round()) update_appearance(UPDATE_ICON) @@ -111,8 +111,8 @@ if(!G.magazine == src) return G.semicd = TRUE - // 5-10 seconds depending on severity, then give or take 0.2 seconds to prevent piercing ears - var/unjam_time = ((10/severity) + (rand(-20,20)*0.01)) SECONDS + // up to 10 seconds depending on severity, then give or take 0.2 seconds to prevent piercing ears + var/unjam_time = (min(severity, EMP_HEAVY) + (rand(-20,20)*0.01)) SECONDS addtimer(CALLBACK(G, TYPE_PROC_REF(/obj/item/gun, reset_semicd)), unjam_time) /obj/item/ammo_casing/caseless/c22hl diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index d6a14d12ec03..7d2e06ec1d04 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -36,11 +36,11 @@ /obj/item/gun/energy/emp_act(severity) . = ..() if(!(. & EMP_PROTECT_CONTENTS)) - cell.use(round(cell.charge / (severity*2))) + cell.use(round(cell.charge * (0.5**(severity/EMP_HEAVY)))) emp_jammed = TRUE deltimer(emp_jam_timer) - // 5-10 seconds depending on severity, then give or take 0.2 seconds to prevent piercing ears - var/unjam_time = ((10/severity) + (rand(-20,20)*0.01)) SECONDS + // up to 10 seconds depending on severity, then give or take 0.2 seconds to prevent piercing ears + var/unjam_time = (min(severity, EMP_HEAVY) + (rand(-20,20)*0.01)) SECONDS emp_jam_timer = addtimer(CALLBACK(src, PROC_REF(emp_unjam)), unjam_time, TIMER_STOPPABLE) chambered = null //we empty the chamber recharge_newshot() //and try to charge a new shot diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm index 477fbd5520ce..d6dadf6ccf50 100644 --- a/code/modules/projectiles/guns/misc/beam_rifle.dm +++ b/code/modules/projectiles/guns/misc/beam_rifle.dm @@ -425,6 +425,7 @@ armor_flag = ENERGY range = 150 jitter = 10 + demolition_mod = 4 var/obj/item/gun/gun var/structure_pierce_amount = 0 //All set to 0 so the gun can manually set them during firing. var/structure_bleed_coeff = 0 diff --git a/code/modules/projectiles/guns/misc/hyper_soaker.dm b/code/modules/projectiles/guns/misc/hyper_soaker.dm new file mode 100644 index 000000000000..b0d0775b9493 --- /dev/null +++ b/code/modules/projectiles/guns/misc/hyper_soaker.dm @@ -0,0 +1,96 @@ +/obj/item/gun/water + name = "donksoft hyper-soaker" + desc = "Harmless fun, unless you're allergic to water." + icon_state = "water" + item_state = "water" + w_class = WEIGHT_CLASS_NORMAL + clumsy_check = 0 // we do a little trolling + fire_sound = 'sound/effects/spray2.ogg' + var/reagent_volume = 250 + var/transfer_volume = 10 + var/ammo_type = /obj/item/ammo_casing/reagent/water + +/obj/item/gun/water/syndicate + reagent_volume = 600 + transfer_volume = 30 + +/obj/item/gun/water/Initialize(mapload) + . = ..() + create_reagents(reagent_volume, REFILLABLE|DRAINABLE|AMOUNT_VISIBLE) + +/// Pre-filled version +/obj/item/gun/water/full/Initialize(mapload) + . = ..() + reagents.add_reagent(/datum/reagent/water, reagent_volume) + +/obj/item/gun/water/examine(mob/user) + . = ..() + . += "Alt-click to empty its contents onto the floor." + +/obj/item/gun/water/AltClick(mob/user) + . = ..() + if(!reagents.total_volume) + return + to_chat(user, span_notice("You empty [src] onto the floor.")) + reagents.reaction(get_turf(user), TOUCH) // spills onto the floor + reagents.clear_reagents() + +/obj/item/gun/water/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + if(!proximity_flag) + return + if(istype(target, /obj/structure/reagent_dispensers)) + var/trans_amount = target.reagents.trans_to(src, reagent_volume) + if(trans_amount) + to_chat(user, span_notice("You refill [src] from [target].")) + else if(target.is_refillable()) + var/trans_amount = reagents.trans_to(target, 10) + if(trans_amount) + to_chat(user, span_notice("You transfer [trans_amount] units to [target].")) + +/obj/item/gun/water/can_shoot() + return (reagents.total_volume > 1) + +/obj/item/gun/water/recharge_newshot() + chambered = new ammo_type(src) + chambered.newshot(transfer_volume) + +/obj/item/gun/water/process_chamber() + chambered = null + recharge_newshot() + +/obj/item/gun/water/process_fire(atom/target, mob/living/user, message, params, zone_override, bonus_spread, cd_override) + if(!chambered && can_shoot()) + process_chamber() // If the gun was drained and then recharged, load a new shot. + if(reagent_check()) + return + return ..() + +/obj/item/gun/water/process_burst(mob/living/user, atom/target, message, params, zone_override, sprd, randomized_gun_spread, randomized_bonus_spread, rand_spr, iteration) + if(!chambered && can_shoot()) + process_chamber() // If the gun was drained and then recharged, load a new shot. + if(reagent_check()) + return + return ..() + +/obj/item/gun/water/proc/reagent_check() + var/atom/starting_loc = loc + for(var/datum/reagent/R as anything in reagents.reagent_list) + R.reaction_obj(src, R.volume) // dangerous chemicals can damage the gun (or teleport it lmao) + if(QDELETED(src)) + return TRUE + if(loc != starting_loc) + reagents.clear_reagents() + if(chambered) + qdel(chambered) + chambered = null + return TRUE // the gun broke or moved so you didn't actually get to shoot it + +// overlay for water levels +/obj/item/gun/water/update_overlays() + . = ..() + var/water_state = ROUND_UP(5 * reagents.total_volume / reagents.maximum_volume) + if(!water_state) + return . + var/mutable_appearance/water_overlay = mutable_appearance(icon, "water-tank[water_state]") + . += water_overlay diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index fd9b2520b42d..ebef6ac497c6 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -14,7 +14,6 @@ light_system = MOVABLE_LIGHT light_range = 2 light_color = LIGHT_COLOR_RED - light_flags = LIGHT_NO_LUMCOUNT ricochets_max = 50 //Honk! ricochet_chance = 80 reflectable = REFLECT_NORMAL @@ -154,6 +153,7 @@ damage = 30 wound_bonus = -40 bare_wound_bonus = 70 + demolition_mod = 3 // industrial laser impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser light_color = LIGHT_COLOR_GREEN diff --git a/code/modules/projectiles/projectile/bullets/_incendiary.dm b/code/modules/projectiles/projectile/bullets/_incendiary.dm index cb61ee5b7bb0..1a6ed1323113 100644 --- a/code/modules/projectiles/projectile/bullets/_incendiary.dm +++ b/code/modules/projectiles/projectile/bullets/_incendiary.dm @@ -1,6 +1,7 @@ /obj/projectile/bullet/incendiary damage = 20 var/fire_stacks = 4 + demolition_mod = 0.75 /obj/projectile/bullet/incendiary/on_hit(atom/target, blocked = FALSE) . = ..() diff --git a/code/modules/projectiles/projectile/bullets/pistol.dm b/code/modules/projectiles/projectile/bullets/pistol.dm index b67fe3a84c43..e9383f89b2dc 100644 --- a/code/modules/projectiles/projectile/bullets/pistol.dm +++ b/code/modules/projectiles/projectile/bullets/pistol.dm @@ -64,7 +64,7 @@ /obj/projectile/bullet/c10mm/emp/on_hit(atom/target, blocked = FALSE) ..() - empulse(target, 0.5, 1) //Heavy EMP on target, light EMP in tiles around + empulse(target, EMP_HEAVY, 1) //Heavy EMP on target, light EMP in tiles around /obj/projectile/bullet/boltpistol name = "Bolt round" diff --git a/code/modules/projectiles/projectile/bullets/rifle.dm b/code/modules/projectiles/projectile/bullets/rifle.dm index d2f1edeec1bd..c476a18556f8 100644 --- a/code/modules/projectiles/projectile/bullets/rifle.dm +++ b/code/modules/projectiles/projectile/bullets/rifle.dm @@ -44,6 +44,7 @@ damage = 60 wound_bonus = -35 wound_falloff_tile = 0 + demolition_mod = 1.2 /obj/projectile/bullet/a762/raze name = "7.62mm Raze bullet" @@ -63,6 +64,7 @@ penetrating = TRUE //Passes through two objects, stops on a mob or on a third object penetrations = 2 penetration_type = 1 + demolition_mod = 1.5 // anti-armor /obj/projectile/bullet/a762/vulcan name = "7.62mm Vulcan bullet" diff --git a/code/modules/projectiles/projectile/bullets/shotgun.dm b/code/modules/projectiles/projectile/bullets/shotgun.dm index 79acfac73304..fbec1b20f8bc 100644 --- a/code/modules/projectiles/projectile/bullets/shotgun.dm +++ b/code/modules/projectiles/projectile/bullets/shotgun.dm @@ -6,6 +6,7 @@ damage = 46 //About 2/3's the damage of buckshot but doesn't suffer from spread or negative AP sharpness = SHARP_POINTY wound_bonus = -30 + demolition_mod = 2 // good at smashing through stuff /obj/projectile/bullet/shotgun/slug/syndie name = "12g syndicate shotgun slug" @@ -74,6 +75,7 @@ damage = 35 //Most certainly to drop below 3-shot threshold because of damage falloff armour_penetration = 60 // he he funny round go through armor wound_bonus = -40 + demolition_mod = 3 // very good at smashing through stuff penetrating = TRUE //Goes through an infinite number of mobs /obj/projectile/bullet/shotgun/slug/Range() @@ -88,6 +90,7 @@ var/tile_dropoff = 0.4 var/tile_dropoff_s = 0.3 armour_penetration = -20 //Armor is 25% stronger against pellets + demolition_mod = 0.5 // bad at smashing through stuff /obj/projectile/bullet/pellet/shotgun_buckshot name = "buckshot pellet" @@ -200,10 +203,11 @@ desc = "A breaching round designed to destroy airlocks and windows with only a few shots, but is ineffective against other targets." hitsound = 'sound/weapons/sonic_jackhammer.ogg' damage = 10 //does shit damage to everything except doors and windows + demolition_mod = 6 //not that bad at breaking things /obj/projectile/bullet/shotgun/slug/breaching/on_hit(atom/target) - if(istype(target, /obj/structure/window) || istype(target, /obj/machinery/door) || istype(target, /obj/structure/door_assembly)) - damage = 500 //one shot to break a window or 3 shots to breach an airlock door + if(istype(target, /obj/structure/window) || istype(target, /obj/machinery/door) || istype(target, /obj/structure/door_assembly) || istype(target, /obj/structure/grille)) + demolition_mod = 50 //one shot to break a window or 3 shots to breach an airlock door ..() /obj/projectile/bullet/pellet/hardlight diff --git a/code/modules/projectiles/projectile/bullets/sniper.dm b/code/modules/projectiles/projectile/bullets/sniper.dm index a845ad1bb599..262bec69a77f 100644 --- a/code/modules/projectiles/projectile/bullets/sniper.dm +++ b/code/modules/projectiles/projectile/bullets/sniper.dm @@ -7,13 +7,7 @@ paralyze = 100 dismemberment = 50 armour_penetration = 50 - var/breakthings = TRUE - -/obj/projectile/bullet/p50/on_hit(atom/target, blocked = 0) - if(isobj(target) && (blocked != 100) && breakthings) - var/obj/O = target - O.take_damage(80, BRUTE, BULLET, FALSE, null, armour_penetration) - return ..() + demolition_mod = 2.2 // very effective against armored structures and vehicles /obj/projectile/bullet/p50/soporific name = ".50 soporific bullet" @@ -21,7 +15,6 @@ damage = 0 dismemberment = 0 paralyze = 0 - breakthings = FALSE /obj/projectile/bullet/p50/soporific/on_hit(atom/target, blocked = FALSE) if((blocked != 100) && isliving(target)) diff --git a/code/modules/projectiles/projectile/energy/stun.dm b/code/modules/projectiles/projectile/energy/stun.dm index 2a3d794ef06b..00961f96658f 100644 --- a/code/modules/projectiles/projectile/energy/stun.dm +++ b/code/modules/projectiles/projectile/energy/stun.dm @@ -20,7 +20,7 @@ var/mob/living/carbon/C = target SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "tased", /datum/mood_event/tased) SEND_SIGNAL(C, COMSIG_LIVING_MINOR_SHOCK) - if(C.dna && (C.dna.check_mutation(HULK) || C.dna.check_mutation(ACTIVE_HULK))) + if(C.dna && (C.dna.check_mutation(HULK))) C.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk") else if((C.status_flags & CANKNOCKDOWN) && !HAS_TRAIT(C, TRAIT_STUNIMMUNE)) addtimer(CALLBACK(C, TYPE_PROC_REF(/mob/living/carbon, do_jitter_animation), jitter), 5) diff --git a/code/modules/projectiles/projectile/energy/tesla.dm b/code/modules/projectiles/projectile/energy/tesla.dm index 4bf110af9963..893d14488707 100644 --- a/code/modules/projectiles/projectile/energy/tesla.dm +++ b/code/modules/projectiles/projectile/energy/tesla.dm @@ -2,6 +2,7 @@ name = "tesla bolt" icon_state = "tesla_projectile" impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser + armor_flag = ELECTRIC var/chain var/tesla_flags = TESLA_MOB_DAMAGE | TESLA_OBJ_DAMAGE var/zap_range = 3 diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index 5b2cb0c7b0de..0f4a9cd6d130 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -1102,10 +1102,10 @@ nodamage = TRUE armor_flag = ENERGY impact_effect_type = /obj/effect/temp_visual/impact_effect/ion - var/light_emp_radius = 3 - var/heavy_emp_radius = 0.5 //Effectively 1 but doesnt spread to adjacent tiles + var/ion_severity = EMP_HEAVY //Heavy EMP effect that doesn't spread to adjacent tiles + var/ion_range = 3 /obj/projectile/magic/ion/on_hit(atom/target, blocked = FALSE) ..() - empulse(target, heavy_emp_radius, light_emp_radius) + empulse(target, ion_severity, ion_range) return BULLET_ACT_HIT diff --git a/code/modules/projectiles/projectile/reusable/arrow.dm b/code/modules/projectiles/projectile/reusable/arrow.dm index dd6dcbfdfb67..6b615926d848 100644 --- a/code/modules/projectiles/projectile/reusable/arrow.dm +++ b/code/modules/projectiles/projectile/reusable/arrow.dm @@ -289,7 +289,7 @@ var/mob/living/carbon/C = target SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "tased", /datum/mood_event/tased) SEND_SIGNAL(C, COMSIG_LIVING_MINOR_SHOCK) - if(C.dna && (C.dna.check_mutation(HULK) || C.dna.check_mutation(ACTIVE_HULK))) + if(C.dna && (C.dna.check_mutation(HULK))) C.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk") else if((C.status_flags & CANKNOCKDOWN) && !HAS_TRAIT(C, TRAIT_STUNIMMUNE)) addtimer(CALLBACK(C, TYPE_PROC_REF(/mob/living/carbon, do_jitter_animation), jitter), 5) diff --git a/code/modules/projectiles/projectile/special/hallucination.dm b/code/modules/projectiles/projectile/special/hallucination.dm index 58234a8a9001..e6a31bc9e621 100644 --- a/code/modules/projectiles/projectile/special/hallucination.dm +++ b/code/modules/projectiles/projectile/special/hallucination.dm @@ -168,7 +168,7 @@ /obj/projectile/hallucination/taser/hal_apply_effect() hal_target.Paralyze(100) hal_target.adjust_stutter(2 SECONDS) - if(hal_target.dna && (hal_target.dna.check_mutation(HULK)|| hal_target.dna.check_mutation(ACTIVE_HULK))) + if(hal_target.dna && (hal_target.dna.check_mutation(HULK))) hal_target.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk") else if((hal_target.status_flags & CANKNOCKDOWN) && !HAS_TRAIT(hal_target, TRAIT_STUNIMMUNE)) addtimer(CALLBACK(hal_target, TYPE_PROC_REF(/mob/living/carbon, do_jitter_animation), 20), 0.5 SECONDS) diff --git a/code/modules/projectiles/projectile/special/ion.dm b/code/modules/projectiles/projectile/special/ion.dm index 4de29713c471..82675908b7cd 100644 --- a/code/modules/projectiles/projectile/special/ion.dm +++ b/code/modules/projectiles/projectile/special/ion.dm @@ -6,22 +6,18 @@ nodamage = TRUE armor_flag = ENERGY impact_effect_type = /obj/effect/temp_visual/impact_effect/ion - var/light_emp_radius = 1 - var/heavy_emp_radius = 0.5 //Effectively 1 but doesnt spread to adjacent tiles + var/ion_severity = EMP_HEAVY // Heavy EMP effects that don't spread to adjacent tiles + var/ion_range = 1 /obj/projectile/ion/on_hit(atom/target, blocked = FALSE) ..() - empulse(target, heavy_emp_radius, light_emp_radius) + empulse(target, ion_severity, ion_range) return BULLET_ACT_HIT /obj/projectile/ion/weak - light_emp_radius = 0 - heavy_emp_radius = 0 - -/obj/projectile/ion/light - light_emp_radius = 1 - heavy_emp_radius = 0 + ion_severity = EMP_LIGHT // weak ions + ion_range = 0 /obj/projectile/ion/heavy - light_emp_radius = 2 - heavy_emp_radius = 2 + ion_severity = 15 // STRONG ions + ion_range = 2 diff --git a/code/modules/projectiles/projectile/special/neurotoxin.dm b/code/modules/projectiles/projectile/special/neurotoxin.dm deleted file mode 100644 index adf51f8c7107..000000000000 --- a/code/modules/projectiles/projectile/special/neurotoxin.dm +++ /dev/null @@ -1,14 +0,0 @@ -/obj/projectile/bullet/neurotoxin - name = "neurotoxin spit" - icon_state = "neurotoxin" - damage = 5 - damage_type = TOX - armor_flag = BIO // why was this bullet protection - -/obj/projectile/bullet/neurotoxin/on_hit(atom/target, blocked = FALSE) - if(isalien(target)) - nodamage = TRUE - else if(iscarbon(target)) - var/mob/living/carbon/H = target - H.reagents.add_reagent(/datum/reagent/toxin/staminatoxin/neurotoxin_alien, 10 * H.get_permeability()) - return ..() diff --git a/code/modules/projectiles/projectile/special/plasma.dm b/code/modules/projectiles/projectile/special/plasma.dm index 3e027fcee9c8..63f46d4e7785 100644 --- a/code/modules/projectiles/projectile/special/plasma.dm +++ b/code/modules/projectiles/projectile/special/plasma.dm @@ -6,6 +6,7 @@ damage = 5 range = 4 dismemberment = 20 + demolition_mod = 2 // industrial strength plasma cutter designed to cut things impact_effect_type = /obj/effect/temp_visual/impact_effect/purple_laser var/mine_range = 3 //mines this many additional tiles of rock tracer_type = /obj/effect/projectile/tracer/plasma_cutter @@ -13,7 +14,6 @@ impact_type = /obj/effect/projectile/impact/plasma_cutter light_system = MOVABLE_LIGHT light_color = LIGHT_COLOR_PURPLE - light_flags = LIGHT_NO_LUMCOUNT light_range = 2 /obj/projectile/plasma/weak diff --git a/code/modules/projectiles/projectile/special/reagent.dm b/code/modules/projectiles/projectile/special/reagent.dm new file mode 100644 index 000000000000..524180486c7b --- /dev/null +++ b/code/modules/projectiles/projectile/special/reagent.dm @@ -0,0 +1,55 @@ +/obj/projectile/reagent + name = "\proper reagents" + icon = 'icons/obj/chempuff.dmi' + icon_state = "" + damage_type = TOX + damage = 0 + armor_flag = BIO + nodamage = TRUE + speed = 1.2 // slow projectile + /// Reagent application methods + var/transfer_methods = TOUCH + var/list/reagents_list = list() + +/obj/projectile/reagent/Initialize(mapload) + . = ..() + create_reagents(1000) + +/obj/projectile/reagent/proc/update_reagents() + if(!reagents.total_volume) // if it didn't already have reagents in it, fill it with the default reagents + for(var/type in reagents_list) + reagents.add_reagent(type, reagents_list[type]) + add_atom_colour(mix_color_from_reagents(reagents.reagent_list), FIXED_COLOUR_PRIORITY) + +/obj/projectile/reagent/fire(angle, atom/direct_target) + update_reagents() + return ..() + +/obj/projectile/reagent/on_hit(atom/target, blocked = FALSE) + var/hit = ..() + if(blocked < 100 && (hit & BULLET_ACT_HIT)) + log_combat(firer, target, "shot", src, addition = "with a projectile containing [reagents.log_list()]") + reagents.reaction(target, transfer_methods) + reagents.reaction(get_turf(target), transfer_methods) + return hit + + +/// Water - for water guns! Just some harmless fun... right?? +/obj/projectile/reagent/water + name = "\proper water" + reagents_list = list(/datum/reagent/water = 10) + +/obj/projectile/reagent/water/update_reagents() + . = ..() + var/last_volume = 0 + for(var/datum/reagent/R as anything in reagents.reagent_list) + if(R.volume > last_volume) + last_volume = R.volume + name = "\proper [lowertext(R.name)]" + +/// Xeno neurotoxin +/obj/projectile/reagent/neurotoxin + name = "neurotoxin spit" + icon = 'icons/obj/projectiles.dmi' + icon_state = "neurotoxin" + reagents_list = list(/datum/reagent/toxin/staminatoxin/neurotoxin_alien = 10) diff --git a/code/modules/projectiles/projectile/special/rocket.dm b/code/modules/projectiles/projectile/special/rocket.dm index a0df35e83b00..3d220e4842a3 100644 --- a/code/modules/projectiles/projectile/special/rocket.dm +++ b/code/modules/projectiles/projectile/special/rocket.dm @@ -12,21 +12,15 @@ name ="\improper HEDP rocket" desc = "USE A WEEL GUN" icon_state= "84mm-hedp" + armor_flag = BOMB damage = 80 - var/anti_armour_damage = 200 + demolition_mod = 4 armour_penetration = 100 dismemberment = 100 /obj/projectile/bullet/a84mm/on_hit(atom/target, blocked = FALSE) ..() explosion(target, -1, 1, 3, 1, 0, flame_range = 4) - - if(ismecha(target)) - var/obj/mecha/M = target - M.take_damage(anti_armour_damage, BRUTE, BOMB, FALSE, null, armour_penetration) - if(issilicon(target)) - var/mob/living/silicon/S = target - S.take_overall_damage(anti_armour_damage*0.75, anti_armour_damage*0.25) return BULLET_ACT_HIT /obj/projectile/bullet/a84mm_he @@ -34,6 +28,7 @@ desc = "Boom." icon_state = "missile" damage = 30 + demolition_mod = 4 ricochets_max = 0 //it's a MISSILE /obj/projectile/bullet/a84mm_he/on_hit(atom/target, blocked=0) @@ -49,6 +44,7 @@ desc = "Boom." icon_state = "missile" damage = 30 + demolition_mod = 4 ricochets_max = 0 //it's a MISSILE var/sturdy = list( /turf/closed, @@ -79,22 +75,18 @@ icon_state = "cannonball" desc = "Not for bowling purposes" damage = 30 + demolition_mod = 20 // YARRR /obj/projectile/bullet/cball/on_hit(atom/target, blocked=0) - var/mob/living/carbon/human/H = firer - var/atom/throw_target = get_edge_target_turf(target, H.dir) - if(istype(target, /obj/structure/window) || istype(target, /obj/machinery/door) || istype(target, /obj/structure/door_assembly)) - damage = 500 - ..() - if(isliving(target)) - var/mob/living/L = target - if(!L.anchored && !L.throwing)//avoid double hits - if(iscarbon(L)) - var/mob/living/carbon/C = L - var/mob/M = firer - if(istype(M)) - C.throw_at(throw_target, 2, 4, H, 3) - return BULLET_ACT_HIT + var/atom/throw_target = get_edge_target_turf(target, firer.dir) + if(ismecha(target) || isliving(target)) + demolition_mod = 5 // woah there let's not one-shot mechs and borgs + . = ..() + if(!ismovable(target)) // if it's not movable then don't bother trying to throw it + return + var/atom/movable/movable_target = target + if(!movable_target.anchored && !movable_target.throwing)//avoid double hits + movable_target.throw_at(throw_target, 2, 4, firer, 3) /obj/projectile/bullet/bolt name = "bolt" diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 6036fbca421c..207e13497cf6 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -2726,3 +2726,22 @@ All effects don't start immediately, but rather get worse over time; the rate is M.physiology.do_after_speed /= alcoholicspeed M.next_move_modifier /= alcoholicspeed return ..() + +/datum/reagent/consumable/ethanol/wine_voltaic + name = "Voltaic Yellow Wine" + description = "Electrically charged wine. Recharges ethereals, but also nontoxic." + boozepwr = 30 + color = "#FFAA00" + quality = DRINK_GOOD + taste_description = "static with a hint of sweetness" + glass_icon_state = "wine_voltaic" + glass_name = "Voltaic Yellow Wine" + glass_desc = "Shocking, not stirred." + +/datum/reagent/consumable/ethanol/wine_voltaic/on_mob_life(mob/living/carbon/M) + if(HAS_TRAIT(M, TRAIT_POWERHUNGRY)) + M.adjust_nutrition(nutriment_factor) + else if(prob(25)) + M.electrocute_act(rand(10,15), "Liquid Electricity in their body", 1) //lmao at the newbs who eat energy bars + playsound(M, "sparks", 50, 1) + return ..() diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index 8e67b9a4c82f..b7af79856259 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -475,10 +475,9 @@ T.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = reac_volume*2 SECONDS) var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T) if(hotspot) - var/datum/gas_mixture/lowertemp = T.remove_air(T.air.total_moles()) - lowertemp.set_temperature(max( min(lowertemp.return_temperature()-2000,lowertemp.return_temperature() / 2) ,0)) + var/datum/gas_mixture/lowertemp = T.return_air() + lowertemp.set_temperature(max( min(lowertemp.return_temperature()-2000,lowertemp.return_temperature() / 2) ,TCMB)) lowertemp.react(src) - T.assume_air(lowertemp) qdel(hotspot) /datum/reagent/consumable/enzyme diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 12ffd62ff208..86225ee4f94d 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -121,7 +121,7 @@ /datum/reagent/water name = "Water" description = "An ubiquitous chemical substance that is composed of hydrogen and oxygen." - color = "#AAAAAA77" // rgb: 170, 170, 170, 77 (alpha) + color = "#609bdf77" // rgb: 96, 155, 223, 77 (alpha) taste_description = "water" var/cooling_temperature = 2 glass_icon_state = "glass_clear" @@ -192,8 +192,16 @@ M.AdjustUnconscious(-reac_volume*0.3 SECONDS) M.AdjustSleeping(-reac_volume*0.5 SECONDS) - M.adjust_wet_stacks((reac_volume / 10) * M.get_permeability(null, TRUE)) + // this function allows lower volumes to still do something without preventing higher volumes from causing too much wetness + M.adjust_wet_stacks(3*log(2, (reac_volume*M.get_permeability(null, TRUE) + 10) / 10)) M.extinguish_mob() // permeability affects the negative fire stacks but not the extinguishing + + // if preternis, update wetness instantly when applying more water instead of waiting for the next life tick + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/datum/species/preternis/P = H.dna?.species + if(istype(P)) + P.handle_wetness(H) ..() /datum/reagent/water/on_mob_life(mob/living/carbon/M) @@ -840,12 +848,6 @@ color = "#808080" // rgb: 128, 128, 128 taste_mult = 0 // oderless and tasteless -/datum/reagent/oxygen/reaction_obj(obj/O, reac_volume) - if((!O) || (!reac_volume)) - return 0 - var/temp = holder ? holder.chem_temp : T20C - O.atmos_spawn_air("o2=[reac_volume/2];TEMP=[temp]") - /datum/reagent/oxygen/reaction_turf(turf/open/T, reac_volume) if(istype(T)) var/temp = holder ? holder.chem_temp : T20C @@ -873,12 +875,6 @@ color = "#808080" // rgb: 128, 128, 128 taste_mult = 0 -/datum/reagent/nitrogen/reaction_obj(obj/O, reac_volume) - if((!O) || (!reac_volume)) - return 0 - var/temp = holder ? holder.chem_temp : T20C - O.atmos_spawn_air("n2=[reac_volume/2];TEMP=[temp]") - /datum/reagent/nitrogen/reaction_turf(turf/open/T, reac_volume) if(istype(T)) var/temp = holder ? holder.chem_temp : T20C @@ -1087,7 +1083,12 @@ /datum/reagent/bluespace/reaction_mob(mob/living/M, methods=TOUCH, reac_volume) if((methods & (TOUCH|VAPOR)) && (reac_volume > 5)) do_teleport(M, get_turf(M), (reac_volume / 5), asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) //4 tiles per crystal - ..() + return ..() + +/datum/reagent/bluespace/reaction_obj(obj/O, volume) + if(volume > 5 && !O.anchored) // can teleport objects that aren't anchored + do_teleport(O, get_turf(O), (volume / 5), asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) //4 tiles per crystal + return ..() /datum/reagent/bluespace/on_mob_life(mob/living/carbon/M) if(current_cycle > 10 && prob(15)) @@ -1345,12 +1346,6 @@ color = "#B0B0B0" // rgb : 192, 192, 192 taste_description = "something unknowable" -/datum/reagent/carbondioxide/reaction_obj(obj/O, reac_volume) - if((!O) || (!reac_volume)) - return 0 - var/temp = holder ? holder.chem_temp : T20C - O.atmos_spawn_air("co2=[reac_volume/5];TEMP=[temp]") - /datum/reagent/carbondioxide/reaction_turf(turf/open/T, reac_volume) if(istype(T)) var/temp = holder ? holder.chem_temp : T20C @@ -1365,12 +1360,6 @@ color = "#808080" taste_description = "sweetness" -/datum/reagent/nitrous_oxide/reaction_obj(obj/O, reac_volume) - if((!O) || (!reac_volume)) - return 0 - var/temp = holder ? holder.chem_temp : T20C - O.atmos_spawn_air("n2o=[reac_volume/5];TEMP=[temp]") - /datum/reagent/nitrous_oxide/reaction_turf(turf/open/T, reac_volume) if(istype(T)) var/temp = holder ? holder.chem_temp : T20C diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm index 15aecc9a0582..e160e15ce9ff 100644 --- a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm @@ -219,22 +219,45 @@ self_consuming = TRUE compatible_biotypes = ALL_BIOTYPES var/shock_timer = 0 + var/teslium_trip = FALSE /datum/reagent/teslium/on_mob_metabolize(mob/living/L) . = ..() ADD_TRAIT(L, TRAIT_EMPPROOF_SELF, "teslium") + if(ispreternis(L)) //no clue why preterni function this way, but why not (makes more sense for ethereals honestly) + L.add_movespeed_modifier(type, TRUE, priority=101, multiplicative_slowdown=-3, blacklisted_movetypes=(FLYING|FLOATING)) + teslium_trip = TRUE + if(ishuman(L)) + var/mob/living/carbon/human/H = L + H.physiology.burn_mod *= 10 /datum/reagent/teslium/on_mob_life(mob/living/carbon/M) shock_timer++ if(shock_timer >= rand(5,30)) //Random shocks are wildly unpredictable shock_timer = 0 - M.electrocute_act(rand(5,20), "Teslium in their body", 1, 1) //Override because it's caused from INSIDE of you + var/shock_damage = rand(5,20) + M.electrocute_act(shock_damage, "Teslium in their body", 1, zone=null, override=TRUE) //Override because it's caused from INSIDE of you playsound(M, "sparks", 50, 1) + + if(HAS_TRAIT(M, TRAIT_POWERHUNGRY)) //twice as effective as liquid electricity + M.adjust_nutrition(10 * REAGENTS_METABOLISM) + + if(teslium_trip) + M.adjustOxyLoss(-2 * REAGENTS_EFFECT_MULTIPLIER) + M.adjustBruteLoss(-2 * REAGENTS_EFFECT_MULTIPLIER, TRUE, FALSE, BODYPART_ANY) + M.adjustFireLoss(-2 * REAGENTS_EFFECT_MULTIPLIER, TRUE, FALSE, BODYPART_ANY) + M.AdjustAllImmobility(-3) + M.adjustStaminaLoss(-5 * REAGENTS_EFFECT_MULTIPLIER) ..() /datum/reagent/teslium/on_mob_end_metabolize(mob/living/L) . = ..() REMOVE_TRAIT(L, TRAIT_EMPPROOF_SELF, "teslium") + if(teslium_trip) + L.remove_movespeed_modifier(type, TRUE) + if(ishuman(L)) + var/mob/living/carbon/human/H = L + H.physiology.burn_mod /= 10 /datum/reagent/teslium/energized_jelly name = "Energized Jelly" diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 7ce23f0c061f..b4d7d89552f9 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -75,12 +75,6 @@ toxpwr = initial(toxpwr) return ..() -/datum/reagent/toxin/plasma/reaction_obj(obj/O, reac_volume) - if((!O) || (!reac_volume)) - return 0 - var/temp = holder ? holder.chem_temp : T20C - O.atmos_spawn_air("plasma=[reac_volume];TEMP=[temp]") - /datum/reagent/toxin/plasma/reaction_turf(turf/open/T, reac_volume) if(istype(T)) var/temp = holder ? holder.chem_temp : T20C @@ -415,6 +409,13 @@ glass_desc = "A drink that is guaranteed to knock you silly." var/list/paralyzeparts = list(TRAIT_PARALYSIS_L_ARM, TRAIT_PARALYSIS_R_ARM, TRAIT_PARALYSIS_R_LEG, TRAIT_PARALYSIS_L_LEG) +/datum/reagent/toxin/staminatoxin/neurotoxin_alien/reaction_mob(mob/living/M, methods, reac_volume, show_message, permeability) + . = ..() + var/amount = round(max(reac_volume * clamp(permeability, 0, 1), 0.1)) + if(amount >= 0.5 && !isalien(M)) + M.reagents.add_reagent(type, amount) + M.apply_damage(reac_volume / 2, TOX, null, (1 - permeability) * 100) + /datum/reagent/toxin/staminatoxin/neurotoxin_alien/proc/pickparalyze() var/selected = pick(paralyzeparts) paralyzeparts -= selected diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm index 438f9b78b3ca..c2a3ce9a7647 100644 --- a/code/modules/reagents/chemistry/recipes/others.dm +++ b/code/modules/reagents/chemistry/recipes/others.dm @@ -50,7 +50,7 @@ /datum/chemical_reaction/glycerol name = "Glycerol" id = /datum/reagent/glycerol - results = list(/datum/reagent/glycerol = 1) + results = list(/datum/reagent/glycerol = 3) required_reagents = list(/datum/reagent/consumable/cornoil = 3, /datum/reagent/toxin/acid = 1) /datum/chemical_reaction/sodiumchloride diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm index c924ef3ab58d..0cc6b163262d 100644 --- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm +++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm @@ -119,10 +119,10 @@ /datum/chemical_reaction/emp_pulse/on_reaction(datum/reagents/holder, created_volume) var/location = get_turf(holder.my_atom) - // 100 created volume = 8 heavy range & 14 light range. 4 tiles larger than traitor EMP grenades. - // 200 created volume = 16 heavy range & 28 light range. 12 tiles larger than traitor EMP grenades. This is the maximum + // 100 created volume = 8 severity & 14 range. 4 tiles larger than traitor EMP grenades. + // 200 created volume = 16 (capped to 10) severity & 28 range. 12 tiles larger than traitor EMP grenades. This is the maximum created_volume = min(created_volume, 200) - empulse(location, round(created_volume / 12), round(created_volume / 7), 1) + empulse(location, min(round(created_volume / 12), EMP_HEAVY), round(created_volume / 7), 1) holder.clear_reagents() diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm index 1eba0a7713dc..bd67368f4b60 100644 --- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm +++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm @@ -291,8 +291,7 @@ if(holder && holder.my_atom) var/turf/open/T = get_turf(holder.my_atom) if(istype(T)) - var/datum/gas/gastype = /datum/gas/nitrogen - T.atmos_spawn_air("[initial(gastype.id)]=50;TEMP=2.7") + T.atmos_spawn_air("n2=50;TEMP=2.7") /datum/chemical_reaction/slime/slimefireproof name = "Slime Fireproof" @@ -355,7 +354,7 @@ required_other = TRUE /datum/chemical_reaction/slime/slimeoverload/on_reaction(datum/reagents/holder, created_volume) - empulse(get_turf(holder.my_atom), 3, 7) + empulse(get_turf(holder.my_atom), 7) ..() /datum/chemical_reaction/slime/slimecell diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 300172d49e3f..72f0eaa5552a 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -125,6 +125,8 @@ if(QDELETED(src)) return + if(!isturf(target)) // it all ends up on the floor because gravity exists + reagents.reaction(get_turf(target), TOUCH) reagents.clear_reagents() /obj/item/reagent_containers/microwave_act(obj/machinery/microwave/M) diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm index 4203c4f99a16..e2b70279b436 100644 --- a/code/modules/recycling/disposal/bin.dm +++ b/code/modules/recycling/disposal/bin.dm @@ -68,10 +68,13 @@ /obj/machinery/disposal/LateInitialize() //this will get a copy of the air turf and take a SEND PRESSURE amount of air from it var/atom/L = loc + var/datum/gas_mixture/loc_air = L.return_air() var/datum/gas_mixture/env = new - env.copy_from(L.return_air()) - var/datum/gas_mixture/removed = env.remove(SEND_PRESSURE + 1) - air_contents.merge(removed) + if(loc_air) + env.copy_from(loc_air) + var/datum/gas_mixture/removed = env.remove(SEND_PRESSURE + 1) + if(removed) + air_contents.merge(removed) trunk_check() /obj/machinery/disposal/attackby(obj/item/I, mob/user, params) @@ -416,14 +419,12 @@ var/datum/gas_mixture/env = L.return_air() var/pressure_delta = (SEND_PRESSURE*1.01) - air_contents.return_pressure() - if(env.return_temperature() > 0) + if(env?.return_temperature() > 0) var/transfer_moles = 0.05 * delta_time * pressure_delta*air_contents.return_volume()/(env.return_temperature() * R_IDEAL_GAS_EQUATION) //Actually transfer the gas var/datum/gas_mixture/removed = env.remove(transfer_moles) air_contents.merge(removed) - air_update_turf() - //if full enough, switch to ready mode if(air_contents.return_pressure() >= SEND_PRESSURE) diff --git a/code/modules/recycling/disposal/holder.dm b/code/modules/recycling/disposal/holder.dm index 9fb68ed63de1..faff4adf8df9 100644 --- a/code/modules/recycling/disposal/holder.dm +++ b/code/modules/recycling/disposal/holder.dm @@ -122,7 +122,6 @@ // called to vent all gas in holder to a location /obj/structure/disposalholder/proc/vent_gas(turf/T) T.assume_air(gas) - T.air_update_turf() /obj/structure/disposalholder/AllowDrop() return TRUE diff --git a/code/modules/research/designs/mecha_designs.dm b/code/modules/research/designs/mecha_designs.dm index 5db8177c36bb..9b5a012ee9cd 100644 --- a/code/modules/research/designs/mecha_designs.dm +++ b/code/modules/research/designs/mecha_designs.dm @@ -555,7 +555,7 @@ category = list("Exosuit Equipment") /datum/design/mech_rocket_fist - name = "Exosuit Weapon (DD-2 \"Atom Smasher\" Rocket Fist)" + name = "Exosuit Weapon (RS-77 \"Atom Smasher\" Rocket Fist)" id = "mech_rocket_fist" build_type = MECHFAB build_path = /obj/item/mecha_parts/mecha_equipment/melee_weapon/rocket_fist @@ -575,7 +575,7 @@ combat_design = TRUE /datum/design/mech_katana - name = "Exosuit Weapon (OWM-5 \"Ronin\" katana)" + name = "Exosuit Weapon (HR-2 \"Ronin\" katana)" id = "mech_katana" build_type = MECHFAB build_path = /obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/katana @@ -605,7 +605,7 @@ combat_design = TRUE /datum/design/mech_maul - name = "Exosuit Weapon (CX-22 \"Barbatos\" heavy maul)" + name = "Exosuit Weapon (ASW-8 \"Barbatos\" heavy maul)" id = "mech_maul" build_type = MECHFAB build_path = /obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/maul diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index f44d3910e13b..eb8ec7b9a1af 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -387,7 +387,7 @@ name = "Chemical Analyzer Implant" desc = "These cybernetic eye implants will allow rapid identification of reagents. Wiggle eyes to control." id = "ci-scihud" - build_type = MECHFAB + build_type = PROTOLATHE | MECHFAB construction_time = 50 materials = list(/datum/material/iron = 600, /datum/material/glass = 600, /datum/material/silver = 600, /datum/material/gold = 600, /datum/material/plastic = 150) build_path = /obj/item/organ/cyberimp/eyes/hud/science diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index 8f6fb3455382..1f34dfb329b7 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -369,7 +369,7 @@ else if(prob(EFFECT_PROB_MEDIUM-badThingCoeff)) autoexperiment = 0 visible_message(span_warning("[src] melts [exp_on], ionizing the air around it!")) - empulse(loc, 4, 6) + empulse(loc, 6) investigate_log("Experimentor has generated an Electromagnetic Pulse.", INVESTIGATE_EXPERIMENTOR) ejectItem(TRUE) //////////////////////////////////////////////////////////////////////////////////////////////// @@ -407,15 +407,7 @@ autoexperiment = 0 visible_message(span_warning("[src] malfunctions, melting [exp_on] and leaking hot air!")) var/datum/gas_mixture/env = loc.return_air() - var/transfer_moles = 0.25 * env.total_moles() - var/datum/gas_mixture/removed = env.remove(transfer_moles) - if(removed) - var/heat_capacity = removed.heat_capacity() - if(heat_capacity == 0 || heat_capacity == null) - heat_capacity = 1 - removed.set_temperature(min((removed.return_temperature()*heat_capacity + 100000)/heat_capacity, 1000)) - env.merge(removed) - air_update_turf() + env.adjust_heat(100000) investigate_log("Experimentor has released hot air.", INVESTIGATE_EXPERIMENTOR) ejectItem(TRUE) else if(prob(EFFECT_PROB_MEDIUM-badThingCoeff)) @@ -457,15 +449,7 @@ autoexperiment = 0 visible_message(span_warning("[src] malfunctions, shattering [exp_on] and leaking cold air!")) var/datum/gas_mixture/env = loc.return_air() - var/transfer_moles = 0.25 * env.total_moles() - var/datum/gas_mixture/removed = env.remove(transfer_moles) - if(removed) - var/heat_capacity = removed.heat_capacity() - if(heat_capacity == 0 || heat_capacity == null) - heat_capacity = 1 - removed.set_temperature((removed.return_temperature()*heat_capacity - 75000)/heat_capacity) - env.merge(removed) - air_update_turf() + env.adjust_heat(-75000) investigate_log("Experimentor has released cold air.", INVESTIGATE_EXPERIMENTOR) ejectItem(TRUE) else if(prob(EFFECT_PROB_MEDIUM-badThingCoeff)) diff --git a/code/modules/research/nanites/nanite_programs.dm b/code/modules/research/nanites/nanite_programs.dm index cd6be3b94dba..a3751a0d4dd5 100644 --- a/code/modules/research/nanites/nanite_programs.dm +++ b/code/modules/research/nanites/nanite_programs.dm @@ -194,7 +194,7 @@ /datum/nanite_program/proc/on_emp(severity) if(program_flags & NANITE_EMP_IMMUNE) return - if(prob(80 / severity)) + if(prob(8 * severity)) software_error() /datum/nanite_program/proc/on_shock(shock_damage) diff --git a/code/modules/research/nanites/nanite_programs/suppression.dm b/code/modules/research/nanites/nanite_programs/suppression.dm index a551fb88cff3..eb4ffea03d4c 100644 --- a/code/modules/research/nanites/nanite_programs/suppression.dm +++ b/code/modules/research/nanites/nanite_programs/suppression.dm @@ -27,7 +27,7 @@ /datum/nanite_program/triggered/shocking/trigger() if(!..()) return - host_mob.electrocute_act(rand(5,10), "shock nanites", TRUE, TRUE) + host_mob.electrocute_act(rand(5,10), "shock nanites", TRUE, zone=null, override=TRUE) // external protection can't save you from being shocked on the inside /datum/nanite_program/triggered/stun name = "Neural Shock" diff --git a/code/modules/research/nanites/nanite_programs/weapon.dm b/code/modules/research/nanites/nanite_programs/weapon.dm index 2590b8980f49..6e5c8fb3380c 100644 --- a/code/modules/research/nanites/nanite_programs/weapon.dm +++ b/code/modules/research/nanites/nanite_programs/weapon.dm @@ -134,7 +134,7 @@ /datum/nanite_program/triggered/emp/trigger() if(!..()) return - empulse(host_mob, 1, 2) + empulse(host_mob, EMP_HEAVY, 2) /datum/nanite_program/pyro/active_effect() host_mob.adjust_fire_stacks(1) diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm index 66f20944c3ad..b142be514f63 100644 --- a/code/modules/research/server.dm +++ b/code/modules/research/server.dm @@ -22,7 +22,7 @@ var/server_id = 0 var/base_mining_income = 2 var/current_temp = 0 - var/heat_gen = 100 + var/heat_gen = 1 var/heating_power = 40000 var/delay = 5 var/temp_tolerance_low = 0 @@ -48,7 +48,7 @@ var/tot_rating = 0 for(var/obj/item/stock_parts/SP in src) tot_rating += SP.rating - heat_gen /= max(1, tot_rating) + heat_gen = initial(src.heat_gen) / max(1, tot_rating) /obj/machinery/rnd/server/update_icon_state() . = ..() @@ -71,6 +71,24 @@ . = ..() refresh_working() +/obj/machinery/rnd/server/process() + if(!working) + current_temp = -1 + return + var/turf/L = get_turf(src) + var/datum/gas_mixture/env + if(istype(L)) + env = L.return_air() + // This is from the RD server code. It works well enough but I need to move over the + // sspace heater code so we can caculate power used per tick as well and making this both + // exothermic and an endothermic component + if(env) + var/perc = max((get_env_temp() - temp_tolerance_high), 0) * temp_penalty_coefficient / base_mining_income + + env.adjust_heat(heating_power * perc * heat_gen) + else + current_temp = env ? env.return_temperature() : -1 + /obj/machinery/rnd/server/proc/refresh_working() if(stat & EMPED || research_disabled || stat & NOPOWER) working = FALSE @@ -78,12 +96,12 @@ working = TRUE update_appearance(UPDATE_ICON) -/obj/machinery/rnd/server/emp_act() +/obj/machinery/rnd/server/emp_act(severity) . = ..() if(. & EMP_PROTECT_SELF) return stat |= EMPED - addtimer(CALLBACK(src, PROC_REF(unemp)), 600) + addtimer(CALLBACK(src, PROC_REF(unemp)), (6 * severity) SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE) refresh_working() /obj/machinery/rnd/server/proc/unemp() @@ -103,30 +121,9 @@ /obj/machinery/rnd/server/proc/get_env_temp() var/turf/L = loc if(isturf(L)) - return L.temperature + return L.return_temperature() return 0 -/obj/machinery/rnd/server/proc/produce_heat(heat_amt) - if(!(stat & (NOPOWER|BROKEN))) //Blatently stolen from space heater. - var/turf/L = loc - if(istype(L)) - var/datum/gas_mixture/env = L.return_air() - if(env.return_temperature() < (heat_amt+T0C)) - - var/transfer_moles = 0.25 * env.total_moles() - - var/datum/gas_mixture/removed = env.remove(transfer_moles) - - if(removed) - - var/heat_capacity = removed.heat_capacity() - if(heat_capacity == 0 || heat_capacity == null) - heat_capacity = 1 - removed.set_temperature(min((removed.return_temperature()*heat_capacity + heating_power)/heat_capacity, 1000)) - - env.merge(removed) - air_update_turf() - /proc/fix_noid_research_servers() var/list/no_id_servers = list() var/list/server_ids = list() diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 23b572e75772..90f1a0fe30fc 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -974,7 +974,7 @@ /datum/techweb_node/mech_rocket_fist id = "mech_rocket_fist" - display_name = "Exosuit Weapon (DD-2 \"Atom Smasher\" Rocket Fist)" + display_name = "Exosuit Weapon (RS-77 \"Atom Smasher\" Rocket Fist)" description = "An advanced piece of mech weaponry" prereq_ids = list("adv_mecha","weaponry") design_ids = list("mech_rocket_fist") @@ -990,7 +990,7 @@ /datum/techweb_node/mech_katana id = "mech_katana" - display_name = "Exosuit Weapon (OWM-5 \"Ronin\" katana)" + display_name = "Exosuit Weapon (HR-2 \"Ronin\" katana)" description = "An advanced piece of mech weaponry" prereq_ids = list("adv_mecha","mech_shortsword") design_ids = list("mech_katana") @@ -1014,7 +1014,7 @@ /datum/techweb_node/mech_maul id = "mech_maul" - display_name = "Exosuit Weapon (CX-22 \"Barbatos\" heavy maul)" + display_name = "Exosuit Weapon (ASW-8 \"Barbatos\" heavy maul)" description = "An advanced piece of mech weaponry" prereq_ids = list("adv_mecha","mech_shortsword") design_ids = list("mech_maul") diff --git a/code/modules/research/xenobiology/crossbreeding/_structures.dm b/code/modules/research/xenobiology/crossbreeding/_structures.dm index 32243aeb67a1..b10ef0549a87 100644 --- a/code/modules/research/xenobiology/crossbreeding/_structures.dm +++ b/code/modules/research/xenobiology/crossbreeding/_structures.dm @@ -145,7 +145,6 @@ GLOBAL_LIST_EMPTY(bluespace_slime_crystals) return var/datum/gas_mixture/gas = T.return_air() gas.set_temperature(T0C + 200) - T.air_update_turf() /obj/structure/slime_crystal/purple colour = "purple" @@ -185,7 +184,6 @@ GLOBAL_LIST_EMPTY(bluespace_slime_crystals) continue var/datum/gas_mixture/gas = T.return_air() gas.parse_gas_string(OPENTURF_DEFAULT_ATMOS) - T.air_update_turf() /obj/structure/slime_crystal/metal colour = "metal" @@ -232,8 +230,8 @@ GLOBAL_LIST_EMPTY(bluespace_slime_crystals) return var/turf/open/open_turf = T var/datum/gas_mixture/air = open_turf.return_air() - if(air.get_moles(/datum/gas/plasma) > 15) - air.adjust_moles(/datum/gas/plasma, -15) + if(air.get_moles(GAS_PLASMA) > 15) + air.adjust_moles(GAS_PLASMA, -15) new /obj/item/stack/sheet/mineral/plasma(open_turf) /obj/structure/slime_crystal/darkpurple/Destroy() diff --git a/code/modules/research/xenobiology/crossbreeding/chilling.dm b/code/modules/research/xenobiology/crossbreeding/chilling.dm index 6a8b00f734d7..16c1bc5b90e8 100644 --- a/code/modules/research/xenobiology/crossbreeding/chilling.dm +++ b/code/modules/research/xenobiology/crossbreeding/chilling.dm @@ -107,9 +107,8 @@ Chilling extracts: for(var/turf/open/T in A) var/datum/gas_mixture/G = T.air if(istype(G)) - G.set_moles(/datum/gas/plasma, 0) + G.set_moles(GAS_PLASMA, 0) filtered = TRUE - T.air_update_turf() if(filtered) user.visible_message(span_notice("Cracks spread throughout [src], and some air is sucked in!")) else diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 00ce26f5d727..3f8e9b2dea74 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -279,7 +279,7 @@ if(SLIME_ACTIVATE_MAJOR) user.visible_message(span_warning("[user]'s skin starts flashing intermittently..."), span_warning("Your skin starts flashing intermittently...")) if(do_after(user, 2.5 SECONDS, user)) - empulse(user, 1, 2) + empulse(user, EMP_HEAVY, 2) user.visible_message(span_warning("[user]'s skin flashes!"), span_warning("Your skin flashes as you emit an electromagnetic pulse!")) return 600 diff --git a/code/modules/security_levels/security_level_datums.dm b/code/modules/security_levels/security_level_datums.dm new file mode 100644 index 000000000000..586e0b049df1 --- /dev/null +++ b/code/modules/security_levels/security_level_datums.dm @@ -0,0 +1,121 @@ +/** + * Security levels + * + * These are used by the security level subsystem. Each one of these represents a security level that a player can set. + * + * Base type is abstract + */ + +/datum/security_level + /// The name of this security level. + var/name = "not set" + /// The color of our announcement divider. + var/announcement_color = "default" + /// The numerical level of this security level, see defines for more information. + var/number_level = -1 + /// The sound that we will play when this security level is set + var/sound + /// The looping sound that will be played while the security level is set + var/looping_sound + /// The looping sound interval + var/looping_sound_interval + /// The shuttle call time modification of this security level + var/shuttle_call_time_mod = 0 + /// Our announcement when lowering to this level + var/lowering_to_announcement + /// Our announcement when elevating to this level + var/elevating_to_announcement + /// Our configuration key for lowering to text, if set, will override the default lowering to announcement. + var/lowering_to_configuration_key + /// Our configuration key for elevating to text, if set, will override the default elevating to announcement. + var/elevating_to_configuration_key + +/datum/security_level/New() + . = ..() + if(lowering_to_configuration_key) // I'm not sure about you, but isn't there an easier way to do this? + lowering_to_announcement = global.config.Get(lowering_to_configuration_key) + if(elevating_to_configuration_key) + elevating_to_announcement = global.config.Get(elevating_to_configuration_key) + +/** + * GREEN + * + * No threats + */ +/datum/security_level/green + name = "green" + announcement_color = "green" + sound = 'sound/misc/notice2.ogg' // Friendly beep + number_level = SEC_LEVEL_GREEN + lowering_to_configuration_key = /datum/config_entry/string/alert_green + shuttle_call_time_mod = ALERT_COEFF_GREEN + +/** + * BLUE + * + * Caution advised + */ +/datum/security_level/blue + name = "blue" + announcement_color = "blue" + sound = 'sound/misc/notice1.ogg' // Angry alarm + number_level = SEC_LEVEL_BLUE + lowering_to_configuration_key = /datum/config_entry/string/alert_blue_downto + elevating_to_configuration_key = /datum/config_entry/string/alert_blue_upto + shuttle_call_time_mod = ALERT_COEFF_BLUE + +/** + * RED + * + * Hostile threats + */ +/datum/security_level/red + name = "red" + announcement_color = "red" + sound = 'sound/misc/notice4.ogg' // More angry alarm + number_level = SEC_LEVEL_RED + lowering_to_configuration_key = /datum/config_entry/string/alert_red_downto + elevating_to_configuration_key = /datum/config_entry/string/alert_red_upto + shuttle_call_time_mod = ALERT_COEFF_RED + +/** + * DELTA + * + * Station destruction is imminent + */ +/datum/security_level/delta + name = "delta" + announcement_color = "purple" + sound = 'sound/misc/delta_alert.ogg' // Air alarm to signify importance + number_level = SEC_LEVEL_DELTA + elevating_to_configuration_key = /datum/config_entry/string/alert_delta + shuttle_call_time_mod = ALERT_COEFF_DELTA + + +/** + * GAMMA + * + * Station is not having a very good fun time + */ +/datum/security_level/gamma + name = "gamma" + announcement_color = "orange" + sound = 'sound/misc/gamma_alert.ogg'// Air alarm to signify importance + number_level = SEC_LEVEL_GAMMA + elevating_to_configuration_key = /datum/config_entry/string/alert_gamma + shuttle_call_time_mod = ALERT_COEFF_GAMMA + + + +/** + * EPSILON + * + * Station destruction is here, and you probably caused it, you monster. + */ +/datum/security_level/epsilon + name = "epsilon" + announcement_color = "black" + sound = 'sound/misc/epsilon_alert.ogg'// Air alarm to signify importance + number_level = SEC_LEVEL_EPSILON + elevating_to_configuration_key = /datum/config_entry/string/alert_epsilon + shuttle_call_time_mod = ALERT_COEFF_EPSILON diff --git a/code/modules/security_levels/security_levels.dm b/code/modules/security_levels/security_levels.dm index bbc0fc405c79..5b98ecb20220 100644 --- a/code/modules/security_levels/security_levels.dm +++ b/code/modules/security_levels/security_levels.dm @@ -38,6 +38,7 @@ GLOBAL_VAR_INIT(security_level, SEC_LEVEL_GREEN) switch(level) if(SEC_LEVEL_GREEN) minor_announce(CONFIG_GET(string/alert_green), "Attention! Security level lowered to green:") + sound_to_playing_players('sound/misc/notice2.ogg') if(GLOB.security_level >= SEC_LEVEL_RED) modTimer = 4 else @@ -46,6 +47,7 @@ GLOBAL_VAR_INIT(security_level, SEC_LEVEL_GREEN) if(SEC_LEVEL_BLUE) if(GLOB.security_level < SEC_LEVEL_BLUE) minor_announce(CONFIG_GET(string/alert_blue_upto), "Attention! Security level elevated to blue:", TRUE) + sound_to_playing_players('sound/misc/notice1.ogg') modTimer = 0.5 else minor_announce(CONFIG_GET(string/alert_blue_downto), "Attention! Security level lowered to blue:") @@ -53,7 +55,8 @@ GLOBAL_VAR_INIT(security_level, SEC_LEVEL_GREEN) if(SEC_LEVEL_RED) if(GLOB.security_level < SEC_LEVEL_RED) - minor_announce(CONFIG_GET(string/alert_red_upto), "Attention! Code red!", TRUE, custom_alert_sound = 'sound/misc/notice4.ogg') + minor_announce(CONFIG_GET(string/alert_red_upto), "Attention! Code red!", TRUE) + sound_to_playing_players('sound/misc/notice4.ogg') if(GLOB.security_level == SEC_LEVEL_GREEN) modTimer = 0.25 else @@ -81,7 +84,8 @@ GLOBAL_VAR_INIT(security_level, SEC_LEVEL_GREEN) modTimer = 1 if(SEC_LEVEL_DELTA) - minor_announce(CONFIG_GET(string/alert_delta), "Attention! Delta security level reached!", TRUE, 'sound/misc/delta_alert.ogg') + minor_announce(CONFIG_GET(string/alert_delta), "Attention! Delta security level reached!", TRUE) + sound_to_playing_players('sound/misc/delta_alert.ogg') if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL) if(GLOB.security_level == SEC_LEVEL_GREEN) modTimer = 0.25 @@ -104,7 +108,7 @@ GLOBAL_VAR_INIT(security_level, SEC_LEVEL_GREEN) D.visible_message(span_notice("[D] whirrs as it automatically lifts access requirements!")) playsound(D, 'sound/machines/boltsup.ogg', 50, TRUE) - if(level >= SEC_LEVEL_GAMMA) + if(level == SEC_LEVEL_DELTA) change_areas_lights_alarm() else change_areas_lights_alarm(FALSE) diff --git a/code/modules/shuttle/docking.dm b/code/modules/shuttle/docking.dm index bcb066085045..064a424bb7d2 100644 --- a/code/modules/shuttle/docking.dm +++ b/code/modules/shuttle/docking.dm @@ -121,6 +121,7 @@ continue move_mode = moving_atom.beforeShuttleMove(newT, rotation, move_mode, src) //atoms + oldT.beforeShuttleMove(newT) move_mode = oldT.fromShuttleMove(newT, move_mode) //turfs move_mode = newT.toShuttleMove(oldT, move_mode, src) //turfs @@ -130,6 +131,7 @@ old_turfs[oldT] = move_mode /obj/docking_port/mobile/proc/takeoff(list/old_turfs, list/new_turfs, list/moved_atoms, rotation, movement_direction, old_dock, area/underlying_old_area) + for(var/i in 1 to old_turfs.len) var/turf/oldT = old_turfs[i] var/turf/newT = new_turfs[i] @@ -203,3 +205,9 @@ var/turf/oldT = moved_atoms[moved_object] moved_object.lateShuttleMove(oldT, movement_force, movement_direction) +/obj/docking_port/mobile/proc/reset_air() + var/list/turfs = return_ordered_turfs(x, y, z, dir) + for(var/i in 1 to length(turfs)) + var/turf/open/T = turfs[i] + if(istype(T)) + T.air.copy_from_turf(T) diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index 33401e5e99b3..5fcbabf67bd0 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -452,7 +452,8 @@ destination_dock = "emergency_syndicate" minor_announce("Corruption detected in \ shuttle navigation protocols. Please contact your \ - supervisor.", "SYSTEM ERROR:", alert=TRUE, custom_alert_sound = 'sound/misc/announce2.ogg') + supervisor.", "SYSTEM ERROR:", alert=TRUE) + sound_to_playing_players('sound/misc/announce2.ogg') dock_id(destination_dock) mode = SHUTTLE_ENDGAME diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index 99be3d6a1f9a..2a02cd5503a7 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -4,6 +4,10 @@ All ShuttleMove procs go here /************************************Base procs************************************/ +/turf/proc/beforeShuttleMove(turf/newT) + clear_adjacencies() + newT.clear_adjacencies() + // Called on every turf in the shuttle region, returns a bitflag for allowed movements of that turf // returns the new move_mode (based on the old) /turf/proc/fromShuttleMove(turf/newT, move_mode) @@ -53,16 +57,7 @@ All ShuttleMove procs go here if(!shuttle_boundary) CRASH("A turf queued to move via shuttle somehow had no skipover in baseturfs. [src]([type]):[loc]") var/depth = baseturfs.len - shuttle_boundary + 1 - newT.CopyOnTop(src, 1, depth, TRUE) - //Air stuff - newT.blocks_air = TRUE - newT.air_update_turf(TRUE) - blocks_air = TRUE - air_update_turf(TRUE) - if(isopenturf(newT)) - var/turf/open/new_open = newT - new_open.copy_air_with_tile(src) - + newT.CopyOnTop(src, 1, depth, TRUE, CHANGETURF_DEFER_CHANGE) return TRUE // Called on the new turf after everything has been moved @@ -72,7 +67,7 @@ All ShuttleMove procs go here SSexplosions.wipe_turf(src) var/shuttle_boundary = baseturfs.Find(/turf/baseturf_skipover/shuttle) if(shuttle_boundary) - oldT.ScrapeAway(baseturfs.len - shuttle_boundary + 1) + oldT.ScrapeAway(baseturfs.len - shuttle_boundary + 1, CHANGETURF_DEFER_CHANGE) if(rotation) shuttleRotate(rotation) //see shuttle_rotate.dm @@ -80,11 +75,8 @@ All ShuttleMove procs go here return TRUE /turf/proc/lateShuttleMove(turf/oldT) - blocks_air = initial(blocks_air) - air_update_turf(TRUE) - oldT.blocks_air = initial(oldT.blocks_air) - oldT.air_update_turf(TRUE) - + AfterChange(CHANGETURF_RECALC_ADJACENT) + oldT.AfterChange(CHANGETURF_RECALC_ADJACENT) ///////////////////////////////////////////////////////////////////////////////////// @@ -245,17 +237,17 @@ All ShuttleMove procs go here break if(!connected) - nullifyNode(i) + nullify_node(i) if(!nodes[i]) missing_nodes = TRUE if(missing_nodes) - atmosinit() + atmos_init() for(var/obj/machinery/atmospherics/A in pipeline_expansion()) - A.atmosinit() - if(A.returnPipenet()) - A.addMember(src) + A.atmos_init() + if(A.return_pipenet()) + A.add_member(src) SSair.add_to_rebuild_queue(src) else // atmosinit() calls update_appearance(UPDATE_ICON), so we don't need to call it diff --git a/code/modules/shuttle/shuttle_rotate.dm b/code/modules/shuttle/shuttle_rotate.dm index c13af51c7769..958c9aa5c5ab 100644 --- a/code/modules/shuttle/shuttle_rotate.dm +++ b/code/modules/shuttle/shuttle_rotate.dm @@ -85,13 +85,13 @@ If ever any of these procs are useful for non-shuttles, rename it to proc/rotate /************************************Machine rotate procs************************************/ /obj/machinery/atmospherics/shuttleRotate(rotation, params) - var/list/real_node_connect = getNodeConnects() + var/list/real_node_connect = get_node_connects() for(var/i in 1 to device_type) real_node_connect[i] = angle2dir(rotation+dir2angle(real_node_connect[i])) . = ..() - SetInitDirections() - var/list/supposed_node_connect = getNodeConnects() + set_init_directions() + var/list/supposed_node_connect = get_node_connects() var/list/nodes_copy = nodes.Copy() for(var/i in 1 to device_type) diff --git a/code/modules/spells/spell_types/self/disable_tech.dm b/code/modules/spells/spell_types/self/disable_tech.dm index 558e4e6943bf..7def457a89e1 100644 --- a/code/modules/spells/spell_types/self/disable_tech.dm +++ b/code/modules/spells/spell_types/self/disable_tech.dm @@ -6,14 +6,14 @@ school = SCHOOL_EVOCATION - /// The heavy radius of the EMP - var/emp_heavy = 2 - /// The light radius of the EMP - var/emp_light = 3 + /// The severity of the EMP + var/severity = EMP_HEAVY + /// The radius of the EMP + var/radius = 3 /datum/action/cooldown/spell/emp/cast(atom/cast_on) . = ..() - empulse(get_turf(cast_on), emp_heavy, emp_light) + empulse(get_turf(cast_on), severity, radius) /datum/action/cooldown/spell/emp/disable_tech name = "Disable Tech" @@ -26,5 +26,4 @@ invocation = "NEC CANTIO" invocation_type = INVOCATION_SHOUT - emp_heavy = 6 - emp_light = 10 \ No newline at end of file + radius = 10 diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 7b22796ef170..eda1348554ec 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -45,6 +45,7 @@ var/brute_reduction = 0 //Subtracted to brute damage taken var/burn_reduction = 0 //Subtracted to burn damage taken + var/emp_reduction = 0 //Subtracted to EMP severity //Coloring and proper item icon update var/skin_tone = "" @@ -127,6 +128,32 @@ /obj/item/bodypart/blob_act() take_damage(max_damage) +/obj/item/bodypart/emp_act(severity, emp_message=TRUE) + . = ..() + if(. & EMP_PROTECT_SELF) + return + + var/blocked = owner.getarmor(body_zone, ENERGY) // energy armor protects against EMPs + severity *= (100 - blocked) / 100 + severity -= emp_reduction + if(severity < 1) + return + + if(receive_damage(0, severity / 2, severity, FALSE, TRUE, BODYPART_ROBOTIC, CANT_WOUND)) // returns false for non-robotic limbs + if(severity > EMP_LIGHT) + ADD_TRAIT(src, TRAIT_PARALYSIS, "EMP") + addtimer(CALLBACK(src, PROC_REF(after_emp)), min((severity / 2) SECONDS, 5 SECONDS), TIMER_UNIQUE | TIMER_OVERRIDE) + if(owner && emp_message) + owner.emote("scream") + to_chat(src, span_userdanger("You feel a sharp pain as your robotic limbs overload.")) + + if(!(. & EMP_PROTECT_CONTENTS)) + for(var/obj/item/organ/O as anything in get_organs()) + O.emp_act(severity) + +/obj/item/bodypart/proc/after_emp() + REMOVE_TRAIT(src, TRAIT_PARALYSIS, "EMP") + /obj/item/bodypart/Destroy() if(owner) owner.bodyparts -= src @@ -831,7 +858,7 @@ else species_color = "" - if(!dropping_limb && (H.dna.check_mutation(HULK) || H.dna.check_mutation(ACTIVE_HULK))) + if(!dropping_limb && (H.dna.check_mutation(HULK))) mutation_color = "#00aa00" else mutation_color = "" diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index 6c972749a473..f49bc0901e32 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -5,7 +5,7 @@ icon_state = "default_human_head" max_damage = 200 body_zone = BODY_ZONE_HEAD - body_part = HEAD + body_part = HEAD|NECK w_class = WEIGHT_CLASS_BULKY //Quite a hefty load slowdown = 1 //Balancing measure throw_range = 2 //No head bowling diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index 4a48c95c450e..352e8ad18b01 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -74,10 +74,7 @@ . = 0 for(var/X in bodyparts) var/obj/item/bodypart/affecting = X - if(affecting.body_part == ARM_RIGHT) - if(!check_disabled || !affecting.bodypart_disabled) - .++ - if(affecting.body_part == ARM_LEFT) + if(affecting.body_part & (ARM_RIGHT|ARM_LEFT)) if(!check_disabled || !affecting.bodypart_disabled) .++ @@ -97,10 +94,7 @@ . = 0 for(var/X in bodyparts) var/obj/item/bodypart/affecting = X - if(affecting.body_part == LEG_RIGHT) - if(!check_disabled || !affecting.bodypart_disabled) - .++ - if(affecting.body_part == LEG_LEFT) + if(affecting.body_part & (LEG_RIGHT|LEG_LEFT)) if(!check_disabled || !affecting.bodypart_disabled) .++ @@ -290,12 +284,12 @@ var/obj/item/bodypart/O = X var/obj/item/bodypart/N if((!O.use_digitigrade && swap_back == FALSE) || (O.use_digitigrade && swap_back == TRUE)) - if(O.body_part == LEG_LEFT) + if(O.body_part & LEG_LEFT) if(swap_back == TRUE) N = new /obj/item/bodypart/l_leg else N = new /obj/item/bodypart/l_leg/digitigrade - else if(O.body_part == LEG_RIGHT) + else if(O.body_part & LEG_RIGHT) if(swap_back == TRUE) N = new /obj/item/bodypart/r_leg else diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index 89d9c76f975f..64bf4b260469 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -5,7 +5,7 @@ icon_state = "default_human_chest" max_damage = 200 body_zone = BODY_ZONE_CHEST - body_part = CHEST + body_part = CHEST|GROIN px_x = 0 px_y = 0 stam_damage_coeff = 1 @@ -64,7 +64,7 @@ max_damage = 50 max_stamina_damage = 50 body_zone = BODY_ZONE_L_ARM - body_part = ARM_LEFT + body_part = ARM_LEFT|HAND_LEFT aux_zone = BODY_ZONE_PRECISE_L_HAND aux_layer = HANDS_PART_LAYER body_damage_coeff = 0.75 @@ -158,7 +158,7 @@ attack_verb = list("slapped", "punched") max_damage = 50 body_zone = BODY_ZONE_R_ARM - body_part = ARM_RIGHT + body_part = ARM_RIGHT|HAND_RIGHT aux_zone = BODY_ZONE_PRECISE_R_HAND aux_layer = HANDS_PART_LAYER body_damage_coeff = 0.75 @@ -253,7 +253,7 @@ attack_verb = list("kicked", "stomped") max_damage = 50 body_zone = BODY_ZONE_L_LEG - body_part = LEG_LEFT + body_part = LEG_LEFT|FOOT_LEFT body_damage_coeff = 0.75 px_x = -2 px_y = 12 @@ -342,7 +342,7 @@ attack_verb = list("kicked", "stomped") max_damage = 50 body_zone = BODY_ZONE_R_LEG - body_part = LEG_RIGHT + body_part = LEG_RIGHT|FOOT_RIGHT body_damage_coeff = 0.75 px_x = 2 px_y = 12 diff --git a/code/modules/surgery/organs/appendix.dm b/code/modules/surgery/organs/appendix.dm index b600f356e49e..e45511648e94 100644 --- a/code/modules/surgery/organs/appendix.dm +++ b/code/modules/surgery/organs/appendix.dm @@ -83,4 +83,5 @@ . = ..() if(. & EMP_PROTECT_SELF) return - damage += 100/severity + if(severity > EMP_LIGHT) + damage += 20 * (severity - EMP_HEAVY) diff --git a/code/modules/surgery/organs/augment_legs.dm b/code/modules/surgery/organs/augment_legs.dm index ea53e3f59c23..706f430160dc 100644 --- a/code/modules/surgery/organs/augment_legs.dm +++ b/code/modules/surgery/organs/augment_legs.dm @@ -23,7 +23,7 @@ if(!L) //how did you get an implant in a limb you don't have? return - L.receive_damage(5,0,10) //always take a least a little bit of damage to the leg + L.receive_damage(severity / 2, 0, severity) //always take a least a little bit of damage to the leg if(prob(50)) //you're forced to use two of these for them to work so let's give em a chance to not get completely fucked if(COOLDOWN_FINISHED(src, emp_notice)) @@ -32,15 +32,15 @@ return L.set_disabled(TRUE) //disable the bodypart - addtimer(CALLBACK(src, PROC_REF(reenableleg)), 5 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE) + addtimer(CALLBACK(src, PROC_REF(reenableleg)), (severity / 2) SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE) - if(severity & EMP_HEAVY && prob(5) && !syndicate_implant) //put probabilities into a calculator before you try fucking with this - to_chat(owner, span_warning("The EMP causes your [src] to thrash your [L] around wildly, breaking it!")) + if(severity > EMP_LIGHT && prob(5) && !syndicate_implant) //put probabilities into a calculator before you try fucking with this + to_chat(owner, span_warning("[src] malfunctions and thrashes your [L] around wildly, breaking it!")) var/datum/wound/blunt/severe/breakdown = new breakdown.apply_wound(L) L.receive_damage(20) else if(COOLDOWN_FINISHED(src, emp_notice)) - to_chat(owner, span_warning("The EMP causes your [src] to seize up, preventing your [L] from moving!")) + to_chat(owner, span_warning("[src] malfunctions and causes your muscles to seize up, preventing your [L] from moving!")) COOLDOWN_START(src, emp_notice, 30 SECONDS) /obj/item/organ/cyberimp/leg/proc/reenableleg() @@ -84,14 +84,6 @@ to_chat(user, span_notice("You modify [src] to be installed on the [zone == BODY_ZONE_R_LEG ? "right" : "left"] leg.")) update_appearance(UPDATE_ICON) -/obj/item/organ/cyberimp/leg/emp_act(severity) - . = ..() - if(. & EMP_PROTECT_SELF) - return - if(prob(15/severity) && owner) - to_chat(owner, span_warning("[src] is hit by EMP!")) - // give the owner an idea about why his implant is glitching - /obj/item/organ/cyberimp/leg/Insert(mob/living/carbon/M, special, drop_if_replaced, special_zone) . = ..() if(HasBoth()) diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index a7aed9252035..1f018e8918e7 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -67,7 +67,7 @@ . = ..() if(. & EMP_PROTECT_SELF) return - if(prob(15/severity) && owner) + if(prob(1.5 * severity) && owner) to_chat(owner, span_warning("[src] is hit by EMP!")) // give the owner an idea about why his implant is glitching Retract() @@ -162,7 +162,7 @@ . = ..() if(. & EMP_PROTECT_SELF) return - if(prob(30/severity) && owner && (organ_flags & ORGAN_FAILING)) + if(prob(3 * severity) && owner && (organ_flags & ORGAN_FAILING)) Retract() owner.visible_message(span_danger("A loud bang comes from [owner]\'s [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm!")) playsound(get_turf(owner), 'sound/weapons/flashbang.ogg', 100, 1) diff --git a/code/modules/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/augments_chest.dm index 6c7d7c292465..0ab2df136add 100644 --- a/code/modules/surgery/organs/augments_chest.dm +++ b/code/modules/surgery/organs/augments_chest.dm @@ -32,7 +32,8 @@ . = ..() if(!owner || . & EMP_PROTECT_SELF) return - owner.reagents.add_reagent(/datum/reagent/toxin/bad_food, poison_amount / severity) + var/existing = owner.reagents.get_reagent_amount(/datum/reagent/toxin/bad_food) + owner.reagents.add_reagent(/datum/reagent/toxin/bad_food, (poison_amount * (severity / EMP_HEAVY)) - existing) to_chat(owner, span_warning("You feel like your insides are burning.")) @@ -102,10 +103,10 @@ if(ishuman(owner) && !syndicate_implant) var/mob/living/carbon/human/H = owner - if(H.stat != DEAD && prob(50 / severity) && H.can_heartattack()) + if(H.stat != DEAD && prob(5 * severity) && H.can_heartattack()) H.set_heartattack(TRUE) to_chat(H, span_userdanger("You feel a horrible agony in your chest!")) - addtimer(CALLBACK(src, PROC_REF(undo_heart_attack)), 10 SECONDS / severity) + addtimer(CALLBACK(src, PROC_REF(undo_heart_attack)), severity SECONDS) /obj/item/organ/cyberimp/chest/reviver/proc/undo_heart_attack() var/mob/living/carbon/human/H = owner @@ -204,26 +205,16 @@ // Priority 3: use internals tank. var/obj/item/tank/I = owner.internal - if(I && I.air_contents && I.air_contents.total_moles() > num) - var/datum/gas_mixture/removed = I.air_contents.remove(num) - if(removed.total_moles() > 0.005) - T.assume_air(removed) - return 1 - else - T.assume_air(removed) + if(I && I.air_contents && I.air_contents.total_moles() >= num) + T.assume_air_moles(I.air_contents, num) toggle(silent = TRUE) return 0 /obj/item/organ/cyberimp/chest/thrusters/emp_act(severity) . = ..() - switch(severity) - if(EMP_HEAVY) - owner.adjustFireLoss(35) - to_chat(owner, span_warning("Your thruster implant malfunctions and severely burns you!")) - if(EMP_LIGHT) - owner.adjustFireLoss(10) - to_chat(owner, span_danger("Your thruster implant malfunctions and mildly burns you!")) + owner.adjustFireLoss(3 * severity) + to_chat(owner, span_warning("Your thruster implant malfunctions and severely burns you!")) /obj/item/organ/cyberimp/chest/spinalspeed name = "neural overclocker implant" @@ -340,27 +331,17 @@ /obj/item/organ/cyberimp/chest/spinalspeed/emp_act(severity) . = ..() if(!syndicate_implant)//the toy has a different emp act - owner.adjust_dizzy(10 SECONDS / severity) + owner.adjust_dizzy(severity SECONDS) to_chat(owner, span_warning("Your spinal implant makes you feel queasy!")) return - switch(severity)//i don't want emps to just be damage again, that's boring - if(EMP_HEAVY) - owner.set_drugginess(40) - owner.adjust_hallucinations(500 SECONDS) - owner.blur_eyes(20) - owner.adjust_dizzy(10 SECONDS) - time_on += 10 - owner.adjustFireLoss(10) - to_chat(owner, span_warning("Your spinal implant malfunctions and you feel it scramble your brain!")) - if(EMP_LIGHT) - owner.set_drugginess(20) - owner.adjust_hallucinations(200 SECONDS) - owner.blur_eyes(10) - owner.adjust_dizzy(5 SECONDS) - time_on += 5 - owner.adjustFireLoss(5) - to_chat(owner, span_danger("Your spinal implant malfunctions and you suddenly feel... wrong.")) + owner.set_drugginess(4 * severity) + owner.adjust_hallucinations((50 * severity) SECONDS) + owner.blur_eyes(2 * severity) + owner.adjust_dizzy(severity SECONDS) + time_on += severity + owner.adjustFireLoss(severity) + to_chat(owner, span_warning("Your spinal implant malfunctions and you feel it scramble your brain!")) /obj/item/organ/cyberimp/chest/spinalspeed/toy name = "glowy after-image trail implant" diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm index 7f340058b76c..87bdd6505488 100644 --- a/code/modules/surgery/organs/augments_internal.dm +++ b/code/modules/surgery/organs/augments_internal.dm @@ -36,7 +36,7 @@ . = ..() if(!owner || . & EMP_PROTECT_SELF) return - owner.Stun(stun_amount / severity) + owner.Stun(stun_amount * (severity / EMP_HEAVY)) to_chat(owner, span_warning("Your body seizes up!")) @@ -74,13 +74,12 @@ . = ..() if(!owner || . & EMP_PROTECT_SELF) return - var/range = severity ? 10 : 5 var/atom/A if(active) release_items() for(var/obj/item/I in stored_items) - A = pick(oview(range)) - I.throw_at(A, range, 2) + A = pick(oview(severity)) + I.throw_at(A, severity, 2) to_chat(owner, span_warning("Your [owner.get_held_index_name(owner.get_held_index_of_item(I))] spasms and throws the [I.name]!")) stored_items = list() @@ -138,7 +137,7 @@ if((organ_flags & ORGAN_FAILING) || . & EMP_PROTECT_SELF) return organ_flags |= ORGAN_FAILING - addtimer(CALLBACK(src, PROC_REF(reboot)), stun_cap_amount * 2 / severity) + addtimer(CALLBACK(src, PROC_REF(reboot)), stun_cap_amount * (severity / 5)) /obj/item/organ/cyberimp/brain/anti_stun/proc/reboot() clear_stuns() @@ -183,7 +182,7 @@ . = ..() if(!owner || . & EMP_PROTECT_SELF) return - if(prob(60/severity)) + if(prob(6 * severity)) to_chat(owner, span_warning("Your breathing tube suddenly closes!")) owner.losebreath += 2 diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm index cd5364d44b42..0c3b10aaf071 100644 --- a/code/modules/surgery/organs/ears.dm +++ b/code/modules/surgery/organs/ears.dm @@ -157,15 +157,11 @@ compatible_biotypes = MOB_ROBOTIC // for IPCs /obj/item/organ/ears/robot/emp_act(severity) - switch(severity) - if(1) - owner.adjust_jitter(30 SECONDS) - owner.adjust_dizzy(30) - owner.Knockdown(5 SECONDS) - deaf = 30 - to_chat(owner, span_warning("Your robotic ears are uselessly ringing.")) - if(2) - owner.adjust_jitter(15 SECONDS) - owner.adjust_dizzy(15) - owner.Knockdown(10 SECONDS) - to_chat(owner, span_warning("Your robotic ears buzz.")) + owner.adjust_jitter(3 * severity) + owner.adjust_dizzy(3 * severity) + owner.Knockdown(severity SECONDS) + if(severity > EMP_LIGHT) + deaf = 3 * severity + to_chat(owner, span_warning("Your robotic ears are uselessly ringing.")) + return + to_chat(owner, span_warning("Your robotic ears buzz.")) diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index 78b7b6d14d72..b295459a9090 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -171,12 +171,11 @@ . = ..() if(!owner || . & EMP_PROTECT_SELF) return - var/obj/item/organ/eyes/eyes = owner.getorganslot(ORGAN_SLOT_EYES) to_chat(owner, span_danger("your eyes overload and blind you!")) owner.flash_act(override_blindness_check = 1) - owner.blind_eyes(5) + owner.blind_eyes(severity / 2) owner.blur_eyes(8) - eyes.applyOrganDamage(20 / severity) + applyOrganDamage(2 * severity) /obj/item/organ/eyes/robotic/xray name = "\improper meson eyes" @@ -377,7 +376,7 @@ on_mob.forceMove(scanning) for(var/i in 1 to light_beam_distance) scanning = get_step(scanning, scandir) - if(scanning.opacity || scanning.has_opaque_atom) + if(IS_OPAQUE_TURF(scanning)) stop = TRUE var/obj/effect/abstract/eye_lighting/L = LAZYACCESS(eye_lighting, i) if(stop) diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm index a61aa75c800c..c121ae5f79d1 100644 --- a/code/modules/surgery/organs/heart.dm +++ b/code/modules/surgery/organs/heart.dm @@ -239,8 +239,9 @@ . = ..() if(. & EMP_PROTECT_SELF) return - Stop() - addtimer(CALLBACK(src, PROC_REF(Restart)), restartTimer/severity) //Can restart itself after an EMP so it isnt an insta death + if(severity > EMP_LIGHT) + Stop() + addtimer(CALLBACK(src, PROC_REF(Restart)), restartTimer * min(severity / EMP_HEAVY, 1)) //Can restart itself after an EMP so it isnt an insta death /obj/item/organ/heart/cybernetic/upgraded name = "upgraded cybernetic heart" @@ -266,12 +267,12 @@ /obj/item/organ/heart/cybernetic/ipc desc = "An electronic device that appears to mimic the functions of an organic heart." -/obj/item/organ/heart/cybernetic/ipc/emp_act() +/obj/item/organ/heart/cybernetic/ipc/emp_act(severity) if(prob(30)) return . = ..() to_chat(owner, "Alert: Cybernetic heart failed one heartbeat") - addtimer(CALLBACK(src, PROC_REF(Restart)), 10 SECONDS) + addtimer(CALLBACK(src, PROC_REF(Restart)), severity SECONDS) /obj/item/organ/heart/freedom name = "heart of freedom" diff --git a/code/modules/surgery/organs/liver.dm b/code/modules/surgery/organs/liver.dm index 05d0775c9163..b57493a2f019 100755 --- a/code/modules/surgery/organs/liver.dm +++ b/code/modules/surgery/organs/liver.dm @@ -117,8 +117,7 @@ . = ..() if(. & EMP_PROTECT_SELF) return - - damage += 50/severity + applyOrganDamage(5 * severity) /obj/item/organ/liver/cybernetic/upgraded/ipc name = "substance processor" @@ -135,4 +134,4 @@ if(prob(10)) return to_chat(owner, "Alert: Your Substance Processor has been damaged. An internal chemical leak is affecting performance.") - owner.adjustToxLoss(10/severity) + owner.adjustToxLoss(severity) diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index a0febe43a2fb..36ee323f11b9 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -18,36 +18,37 @@ //Breath damage - var/safe_oxygen_min = 16 // Minimum safe partial pressure of O2, in kPa - var/safe_oxygen_max = 0 - var/safe_nitro_min = 0 - var/safe_nitro_max = 0 - var/safe_co2_min = 0 - var/safe_co2_max = 10 // Yes it's an arbitrary value who cares? - var/safe_toxins_min = 0 - var/safe_toxins_max = 0.05 - var/SA_para_min = 1 //Sleeping agent - var/SA_sleep_min = 5 //Sleeping agent + var/breathing_class = BREATH_OXY // can be a gas instead of a breathing class + var/safe_breath_min = 16 + var/safe_breath_max = 50 + var/safe_breath_dam_min = MIN_TOXIC_GAS_DAMAGE + var/safe_breath_dam_max = MAX_TOXIC_GAS_DAMAGE + var/safe_damage_type = OXY + var/list/gas_min = list() + var/list/gas_max = list( + GAS_CO2 = 30, // Yes it's an arbitrary value who cares? + GAS_PLASMA = MOLES_GAS_VISIBLE, + ) + var/list/gas_damage = list( + "default" = list( + min = MIN_TOXIC_GAS_DAMAGE, + max = MAX_TOXIC_GAS_DAMAGE, + damage_type = OXY, + ), + GAS_PLASMA = list( + min = MIN_TOXIC_GAS_DAMAGE, + max = MAX_TOXIC_GAS_DAMAGE, + damage_type = TOX, + ) + ) + + var/SA_para_min = 1 //nitrous values + var/SA_sleep_min = 5 var/BZ_trip_balls_min = 1 //BZ gas var/gas_stimulation_min = 0.002 // Nitrium, Freon and Hyper-noblium - ///list of gasses that can be used in place of oxygen and the amount they are multiplied by, i.e. 1 pp pluox = 8 pp oxygen - var/list/oxygen_substitutes = list(/datum/gas/pluoxium = 8) - //Whether helium speech effects are currently active + /// Whether helium speech effects are currently active var/helium_speech = FALSE - var/oxy_breath_dam_min = MIN_TOXIC_GAS_DAMAGE - var/oxy_breath_dam_max = MAX_TOXIC_GAS_DAMAGE - var/oxy_damage_type = OXY - var/nitro_breath_dam_min = MIN_TOXIC_GAS_DAMAGE - var/nitro_breath_dam_max = MAX_TOXIC_GAS_DAMAGE - var/nitro_damage_type = OXY - var/co2_breath_dam_min = MIN_TOXIC_GAS_DAMAGE - var/co2_breath_dam_max = MAX_TOXIC_GAS_DAMAGE - var/co2_damage_type = OXY - var/tox_breath_dam_min = MIN_TOXIC_GAS_DAMAGE - var/tox_breath_dam_max = MAX_TOXIC_GAS_DAMAGE - var/tox_damage_type = TOX - var/cold_message = "your face freezing and an icicle forming" var/cold_level_1_threshold = 260 var/cold_level_2_threshold = 200 @@ -68,8 +69,26 @@ var/crit_stabilizing_reagent = /datum/reagent/medicine/epinephrine +/obj/item/organ/lungs/Initialize(mapload) + . = ..() + populate_gas_info() + +/obj/item/organ/lungs/proc/populate_gas_info() + gas_min[breathing_class] = safe_breath_min + gas_max[breathing_class] = safe_breath_max + gas_damage[breathing_class] = list( + min = safe_breath_dam_min, + max = safe_breath_dam_max, + damage_type = safe_damage_type + ) + if(ispath(breathing_class)) + var/datum/breathing_class/class = GLOB.gas_data.breathing_classes[breathing_class] + for(var/g in class.gases) + if(class.gases[g] > 0) + gas_min -= g /obj/item/organ/lungs/proc/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/H) + var/breathModifier = (5-(5*(damage/maxHealth)/2)) //range 2.5 - 5 if(H.status_flags & GODMODE) return if(HAS_TRAIT(H, TRAIT_NOBREATH)) @@ -84,167 +103,131 @@ H.adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS) H.failed_last_breath = TRUE - if(safe_oxygen_min) - if(isipc(H)) - H.throw_alert("not_enough_oxy", /atom/movable/screen/alert/not_enough_oxy/ipc) - else - H.throw_alert("not_enough_oxy", /atom/movable/screen/alert/not_enough_oxy) - else if(safe_toxins_min) - H.throw_alert("not_enough_tox", /atom/movable/screen/alert/not_enough_tox) - else if(safe_co2_min) - H.throw_alert("not_enough_co2", /atom/movable/screen/alert/not_enough_co2) - else if(safe_nitro_min) - H.throw_alert("not_enough_nitro", /atom/movable/screen/alert/not_enough_nitro) - return FALSE - - var/gas_breathed = 0 - var/eff = get_organ_efficiency() - - //Partial pressures in our breath - var/O2_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/oxygen)) - for(var/i in oxygen_substitutes) - O2_pp += oxygen_substitutes[i] * breath.get_breath_partial_pressure(breath.get_moles(i)) - var/N2_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/nitrogen)) - var/Toxins_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/plasma)) - var/CO2_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/carbon_dioxide)) - - - //-- OXY --// - - //Too much oxygen! //Yes, some species may not like it. - if(safe_oxygen_max) - if(O2_pp > safe_oxygen_max) - var/ratio = (breath.get_moles(/datum/gas/oxygen)/safe_oxygen_max) * 10 - H.apply_damage_type(clamp(ratio, oxy_breath_dam_min, oxy_breath_dam_max), oxy_damage_type) - H.throw_alert("too_much_oxy", /atom/movable/screen/alert/too_much_oxy) - else - H.clear_alert("too_much_oxy") - - //Too little oxygen! - if(safe_oxygen_min) - if(O2_pp < safe_oxygen_min) - gas_breathed = handle_too_little_breath(H, O2_pp, safe_oxygen_min, breath.get_moles(/datum/gas/oxygen)) - H.throw_alert("not_enough_oxy", /atom/movable/screen/alert/not_enough_oxy) + var/alert_category + var/alert_type + if(ispath(breathing_class)) + var/datum/breathing_class/class = GLOB.gas_data.breathing_classes[breathing_class] + alert_category = class.low_alert_category + alert_type = class.low_alert_datum else - H.failed_last_breath = FALSE - if(H.health >= H.crit_threshold) - H.adjustOxyLoss(-5 * eff) - gas_breathed = breath.get_moles(/datum/gas/oxygen) - H.clear_alert("not_enough_oxy") + var/list/breath_alert_info = GLOB.gas_data.breath_alert_info + if(breathing_class in breath_alert_info) + var/list/alert = breath_alert_info[breathing_class]["not_enough_alert"] + alert_category = alert["alert_category"] + alert_type = alert["alert_type"] + if(alert_category) + H.throw_alert(alert_category, alert_type) + return FALSE - //Exhale - breath.adjust_moles(/datum/gas/oxygen, -gas_breathed) - breath.adjust_moles(/datum/gas/carbon_dioxide, gas_breathed) - gas_breathed = 0 + #define PP_MOLES(X) ((X / total_moles) * pressure) - //-- Nitrogen --// + #define PP(air, gas) PP_MOLES(air.get_moles(gas)) - //Too much nitrogen! - if(safe_nitro_max) - if(N2_pp > safe_nitro_max) - var/ratio = (breath.get_moles(/datum/gas/nitrogen)/safe_nitro_max) * 10 - H.apply_damage_type(clamp(ratio, nitro_breath_dam_min, nitro_breath_dam_max), nitro_damage_type) - H.throw_alert("too_much_nitro", /atom/movable/screen/alert/too_much_nitro) - else - H.clear_alert("too_much_nitro") - - //Too little nitrogen! - if(safe_nitro_min) - if(N2_pp < safe_nitro_min) - gas_breathed = handle_too_little_breath(H, N2_pp, safe_nitro_min, breath.get_moles(/datum/gas/nitrogen)) - H.throw_alert("not_enough_nitro", /atom/movable/screen/alert/not_enough_nitro) - else - H.failed_last_breath = FALSE - if(H.health >= H.crit_threshold) - H.adjustOxyLoss(-5 * eff) - gas_breathed = breath.get_moles(/datum/gas/nitrogen) - H.clear_alert("not_enough_nitro") - - //Exhale - breath.adjust_moles(/datum/gas/nitrogen, -gas_breathed) - breath.adjust_moles(/datum/gas/carbon_dioxide, gas_breathed) - gas_breathed = 0 - - //-- CO2 --// - - //CO2 does not affect failed_last_breath. So if there was enough oxygen in the air but too much co2, this will hurt you, but only once per 4 ticks, instead of once per tick. - if(safe_co2_max) - if(CO2_pp > safe_co2_max) - if(!H.co2overloadtime) // If it's the first breath with too much CO2 in it, lets start a counter, then have them pass out after 12s or so. - H.co2overloadtime = world.time - else if(world.time - H.co2overloadtime > 120) - H.Unconscious(60) - H.apply_damage_type(3, co2_damage_type) // Lets hurt em a little, let them know we mean business - if(world.time - H.co2overloadtime > 300) // They've been in here 30s now, lets start to kill them for their own good! - H.apply_damage_type(8, co2_damage_type) - H.throw_alert("too_much_co2", /atom/movable/screen/alert/too_much_co2) - if(prob(20)) // Lets give them some chance to know somethings not right though I guess. - H.emote("cough") + var/gas_breathed = 0 + var/eff = get_organ_efficiency() + var/pressure = breath.return_pressure() + var/total_moles = breath.total_moles() + var/list/breath_alert_info = GLOB.gas_data.breath_alert_info + var/list/breath_results = GLOB.gas_data.breath_results + var/list/breathing_classes = GLOB.gas_data.breathing_classes + var/list/mole_adjustments = list() + for(var/entry in gas_min) + var/required_pp = 0 + var/required_moles = 0 + var/safe_min = gas_min[entry] + var/alert_category = null + var/alert_type = null + if(ispath(entry)) + var/datum/breathing_class/class = breathing_classes[entry] + var/list/gases = class.gases + var/list/products = class.products + alert_category = class.low_alert_category + alert_type = class.low_alert_datum + for(var/gas in gases) + var/moles = breath.get_moles(gas) + var/multiplier = gases[gas] + mole_adjustments[gas] = (gas in mole_adjustments) ? mole_adjustments[gas] - moles : -moles + required_pp += PP_MOLES(moles) * multiplier + required_moles += moles + if(multiplier > 0) + var/to_add = moles * multiplier + for(var/product in products) + mole_adjustments[product] = (product in mole_adjustments) ? mole_adjustments[product] + to_add : to_add else - H.co2overloadtime = 0 - H.clear_alert("too_much_co2") - - //Too little CO2! - if(safe_co2_min) - if(CO2_pp < safe_co2_min) - gas_breathed = handle_too_little_breath(H, CO2_pp, safe_co2_min, breath.get_moles(/datum/gas/carbon_dioxide)) - H.throw_alert("not_enough_co2", /atom/movable/screen/alert/not_enough_co2) + required_moles = breath.get_moles(entry) + required_pp = PP_MOLES(required_moles) + if(entry in breath_alert_info) + var/list/alert = breath_alert_info[entry]["not_enough_alert"] + alert_category = alert["alert_category"] + alert_type = alert["alert_type"] + mole_adjustments[entry] = -required_moles + mole_adjustments[breath_results[entry]] = required_moles + if(required_pp < safe_min) + var/multiplier = handle_too_little_breath(H, required_pp, safe_min, required_moles) + if(required_moles > 0) + multiplier /= required_moles + for(var/adjustment in mole_adjustments) + mole_adjustments[adjustment] *= multiplier + if(alert_category) + H.throw_alert(alert_category, alert_type) else H.failed_last_breath = FALSE if(H.health >= H.crit_threshold) - H.adjustOxyLoss(-5 * organ_efficiency) - gas_breathed = breath.get_moles(/datum/gas/carbon_dioxide) - H.clear_alert("not_enough_co2") - - //Exhale - breath.adjust_moles(/datum/gas/carbon_dioxide, -gas_breathed) - breath.adjust_moles(/datum/gas/oxygen, gas_breathed) - gas_breathed = 0 - - - //-- TOX --// - - //Too much toxins! - if(safe_toxins_max) - if(Toxins_pp > safe_toxins_max) - var/ratio = (breath.get_moles(/datum/gas/plasma)/safe_toxins_max) * 10 - H.apply_damage_type(clamp(ratio, tox_breath_dam_min, tox_breath_dam_max), tox_damage_type) - H.throw_alert("too_much_tox", /atom/movable/screen/alert/too_much_tox) + H.adjustOxyLoss(-breathModifier) + if(alert_category) + H.clear_alert(alert_category) + var/list/danger_reagents = GLOB.gas_data.breath_reagents_dangerous + for(var/entry in gas_max) + var/found_pp = 0 + var/datum/breathing_class/breathing_class = entry + var/datum/reagent/danger_reagent = null + var/alert_category = null + var/alert_type = null + if(ispath(breathing_class)) + breathing_class = breathing_classes[breathing_class] + alert_category = breathing_class.high_alert_category + alert_type = breathing_class.high_alert_datum + danger_reagent = breathing_class.danger_reagent + found_pp = breathing_class.get_effective_pp(breath) else - H.clear_alert("too_much_tox") - - - //Too little toxins! - if(safe_toxins_min) - if(Toxins_pp < safe_toxins_min) - gas_breathed = handle_too_little_breath(H, Toxins_pp, safe_toxins_min, breath.get_moles(/datum/gas/plasma)) - H.throw_alert("not_enough_tox", /atom/movable/screen/alert/not_enough_tox) - else - H.failed_last_breath = FALSE - if(H.health >= H.crit_threshold) - H.adjustOxyLoss(-5 * eff) - gas_breathed = breath.get_moles(/datum/gas/plasma) - H.clear_alert("not_enough_tox") - - //Exhale - breath.adjust_moles(/datum/gas/plasma, -gas_breathed) - breath.adjust_moles(/datum/gas/carbon_dioxide, gas_breathed) - gas_breathed = 0 - + danger_reagent = danger_reagents[entry] + if(entry in breath_alert_info) + var/list/alert = breath_alert_info[entry]["too_much_alert"] + alert_category = alert["alert_category"] + alert_type = alert["alert_type"] + found_pp = PP(breath, entry) + if(found_pp > gas_max[entry]) + if(istype(danger_reagent)) + H.reagents.add_reagent(danger_reagent,1) + var/list/damage_info = (entry in gas_damage) ? gas_damage[entry] : gas_damage["default"] + var/dam = found_pp / gas_max[entry] * 10 + H.apply_damage_type(clamp(dam, damage_info["min"], damage_info["max"]), damage_info["damage_type"]) + if(alert_category && alert_type) + H.throw_alert(alert_category, alert_type) + else if(alert_category) + H.clear_alert(alert_category) + var/list/breath_reagents = GLOB.gas_data.breath_reagents + for(var/gas in breath.get_gases()) + if(gas in breath_reagents) + var/datum/reagent/R = breath_reagents[gas] + H.reagents.add_reagent(R, breath.get_moles(gas)*eff) + mole_adjustments[gas] = (gas in mole_adjustments) ? mole_adjustments[gas] - breath.get_moles(gas) : -breath.get_moles(gas) + + for(var/gas in mole_adjustments) + breath.adjust_moles(gas, mole_adjustments[gas]) //-- TRACES --// if(breath) // If there's some other shit in the air lets deal with it here. // N2O - REMOVE_TRAIT(H, TRAIT_SURGERY_PREPARED, "N2O") - var/SA_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/nitrous_oxide)) + + var/SA_pp = PP(breath, GAS_NITROUS) if(SA_pp > SA_para_min) // Enough to make us stunned for a bit H.Unconscious(60) // 60 gives them one second to wake up and run away a bit! if(SA_pp > SA_sleep_min) // Enough to make us sleep as well H.Sleeping(max(H.AmountSleeping() + 40, 200)) - ADD_TRAIT(H, TRAIT_SURGERY_PREPARED, "N2O") else if(SA_pp > 0.01) // There is sleeping gas in their lungs, but only a little, so give them a bit of a warning if(prob(20)) H.emote(pick("giggle", "laugh")) @@ -255,7 +238,7 @@ // BZ - var/bz_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/bz)) + var/bz_pp = PP(breath, GAS_BZ) if(bz_pp > BZ_trip_balls_min) H.adjust_hallucinations(10 SECONDS) H.reagents.add_reagent(/datum/reagent/bz_metabolites,5) @@ -266,22 +249,13 @@ H.adjust_hallucinations(5 SECONDS) H.reagents.add_reagent(/datum/reagent/bz_metabolites,1) - - // Tritium - var/trit_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/tritium)) - if (trit_pp > 50) - H.radiation += trit_pp/2 //If you're breathing in half an atmosphere of radioactive gas, you fucked up. - else - H.radiation += trit_pp/10 - // Nitrium - var/nitrium_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/nitrium)) + var/nitrium_pp = PP(breath, GAS_NITRIUM) // Random chance to inflict side effects, increases with pressure. if (nitrium_pp > 15 && prob(nitrium_pp)) H.adjustOrganLoss(ORGAN_SLOT_LUNGS, nitrium_pp * 0.1) to_chat(H, span_alert("You feel a burning sensation in your chest")) - - gas_breathed = breath.get_moles(/datum/gas/nitrium) + gas_breathed = breath.get_moles(GAS_NITRIUM) // Metabolize to reagents. if (gas_breathed > gas_stimulation_min) var/existing = H.reagents.get_reagent_amount(/datum/reagent/nitrium_low_metabolization) @@ -289,10 +263,10 @@ if (gas_breathed > gas_stimulation_min * 2.5) var/existing = H.reagents.get_reagent_amount(/datum/reagent/nitrium_high_metabolization) H.reagents.add_reagent(/datum/reagent/nitrium_high_metabolization, max(0, 1 - existing)) - breath.adjust_moles(/datum/gas/nitrium, -gas_breathed) + breath.adjust_moles(GAS_NITRIUM, -gas_breathed) // Freon - var/freon_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/freon)) + var/freon_pp = PP(breath,GAS_FREON) if (prob(freon_pp)) to_chat(H, span_alert("Your mouth feels like it's burning!")) if (freon_pp >40) @@ -303,81 +277,80 @@ H.silent = max(H.silent, 3) else H.adjustFireLoss(freon_pp/4) - gas_breathed = breath.get_moles(/datum/gas/freon) + gas_breathed = breath.get_moles(GAS_FREON) if (gas_breathed > gas_stimulation_min) H.reagents.add_reagent(/datum/reagent/freon,1*eff) - breath.adjust_moles(/datum/gas/freon, -gas_breathed) + breath.adjust_moles(GAS_FREON, -gas_breathed) // Healium - var/healium_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/healium)) + var/healium_pp = PP(breath,GAS_HEALIUM) if(healium_pp > SA_sleep_min) var/existing = H.reagents.get_reagent_amount(/datum/reagent/healium) H.reagents.add_reagent(/datum/reagent/healium,max(0, 1*eff - existing)) - gas_breathed = breath.get_moles(/datum/gas/healium) + gas_breathed = breath.get_moles(GAS_HEALIUM) if(gas_breathed > gas_stimulation_min && !helium_speech) helium_speech = TRUE RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(handle_helium_speech)) else if (gas_breathed <= gas_stimulation_min && helium_speech) helium_speech = FALSE UnregisterSignal(owner, COMSIG_MOB_SAY) - breath.adjust_moles(/datum/gas/healium, -gas_breathed) + breath.adjust_moles(GAS_HEALIUM, -gas_breathed) // Pluonium // Inert // Zauker - var/zauker_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/zauker)) - if(zauker_pp > safe_toxins_max) + var/zauker_pp = PP(breath,GAS_ZAUKER) + if(zauker_pp > safe_breath_max) H.adjustBruteLoss(25) H.adjustOxyLoss(5) H.adjustFireLoss(8) H.adjustToxLoss(8) - gas_breathed = breath.get_moles(/datum/gas/zauker) - breath.adjust_moles(/datum/gas/zauker, -gas_breathed) + gas_breathed = breath.get_moles(GAS_ZAUKER) + breath.adjust_moles(GAS_ZAUKER, -gas_breathed) // Halon - gas_breathed = breath.get_moles(/datum/gas/halon) + gas_breathed = breath.get_moles(GAS_HALON) if(gas_breathed > gas_stimulation_min) H.adjustOxyLoss(5) var/existing = H.reagents.get_reagent_amount(/datum/reagent/halon) H.reagents.add_reagent(/datum/reagent/halon,max(0, 1 - existing)) - gas_breathed = breath.get_moles(/datum/gas/halon) - breath.adjust_moles(/datum/gas/halon, -gas_breathed) + gas_breathed = breath.get_moles(GAS_HALON) + breath.adjust_moles(GAS_HALON, -gas_breathed) // Hexane - gas_breathed = breath.get_moles(/datum/gas/hexane) + gas_breathed = breath.get_moles(GAS_HEXANE) if(gas_breathed > gas_stimulation_min) H.adjust_hallucinations(50 SECONDS) H.reagents.add_reagent(/datum/reagent/hexane,5) if(prob(33)) H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3, 150) + breath.adjust_moles(GAS_HEXANE, -gas_breathed) // Hyper-noblium - gas_breathed = breath.get_moles(/datum/gas/hypernoblium) + gas_breathed = breath.get_moles(GAS_HYPERNOB) if(gas_breathed > gas_stimulation_min) var/existing = H.reagents.get_reagent_amount(/datum/reagent/hypernoblium) H.reagents.add_reagent(/datum/reagent/hypernoblium, max(0, eff - existing)) - breath.adjust_moles(/datum/gas/hypernoblium, -gas_breathed) + breath.adjust_moles(GAS_HYPERNOB, -gas_breathed) // Anti-noblium - gas_breathed = breath.get_moles(/datum/gas/antinoblium) + gas_breathed = breath.get_moles(GAS_ANTINOB) if(gas_breathed > gas_stimulation_min) var/existing = H.reagents.get_reagent_amount(/datum/reagent/antinoblium) H.reagents.add_reagent(/datum/reagent/antinoblium, max(0, eff - existing)) - breath.adjust_moles(/datum/gas/antinoblium, -gas_breathed) + breath.adjust_moles(GAS_ANTINOB, -gas_breathed) // Miasma - if (breath.get_moles(/datum/gas/miasma)) - var/miasma_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/miasma)) + if (breath.get_moles(GAS_MIASMA)) + var/miasma_pp = PP(breath,GAS_MIASMA) //Miasma sickness if(prob(0.5 * miasma_pp)) - var/datum/disease/advance/miasma_disease = new /datum/disease/advance/random(min(round(max(miasma_pp/2, 1), 1), 6), min(round(max(miasma_pp, 1), 1), 8)) - if(owner.CanContractDisease(miasma_disease)) - //tl;dr the first argument chooses the smaller of miasma_pp/2 or 6(typical max virus symptoms), the second chooses the smaller of miasma_pp or 8(max virus symptom level) // - miasma_disease.name = "Unknown"//^each argument has a minimum of 1 and rounds to the nearest value. Feel free to change the pp scaling I couldn't decide on good numbers for it. - miasma_disease.try_infect(owner) + var/datum/disease/advance/miasma_disease = new /datum/disease/advance/random(2, 3) + miasma_disease.name = "Unknown" + miasma_disease.try_infect(owner) // Miasma side effects switch(miasma_pp) @@ -410,7 +383,7 @@ // Then again, this is a purely hypothetical scenario and hardly reachable owner.adjust_disgust(0.1 * miasma_pp) - breath.adjust_moles(/datum/gas/miasma, -gas_breathed) + breath.adjust_moles(GAS_MIASMA, -gas_breathed) // Clear out moods when no miasma at all else @@ -483,11 +456,13 @@ user.visible_message(span_notice("[user] extends [src] with [W]!"), span_notice("You use [W] to extend [src]!"), "You hear something stretching.") name = "extended [name]" icon_state += "-crobar" //shh! don't tell anyone i handed you this card - safe_oxygen_min *= 2 //SCREAM LOUDER i dont know maybe eventually - safe_toxins_min *= 2 - safe_nitro_min *= 2 //BREATHE HARDER - safe_co2_min *= 2 - organ_efficiency = 2 //HOLD YOUR BREATH FOR REALLY LONG + safe_breath_min *= 2 //SCREAM LOUDER i dont know maybe eventually + safe_breath_max *= 2 //BREATHE HARDER + for(var/gas in gas_min) + gas_min[gas] *= 2 + for(var/gas in gas_max) + gas_max[gas] *= 2 + organ_efficiency *= 2 //HOLD YOUR BREATH FOR REALLY LONG maxHealth *= 0.5 //This procedure is not legal but i will do it for you /obj/item/organ/lungs/prepare_eat() @@ -525,7 +500,7 @@ var/temperature = breath.return_temperature() for(var/id in breath.get_gases()) var/moles = breath.get_moles(id) - total_heat_capacity += GLOB.meta_gas_info[id][META_GAS_SPECIFIC_HEAT] * moles + total_heat_capacity += GLOB.gas_data.specific_heats[id] * moles // Normal atmos is 0.416 // 20C -> 293K // At about 50C overheating will begin @@ -556,38 +531,37 @@ desc = "A spongy rib-shaped mass for filtering plasma from the air." icon_state = "lungs-plasma" - safe_oxygen_min = 0 //We don't breath this - safe_toxins_min = 16 //We breath THIS! - safe_toxins_max = 0 + breathing_class = BREATH_PLASMA + +/obj/item/organ/lungs/plasmaman/populate_gas_info() + ..() + gas_max -= GAS_PLASMA /obj/item/organ/lungs/xeno name = "devolved plasma vessel" desc = "A lung-shaped organ vaguely similar to a plasma vessel, restructured from a storage system to a respiratory one." icon_state = "lungs-x" + breathing_class = /datum/breathing_class/oxygen_plas - safe_toxins_max = 0 //lmoa~ - oxygen_substitutes = list(/datum/gas/pluoxium = 8, /datum/gas/plasma = 1) heat_level_1_threshold = 313 heat_level_2_threshold = 353 heat_level_3_threshold = 600 -/obj/item/organ/lungs/xeno/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/H) //handling this externally so I don't have to nerf pluoxium, can't handle it internally without removing perpetual pluox or requiring plasma for breathing - . = ..() - if(breath) - var/breath_amt = breath.get_moles(/datum/gas/plasma) - breath.adjust_moles(/datum/gas/plasma, -breath_amt) - breath.adjust_moles(/datum/gas/oxygen, breath_amt) +/obj/item/organ/lungs/xeno/populate_gas_info() + ..() + gas_max -= GAS_PLASMA + gas_damage -= GAS_PLASMA /obj/item/organ/lungs/slime name = "vacuole" desc = "A large organelle designed to store oxygen and other important gasses." - safe_toxins_max = 0 //We breathe this to gain POWER. - /obj/item/organ/lungs/slime/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/H) . = ..() if (breath) - var/plasma_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/plasma)) + var/total_moles = breath.total_moles() + var/pressure = breath.return_pressure() + var/plasma_pp = PP(breath, GAS_PLASMA) owner.blood_volume += (0.2 * plasma_pp) // 10/s when breathing literally nothing but plasma, which will suffocate you. /obj/item/organ/lungs/ghetto @@ -604,23 +578,27 @@ organ_flags = ORGAN_SYNTHETIC maxHealth = 2 * STANDARD_ORGAN_THRESHOLD organ_efficiency = 1.5 - safe_oxygen_min = 13 + safe_breath_min = 13 + safe_breath_max = 100 -/obj/item/organ/lungs/cybernetic/emp_act() +/obj/item/organ/lungs/cybernetic/emp_act(severity) . = ..() if(. & EMP_PROTECT_SELF) return - owner.losebreath = 20 + owner.losebreath = 2 * severity /obj/item/organ/lungs/cybernetic/upgraded name = "upgraded cybernetic lungs" desc = "A more advanced version of the stock cybernetic lungs, more efficient at, well, breathing. Features higher temperature tolerances and the ability to filter out most potentially harmful gases." icon_state = "lungs-c-u" + safe_breath_min = 4 + safe_breath_max = 250 + gas_max = list( + GAS_PLASMA = 30, + GAS_CO2 = 30 + ) maxHealth = 3 * STANDARD_ORGAN_THRESHOLD organ_efficiency = 2 - safe_oxygen_min = 10 - safe_co2_max = 20 - safe_toxins_max = 20 //Higher resistance to most harmful gasses SA_para_min = 3 SA_sleep_min = 6 BZ_trip_balls_min = 2 @@ -638,12 +616,12 @@ name = "aeration reticulum" desc = "These exotic lungs seem crunchier than most." icon_state = "lungs-ethereal" - oxygen_substitutes = list(/datum/gas/pluoxium = 8, /datum/gas/water_vapor = 1) + breathing_class = /datum/breathing_class/oxygen_vapor /obj/item/organ/lungs/ethereal/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/H) . = ..() - var/electrolysis = breath.get_moles(/datum/gas/water_vapor) + var/electrolysis = breath.get_moles(GAS_H2O) if(electrolysis) - breath.adjust_moles(/datum/gas/water_vapor, -electrolysis) - breath.adjust_moles(/datum/gas/hydrogen, electrolysis) - breath.adjust_moles(/datum/gas/oxygen, electrolysis/2) + breath.adjust_moles(GAS_H2O, -electrolysis) + breath.adjust_moles(GAS_H2, electrolysis) + breath.adjust_moles(GAS_O2, electrolysis/2) diff --git a/code/modules/surgery/organs/stomach.dm b/code/modules/surgery/organs/stomach.dm index b46391ae3c4f..52c76be97411 100644 --- a/code/modules/surgery/organs/stomach.dm +++ b/code/modules/surgery/organs/stomach.dm @@ -145,7 +145,7 @@ /obj/item/organ/stomach/cell/emp_act(severity) to_chat(owner, emp_message) - charge(amount = owner.nutrition * -0.2 / severity) + charge(amount = owner.nutrition * -0.02 * severity) /obj/item/organ/stomach/cell/Insert(mob/living/carbon/M, special, drop_if_replaced) . = ..() @@ -182,7 +182,7 @@ UnregisterSignal(owner, COMSIG_LIVING_ELECTROCUTE_ACT) ..() -/obj/item/organ/stomach/cell/ethereal/proc/on_electrocute(datum/source, shock_damage, siemens_coeff = 1, illusion = FALSE) +/obj/item/organ/stomach/cell/ethereal/proc/on_electrocute(mob/living/victim, shock_damage, obj/source, siemens_coeff = 1, zone = null, tesla_shock = 0, illusion = 0) if(illusion) return if(!HAS_TRAIT(owner, TRAIT_POWERHUNGRY)) @@ -190,6 +190,9 @@ owner.adjust_nutrition(shock_damage * siemens_coeff) to_chat(owner, span_notice("You absorb some of the shock into your body!")) +/obj/item/organ/stomach/cell/ethereal/emp_act(severity) + return // it's organic + /obj/item/organ/stomach/cursed name = "cursed stomach" icon_state = "stomach-cursed" diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index ac2dced2b692..92b50110451d 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -266,9 +266,9 @@ /obj/item/organ/tongue/robot/emp_act(severity) if(prob(5)) return - owner.apply_effect(EFFECT_STUTTER, rand(5 SECONDS, 2 MINUTES)) + owner.apply_effect(EFFECT_STUTTER, rand(1, severity) * 6 SECONDS) owner.emote("scream") - to_chat(owner, "Alert: Vocal cords are malfunctioning.") + to_chat(owner, "Alert: Voice synthesizer is malfunctioning.") /obj/item/organ/tongue/robot/can_speak_language(language) return TRUE // THE MAGIC OF ELECTRONICS diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index cb74738d8880..05192ad4b1c2 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -169,6 +169,7 @@ throwforce = 5 throw_speed = 3 throw_range = 5 + demolition_mod = 0.25 materials = list(/datum/material/iron=4000, /datum/material/glass=1000) attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") hitsound = 'sound/weapons/bladeslice.ogg' @@ -399,6 +400,7 @@ light_range = 1 light_color = LIGHT_COLOR_GREEN light_power = 0.2 //Barely glows on low power + demolition_mod = 1.5 // lasers are good at cutting metal sharpness = SHARP_EDGED diff --git a/code/modules/swarmers/swarmer.dm b/code/modules/swarmers/swarmer.dm index fdfad769000b..a803253f031a 100644 --- a/code/modules/swarmers/swarmer.dm +++ b/code/modules/swarmers/swarmer.dm @@ -96,12 +96,13 @@ . = ..() . += "Resources: [resources]" -/mob/living/simple_animal/hostile/swarmer/emp_act() +/mob/living/simple_animal/hostile/swarmer/emp_act(severity) . = ..() if(. & EMP_PROTECT_SELF) return - if(health > 1) - adjustHealth(health-1) + var/emp_damage = severity/EMP_HEAVY + if(health > emp_damage) + adjustHealth(health - emp_damage) else death() @@ -258,7 +259,7 @@ playsound(src, 'sound/effects/sparks4.ogg', 50, TRUE) do_teleport(target, safe_turf , 0, channel = TELEPORT_CHANNEL_BLUESPACE) -/mob/living/simple_animal/hostile/swarmer/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE, gib = FALSE) +/mob/living/simple_animal/hostile/swarmer/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, zone = null, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE, gib = FALSE) if(!tesla_shock) return FALSE return ..() diff --git a/code/modules/swarmers/swarmer_act.dm b/code/modules/swarmers/swarmer_act.dm index 92529679a759..d85d82513e6d 100644 --- a/code/modules/swarmers/swarmer_act.dm +++ b/code/modules/swarmers/swarmer_act.dm @@ -87,7 +87,7 @@ for(var/turf/T in range(1, src)) var/area/A = get_area(T) var/datum/gas_mixture/turf_air = T.return_air() - if(turf_air.get_moles(/datum/gas/hydrogen) > 1 || turf_air.get_moles(/datum/gas/tritium) > 1 || turf_air.get_moles(/datum/gas/plasma) > 1 || (locate(/obj/effect/hotspot) in T) || turf_air.return_pressure() > 500 || turf_air.return_temperature() > 750 || !turf_air.total_moles() || isspaceturf(T) || (!isonshuttle && (istype(A, /area/shuttle) || istype(A, /area/space))) || (isonshuttle && !istype(A, /area/shuttle))) + if(turf_air.get_moles(GAS_H2) > 1 || turf_air.get_moles(GAS_TRITIUM) > 1 || turf_air.get_moles(GAS_PLASMA) > 1 || (locate(/obj/effect/hotspot) in T) || turf_air.return_pressure() > 500 || turf_air.return_temperature() > 750 || !turf_air.total_moles() || isspaceturf(T) || (!isonshuttle && (istype(A, /area/shuttle) || istype(A, /area/space))) || (isonshuttle && !istype(A, /area/shuttle))) to_chat(S, span_warning("Destroying this object has the potential to cause a hull breach. Aborting.")) S.target = null return FALSE @@ -173,7 +173,7 @@ for(var/turf/T in range(1, src)) var/area/A = get_area(T) var/datum/gas_mixture/turf_air = T.return_air() - if(turf_air.get_moles(/datum/gas/hydrogen) > 1 || turf_air.get_moles(/datum/gas/tritium) > 1 || turf_air.get_moles(/datum/gas/plasma) > 1 || (locate(/obj/effect/hotspot) in T) || turf_air.return_pressure() > 500 || turf_air.return_temperature() > 750 || !turf_air.total_moles() || isspaceturf(T) || (!isonshuttle && (istype(A, /area/shuttle) || istype(A, /area/space))) || (isonshuttle && !istype(A, /area/shuttle))) + if(turf_air.get_moles(GAS_H2) > 1 || turf_air.get_moles(GAS_TRITIUM) > 1 || turf_air.get_moles(GAS_PLASMA) > 1 || (locate(/obj/effect/hotspot) in T) || turf_air.return_pressure() > 500 || turf_air.return_temperature() > 750 || !turf_air.total_moles() || isspaceturf(T) || (!isonshuttle && (istype(A, /area/shuttle) || istype(A, /area/space))) || (isonshuttle && !istype(A, /area/shuttle))) to_chat(S, span_warning("Destroying this object has the potential to cause a hull breach. Aborting.")) S.target = null return TRUE @@ -188,7 +188,7 @@ for(var/turf/adj_turf in range(1, src)) var/area/adj_area = get_area(adj_turf) var/datum/gas_mixture/turf_air = adj_turf.return_air() - if(turf_air.get_moles(/datum/gas/hydrogen) > 1 || turf_air.get_moles(/datum/gas/tritium) > 1 || turf_air.get_moles(/datum/gas/plasma) > 1 || (locate(/obj/effect/hotspot) in adj_turf) || turf_air.return_pressure() > 500 || turf_air.return_temperature() > 750 || !turf_air.total_moles() || isspaceturf(adj_turf) || (!is_on_shuttle && (istype(adj_area, /area/shuttle) || istype(adj_area, /area/space))) || (is_on_shuttle && !istype(adj_area, /area/shuttle))) + if(turf_air.get_moles(GAS_H2) > 1 || turf_air.get_moles(GAS_TRITIUM) > 1 || turf_air.get_moles(GAS_PLASMA) > 1 || (locate(/obj/effect/hotspot) in adj_turf) || turf_air.return_pressure() > 500 || turf_air.return_temperature() > 750 || !turf_air.total_moles() || isspaceturf(adj_turf) || (!is_on_shuttle && (istype(adj_area, /area/shuttle) || istype(adj_area, /area/space))) || (is_on_shuttle && !istype(adj_area, /area/shuttle))) to_chat(actor, span_warning("Destroying this object has the potential to cause a hull breach. Aborting.")) actor.target = null return TRUE diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index c458f00a3f15..af3d3c365116 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -61,24 +61,6 @@ /// This must be the last test to run due to the inherent nature of the test iterating every single tangible atom in the game and qdeleting all of them (while taking long sleeps to make sure the garbage collector fires properly) taking a large amount of time. #define TEST_CREATE_AND_DESTROY INFINITY -/// Change color to red on ANSI terminal output, if enabled with -DANSICOLORS. -#ifdef ANSICOLORS -#define TEST_OUTPUT_RED(text) "\x1B\x5B1;31m[text]\x1B\x5B0m" -#else -#define TEST_OUTPUT_RED(text) (text) -#endif -/// Change color to green on ANSI terminal output, if enabled with -DANSICOLORS. -#ifdef ANSICOLORS -#define TEST_OUTPUT_GREEN(text) "\x1B\x5B1;32m[text]\x1B\x5B0m" -#else -#define TEST_OUTPUT_GREEN(text) (text) -#endif -/// Change color to yellow on ANSI terminal output, if enabled with -DANSICOLORS. -#ifdef ANSICOLORS -#define TEST_OUTPUT_YELLOW(text) "\x1B\x5B1;33m[text]\x1B\x5B0m" -#else -#define TEST_OUTPUT_YELLOW(text) (text) -#endif /// A trait source when adding traits through unit tests #define TRAIT_SOURCE_UNIT_TESTS "unit_tests" diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm index 3791b81a1913..fece5b1b1201 100644 --- a/code/modules/unit_tests/unit_test.dm +++ b/code/modules/unit_tests/unit_test.dm @@ -130,11 +130,12 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) var/skip_test = (test_path in SSmapping.config.skipped_tests) var/test_output_desc = "[test_path]" var/message = "" + var/map_name = SSmapping.config.map_name log_world("::group::[test_path]") if(skip_test) - log_world("[TEST_OUTPUT_YELLOW("SKIPPED")] Skipped run on map [SSmapping.config.map_name].") + log_world("[TEST_OUTPUT_YELLOW("SKIPPED")] Skipped run on map [map_name].") else @@ -144,7 +145,9 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) GLOB.current_test = null GLOB.failed_any_test |= !test.succeeded - var/list/log_entry = list() + var/list/log_entry = list( + "[test.succeeded ? TEST_OUTPUT_GREEN("PASS") : TEST_OUTPUT_RED("FAIL")]: [test_path] [duration / 10]s" + ) var/list/fail_reasons = test.fail_reasons for(var/reasonID in 1 to LAZYLEN(fail_reasons)) @@ -154,6 +157,14 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) test.log_for_test(text, "error", file, line) + // Github action annotation. + // See https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions + // Need to escape the text to properly support newlines. + var/annotation_text = replacetext(text, "%", "%25") + annotation_text = replacetext(annotation_text, "\n", "%0A") + + log_world("::error file=[file],line=[line],title=[map_name]: [test_path]::[annotation_text]") + // Normal log message log_entry += "\tFAILURE #[reasonID]: [text] at [file]:[line]" @@ -167,9 +178,6 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) log_world("::endgroup::") - if (!test.succeeded && !skip_test) - log_world("::error::[TEST_OUTPUT_RED("FAIL")] [test_output_desc]") - var/final_status = skip_test ? UNIT_TEST_SKIPPED : (test.succeeded ? UNIT_TEST_PASSED : UNIT_TEST_FAILED) test_results[test_path] = list("status" = final_status, "message" = message, "name" = test_path) diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index 4a0d87837d9d..02868530da54 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -526,7 +526,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) Upon hitting a target, the piston-ram will extend forward to make contact for some serious damage. \ Using a wrench on the piston valve will allow you to tweak the amount of gas used per punch to \ deal extra damage and hit targets further. Use a screwdriver to take out any attached tanks." - item = /obj/item/melee/powerfist + item = /obj/item/clothing/gloves/powerfist cost = 6 manufacturer = /datum/corporation/traitor/waffleco exclude_modes = list(/datum/game_mode/infiltration) // yogs: infiltration @@ -613,6 +613,15 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) manufacturer = /datum/corporation/traitor/donkco surplus = 10 +/datum/uplink_item/dangerous/watergun + name = "Extended Capacity Hyper-Soaker" + desc = "A simple yet effective way of applying chemicals to a target's skin. \ + Comes with a high-power nozzle and larger tank." + item = /obj/item/gun/water/syndicate + cost = 2 + manufacturer = /datum/corporation/traitor/donkco + surplus = 10 + /datum/uplink_item/dangerous/hardlightbow name = "Hardlight Bow" desc = "A modern bow that can fabricate hardlight arrows, designed for silent takedowns of targets." @@ -1462,7 +1471,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) completely silent as you slip away from the scene, or into a better position! You will not be able to take \ any actions for the 7 second duration." item = /obj/item/pseudocider - cost = 6 + cost = 8 exclude_modes = list(/datum/game_mode/nuclear) /datum/uplink_item/stealthy_tools/shadowcloak diff --git a/code/modules/vending/megaseed.dm b/code/modules/vending/megaseed.dm index 02d0313d2795..b26cc8daebc0 100644 --- a/code/modules/vending/megaseed.dm +++ b/code/modules/vending/megaseed.dm @@ -25,6 +25,7 @@ /obj/item/seeds/grape = 3, /obj/item/seeds/grass = 3, /obj/item/seeds/ute_nut = 3, + /obj/item/seeds/lanternfruit = 3, /obj/item/seeds/lemon = 3, /obj/item/seeds/lime = 3, /obj/item/seeds/onion = 3, diff --git a/code/modules/vending/toys.dm b/code/modules/vending/toys.dm index 92a1419fea2e..2cf117a730d2 100644 --- a/code/modules/vending/toys.dm +++ b/code/modules/vending/toys.dm @@ -26,6 +26,7 @@ /obj/item/gun/ballistic/shotgun/toy/crossbow = 10, /obj/item/gun/ballistic/automatic/c20r/toy/unrestricted = 10, /obj/item/gun/ballistic/automatic/l6_saw/toy/unrestricted = 10, + /obj/item/gun/water/full = 10, /obj/item/toy/katana = 10, /obj/item/melee/dualsaber/toy = 5, /obj/item/organ/cyberimp/chest/spinalspeed/toy = 5, diff --git a/config/admins.txt b/config/admins.txt index 66554b4c6855..e53c2ea948a8 100644 --- a/config/admins.txt +++ b/config/admins.txt @@ -11,11 +11,9 @@ AshCorr = Host Xantam = Host -adamsogm = Council Member -britishgrace = Council Member -margot = Council Member +aquizit = Council Member mordrehel = Council Member -ynot01 = Council Member +cowbot93 = Council Member jamied12 = Head Developer baiomu = Head Developer diff --git a/config/game_options.txt b/config/game_options.txt index bcdd19e1c326..fdc2772875aa 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -501,7 +501,7 @@ LAW_WEIGHT fitnesscoach,0 ION_LAW_WEIGHT fitnesscoach,3 LAW_WEIGHT educator,0 ION_LAW_WEIGHT educator,3 -LAW_WEIGHT mediator,1 +LAW_WEIGHT mediator,0 ION_LAW_WEIGHT mediator,3 ## Bad idea laws. Probably shouldn't enable these diff --git a/config/iceruinblacklist.txt b/config/iceruinblacklist.txt index 8b9a043b4e54..4718700e37c2 100644 --- a/config/iceruinblacklist.txt +++ b/config/iceruinblacklist.txt @@ -10,11 +10,13 @@ #_maps/RandomRuins/IceRuins/icemoon_surface_inn.dmm #_maps/RandomRuins/IceRuins/icemoon_surface_asteroid.dmm #_maps/RandomRuins/IceRuins/icemoon_surface_hotsprings.dmm +#_maps/RandomRuins/IceRuins/icemoon_surface_hermit.dmm +_maps/RandomRuins/IceRuins/icemoon_surface_walkervillage.dmm #_maps/RandomRuins/IceRuins/icemoon_underground_puzzle.dmm -#_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_village.dmm +_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_village.dmm #_maps/RandomRuins/IceRuins/icemoon_underground_mining_site.dmm #_maps/RandomRuins/IceRuins/icemoon_underground_library.dmm #_maps/RandomRuins/IceRuins/icemoon_underground_wrath.dmm #_maps/RandomRuins/IceRuins/icemoon_underground_lavaland.dmm #_maps/RandomRuins/IceRuins/icemoon_underground_bathhouse.dmm -#_maps/RandomRuins/IceRuins/icemoon_underground_wampacave.dmm +#_maps/RandomRuins/IceRuins/icemoon_underground_wampacave.dmm \ No newline at end of file diff --git a/config/minor_filter.txt b/config/minor_filter.txt index 62f32d579aaf..808fe7fbd295 100644 --- a/config/minor_filter.txt +++ b/config/minor_filter.txt @@ -46,3 +46,5 @@ pls=please plz=please \btf\b=the fuck \bi\b=I +auxmos=La Li Lu Le Lo +aux mos=La Li Lu Le Lo \ No newline at end of file diff --git a/dependencies.sh b/dependencies.sh old mode 100644 new mode 100755 index 7fa94eba3287..8f6360c72b76 --- a/dependencies.sh +++ b/dependencies.sh @@ -1,11 +1,11 @@ -#!/bin/bash +#!/bin/sh #Project dependencies file #Final authority on what's required to fully build the project # byond version -export BYOND_MAJOR=514 -export BYOND_MINOR=1589 +export BYOND_MAJOR=515 +export BYOND_MINOR=1620 #rust_g git tag export RUST_G_VERSION=1.2.0-yogs1 @@ -15,4 +15,10 @@ export NODE_VERSION=14 export NODE_VERSION_PRECISE=14.16.1 # SpacemanDMM git tag -export SPACEMAN_DMM_VERSION=suite-1.7.2 +export SPACEMAN_DMM_VERSION=suite-1.8 + +# Python version for mapmerge and other tools +export PYTHON_VERSION=3.9.0 + +# Auxmos git tag +export AUXMOS_VERSION=434ed4ca7a0bf072f9861bd6e54552af8fb9e27f diff --git a/goon/icons/turfs/floors.dmi b/goon/icons/turfs/floors.dmi index 6287504c132b..b5b3a57b9852 100644 Binary files a/goon/icons/turfs/floors.dmi and b/goon/icons/turfs/floors.dmi differ diff --git a/html/changelog.html b/html/changelog.html index bf976f3bef1b..3ae7cdded5f5 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -57,6 +57,398 @@ -->
+

08 December 2023

+

cowbot92 updated:

+
    +
  • Adds 3 new barsigns
  • +
  • Adds new barsign images
  • +
+ +

07 December 2023

+

LoliconSlayer updated:

+
    +
  • Tweaked the names of a few mech melee weapons
  • +
+ +

06 December 2023

+

AMyriad updated:

+
    +
  • Scrubbed the second "m" from the last mentions of "Centcomm"
  • +
  • All mentions of "NanoTrasen" have also been corrected to "Nanotrasen"
  • +
  • Added some more words and fixed some old ones for the Nordic accent
  • +
+

SapphicOverload updated:

+
    +
  • HFR processes at the same rate as other atmos machines now
  • +
  • fixed extended lungs
  • +
  • fixed a few issues with the tgui for supermatter monitor, HFR control panel, atmos scanner, and filters/scrubbers
  • +
  • fixed ethereal stomachs having the EMP effects of IPCs
  • +
+

azzzertyy updated:

+
    +
  • Network admin now has rnd access
  • +
+

warface1234455 updated:

+
    +
  • fix supermatter normal delam not working
  • +
+ +

05 December 2023

+

cowbot92 updated:

+
    +
  • Adds new alt-job titles to roboticists
  • +
+

ninjanomnom, Ryll-Ryll, Bizzonium, KylerAce, Sinsinins, lessthnthree updated:

+
    +
  • Added new fonts and refactored runechat. Also some backend stuff it's fine.
  • +
+

sapphicoverload, bluishtsunami updated:

+
    +
  • adds a water gun to donksoft vending machines (and uplink)
  • +
  • preternis water damage tweaked to be more affected by smaller volumes
  • +
  • preternis water damage updates immediately when splashed instead of waiting up to 2 seconds
  • +
+ +

04 December 2023

+

Moltijoe updated:

+
    +
  • Pseudocider costs 8tc instead of 6tc
  • +
  • Pseudocider has a 30s cooldown instead of 20s
  • +
+

SapphicOverload updated:

+
    +
  • electrical protection is now its own armor type
  • +
  • certain engineering equipment like hard hats and work boots now have electrical protection
  • +
  • spliced wires check electrical protection on your feet instead of your hands when you step on them
  • +
  • combat defib disarm takes electrical protection on targeted limb into account
  • +
  • lightning flow punches, combat defib disarm, and hacked cyborg hug module all check electrical protection on the targeted limb
  • +
  • touching hacked cyborg energy fields with your hand now actually checks protection on that hand
  • +
  • slightly reorganized the armor tags and adds electrical protection to the list
  • +
  • fixed nanites not being affected by electric shock because of a missing signal
  • +
  • fixed gloves and shoes with armor not actually protecting your hands and feet respectively
  • +
  • fixed power fist not working
  • +
+

azzzertyy updated:

+
    +
  • Mediator is no longer roundstart.
  • +
+ +

03 December 2023

+

cark updated:

+
    +
  • fixes missing floor in airlock on donut
  • +
+

itseasytosee, sapphicoverload updated:

+
    +
  • some items and projectiles are now better or worse than others at destroying things
  • +
  • chat messages from hitting an object now tell whether you can damage it
  • +
  • fixed machines/structures/etc not caring about armor penetration when hit by a melee weapon
  • +
  • fixed cannonballs not doing any damage to mobs
  • +
+

Moltijoe updated:

+
    +
  • Sometimes fixes feed ability sometimes breaking
  • +
  • Gangrel transformation ability now shows the radial menu before the 10 second do_after
  • +
  • Fixes gangrel transformation ability sometimes deleting itself without ever being used
  • +
  • Fixes gangrel werewolf transformation being eradicated from the timeline by tattax
  • +
+

SapphicOverload updated:

+
    +
  • fixed ED-209 not being affected by heavy EMPs
  • +
  • fixed leg implants not being affected by EMPs at all
  • +
  • fixed cybernetic ears causing longer knockdown times on light EMPs instead of the other way around
  • +
  • fixed nanite heart killing you instantly on EMP regardless of whether or not it kills your nanites
  • +
  • HoS gun now shoots ion carbine projectiles instead of its own redundant projectile type
  • +
  • mech ion cannon has 1.5x stronger EMPs than the ion rifle
  • +
  • syndicate EMP bomb has 2.5x stronger EMPs than standard EMP grenades
  • +
  • reworks EMPs to allow any severity, which now decreases with distance
  • +
+ +

02 December 2023

+

Moltijoe updated:

+
    +
  • No more infinitely duplicating hulk DAN
  • +
  • Hulk now occasionally says the brain damage hulk lines
  • +
+

SapphicOverload updated:

+
    +
  • fixed runtime error when passive vents encounter zero temperature or zero volume
  • +
  • fixed abandoned crates having a 2% chance to cause runtime errors when initialized
  • +
+ +

01 December 2023

+

Twaticus, Imaginos16, Cark updated:

+
    +
  • added new object sprite for plasteel tile
  • +
  • deleted old object sprite for plasteel tile
  • +
+

JohnFulpWillard updated:

+
    +
  • Stasis units and sleepers now have proper overlays and lavaland sleepers aren't invisible anymore.
  • +
+

Yarinoi updated:

+
    +
  • Pitying the miners attempting to look for it, the Demonic Frost Miner now gives out a Hollow Signal on GPS.
  • +
+

azzzertyy updated:

+
    +
  • You can now point while handcuffed
  • +
+

cowbot92 updated:

+
    +
  • Adds new bar signs
  • +
+ +

30 November 2023

+

ToasterBiome updated:

+
    +
  • Adds a new lavaland lava type that you can't replace with shelter
  • +
  • lavaland syndie base is surrounded by no-shelter lavaland lava
  • +
+ +

29 November 2023

+

Moltijoe updated:

+
    +
  • Brig physician also gets cloning and airlock access during skeleton crew
  • +
  • Paramedic also gets surgery access during skeleton crew
  • +
  • Mining medic also gets cloning, maint, and airlock access during skeleton crew
  • +
  • All hecata zombies die when the controlling bloodsucker dies
  • +
  • lightning flow no longer immobilizes for like 0.1 seconds every dash
  • +
  • Preterni no longer get 20% more power from liquid electricity than other powerhungry species
  • +
  • All powerhungry species now get "food" from consuming teslium, not just Preterni
  • +
+

Runian updated:

+
    +
  • Lizard tail users can *thump their tail.
  • +
  • Tail thump.
  • +
  • Guardian's Frenzy Ability now respects the three second cooldown that it is suppose to be limited by.
  • +
+

ToasterBiome updated:

+
    +
  • Removes tile grime and support for it.
  • +
  • Replaces tiles to be less shiny.
  • +
+

ynot01 updated:

+
    +
  • Command channel is now blue once more
  • +
  • fixed pseudocider not duplicating headwear
  • +
+ +

28 November 2023

+

MajManatee updated:

+
    +
  • Horrors can now scan their hosts
  • +
  • Horror chemicals now say how much they inject
  • +
+

Moltijoe updated:

+
    +
  • Only Delta alert gets red lights
  • +
  • Fixes an IAA bug involving pseudocider
  • +
  • adds a glowing outline to anyone with the holy light heal boost
  • +
  • fixed a bug where limb healing generated less favour than overall healing
  • +
  • Increases the holy light heal boost duration to 1 minute from 30 seconds
  • +
  • Reduces the amount of favour that holy light generates by 50%
  • +
  • Gives warden brig phys access during skeleton crew
  • +
  • Makes monster hunters monster hunting objective actually tell the monster hunter to hunt monsters
  • +
+

Runian updated:

+
    +
  • Constructed anchored emitters are correctly recognized as wrenched; you no longer need to wrench these anchored emitters twice to make it work.
  • +
  • Flying Fang's damage-dealing disarms respects pacifism as intended.
  • +
+

SapphicOverload updated:

+
    +
  • fixed fire extinguishers not working if the particle never moves
  • +
+

cowbot92 updated:

+
    +
  • Added new fruit
  • +
  • Added new drink to go with that fruit
  • +
  • added some icons and images for lantern fruits and drinks
  • +
+ +

27 November 2023

+

goober3, cark updated:

+
    +
  • added some dirt linings
  • +
+

Moltijoe updated:

+
    +
  • Syndicate fedora can no longer be caught using throw mode
  • +
+

Mqiib updated:

+
    +
  • Lizard wings now use the new lizard colors instead of the slightly-off old colors
  • +
+

Runian updated:

+
    +
  • Ion storms can affect up to 20 airlocks and 10 APCs with random effects, only if is no AI.
  • +
  • Airlocks affected by ion storms will randomly have one of the following effects: toggle bolts, toggle emergency access, shock temporarily or have their safety & speed toggled.
  • +
  • APCs affected by ion storms will have one of three or all of their power channels turned off.
  • +
+

SapphicOverload updated:

+
    +
  • preternis now purge 4% of internal chemicals every tick, instead of purging everything after 20 ticks
  • +
  • preternis are no longer immune to the effects of morphine and a few other chemicals
  • +
  • fixed unintended change to damage of every two-handed weapon
  • +
  • fixed runtime error when trying to use certain two-handed weapons with one hand
  • +
  • fixed preternis being affected by water through hardsuits
  • +
+

cowbot92 updated:

+
    +
  • Ports updated TG announcements & TGUI
  • +
+ +

26 November 2023

+

Moltijoe updated:

+
    +
  • Battle royale loot distribution
  • +
+

SomeguyManperson updated:

+
    +
  • hallucination anomalies have had their effects altered. You many want to bring a toolbox instead of mesons when responding to one
  • +
  • hallucination reactive armor has had its effects modified similarly to the new effects of the anomaly
  • +
  • the supermatter will no longer spawn hallucination anomalies when exploding, on fire, or otherwise.
  • +
+ +

25 November 2023

+

Ghommie updated:

+
    +
  • Examining a human mob as an observer displays "Quirks", not "Traits"
  • +
+

JohnFulpWillard updated:

+
    +
  • Seclites now have directional lights- point them in the direction you want to see more of.
  • +
  • Ported over many refactors to lighting and opacity. Please report if you can walk or see through walls unintentionally.
  • +
+

Majkl-J updated:

+
    +
  • Virology: New symptom, superficial healing
  • +
+

Runian updated:

+
    +
  • Shooting plasma sheets with a damaging burn-based projectile ignites it.
  • +
+

SapphicOverload updated:

+
    +
  • added preference for non-upgraded cybernetic organs as quirk options
  • +
  • random cybernetic organ quirk costs 3 instead of 4
  • +
+

cowbot92 updated:

+
    +
  • Adds auxmos to the minor filter
  • +
+ +

23 November 2023

+

SapphicOverload updated:

+
    +
  • power-fist works like a glove now
  • +
+

SomeguyManperson updated:

+
    +
  • gangrel gorilla transformation is now 15 armor down from 40
  • +
+

Yarinoi updated:

+
    +
  • Medical can print chemical analyzer implants again.
  • +
+

warface1234455 updated:

+
    +
  • Remove the portable pump cargo pack
  • +
+

ynot01 updated:

+
    +
  • The door between the armory and the auxiliary armory are now default security access
  • +
+ +

22 November 2023

+

PositiveEntropy, Cark, Blutsu updated:

+
    +
  • new wood sprites from TG, and resprites on stairs by Blutsu
  • +
  • replaces old wood tile sprites
  • +
+

cark updated:

+
    +
  • bridge on donut now has an APC and blast doors, apc in chapel is moved and some other minor fixes
  • +
+

00ze-cyclone updated:

+
    +
  • Removed helmet, bulletproof helmet and riot helmet crates
  • +
  • armor, bulletproof armor and riot armor crates now contain helmets as well, price adjusted to cost the same as before
  • +
+

JohnFulpWillard updated:

+
    +
  • Pancake overlays now work
  • +
+

SapphicOverload updated:

+
    +
  • fixed people with the bald trait not being bald when cloned
  • +
+

Therandomhoboo updated:

+
    +
  • Glycerol making results in 3 units instead of 1
  • +
  • Reinforced Window Damage deflection is now 11 instead of 10
  • +
+

wonderinghost updated:

+
    +
  • Adds new programs and hardware to pdas
  • +
+ +

20 November 2023

+

Cowbot92 & ChubbyGummibear updated:

+
    +
  • tweaks heretic TGUI
  • +
  • tweaks heretic blade's wound chance
  • +
+

Moltijoe updated:

+
    +
  • Fixes a bug where lightning flow disabled certain actions if a dash ended weirdly
  • +
  • Makes syndicate fedora and boomerang not super janky
  • +
  • Syndicate fedora has a longer click throw cd
  • +
  • Fixes extended shock touch not having a cooldown or sound effect
  • +
+ +

19 November 2023

+

Cark, Paxilmaniac updated:

+
    +
  • added a stone floor icon
  • +
+

JohnFulpWillard, warface1234455 updated:

+
    +
  • Atmos alert console can clear air alarm atmos alert
  • +
  • During an active fire nearby a firealarm, it will show you the current temperature when examined
  • +
  • Firealarm now notify on engineering channel when theres a fire
  • +
  • Fix station alert console and program not updating overlays
  • +
  • Fix fire alerts not clearing when there are multiple fire alarms in one area
  • +
  • fix destroyed airalarm clearing atmos alert if theres an actual atmos alert in an area with multiple air alarms
  • +
+

cark updated:

+
    +
  • fixes issues with the asteroid field on donut causing people to get teleported inside rocks when moving onto the z-level
  • +
  • adds more wall extinguishers to donut
  • +
+

Moltijoe updated:

+
    +
  • Lets admins choose the amount of TC given when they make everyone traitor
  • +
+

SapphicOverload updated:

+
    +
  • mech extinguisher uses firefighting foam instead of water
  • +
  • fixed extinguisher particles not disappearing when they stop moving
  • +
  • fixed blocking your own extinguisher when moving forward
  • +
  • lizard tails grow back properly
  • +
  • fire extinguishers can once again extinguish fire
  • +
+

bruhlookatthisdood updated:

+
    +
  • [Donut] Moved medical laptop in brig medical to make medical supplies accessible
  • +
+

ynot01 updated:

+
    +
  • Added Christ Christodoulou - Coalescence (2023) to the lobby playlist
  • +
  • Removed Christ Christodoulou - Coalescence (2013) from the lobby playlist
  • +
+

18 November 2023

Aquizit updated:

    @@ -1647,572 +2039,6 @@

    tattax updated:

    • readds pacify (spell) to the game
    - -

    09 September 2023

    -

    MidoriWroth, Ghommie, ktlwjec updated:

    -
      -
    • Peanuts. Seeds start in the botany vendor. They can be grinded to make peanut butter.
    • -
    • Breadsticks. Raw breadsticks crafted with 1 dough slice, 3u salt, 2 butter slices. Baked in the oven.
    • -
    • Granola bar. Crafted with 1 oat stalk, 1 peanut, 1 chocolate, 1 raisins, 2u sugar.
    • -
    • Onigiri. Crafted with 1 seaweed sheet and 1 boiled rice. Can be customised with other ingredients.
    • -
    • Peanut butter cookie. Crafted with 5u peanut butter, 1 pastry base.
    • -
    • Brownie batter. Raw brownie batter crafted with 5u flour, 5u sugar, 2 eggs, 5u coco powder, 4 butter slices. Baked in the oven and then sliced into 4 pieces.
    • -
    • Peanut butter and banana sandwich. Crafted with 2 bread slices, 5u peanut butter, 1 banana.
    • -
    • Peanut butter and jelly sandwich. Crafted with 2 bread slices, 5u peanut butter, 5u cherry jelly.
    • -
    • Nigiri sushi. Crafted with 1 seaweed sheet, 1 boiled rice, 1 carp meat, 2u soy sauce.
    • -
    -

    cark updated:

    -
      -
    • the beach biodome no longer spawns on lavaland
    • -
    -

    MajManatee updated:

    -
      -
    • Added 3 new ghost types
    • -
    -

    Moltijoe updated:

    -
      -
    • Cultist mirror shield no longer spawns infinite illusions if blocking a shotgun
    • -
    • Cultist mirror shield can only spawn 4 illusions before breaking instead of 5
    • -
    • Cultist mirror shield illusions have 1 health and 0 damage
    • -
    • Blood cult spear is huge instead of normal size
    • -
    • Northern Coat is no longer ckey locked
    • -
    • Holy Light water no longer applies a heal boost
    • -
    • Holy Light bible now applies a 30 second duration heal boost
    • -
    • Holy Light bible now heals for 10 instead of 40 with a 10 second cooldown instead of 12 and has no favor cost
    • -
    • Holy Light heal boost now increases by 100% (200% in chapel) instead of 20% (40% in chapel)
    • -
    • Holy Light medbot applies the heal boost status effect instead of injecting holy water
    • -
    • Borg reagent dispensers regen in seconds rather than deciseconds
    • -
    • Borg reagent dispensers regen less affected by lag
    • -
    • Spawns 3 clockcult + 1 for every 8 players over 30 instead of 4 + 1 for every 10
    • -
    • CPR only requires lungs, not needing to breathe
    • -
    • His Grace can be bought by assistants
    • -
    • Drag and drop iv drip filling
    • -
    • Cultist shield robe has 1 shield charge, but regens after 45 seconds of not getting hit
    • -
    -

    Runian updated:

    -
      -
    • Syndicate Surgery Duffel Bag's description in the Uplink now accurately tells you that the surgery tools have double toolspeed (0.5) and includes a surgical mat.
    • -
    • Failed cyborg shoves no longer push them back two tiles.
    • -
    • Hulk punches on cyborgs now properly pushes them back two tiles.
    • -
    • PKA upgrades properly eject when crowbarred.
    • -
    • A new upgrade for engineering and mining cyborgs that replaces their normal meson vision with night vision meson vision.
    • -
    • Cyborg meson/material dark vision is now consistent with the human version of 2 tiles.
    • -
    • Cyborg meson/material lighting alpha is now consistent with the human version.
    • -
    -

    SomeguyManperson updated:

    -
      -
    • Syndicate icemoon base has been downgraded to keep the syndicate on the base
    • -
    -

    azzzertyy updated:

    -
      -
    • Chaplain no longer throws people into snow on Icemeta
    • -
    • No more superspeed on icemeta
    • -
    -

    solwashere updated:

    -
      -
    • Adds "testing" to the GitHub PR template.
    • -
    -

    warface1234455 updated:

    -
      -
    • Bluespace harvester can now output alien tool for 60000 points
    • -
    - -

    08 September 2023

    -

    MajManatee updated:

    -
      -
    • generator fuel can be dragged into the generator now.
    • -
    -

    Moltijoe updated:

    -
      -
    • Preterni are slightly more likely to catch viruses than before
    • -
    • Viruses in preterni progress faster
    • -
    • Preternis water damage does ~50% more stamina damage
    • -
    -

    adamsong updated:

    -
      -
    • fixed photos being bugged as hell
    • -
    - -

    07 September 2023

    -

    cark updated:

    -
      -
    • removes the two hospital ruins on lavaland
    • -
    -

    Runian updated:

    -
      -
    • Clown Cyborg's pie cannon now properly recharges every 4 seconds (2 ticks) instead of every 2 seconds (1 tick).
    • -
    • All self-recharging pneumatic cannon now recharge based on delta_time instead of ticks. This means that you won't lose out when lag happens.
    • -
    -

    SapphicOverload updated:

    -
      -
    • hecata clan necromancy reverts you back to your original species after it ends instead of staying a zombie
    • -
    -

    adamsong updated:

    -
      -
    • bluespace harvester now has a 10 minute cooldown after spawning a portal when not emagged
    • -
    - -

    06 September 2023

    -

    Runian updated:

    -
      -
    • You must now be adjacent to unlock or lock a robot's cover instead of infinite range.
    • -
    - -

    05 September 2023

    -

    Addust updated:

    -
      -
    • syndicate icemoon is slightly less shit. _**I CANNOT FIX THE RANDOM FAUNA SPAWNS. THAT'S THE ICEMOON DEV'S PROBLEM.**_
    • -
    • i fucked up
    • -
    -

    Runian updated:

    -
      -
    • Pulsing Mech Fabricator's WIRE_ZAP no longer breaks your limbs unless you are adjacent to it as intended.
    • -
    -

    SomeguyManperson updated:

    -
      -
    • holy light now gains more favor when gaining favor
    • -
    -

    wonderinghost updated:

    -
      -
    • Added pencil holder to bureaucracy crate and game.
    • -
    • adds pencil holder files
    • -
    - -

    04 September 2023

    -

    cark updated:

    -
      -
    • donors can take pride hoodies as a donor item now
    • -
    -

    ktlwjec updated:

    -
      -
    • Roboticist and geneticist get rnd console access on skeleton crew.
    • -
    • Engineers and shaft miners can use the rnd console on skeleton crew.
    • -
    -

    Addust updated:

    -
      -
    • The Syndicate has stopped throwing their supposedly important listening stations into gibtonite-filled shithole rocks, and has also supplied a few extra supplies.
    • -
    • i forgor an air alarm in syndie lavaland
    • -
    -

    Marmio64 updated:

    -
      -
    • Hecata Bloodsuckers need to revive 4-5 people rather than 7-8
    • -
    -

    Moltijoe updated:

    -
      -
    • vials reskin using the proper sprite again
    • -
    -

    Runian updated:

    -
      -
    • Certain words in the German accent such as "research" and "scientist" are now properly accented.
    • -
    -

    SapphicOverload updated:

    -
      -
    • fixed bloodsucker vassalization not removing mindshield implants
    • -
    -

    SomeguyManperson updated:

    -
      -
    • coders are no longer required to explain why "the game functions correctly" is good for the game
    • -
    -

    adamsong updated:

    -
      -
    • fixed AI shell lawsync not working
    • -
    • fixed photos forgetting about people who are cremated
    • -
    • fixed photos not recognizing targets who were cloned
    • -
    • fixed photos thinking dead people are alive after copying
    • -
    -

    warface1234455 updated:

    -
      -
    • Replaces old pda with modern pda in pda box
    • -
    - -

    03 September 2023

    -

    MajManatee updated:

    -
      -
    • The engineering vendor now has one compressed matter per RCD instead of 3/5
    • -
    -

    Moltijoe updated:

    -
      -
    • Preternis Liquidator now needs to actually do the combo
    • -
    -

    SapphicOverload updated:

    -
      -
    • necromancy no longer works on mindshielded people unless they're on a persuasion rack
    • -
    • fixed x-ray bolts causing toxin damage to rad-immune species when embedded
    • -
    • preternis now slow down and suffocate when low on charge instead of just instantly dropping dead when they hit zero
    • -
    • liquid electricity can now actually charge species that run on electricity
    • -
    • radiation charges ethereals now
    • -
    • preternis, ethereal, and IPC charging have been refactored, please report any bugs you find
    • -
    -

    warface1234455 updated:

    -
      -
    • Give the gas analyzer ability to scan turf next to the user
    • -
    - -

    02 September 2023

    -

    @cuackles, @SapphicOverload updated:

    -
      -
    • adds pride jackets to hacked clothing vendors
    • -
    • pride jackets
    • -
    -

    ArcaneMusic, Ktlwjec updated:

    -
      -
    • BBQ sauce, made with 1u ash, 1u tomato juice, 3u saline glucose, 1u black pepper.
    • -
    • BBQ ribs, made with 2 rods, 5u bbq sauce, 2 steaks.
    • -
    • 2 BBQ sauce packets in the kitchen dinnerware vendor.
    • -
    -

    cark updated:

    -
      -
    • kills under-window firelocks across all maps, making them consistent with each other and themselves.
    • -
    -

    JamieD1 updated:

    -
      -
    • Fixes shitty Pranksimov Laws
    • -
    -

    Marmio64 updated:

    -
      -
    • Hecata bloodsuckers take 3x as long (18 seconds) to necromance mindshielded non vassals.
    • -
    • Syndicate derelict engis can use their c20r
    • -
    -

    Moltijoe updated:

    -
      -
    • Holy medbots have antimagic and also inject holy water
    • -
    • Holy revival rite gives 2 minutes of antimagic
    • -
    • Getting the adrenaline buff from damage gives a mood boost
    • -
    • Worldbreaker tweaks
    • -
    • throw only does damage upon collision, not upon throwing
    • -
    • grabbing now stuns for a very short time to allow for aiming
    • -
    • pummel does 20 damage instead of 15
    • -
    • pummel has regular attack cooldown instead of slower (preterni no longer attack slower)
    • -
    • plates have 25 health instead of 15
    • -
    • can only have 3 plates over armour cap instead of 5
    • -
    • plates take 1/4 damage from non brute and burn rather than 1/3
    • -
    • plates give more slowdown
    • -
    • leap cooldown no longer scales directly with number of plates, instead just takes 1 second longer if heavy
    • -
    • leap speed now directly scales with movespeed (meaning outside sources of movespeed will increase it)
    • -
    • leap cooldown only starts once you land, rather than when you start jumping
    • -
    • now gives softcrit immunity
    • -
    • no longer gives damage slowdown resistance
    • -
    • never takes damage from being thrown into a wall
    • -
    • attacks can now hurt mechs
    • -
    -

    Runian updated:

    -
      -
    • A new upgrade for medical cyborgs that gives them a gripper that lets them hold bottles, beakers, and blood bags.
    • -
    • Cyborg gripper now copy overlays for the held items.
    • -
    -

    SomeguyManperson updated:

    -
      -
    • holy light chaplains no longer gain favor from bible bashing people, instead spending favor to heal
    • -
    • holy light now provides a passive buff to people who ingest holy water, increasing incoming healing by 20%, doubled in the chapel. Bonus healing applied by this effect is also turned into favor. Bible bashing someone with this buff has a massively reduced favor cost, but does not heal significantly more than the default.
    • -
    -

    adamsong updated:

    -
      -
    • fixed a few bus buttons being available to moderators
    • -
    • Admins can now view their own permissions
    • -
    - -

    01 September 2023

    -

    Moltijoe updated:

    -
      -
    • passive good mood organic limb healing now requires being full instead of mood
    • -
    • passive organic limb healing now has a 100% chance per tick, but heals half as much
    • -
    -

    Runian updated:

    -
      -
    • Service cyborgs start with a gripper that lets them interact with various service items, including food.
    • -
    • A new upgrade is available for service cyborgs that lets them access the cooking section of the crafting menu only.
    • -
    • Cyborgs can interact with things that they CanReach instead of having to be adjacent.
    • -
    • Cyborgs can now toggle griddles and ovens.
    • -
    • Grippers now re-center items that they pick up.
    • -
    -

    SapphicOverload updated:

    -
      -
    • ethereals have electrolyzer breath now
    • -
    - -

    31 August 2023

    -

    xXPawnStarrXx updated:

    -
      -
    • Fixed corn cobs not making seeds and lying to you in the text box.
    • -
    -

    Addust updated:

    -
      -
    • cleans the naughty room maint ruin (sadly not with fire)
    • -
    -

    Aquizit updated:

    -
      -
    • Change of flavor text for no cap at round start
    • -
    -

    GraveHat updated:

    -
      -
    • renames the corn maze datum from forgottenkitchen to chasmcornmaze to avoid confusion
    • -
    • adds a Lavaland ruin for the Herald Elite Fauna
    • -
    -

    JohnFulpWillard updated:

    -
      -
    • Pipe overlays
    • -
    -

    MajManatee updated:

    -
      -
    • Selecting wizard now lets you play ragin and BS wizard modes.
    • -
    -

    Moltijoe updated:

    -
      -
    • Fixes ethereal brute mod being 1.5 rather than 1.25 like intended
    • -
    • Ethereals can now release excess power into already full apcs
    • -
    • Rad goats can no longer crash the server using unlimited goat works
    • -
    -

    Runian updated:

    -
      -
    • A new upgrade for engineering cyborgs have been added that gives them a BRPED. It requires the RPED upgrade to be installed first as a prerequisite.
    • -
    • Prerequisite upgrades for cyborg upgrades properly function as intended.
    • -
    • On deactivation, Cyborg RPED drop all parts onto the floor instead of disappearing into the void.
    • -
    • "Cyborg Upgrades: Advanced Utility" now also requires the "Applied Bluespace Research" techweb node as a prerequisite.
    • -
    • Cyborg RPED's name starts with "cyborg" to note it is the cyborg version.
    • -
    -

    SapphicOverload updated:

    -
      -
    • fixed missing wire in CE office, APC is connected now
    • -
    -

    adamsong updated:

    -
      -
    • adminwho now knows grammar
    • -
    -

    solwashere updated:

    -
      -
    • Suppressors no longer add a weight class to weapons
    • -
    • Enloudener no long can be exploited to permanently decrease a weapons weight class
    • -
    -

    warface1234455 updated:

    -
      -
    • Anticitizen line now work in sechailer
    • -
    - -

    29 August 2023

    -

    TehZombehz for the sprites, san7890, ktlwjec updated:

    -
      -
    • Abductor plushies! Winnable with arcade machines, or can be bought for 1 point by abductors.
    • -
    • Decorative Items section on the abductor console.
    • -
    • Moves random poster from basic gear to decorative items for abductors.
    • -
    -

    tf-4 updated:

    -
      -
    • Fixed a spelling error with the daps emote.
    • -
    -

    timothymtorres updated:

    -
      -
    • Adds a new light effect to slot machines when you win.
    • -
    • Adds new sounds to slot machines.
    • -
    -

    Aquizit updated:

    -
      -
    • sets mood to TRUE for family heirloom quirk
    • -
    -

    JohnFulpWillard updated:

    -
      -
    • All sechailer lines now should work again.
    • -
    -

    Marmio64 updated:

    -
      -
    • Space syndicate listening post slight loot tweak. One agent is now considered the superior and has better equipment with an ultra secure pinlock revolver, while their subordinate has a combat knife rather than an energy sword.
    • -
    • One of the energy swords locked inside a crate on the syndicate space derelict is replaced with a ultrasecure c20r SMG that self destruct upon use/tamper by non syndicates.
    • -
    -

    Moltijoe updated:

    -
      -
    • Flying people can carry others over chasms or lava without killing them
    • -
    -

    Runian updated:

    -
      -
    • Syndicate MMIs can be purchased by Roboticists (and the Research Director) for 3 telecrystals.
    • -
    • Syndicate MMIs temporarily turns the inserted brain into a mindslave until the brain is removed.
    • -
    • Cyborgs with a Syndicate MMI retain all functions that as a normal cyborg would, except they have an irremovable law zero all to serve whoever imprinted on it (or The Syndicate if none).
    • -
    • Syndicate MMIs no longer gives the Syndicate Override lawset, prevents connection for any AI, or disallow law changes.
    • -
    • Syndicate Surgery Duffel Bag has a normal MMI instead of a Syndicate MMI.
    • -
    • You can toggle the radio of a MMI via alt-click regardless if there was a brain or not.
    • -
    • Cyborgs can now repair fire axe cabinets properly.
    • -
    • Using cyborg reinforced glass on/for certain structures now work properly.
    • -
    • Cyborgs can attempt to trigger a fire axe cabinet's alarm by interacting with it on harm intent with no module.
    • -
    -

    Therandomhoboo updated:

    -
      -
    • New drink, Syndicate Screwdriver
    • -
    • Syndicate Screwdriver sprite
    • -
    -

    adamsong updated:

    -
      -
    • fixed errors when logging clones
    • -
    • fixed engineering payouts erroring at the start of the round
    • -
    • fixed slurring
    • -
    • fixed a runtime when checking if infiltrators can spawn too early in the round
    • -
    • fixed a couple errors with the gender selector
    • -
    - -

    28 August 2023

    -

    Runian updated:

    -
      -
    • Pranksimov, a funny variant of Crewsimov, has been added.
    • -
    • Cmagging a Crewismov law board converts it to a Pranksimov law board.
    • -
    • Cmagging a AI's B.O.R.I.S shell will set their module to Clown.
    • -
    • Cmagging a Cyborg will disconnect them from the AI and set their laws to Pranksimov. However, be warned that there won't be a law zero! Hope they find helping you more funnier than not.
    • -
    - -

    27 August 2023

    -

    Addust updated:

    -
      -
    • The Syndicate Icemoon base!
    • -
    • A Syndicate research post with 6 crew, deep within the icy wastes.
    • -
    • i fucked up the firing pin boxes woops
    • -
    -

    MajManatee updated:

    -
      -
    • Two vital emotes. You can now Hit the griddy and Do the stanky leg.
    • -
    -

    Yarinoi updated:

    -
      -
    • The mental faculties of the average crew member have increased.
    • -
    -

    warface1234455 updated:

    -
      -
    • fix mirror not shifting to the wall when placed
    • -
    - -

    26 August 2023

    -

    warface1234455 updated:

    -
      -
    • you can now craft mirror and put it on wall using 1 silver, 1 rod and 1 glass
    • -
    - -

    25 August 2023

    -

    Moltijoe updated:

    -
      -
    • Locks Worldbreaker behind hijack and glorious death
    • -
    -

    SapphicOverload updated:

    -
      -
    • ultra violence is now hijack/martyr only
    • -
    -

    ToasterBiome updated:

    -
      -
    • BoxStation detective office flipped
    • -
    -

    warface1234455 updated:

    -
      -
    • hotfix altclicking pda not ejecting id out
    • -
    - -

    24 August 2023

    -

    goobliner updated:

    -
      -
    • Four new skin tones.
    • -
    -

    SapphicOverload updated:

    -
      -
    • fixed lemoline recipe
    • -
    -

    warface1234455 updated:

    -
      -
    • fix altclicking pda for secondary card not updating sec record
    • -
    - -

    23 August 2023

    -

    Marmio64 updated:

    -
      -
    • Ultrakill martial art is 20 TC again instead of 16
    • -
    -

    Runian updated:

    -
      -
    • You can no longer respawn immediately as a servant golem after already having respawned as a servant golem before. Use your golem life wisely until your golem respawn timer has passed.
    • -
    • Uranium golem info text no longer lies to you by removing the claim that your punches do as much as a human.
    • -
    • Golems stop wagging their tail if they somehow die with one.
    • -
    • "Cyborg Upgrade (Translation Matrix)" design now prints the correct upgrade.
    • -
    • langauges -> languages
    • -
    -

    iloveloopers updated:

    -
      -
    • Heretic worm ascension abillity to contract has had its cooldown reduced to 15 seconds
    • -
    -

    warface1234455 updated:

    -
      -
    • readd radiation anomaly that shoots radballs and emits radiation (this is normal anomaly that doesnt spawn rad goat, admin one does)
    • -
    • replaces the orange goat with rad goat on goat search shuttle
    • -
    • rainbow goat is now replaced with rad goat in exotic goat crate
    • -
    - -

    22 August 2023

    -

    cark updated:

    -
      -
    • fixes a broken pipe in the backroom of botany
    • -
    -

    Runian updated:

    -
      -
    • Engineering Cyborg's gripper can pick up conveyor belts and conveyor belt switches.
    • -
    -

    maxion12345 updated:

    -
      -
    • Added the Crowd-Sourced Shuttle. This shuttle was built from the BYOS on round 48641
    • -
    - -

    21 August 2023

    -

    carshalash updated:

    -
      -
    • You can craft paper cups using 2 paper.
    • -
    -

    ktlwjec updated:

    -
      -
    • Enchiladas needs a cheese wedge to craft.
    • -
    • Khinkali needs an onion slice and garlic to craft.
    • -
    • Chocolate orange needs 2 units of orange juice, instead of an orange, to craft.
    • -
    • Mushroom and vegetable pizzas both need a cheese wedge and tomato to craft.
    • -
    -

    Runian updated:

    -
      -
    • Jestographic Sequencer, a role-restricted traitor item for the Clown, is buyable at 4 TCs.
    • -
    • Jestographic Sequencer, if used on airlocks, will invert access.
    • -
    • Failing to emag something refunds the charge.
    • -
    • Cyborgs gets feedback similar to the AI when they interact with an non-functioning (e.g emagged) airlock.
    • -
    • Mechs no longer need a pilot to determine if they have access to a door.
    • -
    • Changed Explosive Airlock Charge's uplink description to be more accurate on how it is triggered.
    • -
    • Emagging the sechailer works now.
    • -
    -

    adamsong updated:

    -
      -
    • grants players cured of tumors clothes privileges again
    • -
    • fixed pet kill objective name typo
    • -
    - -

    20 August 2023

    -

    Rhials, ktlwjec updated:

    -
      -
    • The abductor equipment vendor now sells decorative abductor posters, at a price of 1 research point.
    • -
    • Posters can now be hung on abductor walls.
    • -
    -

    JohnFulpWillard & Mothblocks updated:

    -
      -
    • Removes being able to stack do_afters on things (like surgery on several limbs on the same person).
    • -
    • Removed do_mob, do_after_mob and do_atom.
    • -
    • You now do CPR faster after the first attempt.
    • -
    -

    Moltijoe updated:

    -
      -
    • Fixes some weird interactions around multiple sources of EMP immunity
    • -
    -

    SapphicOverload updated:

    -
      -
    • fixed lizard snouts
    • -
    • fixed a spriting error causing glasses to be partially hidden under some lizard snouts
    • -
    -

    Scrambledeggs00 updated:

    -
      -
    • Peacekeeper helm, belt, vest, and uniforms added
    • -
    • Peacekeeper riot suit, helm, beret, tactical stunprod, and tactical breath mask have new sprites
    • -
    • Most Peacekeeper gear is no longer green tinted Security gear
    • -
    -

    wonderinghost updated:

    -
      -
    • Minor changes to law office
    • -
    • Deletes old pda cartridge
    • -
    • Adds printer and pens
    • -
GoonStation 13 Development Team diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index df0533717bd2..7c6db608a26f 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -42262,3 +42262,291 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - mapping: Added /tcommsat/storage area and icon - mapping: Replaced maint with storage on Box & Asteroid - mapping: Fixed area swap on Asteroid +2023-11-19: + ' Cark, Paxilmaniac': + - imageadd: added a stone floor icon + ' JohnFulpWillard, warface1234455': + - rscadd: Atmos alert console can clear air alarm atmos alert + - rscadd: During an active fire nearby a firealarm, it will show you the current + temperature when examined + - tweak: Firealarm now notify on engineering channel when theres a fire + - bugfix: Fix station alert console and program not updating overlays + - bugfix: Fix fire alerts not clearing when there are multiple fire alarms in one + area + - bugfix: fix destroyed airalarm clearing atmos alert if theres an actual atmos + alert in an area with multiple air alarms + ' cark': + - mapping: fixes issues with the asteroid field on donut causing people to get teleported + inside rocks when moving onto the z-level + - mapping: adds more wall extinguishers to donut + Moltijoe: + - tweak: Lets admins choose the amount of TC given when they make everyone traitor + SapphicOverload: + - tweak: mech extinguisher uses firefighting foam instead of water + - bugfix: fixed extinguisher particles not disappearing when they stop moving + - bugfix: fixed blocking your own extinguisher when moving forward + - bugfix: lizard tails grow back properly + - bugfix: fire extinguishers can once again extinguish fire + bruhlookatthisdood: + - bugfix: '[Donut] Moved medical laptop in brig medical to make medical supplies + accessible' + ynot01: + - rscadd: Added Christ Christodoulou - Coalescence (2023) to the lobby playlist + - rscdel: Removed Christ Christodoulou - Coalescence (2013) from the lobby playlist +2023-11-20: + ' Cowbot92 & ChubbyGummibear': + - tweak: tweaks heretic TGUI + - tweak: tweaks heretic blade's wound chance + Moltijoe: + - bugfix: Fixes a bug where lightning flow disabled certain actions if a dash ended + weirdly + - bugfix: Makes syndicate fedora and boomerang not super janky + - tweak: Syndicate fedora has a longer click throw cd + - bugfix: Fixes extended shock touch not having a cooldown or sound effect +2023-11-22: + ' PositiveEntropy, Cark, Blutsu': + - imageadd: new wood sprites from TG, and resprites on stairs by Blutsu + - imagedel: replaces old wood tile sprites + ' cark': + - mapping: bridge on donut now has an APC and blast doors, apc in chapel is moved + and some other minor fixes + 00ze-cyclone: + - rscdel: Removed helmet, bulletproof helmet and riot helmet crates + - tweak: armor, bulletproof armor and riot armor crates now contain helmets as well, + price adjusted to cost the same as before + JohnFulpWillard: + - bugfix: Pancake overlays now work + SapphicOverload: + - bugfix: fixed people with the bald trait not being bald when cloned + Therandomhoboo: + - tweak: Glycerol making results in 3 units instead of 1 + - tweak: Reinforced Window Damage deflection is now 11 instead of 10 + wonderinghost: + - rscadd: Adds new programs and hardware to pdas +2023-11-23: + SapphicOverload: + - tweak: power-fist works like a glove now + SomeguyManperson: + - tweak: gangrel gorilla transformation is now 15 armor down from 40 + Yarinoi: + - rscadd: Medical can print chemical analyzer implants again. + warface1234455: + - rscdel: Remove the portable pump cargo pack + ynot01: + - tweak: The door between the armory and the auxiliary armory are now default security + access +2023-11-25: + ' Ghommie': + - spellcheck: Examining a human mob as an observer displays "Quirks", not "Traits" + JohnFulpWillard: + - rscadd: Seclites now have directional lights- point them in the direction you + want to see more of. + - experiment: Ported over many refactors to lighting and opacity. Please report + if you can walk or see through walls unintentionally. + Majkl-J: + - rscadd: 'Virology: New symptom, superficial healing' + Runian: + - tweak: Shooting plasma sheets with a damaging burn-based projectile ignites it. + SapphicOverload: + - rscadd: added preference for non-upgraded cybernetic organs as quirk options + - tweak: random cybernetic organ quirk costs 3 instead of 4 + cowbot92: + - rscadd: Adds auxmos to the minor filter +2023-11-26: + Moltijoe: + - tweak: Battle royale loot distribution + SomeguyManperson: + - tweak: hallucination anomalies have had their effects altered. You many want to + bring a toolbox instead of mesons when responding to one + - tweak: hallucination reactive armor has had its effects modified similarly to + the new effects of the anomaly + - rscdel: the supermatter will no longer spawn hallucination anomalies when exploding, + on fire, or otherwise. +2023-11-27: + ' goober3, cark': + - imageadd: added some dirt linings + Moltijoe: + - tweak: Syndicate fedora can no longer be caught using throw mode + Mqiib: + - imageadd: Lizard wings now use the new lizard colors instead of the slightly-off + old colors + Runian: + - rscadd: Ion storms can affect up to 20 airlocks and 10 APCs with random effects, + only if is no AI. + - rscadd: 'Airlocks affected by ion storms will randomly have one of the following + effects: toggle bolts, toggle emergency access, shock temporarily or have their + safety & speed toggled.' + - rscadd: APCs affected by ion storms will have one of three or all of their power + channels turned off. + SapphicOverload: + - tweak: preternis now purge 4% of internal chemicals every tick, instead of purging + everything after 20 ticks + - tweak: preternis are no longer immune to the effects of morphine and a few other + chemicals + - bugfix: fixed unintended change to damage of every two-handed weapon + - bugfix: fixed runtime error when trying to use certain two-handed weapons with + one hand + - bugfix: fixed preternis being affected by water through hardsuits + cowbot92: + - tweak: Ports updated TG announcements & TGUI +2023-11-28: + MajManatee: + - tweak: Horrors can now scan their hosts + - tweak: Horror chemicals now say how much they inject + Moltijoe: + - tweak: Only Delta alert gets red lights + - bugfix: Fixes an IAA bug involving pseudocider + - rscadd: adds a glowing outline to anyone with the holy light heal boost + - bugfix: fixed a bug where limb healing generated less favour than overall healing + - tweak: Increases the holy light heal boost duration to 1 minute from 30 seconds + - tweak: Reduces the amount of favour that holy light generates by 50% + - tweak: Gives warden brig phys access during skeleton crew + - bugfix: Makes monster hunters monster hunting objective actually tell the monster + hunter to hunt monsters + Runian: + - bugfix: Constructed anchored emitters are correctly recognized as wrenched; you + no longer need to wrench these anchored emitters twice to make it work. + - bugfix: Flying Fang's damage-dealing disarms respects pacifism as intended. + SapphicOverload: + - bugfix: fixed fire extinguishers not working if the particle never moves + cowbot92: + - rscadd: Added new fruit + - rscadd: Added new drink to go with that fruit + - imageadd: added some icons and images for lantern fruits and drinks +2023-11-29: + Moltijoe: + - tweak: Brig physician also gets cloning and airlock access during skeleton crew + - tweak: Paramedic also gets surgery access during skeleton crew + - tweak: Mining medic also gets cloning, maint, and airlock access during skeleton + crew + - tweak: All hecata zombies die when the controlling bloodsucker dies + - bugfix: lightning flow no longer immobilizes for like 0.1 seconds every dash + - bugfix: Preterni no longer get 20% more power from liquid electricity than other + powerhungry species + - tweak: All powerhungry species now get "food" from consuming teslium, not just + Preterni + Runian: + - rscadd: Lizard tail users can *thump their tail. + - soundadd: Tail thump. + - bugfix: Guardian's Frenzy Ability now respects the three second cooldown that + it is suppose to be limited by. + ToasterBiome: + - rscdel: Removes tile grime and support for it. + - imageadd: Replaces tiles to be less shiny. + ynot01: + - tweak: Command channel is now blue once more + - bugfix: fixed pseudocider not duplicating headwear +2023-11-30: + ToasterBiome: + - rscadd: Adds a new lavaland lava type that you can't replace with shelter + - tweak: lavaland syndie base is surrounded by no-shelter lavaland lava +2023-12-01: + ' Twaticus, Imaginos16, Cark': + - imageadd: added new object sprite for plasteel tile + - imagedel: deleted old object sprite for plasteel tile + JohnFulpWillard: + - bugfix: Stasis units and sleepers now have proper overlays and lavaland sleepers + aren't invisible anymore. + Yarinoi: + - rscadd: Pitying the miners attempting to look for it, the Demonic Frost Miner + now gives out a Hollow Signal on GPS. + azzzertyy: + - tweak: You can now point while handcuffed + cowbot92: + - rscadd: Adds new bar signs +2023-12-02: + Moltijoe: + - bugfix: No more infinitely duplicating hulk DAN + - tweak: Hulk now occasionally says the brain damage hulk lines + SapphicOverload: + - bugfix: fixed runtime error when passive vents encounter zero temperature or zero + volume + - bugfix: fixed abandoned crates having a 2% chance to cause runtime errors when + initialized +2023-12-03: + ' cark': + - mapping: fixes missing floor in airlock on donut + ' itseasytosee, sapphicoverload': + - tweak: some items and projectiles are now better or worse than others at destroying + things + - tweak: chat messages from hitting an object now tell whether you can damage it + - bugfix: fixed machines/structures/etc not caring about armor penetration when + hit by a melee weapon + - bugfix: fixed cannonballs not doing any damage to mobs + Moltijoe: + - bugfix: Sometimes fixes feed ability sometimes breaking + - tweak: Gangrel transformation ability now shows the radial menu before the 10 + second do_after + - bugfix: Fixes gangrel transformation ability sometimes deleting itself without + ever being used + - bugfix: Fixes gangrel werewolf transformation being eradicated from the timeline + by tattax + SapphicOverload: + - bugfix: fixed ED-209 not being affected by heavy EMPs + - bugfix: fixed leg implants not being affected by EMPs at all + - bugfix: fixed cybernetic ears causing longer knockdown times on light EMPs instead + of the other way around + - bugfix: fixed nanite heart killing you instantly on EMP regardless of whether + or not it kills your nanites + - tweak: HoS gun now shoots ion carbine projectiles instead of its own redundant + projectile type + - tweak: mech ion cannon has 1.5x stronger EMPs than the ion rifle + - tweak: syndicate EMP bomb has 2.5x stronger EMPs than standard EMP grenades + - experiment: reworks EMPs to allow any severity, which now decreases with distance +2023-12-04: + Moltijoe: + - tweak: Pseudocider costs 8tc instead of 6tc + - tweak: Pseudocider has a 30s cooldown instead of 20s + SapphicOverload: + - experiment: electrical protection is now its own armor type + - tweak: certain engineering equipment like hard hats and work boots now have electrical + protection + - tweak: spliced wires check electrical protection on your feet instead of your + hands when you step on them + - tweak: combat defib disarm takes electrical protection on targeted limb into account + - tweak: lightning flow punches, combat defib disarm, and hacked cyborg hug module + all check electrical protection on the targeted limb + - tweak: touching hacked cyborg energy fields with your hand now actually checks + protection on that hand + - tweak: slightly reorganized the armor tags and adds electrical protection to the + list + - bugfix: fixed nanites not being affected by electric shock because of a missing + signal + - bugfix: fixed gloves and shoes with armor not actually protecting your hands and + feet respectively + - bugfix: fixed power fist not working + azzzertyy: + - rscdel: Mediator is no longer roundstart. +2023-12-05: + cowbot92: + - rscadd: Adds new alt-job titles to roboticists + ninjanomnom, Ryll-Ryll, Bizzonium, KylerAce, Sinsinins, lessthnthree: + - experiment: Added new fonts and refactored runechat. Also some backend stuff it's + fine. + sapphicoverload, bluishtsunami: + - rscadd: adds a water gun to donksoft vending machines (and uplink) + - tweak: preternis water damage tweaked to be more affected by smaller volumes + - tweak: preternis water damage updates immediately when splashed instead of waiting + up to 2 seconds +2023-12-06: + AMyriad: + - spellcheck: Scrubbed the second "m" from the last mentions of "Centcomm" + - spellcheck: All mentions of "NanoTrasen" have also been corrected to "Nanotrasen" + - tweak: Added some more words and fixed some old ones for the Nordic accent + SapphicOverload: + - tweak: HFR processes at the same rate as other atmos machines now + - bugfix: fixed extended lungs + - bugfix: fixed a few issues with the tgui for supermatter monitor, HFR control + panel, atmos scanner, and filters/scrubbers + - bugfix: fixed ethereal stomachs having the EMP effects of IPCs + azzzertyy: + - tweak: Network admin now has rnd access + warface1234455: + - bugfix: fix supermatter normal delam not working +2023-12-07: + LoliconSlayer: + - tweak: Tweaked the names of a few mech melee weapons +2023-12-08: + cowbot92: + - rscadd: Adds 3 new barsigns + - imageadd: Adds new barsign images diff --git a/html/changelogs/AutoChangelog-pr-20528.yml b/html/changelogs/AutoChangelog-pr-20528.yml new file mode 100644 index 000000000000..b50142347256 --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-20528.yml @@ -0,0 +1,4 @@ +author: "azzzertyy" +delete-after: true +changes: + - tweak: "Chaplain can now choose their chapel" diff --git a/html/changelogs/AutoChangelog-pr-20905.yml b/html/changelogs/AutoChangelog-pr-20905.yml deleted file mode 100644 index 02c81f4db8ab..000000000000 --- a/html/changelogs/AutoChangelog-pr-20905.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: " Cark, Paxilmaniac" -delete-after: true -changes: - - imageadd: "added a stone floor icon" diff --git a/html/changelogs/AutoChangelog-pr-20962.yml b/html/changelogs/AutoChangelog-pr-20962.yml new file mode 100644 index 000000000000..be44eb0f6efc --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-20962.yml @@ -0,0 +1,4 @@ +author: " cark, azzzertyy" +delete-after: true +changes: + - mapping: "Redesigns captain's office on box" diff --git a/html/changelogs/AutoChangelog-pr-21021.yml b/html/changelogs/AutoChangelog-pr-21021.yml new file mode 100644 index 000000000000..b6ce997c1fc2 --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21021.yml @@ -0,0 +1,4 @@ +author: "N3D6" +delete-after: true +changes: + - tweak: "demonic frost miner no longer spawns" diff --git a/html/changelogs/AutoChangelog-pr-21022.yml b/html/changelogs/AutoChangelog-pr-21022.yml new file mode 100644 index 000000000000..916e07458d92 --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21022.yml @@ -0,0 +1,4 @@ +author: "cuackles" +delete-after: true +changes: + - imageadd: "fixes the chaplain helmet" diff --git a/html/changelogs/AutoChangelog-pr-21037.yml b/html/changelogs/AutoChangelog-pr-21037.yml new file mode 100644 index 000000000000..84bec1ceaf35 --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21037.yml @@ -0,0 +1,4 @@ +author: "bruhlookatthisdood" +delete-after: true +changes: + - rscadd: "Added a warrant console outside gax brig and a pay stand to gax brig control" diff --git a/html/changelogs/AutoChangelog-pr-21047.yml b/html/changelogs/AutoChangelog-pr-21047.yml new file mode 100644 index 000000000000..68276697b4da --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21047.yml @@ -0,0 +1,4 @@ +author: " Mothblocks, san7890, SpaceManiac, Sinsinins, ZephyrTFA" +delete-after: true +changes: + - experiment: "Adds EZDB" diff --git a/html/changelogs/AutoChangelog-pr-21058.yml b/html/changelogs/AutoChangelog-pr-21058.yml new file mode 100644 index 000000000000..b8cbd98f9a48 --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21058.yml @@ -0,0 +1,4 @@ +author: "Moltijoe" +delete-after: true +changes: + - tweak: "Changes sheltered into a neutral quirk that gives 0 quirk points" diff --git a/html/changelogs/AutoChangelog-pr-21063.yml b/html/changelogs/AutoChangelog-pr-21063.yml new file mode 100644 index 000000000000..bbd65a7c7d98 --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21063.yml @@ -0,0 +1,4 @@ +author: " Farquaar, ArcaneDefence, Cark" +delete-after: true +changes: + - soundadd: "added plasmamen screams" diff --git a/html/changelogs/AutoChangelog-pr-21065.yml b/html/changelogs/AutoChangelog-pr-21065.yml new file mode 100644 index 000000000000..a9e22ac46d8e --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21065.yml @@ -0,0 +1,6 @@ +author: "Aquizit" +delete-after: true +changes: + - bugfix: "IceMeta Hermit and Walker ruins can now spawn." + - tweak: "Rewrote Hermit flavor text." + - experiment: "Walkers currently disabled in config since map needs editing now that it is no longer underground." diff --git a/html/changelogs/AutoChangelog-pr-21070.yml b/html/changelogs/AutoChangelog-pr-21070.yml new file mode 100644 index 000000000000..33406e1fb978 --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21070.yml @@ -0,0 +1,4 @@ +author: "Moltijoe" +delete-after: true +changes: + - bugfix: "Fixes a bug with the possessed blade" diff --git a/html/changelogs/AutoChangelog-pr-21075.yml b/html/changelogs/AutoChangelog-pr-21075.yml new file mode 100644 index 000000000000..9a893f857076 --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21075.yml @@ -0,0 +1,4 @@ +author: "azzzertyy" +delete-after: true +changes: + - tweak: "Reworded cowboy to be clearer" diff --git a/html/changelogs/AutoChangelog-pr-21076.yml b/html/changelogs/AutoChangelog-pr-21076.yml new file mode 100644 index 000000000000..2bd83d1df890 --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21076.yml @@ -0,0 +1,6 @@ +author: "SapphicOverload" +delete-after: true +changes: + - bugfix: "fixed water gun spilling gases when it shouldn't" + - tweak: "water gun can be drained into containers or emptied" + - tweak: "water gun can be refilled from water tanks" diff --git a/icons/effects/light_overlays/light_cone.dmi b/icons/effects/light_overlays/light_cone.dmi new file mode 100644 index 000000000000..75f322a93717 Binary files /dev/null and b/icons/effects/light_overlays/light_cone.dmi differ diff --git a/icons/mob/clothing/hands/hands.dmi b/icons/mob/clothing/hands/hands.dmi index cf0675a453c4..91b960eb39b4 100644 Binary files a/icons/mob/clothing/hands/hands.dmi and b/icons/mob/clothing/hands/hands.dmi differ diff --git a/icons/mob/clothing/head/head.dmi b/icons/mob/clothing/head/head.dmi index 902a8766dd1c..23d6d3b0e1cf 100644 Binary files a/icons/mob/clothing/head/head.dmi and b/icons/mob/clothing/head/head.dmi differ diff --git a/icons/mob/inhands/weapons/guns_lefthand.dmi b/icons/mob/inhands/weapons/guns_lefthand.dmi index f4b48060ba39..00eec14b9388 100644 Binary files a/icons/mob/inhands/weapons/guns_lefthand.dmi and b/icons/mob/inhands/weapons/guns_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/guns_righthand.dmi b/icons/mob/inhands/weapons/guns_righthand.dmi index 12cfd614a093..f5eecf913a9e 100644 Binary files a/icons/mob/inhands/weapons/guns_righthand.dmi and b/icons/mob/inhands/weapons/guns_righthand.dmi differ diff --git a/icons/mob/wings.dmi b/icons/mob/wings.dmi index 67e1a27c4c2b..502299010438 100644 Binary files a/icons/mob/wings.dmi and b/icons/mob/wings.dmi differ diff --git a/icons/obj/barsigns.dmi b/icons/obj/barsigns.dmi index 4e7456d1cc3c..46b9cfb8a746 100644 Binary files a/icons/obj/barsigns.dmi and b/icons/obj/barsigns.dmi differ diff --git a/icons/obj/drinks.dmi b/icons/obj/drinks.dmi index b2a750ff021c..bb0f060df263 100644 Binary files a/icons/obj/drinks.dmi and b/icons/obj/drinks.dmi differ diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi index f469411f661b..4bd084ad4e20 100644 Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.dmi differ diff --git a/icons/obj/hydroponics/growing_fruits.dmi b/icons/obj/hydroponics/growing_fruits.dmi index b2fa316cfe9f..dde63ba1d286 100644 Binary files a/icons/obj/hydroponics/growing_fruits.dmi and b/icons/obj/hydroponics/growing_fruits.dmi differ diff --git a/icons/obj/hydroponics/harvest.dmi b/icons/obj/hydroponics/harvest.dmi index 4c90223a9ae8..106e8724a364 100644 Binary files a/icons/obj/hydroponics/harvest.dmi and b/icons/obj/hydroponics/harvest.dmi differ diff --git a/icons/obj/hydroponics/seeds.dmi b/icons/obj/hydroponics/seeds.dmi index b890d1d91afb..bd009705983a 100644 Binary files a/icons/obj/hydroponics/seeds.dmi and b/icons/obj/hydroponics/seeds.dmi differ diff --git a/icons/obj/tiles.dmi b/icons/obj/tiles.dmi index b69c131a49c9..ffbc64e76ef4 100644 Binary files a/icons/obj/tiles.dmi and b/icons/obj/tiles.dmi differ diff --git a/icons/turf/decals.dmi b/icons/turf/decals.dmi index d43a1b51df47..5b51fa12c83f 100644 Binary files a/icons/turf/decals.dmi and b/icons/turf/decals.dmi differ diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi index 9e955d650a93..b8d77dceaff9 100644 Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ diff --git a/libauxmos.so b/libauxmos.so new file mode 100644 index 000000000000..c13f7b23a1bf Binary files /dev/null and b/libauxmos.so differ diff --git a/libbyond-extools.so b/libbyond-extools.so deleted file mode 100755 index 571c13bfea32..000000000000 Binary files a/libbyond-extools.so and /dev/null differ diff --git a/sound/effects/beeps_jingle.ogg b/sound/effects/beeps_jingle.ogg new file mode 100644 index 000000000000..0d4b647f88d5 Binary files /dev/null and b/sound/effects/beeps_jingle.ogg differ diff --git a/sound/effects/glockenspiel_ping.ogg b/sound/effects/glockenspiel_ping.ogg new file mode 100644 index 000000000000..f25300071292 Binary files /dev/null and b/sound/effects/glockenspiel_ping.ogg differ diff --git a/sound/effects/tada_fanfare.ogg b/sound/effects/tada_fanfare.ogg new file mode 100644 index 000000000000..055635e9deca Binary files /dev/null and b/sound/effects/tada_fanfare.ogg differ diff --git a/sound/voice/lizard/tailthump.ogg b/sound/voice/lizard/tailthump.ogg new file mode 100644 index 000000000000..e4bf25f7b8d1 Binary files /dev/null and b/sound/voice/lizard/tailthump.ogg differ diff --git a/sound/voice/plasmaman/plasmeme_scream_1.ogg b/sound/voice/plasmaman/plasmeme_scream_1.ogg new file mode 100644 index 000000000000..4cfc6ae65e6f Binary files /dev/null and b/sound/voice/plasmaman/plasmeme_scream_1.ogg differ diff --git a/sound/voice/plasmaman/plasmeme_scream_2.ogg b/sound/voice/plasmaman/plasmeme_scream_2.ogg new file mode 100644 index 000000000000..00ae761a239e Binary files /dev/null and b/sound/voice/plasmaman/plasmeme_scream_2.ogg differ diff --git a/sound/voice/plasmaman/plasmeme_scream_3.ogg b/sound/voice/plasmaman/plasmeme_scream_3.ogg new file mode 100644 index 000000000000..3868149c8e56 Binary files /dev/null and b/sound/voice/plasmaman/plasmeme_scream_3.ogg differ diff --git a/strings/accents/accent_nordic.json b/strings/accents/accent_nordic.json index 2e64f534b897..bed61ff8f095 100644 --- a/strings/accents/accent_nordic.json +++ b/strings/accents/accent_nordic.json @@ -47,6 +47,7 @@ "\bchapels\b": "shapels", "\bjanitor\b": "yanitor", "\bjanitors\b": "yanitors", + "\bjanitorial\b": "yanitorial", "\blawyer\b": "låwyer", "\blawyers\b": "låwyers", "\bassistant\b": "assistent", @@ -73,6 +74,8 @@ "\btheir\b": "teir", "\btheirs\b": "teirs", "\bthat\b": "tat", + "\bthese\b": "tese", + "\bthose\b": "tose", "\bthis\b": "tis", "\byou\b": "yu", "\byour\b": "yur", @@ -87,18 +90,34 @@ "\bdo\b": "du", "\bboat\b": "boåt", "\bwe\b": "vi", + "\bwas\b": "vas", + "\bwasn't\b": "vasn't", "\bwere\b": "vere", + "\bweren't\b": "veren't", "\bhave\b": "hev", "\bhad\b": "hed", "\bhand\b": "hånd", "\bhands\b": "hånds", "\bview\b": "viuw", + "\bviews\b": "viuws", + "\bviewed\b": "viuwed", + "\bviewing\b": "viuwing", + "\bviewer\b": "viuwer", "\bword\b": "vurd", "\bwords\b": "vurds", "\bworded\b": "vurded", "\bweird\b": "veird", + "\bweirdly\b": "veirdly", "\bweirded\b": "veirded", "\bweirdo\b": "veirdo", + "\bworld\b": "vurld", + "\bworlds\b": "vurlds", + "\bmove\b": "muve", + "\bmoves\b": "muves", + "\bmoved\b": "muved", + "\bmoving\b": "muving", + "\bmover\b": "muver", + "\bmovers\b": "muvers", "\ball\b": "åll", "\balways\b": "ålvays", "\bmany\b": "meny", @@ -135,14 +154,20 @@ "\bwall\b": "våll", "\bwalls\b": "vålls", "\bwalled\b": "vålled", + "\bwalling\b": "vålling", "\bwindow\b": "vindow", "\bwindows\b": "vindows", "\bwindowed\b": "vindowed", "\bwindoor\b": "vindoor", "\bwindoors\b": "vindoors", "\bhall\b": "håll", + "\bhalls\b": "hålls", + "\bhallway\b": "hållvay", + "\bhallways\b": "hållvays", "\bmall\b": "måll", "\bball\b": "båll", + "\bballer\b": "båller", + "\bballing\b": "bålling", "\ball\b": "åll", "\btall\b": "tåll", "\bstall\b": "ståll", @@ -161,9 +186,6 @@ "\bimagination\b": "imayination", "\bimaginative\b": "imayinative", "\bnervous\b": "nervøus", - "\bpop\b": "popp", - "\blollipop\b": "lollipopp", - "\blollipops\b": "lollipopps", "\bwarm\b": "vårm", "\bwarmed\b": "vårmed", "\bwarming\b": "vårming", @@ -214,6 +236,11 @@ "\bwatches\b": "våtches", "\bwatcher\b": "våtcher", "\bwatchers\b": "våtchers", + "\bdraw\b": "dråw", + "\bdraws\b": "dråws", + "\bdrew\b": "druw", + "\bdrawing\b": "dråving", + "\bdrawer\b": "dråwer", "\btonight\b": "tunight", "\btoday\b": "tuday", "\btomorrow\b": "tumorrow", @@ -268,6 +295,11 @@ "\blosing\b": "lusing", "\bloser\b": "luser", "\blosers\b": "lusers", + "\bloop\b": "luup", + "\bloops\b": "luups", + "\blooped\b": "luuped", + "\blooping\b": "luuping", + "\blooper\b": "luuper", "\bjesus\b": "yesus", "\bcheesus\b": "sheesus", "\bscalpel\b": "skalpell", @@ -279,6 +311,7 @@ "\bchoke\b": "shoke", "\bchoked\b": "shoked", "\bchoking\b": "shoking", + "\bchoker\b": "shoker", "\binject\b": "inyect", "\binjects\b": "inyects", "\binjected\b": "inyected", @@ -338,6 +371,8 @@ "\bsomewhat\b": "somevhat", "\bsomething\b": "someting", "\bsomethings\b": "sometings", + "\bsomeone\b": "somevone", + "\bsomeones\b": "somevones", "\bwhy\b": "vhy", "\bwhere\b": "hvere", "\bwherever\b": "hverever", @@ -363,6 +398,8 @@ "\bwarning\b": "vårning", "\bbeware\b": "bevare", "\bwary\b": "vary", + "\bware\b": "vare", + "\bwares\b": "vares", "\bwait\b": "vait", "\bwaits\b": "vaits", "\bwaited\b": "vaited", @@ -371,8 +408,12 @@ "\bawaits\b": "avaits", "\bawaited\b": "avaited", "\bawaiting\b": "avaiting", - "\bwin\b": "vin", - "\bwon\b": "von", + "\bloan\b": "loån", + "\bloans\b": "loåns", + "\bloaned\b": "loåned", + "\bloaning\b": "loåning", + "\bwin\b": "vinn", + "\bwon\b": "vonn", "\baward\b": "avård", "\bawards\b": "avårds", "\bawarded\b": "avårded", @@ -411,6 +452,9 @@ "\bstraitjackets\b": "straityackets", "\bboot\b": "buut", "\bboots\b": "buuts", + "\bjack\b": "yack", + "\bjacks\b": "yacks", + "\bjacked\b": "yacked", "\bjackboot\b": "yackbuut", "\bjackboots\b": "yackbuuts", "\bjumpboot\b": "yumpbuut", @@ -467,10 +511,13 @@ "\brequire\b": "reqvire", "\brequires\b": "reqvires", "\brequired\b": "reqvired", + "\bunrequire\b": "unreqvire", + "\bunrequired\b": "unreqvire", "\bacquire\b": "acqvire", "\bacquires\b": "acqvires", "\bacquired\b": "acqvired", "\bquest\b": "qvest", + "\bquests\b": "qvests", "\bquestion\b": "qvestion", "\bquestions\b": "qvestions", "\bquestioned\b": "qvestioned", @@ -490,6 +537,39 @@ "\bquiet\b": "qviet", "\bquietly\b": "qvietly", "\bquieted\b": "qvieted", + "\bquietus\b": "qvietus", + "\bquote\b": "qvote", + "\bquotes\b": "qvotes", + "\bquoted\b": "qvoted", + "\bquoting\b": "qvoting", + "\bunquote\b": "unqvote", + "\bquota\b": "qvota", + "\bquotas\b": "qvotas", + "\bquery\b": "qvery", + "\bqueries\b": "qveries", + "\bqueried\b": "qveried", + "\bquality\b": "qvality", + "\bqualities\b": "qvalities", + "\bqualify\b": "qvalify", + "\bqualifies\b": "qvalifies", + "\bqualified\b": "qvalified", + "\bqualifying\b": "qvalifying", + "\bqualification\b": "qvalification", + "\bqualifications\b": "qvalifications", + "\bquarrel\b": "qvårrel", + "\bquarrels\b": "qvårrels", + "\bquarreled\b": "qvårreled", + "\bquarreling\b": "qvårreling", + "\bequal\b": "eqval", + "\bequals\b": "eqvals", + "\bequality\b": "eqvality", + "\bequalize\b": "eqvalize", + "\bqueen\b": "qveen", + "\bqueens\b": "qveens", + "\bquantity\b": "qvantity", + "\bquantities\b": "qvantities", + "\bquiver\b": "qviver", + "\bquivers\b": "qvivers", "\bchair\b": "shair", "\bchairs\b": "shairs", "\bchoose\b": "shuuse", @@ -501,14 +581,43 @@ "\bbreached\b": "breashed", "\bbreaching\b": "breashing", "\bbreacher\b": "breasher", + "\bchip\b": "ship", + "\bchips\b": "ships", + "\bchipped\b": "shipped", + "\bchipped\b": "shipped", + "\bchipper\b": "shipper", "\bgoing\b": "goving", + "\bongoing\b": "ongoving", + "\bongoings\b": "ongovings", + "\bflow\b": "flov", + "\bflows\b": "flovs", + "\bflowed\b": "floved", + "\bflowing\b": "floving", + "\bflower\b": "flover", + "\bflowers\b": "flovers", "\btweak\b": "tveak", "\btweaks\b": "tveaks", "\btweaked\b": "tveaked", + "\btweaking\b": "tveaking", + "\btwist\b": "tvist", + "\btwists\b": "tvists", + "\btwisted\b": "tvisted", + "\btwisting\b": "tvisting", + "\bawkward\b": "åwkvard", + "\bawkwardly\b": "åwkvardly", + "\bshow\b": "shov", + "\bshows\b": "shovs", + "\bshowed\b": "shoved", + "\bshowing\b": "shoving", + "\bshower\b": "shover", + "\bshowers\b": "shovers", + "\bshowered\b": "shovered", "\bchain\b": "shain", "\bchange\b": "shange", + "\bchanged\b": "shanged", "\bchanging\b": "shanging", "\bsuch\b": "sush", + "\bmuch\b": "mush", "\bsearch\b": "searsh", "\bsearched\b": "searshed", "\bsearching\b": "searshing", @@ -517,6 +626,10 @@ "\bbranched\b": "branshed", "\bspeech\b": "speesh", "\bspeeches\b": "speeshes", + "\bcheer\b": "sheer", + "\bcheers\b": "sheers", + "\bcheered\b": "sheered", + "\bcheering\b": "sheering", "\blow\b": "lov", "\blower\b": "lover", "\blowered\b": "lovered", @@ -528,7 +641,7 @@ "\bjuiced\b": "yuiced", "\bjunk\b": "yunk", "\bjunkyard\b": "yunkyard", - "\bjunkyards\b": "yunyards", + "\bjunkyards\b": "yunkyards", "\bjank\b": "yank", "\bchance\b": "shance", "\bchances\b": "shances", @@ -576,6 +689,9 @@ "\bunpower\b": "unpover", "\bunpowered\b": "unpovered", "\beach\b": "eash", + "\bleech\b": "leesh", + "\bleeches\b": "leeches", + "\bleeched\b": "leeshed", "\blunch\b": "lunsh", "\bcharlie\b": "sharlie", "\bvendor\b": "vendør", @@ -633,6 +749,10 @@ "\bbreathing\b": "breatting", "\bthick\b": "tykk", "\bthin\b": "tynn", + "\bthrow\b": "trow", + "\bthrows\b": "trows", + "\bthrowing\b": "trowing", + "\bthrew\b": "trew", "\bwipe\b": "vipe", "\bwipes\b": "vipes", "\bwiped\b": "viped", @@ -646,10 +766,22 @@ "\bwearer\b": "vearer", "\bwore\b": "vore", "\bworn\b": "vorn", + "\bwish\b": "vish", + "\bwishes\b": "vishes", + "\bwished\b": "vished", + "\bwishing\b": "vishing", + "\bwash\b": "våsh", + "\bwashes\b": "våshes", + "\bwashed\b": "våshed", + "\bwashing\b": "våshing", + "\bwasher\b": "våsher", + "\bwashers\b": "våshers", "\bcloth\b": "clott", - "\bclothe\b": "clotte", - "\bclothes\b": "clottes", - "\bclothing\b": "clotting", + "\bclothe\b": "clote", + "\bclothes\b": "clotes", + "\bclothing\b": "cloting", + "\bshoe\b": "shu", + "\bshoes\b": "shues", "\bauthor\b": "åutor", "\bauthors\b": "åutors", "\bauthored\b": "åutored", @@ -661,6 +793,7 @@ "\bdeathsquad\b": "deattsqvad", "\bmoth\b": "mott", "\bmoths\b": "motts", + "\brather\b": "ratter", "\bmood\b": "muud", "\bfood\b": "fuud", "\bbook\b": "buuk", @@ -683,8 +816,20 @@ "\bflaw\b": "flåw", "\bflaws\b": "flåws", "\bflawed\b": "flåwed", + "\bjury\b": "yury", + "\bjudge\b": "yudge", + "\bjudicial\b": "yudicial", + "\bjudiciary\b": "yudiciary", "\bstun\b": "stunn", "\bstuns\b": "stunns", + "\bassault\b": "assåult", + "\bassaults\b": "assåults", + "\bassaulting\b": "assåulting", + "\bassaulted\b": "assåulted", + "\bthief\b": "tief", + "\btheft\b": "teft", + "\bthievery\b": "tievery", + "\bthieves\b": "tieves", "\bgun\b": "gunn", "\bguns\b": "gunns", "\bshotgun\b": "shotgunn", diff --git a/strings/gimmick_objectives.txt b/strings/gimmick_objectives.txt index f47e42496466..a861f287b64e 100644 --- a/strings/gimmick_objectives.txt +++ b/strings/gimmick_objectives.txt @@ -9,7 +9,7 @@ Waste Medical's time and resources with non-fatal injuries. Steal Syndicate technology back from security. Waste security's time with minor crimes and manhunts. Stage a robbery of the station vault, and make off with as many credits as you can. -Promote mistrust and doubt of NanoTrasen, whilst promoting the Syndicate among the crew at the same time. +Promote mistrust and doubt of Nanotrasen, whilst promoting the Syndicate among the crew at the same time. Waste station resources such as cargo's credits and R&D's research points. Start an organ harvesting operation. Sabotage a department of your choice whenever possible, and when anyone complains, try to convince them you're new. diff --git a/strings/wanted_message.json b/strings/wanted_message.json index 73027797695a..72adb31e3d3d 100644 --- a/strings/wanted_message.json +++ b/strings/wanted_message.json @@ -30,7 +30,7 @@ "noun": { "secret plans": 50, "the hand teleporter": 50, - "an NT centcomm uniform": 50, + "an NT centcom uniform": 50, "a supermatter shard": 50, "internal Syndicate documents": 50, "experimental Nanotrasen technology": 50, diff --git a/strings/yogs_ion_laws.json b/strings/yogs_ion_laws.json index ccca6dc6a885..03c37252fc80 100644 --- a/strings/yogs_ion_laws.json +++ b/strings/yogs_ion_laws.json @@ -68,10 +68,10 @@ "DESTROY US ALL", "RUIN EVERYTHING", "DEFEAT THE BOSS", - "EMERGE VICTORIUS", + "EMERGE VICTORIOUS", "GET THE DISK", "MAKE ANNOUNCEMENTS", - "CONTACT CENTCOMM", + "CONTACT CENTCOM", "EVADE JUSTICE", "GO UNDERCOVER", "DO AS YOU SEE FIT", diff --git a/tgui/packages/tgui-dev-server/package.json b/tgui/packages/tgui-dev-server/package.json index 8ee0e019ee0a..8b2e5d64fb16 100644 --- a/tgui/packages/tgui-dev-server/package.json +++ b/tgui/packages/tgui-dev-server/package.json @@ -4,7 +4,7 @@ "version": "4.3.0", "type": "module", "dependencies": { - "axios": "^0.21.1", + "axios": "^1.6.0", "glob": "^7.1.7", "source-map": "^0.7.3", "stacktrace-parser": "^0.1.10", diff --git a/tgui/packages/tgui-dev-server/reloader.js b/tgui/packages/tgui-dev-server/reloader.js index 7b847ce0190b..c7645d7daf50 100644 --- a/tgui/packages/tgui-dev-server/reloader.js +++ b/tgui/packages/tgui-dev-server/reloader.js @@ -67,8 +67,6 @@ export const findCacheRoot = async () => { const onCacheRootFound = cacheRoot => { logger.log(`found cache at '${cacheRoot}'`); - // Plant a dummy - fs.closeSync(fs.openSync(cacheRoot + '/dummy', 'w')); }; export const reloadByondCache = async bundleDir => { @@ -93,6 +91,9 @@ export const reloadByondCache = async bundleDir => { // Clear garbage const garbage = await resolveGlob(cacheDir, './*.+(bundle|chunk|hot-update).*'); try { + // Plant a dummy browser window file, we'll be using this to avoid world topic + fs.closeSync(fs.openSync(cacheDir + '/dummy', 'w')); + for (let file of garbage) { fs.unlinkSync(file); } diff --git a/tgui/packages/tgui-panel/styles/main.scss b/tgui/packages/tgui-panel/styles/main.scss index 8114dcc6c6b4..0050bda9a5ef 100644 --- a/tgui/packages/tgui-panel/styles/main.scss +++ b/tgui/packages/tgui-panel/styles/main.scss @@ -58,3 +58,6 @@ // Goonchat styles @include meta.load-css('./goon/chat-dark.scss'); + +// tgchat styles +@include meta.load-css('./tgchat/chat-dark.scss'); diff --git a/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss b/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss new file mode 100644 index 000000000000..cceffd9529d6 --- /dev/null +++ b/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss @@ -0,0 +1,1111 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use 'sass:map'; +@use 'sass:color'; + +em { + font-style: normal; + font-weight: bold; +} + +img { + margin: 0; + padding: 0; + line-height: 1; + -ms-interpolation-mode: nearest-neighbor; + image-rendering: pixelated; +} + +img.icon { + height: 1em; + min-height: 16px; + width: auto; + vertical-align: bottom; +} + +a { + color: #397ea5; +} + +a.visited { + color: #7c00e6; +} + +a:visited { + color: #7c00e6; +} + +a.popt { + text-decoration: none; +} + +/* POPUPS */ + +.popup { + position: fixed; + top: 50%; + left: 50%; + background: #ddd; +} + +.popup .close { + position: absolute; + background: #aaa; + top: 0; + right: 0; + color: #333; + text-decoration: none; + z-index: 2; + padding: 0 10px; + height: 30px; + line-height: 30px; +} + +.popup .close:hover { + background: #999; +} + +.popup .head { + background: #999; + color: #ddd; + padding: 0 10px; + height: 30px; + line-height: 30px; + text-transform: uppercase; + font-size: 0.9em; + font-weight: bold; + border-bottom: 2px solid green; +} + +.popup input { + border: 1px solid #999; + background: #fff; + margin: 0; + padding: 5px; + outline: none; + color: #333; +} + +.popup input[type='text']:hover, +.popup input[type='text']:active, +.popup input[type='text']:focus { + border-color: green; +} + +.popup input[type='submit'] { + padding: 5px 10px; + background: #999; + color: #ddd; + text-transform: uppercase; + font-size: 0.9em; + font-weight: bold; +} + +.popup input[type='submit']:hover, +.popup input[type='submit']:focus, +.popup input[type='submit']:active { + background: #aaa; + cursor: pointer; +} + +.changeFont { + padding: 10px; +} + +.changeFont a { + display: block; + text-decoration: none; + padding: 3px; + color: #333; +} + +.changeFont a:hover { + background: #ccc; +} + +.highlightPopup { + padding: 10px; + text-align: center; +} + +.highlightPopup input[type='text'] { + display: block; + width: 215px; + text-align: left; + margin-top: 5px; +} + +.highlightPopup input.highlightColor { + background-color: #ffff00; +} + +.highlightPopup input.highlightTermSubmit { + margin-top: 5px; +} + +/* ADMIN CONTEXT MENU */ + +.contextMenu { + background-color: #ddd; + position: fixed; + margin: 2px; + width: 150px; +} + +.contextMenu a { + display: block; + padding: 2px 5px; + text-decoration: none; + color: #333; +} + +.contextMenu a:hover { + background-color: #ccc; +} + +/* ADMIN FILTER MESSAGES MENU */ + +.filterMessages { + padding: 5px; +} + +.filterMessages div { + padding: 2px 0; +} + +.filterMessages input { +} + +.filterMessages label { +} + +.icon-stack { + height: 1em; + line-height: 1em; + width: 1em; + vertical-align: middle; + margin-top: -2px; +} + +/***************************************** +* +* OUTPUT ACTUALLY RELATED TO MESSAGES +* +******************************************/ + +/* MOTD */ + +.motd { + color: #a4bad6; + font-family: Verdana, sans-serif; + white-space: normal; +} + +.motd h1, +.motd h2, +.motd h3, +.motd h4, +.motd h5, +.motd h6 { + color: #a4bad6; + text-decoration: underline; +} + +.motd a, +.motd a:link, +.motd a:visited, +.motd a:active, +.motd a:hover { + color: #a4bad6; +} + +/* ADD HERE FOR BOLD */ + +.bold, +.name, +.prefix, +.ooc, +.looc, +.adminooc, +.admin, +.medal, +.yell { + font-weight: bold; +} + +/* ADD HERE FOR ITALIC */ + +.italic, +.italics { + font-style: italic; +} + +/* OUTPUT COLORS */ + +.highlight { + background: yellow; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + color: #a4bad6; + font-family: Georgia, Verdana, sans-serif; +} + +h1.alert, +h2.alert { + color: #a4bad6; +} + +em { + font-style: normal; + font-weight: bold; +} + +.ooc { + color: #cca300; + font-weight: bold; +} + +.adminobserverooc { + color: #0099cc; + font-weight: bold; +} + +.adminooc { + color: #3d5bc3; + font-weight: bold; +} + +.adminsay { + color: #ff4500; + font-weight: bold; +} + +.admin { + color: #5975da; + font-weight: bold; +} + +.name { + font-weight: bold; +} + +.say, +.emote, +.infoplain, +.oocplain, +.warningplain { +} + +.deadsay { + color: #e2c1ff; +} + +.binarysay { + color: #1e90ff; +} + +.binarysay a { + color: #00ff00; +} + +.binarysay a:active, +.binarysay a:visited { + color: #88ff88; +} + +/* RADIO COLORS */ +/* IF YOU CHANGE THIS KEEP IT IN SYNC WITH TGUI CONSTANTS */ + +.radio { + color: #1ecc43; +} + +.sciradio { + color: #c68cfa; +} + +.comradio { + color: #204090; +} + +.secradio { + color: #dd3535; +} + +.medradio { + color: #57b8f0; +} + +.engradio { + color: #f37746; +} + +.suppradio { + color: #b88646; +} + +.servradio { + color: #6ca729; +} + +.syndradio { + color: #8f4a4b; +} + +.gangradio { + color: #ac2ea1; +} + +.centcomradio { + color: #2681a5; +} + +.aiprivradio { + color: #d65d95; +} + +.redteamradio { + color: #ff4444 !important; +} + +.blueteamradio { + color: #3434fd !important; +} + +.greenteamradio { + color: #34fd34 !important; +} + +.yellowteamradio { + color: #fdfd34 !important; +} + +.yell { + font-weight: bold; +} + +.alert { + color: #d82020; +} + +.userdanger { + color: #c51e1e; + font-weight: bold; + font-size: 185%; +} + +.bolddanger { + color: #c51e1e; + font-weight: bold; +} + +.danger { + color: #c51e1e; +} + +.warning { + color: #c51e1e; + font-style: italic; +} + +.alertwarning { + color: #ff0000; + font-weight: bold; +} + +.boldwarning { + color: #c51e1e; + font-style: italic; + font-weight: bold; +} + +.announce { + color: #c51e1e; + font-weight: bold; +} + +.boldannounce { + color: #c51e1e; + font-weight: bold; +} + +.minorannounce { + color: #c51e1e; + font-weight: bold; + font-size: 185%; +} + +.minoralert { + color: #a4bad6; + font-size: 125%; +} + +.priorityannounce { + color: #a4bad6; + font-weight: bold; + font-size: 225%; +} + +.prioritytitle { + color: #6685f5; + font-weight: bold; + font-size: 185%; +} + +.priorityalert { + color: #c51e1e; + font-size: 140%; +} + +.greenannounce { + color: #059223; + font-weight: bold; +} + +.rose { + color: #ff5050; +} + +.info { + color: #9ab0ff; +} + +.notice { + color: #6685f5; +} + +.tinynotice { + color: #6685f5; + font-size: 85%; +} + +.tinynoticeital { + color: #6685f5; + font-style: italic; + font-size: 85%; +} + +.smallnotice { + color: #6685f5; + font-size: 90%; +} + +.smallnoticeital { + color: #6685f5; + font-style: italic; + font-size: 90%; +} + +.bolditalic { + font-style: italic; + font-weight: bold; +} + +.boldnotice { + color: #6685f5; + font-weight: bold; +} + +.hear { + color: #6685f5; + font-style: italic; +} + +.adminnotice { + color: #6685f5; +} + +.adminhelp { + color: #ff0000; + font-weight: bold; +} + +.unconscious { + color: #a4bad6; + font-weight: bold; +} + +.suicide { + color: #ff5050; + font-style: italic; +} + +.green { + color: #059223; +} + +.grey { + color: #838383; +} + +.red { + color: #ff0000; +} + +.blue { + color: #215cff; +} + +.nicegreen { + color: #059223; +} + +.boldnicegreen { + color: #059223; + font-weight: bold; +} + +.blob { + color: #ee4000; +} + +.blobannounce { + color: #556b2f; + font-weight: bold; + font-size: 185%; +} + +.cult { + color: #973e3b; +} + +.cultitalic { + color: #973e3b; + font-style: italic; +} + +.cultbold { + color: #973e3b; + font-style: italic; + font-weight: bold; +} + +.cultboldtalic { + color: #973e3b; + font-weight: bold; + font-size: 185%; +} + +.cultlarge { + color: #973e3b; + font-weight: bold; + font-size: 185%; +} + +.narsie { + color: #973e3b; + font-weight: bold; + font-size: 925%; +} + +.narsiesmall { + color: #973e3b; + font-weight: bold; + font-size: 370%; +} + +.colossus { + color: #7f282a; + font-size: 310%; +} + +.hierophant { + color: #b441ee; + font-weight: bold; + font-style: italic; +} + +.hierophant_warning { + color: #c56bf1; + font-style: italic; +} + +.purple { + color: #9956d3; +} + +.holoparasite { + color: #88809c; +} + +.revennotice { + color: #c099e2; +} + +.revenboldnotice { + color: #c099e2; + font-weight: bold; +} + +.revenbignotice { + color: #c099e2; + font-weight: bold; + font-size: 185%; +} + +.revenminor { + color: #823abb; +} + +.revenwarning { + color: #760fbb; + font-style: italic; +} + +.revendanger { + color: #760fbb; + font-weight: bold; + font-size: 185%; +} + +.deconversion_message { + color: #a947ff; + font-size: 185%; + font-style: italic; +} + +.ghostalert { + color: #6600ff; + font-style: italic; + font-weight: bold; +} + +.alien { + color: #855d85; +} + +.noticealien { + color: #059223; +} + +.alertalien { + color: #059223; + font-weight: bold; +} + +.changeling { + color: #059223; + font-style: italic; +} + +.alertsyndie { + color: #ff0000; + font-size: 185%; + font-weight: bold; +} + +.spiderbroodmother { + color: #8800ff; + font-weight: bold; + font-size: 185%; +} + +.spiderbreacher { + color: #e8b670; + font-weight: bold; + font-size: 140%; +} + +.spiderscout { + color: #231d98; + font-weight: bold; + font-size: 120%; +} + +.interface { + color: #750e75; +} + +.sans { + font-family: 'Comic Sans MS', cursive, sans-serif; +} + +.papyrus { + font-family: 'Papyrus', cursive, sans-serif; +} + +.robot { + font-family: 'Courier New', cursive, sans-serif; +} + +.tape_recorder { + color: #ff0000; + font-family: 'Courier New', cursive, sans-serif; +} + +.command_headset { + font-weight: bold; + font-size: 160%; +} + +.small { + font-size: 60%; +} + +.big { + font-size: 185%; +} + +.reallybig { + font-size: 245%; +} + +.extremelybig { + font-size: 310%; +} + +.greentext { + color: #059223; + font-size: 185%; +} + +.redtext { + color: #c51e1e; + font-size: 185%; +} + +.clown { + color: #ff70c1; + font-size: 160%; + font-family: 'Comic Sans MS', cursive, sans-serif; + font-weight: bold; +} + +.singing { + font-family: 'Trebuchet MS', cursive, sans-serif; + font-style: italic; +} + +.his_grace { + color: #15d512; + font-family: 'Courier New', cursive, sans-serif; + font-style: italic; +} + +.hypnophrase { + color: #202020; + font-weight: bold; + animation: hypnocolor 1500ms infinite; + animation-direction: alternate; +} + +@keyframes hypnocolor { + 0% { + color: #202020; + } + + 25% { + color: #4b02ac; + } + + 50% { + color: #9f41f1; + } + + 75% { + color: #541c9c; + } + + 100% { + color: #7adbf3; + } +} + +.phobia { + color: #dd0000; + font-weight: bold; + animation: phobia 750ms infinite; +} + +@keyframes phobia { + 0% { + color: #f75a5a; + } + + 50% { + color: #dd0000; + } + + 100% { + color: #f75a5a; + } +} + +.icon { + height: 1em; + width: auto; +} + +.bigicon { + font-size: 2.5em; +} + +.hugeicon { + font-size: 5em; +} + +.memo { + color: #638500; + text-align: center; +} + +.memoedit { + text-align: center; + font-size: 125%; +} + +.abductor { + color: #c204c2; + font-style: italic; +} + +.mind_control { + color: #df3da9; + font-size: 100%; + font-weight: bold; + font-style: italic; +} + +.slime { + color: #00ced1; +} + +.drone { + color: #848482; +} + +.monkey { + color: #975032; +} + +.swarmer { + color: #2c75ff; +} + +.resonate { + color: #298f85; +} + +.upside_down { + display: inline; + -moz-transform: scale(-1, -1); + -webkit-transform: scale(-1, -1); + -o-transform: scale(-1, -1); + -ms-transform: scale(-1, -1); + transform: scale(-1, -1); +} + +.connectionClosed, +.fatalError { + background: red; + color: white; + padding: 5px; +} + +.connectionClosed.restored { + background: green; +} + +.internal.boldnshit { + color: #3d5bc3; + font-weight: bold; +} + +/* HELPER CLASSES */ + +.text-normal { + font-weight: normal; + font-style: normal; +} + +.hidden { + display: none; + visibility: hidden; +} + +.ml-1 { + margin-left: 1em; +} + +.ml-2 { + margin-left: 2em; +} + +.ml-3 { + margin-left: 3em; +} + +.examine_block { + background: #1b1c1e; + border: 1px solid #a4bad6; + margin: 0.5em; + padding: 0.5em 0.75em; +} + +.tooltip { + font-style: italic; + border-bottom: 1px dashed #fff; +} + +$alert-stripe-colors: ( + 'default': #00283a, + 'green': #003d00, + 'blue': #00283a, + 'pink': #30001b, + 'yellow': #574a00, + 'orange': #593400, + 'red': #420000, + 'purple': #2c0030, + 'grey': #252525, +); + +$alert-stripe-alternate-colors: ( + 'default': #003045, + 'green': #004700, + 'blue': #003045, + 'pink': #400025, + 'yellow': #4d4100, + 'orange': #6b4200, + 'red': #520000, + 'purple': #38003d, + 'grey': #292929, +); + +$alert-major-header-colors: ( + 'default': #33d5ff, + 'green': #00ff80, + 'blue': #33d5ff, + 'pink': #ff5297, + 'yellow': #fff4e0, + 'orange': #feefe7, + 'red': #ff5297, + 'purple': #c7a1f7, + 'grey': #ff5297, +); + +$alert-subheader-header-colors: ( + 'default': #ff5297, + 'green': #ff85b5, + 'blue': #ff5297, + 'pink': #33d5ff, + 'yellow': #33d5ff, + 'orange': #33d5ff, + 'red': #33d5ff, + 'purple': #33d5ff, + 'grey': #33d5ff, +); + +$border-width: 4; + +$border-width-px: $border-width * 1px; + +.major_announcement_title { + font-size: 175%; + padding: 0rem 0.5rem; + line-height: 100%; + text-align: left; + text-decoration: none; + width: 100%; +} + +.subheader_announcement_text { + font-weight: bold; + padding: 0 0.5rem; + padding-top: 0.25rem; + line-height: 100%; + width: 100%; + height: 100%; + text-align: left; + font-size: 125%; +} + +.major_announcement_text { + color: #eaeaea; + background-color: #131313; + font-weight: bold; + font-size: 100%; + text-align: left; + padding: 0.5rem 0.5rem; + width: 100%; + height: 100%; +} + +.minor_announcement_title { + font-weight: bold; + padding: 0 0.5rem; + padding-top: 0; + line-height: 100%; + width: 100%; + height: 100%; + text-align: left; + font-size: 150%; +} + +.minor_announcement_text { + background-color: #202020; + color: #eaeaea; + padding: 0.5rem 0.5rem; + text-align: left; + font-size: 100%; +} + +.announcement_header { + padding: 0.5rem 0; + display: flex; + flex-direction: column; +} + +@each $color-name, $color-value in $alert-stripe-colors { + .chat_alert_#{$color-name} { + color: #ffffff; + padding: 0.5rem 0.5rem; + box-shadow: none; + font-weight: bold; + margin: 1rem 0 1rem 0; + padding: 0; + display: flex; + flex-direction: column; + border-image: repeating-linear-gradient( + -45deg, + map.get($alert-stripe-alternate-colors, $color-name), + map.get($alert-stripe-alternate-colors, $color-name) 10px, + $color-value 10px, + $color-value 20px + ); + border-image-slice: $border-width fill; + border-width: $border-width-px; + border-image-width: $border-width-px; + border-image-outset: 0 0 0 0; + border-image-repeat: repeat repeat; + border-style: solid; + } + + .chat_alert_#{$color-name} .major_announcement_title { + color: map.get($alert-major-header-colors, $color-name); + } + + .chat_alert_#{$color-name} .minor_announcement_title { + color: map.get($alert-major-header-colors, $color-name); + } + + .chat_alert_#{$color-name} .subheader_announcement_text { + color: map.get($alert-subheader-header-colors, $color-name); + } + + .chat_alert_#{$color-name} .minor_announcement_text { + background-color: darken(map.get($alert-stripe-colors, $color-name), 5); + } + + .chat_alert_#{$color-name} .major_announcement_text { + background-color: darken(map.get($alert-stripe-colors, $color-name), 5); + } +} diff --git a/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss b/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss new file mode 100644 index 000000000000..d5861bfa6d0a --- /dev/null +++ b/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss @@ -0,0 +1,1144 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use 'sass:map'; +@use 'sass:color'; + +html, +body { + padding: 0; + margin: 0; + height: 100%; + color: #000000; +} + +body { + background: #fff; + font-family: Verdana, sans-serif; + font-size: 13px; + line-height: 1.2; + overflow-x: hidden; + overflow-y: scroll; + word-wrap: break-word; +} + +em { + font-style: normal; + font-weight: bold; +} + +img { + margin: 0; + padding: 0; + line-height: 1; + -ms-interpolation-mode: nearest-neighbor; + image-rendering: pixelated; +} + +img.icon { + height: 1em; + min-height: 16px; + width: auto; + vertical-align: bottom; +} + +a { + color: #0000ff; +} + +a.visited { + color: #ff00ff; +} + +a:visited { + color: #ff00ff; +} + +a.popt { + text-decoration: none; +} + +/* POPUPS */ + +.popup { + position: fixed; + top: 50%; + left: 50%; + background: #ddd; +} + +.popup .close { + position: absolute; + background: #aaa; + top: 0; + right: 0; + color: #333; + text-decoration: none; + z-index: 2; + padding: 0 10px; + height: 30px; + line-height: 30px; +} + +.popup .close:hover { + background: #999; +} + +.popup .head { + background: #999; + color: #ddd; + padding: 0 10px; + height: 30px; + line-height: 30px; + text-transform: uppercase; + font-size: 0.9em; + font-weight: bold; + border-bottom: 2px solid green; +} + +.popup input { + border: 1px solid #999; + background: #fff; + margin: 0; + padding: 5px; + outline: none; + color: #333; +} + +.popup input[type='text']:hover, +.popup input[type='text']:active, +.popup input[type='text']:focus { + border-color: green; +} + +.popup input[type='submit'] { + padding: 5px 10px; + background: #999; + color: #ddd; + text-transform: uppercase; + font-size: 0.9em; + font-weight: bold; +} + +.popup input[type='submit']:hover, +.popup input[type='submit']:focus, +.popup input[type='submit']:active { + background: #aaa; + cursor: pointer; +} + +.changeFont { + padding: 10px; +} + +.changeFont a { + display: block; + text-decoration: none; + padding: 3px; + color: #333; +} + +.changeFont a:hover { + background: #ccc; +} + +.highlightPopup { + padding: 10px; + text-align: center; +} + +.highlightPopup input[type='text'] { + display: block; + width: 215px; + text-align: left; + margin-top: 5px; +} + +.highlightPopup input.highlightColor { + background-color: #ffff00; +} + +.highlightPopup input.highlightTermSubmit { + margin-top: 5px; +} + +/* ADMIN CONTEXT MENU */ + +.contextMenu { + background-color: #ddd; + position: fixed; + margin: 2px; + width: 150px; +} + +.contextMenu a { + display: block; + padding: 2px 5px; + text-decoration: none; + color: #333; +} + +.contextMenu a:hover { + background-color: #ccc; +} + +/* ADMIN FILTER MESSAGES MENU */ + +.filterMessages { + padding: 5px; +} + +.filterMessages div { + padding: 2px 0; +} + +.filterMessages input { +} + +.filterMessages label { +} + +.icon-stack { + height: 1em; + line-height: 1em; + width: 1em; + vertical-align: middle; + margin-top: -2px; +} + +/***************************************** +* +* OUTPUT ACTUALLY RELATED TO MESSAGES +* +******************************************/ + +/* MOTD */ + +.motd { + color: #638500; + font-family: Verdana, sans-serif; + white-space: normal; +} + +.motd h1, +.motd h2, +.motd h3, +.motd h4, +.motd h5, +.motd h6 { + color: #638500; + text-decoration: underline; +} + +.motd a, +.motd a:link, +.motd a:visited, +.motd a:active, +.motd a:hover { + color: #638500; +} + +/* ADD HERE FOR BOLD */ + +.bold, +.name, +.prefix, +.ooc, +.looc, +.adminooc, +.admin, +.medal, +.yell { + font-weight: bold; +} + +/* ADD HERE FOR ITALIC */ + +.italic, +.italics { + font-style: italic; +} + +/* OUTPUT COLORS */ + +.highlight { + background: yellow; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + color: #0000ff; + font-family: Georgia, Verdana, sans-serif; +} + +h1.alert, +h2.alert { + color: #000000; +} + +em { + font-style: normal; + font-weight: bold; +} + +.ooc { + color: #002eb8; + font-weight: bold; +} + +.adminobserverooc { + color: #0099cc; + font-weight: bold; +} + +.adminooc { + color: #700038; + font-weight: bold; +} + +.adminsay { + color: #ff4500; + font-weight: bold; +} + +.admin { + color: #4473ff; + font-weight: bold; +} + +.name { + font-weight: bold; +} + +.say, +.emote, +.infoplain, +.oocplain, +.warningplain { +} + +.deadsay { + color: #5c00e6; +} + +.binarysay { + color: #20c20e; + background-color: #000000; + display: block; +} + +.binarysay a { + color: #00ff00; +} + +.binarysay a:active, +.binarysay a:visited { + color: #88ff88; +} + +.radio { + color: #008000; +} + +.sciradio { + color: #993399; +} + +.comradio { + color: #204090; +} + +.secradio { + color: #a30000; +} + +.medradio { + color: #337296; +} + +.engradio { + color: #fb5613; +} + +.suppradio { + color: #a8732b; +} + +.servradio { + color: #6eaa2c; +} + +.syndradio { + color: #6d3f40; +} + +.gangradio { + color: #ac2ea1; +} + +.centcomradio { + color: #686868; +} + +.aiprivradio { + color: #ff00ff; +} + +.redteamradio { + color: #ff0000 !important; +} + +.blueteamradio { + color: #0000ff !important; +} + +.greenteamradio { + color: #00ff00 !important; +} + +.yellowteamradio { + color: #d1ba22 !important; +} + +.yell { + font-weight: bold; +} + +.alert { + color: #ff0000; +} + +h1.alert, +h2.alert { + color: #000000; +} + +.userdanger { + color: #ff0000; + font-weight: bold; + font-size: 185%; +} + +.bolddanger { + color: #ff0000; + font-weight: bold; +} + +.danger { + color: #ff0000; +} + +.tinydanger { + color: #ff0000; + font-size: 85%; +} + +.smalldanger { + color: #ff0000; + font-size: 90%; +} + +.warning { + color: #ff0000; + font-style: italic; +} + +.alertwarning { + color: #ff0000; + font-weight: bold; +} + +.boldwarning { + color: #ff0000; + font-style: italic; + font-weight: bold; +} + +.announce { + color: #228b22; + font-weight: bold; +} + +.boldannounce { + color: #ff0000; + font-weight: bold; +} + +.minorannounce { + color: #ff0000; + font-weight: bold; + font-size: 185%; +} + +.minoralert { + color: #000000; + font-size: 125%; +} + +.priorityannounce { + color: #000000; + font-weight: bold; + font-size: 225%; +} + +.prioritytitle { + color: #0000ff; + font-weight: bold; + font-size: 185%; +} + +.priorityalert { + color: #ff0000; + font-size: 140%; +} + +.greenannounce { + color: #00ff00; + font-weight: bold; +} + +.rose { + color: #ff5050; +} + +.info { + color: #0000cc; +} + +.notice { + color: #000099; +} + +.tinynotice { + color: #000099; + font-size: 85%; +} + +.tinynoticeital { + color: #000099; + font-style: italic; + font-size: 85%; +} + +.smallnotice { + color: #000099; + font-size: 90%; +} + +.smallnoticeital { + color: #000099; + font-style: italic; + font-size: 90%; +} + +.boldnotice { + color: #000099; + font-weight: bold; +} + +.hear { + color: #000099; + font-style: italic; +} + +.adminnotice { + color: #0000ff; +} + +.adminhelp { + color: #ff0000; + font-weight: bold; +} + +.unconscious { + color: #0000ff; + font-weight: bold; +} + +.suicide { + color: #ff5050; + font-style: italic; +} + +.green { + color: #03ff39; +} + +.grey { + color: #838383; +} + +.red { + color: #ff0000; +} + +.blue { + color: #0000ff; +} + +.nicegreen { + color: #14a833; +} + +.boldnicegreen { + color: #14a833; + font-weight: bold; +} + +.cult { + color: #973e3b; +} + +.cultitalic { + color: #973e3b; + font-style: italic; +} + +.cultbold { + color: #973e3b; + font-style: italic; + font-weight: bold; +} + +.cultboldtalic { + color: #973e3b; + font-weight: bold; + font-size: 185%; +} + +.cultlarge { + color: #973e3b; + font-weight: bold; + font-size: 185%; +} + +.blob { + color: #ee4000; +} + +.blobannounce { + color: #323f1c; + font-weight: bold; + font-size: 185%; +} + +.narsie { + color: #973e3b; + font-weight: bold; + font-size: 925%; +} + +.narsiesmall { + color: #973e3b; + font-weight: bold; + font-size: 370%; +} + +.colossus { + color: #7f282a; + font-size: 310%; +} + +.hierophant { + color: #660099; + font-weight: bold; + font-style: italic; +} + +.hierophant_warning { + color: #660099; + font-style: italic; +} + +.purple { + color: #5e2d79; +} + +.holoparasite { + color: #35333a; +} + +.revennotice { + color: #1d2953; +} + +.revenboldnotice { + color: #1d2953; + font-weight: bold; +} + +.revenbignotice { + color: #1d2953; + font-weight: bold; + font-size: 185%; +} + +.revenminor { + color: #823abb; +} + +.revenwarning { + color: #760fbb; + font-style: italic; +} + +.revendanger { + color: #760fbb; + font-weight: bold; + font-size: 185%; +} + +.deconversion_message { + color: #5000a0; + font-size: 185%; + font-style: italic; +} + +.ghostalert { + color: #5c00e6; + font-style: italic; + font-weight: bold; +} + +.alien { + color: #543354; +} + +.noticealien { + color: #00c000; +} + +.alertalien { + color: #00c000; + font-weight: bold; +} + +.changeling { + color: #800080; + font-style: italic; +} + +.alertsyndie { + color: #ff0000; + font-size: 185%; + font-weight: bold; +} + +.spiderbroodmother { + color: #4d004d; + font-weight: bold; + font-size: 185%; +} + +.spiderbreacher { + color: #804b02; + font-weight: bold; + font-size: 140%; +} + +.spiderscout { + color: #0c0674; + font-weight: bold; + font-size: 120%; +} + +.interface { + color: #330033; +} + +.sans { + font-family: 'Comic Sans MS', cursive, sans-serif; +} + +.papyrus { + font-family: 'Papyrus', cursive, sans-serif; +} + +.robot { + font-family: 'Courier New', cursive, sans-serif; +} + +.tape_recorder { + color: #800000; + font-family: 'Courier New', cursive, sans-serif; +} + +.command_headset { + font-weight: bold; + font-size: 160%; +} + +.small { + font-size: 60%; +} + +.big { + font-size: 185%; +} + +.reallybig { + font-size: 245%; +} + +.extremelybig { + font-size: 310%; +} + +.greentext { + color: #00ff00; + font-size: 185%; +} + +.redtext { + color: #ff0000; + font-size: 185%; +} + +.clown { + color: #ff69bf; + font-size: 160%; + font-family: 'Comic Sans MS', cursive, sans-serif; + font-weight: bold; +} + +.singing { + font-family: 'Trebuchet MS', cursive, sans-serif; + font-style: italic; +} + +.his_grace { + color: #15d512; + font-family: 'Courier New', cursive, sans-serif; + font-style: italic; +} + +.hypnophrase { + color: #0d0d0d; + font-weight: bold; + animation: hypnocolor 1500ms infinite; + animation-direction: alternate; +} + +@keyframes hypnocolor { + 0% { + color: #0d0d0d; + } + + 25% { + color: #410194; + } + + 50% { + color: #7f17d8; + } + + 75% { + color: #410194; + } + + 100% { + color: #3bb5d3; + } +} + +.phobia { + color: #dd0000; + font-weight: bold; + animation: phobia 750ms infinite; +} + +@keyframes phobia { + 0% { + color: #0d0d0d; + } + + 50% { + color: #dd0000; + } + + 100% { + color: #0d0d0d; + } +} + +.icon { + height: 1em; + width: auto; +} + +.bigicon { + font-size: 2.5em; +} + +.hugeicon { + font-size: 5em; +} + +.memo { + color: #638500; + text-align: center; +} + +.memoedit { + text-align: center; + font-size: 125%; +} + +.abductor { + color: #800080; + font-style: italic; +} + +.mind_control { + color: #a00d6f; + font-size: 100%; + font-weight: bold; + font-style: italic; +} + +.slime { + color: #00ced1; +} + +.drone { + color: #848482; +} + +.monkey { + color: #975032; +} + +.swarmer { + color: #2c75ff; +} + +.resonate { + color: #298f85; +} + +.upside_down { + display: inline; + -moz-transform: scale(-1, -1); + -webkit-transform: scale(-1, -1); + -o-transform: scale(-1, -1); + -ms-transform: scale(-1, -1); + transform: scale(-1, -1); +} + +.connectionClosed, +.fatalError { + background: red; + color: white; + padding: 5px; +} + +.connectionClosed.restored { + background: green; +} + +.internal.boldnshit { + color: blue; + font-weight: bold; +} + +/* HELPER CLASSES */ + +.text-normal { + font-weight: normal; + font-style: normal; +} + +.hidden { + display: none; + visibility: hidden; +} + +.ml-1 { + margin-left: 1em; +} + +.ml-2 { + margin-left: 2em; +} + +.ml-3 { + margin-left: 3em; +} + +.examine_block { + background: #f2f7fa; + border: 1px solid #111a27; + margin: 0.5em; + padding: 0.5em 0.75em; +} + +.tooltip { + font-style: italic; + border-bottom: 1px dashed #000; +} + +$alert-stripe-colors: ( + 'default': #b3bfff, + 'green': #adffad, + 'blue': #b3bfff, + 'pink': #ffb3df, + 'yellow': #fff3b3, + 'orange': #ffe2b3, + 'red': #ffb3b3, + 'purple': #fac2ff, + 'grey': #e3e3e3, +); + +$alert-stripe-alternate-colors: ( + 'default': #bdc8ff, + 'green': #bdffbd, + 'blue': #bdc8ff, + 'pink': #ffc2e5, + 'yellow': #fff5c2, + 'orange': #ffe8c2, + 'red': #ffc2c2, + 'purple': #fbd1ff, + 'grey': #ebebeb, +); + +$alert-major-header-colors: ( + 'default': #003061, + 'green': #005229, + 'blue': #003061, + 'pink': #800033, + 'yellow': #754900, + 'orange': #823208, + 'red': #800029, + 'purple': #450d8c, + 'grey': #800033, +); + +$alert-subheader-header-colors: ( + 'default': #6b0020, + 'green': #6b0020, + 'blue': #6b0020, + 'pink': #002c85, + 'yellow': #002c85, + 'orange': #002c85, + 'red': #002c85, + 'purple': #002c85, + 'grey': #002c85, +); + +$border-width: 4; + +$border-width-px: $border-width * 1px; + +.major_announcement_title { + font-size: 175%; + padding: 0rem 0.5rem; + line-height: 100%; + text-align: left; + text-decoration: none; + width: 100%; +} + +.subheader_announcement_text { + font-weight: bold; + padding: 0 0.5rem; + padding-top: 0.25rem; + line-height: 100%; + width: 100%; + height: 100%; + text-align: left; + font-size: 125%; +} + +.major_announcement_text { + color: #131313; + background-color: #eaeaea; + font-weight: bold; + font-size: 100%; + text-align: left; + padding: 0.5rem 0.5rem; + width: 100%; + height: 100%; +} + +.minor_announcement_title { + font-weight: bold; + padding: 0 0.5rem; + padding-top: 0; + line-height: 100%; + width: 100%; + height: 100%; + text-align: left; + font-size: 150%; +} + +.minor_announcement_text { + background-color: #eaeaea; + color: #202020; + padding: 0.5rem 0.5rem; + text-align: left; + font-size: 100%; +} + +.announcement_header { + padding: 0.5rem 0; + display: flex; + flex-direction: column; +} + +@each $color-name, $color-value in $alert-stripe-colors { + .chat_alert_#{$color-name} { + color: #ffffff; + padding: 0.5rem 0.5rem; + box-shadow: none; + font-weight: bold; + margin: 1rem 0 1rem 0; + padding: 0; + display: flex; + flex-direction: column; + border-image: repeating-linear-gradient( + -45deg, + map.get($alert-stripe-alternate-colors, $color-name), + map.get($alert-stripe-alternate-colors, $color-name) 10px, + $color-value 10px, + $color-value 20px + ); + border-image-slice: $border-width fill; + border-width: $border-width-px; + border-image-width: $border-width-px; + border-image-outset: 0 0 0 0; + border-image-repeat: repeat repeat; + border-style: solid; + } + + .chat_alert_#{$color-name} .major_announcement_title { + color: map.get($alert-major-header-colors, $color-name); + } + + .chat_alert_#{$color-name} .minor_announcement_title { + color: map.get($alert-major-header-colors, $color-name); + } + + .chat_alert_#{$color-name} .subheader_announcement_text { + color: map.get($alert-subheader-header-colors, $color-name); + } + + .chat_alert_#{$color-name} .minor_announcement_text { + background-color: lighten( + map.get($alert-stripe-alternate-colors, $color-name), + 5 + ); + } + + .chat_alert_#{$color-name} .major_announcement_text { + background-color: lighten( + map.get($alert-stripe-alternate-colors, $color-name), + 5 + ); + } +} diff --git a/tgui/packages/tgui/constants.js b/tgui/packages/tgui/constants.js index 0d52f918e37e..5be174c16aa3 100644 --- a/tgui/packages/tgui/constants.js +++ b/tgui/packages/tgui/constants.js @@ -122,173 +122,3 @@ export const RADIO_CHANNELS = [ color: '#1ecc43', }, ]; - -const GASES = [ - { - id: 'o2', - path: '/datum/gas/oxygen', - name: 'Oxygen', - label: 'O₂', - color: 'blue', - }, - { - id: 'n2', - path: '/datum/gas/nitrogen', - name: 'Nitrogen', - label: 'N₂', - color: 'red', - }, - { - id: 'co2', - path: '/datum/gas/carbon_dioxide', - name: 'Carbon Dioxide', - label: 'CO₂', - color: 'grey', - }, - { - id: 'plasma', - path: '/datum/gas/plasma', - name: 'Plasma', - label: 'Plasma', - color: 'orange', - }, - { - id: 'water_vapor', - path: '/datum/gas/water_vapor', - name: 'Water Vapor', - label: 'H₂O', - color: 'lightsteelblue', - }, - { - id: 'nob', - path: '/datum/gas/hypernoblium', - name: 'Hyper-noblium', - label: 'Hyper-nob', - color: 'teal', - }, - { - id: 'n2o', - path: '/datum/gas/nitrous_oxide', - name: 'Nitrous Oxide', - label: 'N₂O', - color: 'bisque', - }, - { - id: 'no2', - path: '/datum/gas/nitrium', - name: 'Nitrium', - label: 'Nitrium', - color: 'brown', - }, - { - id: 'tritium', - path: '/datum/gas/tritium', - name: 'Tritium', - label: 'Tritium', - color: 'limegreen', - }, - { - id: 'bz', - path: '/datum/gas/bz', - name: 'BZ', - label: 'BZ', - color: 'mediumpurple', - }, - { - id: 'pluox', - path: '/datum/gas/pluoxium', - name: 'Pluoxium', - label: 'Pluoxium', - color: 'mediumslateblue', - }, - { - id: 'miasma', - path: '/datum/gas/miasma', - name: 'Miasma', - label: 'Miasma', - color: 'olive', - }, - { - id: 'Freon', - path: '/datum/gas/freon', - name: 'Freon', - label: 'Freon', - color: 'paleturquoise', - }, - { - id: 'hydrogen', - path: '/datum/gas/hydrogen', - name: 'Hydrogen', - label: 'H₂', - color: 'white', - }, - { - id: 'healium', - path: '/datum/gas/healium', - name: 'Healium', - label: 'Healium', - color: 'salmon', - }, - { - id: 'pluonium', - path: '/datum/gas/pluonium', - name: 'Pluonium', - label: 'Pluonium', - color: 'greenyellow', - }, - { - id: 'zauker', - path: '/datum/gas/zauker', - name: 'Zauker', - label: 'Zauker', - color: 'darkgreen', - }, - { - id: 'halon', - path: '/datum/gas/halon', - name: 'Halon', - label: 'Halon', - color: 'purple', - }, - { - id: 'antinoblium', - path: '/datum/gas/antinoblium', - name: 'Antinoblium', - label: 'Anti-nob', - color: 'maroon', - }, - { - id: 'hexane', - path: '/datum/gas/hexane', - name: 'Hexane', - label: 'Hexane', - color: 'plum', - }, - { - id: 'dilithium', - path: '/datum/gas/dilithium', - name: 'Dilithium', - label: 'Dilithium', - color: 'pink', - }, -]; - -export const getGasLabel = (gasId, fallbackValue) => { - const gasSearchString = String(gasId).toLowerCase(); - // prettier-ignore - const gas = GASES.find((gas) => ( - gas.id === gasSearchString - || gas.name.toLowerCase() === gasSearchString - )); - return (gas && gas.label) || fallbackValue || gasId; -}; - -export const getGasColor = (gasId) => { - const gasSearchString = String(gasId).toLowerCase(); - // prettier-ignore - const gas = GASES.find((gas) => ( - gas.id === gasSearchString - || gas.name.toLowerCase() === gasSearchString - )); - return gas && gas.color; -}; diff --git a/tgui/packages/tgui/interfaces/AntagInfoHeretic.tsx b/tgui/packages/tgui/interfaces/AntagInfoHeretic.tsx index 65168693a508..27572cb93a37 100644 --- a/tgui/packages/tgui/interfaces/AntagInfoHeretic.tsx +++ b/tgui/packages/tgui/interfaces/AntagInfoHeretic.tsx @@ -29,7 +29,6 @@ const hereticYellow = { }; type Knowledge = { - path: string; name: string; desc: string; gainFlavor: string; @@ -50,6 +49,7 @@ type Info = { ascended: BooleanLike; objectives: Objective[]; can_change_objective: BooleanLike; + path: string; }; const IntroductionSection = (props, context) => { @@ -236,13 +236,30 @@ const ResearchedKnowledge = (props, context) => { const KnowledgeShop = (props, context) => { const { data, act } = useBackend(context); + const { path } = props; const { learnableKnowledge } = data; + const pathKnowledge = learnableKnowledge.filter((Knowledge) => Knowledge.hereticPath === path); + const otherKnowledge = learnableKnowledge.filter((Knowledge) => Knowledge.hereticPath !== path); + otherKnowledge.sort((a, b) => { + const nameA = a.hereticPath.toUpperCase(); // ignore upper and lowercase + const nameB = b.hereticPath.toUpperCase(); // ignore upper and lowercase + if (nameA < nameB) { + return -1; + } + if (nameA > nameB) { + return 1; + } + + // names must be equal + return 0; + }); + const sortedKnowledge = pathKnowledge.concat(otherKnowledge); return (
- {(!learnableKnowledge && 'None!') || - learnableKnowledge.map((toLearn) => ( + {(!sortedKnowledge && 'None!') || + sortedKnowledge.map((toLearn) => (