diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 2f58d4e9ebb..a8a0459bcb1 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -7,4 +7,4 @@ assignees: '' --- -Please place all features requests here: https://nanotrasen.se/forum/60-suggestions/ +Please place all features requests here: https://www.paradisestation.org/forum/60-suggestions/ diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 45b7dc5a642..526be3bcaf0 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -15,7 +15,6 @@ add: Added new things del: Removed old things tweak: tweaked a few things -balance: rebalanced something fix: fixed a few things wip: added a few works in progress soundadd: added a new sound thingy diff --git a/.gitignore b/.gitignore index a4634f3fc84..74660294c3b 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,18 @@ data/ *.db stddef.dm .atom-build.json -*.vscode/* \ No newline at end of file +*.vscode/* +!/.vscode/extensions.json + +# ignore DMI tool build cache +/tools/dmitool/bin/ +/tools/dmitool/.gradle/ +/tools/dmitool/.settings/ +/tools/dmitool/.classpath +/tools/dmitool/.project + +# ignore midi2piano build cache +/tools/midi2piano/obj/* + + + diff --git a/.travis.yml b/.travis.yml index 464e01c8f53..5a731170a79 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,8 +18,8 @@ addons: env: global: - - BYOND_MAJOR="512" - - BYOND_MINOR="1454" + - BYOND_MAJOR="513" + - BYOND_MINOR="1505" - BYOND_MACRO_COUNT=4 matrix: - DM_MAPFILE="cyberiad" @@ -69,4 +69,4 @@ jobs: - npm install --loglevel=error before_script: script: - - gulp + - node node_modules/gulp/bin/gulp.js --require less-loader diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000000..9099488143b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "gbasood.byond-dm-language-support", + "platymuus.dm-langclient" + ] +} diff --git a/README.md b/README.md index d60fe8006c8..eafdb5ffe91 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![forthebadge](http://forthebadge.com/images/badges/contains-technical-debt.svg)](http://forthebadge.com) [![forthebadge](http://forthebadge.com/images/badges/fuck-it-ship-it.svg)](http://forthebadge.com) -[Website](https://nanotrasen.se/) - [Code](https://github.com/ParadiseSS13/Paradise) - [Discord](https://discordapp.com/invite/YJDsXFE) +[Website](https://www.paradisestation.org/) - [Code](https://github.com/ParadiseSS13/Paradise) - [Discord](https://discordapp.com/invite/YJDsXFE) --- @@ -104,7 +104,7 @@ Your server details go in /config/dbconfig.txt, and the SQL schema is in /SQL/paradise_schema.sql or /SQL/paradise_schema_prefix.sql, depending on if you want table prefixes. More detailed setup instructions are located on our wiki: -https://nanotrasen.se/wiki/index.php/Setting_up_the_Database +https://www.paradisestation.org/wiki/index.php/Setting_up_the_Database --- diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql index 1e4692b7e3b..837f8f440d6 100644 --- a/SQL/paradise_schema.sql +++ b/SQL/paradise_schema.sql @@ -97,7 +97,7 @@ CREATE TABLE `customuseritems` ( `cuiPropAdjust` text, `cuiJobMask` text NOT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=56 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=56 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -124,7 +124,7 @@ CREATE TABLE `death` ( `fireloss` int(11) NOT NULL, `oxyloss` int(11) NOT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=166546 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=166546 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -160,7 +160,7 @@ CREATE TABLE `admin` ( `level` int(2) NOT NULL DEFAULT '0', `flags` int(16) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=99 DEFAULT CHARSET=latin1; +) ENGINE=InnoDB AUTO_INCREMENT=99 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -177,7 +177,7 @@ CREATE TABLE `admin_log` ( `adminip` varchar(18) NOT NULL, `log` text NOT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -212,7 +212,7 @@ CREATE TABLE `ban` ( `unbanned_computerid` varchar(32) DEFAULT NULL, `unbanned_ip` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=10685 DEFAULT CHARSET=latin1; +) ENGINE=InnoDB AUTO_INCREMENT=10685 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -230,7 +230,7 @@ CREATE TABLE `feedback` ( `var_value` int(16) DEFAULT NULL, `details` text, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=257638 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=257638 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -272,7 +272,7 @@ CREATE TABLE `player` ( `parallax` tinyint(1) DEFAULT '8', PRIMARY KEY (`id`), UNIQUE KEY `ckey` (`ckey`) -) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=latin1; +) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -293,7 +293,7 @@ CREATE TABLE `poll_option` ( `descmid` varchar(32) DEFAULT NULL, `descmax` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -314,7 +314,7 @@ CREATE TABLE `poll_question` ( `createdby_ckey` varchar(45) NULL DEFAULT NULL, `createdby_ip` varchar(45) NULL DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -333,7 +333,7 @@ CREATE TABLE `poll_textreply` ( `replytext` text NOT NULL, `adminrank` varchar(32) NOT NULL DEFAULT 'Player', PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -353,7 +353,7 @@ CREATE TABLE `poll_vote` ( `adminrank` varchar(32) NOT NULL, `rating` int(2) DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -369,7 +369,7 @@ CREATE TABLE `privacy` ( `consent` bit(1) NOT NULL, PRIMARY KEY (`ckey`), UNIQUE KEY `ckey_UNIQUE` (`ckey`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -391,7 +391,7 @@ CREATE TABLE `karma` ( `spenderip` text NOT NULL, `time` datetime NOT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=73614 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=73614 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -407,7 +407,7 @@ CREATE TABLE `karmatotals` ( `karma` int(11) NOT NULL, `karmaspent` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=6765 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=6765 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -426,7 +426,7 @@ CREATE TABLE `library` ( `ckey` varchar(45) NOT NULL, `flagged` int(11) NOT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=929 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=929 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -442,7 +442,7 @@ CREATE TABLE `legacy_population` ( `admincount` int(11) DEFAULT NULL, `time` datetime NOT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=2550 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=2550 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -458,7 +458,7 @@ CREATE TABLE `whitelist` ( `job` text, `species` text, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=877 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=877 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; @@ -485,7 +485,7 @@ CREATE TABLE `watch` ( `last_editor` varchar(32), `edits` text, PRIMARY KEY (`ckey`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; @@ -505,8 +505,9 @@ CREATE TABLE `notes` ( `last_editor` varchar(32), `edits` text, `server` varchar(50) NOT NULL, + `crew_playtime` mediumint(8) UNSIGNED DEFAULT '0', PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -523,7 +524,7 @@ CREATE TABLE `memo` ( `last_editor` varchar(32), `edits` text, PRIMARY KEY (`ckey`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -537,7 +538,7 @@ CREATE TABLE `ipintel` ( `date` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL, `intel` real NOT NULL DEFAULT '0', PRIMARY KEY (`ip`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -550,7 +551,7 @@ CREATE TABLE `vpn_whitelist` ( `ckey` varchar(32) NOT NULL, `reason` text, PRIMARY KEY (`ckey`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -563,5 +564,34 @@ CREATE TABLE `oauth_tokens` ( `ckey` varchar(32) NOT NULL, `token` varchar(32) NOT NULL, PRIMARY KEY (`token`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; + + +-- +-- Table structure for table `playtime_history` +-- +DROP TABLE IF EXISTS `playtime_history`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `playtime_history` ( + `ckey` varchar(32) NOT NULL, + `date` DATE NOT NULL, + `time_living` SMALLINT NOT NULL, + `time_ghost` SMALLINT NOT NULL, + PRIMARY KEY (`ckey`, `date`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + + +-- +-- Table structure for table `connection_log` +-- +DROP TABLE IF EXISTS `connection_log`; +CREATE TABLE `connection_log` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `datetime` datetime NOT NULL, + `ckey` varchar(32) NOT NULL, + `ip` varchar(32) NOT NULL, + `computerid` varchar(32) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/SQL/paradise_schema_prefixed.sql b/SQL/paradise_schema_prefixed.sql index aa5d5895e56..b43141f6784 100644 --- a/SQL/paradise_schema_prefixed.sql +++ b/SQL/paradise_schema_prefixed.sql @@ -97,7 +97,7 @@ CREATE TABLE `SS13_customuseritems` ( `cuiPropAdjust` text, `cuiJobMask` text NOT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=56 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=56 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -124,7 +124,7 @@ CREATE TABLE `SS13_death` ( `fireloss` int(11) NOT NULL, `oxyloss` int(11) NOT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=166546 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=166546 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -159,7 +159,7 @@ CREATE TABLE `SS13_admin` ( `level` int(2) NOT NULL DEFAULT '0', `flags` int(16) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=99 DEFAULT CHARSET=latin1; +) ENGINE=InnoDB AUTO_INCREMENT=99 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -176,7 +176,7 @@ CREATE TABLE `SS13_admin_log` ( `adminip` varchar(18) NOT NULL, `log` text NOT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -211,7 +211,7 @@ CREATE TABLE `SS13_ban` ( `unbanned_computerid` varchar(32) DEFAULT NULL, `unbanned_ip` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=10685 DEFAULT CHARSET=latin1; +) ENGINE=InnoDB AUTO_INCREMENT=10685 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -229,7 +229,7 @@ CREATE TABLE `SS13_feedback` ( `var_value` int(16) DEFAULT NULL, `details` text, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=257638 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=257638 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -271,7 +271,7 @@ CREATE TABLE `SS13_player` ( `parallax` tinyint(1) DEFAULT '8', PRIMARY KEY (`id`), UNIQUE KEY `ckey` (`ckey`) -) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=latin1; +) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -292,7 +292,7 @@ CREATE TABLE `SS13_poll_option` ( `descmid` varchar(32) DEFAULT NULL, `descmax` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -313,7 +313,7 @@ CREATE TABLE `SS13_poll_question` ( `createdby_ckey` varchar(45) NULL DEFAULT NULL, `createdby_ip` varchar(45) NULL DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -332,7 +332,7 @@ CREATE TABLE `SS13_poll_textreply` ( `replytext` text NOT NULL, `adminrank` varchar(32) NOT NULL DEFAULT 'Player', PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -352,7 +352,7 @@ CREATE TABLE `SS13_poll_vote` ( `adminrank` varchar(32) NOT NULL, `rating` int(2) DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -368,7 +368,7 @@ CREATE TABLE `ss13_privacy` ( `consent` bit(1) NOT NULL, PRIMARY KEY (`ckey`), UNIQUE KEY `ckey_UNIQUE` (`ckey`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -390,7 +390,7 @@ CREATE TABLE `SS13_karma` ( `spenderip` text NOT NULL, `time` datetime NOT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=73614 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=73614 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -406,7 +406,7 @@ CREATE TABLE `SS13_karmatotals` ( `karma` int(11) NOT NULL, `karmaspent` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=6765 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=6765 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -425,7 +425,7 @@ CREATE TABLE `SS13_library` ( `ckey` varchar(45) NOT NULL, `flagged` int(11) NOT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=929 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=929 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -441,7 +441,7 @@ CREATE TABLE `SS13_legacy_population` ( `admincount` int(11) DEFAULT NULL, `time` datetime NOT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=2550 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=2550 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -457,7 +457,7 @@ CREATE TABLE `SS13_whitelist` ( `job` text, `species` text, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=877 DEFAULT CHARSET=latin1; +) ENGINE=MyISAM AUTO_INCREMENT=877 DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; @@ -484,7 +484,7 @@ CREATE TABLE `SS13_watch` ( `last_editor` varchar(32), `edits` text, PRIMARY KEY (`ckey`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; @@ -504,8 +504,9 @@ CREATE TABLE `SS13_notes` ( `last_editor` varchar(32), `edits` text, `server` varchar(50) NOT NULL, + `crew_playtime` mediumint(8) UNSIGNED DEFAULT '0', PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -522,7 +523,7 @@ CREATE TABLE `SS13_memo` ( `last_editor` varchar(32), `edits` text, PRIMARY KEY (`ckey`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -536,7 +537,7 @@ CREATE TABLE `SS13_ipintel` ( `date` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL, `intel` real NOT NULL DEFAULT '0', PRIMARY key (`ip`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -549,7 +550,7 @@ CREATE TABLE `SS13_vpn_whitelist` ( `ckey` varchar(32) NOT NULL, `reason` text, PRIMARY KEY (`ckey`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -562,5 +563,32 @@ CREATE TABLE `SS13_oauth_tokens` ( `ckey` varchar(32) NOT NULL, `token` varchar(32) NOT NULL, PRIMARY KEY (`token`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `SS13_playtime_history` +-- +DROP TABLE IF EXISTS `SS13_playtime_history`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `SS13_playtime_history` ( + `ckey` varchar(32) NOT NULL, + `date` DATE NOT NULL, + `time_living` SMALLINT NOT NULL, + `time_ghost` SMALLINT NOT NULL, + PRIMARY KEY (`ckey`, `date`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- +-- Table structure for table `SS13_connection_log` +-- +DROP TABLE IF EXISTS `SS13_connection_log`; +CREATE TABLE `SS13_connection_log` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `datetime` datetime NOT NULL, + `ckey` varchar(32) NOT NULL, + `ip` varchar(32) NOT NULL, + `computerid` varchar(32) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/SQL/updates/10-11.sql b/SQL/updates/10-11.sql new file mode 100644 index 00000000000..9564d3efaad --- /dev/null +++ b/SQL/updates/10-11.sql @@ -0,0 +1,41 @@ +# Updating SQL from ver 10 to 11 +# Changes tables from latin1 to utf8mb4 +# Based on: https://github.com/BeeStation/BeeStation-Hornet/pull/1074/files +# -Kyet + +# Generation (not necessary to run unless your DB has extra tables) +SELECT CONCAT("ALTER TABLE ", TABLE_SCHEMA, '.', TABLE_NAME," CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;") AS ExecuteTheString +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA="feedback" +AND TABLE_TYPE="BASE TABLE"; + +# Actual table conversion stuff +ALTER TABLE feedback.admin CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.admin_log CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.ban CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.characters CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.connection_log CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.customuseritems CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.death CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.donators CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.erro_privacy CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.feedback CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.ipintel CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.karma CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.karmatotals CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.legacy_population CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.library CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.memo CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.notes CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.oauth_tokens CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.player CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.playtime_history CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.poll_option CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.poll_question CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.poll_textreply CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.poll_vote CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.population CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.privacy CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.vpn_whitelist CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.watch CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE feedback.whitelist CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; \ No newline at end of file diff --git a/SQL/updates/9-10.sql b/SQL/updates/9-10.sql new file mode 100644 index 00000000000..942aca1b541 --- /dev/null +++ b/SQL/updates/9-10.sql @@ -0,0 +1,24 @@ +# Updating SQL from ver 9 to 10 - Kyet + +# Add the 'playtime_history' table that tracks playtime per player per day +CREATE TABLE `playtime_history` ( + `ckey` varchar(32) NOT NULL, + `date` DATE NOT NULL, + `time_living` SMALLINT NOT NULL, + `time_ghost` SMALLINT NOT NULL, + PRIMARY KEY (`ckey`, `date`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +# Add the 'connection_log' table, which is used to log all connections to the server +DROP TABLE IF EXISTS `connection_log`; +CREATE TABLE `connection_log` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `datetime` datetime NOT NULL, + `ckey` varchar(32) NOT NULL, + `ip` varchar(32) NOT NULL, + `computerid` varchar(32) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +# Add the 'crew_playtime' field to the 'notes' table, which gives admins some idea of how many hours have passed for a player since they got a note +ALTER TABLE `notes` ADD `crew_playtime` mediumint(8) UNSIGNED DEFAULT '0' AFTER `server`; diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm index 8de75d7aaf1..8382f800369 100644 --- a/_maps/map_files/cyberiad/cyberiad.dmm +++ b/_maps/map_files/cyberiad/cyberiad.dmm @@ -72015,7 +72015,7 @@ dir = 8; layer = 2.9 }, -/obj/item/circuitboard/rdconsole/public{ +/obj/item/circuitboard/rdconsole{ pixel_x = -4 }, /obj/item/circuitboard/rdserver{ diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm index 0c1b0a35426..157b0312995 100644 --- a/code/ATMOSPHERICS/atmospherics.dm +++ b/code/ATMOSPHERICS/atmospherics.dm @@ -64,8 +64,8 @@ GLOBAL_DATUM_INIT(pipe_icon_manager, /datum/pipe_icon_manager, new()) // Icons/overlays/underlays /obj/machinery/atmospherics/update_icon() - var/turf/T = loc - if(level == 2 || !T.intact) + var/turf/T = get_turf(loc) + if(!T || level == 2 || !T.intact) plane = GAME_PLANE else plane = FLOOR_PLANE diff --git a/code/ATMOSPHERICS/components/binary_devices/circulator.dm b/code/ATMOSPHERICS/components/binary_devices/circulator.dm index e2dd952213a..5574f97ea66 100644 --- a/code/ATMOSPHERICS/components/binary_devices/circulator.dm +++ b/code/ATMOSPHERICS/components/binary_devices/circulator.dm @@ -98,16 +98,16 @@ else return "South" -/obj/machinery/atmospherics/binary/circulator/attackby(obj/item/W as obj, mob/user as mob, params) - if(ismultitool(W)) - if(side_inverted == 0) - side_inverted = 1 - else - side_inverted = 0 - to_chat(user, "You reverse the circulator's valve settings. The inlet of the circulator is now on the [get_inlet_side(dir)] side.") - desc = "A gas circulator pump and heat exchanger. Its input port is on the [get_inlet_side(dir)] side, and its output port is on the [get_outlet_side(dir)] side." +/obj/machinery/atmospherics/binary/circulator/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!side_inverted) + side_inverted = TRUE else - return ..() + side_inverted = FALSE + to_chat(user, "You reverse the circulator's valve settings. The inlet of the circulator is now on the [get_inlet_side(dir)] side.") + desc = "A gas circulator pump and heat exchanger. Its input port is on the [get_inlet_side(dir)] side, and its output port is on the [get_outlet_side(dir)] side." /obj/machinery/atmospherics/binary/circulator/update_icon() ..() diff --git a/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm b/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm index 1b920002227..afdca1d19ce 100644 --- a/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm +++ b/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm @@ -344,27 +344,6 @@ playsound(loc, 'sound/weapons/bladeslice.ogg', 100, TRUE) /obj/machinery/atmospherics/unary/vent_pump/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - to_chat(user, "Now welding the vent.") - if(do_after(user, 20 * WT.toolspeed, target = src)) - if(!src || !WT.isOn()) return - playsound(src.loc, WT.usesound, 50, 1) - if(!welded) - user.visible_message("[user] welds the vent shut.", "You weld the vent shut.", "You hear welding.") - welded = 1 - update_icon() - else - user.visible_message("[user] unwelds the vent.", "You unweld the vent.", "You hear welding.") - welded = 0 - update_icon() - else - to_chat(user, "The welding tool needs to be on to start this task.") - return 1 - else - to_chat(user, "You need more welding fuel to complete this task.") - return 1 if(istype(W, /obj/item/screwdriver)) if(!welded) if(open) @@ -400,6 +379,23 @@ return ..() +/obj/machinery/atmospherics/unary/vent_pump/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_WELD_MESSAGE + if(I.use_tool(src, user, 20, volume = I.tool_volume)) + if(!welded) + welded = TRUE + visible_message("[user] welds [src] shut!",\ + "You weld [src] shut!") + else + welded = FALSE + visible_message("[user] unwelds [src]!",\ + "You unweld [src]!") + update_icon() + + /obj/machinery/atmospherics/unary/vent_pump/attack_hand() if(!welded) if(open) diff --git a/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm index 5fcf7817a30..d9aff36688b 100644 --- a/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm +++ b/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm @@ -393,27 +393,6 @@ playsound(loc, 'sound/weapons/bladeslice.ogg', 100, TRUE) /obj/machinery/atmospherics/unary/vent_scrubber/attackby(var/obj/item/W as obj, var/mob/user as mob, params) - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - to_chat(user, "Now welding the scrubber.") - if(do_after(user, 20 * WT.toolspeed, target = src)) - if(!src || !WT.isOn()) return - playsound(get_turf(src), WT.usesound, 50, 1) - if(!welded) - user.visible_message("[user] welds the scrubber shut.", "You weld the vent scrubber.", "You hear welding.") - welded = 1 - update_icon() - else - user.visible_message("[user] unwelds the scrubber.", "You unweld the scrubber.", "You hear welding.") - welded = 0 - update_icon() - else - to_chat(user, "The welding tool needs to be on to start this task.") - return 1 - else - to_chat(user, "You need more welding fuel to complete this task.") - return 1 if(istype(W, /obj/item/multitool)) update_multitool_menu(user) return 1 @@ -423,3 +402,19 @@ return 1 return ..() + +/obj/machinery/atmospherics/unary/vent_scrubber/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_WELD_MESSAGE + if(I.use_tool(src, user, 20, volume = I.tool_volume)) + if(!welded) + welded = TRUE + visible_message("[user] welds [src] shut!",\ + "You weld [src] shut!") + else + welded = FALSE + visible_message("[user] unwelds [src]!",\ + "You unweld [src]!") + update_icon() diff --git a/code/LINDA/LINDA_turf_tile.dm b/code/LINDA/LINDA_turf_tile.dm index a0a0b6b8784..b86ad2299ff 100644 --- a/code/LINDA/LINDA_turf_tile.dm +++ b/code/LINDA/LINDA_turf_tile.dm @@ -486,7 +486,7 @@ turf/simulated/proc/consider_superconductivity(starting) turf/simulated/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 - 2.7) //hardcoded space temperature + 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* \ diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index df957eaa11e..c94dff5ca6c 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -107,6 +107,7 @@ #define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir) #define COMSIG_MOVABLE_CROSS "movable_cross" //from base of atom/movable/Cross(): (/atom/movable) #define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable) +#define COMSIG_CROSSED_MOVABLE "crossed_movable" //when we cross over something (calling Crossed() on that atom) #define COMSIG_MOVABLE_UNCROSSED "movable_uncrossed" //from base of atom/movable/Uncrossed(): (/atom/movable) #define COMSIG_MOVABLE_UNCROSS "movable_uncross" //from base of atom/movable/Uncross(): (/atom/movable) #define COMPONENT_MOVABLE_BLOCK_UNCROSS 1 diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 7dd5fc5a609..51b895ff12d 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -319,7 +319,7 @@ #define INVESTIGATE_BOMB "bombs" // The SQL version required by this version of the code -#define SQL_VERSION 9 +#define SQL_VERSION 11 // Vending machine stuff #define CAT_NORMAL 1 @@ -384,7 +384,7 @@ #define EXPLOSIVE_WALL_GROUP_SYNDICATE_BASE "syndicate_base" // Filters -#define FILTER_AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-2, size=4, border=4, color="#04080FAA") +#define FILTER_AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-2, size=4, color="#04080FAA") //Fullscreen overlay resolution in tiles. #define FULLSCREEN_OVERLAY_RESOLUTION_X 15 diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index 5b93e570222..34ad4d69e54 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -10,7 +10,6 @@ // justice if someone's abusing your role #define ROLE_SYNDICATE "Syndicate" #define ROLE_TRAITOR "traitor" -#define ROLE_MINDSLAVE "mindslave" #define ROLE_OPERATIVE "operative" #define ROLE_CHANGELING "changeling" #define ROLE_WIZARD "wizard" diff --git a/code/__DEFINES/tools.dm b/code/__DEFINES/tools.dm new file mode 100644 index 00000000000..d0204e1d013 --- /dev/null +++ b/code/__DEFINES/tools.dm @@ -0,0 +1,46 @@ +#define TOOL_CROWBAR "crowbar" +#define TOOL_MULTITOOL "multitool" +#define TOOL_SCREWDRIVER "screwdriver" +#define TOOL_WIRECUTTER "wirecutter" +#define TOOL_WRENCH "wrench" +#define TOOL_WELDER "welder" + +#define MIN_TOOL_SOUND_DELAY 20 + +//Crowbar messages +#define CROWBAR_ATTEMPT_PRY_CIRCUIT_MESSAGE user.visible_message("[user] begins removing the circuit board from [src]...", "You begin removing the circuit board from [src]...", "You hear prying noises.") +#define CROWBAR_PRY_CIRCUIT_SUCCESS_MESSAGE user.visible_message("[user] pries out the circuit board from [src]!", "You pry out the circuit board from [src]!", "You hear prying noises.") + +//Screwdriver messages +#define SCREWDRIVER_SCREW_MESSAGE user.visible_message("[user] tightens the screws on [src]!", "You tighten the screws on [src]!", "You hear a screwdriver.") +#define SCREWDRIVER_UNSCREW_MESSAGE user.visible_message("[user] loosens the screws on [src]!", "You loosen the screws on [src]!", "You hear a screwdriver.") +#define SCREWDRIVER_OPEN_PANEL_MESSAGE user.visible_message("[user] opens the panel on [src]!", "You open the panel on [src]!", "You hear a screwdriver.") +#define SCREWDRIVER_CLOSE_PANEL_MESSAGE user.visible_message("[user] closes the panel on [src]!", "You close the panel on [src]!", "You hear a screwdriver.") + +//Wirecutter messages +#define WIRECUTTER_SNIP_MESSAGE user.visible_message("[user] cuts the wires from [src]!", "You cut the wires from [src]!", "You hear snipping.") +#define WIRECUTTER_ATTEMPT_DISMANTLE_MESSAGE user.visible_message("[user] begins cutting [src] apart... ", "You begin cutting [src] apart...", "You hear snipping.") +#define WIRECUTTER_DISMANTLE_SUCCESS_MESSAGE user.visible_message("[user] cuts [src] apart!", "You cut [src] apart!", "You hear snipping.") + +//Welder messages and other stuff +#define HEALPERWELD 15 +#define WELDER_ATTEMPT_WELD_MESSAGE user.visible_message("[user] begins welding [src]...", "You begin welding [src]...", "You hear welding.") +#define WELDER_WELD_SUCCESS_MESSAGE to_chat(user, "You finish welding [src]!") +#define WELDER_ATTEMPT_REPAIR_MESSAGE user.visible_message("[user] begins repairing the damage on [src]...", "You begin repairing [src]...", "You hear welding.") +#define WELDER_REPAIR_SUCCESS_MESSAGE to_chat(user, "You repair the damage on [src]!") +#define WELDER_ATTEMPT_SLICING_MESSAGE user.visible_message("[user] begins slicing through [src]...", "You begin slicing through [src]...", "You hear welding.") +#define WELDER_SLICING_SUCCESS_MESSAGE to_chat(user, "You slice clean through [src]!") +#define WELDER_ATTEMPT_FLOOR_SLICE_MESSAGE user.visible_message("[user] begins slicing [src] free from [get_turf(src)]...", "You begin slicing [src] free from [get_turf(src)]...", "You hear welding.") +#define WELDER_FLOOR_SLICE_SUCCESS_MESSAGE to_chat(user, "You slice [src] clear of [get_turf(src)]!") +#define WELDER_ATTEMPT_FLOOR_WELD_MESSAGE user.visible_message("[user] begins welding [src] to [get_turf(src)]...", "You begin welding [src] to [get_turf(src)]...", "You hear welding.") +#define WELDER_FLOOR_WELD_SUCCESS_MESSAGE to_chat(user, "You weld [src] to [get_turf(src)]!") + +//Wrench messages +#define WRENCH_ANCHOR_MESSAGE user.visible_message("[user] tightens the bolts on [src]!", "You tighten the bolts on [src]!", "You hear ratcheting.") +#define WRENCH_UNANCHOR_MESSAGE user.visible_message("[user] loosens the bolts on [src]!", "You loosen the bolts on [src]!", "You hear ratcheting.") +#define WRENCH_UNANCHOR_WALL_MESSAGE user.visible_message("[user] unwrenches [src] from the wall!", "You unwrench [src] from the wall!", "You hear ratcheting.") +#define WRENCH_ANCHOR_TO_WALL_MESSAGE user.visible_message("[user] affixes [src] to the wall!", "You affix [src] to the wall!", "You hear ratcheting.") + +//Generic tool messages that don't correspond to any particular tool +#define TOOL_ATTEMPT_DISMANTLE_MESSAGE user.visible_message("[user] begins to disassemble [src] with [I]...", "You begin to disassemble [src] with [I]...", "You hear someone using some kind of tool.") +#define TOOL_DISMANTLE_SUCCESS_MESSAGE user.visible_message("[user] dismantles [src]!", "You dismantle [src]!", "You hear someone using some kind of tool.") diff --git a/code/__DEFINES/typeids.dm b/code/__DEFINES/typeids.dm index 4fd2c390fa7..16b6e475b8e 100644 --- a/code/__DEFINES/typeids.dm +++ b/code/__DEFINES/typeids.dm @@ -2,5 +2,5 @@ #define TYPEID_NULL "0" #define TYPEID_NORMAL_LIST "f" //helper macros -#define GET_TYPEID(ref) ( ( (lentext(ref) <= 10) ? "TYPEID_NULL" : copytext(ref, 4, lentext(ref) - 6) ) ) +#define GET_TYPEID(ref) ( ( (length(ref) <= 10) ? "TYPEID_NULL" : copytext(ref, 4, length(ref) - 6) ) ) #define IS_NORMAL_LIST(L) (GET_TYPEID("\ref[L]") == TYPEID_NORMAL_LIST) \ No newline at end of file diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 65fc87c3b34..7a91c3bf9bc 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -1,5 +1,5 @@ //location of the rust-g library -#define RUST_G "rust_g" +#define RUST_G (world.system_type == UNIX ? "./librust_g.so" : "./rust_g.dll") // On Linux/Unix systems the line endings are LF, on windows it's CRLF, admins that don't use notepad++ // will get logs that are one big line if the system is Linux and they are using notepad. This solves it by adding CR to every line ending @@ -140,6 +140,9 @@ /proc/log_asset(text) WRITE_LOG(GLOB.world_asset_log, "ASSET: [text]") +/proc/log_runtime_summary(text) + WRITE_LOG(GLOB.runtime_summary_log, "[text]") + /** * Standardized method for tracking startup times. */ diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 744b8b86a9a..0ab10447f8c 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -478,7 +478,10 @@ proc/pollCandidates(Question, be_special_type, antag_age_check = FALSE, poll_tim G << 'sound/misc/notice2.ogg'//Alerting them to their consideration if(flashwindow) window_flash(G.client) - switch(alert(G,Question,"Please answer in [poll_time/10] seconds!","No","Yes","Not This Round")) + var/ans = alert(G,Question,"Please answer in [poll_time/10] seconds!","No","Yes","Not This Round") + if(!G?.client) + return + switch(ans) if("Yes") to_chat(G, "Choice registered: Yes.") if((world.time-time_passed)>poll_time)//If more than 30 game seconds passed. diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 49983658d48..5ffe891d95b 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -69,11 +69,6 @@ return list[index] return -/proc/islist(list/list) - if(istype(list)) - return 1 - return 0 - //Return either pick(list) or null if list is not of type /list or is empty /proc/safepick(list/list) if(!islist(list) || !list.len) diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index f3b76064517..db41b411d12 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -20,7 +20,7 @@ if(!istext(t)) t = "[t]" // Just quietly assume any non-texts are supposed to be text var/sqltext = dbcon.Quote(t); - return copytext(sqltext, 2, lentext(sqltext));//Quote() adds quotes around input, we already do that + return copytext(sqltext, 2, length(sqltext));//Quote() adds quotes around input, we already do that /proc/format_table_name(table as text) return sqlfdbktableprefix + table @@ -108,11 +108,10 @@ // Used to get a sanitized input. /proc/stripped_input(mob/user, message = "", title = "", default = "", max_length=MAX_MESSAGE_LEN, no_trim=FALSE) - var/name = input(user, message, title, default) as text|null - if(no_trim) - return copytext(html_encode(name), 1, max_length) - else - return trim(html_encode(name), max_length) //trim is "outside" because html_encode can expand single symbols into multiple symbols (such as turning < into <) + var/name = html_encode(input(user, message, title, default) as text|null) + if(!no_trim) + name = trim(name) //trim is "outside" because html_encode can expand single symbols into multiple symbols (such as turning < into <) + return copytext(name, 1, max_length) // Uses client.typing to check if the popup should appear or not /proc/typing_input(mob/user, message = "", title = "", default = "") @@ -333,9 +332,9 @@ proc/checkhtml(var/t) //is in the other string at the same spot (assuming it is not a replace char). //This is used for fingerprints var/newtext = text - if(lentext(text) != lentext(compare)) + if(length(text) != length(compare)) return 0 - for(var/i = 1, i < lentext(text), i++) + for(var/i = 1, i < length(text), i++) var/a = copytext(text,i,i+1) var/b = copytext(compare,i,i+1) //if it isn't both the same letter, or if they are both the replacement character @@ -355,7 +354,7 @@ proc/checkhtml(var/t) if(!text || !character) return 0 var/count = 0 - for(var/i = 1, i <= lentext(text), i++) + for(var/i = 1, i <= length(text), i++) var/a = copytext(text,i,i+1) if(a == character) count++ @@ -400,8 +399,8 @@ proc/checkhtml(var/t) //Used in preferences' SetFlavorText and human's set_flavor verb //Previews a string of len or less length /proc/TextPreview(var/string,var/len=40) - if(lentext(string) <= len) - if(!lentext(string)) + if(length(string) <= len) + if(!length(string)) return "\[...\]" else return html_encode(string) //NO DECODED HTML YOU CHUCKLEFUCKS @@ -541,7 +540,7 @@ proc/checkhtml(var/t) text = "[text]" else text = "[text]" - + text = copytext(text, 1, MAX_PAPER_MESSAGE_LEN) return text diff --git a/code/__HELPERS/tool_helpers.dm b/code/__HELPERS/tool_helpers.dm new file mode 100644 index 00000000000..15c8e60591e --- /dev/null +++ b/code/__HELPERS/tool_helpers.dm @@ -0,0 +1,51 @@ +//Quick type checks for some tools + +/proc/iswrench(O) + if(istype(O, /obj/item/wrench)) + return TRUE + return FALSE + +/proc/iswelder(O) + if(istype(O, /obj/item/weldingtool)) + return TRUE + return FALSE + +/proc/iswirecutter(O) + if(istype(O, /obj/item/wirecutters)) + return TRUE + return FALSE + +/proc/isscrewdriver(O) + if(istype(O, /obj/item/screwdriver)) + return TRUE + return FALSE + +/proc/ismultitool(O) + if(istype(O, /obj/item/multitool)) + return TRUE + return FALSE + +/proc/iscrowbar(O) + if(istype(O, /obj/item/crowbar)) + return TRUE + return FALSE + +/proc/iscoil(O) + if(istype(O, /obj/item/stack/cable_coil)) + return TRUE + return FALSE + +/proc/ispowertool(O)//used to check if a tool can force powered doors + if(istype(O, /obj/item/crowbar/power) || istype(O, /obj/item/mecha_parts/mecha_equipment/medical/rescue_jaw)) + return TRUE + return FALSE + +/proc/is_surgery_tool(obj/item/W as obj) + return ( \ + istype(W, /obj/item/scalpel) || \ + istype(W, /obj/item/hemostat) || \ + istype(W, /obj/item/retractor) || \ + istype(W, /obj/item/cautery) || \ + istype(W, /obj/item/bonegel) || \ + istype(W, /obj/item/bonesetter) + ) diff --git a/code/__HELPERS/traits.dm b/code/__HELPERS/traits.dm index 472caea4490..7c1d2257e27 100644 --- a/code/__HELPERS/traits.dm +++ b/code/__HELPERS/traits.dm @@ -62,6 +62,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai //mob traits #define TRAIT_PACIFISM "pacifism" +#define TRAIT_WATERBREATH "waterbreathing" // common trait sources #define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention \ No newline at end of file diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 82295bc9d80..45283498ebd 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -540,9 +540,20 @@ Returns 1 if the chain up to the area contains the given typepath /proc/between(var/low, var/middle, var/high) return max(min(middle, high), low) -proc/arctan(x) + + +#if DM_VERSION > 513 +#warn 513 is definitely stable now, remove this +#endif +#if DM_VERSION < 513 +/proc/arctan(x) var/y=arcsin(x/sqrt(1+x*x)) return y +/proc/islist(list/list) + if(istype(list)) + return 1 + return 0 +#endif //returns random gauss number proc/GaussRand(var/sigma) @@ -1131,70 +1142,9 @@ var/list/can_embed_types = typecacheof(list( if(is_type_in_typecache(W, can_embed_types)) return 1 -//Quick type checks for some tools -var/global/list/common_tools = list( -/obj/item/stack/cable_coil, -/obj/item/wrench, -/obj/item/weldingtool, -/obj/item/screwdriver, -/obj/item/wirecutters, -/obj/item/multitool, -/obj/item/crowbar) - -/proc/istool(O) - if(O && is_type_in_list(O, common_tools)) - return 1 - return 0 - -/proc/iswrench(O) - if(istype(O, /obj/item/wrench)) - return 1 - return 0 - -/proc/iswelder(O) - if(istype(O, /obj/item/weldingtool)) - return 1 - return 0 - -/proc/iscoil(O) - if(istype(O, /obj/item/stack/cable_coil)) - return 1 - return 0 - -/proc/iswirecutter(O) - if(istype(O, /obj/item/wirecutters)) - return 1 - return 0 - -/proc/isscrewdriver(O) - if(istype(O, /obj/item/screwdriver)) - return 1 - return 0 - -/proc/ismultitool(O) - if(istype(O, /obj/item/multitool)) - return 1 - return 0 - -/proc/iscrowbar(O) - if(istype(O, /obj/item/crowbar)) - return 1 - return 0 - -/proc/ispowertool(O)//used to check if a tool can force powered doors - if(istype(O, /obj/item/crowbar/power) || istype(O, /obj/item/mecha_parts/mecha_equipment/medical/rescue_jaw)) - return TRUE - return FALSE - -/proc/iswire(O) - if(istype(O, /obj/item/stack/cable_coil)) - return 1 - return 0 - /proc/is_hot(obj/item/W as obj) - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/O = W - if(O.isOn()) + if(W.tool_behaviour == TOOL_WELDER) + if(W.tool_enabled) return 2500 else return 0 @@ -1249,16 +1199,6 @@ var/global/list/common_tools = list( return 1 return 0 -/proc/is_surgery_tool(obj/item/W as obj) - return ( \ - istype(W, /obj/item/scalpel) || \ - istype(W, /obj/item/hemostat) || \ - istype(W, /obj/item/retractor) || \ - istype(W, /obj/item/cautery) || \ - istype(W, /obj/item/bonegel) || \ - istype(W, /obj/item/bonesetter) - ) - /proc/reverse_direction(var/dir) switch(dir) if(NORTH) diff --git a/code/_globalvars/configuration.dm b/code/_globalvars/configuration.dm index 3d7259eef55..ee3f6a73a92 100644 --- a/code/_globalvars/configuration.dm +++ b/code/_globalvars/configuration.dm @@ -32,7 +32,7 @@ var/Debug = 0 // global debug switch var/Debug2 = 1 // enables detailed job debug file in secrets //This was a define, but I changed it to a variable so it can be changed in-game.(kept the all-caps definition because... code...) -Errorage -var/MAX_EX_DEVESTATION_RANGE = 3 +var/MAX_EX_DEVASTATION_RANGE = 3 var/MAX_EX_HEAVY_RANGE = 7 var/MAX_EX_LIGHT_RANGE = 14 var/MAX_EX_FLASH_RANGE = 14 diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm index 43482937afb..10c7d74c752 100644 --- a/code/_globalvars/logging.dm +++ b/code/_globalvars/logging.dm @@ -12,6 +12,8 @@ GLOBAL_VAR(world_href_log) GLOBAL_PROTECT(world_href_log) GLOBAL_VAR(world_asset_log) GLOBAL_PROTECT(world_asset_log) +GLOBAL_VAR(runtime_summary_log) +GLOBAL_PROTECT(runtime_summary_log) var/list/jobMax = list() var/list/admin_log = list ( ) diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 8d58245eda5..7c2214e2287 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -42,8 +42,8 @@ if(control_disabled || stat) return - - var/turf/pixel_turf = get_turf_pixel(A) + + var/turf/pixel_turf = isturf(A) ? A : get_turf_pixel(A) if(isnull(pixel_turf)) return if(!can_see(A)) diff --git a/code/_onclick/hud/plane_master.dm b/code/_onclick/hud/plane_master.dm index a5586578b3f..9c0f498cd83 100644 --- a/code/_onclick/hud/plane_master.dm +++ b/code/_onclick/hud/plane_master.dm @@ -16,7 +16,7 @@ filters += filter(type = "outline", size = _size, color = _color) /obj/screen/plane_master/proc/shadow(_size, _border, _offset = 0, _x = 0, _y = 0, _color = "#04080FAA") - filters += filter(type = "drop_shadow", x = _x, y = _y, color = _color, size = _size, offset = _offset, border = _border) + filters += filter(type = "drop_shadow", x = _x, y = _y, color = _color, size = _size, offset = _offset) /obj/screen/plane_master/proc/clear_filters() filters = list() diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 47b5f2ba337..d2a91da4020 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -1,10 +1,17 @@ /obj/item/proc/melee_attack_chain(mob/user, atom/target, params) - if(pre_attackby(target, user, params)) + if(!tool_attack_chain(user, target) && pre_attackby(target, user, params)) // Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example) var/resolved = target.attackby(src, user, params) if(!resolved && target && !QDELETED(src)) afterattack(target, user, 1, params) // 1: clicking something Adjacent +//Checks if the item can work as a tool, calling the appropriate tool behavior on the target +//Note that if tool_act returns TRUE, then the tool won't call attack_by. +/obj/item/proc/tool_attack_chain(mob/user, atom/target) + if(!tool_behaviour) + return FALSE + return target.tool_act(user, src, tool_behaviour) + // Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown. /obj/item/proc/attack_self(mob/user) if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_SELF, user) & COMPONENT_NO_INTERACT) @@ -50,17 +57,12 @@ return 0 else return 1 - - if(isscrewdriver(src) && ismachine(M) && user.a_intent == INTENT_HELP) + var/obj/item/organ/external/O = M.get_organ(user.zone_selected) + if((is_sharp(src) || (isscrewdriver(src) && O.is_robotic())) && user.a_intent == INTENT_HELP) if(!attempt_initiate_surgery(src, M, user)) - return 0 + return FALSE else - return 1 - if(is_sharp(src) && user.a_intent == INTENT_HELP) - if(!attempt_initiate_surgery(src, M, user)) - return 0 - else - return 1 + return TRUE if(force && HAS_TRAIT(user, TRAIT_PACIFISM)) to_chat(user, "You don't want to harm other living beings!") diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index 5f0c94ecee6..460bc0193f6 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -61,6 +61,8 @@ // health + cyborg analyzer for ghosts /mob/living/attack_ghost(mob/dead/observer/user) + if(!istype(user)) // Make sure user is actually an observer. Revenents also use attack_ghost, but do not have the health_scan var. + return if(user.client && user.health_scan) if(issilicon(src) || ismachine(src)) robot_healthscan(user, src) diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 8ae35d52179..d1a3861676b 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -79,7 +79,7 @@ var/auto_cryo_ssd_mins = 0 var/ssd_warning = 0 - + var/list_afk_minimum = 5 // How long people have to be AFK before it's listed on the "List AFK players" verb var/traitor_objectives_amount = 2 @@ -102,6 +102,7 @@ var/donationsurl = "http://example.org" var/repositoryurl = "http://example.org" var/discordurl = "http://example.org" + var/discordforumurl = "http://example.org" var/overflow_server_url var/forbid_singulo_possession = 0 @@ -144,6 +145,7 @@ var/ipintel_detailsurl = "https://iphub.info/?ip=" var/forum_link_url + var/forum_playerinfo_url var/admin_legacy_system = 0 //Defines whether the server uses the legacy admin system with admins.txt or the SQL system. Config option in config.txt var/ban_legacy_system = 0 //Defines whether the server uses the legacy banning system with the files in /data or the SQL system. Config option in config.txt @@ -244,7 +246,7 @@ //cube monkey limit var/cubemonkeycap = 20 - + // Makes gamemodes respect player limits var/enable_gamemode_player_limit = 0 @@ -354,6 +356,9 @@ if("forum_link_url") config.forum_link_url = value + if("forum_playerinfo_url") + config.forum_playerinfo_url = value + if("log_ooc") config.log_ooc = 1 @@ -483,6 +488,9 @@ if("discordurl") config.discordurl = value + if("discordforumurl") + config.discordforumurl = value + if("donationsurl") config.donationsurl = value @@ -777,7 +785,7 @@ if(BombCap > 128) BombCap = 128 - MAX_EX_DEVESTATION_RANGE = round(BombCap/4) + MAX_EX_DEVASTATION_RANGE = round(BombCap/4) MAX_EX_HEAVY_RANGE = round(BombCap/2) MAX_EX_LIGHT_RANGE = BombCap MAX_EX_FLASH_RANGE = BombCap diff --git a/code/controllers/subsystem/chat.dm b/code/controllers/subsystem/chat.dm index a90e14d0ab4..d2f87c93e06 100644 --- a/code/controllers/subsystem/chat.dm +++ b/code/controllers/subsystem/chat.dm @@ -11,7 +11,8 @@ SUBSYSTEM_DEF(chat) /datum/controller/subsystem/chat/fire() for(var/i in payload) var/client/C = i - C << output(payload[C], "browseroutput:output") + if(C) + C << output(payload[C], "browseroutput:output") payload -= C if(MC_TICK_CHECK) diff --git a/code/controllers/subsystem/idlenpcpool.dm b/code/controllers/subsystem/idlenpcpool.dm index 2dad0abca0f..3757237243f 100644 --- a/code/controllers/subsystem/idlenpcpool.dm +++ b/code/controllers/subsystem/idlenpcpool.dm @@ -29,6 +29,7 @@ SUBSYSTEM_DEF(idlenpcpool) var/mob/living/simple_animal/SA = currentrun[currentrun.len] --currentrun.len if(!SA) + log_debug("idlenpcpool encountered an invalid entry, resumed: [resumed], SA [SA], type of SA [SA?.type], null [SA == null], qdelled [QDELETED(SA)], SA in AI_IDLE list: [SA in GLOB.simple_animals[AI_IDLE]]") GLOB.simple_animals[AI_IDLE] -= SA continue diff --git a/code/controllers/subsystem/jobs.dm b/code/controllers/subsystem/jobs.dm index 166083b36ff..d7e7a3cc33e 100644 --- a/code/controllers/subsystem/jobs.dm +++ b/code/controllers/subsystem/jobs.dm @@ -421,25 +421,25 @@ SUBSYSTEM_DEF(jobs) to_chat(H, "You are the [alt_title ? alt_title : rank].") to_chat(H, "As the [alt_title ? alt_title : rank] you answer directly to [job.supervisors]. Special circumstances may change this.") - to_chat(H, "For more information on how the station works, see Standard Operating Procedure (SOP)") + to_chat(H, "For more information on how the station works, see Standard Operating Procedure (SOP)") if(job.is_service) - to_chat(H, "As a member of Service, make sure to read up on your Department SOP") + to_chat(H, "As a member of Service, make sure to read up on your Department SOP") if(job.is_supply) - to_chat(H, "As a member of Supply, make sure to read up on your Department SOP") + to_chat(H, "As a member of Supply, make sure to read up on your Department SOP") if(job.is_command) - to_chat(H, "As an important member of Command, read up on your Department SOP") + to_chat(H, "As an important member of Command, read up on your Department SOP") if(job.is_legal) - to_chat(H, "Your job requires complete knowledge of Space Law and Legal Standard Operating Procedure") + to_chat(H, "Your job requires complete knowledge of Space Law and Legal Standard Operating Procedure") if(job.is_engineering) - to_chat(H, "As a member of Engineering, make sure to read up on your Department SOP") + to_chat(H, "As a member of Engineering, make sure to read up on your Department SOP") if(job.is_medical) - to_chat(H, "As a member of Medbay, make sure to read up on your Department SOP") + to_chat(H, "As a member of Medbay, make sure to read up on your Department SOP") if(job.is_science) - to_chat(H, "As a member of Science, make sure to read up on your Department SOP") + to_chat(H, "As a member of Science, make sure to read up on your Department SOP") if(job.is_security) - to_chat(H, "As a member of Security, you are to know Space Law, Legal Standard Operating Procedure, as well as your Department SOP") + to_chat(H, "As a member of Security, you are to know Space Law, Legal Standard Operating Procedure, as well as your Department SOP") if(job.req_admin_notify) - to_chat(H, "You are playing a job that is important for the game progression. If you have to disconnect, please notify the admins via adminhelp.") + to_chat(H, "You are playing a job that is important for the game progression. If you have to disconnect, please go to cryo and inform command. If you are unable to do so, please notify the admins via adminhelp.") return H /datum/controller/subsystem/jobs/proc/EquipRank(mob/living/carbon/human/H, rank, joined_late = 0) // Equip and put them in an area @@ -690,4 +690,4 @@ SUBSYSTEM_DEF(jobs) .++ new_id_change_records["[id_change_counter]"] = thisrecord id_change_counter++ - id_change_records = new_id_change_records \ No newline at end of file + id_change_records = new_id_change_records diff --git a/code/controllers/subsystem/npcpool.dm b/code/controllers/subsystem/npcpool.dm index 0de306b12eb..f2e159404fd 100644 --- a/code/controllers/subsystem/npcpool.dm +++ b/code/controllers/subsystem/npcpool.dm @@ -21,6 +21,10 @@ SUBSYSTEM_DEF(npcpool) while(currentrun.len) var/mob/living/simple_animal/SA = currentrun[currentrun.len] --currentrun.len + if(!SA) + log_debug("npcpool encountered an invalid entry, resumed: [resumed], SA [SA], type of SA [SA?.type], null [SA == null], qdelled [QDELETED(SA)], SA in AI_ON list: [SA in GLOB.simple_animals[AI_ON]]") + GLOB.simple_animals[AI_ON] -= SA + continue if(!SA.ckey && !SA.notransform) if(SA.stat != DEAD) diff --git a/code/controllers/subsystem/tickets/tickets.dm b/code/controllers/subsystem/tickets/tickets.dm index 24be623573e..058569250ec 100644 --- a/code/controllers/subsystem/tickets/tickets.dm +++ b/code/controllers/subsystem/tickets/tickets.dm @@ -23,7 +23,7 @@ SUBSYSTEM_DEF(tickets) flags = SS_BACKGROUND - var/list/allTickets + var/list/allTickets = list() //make it here because someone might ahelp before the system has initialized var/ticketCounter = 1 @@ -31,7 +31,6 @@ SUBSYSTEM_DEF(tickets) close_messages = list("- [ticket_name] Rejected! -", "Please try to be calm, clear, and descriptive in admin helps, do not assume the staff member has seen any related events, and clearly state the names of anybody you are reporting. If you asked a question, please ensure it was clear what you were asking.", "Your [ticket_name] has now been closed.") - LAZYINITLIST(allTickets) return ..() /datum/controller/subsystem/tickets/fire() diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 27d499254a1..eca632b7b95 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -52,7 +52,7 @@ SUBSYSTEM_DEF(vote) voting.Cut() current_votes.Cut() - if(auto_muted && !config.ooc_allowed) + if(auto_muted && !config.ooc_allowed && !(config.auto_toggle_ooc_during_round && SSticker.current_state == GAME_STATE_PLAYING)) auto_muted = 0 config.ooc_allowed = !( config.ooc_allowed ) to_chat(world, "The OOC channel has been automatically enabled due to vote end.") diff --git a/code/datums/components/squeak.dm b/code/datums/components/squeak.dm index e5b948f4f26..aca505e6a03 100644 --- a/code/datums/components/squeak.dm +++ b/code/datums/components/squeak.dm @@ -41,6 +41,10 @@ use_delay = use_delay_override /datum/component/squeak/proc/play_squeak() + if(ismob(parent)) + var/mob/M = parent + if(M.stat == DEAD) + return if(prob(squeak_chance)) if(!override_squeak_sounds) playsound(parent, pickweight(default_squeak_sounds), volume, 1, -1) diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index a41e58fa28c..daa50119135 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -548,7 +548,7 @@ to_chat(usr, "This can only be used on instances of type /mob") return - var/new_name = reject_bad_name(sanitize(copytext(input(usr,"What would you like to name this mob?","Input a name",M.real_name) as text|null,1,MAX_NAME_LEN))) + var/new_name = reject_bad_name(sanitize(copytext(input(usr, "What would you like to name this mob?", "Input a name", M.real_name) as text|null, 1, MAX_NAME_LEN)), allow_numbers = TRUE) if( !new_name || !M ) return message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].") diff --git a/code/datums/helper_datums/construction_datum.dm b/code/datums/helper_datums/construction_datum.dm index 8cc1bdc27d8..f73607a2a4e 100644 --- a/code/datums/helper_datums/construction_datum.dm +++ b/code/datums/helper_datums/construction_datum.dm @@ -1,5 +1,6 @@ #define FORWARD -1 #define BACKWARD 1 +#define CONSTRUCTION_TOOL_BEHAVIOURS list(TOOL_CROWBAR, TOOL_SCREWDRIVER, TOOL_WELDER, TOOL_WRENCH) /datum/construction var/list/steps @@ -38,30 +39,13 @@ /datum/construction/proc/is_right_key(atom/used_atom) // returns current step num if used_atom is of the right type. var/list/L = steps[steps.len] - if(istype(used_atom, L["key"])) + if(do_tool_or_atom_check(used_atom, L["key"])) return steps.len return 0 + /datum/construction/proc/custom_action(step, used_atom, user) - if(istype(used_atom, /obj/item/weldingtool)) - var/obj/item/weldingtool/W = used_atom - if(W.remove_fuel(0, user)) - playsound(holder, W.usesound, 50, 1) - else - return 0 - else if(istype(used_atom, /obj/item/wrench)) - var/obj/item/wrench/W = used_atom - playsound(holder, W.usesound, 50, 1) - - else if(istype(used_atom, /obj/item/screwdriver)) - var/obj/item/screwdriver/S = used_atom - playsound(holder, S.usesound, 50, 1) - - else if(istype(used_atom, /obj/item/wirecutters)) - var/obj/item/wirecutters/W = used_atom - playsound(holder, W.usesound, 50, 1) - - else if(istype(used_atom, /obj/item/stack/cable_coil)) + if(istype(used_atom, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C = used_atom if(C.amount<4) to_chat(user, ("There's not enough cable to finish the task.")) @@ -76,18 +60,22 @@ return 0 else S.use(5) + else if(isitem(used_atom)) + var/obj/item/I = used_atom + if(I.tool_behaviour in CONSTRUCTION_TOOL_BEHAVIOURS) + if(!I.use_tool(holder, user, 0, volume = I.tool_volume)) + return 0 return 1 /datum/construction/proc/check_all_steps(atom/used_atom,mob/user as mob) //check all steps, remove matching one. for(var/i=1;i<=steps.len;i++) var/list/L = steps[i]; - if(istype(used_atom, L["key"])) - if(custom_action(i, used_atom, user)) - steps[i]=null;//stupid byond list from list removal... - listclearnulls(steps); - if(!steps.len) - spawn_result(user) - return 1 + if(do_tool_or_atom_check(used_atom, L["key"]) && custom_action(i, used_atom, user)) + steps[i]=null;//stupid byond list from list removal... + listclearnulls(steps); + if(!steps.len) + spawn_result(user) + return 1 return 0 @@ -116,15 +104,12 @@ if(!coil.use(amount)) to_chat(user, "You don't have enough cable! You need at least [amount] coils.") return 0 - // WELDER - if(istype(used_atom,/obj/item/weldingtool)) - var/obj/item/weldingtool/welder=used_atom - if(!welder.isOn()) - to_chat(user, "You tap the [src] with your unlit welder. [pick("Ding","Dong")].") - return 0 - if(!welder.remove_fuel(amount,user)) - to_chat(user, "You don't have enough fuel!") - return 0 + // TOOLS + if(isitem(used_atom)) + var/obj/item/I = used_atom + if(I.tool_behaviour in CONSTRUCTION_TOOL_BEHAVIOURS) + if(!I.use(amount)) + return 0 // STACKS if(istype(used_atom,/obj/item/stack)) var/obj/item/stack/stack=used_atom @@ -134,6 +119,14 @@ stack.use(amount) return 1 +/datum/construction/proc/do_tool_or_atom_check(used_atom, thing_to_check) //Checks if an atom is either a required thing; or if it's a required tool + if(istype(used_atom, thing_to_check)) + return TRUE + else if(isitem(used_atom)) + var/obj/item/I = used_atom + if(I.tool_behaviour == thing_to_check) + return TRUE + /datum/construction/reversible var/index @@ -152,9 +145,9 @@ /datum/construction/reversible/is_right_key(atom/used_atom) // returns index step var/list/L = steps[index] - if(istype(used_atom, L["key"])) + if(do_tool_or_atom_check(used_atom, L["key"])) return FORWARD //to the first step -> forward - else if(L["backkey"] && istype(used_atom, L["backkey"])) + else if(L["backkey"] && do_tool_or_atom_check(used_atom, L["backkey"])) return BACKWARD //to the last step -> backwards return 0 @@ -198,13 +191,13 @@ var/list/state = steps[index] if(state_next in state) var/list/step = state[state_next] - if(istype(used_atom, step["key"])) + if(do_tool_or_atom_check(used_atom, step["key"])) //if(L["consume"] && !try_consume(used_atom,L["consume"])) // return 0 return FORWARD //to the first step -> forward else if(state_prev in state) var/list/step = state[state_prev] - if(istype(used_atom, step["key"])) + if(do_tool_or_atom_check(used_atom, step["key"])) //if(L["consume"] && !try_consume(used_atom,L["consume"])) // return 0 return BACKWARD //to the first step -> forward diff --git a/code/datums/mind.dm b/code/datums/mind.dm index dd1a88b8b36..036d70fa17a 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -225,9 +225,7 @@ /datum/mind/proc/memory_edit_cult(mob/living/carbon/human/H) . = _memory_edit_header("cult") - if(ismindshielded(H)) - . += "NO|cultist" - else if(src in SSticker.mode.cult) + if(src in SSticker.mode.cult) . += "no|CULTIST" . += "
Give tome|equip." else diff --git a/code/datums/spells/area_teleport.dm b/code/datums/spells/area_teleport.dm index 2f07f106d2a..4aa7eafbed6 100644 --- a/code/datums/spells/area_teleport.dm +++ b/code/datums/spells/area_teleport.dm @@ -25,10 +25,13 @@ var/A = null if(!randomise_selection) - A = input("Area to teleport to", "Teleport", A) in teleportlocs + A = input("Area to teleport to", "Teleport", A) as null|anything in teleportlocs else A = pick(teleportlocs) + if(!A) + return + var/area/thearea = teleportlocs[A] if(thearea.tele_proof && !istype(thearea, /area/wizard_station)) diff --git a/code/datums/spells/cluwne.dm b/code/datums/spells/cluwne.dm index 6a87419886c..58a33e31a44 100644 --- a/code/datums/spells/cluwne.dm +++ b/code/datums/spells/cluwne.dm @@ -17,7 +17,7 @@ var/obj/item/organ/internal/brain/cluwne/idiot_brain = new idiot_brain.insert(src, make_cluwne = 0) idiot_brain.dna = dna.Clone() - setBrainLoss(80) + setBrainLoss(80, use_brain_mod = FALSE) set_nutrition(9000) overeatduration = 9000 Confused(30) diff --git a/code/datums/spells/summonitem.dm b/code/datums/spells/summonitem.dm index 8dbaf5afa77..aaef2229856 100644 --- a/code/datums/spells/summonitem.dm +++ b/code/datums/spells/summonitem.dm @@ -52,73 +52,71 @@ marked_item = null else //Getting previously marked item - var/obj/item_to_retrive = marked_item + var/obj/item_to_retrieve = marked_item var/infinite_recursion = 0 //I don't want to know how someone could put something inside itself but these are wizards so let's be safe - while(!isturf(item_to_retrive.loc) && infinite_recursion < 10) //if it's in something you get the whole thing. - if(ismob(item_to_retrive.loc)) //If its on someone, properly drop it - var/mob/M = item_to_retrive.loc + while(!isturf(item_to_retrieve.loc) && infinite_recursion < 10) //if it's in something you get the whole thing. + if(ismob(item_to_retrieve.loc)) //If its on someone, properly drop it + var/mob/M = item_to_retrieve.loc - if(issilicon(M)) //Items in silicons warp the whole silicon - M.loc.visible_message("[M] suddenly disappears!") - M.loc = target.loc + if(issilicon(M) || !M.unEquip(item_to_retrieve)) //Items in silicons warp the whole silicon + M.visible_message("[M] suddenly disappears!", "A force suddenly pulls you away!") + M.forceMove(target.loc) M.loc.visible_message("[M] suddenly appears!") - item_to_retrive = null + item_to_retrieve = null break - M.unEquip(item_to_retrive) - if(ishuman(M)) //Edge case housekeeping var/mob/living/carbon/human/C = M - /*if(C.internal_bodyparts_by_name && item_to_retrive in C.internal_bodyparts_by_name ) //This won't work, as we use organ datums instead of objects. --DZD - C.internal_bodyparts_by_name -= item_to_retrive + /*if(C.internal_bodyparts_by_name && item_to_retrieve in C.internal_bodyparts_by_name ) //This won't work, as we use organ datums instead of objects. --DZD + C.internal_bodyparts_by_name -= item_to_retrieve if(istype(marked_item, /obj/item/brain)) //If this code ever runs I will be happy var/obj/item/brain/B = new /obj/item/brain(target.loc) B.transfer_identity(C) C.death() add_attack_logs(target, C, "Magically debrained INTENT: [uppertext(target.a_intent)]")*/ - if(C.stomach_contents && item_to_retrive in C.stomach_contents) - C.stomach_contents -= item_to_retrive + if(C.stomach_contents && item_to_retrieve in C.stomach_contents) + C.stomach_contents -= item_to_retrieve for(var/X in C.bodyparts) var/obj/item/organ/external/part = X - if(item_to_retrive in part.embedded_objects) - part.embedded_objects -= item_to_retrive - to_chat(C, "The [item_to_retrive] that was embedded in your [part] has mysteriously vanished. How fortunate!") + if(item_to_retrieve in part.embedded_objects) + part.embedded_objects -= item_to_retrieve + to_chat(C, "The [item_to_retrieve] that was embedded in your [part] has mysteriously vanished. How fortunate!") if(!C.has_embedded_objects()) C.clear_alert("embeddedobject") break else - if(istype(item_to_retrive.loc,/obj/machinery/portable_atmospherics/)) //Edge cases for moved machinery - var/obj/machinery/portable_atmospherics/P = item_to_retrive.loc + if(istype(item_to_retrieve.loc,/obj/machinery/portable_atmospherics/)) //Edge cases for moved machinery + var/obj/machinery/portable_atmospherics/P = item_to_retrieve.loc P.disconnect() P.update_icon() - if(istype(item_to_retrive.loc, /obj/structure/disposalholder) || istype(item_to_retrive.loc, /obj/machinery/disposal))//fixes the breaking of disposals. No more bluespace connected disposal bins! + if(istype(item_to_retrieve.loc, /obj/structure/disposalholder) || istype(item_to_retrieve.loc, /obj/machinery/disposal))//fixes the breaking of disposals. No more bluespace connected disposal bins! break - item_to_retrive = item_to_retrive.loc + item_to_retrieve = item_to_retrieve.loc infinite_recursion += 1 - if(!item_to_retrive) + if(!item_to_retrieve) return - item_to_retrive.loc.visible_message("The [item_to_retrive.name] suddenly disappears!") + item_to_retrieve.loc.visible_message("The [item_to_retrieve.name] suddenly disappears!") if(target.hand) //left active hand - if(!target.equip_to_slot_if_possible(item_to_retrive, slot_l_hand, 0, 1, 1)) - if(!target.equip_to_slot_if_possible(item_to_retrive, slot_r_hand, 0, 1, 1)) + if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_l_hand, 0, 1, 1)) + if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_r_hand, 0, 1, 1)) butterfingers = 1 else //right active hand - if(!target.equip_to_slot_if_possible(item_to_retrive, slot_r_hand, 0, 1, 1)) - if(!target.equip_to_slot_if_possible(item_to_retrive, slot_l_hand, 0, 1, 1)) + if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_r_hand, 0, 1, 1)) + if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_l_hand, 0, 1, 1)) butterfingers = 1 if(butterfingers) - item_to_retrive.loc = target.loc - item_to_retrive.loc.visible_message("The [item_to_retrive.name] suddenly appears!") + item_to_retrieve.loc = target.loc + item_to_retrieve.loc.visible_message("The [item_to_retrieve.name] suddenly appears!") playsound(get_turf(target),'sound/magic/summonitems_generic.ogg',50,1) else - item_to_retrive.loc.visible_message("The [item_to_retrive.name] suddenly appears in [target]'s hand!") + item_to_retrieve.loc.visible_message("The [item_to_retrieve.name] suddenly appears in [target]'s hand!") playsound(get_turf(target),'sound/magic/summonitems_generic.ogg',50,1) if(message) diff --git a/code/datums/wires/alarm.dm b/code/datums/wires/alarm.dm index f412e96b5ee..daf8a0dcd48 100644 --- a/code/datums/wires/alarm.dm +++ b/code/datums/wires/alarm.dm @@ -54,8 +54,7 @@ var/const/AALARM_WIRE_AALARM = 16 // to_chat(world, "Power wire cut") if(AALARM_WIRE_AI_CONTROL) - if(A.aidisabled == !mended) - A.aidisabled = mended + A.aidisabled = !mended // to_chat(world, "AI Control Wire Cut") if(AALARM_WIRE_SYPHON) diff --git a/code/datums/wires/wires.dm b/code/datums/wires/wires.dm index 5220fd83a6d..a201617682d 100644 --- a/code/datums/wires/wires.dm +++ b/code/datums/wires/wires.dm @@ -5,12 +5,6 @@ #define MAX_FLAG 65535 -/proc/is_wire_tool(obj/item/I) - if(ismultitool(I)) - return TRUE - if(iswirecutter(I)) - return TRUE - var/list/same_wires = list() // 12 colours, if you're adding more than 12 wires then add more colours here var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown", "gold", "gray", "cyan", "navy", "purple", "pink") diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 8a19fb14d9c..cd7e1e45015 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -332,6 +332,47 @@ if(reagents) reagents.temperature_reagents(exposed_temperature) +/atom/proc/tool_act(mob/living/user, obj/item/I, tool_type) + switch(tool_type) + if(TOOL_CROWBAR) + return crowbar_act(user, I) + if(TOOL_MULTITOOL) + return multitool_act(user, I) + if(TOOL_SCREWDRIVER) + return screwdriver_act(user, I) + if(TOOL_WRENCH) + return wrench_act(user, I) + if(TOOL_WIRECUTTER) + return wirecutter_act(user, I) + if(TOOL_WELDER) + return welder_act(user, I) + + +// Tool-specific behavior procs. To be overridden in subtypes. +/atom/proc/crowbar_act(mob/living/user, obj/item/I) + return + +/atom/proc/multitool_act(mob/living/user, obj/item/I) + return + +//Check if the multitool has an item in its data buffer +/atom/proc/multitool_check_buffer(user, silent = FALSE) + if(!silent) + to_chat(user, "[src] has no data buffer!") + return FALSE + +/atom/proc/screwdriver_act(mob/living/user, obj/item/I) + return + +/atom/proc/wrench_act(mob/living/user, obj/item/I) + return + +/atom/proc/wirecutter_act(mob/living/user, obj/item/I) + return + +/atom/proc/welder_act(mob/living/user, obj/item/I) + return + /atom/proc/emag_act() return diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index cf7f931ff32..2fb8796dc10 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -220,6 +220,7 @@ // This is automatically called when something enters your square /atom/movable/Crossed(atom/movable/AM, oldloc) SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM) + SEND_SIGNAL(AM, COMSIG_CROSSED_MOVABLE, src) /atom/movable/Bump(atom/A, yes) //the "yes" arg is to differentiate our Bump proc from byond's, without it every Bump() call would become a double Bump(). if(A && yes) diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index 32ab33fc983..de42b5b253f 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -205,21 +205,8 @@ user.stop_pulling() /obj/machinery/dna_scannernew/attackby(var/obj/item/item as obj, var/mob/user as mob, params) - if(istype(item, /obj/item/screwdriver)) - if(occupant) - to_chat(user, "The maintenance panel is locked.") - return - default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]", item) - return if(exchange_parts(user, item)) return - - if(istype(item, /obj/item/crowbar)) - if(panel_open) - for(var/obj/I in contents) // in case there is something in the scanner - I.forceMove(src.loc) - default_deconstruction_crowbar(item) - return else if(istype(item, /obj/item/reagent_containers/glass)) if(beaker) to_chat(user, "A beaker is already loaded into the machine.") @@ -255,6 +242,18 @@ return return ..() +/obj/machinery/dna_scannernew/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I)) + for(var/obj/thing in contents) // in case there is something in the scanner + thing.forceMove(src.loc) + +/obj/machinery/dna_scannernew/screwdriver_act(mob/user, obj/item/I) + if(occupant) + to_chat(user, "The maintenance panel is locked.") + return TRUE + if(default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]", I)) + return TRUE + /obj/machinery/dna_scannernew/relaymove(mob/user as mob) if(user.incapacitated()) return 0 //maybe they should be able to get out with cuffs, but whatever diff --git a/code/game/gamemodes/autotraitor/autotraitor.dm b/code/game/gamemodes/autotraitor/autotraitor.dm index cc0cc307ed5..6c89ab45434 100644 --- a/code/game/gamemodes/autotraitor/autotraitor.dm +++ b/code/game/gamemodes/autotraitor/autotraitor.dm @@ -52,7 +52,7 @@ if(!traitor || !istype(traitor)) pre_traitors.Remove(traitor) continue - if(istype(traitor)) + if(istype(traitor)) traitor.special_role = SPECIAL_ROLE_TRAITOR traitor.restricted_roles = restricted_jobs diff --git a/code/game/gamemodes/blob/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm index e1cef880e0a..cc7203d9c40 100644 --- a/code/game/gamemodes/blob/blobs/blob_mobs.dm +++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm @@ -186,6 +186,7 @@ else adjustBruteLoss(0.2) // If you are at full health, you won't lose health. You'll need it. However the moment anybody sneezes on you, the decaying will begin. adjustFireLoss(0.2) + ..() /mob/living/simple_animal/hostile/blob/blobbernaut/New() ..() diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm index 140ead3a947..74ed59d2469 100644 --- a/code/game/gamemodes/blob/overmind.dm +++ b/code/game/gamemodes/blob/overmind.dm @@ -48,13 +48,14 @@ update_health_hud() /mob/camera/blob/update_health_hud() - if(blob_core) + if(blob_core && hud_used) hud_used.blobhealthdisplay.maptext = "
[round(blob_core.obj_integrity)]
" /mob/camera/blob/proc/add_points(var/points) if(points != 0) blob_points = Clamp(blob_points + points, 0, max_blob_points) - hud_used.blobpwrdisplay.maptext = "
[round(src.blob_points)]
" + if(hud_used) + hud_used.blobpwrdisplay.maptext = "
[round(src.blob_points)]
" /mob/camera/blob/say(var/message) if(!message) diff --git a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm index b0b77a456d5..4663fef8b97 100644 --- a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm +++ b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm @@ -40,7 +40,7 @@ name = "protective membranes" desc = "These variable transparency organic membranes will protect you from welders and flashes and heal your eye damage." icon_state = "ling_eyeshield" - eye_colour = null + eye_colour = "#000000" implant_overlay = null slot = "eye_ling" status = 0 @@ -61,7 +61,7 @@ name = "heat receptors" desc = "These heat receptors dramatically increases eyes light sensing ability." icon_state = "ling_thermal" - eye_colour = null + eye_colour = "#000000" implant_overlay = null slot = "eye_ling" status = 0 diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 1cc55d99f0c..39e3c5b7d3f 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -9,24 +9,28 @@ var/global/list/all_cults = list() /proc/is_convertable_to_cult(datum/mind/mind) if(!mind) - return 0 + return FALSE if(!mind.current) - return 0 + return FALSE if(iscultist(mind.current)) - return 1 //If they're already in the cult, assume they are convertable + return TRUE //If they're already in the cult, assume they are convertable if(ishuman(mind.current) && (mind.assigned_role in list("Captain", "Chaplain"))) - return 0 + return FALSE if(ishuman(mind.current)) var/mob/living/carbon/human/H = mind.current - if(ismindshielded(H)) - return 0 + if(ismindshielded(H)) //mindshield protects against conversions unless removed + return FALSE +// if(mind.offstation_role) cant convert offstation roles such as ghost spawns +// return FALSE Commented out until we can figure out why offstation_role is getting set to TRUE on normal crew if(issilicon(mind.current)) - return 0 //can't convert machines, that's ratvar's thing + return FALSE //can't convert machines, that's ratvar's thing if(isguardian(mind.current)) var/mob/living/simple_animal/hostile/guardian/G = mind.current if(!iscultist(G.summoner)) - return 0 //can't convert it unless the owner is converted - return 1 + return FALSE //can't convert it unless the owner is converted + if(isgolem(mind.current)) + return FALSE + return TRUE /proc/is_sacrifice_target(datum/mind/mind) if(SSticker.mode.name == "cult") @@ -178,7 +182,7 @@ var/global/list/all_cults = list() if(!istype(cult_mind)) return 0 var/datum/game_mode/cult/cult_mode = SSticker.mode - if(!(cult_mind in cult) && is_convertable_to_cult(cult_mind)) + if(!(cult_mind in cult)) cult += cult_mind cult_mind.current.faction |= "cult" var/datum/action/innate/cultcomm/C = new() diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index d30ac4f8a68..de8846d292e 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -198,7 +198,7 @@ var/list/blacklisted_pylon_turfs = typecacheof(list( if(last_heal <= world.time) last_heal = world.time + heal_delay for(var/mob/living/L in range(5, src)) - if(iscultist(L) || istype(L, /mob/living/simple_animal/shade) || istype(L, /mob/living/simple_animal/hostile/construct)) + if(iscultist(L) || iswizard(L) || istype(L, /mob/living/simple_animal/shade) || istype(L, /mob/living/simple_animal/hostile/construct)) if(L.health != L.maxHealth) new /obj/effect/temp_visual/heal(get_turf(src), "#960000") if(ishuman(L)) @@ -226,7 +226,7 @@ var/list/blacklisted_pylon_turfs = typecacheof(list( if(istype(T, /turf/simulated/floor)) T.ChangeTurf(/turf/simulated/floor/engine/cult) if(istype(T, /turf/simulated/wall)) - T.ChangeTurf(/turf/simulated/wall/cult) + T.ChangeTurf(/turf/simulated/wall/cult/artificer) else var/turf/simulated/floor/engine/cult/F = safepick(cultturfs) if(F) diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 2f2f0cae02e..d918bead0de 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -340,144 +340,100 @@ var/list/teleport_runes = list() fail_invoke() -//Rite of Enlightenment: Converts a normal crewmember to the cult. Faster for every cultist nearby. +//Rite of Offering: Converts a normal crewmember to the cult or sacrifices mindshielded and sacrifice targets. /obj/effect/rune/convert - cultist_name = "Rite of Enlightenment" - cultist_desc = "converts a normal crewmember on top of it to the cult. Does not work on mindshielded crew." + cultist_name = "Rite of Offering" + cultist_desc = "Offers a non-cultists on top of it to your deity, either converting or sacrificing them." invocation = "Mah'weyh pleggh at e'ntrath!" icon_state = "3" - req_cultists = 2 - + req_cultists = 1 + allow_excess_invokers = TRUE + rune_in_use = FALSE + /obj/effect/rune/convert/do_invoke_glow() return /obj/effect/rune/convert/invoke(var/list/invokers) - var/list/convertees = list() - var/turf/T = get_turf(src) - - for(var/mob/living/M in T.contents) - if(!iscultist(M) && !ismindshielded(M) && !isgolem(M) && ishuman(M)) - convertees.Add(M) - if(!convertees.len) - fail_invoke() - log_game("Convert rune failed - no eligible convertees") - return - var/mob/living/new_cultist = pick(convertees) - if(!is_convertable_to_cult(new_cultist.mind) || new_cultist.null_rod_check()) - for(var/M in invokers) - to_chat(M, "Something is shielding [new_cultist]'s mind!") - if(is_sacrifice_target(new_cultist.mind)) - to_chat(M, "\"I desire this one for myself. SACRIFICE THEM!\"") - fail_invoke() - log_game("Convert rune failed - convertee could not be converted") - return - ..() - - new_cultist.visible_message("[new_cultist] writhes in pain as the markings below them glow a bloody red!", \ - "AAAAAAAAAAAAAA-") - SSticker.mode.add_cultist(new_cultist.mind, 1) - new /obj/item/tome(get_turf(src)) - new_cultist.mind.special_role = "Cultist" - to_chat(new_cultist, "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \ - and something evil takes root.") - to_chat(new_cultist, "Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve [SSticker.cultdat.entity_title3] above all else. Bring it back.\ - ") - -//Rite of Tribute: Sacrifices a crew member to Nar-Sie. Places them into a soul shard if they're in their body. -/obj/effect/rune/sacrifice - cultist_name = "Rite of Tribute" - cultist_desc = "sacrifices a crew member to your god. May place them into a soul shard if their spirit remains in their body." - icon_state = "3" - allow_excess_invokers = 1 - invocation = "Barhah hra zar'garis!" - rune_in_use = 0 - -/obj/effect/rune/sacrifice/New() - ..() - cultist_desc = "sacrifices a crew member to [SSticker.cultdat.entity_title3]. May place them into a soul shard if their spirit remains in their body." - -/obj/effect/rune/sacrifice/invoke(var/list/invokers) if(rune_in_use) return - rune_in_use = 1 - var/mob/living/user = invokers[1] //the first invoker is always the user + var/list/myriad_targets = list() var/turf/T = get_turf(src) - var/list/possible_targets = list() - for(var/mob/living/M in T.contents) - if(M.mind) - if(M.mind in sacrificed) - continue + for(var/mob/living/M in T) if(!iscultist(M)) - possible_targets.Add(M) - var/mob/offering - if(possible_targets.len > 1) //If there's more than one target, allow choice - offering = input(user, "Choose an offering to sacrifice.", "Unholy Tribute") as null|anything in possible_targets - if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated()) - return - else if(possible_targets.len) //Otherwise, if there's a target at all, pick the only one - offering = possible_targets[possible_targets.len] - if(!offering) - rune_in_use = 0 + myriad_targets |= M + if(!myriad_targets.len) + fail_invoke() + log_game("Offer rune failed - no eligible targets") + rune_in_use = FALSE return + + rune_in_use = TRUE + var/mob/living/new_cultist = pick(myriad_targets) + if(is_convertable_to_cult(new_cultist.mind) && !new_cultist.null_rod_check() && !is_sacrifice_target(new_cultist.mind) && new_cultist.stat != DEAD && new_cultist.client != null) + invocation = "Mah'weyh pleggh at e'ntrath!" + ..() + do_convert(new_cultist, invokers) + else + invocation = "Barhah hra zar'garis!" + ..() + do_sacrifice(new_cultist, invokers) + rune_in_use = FALSE + +/obj/effect/rune/convert/proc/do_convert(mob/living/convertee, list/invokers) + if(invokers.len < 2) + fail_invoke() + for(var/I in invokers) + to_chat(I, "You need at least two invokers to convert!") + return + else + convertee.visible_message("[convertee] writhes in pain as the markings below them glow a bloody red!", \ + "AAAAAAAAAAAAAA-") + SSticker.mode.add_cultist(convertee.mind, 1) + new /obj/item/tome(get_turf(src)) + convertee.mind.special_role = "Cultist" + to_chat(convertee, "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \ + and something evil takes root.") + to_chat(convertee, "Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve [SSticker.cultdat.entity_title3] above all else. Bring it back.\ + ") + return + +/obj/effect/rune/convert/proc/do_sacrifice(mob/living/offering, list/invokers) + var/mob/living/user = invokers[1] //the first invoker is always the user if(((ishuman(offering) || isrobot(offering)) && offering.stat != DEAD) || is_sacrifice_target(offering.mind)) //Requires three people to sacrifice living targets if(invokers.len < 3) for(var/M in invokers) to_chat(M, "[offering] is too greatly linked to the world! You need three acolytes!") fail_invoke() log_game("Sacrifice rune failed - not enough acolytes and target is living") - rune_in_use = 0 return - visible_message("[src] pulses blood red!") - color = rgb(126, 23, 23) - ..() - sac(invokers, offering) - color = initial(color) -/obj/effect/rune/sacrifice/proc/sac(var/list/invokers, mob/living/T) var/sacrifice_fulfilled var/datum/game_mode/cult/cult_mode = SSticker.mode - if(T) - if(isdog(T)) // Doggos are the best, but not cats - for(var/M in invokers) - var/mob/living/L = M - to_chat(L, "\"Even I have standards, such as they are!\"") - if(L.reagents) - L.reagents.add_reagent("hell_water", 2) - if(T.mind) - sacrificed.Add(T.mind) - if(is_sacrifice_target(T.mind)) - sacrifice_fulfilled = 1 - new /obj/effect/temp_visual/cult/sac(loc) - if(SSticker && SSticker.mode && SSticker.mode.name == "cult") - - cult_mode.harvested++ - for(var/M in invokers) - if(sacrifice_fulfilled) - to_chat(M, "\"Yes! This is the one I desire! You have done well.\"") - cult_mode.additional_phase() - else - if(ishuman(T) || isrobot(T)) - to_chat(M, "\"I accept this sacrifice.\"") - else - to_chat(M, "\"I accept this meager sacrifice.\"") - if(T.mind) - var/obj/item/soulstone/stone = new /obj/item/soulstone(get_turf(src)) - stone.invisibility = INVISIBILITY_MAXIMUM //so it's not picked up during transfer_soul() - if(!stone.transfer_soul("VICTIM", T, usr)) //If it cannot be added - qdel(stone) - if(stone) - stone.invisibility = 0 - if(!T) - rune_in_use = 0 - return - if(isrobot(T)) - playsound(T, 'sound/effects/EMPulse.ogg', 100, 1) - T.dust() //To prevent the MMI from remaining + if(offering.mind) + sacrificed.Add(offering.mind) + if(is_sacrifice_target(offering.mind)) + sacrifice_fulfilled = TRUE + new /obj/effect/temp_visual/cult/sac(loc) + if(SSticker && SSticker.mode && SSticker.mode.name == "cult") + cult_mode.harvested++ + for(var/M in invokers) + if(sacrifice_fulfilled) + to_chat(M, "\"Yes! This is the one I desire! You have done well.\"") + cult_mode.additional_phase() else - playsound(T, 'sound/magic/disintegrate.ogg', 100, 1) - T.gib() - rune_in_use = 0 + if(ishuman(offering) || isrobot(offering)) + to_chat(M, "\"I accept this sacrifice.\"") + else + to_chat(M, "\"I accept this meager sacrifice.\"") + playsound(offering, 'sound/misc/demon_consume.ogg', 100, 1) + if((ishuman(offering) || isrobot(offering)) && offering.client_mobs_in_contents?.len) + var/obj/item/soulstone/stone = new /obj/item/soulstone(get_turf(src)) + stone.invisibility = INVISIBILITY_MAXIMUM //so it's not picked up during transfer_soul() + stone.transfer_soul("FORCE", offering, user) //If it cannot be added + stone.invisibility = 0 + else + offering.dust() //Ritual of Dimensional Rending: Calls forth the avatar of Nar-Sie upon the station. /obj/effect/rune/narsie @@ -707,6 +663,7 @@ var/list/teleport_runes = list() /obj/effect/rune/raise_dead/fail_invoke() ..() + rune_in_use = FALSE for(var/mob/living/M in range(1,src)) if(M.stat == DEAD) M.visible_message("[M] twitches.") diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index eb54b52c225..70e0e3258eb 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -244,6 +244,7 @@ anchored = 1 density = 1 atom_say_verb = "blares" + speed_process = TRUE // Disgusting fix. Please remove once #12952 is merged var/timing = 0 var/default_timer = 4500 var/detonation_timer diff --git a/code/game/gamemodes/miniantags/abduction/abduction.dm b/code/game/gamemodes/miniantags/abduction/abduction.dm index 908eaa5360f..bcbc86d991b 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction.dm @@ -184,7 +184,7 @@ var/obj/machinery/abductor/console/con = get_team_console(team_number) var/datum/objective/objective = team_objectives[team_number] if(con.experiment.points >= objective.target_amount) - SSshuttle.emergency.request(null, 0.5) + SSshuttle.emergency.request(null, 0.5, reason = "Large amount of abnormal thought patterns detected. All crew are recalled for mandatory evaluation and reconditioning.") SSshuttle.emergency.canRecall = FALSE finished = 1 return ..() @@ -208,12 +208,14 @@ text += "
The abductors were:
" for(var/datum/mind/abductor_mind in abductors) text += printplayer(abductor_mind) + text += "
" text += printobjectives(abductor_mind) text += "
" if(abductees.len) text += "
The abductees were:
" for(var/datum/mind/abductee_mind in abductees) text += printplayer(abductee_mind) + text += "
" text += printobjectives(abductee_mind) text += "
" to_chat(world, text) diff --git a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm index 962da01b74d..c27b230b3b2 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm @@ -587,10 +587,8 @@ Congratulations! You are now trained for invasive xenobiology research!"} ..() make_syndie() -/obj/item/radio/headset/abductor/attackby(obj/item/I, mob/user, params) - if(isscrewdriver(I)) - return // Stops humans from disassembling abductor headsets. - return ..() +/obj/item/radio/headset/abductor/screwdriver_act() + return// Stops humans from disassembling abductor headsets. /obj/item/scalpel/alien name = "alien scalpel" @@ -683,15 +681,6 @@ Congratulations! You are now trained for invasive xenobiology research!"} density = TRUE /obj/structure/table_frame/abductor/attackby(obj/item/I, mob/user, params) - if(iswrench(I)) - to_chat(user, "You start disassembling [src]...") - playsound(loc, I.usesound, 50, 1) - if(do_after(user, 30*I.toolspeed, target = src)) - playsound(loc, 'sound/items/deconstruct.ogg', 50, 1) - for(var/i = 1, i <= framestackamount, i++) - new framestack(get_turf(src)) - qdel(src) - return if(istype(I, /obj/item/stack/sheet/mineral/abductor)) var/obj/item/stack/sheet/P = I if(P.get_amount() < 1) diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm index 63905bc3390..e764f97a46a 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm @@ -41,15 +41,17 @@ return to_chat(user, "Picking up the swarmer may cause it to activate. You should be careful about this.") -/obj/effect/mob_spawn/swarmer/attackby(obj/item/I, mob/user, params) - if(isscrewdriver(I) && user.a_intent != INTENT_HARM) - user.visible_message("[usr.name] deactivates [src].", - "After some fiddling, you find a way to disable [src]'s power source.", - "You hear clicking.") - new /obj/item/deactivated_swarmer(get_turf(src)) - qdel(src) - else - return ..() +/obj/effect/mob_spawn/swarmer/screwdriver_act(mob/user, obj/item/I) + if(user.a_intent == INTENT_HARM) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + user.visible_message("[usr.name] deactivates [src].", + "After some fiddling, you find a way to disable [src]'s power source.", + "You hear clicking.") + new /obj/item/deactivated_swarmer(get_turf(src)) + qdel(src) ////The Mob itself//// diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm index b761af6db92..f86f018757e 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant.dm @@ -162,7 +162,7 @@ to_chat(src, "You are invincible and invisible to everyone but other ghosts. Most abilities will reveal you, rendering you vulnerable.") to_chat(src, "To function, you are to drain the life essence from humans. This essence is a resource, as well as your health, and will power all of your abilities.") to_chat(src, "You do not remember anything of your past lives, nor will you remember anything about this one after your death.") - to_chat(src, "Be sure to read the wiki page at http://nanotrasen.se/wiki/index.php/Revenant to learn more.") + to_chat(src, "Be sure to read the wiki page at http://www.paradisestation.org/wiki/index.php/Revenant to learn more.") var/datum/objective/revenant/objective = new objective.owner = mind mind.objectives += objective diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index 1c4956d096e..714ccbf1d5f 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -1,3 +1,10 @@ +#define NUKE_INTACT 0 +#define NUKE_COVER_OFF 1 +#define NUKE_COVER_OPEN 2 +#define NUKE_SEALANT_OPEN 3 +#define NUKE_UNWRENCHED 4 +#define NUKE_MOBILE 5 + var/bomb_set /obj/machinery/nuclearbomb @@ -17,7 +24,7 @@ var/bomb_set var/yes_code = 0 var/safety = 1 var/obj/item/disk/nuclear/auth = null - var/removal_stage = 0 // 0 is no removal, 1 is covers removed, 2 is covers open, 3 is sealant open, 4 is unwrenched, 5 is removed from bolts. + var/removal_stage = NUKE_INTACT var/lastentered var/is_syndicate = 0 use_power = NO_POWER_USE @@ -50,33 +57,6 @@ var/bomb_set return /obj/machinery/nuclearbomb/attackby(obj/item/O as obj, mob/user as mob, params) - if(istype(O, /obj/item/screwdriver)) - add_fingerprint(user) - if(auth) - if(panel_open == 0) - panel_open = 1 - overlays += image(icon, "npanel_open") - to_chat(user, "You unscrew the control panel of [src].") - playsound(src, O.usesound, 50, 1) - else - panel_open = 0 - overlays -= image(icon, "npanel_open") - to_chat(user, "You screw the control panel of [src] back on.") - playsound(src, O.usesound, 50, 1) - else - if(panel_open == 0) - to_chat(user, "[src] emits a buzzing noise, the panel staying locked in.") - if(panel_open == 1) - panel_open = 0 - overlays -= image(icon, "npanel_open") - to_chat(user, "You screw the control panel of [src] back on.") - playsound(src, O.usesound, 50, 1) - flick("nuclearbombc", src) - return - - if(panel_open && (istype(O, /obj/item/multitool) || istype(O, /obj/item/wirecutters))) - return attack_hand(user) - if(istype(O, /obj/item/disk/nuclear)) if(extended) if(!user.drop_item()) @@ -89,77 +69,107 @@ var/bomb_set else to_chat(user, "You need to deploy \the [src] first. Right click on the sprite, select 'Make Deployable' then click on \the [src] with an empty hand.") return - - if(anchored) - switch(removal_stage) - if(0) - if(istype(O,/obj/item/weldingtool)) - var/obj/item/weldingtool/WT = O - if(!WT.isOn()) return - if(WT.get_fuel() < 5) // uses up 5 fuel. - to_chat(user, "You need more fuel to complete this task.") - return - - user.visible_message("[user] starts cutting loose the anchoring bolt covers on [src].", "You start cutting loose the anchoring bolt covers with [O]...") - - if(do_after(user,40, target = src)) - if(!src || !user || !WT.remove_fuel(5, user)) return - user.visible_message("[user] cuts through the bolt covers on [src].", "You cut through the bolt cover.") - removal_stage = 1 - return - - if(1) - if(istype(O,/obj/item/crowbar)) - user.visible_message("[user] starts forcing open the bolt covers on [src].", "You start forcing open the anchoring bolt covers with [O]...") - - if(do_after(user,15, target = src)) - if(!src || !user) return - user.visible_message("[user] forces open the bolt covers on [src].", "You force open the bolt covers.") - removal_stage = 2 - return - - if(2) - if(istype(O,/obj/item/weldingtool)) - - var/obj/item/weldingtool/WT = O - if(!WT.isOn()) return - if(WT.get_fuel() < 5) // uses up 5 fuel. - to_chat(user, "You need more fuel to complete this task.") - return - - user.visible_message("[user] starts cutting apart the anchoring system sealant on [src].", "You start cutting apart the anchoring system's sealant with [O]...") - - if(do_after(user,40, target = src)) - if(!src || !user || !WT.remove_fuel(5, user)) return - user.visible_message("[user] cuts apart the anchoring system sealant on [src].", "You cut apart the anchoring system's sealant.") - removal_stage = 3 - return - - if(3) - if(istype(O,/obj/item/wrench)) - - user.visible_message("[user] begins unwrenching the anchoring bolts on [src].", "You begin unwrenching the anchoring bolts...") - - if(do_after(user,50, target = src)) - if(!src || !user) return - user.visible_message("[user] unwrenches the anchoring bolts on [src].", "You unwrench the anchoring bolts.") - removal_stage = 4 - return - - if(4) - if(istype(O,/obj/item/crowbar)) - - user.visible_message("[user] begins lifting [src] off of the anchors.", "You begin lifting the device off the anchors...") - - if(do_after(user,80, target = src)) - if(!src || !user) return - user.visible_message("[user] crowbars [src] off of the anchors. It can now be moved.", "You jam the crowbar under the nuclear device and lift it off its anchors. You can now move it!") - anchored = 0 - removal_stage = 5 - return - return return ..() +/obj/machinery/nuclearbomb/crowbar_act(mob/user, obj/item/I) + if(!anchored) + return + if(removal_stage != NUKE_UNWRENCHED && removal_stage != NUKE_COVER_OFF) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(removal_stage == NUKE_COVER_OFF) + user.visible_message("[user] starts forcing open the bolt covers on [src].", "You start forcing open the anchoring bolt covers with [I]...") + if(!I.use_tool(src, user, 15, volume = I.tool_volume) || removal_stage != NUKE_COVER_OFF) + return + user.visible_message("[user] forces open the bolt covers on [src].", "You force open the bolt covers.") + removal_stage = NUKE_COVER_OPEN + else + user.visible_message("[user] begins lifting [src] off of the anchors.", "You begin lifting the device off the anchors...") + if(!I.use_tool(src, user, 80, volume = I.tool_volume) || removal_stage != NUKE_UNWRENCHED) + return + user.visible_message("[user] crowbars [src] off of the anchors. It can now be moved.", "You jam the crowbar under the nuclear device and lift it off its anchors. You can now move it!") + anchored = FALSE + removal_stage = NUKE_MOBILE + +/obj/machinery/nuclearbomb/wrench_act(mob/user, obj/item/I) + if(!anchored) + return + if(removal_stage != NUKE_SEALANT_OPEN) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + user.visible_message("[user] begins unwrenching the anchoring bolts on [src].", "You begin unwrenching the anchoring bolts...") + if(!I.use_tool(src, user, 50, volume = I.tool_volume) || removal_stage != NUKE_SEALANT_OPEN) + return + user.visible_message("[user] unwrenches the anchoring bolts on [src].", "You unwrench the anchoring bolts.") + removal_stage = NUKE_UNWRENCHED + +/obj/machinery/nuclearbomb/multitool_act(mob/user, obj/item/I) + if(!panel_open) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + attack_hand(user) + +/obj/machinery/nuclearbomb/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(auth) + if(!panel_open) + panel_open = TRUE + overlays += image(icon, "npanel_open") + to_chat(user, "You unscrew the control panel of [src].") + else + panel_open = FALSE + overlays -= image(icon, "npanel_open") + to_chat(user, "You screw the control panel of [src] back on.") + else + if(!panel_open) + to_chat(user, "[src] emits a buzzing noise, the panel staying locked in.") + if(panel_open == TRUE) + panel_open = FALSE + overlays -= image(icon, "npanel_open") + to_chat(user, "You screw the control panel of [src] back on.") + flick("nuclearbombc", src) + +/obj/machinery/nuclearbomb/wirecutter_act(mob/user, obj/item/I) + if(!panel_open) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + attack_hand(user) + +/obj/machinery/nuclearbomb/welder_act(mob/user, obj/item/I) + . = TRUE + if(removal_stage != NUKE_INTACT && removal_stage != NUKE_COVER_OPEN) + return + if(!I.tool_use_check(user, 0)) + return + if(removal_stage == NUKE_INTACT) + visible_message("[user] starts cutting loose the anchoring bolt covers on [src].",\ + "You start cutting loose the anchoring bolt covers with [I]...",\ + "You hear welding.") + if(!I.use_tool(src, user, 40, 5, volume = I.tool_volume) || removal_stage != NUKE_INTACT) + return + visible_message("[user] cuts through the bolt covers on [src].",\ + "You cut through the bolt cover.") + removal_stage = NUKE_COVER_OFF + else if(removal_stage == NUKE_COVER_OPEN) + visible_message("[user] starts cutting apart the anchoring system sealant on [src].",\ + "You start cutting apart the anchoring system's sealant with [I]...",\ + "You hear welding.") + if(!I.use_tool(src, user, 40, 5, volume = I.tool_volume) || removal_stage != NUKE_COVER_OPEN) + return + visible_message("[user] cuts apart the anchoring system sealant on [src].",\ + "You cut apart the anchoring system's sealant.") + removal_stage = NUKE_SEALANT_OPEN + /obj/machinery/nuclearbomb/attack_ghost(mob/user as mob) if(extended) attack_hand(user) @@ -171,7 +181,7 @@ var/bomb_set else ui_interact(user) else if(deployable) - if(removal_stage < 5) + if(removal_stage != NUKE_MOBILE) anchored = 1 visible_message("With a steely snap, bolts slide out of [src] and anchor it to the flooring!") else @@ -317,7 +327,7 @@ var/bomb_set timing = 0 bomb_set = 0 if(href_list["anchor"]) - if(removal_stage == 5) + if(removal_stage == NUKE_MOBILE) anchored = 0 visible_message("\The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.") SSnanoui.update_uis(src) @@ -453,3 +463,10 @@ var/bomb_set else error("[src] was supposed to be destroyed, but we were unable to locate a blobstart landmark to spawn a new one.") return QDEL_HINT_LETMELIVE // Cancel destruction unless forced. + +#undef NUKE_INTACT +#undef NUKE_COVER_OFF +#undef NUKE_COVER_OPEN +#undef NUKE_SEALANT_OPEN +#undef NUKE_UNWRENCHED +#undef NUKE_MOBILE diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 214c349978a..89ecb1d103b 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1,4 +1,4 @@ -var/global/list/all_objectives = list() +GLOBAL_LIST_EMPTY(all_objectives) var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datum/theft_objective/steal - /datum/theft_objective/number - /datum/theft_objective/unique @@ -10,13 +10,13 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu var/completed = 0 //currently only used for custom objectives. var/martyr_compatible = 0 //If the objective is compatible with martyr objective, i.e. if you can still do it while dead. -/datum/objective/New(var/text) - all_objectives |= src +/datum/objective/New(text) + GLOB.all_objectives += src if(text) explanation_text = text /datum/objective/Destroy() - all_objectives -= src + GLOB.all_objectives -= src return ..() /datum/objective/proc/check_completion() diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm index b580f88c0b7..b4b4b265711 100644 --- a/code/game/gamemodes/shadowling/shadowling.dm +++ b/code/game/gamemodes/shadowling/shadowling.dm @@ -126,7 +126,7 @@ Made by Xhuis to_chat(shadow.current, "Currently, you are disguised as an employee aboard [world.name].") to_chat(shadow.current, "In your limited state, you have two abilities: Hatch and Shadowling Hivemind (:8).") to_chat(shadow.current, "Any other shadowlings are your allies. You must assist them as they shall assist you.") - to_chat(shadow.current, "If you are new to shadowling, or want to read about abilities, check the wiki page at http://nanotrasen.se/wiki/index.php/Shadowling
") + to_chat(shadow.current, "If you are new to shadowling, or want to read about abilities, check the wiki page at https://www.paradisestation.org/wiki/index.php/Shadowling
") diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index cca11dc0a98..d97ec2af5fd 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -205,24 +205,19 @@ /obj/item/proc/transfer_soul(var/choice as text, var/target, var/mob/U as mob) switch(choice) if("FORCE") - var/obj/item/soulstone/C = src - if(!iscarbon(target)) //TODO: Add sacrifice stoning for non-organics, just because you have no body doesnt mean you dont have a soul - return 0 - if(contents.len) - return 0 - var/mob/living/carbon/T = target + var/obj/item/soulstone/SS = src + var/mob/living/T = target if(T.client != null) - for(var/obj/item/W in T) - T.unEquip(W) - C.init_shade(T, U) - return 1 + SS.init_shade(T, U) else to_chat(U, "Capture failed!: The soul has already fled its mortal frame. You attempt to bring it back...") - return C.getCultGhost(T,U) + T.Paralyse(20) + if(!SS.getCultGhost(T,U)) + T.dust() //If we can't get a ghost, kill the sacrifice anyway. if("VICTIM") var/mob/living/carbon/human/T = target - var/obj/item/soulstone/C = src + var/obj/item/soulstone/SS = src if(T.stat == 0) to_chat(U, "Capture failed!: Kill or maim the victim first!") else @@ -231,94 +226,70 @@ else if(T.client == null) to_chat(U, "Capture failed!: The soul has already fled its mortal frame. You attempt to bring it back...") - C.getCultGhost(T,U) + SS.getCultGhost(T,U) else - if(C.contents.len) + if(SS.contents.len) to_chat(U, "Capture failed!: The soul stone is full! Use or free an existing soul to make room.") else - for(var/obj/item/W in T) - T.unEquip(W) - C.init_shade(T, U, vic = 1) - qdel(T) + SS.init_shade(T, U, vic = 1) + if("SHADE") var/mob/living/simple_animal/shade/T = target - var/obj/item/soulstone/C = src - if(!C.can_use(U)) + var/obj/item/soulstone/SS = src + if(!SS.can_use(U)) U.Paralyse(5) to_chat(U, "Your body is wracked with debilitating pain!") return if(T.stat == DEAD) to_chat(U, "Capture failed!: The shade has already been banished!") else - if(C.contents.len) + if(SS.contents.len) to_chat(U, "Capture failed!: The soul stone is full! Use or free an existing soul to make room.") else - T.loc = C //put shade in stone + T.loc = SS //put shade in stone T.status_flags |= GODMODE T.canmove = 0 T.health = T.maxHealth T.faction |= "\ref[U]" - C.icon_state = "soulstone2" + SS.icon_state = "soulstone2" to_chat(T, "Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form") to_chat(U, "Capture successful!: [T.name]'s has been recaptured and stored within the soul stone.") if("CONSTRUCT") var/obj/structure/constructshell/T = target - var/obj/item/soulstone/C = src - var/mob/living/simple_animal/shade/A = locate() in C - if(A) + var/obj/item/soulstone/SS = src + var/mob/living/simple_animal/shade/SH = locate() in SS + if(SH) var/construct_class = alert(U, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer") switch(construct_class) if("Juggernaut") - var/mob/living/simple_animal/hostile/construct/armoured/Z = new /mob/living/simple_animal/hostile/construct/armoured (get_turf(T.loc)) - Z.key = A.key - Z.faction |= "\ref[U]" - if(iscultist(U)) - if(SSticker.mode.name == "cult") - SSticker.mode:add_cultist(Z.mind) - else - SSticker.mode.cult+=Z.mind - SSticker.mode.update_cult_icons_added(Z.mind) - qdel(T) - to_chat(Z, "You are a Juggernaut. Though slow, your shell can withstand extreme punishment, create shield walls and even deflect energy weapons, and rip apart enemies and walls alike.") - to_chat(Z, "You are still bound to serve your creator, follow [U.p_their()] orders and help [U.p_them()] complete [U.p_their()] goals at all costs.") - Z.cancel_camera() - qdel(C) + var/mob/living/simple_animal/hostile/construct/armoured/C = new /mob/living/simple_animal/hostile/construct/armoured (get_turf(T.loc)) + to_chat(C, "You are a Juggernaut. Though slow, your shell can withstand extreme punishment, create shield walls and even deflect energy weapons, and rip apart enemies and walls alike.") + init_construct(C,SH,SS,T) if("Wraith") - var/mob/living/simple_animal/hostile/construct/wraith/Z = new /mob/living/simple_animal/hostile/construct/wraith (get_turf(T.loc)) - Z.key = A.key - Z.faction |= "\ref[U]" - if(iscultist(U)) - if(SSticker.mode.name == "cult") - SSticker.mode:add_cultist(Z.mind) - else - SSticker.mode.cult+=Z.mind - SSticker.mode.update_cult_icons_added(Z.mind) - qdel(T) - to_chat(Z, "You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls.") - to_chat(Z, "You are still bound to serve your creator, follow [U.p_their()] orders and help [U.p_them()] complete [U.p_their()] goals at all costs.") - Z.cancel_camera() - qdel(C) + var/mob/living/simple_animal/hostile/construct/wraith/C = new /mob/living/simple_animal/hostile/construct/wraith (get_turf(T.loc)) + to_chat(C, "You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls.") + init_construct(C,SH,SS,T) if("Artificer") - var/mob/living/simple_animal/hostile/construct/builder/Z = new /mob/living/simple_animal/hostile/construct/builder (get_turf(T.loc)) - Z.key = A.key - Z.faction |= "\ref[U]" - if(iscultist(U)) - if(SSticker.mode.name == "cult") - SSticker.mode:add_cultist(Z.mind) - else - SSticker.mode.cult+=Z.mind - SSticker.mode.update_cult_icons_added(Z.mind) - qdel(T) - to_chat(Z, "You are an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, use magic missile, repair allied constructs (by clicking on them), and most important of all create new constructs (Use your Artificer spell to summon a new construct shell and Summon Soulstone to create a new soulstone).") - to_chat(Z, "You are still bound to serve your creator, follow [U.p_their()] orders and help [U.p_them()] complete [U.p_their()] goals at all costs.") - Z.cancel_camera() - qdel(C) + var/mob/living/simple_animal/hostile/construct/builder/C = new /mob/living/simple_animal/hostile/construct/builder (get_turf(T.loc)) + to_chat(C, "You are an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, use magic missile, repair allied constructs (by clicking on them), and most important of all create new constructs (Use your Artificer spell to summon a new construct shell and Summon Soulstone to create a new soulstone).") + init_construct(C,SH,SS,T) else to_chat(U, "Creation failed!: The soul stone is empty! Go kill someone!") return +/proc/init_construct(mob/living/simple_animal/hostile/construct/C, mob/living/simple_animal/shade/SH, obj/item/soulstone/SS, obj/structure/constructshell/T) + SH.mind.transfer_to(C) + if(iscultist(C)) + var/datum/action/innate/cultcomm/CC = new() + CC.Grant(C) //We have to grant the cult comms again because they're lost during the mind transfer. + qdel(T) + qdel(SH) + to_chat(C, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") + C.cancel_camera() + qdel(SS) + /proc/makeNewConstruct(var/mob/living/simple_animal/hostile/construct/ctype, var/mob/target, var/mob/stoner = null, cultoverride = 0) if(jobban_isbanned(target, "cultist") || jobban_isbanned(target, "Syndicate")) return @@ -332,14 +303,14 @@ SSticker.mode.cult+=newstruct.mind SSticker.mode.update_cult_icons_added(newstruct.mind) if(stoner && iswizard(stoner)) - to_chat(newstruct, "You are still bound to serve your creator, follow [stoner.p_their()] orders and help [stoner.p_them()] complete [stoner.p_their()] goals at all costs.") + to_chat(newstruct, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") else if(stoner && iscultist(stoner)) - to_chat(newstruct, "You are still bound to serve the cult, follow [stoner.p_their()] orders and help [stoner.p_them()] complete [stoner.p_their()] goals at all costs.") + to_chat(newstruct, "You are still bound to serve the cult, follow their orders and help them complete their goals at all costs.") else - to_chat(newstruct, "You are still bound to serve your creator, follow [stoner.p_their()] orders and help [stoner.p_them()] complete [stoner.p_their()] goals at all costs.") + to_chat(newstruct, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") newstruct.cancel_camera() -/obj/item/soulstone/proc/init_shade(mob/living/carbon/human/T, mob/U, vic = 0) +/obj/item/soulstone/proc/init_shade(mob/living/T, mob/U, vic = 0) new /obj/effect/decal/remains/human(T.loc) //Spawns a skeleton T.invisibility = 101 var/atom/movable/overlay/animation = new /atom/movable/overlay( T.loc ) @@ -355,19 +326,30 @@ S.name = "Shade of [T.real_name]" S.real_name = "Shade of [T.real_name]" S.key = T.key - if(U) - S.faction |= "\ref[U]" //Add the master as a faction, allowing inter-mob cooperation - if(U && iscultist(U)) - SSticker.mode.add_cultist(S.mind, 0) S.cancel_camera() name = "soulstone: Shade of [T.real_name]" icon_state = "soulstone2" - if(U && iswizard(U)) - to_chat(S, "Your soul has been captured! You are now bound to [U.real_name]'s will. Help [U.p_them()] succeed in their goals at all costs.") - else if(U && iscultist(U)) - to_chat(S, "Your soul has been captured! You are now bound to the cult's will. Help [U.p_them()] succeed in their goals at all costs.") + if(U) + S.faction |= "\ref[U]" //Add the master as a faction, allowing inter-mob cooperation + if(iswizard(U)) + SSticker.mode.update_wiz_icons_added(S.mind) + S.mind.special_role = SPECIAL_ROLE_WIZARD_APPRENTICE + if(iscultist(U)) + SSticker.mode.add_cultist(S.mind, 0) + S.mind.special_role = SPECIAL_ROLE_CULTIST + S.mind.store_memory("Serve the cult's will.") + to_chat(S, "Your soul has been captured! You are now bound to the cult's will. Help them succeed in their goals at all costs.") + else + S.mind.store_memory("Serve [U.real_name], your creator.") + to_chat(S, "Your soul has been captured! You are now bound to [U.real_name]'s will. Help them succeed in their goals at all costs.") if(vic && U) to_chat(U, "Capture successful!: [T.real_name]'s soul has been ripped from [U.p_their()] body and stored within the soul stone.") + if(isrobot(T))//Robots have to dust or else they spill out an empty robot brain, and unequiping them spills robot components that shouldn't spawn. + T.dust() + else + for(var/obj/item/W in T) + T.unEquip(W) + qdel(T) /obj/item/soulstone/proc/get_shade_type() return /mob/living/simple_animal/shade/cult @@ -375,7 +357,7 @@ /obj/item/soulstone/anybody/get_shade_type() return /mob/living/simple_animal/shade -/obj/item/soulstone/proc/getCultGhost(mob/living/carbon/human/T, mob/U) +/obj/item/soulstone/proc/getCultGhost(mob/living/T, mob/U) var/mob/dead/observer/chosen_ghost for(var/mob/dead/observer/ghost in GLOB.player_list) //We put them back in their body @@ -395,8 +377,5 @@ if(contents.len) //If they used the soulstone on someone else in the meantime return 0 T.ckey = chosen_ghost.ckey - for(var/obj/item/W in T) - T.unEquip(W) init_shade(T, U) - qdel(T) return 1 diff --git a/code/game/jobs/job/central.dm b/code/game/jobs/job/central.dm index 1d6ae0162a2..1d62afcb266 100644 --- a/code/game/jobs/job/central.dm +++ b/code/game/jobs/job/central.dm @@ -66,7 +66,7 @@ /datum/outfit/job/ntspecops name = "Special Operations Officer" jobtype = /datum/job/ntspecops - uniform = /obj/item/clothing/under/rank/centcom_commander + uniform = /obj/item/clothing/under/rank/centcom/captain suit = /obj/item/clothing/suit/space/deathsquad/officer back = /obj/item/storage/backpack/security belt = /obj/item/storage/belt/military/assault diff --git a/code/game/jobs/job_exp.dm b/code/game/jobs/job_exp.dm index 359981ded4f..b69dbfd3ed4 100644 --- a/code/game/jobs/job_exp.dm +++ b/code/game/jobs/job_exp.dm @@ -263,8 +263,11 @@ var/global/list/role_playtime_requirements = list( myrole = mob.mind.playtime_role else if(mob.mind.assigned_role) myrole = mob.mind.assigned_role + var/added_living = 0 + var/added_ghost = 0 if(mob.stat == CONSCIOUS && myrole) play_records[EXP_TYPE_LIVING] += minutes + added_living += minutes if(announce_changes) to_chat(mob,"You got: [minutes] Living EXP!") for(var/category in exp_jobsmap) @@ -279,6 +282,7 @@ var/global/list/role_playtime_requirements = list( to_chat(mob,"You got: [minutes] Special EXP!") else if(isobserver(mob)) play_records[EXP_TYPE_GHOST] += minutes + added_ghost += minutes if(announce_changes) to_chat(mob,"You got: [minutes] Ghost EXP!") else @@ -286,9 +290,15 @@ var/global/list/role_playtime_requirements = list( var/new_exp = list2params(play_records) prefs.exp = new_exp new_exp = sanitizeSQL(new_exp) - var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("player")] SET exp = '[new_exp]' WHERE ckey='[ckey]'") + var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("player")] SET exp = '[new_exp]',lastseen = Now() WHERE ckey='[ckey]'") if(!update_query.Execute()) var/err = update_query.ErrorMsg() - log_game("SQL ERROR during exp_update_client write. Error : \[[err]\]\n") - message_admins("SQL ERROR during exp_update_client write. Error : \[[err]\]\n") + log_game("SQL ERROR during exp_update_client write 1. Error : \[[err]\]\n") + message_admins("SQL ERROR during exp_update_client write 1. Error : \[[err]\]\n") return + var/DBQuery/update_query_history = dbcon.NewQuery("INSERT INTO [format_table_name("playtime_history")] (ckey, date, time_living, time_ghost) VALUES ('[ckey]',CURDATE(),[added_living],[added_ghost]) ON DUPLICATE KEY UPDATE time_living=time_living+VALUES(time_living),time_ghost=time_ghost+VALUES(time_ghost)") + if(!update_query_history.Execute()) + var/err = update_query_history.ErrorMsg() + log_game("SQL ERROR during exp_update_client write 2. Error : \[[err]\]\n") + message_admins("SQL ERROR during exp_update_client write 2. Error : \[[err]\]\n") + return \ No newline at end of file diff --git a/code/game/machinery/Freezer.dm b/code/game/machinery/Freezer.dm index 91afce20b4d..b6c6121cfd6 100644 --- a/code/game/machinery/Freezer.dm +++ b/code/game/machinery/Freezer.dm @@ -8,6 +8,7 @@ use_power = IDLE_POWER_USE current_heat_capacity = 1000 layer = 3 + plane = GAME_PLANE max_integrity = 300 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 30) @@ -50,36 +51,39 @@ ..(dir,dir) /obj/machinery/atmospherics/unary/cold_sink/freezer/attackby(obj/item/I, mob/user, params) - if(default_deconstruction_screwdriver(user, "freezer-o", "freezer", I)) - on = 0 - update_icon() - return - if(exchange_parts(user, I)) return - - if(default_deconstruction_crowbar(I)) - return - - if(iswrench(I)) - if(!panel_open) - to_chat(user, "Open the maintenance panel first.") - return - var/list/choices = list("West" = WEST, "East" = EAST, "South" = SOUTH, "North" = NORTH) - var/selected = input(user,"Select a direction for the connector.", "Connector Direction") in choices - dir = choices[selected] - playsound(src.loc, I.usesound, 50, 1) - var/node_connect = dir - initialize_directions = dir - for(var/obj/machinery/atmospherics/target in get_step(src,node_connect)) - if(target.initialize_directions & get_dir(target,src)) - node = target - break - build_network() - update_icon() - return return ..() +/obj/machinery/atmospherics/unary/cold_sink/freezer/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I)) + return TRUE + +/obj/machinery/atmospherics/unary/cold_sink/freezer/screwdriver_act(mob/user, obj/item/I) + if(default_deconstruction_screwdriver(user, "freezer-o", "freezer", I)) + on = FALSE + update_icon() + return TRUE + +/obj/machinery/atmospherics/unary/cold_sink/freezer/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!panel_open) + to_chat(user, "Open the maintenance panel first.") + return + var/list/choices = list("West" = WEST, "East" = EAST, "South" = SOUTH, "North" = NORTH) + var/selected = input(user,"Select a direction for the connector.", "Connector Direction") in choices + dir = choices[selected] + var/node_connect = dir + initialize_directions = dir + for(var/obj/machinery/atmospherics/target in get_step(src,node_connect)) + if(target.initialize_directions & get_dir(target,src)) + node = target + break + build_network() + update_icon() + /obj/machinery/atmospherics/unary/cold_sink/freezer/update_icon() if(panel_open) icon_state = "freezer-o" @@ -217,35 +221,38 @@ current_heat_capacity = 1000 * ((H - 1) ** 2) /obj/machinery/atmospherics/unary/heat_reservoir/heater/attackby(obj/item/I, mob/user, params) + if(exchange_parts(user, I)) + return + return ..() + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I)) + return TRUE + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/screwdriver_act(mob/user, obj/item/I) if(default_deconstruction_screwdriver(user, "heater-o", "heater", I)) on = 0 update_icon() - return + return TRUE - if(exchange_parts(user, I)) +/obj/machinery/atmospherics/unary/heat_reservoir/heater/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return - - if(default_deconstruction_crowbar(I)) + if(!panel_open) + to_chat(user, "Open the maintenance panel first.") return - - if(iswrench(I)) - if(!panel_open) - to_chat(user, "Open the maintenance panel first.") - return - var/list/choices = list("West" = WEST, "East" = EAST, "South" = SOUTH, "North" = NORTH) - var/selected = input(user,"Select a direction for the connector.", "Connector Direction") in choices - dir = choices[selected] - playsound(src.loc, I.usesound, 50, 1) - var/node_connect = dir - initialize_directions = dir - for(var/obj/machinery/atmospherics/target in get_step(src,node_connect)) - if(target.initialize_directions & get_dir(target,src)) - node = target - break - build_network() - update_icon() - return - return ..() + var/list/choices = list("West" = WEST, "East" = EAST, "South" = SOUTH, "North" = NORTH) + var/selected = input(user,"Select a direction for the connector.", "Connector Direction") in choices + dir = choices[selected] + var/node_connect = dir + initialize_directions = dir + for(var/obj/machinery/atmospherics/target in get_step(src,node_connect)) + if(target.initialize_directions & get_dir(target,src)) + node = target + break + build_network() + update_icon() /obj/machinery/atmospherics/unary/heat_reservoir/heater/update_icon() if(panel_open) diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index 2c6e60c3d52..8c93028649b 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -131,15 +131,18 @@ if(iscarbon(G.affecting)) take_victim(G.affecting, user) qdel(G) - if(iswrench(I)) - playsound(loc, I.usesound, 50, 1) - if(do_after(user, 20 * I.toolspeed, target = src)) - to_chat(user, "You deconstruct the table.") - new /obj/item/stack/sheet/plasteel(loc, 5) - qdel(src) else return ..() +/obj/machinery/optable/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_start_check(user, 0)) + return + if(I.use_tool(src, user, 20, volume = I.tool_volume)) + to_chat(user, "You deconstruct the table.") + new /obj/item/stack/sheet/plasteel(loc, 5) + qdel(src) + /obj/machinery/optable/proc/check_table(mob/living/carbon/patient as mob) if(src.victim && get_turf(victim) == get_turf(src) && victim.lying) to_chat(usr, "The table is already occupied!") diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm index 817d56cb47a..83778a99c26 100644 --- a/code/game/machinery/PDApainter.dm +++ b/code/game/machinery/PDApainter.dm @@ -75,27 +75,15 @@ P.forceMove(src) P.add_fingerprint(user) update_icon() - else if(iswelder(I) && user.a_intent != INTENT_HARM) - var/obj/item/weldingtool/WT = I - if(stat & BROKEN) - if(WT.remove_fuel(0,user)) - user.visible_message("[user] is repairing [src].", \ - "You begin repairing [src]...", \ - "You hear welding.") - playsound(loc, WT.usesound, 40, 1) - if(do_after(user,40*WT.toolspeed, 1, target = src)) - if(!WT.isOn() || !(stat & BROKEN)) - return - to_chat(user, "You repair [src].") - playsound(loc, 'sound/items/welder2.ogg', 50, 1) - stat &= ~BROKEN - obj_integrity = max_integrity - update_icon() - else - to_chat(user, "[src] does not need repairs.") else return ..() +/obj/machinery/pdapainter/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + default_welder_repair(user, I) + /obj/machinery/pdapainter/deconstruct(disassembled = TRUE) if(!(flags & NODECONSTRUCT)) if(!(stat & BROKEN)) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index fbe594f2269..f1adf1a5f11 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -280,35 +280,9 @@ to_chat(user, "The sleeper has a beaker already.") return - if(isscrewdriver(I)) - if(occupant) - to_chat(user, "The maintenance panel is locked.") - return - default_deconstruction_screwdriver(user, "[base_icon]-o", "[base_icon]-open", I) - return - - if(iswrench(I)) - if(occupant) - to_chat(user, "The scanner is occupied.") - return - if(panel_open) - to_chat(user, "Close the maintenance panel first.") - return - if(dir == EAST) - orient = "LEFT" - setDir(WEST) - else - orient = "RIGHT" - setDir(EAST) - playsound(loc, I.usesound, 50, 1) - return - if(exchange_parts(user, I)) return - if(default_deconstruction_crowbar(I)) - return - if(istype(I, /obj/item/grab)) var/obj/item/grab/G = I if(panel_open) @@ -343,6 +317,34 @@ return ..() +/obj/machinery/sleeper/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I)) + return TRUE + +/obj/machinery/sleeper/screwdriver_act(mob/user, obj/item/I) + if(occupant) + to_chat(user, "The maintenance panel is locked.") + return TRUE + if(default_deconstruction_screwdriver(user, "[base_icon]-o", "[base_icon]-open", I)) + return TRUE + +/obj/machinery/sleeper/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(occupant) + to_chat(user, "The scanner is occupied.") + return + if(panel_open) + to_chat(user, "Close the maintenance panel first.") + return + if(dir == EAST) + orient = "LEFT" + setDir(WEST) + else + orient = "RIGHT" + setDir(EAST) + /obj/machinery/sleeper/ex_act(severity) if(filtering) toggle_filter() diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 0863b65415a..edb12487a68 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -40,33 +40,9 @@ RefreshParts() /obj/machinery/bodyscanner/attackby(obj/item/I, mob/user) - if(isscrewdriver(I)) - if(occupant) - to_chat(user, "The maintenance panel is locked.") - return - default_deconstruction_screwdriver(user, "bodyscanner-o", "bodyscanner-open", I) - return - - if(iswrench(I)) - if(occupant) - to_chat(user, "The scanner is occupied.") - return - if(panel_open) - to_chat(user, "Close the maintenance panel first.") - return - if(dir == EAST) - setDir(WEST) - else - setDir(EAST) - playsound(loc, I.usesound, 50, 1) - return - if(exchange_parts(user, I)) return - if(default_deconstruction_crowbar(I)) - return - if(istype(I, /obj/item/grab)) var/obj/item/grab/TYPECAST_YOUR_SHIT = I if(panel_open) @@ -93,6 +69,28 @@ return ..() +/obj/machinery/bodyscanner/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I)) + return TRUE + +/obj/machinery/bodyscanner/screwdriver_act(mob/user, obj/item/I) + if(default_deconstruction_screwdriver(user, "bodyscanner-o", "bodyscanner-open", I)) + return TRUE + +/obj/machinery/bodyscanner/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(occupant) + to_chat(user, "The scanner is occupied.") + return + if(panel_open) + to_chat(user, "Close the maintenance panel first.") + return + if(dir == EAST) + setDir(WEST) + else + setDir(EAST) /obj/machinery/bodyscanner/MouseDrop_T(mob/living/carbon/human/H, mob/user) if(!istype(H)) diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index d13406eee99..5d286c0a367 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -62,6 +62,10 @@ #define MAX_TEMPERATURE 363.15 // 90C #define MIN_TEMPERATURE 233.15 // -40C +#define AIR_ALARM_FRAME 0 +#define AIR_ALARM_BUILDING 1 +#define AIR_ALARM_READY 2 + //all air alarms in area are connected via magic /area var/obj/machinery/alarm/master_air_alarm @@ -111,7 +115,7 @@ var/danger_level = ATMOS_ALARM_NONE var/alarmActivated = 0 // Manually activated (independent from danger level) - var/buildstage = 2 //2 is built, 1 is building, 0 is frame. + var/buildstage = AIR_ALARM_READY var/target_temperature = T20C var/regulating_temperature = 0 @@ -948,24 +952,6 @@ switch(buildstage) if(2) - if(isscrewdriver(I)) // Opening that Air Alarm up. - wiresexposed = !wiresexposed - to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"]") - update_icon() - return - - if(iswirecutter(I)) // cutting the wires out - if(wires.wires_status == 31) // all wires cut - var/obj/item/stack/cable_coil/new_coil = new /obj/item/stack/cable_coil() - new_coil.amount = 5 - new_coil.forceMove(user.loc) - buildstage = 1 - update_icon() - return - - if(wiresexposed && ((ismultitool(I) || iswirecutter(I)))) - return attack_hand(user) - if(istype(I, /obj/item/card/id) || istype(I, /obj/item/pda))// trying to unlock the interface with an ID card if(stat & (NOPOWER|BROKEN)) to_chat(user, "It does nothing") @@ -980,7 +966,7 @@ return if(1) - if(istype(I, /obj/item/stack/cable_coil)) + if(iscoil(I)) var/obj/item/stack/cable_coil/coil = I if(coil.amount < 5) to_chat(user, "You need more cable for this!") @@ -996,19 +982,6 @@ update_icon() first_run() return - - else if(iscrowbar(I)) - to_chat(user, "You start prying out the circuit.") - playsound(get_turf(src), I.usesound, 50, 1) - if(do_after(user, 20 * I.toolspeed, target = src)) - if(buildstage != 1) - return - to_chat(user, "You pry out the circuit!") - var/obj/item/airalarm_electronics/circuit = new /obj/item/airalarm_electronics() - circuit.forceMove(user.loc) - buildstage = 0 - update_icon() - return if(0) if(istype(I, /obj/item/airalarm_electronics)) to_chat(user, "You insert the circuit!") @@ -1017,16 +990,70 @@ buildstage = 1 update_icon() return - - else if(iswrench(I)) - to_chat(user, "You remove the fire alarm assembly from the wall!") - new /obj/item/mounted/frame/alarm_frame(get_turf(user)) - playsound(get_turf(src), I.usesound, 50, 1) - qdel(src) - return - return ..() +/obj/machinery/alarm/crowbar_act(mob/user, obj/item/I) + if(buildstage != AIR_ALARM_BUILDING) + return + . = TRUE + if(!I.tool_start_check(user, 0)) + return + to_chat(user, "You start prying out the circuit.") + if(!I.use_tool(src, user, 20, volume = I.tool_volume)) + return + if(buildstage != AIR_ALARM_BUILDING) + return + to_chat(user, "You pry out the circuit!") + new /obj/item/airalarm_electronics(user.drop_location()) + buildstage = AIR_ALARM_FRAME + update_icon() + +/obj/machinery/alarm/multitool_act(mob/user, obj/item/I) + if(buildstage != AIR_ALARM_READY) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(wiresexposed) + attack_hand(user) + +/obj/machinery/alarm/screwdriver_act(mob/user, obj/item/I) + if(buildstage != AIR_ALARM_READY) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + wiresexposed = !wiresexposed + update_icon() + if(wiresexposed) + SCREWDRIVER_OPEN_PANEL_MESSAGE + else + SCREWDRIVER_CLOSE_PANEL_MESSAGE + +/obj/machinery/alarm/wirecutter_act(mob/user, obj/item/I) + if(buildstage != AIR_ALARM_READY) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(wires.wires_status == 31) // all wires cut + var/obj/item/stack/cable_coil/new_coil = new /obj/item/stack/cable_coil(user.drop_location()) + new_coil.amount = 5 + buildstage = AIR_ALARM_BUILDING + update_icon() + if(wiresexposed) + wires.Interact(user) + +/obj/machinery/alarm/wrench_act(mob/user, obj/item/I) + if(buildstage != AIR_ALARM_FRAME) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + new /obj/item/mounted/frame/alarm_frame(get_turf(user)) + WRENCH_UNANCHOR_WALL_MESSAGE + qdel(src) + /obj/machinery/alarm/power_change() if(powered(power_channel)) stat &= ~NOPOWER @@ -1076,3 +1103,8 @@ Just an object used in constructing air alarms origin_tech = "engineering=2;programming=1" toolspeed = 1 usesound = 'sound/items/deconstruct.ogg' + + +#undef AIR_ALARM_FRAME +#undef AIR_ALARM_BUILDING +#undef AIR_ALARM_READY diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index 3210e899876..230401b673b 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -78,7 +78,6 @@ var/datum/canister_icons/canister_icon_container = new() use_power = NO_POWER_USE interact_offline = 1 var/release_log = "" - var/busy = 0 var/update_flag = 0 /obj/machinery/portable_atmospherics/canister/New() @@ -264,22 +263,6 @@ update_flag return canister_break() -/obj/machinery/portable_atmospherics/canister/attackby(obj/item/I, mob/user, params) - if(user.a_intent != INTENT_HARM && iswelder(I)) - var/obj/item/weldingtool/WT = I - if(stat & BROKEN) - if(!WT.remove_fuel(0, user)) - return - playsound(loc, WT.usesound, 40, 1) - to_chat(user, "You begin cutting [src] apart...") - if(do_after(user, 30, target = src)) - deconstruct(TRUE) - else - to_chat(user, "You cannot slice [src] apart when it isn't broken.") - return TRUE - else - return ..() - /obj/machinery/portable_atmospherics/canister/proc/canister_break() disconnect() var/datum/gas_mixture/expelled_gas = air_contents.remove(air_contents.total_moles()) @@ -610,21 +593,14 @@ update_flag src.update_icon() // Otherwise new canisters do not have their icon updated with the pressure light, likely want to add this to the canister class constructor, avoiding at current time to refrain from screwing up code for other canisters. --DZD return 1 -/obj/machinery/portable_atmospherics/canister/proc/weld(var/obj/item/weldingtool/WT, var/mob/user) - - if(busy) - return 0 - if(!WT.remove_fuel(0, user)) - return 0 - - // Do after stuff here - to_chat(user, "You start to slice away at \the [src]...") - playsound(src.loc, WT.usesound, 50, 1) - busy = 1 - if(do_after(user, 50 * WT.toolspeed, target = src)) - busy = 0 - if(!WT.isOn()) - return 0 - return 1 - busy = 0 - return 0 +/obj/machinery/portable_atmospherics/canister/welder_act(mob/user, obj/item/I) + if(!(stat & BROKEN)) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_SLICING_MESSAGE + if(I.use_tool(src, user, 50, volume = I.tool_volume)) + to_chat(user, "You salvage whats left of [src]!") + new /obj/item/stack/sheet/metal(drop_location(), 3) + qdel(src) diff --git a/code/game/machinery/atmoalter/portable_atmospherics.dm b/code/game/machinery/atmoalter/portable_atmospherics.dm index b7c2dd152da..5008f4791ba 100644 --- a/code/game/machinery/atmoalter/portable_atmospherics.dm +++ b/code/game/machinery/atmoalter/portable_atmospherics.dm @@ -126,30 +126,32 @@ src.holding = T update_icon() return - else if(istype(W, /obj/item/wrench)) - if(connected_port) - disconnect() - to_chat(user, "You disconnect [name] from the port.") - update_icon() - return - else - var/obj/machinery/atmospherics/unary/portables_connector/possible_port = locate(/obj/machinery/atmospherics/unary/portables_connector/) in loc - if(possible_port) - if(connect(possible_port)) - to_chat(user, "You connect [name] to the port.") - update_icon() - return - else - to_chat(user, "[name] failed to connect to the port.") - return - else - to_chat(user, "Nothing happens.") - return if((istype(W, /obj/item/analyzer)) && get_dist(user, src) <= 1) atmosanalyzer_scan(air_contents, user) return return ..() +/obj/machinery/portable_atmospherics/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(connected_port) + disconnect() + to_chat(user, "You disconnect [name] from the port.") + update_icon() + else + var/obj/machinery/atmospherics/unary/portables_connector/possible_port = locate(/obj/machinery/atmospherics/unary/portables_connector/) in loc + if(possible_port) + if(connect(possible_port)) + to_chat(user, "You connect [src] to the port.") + update_icon() + return + else + to_chat(user, "[src] failed to connect to the port.") + return + else + to_chat(user, "Nothing happens.") + /obj/machinery/portable_atmospherics/attacked_by(obj/item/I, mob/user) if(I.force < 10 && !(stat & BROKEN)) take_damage(0) diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index ae0611e69d4..52ee48f067b 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -174,21 +174,8 @@ if(busy) to_chat(user, "The autolathe is busy. Please wait for completion of previous operation.") return 1 - - if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", O)) - SSnanoui.update_uis(src) - return - if(exchange_parts(user, O)) return - - if(panel_open) - if(istype(O, /obj/item/crowbar)) - default_deconstruction_crowbar(O) - return 1 - else - attack_hand(user) - return 1 if(stat) return 1 @@ -215,6 +202,50 @@ return ..() +/obj/machinery/autolathe/crowbar_act(mob/user, obj/item/I) + if(!I.use_tool(src, user, 0, volume = 0)) + return + . = TRUE + if(busy) + to_chat(user, "The autolathe is busy. Please wait for completion of previous operation.") + return + if(panel_open) + default_deconstruction_crowbar(user, I) + I.play_tool_sound(user, I.tool_volume) + +/obj/machinery/autolathe/screwdriver_act(mob/user, obj/item/I) + if(!I.use_tool(src, user, 0, volume = 0)) + return + . = TRUE + if(busy) + to_chat(user, "The autolathe is busy. Please wait for completion of previous operation.") + return + if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", I)) + SSnanoui.update_uis(src) + I.play_tool_sound(user, I.tool_volume) + +/obj/machinery/autolathe/wirecutter_act(mob/user, obj/item/I) + if(!panel_open) + return + if(!I.use_tool(src, user, 0, volume = 0)) + return + . = TRUE + if(busy) + to_chat(user, "The autolathe is busy. Please wait for completion of previous operation.") + return + interact(user) + +/obj/machinery/autolathe/multitool_act(mob/user, obj/item/I) + if(!panel_open) + return + if(!I.use_tool(src, user, 0, volume = 0)) + return + . = TRUE + if(busy) + to_chat(user, "The autolathe is busy. Please wait for completion of previous operation.") + return + interact(user) + /obj/machinery/autolathe/proc/AfterMaterialInsert(type_inserted, id_inserted, amount_inserted) switch(id_inserted) if(MAT_METAL) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 7e0508ba24f..bb09c247bca 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -127,27 +127,7 @@ var/msg = "You attach [I] into the assembly inner circuits." var/msg2 = "The camera already has that upgrade!" - // DECONSTRUCTION - if(isscrewdriver(I)) - panel_open = !panel_open - to_chat(user, "You screw the camera's panel [panel_open ? "open" : "closed"].") - playsound(loc, I.usesound, 50, 1) - - else if((iswirecutter(I) || ismultitool(I)) && panel_open) - wires.Interact(user) - - else if(iswelder(I) && panel_open && wires.CanDeconstruct()) - var/obj/item/weldingtool/WT = I - if(!WT.remove_fuel(0, user)) - return - to_chat(user, "You start to weld [src]...") - playsound(loc, WT.usesound, 50, 1) - if(do_after(user, 100 * WT.toolspeed, target = src)) - user.visible_message("[user] unwelds [src], leaving it as just a frame bolted to the wall.", - "You unweld [src], leaving it as just a frame bolted to the wall") - deconstruct(TRUE) - - else if(istype(I, /obj/item/analyzer) && panel_open) //XRay + if(istype(I, /obj/item/analyzer) && panel_open) //XRay if(!user.drop_item()) to_chat(user, "[I] is stuck to your hand!") return @@ -233,6 +213,40 @@ else return ..() + +/obj/machinery/camera/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + panel_open = !panel_open + to_chat(user, "You screw [src]'s panel [panel_open ? "open" : "closed"].") + +/obj/machinery/camera/wirecutter_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = 0)) + return + if(panel_open) + wires.Interact(user) + +/obj/machinery/camera/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = 0)) + return + if(panel_open) + wires.Interact(user) + +/obj/machinery/camera/welder_act(mob/user, obj/item/I) + if(!panel_open || !wires.CanDeconstruct()) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_WELD_MESSAGE + if(I.use_tool(src, user, 100, volume = I.tool_volume)) + visible_message("[user] unwelds [src], leaving it as just a frame bolted to the wall.", + "You unweld [src], leaving it as just a frame bolted to the wall") + deconstruct(TRUE) + /obj/machinery/camera/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir) if(stat & BROKEN) return damage_amount diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index 34915f2d01b..bd795ab340b 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -3,6 +3,7 @@ #define ASSEMBLY_WELDED 2 // Welded in place #define ASSEMBLY_WIRED 3 // Wires attached (Upgradable now) #define ASSEMBLY_BUILT 4 // Fully built (incl panel closed) +#define HEY_IM_WORKING_HERE 666 //So nobody can mess with the camera while we're inputting settings /obj/item/camera_assembly name = "camera assembly" @@ -16,7 +17,6 @@ var/list/obj/item/possible_upgrades = list(/obj/item/assembly/prox_sensor, /obj/item/stack/sheet/mineral/plasma, /obj/item/analyzer) var/list/upgrades = list() var/state = ASSEMBLY_UNBUILT - var/busy = FALSE /obj/item/camera_assembly/Destroy() @@ -24,106 +24,18 @@ return ..() /obj/item/camera_assembly/attackby(obj/item/I, mob/living/user, params) - - switch(state) - if(ASSEMBLY_UNBUILT) - // State 0 - if(iswrench(I) && isturf(loc)) - playsound(loc, I.usesound, 50, 1) - to_chat(user, "You wrench the assembly into place.") - anchored = 1 - state = ASSEMBLY_WRENCHED - update_icon() - auto_turn() - return - - if(ASSEMBLY_WRENCHED) - // State 1 - if(iswelder(I)) - if(weld(I, user)) - to_chat(user, "You weld the assembly securely into place.") - anchored = TRUE - state = ASSEMBLY_WELDED - return - - else if(iswrench(I)) - playsound(loc, I.usesound, 50, 1) - to_chat(user, "You unattach the assembly from it's place.") - anchored = FALSE - update_icon() - state = ASSEMBLY_UNBUILT - return - - if(ASSEMBLY_WELDED) - if(iscoil(I)) - var/obj/item/stack/cable_coil/C = I - if(C.use(2)) - to_chat(user, "You add wires to the assembly.") - playsound(loc, I.usesound, 50, 1) - state = ASSEMBLY_WIRED - else - to_chat(user, "You need 2 coils of wire to wire the assembly.") - return - - else if(iswelder(I)) - if(weld(I, user)) - to_chat(user, "You unweld the assembly from it's place.") - state = ASSEMBLY_WRENCHED - anchored = TRUE - return - - - if(ASSEMBLY_WIRED) - if(isscrewdriver(I)) - playsound(loc, I.usesound, 50, 1) - - var/input = strip_html(input(usr, "Which networks would you like to connect this camera to? Seperate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Set Network", "SS13")) - if(!input) - to_chat(usr, "No input found please hang up and try your call again.") - return - - var/list/tempnetwork = splittext(input, ",") - if(tempnetwork.len < 1) - to_chat(usr, "No network found please hang up and try your call again.") - return - - var/area/camera_area = get_area(src) - var/temptag = "[sanitize(camera_area.name)] ([rand(1, 999)])" - input = strip_html(input(usr, "How would you like to name the camera?", "Set Camera Name", temptag)) - - state = ASSEMBLY_BUILT - var/obj/machinery/camera/C = new(loc) - loc = C - C.assembly = src - - C.auto_turn() - - C.network = uniquelist(tempnetwork) - tempnetwork = difflist(C.network,GLOB.restricted_camera_networks) - if(!tempnetwork.len) // Camera isn't on any open network - remove its chunk from AI visibility. - cameranet.removeCamera(C) - - C.c_tag = input - - for(var/i = 5; i >= 0; i -= 1) - var/direct = input(user, "Direction?", "Assembling Camera", null) in list("LEAVE IT", "NORTH", "EAST", "SOUTH", "WEST" ) - if(direct != "LEAVE IT") - C.dir = text2dir(direct) - if(i != 0) - var/confirm = alert(user, "Is this what you want? Chances Remaining: [i]", "Confirmation", "Yes", "No") - if(confirm == "Yes") - break - return - - else if(iswirecutter(I)) - new/obj/item/stack/cable_coil(get_turf(src), 2) - playsound(loc, I.usesound, 50, 1) - to_chat(user, "You cut the wires from the circuits.") - state = ASSEMBLY_WELDED - return + if(state == ASSEMBLY_WELDED && iscoil(I)) + var/obj/item/stack/cable_coil/C = I + if(C.use(2)) + to_chat(user, "You add wires to the assembly.") + playsound(loc, I.usesound, 50, 1) + state = ASSEMBLY_WIRED + else + to_chat(user, "You need 2 coils of wire to wire the assembly.") + return // Upgrades! - if(is_type_in_list(I, possible_upgrades) && !is_type_in_list(I, upgrades)) // Is a possible upgrade and isn't in the camera already. + else if(is_type_in_list(I, possible_upgrades) && !is_type_in_list(I, upgrades)) // Is a possible upgrade and isn't in the camera already. if(!user.unEquip(I)) to_chat(user, "[I] is stuck!") return @@ -132,20 +44,117 @@ user.drop_item() I.loc = src return - - // Taking out upgrades - else if(iscrowbar(I) && upgrades.len) - var/obj/U = locate(/obj) in upgrades - if(U) - to_chat(user, "You unattach an upgrade from the assembly.") - playsound(loc, I.usesound, 50, 1) - U.loc = get_turf(src) - upgrades -= U - return - else return ..() +/obj/item/camera_assembly/crowbar_act(mob/user, obj/item/I) + if(!upgrades.len) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + var/obj/U = locate(/obj) in upgrades + if(U) + to_chat(user, "You unattach an upgrade from the assembly.") + playsound(loc, I.usesound, 50, 1) + U.loc = get_turf(src) + upgrades -= U + +/obj/item/camera_assembly/screwdriver_act(mob/user, obj/item/I) + if(state != ASSEMBLY_WIRED) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + state = HEY_IM_WORKING_HERE + var/input = strip_html(input(usr, "Which networks would you like to connect this camera to? Seperate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Set Network", "SS13")) + if(!input) + state = ASSEMBLY_WIRED + to_chat(usr, "No input found please hang up and try your call again.") + return + + var/list/tempnetwork = splittext(input, ",") + if(tempnetwork.len < 1) + state = ASSEMBLY_WIRED + to_chat(usr, "No network found please hang up and try your call again.") + return + + var/area/camera_area = get_area(src) + var/temptag = "[sanitize(camera_area.name)] ([rand(1, 999)])" + input = strip_html(input(usr, "How would you like to name the camera?", "Set Camera Name", temptag)) + state = ASSEMBLY_BUILT + var/obj/machinery/camera/C = new(loc) + loc = C + C.assembly = src + + C.auto_turn() + + C.network = uniquelist(tempnetwork) + tempnetwork = difflist(C.network,GLOB.restricted_camera_networks) + if(!tempnetwork.len) // Camera isn't on any open network - remove its chunk from AI visibility. + cameranet.removeCamera(C) + + C.c_tag = input + + for(var/i = 5; i >= 0; i -= 1) + var/direct = input(user, "Direction?", "Assembling Camera", null) in list("LEAVE IT", "NORTH", "EAST", "SOUTH", "WEST" ) + if(direct != "LEAVE IT") + C.dir = text2dir(direct) + if(i != 0) + var/confirm = alert(user, "Is this what you want? Chances Remaining: [i]", "Confirmation", "Yes", "No") + if(confirm == "Yes") + break + + +/obj/item/camera_assembly/wirecutter_act(mob/user, obj/item/I) + if(state != ASSEMBLY_WIRED) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + new/obj/item/stack/cable_coil(get_turf(src), 2) + WIRECUTTER_SNIP_MESSAGE + state = ASSEMBLY_WELDED + return + +/obj/item/camera_assembly/wrench_act(mob/user, obj/item/I) + if(state != ASSEMBLY_UNBUILT && state != ASSEMBLY_WRENCHED) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(state == ASSEMBLY_UNBUILT && isturf(loc)) + WRENCH_ANCHOR_TO_WALL_MESSAGE + anchored = TRUE + state = ASSEMBLY_WRENCHED + update_icon() + auto_turn() + else if(state == ASSEMBLY_WRENCHED) + WRENCH_UNANCHOR_WALL_MESSAGE + anchored = FALSE + update_icon() + state = ASSEMBLY_UNBUILT + else + to_chat(user, "[src] can't fit here!") + +/obj/item/camera_assembly/welder_act(mob/user, obj/item/I) + if(state == ASSEMBLY_UNBUILT) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_WELD_MESSAGE + if(state == ASSEMBLY_WRENCHED) + if(!I.use_tool(src, user, 50, volume = I.tool_volume)) + return + to_chat(user, "You weld [src] into place.") + state = ASSEMBLY_WELDED + else if(state == ASSEMBLY_WELDED) + if(!I.use_tool(src, user, 50, volume = I.tool_volume)) + return + to_chat(user, "You unweld [src] from its place.") + state = ASSEMBLY_WRENCHED + /obj/item/camera_assembly/update_icon() if(anchored) icon_state = "camera1" @@ -156,23 +165,6 @@ if(!anchored) ..() -/obj/item/camera_assembly/proc/weld(obj/item/weldingtool/WT, mob/living/user) - if(busy) - return FALSE - if(!WT.remove_fuel(0, user)) - return FALSE - - to_chat(user, "You start to weld the [src]...") - playsound(loc, WT.usesound, 50, 1) - busy = TRUE - if(do_after(user, 20 * WT.toolspeed, target = src)) - busy = FALSE - if(!WT.isOn()) - return FALSE - return TRUE - busy = FALSE - return FALSE - /obj/item/camera_assembly/deconstruct(disassembled = TRUE) if(!(flags & NODECONSTRUCT)) new /obj/item/stack/sheet/metal(loc) @@ -184,3 +176,4 @@ #undef ASSEMBLY_WELDED #undef ASSEMBLY_WIRED #undef ASSEMBLY_BUILT +#undef HEY_IM_WORKING_HERE diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index e6c957c1779..fb87d91e3f0 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -68,17 +68,22 @@ user.visible_message("[user] inserts a cell into the charger.", "You insert a cell into the charger.") chargelevel = -1 updateicon() - else if(iswrench(I)) - if(charging) - to_chat(user, "Remove the cell first!") - return - - anchored = !anchored - to_chat(user, "You [anchored ? "attach" : "detach"] the cell charger [anchored ? "to" : "from"] the ground") - playsound(src.loc, I.usesound, 75, 1) else return ..() +/obj/machinery/cell_charger/wrench_act(mob/user, obj/item/I) + . = TRUE + if(charging) + to_chat(user, "Remove the cell first!") + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + anchored = !anchored + if(anchored) + WRENCH_ANCHOR_MESSAGE + else + WRENCH_UNANCHOR_MESSAGE + /obj/machinery/cell_charger/proc/removecell() charging.update_icon() diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 83a12a6ff81..b810c3a3b73 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -126,6 +126,7 @@ read_only = 1 /obj/item/disk/data/demo/New() + ..() initialize() buf.types=DNA2_BUF_UE|DNA2_BUF_UI //data = "066000033000000000AF00330660FF4DB002690" @@ -145,6 +146,7 @@ read_only = 1 /obj/item/disk/data/monkey/New() + ..() initialize() buf.types=DNA2_BUF_SE var/list/new_SE=list(0x098,0x3E8,0x403,0x44C,0x39F,0x4B0,0x59D,0x514,0x5FC,0x578,0x5DC,0x640,0x6A4) @@ -363,16 +365,9 @@ //Let's unlock this early I guess. Might be too early, needs tweaking. /obj/machinery/clonepod/attackby(obj/item/I, mob/user, params) - if(!(occupant || mess)) - if(default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]", I)) - return - if(exchange_parts(user, I)) return - if(default_deconstruction_crowbar(I)) - return - if(I.GetID()) if(!check_access(I)) to_chat(user, "Access Denied.") @@ -392,29 +387,42 @@ to_chat(user, "[src] processes [I].") biomass += BIOMASS_MEAT_AMOUNT qdel(I) - else if(iswrench(I)) - if(occupant) - to_chat(user, "Can not do that while [src] is in use.") - else - if(anchored) - anchored = FALSE - connected.pods -= src - connected = null - else - anchored = TRUE - playsound(loc, I.usesound, 100, 1) - if(anchored) - user.visible_message("[user] secures [src] to the floor.", "You secure [src] to the floor.") - else - user.visible_message("[user] unsecures [src] from the floor.", "You unsecure [src] from the floor.") - else if(ismultitool(I)) - var/obj/item/multitool/M = I - M.buffer = src - to_chat(user, "You load connection data from [src] to [M].") - return else return ..() +/obj/machinery/clonepod/crowbar_act(mob/user, obj/item/I) + . = TRUE + default_deconstruction_crowbar(user, I) + +/obj/machinery/clonepod/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!I.multitool_check_buffer(user)) + return + var/obj/item/multitool/M = I + M.set_multitool_buffer(user, src) + +/obj/machinery/clonepod/screwdriver_act(mob/user, obj/item/I) + . = TRUE + default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]", I) + +/obj/machinery/clonepod/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(occupant) + to_chat(user, "Can not do that while [src] is in use.") + return + if(anchored) + WRENCH_UNANCHOR_MESSAGE + anchored = FALSE + connected.pods -= src + connected = null + else + WRENCH_ANCHOR_MESSAGE + anchored = TRUE + /obj/machinery/clonepod/emag_act(user) if(isnull(occupant)) return diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm index 4c730963519..cb5e4da5e95 100644 --- a/code/game/machinery/computer/HolodeckControl.dm +++ b/code/game/machinery/computer/HolodeckControl.dm @@ -415,9 +415,11 @@ var/active = 0 /obj/item/holo/esword/green/New() + ..() item_color = "green" /obj/item/holo/esword/red/New() + ..() item_color = "red" /obj/item/holo/esword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) @@ -426,6 +428,7 @@ return 0 /obj/item/holo/esword/New() + ..() item_color = pick("red","blue","green","purple") /obj/item/holo/esword/attack_self(mob/living/user as mob) diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index dfac3250d44..8d27ac5e7fa 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -17,197 +17,185 @@ return ..() /obj/structure/AIcore/attackby(obj/item/P, mob/user, params) - if(istype(P, /obj/item/wrench)) - return default_unfasten_wrench(user, P, 20) - if(!anchored) - if(iswelder(P)) - if(state != EMPTY_CORE) - to_chat(user, "The core must be empty to deconstruct it!") + switch(state) + if(EMPTY_CORE) + if(istype(P, /obj/item/circuitboard/aicore)) + if(!user.drop_item()) + return + playsound(loc, P.usesound, 50, 1) + to_chat(user, "You place the circuit board inside the frame.") + update_icon() + state = CIRCUIT_CORE + P.forceMove(src) + circuit = P return - var/obj/item/weldingtool/WT = P - if(!WT.isOn()) - to_chat(user, "The welder must be on for this task!") - return - playsound(loc, WT.usesound, 50, 1) - to_chat(user, "You start to deconstruct the frame...") - if(do_after(user, 20*P.toolspeed, target = src) && src && state == EMPTY_CORE && WT && WT.remove_fuel(0, user)) - to_chat(user, "You deconstruct the frame.") - deconstruct(TRUE) - return - else - switch(state) - if(EMPTY_CORE) - if(istype(P, /obj/item/circuitboard/aicore)) - if(!user.drop_item()) - return - playsound(loc, P.usesound, 50, 1) - to_chat(user, "You place the circuit board inside the frame.") - update_icon() - state = CIRCUIT_CORE - P.forceMove(src) - circuit = P - return - if(CIRCUIT_CORE) - if(isscrewdriver(P)) - playsound(loc, P.usesound, 50, 1) - to_chat(user, "You screw the circuit board into place.") - state = SCREWED_CORE - update_icon() - return - if(iscrowbar(P)) - playsound(loc, P.usesound, 50, 1) - to_chat(user, "You remove the circuit board.") - state = EMPTY_CORE - update_icon() - circuit.forceMove(loc) - circuit = null - return - if(SCREWED_CORE) - if(iswirecutter(P) && circuit) - playsound(loc, P.usesound, 50, 1) - to_chat(user, "You unfasten the circuit board.") - state = CIRCUIT_CORE - update_icon() - return - if(istype(P, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C = P - if(C.get_amount() >= 5) - playsound(loc, 'sound/items/deconstruct.ogg', 50, 1) - to_chat(user, "You start to add cables to the frame...") - if(do_after(user, 20, target = src) && state == SCREWED_CORE && C.use(5)) - to_chat(user, "You add cables to the frame.") - state = CABLED_CORE - update_icon() - else - to_chat(user, "You need five lengths of cable to wire the AI core!") - return - if(CABLED_CORE) - if(iswirecutter(P)) - if(brain) - to_chat(user, "Get that [brain.name] out of there first!") - else - playsound(loc, P.usesound, 50, 1) - to_chat(user, "You remove the cables.") - state = SCREWED_CORE + if(SCREWED_CORE) + if(istype(P, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C = P + if(C.get_amount() >= 5) + playsound(loc, 'sound/items/deconstruct.ogg', 50, 1) + to_chat(user, "You start to add cables to the frame...") + if(do_after(user, 20, target = src) && state == SCREWED_CORE && C.use(5)) + to_chat(user, "You add cables to the frame.") + state = CABLED_CORE update_icon() - var/obj/item/stack/cable_coil/A = new /obj/item/stack/cable_coil( loc ) - A.amount = 5 + else + to_chat(user, "You need five lengths of cable to wire the AI core!") + return + if(CABLED_CORE) + if(istype(P, /obj/item/stack/sheet/rglass)) + var/obj/item/stack/sheet/rglass/G = P + if(G.get_amount() >= 2) + playsound(loc, 'sound/items/deconstruct.ogg', 50, 1) + to_chat(user, "You start to put in the glass panel...") + if(do_after(user, 20, target = src) && state == CABLED_CORE && G.use(2)) + to_chat(user, "You put in the glass panel.") + state = GLASS_CORE + update_icon() + else + to_chat(user, "You need two sheets of reinforced glass to insert them into the AI core!") + return + + if(istype(P, /obj/item/aiModule/purge)) + laws.clear_inherent_laws() + to_chat(usr, "Law module applied.") + return + + if(istype(P, /obj/item/aiModule/freeform)) + var/obj/item/aiModule/freeform/M = P + laws.add_inherent_law(M.newFreeFormLaw) + to_chat(usr, "Added a freeform law.") + return + + if(istype(P, /obj/item/aiModule)) + var/obj/item/aiModule/M = P + if(!M.laws) + to_chat(usr, "This AI module can not be applied directly to AI cores.") + return + laws = M.laws + + if(istype(P, /obj/item/mmi) && !brain) + var/obj/item/mmi/M = P + if(!M.brainmob) + to_chat(user, "Sticking an empty [P] into the frame would sort of defeat the purpose.") + return + if(M.brainmob.stat == DEAD) + to_chat(user, "Sticking a dead [P] into the frame would sort of defeat the purpose.") return - if(istype(P, /obj/item/stack/sheet/rglass)) - var/obj/item/stack/sheet/rglass/G = P - if(G.get_amount() >= 2) - playsound(loc, 'sound/items/deconstruct.ogg', 50, 1) - to_chat(user, "You start to put in the glass panel...") - if(do_after(user, 20, target = src) && state == CABLED_CORE && G.use(2)) - to_chat(user, "You put in the glass panel.") - state = GLASS_CORE - update_icon() - else - to_chat(user, "You need two sheets of reinforced glass to insert them into the AI core!") + if(!M.brainmob.client) + to_chat(user, "Sticking an inactive [M.name] into the frame would sort of defeat the purpose.") return - if(istype(P, /obj/item/aiModule/purge)) - laws.clear_inherent_laws() - to_chat(usr, "Law module applied.") + if(jobban_isbanned(M.brainmob, "AI") || jobban_isbanned(M.brainmob, "nonhumandept")) + to_chat(user, "This [P] does not seem to fit.") return - if(istype(P, /obj/item/aiModule/freeform)) - var/obj/item/aiModule/freeform/M = P - laws.add_inherent_law(M.newFreeFormLaw) - to_chat(usr, "Added a freeform law.") + if(!M.brainmob.mind) + to_chat(user, "This [M.name] is mindless!") return - if(istype(P, /obj/item/aiModule)) - var/obj/item/aiModule/M = P - if(!M.laws) - to_chat(usr, "This AI module can not be applied directly to AI cores.") - return - laws = M.laws - - if(istype(P, /obj/item/mmi) && !brain) - var/obj/item/mmi/M = P - if(!M.brainmob) - to_chat(user, "Sticking an empty [P] into the frame would sort of defeat the purpose.") - return - if(M.brainmob.stat == DEAD) - to_chat(user, "Sticking a dead [P] into the frame would sort of defeat the purpose.") - return - - if(!M.brainmob.client) - to_chat(user, "Sticking an inactive [M.name] into the frame would sort of defeat the purpose.") - return - - if(jobban_isbanned(M.brainmob, "AI") || jobban_isbanned(M.brainmob, "nonhumandept")) - to_chat(user, "This [P] does not seem to fit.") - return - - if(!M.brainmob.mind) - to_chat(user, "This [M.name] is mindless!") - return - - if(istype(P, /obj/item/mmi/syndie)) - to_chat(user, "This MMI does not seem to fit!") - return - - if(!user.drop_item()) - return - - M.forceMove(src) - brain = M - to_chat(user, "You add [M.name] to the frame.") - update_icon() + if(istype(P, /obj/item/mmi/syndie)) + to_chat(user, "This MMI does not seem to fit!") return - if(iscrowbar(P) && brain) - playsound(loc, P.usesound, 50, 1) - to_chat(user, "You remove the brain.") - brain.forceMove(loc) - brain = null - update_icon() + if(!user.drop_item()) return - if(GLASS_CORE) - if(istype(P, /obj/item/crowbar)) - playsound(loc, P.usesound, 50, 1) - to_chat(user, "You remove the glass panel.") - state = CABLED_CORE - update_icon() - new /obj/item/stack/sheet/rglass(loc, 2) - return + M.forceMove(src) + brain = M + to_chat(user, "You add [M.name] to the frame.") + update_icon() + return - if(isscrewdriver(P)) - playsound(loc, P.usesound, 50, 1) - to_chat(user, "You connect the monitor.") - if(!brain) - var/open_for_latejoin = alert(user, "Would you like this core to be open for latejoining AIs?", "Latejoin", "Yes", "Yes", "No") == "Yes" - var/obj/structure/AIcore/deactivated/D = new(loc) - if(open_for_latejoin) - empty_playable_ai_cores += D - else - if(brain.brainmob.mind) - SSticker.mode.remove_cultist(brain.brainmob.mind, 1) - SSticker.mode.remove_revolutionary(brain.brainmob.mind, 1) - - var/mob/living/silicon/ai/A = new /mob/living/silicon/ai(loc, laws, brain) - if(A) //if there's no brain, the mob is deleted and a structure/AIcore is created - A.rename_self("AI", 1) - feedback_inc("cyborg_ais_created",1) - qdel(src) - - if(AI_READY_CORE) - if(istype(P, /obj/item/aicard)) - P.transfer_ai("INACTIVE", "AICARD", src, user) - return - - if(isscrewdriver(P)) - playsound(loc, P.usesound, 50, 1) - to_chat(user, "You disconnect the monitor.") - state = GLASS_CORE - update_icon() - return + if(AI_READY_CORE) + if(istype(P, /obj/item/aicard)) + P.transfer_ai("INACTIVE", "AICARD", src, user) + return return ..() +/obj/structure/AIcore/crowbar_act(mob/living/user, obj/item/I) + if(state !=CIRCUIT_CORE || state != GLASS_CORE || !(state == CABLED_CORE && brain)) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + switch(state) + if(CIRCUIT_CORE) + to_chat(user, "You remove the circuit board.") + state = EMPTY_CORE + circuit.forceMove(loc) + circuit = null + return + if(GLASS_CORE) + to_chat(user, "You remove the glass panel.") + state = CABLED_CORE + new /obj/item/stack/sheet/rglass(loc, 2) + return + if(CABLED_CORE) + if(brain) + to_chat(user, "You remove the brain.") + brain.forceMove(loc) + brain = null + update_icon() + +/obj/structure/AIcore/screwdriver_act(mob/living/user, obj/item/I) + if(!(state in list(SCREWED_CORE, CIRCUIT_CORE, GLASS_CORE, AI_READY_CORE))) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + switch(state) + if(SCREWED_CORE) + to_chat(user, "You unfasten the circuit board.") + state = CIRCUIT_CORE + if(CIRCUIT_CORE) + to_chat(user, "You screw the circuit board into place.") + state = SCREWED_CORE + if(GLASS_CORE) + to_chat(user, "You connect the monitor.") + if(!brain) + var/open_for_latejoin = alert(user, "Would you like this core to be open for latejoining AIs?", "Latejoin", "Yes", "Yes", "No") == "Yes" + var/obj/structure/AIcore/deactivated/D = new(loc) + if(open_for_latejoin) + empty_playable_ai_cores += D + else + if(brain.brainmob.mind) + SSticker.mode.remove_cultist(brain.brainmob.mind, 1) + SSticker.mode.remove_revolutionary(brain.brainmob.mind, 1) + + var/mob/living/silicon/ai/A = new /mob/living/silicon/ai(loc, laws, brain) + if(A) //if there's no brain, the mob is deleted and a structure/AIcore is created + A.rename_self("AI", 1) + feedback_inc("cyborg_ais_created",1) + qdel(src) + if(AI_READY_CORE) + to_chat(user, "You disconnect the monitor.") + state = GLASS_CORE + update_icon() + + +/obj/structure/AIcore/wirecutter_act(mob/living/user, obj/item/I) + if(state != CABLED_CORE) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(brain) + to_chat(user, "Get that [brain.name] out of there first!") + else + to_chat(user, "You remove the cables.") + state = SCREWED_CORE + update_icon() + var/obj/item/stack/cable_coil/A = new /obj/item/stack/cable_coil( loc ) + A.amount = 5 + +/obj/structure/AIcore/wrench_act(mob/living/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + default_unfasten_wrench(user, I, 20) + /obj/structure/AIcore/update_icon() switch(state) if(EMPTY_CORE) @@ -237,6 +225,18 @@ new /obj/item/stack/sheet/plasteel(loc, 4) qdel(src) +/obj/structure/AIcore/welder_act(mob/user, obj/item/I) + if(!state) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_WELD_MESSAGE + if(I.use_tool(src, user, 20, volume = I.tool_volume)) + to_chat(user, "You deconstruct the frame.") + new /obj/item/stack/sheet/plasteel(drop_location(), 4) + qdel(src) + /obj/structure/AIcore/deactivated name = "inactive AI" icon_state = "ai-empty" diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index 9e8bc08f9b2..6b0e167cbb6 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -454,17 +454,6 @@ anchored = 1 state = 1 return - if(istype(P, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = P - if(!WT.remove_fuel(0, user)) - to_chat(user, "The welding tool must be on to complete this task.") - return - playsound(loc, WT.usesound, 50, 1) - if(do_after(user, 20 * WT.toolspeed, target = src)) - if(!src || !WT.isOn()) return - to_chat(user, "You deconstruct the frame.") - deconstruct(TRUE) - return if(1) if(istype(P, /obj/item/wrench)) playsound(loc, P.usesound, 50, 1) @@ -573,6 +562,18 @@ return ..() +/obj/structure/computerframe/welder_act(mob/user, obj/item/I) + if(state) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_SLICING_MESSAGE + if(I.use_tool(src, user, 50, volume = I.tool_volume) && !state) + to_chat(user, "You deconstruct [src].") + deconstruct(TRUE) + + /obj/structure/computerframe/HONKputer name = "Bananium Computer-frame" @@ -588,17 +589,6 @@ to_chat(user, "You wrench the frame into place.") anchored = 1 state = 1 - if(istype(P, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = P - if(!WT.remove_fuel(0, user)) - to_chat(user, "The welding tool must be on to complete this task.") - return - playsound(loc, WT.usesound, 50, 1) - if(do_after(user, 20 * WT.toolspeed, target = src)) - if(!src || !WT.isOn()) return - to_chat(user, "You deconstruct the frame.") - deconstruct(TRUE) - return if(1) if(istype(P, /obj/item/wrench)) playsound(loc, P.usesound, 50, 1) diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 45f390082a1..3462677d615 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -79,24 +79,24 @@ ui_interact(user) -/obj/machinery/computer/security/telescreen/attackby(obj/item/I, mob/user, params) - if(ismultitool(I)) - var/direction = input(user, "Which direction?", "Select direction!") as null|anything in list("North", "East", "South", "West", "Centre") - if(!direction || !Adjacent(user)) - return - pixel_x = 0 - pixel_y = 0 - switch(direction) - if("North") - pixel_y = 32 - if("East") - pixel_x = 32 - if("South") - pixel_y = -32 - if("West") - pixel_x = -32 - else - return ..() +/obj/machinery/computer/security/telescreen/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + var/direction = input(user, "Which direction?", "Select direction!") as null|anything in list("North", "East", "South", "West", "Centre") + if(!direction || !Adjacent(user)) + return + pixel_x = 0 + pixel_y = 0 + switch(direction) + if("North") + pixel_y = 32 + if("East") + pixel_x = 32 + if("South") + pixel_y = -32 + if("West") + pixel_x = -32 /obj/machinery/computer/security/emag_act(user as mob) if(!emagged) diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index 438c8f92246..aec41c80be3 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -133,10 +133,10 @@ if(istype(user, /mob/dead/observer)) return 0 return ..() -/obj/machinery/computer/attackby(obj/item/I, mob/user, params) - if(isscrewdriver(I) && circuit && !(flags & NODECONSTRUCT)) - playsound(loc, I.usesound, 50, TRUE) - if(do_after(user, 20 * I.toolspeed, target = src)) - deconstruct(TRUE, user) +/obj/machinery/computer/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_start_check(user, 0)) return - return ..() \ No newline at end of file + if(circuit && !(flags & NODECONSTRUCT)) + if(I.use_tool(src, user, 20, volume = I.tool_volume)) + deconstruct(TRUE, user) diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm index fef40c9f93a..55107809ce3 100644 --- a/code/game/machinery/computer/message.dm +++ b/code/game/machinery/computer/message.dm @@ -35,11 +35,8 @@ light_color = LIGHT_COLOR_DARKGREEN -/obj/machinery/computer/message_monitor/attackby(obj/item/O as obj, mob/living/user as mob, params) - if(!istype(user)) - return - if(isscrewdriver(O) && emag) - //Stops people from just unscrewing the monitor and putting it back to get the console working again. +/obj/machinery/computer/message_monitor/screwdriver_act(mob/user, obj/item/I) + if(emag) //Stops people from just unscrewing the monitor and putting it back to get the console working again. to_chat(user, "It is too hot to mess with!") return return ..() diff --git a/code/game/machinery/computer/prisoner.dm b/code/game/machinery/computer/prisoner.dm index 672ebed32e4..bcabdeb511e 100644 --- a/code/game/machinery/computer/prisoner.dm +++ b/code/game/machinery/computer/prisoner.dm @@ -71,8 +71,8 @@ health_display = "DEAD" else if(total_loss) health_display = "HURT ([total_loss])" - if(is_station_level(M.z) && !istype(M.loc, /turf/space)) - loc_display = "[get_area(M)]" + if(is_station_level(Tr.z) && !istype(Tr.loc, /turf/space)) + loc_display = "[get_area(Tr)]" dat += "ID: [T.id]
Subject: [M]
Location: [loc_display]
Health: [health_display]
" dat += "(Message Holder) |
" dat += "********************************
" diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 36ad92714c6..b051ae34ca9 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -257,18 +257,20 @@ to destroy them and players will be able to make replacements. /obj/machinery/vending/modularpc = "Deluxe Silicate Selections", /obj/machinery/vending/crittercare = "CritterCare") -/obj/item/circuitboard/vendor/attackby(obj/item/I, mob/user, params) - if(isscrewdriver(I)) - var/static/list/display_vending_names_paths - if(!display_vending_names_paths) - display_vending_names_paths = list() - for(var/path in vending_names_paths) - display_vending_names_paths[vending_names_paths[path]] = path - var/choice = input(user, "Choose a new brand","Select an Item") as null|anything in display_vending_names_paths - set_type(display_vending_names_paths[choice]) - else - return ..() - +/obj/item/circuitboard/vendor/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + var/static/list/display_vending_names_paths + if(!display_vending_names_paths) + display_vending_names_paths = list() + for(var/path in vending_names_paths) + display_vending_names_paths[vending_names_paths[path]] = path + var/choice = input(user, "Choose a new brand","Select an Item") as null|anything in display_vending_names_paths + if(loc != user) + to_chat(user, "You need to keep [src] in your hands while doing that!") + return + set_type(display_vending_names_paths[choice]) /obj/item/circuitboard/vendor/proc/set_type(obj/machinery/vending/typepath) build_path = typepath @@ -583,20 +585,20 @@ to destroy them and players will be able to make replacements. /obj/item/stock_parts/manipulator = 1, /obj/item/stack/sheet/glass = 1) -/obj/item/circuitboard/chem_master/attackby(obj/item/I, mob/user, params) - if(isscrewdriver(I)) - var/new_name = "ChemMaster" - var/new_path = /obj/machinery/chem_master +/obj/item/circuitboard/chem_master/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + var/new_name = "ChemMaster" + var/new_path = /obj/machinery/chem_master - if(build_path == /obj/machinery/chem_master) - new_name = "CondiMaster" - new_path = /obj/machinery/chem_master/condimaster + if(build_path == /obj/machinery/chem_master) + new_name = "CondiMaster" + new_path = /obj/machinery/chem_master/condimaster - build_path = new_path - name = "circuit board ([new_name] 3000)" - to_chat(user, "You change the circuit board setting to \"[new_name]\".") - else - return ..() + build_path = new_path + name = "circuit board ([new_name] 3000)" + to_chat(user, "You change the circuit board setting to \"[new_name]\".") /obj/item/circuitboard/chem_master/condi_master name = "circuit board (CondiMaster 3000)" diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index 3df7cc8c6ec..16e761d01c6 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -302,20 +302,9 @@ user.visible_message("[user] adds \a [B] to [src]!", "You add \a [B] to [src]!") return - - if(istype(G, /obj/item/screwdriver)) - if(occupant || on) - to_chat(user, "The maintenance panel is locked.") - return - default_deconstruction_screwdriver(user, "pod0-o", "pod0", G) - return - if(exchange_parts(user, G)) return - if(default_deconstruction_crowbar(G)) - return - if(istype(G, /obj/item/grab)) var/obj/item/grab/GG = G if(panel_open) @@ -332,6 +321,17 @@ return return ..() +/obj/machinery/atmospherics/unary/cryo_cell/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I)) + return + +/obj/machinery/atmospherics/unary/cryo_cell/screwdriver_act(mob/user, obj/item/I) + if(occupant || on) + to_chat(user, "The maintenance panel is locked.") + return TRUE + if(default_deconstruction_screwdriver(user, "pod0-o", "pod0", I)) + return TRUE + /obj/machinery/atmospherics/unary/cryo_cell/update_icon() handle_update_icon() diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index ae8b3f5829c..af2c9779717 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -380,7 +380,7 @@ cult_mode.bypass_phase() //Update any existing objectives involving this mob. - for(var/datum/objective/O in all_objectives) + for(var/datum/objective/O in GLOB.all_objectives) // We don't want revs to get objectives that aren't for heads of staff. Letting // them win or lose based on cryo is silly so we remove the objective. if(istype(O,/datum/objective/mutiny) && O.target == occupant.mind) @@ -395,9 +395,10 @@ if(!O) return O.find_target() if(!(O.target)) - all_objectives -= O + GLOB.all_objectives -= O O.owner.objectives -= O qdel(O) + O.owner.announce_objectives() if(occupant.mind && occupant.mind.assigned_role) //Handle job slot/tater cleanup. var/job = occupant.mind.assigned_role diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm index 211f878231f..1fb2dfc422d 100644 --- a/code/game/machinery/dance_machine.dm +++ b/code/game/machinery/dance_machine.dm @@ -57,18 +57,19 @@ STOP_PROCESSING(SSobj, src) return ..() -/obj/machinery/disco/attackby(obj/item/O, mob/user, params) - if(!active) - if(iswrench(O)) - if(!anchored && !isinspace()) - to_chat(user,"You secure [src] to the floor.") - anchored = TRUE - else if(anchored) - to_chat(user,"You unsecure and disconnect [src].") - anchored = FALSE - playsound(src, 'sound/items/deconstruct.ogg', 50, 1) +/obj/machinery/disco/wrench_act(mob/user, obj/item/I) + if(active) return - return ..() + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!anchored && !isinspace()) + anchored = TRUE + WRENCH_ANCHOR_MESSAGE + else if(anchored) + anchored = FALSE + WRENCH_UNANCHOR_MESSAGE + playsound(src, 'sound/items/deconstruct.ogg', 50, 1) /obj/machinery/disco/update_icon() if(active) diff --git a/code/game/machinery/defib_mount.dm b/code/game/machinery/defib_mount.dm index 267ea5da392..ff9609a31bc 100644 --- a/code/game/machinery/defib_mount.dm +++ b/code/game/machinery/defib_mount.dm @@ -98,16 +98,6 @@ else if(defib && I == defib.paddles) user.drop_item() return - else if(iswrench(I)) - if(!defib) - user.visible_message("[user] unwrenches [src] from the wall!", \ - "You unwrench [src]!") - new /obj/item/mounted/frame/defib_mount(get_turf(user)) - playsound(get_turf(src), I.usesound, 50, 1) - qdel(src) - return - to_chat(user, "The [defib] is blocking access to the bolts!") - return var/obj/item/card/id = I.GetID() if(id) if(check_access(id) || security_level >= SEC_LEVEL_RED) //anyone can toggle the clamps in red alert! @@ -122,6 +112,17 @@ return return ..() +/obj/machinery/defibrillator_mount/wrench_act(mob/user, obj/item/I) + . = TRUE + if(defib) + to_chat(user, "The [defib] is blocking access to the bolts!") + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + WRENCH_UNANCHOR_WALL_MESSAGE + new /obj/item/mounted/frame/defib_mount(get_turf(user)) + qdel(src) + /obj/machinery/defibrillator_mount/AltClick(mob/living/carbon/user) if(!istype(user)) return diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index 60d9953e980..f3f75f3c32c 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -29,17 +29,20 @@ if(stacktype) new stacktype(get_turf(src), drop_amount) -/obj/structure/barricade/attackby(obj/item/I, mob/user, params) - if(iswelder(I) && user.a_intent != INTENT_HARM && bar_material == METAL) - var/obj/item/weldingtool/WT = I - if(obj_integrity < max_integrity) - if(WT.remove_fuel(0, user)) - to_chat(user, "You begin repairing [src]...") - playsound(loc, WT.usesound, 40, 1) - if(do_after(user, 40 * I.toolspeed, target = src)) - obj_integrity = Clamp(obj_integrity + 20, 0, max_integrity) - else - return ..() +/obj/structure/barricade/welder_act(mob/user, obj/item/I) + if(obj_integrity >= max_integrity) + to_chat(user, "[src] does not need repairs.") + return + if(user.a_intent == INTENT_HARM) + return + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_REPAIR_MESSAGE + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + WELDER_REPAIR_SUCCESS_MESSAGE + obj_integrity = Clamp(obj_integrity + 20, 0, max_integrity) + update_icon() + return TRUE /obj/structure/barricade/CanPass(atom/movable/mover, turf/target)//So bullets will fly over and stuff. if(locate(/obj/structure/barricade) in get_turf(mover)) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 610bbb73b06..444c319334b 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -37,6 +37,7 @@ #define AIRLOCK_INTEGRITY_MULTIPLIER 1.5 // How much reinforced doors health increases #define AIRLOCK_DAMAGE_DEFLECTION_N 21 // Normal airlock damage deflection #define AIRLOCK_DAMAGE_DEFLECTION_R 30 // Reinforced airlock damage deflection + var/list/airlock_overlays = list() /obj/machinery/door/airlock @@ -823,14 +824,9 @@ About the new airlock wires panel: return 1 /obj/machinery/door/airlock/attackby(obj/item/C, mob/user, params) - if(shock_user(user, 75)) - return - add_fingerprint(user) - - if(headbutt_airlock(user))//See if the user headbutts the airlock + if(!headbutt_shock_check(user)) return - if(panel_open) switch(security_level) if(AIRLOCK_SECURITY_NONE) @@ -864,116 +860,7 @@ About the new airlock wires panel: damage_deflection = AIRLOCK_DAMAGE_DEFLECTION_R update_icon() return - if(AIRLOCK_SECURITY_METAL) - if(iswelder(C)) - var/obj/item/weldingtool/WT = C - if(!WT.remove_fuel(2, user)) - return - to_chat(user, "You begin cutting the panel's shielding...") - playsound(loc, WT.usesound, 40, 1) - if(do_after(user, 40 * WT.toolspeed, 1, target = src)) - if(!panel_open || !WT.isOn()) - return - playsound(loc, WT.usesound, 50, 1) - user.visible_message("[user] cuts through \the [src]'s shielding.", - "You cut through \the [src]'s shielding.", - "You hear welding.") - security_level = AIRLOCK_SECURITY_NONE - spawn_atom_to_turf(/obj/item/stack/sheet/metal, user.loc, 2) - update_icon() - return - if(AIRLOCK_SECURITY_PLASTEEL_I_S) - if(iscrowbar(C)) - var/obj/item/crowbar/W = C - to_chat(user, "You start removing the inner layer of shielding...") - playsound(src, W.usesound, 100, 1) - if(do_after(user, 40 * W.toolspeed, 1, target = src)) - if(!panel_open) - return - if(security_level != AIRLOCK_SECURITY_PLASTEEL_I_S) - return - user.visible_message("[user] remove \the [src]'s shielding.", - "You remove \the [src]'s inner shielding.") - security_level = AIRLOCK_SECURITY_NONE - modify_max_integrity(normal_integrity) - damage_deflection = AIRLOCK_DAMAGE_DEFLECTION_N - spawn_atom_to_turf(/obj/item/stack/sheet/plasteel, user.loc, 1) - update_icon() - return - if(AIRLOCK_SECURITY_PLASTEEL_I) - if(iswelder(C)) - var/obj/item/weldingtool/WT = C - if(!WT.remove_fuel(2, user)) - return - to_chat(user, "You begin cutting the inner layer of shielding...") - playsound(loc, WT.usesound, 40, 1) - if(do_after(user, 40 * WT.toolspeed, 1, target = src)) - if(!panel_open || !WT.isOn()) - return - playsound(loc, WT.usesound, 50, 1) - user.visible_message("[user] cuts through \the [src]'s shielding.", - "You cut through \the [src]'s shielding.", - "You hear welding.") - security_level = AIRLOCK_SECURITY_PLASTEEL_I_S - return - if(AIRLOCK_SECURITY_PLASTEEL_O_S) - if(iscrowbar(C)) - var/obj/item/crowbar/W = C - to_chat(user, "You start removing outer layer of shielding...") - playsound(src, W.usesound, 100, 1) - if(do_after(user, 40 * W.toolspeed, 1, target = src)) - if(!panel_open) - return - if(security_level != AIRLOCK_SECURITY_PLASTEEL_O_S) - return - user.visible_message("[user] remove \the [src]'s shielding.", - "You remove \the [src]'s shielding.") - security_level = AIRLOCK_SECURITY_PLASTEEL_I - spawn_atom_to_turf(/obj/item/stack/sheet/plasteel, user.loc, 1) - return - if(AIRLOCK_SECURITY_PLASTEEL_O) - if(iswelder(C)) - var/obj/item/weldingtool/WT = C - if(!WT.remove_fuel(2, user)) - return - to_chat(user, "You begin cutting the outer layer of shielding...") - playsound(loc, WT.usesound, 40, 1) - if(do_after(user, 40 * WT.toolspeed, 1, target = src)) - if(!panel_open || !WT.isOn()) - return - playsound(loc, WT.usesound, 50, 1) - user.visible_message("[user] cuts through \the [src]'s shielding.", - "You cut through \the [src]'s shielding.", - "You hear welding.") - security_level = AIRLOCK_SECURITY_PLASTEEL_O_S - return - if(AIRLOCK_SECURITY_PLASTEEL) - if(iswirecutter(C)) - var/obj/item/wirecutters/W = C - if(arePowerSystemsOn() && shock(user, 60)) // Protective grille of wiring is electrified - return - to_chat(user, "You start cutting through the outer grille.") - playsound(src, W.usesound, 100, 1) - if(do_after(user, 10 * W.toolspeed, 1, target = src)) - if(!panel_open) - return - user.visible_message("[user] cut through \the [src]'s outer grille.", - "You cut through \the [src]'s outer grille.") - security_level = AIRLOCK_SECURITY_PLASTEEL_O - return - if(isscrewdriver(C)) - panel_open = !panel_open - to_chat(user, "You [panel_open ? "open":"close"] the maintenance panel of the airlock.") - playsound(loc, C.usesound, 50, 1) - update_icon() - else if(iswirecutter(C)) - if(note) - remove_airlock_note(user, TRUE) - else - return interact_with_panel(user) - else if(ismultitool(C)) - return interact_with_panel(user) else if(istype(C, /obj/item/assembly/signaler)) return interact_with_panel(user) else if(istype(C, /obj/item/pai_cable)) // -- TLE @@ -993,102 +880,214 @@ About the new airlock wires panel: else return ..() -/obj/machinery/door/airlock/try_to_weld(obj/item/weldingtool/W, mob/user) - if(!operating && density) - if(user.a_intent != INTENT_HELP) - if(W.remove_fuel(0, user)) +/obj/machinery/door/airlock/screwdriver_act(mob/user, obj/item/I) + if(!headbutt_shock_check(user)) + return + if(user.a_intent == INTENT_HARM) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + panel_open = !panel_open + to_chat(user, "You [panel_open ? "open":"close"] [src]'s maintenance panel.") + update_icon() + +/obj/machinery/door/airlock/crowbar_act(mob/user, obj/item/I) + if(!headbutt_shock_check(user)) + return + if(user.a_intent == INTENT_HARM) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = 0)) + return + if(panel_open && security_level == AIRLOCK_SECURITY_PLASTEEL_I_S) + to_chat(user, "You start removing the inner layer of shielding...") + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + if(!panel_open || security_level != AIRLOCK_SECURITY_PLASTEEL_I_S) + return + user.visible_message("[user] remove \the [src]'s shielding.", + "You remove \the [src]'s inner shielding.") + security_level = AIRLOCK_SECURITY_NONE + modify_max_integrity(normal_integrity) + damage_deflection = AIRLOCK_DAMAGE_DEFLECTION_N + spawn_atom_to_turf(/obj/item/stack/sheet/plasteel, user.loc, 1) + update_icon() + else if(panel_open && security_level == AIRLOCK_SECURITY_PLASTEEL_O_S) + to_chat(user, "You start removing outer layer of shielding...") + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + if(!panel_open || security_level != AIRLOCK_SECURITY_PLASTEEL_O_S) + return + user.visible_message("[user] remove \the [src]'s shielding.", + "You remove \the [src]'s shielding.") + security_level = AIRLOCK_SECURITY_PLASTEEL_I + spawn_atom_to_turf(/obj/item/stack/sheet/plasteel, user.loc, 1) + else + try_to_crowbar(user, I) + +/obj/machinery/door/airlock/wirecutter_act(mob/user, obj/item/I) + if(!headbutt_shock_check(user)) + return + if(!panel_open || user.a_intent == INTENT_HARM) + return + . = TRUE + if(!I.tool_start_check(user, 0)) + return + if(security_level == AIRLOCK_SECURITY_PLASTEEL) + if(arePowerSystemsOn() && shock(user, 60)) // Protective grille of wiring is electrified + return + to_chat(user, "You start cutting through the outer grille.") + if(I.use_tool(src, user, 10, volume = I.tool_volume)) + if(!panel_open || security_level != AIRLOCK_SECURITY_PLASTEEL) + return + user.visible_message("[user] cut through \the [src]'s outer grille.", + "You cut through \the [src]'s outer grille.") + security_level = AIRLOCK_SECURITY_PLASTEEL_O + return + if(note) + remove_airlock_note(user, TRUE) + else + return interact_with_panel(user) + +/obj/machinery/door/airlock/multitool_act(mob/user, obj/item/I) + if(!headbutt_shock_check(user)) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + interact_with_panel(user) + +/obj/machinery/door/airlock/welder_act(mob/user, obj/item/I) //This is god awful but I don't care + if(!headbutt_shock_check(user)) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + switch(security_level) + if(AIRLOCK_SECURITY_METAL) + to_chat(user, "You begin cutting the panel's shielding...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume)) + return + if(!panel_open) + return + visible_message("[user] cuts through \the [src]'s shielding.", + "You cut through \the [src]'s shielding.", + "You hear welding.") + security_level = AIRLOCK_SECURITY_NONE + spawn_atom_to_turf(/obj/item/stack/sheet/metal, user.loc, 2) + if(AIRLOCK_SECURITY_PLASTEEL_O) + to_chat(user, "You begin cutting the outer layer of shielding...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume)) + return + if(!panel_open) + return + visible_message("[user] cuts through \the [src]'s shielding.", + "You cut through \the [src]'s shielding.", + "You hear welding.") + security_level = AIRLOCK_SECURITY_PLASTEEL_O_S + if(AIRLOCK_SECURITY_PLASTEEL_I) + to_chat(user, "You begin cutting the inner layer of shielding...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume)) + return + if(!panel_open) + return + user.visible_message("[user] cuts through \the [src]'s shielding.", + "You cut through \the [src]'s shielding.", + "You hear welding.") + security_level = AIRLOCK_SECURITY_PLASTEEL_I_S + else + if(user.a_intent != INTENT_HELP) user.visible_message("[user] is [welded ? "unwelding":"welding"] the airlock.", \ - "You begin [welded ? "unwelding":"welding"] the airlock...", \ - "You hear welding.") - playsound(loc, W.usesound, 40, 1) - if(do_after(user, 40 * W.toolspeed, 1, target = src, extra_checks = CALLBACK(src, .proc/weld_checks, W, user))) - playsound(loc, 'sound/items/welder2.ogg', 50, 1) + "You begin [welded ? "unwelding":"welding"] the airlock...", \ + "You hear welding.") + + if(I.use_tool(src, user, 40, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/weld_checks, I, user))) + if(!density && !welded) + return welded = !welded user.visible_message("[user.name] has [welded? "welded shut":"unwelded"] [src].", \ - "You [welded ? "weld the airlock shut":"unweld the airlock"].") + "You [welded ? "weld the airlock shut":"unweld the airlock"].") update_icon() - else - if(obj_integrity < max_integrity) - if(W.remove_fuel(0, user)) - user.visible_message("[user] is welding the airlock.", \ - "You begin repairing the airlock...", \ - "You hear welding.") - playsound(loc, W.usesound, 40, 1) - if(do_after(user, 40 * W.toolspeed, 1, target = src, extra_checks = CALLBACK(src, .proc/weld_checks, W, user))) - playsound(loc, 'sound/items/welder2.ogg', 50, 1) - obj_integrity = max_integrity - stat &= ~BROKEN - user.visible_message("[user.name] has repaired [src].", \ - "You finish repairing the airlock.") - update_icon() + else if(obj_integrity < max_integrity) + user.visible_message("[user] is welding the airlock.", \ + "You begin repairing the airlock...", \ + "You hear welding.") + if(I.use_tool(src, user, 40, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/weld_checks, I, user))) + obj_integrity = max_integrity + stat &= ~BROKEN + user.visible_message("[user.name] has repaired [src].", \ + "You finish repairing the airlock.") + update_icon() else to_chat(user, "The airlock doesn't need repairing.") + update_icon() -/obj/machinery/door/airlock/proc/weld_checks(obj/item/weldingtool/W, mob/user) - return !operating && density && user && W && W.isOn() && user.loc +/obj/machinery/door/airlock/proc/weld_checks(obj/item/I, mob/user) + return !operating && density && user && I && I.tool_use_check() && user.loc -/obj/machinery/door/airlock/try_to_crowbar(obj/item/I, mob/living/user) - var/beingcrowbarred = null - if(iscrowbar(I)) - beingcrowbarred = 1 - else - beingcrowbarred = 0 - if(beingcrowbarred && panel_open && ((emagged) || (density && welded && !operating && !arePowerSystemsOn() && !locked))) - playsound(loc, I.usesound, 100, 1) - user.visible_message("[user] removes the electronics from the airlock assembly.", \ - "You start to remove electronics from the airlock assembly...") - if(do_after(user, 40 * I.toolspeed, target = src)) - deconstruct(TRUE, user) - return - else if(arePowerSystemsOn()) - to_chat(user, "The airlock's motors resist your efforts to force it!") - else if(locked) - to_chat(user, "The airlock's bolts prevent it from being forced!") - else if(!welded && !operating) - if(istype(I, /obj/item/twohanded/fireaxe)) //let's make this more specific - var/obj/item/twohanded/fireaxe/F = I - if(F.wielded) - spawn(0) - if(density) - open(1) - else - close(1) - else - to_chat(user, "You need to be wielding the fire axe to do that!") - else +/obj/machinery/door/airlock/proc/headbutt_shock_check(mob/user) + if(shock_user(user, 75)) + return + if(headbutt_airlock(user))//See if the user headbutts the airlock + return + return TRUE + +/obj/machinery/door/airlock/try_to_crowbar(mob/living/user, obj/item/I) //*scream + if(operating) + return + if(istype(I, /obj/item/twohanded/fireaxe)) //let's make this more specific //FUCK YOU + var/obj/item/twohanded/fireaxe/F = I + if(F.wielded) spawn(0) if(density) open(1) else close(1) - - if(ispowertool(I)) //jaws of life and rescue claw - if(isElectrified()) - shock(user, 100)//it's like sticking a forck in a power socket - return - - if(!density)//already open - return - - if(locked) - to_chat(user, "The bolts are down, it won't budge!") - return - - if(welded) - to_chat(user, "It's welded, it won't budge!") - return - - var/time_to_open = 5 - if(arePowerSystemsOn() && !prying_so_hard) - time_to_open = 50 - playsound(src, 'sound/machines/airlock_alien_prying.ogg', 100, 1) //is it aliens or just the CE being a dick? - prying_so_hard = TRUE - var/result = do_after(user, time_to_open, target = src) - prying_so_hard = FALSE - if(result) + else + to_chat(user, "You need to be wielding the fire axe to do that!") + return + var/beingcrowbarred = FALSE + if(I.tool_behaviour == TOOL_CROWBAR && I.tool_use_check(user, 0)) + beingcrowbarred = TRUE + if(beingcrowbarred && panel_open && (emagged || (density && welded && !operating && !arePowerSystemsOn() && !locked))) + user.visible_message("[user] removes the electronics from the airlock assembly.", \ + "You start to remove electronics from the airlock assembly...") + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + deconstruct(TRUE, user) + return + if(welded) + to_chat(user, "[src] is welded shut!") + return + if(locked) + to_chat(user, "The airlock's bolts prevent it from being forced!") + return + else if(!arePowerSystemsOn()) + spawn(0) + if(density) open(1) - if(density && !open(1)) - to_chat(user, "Despite your attempts, [src] refuses to open.") + else + close(1) + return + else if(!ispowertool(I)) + to_chat(user, "The airlock's motors resist your efforts to force it!") + return + if(isElectrified()) + shock(user, 100)//it's like sticking a forck in a power socket + return + + if(!density)//already open + return + + var/time_to_open = 5 + if(!prying_so_hard) + time_to_open = 50 + playsound(src, 'sound/machines/airlock_alien_prying.ogg', 100, 1) //is it aliens or just the CE being a dick? + prying_so_hard = TRUE + var/result = do_after(user, time_to_open, target = src) + prying_so_hard = FALSE + if(result) + open(1) + if(density && !open(1)) + to_chat(user, "Despite your attempts, [src] refuses to open.") /obj/machinery/door/airlock/open(forced=0) if(operating || welded || locked || emagged) diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm index b53a0139fb2..96e4ec8da1c 100644 --- a/code/game/machinery/doors/airlock_types.dm +++ b/code/game/machinery/doors/airlock_types.dm @@ -379,14 +379,20 @@ return add_fingerprint(user) - if((iswelder(C) && !operating && density)) - var/obj/item/weldingtool/W = C - if(W.remove_fuel(0,user)) - welded = !welded - update_icon() - return - else - return + +/obj/machinery/door/airlock/hatch/gamma/welder_act(mob/user, obj/item/I) + if(shock_user(user, 75)) + return + if(operating || !density) + return + . = TRUE + if(!I.use_tool(src, user, 0, amount = 0, volume = I.tool_volume)) + return + welded = !welded + visible_message("[user] [welded ? null : "un"]welds [src]!",\ + "You [welded ? null : "un"]weld [src]!",\ + "You hear welding.") + update_icon() /obj/machinery/door/airlock/maintenance_hatch name = "maintenance hatch" @@ -424,14 +430,22 @@ return add_fingerprint(user) - if((iswelder(C) && !operating && density)) - var/obj/item/weldingtool/W = C - if(W.remove_fuel(0,user)) - welded = !welded - update_icon() - return - else - return + + +/obj/machinery/door/airlock/highsecurity/red/welder_act(mob/user, obj/item/I) + if(shock_user(user, 75)) + return + if(operating || !density) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + welded = !welded + visible_message("[user] [welded ? null : "un"]welds [src]!",\ + "You [welded ? null : "un"]weld [src]!",\ + "You hear welding.") + update_icon() + ////////////////////////////////// /* diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index f23734a0079..8bd7af5dad4 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -444,7 +444,7 @@ //Stolen from status_display /obj/machinery/door_timer/proc/texticon(tn, px = 0, py = 0) var/image/I = image('icons/obj/status_display.dmi', "blank") - var/len = lentext(tn) + var/len = length(tn) for(var/d = 1 to len) var/char = copytext(tn, len-d+1, len-d+2) diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index d1144d7317d..14d1de97327 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -185,24 +185,29 @@ /obj/machinery/door/proc/unrestricted_side(mob/M) //Allows for specific side of airlocks to be unrestrected (IE, can exit maint freely, but need access to enter) return get_dir(src, M) & unres_sides -/obj/machinery/door/proc/try_to_weld(obj/item/weldingtool/W, mob/user) - return - -/obj/machinery/door/proc/try_to_crowbar(obj/item/I, mob/user) +/obj/machinery/door/proc/try_to_crowbar(mob/user, obj/item/I) return /obj/machinery/door/attackby(obj/item/I, mob/user, params) - if(user.a_intent != INTENT_HARM && (iscrowbar(I) || istype(I, /obj/item/twohanded/fireaxe))) - try_to_crowbar(I, user) - return 1 - else if(iswelder(I)) - try_to_weld(I, user) + if(user.a_intent != INTENT_HARM && istype(I, /obj/item/twohanded/fireaxe)) + try_to_crowbar(user, I) return 1 else if(!(I.flags & NOBLUDGEON) && user.a_intent != INTENT_HARM) try_to_activate_door(user) return 1 return ..() + +/obj/machinery/door/crowbar_act(mob/user, obj/item/I) + if(user.a_intent == INTENT_HARM) + return + . = TRUE + if(operating) + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + try_to_crowbar(user, I) + /obj/machinery/door/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) . = ..() if(. && obj_integrity > 0) diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index d562c6b78ea..17b5756e581 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -87,47 +87,60 @@ if(operating) return - - if(welded) - if(iswrench(C)) - if(boltslocked) - to_chat(user, "There are screws locking the bolts in place!") - return - playsound(get_turf(src), C.usesound, 50, 1) - user.visible_message("[user] starts undoing [src]'s bolts...", \ - "You start unfastening [src]'s floor bolts...") - if(!do_after(user, 50 * C.toolspeed, target = src)) - return - playsound(get_turf(src), C.usesound, 50, 1) - user.visible_message("[user] unfastens [src]'s bolts.", \ - "You undo [src]'s floor bolts.") - deconstruct(TRUE) - return - if(isscrewdriver(C)) - user.visible_message("[user] [boltslocked ? "unlocks" : "locks"] [src]'s bolts.", \ - "You [boltslocked ? "unlock" : "lock"] [src]'s floor bolts.") - playsound(get_turf(src), C.usesound, 50, 1) - boltslocked = !boltslocked - return - return ..() /obj/machinery/door/firedoor/try_to_activate_door(mob/user) return -/obj/machinery/door/firedoor/try_to_weld(obj/item/weldingtool/W, mob/user) - if(W.remove_fuel(0, user)) - playsound(get_turf(src), W.usesound, 50, 1) - user.visible_message("[user] starts [welded ? "unwelding" : "welding"] [src].", "You start welding [src].") - if(do_after(user, 40 * W.toolspeed, 1, target=src)) - welded = !welded - to_chat(user, "[user] [welded ? "welds" : "unwelds"] [src].", "You [welded ? "weld" : "unweld"] [src].") - update_icon() +/obj/machinery/door/firedoor/screwdriver_act(mob/user, obj/item/I) + if(user.a_intent == INTENT_HARM) + return + if(operating || !welded) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + user.visible_message("[user] [boltslocked ? "unlocks" : "locks"] [src]'s bolts.", \ + "You [boltslocked ? "unlock" : "lock"] [src]'s floor bolts.") + boltslocked = !boltslocked + +/obj/machinery/door/firedoor/wrench_act(mob/user, obj/item/I) + if(user.a_intent == INTENT_HARM) + return + if(operating || !welded) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(boltslocked) + to_chat(user, "There are screws locking the bolts in place!") + return + user.visible_message("[user] starts undoing [src]'s bolts...", \ + "You start unfastening [src]'s floor bolts...") + if(!I.use_tool(src, user, 50, volume = I.tool_volume) || boltslocked) + return + user.visible_message("[user] unfastens [src]'s bolts.", \ + "You undo [src]'s floor bolts.") + deconstruct(TRUE) + +/obj/machinery/door/firedoor/welder_act(mob/user, obj/item/I) + if(!density) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_WELD_MESSAGE + if(!I.use_tool(src, user, 40, volume = I.tool_volume)) + return + if(!density) //In case someone opens it while it's getting welded + return + WELDER_WELD_SUCCESS_MESSAGE + welded = !welded + update_icon() /obj/machinery/door/firedoor/try_to_crowbar(obj/item/I, mob/user) if(welded || operating) return - if(density) open() else @@ -308,40 +321,6 @@ /obj/structure/firelock_frame/attackby(obj/item/C, mob/user) switch(constructionStep) if(CONSTRUCTION_PANEL_OPEN) - if(iscrowbar(C)) - playsound(get_turf(src), C.usesound, 50, 1) - user.visible_message("[user] starts prying something out from [src]...", \ - "You begin prying out the wire cover...") - if(!do_after(user, 50 * C.toolspeed, target = src)) - return - if(constructionStep != CONSTRUCTION_PANEL_OPEN) - return - playsound(get_turf(src), C.usesound, 50, 1) - user.visible_message("[user] pries out a metal plate from [src], exposing the wires.", \ - "You remove the cover plate from [src], exposing the wires.") - constructionStep = CONSTRUCTION_WIRES_EXPOSED - update_icon() - return - if(iswrench(C)) - if(locate(/obj/machinery/door/firedoor) in get_turf(src)) - to_chat(user, "There's already a firelock there.") - return - playsound(get_turf(src), C.usesound, 50, 1) - user.visible_message("[user] starts bolting down [src]...", \ - "You begin bolting [src]...") - if(!do_after(user, 30 * C.toolspeed, target = src)) - return - if(locate(/obj/machinery/door/firedoor) in get_turf(src)) - return - user.visible_message("[user] finishes the firelock.", \ - "You finish the firelock.") - playsound(get_turf(src), C.usesound, 50, 1) - if(reinforced) - new /obj/machinery/door/firedoor/heavy(get_turf(src)) - else - new /obj/machinery/door/firedoor(get_turf(src)) - qdel(src) - return if(istype(C, /obj/item/stack/sheet/plasteel)) var/obj/item/stack/sheet/plasteel/P = C if(reinforced) @@ -362,53 +341,7 @@ P.use(2) reinforced = 1 return - - if(CONSTRUCTION_WIRES_EXPOSED) - if(iswirecutter(C)) - playsound(get_turf(src), C.usesound, 50, 1) - user.visible_message("[user] starts cutting the wires from [src]...", \ - "You begin removing [src]'s wires...") - if(!do_after(user, 60 * C.toolspeed, target = src)) - return - if(constructionStep != CONSTRUCTION_WIRES_EXPOSED) - return - user.visible_message("[user] removes the wires from [src].", \ - "You remove the wiring from [src], exposing the circuit board.") - var/obj/item/stack/cable_coil/B = new(get_turf(src)) - B.amount = 5 - constructionStep = CONSTRUCTION_GUTTED - update_icon() - return - if(iscrowbar(C)) - playsound(get_turf(src), C.usesound, 50, 1) - user.visible_message("[user] starts prying a metal plate into [src]...", \ - "You begin prying the cover plate back onto [src]...") - if(!do_after(user, 80 * C.toolspeed, target = src)) - return - if(constructionStep != CONSTRUCTION_WIRES_EXPOSED) - return - playsound(get_turf(src), C.usesound, 50, 1) - user.visible_message("[user] pries the metal plate into [src].", \ - "You pry [src]'s cover plate into place, hiding the wires.") - constructionStep = CONSTRUCTION_PANEL_OPEN - update_icon() - return if(CONSTRUCTION_GUTTED) - if(iscrowbar(C)) - user.visible_message("[user] begins removing the circuit board from [src]...", \ - "You begin prying out the circuit board from [src]...") - playsound(get_turf(src), C.usesound, 50, 1) - if(!do_after(user, 50 * C.toolspeed, target = src)) - return - if(constructionStep != CONSTRUCTION_GUTTED) - return - user.visible_message("[user] removes [src]'s circuit board.", \ - "You remove the circuit board from [src].") - new /obj/item/firelock_electronics(get_turf(src)) - playsound(get_turf(src), C.usesound, 50, 1) - constructionStep = CONSTRUCTION_NOCIRCUIT - update_icon() - return if(iscoil(C)) var/obj/item/stack/cable_coil/B = C if(B.get_amount() < 5) @@ -428,25 +361,6 @@ update_icon() return if(CONSTRUCTION_NOCIRCUIT) - if(iswelder(C)) - var/obj/item/weldingtool/W = C - if(W.remove_fuel(1,user)) - playsound(get_turf(src), W.usesound, 50, 1) - user.visible_message("[user] begins cutting apart [src]'s frame...", \ - "You begin slicing [src] apart...") - if(!do_after(user, 40 * W.toolspeed, target = src)) - return - if(constructionStep != CONSTRUCTION_NOCIRCUIT) - return - user.visible_message("[user] cuts apart [src]!", \ - "You cut [src] into metal.") - playsound(get_turf(src), W.usesound, 50, 1) - var/turf/T = get_turf(src) - new /obj/item/stack/sheet/metal(T, 3) - if(reinforced) - new /obj/item/stack/sheet/plasteel(T, 2) - qdel(src) - return if(istype(C, /obj/item/firelock_electronics)) user.visible_message("[user] starts adding [C] to [src]...", \ "You begin adding a circuit board to [src]...") @@ -465,6 +379,109 @@ return return ..() +/obj/structure/firelock_frame/crowbar_act(mob/user, obj/item/I) + if(!(constructionStep in list(CONSTRUCTION_WIRES_EXPOSED, CONSTRUCTION_PANEL_OPEN, CONSTRUCTION_GUTTED))) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(constructionStep == CONSTRUCTION_WIRES_EXPOSED) + user.visible_message("[user] starts prying a metal plate into [src]...", \ + "You begin prying the cover plate back onto [src]...") + if(!I.use_tool(src, user, 50, volume = I.tool_volume)) + return + if(constructionStep != CONSTRUCTION_WIRES_EXPOSED) + return + user.visible_message("[user] pries the metal plate into [src].", \ + "You pry [src]'s cover plate into place, hiding the wires.") + constructionStep = CONSTRUCTION_PANEL_OPEN + else if(constructionStep == CONSTRUCTION_PANEL_OPEN) + user.visible_message("[user] starts prying something out from [src]...", \ + "You begin prying out the wire cover...") + if(!I.use_tool(src, user, 50, volume = I.tool_volume)) + return + if(constructionStep != CONSTRUCTION_PANEL_OPEN) + return + user.visible_message("[user] pries out a metal plate from [src], exposing the wires.", \ + "You remove the cover plate from [src], exposing the wires.") + constructionStep = CONSTRUCTION_WIRES_EXPOSED + else if(constructionStep == CONSTRUCTION_GUTTED) + user.visible_message("[user] begins removing the circuit board from [src]...", \ + "You begin prying out the circuit board from [src]...") + if(!I.use_tool(src, user, 50, volume = I.tool_volume)) + return + if(constructionStep != CONSTRUCTION_GUTTED) + return + user.visible_message("[user] removes [src]'s circuit board.", \ + "You remove the circuit board from [src].") + new /obj/item/firelock_electronics(get_turf(src)) + constructionStep = CONSTRUCTION_NOCIRCUIT + update_icon() + +/obj/structure/firelock_frame/wirecutter_act(mob/user, obj/item/I) + if(constructionStep != CONSTRUCTION_WIRES_EXPOSED) + return + . = TRUE + if(!I.tool_start_check(user, 0)) + return + + user.visible_message("[user] starts cutting the wires from [src]...", \ + "You begin removing [src]'s wires...") + if(!I.use_tool(src, user, 50, volume = I.tool_volume)) + return + if(constructionStep != CONSTRUCTION_WIRES_EXPOSED) + return + user.visible_message("[user] removes the wires from [src].", \ + "You remove the wiring from [src], exposing the circuit board.") + var/obj/item/stack/cable_coil/B = new(get_turf(src)) + B.amount = 5 + constructionStep = CONSTRUCTION_GUTTED + update_icon() + +/obj/structure/firelock_frame/wrench_act(mob/user, obj/item/I) + if(constructionStep != CONSTRUCTION_PANEL_OPEN) + return + . = TRUE + if(locate(/obj/machinery/door/firedoor) in get_turf(src)) + to_chat(user, "There's already a firelock there.") + return + if(!I.tool_start_check(user, 0)) + return + user.visible_message("[user] starts bolting down [src]...", \ + "You begin bolting [src]...") + if(!I.use_tool(src, user, 50, volume = I.tool_volume)) + return + if(locate(/obj/machinery/door/firedoor) in get_turf(src)) + return + user.visible_message("[user] finishes the firelock.", \ + "You finish the firelock.") + if(reinforced) + new /obj/machinery/door/firedoor/heavy(get_turf(src)) + else + new /obj/machinery/door/firedoor(get_turf(src)) + qdel(src) + + + + + +/obj/structure/firelock_frame/welder_act(mob/user, obj/item/I) + if(constructionStep != CONSTRUCTION_NOCIRCUIT) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_SLICING_MESSAGE + if(!I.use_tool(src, user, 40, amount = 1, volume = I.tool_volume)) + return + if(constructionStep != CONSTRUCTION_NOCIRCUIT) + return + WELDER_SLICING_SUCCESS_MESSAGE + new /obj/item/stack/sheet/metal(drop_location(), 3) + if(reinforced) + new /obj/item/stack/sheet/plasteel(drop_location(), 2) + qdel(src) + /obj/structure/firelock_frame/heavy name = "heavy firelock frame" reinforced = 1 @@ -473,4 +490,4 @@ #undef CONSTRUCTION_PANEL_OPEN #undef CONSTRUCTION_WIRES_EXPOSED #undef CONSTRUCTION_GUTTED -#undef CONSTRUCTION_NOCIRCUIT \ No newline at end of file +#undef CONSTRUCTION_NOCIRCUIT diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index fe104ff794c..ae87480e929 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -231,70 +231,80 @@ return add_fingerprint(user) - - if(!(flags & NODECONSTRUCT)) - if(isscrewdriver(I)) - if(density || operating) - to_chat(user, "You need to open the door to access the maintenance panel!") - return - playsound(src.loc, I.usesound, 50, 1) - panel_open = !panel_open - to_chat(user, "You [panel_open ? "open":"close"] the maintenance panel of the [src.name].") - return - - if(iscrowbar(I)) - if(panel_open && !density && !operating) - playsound(loc, I.usesound, 100, 1) - user.visible_message("[user] removes the electronics from the [name].", \ - "You start to remove electronics from the [name]...") - if(do_after(user, 40 * I.toolspeed, target = src)) - if(panel_open && !density && !operating && loc) - var/obj/structure/windoor_assembly/WA = new /obj/structure/windoor_assembly(loc) - switch(base_state) - if("left") - WA.facing = "l" - if("right") - WA.facing = "r" - if("leftsecure") - WA.facing = "l" - WA.secure = TRUE - if("rightsecure") - WA.facing = "r" - WA.secure = TRUE - WA.anchored = TRUE - WA.state= "02" - WA.setDir(dir) - WA.ini_dir = dir - WA.update_icon() - WA.created_name = name - - if(emagged) - to_chat(user, "You discard the damaged electronics.") - qdel(src) - return - - to_chat(user, "You remove the airlock electronics.") - - var/obj/item/airlock_electronics/ae - if(!electronics) - ae = new/obj/item/airlock_electronics(loc) - if(!req_access) - check_access() - if(req_access.len) - ae.conf_access = req_access - else if(req_one_access.len) - ae.conf_access = req_one_access - ae.one_access = 1 - else - ae = electronics - electronics = null - ae.forceMove(loc) - - qdel(src) - return return ..() -/obj/machinery/door/window/try_to_crowbar(obj/item/I, mob/user) +/obj/machinery/door/window/screwdriver_act(mob/user, obj/item/I) + if(flags & NODECONSTRUCT) + return + . = TRUE + if(density || operating) + to_chat(user, "You need to open the door to access the maintenance panel!") + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + panel_open = !panel_open + to_chat(user, "You [panel_open ? "open":"close"] the maintenance panel of the [src.name].") + + +/obj/machinery/door/window/crowbar_act(mob/user, obj/item/I) + if(operating) + return + if(flags & NODECONSTRUCT) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(panel_open && !density && !operating) + user.visible_message("[user] removes the electronics from the [name].", \ + "You start to remove electronics from the [name]...") + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + if(panel_open && !density && !operating && loc) + var/obj/structure/windoor_assembly/WA = new /obj/structure/windoor_assembly(loc) + switch(base_state) + if("left") + WA.facing = "l" + if("right") + WA.facing = "r" + if("leftsecure") + WA.facing = "l" + WA.secure = TRUE + if("rightsecure") + WA.facing = "r" + WA.secure = TRUE + WA.anchored = TRUE + WA.state= "02" + WA.setDir(dir) + WA.ini_dir = dir + WA.update_icon() + WA.created_name = name + + if(emagged) + to_chat(user, "You discard the damaged electronics.") + qdel(src) + return + + to_chat(user, "You remove the airlock electronics.") + + var/obj/item/airlock_electronics/ae + if(!electronics) + ae = new/obj/item/airlock_electronics(loc) + if(!req_access) + check_access() + if(req_access.len) + ae.conf_access = req_access + else if(req_one_access.len) + ae.conf_access = req_one_access + ae.one_access = 1 + else + ae = electronics + electronics = null + ae.forceMove(loc) + + qdel(src) + else + try_to_crowbar(user, I) + +/obj/machinery/door/window/try_to_crowbar(mob/user, obj/item/I) if(!hasPower()) if(density) open(2) diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index d4dc8f854ef..d0fe753a9de 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -41,17 +41,6 @@ var/list/doppler_arrays = list() return PROCESS_KILL /obj/machinery/doppler_array/attackby(obj/item/I, mob/user, params) - if(iswrench(I)) - if(!anchored && !isinspace()) - anchored = TRUE - power_change() - to_chat(user, "You fasten [src].") - else if(anchored) - anchored = FALSE - power_change() - to_chat(user, "You unfasten [src].") - playsound(loc, I.usesound, 50, 1) - return if(istype(I, /obj/item/disk/tech_disk)) var/obj/item/disk/tech_disk/disk = I disk.load_tech(toxins_tech) @@ -59,6 +48,18 @@ var/list/doppler_arrays = list() return return ..() +/obj/machinery/doppler_array/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!anchored && !isinspace()) + anchored = TRUE + WRENCH_ANCHOR_MESSAGE + else if(anchored) + anchored = FALSE + WRENCH_UNANCHOR_MESSAGE + power_change() + /obj/machinery/doppler_array/attack_hand(mob/user) if(..()) return diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 255d8d3cce1..7ae268fca46 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -1,6 +1,11 @@ /* FIRE ALARM */ + +#define FIRE_ALARM_FRAME 0 +#define FIRE_ALARM_UNWIRED 1 +#define FIRE_ALARM_READY 2 + /obj/machinery/firealarm name = "fire alarm" desc = "\"Pull this in case of emergency\". Thus, keep pulling it forever." @@ -83,68 +88,94 @@ FIRE ALARM /obj/machinery/firealarm/attackby(obj/item/I, mob/user, params) add_fingerprint(user) - - if(isscrewdriver(I) && buildstage == 2) - wiresexposed = !wiresexposed - update_icon() - return - if(wiresexposed) - switch(buildstage) - if(2) - if(ismultitool(I)) - detecting = !detecting - if(detecting) - user.visible_message("[user] has reconnected [src]'s detecting unit!", "You have reconnected [src]'s detecting unit.") - else - user.visible_message("[user] has disconnected [src]'s detecting unit!", "You have disconnected [src]'s detecting unit.") - - else if(iswirecutter(I)) // cutting the wires out + if(buildstage == FIRE_ALARM_UNWIRED) + if(istype(I, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/coil = I + if(!coil.use(5)) to_chat(user, "You cut the wires!") - playsound(loc, I.usesound, 50, 1) - var/obj/item/stack/cable_coil/new_coil = new /obj/item/stack/cable_coil() - new_coil.amount = 5 - new_coil.forceMove(user.loc) - buildstage = 1 - update_icon() - if(1) - if(istype(I, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/coil = I - if(!coil.use(5)) - to_chat(user, "You cut the wires!") - return - - buildstage = 2 - playsound(get_turf(src), I.usesound, 50, 1) - to_chat(user, "You wire [src]!") - update_icon() - - else if(iscrowbar(I)) - to_chat(user, "You pry out the circuit!") - playsound(get_turf(src), I.usesound, 50, 1) - if(do_after(user, 20 * I.toolspeed, target = src)) - if(buildstage != 1) - return - var/obj/item/firealarm_electronics/circuit = new /obj/item/firealarm_electronics() - circuit.forceMove(get_turf(src)) - buildstage = 0 - update_icon() - if(0) - if(istype(I, /obj/item/firealarm_electronics)) - to_chat(user, "You insert the circuit!") - qdel(I) - buildstage = 1 - update_icon() - - else if(iswrench(I)) - to_chat(user, "You remove the fire alarm assembly from the wall!") - new /obj/item/mounted/frame/firealarm(get_turf(user)) - playsound(get_turf(src), I.usesound, 50, 1) - qdel(src) + return + buildstage = FIRE_ALARM_READY + playsound(get_turf(src), I.usesound, 50, 1) + to_chat(user, "You wire [src]!") + update_icon() + if(buildstage == FIRE_ALARM_FRAME) + if(istype(I, /obj/item/firealarm_electronics)) + to_chat(user, "You insert the circuit!") + qdel(I) + buildstage = FIRE_ALARM_UNWIRED + update_icon() return return ..() +/obj/machinery/firealarm/crowbar_act(mob/user, obj/item/I) + if(buildstage != FIRE_ALARM_UNWIRED) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + CROWBAR_ATTEMPT_PRY_CIRCUIT_MESSAGE + if(!I.use_tool(src, user, 20, volume = I.tool_volume) || buildstage != FIRE_ALARM_UNWIRED) + return + new /obj/item/firealarm_electronics(drop_location()) + buildstage = FIRE_ALARM_FRAME + update_icon() + CROWBAR_PRY_CIRCUIT_SUCCESS_MESSAGE + +/obj/machinery/firealarm/multitool_act(mob/user, obj/item/I) + if(buildstage != FIRE_ALARM_READY) + return + . = TRUE + if(!wiresexposed) + to_chat(user, "You need to expose the wires first!") + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + detecting = !detecting + if(detecting) + user.visible_message("[user] has reconnected [src]'s detecting unit!", "You have reconnected [src]'s detecting unit.") + else + user.visible_message("[user] has disconnected [src]'s detecting unit!", "You have disconnected [src]'s detecting unit.") + +/obj/machinery/firealarm/screwdriver_act(mob/user, obj/item/I) + if(buildstage != FIRE_ALARM_READY) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + wiresexposed = !wiresexposed + if(wiresexposed) + SCREWDRIVER_OPEN_PANEL_MESSAGE + else + SCREWDRIVER_CLOSE_PANEL_MESSAGE + update_icon() + +/obj/machinery/firealarm/wirecutter_act(mob/user, obj/item/I) + if(buildstage != FIRE_ALARM_READY) + return + . = TRUE + if(!wiresexposed) + to_chat(user, "You need to expose the wires first!") + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + WIRECUTTER_SNIP_MESSAGE + var/obj/item/stack/cable_coil/new_coil = new /obj/item/stack/cable_coil(drop_location()) + new_coil.amount = 5 + buildstage = FIRE_ALARM_UNWIRED + + +/obj/machinery/firealarm/wrench_act(mob/user, obj/item/I) + if(buildstage != FIRE_ALARM_FRAME) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + WRENCH_UNANCHOR_WALL_MESSAGE + new /obj/item/mounted/frame/firealarm(get_turf(user)) + qdel(src) + /obj/machinery/firealarm/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) . = ..() if(.) //damage received @@ -406,3 +437,8 @@ Just a object used in constructing fire alarms usr << browse(null, "window=partyalarm") return return + + +#undef FIRE_ALARM_FRAME +#undef FIRE_ALARM_UNWIRED +#undef FIRE_ALARM_READY diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index 30069ff0310..1f42a6a78c4 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -40,18 +40,6 @@ icon_state = "[base_state]1-p" // sd_set_light(0) -//Don't want to render prison breaks impossible -/obj/machinery/flasher/attackby(obj/item/I, mob/user, params) - if(iswirecutter(I)) - add_fingerprint(user) - disable = !disable - if(disable) - user.visible_message("[user] has disconnected [src]'s flashbulb!", "You disconnect [src]'s flashbulb!") - if(!disable) - user.visible_message("[user] has connected [src]'s flashbulb!", "You connect [src]'s flashbulb!") - else - return ..() - //Let the AI trigger them directly. /obj/machinery/flasher/attack_ai(mob/user) if(anchored) @@ -100,20 +88,28 @@ if((M.m_intent != MOVE_INTENT_WALK) && (anchored)) flash() -/obj/machinery/flasher/portable/attackby(obj/item/I, mob/user, params) - if(iswrench(I)) - add_fingerprint(user) - anchored = !anchored +//Don't want to render prison breaks impossible +/obj/machinery/flasher/portable/wirecutter_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + disable = !disable + if(disable) + user.visible_message("[user] has disconnected [src]'s flashbulb!", "You disconnect [src]'s flashbulb!") + if(!disable) + user.visible_message("[user] has connected [src]'s flashbulb!", "You connect [src]'s flashbulb!") - if(!anchored) - user.show_message(text("[src] can now be moved.")) - overlays.Cut() - - else if(anchored) - user.show_message(text("[src] is now secured.")) - overlays += "[base_state]-s" - else - return ..() +/obj/machinery/flasher/portable/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + anchored = !anchored + if(anchored) + WRENCH_ANCHOR_MESSAGE + overlays.Cut() + else if(anchored) + WRENCH_UNANCHOR_MESSAGE + overlays += "[base_state]-s" // Flasher button /obj/machinery/flasher_button diff --git a/code/game/machinery/gameboard.dm b/code/game/machinery/gameboard.dm index 2df0496ae67..edc1d3499ec 100644 --- a/code/game/machinery/gameboard.dm +++ b/code/game/machinery/gameboard.dm @@ -93,10 +93,10 @@ if(href_list["close"]) close_game() -/obj/machinery/gameboard/attackby(obj/item/I, mob/user, params) - if(default_unfasten_wrench(user, I)) - return +/obj/machinery/gameboard/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I, ignore_panel = TRUE)) + return TRUE - if(default_deconstruction_crowbar(I, ignore_panel = TRUE)) - return - return ..() +/obj/machinery/gameboard/wrench_act(mob/user, obj/item/I) + if(default_unfasten_wrench(user, I)) + return TRUE diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 10708ff9c0e..a742f6b7109 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -100,19 +100,22 @@ var/list/holopads = list() holo_range = holograph_range /obj/machinery/hologram/holopad/attackby(obj/item/I, mob/user, params) - if(default_deconstruction_screwdriver(user, "holopad_open", "holopad0", I)) - return - if(exchange_parts(user, I)) return - - if(default_unfasten_wrench(user, I)) - return - - if(default_deconstruction_crowbar(I)) - return return ..() +/obj/machinery/hologram/holopad/screwdriver_act(mob/user, obj/item/I) + . = TRUE + default_deconstruction_screwdriver(user, "holopad_open", "holopad0", I) + + +/obj/machinery/hologram/holopad/wrench_act(mob/user, obj/item/I) + . = TRUE + default_unfasten_wrench(user, I) + +/obj/machinery/hologram/holopad/crowbar_act(mob/user, obj/item/I) + . = TRUE + default_deconstruction_crowbar(user, I) /obj/machinery/hologram/holopad/attack_hand(mob/living/carbon/human/user) if(..()) diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm index 45056369662..e4bdb0d5478 100755 --- a/code/game/machinery/igniter.dm +++ b/code/game/machinery/igniter.dm @@ -78,21 +78,23 @@ /obj/machinery/sparker/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/detective_scanner)) return - if(isscrewdriver(I)) - add_fingerprint(user) - disable = !disable - if(disable) - user.visible_message("[user] has disabled [src]!", "You disable the connection to [src].") - icon_state = "[base_state]-d" - if(!disable) - user.visible_message("[user] has reconnected [src]!", "You fix the connection to [src].") - if(powered()) - icon_state = "[base_state]" - else - icon_state = "[base_state]-p" - return return ..() +/obj/machinery/sparker/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + disable = !disable + if(disable) + user.visible_message("[user] has disabled [src]!", "You disable the connection to [src].") + icon_state = "[base_state]-d" + if(!disable) + user.visible_message("[user] has reconnected [src]!", "You fix the connection to [src].") + if(powered()) + icon_state = "[base_state]" + else + icon_state = "[base_state]-p" + /obj/machinery/sparker/attack_ai() if(src.anchored) return src.spark() diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm index 4d27ad6b5b5..13406ac4b0f 100644 --- a/code/game/machinery/lightswitch.dm +++ b/code/game/machinery/lightswitch.dm @@ -147,21 +147,26 @@ /obj/machinery/light_switch/attackby(obj/item/W as obj, mob/user as mob, params) if(istype(W, /obj/item/detective_scanner)) return - - if(istype(W, /obj/item/multitool)) - update_multitool_menu(user) - return 1 - - if(istype(W, /obj/item/wrench)) - playsound(get_turf(src), W.usesound, 50, 1) - if(do_after(user, 30 * W.toolspeed, target = src)) - to_chat(user, "You detach \the [src] from the wall.") - new/obj/item/mounted/frame/light_switch(get_turf(src)) - qdel(src) - return 1 - return ..() +/obj/machinery/light_switch/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + update_multitool_menu(user) + +/obj/machinery/light_switch/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + user.visible_message("[user] starts unwrenching [src] from the wall...", "You are unwrenching [src] from the wall...", "You hear ratcheting.") + . = TRUE + if(!I.use_tool(src, user, 30, volume = I.tool_volume)) + return + WRENCH_UNANCHOR_WALL_MESSAGE + new/obj/item/mounted/frame/light_switch(get_turf(src)) + qdel(src) + /obj/machinery/light_switch/multitool_menu(var/mob/user, var/obj/item/multitool/P) return {"
    diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 8f9381cec34..f1ac4e88bbb 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -176,6 +176,10 @@ Class Procs: use_power(7500/severity) new /obj/effect/temp_visual/emp(loc) ..() +/obj/machinery/default_welder_repair(mob/user, obj/item/I) + . = ..() + if(.) + stat &= ~BROKEN //sets the use_power var and then forces an area power update /obj/machinery/proc/update_use_power(var/new_use_power) @@ -371,13 +375,6 @@ Class Procs: uid = gl_uid gl_uid++ -/obj/machinery/proc/default_deconstruction_crowbar(var/obj/item/crowbar/C, var/ignore_panel = 0) - if(istype(C) && (panel_open || ignore_panel) && !(flags & NODECONSTRUCT)) - playsound(loc, C.usesound, 50, 1) - deconstruct(TRUE) - return 1 - return 0 - /obj/machinery/deconstruct(disassembled = TRUE) if(!(flags & NODECONSTRUCT)) on_deconstruction() @@ -402,9 +399,24 @@ Class Procs: if(!(flags & NODECONSTRUCT)) stat |= BROKEN -/obj/machinery/proc/default_deconstruction_screwdriver(var/mob/user, var/icon_state_open, var/icon_state_closed, var/obj/item/screwdriver/S) - if(!(flags & NODECONSTRUCT) && istype(S)) - playsound(loc, S.usesound, 50, 1) +/obj/machinery/proc/default_deconstruction_crowbar(user, obj/item/I, ignore_panel = 0) + if(I.tool_behaviour != TOOL_CROWBAR) + return FALSE + if(!I.use_tool(src, user, 0, volume = 0)) + return FALSE + if((panel_open || ignore_panel) && !(flags & NODECONSTRUCT)) + deconstruct(TRUE) + to_chat(user, "You disassemble [src].") + I.play_tool_sound(user, I.tool_volume) + return 1 + return 0 + +/obj/machinery/proc/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I) + if(I.tool_behaviour != TOOL_SCREWDRIVER) + return FALSE + if(!I.use_tool(src, user, 0, volume = 0)) + return FALSE + if(!(flags & NODECONSTRUCT)) if(!panel_open) panel_open = 1 icon_state = icon_state_open @@ -413,30 +425,26 @@ Class Procs: panel_open = 0 icon_state = icon_state_closed to_chat(user, "You close the maintenance hatch of [src].") + I.play_tool_sound(user, I.tool_volume) return 1 return 0 -/obj/machinery/proc/default_change_direction_wrench(var/mob/user, var/obj/item/wrench/W) - if(panel_open && istype(W)) - playsound(loc, W.usesound, 50, 1) +/obj/machinery/proc/default_change_direction_wrench(mob/user, obj/item/I) + if(I.tool_behaviour != TOOL_WRENCH) + return FALSE + if(!I.use_tool(src, user, 0, volume = 0)) + return FALSE + if(panel_open) dir = turn(dir,-90) to_chat(user, "You rotate [src].") - return 1 - return 0 + I.play_tool_sound(user, I.tool_volume) + return TRUE + return FALSE -/obj/proc/default_unfasten_wrench(mob/user, obj/item/wrench/W, time = 20) - if(!(flags & NODECONSTRUCT) && istype(W)) - to_chat(user, "Now [anchored ? "un" : ""]securing [name].") - playsound(loc, W.usesound, 50, 1) - if(do_after(user, time * W.toolspeed, target = src)) - to_chat(user, "You've [anchored ? "un" : ""]secured [name].") - anchored = !anchored - if(istype(src, /obj/machinery)) - var/obj/machinery/M = src - M.power_change() //Turn on or off the machine depending on the status of power in the new area. - playsound(loc, W.usesound, 50, 1) - return 1 - return 0 +/obj/machinery/default_unfasten_wrench(mob/user, obj/item/I, time) + . = ..() + if(.) + power_change() /obj/machinery/proc/exchange_parts(mob/user, obj/item/storage/part_replacer/W) var/shouldplaysound = 0 diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm index 68878e3ad13..9e6f0d672cc 100644 --- a/code/game/machinery/mass_driver.dm +++ b/code/game/machinery/mass_driver.dm @@ -101,18 +101,6 @@ /obj/machinery/mass_driver_frame/attackby(var/obj/item/W as obj, var/mob/user as mob) switch(build) if(0) // Loose frame - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(!WT.remove_fuel(0, user)) - to_chat(user, "The welding tool must be on to complete this task.") - return 1 - playsound(get_turf(src), WT.usesound, 50, 1) - to_chat(user, "You begin to cut the frame apart...") - if(do_after(user, 30 * WT.toolspeed, target = src) && (build == 0)) - to_chat(user, "You detach the plasteel sheets from each others.") - new /obj/item/stack/sheet/plasteel(get_turf(src),3) - qdel(src) - return 1 if(istype(W, /obj/item/wrench)) to_chat(user, "You begin to anchor \the [src] on the floor.") playsound(get_turf(src), W.usesound, 50, 1) @@ -133,31 +121,7 @@ anchored = 0 to_chat(user, "You de-anchored \the [src]!") return 1 - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(!WT.remove_fuel(0, user)) - to_chat(user, "The welding tool must be on to complete this task.") - return 1 - playsound(get_turf(src), WT.usesound, 50, 1) - to_chat(user, "You begin to weld \the [src] to the floor...") - if(do_after(user, 40 * WT.toolspeed, target = src) && (build == 1)) - to_chat(user, "You welded \the [src] to the floor.") - build++ - update_icon() - return 1 - return if(2) // Welded to the floor - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(!WT.remove_fuel(0, user)) - to_chat(user, "The welding tool must be on to complete this task.") - return 1 - playsound(get_turf(src), WT.usesound, 50, 1) - to_chat(user, "You begin to unweld \the [src] to the floor...") - if(do_after(user, 40 * WT.toolspeed, target = src) && (build == 2)) - to_chat(user, "You unwelded \the [src] to the floor.") - build-- - update_icon() if(istype(W, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C = W to_chat(user, "You start adding cables to \the [src]...") @@ -208,6 +172,30 @@ return return ..() +/obj/machinery/mass_driver_frame/welder_act(mob/user, obj/item/I) + if(build != 0 && build != 1 && build != 2) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(build == 0) //can deconstruct + WELDER_ATTEMPT_SLICING_MESSAGE + if(I.use_tool(src, user, 30, volume = I.tool_volume)) + WELDER_SLICING_SUCCESS_MESSAGE + new /obj/item/stack/sheet/plasteel(drop_location(),3) + qdel(src) + else if(build == 1) //wrenched but not welded down + WELDER_ATTEMPT_FLOOR_WELD_MESSAGE + if(I.use_tool(src, user, 40, volume = I.tool_volume) && build == 1) + WELDER_FLOOR_WELD_SUCCESS_MESSAGE + build = 2 + else if(build == 2) //welded down + WELDER_ATTEMPT_FLOOR_SLICE_MESSAGE + if(I.use_tool(src, user, 40, volume = I.tool_volume) && build == 2) + WELDER_FLOOR_SLICE_SUCCESS_MESSAGE + build = 1 + update_icon() + /obj/machinery/mass_driver_frame/update_icon() icon_state = "mass_driver_b[build]" diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index fba07d684ac..61d96602343 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -568,41 +568,29 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co SSnanoui.update_uis(src) return 1 -/obj/machinery/newscaster/attackby(obj/item/I, mob/living/user, params) - if(istype(I, /obj/item/wrench)) - to_chat(user, "Now [anchored ? "un" : ""]securing [name]") - playsound(loc, I.usesound, 50, 1) - if(do_after(user, 60 * I.toolspeed, target = src)) - playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE) - if(stat & BROKEN) - to_chat(user, "The broken remains of [src] fall on the ground.") - new /obj/item/stack/sheet/metal(loc, 5) - new /obj/item/shard(loc) - new /obj/item/shard(loc) - else - to_chat(user, "You [anchored ? "un" : ""]secure [name].") - new /obj/item/mounted/frame/newscaster_frame(loc) - qdel(src) - else if(iswelder(I) && user.a_intent != INTENT_HARM) - var/obj/item/weldingtool/WT = I - if(stat & BROKEN) - if(WT.remove_fuel(0, user)) - user.visible_message("[user] is repairing [src].", - "You begin repairing [src]...", - "You hear welding.") - playsound(loc, WT.usesound, 40, 1) - if(do_after(user,40 * WT.toolspeed, 1, target = src)) - if(!WT.isOn() || !(stat & BROKEN)) - return - to_chat(user, "You repair [src].") - playsound(loc, 'sound/items/welder2.ogg', 50, 1) - obj_integrity = max_integrity - stat &= ~BROKEN - update_icon() - else - to_chat(user, "[src] does not need repairs.") +/obj/machinery/newscaster/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + to_chat(user, "Now [anchored ? "un" : ""]securing [name]") + if(!I.use_tool(src, user, 60, volume = I.tool_volume)) + return + playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE) + if(stat & BROKEN) + to_chat(user, "The broken remains of [src] fall on the ground.") + new /obj/item/stack/sheet/metal(loc, 5) + new /obj/item/shard(loc) + new /obj/item/shard(loc) else - return ..() + to_chat(user, "You [anchored ? "un" : ""]secure [name].") + new /obj/item/mounted/frame/newscaster_frame(loc) + qdel(src) + +/obj/machinery/newscaster/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + default_welder_repair(user, I) /obj/machinery/newscaster/play_attack_sound(damage, damage_type = BRUTE, damage_flag = 0) switch(damage_type) diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm index b4241b5f19d..570256898f4 100644 --- a/code/game/machinery/pipe/construction.dm +++ b/code/game/machinery/pipe/construction.dm @@ -323,9 +323,10 @@ /obj/item/pipe/attack_self(mob/user as mob) return rotate() -/obj/item/pipe/attackby(var/obj/item/W as obj, var/mob/user as mob, params) - if(!istype(W, /obj/item/wrench)) - return ..() +/obj/item/pipe/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return if(!isturf(src.loc)) return 1 @@ -506,7 +507,6 @@ var/obj/machinery/atmospherics/omni/filter/P = new(loc) P.on_construction(dir, pipe_dir, color) - playsound(src.loc, W.usesound, 50, 1) user.visible_message( \ "[user] fastens the [src].", \ "You have fastened the [src].", \ diff --git a/code/game/machinery/poolcontroller.dm b/code/game/machinery/poolcontroller.dm index 4b512297ffd..53dd0135c54 100644 --- a/code/game/machinery/poolcontroller.dm +++ b/code/game/machinery/poolcontroller.dm @@ -28,21 +28,21 @@ /obj/machinery/poolcontroller/invisible/sea name = "Sea Controller" desc = "A controller for the underwater portion of the sea. Players shouldn't see this." - deep_water = TRUE + deep_water = TRUE -/obj/machinery/poolcontroller/Initialize(mapload) - var/contents_loop = linked_area +/obj/machinery/poolcontroller/Initialize(mapload) + var/contents_loop = linked_area if(!linked_area) contents_loop = range(srange, src) for(var/turf/T in contents_loop) if(istype(T, /turf/simulated/floor/beach/water)) var/turf/simulated/floor/beach/water/W = T - W.linkedcontroller = src + W.linkedcontroller = src linkedturfs += T else if(istype(T, /turf/unsimulated/beach/water)) var/turf/unsimulated/beach/water/W = T - W.linkedcontroller = src + W.linkedcontroller = src linkedturfs += T . = ..() @@ -57,18 +57,15 @@ emagged = 1 //Set the emag var to true. -/obj/machinery/poolcontroller/attackby(obj/item/I, mob/user, params) //Proc is called when a user hits the pool controller with something. - if(ismultitool(I)) //If the mob hits the pool controller with a multitool, reset the emagged status - if(emagged) //Check the emag status - to_chat(user, "You re-enable [src]'s temperature safeguards.")//Inform the user that they have just fixed the safeguards. - - emagged = FALSE //Set the emagged var to false. - else - to_chat(user, "Nothing happens.")//If not emagged, don't do anything, and don't tell the user that it can be emagged. - - - else //If it's not a multitool, defer to /obj/machinery/attackby - return ..() +/obj/machinery/poolcontroller/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(emagged) //Check the emag status + to_chat(user, "You re-enable [src]'s temperature safeguards.")//Inform the user that they have just fixed the safeguards. + emagged = FALSE //Set the emagged var to false. + else + to_chat(user, "Nothing happens.")//If not emagged, don't do anything, and don't tell the user that it can be emagged. /obj/machinery/poolcontroller/attack_hand(mob/user as mob) ui_interact(user) @@ -121,7 +118,7 @@ return //Has internals, no drowning if((NO_BREATHE in drownee.dna.species.species_traits) || (BREATHLESS in drownee.mutations)) return //doesn't breathe, no drowning - if(isskrell(drownee) || isneara(drownee)) + if(HAS_TRAIT(drownee,TRAIT_WATERBREATH)) return //fish things don't drown if(drownee.stat == DEAD) //Dead spacemen don't drown more diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 68c029f2111..f61b920814b 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -830,23 +830,6 @@ var/list/turret_icons build_step = 3 return - else if(istype(I, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = I - if(!WT.isOn()) - return - if(WT.get_fuel() < 5) //uses up 5 fuel. - to_chat(user, "You need more fuel to complete this task.") - return - - playsound(loc, WT.usesound, 50, 1) - if(do_after(user, 20 * WT.toolspeed, target = src)) - if(!src || !WT.remove_fuel(5, user)) return - build_step = 1 - to_chat(user, "You remove the turret's interior metal armor.") - new /obj/item/stack/sheet/metal( loc, 2) - return - - if(3) if(istype(I, /obj/item/gun/energy)) //the gun installation part @@ -911,31 +894,6 @@ var/list/turret_icons build_step = 5 to_chat(user, "You open the internal access hatch.") return - - if(7) - if(istype(I, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = I - if(!WT.isOn()) return - if(WT.get_fuel() < 5) - to_chat(user, "You need more fuel to complete this task.") - - playsound(loc, WT.usesound, 50, 1) - if(do_after(user, 30 * WT.toolspeed, target = src)) - if(!src || !WT.remove_fuel(5, user)) - return - build_step = 8 - to_chat(user, "You weld the turret's armor down.") - - //The final step: create a full turret - var/obj/machinery/porta_turret/Turret = new target_type(loc) - Turret.name = finish_name - Turret.installation = installation - Turret.gun_charge = gun_charge - Turret.enabled = 0 - Turret.setup() - - qdel(src) // qdel - else if(istype(I, /obj/item/crowbar)) playsound(loc, I.usesound, 75, 1) to_chat(user, "You pry off the turret's exterior armor.") @@ -955,6 +913,33 @@ var/list/turret_icons return ..() +/obj/machinery/porta_turret_construct/welder_act(mob/user, obj/item/I) + . = TRUE + if(build_step == 2) + if(!I.use_tool(src, user, 20, 5, volume = I.tool_volume)) + return + if(build_step != 2) + return + build_step = 1 + to_chat(user, "You remove the turret's interior metal armor.") + new /obj/item/stack/sheet/metal(drop_location(), 2) + else if(build_step == 7) + if(!I.use_tool(src, user, 50, amount = 5, volume = I.tool_volume)) + return + if(build_step != 7) + return + build_step = 8 + to_chat(user, "You weld the turret's armor down.") + + //The final step: create a full turret + var/obj/machinery/porta_turret/Turret = new target_type(loc) + Turret.name = finish_name + Turret.installation = installation + Turret.gun_charge = gun_charge + Turret.enabled = 0 + Turret.setup() + + qdel(src) /obj/machinery/porta_turret_construct/attack_hand(mob/user) switch(build_step) diff --git a/code/game/machinery/quantum_pad.dm b/code/game/machinery/quantum_pad.dm index e5a43c523f5..739d8e31a5d 100644 --- a/code/game/machinery/quantum_pad.dm +++ b/code/game/machinery/quantum_pad.dm @@ -42,30 +42,35 @@ teleport_cooldown -= (E * 100) /obj/machinery/quantumpad/attackby(obj/item/I, mob/user, params) - if(default_deconstruction_screwdriver(user, "pad-idle-o", "qpad-idle", I)) - return - - if(panel_open) - if(ismultitool(I)) - var/obj/item/multitool/M = I - M.buffer = src - to_chat(user, "You save the data in the [I.name]'s buffer.") - return 1 - else if(ismultitool(I)) - var/obj/item/multitool/M = I - if(istype(M.buffer, /obj/machinery/quantumpad)) - linked_pad = M.buffer - to_chat(user, "You link the [src] to the one in the [I.name]'s buffer.") - return 1 - if(exchange_parts(user, I)) return - - if(default_deconstruction_crowbar(I)) - return - return ..() +/obj/machinery/quantumpad/crowbar_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + default_deconstruction_crowbar(user, I) + +/obj/machinery/quantumpad/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!I.multitool_check_buffer(user)) + return + var/obj/item/multitool/M = I + if(panel_open) + M.set_multitool_buffer(user, src) + else + linked_pad = M.buffer + to_chat(user, "You link the [src] to the one in the [I.name]'s buffer.") + +/obj/machinery/quantumpad/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + default_deconstruction_screwdriver(user, "pad-idle-o", "qpad-idle", I) + /obj/machinery/quantumpad/attack_hand(mob/user) if(panel_open) to_chat(user, "The panel must be closed before operating this machine!") diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index 8e4e5e3dc59..82b473b50f0 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -29,16 +29,6 @@ recharge_coeff = C.rating /obj/machinery/recharger/attackby(obj/item/G, mob/user, params) - if(iswrench(G)) - if(charging) - to_chat(user, "Remove the charging item first!") - return - anchored = !anchored - power_change() - to_chat(user, "You [anchored ? "attached" : "detached"] [src].") - playsound(loc, G.usesound, 75, 1) - return - var/allowed = is_type_in_list(G, allowed_devices) if(allowed) @@ -67,17 +57,30 @@ else to_chat(user, "[src] isn't connected to anything!") return 1 - - if(anchored && !charging) - if(default_deconstruction_screwdriver(user, "rechargeropen", "recharger0", G)) - return - - if(panel_open && istype(G, /obj/item/crowbar)) - default_deconstruction_crowbar(G) - return - return ..() + +/obj/machinery/recharger/crowbar_act(mob/user, obj/item/I) + if(panel_open && !charging && default_deconstruction_crowbar(user, I)) + return TRUE + +/obj/machinery/recharger/screwdriver_act(mob/user, obj/item/I) + if(anchored && !charging && default_deconstruction_screwdriver(user, "rechargeropen", "recharger0", I)) + return TRUE + +/obj/machinery/recharger/wrench_act(mob/user, obj/item/I) + . = TRUE + if(charging) + to_chat(user, "Remove the charging item first!") + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + anchored = !anchored + if(anchored) + WRENCH_ANCHOR_MESSAGE + else + WRENCH_UNANCHOR_MESSAGE + /obj/machinery/recharger/attack_hand(mob/user) if(issilicon(user)) return diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 57903822b50..5907a27f70e 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -110,21 +110,23 @@ icon_state = "borgcharger0" /obj/machinery/recharge_station/attackby(obj/item/I, mob/user, params) - if(isscrewdriver(I)) - if(occupant) - to_chat(user, "The maintenance panel is locked.") - return - default_deconstruction_screwdriver(user, "borgdecon2", "borgcharger0", I) - return - if(exchange_parts(user, I)) return - if(default_deconstruction_crowbar(I)) - return else return ..() +/obj/machinery/recharge_station/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I)) + return TRUE + +/obj/machinery/recharge_station/screwdriver_act(mob/user, obj/item/I) + if(occupant) + to_chat(user, "The maintenance panel is locked.") + return TRUE + if(default_deconstruction_screwdriver(user, "borgdecon2", "borgcharger0", I)) + return TRUE + /obj/machinery/recharge_station/proc/process_occupant() if(src.occupant) if(istype(occupant, /mob/living/silicon/robot)) @@ -201,7 +203,7 @@ //Welding tools if(istype(O, /obj/item/weldingtool)) var/obj/item/weldingtool/weld = O - weld.reagents.check_and_add("fuel", weld.max_fuel, 2 * coeff) + weld.reagents.check_and_add("fuel", weld.maximum_fuel, 2 * coeff) if(R) if(R.module) R.module.respawn_consumable(R) diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index eb3052dd909..27c1261b3e9 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -8,6 +8,7 @@ var/const/SAFETY_COOLDOWN = 100 layer = MOB_LAYER+1 // Overhead anchored = 1 density = 1 + damage_deflection = 10 var/safety_mode = 0 // Temporarily stops machine if it detects a mob var/icon_name = "grinder-o" var/blood = 0 @@ -50,22 +51,25 @@ var/const/SAFETY_COOLDOWN = 100 ..() update_icon() - /obj/machinery/recycler/attackby(obj/item/I, mob/user, params) add_fingerprint(user) - if(default_deconstruction_screwdriver(user, "grinder-oOpen", "grinder-o0", I)) - return - if(exchange_parts(user, I)) return + return ..() +/obj/machinery/recycler/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I)) + return TRUE + +/obj/machinery/recycler/screwdriver_act(mob/user, obj/item/I) + if(default_deconstruction_screwdriver(user, "grinder-oOpen", "grinder-o0", I)) + return TRUE + +/obj/machinery/recycler/wrench_act(mob/user, obj/item/I) if(default_unfasten_wrench(user, I)) - return + return TRUE + - if(default_deconstruction_crowbar(I)) - return - else - return ..() /obj/machinery/recycler/emag_act(mob/user) if(!emagged) diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index 3cb06daab94..eba5e2f383d 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -240,15 +240,6 @@ malfunction = TRUE update_icon() - else if(isscrewdriver(I)) - playsound(loc, I.usesound, 100, 1) - if(is_open) - to_chat(user, "You close the panel.") - is_open = FALSE - else - to_chat(user, "You open the panel and expose the wiring.") - is_open = TRUE - else if(istype(I, /obj/item/stack/cable_coil) && malfunction && is_open) var/obj/item/stack/cable_coil/coil = I to_chat(user, "You begin to replace the wires.") @@ -262,25 +253,6 @@ to_chat(user, "You repair the [src]!") update_icon() - else if(istype(I, /obj/item/wrench)) - if(locked) - to_chat(user, "The bolts are covered, unlocking this would retract the covers.") - return - if(anchored) - playsound(loc, I.usesound, 100, 1) - to_chat(user, "You unsecure the [src] from the floor!") - if(active) - to_chat(user, "The [src] shuts off!") - shields_down() - anchored = 0 - else - if(istype(get_turf(src), /turf/space)) - return //No wrenching these in space! - playsound(loc, I.usesound, 100, 1) - to_chat(user, "You secure the [src] to the floor!") - anchored = 1 - - else if(istype(I, /obj/item/card/id) || istype(I, /obj/item/pda)) if(allowed(user)) locked = !locked @@ -289,8 +261,36 @@ to_chat(user, "Access denied.") else - ..() + return ..() +/obj/machinery/shieldgen/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + is_open = !is_open + if(is_open) + SCREWDRIVER_OPEN_PANEL_MESSAGE + else + SCREWDRIVER_CLOSE_PANEL_MESSAGE + +/obj/machinery/shieldgen/wrench_act(mob/user, obj/item/I) + . = TRUE + if(locked) + to_chat(user, "The bolts are covered, unlocking this would retract the covers.") + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(anchored) + WRENCH_UNANCHOR_MESSAGE + if(active) + visible_message("[src] shuts off!") + shields_down() + anchored = FALSE + else + if(istype(get_turf(src), /turf/space)) + return //No wrenching these in space! + WRENCH_ANCHOR_MESSAGE + anchored = TRUE /obj/machinery/shieldgen/update_icon() if(active) diff --git a/code/game/machinery/snow_machine.dm b/code/game/machinery/snow_machine.dm index cc59f0a3017..acb69590f9a 100644 --- a/code/game/machinery/snow_machine.dm +++ b/code/game/machinery/snow_machine.dm @@ -43,20 +43,22 @@ to_chat(user, "You [active ? "turn on" : "turn off"] [src].") return ..() -/obj/machinery/snow_machine/attackby(obj/item/I, mob/user) - if(isscrewdriver(I)) - if(default_deconstruction_screwdriver(user, "snow_machine_openpanel", "snow_machine_off", I)) - turn_on_or_off(FALSE) - else if(iscrowbar(I)) - default_deconstruction_crowbar(I) - else if(iswrench(I)) - var/obj/item/wrench/W = I - anchored = !anchored - to_chat(user, "You [anchored ? "tighten" : "loosen"] [src]'s wheels.") - playsound(loc, W.usesound, 50, TRUE) +/obj/machinery/snow_machine/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I)) + return TRUE + +/obj/machinery/snow_machine/screwdriver_act(mob/user, obj/item/I) + if(default_deconstruction_screwdriver(user, "snow_machine_openpanel", "snow_machine_off", I)) turn_on_or_off(FALSE) - else - return ..() + return TRUE + +/obj/machinery/snow_machine/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + anchored = !anchored + to_chat(user, "You [anchored ? "tighten" : "loosen"] [src]'s wheels.") + turn_on_or_off(FALSE) /obj/machinery/snow_machine/process() if(power_used_this_cycle) diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index 3cfe6fe50ff..4021b11c39a 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -68,16 +68,24 @@ else to_chat(user, "The hatch must be open to insert a power cell.") return - else if(isscrewdriver(I)) - open = !open - user.visible_message("[user] [open ? "opens" : "closes"] the hatch on [src].", "You [open ? "open" : "close"] the hatch on [src].") - update_icon() - if(!open && user.machine == src) - user << browse(null, "window=spaceheater") - user.unset_machine() + else return ..() +/obj/machinery/space_heater/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + open = !open + if(open) + SCREWDRIVER_OPEN_PANEL_MESSAGE + else + SCREWDRIVER_CLOSE_PANEL_MESSAGE + update_icon() + if(!open && user.machine == src) + user << browse(null, "window=spaceheater") + user.unset_machine() + /obj/machinery/space_heater/attack_hand(mob/user as mob) src.add_fingerprint(user) interact(user) diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 3437bafeb3b..c3ad823ad3d 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -297,12 +297,7 @@ else to_chat(usr, "The unit is not operational.") return - if(isscrewdriver(I)) - panel_open = !panel_open - playsound(loc, I.usesound, 100, 1) - to_chat(user, text("You [panel_open ? "open up" : "close"] the unit's maintenance panel.")) - updateUsrDialog() - return + if(panel_open) wires.Interact(user) return @@ -313,10 +308,27 @@ updateUsrDialog() to_chat(user, "You load the [I] into the storage compartment.") else - to_chat(user, "The unit already contains that item.") + to_chat(user, "You can't fit [I] into [src]!") return return ..() +/obj/machinery/suit_storage_unit/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(shocked && shock(user, 100)) + return + if(!is_operational()) + if(panel_open) + to_chat(user, "Close the maintenance panel first.") + else + to_chat(user, "The unit is not operational.") + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + + panel_open = !panel_open + to_chat(user, text("You [panel_open ? "open up" : "close"] the unit's maintenance panel.")) + updateUsrDialog() + return /obj/machinery/suit_storage_unit/proc/store_item(obj/item/I, mob/user) . = FALSE diff --git a/code/game/machinery/supply_display.dm b/code/game/machinery/supply_display.dm index d08f68b2914..1fe7ee6e4cb 100644 --- a/code/game/machinery/supply_display.dm +++ b/code/game/machinery/supply_display.dm @@ -14,7 +14,7 @@ else message1 = "CARGO" message2 = SSshuttle.supply.getTimerStr() - if(lentext(message2) > CHARS_PER_LINE) + if(length(message2) > CHARS_PER_LINE) message2 = "Error" update_display(message1, message2) diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm index bc5eace7338..e9b0d25c672 100644 --- a/code/game/machinery/syndicatebeacon.dm +++ b/code/game/machinery/syndicatebeacon.dm @@ -82,7 +82,7 @@ var/datum/antagonist/traitor/T = new() T.give_objectives = FALSE N.mind.add_antag_datum(T) - + to_chat(M, "You have joined the ranks of the Syndicate and become a traitor to the station!") message_admins("[key_name_admin(N)] has accepted a traitor objective from a syndicate beacon.") @@ -153,26 +153,24 @@ return -/obj/machinery/power/singularity_beacon/attackby(obj/item/I, mob/user, params) - if(isscrewdriver(I)) - if(active) - to_chat(user, "You need to deactivate the beacon first!") - return - - if(anchored) - anchored = FALSE - to_chat(user, "You unscrew the beacon from the floor.") - disconnect_from_network() - return - else - if(!connect_to_network()) - to_chat(user, "This device must be placed over an exposed cable.") - return - anchored = TRUE - to_chat(user, "You screw the beacon to the floor and attach the cable.") +/obj/machinery/power/singularity_beacon/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(active) + to_chat(user, "You need to deactivate the beacon first!") + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(anchored) + anchored = FALSE + to_chat(user, "You unscrew the beacon from the floor.") + disconnect_from_network() + return else - return ..() - + if(!connect_to_network()) + to_chat(user, "This device must be placed over an exposed cable.") + return + anchored = TRUE + to_chat(user, "You screw the beacon to the floor and attach the cable.") /obj/machinery/power/singularity_beacon/Destroy() if(active) diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index 28a35680cdb..f038b573871 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -111,45 +111,9 @@ . = timer_set /obj/machinery/syndicatebomb/attackby(obj/item/I, mob/user, params) - if(iswrench(I) && can_unanchor) - if(!anchored) - if(!isturf(loc) || isspaceturf(loc)) - to_chat(user, "The bomb must be placed on solid ground to attach it.") - else - to_chat(user, "You firmly wrench the bomb to the floor.") - playsound(loc, I.usesound, 50, 1) - anchored = 1 - if(active) - to_chat(user, "The bolts lock in place.") - else - if(!active) - to_chat(user, "You wrench the bomb from the floor.") - playsound(loc, I.usesound, 50, 1) - anchored = 0 - else - to_chat(user, "The bolts are locked down!") - - else if(isscrewdriver(I)) - open_panel = !open_panel - update_icon() - to_chat(user, "You [open_panel ? "open" : "close"] the wire panel.") - - else if(istype(I, /obj/item/wirecutters) || istype(I, /obj/item/multitool) || istype(I, /obj/item/assembly/signaler )) + if(istype(I, /obj/item/assembly/signaler)) if(open_panel) wires.Interact(user) - - else if(iscrowbar(I)) - if(open_panel && wires.IsAllCut()) - if(payload) - to_chat(user, "You carefully pry out [payload].") - payload.loc = user.loc - payload = null - else - to_chat(user, "There isn't anything in here to remove!") - else if(open_panel) - to_chat(user, "The wires connecting the shell to the explosives are holding it down!") - else - to_chat(user, "The cover is screwed on, it won't pry off!") else if(istype(I, /obj/item/bombcore)) if(!payload) if(!user.drop_item()) @@ -159,27 +123,82 @@ payload.forceMove(src) else to_chat(user, "[payload] is already loaded into [src], you'll have to remove it first.") - else if(iswelder(I)) - if(payload || !wires.IsAllCut() || !open_panel) - return - var/obj/item/weldingtool/WT = I - if(!WT.isOn()) - return - if(WT.get_fuel() < 5) //uses up 5 fuel. - to_chat(user, "You need more fuel to complete this task!") - return - - playsound(loc, WT.usesound, 50, 1) - to_chat(user, "You start to cut the [src] apart...") - if(do_after(user, 20*I.toolspeed, target = src)) - if(!WT.isOn() || !WT.remove_fuel(5, user)) - return - to_chat(user, "You cut the [src] apart.") - new /obj/item/stack/sheet/plasteel(loc, 3) - qdel(src) else return ..() +/obj/machinery/syndicatebomb/wrench_act(mob/user, obj/item/I) + if(!can_unanchor) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!anchored) + if(!isturf(loc) || isspaceturf(loc)) + to_chat(user, "The bomb must be placed on solid ground to attach it.") + else + WRENCH_ANCHOR_MESSAGE + anchored = TRUE + if(active) + to_chat(user, "The bolts lock in place.") + else + if(!active) + WRENCH_UNANCHOR_MESSAGE + anchored = FALSE + else + to_chat(user, "The bolts are locked down!") + +/obj/machinery/syndicatebomb/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + open_panel = !open_panel + update_icon() + to_chat(user, "You [open_panel ? "open" : "close"] the wire panel.") + +/obj/machinery/syndicatebomb/wirecutter_act(mob/user, obj/item/I) + if(!open_panel) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + wires.Interact(user) + +/obj/machinery/syndicatebomb/multitool_act(mob/user, obj/item/I) + if(!open_panel) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + wires.Interact(user) + +/obj/machinery/syndicatebomb/crowbar_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(open_panel && wires.IsAllCut()) + if(payload) + to_chat(user, "You carefully pry out [payload].") + payload.loc = user.loc + payload = null + else + to_chat(user, "There isn't anything in here to remove!") + else if(open_panel) + to_chat(user, "The wires connecting the shell to the explosives are holding it down!") + else + to_chat(user, "The cover is screwed on, it won't pry off!") + +/obj/machinery/syndicatebomb/welder_act(mob/user, obj/item/I) + . = TRUE + if(payload || !wires.IsAllCut() || !open_panel) + return + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_SLICING_MESSAGE + if(I.use_tool(src, user, 50, volume = I.tool_volume)) + WELDER_SLICING_SUCCESS_MESSAGE + new /obj/item/stack/sheet/plasteel(drop_location(), 3) + qdel(src) + /obj/machinery/syndicatebomb/attack_ghost(mob/user) interact(user) @@ -497,13 +516,7 @@ qdel(src) /obj/item/bombcore/chemical/attackby(obj/item/I, mob/user, params) - if(iscrowbar(I) && beakers.len > 0) - playsound(loc, I.usesound, 50, 1) - for (var/obj/item/B in beakers) - B.loc = get_turf(src) - beakers -= B - return - else if(istype(I, /obj/item/reagent_containers/glass/beaker) || istype(I, /obj/item/reagent_containers/glass/bottle)) + if(istype(I, /obj/item/reagent_containers/glass/beaker) || istype(I, /obj/item/reagent_containers/glass/bottle)) if(beakers.len < max_beakers) if(!user.drop_item()) return @@ -516,6 +529,16 @@ else return ..() +/obj/item/bombcore/chemical/crowbar_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(beakers.len == 0) + return + for(var/obj/item/B in beakers) + B.loc = get_turf(src) + beakers -= B + /obj/item/bombcore/chemical/CheckParts(list/parts_list) ..() // Using different grenade casings, causes the payload to have different properties. @@ -564,11 +587,7 @@ var/obj/item/transfer_valve/ttv = null /obj/item/bombcore/toxins/attackby(obj/item/I, mob/user) - if(iscrowbar(I) && ttv) - playsound(loc, I.usesound, 50, 1) - ttv.forceMove(get_turf(src)) - ttv = null - else if(istype(I, /obj/item/transfer_valve)) + if(istype(I, /obj/item/transfer_valve)) if(!ttv && !check_attached(I)) if(!user.drop_item()) return @@ -582,6 +601,17 @@ else return ..() +/obj/item/bombcore/toxins/crowbar_act(mob/user, obj/item/I) + if(!ttv) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + ttv.forceMove(get_turf(src)) + ttv = null + + + /obj/item/bombcore/toxins/proc/check_attached(obj/item/transfer_valve/ttv) if (ttv.attached_device) return TRUE diff --git a/code/game/machinery/telecomms/traffic_control.dm b/code/game/machinery/telecomms/traffic_control.dm index 1fe1490442a..9ee390ef9ec 100644 --- a/code/game/machinery/telecomms/traffic_control.dm +++ b/code/game/machinery/telecomms/traffic_control.dm @@ -10,12 +10,12 @@ var/window_id // mostly used to let the configuration datum update the user's UI var/unlocked = FALSE -/obj/machinery/computer/telecomms/traffic/attackby(obj/item/I, mob/user) - if(ismultitool(I)) - unlocked = !unlocked - to_chat(user, "This computer is now [unlocked ? "Unlocked" : "Locked"]. Reopen the UI to see the difference.") +/obj/machinery/computer/telecomms/traffic/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return - return ..() + unlocked = !unlocked + to_chat(user, "This computer is now [unlocked ? "Unlocked" : "Locked"]. Reopen the UI to see the difference.") /obj/machinery/computer/telecomms/traffic/attack_hand(mob/user) interact(user) diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index ca2f1c1fa1a..04803286db1 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -348,17 +348,18 @@ return /obj/machinery/teleport/hub/attackby(obj/item/I, mob/user, params) - if(default_deconstruction_screwdriver(user, "tele-o", "tele0", I)) - return - if(exchange_parts(user, I)) return - - if(default_deconstruction_crowbar(I)) - return - return ..() +/obj/machinery/teleport/hub/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I)) + return TRUE + +/obj/machinery/teleport/hub/screwdriver_act(mob/user, obj/item/I) + if(default_deconstruction_screwdriver(user, "tele-o", "tele0", I)) + return TRUE + /obj/machinery/teleport/hub/proc/teleport(atom/movable/M as mob|obj, turf/T) . = TRUE var/obj/machinery/computer/teleporter/com = power_station.teleporter_console @@ -450,17 +451,18 @@ icon_state = "tele0" /obj/machinery/teleport/perma/attackby(obj/item/I, mob/user, params) - if(default_deconstruction_screwdriver(user, "tele-o", "tele0", I)) - return - if(exchange_parts(user, I)) return - - if(default_deconstruction_crowbar(I)) - return - return ..() +/obj/machinery/teleport/perma/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I)) + return TRUE + +/obj/machinery/teleport/perma/screwdriver_act(mob/user, obj/item/I) + if(default_deconstruction_screwdriver(user, "tele-o", "tele0", I)) + return TRUE + /obj/machinery/teleport/station name = "station" desc = "The power control station for a bluespace teleporter." @@ -520,8 +522,27 @@ return ..() /obj/machinery/teleport/station/attackby(obj/item/I, mob/user, params) - if(ismultitool(I) && !panel_open) - var/obj/item/multitool/M = I + if(exchange_parts(user, I)) + return + if(panel_open && istype(I, /obj/item/circuitboard/teleporter_perma)) + var/obj/item/circuitboard/teleporter_perma/C = I + C.target = teleporter_console.target + to_chat(user, "You copy the targeting information from [src] to [C]") + return + return ..() + +/obj/machinery/teleport/station/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I)) + return TRUE + +/obj/machinery/teleport/station/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!I.multitool_check_buffer(user)) + return + var/obj/item/multitool/M = I + if(!panel_open) if(M.buffer && istype(M.buffer, /obj/machinery/teleport/station) && M.buffer != src) if(linked_stations.len < efficiency) linked_stations.Add(M.buffer) @@ -530,34 +551,21 @@ else to_chat(user, "This station can't hold more information, try to use better parts.") return + M.set_multitool_buffer(user, src) +/obj/machinery/teleport/station/screwdriver_act(mob/user, obj/item/I) if(default_deconstruction_screwdriver(user, "controller-o", "controller", I)) update_icon() - return + return TRUE - if(exchange_parts(user, I)) +/obj/machinery/teleport/station/wirecutter_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return - - if(default_deconstruction_crowbar(I)) - return - if(panel_open) - if(ismultitool(I)) - var/obj/item/multitool/M = I - M.buffer = src - to_chat(user, "You download the data to the [M]'s buffer.") - return - if(iswirecutter(I)) - link_console_and_hub() - to_chat(user, "You reconnect the station to nearby machinery.") - return - if(istype(I, /obj/item/circuitboard/teleporter_perma)) - var/obj/item/circuitboard/teleporter_perma/C = I - C.target = teleporter_console.target - to_chat(user, "You copy the targeting information from [src] to [C]") - return + link_console_and_hub() + to_chat(user, "You reconnect the station to nearby machinery.") - return ..() /obj/machinery/teleport/station/attack_ai() src.attack_hand() diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 03b325dd649..00d9f94a356 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -246,25 +246,6 @@ SSnanoui.update_uis(src) return // don't smack that machine with your 2 thalers - if(default_unfasten_wrench(user, I, time = 60)) - return - - if(isscrewdriver(I) && anchored) - playsound(loc, I.usesound, 50, 1) - panel_open = !panel_open - to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.") - overlays.Cut() - if(panel_open) - overlays += image(icon, "[initial(icon_state)]-panel") - SSnanoui.update_uis(src) // Speaker switch is on the main UI, not wires UI - return - - if(panel_open) - if(ismultitool(I) || iswirecutter(I)) - return attack_hand(user) - if(component_parts && iscrowbar(I)) - default_deconstruction_crowbar(I) - return if(istype(I, /obj/item/coin) && premium.len) if(!user.drop_item()) return @@ -296,6 +277,45 @@ return return ..() + + +/obj/machinery/vending/crowbar_act(mob/user, obj/item/I) + if(!component_parts) + return + . = TRUE + default_deconstruction_crowbar(user, I) + +/obj/machinery/vending/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + wires.Interact(user) + +/obj/machinery/vending/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(anchored) + panel_open = !panel_open + if(panel_open) + SCREWDRIVER_OPEN_PANEL_MESSAGE + overlays += image(icon, "[initial(icon_state)]-panel") + else + SCREWDRIVER_CLOSE_PANEL_MESSAGE + overlays.Cut() + SSnanoui.update_uis(src) // Speaker switch is on the main UI, not wires UI + +/obj/machinery/vending/wirecutter_act(mob/user, obj/item/I) + . = TRUE + if(I.use_tool(src, user, 0, volume = 0)) + wires.Interact(user) + +/obj/machinery/vending/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = 0)) + return + default_unfasten_wrench(user, I, time = 60) + //Override this proc to do per-machine checks on the inserted item, but remember to call the parent to handle these generic checks before your logic! /obj/machinery/vending/proc/item_slot_check(mob/user, obj/item/I) if(!item_slot) diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index 5b5f483b94f..0bfbef39289 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -316,40 +316,38 @@ var/mob/originaloccupant = chassis.occupant spawn(0) src = null //if src is deleted, still process the syringe - for(var/i=0, i<6, i++) + var/max_range = 6 + for(var/i=0, i [M] was hit by the syringe!") - if(M.can_inject(null, TRUE)) - if(mechsyringe.reagents) - for(var/datum/reagent/A in mechsyringe.reagents.reagent_list) - R += A.id + " (" - R += num2text(A.volume) + ")," - add_attack_logs(originaloccupant, M, "Shot with [src] containing [R], transferred [mechsyringe.reagents.total_volume] units") - mechsyringe.icon_state = initial(mechsyringe.icon_state) - mechsyringe.icon = initial(mechsyringe.icon) - mechsyringe.reagents.reaction(M, INGEST) - mechsyringe.reagents.trans_to(M, mechsyringe.reagents.total_volume) - M.take_organ_damage(2) - break - else if(mechsyringe.loc == trg) - mechsyringe.icon_state = initial(mechsyringe.icon_state) - mechsyringe.icon = initial(mechsyringe.icon) - mechsyringe.update_icon() - break - else - mechsyringe.icon_state = initial(mechsyringe.icon_state) - mechsyringe.icon = initial(mechsyringe.icon) - mechsyringe.update_icon() + if(!step_towards(mechsyringe,trg)) + break + + var/list/mobs = new + for(var/mob/living/carbon/M in mechsyringe.loc) + mobs += M + var/mob/living/carbon/M = safepick(mobs) + if(M) + var/R + mechsyringe.visible_message(" [M] was hit by the syringe!") + if(M.can_inject(null, TRUE)) + if(mechsyringe.reagents) + for(var/datum/reagent/A in mechsyringe.reagents.reagent_list) + R += A.id + " (" + R += num2text(A.volume) + ")," + add_attack_logs(originaloccupant, M, "Shot with [src] containing [R], transferred [mechsyringe.reagents.total_volume] units") + mechsyringe.reagents.reaction(M, INGEST) + mechsyringe.reagents.trans_to(M, mechsyringe.reagents.total_volume) + M.take_organ_damage(2) + break + else if(mechsyringe.loc == trg) break sleep(1) + if(mechsyringe) + // Revert the syringe icon to normal one once it stops flying. + mechsyringe.icon_state = initial(mechsyringe.icon_state) + mechsyringe.icon = initial(mechsyringe.icon) + mechsyringe.update_icon() return 1 @@ -537,7 +535,7 @@ if(!istype(target, /obj/machinery/door))//early return if we're not trying to open a door return var/obj/machinery/door/D = target //the door we want to open - D.try_to_crowbar(src, chassis.occupant)//use the door's crowbar function + D.try_to_crowbar(chassis.occupant, src)//use the door's crowbar function if(isliving(target)) //interact with living beings var/mob/living/M = target if(chassis.occupant.a_intent == INTENT_HARM)//the patented, medical rescue claw is incapable of doing harm. Worry not. diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm index 895361f301b..239d2ce493f 100644 --- a/code/game/mecha/mech_bay.dm +++ b/code/game/mecha/mech_bay.dm @@ -68,20 +68,23 @@ max_charge = MC * 25 /obj/machinery/mech_bay_recharge_port/attackby(obj/item/I, mob/user, params) - if(default_deconstruction_screwdriver(user, "recharge_port-o", "recharge_port", I)) - return - - if(default_change_direction_wrench(user, I)) - recharging_turf = get_step(loc, dir) - return - if(exchange_parts(user, I)) return - - if(default_deconstruction_crowbar(I)) - return return ..() +/obj/machinery/mech_bay_recharge_port/screwdriver_act(mob/user, obj/item/I) + if(default_deconstruction_screwdriver(user, "recharge_port-o", "recharge_port", I)) + return TRUE + +/obj/machinery/mech_bay_recharge_port/wrench_act(mob/user, obj/item/I) + if(default_change_direction_wrench(user, I)) + recharging_turf = get_step(loc, dir) + return TRUE + +/obj/machinery/mech_bay_recharge_port/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I)) + return TRUE + /obj/machinery/mech_bay_recharge_port/Destroy() if(recharge_console) recharge_console.recharge_port = null diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 1254f9e5357..769ac8d0d54 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -434,7 +434,7 @@ if(exchange_parts(user, W)) return - if(default_deconstruction_crowbar(W)) + if(default_deconstruction_crowbar(user, W)) return TRUE else diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 85f511395f1..7c4aee9781c 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -696,31 +696,6 @@ else to_chat(user, "Maintenance protocols disabled by operator.") - else if(iswrench(W)) - if(state==1) - state = 2 - to_chat(user, "You undo the securing bolts.") - else if(state==2) - state = 1 - to_chat(user, "You tighten the securing bolts.") - return - - else if(iscrowbar(W)) - if(state==2) - state = 3 - to_chat(user, "You open the hatch to the power unit") - else if(state==3) - state=2 - to_chat(user, "You close the hatch to the power unit") - else if(state==4 && pilot_is_mmi()) - // Since having maint protocols available is controllable by the MMI, I see this as a consensual way to remove an MMI without destroying the mech - user.visible_message("[user] begins levering out the MMI from the [src].", "You begin to lever out the MMI from the [src].") - to_chat(occupant, "[user] is prying you out of the exosuit!") - if(do_after(user, 80 * W.toolspeed, target=src)) - user.visible_message("[user] pries the MMI out of the [src]!", "You finish removing the MMI from the [src]!") - go_out() - return - else if(istype(W, /obj/item/stack/cable_coil)) if(state == 3 && hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) var/obj/item/stack/cable_coil/CC = W @@ -732,21 +707,6 @@ to_chat(user, "There's not enough wire to finish the task.") return - else if(isscrewdriver(W) && user.a_intent != INTENT_HARM) - if(hasInternalDamage(MECHA_INT_TEMP_CONTROL)) - clearInternalDamage(MECHA_INT_TEMP_CONTROL) - to_chat(user, "You repair the damaged temperature controller.") - else if(state==3 && cell) - cell.forceMove(loc) - cell = null - state = 4 - to_chat(user, "You unscrew and pry out the powercell.") - log_message("Powercell removed") - else if(state==4 && cell) - state=3 - to_chat(user, "You screw the cell in place.") - return - else if(istype(W, /obj/item/stock_parts/cell)) if(state==4) if(!cell) @@ -760,24 +720,6 @@ to_chat(user, "There's already a powercell installed.") return - else if(iswelder(W) && user.a_intent != INTENT_HARM) - var/obj/item/weldingtool/WT = W - if(obj_integrity < max_integrity) - if(WT.remove_fuel(0, user)) - user.visible_message("[user] starts repairing some damage to [name].", "You start repairing some damage to [name]") - if(do_after_once(user, 15 * WT.toolspeed, target = src, attempt_cancel_message = "You stop repairing [name].")) - if(internal_damage & MECHA_INT_TANK_BREACH) - clearInternalDamage(MECHA_INT_TANK_BREACH) - user.visible_message("[user] repairs the damaged gas tank.", "You repair the damaged gas tank.") - else - user.visible_message("[user] repairs some damage to [name].", "You repair some damage to [name].") - obj_integrity += min(10, max_integrity - obj_integrity) - else - to_chat(user, "The welder must be on for this task!") - else - to_chat(user, "The [name] is at full integrity!") - return TRUE - else if(istype(W, /obj/item/mecha_parts/mecha_tracking)) if(!user.unEquip(W)) to_chat(user, "\the [W] is stuck to your hand, you cannot put it in \the [src]") @@ -828,6 +770,81 @@ else return ..() + +/obj/mecha/crowbar_act(mob/user, obj/item/I) + if(state != 2 && state != 3 && !(state == 4 && pilot_is_mmi())) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(state == 2) + state = 3 + to_chat(user, "You open the hatch to the power unit") + else if(state == 3) + state = 2 + to_chat(user, "You close the hatch to the power unit") + else + // Since having maint protocols available is controllable by the MMI, I see this as a consensual way to remove an MMI without destroying the mech + user.visible_message("[user] begins levering out the MMI from the [src].", "You begin to lever out the MMI from the [src].") + to_chat(occupant, "[user] is prying you out of the exosuit!") + if(I.use_tool(src, user, 80, volume = I.tool_volume) && pilot_is_mmi()) + user.visible_message("[user] pries the MMI out of the [src]!", "You finish removing the MMI from the [src]!") + go_out() + +/obj/mecha/screwdriver_act(mob/user, obj/item/I) + if(user.a_intent == INTENT_HARM) + return + if(!(state==3 && cell) && !(state==4 && cell)) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(hasInternalDamage(MECHA_INT_TEMP_CONTROL)) + clearInternalDamage(MECHA_INT_TEMP_CONTROL) + to_chat(user, "You repair the damaged temperature controller.") + else if(state==3 && cell) + cell.forceMove(loc) + cell = null + state = 4 + to_chat(user, "You unscrew and pry out the powercell.") + log_message("Powercell removed") + else if(state==4 && cell) + state=3 + to_chat(user, "You screw the cell in place.") + +/obj/mecha/wrench_act(mob/user, obj/item/I) + if(state != 1 && state != 2) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(state==1) + state = 2 + to_chat(user, "You undo the securing bolts.") + else + state = 1 + to_chat(user, "You tighten the securing bolts.") + +/obj/mecha/welder_act(mob/user, obj/item/I) + if(user.a_intent == INTENT_HARM) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if((obj_integrity >= max_integrity) && !internal_damage) + to_chat(user, "[src] is at full integrity!") + return + WELDER_ATTEMPT_REPAIR_MESSAGE + if(I.use_tool(src, user, 15, volume = I.tool_volume)) + if(internal_damage & MECHA_INT_TANK_BREACH) + clearInternalDamage(MECHA_INT_TANK_BREACH) + user.visible_message("[user] repairs the damaged gas tank.", "You repair the damaged gas tank.") + else if(obj_integrity < max_integrity) + user.visible_message("[user] repairs some damage to [name].", "You repair some damage to [name].") + obj_integrity += min(10, max_integrity - obj_integrity) + else + to_chat(user, "[src] is at full integrity!") + /obj/mecha/mech_melee_attack(obj/mecha/M) if(!has_charge(melee_energy_drain)) return 0 diff --git a/code/game/mecha/mecha_construction_paths.dm b/code/game/mecha/mecha_construction_paths.dm index 59de4cc45b4..64eac560d39 100644 --- a/code/game/mecha/mecha_construction_paths.dm +++ b/code/game/mecha/mecha_construction_paths.dm @@ -5,25 +5,7 @@ //////////////////////////////// /datum/construction/mecha/custom_action(step, atom/used_atom, mob/user) - if(istype(used_atom, /obj/item/weldingtool)) - var/obj/item/weldingtool/W = used_atom - if(W.remove_fuel(0, user)) - playsound(holder, W.usesound, 50, 1) - else - return 0 - else if(istype(used_atom, /obj/item/wrench)) - var/obj/item/wrench/W = used_atom - playsound(holder, W.usesound, 50, 1) - - else if(istype(used_atom, /obj/item/screwdriver)) - var/obj/item/screwdriver/S = used_atom - playsound(holder, S.usesound, 50, 1) - - else if(istype(used_atom, /obj/item/wirecutters)) - var/obj/item/wirecutters/W = used_atom - playsound(holder, W.usesound, 50, 1) - - else if(istype(used_atom, /obj/item/stack/cable_coil)) + if(istype(used_atom, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C = used_atom if(C.use(4)) playsound(holder, C.usesound, 50, 1) @@ -37,28 +19,11 @@ return 0 else S.use(STANDARD_STACK_AMOUNT) - return 1 + else + return ..() /datum/construction/reversible/mecha/custom_action(index as num, diff as num, atom/used_atom, mob/user as mob) - if(istype(used_atom, /obj/item/weldingtool)) - var/obj/item/weldingtool/W = used_atom - if(W.remove_fuel(0, user)) - playsound(holder, W.usesound, 50, 1) - else - return 0 - else if(istype(used_atom, /obj/item/wrench)) - var/obj/item/wrench/W = used_atom - playsound(holder, W.usesound, 50, 1) - - else if(istype(used_atom, /obj/item/screwdriver)) - var/obj/item/screwdriver/S = used_atom - playsound(holder, S.usesound, 50, 1) - - else if(istype(used_atom, /obj/item/wirecutters)) - var/obj/item/wirecutters/W = used_atom - playsound(holder, W.usesound, 50, 1) - - else if(istype(used_atom, /obj/item/stack/cable_coil)) + if(istype(used_atom, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C = used_atom if(C.use(4)) playsound(holder, C.usesound, 50, 1) @@ -72,6 +37,11 @@ return 0 else S.use(STANDARD_STACK_AMOUNT) + else if(isitem(used_atom)) + var/obj/item/I = used_atom + if(I.tool_behaviour in CONSTRUCTION_TOOL_BEHAVIOURS) + if(!I.use_tool(holder, user, 0, volume = I.tool_volume)) + return 0 return 1 @@ -108,59 +78,59 @@ taskpath = /datum/job_objective/make_ripley steps = list( //1 - list("key"=/obj/item/weldingtool, - "backkey"=/obj/item/wrench, + list("key"=TOOL_WELDER, + "backkey"=TOOL_WRENCH, "desc"="External armor is wrenched."), //2 - list("key"=/obj/item/wrench, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_WRENCH, + "backkey"=TOOL_CROWBAR, "desc"="External armor is installed."), //3 list("key"=/obj/item/stack/sheet/plasteel, - "backkey"=/obj/item/weldingtool, + "backkey"=TOOL_WELDER, "desc"="Internal armor is welded."), //4 - list("key"=/obj/item/weldingtool, - "backkey"=/obj/item/wrench, + list("key"=TOOL_WELDER, + "backkey"=TOOL_WRENCH, "desc"="Internal armor is wrenched."), //5 - list("key"=/obj/item/wrench, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_WRENCH, + "backkey"=TOOL_CROWBAR, "desc"="Internal armor is installed."), //6 list("key"=/obj/item/stack/sheet/metal, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Peripherals control module is secured."), //7 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Peripherals control module is installed."), //8 list("key"=/obj/item/circuitboard/mecha/ripley/peripherals, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Central control module is secured."), //9 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Central control module is installed."), //10 list("key"=/obj/item/circuitboard/mecha/ripley/main, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The wiring is adjusted."), //11 list("key"=/obj/item/wirecutters, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The wiring is added."), //12 list("key"=/obj/item/stack/cable_coil, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The hydraulic systems are active."), //13 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/wrench, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_WRENCH, "desc"="The hydraulic systems are connected."), //14 - list("key"=/obj/item/wrench, + list("key"=TOOL_WRENCH, "desc"="The hydraulic systems are disconnected.") ) @@ -317,83 +287,83 @@ result = "/obj/mecha/combat/gygax" steps = list( //1 - list("key"=/obj/item/weldingtool, - "backkey"=/obj/item/wrench, + list("key"=TOOL_WELDER, + "backkey"=TOOL_WRENCH, "desc"="External armor is wrenched."), //2 - list("key"=/obj/item/wrench, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_WRENCH, + "backkey"=TOOL_CROWBAR, "desc"="External armor is installed."), //3 list("key"=/obj/item/mecha_parts/part/gygax_armour, - "backkey"=/obj/item/weldingtool, + "backkey"=TOOL_WELDER, "desc"="Internal armor is welded."), //4 - list("key"=/obj/item/weldingtool, - "backkey"=/obj/item/wrench, + list("key"=TOOL_WELDER, + "backkey"=TOOL_WRENCH, "desc"="Internal armor is wrenched."), //5 - list("key"=/obj/item/wrench, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_WRENCH, + "backkey"=TOOL_CROWBAR, "desc"="Internal armor is installed."), //6 list("key"=/obj/item/stack/sheet/metal, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Advanced capacitor is secured."), //7 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Advanced capacitor is installed."), //8 list("key"=/obj/item/stock_parts/capacitor/adv, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Advanced scanner module is secured."), //9 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Advanced scanner module is installed."), //10 list("key"=/obj/item/stock_parts/scanning_module/adv, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Scanning module is secured."), //11 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Scanning module is installed."), //12 list("key"=/obj/item/circuitboard/mecha/gygax/targeting, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Peripherals control module is secured."), //13 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Peripherals control module is installed."), //14 list("key"=/obj/item/circuitboard/mecha/gygax/peripherals, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Central control module is secured."), //15 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Central control module is installed."), //16 list("key"=/obj/item/circuitboard/mecha/gygax/main, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The wiring is adjusted."), //17 list("key"=/obj/item/wirecutters, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The wiring is added."), //18 list("key"=/obj/item/stack/cable_coil, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The hydraulic systems are active."), //19 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/wrench, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_WRENCH, "desc"="The hydraulic systems are connected."), //20 - list("key"=/obj/item/wrench, + list("key"=TOOL_WRENCH, "desc"="The hydraulic systems are disconnected.") ) @@ -597,64 +567,64 @@ taskpath = /datum/job_objective/make_ripley steps = list( //1 - list("key"=/obj/item/weldingtool, - "backkey"=/obj/item/wrench, + list("key"=TOOL_WELDER, + "backkey"=TOOL_WRENCH, "desc"="External armor is wrenched."), //2 - list("key"=/obj/item/wrench, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_WRENCH, + "backkey"=TOOL_CROWBAR, "desc"="External armor is installed."), //3 list("key"=/obj/item/stack/sheet/plasteel, - "backkey"=/obj/item/crowbar, + "backkey"=TOOL_CROWBAR, "desc"="External armor is being installed."), //4 list("key"=/obj/item/stack/sheet/plasteel, - "backkey"=/obj/item/weldingtool, + "backkey"=TOOL_WELDER, "desc"="Internal armor is welded."), //5 - list("key"=/obj/item/weldingtool, - "backkey"=/obj/item/wrench, + list("key"=TOOL_WELDER, + "backkey"=TOOL_WRENCH, "desc"="Internal armor is wrenched."), //6 - list("key"=/obj/item/wrench, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_WRENCH, + "backkey"=TOOL_CROWBAR, "desc"="Internal armor is installed."), //7 list("key"=/obj/item/stack/sheet/plasteel, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Peripherals control module is secured."), //8 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Peripherals control module is installed."), //9 list("key"=/obj/item/circuitboard/mecha/ripley/peripherals, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Central control module is secured."), //10 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Central control module is installed."), //11 list("key"=/obj/item/circuitboard/mecha/ripley/main, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The wiring is adjusted."), //12 list("key"=/obj/item/wirecutters, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The wiring is added."), //13 list("key"=/obj/item/stack/cable_coil, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The hydraulic systems are active."), //14 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/wrench, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_WRENCH, "desc"="The hydraulic systems are connected."), //15 - list("key"=/obj/item/wrench, + list("key"=TOOL_WRENCH, "desc"="The hydraulic systems are disconnected.") ) @@ -973,83 +943,83 @@ result = "/obj/mecha/combat/durand" steps = list( //1 - list("key"=/obj/item/weldingtool, - "backkey"=/obj/item/wrench, + list("key"=TOOL_WELDER, + "backkey"=TOOL_WRENCH, "desc"="External armor is wrenched."), //2 - list("key"=/obj/item/wrench, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_WRENCH, + "backkey"=TOOL_CROWBAR, "desc"="External armor is installed."), //3 list("key"=/obj/item/mecha_parts/part/durand_armor, - "backkey"=/obj/item/weldingtool, + "backkey"=TOOL_WELDER, "desc"="Internal armor is welded."), //4 - list("key"=/obj/item/weldingtool, - "backkey"=/obj/item/wrench, + list("key"=TOOL_WELDER, + "backkey"=TOOL_WRENCH, "desc"="Internal armor is wrenched."), //5 - list("key"=/obj/item/wrench, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_WRENCH, + "backkey"=TOOL_CROWBAR, "desc"="Internal armor is installed."), //6 list("key"=/obj/item/stack/sheet/metal, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Super capacitor is secured."), //7 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Super capacitor is installed."), //8 list("key"=/obj/item/stock_parts/capacitor/super, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Phasic scanner module is secured."), //9 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Phasic scanner module is installed."), //10 list("key"=/obj/item/stock_parts/scanning_module/phasic, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Scanning module is secured."), //11 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Scanning module is installed."), //12 list("key"=/obj/item/circuitboard/mecha/durand/targeting, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Peripherals control module is secured."), //13 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Peripherals control module is installed."), //14 list("key"=/obj/item/circuitboard/mecha/durand/peripherals, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Central control module is secured."), //15 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Central control module is installed."), //16 list("key"=/obj/item/circuitboard/mecha/durand/main, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The wiring is adjusted."), //17 list("key"=/obj/item/wirecutters, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The wiring is added."), //18 list("key"=/obj/item/stack/cable_coil, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The hydraulic systems are active."), //19 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/wrench, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_WRENCH, "desc"="The hydraulic systems are connected."), //20 - list("key"=/obj/item/wrench, + list("key"=TOOL_WRENCH, "desc"="The hydraulic systems are disconnected.") ) @@ -1259,95 +1229,95 @@ "backkey"=null, //Cannot remove the anomaly core once it's in "desc"="Anomaly core socket is open and awaiting connection."), //2 - list("key"=/obj/item/weldingtool, - "backkey"=/obj/item/wrench, + list("key"=TOOL_WELDER, + "backkey"=TOOL_WRENCH, "desc"="External armor is wrenched."), //3 - list("key"=/obj/item/wrench, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_WRENCH, + "backkey"=TOOL_CROWBAR, "desc"="External armor is installed."), //4 list("key"=/obj/item/mecha_parts/part/phazon_armor, - "backkey"=/obj/item/weldingtool, + "backkey"=TOOL_WELDER, "desc"="Phase armor is welded."), //5 - list("key"=/obj/item/weldingtool, - "backkey"=/obj/item/wrench, + list("key"=TOOL_WELDER, + "backkey"=TOOL_WRENCH, "desc"="Phase armor is wrenched."), //6 - list("key"=/obj/item/wrench, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_WRENCH, + "backkey"=TOOL_CROWBAR, "desc"="Phase armor is installed."), //7 list("key"=/obj/item/stack/sheet/plasteel, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The bluespace crystal is engaged."), //8 - list("key"=/obj/item/screwdriver, + list("key"=TOOL_SCREWDRIVER, "backkey"=/obj/item/wirecutters, "desc"="The bluespace crystal is connected."), //9 list("key"=/obj/item/stack/cable_coil, - "backkey"=/obj/item/crowbar, + "backkey"=TOOL_CROWBAR, "desc"="The bluespace crystal is installed."), //10 list("key"=/obj/item/stack/ore/bluespace_crystal, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Super capacitor is secured."), //11 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Super capacitor is installed."), //12 list("key"=/obj/item/stock_parts/capacitor/super, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Phasic scanner module is secured."), //13 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Phasic scanner module is installed."), //14 list("key"=/obj/item/stock_parts/scanning_module/phasic, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Scanning module is secured."), //15 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Scanning module is installed."), //16 list("key"=/obj/item/circuitboard/mecha/phazon/targeting, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Peripherals control module is secured."), //17 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Peripherals control module is installed"), //18 list("key"=/obj/item/circuitboard/mecha/phazon/peripherals, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Central control module is secured."), //19 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Central control module is installed."), //20 list("key"=/obj/item/circuitboard/mecha/phazon/main, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The wiring is adjusted."), //21 list("key"=/obj/item/wirecutters, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The wiring is added."), //22 list("key"=/obj/item/stack/cable_coil, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The hydraulic systems are active."), //23 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/wrench, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_WRENCH, "desc"="The hydraulic systems are connected."), //24 - list("key"=/obj/item/wrench, + list("key"=TOOL_WRENCH, "desc"="The hydraulic systems are disconnected.") ) @@ -1579,59 +1549,59 @@ result = "/obj/mecha/medical/odysseus" steps = list( //1 - list("key"=/obj/item/weldingtool, - "backkey"=/obj/item/wrench, + list("key"=TOOL_WELDER, + "backkey"=TOOL_WRENCH, "desc"="External armor is wrenched."), //2 - list("key"=/obj/item/wrench, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_WRENCH, + "backkey"=TOOL_CROWBAR, "desc"="External armor is installed."), //3 list("key"=/obj/item/stack/sheet/plasteel, - "backkey"=/obj/item/weldingtool, + "backkey"=TOOL_WELDER, "desc"="Internal armor is welded."), //4 - list("key"=/obj/item/weldingtool, - "backkey"=/obj/item/wrench, + list("key"=TOOL_WELDER, + "backkey"=TOOL_WRENCH, "desc"="Internal armor is wrenched."), //5 - list("key"=/obj/item/wrench, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_WRENCH, + "backkey"=TOOL_CROWBAR, "desc"="Internal armor is installed."), //6 list("key"=/obj/item/stack/sheet/metal, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Peripherals control module is secured."), //7 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Peripherals control module is installed."), //8 list("key"=/obj/item/circuitboard/mecha/odysseus/peripherals, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="Central control module is secured."), //9 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/crowbar, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_CROWBAR, "desc"="Central control module is installed."), //10 list("key"=/obj/item/circuitboard/mecha/odysseus/main, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The wiring is adjusted."), //11 list("key"=/obj/item/wirecutters, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The wiring is added."), //12 list("key"=/obj/item/stack/cable_coil, - "backkey"=/obj/item/screwdriver, + "backkey"=TOOL_SCREWDRIVER, "desc"="The hydraulic systems are active."), //13 - list("key"=/obj/item/screwdriver, - "backkey"=/obj/item/wrench, + list("key"=TOOL_SCREWDRIVER, + "backkey"=TOOL_WRENCH, "desc"="The hydraulic systems are connected."), //14 - list("key"=/obj/item/wrench, + list("key"=TOOL_WRENCH, "desc"="The hydraulic systems are disconnected.") ) diff --git a/code/game/mecha/mecha_wreckage.dm b/code/game/mecha/mecha_wreckage.dm index 0e0ed85b727..9f01dc83af4 100644 --- a/code/game/mecha/mecha_wreckage.dm +++ b/code/game/mecha/mecha_wreckage.dm @@ -49,46 +49,45 @@ return . += "The AI recovery beacon is active." -/obj/structure/mecha_wreckage/attackby(obj/item/I, mob/user, params) - if(iswelder(I)) - if(salvage_num <= 0 || !length(welder_salvage)) - to_chat(user, "You don't see anything that can be cut with [I]!") - return - var/obj/item/weldingtool/WT = I - playsound(get_turf(src), WT.usesound, 50, TRUE) - if(!WT.remove_fuel(0, user)) - return - if(prob(30)) - to_chat(user, "You fail to salvage anything valuable from [src]!") - return - var/type = pick(welder_salvage) - var/N = new type(get_turf(user)) - user.visible_message("[user] cuts [N] from [src].", "You cut [N] from [src].") - if(!istype(N, /obj/item/stack)) - welder_salvage -= type - salvage_num-- +/obj/structure/mecha_wreckage/crowbar_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return - - if(iswirecutter(I)) - if(wires_removed) - to_chat(user, "You don't see anything that can be cut with [I]!") - return - var/N = new /obj/item/stack/cable_coil(get_turf(user), rand(1, 3)) - user.visible_message("[user] cuts [N] from [src].", "You cut [N] from [src].") - wires_removed = TRUE + if(crowbar_salvage.len) + var/obj/S = pick(crowbar_salvage) + S.forceMove(user.drop_location()) + user.visible_message("[user] pries [S] from [src].", "You pry [S] from [src].") + crowbar_salvage -= S return + to_chat(user, "You don't see anything that can be cut with [I]!") - if(iscrowbar(I)) - if(crowbar_salvage.len) - var/obj/S = pick(crowbar_salvage) - S.forceMove(user.drop_location()) - user.visible_message("[user] pries [S] from [src].", "You pry [S] from [src].") - crowbar_salvage -= S - return +/obj/structure/mecha_wreckage/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(salvage_num <= 0 || !length(welder_salvage)) to_chat(user, "You don't see anything that can be cut with [I]!") return - return ..() + if(prob(30)) + to_chat(user, "You fail to salvage anything valuable from [src]!") + return + var/type = pick(welder_salvage) + var/N = new type(get_turf(user)) + user.visible_message("[user] cuts [N] from [src].", "You cut [N] from [src].") + if(!istype(N, /obj/item/stack)) + welder_salvage -= type + salvage_num-- +/obj/structure/mecha_wreckage/wirecutter_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(wires_removed) + to_chat(user, "You don't see anything that can be cut with [I]!") + return + var/N = new /obj/item/stack/cable_coil(get_turf(user), rand(1, 3)) + user.visible_message("[user] cuts [N] from [src].", "You cut [N] from [src].") + wires_removed = TRUE /obj/structure/mecha_wreckage/transfer_ai(interaction, mob/user, null, obj/item/aicard/card) if(!..()) @@ -213,4 +212,4 @@ /obj/item/mecha_parts/part/odysseus_left_arm, /obj/item/mecha_parts/part/odysseus_right_arm, /obj/item/mecha_parts/part/odysseus_left_leg, - /obj/item/mecha_parts/part/odysseus_right_leg) \ No newline at end of file + /obj/item/mecha_parts/part/odysseus_right_leg) diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index 0ad39cd73be..aa5eef1f04a 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -14,16 +14,16 @@ if(buckled_mobs.len > 1) var/unbuckled = input(user, "Who do you wish to unbuckle?", "Unbuckle Who?") as null|mob in buckled_mobs if(user_unbuckle_mob(unbuckled,user)) - return 1 + return TRUE else if(user_unbuckle_mob(buckled_mobs[1], user)) - return 1 + return TRUE /atom/movable/MouseDrop_T(mob/living/M, mob/living/user) . = ..() if(can_buckle && istype(M) && istype(user)) if(user_buckle_mob(M, user)) - return 1 + return TRUE /atom/movable/proc/has_buckled_mobs() if(!buckled_mobs) @@ -31,6 +31,18 @@ if(buckled_mobs.len) return TRUE +/atom/movable/attack_robot(mob/living/user) + . = ..() + if(can_buckle && has_buckled_mobs() && Adjacent(user)) // attack_robot is called on all ranges, so the Adjacent check is needed + if(buckled_mobs.len > 1) + var/unbuckled = input(user, "Who do you wish to unbuckle?", "Unbuckle Who?") as null|mob in buckled_mobs + if(user_unbuckle_mob(unbuckled,user)) + return TRUE + else + if(user_unbuckle_mob(buckled_mobs[1], user)) + return TRUE + + //procs that handle the actual buckling and unbuckling /atom/movable/proc/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE) if(!buckled_mobs) diff --git a/code/game/objects/effects/decals/contraband.dm b/code/game/objects/effects/decals/contraband.dm index 88821ae34c6..da03aa51837 100644 --- a/code/game/objects/effects/decals/contraband.dm +++ b/code/game/objects/effects/decals/contraband.dm @@ -85,17 +85,16 @@ poster_item_icon_state = initial(selected.poster_item_icon_state) ruined = initial(selected.ruined) -/obj/structure/sign/poster/attackby(obj/item/I, mob/user, params) - if(iswirecutter(I)) - playsound(loc, I.usesound, 100, 1) - if(ruined) - to_chat(user, "You remove the remnants of the poster.") - qdel(src) - else - to_chat(user, "You carefully remove the poster from the wall.") - roll_and_drop(user.loc) +/obj/structure/sign/poster/wirecutter_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return - return ..() + if(ruined) + to_chat(user, "You remove the remnants of the poster.") + qdel(src) + else + to_chat(user, "You carefully remove the poster from the wall.") + roll_and_drop(user.loc) /obj/structure/sign/poster/attack_hand(mob/user) if(ruined) diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index a145fcea1d4..7301eb2df03 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -1181,7 +1181,7 @@ steam.start() -- spawns the effect // Clamp all values to MAX_EXPLOSION_RANGE if(round(amount/12) > 0) - devastation = min (MAX_EX_DEVESTATION_RANGE, devastation + round(amount/12)) + devastation = min (MAX_EX_DEVASTATION_RANGE, devastation + round(amount/12)) if(round(amount/6) > 0) heavy = min (MAX_EX_HEAVY_RANGE, heavy + round(amount/6)) diff --git a/code/game/objects/effects/effect_system/effects_other.dm b/code/game/objects/effects/effect_system/effects_other.dm index 194a37c860f..cec70ad90e6 100644 --- a/code/game/objects/effects/effect_system/effects_other.dm +++ b/code/game/objects/effects/effect_system/effects_other.dm @@ -172,7 +172,7 @@ // Clamp all values to MAX_EXPLOSION_RANGE if(round(amount/12) > 0) - devastation = min (MAX_EX_DEVESTATION_RANGE, devastation + round(amount/12)) + devastation = min (MAX_EX_DEVASTATION_RANGE, devastation + round(amount/12)) if(round(amount/6) > 0) heavy = min (MAX_EX_HEAVY_RANGE, heavy + round(amount/6)) diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm index 99f1ec2965f..ddf43f9c077 100644 --- a/code/game/objects/effects/portals.dm +++ b/code/game/objects/effects/portals.dm @@ -70,12 +70,14 @@ if(target) O.forceMove(target) -/obj/effect/portal/attackby(obj/item/A, mob/user) - if(ismultitool(A) && can_multitool_to_remove) +/obj/effect/portal/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(can_multitool_to_remove) qdel(src) - else if(user && Adjacent(user)) + else user.forceMove(get_turf(src)) - return TRUE /obj/effect/portal/proc/can_teleport(atom/movable/M) . = TRUE diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index 87f489513d2..462a6d7eca7 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -11,7 +11,7 @@ if(!ignorecap) // Clamp all values to MAX_EXPLOSION_RANGE - devastation_range = min (MAX_EX_DEVESTATION_RANGE, devastation_range) + devastation_range = min (MAX_EX_DEVASTATION_RANGE, devastation_range) heavy_impact_range = min (MAX_EX_HEAVY_RANGE, heavy_impact_range) light_impact_range = min (MAX_EX_LIGHT_RANGE, light_impact_range) flash_range = min (MAX_EX_FLASH_RANGE, flash_range) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 4955f7f508a..955998fc0f6 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -83,6 +83,9 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d var/embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME //A time in ticks, multiplied by the w_class. var/embedded_ignore_throwspeed_threshold = FALSE + var/tool_behaviour = NONE //What kind of tool are we? + var/tool_enabled = TRUE //If we can turn on or off, are we currently active? Mostly for welders and this will normally be TRUE + var/tool_volume = 50 //How loud are we when we use our tool? var/toolspeed = 1 // If this item is a tool, the speed multiplier /* Species-specific sprites, concept stolen from Paradise//vg/. @@ -351,6 +354,16 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d return 1 return 0 +// Generic use proc. Depending on the item, it uses up fuel, charges, sheets, etc. +// Returns TRUE on success, FALSE on failure. +/obj/item/proc/use(used) + return !used + +//Generic refill proc. Transfers something (e.g. fuel, charge) from an atom to our tool. returns TRUE if it was successful, FALSE otherwise +//Not sure if there should be an argument that indicates what exactly is being refilled +/obj/item/proc/refill(mob/user, atom/A, amount) + return FALSE + /obj/item/proc/talk_into(mob/M, var/text, var/channel=null) return diff --git a/code/game/objects/items/candle.dm b/code/game/objects/items/candle.dm index 7b6d3612351..ca142e6f8be 100644 --- a/code/game/objects/items/candle.dm +++ b/code/game/objects/items/candle.dm @@ -32,28 +32,15 @@ /obj/item/candle/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(WT.isOn()) //Badasses dont get blinded by lighting their candle with a welding tool - light("[user] casually lights [src] with [WT], what a badass.") - return - if(istype(W, /obj/item/lighter)) - var/obj/item/lighter/L = W - if(L.lit) - light("After some fiddling, [user] manages to light [src] with [L].") - return - if(istype(W, /obj/item/match)) - var/obj/item/match/M = W - if(M.lit) - light("[user] lights [src] with [M]") - return - if(istype(W, /obj/item/candle)) - var/obj/item/candle/C = W - if(C.lit) - light("[user] tilts [C] and lights [src] with it.") + if(is_hot(W)) + light("[user] lights [src] with [W].") return return ..() +/obj/item/candle/welder_act(mob/user, obj/item/I) + . = TRUE + if(I.tool_use_check(user, 0)) //Don't need to flash eyes because you are a badass + light("[user] casually lights the [name] with [I], what a badass.") /obj/item/candle/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE) if(!lit) diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 2685cc4aafa..f91cacd6804 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -326,6 +326,7 @@ on = TRUE //Bio-luminesence has one setting, on. /obj/item/flashlight/slime/New() + ..() set_light(brightness_on) spawn(1) //Might be sloppy, but seems to be necessary to prevent further runtimes and make these work as intended... don't judge me! update_brightness() diff --git a/code/game/objects/items/devices/instruments.dm b/code/game/objects/items/devices/instruments.dm index 3942407b3d8..538b4efaf49 100644 --- a/code/game/objects/items/devices/instruments.dm +++ b/code/game/objects/items/devices/instruments.dm @@ -167,7 +167,7 @@ reqs = list(/obj/item/stack/sheet/wood = 5, /obj/item/stack/cable_coil = 6, /obj/item/stack/tape_roll = 5) - tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) time = 80 category = CAT_MISC @@ -177,7 +177,7 @@ reqs = list(/obj/item/stack/sheet/wood = 5, /obj/item/stack/cable_coil = 6, /obj/item/stack/tape_roll = 5) - tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) time = 80 category = CAT_MISC @@ -187,6 +187,6 @@ reqs = list(/obj/item/stack/sheet/metal = 5, /obj/item/stack/cable_coil = 6, /obj/item/stack/tape_roll = 5) - tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) time = 80 category = CAT_MISC \ No newline at end of file diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm index 562800c2ce0..e354adc28e4 100644 --- a/code/game/objects/items/devices/powersink.dm +++ b/code/game/objects/items/devices/powersink.dm @@ -63,27 +63,27 @@ update_icon() set_light(0) -/obj/item/powersink/attackby(obj/item/I, mob/user) - if(isscrewdriver(I)) - if(mode == DISCONNECTED) - var/turf/T = loc - if(isturf(T) && !T.intact) - attached = locate() in T - if(!attached) - to_chat(user, "No exposed cable here to attach to.") - return - else - set_mode(CLAMPED_OFF) - visible_message("[user] attaches [src] to the cable!") - message_admins("Power sink activated by [key_name_admin(user)] at ([x],[y],[z] - JMP)") - log_game("Power sink activated by [key_name(user)] at ([x],[y],[z])") +/obj/item/powersink/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(mode == DISCONNECTED) + var/turf/T = loc + if(isturf(T) && !T.intact) + attached = locate() in T + if(!attached) + to_chat(user, "No exposed cable here to attach to.") + return else - to_chat(user, "Device must be placed over an exposed cable to attach to it.") + set_mode(CLAMPED_OFF) + visible_message("[user] attaches [src] to the cable!") + message_admins("Power sink activated by [key_name_admin(user)] at ([x],[y],[z] - JMP)") + log_game("Power sink activated by [key_name(user)] at ([x],[y],[z])") else - set_mode(DISCONNECTED) - src.visible_message("[user] detaches [src] from the cable!") + to_chat(user, "Device must be placed over an exposed cable to attach to it.") else - return ..() + set_mode(DISCONNECTED) + src.visible_message("[user] detaches [src] from the cable!") /obj/item/powersink/attack_ai() return diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 0ef3b0b0728..e6716a4f5c8 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -311,34 +311,8 @@ return ..() /obj/item/radio/headset/attackby(obj/item/W as obj, mob/user as mob) - user.set_machine(src) - if(!( istype(W, /obj/item/screwdriver) || (istype(W, /obj/item/encryptionkey/ )))) - return ..() - - if(istype(W, /obj/item/screwdriver)) - if(keyslot1 || keyslot2) - - for(var/ch_name in channels) - SSradio.remove_object(src, SSradio.radiochannels[ch_name]) - secure_radio_connections[ch_name] = null - - if(keyslot1) - var/turf/T = get_turf(user) - if(T) - keyslot1.loc = T - keyslot1 = null - if(keyslot2) - var/turf/T = get_turf(user) - if(T) - keyslot2.loc = T - keyslot2 = null - - recalculateChannels() - to_chat(user, "You pop out the encryption keys in the headset!") - else - to_chat(user, "This headset doesn't have any encryption keys! How useless...") - if(istype(W, /obj/item/encryptionkey/)) + user.set_machine(src) if(keyslot1 && keyslot2) to_chat(user, "The headset can't hold another key!") return @@ -351,10 +325,37 @@ user.drop_item() W.loc = src keyslot2 = W + recalculateChannels() + else + return ..() + +/obj/item/radio/headset/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = 0)) + return + user.set_machine(src) + if(keyslot1 || keyslot2) + + for(var/ch_name in channels) + SSradio.remove_object(src, SSradio.radiochannels[ch_name]) + secure_radio_connections[ch_name] = null + + if(keyslot1) + var/turf/T = get_turf(user) + if(T) + keyslot1.loc = T + keyslot1 = null + if(keyslot2) + var/turf/T = get_turf(user) + if(T) + keyslot2.loc = T + keyslot2 = null recalculateChannels() - return - + to_chat(user, "You pop out the encryption keys in the headset!") + I.play_tool_sound(user, I.tool_volume) + else + to_chat(user, "This headset doesn't have any encryption keys! How useless...") /obj/item/radio/headset/proc/recalculateChannels(var/setDescription = FALSE) channels = list() diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index 8e440dc1d94..f0c97a66d97 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -138,76 +138,82 @@ /obj/item/radio/intercom/attackby(obj/item/W as obj, mob/user as mob) if(istype(W, /obj/item/stack/tape_roll)) //eww return - switch(buildstage) - if(3) - if(iswirecutter(W) && b_stat && wires.IsAllCut()) - to_chat(user, "You cut out the intercoms wiring and disconnect its electronics.") - playsound(get_turf(src), W.usesound, 50, 1) - if(do_after(user, 10 * W.toolspeed, target = src)) - if(buildstage != 3) - return - new /obj/item/stack/cable_coil(get_turf(src),5) - on = 0 - b_stat = 1 - buildstage = 1 - update_icon() - STOP_PROCESSING(SSobj, src) - return 1 - else return ..() - if(2) - if(isscrewdriver(W)) - playsound(get_turf(src), W.usesound, 50, 1) - if(do_after(user, 10 * W.toolspeed, target = src)) - update_icon() - on = 1 - b_stat = 0 - buildstage = 3 - to_chat(user, "You secure the electronics!") - update_icon() - START_PROCESSING(SSobj, src) - for(var/i, i<= 5, i++) - wires.UpdateCut(i,1) - return 1 - if(1) - if(iscoil(W)) - var/obj/item/stack/cable_coil/coil = W - if(coil.amount < 5) - to_chat(user, "You need more cable for this!") - return - if(do_after(user, 10 * coil.toolspeed, target = src)) - coil.use(5) - to_chat(user, "You wire \the [src]!") - buildstage = 2 - return 1 - if(iscrowbar(W)) - to_chat(user, "You begin removing the electronics...") - playsound(get_turf(src), W.usesound, 50, 1) - if(do_after(user, 10 * W.toolspeed, target = src)) - if(buildstage != 1) - return - new /obj/item/intercom_electronics(get_turf(src)) - to_chat(user, "The circuitboard pops out!") - buildstage = 0 - return 1 - if(0) - if(istype(W,/obj/item/intercom_electronics)) - playsound(get_turf(src), W.usesound, 50, 1) - if(do_after(user, 10 * W.toolspeed, target = src)) - qdel(W) - to_chat(user, "You insert \the [W] into \the [src]!") - buildstage = 1 - return 1 - if(iswelder(W)) - var/obj/item/weldingtool/WT=W - playsound(get_turf(src), WT.usesound, 50, 1) - if(!WT.remove_fuel(3, user)) - to_chat(user, "You're out of welding fuel.") - return 1 - if(do_after(user, 10 * WT.toolspeed, target = src)) - to_chat(user, "You cut the intercom frame from the wall!") - new /obj/item/mounted/frame/intercom(get_turf(src)) - qdel(src) - return 1 + else if(iscoil(W) && buildstage == 1) + var/obj/item/stack/cable_coil/coil = W + if(coil.amount < 5) + to_chat(user, "You need more cable for this!") + return + if(do_after(user, 10 * coil.toolspeed, target = src) && buildstage == 1) + coil.use(5) + to_chat(user, "You wire \the [src]!") + buildstage = 2 + return 1 + else if(istype(W,/obj/item/intercom_electronics) && buildstage == 0) + playsound(get_turf(src), W.usesound, 50, 1) + if(do_after(user, 10 * W.toolspeed, target = src) && buildstage == 0) + qdel(W) + to_chat(user, "You insert \the [W] into \the [src]!") + buildstage = 1 + return 1 + else + return ..() + +/obj/item/radio/intercom/crowbar_act(mob/user, obj/item/I) + if(buildstage != 1) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + to_chat(user, "You begin removing the electronics...") + if(!I.use_tool(src, user, 10, volume = I.tool_volume) || buildstage != 1) + return + new /obj/item/intercom_electronics(get_turf(src)) + to_chat(user, "The circuit board pops out!") + buildstage = 0 + +/obj/item/radio/intercom/screwdriver_act(mob/user, obj/item/I) + if(buildstage != 2) + return ..() + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(!I.use_tool(src, user, 10, volume = I.tool_volume) || buildstage != 2) + return + update_icon() + on = 1 + b_stat = 0 + buildstage = 3 + to_chat(user, "You secure the electronics!") + update_icon() + START_PROCESSING(SSobj, src) + for(var/i, i<= 5, i++) + wires.UpdateCut(i,1) + +/obj/item/radio/intercom/wirecutter_act(mob/user, obj/item/I) + if(!(buildstage == 3 && b_stat && wires.IsAllCut())) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + WIRECUTTER_SNIP_MESSAGE + new /obj/item/stack/cable_coil(get_turf(src),5) + on = 0 + b_stat = 1 + buildstage = 1 + update_icon() + STOP_PROCESSING(SSobj, src) + +/obj/item/radio/intercom/welder_act(mob/user, obj/item/I) + if(!buildstage) + return + . = TRUE + if(!I.tool_use_check(user, 3)) + return + to_chat(user, "You start slicing [src] from the wall...") + if(I.use_tool(src, user, 10, amount = 3, volume = I.tool_volume)) + to_chat(user, "You cut [src] free from the wall!") + new /obj/item/mounted/frame/intercom(get_turf(src)) + qdel(src) /obj/item/radio/intercom/update_icon() if(!circuitry_installed) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index aab926f768e..b6b55c9d370 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -603,22 +603,30 @@ var/global/list/default_medbay_channels = list( else . += "\the [src] can not be modified or attached!" -/obj/item/radio/attackby(obj/item/W as obj, mob/user as mob, params) - ..() - user.set_machine(src) - if(!( istype(W, /obj/item/screwdriver) )) +/obj/item/radio/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return - b_stat = !( b_stat ) + user.set_machine(src) + b_stat = !b_stat if(!istype(src, /obj/item/radio/beacon)) if(b_stat) user.show_message("The radio can now be attached and modified!") else user.show_message("The radio can no longer be modified or attached!") updateDialog() - //Foreach goto(83) - add_fingerprint(user) + +/obj/item/radio/wirecutter_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return - else return + interact(user) + +/obj/item/radio/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + interact(user) /obj/item/radio/emp_act(severity) on = 0 @@ -689,33 +697,8 @@ var/global/list/default_medbay_channels = list( set_frequency(ERT_FREQ) /obj/item/radio/borg/attackby(obj/item/W as obj, mob/user as mob, params) -// ..() - user.set_machine(src) - if(!( istype(W, /obj/item/screwdriver) || (istype(W, /obj/item/encryptionkey/ )))) - return - - if(istype(W, /obj/item/screwdriver)) - if(keyslot) - - - for(var/ch_name in channels) - SSradio.remove_object(src, SSradio.radiochannels[ch_name]) - secure_radio_connections[ch_name] = null - - - if(keyslot) - var/turf/T = get_turf(user) - if(T) - keyslot.loc = T - keyslot = null - - recalculateChannels() - to_chat(user, "You pop out the encryption key in the radio!") - - else - to_chat(user, "This radio doesn't have any encryption keys!") - if(istype(W, /obj/item/encryptionkey/)) + user.set_machine(src) if(keyslot) to_chat(user, "The radio can't hold another key!") return @@ -726,8 +709,32 @@ var/global/list/default_medbay_channels = list( keyslot = W recalculateChannels() + else + return ..() - return +/obj/item/radio/borg/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = 0)) + return + user.set_machine(src) + if(keyslot) + for(var/ch_name in channels) + SSradio.remove_object(src, SSradio.radiochannels[ch_name]) + secure_radio_connections[ch_name] = null + + + if(keyslot) + var/turf/T = get_turf(user) + if(T) + keyslot.loc = T + keyslot = null + + recalculateChannels() + to_chat(user, "You pop out the encryption key in the radio!") + I.play_tool_sound(user, I.tool_volume) + + else + to_chat(user, "This radio doesn't have any encryption keys!") /obj/item/radio/borg/proc/recalculateChannels() channels = list() diff --git a/code/game/objects/items/devices/sensor_device.dm b/code/game/objects/items/devices/sensor_device.dm index 22bd6a15a74..8c69402ed70 100644 --- a/code/game/objects/items/devices/sensor_device.dm +++ b/code/game/objects/items/devices/sensor_device.dm @@ -9,6 +9,7 @@ var/datum/nano_module/crew_monitor/crew_monitor /obj/item/sensor_device/New() + ..() crew_monitor = new(src) /obj/item/sensor_device/Destroy() diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index ed8dfebba23..12f5212ffd9 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -15,11 +15,14 @@ var/obj/item/tape/mytape var/open_panel = 0 var/canprint = 1 + var/starts_with_tape = TRUE /obj/item/taperecorder/New() - mytape = new /obj/item/tape/random(src) - update_icon() + ..() + if(starts_with_tape) + mytape = new /obj/item/tape/random(src) + update_icon() /obj/item/taperecorder/Destroy() QDEL_NULL(mytape) @@ -243,8 +246,8 @@ canprint = 1 //empty tape recorders -/obj/item/taperecorder/empty/New() - return +/obj/item/taperecorder/empty + starts_with_tape = FALSE /obj/item/tape @@ -317,4 +320,5 @@ //Random colour tapes /obj/item/tape/random/New() + ..() icon_state = "tape_[pick("white", "blue", "red", "yellow", "purple")]" diff --git a/code/game/objects/items/devices/thermal_drill.dm b/code/game/objects/items/devices/thermal_drill.dm index 2fe4b28f9d4..c35a75ef055 100644 --- a/code/game/objects/items/devices/thermal_drill.dm +++ b/code/game/objects/items/devices/thermal_drill.dm @@ -10,6 +10,7 @@ var/datum/effect_system/spark_spread/spark_system /obj/item/thermal_drill/New() + ..() soundloop = new(list(src), FALSE) spark_system = new /datum/effect_system/spark_spread() spark_system.set_up(1, 0, src) diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm index c6cfe03a151..d814b242b29 100644 --- a/code/game/objects/items/devices/uplinks.dm +++ b/code/game/objects/items/devices/uplinks.dm @@ -316,6 +316,7 @@ var/list/world_uplinks = list() // implant uplink (not the implant tool) and a preset headset uplink. /obj/item/radio/uplink/New() + ..() hidden_uplink = new(src) icon_state = "radio" @@ -339,6 +340,7 @@ var/list/world_uplinks = list() hidden_uplink.uplink_type = "sst" /obj/item/multitool/uplink/New() + ..() hidden_uplink = new(src) /obj/item/multitool/uplink/attack_self(mob/user as mob) diff --git a/code/game/objects/items/flag.dm b/code/game/objects/items/flag.dm index d0118d815fb..1b2eae4db8d 100644 --- a/code/game/objects/items/flag.dm +++ b/code/game/objects/items/flag.dm @@ -245,22 +245,25 @@ message_admins("[key_name_admin(user)] has hidden [I] in the [src] ready for detonation at [A.name] (JMP).") log_game("[key_name(user)] has hidden [I] in the [src] ready for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]).") investigate_log("[key_name(user)] has hidden [I] in the [src] ready for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]).", INVESTIGATE_BOMB) - else if(isscrewdriver(I) && boobytrap && user == trapper) - to_chat(user, "You remove [boobytrap] from the [src].") - boobytrap.forceMove(get_turf(src)) - boobytrap = null - trapper = null - else - return ..() - -/obj/item/flag/chameleon/attackby(obj/item/W, mob/user, params) - if(is_hot(W) && !(resistance_flags & ON_FIRE) && boobytrap && trapper) + else if(is_hot(I) && !(resistance_flags & ON_FIRE) && boobytrap && trapper) var/turf/bombturf = get_turf(src) var/area/A = get_area(bombturf) message_admins("[key_name_admin(user)] has lit the [src] trapped with [boobytrap] by [key_name_admin(trapper)] at [A.name] (JMP).") log_game("[key_name_admin(user)] has lit the [src] trapped with [boobytrap] by [key_name_admin(trapper)] at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]).") investigate_log("[key_name_admin(user)] has lit the [src] trapped with [boobytrap] by [key_name_admin(trapper)] at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]).", INVESTIGATE_BOMB) - return ..() + else + return ..() + +/obj/item/flag/chameleon/screwdriver_act(mob/user, obj/item/I) + if(!boobytrap || user != trapper) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + to_chat(user, "You remove [boobytrap] from [src].") + boobytrap.forceMove(get_turf(src)) + boobytrap = null + trapper = null /obj/item/flag/chameleon/burn() if(boobytrap) diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm index 8c2d64bda59..959b308ee05 100644 --- a/code/game/objects/items/shooting_range.dm +++ b/code/game/objects/items/shooting_range.dm @@ -31,15 +31,12 @@ // the stake now, we have to push the target. - -/obj/item/target/attackby(obj/item/W as obj, mob/user as mob, params) - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - overlays.Cut() - to_chat(usr, "You slice off [src]'s uneven chunks of aluminum and scorch marks.") - return - +/obj/item/target/welder_act(mob/user, obj/item/I) + . = TRUE + if(!use_tool(src, user, 0,, volume = I.tool_volume)) + return + overlays.Cut() + to_chat(usr, "You slice off [src]'s uneven chunks of aluminum and scorch marks.") /obj/item/target/attack_hand(mob/user as mob) // taking pinned targets off! diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 7dc1a97a735..9f8c877aa24 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -12,7 +12,7 @@ var/heal_brute = 0 var/heal_burn = 0 var/self_delay = 20 - var/unique_handling = 0 //some things give a special prompt, do we want to bypass some checks in parent? + var/unique_handling = FALSE //some things give a special prompt, do we want to bypass some checks in parent? var/stop_bleeding = 0 var/healverb = "bandage" @@ -31,28 +31,20 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_selected) if(!H.can_inject(user, TRUE)) - return 1 + return TRUE if(!affecting) to_chat(user, "That limb is missing!") - return 1 + return TRUE if(affecting.is_robotic()) to_chat(user, "This can't be used on a robotic limb.") - return 1 - - if(stop_bleeding) - if(H.bleedsuppress) - to_chat(user, "[H]'s bleeding is already bandaged!") - return 1 - else if(!H.bleed_rate) - to_chat(user, "[H] isn't bleeding!") - return 1 + return TRUE if(M == user && !unique_handling) user.visible_message("[user] starts to apply [src] on [H]...") if(!do_mob(user, H, self_delay)) - return 1 + return TRUE return if(isanimal(M)) @@ -123,6 +115,7 @@ desc = "Some sterile gauze to wrap around bloody stumps." icon_state = "gauze" origin_tech = "biotech=2" + heal_brute = 10 stop_bleeding = 1800 /obj/item/stack/medical/bruise_pack/attackby(obj/item/I, mob/user, params) @@ -140,13 +133,13 @@ /obj/item/stack/medical/bruise_pack/attack(mob/living/M, mob/user) if(..()) - return 1 + return TRUE if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/affecting = H.get_organ(user.zone_selected) - if(affecting.open == 0) + if(affecting.open == FALSE) affecting.germ_level = 0 if(stop_bleeding) @@ -187,6 +180,7 @@ icon_state = "ointment" origin_tech = "biotech=2" healverb = "salve" + heal_burn = 10 /obj/item/stack/medical/ointment/attack(mob/living/M, mob/user) if(..()) @@ -196,7 +190,7 @@ var/mob/living/carbon/human/H = M var/obj/item/organ/external/affecting = H.get_organ(user.zone_selected) - if(affecting.open == 0) + if(affecting.open == FALSE) affecting.germ_level = 0 heal(H, user) diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index f3716459f18..37f726b215d 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -46,29 +46,23 @@ var/global/list/datum/stack_recipe/rod_recipes = list ( \ else icon_state = "rods" -/obj/item/stack/rods/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - - if(get_amount() < 2) - to_chat(user, "You need at least two rods to do this!") - return - - if(WT.remove_fuel(0,user)) - var/obj/item/stack/sheet/metal/new_item = new(user.loc) - if(new_item.get_amount() <= 0) - // stack was moved into another one on the pile - new_item = locate() in user.loc - - user.visible_message("[user.name] shape [src] into metal with the welding tool.", \ - "You shape [src] into metal with the welding tool.", \ - "You hear welding.") - - var/replace = user.is_in_inactive_hand(src) - use(2) - if(get_amount() <= 0 && replace) - user.unEquip(src, 1) - if(new_item) - user.put_in_hands(new_item) +/obj/item/stack/rods/welder_act(mob/user, obj/item/I) + if(get_amount() < 2) + to_chat(user, "You need at least two rods to do this!") return - ..() + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + var/obj/item/stack/sheet/metal/new_item = new(drop_location()) + if(new_item.get_amount() <= 0) + // stack was moved into another one on the pile + new_item = locate() in user.loc + visible_message("[user.name] shapes [src] into metal with [I]!", \ + "You shape [src] into metal with [I]!", \ + "You hear welding.") + var/replace = user.is_in_inactive_hand(src) + use(2) + if(get_amount() <= 0 && replace) + user.unEquip(src, 1) + if(new_item) + user.put_in_hands(new_item) diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 047ffb3292a..a78711f915e 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -216,14 +216,12 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ ..() recipes = plasma_recipes -/obj/item/stack/sheet/mineral/plasma/attackby(obj/item/W, mob/user, params) - if(is_hot(W) > 300)//If the temperature of the object is over 300, then ignite +/obj/item/stack/sheet/mineral/plasma/welder_act(mob/user, obj/item/I) + if(I.use_tool(src, user, volume = I.tool_volume)) message_admins("Plasma sheets ignited by [key_name_admin(user)]([ADMIN_QUE(user,"?")]) ([ADMIN_FLW(user,"FLW")]) in ([x],[y],[z] - JMP)",0,1) log_game("Plasma sheets ignited by [key_name(user)] in ([x],[y],[z])") investigate_log("was ignited by [key_name(user)]","atmos") fire_act() - else - return ..() /obj/item/stack/sheet/mineral/plasma/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE) ..() diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index a4141a7a58a..14ccc103ab1 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -222,7 +222,7 @@ interact(usr) return -/obj/item/stack/proc/use(used, check = TRUE) +/obj/item/stack/use(used, check = TRUE) if(check && zero_amount()) return FALSE if(amount < used) @@ -296,6 +296,8 @@ else return ..() +// Returns TRUE if the stack amount is zero. +// Also qdels the stack gracefully if it is. /obj/item/stack/proc/zero_amount() if(amount < 1) if(isrobot(loc)) @@ -305,7 +307,11 @@ if(ismob(loc)) var/mob/living/L = loc // At this stage, stack code is so horrible and atrocious, I wouldn't be all surprised ghosts can somehow have stacks. If this happens, then the world deserves to burn. L.unEquip(src, TRUE) - qdel(src) + if(amount < 1) + // If you stand on top of a stack, and drop a - different - 0-amount stack on the floor, + // the two get merged, so the amount of items in the stack can increase from the 0 that it had before. + // Check the amount again, to be sure we're not qdeling healthy stacks. + qdel(src) return TRUE return FALSE diff --git a/code/game/objects/items/stacks/tiles/tile_mineral.dm b/code/game/objects/items/stacks/tiles/tile_mineral.dm index 019ca77b6ad..0b0044005e7 100644 --- a/code/game/objects/items/stacks/tiles/tile_mineral.dm +++ b/code/game/objects/items/stacks/tiles/tile_mineral.dm @@ -8,6 +8,16 @@ mineralType = "plasma" materials = list(MAT_PLASMA=500) +/obj/item/stack/tile/mineral/plasma/welder_act(mob/user, obj/item/I) + if(I.use_tool(src, user, volume = I.tool_volume)) + atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, 5) + user.visible_message("[user.name] sets the plasma tiles on fire!", \ + "You set the plasma tiles on fire!") + message_admins("Plasma tiles ignited by [key_name_admin(user)](?) (FLW) in ([x],[y],[z] - JMP)",0,1) + log_game("Plasma tiles ignited by [key_name(user)] in ([x],[y],[z])") + investigate_log("was ignited by [key_name(user)]","atmos") + qdel(src) + /obj/item/stack/tile/mineral/uranium name = "uranium tile" singular_name = "uranium floor tile" diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index 564010b1aed..3e664c951a5 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -21,56 +21,38 @@ pixel_x = rand(-3, 3) pixel_y = rand(-3, 3) //randomize a little -/obj/item/stack/tile/attackby(obj/item/W, mob/user, params) - if(iswelder(W)) - var/obj/item/weldingtool/WT = W +/obj/item/stack/tile/welder_act(mob/user, obj/item/I) + if(get_amount() < 4) + to_chat(user, "You need at least four tiles to do this!") + return + . = TRUE + if(!I.use_tool(src, user, volume = I.tool_volume)) + to_chat(user, "You can not reform this!") + return + if (mineralType == "metal") + var/obj/item/stack/sheet/metal/new_item = new(user.loc) + user.visible_message("[user.name] shaped [src] into metal with the welding tool.", \ + "You shaped [src] into metal with the welding tool.", \ + "You hear welding.") + var/obj/item/stack/rods/R = src + src = null + var/replace = (user.get_inactive_hand()==R) + R.use(4) + if(!R && replace) + user.put_in_hands(new_item) - if(is_hot(W) && !mineralType) - to_chat(user, "You can not reform this!") - return - - if(get_amount() < 4) - to_chat(user, "You need at least four tiles to do this!") - return - - if(WT.remove_fuel(0,user)) - - if(mineralType == "plasma") - atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, 5) - user.visible_message("[user.name] sets the plasma tiles on fire!", \ - "You set the plasma tiles on fire!") - message_admins("Plasma tiles ignited by [key_name_admin(user)](?) (FLW) in ([x],[y],[z] - JMP)",0,1) - log_game("Plasma tiles ignited by [key_name(user)] in ([x],[y],[z])") - investigate_log("was ignited by [key_name(user)]","atmos") - qdel(src) - return - - if (mineralType == "metal") - var/obj/item/stack/sheet/metal/new_item = new(user.loc) - user.visible_message("[user.name] shaped [src] into metal with the welding tool.", \ - "You shaped [src] into metal with the welding tool.", \ - "You hear welding.") - var/obj/item/stack/rods/R = src - src = null - var/replace = (user.get_inactive_hand()==R) - R.use(4) - if(!R && replace) - user.put_in_hands(new_item) - - else - var/sheet_type = text2path("/obj/item/stack/sheet/mineral/[mineralType]") - var/obj/item/stack/sheet/mineral/new_item = new sheet_type(user.loc) - user.visible_message("[user.name] shaped [src] into a sheet with the welding tool.", \ - "You shaped [src] into a sheet with the welding tool.", \ - "You hear welding.") - var/obj/item/stack/rods/R = src - src = null - var/replace = (user.get_inactive_hand()==R) - R.use(4) - if (!R && replace) - user.put_in_hands(new_item) else - return ..() + var/sheet_type = text2path("/obj/item/stack/sheet/mineral/[mineralType]") + var/obj/item/stack/sheet/mineral/new_item = new sheet_type(user.loc) + user.visible_message("[user.name] shaped [src] into a sheet with the welding tool.", \ + "You shaped [src] into a sheet with the welding tool.", \ + "You hear welding.") + var/obj/item/stack/rods/R = src + src = null + var/replace = (user.get_inactive_hand()==R) + R.use(4) + if (!R && replace) + user.put_in_hands(new_item) //Grass /obj/item/stack/tile/grass diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm new file mode 100644 index 00000000000..134194bf4a7 --- /dev/null +++ b/code/game/objects/items/tools/crowbar.dm @@ -0,0 +1,85 @@ +/obj/item/crowbar + name = "pocket crowbar" + desc = "A small crowbar. This handy tool is useful for lots of things, such as prying floor tiles or opening unpowered doors." + icon = 'icons/obj/tools.dmi' + icon_state = "crowbar" + item_state = "crowbar" + usesound = 'sound/items/crowbar.ogg' + flags = CONDUCT + slot_flags = SLOT_BELT + force = 5 + throwforce = 7 + item_state = "crowbar" + w_class = WEIGHT_CLASS_SMALL + materials = list(MAT_METAL=50) + origin_tech = "engineering=1;combat=1" + attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked") + toolspeed = 1 + + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) + tool_behaviour = TOOL_CROWBAR + +/obj/item/crowbar/red + icon_state = "crowbar_red" + item_state = "crowbar_red" + force = 8 + +/obj/item/crowbar/brass + name = "brass crowbar" + desc = "A brass crowbar. It feels faintly warm to the touch." + icon_state = "crowbar_brass" + item_state = "crowbar_brass" + toolspeed = 0.5 + resistance_flags = FIRE_PROOF | ACID_PROOF + +/obj/item/crowbar/abductor + name = "alien crowbar" + desc = "A hard-light crowbar. It appears to pry by itself, without any effort required." + icon = 'icons/obj/abductor.dmi' + usesound = 'sound/weapons/sonic_jackhammer.ogg' + icon_state = "crowbar" + toolspeed = 0.1 + origin_tech = "combat=4;engineering=4;abductor=3" + +/obj/item/crowbar/large + name = "crowbar" + desc = "It's a big crowbar. It doesn't fit in your pockets, because its too big." + force = 12 + w_class = WEIGHT_CLASS_NORMAL + throw_speed = 3 + throw_range = 3 + materials = list(MAT_METAL=70) + icon_state = "crowbar_large" + item_state = "crowbar_large" + toolspeed = 0.5 + +/obj/item/crowbar/cyborg + name = "hydraulic crowbar" + desc = "A hydraulic prying tool, compact but powerful. Designed to replace crowbar in construction cyborgs." + usesound = 'sound/items/jaws_pry.ogg' + force = 10 + toolspeed = 0.5 + +/obj/item/crowbar/power + name = "jaws of life" + desc = "A set of jaws of life, the magic of science has managed to fit it down into a device small enough to fit in a tool belt. It's fitted with a prying head." + icon_state = "jaws_pry" + item_state = "jawsoflife" + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + origin_tech = "materials=2;engineering=2" + usesound = 'sound/items/jaws_pry.ogg' + force = 15 + toolspeed = 0.25 + var/airlock_open_time = 100 // Time required to open powered airlocks + +/obj/item/crowbar/power/suicide_act(mob/user) + user.visible_message("[user] is putting [user.p_their()] head in [src]. It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, 'sound/items/jaws_pry.ogg', 50, 1, -1) + return BRUTELOSS + +/obj/item/crowbar/power/attack_self(mob/user) + playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) + var/obj/item/wirecutters/power/cutjaws = new /obj/item/wirecutters/power + to_chat(user, "You attach the cutting jaws to [src].") + qdel(src) + user.put_in_active_hand(cutjaws) diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/tools/multitool.dm similarity index 88% rename from code/game/objects/items/devices/multitool.dm rename to code/game/objects/items/tools/multitool.dm index 62fc36863fc..22c9861da6e 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/tools/multitool.dm @@ -1,111 +1,121 @@ -#define PROXIMITY_NONE "" -#define PROXIMITY_ON_SCREEN "_red" -#define PROXIMITY_NEAR "_yellow" - -/** - * Multitool -- A multitool is used for hacking electronic devices. - * TO-DO -- Using it as a power measurement tool for cables etc. Nannek. - * - */ - -/obj/item/multitool - name = "multitool" - desc = "Used for pulsing wires to test which to cut. Not recommended by doctors." - icon = 'icons/obj/device.dmi' - icon_state = "multitool" - flags = CONDUCT - force = 5.0 - w_class = WEIGHT_CLASS_SMALL - throwforce = 0 - throw_range = 7 - throw_speed = 3 - materials = list(MAT_METAL=50, MAT_GLASS=20) - origin_tech = "magnets=1;engineering=2" - toolspeed = 1 - hitsound = 'sound/weapons/tap.ogg' - var/shows_wire_information = FALSE // shows what a wire does if set to TRUE - var/obj/machinery/buffer // simple machine buffer for device linkage - -/obj/item/multitool/proc/IsBufferA(var/typepath) - if(!buffer) - return 0 - return istype(buffer,typepath) - -// Syndicate device disguised as a multitool; it will turn red when an AI camera is nearby. - -/obj/item/multitool/Destroy() - buffer = null - return ..() - -/obj/item/multitool/ai_detect - var/track_cooldown = 0 - var/track_delay = 10 //How often it checks for proximity - var/detect_state = PROXIMITY_NONE - var/rangealert = 8 //Glows red when inside - var/rangewarning = 20 //Glows yellow when inside - origin_tech = "magnets=1;engineering=2;syndicate=1" - -/obj/item/multitool/ai_detect/New() - ..() - START_PROCESSING(SSobj, src) - -/obj/item/multitool/ai_detect/Destroy() - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/item/multitool/ai_detect/process() - if(track_cooldown > world.time) - return - detect_state = PROXIMITY_NONE - multitool_detect() - icon_state = "[initial(icon_state)][detect_state]" - track_cooldown = world.time + track_delay - -/obj/item/multitool/ai_detect/proc/multitool_detect() - var/turf/our_turf = get_turf(src) - for(var/mob/living/silicon/ai/AI in ai_list) - if(AI.cameraFollow == src) - detect_state = PROXIMITY_ON_SCREEN - break - - if(!detect_state && cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z)) - var/datum/camerachunk/chunk = cameranet.getCameraChunk(our_turf.x, our_turf.y, our_turf.z) - if(chunk) - if(chunk.seenby.len) - for(var/mob/camera/aiEye/A in chunk.seenby) - var/turf/detect_turf = get_turf(A) - if(get_dist(our_turf, detect_turf) < rangealert) - detect_state = PROXIMITY_ON_SCREEN - break - if(get_dist(our_turf, detect_turf) < rangewarning) - detect_state = PROXIMITY_NEAR - break - -/obj/item/multitool/ai_detect/admin - desc = "Used for pulsing wires to test which to cut. Not recommended by doctors. Has a strange tag that says 'Grief in Safety'" //What else should I say for a meme item? - track_delay = 5 - shows_wire_information = TRUE - -/obj/item/multitool/ai_detect/admin/multitool_detect() - var/turf/our_turf = get_turf(src) - for(var/mob/J in urange(rangewarning,our_turf)) - if(check_rights(R_ADMIN, 0, J)) - detect_state = PROXIMITY_NEAR - var/turf/detect_turf = get_turf(J) - if(get_dist(our_turf, detect_turf) < rangealert) - detect_state = PROXIMITY_ON_SCREEN - break - -/obj/item/multitool/cyborg - name = "multitool" - desc = "Optimised and stripped-down version of a regular multitool." - toolspeed = 0.5 - -/obj/item/multitool/abductor - name = "alien multitool" - desc = "An omni-technological interface." - icon = 'icons/obj/abductor.dmi' - icon_state = "multitool" - toolspeed = 0.1 - origin_tech = "magnets=5;engineering=5;abductor=3" - shows_wire_information = TRUE +#define PROXIMITY_NONE "" +#define PROXIMITY_ON_SCREEN "_red" +#define PROXIMITY_NEAR "_yellow" + +/** + * Multitool -- A multitool is used for hacking electronic devices. + */ + +/obj/item/multitool + name = "multitool" + desc = "Used for pulsing wires to test which to cut. Not recommended by doctors." + icon = 'icons/obj/device.dmi' + icon_state = "multitool" + flags = CONDUCT + force = 5.0 + w_class = WEIGHT_CLASS_SMALL + throwforce = 0 + throw_range = 7 + throw_speed = 3 + materials = list(MAT_METAL=50, MAT_GLASS=20) + origin_tech = "magnets=1;engineering=2" + toolspeed = 1 + tool_behaviour = TOOL_MULTITOOL + hitsound = 'sound/weapons/tap.ogg' + var/shows_wire_information = FALSE // shows what a wire does if set to TRUE + var/obj/machinery/buffer // simple machine buffer for device linkage + +/obj/item/multitool/proc/IsBufferA(var/typepath) + if(!buffer) + return 0 + return istype(buffer,typepath) + +/obj/item/multitool/multitool_check_buffer(user, silent = FALSE) + return TRUE + +/obj/item/multitool/proc/set_multitool_buffer(mob/user, obj/machinery/M) //Loads a machine into memory, returns TRUE if it does + if(!ismachinery(M)) + to_chat(user, "That's not a machine!") + return + buffer = M + to_chat(user, "You load [M] into [src]'s internal buffer.") + return TRUE + +// Syndicate device disguised as a multitool; it will turn red when an AI camera is nearby. + +/obj/item/multitool/Destroy() + buffer = null + return ..() + +/obj/item/multitool/ai_detect + var/track_cooldown = 0 + var/track_delay = 10 //How often it checks for proximity + var/detect_state = PROXIMITY_NONE + var/rangealert = 8 //Glows red when inside + var/rangewarning = 20 //Glows yellow when inside + origin_tech = "magnets=1;engineering=2;syndicate=1" + +/obj/item/multitool/ai_detect/New() + ..() + START_PROCESSING(SSobj, src) + +/obj/item/multitool/ai_detect/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/multitool/ai_detect/process() + if(track_cooldown > world.time) + return + detect_state = PROXIMITY_NONE + multitool_detect() + icon_state = "[initial(icon_state)][detect_state]" + track_cooldown = world.time + track_delay + +/obj/item/multitool/ai_detect/proc/multitool_detect() + var/turf/our_turf = get_turf(src) + for(var/mob/living/silicon/ai/AI in ai_list) + if(AI.cameraFollow == src) + detect_state = PROXIMITY_ON_SCREEN + break + + if(!detect_state && cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z)) + var/datum/camerachunk/chunk = cameranet.getCameraChunk(our_turf.x, our_turf.y, our_turf.z) + if(chunk) + if(chunk.seenby.len) + for(var/mob/camera/aiEye/A in chunk.seenby) + var/turf/detect_turf = get_turf(A) + if(get_dist(our_turf, detect_turf) < rangealert) + detect_state = PROXIMITY_ON_SCREEN + break + if(get_dist(our_turf, detect_turf) < rangewarning) + detect_state = PROXIMITY_NEAR + break + +/obj/item/multitool/ai_detect/admin + desc = "Used for pulsing wires to test which to cut. Not recommended by doctors. Has a strange tag that says 'Grief in Safety'" //What else should I say for a meme item? + track_delay = 5 + shows_wire_information = TRUE + +/obj/item/multitool/ai_detect/admin/multitool_detect() + var/turf/our_turf = get_turf(src) + for(var/mob/J in urange(rangewarning,our_turf)) + if(check_rights(R_ADMIN, 0, J)) + detect_state = PROXIMITY_NEAR + var/turf/detect_turf = get_turf(J) + if(get_dist(our_turf, detect_turf) < rangealert) + detect_state = PROXIMITY_ON_SCREEN + break + +/obj/item/multitool/cyborg + name = "multitool" + desc = "Optimised and stripped-down version of a regular multitool." + toolspeed = 0.5 + +/obj/item/multitool/abductor + name = "alien multitool" + desc = "An omni-technological interface." + icon = 'icons/obj/abductor.dmi' + icon_state = "multitool" + toolspeed = 0.1 + origin_tech = "magnets=5;engineering=5;abductor=3" + shows_wire_information = TRUE diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm new file mode 100644 index 00000000000..17169ce8970 --- /dev/null +++ b/code/game/objects/items/tools/screwdriver.dm @@ -0,0 +1,101 @@ +//Screwdriver +/obj/item/screwdriver + name = "screwdriver" + desc = "You can be totally screwy with this." + icon = 'icons/obj/tools.dmi' + icon_state = "screwdriver_map" + flags = CONDUCT + slot_flags = SLOT_BELT + force = 5 + w_class = WEIGHT_CLASS_TINY + throwforce = 5 + throw_speed = 3 + throw_range = 5 + materials = list(MAT_METAL=75) + attack_verb = list("stabbed") + hitsound = 'sound/weapons/bladeslice.ogg' + usesound = 'sound/items/screwdriver.ogg' + toolspeed = 1 + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) + tool_behaviour = TOOL_SCREWDRIVER + var/random_color = TRUE //if the screwdriver uses random coloring + +/obj/item/screwdriver/nuke + name = "screwdriver" + desc = "A screwdriver with an ultra thin tip." + icon_state = "screwdriver_nuke" + toolspeed = 0.5 + +/obj/item/screwdriver/suicide_act(mob/user) + user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!") + return BRUTELOSS + +/obj/item/screwdriver/New(loc, var/param_color = null) + ..() + if(random_color) + if(!param_color) + param_color = pick("red","blue","pink","brown","green","cyan","yellow") + icon_state = "screwdriver_[param_color]" + + if (prob(75)) + src.pixel_y = rand(0, 16) + +/obj/item/screwdriver/attack(mob/living/carbon/M, mob/living/carbon/user) + if(!istype(M) || user.a_intent == INTENT_HELP) + return ..() + if(user.zone_selected != "eyes" && user.zone_selected != "head") + return ..() + if((CLUMSY in user.mutations) && prob(50)) + M = user + return eyestab(M,user) + +/obj/item/screwdriver/brass + name = "brass screwdriver" + desc = "A screwdriver made of brass. The handle feels freezing cold." + icon_state = "screwdriver_brass" + toolspeed = 0.5 + random_color = FALSE + resistance_flags = FIRE_PROOF | ACID_PROOF + +/obj/item/screwdriver/abductor + name = "alien screwdriver" + desc = "An ultrasonic screwdriver." + icon = 'icons/obj/abductor.dmi' + icon_state = "screwdriver" + usesound = 'sound/items/pshoom.ogg' + toolspeed = 0.1 + random_color = FALSE + +/obj/item/screwdriver/power + name = "hand drill" + desc = "A simple hand drill with a screwdriver bit attached." + icon_state = "drill_screw" + item_state = "drill" + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get + force = 8 //might or might not be too high, subject to change + throwforce = 8 + throw_speed = 2 + throw_range = 3//it's heavier than a screw driver/wrench, so it does more damage, but can't be thrown as far + attack_verb = list("drilled", "screwed", "jabbed","whacked") + hitsound = 'sound/items/drill_hit.ogg' + usesound = 'sound/items/drill_use.ogg' + toolspeed = 0.25 + random_color = FALSE + +/obj/item/screwdriver/power/suicide_act(mob/user) + user.visible_message("[user] is putting [src] to [user.p_their()] temple. It looks like [user.p_theyre()] trying to commit suicide!") + return BRUTELOSS + +/obj/item/screwdriver/power/attack_self(mob/user) + playsound(get_turf(user), 'sound/items/change_drill.ogg', 50, 1) + var/obj/item/wrench/power/b_drill = new /obj/item/wrench/power + to_chat(user, "You attach the bolt driver bit to [src].") + qdel(src) + user.put_in_active_hand(b_drill) + +/obj/item/screwdriver/cyborg + name = "powered screwdriver" + desc = "An electrical screwdriver, designed to be both precise and quick." + usesound = 'sound/items/drill_use.ogg' + toolspeed = 0.5 diff --git a/code/game/objects/items/tools/tool_behaviour.dm b/code/game/objects/items/tools/tool_behaviour.dm new file mode 100644 index 00000000000..c937f80c30d --- /dev/null +++ b/code/game/objects/items/tools/tool_behaviour.dm @@ -0,0 +1,60 @@ +// Called when a mob tries to use the item as a tool. +// Handles most checks. +/obj/item/proc/use_tool(atom/target, mob/living/user, delay, amount=0, volume=0, datum/callback/extra_checks) + // No delay means there is no start message, and no reason to call tool_start_check before use_tool. + // Run the start check here so we wouldn't have to call it manually. + target.add_fingerprint(user) + if(!tool_start_check(user, amount) && !delay) + return + delay *= toolspeed + + // Play tool sound at the beginning of tool usage. + play_tool_sound(target, volume) + + if(delay) + // Create a callback with checks that would be called every tick by do_after. + var/datum/callback/tool_check = CALLBACK(src, .proc/tool_check_callback, user, target, amount, extra_checks) + + if(ismob(target)) + if(!do_mob(user, target, delay, extra_checks=tool_check)) + return + + else + if(!do_after(user, delay, target=target, extra_checks=tool_check)) + return + else + // Invoke the extra checks once, just in case. + if(extra_checks && !extra_checks.Invoke()) + return + + // Use tool's fuel, stack sheets or charges if amount is set. + if(amount && !use(amount)) + return + + // Play tool sound at the end of tool usage, + // but only if the delay between the beginning and the end is not too small + if(delay >= MIN_TOOL_SOUND_DELAY) + play_tool_sound(target, volume) + return TRUE + +// Called before use_tool if there is a delay, or by use_tool if there isn't. +// Only ever used by welding tools and stacks, so it's not added on any other use_tool checks. +/obj/item/proc/tool_start_check(mob/living/user, amount=0) + return tool_use_check(user, amount) + +// A check called by tool_start_check once, and by use_tool on every tick of delay. +/obj/item/proc/tool_use_check(mob/living/user, amount) + return !amount + +/obj/item/proc/play_tool_sound(atom/target, volume = tool_volume) + if(target && usesound && volume) + var/played_sound = usesound + + if(islist(usesound)) + played_sound = pick(usesound) + + playsound(target, played_sound, volume, 1) + +// Used in a callback that is passed by use_tool into do_after call. Do not override, do not call manually. +/obj/item/proc/tool_check_callback(mob/living/user, atom/target, amount, datum/callback/extra_checks) + return tool_use_check(user, amount) && (!extra_checks || extra_checks.Invoke()) diff --git a/code/game/objects/items/tools/welder.dm b/code/game/objects/items/tools/welder.dm new file mode 100644 index 00000000000..b002ed32205 --- /dev/null +++ b/code/game/objects/items/tools/welder.dm @@ -0,0 +1,232 @@ +#define GET_FUEL reagents.get_reagent_amount("fuel") + +/obj/item/weldingtool + name = "welding tool" + desc = "A standard edition welder provided by Nanotrasen." + icon = 'icons/obj/tools.dmi' + icon_state = "welder" + item_state = "welder" + flags = CONDUCT + slot_flags = SLOT_BELT + force = 3 + throwforce = 5 + throw_speed = 3 + throw_range = 5 + hitsound = "swing_hit" + 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 + materials = list(MAT_METAL=70, MAT_GLASS=30) + origin_tech = "engineering=1;plasmatech=1" + tool_behaviour = TOOL_WELDER + toolspeed = 1 + tool_enabled = FALSE + usesound = 'sound/items/welder.ogg' + var/maximum_fuel = 20 + var/requires_fuel = TRUE //Set to FALSE if it doesn't need fuel, but serves equally well as a cost modifier + var/refills_over_time = FALSE //Do we regenerate fuel? + var/activation_sound = 'sound/items/welderactivate.ogg' + var/deactivation_sound = 'sound/items/welderdeactivate.ogg' + var/light_intensity = 2 + var/low_fuel_changes_icon = TRUE//More than one icon_state due to low fuel? + var/progress_flash_divisor = 10 //Length of time between each "eye flash" + +/obj/item/weldingtool/Initialize(mapload) + ..() + create_reagents(maximum_fuel) + reagents.add_reagent("fuel", maximum_fuel) + if(refills_over_time) + reagents.reagents_generated_per_cycle += list("fuel" = 1) + update_icon() + +/obj/item/weldingtool/examine(mob/user) + . = ..() + if(get_dist(user, src) <= 0) + . += "It contains [GET_FUEL] unit\s of fuel out of [maximum_fuel]." + +/obj/item/weldingtool/suicide_act(mob/user) + user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!") + return FIRELOSS + +/obj/item/weldingtool/process() + var/turf/T = get_turf(src) + T.hotspot_expose(2500, 5) + if(prob(5)) + remove_fuel(1) + ..() + +/obj/item/weldingtool/attack_self(mob/user) + if(tool_enabled) //Turn off the welder if it's on + to_chat(user, "You switch off [src].") + toggle_welder() + return + else if(GET_FUEL) //The welder is off, but we need to check if there is fuel in the tank + to_chat(user, "You switch on [src].") + toggle_welder() + else //The welder is off and unfuelled + to_chat(user, "[src] is out of fuel!") + +/obj/item/weldingtool/proc/toggle_welder(turn_off = FALSE) //Turn it on or off, forces it to deactivate + tool_enabled = turn_off ? FALSE : !tool_enabled + if(tool_enabled) + START_PROCESSING(SSobj, src) + damtype = BURN + force = 15 + hitsound = 'sound/items/welder.ogg' + playsound(loc, activation_sound, 50, 1) + set_light(light_intensity) + else + STOP_PROCESSING(SSobj, src) + damtype = BRUTE + force = 3 + hitsound = "swing_hit" + playsound(loc, deactivation_sound, 50, 1) + set_light(0) + update_icon() + if(ismob(loc)) + var/mob/M = loc + M.update_inv_r_hand() + M.update_inv_l_hand() + +// If welding tool ran out of fuel during a construction task, construction fails. +/obj/item/weldingtool/tool_use_check(mob/living/user, amount) + if(!tool_enabled) + to_chat(user, "[src] has to be on to complete this task!") + return FALSE + if(GET_FUEL >= amount * requires_fuel) + return TRUE + else + to_chat(user, "You need more welding fuel to complete this task!") + return FALSE + +// When welding is about to start, run a normal tool_use_check, then flash a mob if it succeeds. +/obj/item/weldingtool/tool_start_check(mob/living/user, amount=0) + . = tool_use_check(user, amount) + if(. && user) + user.flash_eyes(light_intensity) + +/obj/item/weldingtool/use(amount) + if(GET_FUEL < amount * requires_fuel) + return + remove_fuel(amount) + return TRUE + +/obj/item/weldingtool/use_tool(target, user, delay, amount, volume, datum/callback/extra_checks) + var/did_thing = ..() + if(did_thing) + remove_fuel(1) //Consume some fuel after we do a welding action + if(delay) + progress_flash_divisor = initial(progress_flash_divisor) + return did_thing + +/obj/item/weldingtool/tool_check_callback(mob/living/user, amount, datum/callback/extra_checks) + . = ..() + if(. && user) + if(progress_flash_divisor == 0) + user.flash_eyes(min(light_intensity, 1)) + progress_flash_divisor = initial(progress_flash_divisor) + else + progress_flash_divisor-- + +/obj/item/weldingtool/proc/remove_fuel(amount) //NB: doesn't check if we have enough fuel, it just removes however much is left if there's not enough + reagents.remove_reagent("fuel", amount * requires_fuel) + if(!GET_FUEL) + toggle_welder(TRUE) + +/obj/item/weldingtool/refill(mob/user, atom/A, amount) + if(!A.reagents) + return + if(GET_FUEL >= maximum_fuel) + to_chat(user, "[src] is already full!") + return + var/amount_transferred = A.reagents.trans_id_to(src, "fuel", amount) + if(amount_transferred) + to_chat(user, "You refuel [src] by [amount_transferred] unit\s.") + playsound(src, 'sound/effects/refill.ogg', 50, 1) + update_icon() + return amount_transferred + else + to_chat(user, "There's not enough fuel in [A] to refuel [src]!") + +/obj/item/weldingtool/proc/update_torch() + overlays.Cut() + if(tool_enabled) + overlays += "[initial(icon_state)]-on" + item_state = "[initial(item_state)]1" + else + item_state = "[initial(item_state)]" + +/obj/item/weldingtool/update_icon() + if(low_fuel_changes_icon) + var/ratio = GET_FUEL / maximum_fuel + ratio = Ceiling(ratio*4) * 25 + if(ratio == 100) + icon_state = initial(icon_state) + else + icon_state = "[initial(icon_state)][ratio]" + update_torch() + ..() + + +/obj/item/weldingtool/largetank + name = "industrial welding tool" + desc = "A slightly larger welder with a larger tank." + icon_state = "indwelder" + maximum_fuel = 40 + materials = list(MAT_METAL=70, MAT_GLASS=60) + origin_tech = "engineering=2;plasmatech=2" + +/obj/item/weldingtool/largetank/cyborg + name = "integrated welding tool" + desc = "An advanced welder designed to be used in robotic systems." + toolspeed = 0.5 + +/obj/item/weldingtool/mini + name = "emergency welding tool" + desc = "A miniature welder used during emergencies." + icon_state = "miniwelder" + maximum_fuel = 10 + w_class = WEIGHT_CLASS_TINY + materials = list(MAT_METAL=30, MAT_GLASS=10) + low_fuel_changes_icon = FALSE + +/obj/item/weldingtool/abductor + name = "alien welding tool" + desc = "An alien welding tool. Whatever fuel it uses, it never runs out." + icon = 'icons/obj/abductor.dmi' + icon_state = "welder" + toolspeed = 0.1 + light_intensity = 0 + origin_tech = "plasmatech=5;engineering=5;abductor=3" + requires_fuel = FALSE + refills_over_time = TRUE + low_fuel_changes_icon = FALSE + +/obj/item/weldingtool/hugetank + name = "upgraded welding tool" + desc = "An upgraded welder based off the industrial welder." + icon_state = "upindwelder" + item_state = "upindwelder" + maximum_fuel = 80 + materials = list(MAT_METAL=70, MAT_GLASS=120) + origin_tech = "engineering=3;plasmatech=2" + +/obj/item/weldingtool/experimental + name = "experimental welding tool" + desc = "An experimental welder capable of self-fuel generation and less harmful to the eyes." + icon_state = "exwelder" + item_state = "exwelder" + maximum_fuel = 40 + materials = list(MAT_METAL=70, MAT_GLASS=120) + origin_tech = "materials=4;engineering=4;bluespace=3;plasmatech=4" + light_intensity = 1 + toolspeed = 0.5 + refills_over_time = TRUE + low_fuel_changes_icon = FALSE + +/obj/item/weldingtool/experimental/brass + name = "brass welding tool" + desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch." + icon_state = "brasswelder" + item_state = "brasswelder" + resistance_flags = FIRE_PROOF | ACID_PROOF diff --git a/code/game/objects/items/tools/wirecutters.dm b/code/game/objects/items/tools/wirecutters.dm new file mode 100644 index 00000000000..939139ce0b8 --- /dev/null +++ b/code/game/objects/items/tools/wirecutters.dm @@ -0,0 +1,95 @@ +/obj/item/wirecutters + name = "wirecutters" + desc = "This cuts wires." + icon = 'icons/obj/tools.dmi' + icon_state = "cutters" + flags = CONDUCT + slot_flags = SLOT_BELT + force = 6 + throw_speed = 3 + throw_range = 7 + w_class = WEIGHT_CLASS_SMALL + materials = list(MAT_METAL=80) + origin_tech = "materials=1;engineering=1" + attack_verb = list("pinched", "nipped") + hitsound = 'sound/items/wirecutter.ogg' + usesound = 'sound/items/wirecutter.ogg' + sharp = 1 + toolspeed = 1 + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) + tool_behaviour = TOOL_WIRECUTTER + var/random_color = TRUE + +/obj/item/wirecutters/New(loc, param_color = null) + ..() + if(random_color) + if(!param_color) + param_color = pick("yellow", "red") + icon_state = "cutters_[param_color]" + +/obj/item/wirecutters/attack(mob/living/carbon/C, mob/user) + if(istype(C) && C.handcuffed && istype(C.handcuffed, /obj/item/restraints/handcuffs/cable)) + user.visible_message("[user] cuts [C]'s restraints with [src]!") + QDEL_NULL(C.handcuffed) + if(C.buckled && C.buckled.buckle_requires_restraints) + C.buckled.unbuckle_mob(C) + C.update_handcuffed() + return + else + ..() + +/obj/item/wirecutters/suicide_act(mob/user) + user.visible_message("[user] is cutting at [user.p_their()] arteries with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, usesound, 50, 1, -1) + return BRUTELOSS + +/obj/item/wirecutters/brass + name = "brass wirecutters" + desc = "A pair of wirecutters made of brass. The handle feels freezing cold to the touch." + icon_state = "cutters_brass" + toolspeed = 0.5 + random_color = FALSE + resistance_flags = FIRE_PROOF | ACID_PROOF + +/obj/item/wirecutters/abductor + name = "alien wirecutters" + desc = "Extremely sharp wirecutters, made out of a silvery-green metal." + icon = 'icons/obj/abductor.dmi' + icon_state = "cutters" + toolspeed = 0.1 + origin_tech = "materials=5;engineering=4;abductor=3" + random_color = FALSE + +/obj/item/wirecutters/cyborg + name = "wirecutters" + desc = "This cuts wires." + toolspeed = 0.5 + +/obj/item/wirecutters/power + name = "jaws of life" + desc = "A set of jaws of life, the magic of science has managed to fit it down into a device small enough to fit in a tool belt. It's fitted with a cutting head." + icon_state = "jaws_cutter" + item_state = "jawsoflife" + origin_tech = "materials=2;engineering=2" + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + usesound = 'sound/items/jaws_cut.ogg' + toolspeed = 0.25 + random_color = FALSE + +/obj/item/wirecutters/power/suicide_act(mob/user) + user.visible_message("[user] is wrapping \the [src] around [user.p_their()] neck. It looks like [user.p_theyre()] trying to rip [user.p_their()] head off!") + playsound(loc, 'sound/items/jaws_cut.ogg', 50, 1, -1) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + var/obj/item/organ/external/head/head = H.bodyparts_by_name["head"] + if(head) + head.droplimb(0, DROPLIMB_BLUNT, FALSE, TRUE) + playsound(loc,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1) + return BRUTELOSS + +/obj/item/wirecutters/power/attack_self(mob/user) + playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) + var/obj/item/crowbar/power/pryjaws = new /obj/item/crowbar/power + to_chat(user, "You attach the pry jaws to [src].") + qdel(src) + user.put_in_active_hand(pryjaws) diff --git a/code/game/objects/items/tools/wrench.dm b/code/game/objects/items/tools/wrench.dm new file mode 100644 index 00000000000..5af1185e90b --- /dev/null +++ b/code/game/objects/items/tools/wrench.dm @@ -0,0 +1,105 @@ +//Wrench +/obj/item/wrench + name = "wrench" + desc = "A wrench with common uses. Can be found in your hand." + icon = 'icons/obj/tools.dmi' + icon_state = "wrench" + flags = CONDUCT + slot_flags = SLOT_BELT + force = 5 + throwforce = 7 + usesound = 'sound/items/ratchet.ogg' + w_class = WEIGHT_CLASS_SMALL + materials = list(MAT_METAL=150) + origin_tech = "materials=1;engineering=1" + attack_verb = list("bashed", "battered", "bludgeoned", "whacked") + toolspeed = 1 + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) + tool_behaviour = TOOL_WRENCH + +/obj/item/wrench/suicide_act(mob/user) + user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) + return BRUTELOSS + +/obj/item/wrench/cyborg + name = "automatic wrench" + desc = "An advanced robotic wrench. Can be found in construction cyborgs." + toolspeed = 0.5 + +/obj/item/wrench/brass + name = "brass wrench" + desc = "A brass wrench. It's faintly warm to the touch." + icon_state = "wrench_brass" + toolspeed = 0.5 + resistance_flags = FIRE_PROOF | ACID_PROOF + +/obj/item/wrench/abductor + name = "alien wrench" + desc = "A polarized wrench. It causes anything placed between the jaws to turn." + icon = 'icons/obj/abductor.dmi' + icon_state = "wrench" + usesound = 'sound/effects/empulse.ogg' + toolspeed = 0.1 + origin_tech = "materials=5;engineering=5;abductor=3" + +/obj/item/wrench/power + name = "hand drill" + desc = "A simple powered drill with a bolt bit." + icon_state = "drill_bolt" + item_state = "drill" + usesound = 'sound/items/drill_use.ogg' + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get + force = 8 //might or might not be too high, subject to change + throwforce = 8 + attack_verb = list("drilled", "screwed", "jabbed") + toolspeed = 0.25 + +/obj/item/wrench/power/attack_self(mob/user) + playsound(get_turf(user),'sound/items/change_drill.ogg', 50, 1) + var/obj/item/wirecutters/power/s_drill = new /obj/item/screwdriver/power + to_chat(user, "You attach the screwdriver bit to [src].") + qdel(src) + user.put_in_active_hand(s_drill) + +/obj/item/wrench/power/suicide_act(mob/user) + user.visible_message("[user] is pressing [src] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!") + return BRUTELOSS + +/obj/item/wrench/medical + name = "medical wrench" + desc = "A medical wrench with common (medical?) uses. Can be found in your hand." + icon_state = "wrench_medical" + force = 2 //MEDICAL + throwforce = 4 + origin_tech = "materials=1;engineering=1;biotech=3" + attack_verb = list("wrenched", "medicaled", "tapped", "jabbed", "whacked") + +/obj/item/wrench/medical/suicide_act(mob/user) + user.visible_message("[user] is praying to the medical wrench to take [user.p_their()] soul. It looks like [user.p_theyre()] trying to commit suicide!") + // TODO Make them glow with the power of the M E D I C A L W R E N C H + // during their ascension + + // Stun stops them from wandering off + user.Stun(5) + playsound(loc, 'sound/effects/pray.ogg', 50, 1, -1) + + // Let the sound effect finish playing + sleep(20) + + if(!user) + return + + for(var/obj/item/W in user) + user.unEquip(W) + + var/obj/item/wrench/medical/W = new /obj/item/wrench/medical(loc) + W.add_fingerprint(user) + W.desc += " For some reason, it reminds you of [user.name]." + + if(!user) + return + + user.dust() + return OBLITERATION diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 71d5e36badf..2fe83a08398 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -38,6 +38,7 @@ item_state = "balloon-empty" /obj/item/toy/balloon/New() + ..() create_reagents(10) /obj/item/toy/balloon/attack(mob/living/carbon/human/M as mob, mob/user as mob) @@ -799,6 +800,7 @@ obj/item/toy/cards/deck/syndicate/black resistance_flags = FLAMMABLE /obj/item/toy/therapy/New() + ..() if(item_color) name = "[item_color] therapy doll" desc += " This one is [item_color]." @@ -1069,6 +1071,22 @@ obj/item/toy/cards/deck/syndicate/black name = "tuxedo cat plushie" icon_state = "tuxedocat" +/obj/item/toy/plushie/voxplushie + name = "vox plushie" + desc = "A stitched-together vox, fresh from the skipjack. Press its belly to hear it skree!" + icon_state = "plushie_vox" + item_state = "plushie_vox" + var/cooldown = 0 + +/obj/item/toy/plushie/voxplushie/attack_self(mob/user) + if(!cooldown) + playsound(user, 'sound/voice/shriek1.ogg', 10, 0) + visible_message("Skreee!") + cooldown = 1 + spawn(30) cooldown = 0 + return + ..() + //New generation TG plushies /obj/item/toy/plushie/lizardplushie diff --git a/code/game/objects/items/weapons/RCL.dm b/code/game/objects/items/weapons/RCL.dm index 10e52fc716a..fc803a5398e 100644 --- a/code/game/objects/items/weapons/RCL.dm +++ b/code/game/objects/items/weapons/RCL.dm @@ -36,26 +36,30 @@ return update_icon() to_chat(user, "You add the cables to the [src]. It now contains [loaded.amount].") - else if(isscrewdriver(W)) - if(!loaded) - return - to_chat(user, "You loosen the securing screws on the side, allowing you to lower the guiding edge and retrieve the wires.") - while(loaded.amount > 30) //There are only two kinds of situations: "nodiff" (60,90), or "diff" (31-59, 61-89) - var/diff = loaded.amount % 30 - if(diff) - loaded.use(diff) - new /obj/item/stack/cable_coil(user.loc, diff) - else - loaded.use(30) - new /obj/item/stack/cable_coil(user.loc, 30) - loaded.max_amount = initial(loaded.max_amount) - loaded.forceMove(user.loc) - user.put_in_hands(loaded) - loaded = null - update_icon() else ..() +/obj/item/twohanded/rcl/screwdriver_act(mob/user, obj/item/I) + if(!loaded) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + to_chat(user, "You loosen the securing screws on the side, allowing you to lower the guiding edge and retrieve the wires.") + while(loaded.amount > 30) //There are only two kinds of situations: "nodiff" (60,90), or "diff" (31-59, 61-89) + var/diff = loaded.amount % 30 + if(diff) + loaded.use(diff) + new /obj/item/stack/cable_coil(user.loc, diff) + else + loaded.use(30) + new /obj/item/stack/cable_coil(user.loc, 30) + loaded.max_amount = initial(loaded.max_amount) + loaded.forceMove(user.loc) + user.put_in_hands(loaded) + loaded = null + update_icon() + /obj/item/twohanded/rcl/examine(mob/user) . = ..() if(loaded) diff --git a/code/game/objects/items/weapons/RSF.dm b/code/game/objects/items/weapons/RSF.dm index 2b5b8e1e8fc..55dfa04c394 100644 --- a/code/game/objects/items/weapons/RSF.dm +++ b/code/game/objects/items/weapons/RSF.dm @@ -18,6 +18,7 @@ RSF var/list/configured_items = list() /obj/item/rsf/New() + ..() desc = "A RSF. It currently holds [matter]/30 fabrication-units." // configured_items[ID_NUMBER] = list("Human-readable name", price in energy, /type/path) configured_items[++configured_items.len] = list("Dosh", 50, /obj/item/stack/spacecash/c10) @@ -30,7 +31,6 @@ RSF configured_items[++configured_items.len] = list("Snack - Donut", 4000, /obj/item/reagent_containers/food/snacks/donut) configured_items[++configured_items.len] = list("Snack - Chicken Soup", 4000, /obj/item/reagent_containers/food/drinks/chicken_soup) configured_items[++configured_items.len] = list("Snack - Turkey Burger", 4000, /obj/item/reagent_containers/food/snacks/tofuburger) - return /obj/item/rsf/attackby(obj/item/W as obj, mob/user as mob, params) ..() diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index b0167701fac..626bb7bbfe3 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -681,6 +681,7 @@ /obj/item/card/id/prisoner/random /obj/item/card/id/prisoner/random/New() + ..() var/random_number = "#[rand(0, 99)]-[rand(0, 999)]" name = "Prisoner [random_number]" registered_name = name diff --git a/code/game/objects/items/weapons/cigs.dm b/code/game/objects/items/weapons/cigs.dm index fa4b90e0e37..de3eb52bdd2 100644 --- a/code/game/objects/items/weapons/cigs.dm +++ b/code/game/objects/items/weapons/cigs.dm @@ -64,14 +64,14 @@ LIGHTERS ARE IN LIGHTERS.DM ..() light() +/obj/item/clothing/mask/cigarette/welder_act(mob/user, obj/item/I) + . = TRUE + if(I.tool_use_check(user, 0)) //Don't need to flash eyes because you are a badass + light("[user] casually lights the [name] with [I], what a badass.") + /obj/item/clothing/mask/cigarette/attackby(obj/item/W as obj, mob/user as mob, params) ..() - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(WT.isOn())//Badasses dont get blinded while lighting their cig with a welding tool - light("[user] casually lights the [name] with [W], what a badass.") - - else if(istype(W, /obj/item/lighter/zippo)) + if(istype(W, /obj/item/lighter/zippo)) var/obj/item/lighter/zippo/Z = W if(Z.lit) light("With a single flick of [user.p_their()] wrist, [user] smoothly lights [user.p_their()] [name] with [user.p_their()] [W]. Damn [user.p_theyre()] cool.") diff --git a/code/game/objects/items/weapons/conversion_kit.dm b/code/game/objects/items/weapons/conversion_kit.dm new file mode 100644 index 00000000000..4eb09ff6f6e --- /dev/null +++ b/code/game/objects/items/weapons/conversion_kit.dm @@ -0,0 +1,21 @@ +// Conversion kit +/obj/item/conversion_kit + name = "\improper Revolver Conversion Kit" + desc = "A professional conversion kit used to convert any knock off revolver into the real deal capable of shooting lethal .357 rounds without the possibility of catastrophic failure." + icon_state = "kit" + flags = CONDUCT + w_class = WEIGHT_CLASS_SMALL + origin_tech = "combat=2" + var/open = 0 + +/obj/item/conversion_kit/New() + ..() + update_icon() + +/obj/item/conversion_kit/update_icon() + icon_state = "[initial(icon_state)]_[open]" + +/obj/item/conversion_kit/attack_self(mob/user) + open = !open + to_chat(user, "You [open ? "open" : "close"] the conversion kit.") + update_icon() diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm index 9f1f6bc194f..b7aa9675891 100644 --- a/code/game/objects/items/weapons/cosmetics.dm +++ b/code/game/objects/items/weapons/cosmetics.dm @@ -48,6 +48,7 @@ name = "lipstick" /obj/item/lipstick/random/New() + ..() var/lscolor = pick(lipstick_colors)//A random color is picked from the var defined initially in a new var. colour = lipstick_colors[lscolor]//The color of the lipstick is pulled from the new variable (right hand side, HTML & Hex RGB) name = "[lscolor] lipstick"//The new variable is also used to match the name to the color of the lipstick. Kudos to Desolate & Lemon diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm index 9ccbc3bffd5..3ea5fdff56a 100644 --- a/code/game/objects/items/weapons/extinguisher.dm +++ b/code/game/objects/items/weapons/extinguisher.dm @@ -46,6 +46,7 @@ /obj/item/extinguisher/New() + ..() create_reagents(max_water) reagents.add_reagent("water", max_water) diff --git a/code/game/objects/items/weapons/fireworks.dm b/code/game/objects/items/weapons/fireworks.dm index d2e523cf953..7db6eb18250 100644 --- a/code/game/objects/items/weapons/fireworks.dm +++ b/code/game/objects/items/weapons/fireworks.dm @@ -7,7 +7,7 @@ obj/item/firework obj/item/firework/attackby(obj/item/W,mob/user, params) if(litzor) return - if(istype(W, /obj/item/weldingtool) && W:welding || istype(W,/obj/item/lighter) && W:lit) + if(is_hot(W)) for(var/mob/M in viewers(user)) to_chat(M, "[user] lits \the [src]") litzor = 1 @@ -29,7 +29,7 @@ obj/item/sparkler obj/item/sparkler/attackby(obj/item/W,mob/user, params) if(litzor) return - if(istype(W, /obj/item/weldingtool) && W:welding || istype(W,/obj/item/lighter) && W:lit) + if(is_hot(W)) for(var/mob/M in viewers(user)) to_chat(M, "[user] lits \the [src]") litzor = 1 diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm index 298ce493b14..fc1a0ca6c12 100644 --- a/code/game/objects/items/weapons/flamethrower.dm +++ b/code/game/objects/items/weapons/flamethrower.dm @@ -76,28 +76,7 @@ flame_turf(turflist) /obj/item/flamethrower/attackby(obj/item/I, mob/user, params) - if(iswrench(I) && !status)//Taking this apart - var/turf/T = get_turf(src) - if(weldtool) - weldtool.forceMove(T) - weldtool = null - if(igniter) - igniter.forceMove(T) - igniter = null - if(ptank) - ptank.forceMove(T) - ptank = null - new /obj/item/stack/rods(T) - qdel(src) - return - - else if(isscrewdriver(I) && igniter && !lit) - status = !status - to_chat(user, "[igniter] is now [status ? "secured" : "unsecured"]!") - update_icon() - return - - else if(isigniter(I)) + if(isigniter(I)) var/obj/item/assembly/igniter/IG = I if(IG.secured) return @@ -130,6 +109,34 @@ else return ..() +/obj/item/flamethrower/wrench_act(mob/user, obj/item/I) + if(status) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + var/turf/T = get_turf(src) + if(weldtool) + weldtool.forceMove(T) + weldtool = null + if(igniter) + igniter.forceMove(T) + igniter = null + if(ptank) + ptank.forceMove(T) + ptank = null + new /obj/item/stack/rods(T) + qdel(src) + +/obj/item/flamethrower/screwdriver_act(mob/user, obj/item/I) + if(!igniter || lit) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + status = !status + to_chat(user, "[igniter] is now [status ? "secured" : "unsecured"]!") + update_icon() /obj/item/flamethrower/attack_self(mob/user) toggle_igniter(user) @@ -168,7 +175,6 @@ ..() weldtool = locate(/obj/item/weldingtool) in contents igniter = locate(/obj/item/assembly/igniter) in contents - weldtool.status = FALSE igniter.secured = FALSE status = TRUE update_icon() @@ -216,7 +222,6 @@ if(create_full) if(!weldtool) weldtool = new /obj/item/weldingtool(src) - weldtool.status = FALSE if(!igniter) igniter = new igniter_type(src) igniter.secured = FALSE diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index 91c6252d9b2..8b08a4dc5b0 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -26,6 +26,7 @@ var/cores = "" // Also for logging /obj/item/grenade/chem_grenade/New() + ..() create_reagents(1000) if(payload_name) payload_name += " " // formatting, ignore me @@ -387,18 +388,18 @@ origin_tech = "combat=3;engineering=4" var/unit_spread = 10 // Amount of units per repeat. Can be altered with a multitool. -/obj/item/grenade/chem_grenade/adv_release/attackby(obj/item/I, mob/user, params) - if(ismultitool(I)) - switch(unit_spread) - if(0 to 24) - unit_spread += 5 - if(25 to 99) - unit_spread += 25 - else - unit_spread = 5 - to_chat(user, " You set the time release to [unit_spread] units per detonation.") +/obj/item/grenade/chem_grenade/adv_release/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return - ..() + switch(unit_spread) + if(0 to 24) + unit_spread += 5 + if(25 to 99) + unit_spread += 25 + else + unit_spread = 5 + to_chat(user, " You set the time release to [unit_spread] units per detonation.") /obj/item/grenade/chem_grenade/adv_release/prime() if(stage != READY) diff --git a/code/game/objects/items/weapons/grenades/frag.dm b/code/game/objects/items/weapons/grenades/frag.dm index db7943ca7d9..5b2e836bf81 100644 --- a/code/game/objects/items/weapons/grenades/frag.dm +++ b/code/game/objects/items/weapons/grenades/frag.dm @@ -47,4 +47,5 @@ hitsound = 'sound/weapons/pierce.ogg' /obj/item/embedded/shrapnel/New() + ..() icon_state = pick("shrapnel1", "shrapnel2", "shrapnel3") diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm index 33d72c1ebb5..95cf1e7026a 100644 --- a/code/game/objects/items/weapons/holy_weapons.dm +++ b/code/game/objects/items/weapons/holy_weapons.dm @@ -556,6 +556,7 @@ var/faith = 99 //a conversion requires 100 faith to attempt. faith recharges over time while you are wearing missionary robes that have been linked to the staff. /obj/item/nullrod/missionary_staff/New() + ..() team_color = pick("red", "blue") icon_state = "godstaff-[team_color]" item_state = "godstaff-[team_color]" diff --git a/code/game/objects/items/weapons/implants/implant_traitor.dm b/code/game/objects/items/weapons/implants/implant_traitor.dm index f281353c62f..05d2363ee01 100644 --- a/code/game/objects/items/weapons/implants/implant_traitor.dm +++ b/code/game/objects/items/weapons/implants/implant_traitor.dm @@ -48,7 +48,7 @@ return -1 mindslave_target.implanting = 1 - to_chat(mindslave_target, "You feel completely loyal to [user.name].") + to_chat(mindslave_target, "You feel completely loyal to [user.name].") if(!(user.mind in SSticker.mode.implanter)) SSticker.mode.implanter[user.mind] = list() implanters = SSticker.mode.implanter[user.mind] @@ -57,7 +57,7 @@ SSticker.mode.implanted[mindslave_target.mind] = user.mind SSticker.mode.implanter[user.mind] = implanters - to_chat(mindslave_target, "You're now completely loyal to [user.name]! You now must lay down your life to protect [user.p_them()] and assist in [user.p_their()] goals at any cost.") + to_chat(mindslave_target, "You're now completely loyal to [user.name]! You now must lay down your life to protect [user.p_them()] and assist in [user.p_their()] goals at any cost.") var/datum/objective/protect/mindslave/MS = new MS.owner = mindslave_target.mind diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm index 66d1e625e8c..77f133b775c 100644 --- a/code/game/objects/items/weapons/kitchen.dm +++ b/code/game/objects/items/weapons/kitchen.dm @@ -36,11 +36,11 @@ var/max_contents = 1 /obj/item/kitchen/utensil/New() + ..() if(prob(60)) src.pixel_y = rand(0, 4) create_reagents(5) - return /obj/item/kitchen/utensil/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) if(!istype(M)) diff --git a/code/game/objects/items/weapons/lighters.dm b/code/game/objects/items/weapons/lighters.dm index d141d7ade27..23c55cc1a63 100644 --- a/code/game/objects/items/weapons/lighters.dm +++ b/code/game/objects/items/weapons/lighters.dm @@ -26,10 +26,11 @@ icon_off = "zippo" /obj/item/lighter/random/New() - var/color = pick("r","c","y","g") - icon_on = "lighter-[color]-on" - icon_off = "lighter-[color]" - icon_state = icon_off + ..() + var/color = pick("r","c","y","g") + icon_on = "lighter-[color]-on" + icon_off = "lighter-[color]" + icon_state = icon_off /obj/item/lighter/attack_self(mob/living/user) if(user.r_hand == src || user.l_hand == src || isrobot(user)) diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm index 4d36c640784..4cc4cb948ce 100644 --- a/code/game/objects/items/weapons/manuals.dm +++ b/code/game/objects/items/weapons/manuals.dm @@ -18,7 +18,7 @@ - + @@ -164,7 +164,7 @@ - + @@ -805,7 +805,7 @@ - + @@ -828,7 +828,7 @@ - + diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index 89146cf9952..e97fc554d59 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -119,6 +119,7 @@ var/hacked = 0 /obj/item/melee/energy/sword/New() + ..() if(item_color == null) item_color = pick("red", "blue", "green", "purple") @@ -219,9 +220,6 @@ icon_state_on = "cutlass1" light_color = LIGHT_COLOR_RED -/obj/item/melee/energy/sword/pirate/New() - return - /obj/item/melee/energy/blade name = "energy blade" desc = "A concentrated beam of energy in the shape of a blade. Very stylish... and lethal." diff --git a/code/game/objects/items/weapons/misc.dm b/code/game/objects/items/weapons/misc.dm index a718d3bd389..0732c0fdd1d 100644 --- a/code/game/objects/items/weapons/misc.dm +++ b/code/game/objects/items/weapons/misc.dm @@ -90,7 +90,8 @@ desc = "test lightning" /obj/item/lightning/New() - icon_state = "1" + ..() + icon_state = "1" /obj/item/lightning/afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params) var/angle = get_angle(A, user) diff --git a/code/game/objects/items/weapons/pneumaticCannon.dm b/code/game/objects/items/weapons/pneumaticCannon.dm index 6a2ee5635d7..21127f6869f 100644 --- a/code/game/objects/items/weapons/pneumaticCannon.dm +++ b/code/game/objects/items/weapons/pneumaticCannon.dm @@ -138,8 +138,7 @@ /datum/crafting_recipe/improvised_pneumatic_cannon //Pretty easy to obtain but name = "Pneumatic Cannon" result = /obj/item/pneumatic_cannon/ghetto - tools = list(/obj/item/weldingtool, - /obj/item/wrench) + tools = list(TOOL_WELDER, TOOL_WRENCH) reqs = list(/obj/item/stack/sheet/metal = 4, /obj/item/stack/packageWrap = 8, /obj/item/pipe = 2) diff --git a/code/game/objects/items/weapons/powerfist.dm b/code/game/objects/items/weapons/powerfist.dm index 4aab2c25d22..217cb963719 100644 --- a/code/game/objects/items/weapons/powerfist.dm +++ b/code/game/objects/items/weapons/powerfist.dm @@ -37,20 +37,29 @@ to_chat(user, "[IT] is too small for [src].") return updateTank(W, 0, user) - else if(iswrench(W)) - switch(fisto_setting) - if(1) - fisto_setting = 2 - if(2) - fisto_setting = 3 - if(3) - fisto_setting = 1 - playsound(loc, W.usesound, 50, 1) - to_chat(user, "You tweak [src]'s piston valve to [fisto_setting].") - else if(isscrewdriver(W)) - if(tank) - updateTank(tank, 1, user) + return + return ..() +/obj/item/melee/powerfist/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + switch(fisto_setting) + if(1) + fisto_setting = 2 + if(2) + fisto_setting = 3 + if(3) + fisto_setting = 1 + to_chat(user, "You tweak [src]'s piston valve to [fisto_setting].") + +/obj/item/melee/powerfist/screwdriver_act(mob/user, obj/item/I) + if(!tank) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + updateTank(tank, 1, user) /obj/item/melee/powerfist/proc/updateTank(obj/item/tank/thetank, removing = 0, mob/living/carbon/human/user) if(removing) diff --git a/code/game/objects/items/weapons/scissors.dm b/code/game/objects/items/weapons/scissors.dm index 3340542ea15..f2d750aafa2 100644 --- a/code/game/objects/items/weapons/scissors.dm +++ b/code/game/objects/items/weapons/scissors.dm @@ -27,57 +27,11 @@ return if(ishuman(M)) var/mob/living/carbon/human/H = M - //see code/modules/mob/new_player/preferences.dm at approx line 545 for comments! - //this is largely copypasted from there. - //handle facial hair (if necessary) - var/list/species_facial_hair = list() var/obj/item/organ/external/head/C = H.get_organ("head") - var/datum/robolimb/robohead = all_robolimbs[C.model] - if(H.gender == MALE || isvulpkanin(H)) - if(C.dna.species) - for(var/i in GLOB.facial_hair_styles_list) - var/datum/sprite_accessory/facial_hair/tmp_facial = GLOB.facial_hair_styles_list[i] - if(C.dna.species.name in tmp_facial.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human hair styles. - if(C.dna.species.bodyflags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. - if(robohead.is_monitor) - to_chat(user, "You are unable to find anything on [H]'s face worth cutting. How disappointing.") - return - continue //If the head DOES support human hair wigs, make sure they don't get monitor-oriented styles. - species_facial_hair += i - else - if(C.dna.species.bodyflags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. - if(!robohead.is_monitor) - if("Human" in tmp_facial.species_allowed) - species_facial_hair += i - else //Otherwise, they won't be getting any hairstyles. - to_chat(user, "You are unable to find anything on [H]'s face worth cutting. How disappointing.") - return - else - species_facial_hair = GLOB.facial_hair_styles_list - var/f_new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in species_facial_hair + //facial hair + var/f_new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in H.generate_valid_facial_hairstyles() //handle normal hair - var/list/species_hair = list() - if(C.dna.species) - for(var/i in GLOB.hair_styles_public_list) - var/datum/sprite_accessory/hair/tmp_hair = GLOB.hair_styles_public_list[i] - if(C.dna.species.name in tmp_hair.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human facial hair styles. - if(C.dna.species.bodyflags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. - if(robohead.is_monitor) - to_chat(user, "You are unable to find anything on [H]'s head worth cutting. How disappointing.") - return - continue //If the head DOES support human hair wigs, make sure they don't get monitor-oriented styles. - species_hair += i - else - if(C.dna.species.bodyflags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. - if(!robohead.is_monitor) - if("Human" in tmp_hair.species_allowed) - species_hair += i - else //Otherwise, they won't be getting any hairstyles. - to_chat(user, "You are unable to find anything on [H]'s head worth cutting. How disappointing.") - return - else - species_hair = GLOB.hair_styles_public_list - var/h_new_style = input(user, "Select a hair style", "Grooming") as null|anything in species_hair + var/h_new_style = input(user, "Select a hair style", "Grooming") as null|anything in H.generate_valid_hairstyles() user.visible_message("[user] starts cutting [M]'s hair!", "You start cutting [M]'s hair!") //arguments for this are: 1. what others see 2. what the user sees. --Fixed grammar, (TGameCo) playsound(loc, 'sound/goonstation/misc/scissor.ogg', 100, 1) if(do_after(user, 50 * toolspeed, target = H)) //this is the part that adds a delay. delay is in deciseconds. --Made it 5 seconds, because hair isn't cut in one second in real life, and I want at least a little bit longer time, (TGameCo) diff --git a/code/game/objects/items/weapons/shards.dm b/code/game/objects/items/weapons/shards.dm index 1bad335bb49..52c2aea5ddb 100644 --- a/code/game/objects/items/weapons/shards.dm +++ b/code/game/objects/items/weapons/shards.dm @@ -60,26 +60,27 @@ H.UpdateDamageIcon() /obj/item/shard/attackby(obj/item/I, mob/user, params) - if(iswelder(I)) - var/obj/item/weldingtool/WT = I - if(WT.remove_fuel(0, user)) - var/obj/item/stack/sheet/NG = new welded_type(user.loc) - for(var/obj/item/stack/sheet/G in user.loc) - if(!istype(G, welded_type)) - continue - if(G == NG) - continue - if(G.amount >= G.max_amount) - continue - G.attackby(NG, user) - to_chat(user, "You add the newly-formed glass to the stack. It now contains [NG.amount] sheet\s.") - qdel(src) - return if(istype(I, /obj/item/lightreplacer)) I.attackby(src, user) return return ..() +/obj/item/shard/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, volume = I.tool_volume)) + return + var/obj/item/stack/sheet/NG = new welded_type(user.loc) + for(var/obj/item/stack/sheet/G in user.loc) + if(!istype(G, welded_type)) + continue + if(G == NG) + continue + if(G.amount >= G.max_amount) + continue + G.attackby(NG, user) + to_chat(user, "You add the newly-formed glass to the stack. It now contains [NG.amount] sheet\s.") + qdel(src) + /obj/item/shard/Crossed(mob/living/L, oldloc) if(istype(L) && has_gravity(loc)) if(L.incorporeal_move || L.flying) @@ -95,4 +96,4 @@ icon_state = "plasmalarge" materials = list(MAT_PLASMA = MINERAL_MATERIAL_AMOUNT * 0.5, MAT_GLASS = MINERAL_MATERIAL_AMOUNT) icon_prefix = "plasma" - welded_type = /obj/item/stack/sheet/plasmaglass \ No newline at end of file + welded_type = /obj/item/stack/sheet/plasmaglass diff --git a/code/game/objects/items/weapons/stock_parts.dm b/code/game/objects/items/weapons/stock_parts.dm index a7cdea64693..1cc2b25edf0 100644 --- a/code/game/objects/items/weapons/stock_parts.dm +++ b/code/game/objects/items/weapons/stock_parts.dm @@ -68,6 +68,7 @@ usesound = 'sound/items/deconstruct.ogg' /obj/item/stock_parts/New() + ..() src.pixel_x = rand(-5.0, 5) src.pixel_y = rand(-5.0, 5) diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index 57f4e999ac8..96806bb827a 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -61,10 +61,6 @@ cant_hold = list(/obj/item/storage/backpack/holding) armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 60, "acid" = 50) -/obj/item/storage/backpack/holding/New() - ..() - return - /obj/item/storage/backpack/holding/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/storage/backpack/holding)) var/response = alert(user, "This creates a singularity, destroying you and much of the station. Are you SURE?","IMMINENT DEATH!", "No", "Yes") @@ -373,6 +369,10 @@ new /obj/item/clothing/under/rank/miner/lavaland(src) new /obj/item/encryptionkey/headset_cargo(src) new /obj/item/clothing/mask/gas/explorer(src) + new /obj/item/gun/energy/kinetic_accelerator(src) + new /obj/item/kitchen/knife/combat/survival(src) + new /obj/item/flashlight/seclite(src) + new /obj/item/clothing/suit/hooded/explorer(src) /obj/item/storage/backpack/duffel/syndie/ammo/smg diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 5560f3b4306..0ebd553fc3b 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -396,7 +396,7 @@ ..() new /obj/item/lightreplacer(src) new /obj/item/holosign_creator(src) - new /obj/item/reagent_containers/spray(src) + new /obj/item/reagent_containers/spray/cleaner(src) new /obj/item/soap(src) new /obj/item/grenade/chem_grenade/cleaner(src) new /obj/item/grenade/chem_grenade/cleaner(src) diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 776a53a7f26..93c1a9f0d0a 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -1099,6 +1099,7 @@ desc = "Contains a variety of deluxe stock parts." /obj/item/storage/box/stockparts/deluxe/New() + ..() for(var/i in 1 to 3) new /obj/item/stock_parts/capacitor/quadratic(src) new /obj/item/stock_parts/scanning_module/triphasic(src) diff --git a/code/game/objects/items/weapons/storage/briefcase.dm b/code/game/objects/items/weapons/storage/briefcase.dm index 8ba79674ab9..3f747e0f799 100644 --- a/code/game/objects/items/weapons/storage/briefcase.dm +++ b/code/game/objects/items/weapons/storage/briefcase.dm @@ -48,19 +48,7 @@ stored_gun.afterattack(A, user, flag, params) /obj/item/storage/briefcase/false_bottomed/attackby(var/obj/item/I, mob/user) - if(isscrewdriver(I)) - if(!bottom_open && !busy_hunting) - to_chat(user, "You begin to hunt around the rim of the [src]...") - busy_hunting = TRUE - if(do_after(user, 20, target = src)) - if(user) - to_chat(user, "You pry open the false bottom!") - bottom_open = TRUE - busy_hunting = FALSE - else if(bottom_open) - to_chat(user, "You push the false bottom down and close it with a click[stored_item ? ", with the [stored_item] snugly inside." : "."]") - bottom_open = FALSE - else if(bottom_open) + if(bottom_open) if(stored_item) to_chat(user, "There's already something in the false bottom!") return @@ -78,6 +66,24 @@ else return ..() +/obj/item/storage/briefcase/false_bottomed/screwdriver_act(mob/user, obj/item/I) + if(!bottom_open && busy_hunting) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!bottom_open) + to_chat(user, "You begin to hunt around the rim of the [src]...") + busy_hunting = TRUE + if(do_after(user, 20, target = src)) + if(user) + to_chat(user, "You pry open the false bottom!") + bottom_open = TRUE + busy_hunting = FALSE + else + to_chat(user, "You push the false bottom down and close it with a click[stored_item ? ", with the [stored_item] snugly inside." : "."]") + bottom_open = FALSE + /obj/item/storage/briefcase/false_bottomed/attack_hand(mob/user) if(bottom_open && stored_item) user.put_in_hands(stored_item) diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm index c463c7897fc..117bb90c35f 100644 --- a/code/game/objects/items/weapons/teleportation.dm +++ b/code/game/objects/items/weapons/teleportation.dm @@ -70,9 +70,10 @@ Frequency: for(var/obj/item/implant/tracking/T in GLOB.tracked_implants) if(!T.implanted || !T.imp_in) continue + var/turf/Tr = get_turf(T) - if(T && T.z == z) - temp += "[T.id]: [T.imp_in.x], [T.imp_in.y], [T.imp_in.z]
    " + if(Tr && Tr.z == sr.z) + temp += "[T.id]: [Tr.x], [Tr.y], [Tr.z]
    " temp += "You are at \[[sr.x],[sr.y],[sr.z]\]." temp += "

    Refresh
    " diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index fdaea1eb183..fba969f05b7 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -240,6 +240,7 @@ var/colormap = list(red=LIGHT_COLOR_RED, blue=LIGHT_COLOR_LIGHTBLUE, green=LIGHT_COLOR_GREEN, purple=LIGHT_COLOR_PURPLE, rainbow=LIGHT_COLOR_WHITE) /obj/item/twohanded/dualsaber/New() + ..() if(!blade_color) blade_color = pick("red", "blue", "green", "purple") @@ -311,17 +312,17 @@ hitsound = 'sound/weapons/blade1.ogg' w_class = w_class_on -/obj/item/twohanded/dualsaber/attackby(obj/item/W, mob/user, params) - if(ismultitool(W)) - if(!hacked) - hacked = TRUE - to_chat(user, "2XRNBW_ENGAGE") - blade_color = "rainbow" - update_icon() - else - to_chat(user, "It's starting to look like a triple rainbow - no, nevermind.") +/obj/item/twohanded/dualsaber/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!hacked) + hacked = TRUE + to_chat(user, "2XRNBW_ENGAGE") + blade_color = "rainbow" + update_icon() else - return ..() + to_chat(user, "It's starting to look like a triple rainbow - no, nevermind.") //spears /obj/item/twohanded/spear diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index c1afed03b96..0d0a8ff8d36 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -271,6 +271,38 @@ a { user.set_machine(src) onclose(user, "mtcomputer") +/obj/proc/default_welder_repair(mob/user, obj/item/I) //Returns TRUE if the object was successfully repaired. Fully repairs an object (setting BROKEN to FALSE), default repair time = 40 + if(obj_integrity >= max_integrity) + to_chat(user, "[src] does not need repairs.") + return + if(I.tool_behaviour != TOOL_WELDER) + return + if(!I.tool_use_check(user, 0)) + return + var/time = max(50 * (1 - obj_integrity / max_integrity), 5) + WELDER_ATTEMPT_REPAIR_MESSAGE + if(I.use_tool(src, user, time, volume = I.tool_volume)) + WELDER_REPAIR_SUCCESS_MESSAGE + obj_integrity = max_integrity + update_icon() + return TRUE + +/obj/proc/default_unfasten_wrench(mob/user, obj/item/I, time = 20) + if(!anchored && !isfloorturf(loc)) + user.visible_message("A floor must be present to secure [src]!") + return FALSE + if(I.tool_behaviour != TOOL_WRENCH) + return FALSE + if(!I.tool_use_check(user, 0)) + return FALSE + if(!(flags & NODECONSTRUCT)) + to_chat(user, "Now [anchored ? "un" : ""]securing [name].") + if(I.use_tool(src, user, time, volume = I.tool_volume)) + to_chat(user, "You've [anchored ? "un" : ""]secured [name].") + anchored = !anchored + return TRUE + return FALSE + /obj/water_act(volume, temperature, source, method = TOUCH) . = ..() extinguish() diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 23ee0d0c5df..f6617feed87 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -14,9 +14,7 @@ var/locked = FALSE var/wall_mounted = 0 //never solid (You can always pass over it) var/lastbang - var/cutting_tool = /obj/item/weldingtool var/sound = 'sound/machines/click.ogg' - var/cutting_sound var/storage_capacity = 30 //This is so that someone can't pack hundreds of items in a locker/crate then open it in a populated area to crash clients. var/material_drop = /obj/item/stack/sheet/metal var/material_drop_amount = 2 @@ -220,22 +218,6 @@ MouseDrop_T(W:affecting, user) //act like they were dragged onto the closet if(istype(W,/obj/item/tk_grab)) return FALSE - if(istype(W, cutting_tool)) - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(!WT.remove_fuel(0, user)) - return - to_chat(user, "You begin cutting \the [src] apart...") - playsound(loc, cutting_sound ? cutting_sound : WT.usesound, 40, 1) - if(do_after(user, 40 * WT.toolspeed, 1, target = src)) - if(!opened || !WT.isOn()) - return - playsound(loc, cutting_sound ? cutting_sound : WT.usesound, 50, 1) - visible_message("[user] slices apart \the [src].", - "You cut \the [src] apart with \the [WT].", - "You hear welding.") - deconstruct(TRUE) - return if(isrobot(user)) return if(!user.drop_item()) //couldn't drop the item @@ -245,25 +227,36 @@ W.forceMove(loc) else if(istype(W, /obj/item/stack/packageWrap)) return - else if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(src == user.loc) - to_chat(user, "You can not [welded?"unweld":"weld"] the locker from inside.") - return - if(!WT.remove_fuel(0, user)) - to_chat(user, "You need more welding fuel to complete this task.") - return - if(!do_after_once(user, 15, target = src)) - return - welded = !welded - update_icon() - for(var/mob/M in viewers(src)) - M.show_message("[src] has been [welded?"welded shut":"unwelded"] by [user.name].", 3, "You hear welding.", 2) else if(user.a_intent != INTENT_HARM) attack_hand(user) else return ..() +/obj/structure/closet/welder_act(mob/user, obj/item/I) + . = TRUE + if(!opened && user.loc == src) + to_chat(user, "You can't weld [src] from inside!") + return + if(!I.tool_use_check(user, 0)) + return + if(opened) + WELDER_ATTEMPT_SLICING_MESSAGE + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + WELDER_SLICING_SUCCESS_MESSAGE + deconstruct(TRUE) + return + else + var/adjective = welded ? "open" : "shut" + user.visible_message("[user] begins welding [src] [adjective]...", "You begin welding [src] [adjective]...", "You hear welding.") + if(I.use_tool(src, user, 15, volume = I.tool_volume)) + if(opened) + to_chat(user, "Keep [src] shut while doing that!") + return + user.visible_message("[user] welds [src] [adjective]!", "You weld [src] [adjective]!") + welded = !welded + update_icon() + return + /obj/structure/closet/MouseDrop_T(atom/movable/O, mob/user) ..() if(istype(O, /obj/screen)) //fix for HUD elements making their way into the world -Pete diff --git a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm index 6f0bd9f257c..593212c97f2 100644 --- a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm +++ b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm @@ -11,7 +11,6 @@ sound = 'sound/effects/rustle2.ogg' material_drop = /obj/item/stack/sheet/cardboard var/amt = 4 - cutting_sound = 'sound/items/poster_ripped.ogg' var/move_delay = 0 var/egged = 0 @@ -58,11 +57,11 @@ I.alpha = 0 animate(I, pixel_z = 32, alpha = 255, time = 5, easing = ELASTIC_EASING) +/obj/structure/closet/cardboard/welder_act() + return /obj/structure/closet/cardboard/attackby(obj/item/W as obj, mob/user as mob, params) if(src.opened) - if(istype(W, /obj/item/weldingtool)) - return if(istype(W, /obj/item/wirecutters)) var/obj/item/wirecutters/WC = W new /obj/item/stack/sheet/cardboard(src.loc, amt) diff --git a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm index dea63a0d69d..741a9bae5a2 100644 --- a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm +++ b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm @@ -196,4 +196,7 @@ return /obj/structure/closet/fireaxecabinet/close() - return \ No newline at end of file + return + +/obj/structure/closet/fireaxecabinet/welder_act(mob/user, obj/item/I) //A bastion of sanity in a sea of madness + return diff --git a/code/game/objects/structures/crates_lockers/closets/statue.dm b/code/game/objects/structures/crates_lockers/closets/statue.dm index a6fe47e0e9d..3cd753740fb 100644 --- a/code/game/objects/structures/crates_lockers/closets/statue.dm +++ b/code/game/objects/structures/crates_lockers/closets/statue.dm @@ -92,6 +92,9 @@ shatter(M) ..() +/obj/structure/closet/statue/welder_act() + return + /obj/structure/closet/statue/MouseDrop_T() return diff --git a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm index a89bce34396..504d2b29644 100644 --- a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm @@ -104,6 +104,7 @@ icon_opened = "toolclosetopen" /obj/structure/closet/toolcloset/New() + ..() if(prob(40)) new /obj/item/clothing/suit/storage/hazardvest(src) if(prob(70)) diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 1b116678151..31747323e07 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -185,6 +185,9 @@ dump_contents() ..() +/obj/structure/closet/crate/welder_act() + return + /obj/structure/closet/crate/attack_hand(mob/user) if(manifest) to_chat(user, "You tear the manifest off of the crate.") @@ -439,35 +442,11 @@ icon_closed = "largebin" anchored = TRUE -/obj/structure/closet/crate/can/attackby(obj/item/W, mob/living/user, params) - if(iswrench(W)) - add_fingerprint(user) - user.changeNext_move(CLICK_CD_MELEE) - if(anchored) - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] starts loosening [src]'s floor casters.", \ - "You start loosening [src]'s floor casters...") - if(do_after(user, 40 * W.toolspeed, target = src)) - if(!loc || !anchored) - return - user.visible_message("[user] loosened [src]'s floor casters.", \ - "You loosen [src]'s floor casters.") - anchored = FALSE - else - if(!isfloorturf(loc)) - user.visible_message("A floor must be present to secure [src]!") - return - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] start securing [src]'s floor casters...", \ - "You start securing [src]'s floor casters...") - if(do_after(user, 40 * W.toolspeed, target = src)) - if(!loc || anchored) - return - user.visible_message("[user] has secured [src]'s floor casters.", \ - "You have secured [src]'s floor casters.") - anchored = TRUE - else - return ..() +/obj/structure/closet/crate/can/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + default_unfasten_wrench(user, I, 40) /obj/structure/closet/crate/radiation desc = "A crate with a radiation sign on it." diff --git a/code/game/objects/structures/curtains.dm b/code/game/objects/structures/curtains.dm index 7a3f787b91e..e2ab534923d 100644 --- a/code/game/objects/structures/curtains.dm +++ b/code/game/objects/structures/curtains.dm @@ -41,34 +41,36 @@ /obj/structure/curtain/attackby(obj/item/W, mob/user) if(istype(W, /obj/item/toy/crayon)) color = input(user, "Choose Color") as color - else if(isscrewdriver(W)) - if(anchored) - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] unscrews [src] from the floor.", "You start to unscrew [src] from the floor...", "You hear rustling noises.") - if(do_after(user, 50 * W.toolspeed, target = src)) - if(!anchored) - return - anchored = FALSE - to_chat(user, "You unscrew [src] from the floor.") - else - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] screws [src] to the floor.", "You start to screw [src] to the floor...", "You hear rustling noises.") - if(do_after(user, 50 * W.toolspeed, target = src)) - if(anchored) - return - anchored = TRUE - to_chat(user, "You screw [src] to the floor.") - else if(istype(W, /obj/item/wirecutters)) - if(!anchored) - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] cuts apart [src].", "You start to cut apart [src].", "You hear cutting.") - if(do_after(user, 50 * W.toolspeed, target = src)) - if(anchored) - return - to_chat(user, "You cut apart [src].") - deconstruct() + return + return ..() + +/obj/structure/curtain/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_start_check(user, 0)) + return + if(anchored) + user.visible_message("[user] unscrews [src] from the floor.", "You start to unscrew [src] from the floor...", "You hear rustling noises.") + if(I.use_tool(src, user, 50, volume = I.tool_volume) && anchored) + anchored = FALSE + to_chat(user, "You unscrew [src] from the floor.") else - return ..() + user.visible_message("[user] screws [src] to the floor.", "You start to screw [src] to the floor...", "You hear rustling noises.") + if(I.use_tool(src, user, 50, volume = I.tool_volume) && !anchored) + anchored = TRUE + to_chat(user, "You screw [src] to the floor.") + + + +/obj/structure/curtain/wirecutter_act(mob/user, obj/item/I) + if(anchored) + return + . = TRUE + if(!I.tool_start_check(user, 0)) + return + WIRECUTTER_ATTEMPT_DISMANTLE_MESSAGE + if(I.use_tool(src, user, 50, volume = I.tool_volume)) + WIRECUTTER_DISMANTLE_SUCCESS_MESSAGE + deconstruct() /obj/structure/curtain/deconstruct(disassembled = TRUE) new /obj/item/stack/sheet/cloth(loc, 2) diff --git a/code/game/objects/structures/depot.dm b/code/game/objects/structures/depot.dm index 79365ade192..0309db3dffb 100644 --- a/code/game/objects/structures/depot.dm +++ b/code/game/objects/structures/depot.dm @@ -37,21 +37,22 @@ if(obj_integrity <= 0 && istype(depotarea)) overload(TRUE) -/obj/structure/fusionreactor/attackby(obj/item/I, mob/user, params) - if(iswrench(I)) - playsound(loc, I.usesound, 50, 1) - to_chat(user, "The [src] is too well secured to the floor.") - return - if(isscrewdriver(I)) - to_chat(user, "You try to screwdriver open [src], but accidentally release some radiation!") - if(prob(50)) - empulse(src, 4, 10) - else - for(var/mob/living/M in range(10, loc)) - M.apply_effect(rand(5, 25), IRRADIATE) +/obj/structure/fusionreactor/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return + to_chat(user, "You try to screwdriver open [src], but accidentally release some radiation!") + if(prob(50)) + empulse(src, 4, 10) else - return ..() + for(var/mob/living/M in range(10, loc)) + M.apply_effect(rand(5, 25), IRRADIATE) + +/obj/structure/fusionreactor/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + to_chat(user, "The [src] is too well secured to the floor.") /obj/structure/fusionreactor/proc/overload(containment_failure = FALSE, skip_qdel = FALSE) if(has_overloaded) diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index 68755d0fb68..f515471acfc 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -105,31 +105,6 @@ toggle_lock(user) else to_chat(user, "Access denied.") - else if(iswelder(I) && user.a_intent == INTENT_HELP && !broken) - var/obj/item/weldingtool/WT = I - if(obj_integrity < max_integrity && WT.remove_fuel(5, user)) - to_chat(user, "You begin repairing [src].") - playsound(loc, WT.usesound, 40, 1) - if(do_after(user, 40 * WT.toolspeed, target = src)) - obj_integrity = max_integrity - playsound(loc, 'sound/items/welder2.ogg', 50, 1) - update_icon() - to_chat(user, "You repair [src].") - else - to_chat(user, "[src] is already in good condition!") - return - else if(!alert && iscrowbar(I) && openable) //Only applies to the lab cage and player made display cases - if(broken) - if(showpiece) - to_chat(user, "Remove the displayed object first.") - else - to_chat(user, "You remove the destroyed case") - qdel(src) - else - to_chat(user, "You start to [open ? "close":"open"] [src].") - if(do_after(user, 20 * I.toolspeed, target = src)) - to_chat(user, "You [open ? "close":"open"] [src].") - toggle_lock(user) else if(open && !showpiece) if(user.drop_item()) I.forceMove(src) @@ -150,6 +125,30 @@ else return ..() +/obj/structure/displaycase/crowbar_act(mob/user, obj/item/I) //Only applies to the lab cage and player made display cases + if(alert || !openable) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(broken) + if(showpiece) + to_chat(user, "Remove the displayed object first.") + if(I.use_tool(src, user, 0, volume = I.tool_volume)) + to_chat(user, "You remove the destroyed case") + qdel(src) + else + to_chat(user, "You start to [open ? "close":"open"] [src].") + if(!I.use_tool(src, user, 20, volume = I.tool_volume)) + return + to_chat(user, "You [open ? "close":"open"] [src].") + toggle_lock(user) + +obj/structure/displaycase/welder_act(mob/user, obj/item/I) + . = TRUE + if(default_welder_repair(user, I)) + broken = FALSE + /obj/structure/displaycase/proc/toggle_lock(mob/user) open = !open update_icon() @@ -180,15 +179,7 @@ var/obj/item/airlock_electronics/electronics /obj/structure/displaycase_chassis/attackby(obj/item/I, mob/user, params) - if(iswrench(I)) //The player can only deconstruct the wooden frame - to_chat(user, "You start disassembling [src]...") - playsound(src.loc, I.usesound, 50, 1) - if(do_after(user, 30 * I.toolspeed, target = src)) - playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1) - new /obj/item/stack/sheet/wood(get_turf(src), 5) - qdel(src) - - else if(istype(I, /obj/item/airlock_electronics)) + if(istype(I, /obj/item/airlock_electronics)) to_chat(user, "You start installing the electronics into [src]...") playsound(src.loc, I.usesound, 50, 1) if(do_after(user, 30, target = src)) @@ -217,6 +208,16 @@ else return ..() +/obj/structure/displaycase_chassis/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + TOOL_ATTEMPT_DISMANTLE_MESSAGE + if(!I.use_tool(src, user, 30, volume = I.tool_volume)) + return + TOOL_DISMANTLE_SUCCESS_MESSAGE + new /obj/item/stack/sheet/wood(get_turf(src), 5) + qdel(src) //The lab cage and captains display case do not spawn with electronics, which is why req_access is needed. /obj/structure/displaycase/captain diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 461f300ae4d..ee30932dabe 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -63,58 +63,6 @@ created_name = t return - else if(iswelder(W) && (mineral || glass || !anchored )) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - playsound(loc, WT.usesound, 50, 1) - if(mineral) - var/obj/item/stack/sheet/mineral/mineral_path = text2path("/obj/item/stack/sheet/mineral/[mineral]") - user.visible_message("[user] welds the [mineral] plating off the airlock assembly.", "You start to weld the [mineral] plating off the airlock assembly...") - if(do_after(user, 40 * WT.toolspeed, target = src)) - if(!src || !WT.isOn()) - return - to_chat(user, "You weld the [mineral] plating off.") - new mineral_path(loc, 2) - var/obj/structure/door_assembly/PA = new previous_assembly(loc) - transfer_assembly_vars(src, PA) - - else if(glass) - user.visible_message("[user] welds the glass panel out of the airlock assembly.", "You start to weld the glass panel out of the airlock assembly...") - if(do_after(user, 40 * WT.toolspeed, target = src)) - if(!src || !WT.isOn()) - return - to_chat(user, "You weld the glass panel out.") - if(heat_proof_finished) - new /obj/item/stack/sheet/rglass(get_turf(src)) - heat_proof_finished = FALSE - else - new /obj/item/stack/sheet/glass(get_turf(src)) - glass = FALSE - else if(!anchored) - user.visible_message("[user] disassembles the airlock assembly.", \ - "You start to disassemble the airlock assembly...") - if(do_after(user, 40 * WT.toolspeed, target = src)) - if(!src || !WT.isOn()) - return - to_chat(user, "You disassemble the airlock assembly.") - deconstruct(TRUE) - else - to_chat(user, "You need more welding fuel.") - return - - else if(iswrench(W) && state == AIRLOCK_ASSEMBLY_NEEDS_WIRES) - playsound(loc, W.usesound, 100, 1) - if(anchored) - user.visible_message("[user] unsecures the airlock assembly from the floor.", "You start to unsecure the airlock assembly from the floor...") - else - user.visible_message("[user] secures the airlock assembly to the floor.", "You start to secure the airlock assembly to the floor...") - - if(do_after(user, 40 * W.toolspeed, target = src)) - if(!src) - return - to_chat(user, "You [anchored ? "un" : ""]secure the airlock assembly.") - anchored = !anchored - else if(iscoil(W) && state == AIRLOCK_ASSEMBLY_NEEDS_WIRES && anchored) var/obj/item/stack/cable_coil/coil = W if(coil.get_amount() < 1) @@ -128,17 +76,6 @@ state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS to_chat(user, "You wire the airlock assembly.") - else if(iswirecutter(W) && state == AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS) - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] cuts the wires from the airlock assembly.", "You start to cut the wires from airlock assembly...") - - if(do_after(user, 40 * W.toolspeed, target = src)) - if(state != AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS) - return - to_chat(user, "You cut the wires from the airlock assembly.") - new/obj/item/stack/cable_coil(get_turf(user), 1) - state = AIRLOCK_ASSEMBLY_NEEDS_WIRES - else if(istype(W, /obj/item/airlock_electronics) && state == AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS && W.icon_state != "door_electronics_smoked") playsound(loc, W.usesound, 100, 1) user.visible_message("[user] installs the electronics into the airlock assembly.", "You start to install electronics into the airlock assembly...") @@ -153,24 +90,6 @@ name = "near finished airlock assembly" electronics = W - else if(iscrowbar(W) && state == AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER ) - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics from the airlock assembly...") - - if(do_after(user, 40 * W.toolspeed, target = src)) - if(state != AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER) - return - to_chat(user, "You remove the airlock electronics.") - state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS - name = "wired airlock assembly" - var/obj/item/airlock_electronics/ae - if(!electronics) - ae = new/obj/item/airlock_electronics(loc) - else - ae = electronics - electronics = null - ae.forceMove(loc) - else if(istype(W, /obj/item/stack/sheet) && (!glass || !mineral)) var/obj/item/stack/sheet/S = W if(S) @@ -210,41 +129,135 @@ to_chat(user, "You cannot add [S] to [src]!") else to_chat(user, "You cannot add [S] to [src]!") - - else if(isscrewdriver(W) && state == AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER ) - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] finishes the airlock.", \ - "You start finishing the airlock...") - - if(do_after(user, 40 * W.toolspeed, target = src)) - if(loc && state == AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER) - to_chat(user, "You finish the airlock.") - var/obj/machinery/door/airlock/door - if(glass) - door = new glass_type(loc) - else - door = new airlock_type(loc) - door.setDir(dir) - door.electronics = electronics - door.unres_sides = electronics.unres_sides - door.heat_proof = heat_proof_finished - if(electronics.one_access) - door.req_access = null - door.req_one_access = electronics.conf_access - else - door.req_access = electronics.conf_access - if(created_name) - door.name = created_name - else - door.name = base_name - door.previous_airlock = previous_assembly - electronics.forceMove(door) - qdel(src) else return ..() update_name() update_icon() +/obj/structure/door_assembly/crowbar_act(mob/user, obj/item/I) + if(state != AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER ) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + user.visible_message("[user] is removing the electronics from the airlock assembly...", "You start to remove electronics from the airlock assembly...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || state != AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER) + return + to_chat(user, "You remove the airlock electronics.") + state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS + name = "wired airlock assembly" + var/obj/item/airlock_electronics/ae + if(!electronics) + ae = new/obj/item/airlock_electronics(loc) + else + ae = electronics + electronics = null + ae.forceMove(loc) + update_icon() + update_name() + +/obj/structure/door_assembly/screwdriver_act(mob/user, obj/item/I) + if(state != AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER ) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + user.visible_message("[user] is finishing the airlock...", \ + "You start finishing the airlock...") + . = TRUE + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || state != AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER) + return + to_chat(user, "You finish the airlock.") + var/obj/machinery/door/airlock/door + if(glass) + door = new glass_type(loc) + else + door = new airlock_type(loc) + door.setDir(dir) + door.electronics = electronics + door.unres_sides = electronics.unres_sides + door.heat_proof = heat_proof_finished + if(electronics.one_access) + door.req_access = null + door.req_one_access = electronics.conf_access + else + door.req_access = electronics.conf_access + if(created_name) + door.name = created_name + else + door.name = base_name + door.previous_airlock = previous_assembly + electronics.forceMove(door) + qdel(src) + update_icon() + +/obj/structure/door_assembly/wirecutter_act(mob/user, obj/item/I) + if(state != AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + user.visible_message("[user] is cutting the wires from the airlock assembly...", "You start to cut the wires from airlock assembly...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || state != AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS) + return + to_chat(user, "You cut the wires from the airlock assembly.") + new/obj/item/stack/cable_coil(get_turf(user), 1) + state = AIRLOCK_ASSEMBLY_NEEDS_WIRES + update_icon() + +/obj/structure/door_assembly/wrench_act(mob/user, obj/item/I) + if(state != AIRLOCK_ASSEMBLY_NEEDS_WIRES) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(anchored) + user.visible_message("[user] is unsecuring the airlock assembly from the floor...", "You start to unsecure the airlock assembly from the floor...") + else + user.visible_message("[user] is securing the airlock assembly to the floor...", "You start to secure the airlock assembly to the floor...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || state != AIRLOCK_ASSEMBLY_NEEDS_WIRES) + return + to_chat(user, "You [anchored ? "un" : ""]secure the airlock assembly.") + anchored = !anchored + +/obj/structure/door_assembly/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(mineral) + var/obj/item/stack/sheet/mineral/mineral_path = text2path("/obj/item/stack/sheet/mineral/[mineral]") + visible_message("[user] welds the [mineral] plating off [src].",\ + "You start to weld the [mineral] plating off [src]...",\ + "You hear welding.") + if(!I.use_tool(src, user, 40, volume = I.tool_volume)) + return + to_chat(user, "You weld the [mineral] plating off.") + new mineral_path(loc, 2) + var/obj/structure/door_assembly/PA = new previous_assembly(loc) + transfer_assembly_vars(src, PA) + else if(glass) + visible_message("[user] welds the glass panel out of [src].",\ + "You start to weld the glass panel out of the [src]...",\ + "You hear welding.") + if(!I.use_tool(src, user, 40, volume = I.tool_volume)) + return + to_chat(user, "You weld the glass panel out.") + if(heat_proof_finished) + new /obj/item/stack/sheet/rglass(get_turf(src)) + heat_proof_finished = FALSE + else + new /obj/item/stack/sheet/glass(get_turf(src)) + glass = FALSE + else if(!anchored) + visible_message("[user] disassembles [src].", \ + "You start to disassemble [src]...",\ + "You hear welding.") + if(!I.use_tool(src, user, 40, volume = I.tool_volume)) + return + to_chat(user, "You disassemble the airlock assembly.") + deconstruct(TRUE) + update_icon() + /obj/structure/door_assembly/update_icon() overlays.Cut() if(!glass) diff --git a/code/game/objects/structures/dresser.dm b/code/game/objects/structures/dresser.dm index 1c657b9e244..f432e19b51a 100644 --- a/code/game/objects/structures/dresser.dm +++ b/code/game/objects/structures/dresser.dm @@ -53,41 +53,29 @@ add_fingerprint(H) H.update_body() -/obj/structure/dresser/attackby(obj/item/W, mob/living/user, params) - add_fingerprint(user) - user.changeNext_move(CLICK_CD_MELEE) - if(iswrench(W)) - if(anchored) - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] is loosening [src]'s bolts.", \ - "You are loosening [src]'s bolts...") - if(do_after(user, 40 * W.toolspeed, target = src)) - if(!loc || !anchored) - return - user.visible_message("[user] loosened [src]'s bolts!", \ - "You loosen [src]'s bolts!") - anchored = 0 - else - if(!isfloorturf(loc)) - user.visible_message("A floor must be present to secure [src]!") - return - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] is securing [src]'s bolts...", \ - "You are securing [src]'s bolts...") - if(do_after(user, 40 * W.toolspeed, target = src)) - if(!loc || anchored) - return - user.visible_message("[user] has secured [src]'s bolts.", \ - "You have secured [src]'s bolts.") - anchored = 1 + +/obj/structure/dresser/crowbar_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_start_check(user, 0)) return - if(iscrowbar(W) && !anchored) - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] is attempting to dismantle [src].", "You begin to dismantle [src]...") - if(do_after(user, 40 * W.toolspeed, target = src)) - deconstruct() + TOOL_ATTEMPT_DISMANTLE_MESSAGE + if(I.use_tool(src, user, 50, volume = I.tool_volume)) + TOOL_DISMANTLE_SUCCESS_MESSAGE + + +/obj/structure/dresser/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return - return ..() + if(anchored) + WRENCH_UNANCHOR_MESSAGE + anchored = FALSE + else + if(!isfloorturf(loc)) + user.visible_message("A floor must be present to secure [src]!") + return + WRENCH_ANCHOR_MESSAGE + anchored = TRUE /obj/structure/dresser/deconstruct(disassembled = TRUE) new /obj/item/stack/sheet/wood(drop_location(), 30) diff --git a/code/game/objects/structures/extinguisher.dm b/code/game/objects/structures/extinguisher.dm index 0a8be5854ab..2dc0cf415cc 100644 --- a/code/game/objects/structures/extinguisher.dm +++ b/code/game/objects/structures/extinguisher.dm @@ -77,25 +77,6 @@ playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3) opened = !opened update_icon() - else if(istype(O, /obj/item/weldingtool)) - if(has_extinguisher) - to_chat(user, "You need to remove the extinguisher before deconstructing the cabinet!") - return - if(!opened) - to_chat(user, "Open the cabinet before cutting it apart!") - return - var/obj/item/weldingtool/WT = O - if(!WT.remove_fuel(0, user)) - return - to_chat(user, "You begin cutting [src] apart...") - playsound(loc, WT.usesound, 40, 1) - if(do_after(user, 40 * WT.toolspeed, 1, target = src)) - if(!src ||!opened || !WT.isOn()) // !src to prevent it being duped - return - visible_message("[user] slices apart [src].", - "You cut [src] apart with [WT].", - "You hear welding.") - deconstruct(TRUE) else if(user.a_intent != INTENT_HARM) playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3) opened = !opened @@ -103,6 +84,20 @@ else return ..() +/obj/structure/extinguisher_cabinet/welder_act(mob/user, obj/item/I) + if(has_extinguisher) + to_chat(user, "You need to remove the extinguisher before deconstructing [src]!") + return + if(!opened) + to_chat(user, "Open the cabinet before cutting it apart!") + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_SLICING_MESSAGE + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + WELDER_SLICING_SUCCESS_MESSAGE + deconstruct(TRUE) /obj/structure/extinguisher_cabinet/attack_hand(mob/user) if(isrobot(user) || isalien(user)) diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index 113d1d12e7b..57c133388ac 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -119,16 +119,20 @@ return user.visible_message("[user] tightens some bolts on the wall.", "You tighten the bolts on the wall.") ChangeToWall() - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - dismantle(user, TRUE) else to_chat(user, "You can't reach, close it first!") if(istype(W, /obj/item/gun/energy/plasmacutter) || istype(W, /obj/item/pickaxe/drill/diamonddrill) || istype(W, /obj/item/pickaxe/drill/jackhammer) || istype(W, /obj/item/melee/energy/blade)) dismantle(user, TRUE) +/obj/structure/falsewall/welder_act(mob/user, obj/item/I) + if(!density) + return + . = TRUE + if(!I.use_tool(src, user, volume = I.tool_volume)) + return + dismantle(user, TRUE) + /obj/structure/falsewall/proc/dismantle(mob/user, disassembled = TRUE) user.visible_message("[user] dismantles the false wall.", "You dismantle the false wall.") playsound(src, 'sound/items/welder.ogg', 100, TRUE) diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 01d60f8860d..6b65d3028d9 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -9,6 +9,7 @@ max_integrity = 200 var/can_displace = TRUE //If the girder can be moved around by crowbarring it var/metalUsed = 2 //used to determine amount returned in deconstruction + var/metal_type = /obj/item/stack/sheet/metal /obj/structure/girder/examine(mob/user) . = ..() @@ -27,7 +28,7 @@ /obj/structure/girder/proc/refundMetal(metalAmount) //refunds metal used in construction when deconstructed for(var/i=0;i < metalAmount;i++) - new /obj/item/stack/sheet/metal(get_turf(src)) + new metal_type(get_turf(src)) /obj/structure/girder/temperature_expose(datum/gas_mixture/air, exposed_temperature) ..() @@ -37,62 +38,7 @@ /obj/structure/girder/attackby(obj/item/W, mob/user, params) add_fingerprint(user) - if(isscrewdriver(W)) - if(state == GIRDER_DISPLACED) - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] disassembles the girder.", \ - "You start to disassemble the girder...", "You hear clanking and banging noises.") - if(do_after(user, 40*W.toolspeed, target = src)) - if(state != GIRDER_DISPLACED) - return - state = GIRDER_DISASSEMBLED - to_chat(user, "You disassemble the girder.") - var/obj/item/stack/sheet/metal/M = new(loc, 2) - M.add_fingerprint(user) - qdel(src) - else if(state == GIRDER_REINF) - playsound(loc, W.usesound, 100, 1) - to_chat(user, "You start unsecuring support struts...") - if(do_after(user, 40*W.toolspeed, target = src)) - if(state != GIRDER_REINF) - return - to_chat(user, "You unsecure the support struts.") - state = GIRDER_REINF_STRUTS - else if(state == GIRDER_REINF_STRUTS) - playsound(loc, W.usesound, 100, 1) - to_chat(user, "You start securing support struts...") - if(do_after(user, 40*W.toolspeed, target = src)) - if(state != GIRDER_REINF_STRUTS) - return - to_chat(user, "You secure the support struts.") - state = GIRDER_REINF - - else if(iswrench(W)) - if(state == GIRDER_NORMAL) - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] disassembles the girder.", \ - "You start to disassemble the girder...", "You hear clanking and banging noises.") - if(do_after(user, 40*W.toolspeed, target = src)) - if(state != GIRDER_NORMAL) - return - state = GIRDER_DISASSEMBLED - to_chat(user, "You disassemble the girder.") - var/obj/item/stack/sheet/metal/M = new(loc, 2) - M.add_fingerprint(user) - qdel(src) - else if(state == GIRDER_DISPLACED) - if(!isfloorturf(loc)) - to_chat(user, "A floor must be present to secure the girder!") - return - playsound(loc, W.usesound, 100, 1) - to_chat(user, "You start securing the girder...") - if(do_after(user, 40*W.toolspeed, target = src)) - to_chat(user, "You secure the girder.") - var/obj/structure/girder/G = new(loc) - transfer_fingerprints_to(G) - qdel(src) - - else if(istype(W, /obj/item/gun/energy/plasmacutter)) + if(istype(W, /obj/item/gun/energy/plasmacutter)) to_chat(user, "You start slicing apart the girder...") if(do_after(user, 40 * W.toolspeed, target = src)) if(!src) @@ -113,28 +59,6 @@ refundMetal(metalUsed) qdel(src) - else if(iswirecutter(W) && state == GIRDER_REINF_STRUTS) - playsound(loc, W.usesound, 100, 1) - to_chat(user, "You start removing the inner grille...") - if(do_after(user, 40 * W.toolspeed, target = src)) - if(!src) - return - to_chat(user, "You remove the inner grille.") - new /obj/item/stack/sheet/plasteel(get_turf(src)) - var/obj/structure/girder/G = new (loc) - transfer_fingerprints_to(G) - qdel(src) - - else if(iscrowbar(W)) - if(state == GIRDER_NORMAL && can_displace) - playsound(loc, W.usesound, 100, 1) - to_chat(user, "You start dislodging the girder...") - if(do_after(user, 40*W.toolspeed, target = src)) - to_chat(user, "You dislodge the girder.") - var/obj/structure/girder/displaced/D = new (loc) - transfer_fingerprints_to(D) - qdel(src) - else if(istype(W, /obj/item/stack)) if(iswallturf(loc)) to_chat(user, "There is already a wall present!") @@ -342,6 +266,101 @@ else return ..() +/obj/structure/girder/crowbar_act(mob/user, obj/item/I) + if(!can_displace || state != GIRDER_NORMAL) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + to_chat(user, "You start dislodging the girder...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || state != GIRDER_NORMAL) + return + to_chat(user, "You dislodge the girder.") + var/obj/structure/girder/displaced/D = new (loc) + transfer_fingerprints_to(D) + qdel(src) + +/obj/structure/girder/screwdriver_act(mob/user, obj/item/I) + if(state != GIRDER_DISPLACED && state != GIRDER_REINF && state != GIRDER_REINF_STRUTS) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + switch(state) + if(GIRDER_DISPLACED) + TOOL_ATTEMPT_DISMANTLE_MESSAGE + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || state != GIRDER_DISPLACED) + return + state = GIRDER_DISASSEMBLED + TOOL_DISMANTLE_SUCCESS_MESSAGE + var/obj/item/stack/sheet/metal/M = new(loc, 2) + M.add_fingerprint(user) + qdel(src) + if(GIRDER_REINF) + to_chat(user, "You start unsecuring support struts...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || state != GIRDER_REINF) + return + to_chat(user, "You unsecure the support struts.") + state = GIRDER_REINF_STRUTS + if(GIRDER_REINF_STRUTS) + to_chat(user, "You start securing support struts...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || state != GIRDER_REINF_STRUTS) + return + to_chat(user, "You secure the support struts.") + state = GIRDER_REINF + +/obj/structure/girder/wirecutter_act(mob/user, obj/item/I) + if(state != GIRDER_REINF_STRUTS) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + to_chat(user, "You start removing the inner grille...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || state != GIRDER_REINF_STRUTS) + return + to_chat(user, "You remove the inner grille.") + new /obj/item/stack/sheet/plasteel(get_turf(src)) + var/obj/structure/girder/G = new (loc) + transfer_fingerprints_to(G) + qdel(src) + +/obj/structure/girder/wrench_act(mob/user, obj/item/I) + if(state != GIRDER_NORMAL && state != GIRDER_DISPLACED) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(state == GIRDER_NORMAL) + TOOL_ATTEMPT_DISMANTLE_MESSAGE + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || state != GIRDER_NORMAL) + return + state = GIRDER_DISASSEMBLED + TOOL_DISMANTLE_SUCCESS_MESSAGE + var/obj/item/stack/sheet/metal/M = new(loc, 2) + M.add_fingerprint(user) + qdel(src) + else + if(!isfloorturf(loc)) + to_chat(user, "A floor must be present to secure the girder!") + return + to_chat(user, "You start securing the girder...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || state != GIRDER_DISPLACED) + return + to_chat(user, "You secure the girder.") + var/obj/structure/girder/G = new(loc) + transfer_fingerprints_to(G) + qdel(src) + +/obj/structure/girder/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_SLICING_MESSAGE + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + WELDER_SLICING_SUCCESS_MESSAGE + refundMetal(metalUsed) + qdel(src) + /obj/structure/girder/CanPass(atom/movable/mover, turf/target, height=0) if(height==0) return 1 @@ -392,6 +411,7 @@ icon_state = "cultgirder" can_displace = FALSE metalUsed = 1 + metal_type = /obj/item/stack/sheet/runed_metal /obj/structure/girder/cult/New() . = ..() @@ -407,21 +427,6 @@ user.visible_message("[user] strikes [src] with [W]!", "You demolish [src].") refundMetal(metalUsed) qdel(src) - - else if(iswelder(W)) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - playsound(loc, W.usesound, 50, 1) - to_chat(user, "You start slicing apart the girder...") - if(do_after(user, 40*W.toolspeed, target = src)) - if(!WT.isOn()) - return - to_chat(user, "You slice apart the girder.") - var/obj/item/stack/sheet/runed_metal/R = new(get_turf(src)) - R.amount = 1 - transfer_fingerprints_to(R) - qdel(src) - else if(istype(W, /obj/item/gun/energy/plasmacutter)) to_chat(user, "You start slicing apart the girder...") if(do_after(user, 40* W.toolspeed, target = src)) @@ -431,7 +436,6 @@ R.amount = 1 transfer_fingerprints_to(R) qdel(src) - else if(istype(W, /obj/item/pickaxe/drill/jackhammer)) var/obj/item/pickaxe/drill/jackhammer/D = W to_chat(user, "Your jackhammer smashes through the girder!") diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index f3a4b8a241c..ae24a1a23e9 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -69,7 +69,7 @@ /obj/structure/grille/attack_animal(mob/user) . = ..() - if(!shock(user, 70)) + if(. && !QDELETED(src) && !shock(user, 70)) take_damage(rand(5,10), BRUTE, "melee", 1) /obj/structure/grille/hulk_damage() @@ -118,18 +118,7 @@ /obj/structure/grille/attackby(obj/item/W, mob/user, params) user.changeNext_move(CLICK_CD_MELEE) add_fingerprint(user) - if(iswirecutter(W)) - if(!shock(user, 100)) - playsound(loc, W.usesound, 100, 1) - deconstruct() - else if((isscrewdriver(W)) && (istype(loc, /turf/simulated) || anchored)) - if(!shock(user, 90)) - playsound(src, W.usesound, 100, 1) - anchored = !anchored - user.visible_message("[user] [anchored ? "fastens" : "unfastens"] [src].", \ - "You [anchored ? "fasten [src] to" : "unfasten [src] from"] the floor.") - return - else if(istype(W, /obj/item/stack/rods) && broken) + if(istype(W, /obj/item/stack/rods) && broken) var/obj/item/stack/rods/R = W if(!shock(user, 90)) user.visible_message("[user] rebuilds the broken grille.", \ @@ -148,6 +137,26 @@ else if(istype(W, /obj/item/shard) || !shock(user, 70)) return ..() +/obj/structure/grille/wirecutter_act(mob/user, obj/item/I) + . = TRUE + if(shock(user, 100)) + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + deconstruct() + +/obj/structure/grille/screwdriver_act(mob/user, obj/item/I) + if(!(istype(loc, /turf/simulated) || anchored)) + return + . = TRUE + if(shock(user, 90)) + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + anchored = !anchored + user.visible_message("[user] [anchored ? "fastens" : "unfastens"] [src].", \ + "You [anchored ? "fasten [src] to" : "unfasten [src] from"] the floor.") + /obj/structure/grille/proc/build_window(obj/item/stack/sheet/S, mob/user) var/dir_to_set = NORTH if(!istype(S) || !user) diff --git a/code/game/objects/structures/guillotine.dm b/code/game/objects/structures/guillotine.dm index eba923d5ea4..e5b5b6c7373 100644 --- a/code/game/objects/structures/guillotine.dm +++ b/code/game/objects/structures/guillotine.dm @@ -175,52 +175,45 @@ else to_chat(user, "You need to raise the blade in order to sharpen it!") return - if(iswrench(W)) - if(current_action) - return - - current_action = GUILLOTINE_ACTION_WRENCH - - if(do_after(user, GUILLOTINE_WRENCH_DELAY, target = src)) - current_action = 0 - if(has_buckled_mobs()) - to_chat(user, "Can't unfasten, someone's strapped in!") - return - - if(current_action) - return - to_chat(user, "You [anchored ? "un" : ""]secure [src].") - anchored = !anchored - playsound(src, 'sound/items/deconstruct.ogg', 50, 1) - dir = SOUTH - return TRUE - else - current_action = 0 - if(iswelder(W)) - var/obj/item/weldingtool/WT = W - if(!WT.remove_fuel(0, user)) - return - to_chat(user, "You begin cutting [src] apart...") - playsound(loc, WT.usesound, 40, 1) - if(do_after(user, 150 * WT.toolspeed, 1, target = src)) - if(!WT.isOn()) - return - playsound(loc, WT.usesound, 50, 1) - visible_message("[user] slices apart [src].", - "You cut [src] apart with [WT].", - "You hear welding.") - var/turf/T = get_turf(src) - if(blade_sharpness == GUILLOTINE_BLADE_MAX_SHARP) - new /obj/item/stack/sheet/plasteel(T, 3) - else - new /obj/item/stack/sheet/plasteel(T, 2) //prevents reconstructing to sharpen the guillotine without additional plasteel - new /obj/item/stack/sheet/wood(T, 20) - new /obj/item/stack/cable_coil(T, 10) - qdel(src) - return else return ..() +/obj/structure/guillotine/wrench_act(mob/user, obj/item/I) + if(current_action) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + current_action = GUILLOTINE_ACTION_WRENCH + if(!I.use_tool(src, user, GUILLOTINE_WRENCH_DELAY, volume = I.tool_volume)) + current_action = 0 + return + if(has_buckled_mobs()) + to_chat(user, "Can't unfasten, someone's strapped in!") + return + + current_action = 0 + to_chat(user, "You [anchored ? "un" : ""]secure [src].") + anchored = !anchored + playsound(src, 'sound/items/deconstruct.ogg', 50, 1) + dir = SOUTH + +/obj/structure/guillotine/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_SLICING_MESSAGE + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + WELDER_SLICING_SUCCESS_MESSAGE + var/turf/T = get_turf(src) + if(blade_sharpness == GUILLOTINE_BLADE_MAX_SHARP) + new /obj/item/stack/sheet/plasteel(T, 3) + else + new /obj/item/stack/sheet/plasteel(T, 2) //prevents reconstructing to sharpen the guillotine without additional plasteel + new /obj/item/stack/sheet/wood(T, 20) + new /obj/item/stack/cable_coil(T, 10) + qdel(src) + /obj/structure/guillotine/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE) if(!anchored) to_chat(usr, "The [src] needs to be wrenched to the floor!") diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 83da489a466..6a34c39a94d 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -45,19 +45,20 @@ desc = "Oh no, seven years of bad luck!" broken = TRUE -/obj/structure/mirror/attackby(obj/item/I, mob/living/user, params) - if(isscrewdriver(I)) - user.visible_message("[user] begins to unfasten [src].", "You begin to unfasten [src].") - if(do_after(user, 30 * I.toolspeed, target = src)) - if(broken) - user.visible_message("[user] drops the broken shards to the floor.", "You drop the broken shards on the floor.") - new /obj/item/shard(get_turf(user)) - else - user.visible_message("[user] carefully places [src] on the floor.", "You carefully place [src] on the floor.") - new /obj/item/mounted/mirror(get_turf(user)) - qdel(src) +/obj/structure/mirror/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) return - return ..() + user.visible_message("[user] begins to unfasten [src].", "You begin to unfasten [src].") + if(!I.use_tool(src, user, 30, volume = I.tool_volume)) + return + if(broken) + user.visible_message("[user] drops the broken shards to the floor.", "You drop the broken shards on the floor.") + new /obj/item/shard(get_turf(user)) + else + user.visible_message("[user] carefully places [src] on the floor.", "You carefully place [src] on the floor.") + new /obj/item/mounted/mirror(get_turf(user)) + qdel(src) /obj/structure/mirror/deconstruct(disassembled = TRUE) if(!(flags & NODECONSTRUCT)) diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm index 274645933b2..8c025b63a97 100644 --- a/code/game/objects/structures/musician.dm +++ b/code/game/objects/structures/musician.dm @@ -88,12 +88,12 @@ if(!playing || shouldStopPlaying(user)) //If the instrument is playing, or special case playing = 0 return - if(lentext(note) == 0) + if(length(note) == 0) continue var/cur_note = text2ascii(note) - 96 if(cur_note < 1 || cur_note > 7) continue - for(var/i=2 to lentext(note)) + for(var/i=2 to length(note)) var/ni = copytext(note,i,i+1) if(!text2num(ni)) if(ni == "#" || ni == "b" || ni == "n") @@ -159,11 +159,11 @@ if(!in_range(instrumentObj, usr)) return - if(lentext(t) >= 12000) + if(length(t) >= 12000) var/cont = input(usr, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no") if(cont == "no") break - while(lentext(t) > 12000) + while(length(t) > 12000) //split into lines spawn() @@ -180,7 +180,7 @@ lines.Cut(201) var/linenum = 1 for(var/l in lines) - if(lentext(l) > 200) + if(length(l) > 200) to_chat(usr, "Line [linenum] too long!") lines.Remove(l) else @@ -223,7 +223,7 @@ return if(lines.len > 200) return - if(lentext(newline) > 200) + if(length(newline) > 200) newline = copytext(newline, 1, 200) lines.Insert(num, newline) @@ -241,7 +241,7 @@ var/content = html_encode(input("Enter your line: ", instrumentObj.name, lines[num]) as text|null) if(!content || !in_range(instrumentObj, usr)) return - if(lentext(content) > 200) + if(length(content) > 200) content = copytext(content, 1, 200) if(num > lines.len || num < 1) return @@ -315,25 +315,27 @@ /obj/structure/piano/Topic(href, href_list) song.Topic(href, href_list) -/obj/structure/piano/attackby(obj/item/O as obj, mob/user as mob, params) - if(iswrench(O)) - if(!anchored && !isinspace()) - playsound(src.loc, O.usesound, 50, 1) - to_chat(user, " You begin to tighten \the [src] to the floor...") - if(do_after(user, 20 * O.toolspeed, target = src)) - user.visible_message( \ - "[user] tightens \the [src]'s casters.", \ - " You have tightened \the [src]'s casters. Now it can be played again.", \ - "You hear ratchet.") - anchored = 1 - else if(anchored) - playsound(src.loc, O.usesound, 50, 1) - to_chat(user, " You begin to loosen \the [src]'s casters...") - if(do_after(user, 40 * O.toolspeed, target = src)) - user.visible_message( \ - "[user] loosens \the [src]'s casters.", \ - " You have loosened \the [src]. Now it can be pulled somewhere else.", \ - "You hear ratchet.") - anchored = 0 +/obj/structure/piano/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(!anchored && !isinspace()) + WRENCH_ANCHOR_MESSAGE + if(!I.use_tool(src, user, 20, volume = I.tool_volume)) + return + user.visible_message( \ + "[user] tightens [src]'s casters.", \ + " You have tightened [src]'s casters. Now it can be played again.", \ + "You hear ratchet.") + anchored = TRUE + else if(anchored) + to_chat(user, " You begin to loosen [src]'s casters...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume)) + return + user.visible_message( \ + "[user] loosens [src]'s casters.", \ + " You have loosened [src]. Now it can be pulled somewhere else.", \ + "You hear ratchet.") + anchored = FALSE else - return ..() + to_chat(user, "[src] needs to be bolted to the floor!") diff --git a/code/game/objects/structures/noticeboard.dm b/code/game/objects/structures/noticeboard.dm index aa6528ee118..5938a52c1d5 100644 --- a/code/game/objects/structures/noticeboard.dm +++ b/code/game/objects/structures/noticeboard.dm @@ -78,10 +78,5 @@ if(href_list["read"]) var/obj/item/paper/P = locate(href_list["read"]) if((P && P.loc == src)) - if(!( istype(usr, /mob/living/carbon/human) )) - usr << browse("[P.name][stars(P.info)]", "window=[P.name]") - onclose(usr, "[P.name]") - else - usr << browse("[P.name][P.info]", "window=[P.name]") - onclose(usr, "[P.name]") + P.show_content(usr) return diff --git a/code/game/objects/structures/plasticflaps.dm b/code/game/objects/structures/plasticflaps.dm index 2ce0918ac16..15b3c5d6420 100644 --- a/code/game/objects/structures/plasticflaps.dm +++ b/code/game/objects/structures/plasticflaps.dm @@ -17,43 +17,37 @@ if(PLASTIC_FLAPS_DETACHED) . += "[src] are no longer screwed to the floor, and the flaps can be sliced apart." -/obj/structure/plasticflaps/attackby(obj/item/W, mob/user, params) - add_fingerprint(user) - if(isscrewdriver(W)) - if(state == PLASTIC_FLAPS_NORMAL) - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] unscrews [src] from the floor.", "You start to unscrew [src] from the floor...", "You hear rustling noises.") - if(do_after(user, 180*W.toolspeed, target = src)) - if(state != PLASTIC_FLAPS_NORMAL) - return - state = PLASTIC_FLAPS_DETACHED - anchored = FALSE - to_chat(user, "You unscrew [src] from the floor.") - else if(state == PLASTIC_FLAPS_DETACHED) - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] screws [src] to the floor.", "You start to screw [src] to the floor...", "You hear rustling noises.") - if(do_after(user, 40*W.toolspeed, target = src)) - if(state != PLASTIC_FLAPS_DETACHED) - return - state = PLASTIC_FLAPS_NORMAL - anchored = TRUE - to_chat(user, "You screw [src] to the floor.") - else if(iswelder(W)) - if(state == PLASTIC_FLAPS_DETACHED) - var/obj/item/weldingtool/WT = W - if(!WT.remove_fuel(0, user)) - return - playsound(loc, WT.usesound, 100, 1) - user.visible_message("[user] slices apart [src].", "You start to slice apart [src].", "You hear welding.") - if(do_after(user, 120*WT.toolspeed, target = src)) - if(state != PLASTIC_FLAPS_DETACHED) - return - to_chat(user, "You slice apart [src].") - var/obj/item/stack/sheet/plastic/five/P = new(loc) - P.add_fingerprint(user) - qdel(src) - else - return ..() +/obj/structure/plasticflaps/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(state == PLASTIC_FLAPS_NORMAL) + user.visible_message("[user] starts unscrewing [src] from the floor...", "You start to unscrew [src] from the floor...", "You hear rustling noises.") + if(!I.use_tool(src, user, 180, volume = I.tool_volume) || state != PLASTIC_FLAPS_NORMAL) + return + state = PLASTIC_FLAPS_DETACHED + anchored = FALSE + to_chat(user, "You unscrew [src] from the floor.") + else if(state == PLASTIC_FLAPS_DETACHED) + user.visible_message("[user] starts screwing [src] to the floor.", "You start to screw [src] to the floor...", "You hear rustling noises.") + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || state != PLASTIC_FLAPS_DETACHED) + return + state = PLASTIC_FLAPS_NORMAL + anchored = TRUE + to_chat(user, "You screw [src] to the floor.") + +/obj/structure/plasticflaps/welder_act(mob/user, obj/item/I) + if(state != PLASTIC_FLAPS_DETACHED) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_SLICING_MESSAGE + if(I.use_tool(src, user, 120, volume = I.tool_volume)) + WELDER_SLICING_SUCCESS_MESSAGE + var/obj/item/stack/sheet/plastic/five/P = new(drop_location()) + P.add_fingerprint(user) + qdel(src) /obj/structure/plasticflaps/CanPass(atom/A, turf/T) if(istype(A) && A.checkpass(PASSGLASS)) diff --git a/code/game/objects/structures/reflector.dm b/code/game/objects/structures/reflector.dm index e3ebb0579a4..5620422cc45 100644 --- a/code/game/objects/structures/reflector.dm +++ b/code/game/objects/structures/reflector.dm @@ -12,9 +12,9 @@ /obj/structure/reflector/bullet_act(obj/item/projectile/P) var/turf/reflector_turf = get_turf(src) var/turf/reflect_turf - var/new_dir = get_reflection(dir, P.dir) if(!istype(P, /obj/item/projectile/beam)) return ..() + var/new_dir = get_reflection(dir, P.dir) if(new_dir) reflect_turf = get_step(reflect_turf, new_dir) else @@ -30,48 +30,15 @@ P.current = reflector_turf P.yo = reflect_turf.y - reflector_turf.y P.xo = reflect_turf.x - reflector_turf.x + P.ignore_source_check = TRUE //If shot by a laser, will now hit the mob that fired it + var/reflect_angle = dir2angle(new_dir) + P.setAngle(reflect_angle) + new_dir = 0 return -1 /obj/structure/reflector/attackby(obj/item/W, mob/user, params) - if(iswrench(W)) - if(anchored) - to_chat(user, "Unweld [src] first!") - return - playsound(user, 'sound/items/Ratchet.ogg', 50, 1) - to_chat(user, "You begin to dismantle [src].") - if(do_after(user, 80, target = src)) - playsound(user, 'sound/items/Ratchet.ogg', 50, 1) - to_chat(user, "You dismantle [src].") - new /obj/item/stack/sheet/metal(src.loc, 5) - qdel(src) - return - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(!anchored) - if(WT.remove_fuel(0,user)) - playsound(user, 'sound/items/Welder2.ogg', 50, 1) - user.visible_message("[user.name] starts to weld [src.name] to the floor.", \ - "You start to weld [src] to the floor...", \ - "You hear welding.") - if(do_after(user,20, target = src)) - if(!src || !WT.isOn()) - return - anchored = 1 - to_chat(user, "You weld [src] to the floor.") - else - if(WT.remove_fuel(0,user)) - playsound(user, 'sound/items/Welder2.ogg', 50, 1) - user.visible_message("[user] starts to cut [src] free from the floor.", \ - "You start to cut [src] free from the floor...", \ - "You hear welding.") - if(do_after(user,20, target = src)) - if(!src || !WT.isOn()) - return - anchored = 0 - to_chat(user, "You cut [src] free from the floor.") - return //Finishing the frame if(istype(W,/obj/item/stack/sheet)) if(finished) @@ -101,6 +68,38 @@ return return ..() +/obj/structure/reflector/wrench_act(mob/user, obj/item/I) + . = TRUE + if(anchored) + to_chat(user, "Unweld [src] first!") + return + if(!I.tool_use_check(user, 0)) + return + TOOL_ATTEMPT_DISMANTLE_MESSAGE + if(!I.use_tool(src, user, 80, volume = I.tool_volume)) + return + playsound(user, 'sound/items/Ratchet.ogg', 50, 1) + TOOL_DISMANTLE_SUCCESS_MESSAGE + new /obj/item/stack/sheet/metal(src.loc, 5) + qdel(src) + +/obj/structure/reflector/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(anchored) + WELDER_ATTEMPT_FLOOR_SLICE_MESSAGE + if(!I.use_tool(src, user, 20, volume = I.tool_volume)) + return + WELDER_FLOOR_SLICE_SUCCESS_MESSAGE + anchored = FALSE + else + WELDER_ATTEMPT_FLOOR_WELD_MESSAGE + if(!I.use_tool(src, user, 20, volume = I.tool_volume)) + return + WELDER_FLOOR_WELD_SUCCESS_MESSAGE + anchored = TRUE + /obj/structure/reflector/proc/get_reflection(srcdir,pdir) return 0 diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm index 707d30dbcfa..930dcc0995c 100644 --- a/code/game/objects/structures/signs.dm +++ b/code/game/objects/structures/signs.dm @@ -17,19 +17,22 @@ if(BURN) playsound(loc, 'sound/items/welder.ogg', 80, TRUE) -/obj/structure/sign/attackby(obj/item/tool as obj, mob/user as mob) //deconstruction - if(istype(tool, /obj/item/screwdriver) && !istype(src, /obj/structure/sign/double)) - to_chat(user, "You unfasten the sign with your [tool].") - var/obj/item/sign/S = new(src.loc) - S.name = name - S.desc = desc - S.icon_state = icon_state - //var/icon/I = icon('icons/obj/decals.dmi', icon_state) - //S.icon = I.Scale(24, 24) - S.sign_state = icon_state - qdel(src) - else - return ..() +/obj/structure/sign/screwdriver_act(mob/user, obj/item/I) + if(istype(src, /obj/structure/sign/double)) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + to_chat(user, "You unfasten the sign with [I].") + var/obj/item/sign/S = new(src.loc) + S.name = name + S.desc = desc + S.icon_state = icon_state + //var/icon/I = icon('icons/obj/decals.dmi', icon_state) + //S.icon = I.Scale(24, 24) + S.sign_state = icon_state + qdel(src) + /obj/item/sign name = "sign" diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm index 6af52d6999b..0d6166b928e 100644 --- a/code/game/objects/structures/statues.dm +++ b/code/game/objects/structures/statues.dm @@ -25,23 +25,21 @@ "You slice apart the [name].") deconstruct(TRUE) return - - else if(iswelder(W)) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - playsound(loc, W.usesound, 40, 1) - user.visible_message("[user] is slicing apart the [name].", \ - "You are slicing apart the [name]...") - if(do_after(user, 40 * W.toolspeed, target = src)) - if(!loc) - return - playsound(loc, W.usesound, 50, 1) - user.visible_message("[user] slices apart the [name].", \ - "You slice apart the [name]!") - deconstruct(TRUE) - return return ..() + +/obj/structure/statue/welder_act(mob/user, obj/item/I) + if(anchored) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_SLICING_MESSAGE + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + WELDER_SLICING_SUCCESS_MESSAGE + deconstruct(TRUE) + + /obj/structure/statue/attack_hand(mob/living/user) user.changeNext_move(CLICK_CD_MELEE) add_fingerprint(user) @@ -139,6 +137,18 @@ return return ..() +/obj/structure/statue/plasma/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, volume = I.tool_volume)) + return + user.visible_message("[user] sets [src] on fire!",\ + "[src] disintegrates into a cloud of plasma!",\ + "You hear a 'whoompf' and a roar.") + message_admins("[key_name_admin(user)] ignited a plasma statue at [COORD(loc)]") + log_game("[key_name(user)] ignited plasma a statue at [COORD(loc)]") + investigate_log("[key_name(user)] ignited a plasma statue at [COORD(loc)]", "atmos") + ignite(2500) + /obj/structure/statue/plasma/proc/PlasmaBurn() atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, 160) deconstruct(FALSE) diff --git a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm index f8c65089324..6a2180efcac 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm @@ -8,6 +8,7 @@ max_integrity = 120 var/image/nest_overlay comfort = 0 + flags = NODECONSTRUCT /obj/structure/bed/nest/New() nest_overlay = image('icons/mob/alien.dmi', "nestoverlay", layer=MOB_LAYER - 0.2) diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index 23802cf56a5..b823cc1b623 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -40,12 +40,14 @@ /obj/structure/bed/proc/handle_rotation() return -/obj/structure/bed/attackby(obj/item/W, mob/user, params) - if(iswrench(W) && !(flags & NODECONSTRUCT)) - playsound(loc, W.usesound, 50, TRUE) - deconstruct(TRUE) - else - return ..() +/obj/structure/bed/wrench_act(mob/user, obj/item/I) + . = TRUE + if(flags & NODECONSTRUCT) + to_chat(user, "You can't figure out how to deconstruct [src]!") + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + deconstruct(TRUE) /obj/structure/bed/deconstruct(disassembled = TRUE) if(!(flags & NODECONSTRUCT)) diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm index 0e9b7b3a6ae..90b489300d3 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -54,12 +54,17 @@ SK.master = E qdel(src) return - if(iswrench(W) && !(flags & NODECONSTRUCT)) - playsound(loc, W.usesound, 50, 1) - deconstruct(TRUE) - return return ..() +/obj/structure/chair/wrench_act(mob/user, obj/item/I) + . = TRUE + if(flags & NODECONSTRUCT) + to_chat(user, "Try as you might, you can't figure out how to deconstruct [src].") + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + deconstruct(TRUE) + /obj/structure/chair/deconstruct() // If we have materials, and don't have the NOCONSTRUCT flag if(buildstacktype && (!(flags & NODECONSTRUCT))) diff --git a/code/game/objects/structures/table_frames.dm b/code/game/objects/structures/table_frames.dm index fe2ee995413..575f666848a 100644 --- a/code/game/objects/structures/table_frames.dm +++ b/code/game/objects/structures/table_frames.dm @@ -22,13 +22,7 @@ var/framestackamount = 2 /obj/structure/table_frame/attackby(obj/item/I, mob/user, params) - if(iswrench(I)) - to_chat(user, "You start disassembling [src]...") - playsound(loc, I.usesound, 50, 1) - if(do_after(user, 30*I.toolspeed, target = src)) - playsound(loc, 'sound/items/deconstruct.ogg', 50, 1) - deconstruct(TRUE) - else if(istype(I, /obj/item/stack/sheet/plasteel)) + if(istype(I, /obj/item/stack/sheet/plasteel)) var/obj/item/stack/sheet/plasteel/P = I if(P.get_amount() < 1) to_chat(user, "You need one plasteel sheet to do this!") @@ -71,6 +65,17 @@ else return ..() +/obj/structure/table_frame/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + TOOL_ATTEMPT_DISMANTLE_MESSAGE + if(I.use_tool(src, user, 30, volume = I.tool_volume)) + TOOL_DISMANTLE_SUCCESS_MESSAGE + for(var/i = 1, i <= framestackamount, i++) + new framestack(get_turf(src)) + qdel(src) + /obj/structure/table_frame/proc/make_new_table(table_type) //makes sure the new table made retains what we had as a frame var/obj/structure/table/T = new table_type(loc) T.frame = type diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index c8c148ac1e1..1f7fd24d803 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -212,21 +212,6 @@ if(istype(I, /obj/item/grab)) tablepush(I, user) return - if(!(flags & NODECONSTRUCT)) - if(isscrewdriver(I) && deconstruction_ready) - to_chat(user, "You start disassembling [src]...") - playsound(loc, I.usesound, 50, 1) - if(do_after(user, 20*I.toolspeed, target = src)) - deconstruct(TRUE) - return - - if(iswrench(I) && deconstruction_ready) - to_chat(user, "You start deconstructing [src]...") - playsound(loc, I.usesound, 50, 1) - if(do_after(user, 40*I.toolspeed, target = src)) - playsound(loc, 'sound/items/deconstruct.ogg', 50, 1) - deconstruct(TRUE, 1) - return if(isrobot(user)) return @@ -245,6 +230,33 @@ else return ..() + +/obj/structure/table/screwdriver_act(mob/user, obj/item/I) + if(flags & NODECONSTRUCT) + return + if(!deconstruction_ready) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + TOOL_ATTEMPT_DISMANTLE_MESSAGE + if(I.use_tool(src, user, 20, volume = I.tool_volume) && deconstruction_ready) + deconstruct(TRUE) + TOOL_DISMANTLE_SUCCESS_MESSAGE + +/obj/structure/table/wrench_act(mob/user, obj/item/I) + if(flags & NODECONSTRUCT) + return + if(!deconstruction_ready) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + TOOL_ATTEMPT_DISMANTLE_MESSAGE + if(I.use_tool(src, user, 40, volume = I.tool_volume) && deconstruction_ready) + deconstruct(TRUE, 1) + TOOL_DISMANTLE_SUCCESS_MESSAGE + /obj/structure/table/deconstruct(disassembled = TRUE, wrench_disassembly = 0) if(!(flags & NODECONSTRUCT)) var/turf/T = get_turf(src) @@ -524,27 +536,14 @@ else return ..() -/obj/structure/table/reinforced/attackby(obj/item/W, mob/user, params) - if(iswelder(W)) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - playsound(loc, W.usesound, 50, 1) - if(deconstruction_ready) - to_chat(user, "You start strengthening the reinforced table...") - if (do_after(user, 50*W.toolspeed, target = src)) - if(!src || !WT.isOn()) - return - to_chat(user, "You strengthen the table.") - deconstruction_ready = FALSE - else - to_chat(user, "You start weakening the reinforced table...") - if (do_after(user, 50*W.toolspeed, target = src)) - if(!src || !WT.isOn()) - return - to_chat(user, "You weaken the table.") - deconstruction_ready = TRUE - else - return ..() +/obj/structure/table/reinforced/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + to_chat(user, "You start [deconstruction_ready ? "strengthening" : "weakening"] the reinforced table...") + if(I.use_tool(src, user, 50, volume = I.tool_volume)) + to_chat(user, "You [deconstruction_ready ? "strengthen" : "weaken"] the table.") + deconstruction_ready = !deconstruction_ready /obj/structure/table/reinforced/brass name = "brass table" @@ -682,10 +681,6 @@ step(O, get_dir(O, src)) /obj/structure/rack/attackby(obj/item/W, mob/user, params) - if(iswrench(W) && !(flags & NODECONSTRUCT) && user.a_intent != INTENT_HELP) - playsound(loc, W.usesound, 50, 1) - deconstruct(TRUE) - return if(isrobot(user)) return if(user.a_intent == INTENT_HARM) @@ -695,6 +690,15 @@ W.Move(loc) return +/obj/structure/rack/wrench_act(mob/user, obj/item/I) + . = TRUE + if(flags & NODECONSTRUCT) + to_chat(user, "Try as you might, you can't figure out how to deconstruct this.") + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + deconstruct(TRUE) + /obj/structure/rack/attack_hand(mob/living/user) if(user.IsWeakened() || user.resting || user.lying) return @@ -750,12 +754,12 @@ materials = list(MAT_METAL=2000) var/building = FALSE -/obj/item/rack_parts/attackby(obj/item/W, mob/user, params) - if(iswrench(W)) - new /obj/item/stack/sheet/metal(user.loc) - qdel(src) - else - return ..() +/obj/item/rack_parts/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + new /obj/item/stack/sheet/metal(user.loc) + qdel(src) /obj/item/rack_parts/attack_self(mob/user) if(building) diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index d518d86c777..32c9daf3c76 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -63,54 +63,6 @@ layer = FLY_LAYER /obj/structure/toilet/attackby(obj/item/I, mob/living/user, params) - if(iswrench(I)) - var/choices = list() - if(cistern) - choices += "Stash" - if(anchored) - choices += "Disconnect" - else - choices += "Connect" - choices += "Rotate" - - var/response = input(user, "What do you want to do?", "[src]") as null|anything in choices - if(!Adjacent(user) || !response) //moved away or cancelled - return - switch(response) - if("Stash") - stash_goods(I, user) - if("Disconnect") - user.visible_message("[user] starts disconnecting [src].", "You begin disconnecting [src]...") - if(do_after(user, 40 * I.toolspeed, target = src)) - if(!loc || !anchored) - return - user.visible_message("[user] disconnects [src]!", "You disconnect [src]!") - anchored = 0 - update_icon() - if("Connect") - user.visible_message("[user] starts connecting [src].", "You begin connecting [src]...") - if(do_after(user, 40 * I.toolspeed, target = src)) - if(!loc || anchored) - return - user.visible_message("[user] connects [src]!", "You connect [src]!") - anchored = 1 - update_icon() - if("Rotate") - var/list/dir_choices = list("North" = NORTH, "East" = EAST, "South" = SOUTH, "West" = WEST) - var/selected = input(user,"Select a direction for the connector.", "Connector Direction") in dir_choices - dir = dir_choices[selected] - update_icon() //is this necessary? probably not - return - - if(istype(I, /obj/item/crowbar)) - to_chat(user, "You start to [cistern ? "replace the lid on the cistern" : "lift the lid off the cistern"]...") - playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 50, 1) - if(do_after(user, 30 * I.toolspeed, target = src)) - user.visible_message("[user] [cistern ? "replaces the lid on the cistern" : "lifts the lid off the cistern"]!", "You [cistern ? "replace the lid on the cistern" : "lift the lid off the cistern"]!", "You hear grinding porcelain.") - cistern = !cistern - update_icon() - return - if(istype(I, /obj/item/reagent_containers)) if(!open) return @@ -158,6 +110,58 @@ stash_goods(I, user) return + +/obj/structure/toilet/crowbar_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + to_chat(user, "You start to [cistern ? "replace the lid on the cistern" : "lift the lid off the cistern"]...") + playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 50, 1) + if(I.use_tool(src, user, 30, volume = I.tool_volume)) + user.visible_message("[user] [cistern ? "replaces the lid on the cistern" : "lifts the lid off the cistern"]!", "You [cistern ? "replace the lid on the cistern" : "lift the lid off the cistern"]!", "You hear grinding porcelain.") + cistern = !cistern + update_icon() + return + +/obj/structure/toilet/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + var/choices = list() + if(cistern) + choices += "Stash" + if(anchored) + choices += "Disconnect" + else + choices += "Connect" + choices += "Rotate" + + var/response = input(user, "What do you want to do?", "[src]") as null|anything in choices + if(!Adjacent(user) || !response) //moved away or cancelled + return + switch(response) + if("Stash") + stash_goods(I, user) + if("Disconnect") + user.visible_message("[user] starts disconnecting [src].", "You begin disconnecting [src]...") + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + if(!loc || !anchored) + return + user.visible_message("[user] disconnects [src]!", "You disconnect [src]!") + anchored = 0 + if("Connect") + user.visible_message("[user] starts connecting [src].", "You begin connecting [src]...") + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + if(!loc || anchored) + return + user.visible_message("[user] connects [src]!", "You connect [src]!") + anchored = 1 + if("Rotate") + var/list/dir_choices = list("North" = NORTH, "East" = EAST, "South" = SOUTH, "West" = WEST) + var/selected = input(user,"Select a direction for the connector.", "Connector Direction") in dir_choices + dir = dir_choices[selected] + update_icon() //is this necessary? probably not + /obj/structure/toilet/proc/stash_goods(obj/item/I, mob/user) if(!I) return @@ -196,27 +200,6 @@ /obj/structure/urinal/attackby(obj/item/I, mob/user, params) - if(iswrench(I)) - if(anchored) - user.visible_message("[user] begins disconnecting [src]...", "You begin to disconnect [src]...") - if(do_after(user, 40 * I.toolspeed, target = src)) - if(!loc || !anchored) - return - user.visible_message("[user] disconnects [src]!", "You disconnect [src]!") - anchored = 0 - pixel_x = 0 - pixel_y = 0 - else - user.visible_message("[user] begins connecting [src]...", "You begin to connect [src]...") - if(do_after(user, 40 * I.toolspeed, target = src)) - if(!loc || anchored) - return - user.visible_message("[user] connects [src]!", "You connect [src]!") - anchored = 1 - pixel_x = 0 - pixel_y = 32 - return - if(istype(I, /obj/item/grab)) var/obj/item/grab/G = I if(!G.confirm()) @@ -234,7 +217,28 @@ else to_chat(user, "You need a tighter grip!") - +/obj/structure/urinal/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(anchored) + user.visible_message("[user] begins disconnecting [src]...", "You begin to disconnect [src]...") + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + if(!loc || !anchored) + return + user.visible_message("[user] disconnects [src]!", "You disconnect [src]!") + anchored = 0 + pixel_x = 0 + pixel_y = 0 + else + user.visible_message("[user] begins connecting [src]...", "You begin to connect [src]...") + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + if(!loc || anchored) + return + user.visible_message("[user] connects [src]!", "You connect [src]!") + anchored = 1 + pixel_x = 0 + pixel_y = 32 /obj/machinery/shower name = "shower" @@ -298,41 +302,41 @@ /obj/machinery/shower/attackby(obj/item/I as obj, mob/user as mob, params) if(I.type == /obj/item/analyzer) to_chat(user, "The water temperature seems to be [watertemp].") - if(iswrench(I)) - to_chat(user, "You begin to adjust the temperature valve with the [I].") - if(do_after(user, 50 * I.toolspeed, target = src)) - switch(watertemp) - if("normal") - watertemp = "freezing" - if("freezing") - watertemp = "boiling" - if("boiling") - watertemp = "normal" - user.visible_message("[user] adjusts the shower with the [I].", "You adjust the shower with the [I].") - update_icon() //letsa update whenever we change the temperature, since the mist might need to change - if(iswelder(I)) - if(on) - to_chat(user, "Turn [src] off before you attempt to cut it loose.") - return - var/obj/item/weldingtool/WT = I - if(WT.isOn()) - user.visible_message("[user] begins to cut [src] loose.", "You begin to cut [src] loose.") - if(do_after(user, 40 * WT.toolspeed, target = src)) - if(!src || !WT.remove_fuel(0, user)) - return - if(on) //in case someone turned it back on while you were working, make sure we shut that all down - on = 0 - if(mymist) - qdel(mymist) - ismist = 0 - user.visible_message("[user] cuts [src] loose!", "You cut [src] loose!") - var/obj/item/mounted/shower/S = new /obj/item/mounted/shower(get_turf(user)) - transfer_prints_to(S, TRUE) - qdel(src) - else - to_chat(user, "[WT] must be on for this task.") if(on) I.water_act(100, convertHeat(), src) + return ..() + +/obj/machinery/shower/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + to_chat(user, "You begin to adjust the temperature valve with the [I].") + if(I.use_tool(src, user, 50, volume = I.tool_volume)) + switch(watertemp) + if("normal") + watertemp = "freezing" + if("freezing") + watertemp = "boiling" + if("boiling") + watertemp = "normal" + user.visible_message("[user] adjusts the shower with the [I].", "You adjust [src] to [watertemp].") + update_icon() //letsa update whenever we change the temperature, since the mist might need to change + +/obj/machinery/shower/welder_act(mob/user, obj/item/I) + . = TRUE + if(on) + to_chat(user, "Turn [src] off before you attempt to cut it loose.") + return + if(!I.tool_use_check(user, 0)) + return + visible_message("[user] begins slicing [src] free...", "You begin slicing [src] free...", "You hear welding.") + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + if(mymist) + qdel(mymist) + user.visible_message("[user] cuts [src] loose!", "You cut [src] loose!") + var/obj/item/mounted/shower/S = new /obj/item/mounted/shower(get_turf(user)) + transfer_prints_to(S, TRUE) + qdel(src) /obj/machinery/shower/update_icon() //this makes the shower mist up or clear mist (depending on water temperature) overlays.Cut() //once it's been on for a while, in addition to handling the water overlay. @@ -577,53 +581,6 @@ if(!(istype(O))) return - if(iswrench(O)) - var/obj/item/wrench/W = O - - var/choices = list() - if(anchored) - choices += "Wash" - if(can_move) - choices += "Disconnect" - else - choices += "Connect" - if(can_rotate) - choices += "Rotate" - - var/response = input(user, "What do you want to do?", "[src]") as null|anything in choices - if(!Adjacent(user) || !response) //moved away or cancelled - return - switch(response) - if("Wash") - busy = 1 - var/wateract = 0 - wateract = (W.wash(user, src)) - busy = 0 - if(wateract) - W.water_act(20, COLD_WATER_TEMPERATURE, src) - if("Disconnect") - user.visible_message("[user] starts disconnecting [src].", "You begin disconnecting [src]...") - if(do_after(user, 40 * O.toolspeed, target = src)) - if(!loc || !anchored) - return - user.visible_message("[user] disconnects [src]!", "You disconnect [src]!") - anchored = 0 - update_icon() - if("Connect") - user.visible_message("[user] starts connecting [src].", "You begin connecting [src]...") - if(do_after(user, 40 * O.toolspeed, target = src)) - if(!loc || anchored) - return - user.visible_message("[user] connects [src]!", "You connect [src]!") - anchored = 1 - update_icon() - if("Rotate") - var/list/dir_choices = list("North" = NORTH, "East" = EAST, "South" = SOUTH, "West" = WEST) - var/selected = input(user, "Select a direction for the connector.", "Connector Direction") in dir_choices - dir = dir_choices[selected] - update_icon() //is this necessary? probably not - return - if(!anchored) to_chat(user, "[src] isn't connected, wrench it into position first!") return @@ -635,6 +592,51 @@ if(wateract) O.water_act(20, COLD_WATER_TEMPERATURE, src) +/obj/structure/sink/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + var/choices = list() + if(anchored) + choices += "Wash" + if(can_move) + choices += "Disconnect" + else + choices += "Connect" + if(can_rotate) + choices += "Rotate" + + var/response = input(user, "What do you want to do?", "[src]") as null|anything in choices + if(!Adjacent(user) || !response) //moved away or cancelled + return + switch(response) + if("Wash") + busy = 1 + var/wateract = 0 + wateract = (I.wash(user, src)) + busy = 0 + if(wateract) + I.water_act(20, COLD_WATER_TEMPERATURE, src) + if("Disconnect") + user.visible_message("[user] starts disconnecting [src].", "You begin disconnecting [src]...") + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + if(!loc || !anchored) + return + user.visible_message("[user] disconnects [src]!", "You disconnect [src]!") + anchored = FALSE + if("Connect") + user.visible_message("[user] starts connecting [src].", "You begin connecting [src]...") + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + if(!loc || anchored) + return + user.visible_message("[user] connects [src]!", "You connect [src]!") + anchored = TRUE + if("Rotate") + var/list/dir_choices = list("North" = NORTH, "East" = EAST, "South" = SOUTH, "West" = WEST) + var/selected = input(user, "Select a direction for the connector.", "Connector Direction") in dir_choices + dir = dir_choices[selected] + update_icon() //is this necessary? probably not + /obj/structure/sink/update_icon() ..() layer = OBJ_LAYER diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm index 0eee91ee068..3a1546bdd2b 100644 --- a/code/game/objects/structures/windoor_assembly.dm +++ b/code/game/objects/structures/windoor_assembly.dm @@ -1,4 +1,4 @@ -/* Windoor (window door) assembly -Nodrak +/* Windoor (window door) assembly -Nodrak //I hope you step on a plug * Step 1: Create a windoor out of rglass * Step 2: Add plasteel to the assembly to make a secure windoor (Optional) * Step 3: Rotate or Flip the assembly to face and open the way you want @@ -84,70 +84,13 @@ obj/structure/windoor_assembly/Destroy() else return 1 - /obj/structure/windoor_assembly/attackby(obj/item/W, mob/user, params) //I really should have spread this out across more states but thin little windoors are hard to sprite. add_fingerprint(user) switch(state) if("01") - if(iswelder(W) && !anchored) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - user.visible_message("[user] disassembles the windoor assembly.", "You start to disassemble the windoor assembly...") - playsound(loc, 'sound/items/welder2.ogg', 50, 1) - - if(do_after(user, 40 * WT.toolspeed, target = src)) - if(!src || !WT.isOn()) - return - to_chat(user, "You disassemble the windoor assembly.") - var/obj/item/stack/sheet/rglass/RG = new (get_turf(src), 5) - RG.add_fingerprint(user) - if(secure) - var/obj/item/stack/rods/R = new (get_turf(src), 4) - R.add_fingerprint(user) - qdel(src) - return - - //Wrenching an unsecure assembly anchors it in place. Step 4 complete - if(iswrench(W) && !anchored) - for(var/obj/machinery/door/window/WD in loc) - if(WD.dir == dir) - to_chat(user, "There is already a windoor in that location!") - return - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] secures the windoor assembly to the floor.", "You start to secure the windoor assembly to the floor...") - - if(do_after(user, 40 * W.toolspeed, target = src)) - if(!src || anchored) - return - for(var/obj/machinery/door/window/WD in loc) - if(WD.dir == dir) - to_chat(user, "There is already a windoor in that location!") - return - to_chat(user, "You secure the windoor assembly.") - anchored = TRUE - if(secure) - name = "secure anchored windoor assembly" - else - name = "anchored windoor assembly" - - //Unwrenching an unsecure assembly un-anchors it. Step 4 undone - else if(iswrench(W) && anchored) - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] unsecures the windoor assembly from the floor.", "You start to unsecure the windoor assembly from the floor...") - - if(do_after(user, 40 * W.toolspeed, target = src)) - if(!src || !anchored) - return - to_chat(user, "You unsecure the windoor assembly.") - anchored = FALSE - if(secure) - name = "secure windoor assembly" - else - name = "windoor assembly" - //Adding plasteel makes the assembly a secure windoor assembly. Step 2 (optional) complete. - else if(istype(W, /obj/item/stack/sheet/plasteel) && !secure) + if(istype(W, /obj/item/stack/sheet/plasteel) && !secure) var/obj/item/stack/sheet/plasteel/P = W if(P.get_amount() < 2) to_chat(user, "You need more plasteel to do this!") @@ -187,26 +130,8 @@ obj/structure/windoor_assembly/Destroy() return ..() if("02") - - //Removing wire from the assembly. Step 5 undone. - if(iswirecutter(W)) - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] cuts the wires from the airlock assembly.", "You start to cut the wires from airlock assembly...") - - if(do_after(user, 40 * W.toolspeed, target = src)) - if(!src || state != "02") - return - - to_chat(user, "You cut the windoor wires.") - new/obj/item/stack/cable_coil(get_turf(user), 1) - state = "01" - if(secure) - name = "secure anchored windoor assembly" - else - name = "anchored windoor assembly" - //Adding airlock electronics for access. Step 6 complete. - else if(istype(W, /obj/item/airlock_electronics)) + if(istype(W, /obj/item/airlock_electronics)) playsound(loc, W.usesound, 100, 1) user.visible_message("[user] installs the electronics into the airlock assembly.", "You start to install electronics into the airlock assembly...") user.drop_item() @@ -222,24 +147,6 @@ obj/structure/windoor_assembly/Destroy() else W.forceMove(loc) - //Screwdriver to remove airlock electronics. Step 6 undone. - else if(isscrewdriver(W)) - if(!electronics) - return - - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to uninstall electronics from the airlock assembly...") - - if(do_after(user, 40 * W.toolspeed, target = src)) - if(!src || !electronics) - return - to_chat(user, "You remove the airlock electronics.") - name = "wired windoor assembly" - var/obj/item/airlock_electronics/ae - ae = electronics - electronics = null - ae.forceMove(loc) - else if(istype(W, /obj/item/pen)) var/t = stripped_input(user, "Enter the name for the door.", name, created_name,MAX_NAME_LEN) if(!t) @@ -248,65 +155,153 @@ obj/structure/windoor_assembly/Destroy() return created_name = t return - - - - //Crowbar to complete the assembly, Step 7 complete. - else if(iscrowbar(W)) - if(!electronics) - to_chat(usr, "The assembly is missing electronics!") - return - usr << browse(null, "window=windoor_access") - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] pries the windoor into the frame.", "You start prying the windoor into the frame...") - - if(do_after(user, 40 * W.toolspeed, target = src)) - - if(loc && electronics) - for(var/obj/machinery/door/window/WD in loc) - if(WD.dir == dir) - return - - density = TRUE //Shouldn't matter but just incase - to_chat(user, "You finish the windoor.") - var/obj/machinery/door/window/windoor - if(secure) - windoor = new /obj/machinery/door/window/brigdoor(src.loc) - if(facing == "l") - windoor.icon_state = "leftsecureopen" - windoor.base_state = "leftsecure" - else - windoor.icon_state = "rightsecureopen" - windoor.base_state = "rightsecure" - else - windoor = new /obj/machinery/door/window(loc) - if(facing == "l") - windoor.icon_state = "leftopen" - windoor.base_state = "left" - else - windoor.icon_state = "rightopen" - windoor.base_state = "right" - windoor.setDir(dir) - windoor.density = FALSE - - if(electronics.one_access) - windoor.req_one_access = electronics.conf_access - else - windoor.req_access = electronics.conf_access - windoor.electronics = src.electronics - electronics.forceMove(windoor) - electronics = null - if(created_name) - windoor.name = created_name - qdel(src) - windoor.close() - else return ..() //Update to reflect changes(if applicable) update_icon() +/obj/structure/windoor_assembly/crowbar_act(mob/user, obj/item/I) //Crowbar to complete the assembly, Step 7 complete. + if(state != "02") + return + . = TRUE + if(!electronics) + to_chat(user, "[src] is missing electronics!") + return + if(!I.tool_use_check(user, 0)) + return + user << browse(null, "window=windoor_access") + user.visible_message("[user] pries the windoor into the frame.", "You start prying the windoor into the frame...") + + if(!I.use_tool(src, user, 40, volume = I.tool_volume)) + return + if(loc && electronics) + for(var/obj/machinery/door/window/WD in loc) + if(WD.dir == dir) + return + + density = TRUE //Shouldn't matter but just incase + to_chat(user, "You finish the windoor.") + var/obj/machinery/door/window/windoor + if(secure) + windoor = new /obj/machinery/door/window/brigdoor(src.loc) + if(facing == "l") + windoor.icon_state = "leftsecureopen" + windoor.base_state = "leftsecure" + else + windoor.icon_state = "rightsecureopen" + windoor.base_state = "rightsecure" + else + windoor = new /obj/machinery/door/window(loc) + if(facing == "l") + windoor.icon_state = "leftopen" + windoor.base_state = "left" + else + windoor.icon_state = "rightopen" + windoor.base_state = "right" + windoor.setDir(dir) + windoor.density = FALSE + + if(electronics.one_access) + windoor.req_one_access = electronics.conf_access + else + windoor.req_access = electronics.conf_access + windoor.electronics = src.electronics + electronics.forceMove(windoor) + electronics = null + if(created_name) + windoor.name = created_name + qdel(src) + windoor.close() + +/obj/structure/windoor_assembly/screwdriver_act(mob/user, obj/item/I) + if(state != "02" || electronics) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to uninstall electronics from the airlock assembly...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || electronics) + return + to_chat(user, "You remove the airlock electronics.") + name = "wired windoor assembly" + var/obj/item/airlock_electronics/ae + ae = electronics + electronics = null + ae.forceMove(loc) + +/obj/structure/windoor_assembly/wirecutter_act(mob/user, obj/item/I) + if(state != "02") + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + user.visible_message("[user] cuts the wires from the airlock assembly.", "You start to cut the wires from airlock assembly...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || state != "02") + return + to_chat(user, "You cut the windoor wires.") + new/obj/item/stack/cable_coil(get_turf(user), 1) + state = "01" + if(secure) + name = "secure anchored windoor assembly" + else + name = "anchored windoor assembly" + update_icon() + +/obj/structure/windoor_assembly/wrench_act(mob/user, obj/item/I) + if(state != "01") + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(!anchored) //Wrenching an unsecure assembly anchors it in place. Step 4 complete + for(var/obj/machinery/door/window/WD in loc) + if(WD.dir == dir) + to_chat(user, "There is already a windoor in that location!") + return + user.visible_message("[user] secures the windoor assembly to the floor.", "You start to secure the windoor assembly to the floor...") + + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || anchored || state != "01") + return + for(var/obj/machinery/door/window/WD in loc) + if(WD.dir == dir) + to_chat(user, "There is already a windoor in that location!") + return + to_chat(user, "You secure the windoor assembly.") + anchored = TRUE + if(secure) + name = "secure anchored windoor assembly" + else + name = "anchored windoor assembly" + + else //Unwrenching an unsecure assembly un-anchors it. Step 4 undone + user.visible_message("[user] unsecures the windoor assembly from the floor.", "You start to unsecure the windoor assembly from the floor...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || !anchored || state != "01") + return + to_chat(user, "You unsecure the windoor assembly.") + anchored = FALSE + if(secure) + name = "secure windoor assembly" + else + name = "windoor assembly" + update_icon() + +/obj/structure/windoor_assembly/welder_act(mob/user, obj/item/I) + if(state != "01") + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_SLICING_MESSAGE + if(I.use_tool(src, user, 40, volume = I.tool_volume) && state == "01") + WELDER_FLOOR_SLICE_SUCCESS_MESSAGE + var/obj/item/stack/sheet/rglass/RG = new (get_turf(src), 5) + RG.add_fingerprint(user) + if(secure) + var/obj/item/stack/rods/R = new (get_turf(src), 4) + R.add_fingerprint(user) + qdel(src) + //Rotates the windoor assembly clockwise /obj/structure/windoor_assembly/verb/revrotate() diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 553f2c476e7..90d20ecbd75 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -212,22 +212,6 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f return 1 //skip the afterattack add_fingerprint(user) - - if(iswelder(I) && user.a_intent == INTENT_HELP) - var/obj/item/weldingtool/WT = I - if(obj_integrity < max_integrity) - if(WT.remove_fuel(0,user)) - to_chat(user, "You begin repairing [src]...") - playsound(src, WT.usesound, 40, 1) - if(do_after(user, 40*I.toolspeed, target = src)) - obj_integrity = max_integrity - playsound(src, 'sound/items/welder2.ogg', 50, 1) - update_nearby_icons() - to_chat(user, "You repair [src].") - else - to_chat(user, "[src] is already in good condition!") - return - if(istype(I, /obj/item/grab) && get_dist(src, user) < 2) var/obj/item/grab/G = I if(isliving(G.affecting)) @@ -256,51 +240,87 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f M.apply_damage(30) take_damage(75) return - - if(!(flags & NODECONSTRUCT)) - if(isscrewdriver(I)) - playsound(src, I.usesound, 75, 1) - if(reinf) - if(state == WINDOW_SCREWED_TO_FRAME || state == WINDOW_IN_FRAME) - to_chat(user, "You begin to [state == WINDOW_SCREWED_TO_FRAME ? "unscrew the window from":"screw the window to"] the frame...") - if(do_after(user, decon_speed*I.toolspeed, target = src, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored))) - state = (state == WINDOW_IN_FRAME ? WINDOW_SCREWED_TO_FRAME : WINDOW_IN_FRAME) - to_chat(user, "You [state == WINDOW_IN_FRAME ? "unfasten the window from":"fasten the window to"] the frame.") - else if(state == WINDOW_OUT_OF_FRAME) - to_chat(user, "You begin to [anchored ? "unscrew the frame from":"screw the frame to"] the floor...") - if(do_after(user, decon_speed*I.toolspeed, target = src, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored))) - anchored = !anchored - update_nearby_icons() - to_chat(user, "You [anchored ? "fasten the frame to":"unfasten the frame from"] the floor.") - else //if we're not reinforced, we don't need to check or update state - to_chat(user, "You begin to [anchored ? "unscrew the window from":"screw the window to"] the floor...") - if(do_after(user, decon_speed*I.toolspeed, target = src, extra_checks = CALLBACK(src, .proc/check_anchored, anchored))) - anchored = !anchored - air_update_turf(TRUE) - update_nearby_icons() - to_chat(user, "You [anchored ? "fasten the window to":"unfasten the window from"] the floor.") - return - - else if(iscrowbar(I) && reinf && (state == WINDOW_OUT_OF_FRAME || state == WINDOW_IN_FRAME)) - to_chat(user, "You begin to lever the window [state == WINDOW_OUT_OF_FRAME ? "into":"out of"] the frame...") - playsound(src, I.usesound, 75, 1) - if(do_after(user, decon_speed*I.toolspeed, target = src, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored))) - state = (state == WINDOW_OUT_OF_FRAME ? WINDOW_IN_FRAME : WINDOW_OUT_OF_FRAME) - to_chat(user, "You pry the window [state == WINDOW_IN_FRAME ? "into":"out of"] the frame.") - return - - else if(iswrench(I) && !anchored) - playsound(src, I.usesound, 75, 1) - to_chat(user, " You begin to disassemble [src]...") - if(do_after(user, decon_speed*I.toolspeed, target = src, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored))) - var/obj/item/stack/sheet/G = new glass_type(user.loc, glass_amount) - G.add_fingerprint(user) - playsound(src, 'sound/items/deconstruct.ogg', 50, 1) - to_chat(user, "You successfully disassemble [src].") - qdel(src) - return return ..() + +/obj/structure/window/crowbar_act(mob/user, obj/item/I) + if(!reinf) + return + if(state != WINDOW_OUT_OF_FRAME && state != WINDOW_IN_FRAME) + return + if(flags & NODECONSTRUCT) + return + . = TRUE + if(!can_be_reached(user)) + return + to_chat(user, "You begin to lever the window [state == WINDOW_OUT_OF_FRAME ? "into":"out of"] the frame...") + if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored))) + return + state = (state == WINDOW_OUT_OF_FRAME ? WINDOW_IN_FRAME : WINDOW_OUT_OF_FRAME) + to_chat(user, "You pry the window [state == WINDOW_IN_FRAME ? "into":"out of"] the frame.") + +/obj/structure/window/screwdriver_act(mob/user, obj/item/I) + if(flags & NODECONSTRUCT) + return + . = TRUE + if(!can_be_reached(user)) + return + if(reinf) + if(state == WINDOW_SCREWED_TO_FRAME || state == WINDOW_IN_FRAME) + to_chat(user, "You begin to [state == WINDOW_SCREWED_TO_FRAME ? "unscrew the window from":"screw the window to"] the frame...") + if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored))) + return + state = (state == WINDOW_IN_FRAME ? WINDOW_SCREWED_TO_FRAME : WINDOW_IN_FRAME) + to_chat(user, "You [state == WINDOW_IN_FRAME ? "unfasten the window from":"fasten the window to"] the frame.") + else if(state == WINDOW_OUT_OF_FRAME) + to_chat(user, "You begin to [anchored ? "unscrew the frame from":"screw the frame to"] the floor...") + if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored))) + return + anchored = !anchored + update_nearby_icons() + to_chat(user, "You [anchored ? "fasten the frame to":"unfasten the frame from"] the floor.") + else //if we're not reinforced, we don't need to check or update state + to_chat(user, "You begin to [anchored ? "unscrew the window from":"screw the window to"] the floor...") + if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_anchored, anchored))) + return + anchored = !anchored + air_update_turf(TRUE) + update_nearby_icons() + to_chat(user, "You [anchored ? "fasten the window to":"unfasten the window from"] the floor.") + +/obj/structure/window/wrench_act(mob/user, obj/item/I) + if(flags & NODECONSTRUCT) + return + if(anchored) + return + . = TRUE + if(!can_be_reached(user)) + return + TOOL_ATTEMPT_DISMANTLE_MESSAGE + if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored))) + return + var/obj/item/stack/sheet/G = new glass_type(user.loc, glass_amount) + G.add_fingerprint(user) + playsound(src, 'sound/items/deconstruct.ogg', 50, 1) + to_chat(user, "You successfully disassemble [src].") + qdel(src) + +/obj/structure/window/welder_act(mob/user, obj/item/I) + if(user.a_intent != INTENT_HELP) + return + . = TRUE + if(!can_be_reached(user)) + return + if(obj_integrity >= max_integrity) + to_chat(user, "[src] is already in good condition!") + return + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_REPAIR_MESSAGE + if(I.use_tool(src, user, 40, volume = I.tool_volume)) + obj_integrity = max_integrity + WELDER_REPAIR_SUCCESS_MESSAGE + /obj/structure/window/proc/check_state(checked_state) if(state == checked_state) return TRUE diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 2124d9c49ea..cfa5f43858e 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -30,6 +30,7 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3"," var/obj/item/stack/tile/builtin_tile = null //needed for performance reasons when the singularity rips off floor tiles var/list/broken_states = list("damaged1", "damaged2", "damaged3", "damaged4", "damaged5") var/list/burnt_states = list("floorscorched1", "floorscorched2") + var/list/prying_tool_list = list(TOOL_CROWBAR) //What tool/s can we use to pry up the tile? /turf/simulated/floor/New() ..() @@ -144,10 +145,6 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3"," if(..()) return TRUE - if(intact && iscrowbar(C)) - pry_tile(C, user) - return TRUE - if(intact && istype(C, /obj/item/stack/tile)) try_replace_tile(C, user, params) @@ -178,21 +175,28 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3"," return TRUE return FALSE +/turf/simulated/floor/crowbar_act(mob/user, obj/item/I) + if(!intact) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + pry_tile(I, user, TRUE) + /turf/simulated/floor/proc/try_replace_tile(obj/item/stack/tile/T, mob/user, params) if(T.turf_type == type) return - var/obj/item/crowbar/CB - if(iscrowbar(user.get_inactive_hand())) - CB = user.get_inactive_hand() - if(!CB) + var/obj/item/thing = user.get_inactive_hand() + if(!prying_tool_list.Find(thing.tool_behaviour)) return - var/turf/simulated/floor/plating/P = pry_tile(CB, user, TRUE) + var/turf/simulated/floor/plating/P = pry_tile(thing, user, TRUE) if(!istype(P)) return P.attackby(T, user, params) /turf/simulated/floor/proc/pry_tile(obj/item/C, mob/user, silent = FALSE) - playsound(src, C.usesound, 80, 1) + if(!silent) + playsound(src, C.usesound, 80, 1) return remove_tile(user, silent) /turf/simulated/floor/proc/remove_tile(mob/user, silent = FALSE, make_tile = TRUE) diff --git a/code/game/turfs/simulated/floor/asteroid.dm b/code/game/turfs/simulated/floor/asteroid.dm index 049f5ff8509..eccc5805657 100644 --- a/code/game/turfs/simulated/floor/asteroid.dm +++ b/code/game/turfs/simulated/floor/asteroid.dm @@ -100,6 +100,9 @@ ChangeTurf(Z.turf_type, keep_icon = FALSE) playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) +/turf/simulated/floor/plating/asteroid/welder_act(mob/user, obj/item/I) + return + /turf/simulated/floor/plating/asteroid/basalt name = "volcanic floor" baseturf = /turf/simulated/floor/plating/asteroid/basalt diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm index 2ce85481751..3ab424e69cc 100644 --- a/code/game/turfs/simulated/floor/fancy_floor.dm +++ b/code/game/turfs/simulated/floor/fancy_floor.dm @@ -1,6 +1,7 @@ /turf/simulated/floor/wood icon_state = "wood" floor_tile = /obj/item/stack/tile/wood + prying_tool_list = list(TOOL_SCREWDRIVER) broken_states = list("wood-broken", "wood-broken2", "wood-broken3", "wood-broken4", "wood-broken5", "wood-broken6", "wood-broken7") footstep_sounds = list( @@ -8,49 +9,34 @@ "xeno" = list('sound/effects/footstep/wood_all.ogg') //@RonaldVanWonderen of Freesound.org ) -/turf/simulated/floor/wood/attackby(obj/item/C, mob/user, params) - if(..()) - return - if(isscrewdriver(C)) - pry_tile(C, user) +/turf/simulated/floor/wood/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return + remove_tile(user, FALSE, TRUE) -/turf/simulated/floor/wood/try_replace_tile(obj/item/stack/tile/T, mob/user, params) - if(T.turf_type == type) +/turf/simulated/floor/wood/crowbar_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return - var/obj/item/tool - if(isscrewdriver(user.get_inactive_hand())) - tool = user.get_inactive_hand() - if(!tool && iscrowbar(user.get_inactive_hand())) - tool = user.get_inactive_hand() - if(!tool) - return - var/turf/simulated/floor/plating/P = pry_tile(tool, user, TRUE) - if(!istype(P)) - return - P.attackby(T, user, params) - -/turf/simulated/floor/wood/pry_tile(obj/item/C, mob/user, silent = FALSE) - var/is_screwdriver = isscrewdriver(C) - playsound(src, C.usesound, 80, 1) - return remove_tile(user, silent, make_tile = is_screwdriver) + remove_tile(user, FALSE, FALSE) /turf/simulated/floor/wood/remove_tile(mob/user, silent = FALSE, make_tile = TRUE) if(broken || burnt) broken = 0 burnt = 0 if(user && !silent) - to_chat(user, "You remove the broken planks.") + to_chat(user, "You remove the broken planks.") else if(make_tile) if(user && !silent) - to_chat(user, "You unscrew the planks.") + to_chat(user, "You unscrew the planks.") if(builtin_tile) builtin_tile.forceMove(src) builtin_tile = null else if(user && !silent) - to_chat(user, "You forcefully pry off the planks, destroying them in the process.") + to_chat(user, "You forcefully pry off the planks, destroying them in the process.") return make_plating() /turf/simulated/floor/wood/cold @@ -64,15 +50,12 @@ floor_tile = /obj/item/stack/tile/grass broken_states = list("sand") -/turf/simulated/floor/grass/New() +/turf/simulated/floor/grass/Initialize() + update_icon() ..() - spawn(1) - update_icon() /turf/simulated/floor/grass/update_icon() - ..() - if(!(icon_state in list("grass1", "grass2", "grass3", "grass4", "sand"))) - icon_state = "grass[pick("1","2","3","4")]" + icon_state = "grass[pick("1","2","3","4")]" /turf/simulated/floor/grass/attackby(obj/item/C, mob/user, params) if(..()) diff --git a/code/game/turfs/simulated/floor/lava.dm b/code/game/turfs/simulated/floor/lava.dm index 22b056568de..5a512b5455f 100644 --- a/code/game/turfs/simulated/floor/lava.dm +++ b/code/game/turfs/simulated/floor/lava.dm @@ -113,6 +113,9 @@ /turf/simulated/floor/plating/lava/attackby(obj/item/C, mob/user, params) //Lava isn't a good foundation to build on return +/turf/simulated/floor/plating/lava/welder_act() + return + /turf/simulated/floor/plating/lava/break_tile() return diff --git a/code/game/turfs/simulated/floor/light_floor.dm b/code/game/turfs/simulated/floor/light_floor.dm index dab0ecff341..332cf745a4c 100644 --- a/code/game/turfs/simulated/floor/light_floor.dm +++ b/code/game/turfs/simulated/floor/light_floor.dm @@ -76,8 +76,6 @@ update_icon() /turf/simulated/floor/light/attackby(obj/item/C, mob/user, params) - if(..()) - return if(istype(C,/obj/item/light/bulb)) //only for light tiles if(istype(builtin_tile, /obj/item/stack/tile/light)) if(!state) @@ -87,19 +85,24 @@ to_chat(user, "You replace the light bulb.") else to_chat(user, "The light bulb seems fine, no need to replace it.") - if(ismultitool(C)) - if(!can_modify_colour) - return - if(state != 0) - if(state < LIGHTFLOOR_PURPLE) - state++ - else - state = LIGHTFLOOR_ON - to_chat(user, "You change \the [src]'s light bulb color.") - update_icon() - else - to_chat(user, "\The [src]'s light bulb appears to have burned out.") + else + return ..() +/turf/simulated/floor/light/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!can_modify_colour) + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(state != 0) + if(state < LIGHTFLOOR_PURPLE) + state++ + else + state = LIGHTFLOOR_ON + to_chat(user, "You change [src]'s light bulb color.") + update_icon() + else + to_chat(user, "[src]'s light bulb appears to have burned out.") //Cycles through all of the colours /turf/simulated/floor/light/colour_cycle diff --git a/code/game/turfs/simulated/floor/mineral.dm b/code/game/turfs/simulated/floor/mineral.dm index 9031a0a350c..1d52c9274c3 100644 --- a/code/game/turfs/simulated/floor/mineral.dm +++ b/code/game/turfs/simulated/floor/mineral.dm @@ -46,6 +46,16 @@ return ..() +/turf/simulated/floor/mineral/plasma/welder_act(mob/user, obj/item/I) + if(I.use_tool(src, user, volume = I.tool_volume)) + user.visible_message("[user] sets [src] on fire!",\ + "[src] disintegrates into a cloud of plasma!",\ + "You hear a 'whoompf' and a roar.") + ignite(2500) //Big enough to ignite + message_admins("Plasma wall ignited by [key_name_admin(user)] in ([x], [y], [z] - JMP)",0,1) + log_game("Plasma wall ignited by [key_name(user)] in ([x], [y], [z])") + investigate_log("was ignited by [key_name(user)]","atmos") + /turf/simulated/floor/mineral/plasma/proc/PlasmaBurn() make_plating() atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, 20) diff --git a/code/game/turfs/simulated/floor/misc_floor.dm b/code/game/turfs/simulated/floor/misc_floor.dm index a29eab05a3b..ee7c1bcbb30 100644 --- a/code/game/turfs/simulated/floor/misc_floor.dm +++ b/code/game/turfs/simulated/floor/misc_floor.dm @@ -155,17 +155,15 @@ for(var/obj/structure/lattice/L in src) L.ratvar_act() -/turf/simulated/floor/clockwork/attackby(obj/item/I, mob/living/user, params) - if(iscrowbar(I)) - user.visible_message("[user] begins slowly prying up [src]...", "You begin painstakingly prying up [src]...") - playsound(src, I.usesound, 20, 1) - if(!do_after(user, 70 * I.toolspeed, target = src)) - return 0 - user.visible_message("[user] pries up [src]!", "You pry up [src]!") - playsound(src, I.usesound, 80, 1) - make_plating() - return 1 - return ..() +/turf/simulated/floor/clockwork/crowbar_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + user.visible_message("[user] begins slowly prying up [src]...", "You begin painstakingly prying up [src]...") + if(!I.use_tool(src, user, 70, volume = I.tool_volume)) + return + user.visible_message("[user] pries up [src]!", "You pry up [src]!") + make_plating() /turf/simulated/floor/clockwork/make_plating() if(!dropped_brass) diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index e5b41154dbf..85b03d3378d 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -72,40 +72,37 @@ to_chat(user, "This section is too damaged to support a tile! Use a welder to fix the damage.") return TRUE - else if(isscrewdriver(C)) - var/obj/item/screwdriver/screwdriver = C - to_chat(user, "You start [unfastened ? "fastening" : "unfastening"] [src].") - playsound(src, screwdriver.usesound, 50, 1) - if(do_after(user, 20 * screwdriver.toolspeed, target = src) && screwdriver) - to_chat(user, "You [unfastened ? "fasten" : "unfasten"] [src].") - unfastened = !unfastened - return TRUE +/turf/simulated/floor/plating/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + to_chat(user, "You start [unfastened ? "fastening" : "unfastening"] [src].") + . = TRUE + if(!I.use_tool(src, user, 20, volume = I.tool_volume)) + return + to_chat(user, "You [unfastened ? "fasten" : "unfasten"] [src].") + unfastened = !unfastened - else if(iswelder(C)) - var/obj/item/weldingtool/welder = C - if(welder.isOn()) - if(!welder.remove_fuel(0, user)) - to_chat(user, "You need more welding fuel to complete this task.") - return TRUE - - if(broken || burnt) - to_chat(user, "You fix some dents on the broken plating.") - playsound(src, welder.usesound, 80, 1) - overlays -= current_overlay - current_overlay = null - burnt = FALSE - broken = FALSE - update_icon() - if(unfastened) - to_chat(user, "You start removing [src] exposing space after you're done!") - playsound(src, welder.usesound, 100, 1) - if(do_after(user, 50 * welder.toolspeed, target = src) && welder && welder.isOn()) - to_chat(user, "You remove [src].") - new /obj/item/stack/tile/plasteel(get_turf(src)) - remove_plating(user) - return TRUE - - return TRUE +/turf/simulated/floor/plating/welder_act(mob/user, obj/item/I) + if(!broken && !burnt && !unfastened) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(unfastened) + to_chat(user, "You start removing [src], exposing space after you're done!") + if(!I.use_tool(src, user, 50, volume = I.tool_volume * 2)) //extra loud to let people know something's going down + return + new /obj/item/stack/tile/plasteel(get_turf(src)) + remove_plating(user) + return + if(I.use_tool(src, user, volume = I.tool_volume)) //If we got this far, something needs fixing + to_chat(user, "You fix some dents on the broken plating.") + overlays -= current_overlay + current_overlay = null + burnt = FALSE + broken = FALSE + update_icon() /turf/simulated/floor/plating/proc/remove_plating(mob/user) if(baseturf == /turf/space) diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm index c4f0e93dbd6..118132765a1 100644 --- a/code/game/turfs/simulated/minerals.dm +++ b/code/game/turfs/simulated/minerals.dm @@ -8,7 +8,6 @@ smooth = SMOOTH_MORE | SMOOTH_BORDER canSmoothWith = null baseturf = /turf/simulated/floor/plating/asteroid/airless - temperature = 2.7 opacity = 1 density = TRUE blocks_air = TRUE diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 75709978b86..7dd41815a4c 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -25,6 +25,7 @@ thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT heat_capacity = 312500 //a little over 5 cm thick , 312500 for 1 m by 2.5 m by 0.25 m plasteel wall + var/can_dismantle_with_welder = TRUE var/hardness = 40 //lower numbers are harder. Used to determine the probability of a hulk smashing through. var/slicing_duration = 100 var/engraving //engraving on the wall @@ -249,7 +250,7 @@ var/turf/simulated/floor/F = src F.burn_tile() - F.icon_state = "wall_thermite" + F.icon_state = "plating" if(user) to_chat(user, "The thermite starts melting through the wall.") @@ -326,54 +327,61 @@ return ..() -/turf/simulated/wall/proc/try_rot(obj/item/I, mob/user, params) - if(iswelder(I)) - var/obj/item/weldingtool/WT = I - if(WT.remove_fuel(0, user)) - to_chat(user, "You burn away the fungi with [WT].") - playsound(src, WT.usesound, 10, 1) +/turf/simulated/wall/welder_act(mob/user, obj/item/I) + . = TRUE + if(thermite && I.use_tool(src, user, volume = I.tool_volume)) + thermitemelt(user) + return + if(rotting) + if(I.use_tool(src, user, volume = I.tool_volume)) for(var/obj/effect/overlay/wall_rot/WR in src) qdel(WR) - rotting = 0 - return TRUE - else if((!is_sharp(I) && I.force >= 10) || I.force >= 20) + rotting = FALSE + to_chat(user, "You burn off the fungi with [I].") + return + + if(!I.tool_use_check(user, 0)) //Wall repair stuff + return + + var/time_required = slicing_duration + var/intention + if(can_dismantle_with_welder) + intention = "Dismantle" + if(damage || LAZYLEN(dent_decals)) + intention = "Repair" + if(can_dismantle_with_welder) + var/moved_away = user.loc + intention = alert(user, "Would you like to repair or dismantle [src]?", "[src]", "Repair", "Dismantle") + if(user.loc != moved_away) + to_chat(user, "Stay still while doing this!") + return + if(intention == "Repair") + time_required = max(5, damage / 5) + if(!intention) + return + if(intention == "Dismantle") + WELDER_ATTEMPT_SLICING_MESSAGE + else + WELDER_ATTEMPT_REPAIR_MESSAGE + if(I.use_tool(src, user, time_required, volume = I.tool_volume)) + if(intention == "Dismantle") + WELDER_SLICING_SUCCESS_MESSAGE + dismantle_wall() + else + WELDER_REPAIR_SUCCESS_MESSAGE + cut_overlay(dent_decals) + dent_decals?.Cut() + take_damage(-damage) + +/turf/simulated/wall/proc/try_rot(obj/item/I, mob/user, params) + if((!is_sharp(I) && I.force >= 10) || I.force >= 20) to_chat(user, "[src] crumbles away under the force of your [I.name].") dismantle_wall(1) return TRUE return FALSE /turf/simulated/wall/proc/try_decon(obj/item/I, mob/user, params) - if(iswelder(I)) - var/obj/item/weldingtool/WT = I - if(!WT.remove_fuel(0, user)) - to_chat(user, "You need more welding fuel to complete this task.") - return TRUE // this means "don't continue trying to find alternative uses in attackby", not "decon succeeded" - - var/response = "Dismantle" - if(damage || LAZYLEN(dent_decals)) - response = alert(user, "Would you like to repair or dismantle [src]?", "[src]", "Repair", "Dismantle") - - switch(response) - if("Repair") - to_chat(user, "You start repairing the damage to [src].") - playsound(src, WT.usesound, 100, 1) - if(do_after(user, max(5, damage / 5) * WT.toolspeed, target = src) && WT && WT.isOn()) - to_chat(user, "You finish repairing the damage to [src].") - cut_overlay(dent_decals) - dent_decals?.Cut() - take_damage(-damage) - else - to_chat(user, "You begin slicing through the outer plating.") - playsound(src, WT.usesound, 100, 1) - - if(do_after(user, slicing_duration * WT.toolspeed, target = src) && WT && WT.isOn()) - to_chat(user, "You remove the outer plating.") - dismantle_wall() - else - to_chat(user, "You stop slicing through [src].") - return TRUE - - else if(istype(I, /obj/item/gun/energy/plasmacutter)) + if(istype(I, /obj/item/gun/energy/plasmacutter)) to_chat(user, "You begin slicing through the outer plating.") playsound(src, I.usesound, 100, 1) diff --git a/code/game/turfs/simulated/walls_indestructible.dm b/code/game/turfs/simulated/walls_indestructible.dm index a5cfa4956ac..9b522e34640 100644 --- a/code/game/turfs/simulated/walls_indestructible.dm +++ b/code/game/turfs/simulated/walls_indestructible.dm @@ -6,6 +6,9 @@ /turf/simulated/wall/indestructible/take_damage(dam) return +/turf/simulated/wall/indestructible/welder_act() + return + /turf/simulated/wall/indestructible/ex_act(severity) return diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm index 4ab20600b1a..78bfa26fef6 100644 --- a/code/game/turfs/simulated/walls_mineral.dm +++ b/code/game/turfs/simulated/walls_mineral.dm @@ -101,6 +101,16 @@ return ..() +/turf/simulated/wall/mineral/plasma/welder_act(mob/user, obj/item/I) + if(I.tool_enabled) + ignite(2500) //The number's big enough + user.visible_message("[user] sets [src] on fire!",\ + "[src] disintegrates into a cloud of plasma!",\ + "You hear a 'whoompf' and a roar.") + message_admins("Plasma wall ignited by [key_name_admin(user)] in ([x], [y], [z] - JMP)",0,1) + log_game("Plasma wall ignited by [key_name(user)] in ([x], [y], [z])") + investigate_log("was ignited by [key_name(user)]","atmos") + /turf/simulated/wall/mineral/plasma/proc/PlasmaBurn(temperature) new girder_type(src) ChangeTurf(/turf/simulated/floor) diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm index ce3d7f1a258..4c211291ae0 100644 --- a/code/game/turfs/simulated/walls_reinforced.dm +++ b/code/game/turfs/simulated/walls_reinforced.dm @@ -12,6 +12,8 @@ sheet_type = /obj/item/stack/sheet/plasteel sheet_amount = 1 girder_type = /obj/structure/girder/reinforced + can_dismantle_with_welder = FALSE + var/d_state = RWALL_INTACT var/can_be_reinforced = 1 @@ -34,50 +36,48 @@ . += "The support rods have been sliced through, and the outer sheath is connected loosely to the girder." /turf/simulated/wall/r_wall/attackby(obj/item/I, mob/user, params) - if(try_repair(I, user, params)) + if(d_state == RWALL_COVER && istype(I, /obj/item/gun/energy/plasmacutter)) + to_chat(user, "You begin slicing through the metal cover...") + if(I.use_tool(src, user, 40, volume = I.tool_volume) && d_state == RWALL_COVER) + d_state = RWALL_CUT_COVER + update_icon() + to_chat(user, "You press firmly on the cover, dislodging it.") return - return ..() - -/turf/simulated/wall/r_wall/proc/try_repair(obj/item/I, mob/user, params) - if((damage || LAZYLEN(dent_decals)) && iswelder(I)) - var/obj/item/weldingtool/WT = I - if(!WT.remove_fuel(0, user)) - to_chat(user, "You need more welding fuel to complete this task.") - return TRUE - - to_chat(user, "You start repairing the damage to [src].") - playsound(src, WT.usesound, 100, 1) - if(do_after(user, max(5, damage / 5) * WT.toolspeed, target = src) && WT && WT.isOn()) - to_chat(user, "You finish repairing the damage to [src].") - cut_overlay(dent_decals) - dent_decals?.Cut() - take_damage(-damage) - return TRUE - - if(d_state) + else if(RWALL_SUPPORT_RODS && istype(I, /obj/item/gun/energy/plasmacutter)) + to_chat(user, "You begin slicing through the support rods...") + if(I.use_tool(src, user, 70, volume = I.tool_volume) && d_state == RWALL_SUPPORT_RODS) + d_state = RWALL_SHEATH + update_icon() + return + else if(d_state == RWALL_SUPPORT_LINES && istype(I, /obj/item/stack/rods)) + var/obj/item/stack/S = I + if(S.use(1)) + d_state = RWALL_INTACT + update_icon() + to_chat(user, "You replace the outer grille.") + else + to_chat(user, "You don't have enough rods for that!") + return + else if(d_state) // Repairing if(istype(I, /obj/item/stack/sheet/metal)) var/obj/item/stack/sheet/metal/MS = I - to_chat(user, "You begin patching-up the wall with [MS]...") if(do_after(user, max(20 * d_state, 100) * MS.toolspeed, target = src) && d_state) if(!MS.use(1)) to_chat(user, "You don't have enough [MS.name] for that!") - return TRUE - + return d_state = RWALL_INTACT update_icon() queue_smooth_neighbors(src) to_chat(user, "You repair the last of the damage.") - - return TRUE + return else if(istype(I, /obj/item/stack/sheet/plasteel)) var/obj/item/stack/sheet/plasteel/PS = I if(!can_be_reinforced) to_chat(user, "The wall is already coated!") - return FALSE - + return to_chat(user, "You begin adding an additional layer of coating to the wall with [PS]...") if(do_after(user, 40 * PS.toolspeed, target = src) && !d_state) if(!PS.use(2)) @@ -88,185 +88,116 @@ update_icon() queue_smooth_neighbors(src) can_be_reinforced = FALSE + return + else + return ..() + +/turf/simulated/wall/r_wall/welder_act(mob/user, obj/item/I) + if(thermite && I.use_tool(src, user, volume = I.tool_volume)) + thermitemelt(user) return TRUE - return FALSE + if(!(d_state in list(RWALL_COVER, RWALL_SUPPORT_RODS, RWALL_CUT_COVER))) + return ..() + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(d_state == RWALL_COVER) + to_chat(user, "You begin slicing through the metal cover...") + if(I.use_tool(src, user, 60, volume = I.tool_volume) && d_state == RWALL_COVER) + d_state = RWALL_CUT_COVER + to_chat(user, "You press firmly on the cover, dislodging it.") + else if(d_state == RWALL_SUPPORT_RODS) + to_chat(user, "You begin slicing through the support rods...") + if(I.use_tool(src, user, 100, volume = I.tool_volume) && d_state == RWALL_SUPPORT_RODS) + d_state = RWALL_SHEATH + else if(d_state == RWALL_CUT_COVER) + to_chat(user, "You begin welding the metal cover back to the frame...") + if(I.use_tool(src, user, 60, volume = I.tool_volume) && d_state == RWALL_CUT_COVER) + to_chat(user, "The metal cover has been welded securely to the frame.") + d_state = RWALL_COVER + update_icon() - -/turf/simulated/wall/r_wall/try_decon(obj/item/I, mob/user, params) +/turf/simulated/wall/r_wall/crowbar_act(mob/user, obj/item/I) + if(!(d_state in list(RWALL_CUT_COVER, RWALL_SHEATH, RWALL_BOLTS))) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return switch(d_state) - if(RWALL_INTACT) - // RWALL_INTACT > RWALL_SUPPORT_LINES - if(iswirecutter(I)) - playsound(src, I.usesound, 100, 1) - d_state = RWALL_SUPPORT_LINES - update_icon() - new /obj/item/stack/rods(src) - to_chat(user, "You cut the outer grille.") - return TRUE - - if(RWALL_SUPPORT_LINES) - // RWALL_SUPPORT_LINES > RWALL_COVER - if(isscrewdriver(I)) - to_chat(user, "You begin unsecuring the support lines...") - playsound(src, I.usesound, 100, 1) - - if(do_after(user, 40 * I.toolspeed, target = src) && d_state == RWALL_SUPPORT_LINES) - d_state = RWALL_COVER - update_icon() - to_chat(user, "You unsecure the support lines.") - return TRUE - - // RWALL_INTACT < RWALL_SUPPORT_LINES - if(istype(I, /obj/item/stack/rods)) - var/obj/item/stack/S = I - if(S.use(1)) - d_state = RWALL_INTACT - update_icon() - to_chat(user, "You replace the outer grille.") - else - to_chat(user, "You don't have enough rods for that!") - return TRUE - - if(RWALL_COVER) - // RWALL_COVER > RWALL_CUT_COVER - if(iswelder(I)) - var/obj/item/weldingtool/WT = I - if(!WT.remove_fuel(0, user)) - to_chat(user, "You need more welding fuel to complete this task.") - return TRUE - - to_chat(user, "You begin slicing through the metal cover...") - playsound(src, WT.usesound, 100, 1) - - if(do_after(user, 60 * WT.toolspeed, target = src) && d_state == RWALL_COVER) - d_state = RWALL_CUT_COVER - update_icon() - to_chat(user, "You press firmly on the cover, dislodging it.") - return TRUE - - // RWALL_COVER > RWALL_CUT_COVER - if(istype(I, /obj/item/gun/energy/plasmacutter)) - to_chat(user, "You begin slicing through the metal cover...") - playsound(src, I.usesound, 100, 1) - - if(do_after(user, 40 * I.toolspeed, target = src) && d_state == RWALL_COVER) - d_state = RWALL_CUT_COVER - update_icon() - to_chat(user, "You press firmly on the cover, dislodging it.") - return TRUE - - // RWALL_SUPPORT_LINES < RWALL_COVER - if(isscrewdriver(I)) - to_chat(user, "You begin securing the support lines...") - playsound(src, I.usesound, 100, 1) - if(do_after(user, 40 * I.toolspeed, target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !I || d_state != RWALL_COVER) - return TRUE - d_state = RWALL_SUPPORT_LINES - update_icon() - to_chat(user, "The support lines have been secured.") - return TRUE - if(RWALL_CUT_COVER) - // RWALL_CUT_COVER > RWALL_BOLTS - if(iscrowbar(I)) - to_chat(user, "You struggle to pry off the cover...") - playsound(src, I.usesound, 100, 1) - - if(do_after(user, 100 * I.toolspeed, target = src) && d_state == RWALL_CUT_COVER) - d_state = RWALL_BOLTS - update_icon() - to_chat(user, "You pry off the cover.") - return TRUE - - // RWALL_COVER < RWALL_CUT_COVER - if(iswelder(I)) - var/obj/item/weldingtool/WT = I - if(!WT.remove_fuel(0, user)) - return TRUE - - to_chat(user, "You begin welding the metal cover back to the frame...") - playsound(src, WT.usesound, 100, 1) - if(do_after(user, 60 * WT.toolspeed, target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !WT || !WT.isOn() || d_state != RWALL_CUT_COVER) - return TRUE - d_state = RWALL_COVER - update_icon() - to_chat(user, "The metal cover has been welded securely to the frame.") - return TRUE - - if(RWALL_BOLTS) - // RWALL_BOLTS > RWALL_SUPPORT_RODS - if(iswrench(I)) - to_chat(user, "You start loosening the anchoring bolts which secure the support rods to their frame...") - playsound(src, I.usesound, 100, 1) - - if(do_after(user, 40 * I.toolspeed, target = src) && d_state == RWALL_BOLTS) - d_state = RWALL_SUPPORT_RODS - update_icon() - to_chat(user, "You remove the bolts anchoring the support rods.") - return TRUE - - // RWALL_CUT_COVER < RWALL_BOLTS - if(iscrowbar(I)) - to_chat(user, "You start to pry the cover back into place...") - playsound(src, I.usesound, 100, 1) - if(do_after(user, 20 * I.toolspeed, target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !I || d_state != RWALL_BOLTS) - return TRUE - d_state = RWALL_CUT_COVER - update_icon() - to_chat(user, "The metal cover has been pried back into place.") - return TRUE - - if(RWALL_SUPPORT_RODS) - // RWALL_SUPPORT_RODS > RWALL_SHEATH - if(iswelder(I)) - var/obj/item/weldingtool/WT = I - if(!WT.remove_fuel(0, user)) - to_chat(user, "You need more welding fuel to complete this task.") - return TRUE - - to_chat(user, "You begin slicing through the support rods...") - playsound(src, WT.usesound, 100, 1) - - if(do_after(user, 100 * WT.toolspeed, target = src) && d_state == RWALL_SUPPORT_RODS) - d_state = RWALL_SHEATH - update_icon() - return TRUE - - // RWALL_SUPPORT_RODS > RWALL_SHEATH - if(istype(I, /obj/item/gun/energy/plasmacutter)) - to_chat(user, "You begin slicing through the support rods...") - playsound(src, I.usesound, 100, 1) - - if(do_after(user, 70 * I.toolspeed, target = src) && d_state == RWALL_SUPPORT_RODS) - d_state = RWALL_SHEATH - update_icon() - return TRUE - - // RWALL_BOLTS < RWALL_SUPPORT_RODS - if(iswrench(I)) - to_chat(user, "You start tightening the bolts which secure the support rods to their frame...") - playsound(src, I.usesound, 100, 1) - if(do_after(user, 40 * I.toolspeed, target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !I || d_state != RWALL_SUPPORT_RODS) - return TRUE - d_state = RWALL_BOLTS - update_icon() - to_chat(user, "You tighten the bolts anchoring the support rods.") - return TRUE - + to_chat(user, "You struggle to pry off the cover...") + if(!I.use_tool(src, user, 100, volume = I.tool_volume) || d_state != RWALL_CUT_COVER) + return + d_state = RWALL_BOLTS + to_chat(user, "You pry off the cover.") if(RWALL_SHEATH) - // RWALL_SHEATH > deconstructed - if(iscrowbar(I)) - to_chat(user, "You struggle to pry off the outer sheath...") - playsound(src, I.usesound, 100, 1) + to_chat(user, "You struggle to pry off the outer sheath...") + if(!I.use_tool(src, user, 100, volume = I.tool_volume) || d_state != RWALL_SHEATH) + return + to_chat(user, "You pry off the outer sheath.") + dismantle_wall() + return + if(RWALL_BOLTS) + to_chat(user, "You start to pry the cover back into place...") + playsound(src, I.usesound, 100, 1) + if(!I.use_tool(src, user, 20, volume = I.tool_volume) || d_state != RWALL_BOLTS) + return + d_state = RWALL_CUT_COVER + to_chat(user, "The metal cover has been pried back into place.") + update_icon() - if(do_after(user, 100 * I.toolspeed, target = src) && d_state == RWALL_SHEATH) - to_chat(user, "You pry off the outer sheath.") - dismantle_wall() - return TRUE +/turf/simulated/wall/r_wall/screwdriver_act(mob/user, obj/item/I) + if(d_state != RWALL_SUPPORT_LINES && d_state != RWALL_COVER) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + var/state_check = d_state + if(d_state == RWALL_SUPPORT_LINES) + to_chat(user, "You begin unsecuring the support lines...") + else + to_chat(user, "You begin securing the support lines...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || state_check != d_state) + return + if(d_state == RWALL_SUPPORT_LINES) + d_state = RWALL_COVER + to_chat(user, "You unsecure the support lines.") + else + d_state = RWALL_SUPPORT_LINES + to_chat(user, "The support lines have been secured.") + update_icon() + +/turf/simulated/wall/r_wall/wirecutter_act(mob/user, obj/item/I) + if(d_state != RWALL_INTACT) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + d_state = RWALL_SUPPORT_LINES + update_icon() + new /obj/item/stack/rods(src) + to_chat(user, "You cut the outer grille.") + +/turf/simulated/wall/r_wall/wrench_act(mob/user, obj/item/I) + if(d_state != RWALL_BOLTS && d_state != RWALL_SUPPORT_RODS) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + var/state_check = d_state + if(d_state == RWALL_BOLTS) + to_chat(user, "You start loosening the anchoring bolts which secure the support rods to their frame...") + else + to_chat(user, "You start tightening the bolts which secure the support rods to their frame...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || state_check != d_state) + return + if(d_state == RWALL_BOLTS) + d_state = RWALL_SUPPORT_RODS + to_chat(user, "You remove the bolts anchoring the support rods.") + else + d_state = RWALL_BOLTS + to_chat(user, "You tighten the bolts anchoring the support rods.") + update_icon() /turf/simulated/wall/r_wall/try_destroy(obj/item/I, mob/user, params) if(istype(I, /obj/item/pickaxe/drill/diamonddrill)) diff --git a/code/game/world.dm b/code/game/world.dm index b059a7289de..cccf5eb497a 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -4,6 +4,7 @@ var/global/list/map_transition_config = MAP_TRANSITION_CONFIG /world/New() SetupLogs() + enable_debugger() // Enable the extools debugger log_world("World loaded at [time_stamp()]") log_world("[GLOB.vars.len - GLOB.gvars_datum_in_built_vars.len] global variables") @@ -414,6 +415,13 @@ var/failed_old_db_connections = 0 start_log(GLOB.world_runtime_log) start_log(GLOB.world_qdel_log) + // This log follows a special format and this path should NOT be used for anything else + GLOB.runtime_summary_log = "data/logs/runtime_summary.log" + if(fexists(GLOB.runtime_summary_log)) + fdel(GLOB.runtime_summary_log) + start_log(GLOB.runtime_summary_log) + // And back to sanity + if(fexists(GLOB.config_error_log)) fcopy(GLOB.config_error_log, "[GLOB.log_directory]/config_error.log") fdel(GLOB.config_error_log) @@ -461,3 +469,10 @@ proc/establish_db_connection() return 1 #undef FAILED_DB_CONNECTION_CUTOFF + +// Proc to enable the extools debugger, which allows breakpoints, live var checking, and many other useful tools +// The DLL is injected into the env by visual studio code. If not running VSCode, the proc will not call the initialization +/world/proc/enable_debugger() + var/dll = world.GetConfig("env", "EXTOOLS_DLL") + if (dll) + call(dll, "debug_initialize")() \ No newline at end of file diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm index 1ce6c2b90f0..86a6b228b60 100644 --- a/code/modules/admin/DB ban/functions.dm +++ b/code/modules/admin/DB ban/functions.dm @@ -469,13 +469,13 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) if(playercid) cidsearch = "AND computerid = '[playercid]' " else - if(adminckey && lentext(adminckey) >= 3) + if(adminckey && length(adminckey) >= 3) adminsearch = "AND a_ckey LIKE '[adminckey]%' " - if(playerckey && lentext(playerckey) >= 3) + if(playerckey && length(playerckey) >= 3) playersearch = "AND ckey LIKE '[playerckey]%' " - if(playerip && lentext(playerip) >= 3) + if(playerip && length(playerip) >= 3) ipsearch = "AND ip LIKE '[playerip]%' " - if(playercid && lentext(playercid) >= 7) + if(playercid && length(playercid) >= 7) cidsearch = "AND computerid LIKE '[playercid]%' " if(dbbantype) diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index 045819c365b..d776b4a2095 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -1,5 +1,5 @@ //Blocks an attempt to connect before even creating our client datum thing. -world/IsBanned(key, address, computer_id, check_ipintel = TRUE) +world/IsBanned(key, address, computer_id, type, check_ipintel = TRUE) if(!config.ban_legacy_system) if(address) @@ -11,11 +11,20 @@ world/IsBanned(key, address, computer_id, check_ipintel = TRUE) log_adminwarn("Failed Login (invalid data): [key] [address]-[computer_id]") return list("reason"="invalid login data", "desc"="Error: Could not check ban status, please try again. Error message: Your computer provided invalid or blank information to the server on connection (BYOND Username, IP, and Computer ID). Provided information for reference: Username: '[key]' IP: '[address]' Computer ID: '[computer_id]'. If you continue to get this error, please restart byond or contact byond support.") + if(type == "world") + return ..() //shunt world topic banchecks to purely to byond's internal ban system + if(text2num(computer_id) == 2147483647) //this cid causes stickybans to go haywire log_adminwarn("Failed Login (invalid cid): [key] [address]-[computer_id]") return list("reason"="invalid login data", "desc"="Error: Could not check ban status, Please try again. Error message: Your computer provided an invalid Computer ID.") + var/admin = 0 var/ckey = ckey(key) + + var/client/C = GLOB.directory[ckey] + if (C && ckey == C.ckey && computer_id == C.computer_id && address == C.address) + return //don't recheck connected clients. + if((ckey in admin_datums) || (ckey in GLOB.deadmins)) var/datum/admins/A = admin_datums[ckey] if(A && (A.rights & R_ADMIN)) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 6967a374b51..55fb1c4047a 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -100,8 +100,10 @@ var/global/nologevent = 0 body += "Jobban | " body += "Appearance Ban | " body += "Notes | " + if(config.forum_playerinfo_url) + body += "WebInfo | " if(M.client) - if(M.client.check_watchlist(M.client.ckey)) + if(check_watchlist(M.client.ckey)) body += "Remove from Watchlist | " body += "Edit Watchlist Reason " else diff --git a/code/modules/admin/permissionverbs/permissionedit.dm b/code/modules/admin/permissionverbs/permissionedit.dm index 9d9e60db014..57d58533437 100644 --- a/code/modules/admin/permissionverbs/permissionedit.dm +++ b/code/modules/admin/permissionverbs/permissionedit.dm @@ -86,17 +86,18 @@ new_admin = 0 admin_id = text2num(select_query.item[1]) + flag_account_for_forum_sync(adm_ckey) if(new_admin) var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO [format_table_name("admin")] (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)") insert_query.Execute() - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.[format_table_name("admin_log")] (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');") + var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');") log_query.Execute() to_chat(usr, "New admin added.") else if(!isnull(admin_id) && isnum(admin_id)) var/DBQuery/insert_query = dbcon.NewQuery("UPDATE [format_table_name("admin")] SET rank = '[new_rank]' WHERE id = [admin_id]") insert_query.Execute() - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.[format_table_name("admin_log")] (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Edited the rank of [adm_ckey] to [new_rank]');") + var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Edited the rank of [adm_ckey] to [new_rank]');") log_query.Execute() to_chat(usr, "Admin rank changed.") @@ -141,16 +142,17 @@ if(!admin_id) return + flag_account_for_forum_sync(adm_ckey) if(admin_rights & new_permission) //This admin already has this permission, so we are removing it. var/DBQuery/insert_query = dbcon.NewQuery("UPDATE [format_table_name("admin")] SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]") insert_query.Execute() - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.[format_table_name("admin_log")] (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');") + var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');") log_query.Execute() to_chat(usr, "Permission removed.") else //This admin doesn't have this permission, so we are adding it. var/DBQuery/insert_query = dbcon.NewQuery("UPDATE [format_table_name("admin")] SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]") insert_query.Execute() - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.[format_table_name("admin_log")] (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]')") + var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]')") log_query.Execute() to_chat(usr, "Permission added.") @@ -165,3 +167,4 @@ var/DBQuery/query_update = dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastadminrank = '[sql_admin_rank]' WHERE ckey = '[sql_ckey]'") query_update.Execute() + flag_account_for_forum_sync(sql_ckey) \ No newline at end of file diff --git a/code/modules/admin/sql_notes.dm b/code/modules/admin/sql_notes.dm index 18112f584c2..a6ac31a4114 100644 --- a/code/modules/admin/sql_notes.dm +++ b/code/modules/admin/sql_notes.dm @@ -4,22 +4,30 @@ if(!dbcon.IsConnected()) to_chat(usr, "Failed to establish database connection.") return + if(!target_ckey) var/new_ckey = ckey(clean_input("Who would you like to add a note for?","Enter a ckey",null)) if(!new_ckey) return - new_ckey = ckey(new_ckey) - var/DBQuery/query_find_ckey = dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[new_ckey]'") - if(!query_find_ckey.Execute()) - var/err = query_find_ckey.ErrorMsg() - log_game("SQL ERROR obtaining ckey from player table. Error : \[[err]\]\n") - return - if(!query_find_ckey.NextRow()) - to_chat(usr, "[new_ckey] has not been seen before, you can only add notes to known players.") - return - else - target_ckey = new_ckey - var/target_sql_ckey = ckey(target_ckey) + target_ckey = ckey(new_ckey) + else + target_ckey = ckey(target_ckey) + + var/DBQuery/query_find_ckey = dbcon.NewQuery("SELECT ckey, exp FROM [format_table_name("player")] WHERE ckey = '[target_ckey]'") + if(!query_find_ckey.Execute()) + var/err = query_find_ckey.ErrorMsg() + log_game("SQL ERROR obtaining ckey from player table. Error : \[[err]\]\n") + return + if(!query_find_ckey.NextRow()) + to_chat(usr, "[target_ckey] has not been seen before, you can only add notes to known players.") + return + + var/exp_data = query_find_ckey.item[2] + var/crew_number = 0 + if(exp_data) + var/list/play_records = params2list(exp_data) + crew_number = play_records[EXP_TYPE_CREW] + if(!notetext) notetext = input(usr,"Write your note","Add Note") as message|null if(!notetext) @@ -38,7 +46,7 @@ if(config && config.server_name) server = config.server_name server = sanitizeSQL(server) - var/DBQuery/query_noteadd = dbcon.NewQuery("INSERT INTO [format_table_name("notes")] (ckey, timestamp, notetext, adminckey, server) VALUES ('[target_sql_ckey]', '[timestamp]', '[notetext]', '[admin_sql_ckey]', '[server]')") + var/DBQuery/query_noteadd = dbcon.NewQuery("INSERT INTO [format_table_name("notes")] (ckey, timestamp, notetext, adminckey, server, crew_playtime) VALUES ('[target_ckey]', '[timestamp]', '[notetext]', '[admin_sql_ckey]', '[server]', '[crew_number]')") if(!query_noteadd.Execute()) var/err = query_noteadd.ErrorMsg() log_game("SQL ERROR adding new note to table. Error : \[[err]\]\n") @@ -131,10 +139,10 @@ output = navbar if(target_ckey) var/target_sql_ckey = ckey(target_ckey) - var/DBQuery/query_get_notes = dbcon.NewQuery("SELECT id, timestamp, notetext, adminckey, last_editor, server FROM [format_table_name("notes")] WHERE ckey = '[target_sql_ckey]' ORDER BY timestamp") + var/DBQuery/query_get_notes = dbcon.NewQuery("SELECT id, timestamp, notetext, adminckey, last_editor, server, crew_playtime FROM [format_table_name("notes")] WHERE ckey = '[target_sql_ckey]' ORDER BY timestamp") if(!query_get_notes.Execute()) var/err = query_get_notes.ErrorMsg() - log_game("SQL ERROR obtaining ckey, notetext, adminckey, last_editor, server from notes table. Error : \[[err]\]\n") + log_game("SQL ERROR obtaining ckey, notetext, adminckey, last_editor, server, crew_playtime from notes table. Error : \[[err]\]\n") return output += "

    Notes of [target_ckey]

    " if(!linkless) @@ -147,7 +155,13 @@ var/adminckey = query_get_notes.item[4] var/last_editor = query_get_notes.item[5] var/server = query_get_notes.item[6] - output += "[timestamp] | [server] | [adminckey]" + var/mins = text2num(query_get_notes.item[7]) + output += "[timestamp] | [server] | [adminckey]" + if(mins) + var/playstring = get_exp_format(mins) + output += " | [playstring] as Crew" + output += "" + if(!linkless) output += " \[Remove Note\] \[Edit Note\]" if(last_editor) @@ -182,10 +196,10 @@ /proc/show_player_info_irc(var/key as text) var/target_sql_ckey = ckey(key) - var/DBQuery/query_get_notes = dbcon.NewQuery("SELECT timestamp, notetext, adminckey, server FROM [format_table_name("notes")] WHERE ckey = '[target_sql_ckey]' ORDER BY timestamp") + var/DBQuery/query_get_notes = dbcon.NewQuery("SELECT timestamp, notetext, adminckey, server, crew_playtime FROM [format_table_name("notes")] WHERE ckey = '[target_sql_ckey]' ORDER BY timestamp") if(!query_get_notes.Execute()) var/err = query_get_notes.ErrorMsg() - log_game("SQL ERROR obtaining timestamp, notetext, adminckey, server from notes table. Error : \[[err]\]\n") + log_game("SQL ERROR obtaining timestamp, notetext, adminckey, server, crew_playtime from notes table. Error : \[[err]\]\n") return var/output = " Info on [key]%0D%0A" while(query_get_notes.NextRow()) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index a318c316532..2d98626a1c3 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -212,7 +212,7 @@ if(admin_ranks.len) new_rank = input("Please select a rank", "New rank", null, null) as null|anything in (admin_ranks|"*New Rank*") else - new_rank = input("Please select a rank", "New rank", null, null) as null|anything in list("Game Master","Game Admin", "Trial Admin", "Admin Observer","*New Rank*") + new_rank = input("Please select a rank", "New rank", null, null) as null|anything in list("Mentor", "Trial Admin", "Game Admin", "*New Rank*") var/rights = 0 if(D) @@ -936,6 +936,13 @@ target = text2num(target) show_note(index = target) + else if(href_list["webtools"]) + var/target_ckey = href_list["webtools"] + if(config.forum_playerinfo_url) + var/url_to_open = config.forum_playerinfo_url + target_ckey + if(alert("Open [url_to_open]",,"Yes","No")=="Yes") + usr.client << link(url_to_open) + else if(href_list["shownoteckey"]) var/target_ckey = href_list["shownoteckey"] show_note(target_ckey) @@ -995,6 +1002,8 @@ feedback_inc("ban_tmp",1) DB_ban_record(BANTYPE_TEMP, M, mins, reason) feedback_inc("ban_tmp_mins",mins) + if(M.client) + M.client.link_forum_account(TRUE) if(config.banappeals) to_chat(M, "To try to resolve this matter head to [config.banappeals]") else @@ -1011,6 +1020,8 @@ AddBan(M.ckey, M.computer_id, reason, usr.ckey, 0, 0, M.lastKnownIP) to_chat(M, "You have been banned by [usr.client.ckey].\nReason: [reason].") to_chat(M, "This ban does not expire automatically and must be appealed.") + if(M.client) + M.client.link_forum_account(TRUE) if(config.banappeals) to_chat(M, "To try to resolve this matter head to [config.banappeals]") else @@ -2153,7 +2164,7 @@ var/obj/pageobj = B.contents[page] data += "Page [page] - [pageobj.name]
    " - usr << browse(data, "window=[B.name]") + usr << browse(data, "window=PaperBundle[B.UID()]") else to_chat(usr, "The faxed item is not viewable. This is probably a bug, and should be reported on the tracker: [fax.type]") @@ -2712,15 +2723,15 @@ if(newBombCap > 128) newBombCap = 128 - MAX_EX_DEVESTATION_RANGE = round(newBombCap/4) + MAX_EX_DEVASTATION_RANGE = round(newBombCap/4) MAX_EX_HEAVY_RANGE = round(newBombCap/2) MAX_EX_LIGHT_RANGE = newBombCap //I don't know why these are their own variables, but fuck it, they are. MAX_EX_FLASH_RANGE = newBombCap MAX_EX_FLAME_RANGE = newBombCap - message_admins("[key_name_admin(usr)] changed the bomb cap to [MAX_EX_DEVESTATION_RANGE], [MAX_EX_HEAVY_RANGE], [MAX_EX_LIGHT_RANGE]") - log_admin("[key_name(usr)] changed the bomb cap to [MAX_EX_DEVESTATION_RANGE], [MAX_EX_HEAVY_RANGE], [MAX_EX_LIGHT_RANGE]") + message_admins("[key_name_admin(usr)] changed the bomb cap to [MAX_EX_DEVASTATION_RANGE], [MAX_EX_HEAVY_RANGE], [MAX_EX_LIGHT_RANGE]") + log_admin("[key_name(usr)] changed the bomb cap to [MAX_EX_DEVASTATION_RANGE], [MAX_EX_HEAVY_RANGE], [MAX_EX_LIGHT_RANGE]") if("flicklights") feedback_inc("admin_secrets_fun_used",1) @@ -3066,7 +3077,7 @@ else if(href_list["ac_set_channel_name"]) src.admincaster_feed_channel.channel_name = strip_html_simple(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "")) while(findtext(src.admincaster_feed_channel.channel_name," ") == 1) - src.admincaster_feed_channel.channel_name = copytext(src.admincaster_feed_channel.channel_name,2,lentext(src.admincaster_feed_channel.channel_name)+1) + src.admincaster_feed_channel.channel_name = copytext(src.admincaster_feed_channel.channel_name,2,length(src.admincaster_feed_channel.channel_name)+1) src.access_news_network() else if(href_list["ac_set_channel_lock"]) @@ -3105,7 +3116,7 @@ else if(href_list["ac_set_new_message"]) src.admincaster_feed_message.body = adminscrub(input(usr, "Write your Feed story", "Network Channel Handler", "")) while(findtext(src.admincaster_feed_message.body," ") == 1) - src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.body,2,lentext(src.admincaster_feed_message.body)+1) + src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.body,2,length(src.admincaster_feed_message.body)+1) src.access_news_network() else if(href_list["ac_submit_new_message"]) @@ -3159,13 +3170,13 @@ else if(href_list["ac_set_wanted_name"]) src.admincaster_feed_message.author = adminscrub(input(usr, "Provide the name of the Wanted person", "Network Security Handler", "")) while(findtext(src.admincaster_feed_message.author," ") == 1) - src.admincaster_feed_message.author = copytext(admincaster_feed_message.author,2,lentext(admincaster_feed_message.author)+1) + src.admincaster_feed_message.author = copytext(admincaster_feed_message.author,2,length(admincaster_feed_message.author)+1) src.access_news_network() else if(href_list["ac_set_wanted_desc"]) src.admincaster_feed_message.body = adminscrub(input(usr, "Provide the a description of the Wanted person and any other details you deem important", "Network Security Handler", "")) while(findtext(src.admincaster_feed_message.body," ") == 1) - src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.body,2,lentext(src.admincaster_feed_message.body)+1) + src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.body,2,length(src.admincaster_feed_message.body)+1) src.access_news_network() else if(href_list["ac_submit_wanted"]) diff --git a/code/modules/admin/verbs/freeze.dm b/code/modules/admin/verbs/freeze.dm index 4d60fb72bee..9b01e94846c 100644 --- a/code/modules/admin/verbs/freeze.dm +++ b/code/modules/admin/verbs/freeze.dm @@ -26,7 +26,7 @@ var/global/list/frozen_mob_list = list() /mob/living/var/frozen = null //used for preventing attacks on admin-frozen mobs /mob/living/var/admin_prev_sleeping = 0 //used for keeping track of previous sleeping value with admin freeze -/mob/living/proc/admin_Freeze(var/client/admin, skip_overlays = FALSE) +/mob/living/proc/admin_Freeze(client/admin, skip_overlays = FALSE) if(istype(admin)) to_chat(src, "You have been frozen by [admin]") message_admins("[key_name_admin(admin)] froze [key_name_admin(src)]") @@ -34,24 +34,27 @@ var/global/list/frozen_mob_list = list() var/obj/effect/overlay/adminoverlay/AO = new if(skip_overlays) - src.overlays += AO + overlays += AO - anchored = 1 - frozen = AO + anchored = TRUE + canmove = FALSE admin_prev_sleeping = sleeping AdjustSleeping(20000) + frozen = AO if(!(src in frozen_mob_list)) frozen_mob_list += src -/mob/living/proc/admin_unFreeze(var/client/admin, skip_overlays = FALSE) +/mob/living/proc/admin_unFreeze(client/admin, skip_overlays = FALSE) if(istype(admin)) to_chat(src, "You have been unfrozen by [admin]") message_admins("[key_name_admin(admin)] unfroze [key_name_admin(src)]") log_admin("[key_name(admin)] unfroze [key_name(src)]") - anchored = 0 if(skip_overlays) overlays -= frozen + + anchored = FALSE + canmove = TRUE frozen = null SetSleeping(admin_prev_sleeping) admin_prev_sleeping = null diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm index f3be2161bb2..c5348fbeabe 100644 --- a/code/modules/admin/verbs/modifyvariables.dm +++ b/code/modules/admin/verbs/modifyvariables.dm @@ -306,11 +306,11 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", // the type with the base type removed from the begaining var/fancytype = types[D.type] if(findtext(fancytype, types[type])) - fancytype = copytext(fancytype, lentext(types[type])+1) - var/shorttype = copytext("[D.type]", lentext("[type]")+1) - if(lentext(shorttype) > lentext(fancytype)) + fancytype = copytext(fancytype, length(types[type])+1) + var/shorttype = copytext("[D.type]", length("[type]")+1) + if(length(shorttype) > length(fancytype)) shorttype = fancytype - if(!lentext(shorttype)) + if(!length(shorttype)) shorttype = "/" .["[D]([shorttype])\ref[D]#[i]"] = D diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index caf7fdf2663..a347f65590b 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -116,7 +116,7 @@ if(!msg) return - msg = pencode_to_html(msg) + msg = admin_pencode_to_html(msg) to_chat(world, "[msg]") log_admin("GlobalNarrate: [key_name(usr)] : [msg]") message_admins("GlobalNarrate: [key_name_admin(usr)]: [msg]
    ", 1) @@ -989,12 +989,14 @@ Traitors and the like can also be revived with the previous role mostly intact. if(job_string in command_positions) job_string = "" + job_string + "" role_string = "-" + obj_count = 0 + obj_string = "" if(H.mind) if(H.mind.special_role) role_string = "[H.mind.special_role]" if(!H.key && H.mind.key) key_string = H.mind.key - for(var/datum/objective/O in all_objectives) + for(var/datum/objective/O in GLOB.all_objectives) if(O.target == H.mind) obj_count++ if(obj_count > 0) @@ -1033,7 +1035,7 @@ Traitors and the like can also be revived with the previous role mostly intact. role_string = "[H.mind.special_role]" if(!H.key && H.mind.key) key_string = H.mind.key - for(var/datum/objective/O in all_objectives) + for(var/datum/objective/O in GLOB.all_objectives) if(O.target == H.mind) obj_count++ if(obj_count > 0) diff --git a/code/modules/admin/watchlist.dm b/code/modules/admin/watchlist.dm index 040bc08112b..a908c2c264b 100644 --- a/code/modules/admin/watchlist.dm +++ b/code/modules/admin/watchlist.dm @@ -113,9 +113,7 @@ output += "
    [reason]
    " usr << browse(output, "window=watchwin;size=900x500") -/client/proc/check_watchlist(target_ckey) - if(!check_rights(R_ADMIN,0)) - return +/proc/check_watchlist(target_ckey) var/target_sql_ckey = sanitizeSQL(target_ckey) var/DBQuery/query_watch = dbcon.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'") if(!query_watch.Execute()) diff --git a/code/modules/antagonists/traitor/datum_mindslave.dm b/code/modules/antagonists/traitor/datum_mindslave.dm index c96b2182d9e..5efd35715ad 100644 --- a/code/modules/antagonists/traitor/datum_mindslave.dm +++ b/code/modules/antagonists/traitor/datum_mindslave.dm @@ -3,8 +3,8 @@ /datum/antagonist/mindslave name = "Mindslave" roundend_category = "mindslaves" - job_rank = ROLE_MINDSLAVE - var/special_role = ROLE_MINDSLAVE + job_rank = SPECIAL_ROLE_TRAITOR + var/special_role = SPECIAL_ROLE_TRAITOR /datum/antagonist/mindslave/on_gain() owner.special_role = special_role diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 4e9a5ad4bf7..9e6f1b79bfa 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -6,7 +6,7 @@ name = "Traitor" roundend_category = "traitors" job_rank = ROLE_TRAITOR - var/special_role = ROLE_TRAITOR + var/special_role = SPECIAL_ROLE_TRAITOR var/give_objectives = TRUE var/should_give_codewords = TRUE var/should_equip = TRUE @@ -28,6 +28,7 @@ forge_traitor_objectives() if(!silent) greet() + apply_innate_effects() update_traitor_icons_added() finalize_traitor() @@ -54,6 +55,7 @@ assigned_targets.Cut() SSticker.mode.traitors -= owner owner.special_role = null + remove_innate_effects() update_traitor_icons_removed() if(!silent && owner.current) @@ -67,8 +69,10 @@ if(owner.assigned_role == "Clown") var/mob/living/carbon/human/traitor_mob = owner.current if(traitor_mob && istype(traitor_mob)) - to_chat(traitor_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") + to_chat(traitor_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") traitor_mob.mutations.Remove(CLUMSY) + var/datum/action/innate/toggle_clumsy/A = new + A.Grant(traitor_mob) /datum/antagonist/traitor/remove_innate_effects() @@ -76,7 +80,11 @@ if(owner.assigned_role == "Clown") var/mob/living/carbon/human/traitor_mob = owner.current if(traitor_mob && istype(traitor_mob)) + to_chat(traitor_mob, "You lose your syndicate training and return to your own clumsy, clownish self.") traitor_mob.mutations.Add(CLUMSY) + for(var/datum/action/innate/A in traitor_mob.actions) + if(istype(A, /datum/action/innate/toggle_clumsy)) + A.Remove(traitor_mob) // Adding/removing objectives in the owner's mind until we can datumize all antags. Then we can use the /datum/antagonist/objectives var to handle them // Change "owner.objectives" to "objectives" once objectives are handled in antag datums instead of the mind diff --git a/code/modules/arcade/arcade_base.dm b/code/modules/arcade/arcade_base.dm index 80d6cad031a..df007b83ad3 100644 --- a/code/modules/arcade/arcade_base.dm +++ b/code/modules/arcade/arcade_base.dm @@ -78,7 +78,7 @@ tokens += 1 return if(panel_open && component_parts && istype(O, /obj/item/crowbar)) - default_deconstruction_crowbar(O) + default_deconstruction_crowbar(user, O) return return ..() diff --git a/code/modules/arcade/mob_hunt/mob_cards.dm b/code/modules/arcade/mob_hunt/mob_cards.dm index 8623b25d0f1..0fbd236dee6 100644 --- a/code/modules/arcade/mob_hunt/mob_cards.dm +++ b/code/modules/arcade/mob_hunt/mob_cards.dm @@ -27,6 +27,7 @@ desc = "A random Nano-Mob Trading Card from a Booster Pack. Wonder what it is?" /obj/item/nanomob_card/booster/New() + ..() var/datum/mob_hunt/mob_info = pick(subtypesof(/datum/mob_hunt)) mob_data = new mob_info(0,null,1) update_info() diff --git a/code/modules/arcade/prize_counter.dm b/code/modules/arcade/prize_counter.dm index a48b1011adc..4d1d6973909 100644 --- a/code/modules/arcade/prize_counter.dm +++ b/code/modules/arcade/prize_counter.dm @@ -52,7 +52,7 @@ if(component_parts && istype(O, /obj/item/crowbar)) if(tickets) //save the tickets! print_tickets() - default_deconstruction_crowbar(O) + default_deconstruction_crowbar(user, O) return return ..() diff --git a/code/modules/assembly/assembly.dm b/code/modules/assembly/assembly.dm index d94e3243013..b2a44940053 100644 --- a/code/modules/assembly/assembly.dm +++ b/code/modules/assembly/assembly.dm @@ -116,14 +116,18 @@ if(!A.secured && !secured) attach_assembly(A, user) return - if(isscrewdriver(W)) - if(toggle_secure()) - to_chat(user, "[src] is ready!") - else - to_chat(user, "[src] can now be attached!") - return + return ..() +/obj/item/assembly/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(toggle_secure()) + to_chat(user, "[src] is ready!") + else + to_chat(user, "[src] can now be attached!") + /obj/item/assembly/process() STOP_PROCESSING(SSobj, src) diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm index e0454d5f5ea..d5039af0a84 100644 --- a/code/modules/assembly/bomb.dm +++ b/code/modules/assembly/bomb.dm @@ -28,35 +28,38 @@ if(istype(W, /obj/item/analyzer)) bombtank.attackby(W, user, params) return - if(iswrench(W) && !status) //This is basically bomb assembly code inverted. apparently it works. + return ..() - to_chat(user, "You disassemble [src].") - - bombassembly.loc = user.loc - bombassembly.master = null - bombassembly = null - - bombtank.loc = user.loc - bombtank.master = null - bombtank = null - - qdel(src) +/obj/item/onetankbomb/wrench_act(mob/user, obj/item/I) //This is basically bomb assembly code inverted. apparently it works. + if(status) return - if(iswelder(W)) - var/obj/item/weldingtool/WT = W - if(WT.welding) - if(!status) - status = TRUE - investigate_log("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", INVESTIGATE_BOMB) - msg_admin_attack("[key_name_admin(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", ATKLOG_FEW) - log_game("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature - T0C]") - to_chat(user, "A pressure hole has been bored to [bombtank] valve. [bombtank] can now be ignited.") - else - status = FALSE - investigate_log("[key_name(user)] unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", INVESTIGATE_BOMB) - to_chat(user, "The hole has been closed.") - add_fingerprint(user) - ..() + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + to_chat(user, "You disassemble [src].") + bombassembly.loc = user.loc + bombassembly.master = null + bombassembly = null + bombtank.loc = user.loc + bombtank.master = null + bombtank = null + qdel(src) + +/obj/item/onetankbomb/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, volume = I.tool_volume)) + return + if(!status) + status = TRUE + investigate_log("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", INVESTIGATE_BOMB) + msg_admin_attack("[key_name_admin(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", ATKLOG_FEW) + log_game("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature - T0C]") + to_chat(user, "A pressure hole has been bored to [bombtank] valve. [bombtank] can now be ignited.") + else + status = FALSE + investigate_log("[key_name(user)] unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", INVESTIGATE_BOMB) + to_chat(user, "The hole has been closed.") + /obj/item/onetankbomb/attack_self(mob/user) //pressing the bomb accesses its assembly bombassembly.attack_self(user, 1) diff --git a/code/modules/assembly/health.dm b/code/modules/assembly/health.dm index 3a543e38f72..6648a9ce22d 100644 --- a/code/modules/assembly/health.dm +++ b/code/modules/assembly/health.dm @@ -28,17 +28,16 @@ update_icon() return secured -/obj/item/assembly/health/attackby(obj/item/W, mob/user) - if(ismultitool(W)) - if(alarm_health == 0) - alarm_health = -90 - user.show_message("You toggle [src] to \"detect death\" mode.") - else - alarm_health = 0 - user.show_message("You toggle [src] to \"detect critical state\" mode.") +/obj/item/assembly/health/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return + if(alarm_health == 0) + alarm_health = -90 + user.show_message("You toggle [src] to \"detect death\" mode.") else - return ..() + alarm_health = 0 + user.show_message("You toggle [src] to \"detect critical state\" mode.") /obj/item/assembly/health/process() if(!scanning || !secured) diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index a7007806289..236ee94bd9d 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -139,24 +139,21 @@ ..() return -/obj/item/assembly_holder/attackby(obj/item/W, mob/user, params) - if(isscrewdriver(W)) - if(!a_left || !a_right) - to_chat(user, "BUG:Assembly part missing, please report this!") - return - a_left.toggle_secure() - a_right.toggle_secure() - secured = !secured - if(secured) - to_chat(user, "[src] is ready!") - else - to_chat(user, "[src] can now be taken apart!") - update_icon() +/obj/item/assembly_holder/screwdriver_act(mob/user, obj/item/I) + if(!a_left || !a_right) + to_chat(user, "BUG:Assembly part missing, please report this!") return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + a_left.toggle_secure() + a_right.toggle_secure() + secured = !secured + if(secured) + to_chat(user, "[src] is ready!") else - ..() - return - + to_chat(user, "[src] can now be taken apart!") + update_icon() /obj/item/assembly_holder/attack_self(mob/user) add_fingerprint(user) diff --git a/code/modules/awaymissions/mission_code/stationCollision.dm b/code/modules/awaymissions/mission_code/stationCollision.dm index 619b3c398f0..8d6a7fabe05 100644 --- a/code/modules/awaymissions/mission_code/stationCollision.dm +++ b/code/modules/awaymissions/mission_code/stationCollision.dm @@ -105,11 +105,13 @@ var/sc_safecode5 = "[rand(0,9)]" name = "smudged paper" /obj/item/paper/sc_safehint_paper_prison/New() + ..() info = "The ink is smudged, you can only make out a couple numbers: '[sc_safecode1]**[sc_safecode4]*'" /obj/item/paper/sc_safehint_paper_hydro name = "shredded paper" /obj/item/paper/sc_safehint_paper_hydro/New() + ..() info = "Although the paper is shredded, you can clearly see the number: '[sc_safecode2]'" /obj/item/paper/sc_safehint_paper_caf @@ -120,6 +122,7 @@ var/sc_safecode5 = "[rand(0,9)]" /obj/item/paper/sc_safehint_paper_bible name = "hidden paper" /obj/item/paper/sc_safehint_paper_bible/New() + ..() info = {"It would appear that the pen hidden with the paper had leaked ink over the paper. However you can make out the last three digits:'[sc_safecode3][sc_safecode4][sc_safecode5]' "} diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 6f971d308fa..962be47cae9 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -360,10 +360,10 @@ . = ..() //calls mob.Login() - if(ckey in clientmessages) - for(var/message in clientmessages[ckey]) + if(ckey in GLOB.clientmessages) + for(var/message in GLOB.clientmessages[ckey]) to_chat(src, message) - clientmessages.Remove(ckey) + GLOB.clientmessages.Remove(ckey) if(SSinput.initialized) set_macros() @@ -413,7 +413,7 @@ for(var/mob/M in GLOB.player_list) if(M.client) playercount += 1 - + if(playercount >= 150 && GLOB.panic_bunker_enabled == 0) GLOB.panic_bunker_enabled = 1 message_admins("Panic bunker has been automatically enabled due to playercount surpassing 150") @@ -553,16 +553,15 @@ src << "Sorry but the server is currently not accepting connections from never before seen players. Please try again later." del(src) return // Dont insert or they can just go in again - + var/DBQuery/query_insert = dbcon.NewQuery("INSERT INTO [format_table_name("player")] (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, '[ckey]', Now(), Now(), '[sql_ip]', '[sql_computerid]', '[sql_admin_rank]')") if(!query_insert.Execute()) var/err = query_insert.ErrorMsg() log_game("SQL ERROR during log_client_to_db (insert). Error : \[[err]\]\n") message_admins("SQL ERROR during log_client_to_db (insert). Error : \[[err]\]\n") - //Logging player access - var/serverip = "[world.internet_address]:[world.port]" - var/DBQuery/query_accesslog = dbcon.NewQuery("INSERT INTO `[format_table_name("connection_log")]`(`id`,`datetime`,`serverip`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),'[serverip]','[ckey]','[sql_ip]','[sql_computerid]');") + // Log player connections to DB + var/DBQuery/query_accesslog = dbcon.NewQuery("INSERT INTO `[format_table_name("connection_log")]`(`datetime`,`ckey`,`ip`,`computerid`) VALUES(Now(),'[ckey]','[sql_ip]','[sql_computerid]');") query_accesslog.Execute() /client/proc/check_ip_intel() @@ -601,8 +600,13 @@ /client/proc/check_forum_link() - if(config.forum_link_url && prefs && !prefs.fuid) - to_chat(src, "You do not have your forum account linked. LINK FORUM ACCOUNT") + if(!config.forum_link_url || !prefs || prefs.fuid) + return + if(config.use_exp_tracking) + var/living_hours = get_exp_type_num(EXP_TYPE_LIVING) / 60 + if(living_hours < 20) + return + to_chat(src, "You have no verified forum account. VERIFY FORUM ACCOUNT") /client/proc/create_oauth_token() var/DBQuery/query_find_token = dbcon.NewQuery("SELECT token FROM [format_table_name("oauth_tokens")] WHERE ckey = '[ckey]' limit 1") @@ -617,12 +621,15 @@ return return tokenstr -/client/proc/link_forum_account() +/client/proc/link_forum_account(fromban) + if(!config.forum_link_url) + return if(IsGuestKey(key)) to_chat(src, "Guest keys cannot be linked.") return if(prefs && prefs.fuid) - to_chat(src, "Your forum account is already set.") + if(!fromban) + to_chat(src, "Your forum account is already set.") return var/DBQuery/query_find_link = dbcon.NewQuery("SELECT fuid FROM [format_table_name("player")] WHERE ckey = '[ckey]' limit 1") if(!query_find_link.Execute()) @@ -630,14 +637,19 @@ return if(query_find_link.NextRow()) if(query_find_link.item[1]) - to_chat(src, "Your forum account is already set. (" + query_find_link.item[1] + ")") + if(!fromban) + to_chat(src, "Your forum account is already set. (" + query_find_link.item[1] + ")") return var/tokenid = create_oauth_token() if(!tokenid) to_chat(src, "link_forum_account: unable to create token") return var/url = "[config.forum_link_url][tokenid]" - to_chat(src, {"Now opening a windows to verify your information with the forums. If the window does not load, please go to: [url]."}) + if(fromban) + url += "&fwd=appeal" + to_chat(src, {"Now opening a window to verify your information with the forums, so that you can appeal your ban. If the window does not load, please copy/paste this link: [url]"}) + else + to_chat(src, {"Now opening a window to verify your information with the forums. If the window does not load, please go to: [url]"}) src << link(url) return @@ -774,7 +786,7 @@ // Change the way they should download resources. if(config.resource_urls) preload_rsc = pick(config.resource_urls) - else + else preload_rsc = 1 // If config.resource_urls is not set, preload like normal. // Most assets are now handled through global_cache.dm getFiles( diff --git a/code/modules/client/message.dm b/code/modules/client/message.dm index a5c78008b4f..ba09e7e1567 100644 --- a/code/modules/client/message.dm +++ b/code/modules/client/message.dm @@ -1,9 +1,10 @@ -var/list/clientmessages = list() +GLOBAL_LIST_EMPTY(clientmessages) proc/addclientmessage(var/ckey, var/message) ckey = ckey(ckey) if(!ckey || !message) return - if(!(ckey in clientmessages)) - clientmessages[ckey] = list() - clientmessages[ckey] += message + var/list/L = GLOB.clientmessages[ckey] + if(!L) + GLOB.clientmessages[ckey] = L = list() + L += message \ No newline at end of file diff --git a/code/modules/client/preference/loadout/loadout_racial.dm b/code/modules/client/preference/loadout/loadout_racial.dm index 38d216ae156..0d7b945bb78 100644 --- a/code/modules/client/preference/loadout/loadout_racial.dm +++ b/code/modules/client/preference/loadout/loadout_racial.dm @@ -1,43 +1,47 @@ /datum/gear/racial sort_category = "Racial" subtype_path = /datum/gear/racial - cost = 2 + cost = 1 - -/datum/gear/racial/tajciv +/datum/gear/racial/taj display_name = "embroidered veil" description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races." path = /obj/item/clothing/glasses/tajblind - cost = 1 + slot = slot_glasses -/datum/gear/racial/tajsec +/datum/gear/racial/taj/sec display_name = "sleek veil" description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races. This one has an in-built security HUD." path = /obj/item/clothing/glasses/hud/security/tajblind allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot", "Internal Affairs Agent", "Magistrate") + cost = 2 -/datum/gear/racial/tajmed +/datum/gear/racial/taj/med display_name = "lightweight veil" description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races. This one has an in-built medical HUD." path = /obj/item/clothing/glasses/hud/health/tajblind allowed_roles = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Psychiatrist", "Paramedic", "Virologist", "Brig Physician" , "Coroner") + cost = 2 -/datum/gear/racial/tajsci +/datum/gear/racial/taj/sci display_name = "hi-tech veil" description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races." path = /obj/item/clothing/glasses/tajblind/sci + cost = 2 -/datum/gear/racial/tajeng +/datum/gear/racial/taj/eng display_name = "industrial veil" description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races." path = /obj/item/clothing/glasses/tajblind/eng - -/datum/gear/racial/tajcargo + cost = 2 + +/datum/gear/racial/taj/cargo display_name = "khaki veil" description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races. It is light and comfy!" path = /obj/item/clothing/glasses/tajblind/cargo - + cost = 2 + /datum/gear/racial/footwraps display_name = "cloth footwraps" path = /obj/item/clothing/shoes/footwraps - cost = 1 \ No newline at end of file + slot = slot_shoes diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index 11eb454a241..eb1587ff28c 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -294,8 +294,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts dat += "Disabilities: \[Set\]
    " dat += "Nanotrasen Relation: [nanotrasen_relation]
    " dat += "Set Flavor Text
    " - if(lentext(flavor_text) <= 40) - if(!lentext(flavor_text)) dat += "\[...\]
    " + if(length(flavor_text) <= 40) + if(!length(flavor_text)) dat += "\[...\]
    " else dat += "[flavor_text]
    " else dat += "[TextPreview(flavor_text)]...
    " @@ -886,21 +886,21 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts HTML += "Medical Records
    " - if(lentext(med_record) <= 40) + if(length(med_record) <= 40) HTML += "[med_record]" else HTML += "[copytext(med_record, 1, 37)]..." HTML += "
    Employment Records
    " - if(lentext(gen_record) <= 40) + if(length(gen_record) <= 40) HTML += "[gen_record]" else HTML += "[copytext(gen_record, 1, 37)]..." HTML += "
    Security Records
    " - if(lentext(sec_record) <= 40) + if(length(sec_record) <= 40) HTML += "[sec_record]
    " else HTML += "[copytext(sec_record, 1, 37)]...
    " @@ -1308,7 +1308,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts else //Not using the whitelist? Aliens for everyone! new_species += GLOB.whitelisted_species - species = input("Please select a species", "Character Generation", null) in new_species + species = input("Please select a species", "Character Generation", null) in sortTim(new_species, /proc/cmp_text_asc) var/datum/species/NS = GLOB.all_species[species] if(!istype(NS)) //The species was invalid. Notify the user and fail out. species = prev_species @@ -1406,7 +1406,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if(!(lang.flags & RESTRICTED)) new_languages += lang.name - language = input("Please select a secondary language", "Character Generation", null) in new_languages + language = input("Please select a secondary language", "Character Generation", null) in sortTim(new_languages, /proc/cmp_text_asc) if("autohiss_mode") if(S.autohiss_basic_map) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index a6fe3789aae..adb35b0fb3b 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -527,7 +527,7 @@ BLIND // can't see anything end up with a suffix of _open_open if adjusted twice, since their initial state is _open. */ item_state = copytext(item_state, 1, findtext(item_state, "_open")) if(adjust_flavour) - flavour = "[copytext(adjust_flavour, 3, lentext(adjust_flavour) + 1)] up" //Trims off the 'un' at the beginning of the word. unzip -> zip, unbutton->button. + flavour = "[copytext(adjust_flavour, 3, length(adjust_flavour) + 1)] up" //Trims off the 'un' at the beginning of the word. unzip -> zip, unbutton->button. to_chat(user, "You [flavour] \the [src].") suit_adjusted = 0 //Suit is no longer adjusted. for(var/X in actions) @@ -601,13 +601,14 @@ BLIND // can't see anything min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT heat_protection = HEAD max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT - species_restricted = list("exclude","Vox","Wryn") + species_restricted = list("exclude","Wryn") flash_protect = 2 strip_delay = 50 put_on_delay = 50 resistance_flags = NONE dog_fashion = null + /obj/item/clothing/suit/space name = "Space suit" desc = "A suit that protects against low pressure environments. Has a big 13 on the back." @@ -630,7 +631,8 @@ BLIND // can't see anything put_on_delay = 80 resistance_flags = NONE hide_tail_by_species = null - species_restricted = list("exclude","Vox","Wryn") + species_restricted = list("exclude","Wryn") + //Under clothing /obj/item/clothing/under diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index ce29fa8f7b1..e80f461246e 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -274,6 +274,11 @@ see_in_dark = 0 flash_protect = 0 tint = 0 + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/eyes.dmi', + "Drask" = 'icons/mob/species/drask/eyes.dmi', + "Grey" = 'icons/mob/species/grey/eyes.dmi' + ) /obj/item/clothing/glasses/sunglasses/noir name = "noir sunglasses" diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm index fef737982fa..429a87ba58a 100644 --- a/code/modules/clothing/gloves/miscellaneous.dm +++ b/code/modules/clothing/gloves/miscellaneous.dm @@ -143,13 +143,18 @@ update_icon() else to_chat(user, "[src] already has a cell.") + else + return ..() - else if(iswirecutter(W)) - if(cell) - to_chat(user, "You cut [cell] away from [src].") - cell.forceMove(get_turf(loc)) - cell = null - update_icon() +/obj/item/clothing/gloves/color/yellow/stun/wirecutter_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(cell) + to_chat(user, "You cut [cell] away from [src].") + cell.forceMove(get_turf(loc)) + cell = null + update_icon() /obj/item/clothing/gloves/fingerless/rapid name = "Gloves of the North Star" diff --git a/code/modules/clothing/gloves/rings.dm b/code/modules/clothing/gloves/rings.dm index 6bef80bfe6d..29e5af2121a 100644 --- a/code/modules/clothing/gloves/rings.dm +++ b/code/modules/clothing/gloves/rings.dm @@ -9,16 +9,14 @@ var/fluff_material = FALSE //If true, will ignore the material when examining var/material = "iron" var/stud = 0 + var/ring_color = "iron" /obj/item/clothing/gloves/ring/New() ..() update_icon() /obj/item/clothing/gloves/ring/update_icon() - if(stud) - icon_state = "d_[initial(icon_state)]" - else - icon_state = initial(icon_state) + icon_state = "[stud ? "d_" : ""][ring_color]ring" /obj/item/clothing/gloves/ring/examine(mob/user) . = ..() @@ -44,6 +42,7 @@ name = "silver ring" icon_state = "silverring" material = "silver" + ring_color = "silver" /obj/item/clothing/gloves/ring/silver/blessed // todo name = "blessed silver ring" @@ -52,6 +51,7 @@ name = "gold ring" icon_state = "goldring" material = "gold" + ring_color = "gold" /obj/item/clothing/gloves/ring/gold/blessed name = "wedding band" @@ -61,40 +61,45 @@ name = "white plastic ring" icon_state = "whitering" material = "plastic" + ring_color = "white" /obj/item/clothing/gloves/ring/plastic/blue name = "blue plastic ring" icon_state = "bluering" + ring_color = "blue" /obj/item/clothing/gloves/ring/plastic/red name = "red plastic ring" icon_state = "redring" - -/obj/item/clothing/gloves/ring/plastic/random + ring_color = "red" /obj/item/clothing/gloves/ring/plastic/random/New() - var/c = pick("white","blue","red") - name = "[c] plastic ring" - icon_state = "[c]ring" + ring_color = pick("white","blue","red") + name = "[ring_color] plastic ring" + ..() // weird /obj/item/clothing/gloves/ring/glass name = "glass ring" icon_state = "whitering" material = "glass" + ring_color = "white" /obj/item/clothing/gloves/ring/plasma name = "plasma ring" icon_state = "plasmaring" material = "plasma" + ring_color = "plasma" /obj/item/clothing/gloves/ring/uranium name = "uranium ring" icon_state = "uraniumring" material = "uranium" + ring_color = "uranium" // cultish /obj/item/clothing/gloves/ring/shadow name = "shadow ring" icon_state = "shadowring" material = "shadows" + ring_color = "shadow" diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index 789696ae874..867a50cb70f 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -135,14 +135,7 @@ materials = list(MAT_METAL=500, MAT_GLASS=50) /obj/item/clothing/mask/muzzle/safety/shock/attackby(obj/item/W, mob/user, params) - if(isscrewdriver(W) && trigger) - to_chat(user, "You disassemble [src].") - trigger.forceMove(get_turf(user)) - trigger.master = null - trigger.holder = null - trigger = null - return TRUE - else if(istype(W, /obj/item/assembly/signaler) || istype(W, /obj/item/assembly/voice)) + if(istype(W, /obj/item/assembly/signaler) || istype(W, /obj/item/assembly/voice)) if(istype(trigger, /obj/item/assembly/signaler) || istype(trigger, /obj/item/assembly/voice)) to_chat(user, "Something is already attached to [src].") return FALSE @@ -161,6 +154,17 @@ return ..() +/obj/item/clothing/mask/muzzle/safety/shock/screwdriver_act(mob/user, obj/item/I) + if(!trigger) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + to_chat(user, "You remove [trigger] from [src].") + trigger.forceMove(get_turf(user)) + trigger.master = null + trigger.holder = null + trigger = null /obj/item/clothing/mask/muzzle/safety/shock/proc/can_shock(obj/item/clothing/C) if(istype(C)) diff --git a/code/modules/clothing/spacesuits/breaches.dm b/code/modules/clothing/spacesuits/breaches.dm index c8891fde00d..483c122fd80 100644 --- a/code/modules/clothing/spacesuits/breaches.dm +++ b/code/modules/clothing/spacesuits/breaches.dm @@ -194,25 +194,18 @@ var/global/list/breach_burn_descriptors = list( repair_breaches(BURN, ( istype(P,/obj/item/stack/sheet/plastic) ? 3 : 5), user) return - else if(istype(W, /obj/item/weldingtool)) - if(istype(src.loc,/mob/living)) - to_chat(user, "How do you intend to patch a hardsuit while someone is wearing it?") - return - - if(!damage || ! brute_damage) - to_chat(user, "There is no structural damage on \the [src] to repair.") - return - - var/obj/item/weldingtool/WT = W - if(!WT.remove_fuel(5)) - to_chat(user, "You need more welding fuel to repair this suit.") - return - - repair_breaches(BRUTE, 3, user) +/obj/item/clothing/suit/space/welder_act(mob/user, obj/item/I) + . = TRUE + if(istype(src.loc,/mob/living)) + to_chat(user, "How do you intend to patch a hardsuit while someone is wearing it?") return - - ..() + if(!damage || ! brute_damage) + to_chat(user, "There is no structural damage on \the [src] to repair.") + return + if(!I.use_tool(src, user, amount = 5, volume = I.tool_volume)) + return + repair_breaches(BRUTE, 3, user) /obj/item/clothing/suit/space/examine(mob/user) . = ..() diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index 32b594b1387..f9366e12778 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -138,21 +138,23 @@ jetpack = I to_chat(user, "You successfully install the jetpack into [src].") return - else if(isscrewdriver(I)) - if(!jetpack) - to_chat(user, "[src] has no jetpack installed.") - return - if(src == user.get_item_by_slot(slot_wear_suit)) - to_chat(user, "You cannot remove the jetpack from [src] while wearing it.") - return - - jetpack.turn_off(user) - jetpack.forceMove(drop_location()) - jetpack = null - to_chat(user, "You successfully remove the jetpack from [src].") - return return ..() +/obj/item/clothing/suit/space/hardsuit/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!jetpack) + to_chat(user, "[src] has no jetpack installed.") + return + if(src == user.get_item_by_slot(slot_wear_suit)) + to_chat(user, "You cannot remove the jetpack from [src] while wearing it.") + return + jetpack.turn_off(user) + jetpack.forceMove(drop_location()) + jetpack = null + to_chat(user, "You successfully remove the jetpack from [src].") + /obj/item/clothing/suit/space/hardsuit/equipped(mob/user, slot) ..() if(jetpack) @@ -560,24 +562,24 @@ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi jetpack = /obj/item/tank/jetpack/suit -/obj/item/clothing/suit/space/hardsuit/shielded/syndi/attackby(obj/item/I, mob/user, params) - if(ismultitool(I)) - if(shield_state == "broken") - to_chat(user, "You can't interface with the hardsuit's software if the shield's broken!") - return - - if(shield_state == "shield-red") - shield_state = "shield-old" - shield_on = "shield-old" - to_chat(user, "You roll back the hardsuit's software, changing the shield's color!") - - else - shield_state = "shield-red" - shield_on = "shield-red" - to_chat(user, "You update the hardsuit's hardware, changing back the shield's color to red.") - user.update_inv_wear_suit() +/obj/item/clothing/suit/space/hardsuit/shielded/syndi/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return - return ..() + if(shield_state == "broken") + to_chat(user, "You can't interface with the hardsuit's software if the shield's broken!") + return + + if(shield_state == "shield-red") + shield_state = "shield-old" + shield_on = "shield-old" + to_chat(user, "You roll back the hardsuit's software, changing the shield's color!") + + else + shield_state = "shield-red" + shield_on = "shield-red" + to_chat(user, "You update the hardsuit's hardware, changing back the shield's color to red.") + user.update_inv_wear_suit() /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi name = "blood-red hardsuit helmet" diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index a786364e4e2..f516627e182 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -229,7 +229,6 @@ armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20, fire = 50, acid = 65) flash_protect = 0 species_restricted = list("exclude", "Wryn") - sprite_sheets = list( "Tajaran" = 'icons/mob/species/tajaran/helmet.dmi', "Unathi" = 'icons/mob/species/unathi/helmet.dmi', @@ -249,8 +248,9 @@ desc = ". . ." icon_state = "spacemimehelmet" item_state = "spacemimehelmet" - species_restricted = list("exclude","Vox","Wryn") - sprite_sheets = null + species_restricted = list("exclude","Wryn") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/helmet.dmi') sprite_sheets_obj = null /obj/item/clothing/suit/space/eva/mime @@ -259,8 +259,9 @@ desc = ". . ." icon_state = "spacemime_suit" item_state = "spacemime_items" - species_restricted = list("exclude","Vox","Wryn") - sprite_sheets = null + species_restricted = list("exclude","Wryn") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/suit.dmi') sprite_sheets_obj = null /obj/item/clothing/head/helmet/space/eva/clown @@ -269,8 +270,9 @@ desc = "An EVA helmet specifically designed for the clown. SPESSHONK!" icon_state = "clownhelmet" item_state = "clownhelmet" - species_restricted = list("exclude","Vox","Wryn") - sprite_sheets = null + species_restricted = list("exclude","Wryn") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/helmet.dmi') sprite_sheets_obj = null /obj/item/clothing/suit/space/eva/clown @@ -279,6 +281,7 @@ desc = "An EVA suit specifically designed for the clown. SPESSHONK!" icon_state = "spaceclown_suit" item_state = "spaceclown_items" - species_restricted = list("exclude","Vox","Wryn") - sprite_sheets = null + species_restricted = list("exclude","Wryn") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/suit.dmi') sprite_sheets_obj = null diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index 73b95c0d3f7..bd35abb19a6 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -62,14 +62,21 @@ actions_types = list(/datum/action/item_action/toggle_helmet_light) /obj/item/clothing/head/helmet/space/plasmaman/attack_self(mob/user) + toggle_light(user) + +/obj/item/clothing/head/helmet/space/plasmaman/proc/toggle_light(mob/user) on = !on icon_state = "[initial(icon_state)][on ? "-light":""]" item_state = icon_state - user.update_inv_head() //So the mob overlay updates + + var/mob/living/carbon/human/H = user + if(istype(H)) + H.update_inv_head() if(on) if(!up) - to_chat(user, "Your helmet's torch can't pass through your welding visor!") + if(istype(H)) + to_chat(user, "Your helmet's torch can't pass through your welding visor!") set_light(0) else set_light(brightness_on) @@ -80,6 +87,10 @@ var/datum/action/A=X A.UpdateButtonIcon() +/obj/item/clothing/head/helmet/space/plasmaman/extinguish_light() + if(on) + toggle_light() + /obj/item/clothing/head/helmet/space/plasmaman/security name = "security plasma envirosuit helmet" desc = "A plasmaman containment helmet designed for security officers, protecting them from being flashed and burning alive, along-side other undesirables." diff --git a/code/modules/clothing/spacesuits/rig/modules/utility.dm b/code/modules/clothing/spacesuits/rig/modules/utility.dm index e87e35a0dea..4b19d2a7753 100644 --- a/code/modules/clothing/spacesuits/rig/modules/utility.dm +++ b/code/modules/clothing/spacesuits/rig/modules/utility.dm @@ -465,18 +465,12 @@ else to_chat(holder.wearer, "You need to have a welding tool in one of your hands to dispense fuel.") -/obj/item/rig_module/welding_tank/proc/fill_welder(var/obj/item/weldingtool/W) +/obj/item/rig_module/welding_tank/proc/fill_welder(obj/item/weldingtool/W) if(!istype(W)) - return 0 - - if(reagents) - if(get_fuel() >= W.max_fuel) - reagents.trans_to(W, W.max_fuel) - to_chat(holder.wearer, "Your [holder] dispenses some of the contents of the welding fuel tank into \the [W].") - else - reagents.trans_to(W, W.max_fuel) - to_chat(holder.wearer, "You hear a faint dripping as your hardsuit welding tank completely empties.") - W.update_icon() + return + W.refill(holder.wearer, src, W.maximum_fuel) + if(!reagents.get_reagent_amount("fuel")) + to_chat(holder.wearer, "You hear a faint dripping as your hardsuit welding tank completely empties.") /obj/item/rig_module/welding_tank/proc/get_fuel() return reagents.get_reagent_amount("fuel") diff --git a/code/modules/clothing/spacesuits/syndi.dm b/code/modules/clothing/spacesuits/syndi.dm index 44d9946dfd6..a1043eb2643 100644 --- a/code/modules/clothing/spacesuits/syndi.dm +++ b/code/modules/clothing/spacesuits/syndi.dm @@ -6,6 +6,13 @@ item_state = "syndicate" desc = "Has a tag on it: Totally not property of a hostile corporation, honest!" armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85) + sprite_sheets = list( + "Grey" = 'icons/mob/species/grey/helmet.dmi', + "Tajaran" = 'icons/mob/species/tajaran/helmet.dmi', + "Unathi" = 'icons/mob/species/unathi/helmet.dmi', + "Vulpkanin" = 'icons/mob/species/vulpkanin/helmet.dmi', + "Vox" = 'icons/mob/species/vox/helmet.dmi') + /obj/item/clothing/suit/space/syndicate name = "red space suit" @@ -15,6 +22,11 @@ w_class = WEIGHT_CLASS_NORMAL allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword/saber,/obj/item/restraints/handcuffs,/obj/item/tank) armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85) + sprite_sheets = list( + "Tajaran" = 'icons/mob/species/tajaran/suit.dmi', + "Unathi" = 'icons/mob/species/unathi/suit.dmi', + "Vulpkanin" = 'icons/mob/species/vulpkanin/suit.dmi', + "Vox" = 'icons/mob/species/vox/suit.dmi') //Green syndicate space suit diff --git a/code/modules/clothing/spacesuits/void.dm b/code/modules/clothing/spacesuits/void.dm index cd3bb043cae..0f97be88e10 100644 --- a/code/modules/clothing/spacesuits/void.dm +++ b/code/modules/clothing/spacesuits/void.dm @@ -6,6 +6,12 @@ icon_state = "void-red" item_state = "void" flags_inv = HIDEMASK|HIDEEARS + sprite_sheets = list( + "Grey" = 'icons/mob/species/grey/helmet.dmi', + "Tajaran" = 'icons/mob/species/tajaran/helmet.dmi', + "Unathi" = 'icons/mob/species/unathi/helmet.dmi', + "Vulpkanin" = 'icons/mob/species/vulpkanin/helmet.dmi', + "Vox" = 'icons/mob/species/vox/helmet.dmi') /obj/item/clothing/suit/space/nasavoid name = "NASA Void Suit" @@ -13,6 +19,11 @@ item_state = "void" desc = "A high tech, NASA Centcom branch designed space suit. Used for AI satellite maintenance." allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/multitool) + sprite_sheets = list( + "Tajaran" = 'icons/mob/species/tajaran/suit.dmi', + "Unathi" = 'icons/mob/species/unathi/suit.dmi', + "Vulpkanin" = 'icons/mob/species/vulpkanin/suit.dmi', + "Vox" = 'icons/mob/species/vox/suit.dmi') //Colors!!! /obj/item/clothing/head/helmet/space/nasavoid/green diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 9e009014deb..5203aafdcf6 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -96,38 +96,35 @@ item_color = "centcom" /obj/item/clothing/under/rank/centcom/officer - desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Lieutenant-Commander\" and bears \"N.C.V. Fearless CV-286\" on the left shoulder." - name = "\improper Nanotrasen Officers Uniform" - icon_state = "officer" - item_state = "g_suit" - item_color = "officer" + desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Lieutenant-Commander\" and bears \"N.A.S. Trurl \" on the left shoulder. Worn exclusively by officers of the Nanotrasen Navy. It's got exotic materials for protection." + name = "\improper Nanotrasen Naval Officer Uniform" + icon_state = "navy_gold" + item_state = "navy_gold" + item_color = "navy_gold" displays_id = 0 flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/centcom/captain - desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Captain\" and bears \"N.C.V. Fearless CV-286\" on the left shoulder." - name = "\improper Nanotrasen Captains Uniform" - icon_state = "centcom" - item_state = "dg_suit" - item_color = "centcom" + desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Captain\" and bears \"N.A.S. Trurl \" on the left shoulder. Worn exclusively by officers of the Nanotrasen Navy. It's got exotic materials for protection." + name = "\improper Nanotrasen Naval Captain Uniform" + icon_state = "navy_gold" + item_state = "navy_gold" + item_color = "navy_gold" displays_id = 0 + flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/centcom/blueshield - desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Lieutenant\" and bears \"N.S.S. Cyberiad\" on the left shoulder." - name = "\improper Nanotrasen Navy Uniform" + desc = "Gold trim on space-black cloth, this uniform bears \"Close Protection\" on the left shoulder." + name = "\improper Formal Nanotrasen Uniform" icon_state = "officer" item_state = "g_suit" item_color = "officer" displays_id = 0 flags_size = ONESIZEFITSALL -/obj/item/clothing/under/rank/centcom/blueshield/New() - ..() - desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Lieutenant\" and bears [station_name()] on the left shoulder." - /obj/item/clothing/under/rank/centcom/representative - desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Ensign\" and bears \"N.S.S. Cyberiad\" on the left shoulder." - name = "\improper Nanotrasen Navy Uniform" + desc = "Gold trim on space-black cloth, this uniform bears \"N.S.S. Cyberiad\" on the left shoulder." + name = "\improper Formal Nanotrasen Uniform" icon_state = "officer" item_state = "g_suit" item_color = "officer" @@ -136,11 +133,11 @@ /obj/item/clothing/under/rank/centcom/representative/New() ..() - desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Ensign\" and bears [station_name()] on the left shoulder." + desc = "Gold trim on space-black cloth, this uniform bears [station_name()] on the left shoulder." /obj/item/clothing/under/rank/centcom/magistrate desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Magistrate\" and bears \"N.S.S. Cyberiad\" on the left shoulder." - name = "\improper Nanotrasen Navy Uniform" + name = "\improper Formal Nanotrasen Uniform" icon_state = "officer" item_state = "g_suit" item_color = "officer" @@ -161,7 +158,7 @@ /obj/item/clothing/under/rank/blueshield name = "blueshield uniform" - desc = "A short-sleeved black uniform, paired with grey digital-camo cargo pants. Standard issue to Blueshield officers." + desc = "A short-sleeved black uniform, paired with grey digital-camo cargo pants. Standard issue to Blueshields." icon_state = "ert_uniform" item_state = "bl_suit" item_color = "ert_uniform" @@ -169,7 +166,7 @@ /obj/item/clothing/under/rank/blueshield/skirt name = "blueshield skirt" - desc = "A short, black and grey with blue markings skirted uniform. For the feminine Blueshield officers." + desc = "A short, black and grey with blue markings skirted uniform. For the feminine Blueshield." icon_state = "blueshieldf" item_state = "blueshieldf" item_color = "blueshieldf" diff --git a/code/modules/crafting/craft.dm b/code/modules/crafting/craft.dm index 391338fc181..36f0da802cc 100644 --- a/code/modules/crafting/craft.dm +++ b/code/modules/crafting/craft.dm @@ -89,7 +89,8 @@ /datum/personal_crafting/proc/get_surroundings(mob/user) . = list() - .["other"] = list() + .["other"] = list() //paths go in here + .["toolsother"] = list() // items go in here for(var/obj/item/I in get_environment(user)) if(I.flags_2 & HOLOGRAM_2) continue @@ -102,47 +103,78 @@ if(RC.is_drainable()) for(var/datum/reagent/A in RC.reagents.reagent_list) .["other"][A.type] += A.volume - .["other"][I.type] += 1 + .["other"][I.type] += 1 + .["toolsother"][I] += 1 /datum/personal_crafting/proc/check_tools(mob/user, datum/crafting_recipe/R, list/contents) - if(!R.tools.len) + if(!R.tools.len) //does not run if no tools are needed return TRUE var/list/possible_tools = list() - for(var/obj/item/I in user.contents) + var/list/tools_used = list() + for(var/obj/item/I in user.contents) //searchs the inventory of the mob if(istype(I, /obj/item/storage)) for(var/obj/item/SI in I.contents) - possible_tools += SI.type - possible_tools += I.type - possible_tools |= contents["other"] + if(SI.tool_behaviour) //filters for tool behaviours + possible_tools += SI + if(I.tool_behaviour) + possible_tools += I - main_loop: + possible_tools |= contents["toolsother"] // this add contents to possible_tools + main_loop: // checks if all tools found are usable with the recipe for(var/A in R.tools) - for(var/I in possible_tools) + for(var/obj/item/I in possible_tools) + if(A == I.tool_behaviour) + tools_used += I + continue main_loop + return FALSE + for(var/obj/item/T in tools_used) + if(!T.tool_start_check(user, 0)) //Check if all our tools are valid for their use + return FALSE + return TRUE + +/datum/personal_crafting/proc/check_pathtools(mob/user, datum/crafting_recipe/R, list/contents) + if(!R.pathtools.len) //does not run if no tools are needed + return TRUE + var/list/other_possible_tools = list() + for(var/obj/item/I in user.contents) // searchs the inventory of the mob + if(istype(I, /obj/item/storage)) + for(var/obj/item/SI in I.contents) + other_possible_tools += SI.type // filters type paths + other_possible_tools += I.type + + other_possible_tools |= contents["other"] // this adds contents to the other_possible_tools + main_loop: // checks if all tools found are usable with the recipe + for(var/A in R.pathtools) + for(var/I in other_possible_tools) if(ispath(I,A)) continue main_loop return FALSE return TRUE -/datum/personal_crafting/proc/construct_item(mob/user, datum/crafting_recipe/R) +/datum/personal_crafting/proc/construct_item(mob/user, datum/crafting_recipe/R) var/list/contents = get_surroundings(user) var/send_feedback = 1 if(check_contents(R, contents)) if(check_tools(user, R, contents)) - if(do_after(user, R.time, target = user)) - contents = get_surroundings(user) - if(!check_contents(R, contents)) - return ", missing component." - if(!check_tools(user, R, contents)) - return ", missing tool." - var/list/parts = del_reqs(R, user) - var/atom/movable/I = new R.result (get_turf(user.loc)) - I.CheckParts(parts, R) - if(isitem(I)) - user.put_in_hands(I) - if(send_feedback) - feedback_add_details("object_crafted","[I.type]") - return 0 - return "." + if(check_pathtools(user, R, contents)) + if(do_after(user, R.time, target = user)) + contents = get_surroundings(user) + if(!check_contents(R, contents)) + return ", missing component." + if(!check_tools(user, R, contents)) + return ", missing tool." + if(!check_pathtools(user, R, contents)) + return ", missing tool." + var/list/parts = del_reqs(R, user) + var/atom/movable/I = new R.result (get_turf(user.loc)) + I.CheckParts(parts, R) + if(isitem(I)) + user.put_in_hands(I) + if(send_feedback) + feedback_add_details("object_crafted","[I.type]") + return 0 + return "." + return ", missing tool." return ", missing tool." return ", missing component." @@ -407,12 +439,15 @@ catalyst_text = replacetext(catalyst_text, ",", "", -1) data["catalyst_text"] = catalyst_text - for(var/a in R.tools) + for(var/a in R.pathtools) if(ispath(a, /obj/item)) var/obj/item/b = a tool_text += " [initial(b.name)]," else tool_text += " [a]," + for(var/a in R.tools) + var/b = a + tool_text += " [b]," tool_text = replacetext(tool_text, ",", "", -1) data["tool_text"] = tool_text diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm index b49e20f1302..ec334979cd2 100644 --- a/code/modules/crafting/recipes.dm +++ b/code/modules/crafting/recipes.dm @@ -3,7 +3,8 @@ var/reqs[] = list() //type paths of items consumed associated with how many are needed var/blacklist[] = list() //type paths of items explicitly not allowed as an ingredient var/result //type path of item resulting from this craft - var/tools[] = list() //type paths of items needed but not consumed + var/tools[] = list() //tool behaviours of items needed but not consumed + var/pathtools[] = list() //type paths of items needed but not consumed var/time = 30 //time in deciseconds var/parts[] = list() //type paths of items that will be placed in the result var/chem_catalysts[] = list() //like tools but for reagents @@ -65,7 +66,7 @@ /obj/item/gun/energy/gun/advtaser = 1, /obj/item/stock_parts/cell = 1, /obj/item/assembly/prox_sensor = 1) - tools = list(/obj/item/weldingtool, /obj/item/screwdriver) + tools = list(TOOL_WELDER, TOOL_SCREWDRIVER) time = 60 category = CAT_ROBOT @@ -77,7 +78,7 @@ /obj/item/melee/baton = 1, /obj/item/assembly/prox_sensor = 1, /obj/item/robot_parts/r_arm = 1) - tools = list(/obj/item/weldingtool) + tools = list(TOOL_WELDER) time = 60 category = CAT_ROBOT @@ -90,7 +91,7 @@ /obj/item/assembly/prox_sensor = 1, /obj/item/robot_parts/r_arm = 2, /obj/item/robot_parts/l_arm = 2) - tools = list(/obj/item/weldingtool) + tools = list(TOOL_WELDER) time = 120 category = CAT_ROBOT @@ -142,7 +143,7 @@ /obj/item/stack/rods = 1) parts = list(/obj/item/assembly/igniter = 1, /obj/item/weldingtool = 1) - tools = list(/obj/item/screwdriver) + tools = list(TOOL_SCREWDRIVER) time = 10 category = CAT_WEAPONRY subcategory = CAT_WEAPON @@ -153,7 +154,7 @@ reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1, /obj/item/rcd_ammo = 1, /obj/item/stock_parts/manipulator = 2) - tools = list(/obj/item/screwdriver) + tools = list(TOOL_SCREWDRIVER) time = 5 category = CAT_WEAPONRY subcategory = CAT_AMMO @@ -164,7 +165,7 @@ reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1, /obj/item/stock_parts/capacitor/adv = 2, /obj/item/stock_parts/micro_laser/ultra = 1) - tools = list(/obj/item/screwdriver) + tools = list(TOOL_SCREWDRIVER) time = 5 category = CAT_WEAPONRY subcategory = CAT_AMMO @@ -174,7 +175,7 @@ result = /obj/item/ammo_casing/shotgun/incendiary/dragonsbreath reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1, /datum/reagent/phosphorus = 5,) - tools = list(/obj/item/screwdriver) + tools = list(TOOL_SCREWDRIVER) time = 5 category = CAT_WEAPONRY subcategory = CAT_AMMO @@ -186,7 +187,7 @@ /datum/reagent/glycerol = 5, /datum/reagent/acid = 5, /datum/reagent/acid/facid = 5,) - tools = list(/obj/item/screwdriver) + tools = list(TOOL_SCREWDRIVER) time = 5 category = CAT_WEAPONRY subcategory = CAT_AMMO @@ -197,7 +198,7 @@ reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1, /obj/item/stock_parts/micro_laser/ultra = 1, /obj/item/stock_parts/subspace/crystal = 1) - tools = list(/obj/item/screwdriver) + tools = list(TOOL_SCREWDRIVER) time = 5 category = CAT_WEAPONRY subcategory = CAT_AMMO @@ -209,7 +210,7 @@ /obj/item/stack/sheet/metal = 1, /obj/item/stack/cable_coil = 1, /datum/reagent/fuel = 10) - tools = list(/obj/item/screwdriver) + tools = list(TOOL_SCREWDRIVER) time = 5 category = CAT_WEAPONRY subcategory = CAT_AMMO @@ -220,7 +221,7 @@ reqs = list(/obj/item/ammo_casing/shotgun/improvised = 1, /datum/reagent/blackpowder = 10, /datum/reagent/plasma_dust = 20) - tools = list(/obj/item/screwdriver) + tools = list(TOOL_SCREWDRIVER) time = 5 category = CAT_WEAPONRY subcategory = CAT_AMMO @@ -231,7 +232,7 @@ reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1, /obj/item/stock_parts/capacitor/adv = 1, /obj/item/stock_parts/micro_laser/high = 1) - tools = list(/obj/item/screwdriver) + tools = list(TOOL_SCREWDRIVER) time = 5 category = CAT_WEAPONRY subcategory = CAT_AMMO @@ -243,7 +244,7 @@ /obj/item/pipe = 1, /obj/item/weaponcrafting/stock = 1, /obj/item/stack/packageWrap = 5,) - tools = list(/obj/item/screwdriver) + tools = list(TOOL_SCREWDRIVER) time = 100 category = CAT_WEAPONRY subcategory = CAT_WEAPON @@ -254,7 +255,7 @@ reqs = list(/obj/item/circular_saw = 1, /obj/item/stack/cable_coil = 1, /obj/item/stack/sheet/plasteel = 1) - tools = list(/obj/item/weldingtool) + tools = list(TOOL_WELDER) time = 50 category = CAT_WEAPONRY subcategory = CAT_WEAPON @@ -307,7 +308,7 @@ time = 15 reqs = list(/obj/item/stack/sheet/wood = 1, /obj/item/stack/cable_coil = 5) - tools = list(/obj/item/kitchen/knife) // Gotta carve the wood into handles + pathtools = list(/obj/item/kitchen/knife) // Gotta carve the wood into handles category = CAT_WEAPONRY subcategory = CAT_WEAPON @@ -316,7 +317,7 @@ result = /obj/item/arrow/rod time = 5 reqs = list(/obj/item/stack/rods = 1) - tools = list(/obj/item/weldingtool) + tools = list(TOOL_WELDER) category = CAT_WEAPONRY subcategory = CAT_AMMO @@ -328,8 +329,7 @@ /obj/item/stack/cable_coil = 10, /obj/item/stack/sheet/plastic = 3, /obj/item/stack/sheet/wood = 5) - tools = list(/obj/item/weldingtool, - /obj/item/screwdriver) + tools = list(TOOL_WELDER, TOOL_SCREWDRIVER) category = CAT_WEAPONRY subcategory = CAT_WEAPON @@ -354,7 +354,7 @@ result = /obj/item/stack/tile/carpet/black time = 20 reqs = list(/obj/item/stack/tile/carpet = 1) - tools = list(/obj/item/toy/crayon) + pathtools = list(/obj/item/toy/crayon) category = CAT_MISC /datum/crafting_recipe/showercurtain @@ -525,7 +525,7 @@ reqs = list(/obj/item/stack/sheet/plasteel = 3, /obj/item/stack/sheet/wood = 20, /obj/item/stack/cable_coil = 10) - tools = list(/obj/item/screwdriver, /obj/item/wrench, /obj/item/weldingtool) + tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER) category = CAT_MISC /datum/crafting_recipe/drill @@ -537,7 +537,7 @@ /obj/item/stock_parts/cell = 1, /obj/item/stack/rods = 2, /obj/item/assembly/timer = 1) - tools = list(/obj/item/screwdriver, /obj/item/wrench) + tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH) category = CAT_MISC /datum/crafting_recipe/d_drill @@ -549,7 +549,7 @@ /obj/item/stock_parts/cell = 1, /obj/item/stack/rods = 2, /obj/item/assembly/prox_sensor = 1) // Not a timer because the system sees a diamond drill as a drill too, letting you make both otherwise. - tools = list(/obj/item/screwdriver, /obj/item/wrench) + tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH) category = CAT_MISC /datum/crafting_recipe/faketoolbox @@ -559,7 +559,7 @@ reqs = list(/datum/reagent/paint/red = 10, /datum/reagent/paint/black = 30, /obj/item/storage/toolbox = 1) //Paint in reagents so it doesnt take the container up, yet still take it from the beaker - tools = list(/obj/item/reagent_containers/glass/rag = 1) //need something to paint with it + pathtools = list(/obj/item/reagent_containers/glass/rag = 1) //need something to paint with it category = CAT_MISC /datum/crafting_recipe/snowman @@ -578,152 +578,153 @@ result = /obj/item/decorations/sticky_decorations/flammable/heart reqs = list(/obj/item/paper = 1, /obj/item/stack/tape_roll = 1) - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/red)//cutters act as makeshift scissors. I doubt the barber wants to have their scissors stolen when somone wants to decorate + tools = list(TOOL_WIRECUTTER) //cutters act as makeshift scissors. I doubt the barber wants to have their scissors stolen when somone wants to decorate + pathtools = list(/obj/item/toy/crayon/red) category = CAT_DECORATIONS subcategory = CAT_DECORATION /datum/crafting_recipe/paper_craft/single_eye name = "Paper Eye" result = /obj/item/decorations/sticky_decorations/flammable/singleeye - tools = list(/obj/item/wirecutters, - /obj/item/pen, - /obj/item/toy/crayon/blue) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/pen, /obj/item/toy/crayon/blue) category = CAT_DECORATIONS subcategory = CAT_DECORATION /datum/crafting_recipe/paper_craft/googlyeyes name = "Paper Googly Eye" result = /obj/item/decorations/sticky_decorations/flammable/googlyeyes - tools = list(/obj/item/wirecutters, - /obj/item/pen) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/pen) category = CAT_DECORATIONS subcategory = CAT_DECORATION /datum/crafting_recipe/paper_craft/clock name = "Paper Clock" result = /obj/item/decorations/sticky_decorations/flammable/paperclock - tools = list(/obj/item/wirecutters, - /obj/item/pen) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/pen) category = CAT_DECORATIONS subcategory = CAT_DECORATION /datum/crafting_recipe/paper_craft/jack_o_lantern name = "Paper Jack o'Lantern" result = /obj/item/decorations/sticky_decorations/flammable/jack_o_lantern - tools = list(/obj/item/wirecutters, - /obj/item/pen, - /obj/item/toy/crayon/orange, - /obj/item/toy/crayon/green)//pen ink is black + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/pen, + /obj/item/toy/crayon/orange, + /obj/item/toy/crayon/green)//pen ink is black category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/ghost name = "Paper Ghost" result = /obj/item/decorations/sticky_decorations/flammable/ghost - tools = list(/obj/item/wirecutters, - /obj/item/pen)//it's white paper why need a white crayon? + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/pen)//it's white paper why need a white crayon? category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/spider name = "Paper Spider" result = /obj/item/decorations/sticky_decorations/flammable/spider - tools = list(/obj/item/wirecutters, - /obj/item/pen, - /obj/item/toy/crayon/red) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/pen, + /obj/item/toy/crayon/red) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/spiderweb name = "Paper Spiderweb" result = /obj/item/decorations/sticky_decorations/flammable/spiderweb - tools = list(/obj/item/wirecutters) + tools = list(TOOL_WIRECUTTER) + pathtools = list() category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/skull name = "Paper Skull" result = /obj/item/decorations/sticky_decorations/flammable/skull - tools = list(/obj/item/wirecutters, - /obj/item/pen) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/pen) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/skeleton name = "Paper Skeleton" result = /obj/item/decorations/sticky_decorations/flammable/skeleton - tools = list(/obj/item/wirecutters, - /obj/item/pen) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/pen) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/cauldron name = "Paper Cauldron" result = /obj/item/decorations/sticky_decorations/flammable/cauldron - tools = list(/obj/item/wirecutters, - /obj/item/pen) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/pen) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/snowman name = "Paper Snowman" result = /obj/item/decorations/sticky_decorations/flammable/snowman - tools = list(/obj/item/wirecutters, - /obj/item/pen, - /obj/item/toy/crayon/orange) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/pen, + /obj/item/toy/crayon/orange) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/christmas_stocking name = "Paper Christmas Stocking" result = /obj/item/decorations/sticky_decorations/flammable/christmas_stocking - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/red) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/red) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/christmas_tree name = "Paper Christmas Tree" result = /obj/item/decorations/sticky_decorations/flammable/christmas_tree - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/red, - /obj/item/toy/crayon/yellow, - /obj/item/toy/crayon/blue, - /obj/item/toy/crayon/green) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/red, + /obj/item/toy/crayon/yellow, + /obj/item/toy/crayon/blue, + /obj/item/toy/crayon/green) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/snowflake name = "Paper Snowflake" result = /obj/item/decorations/sticky_decorations/flammable/snowflake - tools = list(/obj/item/wirecutters) + tools = list(TOOL_WIRECUTTER) + pathtools = list() category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/candy_cane name = "Paper Candy Cane" result = /obj/item/decorations/sticky_decorations/flammable/candy_cane - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/red) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/red) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/mistletoe name = "Paper Mistletoe" result = /obj/item/decorations/sticky_decorations/flammable/mistletoe - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/red, - /obj/item/toy/crayon/green) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/red, + /obj/item/toy/crayon/green) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/holly name = "Paper Holly" result = /obj/item/decorations/sticky_decorations/flammable/holly - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/red, - /obj/item/toy/crayon/green) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/red, + /obj/item/toy/crayon/green) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -733,7 +734,8 @@ result = /obj/item/decorations/sticky_decorations/flammable/tinsel reqs = list(/obj/item/paper = 1, /obj/item/stack/tape_roll = 2) - tools = list(/obj/item/wirecutters) + tools = list(TOOL_WIRECUTTER) + pathtools = list() category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -743,8 +745,8 @@ result = /obj/item/decorations/sticky_decorations/flammable/tinsel/red reqs = list(/obj/item/paper = 1, /obj/item/stack/tape_roll = 2) - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/red) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/red) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -754,8 +756,8 @@ result = /obj/item/decorations/sticky_decorations/flammable/tinsel/blue reqs = list(/obj/item/paper = 1, /obj/item/stack/tape_roll = 2) - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/blue) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/blue) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -765,8 +767,8 @@ result = /obj/item/decorations/sticky_decorations/flammable/tinsel/yellow reqs = list(/obj/item/paper = 1, /obj/item/stack/tape_roll = 2) - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/yellow) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/yellow) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -776,8 +778,8 @@ result = /obj/item/decorations/sticky_decorations/flammable/tinsel/purple reqs = list(/obj/item/paper = 1, /obj/item/stack/tape_roll = 2) - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/purple) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/purple) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -787,8 +789,8 @@ result = /obj/item/decorations/sticky_decorations/flammable/tinsel/green reqs = list(/obj/item/paper = 1, /obj/item/stack/tape_roll = 2) - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/green) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/green) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -798,8 +800,8 @@ result = /obj/item/decorations/sticky_decorations/flammable/tinsel/orange reqs = list(/obj/item/paper = 1, /obj/item/stack/tape_roll = 2) - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/orange) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/orange) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -809,8 +811,8 @@ result = /obj/item/decorations/sticky_decorations/flammable/tinsel/black reqs = list(/obj/item/paper = 1, /obj/item/stack/tape_roll = 2) - tools = list(/obj/item/wirecutters, - /obj/item/pen) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/pen) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -820,17 +822,17 @@ result = /obj/item/decorations/sticky_decorations/flammable/tinsel/halloween reqs = list(/obj/item/paper = 1, /obj/item/stack/tape_roll = 2) - tools = list(/obj/item/wirecutters, - /obj/item/pen, - /obj/item/toy/crayon/orange) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/pen, + /obj/item/toy/crayon/orange) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/arrowed_heart name = "Paper Arrowed Heart" result = /obj/item/decorations/sticky_decorations/flammable/arrowed_heart - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/red) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/red) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -840,24 +842,24 @@ reqs = list(/obj/item/paper = 1, /obj/item/stack/tape_roll = 2, /obj/item/stack/cable_coil = 2) - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/red) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/red) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/four_leaf_clover name = "Paper Four Leaf Clover" result = /obj/item/decorations/sticky_decorations/flammable/four_leaf_clover - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/green) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/green) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/pot_of_gold name = "Paper Pot of Gold" result = /obj/item/decorations/sticky_decorations/flammable/pot_of_gold - tools = list(/obj/item/wirecutters, - /obj/item/pen, + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/pen, /obj/item/toy/crayon/red, /obj/item/toy/crayon/yellow, /obj/item/toy/crayon/orange, @@ -871,8 +873,8 @@ name = "Paper Leprechaun Hat" time = 10 result = /obj/item/decorations/sticky_decorations/flammable/leprechaun_hat - tools = list(/obj/item/wirecutters, - /obj/item/pen, + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/pen, /obj/item/toy/crayon/yellow, /obj/item/toy/crayon/green) category = CAT_DECORATIONS @@ -881,8 +883,8 @@ /datum/crafting_recipe/paper_craft/easter_bunny name = "Paper Easter Bunny" result = /obj/item/decorations/sticky_decorations/flammable/easter_bunny - tools = list(/obj/item/wirecutters, - /obj/item/pen, + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/pen, /obj/item/toy/crayon/blue, /obj/item/toy/crayon/purple) category = CAT_DECORATIONS @@ -891,40 +893,40 @@ /datum/crafting_recipe/paper_craft/easter_egg_blue name = "Blue Paper Easter Egg" result = /obj/item/decorations/sticky_decorations/flammable/easter_egg - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/blue) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/blue) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/easter_egg_yellow name = "Yellow Paper Easter Egg" result = /obj/item/decorations/sticky_decorations/flammable/easter_egg/yellow - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/yellow) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/yellow) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/easter_egg_red name = "Red Paper Easter Egg" result = /obj/item/decorations/sticky_decorations/flammable/easter_egg/red - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/red) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/red) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/easter_egg_purple name = "Purple Paper Easter Egg" result = /obj/item/decorations/sticky_decorations/flammable/easter_egg/purple - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/purple) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/purple) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY /datum/crafting_recipe/paper_craft/easter_egg_orange name = "Orange Paper Easter Egg" result = /obj/item/decorations/sticky_decorations/flammable/easter_egg/orange - tools = list(/obj/item/wirecutters, - /obj/item/toy/crayon/orange) + tools = list(TOOL_WIRECUTTER) + pathtools = list(/obj/item/toy/crayon/orange) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -934,7 +936,7 @@ result = /obj/structure/decorative_structures/metal/statue/metal_angel reqs = list(/obj/item/stack/sheet/metal = 10, /obj/item/stack/sheet/mineral/gold = 6) - tools = list(/obj/item/weldingtool) + tools = list(TOOL_WELDER) category = CAT_DECORATIONS subcategory = CAT_LARGE_DECORATIONS @@ -945,7 +947,7 @@ reqs = list(/obj/item/stack/sheet/metal = 10, /obj/item/stack/sheet/mineral/plasma = 3, /obj/item/stack/sheet/mineral/gold = 8) - tools = list(/obj/item/weldingtool) + tools = list(TOOL_WELDER) category = CAT_DECORATIONS subcategory = CAT_LARGE_DECORATIONS @@ -955,7 +957,7 @@ result = /obj/structure/decorative_structures/metal/statue/sun reqs = list(/obj/item/stack/sheet/metal = 6, /obj/item/stack/sheet/mineral/gold = 4) - tools = list(/obj/item/weldingtool) + tools = list(TOOL_WELDER) category = CAT_DECORATIONS subcategory = CAT_LARGE_DECORATIONS @@ -966,7 +968,7 @@ reqs = list(/obj/item/stack/sheet/metal = 6, /obj/item/stack/sheet/mineral/silver = 6, /obj/item/stack/sheet/mineral/gold = 4) - tools = list(/obj/item/weldingtool) + tools = list(TOOL_WELDER) category = CAT_DECORATIONS subcategory = CAT_LARGE_DECORATIONS @@ -976,7 +978,7 @@ result = /obj/structure/decorative_structures/metal/statue/tesla reqs = list(/obj/item/stack/sheet/metal = 4, /obj/item/stack/sheet/glass = 8) - tools = list(/obj/item/weldingtool) + tools = list(TOOL_WELDER) category = CAT_DECORATIONS subcategory = CAT_LARGE_DECORATIONS @@ -987,7 +989,7 @@ reqs = list(/obj/item/stack/sheet/metal = 8, /obj/item/stock_parts/cell = 3, /obj/item/stack/cable_coil = 4) - tools = list(/obj/item/weldingtool) + tools = list(TOOL_WELDER) category = CAT_DECORATIONS subcategory = CAT_LARGE_DECORATIONS @@ -1010,9 +1012,9 @@ /obj/item/stack/rods = 4, /obj/item/stock_parts/cell = 1, /obj/item/stack/cable_coil = 4)//thing is a wireframe construct with an electro magnetic hover field - tools = list(/obj/item/wirecutters, - /obj/item/pen, - /obj/item/weldingtool, + tools = list(TOOL_WIRECUTTER, + TOOL_WELDER) + pathtools = list(/obj/item/pen, /obj/item/toy/crayon/red) category = CAT_DECORATIONS subcategory = CAT_LARGE_DECORATIONS diff --git a/code/modules/crafting/tailoring.dm b/code/modules/crafting/tailoring.dm index a46e509001c..6973fd04ad3 100644 --- a/code/modules/crafting/tailoring.dm +++ b/code/modules/crafting/tailoring.dm @@ -54,7 +54,7 @@ name = "Security HUDsunglasses" result = /obj/item/clothing/glasses/hud/security/sunglasses time = 20 - tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) reqs = list(/obj/item/clothing/glasses/hud/security = 1, /obj/item/clothing/glasses/sunglasses = 1, /obj/item/stack/cable_coil = 5) @@ -64,7 +64,7 @@ name = "Security HUD removal" result = /obj/item/clothing/glasses/sunglasses time = 20 - tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) reqs = list(/obj/item/clothing/glasses/hud/security/sunglasses = 1) category = CAT_CLOTHING @@ -72,7 +72,7 @@ name = "Medical HUDsunglasses" result = /obj/item/clothing/glasses/hud/health/sunglasses time = 20 - tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) reqs = list(/obj/item/clothing/glasses/hud/health = 1, /obj/item/clothing/glasses/sunglasses = 1, /obj/item/stack/cable_coil = 5) @@ -82,7 +82,7 @@ name = "Medical HUD removal" result = /obj/item/clothing/glasses/sunglasses time = 20 - tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) reqs = list(/obj/item/clothing/glasses/hud/health/sunglasses = 1) category = CAT_CLOTHING @@ -90,7 +90,7 @@ name = "Diagnostic HUDsunglasses" result = /obj/item/clothing/glasses/hud/diagnostic/sunglasses time = 20 - tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) reqs = list(/obj/item/clothing/glasses/hud/diagnostic = 1, /obj/item/clothing/glasses/sunglasses = 1, /obj/item/stack/cable_coil = 5) @@ -100,7 +100,7 @@ name = "Diagnostic HUD removal" result = /obj/item/clothing/glasses/sunglasses time = 20 - tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) reqs = list(/obj/item/clothing/glasses/hud/diagnostic/sunglasses = 1) category = CAT_CLOTHING @@ -108,7 +108,7 @@ name = "Beer Goggles" result = /obj/item/clothing/glasses/sunglasses/reagent time = 20 - tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) reqs = list(/obj/item/clothing/glasses/science = 1, /obj/item/clothing/glasses/sunglasses = 1, /obj/item/stack/cable_coil = 5) @@ -118,7 +118,7 @@ name = "Beer Goggles removal" result = /obj/item/clothing/glasses/sunglasses time = 20 - tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) reqs = list(/obj/item/clothing/glasses/sunglasses/reagent = 1) category = CAT_CLOTHING @@ -126,7 +126,7 @@ name = "Ghost Sheet" result = /obj/item/clothing/suit/ghost_sheet time = 5 - tools = list(/obj/item/wirecutters) + tools = list(TOOL_WIRECUTTER) reqs = list(/obj/item/bedsheet = 1) category = CAT_CLOTHING diff --git a/code/modules/economy/ATM.dm b/code/modules/economy/ATM.dm index eafd038977d..df542964163 100644 --- a/code/modules/economy/ATM.dm +++ b/code/modules/economy/ATM.dm @@ -71,7 +71,7 @@ log transactions playsound(loc, pick('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg'), 50, 1) for(var/obj/item/stack/spacecash/S in T) S.use(S.amount) - authenticated_account.charge(-cash_amount, null, "Credit deposit", terminal_id = machine_id, dest_name = "Terminal") + authenticated_account.charge(-cash_amount, null, "Credit deposit", machine_id, "Terminal") /obj/machinery/atm/proc/reconnect_database() for(var/obj/machinery/computer/account_database/DB in GLOB.machines) diff --git a/code/modules/error_handler/error_handler.dm b/code/modules/error_handler/error_handler.dm index 09a5d20833e..4888948344a 100644 --- a/code/modules/error_handler/error_handler.dm +++ b/code/modules/error_handler/error_handler.dm @@ -44,6 +44,9 @@ var/total_runtimes_skipped = 0 error_last_seen[erroruid] = world.time error_cooldown[erroruid] = cooldown + // This line will log a runtime summary to a file which can be publicly distributed without sending player data + log_runtime_summary("Runtime in [e.file],[e.line]: [e]") + // The detailed error info needs some tweaking to make it look nice var/list/srcinfo = null var/list/usrinfo = null diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index 1c99d2d1bc0..ece0b5c607e 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -197,8 +197,8 @@ var/list/event_last_fired = list() new /datum/event_meta/alien(EVENT_LEVEL_MAJOR, "Alien Infestation", /datum/event/alien_infestation, 0, list(ASSIGNMENT_SECURITY = 15), 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Traders", /datum/event/traders, 180, is_one_shot = 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Terror Spiders", /datum/event/spider_terror, 0, list(ASSIGNMENT_SECURITY = 15), is_one_shot = 1), - new /datum/event_meta(EVENT_LEVEL_MAJOR, "Slaughter Demon", /datum/event/spawn_slaughter, 15, is_one_shot = 1), - new /datum/event_meta(EVENT_LEVEL_MAJOR, "Floor Cluwne", /datum/event/spawn_floor_cluwne, 15, is_one_shot = 1) + new /datum/event_meta(EVENT_LEVEL_MAJOR, "Slaughter Demon", /datum/event/spawn_slaughter, 15, is_one_shot = 1) + //new /datum/event_meta(EVENT_LEVEL_MAJOR, "Floor Cluwne", /datum/event/spawn_floor_cluwne, 15, is_one_shot = 1) ) diff --git a/code/modules/events/sentience.dm b/code/modules/events/sentience.dm index 52e8918a16c..fb896e9e2a6 100644 --- a/code/modules/events/sentience.dm +++ b/code/modules/events/sentience.dm @@ -36,9 +36,9 @@ SA.universal_speak = 1 SA.sentience_act() SA.can_collar = 1 - SA.maxHealth = max(SA.maxHealth + 200) - SA.melee_damage_lower = max(SA.melee_damage_lower + 15) - SA.melee_damage_upper = max(SA.melee_damage_upper + 15) + SA.maxHealth += 200 + SA.melee_damage_lower += 15 + SA.melee_damage_upper += 15 SA.health = SA.maxHealth SA.del_on_death = FALSE greet_sentient(SA) @@ -50,4 +50,3 @@ to_chat(M, "Due to freak radiation, you have gained \ human level intelligence and the ability to speak and understand \ human language!") - diff --git a/code/modules/events/spider_terror.dm b/code/modules/events/spider_terror.dm index 1ecf5aa22ca..925051cff11 100644 --- a/code/modules/events/spider_terror.dm +++ b/code/modules/events/spider_terror.dm @@ -15,6 +15,10 @@ var/list/vents = list() for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in GLOB.all_vent_pumps) if(is_station_level(temp_vent.loc.z) && !temp_vent.welded) + if(!temp_vent.parent) + // Issue happening more often with vents. Log and continue. Delete once solved + log_debug("spider_terror/start(), vent has no parent: [temp_vent], qdeled: [QDELETED(temp_vent)], loc: [temp_vent.loc]") + continue if(temp_vent.parent.other_atmosmch.len > 50) vents += temp_vent var/spider_type diff --git a/code/modules/events/traders.dm b/code/modules/events/traders.dm index 04663f93152..b481bca88eb 100644 --- a/code/modules/events/traders.dm +++ b/code/modules/events/traders.dm @@ -18,6 +18,9 @@ var/global/list/unused_trade_stations = list("sol") return if(seclevel2num(get_security_level()) >= SEC_LEVEL_RED) event_announcement.Announce("A trading shuttle from Jupiter Station has been denied docking permission due to the heightened security alert aboard [station_name()].", "Trader Shuttle Docking Request Refused") + // if the docking request was refused, fire another major event in 60 seconds + var/list/datum/event_container/EC = SSevents.event_containers[EVENT_LEVEL_MAJOR] + EC.next_event_time = world.time + (60 * 10) return var/list/spawnlocs = list() diff --git a/code/modules/fish/fish_items.dm b/code/modules/fish/fish_items.dm index a0882ae5df8..4a7a678a09e 100644 --- a/code/modules/fish/fish_items.dm +++ b/code/modules/fish/fish_items.dm @@ -103,8 +103,8 @@ icon_state = "glofish" /obj/item/fish/glofish/New() - ..() - set_light(2,1,"#99FF66") + ..() + set_light(2,1,"#99FF66") /obj/item/fish/electric_eel name = "electric eel" @@ -143,6 +143,7 @@ materials = list() /obj/item/shard/shark_teeth/New() + ..() src.pixel_x = rand(-5,5) src.pixel_y = rand(-5,5) diff --git a/code/modules/fish/fishtank.dm b/code/modules/fish/fishtank.dm index 95cf9f15799..d54e22c6fc4 100644 --- a/code/modules/fish/fishtank.dm +++ b/code/modules/fish/fishtank.dm @@ -364,6 +364,12 @@ egg_list.Add(parent2.egg_item) egg_count++ +/obj/machinery/fishtank/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + default_welder_repair(user, I) + ////////////////////////////// Note from FalseIncarnate: // EXAMINE PROC // This proc is massive, messy, and probably could be handled better. ////////////////////////////// Feel free to try cleaning it up if you think of a better way to do it. @@ -558,25 +564,8 @@ qdel(src) /obj/machinery/fishtank/attackby(obj/item/O, mob/user) - //Welders repair damaged tanks on help intent, damage on all others - if(iswelder(O)) - var/obj/item/weldingtool/W = O - if(user.a_intent == INTENT_HELP) - if(W.isOn()) - if(obj_integrity < max_integrity) - playsound(loc, W.usesound, 50, 1) - to_chat(user, "You repair some of the cracks on [src].") - obj_integrity = min(obj_integrity + 20, max_integrity) - check_health() - else - to_chat(user, "There is no damage to fix!") - else - if(obj_integrity < max_integrity) - to_chat(user, "[W] must be on to repair this damage.") - else - return ..() //Open reagent containers add and remove water - else if(O.is_drainable()) + if(O.is_drainable()) //Containers with any reagents will get dumped in if(O.reagents.total_volume) var/water_value = 0 @@ -616,15 +605,6 @@ O.reagents.add_reagent("fishwater", water_level) adjust_water_level(-water_level) user.visible_message("[user.name] scoops out some water from [src].", "You fill [O.name] with the last of the water in [src].") - //Wrenches can deconstruct empty tanks, but not tanks with any water. Kills any fish left inside and destroys any unharvested eggs in the process - else if(iswrench(O)) - if(!water_level) - to_chat(user, "Now disassembling [src].") - playsound(loc, O.usesound, 50, 1) - if(do_after(user, 50 * O.toolspeed, target = src)) - deconstruct(TRUE) - else - to_chat(user, "[src] must be empty before you disassemble it!") //Fish eggs else if(istype(O, /obj/item/fish_eggs)) var/obj/item/fish_eggs/egg = O @@ -670,4 +650,15 @@ adjust_filth_level(-filth_level) user.visible_message("[user.name] scrubs the inside of [src], cleaning the filth.", "You scrub the inside of [src], cleaning the filth.") else - return ..() \ No newline at end of file + return ..() + +/obj/machinery/fishtank/wrench_act(mob/user, obj/item/I) //Wrenches can deconstruct empty tanks, but not tanks with any water. Kills any fish left inside and destroys any unharvested eggs in the process + . = TRUE + if(water_level) + to_chat(user, "[src] must be empty before you disassemble it!") + return + if(!I.tool_use_check(user, 0)) + return + to_chat(user, "Now disassembling [src].") + if(I.use_tool(src, user, 50, volume = I.tool_volume)) + deconstruct(TRUE) diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index ea12f0a82d3..ee28919fd67 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -147,6 +147,8 @@ Gunshots/explosions/opening doors/less rare audio (done) START_PROCESSING(SSobj, src) /obj/effect/hallucination/fake_flood/process() + if(!target) + qdel(src) if(next_expand <= world.time) radius++ if(radius > FAKE_FLOOD_MAX_RADIUS) diff --git a/code/modules/flufftext/TextFilters.dm b/code/modules/flufftext/TextFilters.dm index 02a02a6f5b2..e00f653ac45 100644 --- a/code/modules/flufftext/TextFilters.dm +++ b/code/modules/flufftext/TextFilters.dm @@ -1,7 +1,7 @@ proc/Intoxicated(phrase) phrase = html_decode(phrase) - var/leng=lentext(phrase) - var/counter=lentext(phrase) + var/leng=length(phrase) + var/counter=length(phrase) var/newphrase="" var/newletter="" while(counter>=1) diff --git a/code/modules/food_and_drinks/drinks/bottler/bottler.dm b/code/modules/food_and_drinks/drinks/bottler/bottler.dm index 4cf5c58bd06..39d175968d4 100644 --- a/code/modules/food_and_drinks/drinks/bottler/bottler.dm +++ b/code/modules/food_and_drinks/drinks/bottler/bottler.dm @@ -40,15 +40,6 @@ qdel(recipe) /obj/machinery/bottler/attackby(obj/item/O, mob/user, params) - if(iswrench(O)) //This being before the canUnequip check allows borgs to (un)wrench bottlers in case they need move them to fix stuff - playsound(src, O.usesound, 50, 1) - if(anchored) - anchored = 0 - to_chat(user, "[src] can now be moved.") - else - anchored = 1 - to_chat(user, "[src] is now secured.") - return 1 if(!user.canUnEquip(O, 0)) to_chat(user, "[O] is stuck to your hand, you can't seem to put it down!") return 0 @@ -91,7 +82,17 @@ else //If it doesn't qualify in the above checks, we don't want it. Inform the person so they (ideally) stop trying to put the nuke disc in. to_chat(user, "You aren't sure this is able to be processed by the machine.") return 0 - //..() + return ..() + +/obj/machinery/bottler/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + anchored = !anchored + if(anchored) + WRENCH_ANCHOR_MESSAGE + else + WRENCH_UNANCHOR_MESSAGE /obj/machinery/bottler/proc/insert_item(obj/item/O, mob/user) if(!O || !user) diff --git a/code/modules/food_and_drinks/food/foods/meat.dm b/code/modules/food_and_drinks/food/foods/meat.dm index f66d46f0da6..0eea67d946e 100644 --- a/code/modules/food_and_drinks/food/foods/meat.dm +++ b/code/modules/food_and_drinks/food/foods/meat.dm @@ -286,7 +286,7 @@ if(faction) creature.faction = faction if(LAZYLEN(fingerprintshidden)) - creature.fingerprintshidden = fingerprintshidden.Copy() + creature.fingerprintshidden = fingerprintshidden creature.set_species(monkey_type) SSmobs.cubemonkeys += creature qdel(src) diff --git a/code/modules/food_and_drinks/food/foods/pizza.dm b/code/modules/food_and_drinks/food/foods/pizza.dm index e1290d9148a..1f1092dd666 100644 --- a/code/modules/food_and_drinks/food/foods/pizza.dm +++ b/code/modules/food_and_drinks/food/foods/pizza.dm @@ -248,21 +248,26 @@ ..() /obj/item/pizzabox/margherita/New() + ..() pizza = new /obj/item/reagent_containers/food/snacks/sliceable/pizza/margherita(src) boxtag = "margherita deluxe" /obj/item/pizzabox/vegetable/New() + ..() pizza = new /obj/item/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza(src) boxtag = "gourmet vegatable" /obj/item/pizzabox/mushroom/New() + ..() pizza = new /obj/item/reagent_containers/food/snacks/sliceable/pizza/mushroompizza(src) boxtag = "mushroom special" /obj/item/pizzabox/meat/New() + ..() pizza = new /obj/item/reagent_containers/food/snacks/sliceable/pizza/meatpizza(src) boxtag = "meatlover's supreme" /obj/item/pizzabox/hawaiian/New() + ..() pizza = new /obj/item/reagent_containers/food/snacks/sliceable/pizza/hawaiianpizza(src) boxtag = "Hawaiian feast" \ No newline at end of file diff --git a/code/modules/food_and_drinks/kitchen_machinery/cooker.dm b/code/modules/food_and_drinks/kitchen_machinery/cooker.dm index 802f8f08c54..eb2e8bd3e7b 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/cooker.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/cooker.dm @@ -98,12 +98,6 @@ if(upgradeable) //Not all cooker types currently support build/upgrade stuff, so not all of it will work well with this //Until we decide whether or not we want to bring back the cereal maker or old grill/oven in some form, this initial check will have to suffice - if(isscrewdriver(I)) - default_deconstruction_screwdriver(user, openicon, officon, I) - return - if(iscrowbar(I)) - default_deconstruction_crowbar(I) - return if(istype(I, /obj/item/storage/part_replacer)) exchange_parts(user, I) return @@ -146,6 +140,20 @@ turnoff(I) //qdel(I) +/obj/machinery/cooker/crowbar_act(mob/user, obj/item/I) + if(!upgradeable) + return + if(default_deconstruction_crowbar(user, I)) + return TRUE + +/obj/machinery/cooker/screwdriver_act(mob/user, obj/item/I) + if(!upgradeable) + return + if(default_deconstruction_screwdriver(user, openicon, officon, I)) + return TRUE + + + /obj/machinery/cooker/proc/special_attack(obj/item/grab/G, mob/user) return 0 diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm index 2aee35c225d..e0f456facec 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm @@ -108,7 +108,7 @@ if(default_unfasten_wrench(user, P)) return - if(default_deconstruction_crowbar(P)) + if(default_deconstruction_crowbar(user, P)) return return ..() diff --git a/code/modules/food_and_drinks/kitchen_machinery/icecream_vat_2.dm b/code/modules/food_and_drinks/kitchen_machinery/icecream_vat_2.dm index 1554dbb0211..f1e03da035b 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/icecream_vat_2.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/icecream_vat_2.dm @@ -232,6 +232,7 @@ var/list/ingredients_source = list( bitesize = 3 /obj/item/reagent_containers/food/snacks/icecream/New() + ..() create_reagents(20) reagents.add_reagent("nutriment", 5) diff --git a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm index 298a5ae2e7e..e0d0c5ec396 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm @@ -78,7 +78,7 @@ to_chat(user, "\The [src] is now secured.") return - default_deconstruction_crowbar(O) + default_deconstruction_crowbar(user, O) if(broken > 0) if(broken == 2 && istype(O, /obj/item/screwdriver)) // If it's broken and they're using a screwdriver diff --git a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm index 6bbd1f20ee5..a648d37656d 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm @@ -56,7 +56,7 @@ GLOBAL_LIST_EMPTY(monkey_recyclers) power_change() return - if(default_deconstruction_crowbar(O)) + if(default_deconstruction_crowbar(user, O)) return if(istype(O, /obj/item/multitool)) diff --git a/code/modules/food_and_drinks/kitchen_machinery/processor.dm b/code/modules/food_and_drinks/kitchen_machinery/processor.dm index 394ee10384b..61f887e44bc 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/processor.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/processor.dm @@ -175,7 +175,7 @@ if(default_unfasten_wrench(user, O)) return - default_deconstruction_crowbar(O) + default_deconstruction_crowbar(user, O) var/obj/item/what = O diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm index 3cd95f37923..3986bb64ae0 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm @@ -253,7 +253,7 @@ power_change() return - if(default_deconstruction_crowbar(O)) + if(default_deconstruction_crowbar(user, O)) return if(istype(O, /obj/item/multitool)||istype(O, /obj/item/wirecutters)) @@ -386,7 +386,7 @@ return data /obj/machinery/smartfridge/Topic(href, href_list) - if(..()) + if(..()) return FALSE var/mob/user = usr @@ -492,7 +492,7 @@ /obj/machinery/smartfridge/drying_rack/spawn_frame() return -/obj/machinery/smartfridge/drying_rack/default_deconstruction_crowbar(obj/item/crowbar/C, ignore_panel = 1) +/obj/machinery/smartfridge/drying_rack/default_deconstruction_crowbar(user, obj/item/crowbar/C, ignore_panel = 1) ..() /obj/machinery/smartfridge/drying_rack/Topic(href, href_list) diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_table.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_table.dm index a0988951855..2a2ee410522 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_table.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_table.dm @@ -95,7 +95,7 @@ /obj/item/reagent_containers/food/snacks/boiledrice = 1, /obj/item/reagent_containers/food/snacks/boiled_shrimp = 4, ) - tools = list(/obj/item/kitchen/sushimat) + pathtools = list(/obj/item/kitchen/sushimat) result = /obj/item/reagent_containers/food/snacks/sliceable/Ebi_maki category = CAT_FOOD subcategory = CAT_SUSHI @@ -116,7 +116,7 @@ /obj/item/reagent_containers/food/snacks/boiledrice = 1, /obj/item/fish_eggs/salmon = 4, ) - tools = list(/obj/item/kitchen/sushimat) + pathtools = list(/obj/item/kitchen/sushimat) result = /obj/item/reagent_containers/food/snacks/sliceable/Ikura_maki category = CAT_FOOD subcategory = CAT_SUSHI @@ -137,7 +137,7 @@ /obj/item/reagent_containers/food/snacks/boiledrice = 1, /obj/item/reagent_containers/food/snacks/fried_tofu = 4, ) - tools = list(/obj/item/kitchen/sushimat) + pathtools = list(/obj/item/kitchen/sushimat) result = /obj/item/reagent_containers/food/snacks/sliceable/Inari_maki category = CAT_FOOD subcategory = CAT_SUSHI @@ -158,7 +158,7 @@ /obj/item/reagent_containers/food/snacks/boiledrice = 1, /obj/item/reagent_containers/food/snacks/salmonmeat = 4, ) - tools = list(/obj/item/kitchen/sushimat) + pathtools = list(/obj/item/kitchen/sushimat) result = /obj/item/reagent_containers/food/snacks/sliceable/Sake_maki category = CAT_FOOD subcategory = CAT_SUSHI @@ -179,7 +179,7 @@ /obj/item/reagent_containers/food/snacks/boiledrice = 1, /obj/item/reagent_containers/food/snacks/salmonsteak = 4, ) - tools = list(/obj/item/kitchen/sushimat) + pathtools = list(/obj/item/kitchen/sushimat) result = /obj/item/reagent_containers/food/snacks/sliceable/SmokedSalmon_maki category = CAT_FOOD subcategory = CAT_SUSHI @@ -200,7 +200,7 @@ /obj/item/reagent_containers/food/snacks/boiledrice = 1, /obj/item/fish_eggs/goldfish = 4, ) - tools = list(/obj/item/kitchen/sushimat) + pathtools = list(/obj/item/kitchen/sushimat) result = /obj/item/reagent_containers/food/snacks/sliceable/Masago_maki category = CAT_FOOD subcategory = CAT_SUSHI @@ -221,7 +221,7 @@ /obj/item/reagent_containers/food/snacks/boiledrice = 1, /obj/item/fish_eggs/shark = 4, ) - tools = list(/obj/item/kitchen/sushimat) + pathtools = list(/obj/item/kitchen/sushimat) result = /obj/item/reagent_containers/food/snacks/sliceable/Tobiko_maki category = CAT_FOOD subcategory = CAT_SUSHI @@ -242,7 +242,7 @@ /obj/item/reagent_containers/food/snacks/sushi_Tobiko = 4, /obj/item/reagent_containers/food/snacks/egg = 4, ) - tools = list(/obj/item/kitchen/sushimat) + pathtools = list(/obj/item/kitchen/sushimat) result = /obj/item/reagent_containers/food/snacks/sliceable/TobikoEgg_maki category = CAT_FOOD subcategory = CAT_SUSHI @@ -253,7 +253,7 @@ /obj/item/reagent_containers/food/snacks/sushi_Tobiko = 4, /obj/item/reagent_containers/food/snacks/egg = 4, ) - tools = list(/obj/item/kitchen/sushimat) + pathtools = list(/obj/item/kitchen/sushimat) result = /obj/item/reagent_containers/food/snacks/sliceable/TobikoEgg_maki category = CAT_FOOD subcategory = CAT_SUSHI @@ -274,7 +274,7 @@ /obj/item/reagent_containers/food/snacks/boiledrice = 1, /obj/item/reagent_containers/food/snacks/catfishmeat = 4, ) - tools = list(/obj/item/kitchen/sushimat) + pathtools = list(/obj/item/kitchen/sushimat) result = /obj/item/reagent_containers/food/snacks/sliceable/Tai_maki category = CAT_FOOD subcategory = CAT_SUSHI diff --git a/code/modules/holiday/christmas.dm b/code/modules/holiday/christmas.dm index 37a482231c2..ba65047ecab 100644 --- a/code/modules/holiday/christmas.dm +++ b/code/modules/holiday/christmas.dm @@ -33,9 +33,6 @@ desc = "Directions for use: Requires two people, one to pull each end." var/cracked = 0 -/obj/item/toy/xmas_cracker/New() - ..() - /obj/item/toy/xmas_cracker/attack(mob/target, mob/user) if( !cracked && istype(target,/mob/living/carbon/human) && (target.stat == CONSCIOUS) && !target.get_active_hand() ) target.visible_message("[user] and [target] pop \an [src]! *pop*", "You pull \an [src] with [target]! *pop*", "You hear a *pop*.") diff --git a/code/modules/hydroponics/beekeeping/beebox.dm b/code/modules/hydroponics/beekeeping/beebox.dm index 5427ac9f2c9..4f9daa1ea92 100644 --- a/code/modules/hydroponics/beekeeping/beebox.dm +++ b/code/modules/hydroponics/beekeeping/beebox.dm @@ -160,10 +160,6 @@ to_chat(user, "There's no room for anymore frames in the apiary!") return - if(iswrench(I)) - if(default_unfasten_wrench(user, I, time = 20)) - return - if(istype(I, /obj/item/queen_bee)) if(queen_bee) to_chat(user, "This hive already has a queen!") @@ -202,6 +198,11 @@ return return ..() +/obj/structure/beebox/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + default_unfasten_wrench(user, I, time = 20) /obj/structure/beebox/attack_hand(mob/user) if(ishuman(user)) diff --git a/code/modules/hydroponics/biogenerator.dm b/code/modules/hydroponics/biogenerator.dm index 3332b12e1bd..c1b5e471315 100644 --- a/code/modules/hydroponics/biogenerator.dm +++ b/code/modules/hydroponics/biogenerator.dm @@ -93,7 +93,7 @@ if(exchange_parts(user, O)) return - if(default_deconstruction_crowbar(O)) + if(default_deconstruction_crowbar(user, O)) return if(istype(O, /obj/item/reagent_containers/glass)) diff --git a/code/modules/hydroponics/gene_modder.dm b/code/modules/hydroponics/gene_modder.dm index fce2a2905fc..d39a0168f14 100644 --- a/code/modules/hydroponics/gene_modder.dm +++ b/code/modules/hydroponics/gene_modder.dm @@ -100,7 +100,7 @@ return if(exchange_parts(user, I)) return - if(default_deconstruction_crowbar(I)) + if(default_deconstruction_crowbar(user, I)) return if(isrobot(user)) return diff --git a/code/modules/hydroponics/grown/misc.dm b/code/modules/hydroponics/grown/misc.dm index 7d494803495..d13b7a11e5b 100644 --- a/code/modules/hydroponics/grown/misc.dm +++ b/code/modules/hydroponics/grown/misc.dm @@ -145,6 +145,9 @@ message_admins("[user] ([user.key ? user.key : "no key"]) primed a cherry bomb for detonation at [A] ([user.x], [user.y], [user.z]) (JMP)") log_game("[user] ([user.key ? user.key : "no key"]) primed a cherry bomb for detonation at [A] ([user.x],[user.y],[user.z]).") prime() + if(iscarbon(user)) + var/mob/living/carbon/C = user + C.throw_mode_on() /obj/item/reagent_containers/food/snacks/grown/cherry_bomb/deconstruct(disassembled = TRUE) if(!disassembled) diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 752c915f145..58c7636ae7c 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -85,14 +85,17 @@ if(exchange_parts(user, I)) return - if(iscrowbar(I)) - if(using_irrigation) - to_chat(user, "Disconnect the hoses first!") - else if(default_deconstruction_crowbar(I, 1)) - return else return ..() +/obj/machinery/hydroponics/constructable/crowbar_act(mob/user, obj/item/I) + + if(using_irrigation) + to_chat(user, "Disconnect the hoses first!") + return TRUE + if(default_deconstruction_crowbar(user, I, 1)) + return TRUE + /obj/machinery/hydroponics/proc/FindConnected() var/list/connected = list() var/list/processing_atoms = list(src) @@ -847,39 +850,6 @@ return S.handle_item_insertion(G, 1) - else if(iswrench(O) && wrenchable) - if(using_irrigation) - to_chat(user, "Disconnect the hoses first!") - return - - if(!anchored && !isinspace()) - user.visible_message("[user] begins to wrench [src] into place.", "You begin to wrench [src] in place...") - playsound(loc, O.usesound, 50, 1) - if (do_after(user, 20 * O.toolspeed, target = src)) - if(anchored) - return - anchored = 1 - user.visible_message("[user] wrenches [src] into place.", \ - "You wrench [src] in place.") - else if(anchored) - user.visible_message("[user] begins to unwrench [src].", \ - "You begin to unwrench [src]...") - playsound(loc, O.usesound, 50, 1) - if (do_after(user, 20 * O.toolspeed, target = src)) - if(!anchored) - return - anchored = 0 - user.visible_message("[user] unwrenches [src].", \ - "You unwrench [src].") - - else if(iswirecutter(O) && wrenchable) - using_irrigation = !using_irrigation - playsound(src, O.usesound, 50, 1) - user.visible_message("[user] [using_irrigation ? "" : "dis"]connects [src]'s irrigation hoses.", \ - "You [using_irrigation ? "" : "dis"]connect [src]'s irrigation hoses.") - for(var/obj/machinery/hydroponics/h in range(1,src)) - h.update_icon() - else if(istype(O, /obj/item/shovel/spade)) if(!myseed && !weedlevel) to_chat(user, "[src] doesn't have any plants or weeds!") @@ -905,6 +875,44 @@ else return ..() +/obj/machinery/hydroponics/wirecutter_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + else if(wrenchable) + using_irrigation = !using_irrigation + user.visible_message("[user] [using_irrigation ? "" : "dis"]connects [src]'s irrigation hoses.", \ + "You [using_irrigation ? "" : "dis"]connect [src]'s irrigation hoses.") + for(var/obj/machinery/hydroponics/h in range(1,src)) + h.update_icon() + +/obj/machinery/hydroponics/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_start_check(user, 0)) + return + if(wrenchable) + if(using_irrigation) + to_chat(user, "Disconnect the hoses first!") + return + + if(!anchored && !isinspace()) + user.visible_message("[user] begins to wrench [src] into place.", "You begin to wrench [src] in place...") + if(I.use_tool(src, user, 20, volume = I.tool_volume)) + if(anchored) + return + anchored = TRUE + user.visible_message("[user] wrenches [src] into place.", \ + "You wrench [src] in place.") + else if(anchored) + user.visible_message("[user] begins to unwrench [src].", \ + "You begin to unwrench [src]...") + if(I.use_tool(src, user, 20, volume = I.tool_volume)) + if(!anchored) + return + anchored = FALSE + user.visible_message("[user] unwrenches [src].", \ + "You unwrench [src].") + /obj/machinery/hydroponics/attack_hand(mob/user) if(issilicon(user)) //How does AI know what plant is? return diff --git a/code/modules/hydroponics/seed_extractor.dm b/code/modules/hydroponics/seed_extractor.dm index 72b92f21964..36e58f46395 100644 --- a/code/modules/hydroponics/seed_extractor.dm +++ b/code/modules/hydroponics/seed_extractor.dm @@ -77,7 +77,7 @@ if(default_unfasten_wrench(user, O)) return - if(default_deconstruction_crowbar(O)) + if(default_deconstruction_crowbar(user, O)) return if (istype(O,/obj/item/storage/bag/plants)) diff --git a/code/modules/keybindings/bindings_client.dm b/code/modules/keybindings/bindings_client.dm index d59e3da4e8e..f38e485d226 100644 --- a/code/modules/keybindings/bindings_client.dm +++ b/code/modules/keybindings/bindings_client.dm @@ -25,7 +25,7 @@ else log_admin("Client [ckey] was just autokicked for flooding keysends; likely abuse but potentially lagspike.") message_admins("Client [ckey] was just autokicked for flooding keysends; likely abuse but potentially lagspike.") - QDEL_IN(src, 1) + qdel(src) return ///Check if the key is short enough to even be a real key @@ -33,7 +33,7 @@ to_chat(src, "Invalid KeyDown detected! You have been disconnected from the server automatically.") log_admin("Client [ckey] just attempted to send an invalid keypress. Keymessage was over [MAX_KEYPRESS_COMMANDLENGTH] characters, autokicking due to likely abuse.") message_admins("Client [ckey] just attempted to send an invalid keypress. Keymessage was over [MAX_KEYPRESS_COMMANDLENGTH] characters, autokicking due to likely abuse.") - QDEL_IN(src, 1) + qdel(src) return //offset by 1 because the buffer address is 0 indexed because the math was simpler keys_held[current_key_address + 1] = _key diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index 4439993326c..dabd25c0f74 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -244,17 +244,14 @@ scanner.computer.inventory.Add(src) to_chat(user, "[W]'s screen flashes: 'Book stored in buffer. Title added to general inventory.'") return 1 - else if(istype(W, /obj/item/kitchen/knife) || iswirecutter(W)) - if(carved) - return 1 - to_chat(user, "You begin to carve out [title].") - if(do_after(user, 30 * W.toolspeed, target = src)) - to_chat(user, "You carve out the pages from [title]! You didn't want to read it anyway.") - carved = 1 - return 1 + else if(istype(W, /obj/item/kitchen/knife) && !carved) + carve_book(user, W) else return ..() +/obj/item/book/wirecutter_act(mob/user, obj/item/I) + return carve_book(user, I) + /obj/item/book/attack(mob/M, mob/living/user) if(user.a_intent == INTENT_HELP) force = 0 @@ -264,6 +261,17 @@ attack_verb = list("bashed", "whacked") ..() +/obj/item/book/proc/carve_book(mob/user, obj/item/I) + if(!I.sharp && I.tool_behaviour != TOOL_WIRECUTTER) //Only sharp and wirecutter things can carve books + to_chat(user, "") + return + if(carved) + return + to_chat(user, "You begin to carve out [title].") + if(I.use_tool(src, user, 30, volume = I.tool_volume)) + to_chat(user, "You carve out the pages from [title]! You didn't want to read it anyway.") + carved = TRUE + return TRUE /* * Barcode Scanner */ diff --git a/code/modules/logic/logic_base.dm b/code/modules/logic/logic_base.dm index 50aecd79283..e2e4450c982 100644 --- a/code/modules/logic/logic_base.dm +++ b/code/modules/logic/logic_base.dm @@ -210,7 +210,7 @@ to_chat(user, "You [panel_open ? "open" : "close"] the access panel.") return 1 if(panel_open && istype(O, /obj/item/crowbar)) - default_deconstruction_crowbar(O) + default_deconstruction_crowbar(user, O) return 1 return ..() diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index df943d6f30d..ee3eb10598a 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -40,21 +40,24 @@ . += "It has \a [T] attached, which causes [T.effect_desc()]." /obj/item/twohanded/kinetic_crusher/attackby(obj/item/I, mob/living/user) - if(iscrowbar(I)) - if(LAZYLEN(trophies)) - to_chat(user, "You remove [src]'s trophies.") - playsound(loc, I.usesound, 100, 1) - for(var/t in trophies) - var/obj/item/crusher_trophy/T = t - T.remove_from(src, user) - else - to_chat(user, "There are no trophies on [src].") - else if(istype(I, /obj/item/crusher_trophy)) + if(istype(I, /obj/item/crusher_trophy)) var/obj/item/crusher_trophy/T = I T.add_to(src, user) else return ..() +/obj/item/twohanded/kinetic_crusher/crowbar_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(LAZYLEN(trophies)) + to_chat(user, "You remove [src]'s trophies.") + for(var/t in trophies) + var/obj/item/crusher_trophy/T = t + T.remove_from(src, user) + else + to_chat(user, "There are no trophies on [src].") + /obj/item/twohanded/kinetic_crusher/attack(mob/living/target, mob/living/carbon/user) if(!wielded) to_chat(user, "[src] is too heavy to use with one hand. You fumble and drop everything.") diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index ffe7a062bbe..904a3462808 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -189,7 +189,7 @@ return var/failText = "The snake seems unsatisfied with your incomplete oath and returns to its previous place on the rod, returning to its dormant, wooden state. You must stand still while completing your oath!" to_chat(itemUser, "The wooden snake that was carved into the rod seems to suddenly come alive and begins to slither down your arm! The compulsion to help others grows abnormally strong...") - if(do_after(itemUser, 40, target = itemUser)) + if(do_after_once(itemUser, 40, target = itemUser)) itemUser.say("I swear to fulfill, to the best of my ability and judgment, this covenant:") else to_chat(itemUser, failText) diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm index bab4c8bee1a..922b18023a3 100644 --- a/code/modules/mining/machine_redemption.dm +++ b/code/modules/mining/machine_redemption.dm @@ -188,13 +188,6 @@ /obj/machinery/mineral/ore_redemption/attackby(obj/item/W, mob/user, params) if(exchange_parts(user, W)) return - if(default_unfasten_wrench(user, W)) - return - if(default_deconstruction_screwdriver(user, "ore_redemption-open", "ore_redemption", W)) - updateUsrDialog() - return - if(default_deconstruction_crowbar(W)) - return if(!powered()) return @@ -208,12 +201,6 @@ interact(user) return - if(ismultitool(W) && panel_open) - input_dir = turn(input_dir, -90) - output_dir = turn(output_dir, -90) - to_chat(user, "You change [src]'s I/O settings, setting the input to [dir2text(input_dir)] and the output to [dir2text(output_dir)].") - return - if(istype(W, /obj/item/disk/design_disk)) if(user.drop_item()) W.forceMove(src) @@ -223,6 +210,32 @@ return ..() + +/obj/machinery/mineral/ore_redemption/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I)) + return TRUE + +/obj/machinery/mineral/ore_redemption/multitool_act(mob/user, obj/item/I) + if(!panel_open) + return + . = TRUE + if(!powered()) + return + if(!I.tool_start_check(user, 0)) + return + input_dir = turn(input_dir, -90) + output_dir = turn(output_dir, -90) + to_chat(user, "You change [src]'s I/O settings, setting the input to [dir2text(input_dir)] and the output to [dir2text(output_dir)].") + +/obj/machinery/mineral/ore_redemption/screwdriver_act(mob/user, obj/item/I) + if(default_deconstruction_screwdriver(user, "ore_redemption-open", "ore_redemption", I)) + updateUsrDialog() + return TRUE + +/obj/machinery/mineral/ore_redemption/wrench_act(mob/user, obj/item/I) + if(default_unfasten_wrench(user, I)) + return TRUE + /obj/machinery/mineral/ore_redemption/attack_hand(mob/user) if(..()) return diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm index c8fbba6fe51..f27e2a7c3c1 100644 --- a/code/modules/mining/machine_vending.dm +++ b/code/modules/mining/machine_vending.dm @@ -187,7 +187,7 @@ if(istype(I, /obj/item/crowbar)) if(inserted_id) inserted_id.forceMove(loc) //Prevents deconstructing the ORM from deleting whatever ID was inside it. - default_deconstruction_crowbar(I) + default_deconstruction_crowbar(user, I) return 1 if(istype(I, /obj/item/mining_voucher)) if(!powered()) @@ -299,8 +299,4 @@ /obj/item/storage/backpack/duffel/mining_conscript/full/New() ..() - new /obj/item/clothing/suit/hooded/explorer(src) new /obj/item/card/id/mining_access_card(src) - new /obj/item/gun/energy/kinetic_accelerator(src) - new /obj/item/kitchen/knife/combat/survival(src) - new /obj/item/flashlight/seclite(src) diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm index 869864e5768..fdd6b15e8ae 100644 --- a/code/modules/mining/minebot.dm +++ b/code/modules/mining/minebot.dm @@ -88,28 +88,41 @@ /mob/living/simple_animal/hostile/mining_drone/attackby(obj/item/I, mob/user, params) - if(iswelder(I) && user.a_intent == INTENT_HELP) - var/obj/item/weldingtool/W = I - if(W.welding && !stat) - if(AIStatus != AI_OFF && AIStatus != AI_IDLE) - to_chat(user, "[src] is moving around too much to repair!") - return - if(do_after_once(user, 15, target = src)) - if(maxHealth == health) - to_chat(user, "[src] is at full integrity.") - else - adjustBruteLoss(-20) - to_chat(user, "You repair some of the armor on [src].") - return if(istype(I, /obj/item/mining_scanner) || istype(I, /obj/item/t_scanner/adv_mining_scanner)) to_chat(user, "You instruct [src] to drop any collected ore.") DropOre() return - if(iscrowbar(I) || istype(I, /obj/item/borg/upgrade/modkit)) + if(istype(I, /obj/item/borg/upgrade/modkit)) I.melee_attack_chain(user, stored_gun, params) return ..() +/mob/living/simple_animal/hostile/mining_drone/crowbar_act(mob/user, obj/item/I) + if(user.a_intent != INTENT_HELP) + return + . = TRUE + if(!I.tool_start_check(user, 0)) + return + I.melee_attack_chain(user, stored_gun) + +/mob/living/simple_animal/hostile/mining_drone/welder_act(mob/user, obj/item/I) + if(user.a_intent != INTENT_HELP) + return + . = TRUE + if(health == maxHealth) + to_chat(user, "[src] doesn't need repairing!") + return + if(!I.tool_use_check(user, 1)) + return + if(AIStatus != AI_OFF && AIStatus != AI_IDLE) + to_chat(user, "[src] is moving around too much to repair!") + return + WELDER_ATTEMPT_REPAIR_MESSAGE + if(I.use_tool(src, user, 15, 1, volume = I.tool_volume) && health != maxHealth) + adjustBruteLoss(-20) + WELDER_REPAIR_SUCCESS_MESSAGE + return + /mob/living/simple_animal/hostile/mining_drone/death() DropOre(0) if(stored_gun) diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index 37ff230ff44..6f9572a8a0c 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -21,15 +21,16 @@ if(is_mining_level(z)) score_oremined++ //When ore spawns, increment score. Only include ore spawned on mining level (No Clown Planet) -/obj/item/stack/ore/attackby(obj/item/I, mob/user, params) - ..() - if(istype(I, /obj/item/weldingtool)) - var/obj/item/weldingtool/W = I - if(W.remove_fuel(15) && refined_type) - new refined_type(get_turf(src.loc), amount) - qdel(src) - else if(W.isOn()) - to_chat(user, "Not enough fuel to smelt [src].") +/obj/item/stack/ore/welder_act(mob/user, obj/item/I) + . = TRUE + if(!refined_type) + to_chat(user, "You can't smelt [src] into anything useful!") + return + if(!I.use_tool(src, user, 0, 15, volume = I.tool_volume)) + return + new refined_type(drop_location(), amount) + to_chat(user, "You smelt [src] into its refined form!") + qdel(src) /obj/item/stack/ore/Crossed(atom/movable/AM, oldloc) var/obj/item/storage/bag/ore/OB @@ -144,14 +145,6 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ refined_type = /obj/item/stack/sheet/mineral/plasma materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT) -/obj/item/stack/ore/plasma/attackby(obj/item/I as obj, mob/user as mob, params) - if(istype(I, /obj/item/weldingtool)) - var/obj/item/weldingtool/W = I - if(W.welding) - to_chat(user, "You can't hit a high enough temperature to smelt [src] properly!") - else - ..() - /obj/item/stack/ore/silver name = "silver ore" icon_state = "Silver ore" @@ -332,6 +325,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ var/credits = 10 /obj/item/coin/New() + ..() pixel_x = rand(0,16)-8 pixel_y = rand(0,8)-8 @@ -443,21 +437,24 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ overlays = list() string_attached = null to_chat(user, "You detach the string from the coin.") - else if(istype(W,/obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(WT.welding && WT.remove_fuel(0, user)) - var/typelist = list("iron" = /obj/item/clothing/gloves/ring, - "silver" = /obj/item/clothing/gloves/ring/silver, - "gold" = /obj/item/clothing/gloves/ring/gold, - "plasma" = /obj/item/clothing/gloves/ring/plasma, - "uranium" = /obj/item/clothing/gloves/ring/uranium) - var/typekey = typelist[cmineral] - if(ispath(typekey)) - to_chat(user, "You make [src] into a ring.") - new typekey(get_turf(loc)) - qdel(src) else ..() +/obj/item/coin/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + var/typelist = list("iron" = /obj/item/clothing/gloves/ring, + "silver" = /obj/item/clothing/gloves/ring/silver, + "gold" = /obj/item/clothing/gloves/ring/gold, + "plasma" = /obj/item/clothing/gloves/ring/plasma, + "uranium" = /obj/item/clothing/gloves/ring/uranium) + var/typekey = typelist[cmineral] + if(ispath(typekey)) + to_chat(user, "You make [src] into a ring.") + new typekey(get_turf(loc)) + qdel(src) + + /obj/item/coin/attack_self(mob/user as mob) if(cooldown < world.time - 15) var/coinflip = pick(sideslist) diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 304bdc419a2..57232d74f44 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -30,12 +30,10 @@ // All mobs should have custom emote, really.. /mob/proc/custom_emote(var/m_type=EMOTE_VISUAL,var/message = null) - if(stat || !use_me && usr == src) if(usr) to_chat(usr, "You are unable to emote.") return - var/muzzled = is_muzzled() if(muzzled) var/obj/item/clothing/mask/muzzle/M = wear_mask @@ -57,7 +55,10 @@ if(message) log_emote(message, src) - + if(isliving(src)) //isliving because these are defined on the mob/living level not mob + var/mob/living/L = src + L.say_log += "EMOTE: [input]" //say log too so it is easier on admins instead of having to merge the two with timestamps etc + L.emote_log += input //emote only log if an admin wants to search just for emotes they don't have to sift through the say // Hearing gasp and such every five seconds is not good emotes were not global for a reason. // Maybe some people are okay with that. for(var/mob/M in GLOB.player_list) diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm index 45d4cda2202..a91aeed7bdf 100644 --- a/code/modules/mob/hear_say.dm +++ b/code/modules/mob/hear_say.dm @@ -162,7 +162,7 @@ if(copytext(heardword,1, 1) in punctuation) heardword = copytext(heardword,2) if(copytext(heardword,-1) in punctuation) - heardword = copytext(heardword,1,lentext(heardword)) + heardword = copytext(heardword,1,length(heardword)) heard = "...You hear something about... '[heardword]'..." else heard = "...You almost hear something......" diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index f4832e20384..04924d4b310 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -79,5 +79,5 @@ In all, this is a lot like the monkey code. /N if(M.is_adult) damage = rand(10, 40) adjustBruteLoss(damage) - add_attack_logs(src, M, "Slime'd for [damage] damage") + add_attack_logs(M, src, "Slime'd for [damage] damage") updatehealth("slime attack") \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm index ffe70211a37..e3cf646d579 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/carbon/brain/MMI.dm @@ -90,25 +90,28 @@ return // Maybe later add encryption key support, but that's a pain in the neck atm - if(isscrewdriver(O)) - if(radio) - user.visible_message("[user] begins to uninstall the radio from [src]...", \ - "You start to uninstall the radio from [src]...") - if(do_after(user, 40 * O.toolspeed, target = src)) - uninstall_radio() - new /obj/item/mmi_radio_upgrade(get_turf(src)) - user.visible_message("[user] uninstalls the radio from [src].", \ - "You uninstall the radio from [src].") - else - to_chat(user, "There is no radio in [src]!") - return if(brainmob) O.attack(brainmob, user)//Oh noooeeeee // Brainmobs can take damage, but they can't actually die. Maybe should fix. return - ..() + return ..() +/obj/item/mmi/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(!radio) + to_chat(user, "There is no radio in [src]!") + return + user.visible_message("[user] begins to uninstall the radio from [src]...", \ + "You start to uninstall the radio from [src]...") + if(!I.use_tool(src, user, 40, volume = I.tool_volume) || !radio) + return + uninstall_radio() + new /obj/item/mmi_radio_upgrade(get_turf(src)) + user.visible_message("[user] uninstalls the radio from [src].", \ + "You uninstall the radio from [src].") /obj/item/mmi/attack_self(mob/user as mob) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index fd60d5d49bd..7347e8eb3e9 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -615,10 +615,12 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, return TRUE /mob/living/carbon/restrained() - if(handcuffed) + if(get_restraining_item()) return TRUE - return + return FALSE +/mob/living/carbon/get_restraining_item() + return handcuffed /mob/living/carbon/unEquip(obj/item/I, force) //THIS PROC DID NOT CALL ..() . = ..() //Sets the default return value to what the parent returns. @@ -773,12 +775,15 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, /mob/living/carbon/resist_buckle() spawn(0) resist_muzzle() - if(restrained()) + var/obj/item/I + if((I = get_restraining_item())) // If there is nothing to restrain him then he is not restrained + var/breakouttime = I.breakouttime + var/displaytime = breakouttime / 10 changeNext_move(CLICK_CD_BREAKOUT) last_special = world.time + CLICK_CD_BREAKOUT visible_message("[src] attempts to unbuckle [p_them()]self!", \ - "You attempt to unbuckle yourself... (This will take around one minute and you need to stay still.)") - if(do_after(src, 600, 0, target = src)) + "You attempt to unbuckle yourself... (This will take around [displaytime] seconds and you need to stay still.)") + if(do_after(src, breakouttime, 0, target = src)) if(!buckled) return buckled.user_unbuckle_mob(src,src) @@ -836,10 +841,10 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, /mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 600, cuff_break = 0) breakouttime = I.breakouttime - var/displaytime = breakouttime / 600 + var/displaytime = breakouttime / 10 if(!cuff_break) visible_message("[src] attempts to remove [I]!") - to_chat(src, "You attempt to remove [I]... (This will take around [displaytime] minutes and you need to stand still.)") + to_chat(src, "You attempt to remove [I]... (This will take around [displaytime] seconds and you need to stand still.)") if(do_after(src, breakouttime, 0, target = src)) if(I.loc != src || buckled) return diff --git a/code/modules/mob/living/carbon/give.dm b/code/modules/mob/living/carbon/give.dm index c0dba9b77e5..a53c4af4563 100644 --- a/code/modules/mob/living/carbon/give.dm +++ b/code/modules/mob/living/carbon/give.dm @@ -18,10 +18,11 @@ to_chat(usr, "That's not exactly something you can give.") return if(target.r_hand == null || target.l_hand == null) - switch(alert(target,"[usr] wants to give you \a [I]?",,"Yes","No")) + var/ans = alert(target,"[usr] wants to give you \a [I]?",,"Yes","No") + if(!I || !target) + return + switch(ans) if("Yes") - if(!I) - return if(target.incapacitated() || usr.incapacitated()) return if(!Adjacent(target)) diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 146d107daba..a0fd10e0610 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -323,7 +323,7 @@ valid_species += current_species_name - return valid_species + return sortTim(valid_species, /proc/cmp_text_asc) /mob/living/carbon/human/proc/generate_valid_hairstyles() var/list/valid_hairstyles = new() @@ -351,7 +351,7 @@ if(H.dna.species.name in S.species_allowed) //If the user's head is of a species the hairstyle allows, add it to the list. valid_hairstyles += hairstyle - return valid_hairstyles + return sortTim(valid_hairstyles, /proc/cmp_text_asc) /mob/living/carbon/human/proc/generate_valid_facial_hairstyles() var/list/valid_facial_hairstyles = new() @@ -380,7 +380,7 @@ if(H.dna.species.name in S.species_allowed) //If the user's head is of a species the facial hair style allows, add it to the list. valid_facial_hairstyles += facialhairstyle - return valid_facial_hairstyles + return sortTim(valid_facial_hairstyles, /proc/cmp_text_asc) /mob/living/carbon/human/proc/generate_valid_head_accessories() var/list/valid_head_accessories = new() @@ -395,7 +395,7 @@ continue valid_head_accessories += head_accessory - return valid_head_accessories + return sortTim(valid_head_accessories, /proc/cmp_text_asc) /mob/living/carbon/human/proc/generate_valid_markings(var/location = "body") var/list/valid_markings = new() @@ -433,7 +433,7 @@ continue valid_markings += marking - return valid_markings + return sortTim(valid_markings, /proc/cmp_text_asc) /mob/living/carbon/human/proc/generate_valid_body_accessories() var/list/valid_body_accessories = new() @@ -448,7 +448,7 @@ if(dna.species.name in A.allowed_species) //If the user is not of a species the body accessory style allows, skip it. Otherwise, add it to the list. valid_body_accessories += B - return valid_body_accessories + return sortTim(valid_body_accessories, /proc/cmp_text_asc) /mob/living/carbon/human/proc/generate_valid_alt_heads() var/list/valid_alt_heads = list() @@ -463,7 +463,7 @@ valid_alt_heads += alternate_head - return valid_alt_heads + return sortTim(valid_alt_heads, /proc/cmp_text_asc) /mob/living/carbon/human/proc/scramble_appearance() scramble(1, src, 100) diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 4ceedc5b49c..d95badbbb01 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -158,10 +158,14 @@ return /mob/living/carbon/human/proc/ChangeToHusk() - var/obj/item/organ/external/head/H = bodyparts_by_name["head"] + + // If the target has no DNA to begin with, its DNA can't be damaged beyond repair. + if(NO_DNA in dna.species.species_traits) + return if(HUSK in mutations) return + var/obj/item/organ/external/head/H = bodyparts_by_name["head"] if(istype(H)) H.disfigured = TRUE //makes them unknown without fucking up other stuff like admintools if(H.f_style) diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 32841d3804d..01c2d773d51 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -118,6 +118,10 @@ on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm if("cough", "coughs", "slap", "slaps", "highfive") on_CD = handle_emote_CD() + if("gasp", "gasps") + on_CD = handle_emote_CD() + if("deathgasp", "deathgasps") + on_CD = handle_emote_CD(50) if("sneeze", "sneezes") on_CD = handle_emote_CD() if("clap", "claps") @@ -502,6 +506,14 @@ else if(!muzzled) message = "[src] gasps!" + if(health <= 0) + if(gender == FEMALE) + playsound(loc, pick(dna.species.female_dying_gasp_sounds), 100, 1, frequency = get_age_pitch()) + else + playsound(loc, pick(dna.species.male_dying_gasp_sounds), 100, 1, frequency = get_age_pitch()) + + else + playsound(loc, dna.species.gasp_sound, 15, 1, frequency = get_age_pitch()) m_type = 2 else message = "[src] makes a weak noise." @@ -509,6 +521,7 @@ if("deathgasp", "deathgasps") message = "[src] [replacetext(dna.species.death_message, "their", p_their())]" + playsound(loc, pick(dna.species.death_sounds), 40, 1, frequency = get_age_pitch()) m_type = 1 if("giggle", "giggles") @@ -824,9 +837,9 @@ message = "[src] [dna.species.scream_verb][M ? " at [M]" : ""]!" m_type = 2 if(gender == FEMALE) - playsound(loc, "[dna.species.female_scream_sound]", 80, 1, frequency = get_age_pitch()) + playsound(loc, dna.species.female_scream_sound, 80, 1, frequency = get_age_pitch()) else - playsound(loc, "[dna.species.male_scream_sound]", 80, 1, frequency = get_age_pitch()) //default to male screams if no gender is present. + playsound(loc, dna.species.male_scream_sound, 80, 1, frequency = get_age_pitch()) //default to male screams if no gender is present. else message = "[src] makes a very loud noise[M ? " at [M]" : ""]." diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 7a18e881eb6..85bb90a168e 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -215,6 +215,12 @@ else if(E.status & ORGAN_SPLINTED) wound_flavor_text["[E.limb_name]"] = "[p_they(TRUE)] [p_have()] a splint on [p_their()] [E.name]!\n" + if(E.open) + if(E.is_robotic()) + msg += "The maintenance hatch on [p_their()] [ignore_limb_branding(E.limb_name)] is open!\n" + else + msg += "[p_their(TRUE)] [ignore_limb_branding(E.limb_name)] has an open incision!\n" + for(var/obj/item/I in E.embedded_objects) msg += "[p_they(TRUE)] [p_have()] \a [bicon(I)] [I] embedded in [p_their()] [E.name]!\n" @@ -370,7 +376,7 @@ msg += "*---------*" if(pose) - if( findtext(pose,".",lentext(pose)) == 0 && findtext(pose,"!",lentext(pose)) == 0 && findtext(pose,"?",lentext(pose)) == 0 ) + if( findtext(pose,".",length(pose)) == 0 && findtext(pose,"!",length(pose)) == 0 && findtext(pose,"?",length(pose)) == 0 ) pose = addtext(pose,".") //Makes sure all emotes end with a period. msg += "\n[p_they(TRUE)] [p_are()] [pose]" @@ -403,3 +409,29 @@ return 0 else return 0 + +// Ignores robotic limb branding prefixes like "Morpheus Cybernetics" +/proc/ignore_limb_branding(limb_name) + switch(limb_name) + if("chest") + . = "upper body" + if("groin") + . = "lower body" + if("head") + . = "head" + if("l_arm") + . = "left arm" + if("r_arm") + . = "right arm" + if("l_leg") + . = "left leg" + if("r_leg") + . = "right leg" + if("l_foot") + . = "left foot" + if("r_foot") + . = "right foot" + if("l_hand") + . = "left hand" + if("r_hand") + . = "right hand" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index fd4c9f0116e..2c00a4f91bd 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -312,13 +312,10 @@ return 0 ..() -/mob/living/carbon/human/restrained() - if(handcuffed) - return 1 - if(istype(wear_suit, /obj/item/clothing/suit/straight_jacket)) - return 1 - return 0 - +/mob/living/carbon/human/get_restraining_item() + . = ..() + if(!. && istype(wear_suit, /obj/item/clothing/suit/straight_jacket)) + . = wear_suit /mob/living/carbon/human/var/temperature_resistance = T0C+75 @@ -457,12 +454,6 @@ popup.set_content(dat) popup.open() - -/mob/living/carbon/human/Crossed(atom/movable/AM, oldloc) - var/mob/living/simple_animal/bot/mulebot/MB = AM - if(istype(MB)) - MB.RunOver(src) - // Get rank from ID, ID inside PDA, PDA, ID in wallet, etc. /mob/living/carbon/human/proc/get_authentification_rank(var/if_no_id = "No id", var/if_no_job = "No job") var/obj/item/pda/pda = wear_id @@ -668,7 +659,7 @@ if(place_item) usr.unEquip(place_item) equip_to_slot_if_possible(place_item, pocket_id, 0, 1) - add_attack_logs(usr, src, "Equipped with [pocket_item]", isLivingSSD(src) ? null : ATKLOG_ALL) + add_attack_logs(usr, src, "Equipped with [place_item]", isLivingSSD(src) ? null : ATKLOG_ALL) // Update strip window if(usr.machine == src && in_range(src, usr)) diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 71a3ae3e87c..65a75f80e8c 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -22,7 +22,7 @@ med_hud_set_status() handle_hud_icons_health() -/mob/living/carbon/human/adjustBrainLoss(amount, updating = TRUE) +/mob/living/carbon/human/adjustBrainLoss(amount, updating = TRUE, use_brain_mod = TRUE) if(status_flags & GODMODE) return STATUS_UPDATE_NONE //godmode @@ -30,7 +30,8 @@ var/obj/item/organ/internal/brain/sponge = get_int_organ(/obj/item/organ/internal/brain) if(sponge) if(dna.species && amount > 0) - amount = amount * dna.species.brain_mod + if(use_brain_mod) + amount = amount * dna.species.brain_mod sponge.damage = Clamp(sponge.damage + amount, 0, 120) if(sponge.damage >= 120) visible_message("[src] goes limp, [p_their()] facial expression utterly blank.") @@ -39,7 +40,7 @@ update_stat("adjustBrainLoss") return STATUS_UPDATE_STAT -/mob/living/carbon/human/setBrainLoss(amount, updating = TRUE) +/mob/living/carbon/human/setBrainLoss(amount, updating = TRUE, use_brain_mod = TRUE) if(status_flags & GODMODE) return STATUS_UPDATE_NONE //godmode @@ -47,7 +48,8 @@ var/obj/item/organ/internal/brain/sponge = get_int_organ(/obj/item/organ/internal/brain) if(sponge) if(dna.species && amount > 0) - amount = amount * dna.species.brain_mod + if(use_brain_mod) + amount = amount * dna.species.brain_mod sponge.damage = Clamp(amount, 0, 120) if(sponge.damage >= 120) visible_message("[src] goes limp, [p_their()] facial expression utterly blank.") diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 6c1cfeb7714..e0a9001437e 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -16,20 +16,8 @@ emp_act if(check_reflect(def_zone)) // Checks if you've passed a reflection% check visible_message("The [P.name] gets reflected by [src]!", \ "The [P.name] gets reflected by [src]!") - // Find a turf near or on the original location to bounce to - if(P.starting) - var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/turf/curloc = get_turf(src) - // redirect the projectile - P.firer = src - P.original = locate(new_x, new_y, P.z) - P.starting = curloc - P.current = curloc - P.yo = new_y - curloc.y - P.xo = new_x - curloc.x - P.Angle = null + P.reflect_back(src) return -1 // complete projectile permutation @@ -47,6 +35,63 @@ emp_act return (..(P , def_zone)) +/mob/living/carbon/human/welder_act(mob/user, obj/item/I) + if(user.a_intent != INTENT_HELP) + return + if(!I.tool_use_check(user, 1)) + return + var/obj/item/organ/external/S = bodyparts_by_name[user.zone_selected] + if(!S) + return + if(!S.is_robotic() || S.open == 2) + return + . = TRUE + if(S.brute_dam > ROBOLIMB_SELF_REPAIR_CAP) + to_chat(user, "The damage is far too severe to patch over externally.") + return + + if(!S.brute_dam) + to_chat(user, "Nothing to fix!") + return + + var/surgery_time = 0 + if(user == src) + surgery_time = 10 + if(!I.use_tool(src, user, surgery_time, amount = 1, volume = I.tool_volume)) + return + var/rembrute = HEALPERWELD + var/nrembrute = 0 + var/childlist + if(!isnull(S.children)) + childlist = S.children.Copy() + var/parenthealed = FALSE + while(rembrute > 0) + var/obj/item/organ/external/E + if(S.brute_dam) + E = S + else if(LAZYLEN(childlist)) + E = pick_n_take(childlist) + if(!E.brute_dam || !E.is_robotic()) + continue + else if(S.parent && !parenthealed) + E = S.parent + parenthealed = TRUE + if(!E.brute_dam || !E.is_robotic()) + break + else + break + nrembrute = max(rembrute - E.brute_dam, 0) + E.heal_damage(rembrute,0,0,1) + rembrute = nrembrute + user.visible_message("[user] patches some dents on [src]'s [E.name] with [I].") + if(bleed_rate && isSynthetic()) + bleed_rate = 0 + user.visible_message("[user] patches some leaks on [src] with [I].") + if(IgniteMob()) + message_admins("[key_name_admin(user)] set [key_name_admin(src)] on fire with [I]") + log_game("[key_name(user)] set [key_name(src)] on fire with [I]") + + /mob/living/carbon/human/check_projectile_dismemberment(obj/item/projectile/P, def_zone) var/obj/item/organ/external/affecting = get_organ(check_zone(def_zone)) if(affecting && !affecting.cannot_amputate && affecting.get_damage() >= (affecting.max_damage - P.dismemberment)) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 2643d1f3102..93e7ff54ec6 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -542,7 +542,7 @@ if(COLDRES in mutations) return 1 //Fully protected from the cold. - temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K. + temperature = max(temperature, TCMB) //There is an occasional bug where the temperature is miscalculated in areas with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K. var/thermal_protection_flags = get_cold_protection_flags(temperature) var/thermal_protection = 0.0 diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 2f181d77077..220c3b9df84 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -97,6 +97,9 @@ return real_name /mob/living/carbon/human/IsVocal() + var/obj/item/organ/internal/cyberimp/brain/speech_translator/translator = locate(/obj/item/organ/internal/cyberimp/brain/speech_translator) in internal_organs + if(translator && translator.active) + return TRUE // how do species that don't breathe talk? magic, that's what. var/breathes = (!(NO_BREATHE in dna.species.species_traits)) var/obj/item/organ/internal/L = get_organ_slot("lungs") diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm index c56f0140ee2..77de1175178 100644 --- a/code/modules/mob/living/carbon/human/species/_species.dm +++ b/code/modules/mob/living/carbon/human/species/_species.dm @@ -115,6 +115,10 @@ var/scream_verb = "screams" var/male_scream_sound = 'sound/goonstation/voice/male_scream.ogg' var/female_scream_sound = 'sound/goonstation/voice/female_scream.ogg' + var/list/death_sounds = list('sound/goonstation/voice/deathgasp_1.ogg', 'sound/goonstation/voice/deathgasp_2.ogg') + var/list/male_dying_gasp_sounds = list('sound/goonstation/voice/male_dying_gasp_1.ogg', 'sound/goonstation/voice/male_dying_gasp_2.ogg', 'sound/goonstation/voice/male_dying_gasp_3.ogg', 'sound/goonstation/voice/male_dying_gasp_4.ogg', 'sound/goonstation/voice/male_dying_gasp_5.ogg') + var/list/female_dying_gasp_sounds = list('sound/goonstation/voice/female_dying_gasp_1.ogg', 'sound/goonstation/voice/female_dying_gasp_2.ogg', 'sound/goonstation/voice/female_dying_gasp_3.ogg', 'sound/goonstation/voice/female_dying_gasp_4.ogg', 'sound/goonstation/voice/female_dying_gasp_5.ogg') + var/gasp_sound = 'sound/goonstation/voice/gasp.ogg' var/male_cough_sounds = list('sound/effects/mob_effects/m_cougha.ogg','sound/effects/mob_effects/m_coughb.ogg', 'sound/effects/mob_effects/m_coughc.ogg') var/female_cough_sounds = list('sound/effects/mob_effects/f_cougha.ogg','sound/effects/mob_effects/f_coughb.ogg') var/male_sneeze_sound = 'sound/effects/mob_effects/sneeze.ogg' diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm index 7c92d8748bd..f88670fc0c1 100644 --- a/code/modules/mob/living/carbon/human/species/golem.dm +++ b/code/modules/mob/living/carbon/human/species/golem.dm @@ -474,19 +474,9 @@ if(P.is_reflectable) H.visible_message("The [P.name] gets reflected by [H]'s glass skin!", \ "The [P.name] gets reflected by [H]'s glass skin!") - if(P.starting) - var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/turf/curloc = get_turf(H) + + P.reflect_back(H) - // redirect the projectile - P.firer = src - P.original = locate(new_x, new_y, P.z) - P.starting = curloc - P.current = curloc - P.yo = new_y - curloc.y - P.xo = new_x - curloc.x - P.Angle = null return FALSE return TRUE diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm index a0980256718..b357d2c5345 100644 --- a/code/modules/mob/living/carbon/human/species/monkey.dm +++ b/code/modules/mob/living/carbon/human/species/monkey.dm @@ -131,6 +131,13 @@ "appendix" = /obj/item/organ/internal/appendix, "eyes" = /obj/item/organ/internal/eyes/skrell //Tajara monkey-forms are uniquely colourblind and have excellent darksight, which is why they need a subtype of their greater-form's organ.. ) +/datum/species/monkey/skrell/on_species_gain(mob/living/carbon/human/H) + ..() + ADD_TRAIT(H, TRAIT_WATERBREATH, "species") + +/datum/species/monkey/skrell/on_species_loss(mob/living/carbon/human/H) + ..() + REMOVE_TRAIT(H, TRAIT_WATERBREATH, "species") /datum/species/monkey/unathi name = "Stok" diff --git a/code/modules/mob/living/carbon/human/species/skrell.dm b/code/modules/mob/living/carbon/human/species/skrell.dm index 009514f4902..9e21c0bf390 100644 --- a/code/modules/mob/living/carbon/human/species/skrell.dm +++ b/code/modules/mob/living/carbon/human/species/skrell.dm @@ -12,6 +12,7 @@ herbivores on the whole and tend to be co-operative with the other species of the galaxy, although they rarely reveal \ the secrets of their empire to their allies." + species_traits = list(LIPS) clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS bodyflags = HAS_SKIN_COLOR | HAS_BODY_MARKINGS @@ -43,4 +44,12 @@ "is jamming their thumbs into their eye sockets!", "is twisting their own neck!", "makes like a fish and suffocates!", - "is strangling themselves with their own tendrils!") \ No newline at end of file + "is strangling themselves with their own tendrils!") + +/datum/species/skrell/on_species_gain(mob/living/carbon/human/H) + ..() + ADD_TRAIT(H, TRAIT_WATERBREATH, "species") + +/datum/species/skrell/on_species_loss(mob/living/carbon/human/H) + ..() + REMOVE_TRAIT(H, TRAIT_WATERBREATH, "species") \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/slime.dm b/code/modules/mob/living/carbon/human/species/slime.dm index 42a566e450c..e7501486b72 100644 --- a/code/modules/mob/living/carbon/human/species/slime.dm +++ b/code/modules/mob/living/carbon/human/species/slime.dm @@ -72,6 +72,7 @@ grow.Grant(H) recolor = new() recolor.Grant(H) + ADD_TRAIT(H, TRAIT_WATERBREATH, "species") /datum/species/slime/on_species_loss(mob/living/carbon/human/H) ..() @@ -79,6 +80,7 @@ grow.Remove(H) if(recolor) recolor.Remove(H) + REMOVE_TRAIT(H, TRAIT_WATERBREATH, "species") /datum/species/slime/handle_life(mob/living/carbon/human/H) // Slowly shifting to the color of the reagents diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index ba822c9cc5e..b35556903f2 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -270,6 +270,13 @@ take_organ_damage(acidpwr * min(1, acid_volume * 0.1)) return 1 +/mob/living/welder_act(mob/user, obj/item/I) + if(!I.tool_use_check(null, 0)) //Don't need the message, just if it succeeded + return + if(IgniteMob()) + message_admins("[key_name_admin(user)] set [key_name_admin(src)] on fire with [I]") + log_game("[key_name(user)] set [key_name(src)] on fire with [I]") + /mob/living/proc/updatehealth(reason = "none given") if(status_flags & GODMODE) health = maxHealth @@ -397,6 +404,7 @@ if(C.reagents) C.reagents.clear_reagents() QDEL_LIST(C.reagents.addiction_list) + C.reagents.addiction_threshold_accumulated.Cut() // rejuvenate: Called by `revive` to get the mob into a revivable state // the admin "rejuvenate" command calls `revive`, not this proc. diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 67ea6e7f887..2b148a6a0a2 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -296,7 +296,7 @@ return FALSE if(stat != DEAD) - add_attack_logs(src, M, "Slime'd") + add_attack_logs(M, src, "Slime'd") M.do_attack_animation(src) visible_message("\The [M.name] glomps [src]!", "\The [M.name] glomps you!") return TRUE diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 74a51a771ac..8f5ed797b6c 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -59,6 +59,7 @@ var/tesla_ignore = FALSE var/list/say_log = list() //a log of what we've said, plain text, no spans or junk, essentially just each individual "message" + var/list/emote_log = list() //like say_log but for emotes var/list/recent_tastes = list() var/blood_volume = 0 //how much blood the mob has diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 7822584ab98..8ae4fc6a419 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -1125,6 +1125,8 @@ var/list/ai_verbs_default = list( else return ..() +/mob/living/silicon/ai/welder_act() + return /mob/living/silicon/ai/proc/control_integrated_radio() set name = "Radio Settings" @@ -1200,7 +1202,8 @@ var/list/ai_verbs_default = list( if(isturf(loc)) //AI in core, check if on cameras //get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera //apc_override is needed here because AIs use their own APC when depowered - return (cameranet && cameranet.checkTurfVis(get_turf_pixel(A))) || apc_override + var/turf/T = isturf(A) ? A : get_turf_pixel(A) + return (cameranet && cameranet.checkTurfVis(T)) || apc_override //AI is carded/shunted //view(src) returns nothing for carded/shunted AIs and they have x-ray vision so just use get_dist var/list/viewscale = getviewsize(client.view) diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm index 36f248cd2c2..b4db13f5452 100644 --- a/code/modules/mob/living/silicon/ai/say.dm +++ b/code/modules/mob/living/silicon/ai/say.dm @@ -129,7 +129,8 @@ var/const/VOX_PATH = "sound/vox_fem/" announcing_vox = world.time + VOX_DELAY - log_game("[key_name_admin(src)] made a vocal announcement with the following message: [message].") + log_game("[key_name(src)] made a vocal announcement: [message].") + message_admins("[key_name_admin(src)] made a vocal announcement: [message].") for(var/word in words) play_vox_word(word, src.z, null) diff --git a/code/modules/mob/living/silicon/decoy/decoy.dm b/code/modules/mob/living/silicon/decoy/decoy.dm index d8f82cf9d93..64965ae518f 100644 --- a/code/modules/mob/living/silicon/decoy/decoy.dm +++ b/code/modules/mob/living/silicon/decoy/decoy.dm @@ -19,6 +19,9 @@ else return ..() +/mob/living/silicon/decoy/welder_act() + return + /mob/living/silicon/decoy/syndicate faction = list("syndicate") name = "R.O.D.G.E.R" diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 25547e5de9e..a022e29eb5b 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -470,6 +470,9 @@ close_up() return +/mob/living/silicon/pai/welder_act() + return + /mob/living/silicon/pai/attack_hand(mob/user as mob) if(stat == DEAD) return @@ -538,7 +541,7 @@ if(print_flavor_text()) msg += "\n[print_flavor_text()]" if(pose) - if( findtext(pose,".",lentext(pose)) == 0 && findtext(pose,"!",lentext(pose)) == 0 && findtext(pose,"?",lentext(pose)) == 0 ) + if( findtext(pose,".",length(pose)) == 0 && findtext(pose,"!",length(pose)) == 0 && findtext(pose,"?",length(pose)) == 0 ) pose = addtext(pose,".") //Makes sure all emotes end with a period. msg += "\nIt is [pose]" msg += "\n*---------*" diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm index 0750e4ea3ed..26b5683d1a3 100644 --- a/code/modules/mob/living/silicon/robot/component.dm +++ b/code/modules/mob/living/silicon/robot/component.dm @@ -10,15 +10,11 @@ var/max_damage = 30 var/component_disabled = 0 var/mob/living/silicon/robot/owner - -// The actual device object that has to be installed for this. -/datum/robot_component/var/external_type = null - -// The wrapped device(e.g. radio), only set if external_type isn't null -/datum/robot_component/var/obj/item/wrapped = null + var/external_type = null // The actual device object that has to be installed for this. + var/obj/item/wrapped = null // The wrapped device(e.g. radio), only set if external_type isn't null /datum/robot_component/New(mob/living/silicon/robot/R) - src.owner = R + owner = R /datum/robot_component/proc/install() go_online() @@ -109,6 +105,13 @@ name = "power cell" max_damage = 50 +/datum/robot_component/cell/New(mob/living/silicon/robot/R) + . = ..() + // sets `external_type` to the borg's currently installed cell type + if(owner.cell) + var/obj/item/stock_parts/cell/C = owner.cell + external_type = C.type + /datum/robot_component/cell/is_powered() return ..() && owner.cell diff --git a/code/modules/mob/living/silicon/robot/examine.dm b/code/modules/mob/living/silicon/robot/examine.dm index 56d01fea839..198b687e496 100644 --- a/code/modules/mob/living/silicon/robot/examine.dm +++ b/code/modules/mob/living/silicon/robot/examine.dm @@ -50,7 +50,7 @@ if(print_flavor_text()) msg += "\n[print_flavor_text()]\n" if(pose) - if( findtext(pose,".",lentext(pose)) == 0 && findtext(pose,"!",lentext(pose)) == 0 && findtext(pose,"?",lentext(pose)) == 0 ) + if( findtext(pose,".",length(pose)) == 0 && findtext(pose,"!",length(pose)) == 0 && findtext(pose,"?",length(pose)) == 0 ) pose = addtext(pose,".") //Makes sure all emotes end with a period. msg += "\nIt is [pose]" diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 1cded581118..6c399a7161f 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -142,6 +142,9 @@ var/list/robot_verbs_default = list( mmi = new /obj/item/mmi/robotic_brain(src) //Give the borg an MMI if he spawns without for some reason. (probably not the correct way to spawn a robotic brain, but it works) mmi.icon_state = "boris" + if(!cell) // Make sure a new cell gets created *before* executing initialize_components(). The cell component needs an existing cell for it to get set up properly + cell = new /obj/item/stock_parts/cell/high(src) + initialize_components() //if(!unfinished) // Create all the robot parts. @@ -150,9 +153,6 @@ var/list/robot_verbs_default = list( C.installed = 1 C.wrapped = new C.external_type - if(!cell) - cell = new /obj/item/stock_parts/cell/high(src) - ..() add_robot_verbs() @@ -602,7 +602,8 @@ var/list/robot_verbs_default = list( /mob/living/silicon/robot/attackby(obj/item/W, mob/user, params) - if(opened) // Are they trying to insert something? + // Check if the user is trying to insert another component like a radio, actuator, armor etc. + if(istype(W, /obj/item/robot_parts/robot_component) && opened) for(var/V in components) var/datum/robot_component/C = components[V] if(!C.installed && istype(W, C.external_type)) @@ -621,28 +622,7 @@ var/list/robot_verbs_default = list( return - if(istype(W, /obj/item/weldingtool) && user.a_intent == INTENT_HELP) - if(W == module_active) - return - if(!getBruteLoss()) - to_chat(user, "Nothing to fix!") - return - else if(!getBruteLoss(TRUE)) - to_chat(user, "The damaged components are beyond saving!") - return - var/obj/item/weldingtool/WT = W - user.changeNext_move(CLICK_CD_MELEE) - if(WT.remove_fuel(0)) - playsound(src.loc, W.usesound, 50, 1) - adjustBruteLoss(-30) - add_fingerprint(user) - user.visible_message("\The [user] patches some dents on \the [src] with \the [WT].") - else - to_chat(user, "Need more welding fuel!") - return - - - else if(istype(W, /obj/item/stack/cable_coil) && user.a_intent == INTENT_HELP && (wiresexposed || istype(src, /mob/living/silicon/robot/drone))) + if(istype(W, /obj/item/stack/cable_coil) && user.a_intent == INTENT_HELP && (wiresexposed || istype(src, /mob/living/silicon/robot/drone))) user.changeNext_move(CLICK_CD_MELEE) if(!getFireLoss()) to_chat(user, "Nothing to fix!") @@ -657,60 +637,8 @@ var/list/robot_verbs_default = list( coil.use(1) user.visible_message("\The [user] fixes some of the burnt wires on \the [src] with \the [coil].") - else if(istype(W, /obj/item/crowbar)) // crowbar means open or close the cover - if(opened) - if(cell) - to_chat(user, "You close the cover.") - opened = 0 - update_icons() - else if(wiresexposed && wires.IsAllCut()) - //Cell is out, wires are exposed, remove MMI, produce damaged chassis, baleet original mob. - if(!mmi) - to_chat(user, "[src] has no brain to remove.") - return - - to_chat(user, "You jam the crowbar into the robot and begin levering the securing bolts.") - if(do_after(user, 30 * W.toolspeed, target = src)) - user.visible_message("[user] deconstructs [src]!", "You unfasten the securing bolts, and [src] falls to pieces!") - deconstruct() - else - // Okay we're not removing the cell or an MMI, but maybe something else? - var/list/removable_components = list() - for(var/V in components) - if(V == "power cell") continue - var/datum/robot_component/C = components[V] - if(C.installed == 1 || C.installed == -1) - removable_components += V - if(module) - removable_components += module.custom_removals - var/remove = input(user, "Which component do you want to pry out?", "Remove Component") as null|anything in removable_components - if(!remove) - return - if(module && module.handle_custom_removal(remove, user, W, params)) - return - var/datum/robot_component/C = components[remove] - var/obj/item/robot_parts/robot_component/I = C.wrapped - to_chat(user, "You remove \the [I].") - if(istype(I)) - I.brute = C.brute_damage - I.burn = C.electronics_damage - - I.loc = src.loc - var/was_installed = C.installed - C.installed = 0 - if(was_installed == 1) - C.uninstall() - - else - if(locked) - to_chat(user, "The cover is locked and cannot be opened.") - else - to_chat(user, "You open the cover.") - opened = 1 - update_icons() - else if(istype(W, /obj/item/stock_parts/cell) && opened) // trying to put a cell inside - var/datum/robot_component/C = components["power cell"] + var/datum/robot_component/cell/C = components["power cell"] if(wiresexposed) to_chat(user, "Close the panel first.") else if(cell) @@ -724,29 +652,12 @@ var/list/robot_verbs_default = list( C.installed = 1 C.wrapped = W C.install() + C.external_type = W.type // Update the cell component's `external_type` to the path of new cell //This will mean that removing and replacing a power cell will repair the mount, but I don't care at this point. ~Z C.brute_damage = 0 C.electronics_damage = 0 diag_hud_set_borgcell() - else if(istype(W, /obj/item/wirecutters) || istype(W, /obj/item/multitool)) - if(wiresexposed) - wires.Interact(user) - else - to_chat(user, "You can't reach the wiring.") - - else if(istype(W, /obj/item/screwdriver) && opened && !cell) // haxing - wiresexposed = !wiresexposed - to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"]") - update_icons() - - else if(istype(W, /obj/item/screwdriver) && opened && cell) // radio - if(radio) - radio.attackby(W,user)//Push it to the radio to let it handle everything - else - to_chat(user, "Unable to locate a radio.") - update_icons() - else if(istype(W, /obj/item/encryptionkey/) && opened) if(radio)//sanityyyyyy radio.attackby(W,user)//GTFO, you have your own procs @@ -801,6 +712,108 @@ var/list/robot_verbs_default = list( else return ..() +/mob/living/silicon/robot/wirecutter_act(mob/user, obj/item/I) + if(!opened) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = 0)) + return + if(wiresexposed) + wires.Interact(user) + +/mob/living/silicon/robot/multitool_act(mob/user, obj/item/I) + if(!opened) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = 0)) + return + if(wiresexposed) + wires.Interact(user) + +/mob/living/silicon/robot/screwdriver_act(mob/user, obj/item/I) + if(!opened) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = 0)) + return + if(!cell) // haxing + wiresexposed = !wiresexposed + to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"]") + update_icons() + I.play_tool_sound(user, I.tool_volume) + else //radio check + if(radio) + radio.screwdriver_act(user, I)//Push it to the radio to let it handle everything + else + to_chat(user, "Unable to locate a radio.") + update_icons() + +/mob/living/silicon/robot/crowbar_act(mob/user, obj/item/I) + if(user.a_intent != INTENT_HELP) + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(!opened) + if(locked) + to_chat(user, "The cover is locked and cannot be opened.") + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + to_chat(user, "You open the cover.") + opened = TRUE + update_icons() + return + else if(cell) + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + to_chat(user, "You close the cover.") + opened = FALSE + update_icons() + return + else if(wiresexposed && wires.IsAllCut()) + //Cell is out, wires are exposed, remove MMI, produce damaged chassis, baleet original mob. + if(!mmi) + to_chat(user, "[src] has no brain to remove.") + return + to_chat(user, "You jam the crowbar into the robot and begin levering the securing bolts...") + if(I.use_tool(src, user, 30, volume = I.tool_volume)) + user.visible_message("[user] deconstructs [src]!", "You unfasten the securing bolts, and [src] falls to pieces!") + deconstruct() + return + // Okay we're not removing the cell or an MMI, but maybe something else? + var/list/removable_components = list() + for(var/V in components) + if(V == "power cell") + continue + var/datum/robot_component/C = components[V] + if(C.installed == 1 || C.installed == -1) + removable_components += V + if(module) + removable_components += module.custom_removals + var/remove = input(user, "Which component do you want to pry out?", "Remove Component") as null|anything in removable_components + if(!remove) + return + if(module && module.handle_custom_removal(remove, user, I)) + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + var/datum/robot_component/C = components[remove] + var/obj/item/robot_parts/robot_component/thing = C.wrapped + to_chat(user, "You remove \the [thing].") + if(istype(thing)) + thing.brute = C.brute_damage + thing.burn = C.electronics_damage + + thing.loc = loc + var/was_installed = C.installed + C.installed = 0 + if(was_installed == 1) + C.uninstall() + + + + /mob/living/silicon/robot/attacked_by(obj/item/I, mob/living/user, def_zone) if(I.force && I.damtype != STAMINA && stat != DEAD) //only sparks if real damage is dealt. spark_system.start() @@ -1408,6 +1421,8 @@ var/list/robot_verbs_default = list( burn = borked_part.electronics_damage borked_part.installed = 1 borked_part.wrapped = new borked_part.external_type + if(ispath(borked_part.external_type, /obj/item/stock_parts/cell)) // is the broken part a cell? + cell = new borked_part.external_type // borgs that have their cell destroyed have their `cell` var set to null. we need create a new cell for them based on their old cell type. borked_part.heal_damage(brute,burn) borked_part.install() @@ -1457,4 +1472,3 @@ var/list/robot_verbs_default = list( SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT) sync_lighting_plane_alpha() - diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 76c7f5bc1af..5baf020d563 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -28,6 +28,7 @@ /obj/item/robot_module/New() + ..() modules += new /obj/item/flash/cyborg(src) emag = new /obj/item/toy/sword(src) emag.name = "Placeholder Emag Item" @@ -106,7 +107,7 @@ R.module_actions.Cut() // Return true in an overridden subtype to prevent normal removal handling -/obj/item/robot_module/proc/handle_custom_removal(component_id, mob/living/user, obj/item/W, params) +/obj/item/robot_module/proc/handle_custom_removal(component_id, mob/living/user, obj/item/W) return FALSE /obj/item/robot_module/proc/handle_death(gibbed) @@ -358,10 +359,10 @@ fix_modules() -/obj/item/robot_module/miner/handle_custom_removal(component_id, mob/living/user, obj/item/W, params) +/obj/item/robot_module/miner/handle_custom_removal(component_id, mob/living/user, obj/item/W) if(component_id == "KA modkits") for(var/obj/item/gun/energy/kinetic_accelerator/cyborg/D in src) - D.attackby(W, user, params) + D.attackby(W, user) return TRUE return ..() @@ -505,6 +506,7 @@ ) /obj/item/robot_module/alien/hunter/New() + ..() modules += new /obj/item/melee/energy/alien/claws(src) modules += new /obj/item/flash/cyborg/alien(src) var/obj/item/reagent_containers/spray/alien/stun/S = new /obj/item/reagent_containers/spray/alien/stun(src) @@ -538,6 +540,7 @@ ) /obj/item/robot_module/drone/New() + ..() modules += new /obj/item/weldingtool/largetank/cyborg(src) modules += new /obj/item/screwdriver/cyborg(src) modules += new /obj/item/wrench/cyborg(src) diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 51841440989..e70c00158a7 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -100,6 +100,25 @@ /mob/living/silicon/IsAdvancedToolUser() return TRUE +/mob/living/silicon/robot/welder_act(mob/user, obj/item/I) + if(user.a_intent != INTENT_HELP) + return + if(user == src) //No self-repair dummy + return + . = TRUE + if(!getBruteLoss()) + to_chat(user, "Nothing to fix!") + return + else if(!getBruteLoss(TRUE)) + to_chat(user, "The damaged components are beyond saving!") + return + if(!I.use_tool(src, user, volume = I.tool_volume)) + return + adjustBruteLoss(-30) + add_fingerprint(user) + user.visible_message("[user] patches some dents on [src] with [I].") + + /mob/living/silicon/bullet_act(var/obj/item/projectile/Proj) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 1fba341fd59..7f1868b0bdb 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -146,7 +146,7 @@ access_card.access += access_robotics set_custom_texts() Radio = new/obj/item/radio/headset/bot(src) - + Radio.follow_target = src add_language("Galactic Common", 1) add_language("Sol Common", 1) add_language("Tradeband", 1) @@ -357,25 +357,25 @@ user.visible_message("[user] uses [W] to pull [paicard] out of [bot_name]!","You pull [paicard] out of [bot_name] with [W].") ejectpai(user) else - user.changeNext_move(CLICK_CD_MELEE) - if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM) - if(health >= maxHealth) - to_chat(user, "[src] does not need a repair!") - return - if(!open) - to_chat(user, "Unable to repair with the maintenance panel closed!") - return - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - adjustHealth(-10) - add_fingerprint(user) - user.visible_message("[user] repairs [src]!","You repair [src].") - else - to_chat(user, "The welder must be on for this task!") - else - if(W.force) //if force is non-zero - do_sparks(5, 1, src) - ..() + return ..() + +/mob/living/simple_animal/bot/welder_act(mob/user, obj/item/I) + if(user.a_intent != INTENT_HELP) + return + if(user == src) //No self-repair dummy + return + . = TRUE + if(health >= maxHealth) + to_chat(user, "[src] does not need a repair!") + return + if(!open) + to_chat(user, "Unable to repair with the maintenance panel closed!") + return + if(!I.use_tool(src, user, volume = I.tool_volume)) + return + adjustBruteLoss(-10) + add_fingerprint(user) + user.visible_message("[user] repairs [src]!","You repair [src].") /mob/living/simple_animal/bot/bullet_act(obj/item/projectile/Proj) if(Proj && (Proj.damage_type == BRUTE || Proj.damage_type == BURN)) diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm index 5feebb53059..52155a73a44 100644 --- a/code/modules/mob/living/simple_animal/bot/construction.dm +++ b/code/modules/mob/living/simple_animal/bot/construction.dm @@ -96,12 +96,10 @@ var/robot_arm = /obj/item/robot_parts/l_arm icon_state = "[lasercolor]ed209_shell" if(3) - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - build_step++ - name = "shielded frame assembly" - to_chat(user, "You weld the vest to [src].") + if(W.tool_behaviour == TOOL_WELDER && W.use_tool(src, user, volume = W.tool_volume)) + build_step++ + name = "shielded frame assembly" + to_chat(user, "You weld the vest to [src].") if(4) switch(lasercolor) if("b") @@ -440,19 +438,15 @@ var/robot_arm = /obj/item/robot_parts/l_arm /obj/item/secbot_assembly/attackby(obj/item/I, mob/user, params) ..() - if(istype(I, /obj/item/weldingtool)) + if(I.tool_behaviour == TOOL_WELDER && I.use_tool(src, user, volume = I.tool_volume)) if(!build_step) - var/obj/item/weldingtool/WT = I - if(WT.remove_fuel(0, user)) - build_step++ - overlays += "hs_hole" - to_chat(user, "You weld a hole in [src]!") + build_step++ + overlays += "hs_hole" + to_chat(user, "You weld a hole in [src]!") else if(build_step == 1) - var/obj/item/weldingtool/WT = I - if(WT.remove_fuel(0, user)) - build_step-- - overlays -= "hs_hole" - to_chat(user, "You weld the hole in [src] shut!") + build_step-- + overlays -= "hs_hole" + to_chat(user, "You weld the hole in [src] shut!") else if(isprox(I) && (build_step == 1)) if(!user.unEquip(I)) diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 2c8e56f3fbe..83c038cc125 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -63,6 +63,7 @@ mulebot_count++ set_suffix(suffix ? suffix : "#[mulebot_count]") + RegisterSignal(src, COMSIG_CROSSED_MOVABLE, .proc/human_squish_check) /mob/living/simple_animal/bot/mulebot/Destroy() unload(0) @@ -866,6 +867,11 @@ else ..() +/mob/living/simple_animal/bot/mulebot/proc/human_squish_check(src, atom/movable/AM) + if(!ishuman(AM)) + return + RunOver(AM) + #undef SIGH #undef ANNOYED #undef DELIGHT diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 0c003b9e3b8..9dce0cecb62 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -47,6 +47,10 @@ if(SSticker.cultdat?.theme == "blood") updateglow() +/mob/living/simple_animal/hostile/construct/death(gibbed) + . = ..() + SSticker.mode.remove_cultist(src.mind, FALSE) + /mob/living/simple_animal/hostile/construct/examine(mob/user) . = ..() @@ -132,19 +136,7 @@ visible_message("The [P.name] gets reflected by [src]'s shell!", \ "The [P.name] gets reflected by [src]'s shell!") - // Find a turf near or on the original location to bounce to - if(P.starting) - var/new_x = P.starting.x + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3) - var/new_y = P.starting.y + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3) - var/turf/curloc = get_turf(src) - - // redirect the projectile - P.original = locate(new_x, new_y, P.z) - P.starting = curloc - P.current = curloc - P.firer = src - P.yo = new_y - curloc.y - P.xo = new_x - curloc.x + P.reflect_back(src, list(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3)) return -1 // complete projectile permutation diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm index 55aa587eff9..3717493d26c 100644 --- a/code/modules/mob/living/simple_animal/friendly/dog.dm +++ b/code/modules/mob/living/simple_animal/friendly/dog.dm @@ -37,7 +37,7 @@ playsound(src, yelp_sound, 75, TRUE) /mob/living/simple_animal/pet/dog/emote(act, m_type = 1, message = null, force) - if(!incapacitated()) + if(incapacitated()) return var/on_CD = 0 diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index 3ca0c840efd..d6f38d33268 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -41,7 +41,7 @@ AddComponent(/datum/component/squeak, list('sound/creatures/mousesqueak.ogg' = 1), 100) /mob/living/simple_animal/mouse/handle_automated_action() - if(prob(chew_probability)) + if(prob(chew_probability) && isturf(loc)) var/turf/simulated/floor/F = get_turf(src) if(istype(F) && !F.intact) var/obj/structure/cable/C = locate() in F diff --git a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm index 424d852d56b..dd248b88a62 100644 --- a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm +++ b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm @@ -87,19 +87,6 @@ update_icon() return 1 - else if(iswelder(O) && user.a_intent == INTENT_HELP) - var/obj/item/weldingtool/WT = O - user.changeNext_move(CLICK_CD_MELEE) - if(WT.remove_fuel(0)) - if(health < maxHealth) - adjustHealth(-5) - playsound(loc, WT.usesound, 50, 1) - add_fingerprint(user) - visible_message("[user] has spot-welded some of the damage to [src]!") - else - to_chat(user, "[src] is undamaged!") - else - to_chat(user, "Need more welding fuel!") else if(istype(O, /obj/item/card/id) || istype(O, /obj/item/pda)) if(!mmi) to_chat(user, "There's no reason to swipe your ID - the spiderbot has no brain to remove.") @@ -128,6 +115,23 @@ else ..() +/mob/living/simple_animal/spiderbot/welder_act(mob/user, obj/item/I) + if(user.a_intent != INTENT_HELP) + return + if(user == src) //No self-repair dummy + return + if(health >= maxHealth) + to_chat(user, "[src] does not need repairing!") + return + to_chat(user, "Unable to repair with the maintenance panel closed!") + return + . = TRUE + if(!I.use_tool(src, user, volume = I.tool_volume)) + return + adjustHealth(-5) + add_fingerprint(user) + user.visible_message("[user] repairs [src]!","You repair [src].") + /mob/living/simple_animal/spiderbot/emag_act(mob/living/user) if(emagged) to_chat(user, "[src] doesn't seem to respond.") diff --git a/code/modules/mob/living/simple_animal/hostile/headcrab.dm b/code/modules/mob/living/simple_animal/hostile/headcrab.dm index e48d980c2a4..ece990c7743 100644 --- a/code/modules/mob/living/simple_animal/hostile/headcrab.dm +++ b/code/modules/mob/living/simple_animal/hostile/headcrab.dm @@ -19,7 +19,7 @@ attack_sound = 'sound/creatures/headcrab_attack.ogg' speak_emote = list("hisses") var/is_zombie = 0 - stat_attack = DEAD //so they continue to attack when they are on the ground. + stat_attack = DEAD // Necessary for them to attack (zombify) dead humans robust_searching = 1 var/host_species = "" var/list/human_overlays = list() @@ -37,7 +37,7 @@ visible_message("[src] consumes [target] whole!") if(health < maxHealth) health += 10 - qdel(K) + qdel(K) break cycles = 0 cycles++ @@ -71,6 +71,7 @@ melee_damage_lower = 10 melee_damage_upper = 15 ranged = 0 + stat_attack = CONSCIOUS // Disables their targeting of dead mobs once they're already a zombie icon = H.icon speak = list('sound/creatures/zombie_idle1.ogg','sound/creatures/zombie_idle2.ogg','sound/creatures/zombie_idle3.ogg') speak_chance = 50 @@ -118,7 +119,13 @@ I = image('icons/mob/headcrab.dmi', icon_state = "headcrabpod_gray") overlays += I - +/mob/living/simple_animal/hostile/headcrab/CanAttack(atom/the_target) + if(stat_attack == DEAD && isliving(the_target) && !ishuman(the_target)) + var/mob/living/L = the_target + if(L.stat == DEAD) + // Override default behavior of stat_attack, to stop headcrabs targeting dead mobs they cannot infect, such as silicons. + return FALSE + return ..() /mob/living/simple_animal/hostile/headcrab/fast name = "fast headcrab" diff --git a/code/modules/mob/living/simple_animal/hostile/headslug.dm b/code/modules/mob/living/simple_animal/hostile/headslug.dm index d2329162da7..801514a3256 100644 --- a/code/modules/mob/living/simple_animal/hostile/headslug.dm +++ b/code/modules/mob/living/simple_animal/hostile/headslug.dm @@ -22,6 +22,7 @@ ventcrawler = 2 var/datum/mind/origin var/egg_lain = 0 + sentience_type = SENTIENCE_OTHER /mob/living/simple_animal/hostile/headslug/examine(mob/user) . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/hellhound.dm b/code/modules/mob/living/simple_animal/hostile/hellhound.dm index 201c4c07992..9107aa03457 100644 --- a/code/modules/mob/living/simple_animal/hostile/hellhound.dm +++ b/code/modules/mob/living/simple_animal/hostile/hellhound.dm @@ -1,6 +1,6 @@ // Hellhound /mob/living/simple_animal/hostile/hellhound - // Sprites by FoS: http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 + // Sprites by FoS: https://www.paradisestation.org/forum/profile/335-fos name = "Lesser Hellhound" desc = "A demonic-looking black canine monster with glowing red eyes and sharp teeth. A firey, lava-like substance drips from it." icon_state = "hellhound" diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 02d5ee5d14b..513ab39b180 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -148,8 +148,10 @@ // This prevents someone from aggroing a depot mob, then hiding in a locker, perfectly safe, while the mob stands there getting killed by their friends. LoseTarget() -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/handle_automated_movement() +/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/handle_automated_action() . = ..() + if(!.) + return if(!istype(depotarea)) return if(seen_enemy) @@ -184,6 +186,10 @@ else scan_cycles++ +/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/AIShouldSleep(var/list/possible_targets) + FindTarget(possible_targets, 1) + return FALSE + /mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/proc/raise_alert(var/reason) if(istype(depotarea) && (!raised_alert || seen_revived_enemy) && !depotarea.used_self_destruct) raised_alert = TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/black.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/black.dm index c9dc370648a..eae926b88e1 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/black.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/black.dm @@ -6,7 +6,7 @@ // -------------: AI: attacks to inject its venom, then retreats. Will inject its enemies multiple times then hang back to ensure they die. // -------------: SPECIAL: venom that does more damage the more of it is in you // -------------: TO FIGHT IT: if bitten once, retreat, get charcoal/etc treatment, and come back with a gun. -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/black name = "Black Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm index 1c6fcdb6e5d..fd30532a7bc 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm @@ -5,7 +5,7 @@ // -------------: AI: none - this is strictly adminspawn-only and intended for RP events, coder testing, and teaching people 'how to queen' // -------------: SPECIAL: Lay Eggs ability that allows laying queen-level eggs. // -------------: TO FIGHT IT: run away screaming? -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/queen/empress name = "Empress of Terror" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm index 14aa2b9299a..c06a7c2fee6 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm @@ -6,7 +6,7 @@ // -------------: AI: hides in vents, emerges when prey is near to kill it, then hides again. Intended to scare normal crew. // -------------: SPECIAL: invisible when on top of a vent, emerges when prey approaches or gets trapped in webs. // -------------: TO FIGHT IT: shoot it through a window, or make it regret ambushing you -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/gray name = "Gray Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/green.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/green.dm index 43d21286f8f..e7daced65ff 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/green.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/green.dm @@ -6,7 +6,7 @@ // -------------: AI: after it kills you, it webs you and lays new terror eggs on your body // -------------: SPECIAL: can also create webs, web normal objects, etc // -------------: TO FIGHT IT: kill it however you like - just don't die to it! -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/green name = "Green Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/mother.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/mother.dm index d1e171d2f55..65a3ff3db47 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/mother.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/mother.dm @@ -6,7 +6,7 @@ // -------------: AI: no special ai // -------------: SPECIAL: spawns an ungodly number of spiderlings when killed // -------------: TO FIGHT IT: don't! Just leave it alone! It is harmless by itself... but god help you if you aggro it. -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/mother name = "Mother of Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/prince.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/prince.dm index 646e9e50660..e486872abbb 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/prince.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/prince.dm @@ -6,7 +6,7 @@ // -------------: AI: no special ai // -------------: SPECIAL: massive health // -------------: TO FIGHT IT: a squad of at least 4 people with laser rifles. -// -------------: SPRITES FROM: Travelling Merchant, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=2766 +// -------------: SPRITES FROM: Travelling Merchant, https://www.paradisestation.org/forum/profile/2715-travelling-merchant/ /mob/living/simple_animal/hostile/poison/terror_spider/prince name = "Prince of Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm index 419f2a617f6..828e0e5f8f6 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm @@ -6,7 +6,7 @@ // -------------: AI: as green, but will evolve to queen when it can // -------------: SPECIAL: can evolve into a queen, if fed enough // -------------: TO FIGHT IT: kill it before it evolves -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/princess name = "Princess of Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/purple.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/purple.dm index 62832527293..92c7688e1e1 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/purple.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/purple.dm @@ -6,7 +6,7 @@ // -------------: AI: dies if too far from queen // -------------: SPECIAL: chance to stun on hit // -------------: TO FIGHT IT: shoot it from range, bring friends! -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/purple name = "Purple Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm index 3f16eb44837..a96486e473e 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm @@ -7,7 +7,7 @@ // -------------: AI: uses very powerful fangs to wreck people in melee // -------------: SPECIAL: the more you hurt it, the harder it bites you // -------------: TO FIGHT IT: shoot it from range. Kite it. -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/red name = "Red Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/white.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/white.dm index 8b5010c9d25..f62167792a3 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/white.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/white.dm @@ -5,7 +5,7 @@ // -------------: AI: injects a venom that makes you grow spiders in your body, then retreats // -------------: SPECIAL: stuns you on first attack - vulnerable to groups while it does this // -------------: TO FIGHT IT: blast it before it can get away -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/white name = "White Terror spider" diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm index 3f7b76c5af0..948c16314c9 100644 --- a/code/modules/mob/living/simple_animal/shade.dm +++ b/code/modules/mob/living/simple_animal/shade.dm @@ -28,6 +28,9 @@ del_on_death = 1 deathmessage = "lets out a contented sigh as their form unwinds." +/mob/living/simple_animal/shade/death(gibbed) + . = ..() + SSticker.mode.remove_cultist(src.mind, FALSE) /mob/living/simple_animal/shade/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri if(istype(O, /obj/item/soulstone)) diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 0e1a19da662..72f136304d7 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -344,6 +344,8 @@ return SetSleeping(max(sleeping, amount), updating, no_alert) /mob/living/SetSleeping(amount, updating = 1, no_alert = FALSE) + if(frozen) // If the mob has been admin frozen, sleeping should not be changeable + return . = STATUS_UPDATE_STAT if((!!amount) == (!!sleeping)) // We're not changing from + to 0 or vice versa updating = FALSE diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index c9e77e294d2..609940bc2a6 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -726,7 +726,7 @@ var/list/slot_equipment_priority = list( \ /mob/proc/print_flavor_text(var/shrink = 1) if(flavor_text && flavor_text != "") var/msg = replacetext(flavor_text, "\n", " ") - if(lentext(msg) <= 40 || !shrink) + if(length(msg) <= 40 || !shrink) return "[html_encode(msg)]" //Repeat after me, "I will not give players access to decoded HTML." else return "[copytext_preserve_html(msg, 1, 37)]... More..." diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index ec81cc33950..a96a832fef4 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -201,8 +201,8 @@ /proc/slur(phrase, var/list/slurletters = ("'"))//use a different list as an input if you want to make robots slur with $#@%! characters phrase = html_decode(phrase) - var/leng=lentext(phrase) - var/counter=lentext(phrase) + var/leng=length(phrase) + var/counter=length(phrase) var/newphrase="" var/newletter="" while(counter>=1) @@ -295,8 +295,8 @@ proc/muffledspeech(phrase) phrase = html_decode(phrase) - var/leng=lentext(phrase) - var/counter=lentext(phrase) + var/leng=length(phrase) + var/counter=length(phrase) var/newphrase="" var/newletter="" while(counter>=1) @@ -568,10 +568,10 @@ var/list/intents = list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM) //Fixes renames not being reflected in objective text var/length var/pos - for(var/datum/objective/objective in all_objectives) + for(var/datum/objective/objective in GLOB.all_objectives) if(!mind || objective.target != mind) continue - length = lentext(oldname) + length = length(oldname) pos = findtextEx(objective.explanation_text, oldname) objective.explanation_text = copytext(objective.explanation_text, 1, pos)+newname+copytext(objective.explanation_text, pos+length) return 1 @@ -610,8 +610,8 @@ var/list/intents = list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM) /proc/cultslur(n) // Inflicted on victims of a stun talisman var/phrase = html_decode(n) - var/leng = lentext(phrase) - var/counter=lentext(phrase) + var/leng = length(phrase) + var/counter=length(phrase) var/newphrase="" var/newletter="" while(counter>=1) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index ac8917398c5..fc246f661c3 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -373,9 +373,9 @@ if(character.mind.assigned_role == "Cyborg") AnnounceCyborg(character, rank, join_message) else - data_core.manifest_inject(character) SSticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn if(!IsAdminJob(rank)) + data_core.manifest_inject(character) AnnounceArrival(character, rank, join_message) AddEmploymentContract(character) diff --git a/code/modules/mob/update_status.dm b/code/modules/mob/update_status.dm index 29bcced144a..1708bcfb7a2 100644 --- a/code/modules/mob/update_status.dm +++ b/code/modules/mob/update_status.dm @@ -48,7 +48,10 @@ /mob/proc/restrained(ignore_grab) // All are created free - return 0 + return FALSE + +/mob/proc/get_restraining_item() + return null // Procs that update other things about the mob diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index b58dfd4cc66..1e43884df9a 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -325,23 +325,6 @@ qdel(src) return - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(!WT.isOn()) - to_chat(user, "\The [W] is off.") - return - - if(obj_integrity == max_integrity) - to_chat(user, "\The [src] does not require repairs.") - return - - to_chat(user, "You begin repairing damage to \the [src]...") - var/dmg = round(max_integrity - obj_integrity) - if(WT.remove_fuel(round(dmg/75)) && do_after(usr, dmg/10)) - obj_integrity = max_integrity - to_chat(user, "You repair \the [src].") - return - if(istype(W, /obj/item/screwdriver)) if(!all_components.len) to_chat(user, "This device doesn't have any components installed.") @@ -369,6 +352,12 @@ ..() +/obj/item/modular_computer/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + default_welder_repair(user, I) + // Used by processor to relay qdel() to machinery type. /obj/item/modular_computer/proc/relay_qdel() return diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index a88565d3818..75d6d9084ca 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -80,7 +80,7 @@ else data = "
    [infolinks ? info_links : info]
    [stamps]" if(view) - var/datum/browser/popup = new(user, name, , paper_width, paper_height) + var/datum/browser/popup = new(user, "Paper[UID()]", , paper_width, paper_height) popup.stylesheets = list() popup.set_content(data) if(!stars) @@ -720,6 +720,7 @@ origin_tech = "combat=4;materials=4;engineering=4;biotech=4" /obj/item/paper/researchnotes/New() + ..() var/list/possible_techs = list("materials", "engineering", "plasmatech", "powerstorage", "bluespace", "biotech", "combat", "magnets", "programming", "syndicate") var/mytech = pick(possible_techs) var/mylevel = rand(7, 9) diff --git a/code/modules/paperwork/paper_bundle.dm b/code/modules/paperwork/paper_bundle.dm index ecc26ba0cff..06bd0ec25c6 100644 --- a/code/modules/paperwork/paper_bundle.dm +++ b/code/modules/paperwork/paper_bundle.dm @@ -63,13 +63,13 @@ qdel(W) else if(istype(W, /obj/item/pen) || istype(W, /obj/item/toy/crayon)) - usr << browse("", "window=[name]") //Closes the dialog + usr << browse("", "window=PaperBundle[UID()]") //Closes the dialog P = src[page] P.attackby(W, user, params) update_icon() - if(winget(usr, "[name]", "is-visible") == "true") // NOT MY FAULT IT IS A BUILT IN PROC PLEASE DO NOT HIT ME + if(winget(usr, "PaperBundle[UID()]", "is-visible") == "true") // NOT MY FAULT IT IS A BUILT IN PROC PLEASE DO NOT HIT ME attack_self(usr) //Update the browsed page. add_fingerprint(usr) return @@ -125,7 +125,7 @@ if(istype(src[page], /obj/item/paper)) var/obj/item/paper/P = W dat += P.show_content(usr, view = 0) - usr << browse(dat, "window=[name]") + usr << browse(dat, "window=PaperBundle[UID()]") else if(istype(src[page], /obj/item/photo)) var/obj/item/photo/P = W usr << browse_rsc(P.img, "tmp_photo.png") @@ -133,7 +133,7 @@ + "" \ + "

    Written on the back:
    [P.scribble]" : ""]"\ - + "", "window=[name]") + + "", "window=PaperBundle[UID()]") /obj/item/paper_bundle/attack_self(mob/user as mob) src.show_content(user) diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index e7be4698fcf..0954127b00a 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -167,10 +167,6 @@ updateUsrDialog() else to_chat(user, "This cartridge is not yet ready for replacement! Use up the rest of the toner.") - else if(istype(O, /obj/item/wrench)) - playsound(loc, O.usesound, 50, 1) - anchored = !anchored - to_chat(user, "You [anchored ? "wrench" : "unwrench"] \the [src].") else if(istype(O, /obj/item/grab)) //For ass-copying. var/obj/item/grab/G = O if(ismob(G.affecting) && G.affecting != ass) @@ -185,6 +181,10 @@ else return ..() +/obj/machinery/photocopier/wrench_act(mob/user, obj/item/I) + . = TRUE + default_unfasten_wrench(user, I) + /obj/machinery/photocopier/proc/copy(var/obj/item/paper/copy) var/obj/item/paper/c = new /obj/item/paper (loc) c.info = copy.info diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 11beb1a7cb6..4129ddf30ad 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -81,13 +81,22 @@ . += "It is too far away." /obj/item/photo/proc/show(mob/user as mob) - usr << browse_rsc(img, "tmp_photo.png") + var/icon/img_shown = new/icon(img) + var/colormatrix = user.get_screen_colour() + // Apply colorblindness effects, if any. + if(islist(colormatrix)) + img_shown.MapColors( + colormatrix[1], colormatrix[2], colormatrix[3], + colormatrix[4], colormatrix[5], colormatrix[6], + colormatrix[7], colormatrix[8], colormatrix[9], + ) + usr << browse_rsc(img_shown, "tmp_photo.png") usr << browse("[name]" \ + "" \ + "" \ + "[scribble ? "
    Written on the back:
    [scribble]" : ""]"\ - + "", "window=book;size=[64*photo_size]x[scribble ? 400 : 64*photo_size]") - onclose(usr, "[name]") + + "", "window=Photo[UID()];size=[64*photo_size]x[scribble ? 400 : 64*photo_size]") + onclose(usr, "Photo[UID()]") return /obj/item/photo/verb/rename() diff --git a/code/modules/pda/pdas.dm b/code/modules/pda/pdas.dm index 676d193a6d3..0e5c58f968a 100644 --- a/code/modules/pda/pdas.dm +++ b/code/modules/pda/pdas.dm @@ -186,6 +186,12 @@ default_cartridge = /obj/item/cartridge/centcom icon_state = "pda-h" +/obj/item/pda/centcom/New() + ..() + var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger) + if(M) + M.m_hidden = 1 + //Some spare PDAs in a box /obj/item/storage/box/PDAs name = "spare PDAs" @@ -194,16 +200,16 @@ icon_state = "pdabox" /obj/item/storage/box/PDAs/New() - ..() - new /obj/item/pda(src) - new /obj/item/pda(src) - new /obj/item/pda(src) - new /obj/item/pda(src) - new /obj/item/cartridge/head(src) + ..() + new /obj/item/pda(src) + new /obj/item/pda(src) + new /obj/item/pda(src) + new /obj/item/pda(src) + new /obj/item/cartridge/head(src) - var/newcart = pick( /obj/item/cartridge/engineering, - /obj/item/cartridge/security, - /obj/item/cartridge/medical, - /obj/item/cartridge/signal/toxins, - /obj/item/cartridge/quartermaster) - new newcart(src) + var/newcart = pick( /obj/item/cartridge/engineering, + /obj/item/cartridge/security, + /obj/item/cartridge/medical, + /obj/item/cartridge/signal/toxins, + /obj/item/cartridge/quartermaster) + new newcart(src) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index e051fc50660..83b3578495c 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -30,6 +30,11 @@ #define APC_UPDATE_ICON_COOLDOWN 200 // 20 seconds +// APC malf status +#define APC_MALF_NOT_HACKED 1 +#define APC_MALF_HACKED 2 // APC hacked by user, and user is in its core. +#define APC_MALF_SHUNTED_HERE 3 // User is shunted in this APC +#define APC_MALF_SHUNTED_OTHER 4 // User is shunted in another APC // the Area Power Controller (APC), formerly Power Distribution Unit (PDU) // one per area, needs wire conection to power network through a terminal @@ -436,59 +441,6 @@ if(issilicon(user) && get_dist(src,user)>1) return src.attack_hand(user) - if(istype(W, /obj/item/crowbar)) //Using crowbar - if(opened) // a) on open apc - if(has_electronics==1) - if(terminal) - to_chat(user, "Disconnect the wires first!") - return - playsound(src.loc, W.usesound, 50, 1) - to_chat(user, "You are trying to remove the power control board..." ) - if(do_after(user, 50*W.toolspeed, target = src)) - if(has_electronics==1) - has_electronics = 0 - if(stat & BROKEN) - user.visible_message(\ - "[user.name] has broken the power control board inside [src.name]!", - "You break the charred power control board and remove the remains.", - "You hear a crack.") - return - //SSticker.mode:apcs-- //XSI said no and I agreed. -rastaf0 - else if(emagged) // We emag board, not APC's frame - emagged = FALSE - user.visible_message( - "[user.name] has discarded emaged power control board from [src.name]!", - "You discarded shorten board.") - return - else if(malfhack) // AI hacks board, not APC's frame - user.visible_message(\ - "[user.name] has discarded strangely programmed power control board from [src.name]!", - "You discarded strangely programmed board.") - malfai = null - malfhack = 0 - return - else - user.visible_message(\ - "[user.name] has removed the power control board from [src.name]!", - "You remove the power control board.") - new /obj/item/apc_electronics(loc) - return - else if(opened!=2) //cover isn't removed - opened = 0 - coverlocked = TRUE //closing cover relocks it - update_icon() - return - else if(!(stat & BROKEN)) // b) on closed and not broken APC - if(coverlocked && !(stat & MAINT)) // locked... - to_chat(user, "The cover is locked and cannot be opened!") - return - else if(panel_open) // wires are exposed - to_chat(user, "Exposed wires prevents you from opening it!") - return - else - opened = 1 - update_icon() - return else if (istype(W, /obj/item/stock_parts/cell) && opened) // trying to put a cell inside if(cell) @@ -508,35 +460,6 @@ chargecount = 0 update_icon() - else if(istype(W, /obj/item/screwdriver)) // haxing - if(opened) - if(cell) - to_chat(user, "Close the APC first!") //Less hints more mystery! - return - else - if(has_electronics==1) - has_electronics = 2 - stat &= ~MAINT - playsound(src.loc, W.usesound, 50, 1) - to_chat(user, "You screw the circuit electronics into place.") - else if(has_electronics==2) - has_electronics = 1 - stat |= MAINT - playsound(src.loc, W.usesound, 50, 1) - to_chat(user, "You unfasten the electronics.") - else /* has_electronics==0 */ - to_chat(user, "There is nothing to secure!") - return - update_icon() - else if(emagged) - to_chat(user, "The interface is broken!") - else if((stat & MAINT) && !opened) - ..() //its an empty closed frame... theres no wires to expose! - else - panel_open = !panel_open - to_chat(user, "The wires have been [panel_open ? "exposed" : "unexposed"]") - update_icon() - else if(W.GetID()) // trying to unlock the interface with an ID card togglelock(user) @@ -576,9 +499,6 @@ make_terminal() terminal.connect_to_network() - else if(istype(W, /obj/item/wirecutters) && terminal && opened) - terminal.dismantle(user, W) - else if(istype(W, /obj/item/apc_electronics) && opened) if(has_electronics!=0) // there are already electronicks inside to_chat(user, "You cannot put the board inside, there already is one!") @@ -597,31 +517,6 @@ to_chat(user, "You place the power control board inside the frame.") qdel(W) - else if(istype(W, /obj/item/weldingtool) && opened && has_electronics==0 && !terminal) - var/obj/item/weldingtool/WT = W - if(WT.get_fuel() < 3) - to_chat(user, "You need more welding fuel to complete this task!") - return - user.visible_message("[user.name] welds [src].", \ - "You start welding the APC frame...", \ - "You hear welding.") - playsound(src.loc, WT.usesound, 50, 1) - if(do_after(user, 50*W.toolspeed, target = src)) - if(!src || !WT.remove_fuel(3, user)) - return - if((stat & BROKEN) || opened==2) - new /obj/item/stack/sheet/metal(loc) - user.visible_message(\ - "[user.name] has cut [src] apart with [W].",\ - "You disassembled the broken APC frame.") - else - new /obj/item/mounted/frame/apc_frame(loc) - user.visible_message(\ - "[user.name] has cut [src] from the wall with [W].",\ - "You cut the APC frame from the wall.") - qdel(src) - return - else if(istype(W, /obj/item/mounted/frame/apc_frame) && opened) if(!(stat & BROKEN || opened==2 || obj_integrity < max_integrity)) // There is nothing to repair to_chat(user, "You found no reason for repairing this APC") @@ -649,11 +544,110 @@ opened = 1 update_icon() return - else if(panel_open && !opened && is_wire_tool(W)) - wires.Interact(user) else return ..() + +/obj/machinery/power/apc/crowbar_act(mob/living/user, obj/item/I) + . = TRUE + if(!I.tool_start_check(user, 0)) + return + if(opened) // a) on open apc + if(has_electronics==1) + if(terminal) + to_chat(user, "Disconnect the wires first!") + return + to_chat(user, "You are trying to remove the power control board..." ) + if(I.use_tool(src, user, 50, volume = I.tool_volume)) + if(has_electronics==1) + has_electronics = 0 + if(stat & BROKEN) + user.visible_message(\ + "[user.name] has broken the power control board inside [src.name]!", + "You break the charred power control board and remove the remains.", + "You hear a crack.") + return + //SSticker.mode:apcs-- //XSI said no and I agreed. -rastaf0 + else if(emagged) // We emag board, not APC's frame + emagged = FALSE + user.visible_message( + "[user.name] has discarded emaged power control board from [src.name]!", + "You discarded shorten board.") + return + else if(malfhack) // AI hacks board, not APC's frame + user.visible_message(\ + "[user.name] has discarded strangely programmed power control board from [src.name]!", + "You discarded strangely programmed board.") + malfai = null + malfhack = 0 + return + else + user.visible_message(\ + "[user.name] has removed the power control board from [src.name]!", + "You remove the power control board.") + new /obj/item/apc_electronics(loc) + return + else if(opened!=2) //cover isn't removed + opened = 0 + coverlocked = TRUE //closing cover relocks it + update_icon() + return + else if(!(stat & BROKEN)) // b) on closed and not broken APC + if(coverlocked && !(stat & MAINT)) // locked... + to_chat(user, "The cover is locked and cannot be opened!") + return + else if(panel_open) // wires are exposed + to_chat(user, "Exposed wires prevents you from opening it!") + return + else + opened = 1 + update_icon() + +/obj/machinery/power/apc/screwdriver_act(mob/living/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + else if(opened) + if(cell && !(stat & MAINT)) + to_chat(user, "Close the APC first!") //Less hints more mystery! + return + else + if(has_electronics==1) + has_electronics = 2 + stat &= ~MAINT + to_chat(user, "You screw the circuit electronics into place.") + else if(has_electronics==2) + has_electronics = 1 + stat |= MAINT + to_chat(user, "You unfasten the electronics.") + else + to_chat(user, "There is nothing to secure!") + return + update_icon() + else if(emagged) + to_chat(user, "The interface is broken!") + else + panel_open = !panel_open + to_chat(user, "The wires have been [panel_open ? "exposed" : "unexposed"]") + update_icon() + + +/obj/machinery/power/apc/wirecutter_act(mob/living/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(panel_open && !opened) + wires.Interact(user) + else if(terminal && opened) + terminal.dismantle(user, I) + +/obj/machinery/power/apc/multitool_act(mob/living/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(panel_open && !opened) + wires.Interact(user) + /obj/machinery/power/apc/proc/togglelock(mob/living/user) if(emagged) to_chat(user, "The interface is broken!") @@ -690,6 +684,26 @@ visible_message("The APC cover is knocked down!") update_icon() +/obj/machinery/power/apc/welder_act(mob/user, obj/item/I) + if(!opened || has_electronics || terminal) + return + . = TRUE + if(!I.tool_use_check(user, 3)) + return + WELDER_ATTEMPT_SLICING_MESSAGE + if(I.use_tool(src, user, 50, amount = 3, volume = I.tool_volume)) + if((stat & BROKEN) || opened==2) + new /obj/item/stack/sheet/metal(loc) + user.visible_message(\ + "[user.name] has cut [src] apart with [I].",\ + "You disassembled the broken APC frame.") + else + new /obj/item/mounted/frame/apc_frame(loc) + user.visible_message(\ + "[user.name] has cut [src] from the wall with [I].",\ + "You cut the APC frame from the wall.") + qdel(src) + /obj/machinery/power/apc/emag_act(user as mob) if(!(emagged || malfhack)) // trying to unlock with an emag card if(opened) @@ -749,18 +763,22 @@ /obj/machinery/power/apc/proc/get_malf_status(mob/living/silicon/ai/malf) - if(istype(malf) && malf.mind.has_antag_datum(/datum/antagonist/traitor)) - if(malfai == (malf.parent || malf)) - if(occupier == malf) - return 3 // 3 = User is shunted in this APC - else if(istype(malf.loc, /obj/machinery/power/apc)) - return 4 // 4 = User is shunted in another APC - else - return 2 // 2 = APC hacked by user, and user is in its core. + if(!istype(malf)) + return FALSE + + // Only if they're a traitor OR they have the malf picker from the combat module + if(!malf.mind.has_antag_datum(/datum/antagonist/traitor) && !malf.malf_picker) + return FALSE + + if(malfai == (malf.parent || malf)) + if(occupier == malf) + return APC_MALF_SHUNTED_HERE + else if(istype(malf.loc, /obj/machinery/power/apc)) + return APC_MALF_SHUNTED_OTHER else - return 1 // 1 = APC not hacked. + return APC_MALF_HACKED else - return 0 // 0 = User is not a Malf AI + return APC_MALF_NOT_HACKED /obj/machinery/power/apc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) if(!user) @@ -1008,7 +1026,7 @@ /obj/machinery/power/apc/proc/malfhack(mob/living/silicon/ai/malf) if(!istype(malf)) return - if(get_malf_status(malf) != 1) + if(get_malf_status(malf) != APC_MALF_NOT_HACKED) return if(malf.malfhacking) to_chat(malf, "You are already hacking an APC.") diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 6d22afe282f..9f48d451f36 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -159,20 +159,10 @@ By design, d1 is the smallest direction and d2 is the highest // - Multitool : get the power currently passing through the cable // /obj/structure/cable/attackby(obj/item/W, mob/user) - var/turf/T = get_turf(src) if(T.intact) return - if(iswirecutter(W)) - if(shock(user, 50)) - return - user.visible_message("[user] cuts the cable.", "You cut the cable.") - investigate_log("was cut by [key_name(usr, 1)] in [get_area(user)]([T.x], [T.y], [T.z] - [ADMIN_JMP(T)])","wires") - deconstruct() - return - - else if(istype(W, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/coil = W if(coil.get_amount() < 1) @@ -186,14 +176,6 @@ By design, d1 is the smallest direction and d2 is the highest R.loaded.cable_join(src, user) R.is_empty(user) - else if(istype(W, /obj/item/multitool)) - - if(powernet && (powernet.avail > 0)) // is it powered? - to_chat(user, "Total power: [DisplayPower(powernet.avail)]\nLoad: [DisplayPower(powernet.load)]\nExcess power: [DisplayPower(surplus())]") - else - to_chat(user, "The cable is not powered.") - shock(user, 5, 0.2) - else if(istype(W, /obj/item/toy/crayon)) var/obj/item/toy/crayon/C = W cable_color(C.colourName) @@ -204,6 +186,32 @@ By design, d1 is the smallest direction and d2 is the highest add_fingerprint(user) +/obj/structure/cable/multitool_act(mob/user, obj/item/I) + . = TRUE + var/turf/T = get_turf(src) + if(T.intact) + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(powernet && (powernet.avail > 0)) // is it powered? + to_chat(user, "Total power: [DisplayPower(powernet.avail)]\nLoad: [DisplayPower(powernet.load)]\nExcess power: [DisplayPower(surplus())]") + else + to_chat(user, "The cable is not powered.") + shock(user, 5, 0.2) + +/obj/structure/cable/wirecutter_act(mob/user, obj/item/I) + . = TRUE + var/turf/T = get_turf(src) + if(T.intact) + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(shock(user, 50)) + return + user.visible_message("[user] cuts the cable.", "You cut the cable.") + investigate_log("was cut by [key_name(usr, 1)] in [get_area(user)]([T.x], [T.y], [T.z] - [ADMIN_JMP(T)])","wires") + deconstruct() + // shock the user with probability prb /obj/structure/cable/proc/shock(mob/user, prb, siemens_coeff = 1) if(!prob(prb)) diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 9a7818ed321..588ea6b231f 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -64,7 +64,7 @@ return 100 * charge / maxcharge // use power from a cell -/obj/item/stock_parts/cell/proc/use(amount) +/obj/item/stock_parts/cell/use(amount) if(rigged && amount > 0) explode() return 0 diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm index 3d137a3c298..4a88e3363fc 100644 --- a/code/modules/power/generator.dm +++ b/code/modules/power/generator.dm @@ -158,34 +158,37 @@ return interact(user) -/obj/machinery/power/generator/attackby(obj/item/W as obj, mob/user as mob, params) - if(istype(W, /obj/item/wrench)) - anchored = !anchored - if(!anchored) - disconnect() - power_change() - else - connect() - playsound(loc, W.usesound, 50, 1) - to_chat(user, "You [anchored ? "secure" : "unsecure"] the bolts holding [src] to the floor.") - else if(ismultitool(W)) - if(cold_dir == WEST) - cold_dir = EAST - hot_dir = WEST - else if(cold_dir == NORTH) - cold_dir = SOUTH - hot_dir = NORTH - else if(cold_dir == EAST) - cold_dir = WEST - hot_dir = EAST - else - cold_dir = NORTH - hot_dir = SOUTH - connect() - to_chat(user, "You reverse the generator's circulator settings. The cold circulator is now on the [dir2text(cold_dir)] side, and the heat circulator is now on the [dir2text(hot_dir)] side.") - update_desc() +/obj/machinery/power/generator/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(cold_dir == WEST) + cold_dir = EAST + hot_dir = WEST + else if(cold_dir == NORTH) + cold_dir = SOUTH + hot_dir = NORTH + else if(cold_dir == EAST) + cold_dir = WEST + hot_dir = EAST else - return ..() + cold_dir = NORTH + hot_dir = SOUTH + connect() + to_chat(user, "You reverse the generator's circulator settings. The cold circulator is now on the [dir2text(cold_dir)] side, and the heat circulator is now on the [dir2text(hot_dir)] side.") + update_desc() + +/obj/machinery/power/generator/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + anchored = !anchored + if(!anchored) + disconnect() + power_change() + else + connect() + to_chat(user, "You [anchored ? "secure" : "unsecure"] the bolts holding [src] to the floor.") /obj/machinery/power/generator/proc/get_menu(include_link = 1) var/t = "" diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm index 08464600487..d45981c7c22 100644 --- a/code/modules/power/gravitygenerator.dm +++ b/code/modules/power/gravitygenerator.dm @@ -187,15 +187,6 @@ var/const/GRAV_NEEDS_WRENCH = 3 broken_state++ update_icon() return - if(GRAV_NEEDS_WELDING) - if(istype(I, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = I - if(WT.remove_fuel(1, user)) - to_chat(user, "You mend the damaged framework.") - playsound(src.loc, WT.usesound, 50, 1) - broken_state++ - update_icon() - return if(GRAV_NEEDS_PLASTEEL) if(istype(I, /obj/item/stack/sheet/plasteel)) var/obj/item/stack/sheet/plasteel/PS = I @@ -216,6 +207,16 @@ var/const/GRAV_NEEDS_WRENCH = 3 return return ..() +/obj/machinery/gravity_generator/main/welder_act(mob/user, obj/item/I) + if(broken_state != GRAV_NEEDS_WELDING) + return + . = TRUE + if(!I.use_tool(src, user, amount = 1, volume = I.tool_volume)) + return + to_chat(user, "You mend the damaged framework.") + broken_state++ + update_icon() + /obj/machinery/gravity_generator/main/attack_hand(mob/user as mob) if(!..()) return interact(user) diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm index ee0924578ff..05150c7389d 100644 --- a/code/modules/power/port_gen.dm +++ b/code/modules/power/port_gen.dm @@ -306,7 +306,7 @@ exchange_parts(user, O) return else if(istype(O, /obj/item/crowbar) && panel_open) - default_deconstruction_crowbar(O) + default_deconstruction_crowbar(user, O) else return ..() diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 8977062c947..3899d429d59 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -254,6 +254,7 @@ shot_number = 0 P.setDir(dir) P.starting = loc + P.Angle = null P.fire() return P @@ -285,42 +286,6 @@ to_chat(user, "The [src.name] needs to be unwelded from the floor.") return - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(active) - to_chat(user, "Turn off the [src] first.") - return - switch(state) - if(0) - to_chat(user, "The [src.name] needs to be wrenched to the floor.") - if(1) - if(WT.remove_fuel(0,user)) - playsound(src.loc, WT.usesound, 50, 1) - user.visible_message("[user.name] starts to weld the [src.name] to the floor.", \ - "You start to weld the [src] to the floor.", \ - "You hear welding") - if(do_after(user, 20 * WT.toolspeed, target = src)) - if(!src || !WT.isOn()) return - state = 2 - to_chat(user, "You weld the [src] to the floor.") - connect_to_network() - else - to_chat(user, "You need more welding fuel to complete this task.") - if(2) - if(WT.remove_fuel(0,user)) - playsound(src.loc, WT.usesound, 50, 1) - user.visible_message("[user.name] starts to cut the [src.name] free from the floor.", \ - "You start to cut the [src] free from the floor.", \ - "You hear welding") - if(do_after(user, 20 * WT.toolspeed, target = src)) - if(!src || !WT.isOn()) return - state = 1 - to_chat(user, "You cut the [src] free from the floor.") - disconnect_from_network() - else - to_chat(user, "You need more welding fuel to complete this task.") - return - if(istype(W, /obj/item/card/id) || istype(W, /obj/item/pda)) if(emagged) to_chat(user, "The lock seems to be broken") @@ -342,7 +307,7 @@ if(exchange_parts(user, W)) return - if(default_deconstruction_crowbar(W)) + if(default_deconstruction_crowbar(user, W)) return return ..() @@ -353,3 +318,29 @@ emagged = 1 if(user) user.visible_message("[user.name] emags the [src.name].","You short out the lock.") + + +/obj/machinery/power/emitter/welder_act(mob/user, obj/item/I) + if(active) + to_chat(user, "Turn off [src] first.") + return + if(state == 0) + to_chat(user, "[src] needs to be wrenched to the floor.") + return + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(state == 1) + WELDER_ATTEMPT_FLOOR_WELD_MESSAGE + else if(state == 2) + WELDER_ATTEMPT_FLOOR_SLICE_MESSAGE + if(!I.use_tool(src, user, 20, volume = I.tool_volume)) + return + if(state == 1) + WELDER_FLOOR_WELD_SUCCESS_MESSAGE + connect_to_network() + state = 2 + else if(state == 2) + WELDER_FLOOR_SLICE_SUCCESS_MESSAGE + disconnect_from_network() + state = 1 diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index d6711be53e1..7dcd7c71135 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -101,41 +101,29 @@ field_generator power level display anchored = 0 if(FG_WELDED) to_chat(user, "The [name] needs to be unwelded from the floor!") - - else if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - switch(state) - if(FG_UNSECURED) - to_chat(user, "The [name] needs to be wrenched to the floor!") - - if(FG_SECURED) - if(WT.remove_fuel(0,user)) - playsound(loc, WT.usesound, 50, 1) - user.visible_message("[user.name] starts to weld the [name] to the floor.", \ - "You start to weld \the [src] to the floor...", \ - "You hear welding.") - if(do_after(user, 20 * WT.toolspeed, target = src)) - if(!src || !WT.isOn()) - return - state = FG_WELDED - to_chat(user, "You weld the field generator to the floor.") - - if(FG_WELDED) - if(WT.remove_fuel(0,user)) - playsound(loc, WT.usesound, 50, 1) - user.visible_message("[user.name] starts to cut the [name] free from the floor.", \ - "You start to cut \the [src] free from the floor...", \ - "You hear welding.") - if(do_after(user, 20 * WT.toolspeed, target = src)) - if(!src || !WT.isOn()) - return - state = FG_SECURED - to_chat(user, "You cut \the [src] free from the floor.") - else return ..() +/obj/machinery/field/generator/welder_act(mob/user, obj/item/I) + . = TRUE + if(state == FG_UNSECURED) + to_chat(user, "[src] needs to be wrenched to the floor!") + return + if(!I.tool_use_check(user, 0)) + return + if(state == FG_SECURED) + WELDER_ATTEMPT_FLOOR_SLICE_MESSAGE + else if(state == FG_WELDED) + WELDER_ATTEMPT_FLOOR_WELD_MESSAGE + if(I.use_tool(src, user, 20, volume = I.tool_volume)) + if(state == FG_SECURED) + WELDER_FLOOR_SLICE_SUCCESS_MESSAGE + state = FG_WELDED + else if(state == FG_WELDED) + WELDER_FLOOR_WELD_SUCCESS_MESSAGE + state = FG_SECURED + /obj/machinery/field/generator/emp_act() return 0 diff --git a/code/modules/power/singularity/particle_accelerator/particle.dm b/code/modules/power/singularity/particle_accelerator/particle.dm index 327c29cebda..c7fcfcda5e7 100644 --- a/code/modules/power/singularity/particle_accelerator/particle.dm +++ b/code/modules/power/singularity/particle_accelerator/particle.dm @@ -22,30 +22,29 @@ energy = 50 -/obj/effect/accelerated_particle/New(loc) - ..() +/obj/effect/accelerated_particle/Initialize(loc) + . = ..() + addtimer(CALLBACK(src, .proc/propagate), 1) + RegisterSignal(src, COMSIG_CROSSED_MOVABLE, .proc/try_irradiate) + RegisterSignal(src, COMSIG_MOVABLE_CROSSED, .proc/try_irradiate) + QDEL_IN(src, movement_range) - addtimer(CALLBACK(src, .proc/move), 1) - - -/obj/effect/accelerated_particle/Bump(atom/A) - if(A) - if(isliving(A)) - toxmob(A) - else if(istype(A, /obj/machinery/the_singularitygen)) - var/obj/machinery/the_singularitygen/S = A - S.energy += energy - else if(istype(A, /obj/singularity)) - var/obj/singularity/S = A - S.energy += energy - else if(istype(A, /obj/structure/blob)) - var/obj/structure/blob/B = A - B.take_damage(energy * 0.6) - movement_range = 0 - -/obj/effect/accelerated_particle/Crossed(atom/A, oldloc) +/obj/effect/accelerated_particle/proc/try_irradiate(src, atom/A) if(isliving(A)) - toxmob(A) + var/mob/living/L = A + L.apply_effect((energy * 6), IRRADIATE, 0) + else if(istype(A, /obj/machinery/the_singularitygen)) + var/obj/machinery/the_singularitygen/S = A + S.energy += energy + else if(istype(A, /obj/structure/blob)) + var/obj/structure/blob/B = A + B.take_damage(energy * 0.6) + movement_range = 0 + +/obj/effect/accelerated_particle/Bump(obj/singularity/S) + if(!istype(S)) + return ..() + S.energy += energy /obj/effect/accelerated_particle/ex_act(severity) @@ -54,17 +53,7 @@ /obj/effect/accelerated_particle/singularity_pull() return - - -/obj/effect/accelerated_particle/proc/toxmob(mob/living/M) - M.apply_effect((energy * 6), IRRADIATE, 0) - -/obj/effect/accelerated_particle/proc/move() +/obj/effect/accelerated_particle/proc/propagate() + addtimer(CALLBACK(src, .proc/propagate), 1) if(!step(src,dir)) forceMove(get_step(src, dir)) - movement_range-- - if(movement_range == 0) - qdel(src) - else - sleep(speed) - move() \ No newline at end of file diff --git a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm index 2942acfdb35..059f5e78b7b 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm @@ -54,6 +54,10 @@ Strength being set by the computer and a null strength (Computer is powered off So, hopefully this is helpful if any more icons are to be added/changed/wondering what the hell is going on here */ +#define ACCELERATOR_UNWRENCHED 0 +#define ACCELERATOR_WRENCHED 1 +#define ACCELERATOR_WIRED 2 +#define ACCELERATOR_READY 3 /obj/structure/particle_accelerator name = "Particle Accelerator" @@ -136,12 +140,6 @@ So, hopefully this is helpful if any more icons are to be added/changed/wonderin desc = desc_holder . = ..() -/obj/structure/particle_accelerator/attackby(obj/item/W, mob/user, params) - if(istool(W)) - if(process_tool_hit(W,user)) - return - return..() - /obj/structure/particle_accelerator/deconstruct(disassembled = TRUE) if(!(flags & NODECONSTRUCT)) new /obj/item/stack/sheet/metal (loc, 5) @@ -196,66 +194,58 @@ So, hopefully this is helpful if any more icons are to be added/changed/wonderin return 1 return 0 +/obj/structure/particle_accelerator/attackby(obj/item/W, mob/user, params) + if(!iscoil(W)) + return ..() + if(construction_state == ACCELERATOR_WRENCHED) + var/obj/item/stack/cable_coil/C = W + if(C.use(1)) + playsound(loc, C.usesound, 50, 1) + user.visible_message("[user.name] adds wires to the [name].", \ + "You add some wires.") + construction_state = ACCELERATOR_WIRED + update_icon() -/obj/structure/particle_accelerator/proc/process_tool_hit(var/obj/item/O, var/mob/user) - if(!(O) || !(user)) - return 0 - if(!ismob(user) || !isobj(O)) - return 0 - var/temp_state = construction_state +/obj/structure/particle_accelerator/screwdriver_act(mob/user, obj/item/I) + if(construction_state != ACCELERATOR_WIRED && construction_state != ACCELERATOR_READY) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(construction_state == ACCELERATOR_WIRED) + SCREWDRIVER_CLOSE_PANEL_MESSAGE + construction_state = ACCELERATOR_READY - switch(construction_state)//TODO:Might be more interesting to have it need several parts rather than a single list of steps - if(0) - if(iswrench(O) && !isinspace()) - playsound(loc, O.usesound, 50, 1) - anchored = 1 - user.visible_message("[user.name] secures the [name] to the floor.", \ - "You secure the external bolts.") - temp_state++ - if(1) - if(iswrench(O)) - playsound(loc, O.usesound, 50, 1) - anchored = 0 - user.visible_message("[user.name] detaches the [name] from the floor.", \ - "You remove the external bolts.") - temp_state-- - else if(iscoil(O)) - var/obj/item/stack/cable_coil/C = O - if(C.use(1)) - playsound(loc, O.usesound, 50, 1) - user.visible_message("[user.name] adds wires to the [name].", \ - "You add some wires.") - temp_state++ - else - to_chat(user, "You need one length of cable to wire the [name]!") - return - if(2) - if(iswirecutter(O))//TODO:Shock user if its on? - playsound(loc, O.usesound, 50, 1) - user.visible_message("[user.name] removes some wires from the [name].", \ - "You remove some wires.") - temp_state-- - else if(isscrewdriver(O)) - playsound(loc, O.usesound, 50, 1) - user.visible_message("[user.name] closes the [name]'s access panel.", \ - "You close the access panel.") - temp_state++ - if(3) - if(isscrewdriver(O)) - playsound(loc, O.usesound, 50, 1) - user.visible_message("[user.name] opens the [name]'s access panel.", \ - "You open the access panel.") - temp_state-- - if(temp_state == construction_state)//Nothing changed - return 0 else - construction_state = temp_state - if(construction_state < 3)//Was taken apart, update state - update_state() - update_icon() - return 1 - return 0 + construction_state = ACCELERATOR_WIRED + SCREWDRIVER_OPEN_PANEL_MESSAGE + update_state() + update_icon() +/obj/structure/particle_accelerator/wirecutter_act(mob/user, obj/item/I) + if(construction_state != ACCELERATOR_WIRED) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + WIRECUTTER_SNIP_MESSAGE + construction_state = ACCELERATOR_WRENCHED + +/obj/structure/particle_accelerator/wrench_act(mob/user, obj/item/I) + if(construction_state != ACCELERATOR_UNWRENCHED && construction_state != ACCELERATOR_WRENCHED) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(construction_state == ACCELERATOR_UNWRENCHED) + anchored = TRUE + WRENCH_ANCHOR_MESSAGE + construction_state = ACCELERATOR_WRENCHED + else + anchored = FALSE + WRENCH_UNANCHOR_MESSAGE + construction_state = ACCELERATOR_UNWRENCHED + update_icon() /obj/machinery/particle_accelerator @@ -306,72 +296,65 @@ So, hopefully this is helpful if any more icons are to be added/changed/wonderin return /obj/machinery/particle_accelerator/attackby(obj/item/W, mob/user, params) - if(istool(W)) - if(process_tool_hit(W,user)) - return - return ..() + if(!iscoil(W)) + return ..() + if(construction_state == ACCELERATOR_WRENCHED) + var/obj/item/stack/cable_coil/C = W + if(C.use(1)) + playsound(loc, C.usesound, 50, 1) + user.visible_message("[user.name] adds wires to the [name].", \ + "You add some wires.") + construction_state = ACCELERATOR_WIRED + update_icon() + +/obj/machinery/particle_accelerator/screwdriver_act(mob/user, obj/item/I) + if(construction_state != ACCELERATOR_WIRED && construction_state != ACCELERATOR_READY) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(construction_state == ACCELERATOR_WIRED) + SCREWDRIVER_CLOSE_PANEL_MESSAGE + construction_state = ACCELERATOR_READY + use_power = IDLE_POWER_USE + else + construction_state = ACCELERATOR_WIRED + SCREWDRIVER_OPEN_PANEL_MESSAGE + use_power = NO_POWER_USE + update_state() + update_icon() + +/obj/machinery/particle_accelerator/wirecutter_act(mob/user, obj/item/I) + if(construction_state != ACCELERATOR_WIRED) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + WIRECUTTER_SNIP_MESSAGE + construction_state = ACCELERATOR_WRENCHED + +/obj/machinery/particle_accelerator/wrench_act(mob/user, obj/item/I) + if(construction_state != ACCELERATOR_UNWRENCHED && construction_state != ACCELERATOR_WRENCHED) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(construction_state == ACCELERATOR_UNWRENCHED) + anchored = TRUE + WRENCH_ANCHOR_MESSAGE + construction_state = ACCELERATOR_WRENCHED + else + anchored = FALSE + WRENCH_UNANCHOR_MESSAGE + construction_state = ACCELERATOR_UNWRENCHED + update_icon() + /obj/machinery/particle_accelerator/proc/update_state() return 0 -/obj/machinery/particle_accelerator/proc/process_tool_hit(var/obj/item/O, var/mob/user) - if(!(O) || !(user)) - return 0 - if(!ismob(user) || !isobj(O)) - return 0 - var/temp_state = construction_state - switch(construction_state)//TODO:Might be more interesting to have it need several parts rather than a single list of steps - if(0) - if(iswrench(O)) - playsound(loc, O.usesound, 50, 1) - anchored = 1 - user.visible_message("[user.name] secures the [name] to the floor.", \ - "You secure the external bolts.") - temp_state++ - power_change() - if(1) - if(iswrench(O)) - playsound(loc, O.usesound, 50, 1) - anchored = 0 - user.visible_message("[user.name] detaches the [name] from the floor.", \ - "You remove the external bolts.") - temp_state-- - power_change() - else if(iscoil(O)) - if(O:use(1)) - playsound(loc, O.usesound, 50, 1) - user.visible_message("[user.name] adds wires to the [name].", \ - "You add some wires.") - temp_state++ - if(2) - if(iswirecutter(O))//TODO:Shock user if its on? - playsound(loc, O.usesound, 50, 1) - user.visible_message("[user.name] removes some wires from the [name].", \ - "You remove some wires.") - temp_state-- - else if(isscrewdriver(O)) - playsound(loc, O.usesound, 50, 1) - user.visible_message("[user.name] closes the [name]'s access panel.", \ - "You close the access panel.") - temp_state++ - if(3) - if(isscrewdriver(O)) - playsound(loc, O.usesound, 50, 1) - user.visible_message("[user.name] opens the [name]'s access panel.", \ - "You open the access panel.") - temp_state-- - active = 0 - if(temp_state == construction_state)//Nothing changed - return 0 - else - if(construction_state < 3)//Was taken apart, update state - update_state() - if(use_power) - use_power = NO_POWER_USE - construction_state = temp_state - if(construction_state >= 3) - use_power = IDLE_POWER_USE - update_icon() - return 1 - return 0 +#undef ACCELERATOR_UNWRENCHED +#undef ACCELERATOR_WRENCHED +#undef ACCELERATOR_WIRED +#undef ACCELERATOR_READY diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 531bde2b000..c67e676ee13 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -110,8 +110,12 @@ /obj/singularity/process() - if(current_size >= STAGE_TWO) + if(allowed_size >= STAGE_TWO) + // Start moving even before we reach "true" stage two. + // If we are stage one and are sufficiently energetic to be allowed to 2, + // it might mean we are stuck in a corner somewere. So move around to try to expand. move() + if(current_size >= STAGE_TWO) pulse() if(prob(event_chance))//Chance for it to run a special event TODO:Come up with one or two more that fit event() diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index 4773df11395..031ef83a264 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -224,7 +224,7 @@ return //crowbarring it ! - if(default_deconstruction_crowbar(I)) + if(default_deconstruction_crowbar(user, I)) return return ..() diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index f3ca60effda..7d830d69321 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -55,17 +55,15 @@ update_icon() - -/obj/machinery/power/solar/attackby(obj/item/W, mob/user, params) - if(iscrowbar(W)) - playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - user.visible_message("[user] begins to take the glass off the solar panel.", "You begin to take the glass off the solar panel...") - if(do_after(user, 50 * W.toolspeed, target = src)) - playsound(src.loc, W.usesound, 50, 1) - user.visible_message("[user] takes the glass off the solar panel.", "You take the glass off the solar panel.") - deconstruct(TRUE) +/obj/machinery/power/solar/crowbar_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) return - return ..() + playsound(loc, 'sound/machines/click.ogg', 50, 1) + user.visible_message("[user] begins to take the glass off the solar panel.", "You begin to take the glass off the solar panel...") + if(I.use_tool(src, user, 50, volume = I.tool_volume)) + user.visible_message("[user] takes the glass off the solar panel.", "You take the glass off the solar panel.") + deconstruct(TRUE) /obj/machinery/power/solar/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) switch(damage_type) diff --git a/code/modules/power/supermatter/sm_shard.dm b/code/modules/power/supermatter/sm_shard.dm index c5d7549e0a7..b9e4a2435e6 100644 --- a/code/modules/power/supermatter/sm_shard.dm +++ b/code/modules/power/supermatter/sm_shard.dm @@ -13,6 +13,7 @@ var/brightness = 2 /obj/item/shard/supermatter/New() + ..() src.icon_state = "supermatter" + pick("large", "medium", "small") switch(src.icon_state) if("supermattersmall") diff --git a/code/modules/power/tesla/coil.dm b/code/modules/power/tesla/coil.dm index 6f1e84da526..5f58bcb5dd4 100644 --- a/code/modules/power/tesla/coil.dm +++ b/code/modules/power/tesla/coil.dm @@ -33,28 +33,48 @@ input_power_multiplier = power_multiplier /obj/machinery/power/tesla_coil/attackby(obj/item/W, mob/user, params) - if(default_deconstruction_screwdriver(user, "coil_open[anchored]", "coil[anchored]", W)) - return - if(exchange_parts(user, W)) return - if(default_unfasten_wrench(user, W)) + else if(istype(W, /obj/item/assembly/signaler) && panel_open) + wires.Interact(user) + + else + return ..() + +/obj/machinery/power/tesla_coil/crowbar_act(mob/user, obj/item/I) + . = TRUE + default_deconstruction_crowbar(user, I) + +/obj/machinery/power/tesla_coil/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(panel_open) + wires.Interact(user) + +/obj/machinery/power/tesla_coil/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + default_deconstruction_screwdriver(user, "coil_open[anchored]", "coil[anchored]", I) + +/obj/machinery/power/tesla_coil/wirecutter_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(panel_open) + wires.Interact(user) + +/obj/machinery/power/tesla_coil/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(default_unfasten_wrench(user, I)) if(!anchored) disconnect_from_network() else connect_to_network() - return - - if(default_deconstruction_crowbar(W)) - return - - else if(iswirecutter(W) || ismultitool(W) || istype(W, /obj/item/assembly/signaler)) - if(panel_open) - wires.Interact(user) - - else - return ..() /obj/machinery/power/tesla_coil/tesla_act(var/power) if(anchored && !panel_open) @@ -97,22 +117,23 @@ RefreshParts() /obj/machinery/power/grounding_rod/attackby(obj/item/W, mob/user, params) - if(default_deconstruction_screwdriver(user, "grounding_rod_open[anchored]", "grounding_rod[anchored]", W)) - return - if(exchange_parts(user, W)) return - if(default_unfasten_wrench(user, W)) - return +/obj/machinery/power/grounding_rod/screwdriver_act(mob/user, obj/item/I) + . = TRUE + default_deconstruction_screwdriver(user, "grounding_rod_open[anchored]", "grounding_rod[anchored]", I) - if(default_deconstruction_crowbar(W)) - return +/obj/machinery/power/grounding_rod/wrench_act(mob/user, obj/item/I) + . = TRUE + default_unfasten_wrench(user, I) - return ..() +/obj/machinery/power/grounding_rod/crowbar_act(mob/user, obj/item/I) + . = TRUE + default_deconstruction_crowbar(user, I) /obj/machinery/power/grounding_rod/tesla_act(var/power) if(anchored && !panel_open) flick("grounding_rodhit", src) else - ..() \ No newline at end of file + ..() diff --git a/code/modules/power/tracker.dm b/code/modules/power/tracker.dm index 5706eb6d3da..69dc8c4fd03 100644 --- a/code/modules/power/tracker.dm +++ b/code/modules/power/tracker.dm @@ -59,16 +59,16 @@ if(powernet && (powernet == control.powernet)) //update if we're still in the same powernet control.cdir = angle -/obj/machinery/power/tracker/attackby(var/obj/item/W, var/mob/user) - if(iscrowbar(W)) - playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - user.visible_message("[user] begins to take the glass off the solar tracker.") - if(do_after(user, 50 * W.toolspeed, target = src)) - playsound(src.loc, W.usesound, 50, 1) - user.visible_message("[user] takes the glass off the tracker.") - deconstruct(TRUE) +/obj/machinery/power/tracker/crowbar_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) return - return ..() + playsound(src.loc, 'sound/machines/click.ogg', 50, 1) + user.visible_message("[user] begins to take the glass off the solar tracker.") + if(I.use_tool(src, user, 50, volume = I.tool_volume)) + user.visible_message("[user] takes the glass off the tracker.") + deconstruct(TRUE) + /obj/machinery/power/tracker/obj_break(damage_flag) if(!(stat & BROKEN) && !(flags & NODECONSTRUCT)) diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm index 6f3c0856406..15a9dcbdb84 100644 --- a/code/modules/power/turbine.dm +++ b/code/modules/power/turbine.dm @@ -110,9 +110,6 @@ efficiency = E / 6 /obj/machinery/power/compressor/attackby(obj/item/I, mob/user, params) - if(default_deconstruction_screwdriver(user, initial(icon_state), initial(icon_state), I)) - return - if(default_change_direction_wrench(user, I)) turbine = null inturf = get_step(src, dir) @@ -128,10 +125,17 @@ if(exchange_parts(user, I)) return - if(default_deconstruction_crowbar(I)) - return + return ..() +/obj/machinery/power/compressor/crowbar_act(mob/user, obj/item/I) + if(default_deconstruction_crowbar(user, I)) + return TRUE + +/obj/machinery/power/compressor/screwdriver_act(mob/user, obj/item/I) + if(default_deconstruction_screwdriver(user, initial(icon_state), initial(icon_state), I)) + return TRUE + /obj/machinery/power/compressor/CanAtmosPass(turf/T) return !density @@ -285,7 +289,7 @@ if(exchange_parts(user, I)) return - if(default_deconstruction_crowbar(I)) + if(default_deconstruction_crowbar(user, I)) return return ..() diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm index 726580573e3..d2df6b4a03b 100644 --- a/code/modules/projectiles/ammunition.dm +++ b/code/modules/projectiles/ammunition.dm @@ -102,6 +102,7 @@ var/list/initial_mats //For calculating refund values. /obj/item/ammo_box/New() + ..() for(var/i in 1 to max_ammo) stored_ammo += new ammo_type(src) update_icon() diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm index 2f422e227b3..d756dda4f41 100644 --- a/code/modules/projectiles/ammunition/magazines.dm +++ b/code/modules/projectiles/ammunition/magazines.dm @@ -157,6 +157,8 @@ multiload = 0 /obj/item/ammo_box/magazine/internal/rus357/New() + ..() + stored_ammo.Cut() // We only want 1 bullet in there stored_ammo += new ammo_type(src) /obj/item/ammo_box/magazine/internal/boltaction diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 4df4e46da20..d4a333c495d 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -301,21 +301,6 @@ if(loc == user) A.Grant(user) - if(isscrewdriver(I)) - if(gun_light && can_flashlight) - for(var/obj/item/flashlight/seclite/S in src) - to_chat(user, "You unscrew the seclite from [src].") - gun_light = null - S.loc = get_turf(user) - update_gun_light(user) - S.update_brightness(user) - update_icon() - for(var/datum/action/item_action/toggle_gunlight/TGL in actions) - qdel(TGL) - else if(bayonet && can_bayonet) //if it has a bayonet, and the bayonet can be removed - bayonet.forceMove(get_turf(user)) - clear_bayonet() - if(unique_rename) if(istype(I, /obj/item/pen)) rename_gun(user) @@ -339,6 +324,24 @@ else return ..() +/obj/item/gun/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(gun_light && can_flashlight) + for(var/obj/item/flashlight/seclite/S in src) + to_chat(user, "You unscrew the seclite from [src].") + gun_light = null + S.loc = get_turf(user) + update_gun_light(user) + S.update_brightness(user) + update_icon() + for(var/datum/action/item_action/toggle_gunlight/TGL in actions) + qdel(TGL) + else if(bayonet && can_bayonet) //if it has a bayonet, and the bayonet can be removed + bayonet.forceMove(get_turf(user)) + clear_bayonet() + /obj/item/gun/proc/toggle_gunlight() set name = "Toggle Gun Light" set category = "Object" diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index c745d6be846..a686eda11f0 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -98,7 +98,7 @@ return if(!chambered) var/obj/item/ammo_casing/energy/shot = ammo_type[select] - if(cell.charge >= shot.e_cost) //if there's enough power in the cell cell... + if(cell.charge >= shot.e_cost) //if there's enough power in the WEAPON'S cell... chambered = shot //...prepare a new shot based on the current ammo type selected if(!chambered.BB) chambered.newshot() @@ -111,6 +111,11 @@ chambered = null //either way, released the prepared shot newshot() +/obj/item/gun/energy/process_fire(atom/target, mob/living/user, message = 1, params, zone_override, bonus_spread = 0) + if(!chambered && can_shoot()) + process_chamber() + return ..() + /obj/item/gun/energy/proc/select_fire(mob/living/user) select++ if(select > ammo_type.len) @@ -193,6 +198,9 @@ . = ..() /obj/item/gun/energy/proc/robocharge() + if(cell.charge == cell.maxcharge) + // No point in recharging a weapon's cell that is already at 100%. That would just waste borg cell power for no reason. + return if(isrobot(loc)) var/mob/living/silicon/robot/R = loc if(R && R.cell) diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index 60ab08f979d..518caa8ba70 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -37,20 +37,23 @@ . += "There is a [M.name] mod installed, using [M.cost]% capacity." /obj/item/gun/energy/kinetic_accelerator/attackby(obj/item/I, mob/user) - if(iscrowbar(I)) - if(modkits.len) - to_chat(user, "You pry the modifications out.") - playsound(loc, I.usesound, 100, 1) - for(var/obj/item/borg/upgrade/modkit/M in modkits) - M.uninstall(src) - else - to_chat(user, "There are no modifications currently installed.") - else if(istype(I, /obj/item/borg/upgrade/modkit)) + if(istype(I, /obj/item/borg/upgrade/modkit)) var/obj/item/borg/upgrade/modkit/MK = I MK.install(src, user) else return ..() +/obj/item/gun/energy/kinetic_accelerator/crowbar_act(mob/user, obj/item/I) + . = TRUE + if(!modkits.len) + to_chat(user, "There are no modifications currently installed.") + return + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + to_chat(user, "You pry the modifications out.") + for(var/obj/item/borg/upgrade/modkit/M in modkits) + M.uninstall(src) + /obj/item/gun/energy/kinetic_accelerator/proc/get_remaining_mod_capacity() var/current_capacity_used = 0 for(var/A in get_modkits()) diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm index 21992f43704..b29544c5755 100644 --- a/code/modules/projectiles/guns/projectile/revolver.dm +++ b/code/modules/projectiles/guns/projectile/revolver.dm @@ -114,36 +114,38 @@ return 0 ..() -/obj/item/gun/projectile/revolver/detective/attackby(obj/item/A, mob/user, params) - if(istype(A, /obj/item/screwdriver)) - if(magazine.caliber == "38") - to_chat(user, "You begin to reinforce the barrel of [src]...") - if(magazine.ammo_count()) - afterattack(user, user) //you know the drill - user.visible_message("[src] goes off!", "[src] goes off in your face!") - return - if(do_after(user, 30 * A.toolspeed, target = src)) - if(magazine.ammo_count()) - to_chat(user, "You can't modify it!") - return - magazine.caliber = "357" - desc = "The barrel and chamber assembly seems to have been modified." - to_chat(user, "You reinforce the barrel of [src]. Now it will fire .357 rounds.") - else - to_chat(user, "You begin to revert the modifications to [src]...") - if(magazine.ammo_count()) - afterattack(user, user) //and again - user.visible_message("[src] goes off!", "[src] goes off in your face!") - return - if(do_after(user, 30 * A.toolspeed, target = src)) - if(magazine.ammo_count()) - to_chat(user, "You can't modify it!") - return - magazine.caliber = "38" - desc = initial(desc) - to_chat(user, "You remove the modifications on [src]. Now it will fire .38 rounds.") +/obj/item/gun/projectile/revolver/detective/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + if(magazine.caliber == "38") + to_chat(user, "You begin to reinforce the barrel of [src]...") + if(magazine.ammo_count()) + afterattack(user, user) //you know the drill + user.visible_message("[src] goes off!", "[src] goes off in your face!") + return + if(!I.use_tool(src, user, 30, volume = I.tool_volume)) + return + if(magazine.ammo_count()) + to_chat(user, "You can't modify it!") + return + magazine.caliber = "357" + desc = "The barrel and chamber assembly seems to have been modified." + to_chat(user, "You reinforce the barrel of [src]. Now it will fire .357 rounds.") else - return ..() + to_chat(user, "You begin to revert the modifications to [src]...") + if(magazine.ammo_count()) + afterattack(user, user) //and again + user.visible_message("[src] goes off!", "[src] goes off in your face!") + return + if(!I.use_tool(src, user, 30, volume = I.tool_volume)) + return + if(magazine.ammo_count()) + to_chat(user, "You can't modify it!") + return + magazine.caliber = "38" + desc = initial(desc) + to_chat(user, "You remove the modifications on [src]. Now it will fire .38 rounds.") /obj/item/gun/projectile/revolver/fingergun //Summoned by the Finger Gun spell, from advanced mimery traitor item name = "\improper finger gun" diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index dc798e10830..d31231823f8 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -24,7 +24,7 @@ var/p_x = 16 var/p_y = 16 // the pixel location of the tile that the player clicked. Default is the center var/speed = 1 //Amount of deciseconds it takes for projectile to travel - var/Angle = 0 + var/Angle = null var/spread = 0 //amount (in degrees) of projectile spread var/legacy = FALSE //legacy projectile system animate_movement = 0 @@ -240,8 +240,7 @@ if(!paused) if((!( current ) || loc == current)) current = locate(Clamp(x+xo,1,world.maxx),Clamp(y+yo,1,world.maxy),z) - - if(!Angle) + if(isnull(Angle)) Angle=round(Get_Angle(src,current)) if(spread) Angle += (rand() - 0.5) * spread @@ -302,6 +301,25 @@ Range() sleep(1) +obj/item/projectile/proc/reflect_back(atom/source, list/position_modifiers = list(0, 0, 0, 0, 0, -1, 1, -2, 2)) + if(starting) + var/new_x = starting.x + pick(position_modifiers) + var/new_y = starting.y + pick(position_modifiers) + var/turf/curloc = get_turf(source) + + if(ismob(source)) + firer = source // The reflecting mob will be the new firer + else + firer = null // Reflected by something other than a mob so firer will be null + + // redirect the projectile + original = locate(new_x, new_y, z) + starting = curloc + current = curloc + yo = new_y - curloc.y + xo = new_x - curloc.x + Angle = null // Will be calculated in fire() + obj/item/projectile/Crossed(atom/movable/AM, oldloc) //A mob moving on a tile with a projectile is hit by it. ..() if(isliving(AM) && AM.density && !checkpass(PASSMOB)) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 1945c6dffe5..ab9f633a43a 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -11,7 +11,9 @@ var/const/INGEST = 2 var/atom/my_atom = null var/chem_temp = T20C var/list/datum/reagent/addiction_list = new/list() + var/list/addiction_threshold_accumulated = new/list() var/flags + var/list/reagents_generated_per_cycle = new/list() /datum/reagents/New(maximum = 100) maximum_volume = maximum @@ -209,7 +211,7 @@ var/const/INGEST = 2 return var/datum/reagents/R = target.reagents - if(get_reagent_amount(reagent) (R.last_addiction_dose + ADDICTION_TIME))) //Each addiction lasts 8 minutes before it can end to_chat(M, "You no longer feel reliant on [R.name]!") addiction_list.Remove(R) @@ -348,7 +363,8 @@ var/const/INGEST = 2 if(flags & REAGENT_NOREACT) STOP_PROCESSING(SSobj, src) return - + for(var/thing in reagents_generated_per_cycle) + add_reagent(thing, reagents_generated_per_cycle[thing]) for(var/datum/reagent/R in reagent_list) R.on_tick() diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index e822dc1ea88..758b228a989 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -242,46 +242,10 @@ return TRUE // update UIs attached to this object /obj/machinery/chem_dispenser/attackby(obj/item/I, mob/user, params) - if(ismultitool(I)) - if(!hackedcheck) - to_chat(user, hack_message) - dispensable_reagents += hacked_reagents - hackedcheck = TRUE - else - to_chat(user, unhack_message) - dispensable_reagents -= hacked_reagents - hackedcheck = FALSE - SSnanoui.update_uis(src) - return - - if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", "[initial(icon_state)]", I)) - return - if(exchange_parts(user, I)) SSnanoui.update_uis(src) return - if(iswrench(I)) - playsound(src, I.usesound, 50, 1) - if(anchored) - anchored = FALSE - to_chat(user, "[src] can now be moved.") - else if(!anchored) - anchored = TRUE - to_chat(user, "[src] is now secured.") - return - - if(panel_open) - if(iscrowbar(I)) - if(beaker) - beaker.forceMove(loc) - beaker = null - if(cell) - cell.forceMove(loc) - cell = null - default_deconstruction_crowbar(I) - return TRUE - if(isrobot(user)) return @@ -307,6 +271,48 @@ return return ..() +/obj/machinery/chem_dispenser/crowbar_act(mob/user, obj/item/I) + if(!panel_open) + return + if(default_deconstruction_crowbar(user, I)) + if(beaker) + beaker.forceMove(loc) + beaker = null + if(cell) + cell.forceMove(loc) + cell = null + return TRUE + + +/obj/machinery/chem_dispenser/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!hackedcheck) + to_chat(user, hack_message) + dispensable_reagents += hacked_reagents + hackedcheck = TRUE + else + to_chat(user, unhack_message) + dispensable_reagents -= hacked_reagents + hackedcheck = FALSE + SSnanoui.update_uis(src) + + +/obj/machinery/chem_dispenser/screwdriver_act(mob/user, obj/item/I) + if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", "[initial(icon_state)]", I)) + return TRUE + +/obj/machinery/chem_dispenser/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(anchored) + anchored = FALSE + WRENCH_UNANCHOR_MESSAGE + else if(!anchored) + anchored = TRUE + WRENCH_ANCHOR_MESSAGE /obj/machinery/chem_dispenser/attack_ai(mob/user) return attack_hand(user) diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm index 247c802f239..169b668250c 100644 --- a/code/modules/reagents/chemistry/machinery/chem_heater.dm +++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm @@ -58,9 +58,6 @@ SSnanoui.update_uis(src) /obj/machinery/chem_heater/attackby(obj/item/I, mob/user) - if(default_unfasten_wrench(user, I)) - power_change() - return if(isrobot(user)) return @@ -77,19 +74,26 @@ SSnanoui.update_uis(src) return - if(default_deconstruction_screwdriver(user, "mixer0b", "mixer0b", I)) - return - if(exchange_parts(user, I)) return - if(panel_open) - if(istype(I, /obj/item/crowbar)) - eject_beaker() - default_deconstruction_crowbar(I) - return 1 return ..() +/obj/machinery/chem_heater/wrench_act(mob/user, obj/item/I) + . = TRUE + default_unfasten_wrench(user, I) + +/obj/machinery/chem_heater/screwdriver_act(mob/user, obj/item/I) + . = TRUE + default_deconstruction_screwdriver(user, "mixer0b", "mixer0b", I) + +/obj/machinery/chem_heater/crowbar_act(mob/user, obj/item/I) + if(!panel_open) + return + . = TRUE + eject_beaker() + default_deconstruction_crowbar(user, I) + /obj/machinery/chem_heater/attack_hand(mob/user) ui_interact(user) diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index ca069ddf514..ea53c0c782d 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -77,30 +77,12 @@ update_icon() /obj/machinery/chem_master/attackby(obj/item/I, mob/user, params) - if(default_deconstruction_screwdriver(user, "mixer0_nopower", "mixer0", I)) - if(beaker) - beaker.forceMove(get_turf(src)) - beaker = null - reagents.clear_reagents() - if(loaded_pill_bottle) - loaded_pill_bottle.forceMove(get_turf(src)) - loaded_pill_bottle = null - return - if(exchange_parts(user, I)) return if(panel_open) - if(iscrowbar(I)) - default_deconstruction_crowbar(I) - return TRUE - else - to_chat(user, "You can't use the [name] while it's panel is opened!") - return TRUE - - if(default_unfasten_wrench(user, I)) - power_change() - return + to_chat(user, "You can't use the [name] while it's panel is opened!") + return TRUE if(istype(I, /obj/item/reagent_containers/glass) || istype(I, /obj/item/reagent_containers/food/drinks/drinkingglass)) if(beaker) @@ -131,6 +113,35 @@ else return ..() + + + + +/obj/machinery/chem_master/crowbar_act(mob/user, obj/item/I) + if(!panel_open) + return + if(default_deconstruction_crowbar(user, I)) + return TRUE + +/obj/machinery/chem_master/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(default_deconstruction_screwdriver(user, "mixer0_nopower", "mixer0", I)) + if(beaker) + beaker.forceMove(get_turf(src)) + beaker = null + reagents.clear_reagents() + if(loaded_pill_bottle) + loaded_pill_bottle.forceMove(get_turf(src)) + loaded_pill_bottle = null + return TRUE + +/obj/machinery/chem_master/wrench_act(mob/user, obj/item/I) + if(panel_open) + return + if(default_unfasten_wrench(user, I)) + power_change() + return TRUE + /obj/machinery/chem_master/Topic(href, href_list) if(..()) return TRUE diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm index 41a0a747118..2422c7a143d 100644 --- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm +++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm @@ -133,77 +133,105 @@ else icon_state = "juicer0" +/obj/machinery/reagentgrinder/crowbar_act(mob/user, obj/item/I) + . = TRUE + if(!anchored || beaker) + return + if(!panel_open) + return + if(!I.tool_use_check(user, 0)) + return + default_deconstruction_crowbar(I) + +/obj/machinery/reagentgrinder/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!anchored || beaker) + return + if(!I.tool_use_check(user, 0)) + return + default_deconstruction_screwdriver(user, "juicer_open", "juicer0", I) + +/obj/machinery/reagentgrinder/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + default_unfasten_wrench(user, I) + /obj/machinery/reagentgrinder/attackby(obj/item/I, mob/user, params) - if(default_unfasten_wrench(user, I)) - return - if(exchange_parts(user, I)) - return + if(exchange_parts(user, I)) + return - if(anchored && !beaker) - if(default_deconstruction_screwdriver(user, "juicer_open", "juicer0", I)) - return + if(istype(I, /obj/item/reagent_containers) && (I.container_type & OPENCONTAINER) ) + if(beaker) + to_chat(user, "There's already a container inside.") + else if(panel_open) + to_chat(user, "Close the maintenance panel first.") + else + if(!user.drop_item()) + return FALSE + beaker = I + beaker.loc = src + update_icon() + updateUsrDialog() + return TRUE //no afterattack - if(panel_open && istype(I, /obj/item/crowbar)) - default_deconstruction_crowbar(I) - return + if(is_type_in_list(I, dried_items)) + if(istype(I, /obj/item/reagent_containers/food/snacks/grown)) + var/obj/item/reagent_containers/food/snacks/grown/G = I + if(!G.dry) + to_chat(user, "You must dry that first!") + return FALSE - if (istype(I, /obj/item/reagent_containers) && (I.container_type & OPENCONTAINER) ) - if(beaker) - to_chat(user, "There's already a container inside.") - else if(panel_open) - to_chat(user, "Close the maintenance panel first.") - else - if(!user.drop_item()) - return 1 - beaker = I - beaker.loc = src - update_icon() - src.updateUsrDialog() - return 1 //no afterattack + if(holdingitems && holdingitems.len >= limit) + to_chat(usr, "The machine cannot hold anymore items.") + return FALSE - if(is_type_in_list(I, dried_items)) - if(istype(I, /obj/item/reagent_containers/food/snacks/grown)) - var/obj/item/reagent_containers/food/snacks/grown/G = I - if(!G.dry) - to_chat(user, "You must dry that first!") - return 1 + //Fill machine with a bag! + if(istype(I, /obj/item/storage/bag)) + var/obj/item/storage/bag/B = I + if(!B.contents.len) + to_chat(user, "[B] is empty.") + return FALSE - if(holdingitems && holdingitems.len >= limit) - to_chat(usr, "The machine cannot hold anymore items.") - return 1 + var/original_contents_len = B.contents.len - //Fill machine with a bag! - if(istype(I, /obj/item/storage/bag)) - var/obj/item/storage/bag/B = I - for (var/obj/item/reagent_containers/food/snacks/grown/G in B.contents) - B.remove_from_storage(G, src) - holdingitems += G - if(holdingitems && holdingitems.len >= limit) //Sanity checking so the blender doesn't overfill - to_chat(user, "You fill the All-In-One grinder to the brim.") - break + for(var/obj/item/G in B.contents) + if(is_type_in_list(G, blend_items) || is_type_in_list(G, juice_items)) + B.remove_from_storage(G, src) + holdingitems += G + if(holdingitems && holdingitems.len >= limit) //Sanity checking so the blender doesn't overfill + to_chat(user, "You fill the All-In-One grinder to the brim.") + break - if(!I.contents.len) - to_chat(user, "You empty the plant bag into the All-In-One grinder.") + if(B.contents.len == original_contents_len) + to_chat(user, "Nothing in [B] can be put into the All-In-One grinder.") + return FALSE + else if(!B.contents.len) + to_chat(user, "You empty all of [B]'s contents into the All-In-One grinder.") + else + to_chat(user, "You empty some of [B]'s contents into the All-In-One grinder.") - src.updateUsrDialog() - return 1 + updateUsrDialog() + return TRUE + + if(!is_type_in_list(I, blend_items) && !is_type_in_list(I, juice_items)) + if(user.a_intent == INTENT_HARM) + return ..() + else + to_chat(user, "Cannot refine into a reagent!") + return TRUE + + if(user.drop_item()) + I.loc = src + holdingitems += I + src.updateUsrDialog() + return FALSE - if (!is_type_in_list(I, blend_items) && !is_type_in_list(I, juice_items)) - if(user.a_intent == INTENT_HARM) - return ..() - else - to_chat(user, "Cannot refine into a reagent!") - return 1 - if(user.drop_item()) - I.loc = src - holdingitems += I - src.updateUsrDialog() - return 0 /obj/machinery/reagentgrinder/attack_ai(mob/user) - return 0 + return FALSE /obj/machinery/reagentgrinder/attack_hand(mob/user) user.set_machine(src) @@ -301,8 +329,8 @@ /obj/machinery/reagentgrinder/proc/is_allowed(obj/item/reagent_containers/O) for (var/i in blend_items) if(istype(O, i)) - return 1 - return 0 + return TRUE + return FALSE /obj/machinery/reagentgrinder/proc/get_allowed_by_id(obj/item/O) for (var/i in blend_items) diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 05967be04ca..a9350961357 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -20,6 +20,9 @@ var/can_synth = TRUE //whether or not a mech syringe gun and synthesize this reagent var/overdose_threshold = 0 var/addiction_chance = 0 + var/addiction_chance_additional = 100 // If we want to lower the chance of addiction even more, set this + var/addiction_threshold = 0 // How much of a chem do we have to absorb before we can start rolling for its ill effects? + var/minor_addiction = FALSE var/addiction_stage = 1 var/last_addiction_dose = 0 var/overdosed = FALSE // You fucked up and this is now triggering it's overdose effects, purge that shit quick. @@ -53,12 +56,7 @@ var/can_become_addicted = M.reagents.reaction_check(M, src) if(can_become_addicted) - if(prob(addiction_chance) && !is_type_in_list(src, M.reagents.addiction_list)) - to_chat(M, "You suddenly feel invigorated and guilty...") - var/datum/reagent/new_reagent = new type() - new_reagent.last_addiction_dose = world.timeofday - M.reagents.addiction_list.Add(new_reagent) - else if(is_type_in_list(src, M.reagents.addiction_list)) + if(is_type_in_list(src, M.reagents.addiction_list)) to_chat(M, "You feel slightly better, but for how long?") for(var/A in M.reagents.addiction_list) var/datum/reagent/AD = A @@ -75,9 +73,24 @@ /datum/reagent/proc/on_mob_life(mob/living/M) current_cycle++ - holder.remove_reagent(id, metabolization_rate * M.metabolism_efficiency * M.digestion_ratio) //By default it slowly disappears. + var/total_depletion_rate = metabolization_rate * M.metabolism_efficiency * M.digestion_ratio // Cache it + + handle_addiction(M, total_depletion_rate) + + holder.remove_reagent(id, total_depletion_rate) //By default it slowly disappears. return STATUS_UPDATE_NONE +/datum/reagent/proc/handle_addiction(mob/living/M, consumption_rate) + if(addiction_chance && !is_type_in_list(src, M.reagents.addiction_list)) + M.reagents.addiction_threshold_accumulated[id] += consumption_rate + var/current_threshold_accumulated = M.reagents.addiction_threshold_accumulated[id] + + if(addiction_threshold < current_threshold_accumulated && prob(addiction_chance) && prob(addiction_chance_additional)) + to_chat(M, "You suddenly feel invigorated and guilty...") + var/datum/reagent/new_reagent = new type() + new_reagent.last_addiction_dose = world.timeofday + M.reagents.addiction_list.Add(new_reagent) + /datum/reagent/proc/on_mob_death(mob/living/M) //use this to have chems have a "death-triggered" effect return @@ -139,6 +152,8 @@ M.emote("twitch_s") if(prob(8)) M.emote("shiver") + if(prob(4)) + to_chat(M, "Your head hurts.") if(prob(4)) to_chat(M, "You begin craving [name]!") return STATUS_UPDATE_NONE @@ -147,23 +162,32 @@ if(prob(8)) M.emote("twitch") if(prob(4)) - to_chat(M, "You have the strong urge for some [name]!") + to_chat(M, "You have a pounding headache.") if(prob(4)) + to_chat(M, "You have the strong urge for some [name]!") + else if(prob(4)) to_chat(M, "You REALLY crave some [name]!") return STATUS_UPDATE_NONE /datum/reagent/proc/addiction_act_stage5(mob/living/M) var/update_flags = STATUS_UPDATE_NONE + if(minor_addiction) + if(prob(6)) + M.AdjustSlowed(3) + to_chat(M, "You feel [pick("tired", "exhausted", "sluggish")].") + else + if(prob(6)) + to_chat(M, "Your stomach lurches painfully!") + M.visible_message("[M] gags and retches!") + update_flags |= M.Stun(rand(2,4), FALSE) + update_flags |= M.Weaken(rand(2,4), FALSE) if(prob(8)) - M.emote("twitch") - if(prob(6)) - to_chat(M, "Your stomach lurches painfully!") - M.visible_message("[M] gags and retches!") - update_flags |= M.Stun(rand(2,4), FALSE) - update_flags |= M.Weaken(rand(2,4), FALSE) + M.emote(pick("twitch", "twitch_s", "shiver")) + if(prob(4)) + to_chat(M, "Your head is killing you!") if(prob(5)) to_chat(M, "You feel like you can't live without [name]!") - if(prob(5)) + else if(prob(5)) to_chat(M, "You would DIE for some [name] right now!") return update_flags diff --git a/code/modules/reagents/chemistry/reagents/alcohol.dm b/code/modules/reagents/chemistry/reagents/alcohol.dm index d4d2bbe2d88..82a7bafe4c6 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol.dm @@ -6,6 +6,8 @@ reagent_state = LIQUID nutriment_factor = 0 //So alcohol can fill you up! If they want to. color = "#404030" // rgb: 64, 64, 48 + addiction_chance = 1 + addiction_threshold = 10 var/dizzy_adj = 3 var/alcohol_perc = 1 //percentage of ethanol in a beverage 0.0 - 1.0 taste_description = "liquid fire" @@ -1190,15 +1192,17 @@ taste_description = "motor oil" /datum/reagent/consumable/ethanol/synthanol/on_mob_life(mob/living/M) - if(!M.isSynthetic()) + if(!(M.dna.species.reagent_tag & PROCESS_SYN)) holder.remove_reagent(id, 3.6) //gets removed from organics very fast if(prob(25)) holder.remove_reagent(id, 15) M.fakevomit() + return ..() + /datum/reagent/consumable/ethanol/synthanol/reaction_mob(mob/living/M, method=TOUCH, volume) - if(M.isSynthetic()) + if(M.dna.species.reagent_tag & PROCESS_SYN) return if(method == INGEST) to_chat(M, pick("That was awful!", "Yuck!")) diff --git a/code/modules/reagents/chemistry/reagents/drinks.dm b/code/modules/reagents/chemistry/reagents/drinks.dm index 6298e79d71d..a5a433b5ffe 100644 --- a/code/modules/reagents/chemistry/reagents/drinks.dm +++ b/code/modules/reagents/chemistry/reagents/drinks.dm @@ -276,7 +276,10 @@ adj_sleepy = -2 adj_temp_hot = 25 overdose_threshold = 45 - addiction_chance = 1 // It's true. + addiction_chance = 2 // It's true. + addiction_chance_additional = 20 + addiction_threshold = 10 + minor_addiction = TRUE heart_rate_increase = 1 drink_icon = "glass_brown" drink_name = "Glass of coffee" @@ -367,6 +370,10 @@ adj_drowsy = -1 adj_sleepy = -3 adj_temp_hot = 20 + addiction_chance = 1 + addiction_chance_additional = 1 + addiction_threshold = 10 + minor_addiction = TRUE drink_icon = "glass_brown" drink_name = "Glass of Tea" drink_desc = "A glass of hot tea. Perhaps a cup with a handle would have been smarter?" diff --git a/code/modules/reagents/chemistry/reagents/drugs.dm b/code/modules/reagents/chemistry/reagents/drugs.dm index 1e2099a901b..2a265e71709 100644 --- a/code/modules/reagents/chemistry/reagents/drugs.dm +++ b/code/modules/reagents/chemistry/reagents/drugs.dm @@ -35,7 +35,8 @@ reagent_state = LIQUID color = "#9087A2" metabolization_rate = 0.2 - addiction_chance = 65 + addiction_chance = 15 + addiction_threshold = 10 heart_rate_decrease = 1 taste_description = "a synthetic high" @@ -88,7 +89,9 @@ reagent_state = LIQUID color = "#60A584" // rgb: 96, 165, 132 overdose_threshold = 35 - addiction_chance = 70 + addiction_chance = 15 + addiction_threshold = 10 + minor_addiction = TRUE heart_rate_increase = 1 taste_description = "calm" @@ -154,7 +157,8 @@ reagent_state = LIQUID color = "#60A584" // rgb: 96, 165, 132 overdose_threshold = 20 - addiction_chance = 50 + addiction_chance = 10 + addiction_threshold = 5 taste_description = "bitterness" /datum/reagent/crank/on_mob_life(mob/living/M) @@ -227,7 +231,8 @@ reagent_state = LIQUID color = "#0264B4" overdose_threshold = 20 - addiction_chance = 50 + addiction_chance = 10 + addiction_threshold = 10 taste_description = "very poor life choices" @@ -299,7 +304,8 @@ reagent_state = LIQUID color = "#60A584" // rgb: 96, 165, 132 overdose_threshold = 20 - addiction_chance = 60 + addiction_chance = 10 + addiction_threshold = 5 metabolization_rate = 0.6 heart_rate_increase = 1 taste_description = "speed" @@ -360,7 +366,8 @@ reagent_state = SOLID color = "#FAFAFA" overdose_threshold = 20 - addiction_chance = 80 + addiction_chance = 15 + addiction_threshold = 5 metabolization_rate = 0.6 taste_description = "WAAAAGH" @@ -460,7 +467,8 @@ description = "Jenkem is a prison drug made from fermenting feces in a solution of urine. Extremely disgusting." reagent_state = LIQUID color = "#644600" - addiction_chance = 30 + addiction_chance = 5 + addiction_threshold = 5 taste_description = "the inside of a toilet... or worse" /datum/reagent/jenkem/on_mob_life(mob/living/M) @@ -526,7 +534,9 @@ metabolization_rate = 0.2 overdose_threshold = 15 process_flags = ORGANIC | SYNTHETIC //Flipping for everyone! - addiction_chance = 10 + addiction_chance = 1 + addiction_chance_additional = 20 + addiction_threshold = 10 taste_description = "flips" /datum/reagent/fliptonium/on_mob_life(mob/living/M) @@ -631,7 +641,8 @@ color = "#1BB1FF" process_flags = SYNTHETIC overdose_threshold = 20 - addiction_chance = 60 + addiction_chance = 10 + addiction_threshold = 5 metabolization_rate = 0.6 taste_description = "wiper fluid" @@ -684,7 +695,8 @@ process_flags = SYNTHETIC overdose_threshold = 20 - addiction_chance = 50 + addiction_chance = 10 + addiction_threshold = 5 taste_description = "silicon" diff --git a/code/modules/reagents/chemistry/reagents/food.dm b/code/modules/reagents/chemistry/reagents/food.dm index 5353dc54b88..f668807c1c5 100644 --- a/code/modules/reagents/chemistry/reagents/food.dm +++ b/code/modules/reagents/chemistry/reagents/food.dm @@ -149,6 +149,10 @@ description = "This is what makes chilis hot." reagent_state = LIQUID color = "#B31008" // rgb: 179, 16, 8 + addiction_chance = 1 + addiction_chance_additional = 10 + addiction_threshold = 2 + minor_addiction = TRUE taste_description = "HOTNESS" taste_mult = 1.5 @@ -651,6 +655,10 @@ reagent_state = LIQUID color = "#B2B139" overdose_threshold = 50 + addiction_chance = 2 + addiction_chance_additional = 10 + addiction_threshold = 5 + minor_addiction = TRUE harmless = FALSE taste_description = "cheese?" @@ -667,7 +675,10 @@ description = "Hell, I don't even know if this IS cheese. Whatever it is, it ain't normal. If you want to, pour it out to make it solid." reagent_state = SOLID color = "#50FF00" - addiction_chance = 5 + addiction_chance = 1 + addiction_chance_additional = 10 + addiction_threshold = 5 + minor_addiction = TRUE taste_description = "cheeeeeese...?" /datum/reagent/consumable/weird_cheese/on_mob_life(mob/living/M) diff --git a/code/modules/reagents/chemistry/reagents/medicine.dm b/code/modules/reagents/chemistry/reagents/medicine.dm index c297716c1a7..8014238d9b3 100644 --- a/code/modules/reagents/chemistry/reagents/medicine.dm +++ b/code/modules/reagents/chemistry/reagents/medicine.dm @@ -6,7 +6,11 @@ /datum/reagent/medicine/on_mob_life(mob/living/M) current_cycle++ - holder.remove_reagent(id, (metabolization_rate / M.metabolism_efficiency) * M.digestion_ratio) //medicine reagents stay longer if you have a better metabolism + var/total_depletion_rate = (metabolization_rate / M.metabolism_efficiency) * M.digestion_ratio // Cache it + + handle_addiction(M, total_depletion_rate) + + holder.remove_reagent(id, total_depletion_rate) //medicine reagents stay longer if you have a better metabolism return STATUS_UPDATE_NONE /datum/reagent/medicine/hydrocodone @@ -293,7 +297,9 @@ color = "#C8A5DC" metabolization_rate = 0.2 overdose_threshold = 30 - addiction_chance = 5 + addiction_chance = 1 + addiction_chance_additional = 20 + addiction_threshold = 5 harmless = FALSE taste_description = "health" @@ -440,7 +446,9 @@ reagent_state = LIQUID color = "#C8A5DC" metabolization_rate = 0.2 - addiction_chance = 20 + addiction_chance = 1 + addiction_chance_additional = 20 + addiction_threshold = 10 harmless = FALSE taste_description = "oxygenation" @@ -462,7 +470,9 @@ color = "#C8A5DC" metabolization_rate = 0.3 overdose_threshold = 35 - addiction_chance = 25 + addiction_chance = 1 + addiction_chance = 10 + addiction_threshold = 10 harmless = FALSE taste_description = "stimulation" @@ -512,7 +522,8 @@ description = "Anti-allergy medication. May cause drowsiness, do not operate heavy machinery while using this." reagent_state = LIQUID color = "#5BCBE1" - addiction_chance = 10 + addiction_chance = 1 + addiction_threshold = 10 harmless = FALSE taste_description = "antihistamine" @@ -535,7 +546,8 @@ reagent_state = LIQUID color = "#C8A5DC" overdose_threshold = 20 - addiction_chance = 50 + addiction_chance = 10 + addiction_threshold = 15 shock_reduction = 50 harmless = FALSE taste_description = "a delightful numbing" @@ -883,7 +895,9 @@ description = "This experimental plasma-based compound seems to regulate body temperature." reagent_state = LIQUID color = "#D782E6" - addiction_chance = 20 + addiction_chance = 1 + addiction_chance_additional = 10 + addiction_threshold = 10 overdose_threshold = 50 taste_description = "warmth and stability" diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic.dm index 17eee91080e..a1f2d74e77e 100644 --- a/code/modules/reagents/chemistry/reagents/pyrotechnic.dm +++ b/code/modules/reagents/chemistry/reagents/pyrotechnic.dm @@ -198,6 +198,7 @@ if(!S.reagents) S.create_reagents(volume) S.reagents.add_reagent("thermite", volume) + S.thermite = TRUE S.overlays.Cut() S.overlays = image('icons/effects/effects.dmi', icon_state = "thermite") if(S.active_hotspot) diff --git a/code/modules/reagents/chemistry/reagents/toxins.dm b/code/modules/reagents/chemistry/reagents/toxins.dm index b8ccede11bd..59a7d07e241 100644 --- a/code/modules/reagents/chemistry/reagents/toxins.dm +++ b/code/modules/reagents/chemistry/reagents/toxins.dm @@ -419,7 +419,7 @@ color = "#9ACD32" taste_description = "bitterness" -/datum/reagent/spores/on_mob_life(mob/living/M) +/datum/reagent/spore/on_mob_life(mob/living/M) var/update_flags = STATUS_UPDATE_NONE update_flags |= M.adjustToxLoss(1, FALSE) M.damageoverlaytemp = 60 diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 482b8b20ccd..a4320639f39 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -43,21 +43,22 @@ to_chat(user, "[src] is empty!") return + var/contents_log = reagents.reagent_list.Join(", ") spray(A) playsound(loc, 'sound/effects/spray2.ogg', 50, 1, -6) user.changeNext_move(CLICK_CD_RANGE*2) user.newtonian_move(get_dir(A, user)) - if(reagents.has_reagent("sacid")) - msg_admin_attack("[key_name_admin(user)] fired sulphuric acid from \a [src] at [COORD(user)].", ATKLOG_FEW) - log_game("[key_name(user)] fired sulphuric acid from \a [src] at [COORD(user)].") - if(reagents.has_reagent("facid")) - msg_admin_attack("[key_name_admin(user)] fired fluorosulfuric acid from \a [src] at [COORD(user)].", ATKLOG_FEW) - log_game("[key_name(user)] fired fluorosulfuric Acid from \a [src] at [COORD(user)].") - if(reagents.has_reagent("lube")) - msg_admin_attack("[key_name_admin(user)] fired space lube from \a [src] at [COORD(user)].") - log_game("[key_name(user)] fired space lube from \a [src] at [COORD(user)].") + if(reagents.reagent_list.len == 1 && reagents.has_reagent("cleaner")) // Only show space cleaner logs if it's burning people from being too hot or cold + if(reagents.chem_temp < 300 && reagents.chem_temp > 280) // 280 is the cold threshold for slimes, 300 the hot threshold for drask + return + + var/attack_log_type = ATKLOG_MOST + if(reagents.has_reagent("sacid") || reagents.has_reagent("facid") || reagents.has_reagent("lube")) + attack_log_type = ATKLOG_FEW + msg_admin_attack("[key_name_admin(user)] used a spray bottle at [COORD(user)] - Contents: [contents_log] - Temperature: [reagents.chem_temp]K", attack_log_type) + log_game("[key_name(user)] used a spray bottle at [COORD(user)] - Contents: [contents_log] - Temperature: [reagents.chem_temp]K") return diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index c1e4b89e774..1c74be11965 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -151,29 +151,24 @@ test.Shift(NORTH, 1) test.Shift(EAST, 6) overlays += test - - if(istype(I, /obj/item/weldingtool)) - if(!reagents.has_reagent("fuel")) - to_chat(user, "[src] is out of fuel!") - return - var/obj/item/weldingtool/W = I - if(!W.welding) - if(W.reagents.has_reagent("fuel", W.max_fuel)) - to_chat(user, "Your [W] is already full!") - return - reagents.trans_to(W, W.max_fuel) - user.visible_message("[user] refills [user.p_their()] [W].", "You refill [W].") - playsound(src, 'sound/effects/refill.ogg', 50, 1) - W.update_icon() - else - user.visible_message("[user] catastrophically fails at refilling [user.p_their()] [W]!", "That was stupid of you.") - message_admins("[key_name_admin(user)] triggered a fueltank explosion at [COORD(loc)]") - log_game("[key_name(user)] triggered a fueltank explosion at [COORD(loc)]") - investigate_log("[key_name(user)] triggered a fueltank explosion at [COORD(loc)]", INVESTIGATE_BOMB) - boom() else return ..() +obj/structure/reagent_dispensers/fueltank/welder_act(mob/user, obj/item/I) + . = TRUE + if(!reagents.has_reagent("fuel")) + to_chat(user, "[src] is out of fuel!") + return + if(I.tool_enabled && I.use_tool(src, user, volume = I.tool_volume)) //check it's enabled first to prevent duplicate messages when refuelling + user.visible_message("[user] catastrophically fails at refilling [user.p_their()] [I]!", "That was stupid of you.") + message_admins("[key_name_admin(user)] triggered a fueltank explosion at [COORD(loc)]") + log_game("[key_name(user)] triggered a fueltank explosion at [COORD(loc)]") + investigate_log("[key_name(user)] triggered a fueltank explosion at [COORD(loc)]", INVESTIGATE_BOMB) + boom() + else + I.refill(user, src, reagents.get_reagent_amount("fuel")) //Try dump all fuel into the welder + + /obj/structure/reagent_dispensers/fueltank/Move() ..() if(rig) @@ -233,35 +228,11 @@ user.put_in_hands(S) paper_cups-- -/obj/structure/reagent_dispensers/water_cooler/attackby(obj/item/W, mob/living/user, params) - add_fingerprint(user) - user.changeNext_move(CLICK_CD_MELEE) - if(iswrench(W)) - if(anchored) - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] starts loosening [src]'s floor casters.", \ - "You start loosening [src]'s floor casters...") - if(do_after(user, 40 * W.toolspeed, target = src)) - if(!loc || !anchored) - return - user.visible_message("[user] loosened [src]'s floor casters.", \ - "You loosen [src]'s floor casters.") - anchored = 0 - else - if(!isfloorturf(loc)) - user.visible_message("A floor must be present to secure [src]!") - return - playsound(loc, W.usesound, 100, 1) - user.visible_message("[user] start securing [src]'s floor casters...", \ - "You start securing [src]'s floor casters...") - if(do_after(user, 40 * W.toolspeed, target = src)) - if(!loc || anchored) - return - user.visible_message("[user] has secured [src]'s floor casters.", \ - "You have secured [src]'s floor casters.") - anchored = 1 +/obj/structure/reagent_dispensers/water_cooler/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) return - return ..() + default_unfasten_wrench(user, I, 40) /obj/structure/reagent_dispensers/beerkeg name = "beer keg" diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm index 933f223d120..4d242212f2c 100644 --- a/code/modules/recycling/conveyor2.dm +++ b/code/modules/recycling/conveyor2.dm @@ -50,20 +50,8 @@ GLOBAL_LIST_INIT(conveyor_switches, list()) // attack with item, place item on conveyor /obj/machinery/conveyor/attackby(obj/item/I, mob/user) - if(iscrowbar(I)) - if(!(stat & BROKEN)) - var/obj/item/conveyor_construct/C = new(loc) - C.id = id - transfer_fingerprints_to(C) - playsound(loc, I.usesound, 50, 1) - to_chat(user,"You remove the conveyor belt.") - qdel(src) - else if(stat & BROKEN) + if(stat & BROKEN) return ..() - else if(iswrench(I)) - set_rotation(user) - update_move_direction() - playsound(loc, I.usesound, 50, 1) else if(istype(I, /obj/item/conveyor_switch_construct)) var/obj/item/conveyor_switch_construct/S = I if(S.id == id) @@ -79,6 +67,25 @@ GLOBAL_LIST_INIT(conveyor_switches, list()) else return ..() + +/obj/machinery/conveyor/crowbar_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!(stat & BROKEN)) + var/obj/item/conveyor_construct/C = new(loc) + C.id = id + transfer_fingerprints_to(C) + to_chat(user,"You remove [src].") + qdel(src) + +/obj/machinery/conveyor/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + set_rotation(user) + update_move_direction() + // attack with hand, move pulled object onto conveyor /obj/machinery/conveyor/attack_hand(mob/user as mob) user.Move_Pulled(src) @@ -305,17 +312,21 @@ GLOBAL_LIST_INIT(conveyor_switches, list()) S.update_icon() CHECK_TICK -/obj/machinery/conveyor_switch/attackby(obj/item/I, mob/user) - if(iscrowbar(I)) - var/obj/item/conveyor_switch_construct/C = new(loc, id) - transfer_fingerprints_to(C) - to_chat(user,"You detach the conveyor switch.") - qdel(src) - else if(ismultitool(I)) - one_way = !one_way - to_chat(user, "[src] will now go [one_way ? "forwards only" : "both forwards and backwards"].") - else - return ..() +/obj/machinery/conveyor_switch/crowbar_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + var/obj/item/conveyor_switch_construct/C = new(loc, id) + transfer_fingerprints_to(C) + to_chat(user,"You detach [src].") + qdel(src) + +/obj/machinery/conveyor_switch/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + one_way = !one_way + to_chat(user, "[src] will now go [one_way ? "forwards only" : "both forwards and backwards"].") /obj/machinery/conveyor_switch/power_change() ..() diff --git a/code/modules/recycling/disposal-construction.dm b/code/modules/recycling/disposal-construction.dm index 0c1c775c1f9..66caa897f21 100644 --- a/code/modules/recycling/disposal-construction.dm +++ b/code/modules/recycling/disposal-construction.dm @@ -207,12 +207,9 @@ if(istype(I, /obj/item/weldingtool)) if(anchored) - var/obj/item/weldingtool/W = I - if(W.remove_fuel(0,user)) - playsound(src.loc, W.usesound, 100, 1) + if(I.tool_use_check(user, 0)) to_chat(user, "Welding the [nicetype] in place.") - if(do_after(user, 20 * W.toolspeed, target = src)) - if(!src || !W.isOn()) return + if(I.use_tool(src, user, 20, volume = I.tool_volume)) to_chat(user, "The [nicetype] has been welded in place!") update() // TODO: Make this neat if(ispipe) // Pipe diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 02ca42e94d9..59f6d395aff 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -26,9 +26,12 @@ var/flush_every_ticks = 30 //Every 30 ticks it will look whether it is ready to flush var/flush_count = 0 //this var adds 1 once per tick. When it reaches flush_every_ticks it resets and tries to flush. var/last_sound = 0 + var/required_mode_to_deconstruct = -1 + var/deconstructs_to = PIPE_DISPOSALS_BIN active_power_usage = 600 idle_power_usage = 100 + // create a new disposal // find the attached trunk (if present) /obj/machinery/disposal/New() @@ -95,44 +98,6 @@ return src.add_fingerprint(user) - if(mode<=0) // It's off - if(istype(I, /obj/item/screwdriver)) - if(contents.len > 0) - to_chat(user, "Eject the items first!") - return - if(mode==0) // It's off but still not unscrewed - mode=-1 // Set it to doubleoff l0l - playsound(src.loc, I.usesound, 50, 1) - to_chat(user, "You remove the screws around the power connection.") - return - else if(mode==-1) - mode=0 - playsound(src.loc, I.usesound, 50, 1) - to_chat(user, "You attach the screws around the power connection.") - return - else if(istype(I,/obj/item/weldingtool) && mode==-1) - if(contents.len > 0) - to_chat(user, "Eject the items first!") - return - var/obj/item/weldingtool/W = I - if(W.remove_fuel(0,user)) - playsound(src.loc, W.usesound, 100, 1) - to_chat(user, "You start slicing the floorweld off the disposal unit.") - - if(do_after(user, 20 * W.toolspeed, target = src)) - if(!src || !W.isOn()) return - to_chat(user, "You sliced the floorweld off the disposal unit.") - var/obj/structure/disposalconstruct/C = new (src.loc) - src.transfer_fingerprints_to(C) - C.ptype = PIPE_DISPOSALS_BIN - C.anchored = 1 - C.density = 1 - C.update() - qdel(src) - return - else - to_chat(user, "You need more welding fuel to complete this task.") - return if(istype(I, /obj/item/melee/energy/blade)) to_chat(user, "You can't place that item inside the disposal unit.") @@ -179,6 +144,43 @@ update() + + + +/obj/machinery/disposal/screwdriver_act(mob/user, obj/item/I) + if(mode>0) // It's on + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(contents.len > 0) + to_chat(user, "Eject the items first!") + return + if(mode==0) // It's off but still not unscrewed + mode=-1 // Set it to doubleoff l0l + else if(mode==-1) + mode=0 + to_chat(user, "You [mode ? "unfasten": "fasten"] the screws around the power connection.") + +/obj/machinery/disposal/welder_act(mob/user, obj/item/I) + . = TRUE + if(mode != required_mode_to_deconstruct) + return + if(contents.len > 0) + to_chat(user, "Eject the items first!") + return + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_FLOOR_SLICE_MESSAGE + if(I.use_tool(src, user, 20, volume = I.tool_volume)) + WELDER_FLOOR_SLICE_SUCCESS_MESSAGE + var/obj/structure/disposalconstruct/C = new (src.loc) + C.ptype = deconstructs_to + C.update() + C.anchored = 1 + C.density = 1 + qdel(src) + // mouse drop another mob or self // /obj/machinery/disposal/MouseDrop_T(mob/target, mob/user) @@ -893,21 +895,15 @@ add_fingerprint(user) - if(istype(I, /obj/item/weldingtool)) - var/obj/item/weldingtool/W = I - if(W.remove_fuel(0, user)) - to_chat(user, "You begin slicing \the [src].") - playsound(loc, W.usesound, 100, 1) - if(do_after(user, 30 * W.toolspeed, target = src)) - to_chat(user, "You finish slicing \the [src].") - welded() - else - to_chat(user, "You need more welding fuel to cut the pipe.") - -// called when pipe is cut with welder -/obj/structure/disposalpipe/proc/welded() - - var/obj/structure/disposalconstruct/C = new (src.loc) +/obj/structure/disposalpipe/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_SLICING_MESSAGE + if(!I.use_tool(src, user, 30, volume = I.tool_volume)) + return + WELDER_SLICING_SUCCESS_MESSAGE + var/obj/structure/disposalconstruct/C = new (get_turf(src)) switch(base_icon_state) if("pipe-s") C.ptype = PIPE_DISPOSALS_STRAIGHT @@ -927,8 +923,8 @@ C.ptype = PIPE_DISPOSALS_SORT_LEFT src.transfer_fingerprints_to(C) C.dir = dir - C.density = 0 - C.anchored = 1 + C.density = FALSE + C.anchored = TRUE C.update() qdel(src) @@ -1210,19 +1206,6 @@ if(T.intact) return // prevent interaction with T-scanner revealed pipes src.add_fingerprint(user) - if(istype(I, /obj/item/weldingtool)) - var/obj/item/weldingtool/W = I - - if(W.remove_fuel(0,user)) - playsound(loc, W.usesound, 100, 1) - to_chat(user, "Slicing the disposal pipe.") - if(do_after(user, 30 * W.toolspeed, target = src)) - if(!W.isOn()) - return - welded() - else - to_chat(user, "You need more welding fuel to cut the pipe.") - return // would transfer to next pipe segment, but we are in a trunk // if not entering from disposal bin, @@ -1269,8 +1252,12 @@ update() return -/obj/structure/disposalpipe/broken/welded() - qdel(src) +/obj/structure/disposalpipe/broken/welder_act(mob/user, obj/item/I) + if(I.use_tool(src, user, 0, volume = I.tool_volume)) + to_chat(user, "You remove [src]!") + I.play_tool_sound(src, I.tool_volume) + qdel(src) + return TRUE // the disposal outlet machine @@ -1334,25 +1321,21 @@ playsound(src.loc, I.usesound, 50, 1) to_chat(user, "You attach the screws around the power connection.") return - else if(istype(I,/obj/item/weldingtool) && mode==1) - var/obj/item/weldingtool/W = I - if(W.remove_fuel(0,user)) - playsound(src.loc, W.usesound, 100, 1) - to_chat(user, "You start slicing the floorweld off the disposal outlet.") - if(do_after(user, 20 * W.toolspeed, target = src)) - if(!src || !W.isOn()) return - to_chat(user, "You sliced the floorweld off the disposal outlet.") - var/obj/structure/disposalconstruct/C = new (src.loc) - src.transfer_fingerprints_to(C) - C.ptype = PIPE_DISPOSALS_OUTLET - C.update() - C.anchored = 1 - C.density = 1 - qdel(src) - return - else - to_chat(user, "You need more welding fuel to complete this task.") - return + +/obj/structure/disposaloutlet/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_FLOOR_SLICE_MESSAGE + if(I.use_tool(src, user, 20, volume = I.tool_volume)) + WELDER_FLOOR_SLICE_SUCCESS_MESSAGE + var/obj/structure/disposalconstruct/C = new (src.loc) + C.ptype = PIPE_DISPOSALS_OUTLET + C.update() + C.anchored = TRUE + C.density = TRUE + transfer_fingerprints_to(C) + qdel(src) //When the disposalsoutlet is forcefully moved. Due to meteorshot or the recall item spell for instance /obj/structure/disposaloutlet/Moved(atom/OldLoc, Dir) diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index fd94341d93c..95e076d2670 100755 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -271,8 +271,9 @@ desc = "A chute for big and small packages alike!" density = 1 icon_state = "intake" - - var/c_mode = 0 + required_mode_to_deconstruct = 1 + deconstructs_to = PIPE_DISPOSALS_CHUTE + var/can_deconstruct = FALSE /obj/machinery/disposal/deliveryChute/New() ..() @@ -343,39 +344,31 @@ update() return -/obj/machinery/disposal/deliveryChute/attackby(obj/item/I, mob/user, params) - if(!I || !user) +/obj/machinery/disposal/deliveryChute/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return + can_deconstruct = !can_deconstruct + to_chat(user, "You [can_deconstruct ? "unfasten": "fasten"] the screws around the power connection.") - if(istype(I, /obj/item/screwdriver)) - if(c_mode==0) - c_mode=1 - playsound(src.loc, I.usesound, 50, 1) - to_chat(user, "You remove the screws around the power connection.") - return - else if(c_mode==1) - c_mode=0 - playsound(src.loc, I.usesound, 50, 1) - to_chat(user, "You attach the screws around the power connection.") - return - else if(istype(I,/obj/item/weldingtool) && c_mode==1) - var/obj/item/weldingtool/W = I - if(W.remove_fuel(0,user)) - playsound(src.loc, W.usesound, 100, 1) - to_chat(user, "You start slicing the floorweld off the delivery chute.") - if(do_after(user, 20 * W.toolspeed, target = src)) - if(!src || !W.isOn()) return - to_chat(user, "You sliced the floorweld off the delivery chute.") - var/obj/structure/disposalconstruct/C = new (src.loc) - C.ptype = PIPE_DISPOSALS_CHUTE - C.update() - C.anchored = 1 - C.density = 1 - qdel(src) - return - else - to_chat(user, "You need more welding fuel to complete this task.") - return +/obj/machinery/disposal/deliveryChute/welder_act(mob/user, obj/item/I) + . = TRUE + if(!can_deconstruct) + return + if(contents.len > 0) + to_chat(user, "Eject the items first!") + return + if(!I.tool_use_check(user, 0)) + return + WELDER_ATTEMPT_FLOOR_SLICE_MESSAGE + if(I.use_tool(src, user, 20, volume = I.tool_volume)) + WELDER_FLOOR_SLICE_SUCCESS_MESSAGE + var/obj/structure/disposalconstruct/C = new (loc) + C.ptype = deconstructs_to + C.update() + C.anchored = TRUE + C.density = TRUE + qdel(src) /obj/item/shippingPackage name = "Shipping package" diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm index 2ddab9b2f12..0332b30a413 100644 --- a/code/modules/research/circuitprinter.dm +++ b/code/modules/research/circuitprinter.dm @@ -94,7 +94,7 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). reagents.trans_to(I, reagents.total_volume) I.loc = src.loc materials.retrieve_all() - default_deconstruction_crowbar(O) + default_deconstruction_crowbar(user, O) return else to_chat(user, "You can't load the [src.name] while it's opened.") diff --git a/code/modules/research/destructive_analyzer.dm b/code/modules/research/destructive_analyzer.dm index 027a8549df4..a360e0ee231 100644 --- a/code/modules/research/destructive_analyzer.dm +++ b/code/modules/research/destructive_analyzer.dm @@ -56,7 +56,7 @@ Note: Must be placed within 3 tiles of the R&D Console if(exchange_parts(user, O)) return - if(default_deconstruction_crowbar(O)) + if(default_deconstruction_crowbar(user, O)) return if(disabled) diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index 1548125b785..3951cf23312 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -125,7 +125,7 @@ return if(panel_open && istype(O, /obj/item/crowbar)) - default_deconstruction_crowbar(O) + default_deconstruction_crowbar(user, O) return if(!checkCircumstances(O)) @@ -157,7 +157,7 @@ return -/obj/machinery/r_n_d/experimentor/default_deconstruction_crowbar(obj/item/O) +/obj/machinery/r_n_d/experimentor/default_deconstruction_crowbar(user, obj/item/O) ejectItem() ..(O) @@ -618,6 +618,7 @@ var/floof /obj/item/relic/New() + ..() icon_state = pick("shock_kit","armor-igniter-analyzer","infra-igniter0","infra-igniter1","radio-multitool","prox-radio1","radio-radio","timer-multitool0","radio-igniter-tank") realName = "[pick("broken","twisted","spun","improved","silly","regular","badly made")] [pick("device","object","toy","suspicious tech","gear")]" floof = pick(/mob/living/simple_animal/pet/dog/corgi, /mob/living/simple_animal/pet/cat, /mob/living/simple_animal/pet/dog/fox, /mob/living/simple_animal/mouse, /mob/living/simple_animal/pet/dog/pug, /mob/living/simple_animal/lizard, /mob/living/simple_animal/diona, /mob/living/simple_animal/butterfly, /mob/living/carbon/human/monkey) diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm index a441dff00b3..de71f51a0cd 100644 --- a/code/modules/research/protolathe.dm +++ b/code/modules/research/protolathe.dm @@ -102,7 +102,7 @@ Note: Must be placed west/left of and R&D console to function. for(var/obj/item/reagent_containers/glass/G in component_parts) reagents.trans_to(G, G.reagents.maximum_volume) materials.retrieve_all() - default_deconstruction_crowbar(O) + default_deconstruction_crowbar(user, O) return 1 else to_chat(user, "You can't load the [src.name] while it's opened.") diff --git a/code/modules/research/research.dm b/code/modules/research/research.dm index 05786daed94..65d9a1d3ad4 100644 --- a/code/modules/research/research.dm +++ b/code/modules/research/research.dm @@ -345,6 +345,7 @@ datum/tech/robotics var/default_desc = "A disk for storing technology data for further research." /obj/item/disk/tech_disk/New() + ..() src.pixel_x = rand(-5.0, 5) src.pixel_y = rand(-5.0, 5) diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm index abb20ac091a..d7aefee96b7 100644 --- a/code/modules/research/server.dm +++ b/code/modules/research/server.dm @@ -146,7 +146,7 @@ if(panel_open) if(istype(O, /obj/item/crowbar)) griefProtection() - default_deconstruction_crowbar(O) + default_deconstruction_crowbar(user, O) return 1 else return ..() diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm index dbb8f597905..746e0ece0e8 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -163,15 +163,20 @@ if(loaded) to_chat(user, "You fill [src] with the monkey cubes stored in [O]. [src] now has [monkeys] monkey cubes stored.") return - else if(ismultitool(O)) - var/obj/item/multitool/I = O - if(istype(I.buffer, /obj/machinery/monkey_recycler)) - to_chat(user, "You link [src] with [I.buffer] in [I] buffer.") - connected_recycler = I.buffer - connected_recycler.connected += src - return return ..() +/obj/machinery/computer/camera_advanced/xenobio/multitool_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!I.multitool_check_buffer(user)) + return + var/obj/item/multitool/M = I + if(istype(M.buffer, /obj/machinery/monkey_recycler)) + M.set_multitool_buffer(user, src) + connected_recycler = M.buffer + connected_recycler.connected += src + /datum/action/innate/slime_place name = "Place Slimes" button_icon_state = "slime_down" diff --git a/code/modules/ruins/lavalandruin_code/dead_ratvar.dm b/code/modules/ruins/lavalandruin_code/dead_ratvar.dm index 4c37572c989..0d56293f1bc 100644 --- a/code/modules/ruins/lavalandruin_code/dead_ratvar.dm +++ b/code/modules/ruins/lavalandruin_code/dead_ratvar.dm @@ -92,22 +92,26 @@ /obj/structure/clockwork/wall_gear/emp_act(severity) return +/obj/structure/clockwork/wall_gear/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(anchored) + to_chat(user, "[src] needs to be unsecured to disassemble it!") + return + if(!I.tool_use_check(user, 0)) + return + TOOL_ATTEMPT_DISMANTLE_MESSAGE + if(I.use_tool(src, user, 30, volume = I.tool_volume)) + TOOL_DISMANTLE_SUCCESS_MESSAGE + deconstruct(TRUE) + +/obj/structure/clockwork/wall_gear/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + default_unfasten_wrench(user, I, 10) + /obj/structure/clockwork/wall_gear/attackby(obj/item/I, mob/user, params) - if(iswrench(I)) - default_unfasten_wrench(user, I, 10) - return 1 - else if(isscrewdriver(I)) - if(anchored) - to_chat(user, "[src] needs to be unsecured to disassemble it!") - else - var/obj/item/screwdriver/S = I - user.visible_message("[user] starts to disassemble [src].", "You start to disassemble [src]...") - if(do_after(user, 30 * S.toolspeed, target = src) && !anchored) - playsound(loc, S.usesound, 50, 1) - to_chat(user, "You disassemble [src].") - deconstruct(TRUE) - return 1 - else if(istype(I, /obj/item/stack/tile/brass)) + if(istype(I, /obj/item/stack/tile/brass)) var/obj/item/stack/tile/brass/W = I if(W.get_amount() < 1) to_chat(user, "You need one brass sheet to do this!") diff --git a/code/modules/security_levels/keycard authentication.dm b/code/modules/security_levels/keycard authentication.dm index e1e3104e643..71a77d83655 100644 --- a/code/modules/security_levels/keycard authentication.dm +++ b/code/modules/security_levels/keycard authentication.dm @@ -99,7 +99,7 @@ if(href_list["reset"]) reset() if(href_list["ert"]) - ert_reason = input(usr, "Reason for ERT Call:", "", "") + ert_reason = stripped_input(usr, "Reason for ERT Call:", "", "") SSnanoui.update_uis(src) add_fingerprint(usr) @@ -165,9 +165,10 @@ feedback_inc("alert_keycard_auth_stationRevoke",1) if("Emergency Response Team") if(is_ert_blocked()) - to_chat(usr, "All Emergency Response Teams are dispatched and can not be called at this time.") + atom_say("All Emergency Response Teams are dispatched and can not be called at this time.") return - to_chat(usr, "ERT request transmitted.") + atom_say("ERT request transmitted!") + command_announcer.autosay("ERT request transmitted. Reason: [ert_reason]", name) print_centcom_report(ert_reason, station_time_timestamp() + " ERT Request") var/fullmin_count = 0 @@ -221,4 +222,4 @@ var/global/station_all_access = 0 D.emergency = 0 D.update_icon(0) minor_announcement.Announce("Access restrictions on all station airlocks have been re-added. Seek station AI or a colleague's assistance if you are stuck.") - station_all_access = 0 \ No newline at end of file + station_all_access = 0 diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index 953c0e6682c..5af2d472416 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -174,43 +174,37 @@ /obj/docking_port/mobile/emergency/proc/is_hijacked() for(var/mob/living/player in GLOB.player_list) - if(player.mind) - if(player.stat != DEAD || !iszombie(player)) - if(issilicon(player)) //Borgs are technically dead anyways + if(!player.mind) + continue + if(player.stat == DEAD) // Corpses + continue + if(iszombie(player)) // Walking corpses + continue + if(issilicon(player)) //Borgs are technically dead anyways + continue + if(isanimal(player)) //Poly does not own the shuttle + continue + if(ishuman(player)) //hostages allowed on the shuttle, check for restraints + var/mob/living/carbon/human/H = player + if(!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD) //new crit users who are in hard crit are considered dead + continue + if(H.handcuffed) //cuffs + continue + if(H.wear_suit && H.wear_suit.breakouttime) //straight jacket + continue + if(istype(H.loc, /obj/structure/closet)) //locked/welded locker, all aboard the clown train honk honk + var/obj/structure/closet/C = H.loc + if(C.welded || C.locked) continue - if(isanimal(player)) //Poly does not own the shuttle - continue - if(ishuman(player)) //hostages allowed on the shuttle, check for restraints - var/mob/living/carbon/human/H = player - if(!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD) //new crit users who are in hard crit are considered dead - continue - if(H.handcuffed) //cuffs - continue - if(H.wear_suit && H.wear_suit.breakouttime) //straight jacket - continue - if(istype(H.loc, /obj/structure/closet)) //locked/welded locker, all aboard the clown train honk honk - var/obj/structure/closet/C = H.loc - if(C.welded || C.locked) - continue - var/special_role = player.mind.special_role - if(special_role) - if(special_role == SPECIAL_ROLE_TRAITOR) // traitors can hijack the shuttle - continue + var/special_role = player.mind.special_role + if(special_role) + // There's a long list of special roles, but almost all of them are antags anyway. + // If you manage to escape with a pet slaughter demon - go for it! Greentext well earned! + if(special_role != SPECIAL_ROLE_EVENTMISC && special_role != SPECIAL_ROLE_ERT && special_role != SPECIAL_ROLE_DEATHSQUAD) + continue - if(special_role == SPECIAL_ROLE_CHANGELING) // changelings as well - continue - - if(special_role == SPECIAL_ROLE_VAMPIRE || special_role == SPECIAL_ROLE_VAMPIRE_THRALL) // for traitorvamp - continue - - if(special_role == SPECIAL_ROLE_NUKEOPS) // so can nukeops, for the hell of it - continue - - if(special_role == SPECIAL_ROLE_SYNDICATE_DEATHSQUAD) // and the syndie deathsquad i guess - continue - - if(get_area(player) == areaInstance) - return FALSE + if(get_area(player) == areaInstance) + return FALSE return TRUE diff --git a/code/modules/shuttle/ert.dm b/code/modules/shuttle/ert.dm index cbd007b32f9..9d124f78f29 100644 --- a/code/modules/shuttle/ert.dm +++ b/code/modules/shuttle/ert.dm @@ -4,6 +4,7 @@ shuttleId = "specops" possible_destinations = "specops_home;specops_away;specops_custom" resistance_flags = INDESTRUCTIBLE + flags = NODECONSTRUCT /obj/machinery/computer/camera_advanced/shuttle_docker/ert name = "specops navigation computer" @@ -16,6 +17,7 @@ x_offset = 0 y_offset = 0 resistance_flags = INDESTRUCTIBLE + flags = NODECONSTRUCT access_tcomms = FALSE access_construction = FALSE access_mining = FALSE \ No newline at end of file diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm index 9da43d08fbf..446b6466dc5 100644 --- a/code/modules/shuttle/supply.dm +++ b/code/modules/shuttle/supply.dm @@ -475,7 +475,7 @@ SSnanoui.update_uis(src) return 1 - var/index = copytext(href_list["doorder"], 1, lentext(href_list["doorder"])) //text2num(copytext(href_list["doorder"], 1)) + var/index = copytext(href_list["doorder"], 1, length(href_list["doorder"])) //text2num(copytext(href_list["doorder"], 1)) var/multi = text2num(copytext(href_list["doorder"], -1)) if(!isnum(multi)) return 1 @@ -656,7 +656,7 @@ SSnanoui.update_uis(src) return 1 - var/index = copytext(href_list["doorder"], 1, lentext(href_list["doorder"])) //text2num(copytext(href_list["doorder"], 1)) + var/index = copytext(href_list["doorder"], 1, length(href_list["doorder"])) //text2num(copytext(href_list["doorder"], 1)) var/multi = text2num(copytext(href_list["doorder"], -1)) if(!isnum(multi)) return 1 diff --git a/code/modules/shuttle/syndicate.dm b/code/modules/shuttle/syndicate.dm index 5c0be6a78a5..6c3c4155ff0 100644 --- a/code/modules/shuttle/syndicate.dm +++ b/code/modules/shuttle/syndicate.dm @@ -9,6 +9,7 @@ shuttleId = "syndicate" possible_destinations = "syndicate_away;syndicate_z5;syndicate_z3;syndicate_ne;syndicate_nw;syndicate_n;syndicate_se;syndicate_sw;syndicate_s;syndicate_custom" resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF + flags = NODECONSTRUCT var/challenge = FALSE var/moved = FALSE diff --git a/code/modules/shuttle/vox.dm b/code/modules/shuttle/vox.dm index 3899a23dee1..21076b7683a 100644 --- a/code/modules/shuttle/vox.dm +++ b/code/modules/shuttle/vox.dm @@ -4,6 +4,7 @@ shuttleId = "skipjack" possible_destinations = "skipjack_away;skipjack_ne;skipjack_nw;skipjack_se;skipjack_sw;skipjack_z5;skipjack_custom" resistance_flags = INDESTRUCTIBLE + flags = NODECONSTRUCT /obj/machinery/computer/camera_advanced/shuttle_docker/vox name = "skipjack navigation computer" @@ -16,4 +17,5 @@ x_offset = -10 y_offset = -10 resistance_flags = INDESTRUCTIBLE + flags = NODECONSTRUCT access_derelict = TRUE diff --git a/code/modules/spacepods/construction.dm b/code/modules/spacepods/construction.dm index a6a7ddb0927..eba600d883f 100644 --- a/code/modules/spacepods/construction.dm +++ b/code/modules/spacepods/construction.dm @@ -53,12 +53,12 @@ list( "desc" = "A crudely-wired pod frame.", state_prev = list( - "key" = /obj/item/wirecutters, + "key" = TOOL_WIRECUTTER, "vis_msg" = "{USER} cuts out the {HOLDER}'s wiring.", "self_msg" = "You remove the {HOLDER}'s wiring." ), state_next = list( - "key" = /obj/item/screwdriver, + "key" = TOOL_SCREWDRIVER, "vis_msg" = "{USER} adjusts the wiring.", "self_msg" = "You adjust the {HOLDER}'s wiring." ) @@ -67,7 +67,7 @@ list( "desc" = "A wired pod frame.", state_prev = list( - "key" = /obj/item/screwdriver, + "key" = TOOL_SCREWDRIVER, "vis_msg" = "{USER} unclips {HOLDER}'s wiring harnesses.", "self_msg" = "You unclip {HOLDER}'s wiring harnesses." ), @@ -82,7 +82,7 @@ list( "desc" = "A wired pod frame with a loose mainboard.", state_prev = list( - "key" = /obj/item/crowbar, + "key" = TOOL_CROWBAR, "vis_msg" = "{USER} pries out the mainboard.", "self_msg" = "You pry out the mainboard.", @@ -90,7 +90,7 @@ "amount" = 1 ), state_next = list( - "key" = /obj/item/screwdriver, + "key" = TOOL_SCREWDRIVER, "vis_msg" = "{USER} secures the mainboard.", "self_msg" = "You secure the mainboard." ) @@ -99,7 +99,7 @@ list( "desc" = "A wired pod frame with a secured mainboard.", state_prev = list( - "key" = /obj/item/screwdriver, + "key" = TOOL_SCREWDRIVER, "vis_msg" = "{USER} unsecures the mainboard.", "self_msg" = "You unscrew the mainboard from the {HOLDER}." ), @@ -115,7 +115,7 @@ list( "desc" = "A naked space pod with a loose core.", state_prev = list( - "key" = /obj/item/crowbar, + "key" = TOOL_CROWBAR, "vis_msg" = "{USER} delicately removes the core from the {HOLDER} with a crowbar.", "self_msg" = "You delicately remove the core from the {HOLDER} with a crowbar.", @@ -123,7 +123,7 @@ "amount" = 1 ), state_next = list( - "key" = /obj/item/wrench, + "key" = TOOL_WRENCH, "vis_msg" = "{USER} secures the core's bolts.", "self_msg" = "You secure the core's bolts." ) @@ -132,7 +132,7 @@ list( "desc" = "A naked space pod with an exposed core. How lewd.", state_prev = list( - "key" = /obj/item/wrench, + "key" = TOOL_WRENCH, "vis_msg" = "{USER} unsecures the {HOLDER}'s core.", "self_msg" = "You unsecure the {HOLDER}'s core." ), @@ -147,7 +147,7 @@ list( "desc" = "A space pod with loose bulkhead panelling exposed.", state_prev = list( - "key" = /obj/item/crowbar, + "key" = TOOL_CROWBAR, "vis_msg" = "{USER} pops the {HOLDER}'s bulkhead panelling loose.", "self_msg" = "You pop the {HOLDER}'s bulkhead panelling loose.", @@ -155,7 +155,7 @@ "amount" = 5, ), state_next = list( - "key" = /obj/item/wrench, + "key" = TOOL_WRENCH, "vis_msg" = "{USER} secures the {HOLDER}'s bulkhead panelling.", "self_msg" = "You secure the {HOLDER}'s bulkhead panelling." ) @@ -164,12 +164,12 @@ list( "desc" = "A space pod with unwelded bulkhead panelling exposed.", state_prev = list( - "key" = /obj/item/wrench, + "key" = TOOL_WRENCH, "vis_msg" = "{USER} unbolts the {HOLDER}'s bulkhead panelling.", "self_msg" = "You unbolt the {HOLDER}'s bulkhead panelling." ), state_next = list( - "key" = /obj/item/weldingtool, + "key" = TOOL_WELDER, "vis_msg" = "{USER} seals the {HOLDER}'s bulkhead panelling with a weld.", "self_msg" = "You seal the {HOLDER}'s bulkhead panelling with a weld." ) @@ -178,7 +178,7 @@ list( "desc" = "A space pod with sealed bulkhead panelling exposed.", state_prev = list( - "key" = /obj/item/weldingtool, + "key" = TOOL_WELDER, "vis_msg" = "{USER} cuts the {HOLDER}'s bulkhead panelling loose.", "self_msg" = "You cut the {HOLDER}'s bulkhead panelling loose." ), @@ -193,14 +193,14 @@ list( "desc" = "A space pod with unsecured armor.", state_prev = list( - "key" = /obj/item/crowbar, + "key" = TOOL_CROWBAR, "vis_msg" = "{USER} pries off {HOLDER}'s armor.", "self_msg" = "You pry off {HOLDER}'s armor.", "spawn" = /obj/item/pod_parts/armor, "amount" = 1 ), state_next = list( - "key" = /obj/item/wrench, + "key" = TOOL_WRENCH, "vis_msg" = "{USER} bolts down the {HOLDER}'s armor.", "self_msg" = "You bolt down the {HOLDER}'s armor." ) @@ -209,12 +209,12 @@ list( "desc" = "A space pod with unsecured armor.", state_prev = list( - "key" = /obj/item/wrench, + "key" = TOOL_WRENCH, "vis_msg" = "{USER} unsecures the {HOLDER}'s armor.", "self_msg" = "You unsecure the {HOLDER}'s armor." ), state_next = list( - "key" = /obj/item/weldingtool, + "key" = TOOL_WELDER, "vis_msg" = "{USER} welds the {HOLDER}'s armor.", "self_msg" = "You weld the {HOLDER}'s armor." ) diff --git a/code/modules/spacepods/equipment.dm b/code/modules/spacepods/equipment.dm index 8ca4d1be65c..5996b5c7603 100644 --- a/code/modules/spacepods/equipment.dm +++ b/code/modules/spacepods/equipment.dm @@ -156,16 +156,16 @@ icon_state = "pod_locator" enabled = 0 -/obj/item/spacepod_equipment/misc/tracker/attackby(obj/item/I as obj, mob/user as mob, params) - if(isscrewdriver(I)) - if(enabled) - enabled = 0 - user.show_message("You disable \the [src]'s power.") - return - enabled = 1 - user.show_message("You enable \the [src]'s power.") - else - return ..() +/obj/item/spacepod_equipment/misc/tracker/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(enabled) + enabled = 0 + user.show_message("You disable \the [src]'s power.") + return + enabled = 1 + user.show_message("You enable \the [src]'s power.") /* /////////////////////////////////////// diff --git a/code/modules/spacepods/spacepod.dm b/code/modules/spacepods/spacepod.dm index 32239466b82..5b0be539578 100644 --- a/code/modules/spacepods/spacepod.dm +++ b/code/modules/spacepods/spacepod.dm @@ -312,106 +312,109 @@ to_chat(M, mymessage) /obj/spacepod/attackby(obj/item/W as obj, mob/user as mob, params) - if(user.a_intent == INTENT_HARM) - ..() - deal_damage(W.force) - else - if(iscrowbar(W)) - if(!equipment_system.lock_system || unlocked || hatch_open) - hatch_open = !hatch_open - playsound(loc, W.usesound, 50, 1) - to_chat(user, "You [hatch_open ? "open" : "close"] the maintenance hatch.") - else - to_chat(user, "The hatch is locked shut!") + if(istype(W, /obj/item/stock_parts/cell)) + if(!hatch_open) + to_chat(user, "The maintenance hatch is closed!") return - if(istype(W, /obj/item/stock_parts/cell)) - if(!hatch_open) - to_chat(user, "The maintenance hatch is closed!") - return - if(battery) - to_chat(user, "The pod already has a battery.") - return - to_chat(user, "You insert [W] into the pod.") - user.drop_item(W) - battery = W - W.forceMove(src) + if(battery) + to_chat(user, "The pod already has a battery.") return - if(istype(W, /obj/item/spacepod_equipment)) - if(!hatch_open) - to_chat(user, "The maintenance hatch is closed!") - return - if(!equipment_system) - to_chat(user, "The pod has no equipment datum, yell at the coders") - return - if(istype(W, /obj/item/spacepod_equipment/weaponry)) - add_equipment(user, W, "weapon_system") - return - if(istype(W, /obj/item/spacepod_equipment/misc)) - add_equipment(user, W, "misc_system") - return - if(istype(W, /obj/item/spacepod_equipment/cargo)) - add_equipment(user, W, "cargo_system") - return - if(istype(W, /obj/item/spacepod_equipment/sec_cargo)) - add_equipment(user, W, "sec_cargo_system") - return - if(istype(W, /obj/item/spacepod_equipment/lock)) - add_equipment(user, W, "lock_system") - return - - if(istype(W, /obj/item/spacepod_key) && istype(equipment_system.lock_system, /obj/item/spacepod_equipment/lock/keyed)) - var/obj/item/spacepod_key/key = W - if(key.id == equipment_system.lock_system.id) - lock_pod() - return - else - to_chat(user, "This is the wrong key!") - return - - if(istype(W, /obj/item/weldingtool)) - if(!hatch_open) - to_chat(user, "You must open the maintenance hatch before attempting repairs.") - return - var/obj/item/weldingtool/WT = W - if(!WT.isOn()) - to_chat(user, "The welder must be on for this task.") - return - if(health < initial(health)) - to_chat(user, "You start welding the spacepod...") - playsound(loc, W.usesound, 50, 1) - if(do_after(user, 20 * W.toolspeed, target = src)) - if(!src || !WT.remove_fuel(3, user)) return - repair_damage(10) - to_chat(user, "You mend some [pick("dents","bumps","damage")] with [WT]") - return - to_chat(user, "[src] is fully repaired!") + to_chat(user, "You insert [W] into the pod.") + user.drop_item(W) + battery = W + W.forceMove(src) + return + else if(istype(W, /obj/item/spacepod_equipment)) + if(!hatch_open) + to_chat(user, "The maintenance hatch is closed!") + return + if(!equipment_system) + to_chat(user, "The pod has no equipment datum, yell at the coders") + return + if(istype(W, /obj/item/spacepod_equipment/weaponry)) + add_equipment(user, W, "weapon_system") + return + if(istype(W, /obj/item/spacepod_equipment/misc)) + add_equipment(user, W, "misc_system") + return + if(istype(W, /obj/item/spacepod_equipment/cargo)) + add_equipment(user, W, "cargo_system") + return + if(istype(W, /obj/item/spacepod_equipment/sec_cargo)) + add_equipment(user, W, "sec_cargo_system") + return + if(istype(W, /obj/item/spacepod_equipment/lock)) + add_equipment(user, W, "lock_system") return - if(istype(W, /obj/item/lock_buster)) - var/obj/item/lock_buster/L = W - if(L.on && equipment_system.lock_system) - user.visible_message(user, "[user] is drilling through the [src]'s lock!", - "You start drilling through the [src]'s lock!") - if(do_after(user, 100 * W.toolspeed, target = src)) - QDEL_NULL(equipment_system.lock_system) - unlocked = TRUE - user.visible_message(user, "[user] has destroyed the [src]'s lock!", - "You destroy the [src]'s lock!") - else - user.visible_message(user, "[user] fails to break through the [src]'s lock!", - "You were unable to break through the [src]'s lock!") - return - if(L.on && unlocked == FALSE) //The buster is on, we don't have a lock system, and the pod is still somehow locked, unlocking. + else if(istype(W, /obj/item/spacepod_key) && istype(equipment_system.lock_system, /obj/item/spacepod_equipment/lock/keyed)) + var/obj/item/spacepod_key/key = W + if(key.id == equipment_system.lock_system.id) + lock_pod() + return + else + to_chat(user, "This is the wrong key!") + return + + else if(istype(W, /obj/item/lock_buster)) + var/obj/item/lock_buster/L = W + if(L.on && equipment_system.lock_system) + user.visible_message(user, "[user] is drilling through the [src]'s lock!", + "You start drilling through the [src]'s lock!") + if(do_after(user, 100 * W.toolspeed, target = src)) + QDEL_NULL(equipment_system.lock_system) unlocked = TRUE - user.visible_message(user, "[user] repairs [src]'s doors with [L].", - "You repair [src]'s doors with [L].") - to_chat(user, "Turn the [L] on first.") + user.visible_message(user, "[user] has destroyed the [src]'s lock!", + "You destroy the [src]'s lock!") + else + user.visible_message(user, "[user] fails to break through the [src]'s lock!", + "You were unable to break through the [src]'s lock!") return + if(L.on && unlocked == FALSE) //The buster is on, we don't have a lock system, and the pod is still somehow locked, unlocking. + unlocked = TRUE + user.visible_message(user, "[user] repairs [src]'s doors with [L].", + "You repair [src]'s doors with [L].") + to_chat(user, "Turn the [L] on first.") + return - if(cargo_hold.storage_slots > 0 && !hatch_open && unlocked) // must be the last option as all items not listed prior will be stored - cargo_hold.attackby(W, user, params) + else if(cargo_hold.storage_slots > 0 && !hatch_open && unlocked) // must be the last option as all items not listed prior will be stored + cargo_hold.attackby(W, user, params) + else + if(user.a_intent == INTENT_HARM) + deal_damage(W.force) + return ..() -obj/spacepod/proc/add_equipment(mob/user, var/obj/item/spacepod_equipment/SPE, var/slot) +/obj/spacepod/crowbar_act(mob/user, obj/item/I) + if(user.a_intent == INTENT_HARM) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!equipment_system.lock_system || unlocked || hatch_open) + hatch_open = !hatch_open + to_chat(user, "You [hatch_open ? "open" : "close"] the maintenance hatch.") + else + to_chat(user, "The hatch is locked shut!") + +/obj/spacepod/welder_act(mob/user, obj/item/I) + if(user.a_intent == INTENT_HARM) + return + . = TRUE + if(!hatch_open) + to_chat(user, "You must open the maintenance hatch before attempting repairs.") + return + if(health >= initial(health)) + to_chat(user, "[src] is fully repaired!") + return + if(!I.tool_use_check(user, 0)) + return + to_chat(user, "You start welding the spacepod...") + if(I.use_tool(src, user, 20, 3, volume = I.tool_volume)) + repair_damage(10) + to_chat(user, "You mend some [pick("dents","bumps","damage")] with [I]") + + +/obj/spacepod/proc/add_equipment(mob/user, var/obj/item/spacepod_equipment/SPE, var/slot) if(equipment_system.vars[slot]) to_chat(user, "The pod already has a [slot], remove it first.") return diff --git a/code/modules/station_goals/dna_vault.dm b/code/modules/station_goals/dna_vault.dm index 5cc26bcca14..a55657fc724 100644 --- a/code/modules/station_goals/dna_vault.dm +++ b/code/modules/station_goals/dna_vault.dm @@ -110,6 +110,9 @@ var/list/non_simple_animals = typecacheof(list(/mob/living/carbon/human/monkey,/ //humans if(ishuman(target)) var/mob/living/carbon/human/H = target + if(NO_DNA in H.dna.species.species_traits) + to_chat(user, "This humanoid doesn't have DNA.") + return if(dna[H.dna.uni_identity]) to_chat(user, "Humanoid data already present in local storage.") return diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index c66d95df899..39c21bf1ee1 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -1,7 +1,7 @@ -//Procedures in this file: Gneric surgery steps -////////////////////////////////////////////////////////////////// +//Procedures in this file: Generic surgery steps +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // COMMON STEPS // -////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /datum/surgery_step/generic/ can_infect = 1 @@ -83,7 +83,7 @@ /datum/surgery_step/generic/clamp_bleeders/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) var/obj/item/organ/external/affected = target.get_organ(target_zone) - user.visible_message(" [user]'s hand slips, tearing blood vessals and causing massive bleeding in [target]'s [affected.name] with \the [tool]!", \ + user.visible_message(" [user]'s hand slips, tearing blood vessels and causing massive bleeding in [target]'s [affected.name] with \the [tool]!", \ " Your hand slips, tearing blood vessels and causing massive bleeding in [target]'s [affected.name] with \the [tool]!",) affected.receive_damage(10) return 0 @@ -237,7 +237,7 @@ /datum/surgery_step/generic/amputate/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message(" [user]'s hand slips, sawing through the bone in [target]'s [affected.name] with \the [tool]!", \ - " Your hand slips, sawwing through the bone in [target]'s [affected.name] with \the [tool]!") + " Your hand slips, sawing through the bone in [target]'s [affected.name] with \the [tool]!") affected.receive_damage(30) affected.fracture() return 0 diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index 840b2ed5749..6215bbe88bc 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -33,17 +33,18 @@ . = ..() . += "[src] is assembled in the [parent_organ == "r_arm" ? "right" : "left"] arm configuration. You can use a screwdriver to reassemble it." -/obj/item/organ/internal/cyberimp/arm/attackby(obj/item/I, mob/user, params) - if(isscrewdriver(I)) - if(parent_organ == "r_arm") - parent_organ = "l_arm" - else - parent_organ = "r_arm" - slot = parent_organ + "_device" - to_chat(user, "You modify [src] to be installed on the [parent_organ == "r_arm" ? "right" : "left"] arm.") - update_icon() +/obj/item/organ/internal/cyberimp/arm/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(parent_organ == "r_arm") + parent_organ = "l_arm" else - return ..() + parent_organ = "r_arm" + slot = parent_organ + "_device" + to_chat(user, "You modify [src] to be installed on the [parent_organ == "r_arm" ? "right" : "left"] arm.") + update_icon() + /obj/item/organ/internal/cyberimp/arm/remove(mob/living/carbon/M, special = 0) Retract() diff --git a/code/modules/surgery/organs/augments_eyes.dm b/code/modules/surgery/organs/augments_eyes.dm index 463911861c2..80dceea5048 100644 --- a/code/modules/surgery/organs/augments_eyes.dm +++ b/code/modules/surgery/organs/augments_eyes.dm @@ -12,12 +12,11 @@ var/see_invisible = 0 var/lighting_alpha - var/eye_colour = "#000000" + var/eye_colour = "#000000" // Should never be null var/old_eye_colour = "#000000" var/flash_protect = 0 var/aug_message = "Your vision is augmented!" - /obj/item/organ/internal/cyberimp/eyes/insert(var/mob/living/carbon/M, var/special = 0) ..() var/mob/living/carbon/human/H = M diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm index e9626a6b76d..fab2d0fd8a4 100644 --- a/code/modules/surgery/organs/augments_internal.dm +++ b/code/modules/surgery/organs/augments_internal.dm @@ -39,9 +39,9 @@ /obj/item/organ/internal/cyberimp/brain/anti_drop name = "Anti-drop implant" desc = "This cybernetic brain implant will allow you to force your hand muscles to contract, preventing item dropping. Twitch ear to toggle." - var/active = 0 - var/l_hand_ignore = 0 - var/r_hand_ignore = 0 + var/active = FALSE + var/l_hand_ignore = FALSE + var/r_hand_ignore = FALSE var/obj/item/l_hand_obj = null var/obj/item/r_hand_obj = null implant_color = "#DE7E00" @@ -56,17 +56,17 @@ r_hand_obj = owner.r_hand if(l_hand_obj) if(owner.l_hand.flags & NODROP) - l_hand_ignore = 1 + l_hand_ignore = TRUE else owner.l_hand.flags |= NODROP - l_hand_ignore = 0 + l_hand_ignore = FALSE if(r_hand_obj) if(owner.r_hand.flags & NODROP) - r_hand_ignore = 1 + r_hand_ignore = TRUE else owner.r_hand.flags |= NODROP - r_hand_ignore = 0 + r_hand_ignore = FALSE if(!l_hand_obj && !r_hand_obj) to_chat(owner, "You are not holding any items, your hands relax...") @@ -102,12 +102,15 @@ A = pick(oview(range)) L_item.throw_at(A, range, 2) to_chat(owner, "Your left arm spasms and throws the [L_item.name]!") + l_hand_obj = null if(R_item) A = pick(oview(range)) R_item.throw_at(A, range, 2) to_chat(owner, "Your right arm spasms and throws the [R_item.name]!") + r_hand_obj = null /obj/item/organ/internal/cyberimp/brain/anti_drop/proc/release_items() + active = FALSE if(!l_hand_ignore && l_hand_obj in owner.contents) l_hand_obj.flags ^= NODROP if(!r_hand_ignore && r_hand_obj in owner.contents) diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index fba2df57e8a..2973573bc2c 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -5,7 +5,7 @@ organ_tag = "eyes" parent_organ = "head" slot = "eyes" - var/eye_colour = "#000000" + var/eye_colour = "#000000" // Should never be null var/list/colourmatrix = null var/list/colourblind_matrix = MATRIX_GREYSCALE //Special colourblindness parameters. By default, it's black-and-white. var/list/replace_colours = LIST_GREYSCALE_REPLACE diff --git a/code/modules/surgery/organs/organ_external.dm b/code/modules/surgery/organs/organ_external.dm index 2c891632770..305c08ff17e 100644 --- a/code/modules/surgery/organs/organ_external.dm +++ b/code/modules/surgery/organs/organ_external.dm @@ -47,7 +47,7 @@ var/damage_msg = "You feel an intense pain" var/broken_description - var/open = 0 + var/open = 0 // If the body part has an open incision from surgery var/sabotaged = 0 //If a prosthetic limb is emagged, it will detonate when it fails. var/encased // Needs to be opened with a saw to access the organs. @@ -404,7 +404,7 @@ Note that amputating the affected organ does in fact remove the infection from t fracture() /obj/item/organ/external/proc/check_for_internal_bleeding(damage) - if(NO_BLOOD in owner.dna.species.species_traits) + if(owner && NO_BLOOD in owner.dna.species.species_traits) return var/local_damage = brute_dam + damage if(damage > 15 && local_damage > 30 && prob(damage) && !is_robotic()) diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 98ed11672fb..25f87d71104 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -283,7 +283,7 @@ /obj/item/organ/internal/honktumor/cursed/on_life() //No matter what you do, no matter who you are, no matter where you go, you're always going to be a fat, stuttering dimwit. ..() - owner.setBrainLoss(80) + owner.setBrainLoss(80, use_brain_mod = FALSE) owner.set_nutrition(9000) owner.overeatduration = 9000 diff --git a/code/modules/surgery/rig_removal.dm b/code/modules/surgery/rig_removal.dm index 1fbd3e528a3..de15eacf8f3 100644 --- a/code/modules/surgery/rig_removal.dm +++ b/code/modules/surgery/rig_removal.dm @@ -31,10 +31,11 @@ /datum/surgery_step/hardsuit/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!istype(target)) return 0 - if(istype(tool,/obj/item/weldingtool)) - var/obj/item/weldingtool/welder = tool - if(!welder.isOn() || !welder.remove_fuel(1,user)) - return 0 + if(tool.tool_behaviour == TOOL_WELDER) + if(!tool.tool_use_check(user, 0)) + return + if(!tool.use(1)) + return return (target_zone == "chest") && istype(target.back, /obj/item/rig) && (target.back.flags&NODROP) /datum/surgery_step/rigsuit/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm index c3198b961be..31164aaf54e 100644 --- a/code/modules/surgery/robotics.dm +++ b/code/modules/surgery/robotics.dm @@ -225,9 +225,8 @@ if(!(affected.brute_dam > 0 || affected.disfigured)) to_chat(user, "The [affected] does not require welding repair!") return -1 - if(istype(tool,/obj/item/weldingtool)) - var/obj/item/weldingtool/welder = tool - if(!welder.isOn() || !welder.remove_fuel(1,user)) + if(tool.tool_behaviour == TOOL_WELDER) + if(!tool.use(1)) return -1 user.visible_message("[user] begins to patch damage to [target]'s [affected.name]'s support structure with \the [tool]." , \ "You begin to patch damage to [target]'s [affected.name]'s support structure with \the [tool].") diff --git a/code/modules/telesci/telepad.dm b/code/modules/telesci/telepad.dm index 581df91e267..1ec94634b47 100644 --- a/code/modules/telesci/telepad.dm +++ b/code/modules/telesci/telepad.dm @@ -37,23 +37,28 @@ efficiency = E /obj/machinery/telepad/attackby(obj/item/I, mob/user, params) - if(default_deconstruction_screwdriver(user, "pad-idle-o", "pad-idle", I)) - return - - if(panel_open) - if(istype(I, /obj/item/multitool)) - var/obj/item/multitool/M = I - M.buffer = src - to_chat(user, "You save the data in the [I.name]'s buffer.") - return - if(exchange_parts(user, I)) return - - if(default_deconstruction_crowbar(I)) - return return ..() +/obj/machinery/telepad/screwdriver_act(mob/user, obj/item/I) + . = TRUE + default_deconstruction_screwdriver(user, "pad-idle-o", "pad-idle", I) + +/obj/machinery/telepad/multitool_act(mob/user, obj/item/I) + if(!panel_open) + return + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + return + if(!I.multitool_check_buffer(user)) + return + var/obj/item/multitool/M = I + M.set_multitool_buffer(user, src) + +/obj/machinery/telepad/crowbar_act(mob/user, obj/item/I) + . = TRUE + default_deconstruction_crowbar(user, I) //CARGO TELEPAD// /obj/machinery/telepad_cargo @@ -67,32 +72,23 @@ active_power_usage = 500 var/stage = 0 -/obj/machinery/telepad_cargo/attackby(obj/item/I, mob/user, params) - if(iswrench(I)) - playsound(src, I.usesound, 50, 1) - if(anchored) - anchored = FALSE - to_chat(user, " The [src] can now be moved.") - else if(!anchored) - anchored = TRUE - to_chat(user, " The [src] is now secured.") +/obj/machinery/telepad_cargo/crowbar_act(mob/living/user, obj/item/I) + if(stage != 1) return - if(isscrewdriver(I)) - if(stage == 0) - playsound(src, I.usesound, 50, 1) - to_chat(user, " You unscrew the telepad's tracking beacon.") - stage = 1 - else if(stage == 1) - playsound(src, I.usesound, 50, 1) - to_chat(user, " You screw in the telepad's tracking beacon.") - stage = 0 + . = TRUE + default_deconstruction_crowbar(user, I) + +/obj/machinery/telepad_cargo/screwdriver_act(mob/user, obj/item/I) + . = TRUE + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return - if(iswelder(I) && stage == 1) - playsound(src, I.usesound, 50, 1) - to_chat(user, " You disassemble the telepad.") - deconstruct(TRUE) - return - return ..() + to_chat(user, " You [stage ? "screw in" : "unscrew"] the telepad's tracking beacon.") + stage = !stage + +/obj/machinery/telepad_cargo/wrench_act(mob/user, obj/item/I) + . = TRUE + default_unfasten_wrench(user, I) + /obj/machinery/telepad_cargo/deconstruct(disassembled = TRUE) if(!(flags & NODECONSTRUCT)) diff --git a/config/example/config.txt b/config/example/config.txt index 7dfdc1e413a..18c280f6141 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -114,7 +114,6 @@ PROBABILITY RAGINMAGES 0 PROBABILITY METEOR 0 PROBABILITY HEIST 0 PROBABILITY VAMPIRE 3 -PROBABILITY NATIONS 0 PROBABILITY EXTENDED 2 PROBABILITY NUCLEAR 3 PROBABILITY ABDUCTION 0 @@ -213,6 +212,9 @@ GUEST_BAN ## URL to use to link forum accounts. If not set, no link option will be offered. #FORUM_LINK_URL https://example.com/link.php?token= +## URL to use for admins accessing the web-based tools menu +#FORUM_PLAYERINFO_URL https://example.com/info.php?ckey= + ## Comment to disable checking for the cid randomizer dll. (disabled if database isn't enabled or connected) CHECK_RANDOMIZER @@ -237,6 +239,9 @@ CHECK_RANDOMIZER ## Discord address # DISCORDURL http://example.org +## Discord address (forum-based invite) +# DISCORDFORUMURL http://example.org + ## Donations address # DONATIONSURL http://example.org @@ -451,4 +456,4 @@ DISABLE_HIGH_POP_MC_MODE_AMOUNT 60 #START_NOW_CONFIRMATION ## If uncommented, all gamemodes will respect the number of required players. Defaults to no. -#ENABLE_GAMEMODE_PLAYER_LIMIT \ No newline at end of file +#ENABLE_GAMEMODE_PLAYER_LIMIT diff --git a/config/example/dbconfig.txt b/config/example/dbconfig.txt index ad859d92543..b1113fb625d 100644 --- a/config/example/dbconfig.txt +++ b/config/example/dbconfig.txt @@ -9,7 +9,7 @@ ## This value must be set to the version of the paradise schema in use. ## If this value does not match, the SQL database will not be loaded and an error will be generated. ## Roundstart will be delayed. -DB_VERSION 9 +DB_VERSION 11 ## Server the MySQL database can be found at. # Examples: localhost, 200.135.5.43, www.mysqldb.com, etc. diff --git a/config/example/motd.txt b/config/example/motd.txt index 106be771704..f39e579a6f7 100644 --- a/config/example/motd.txt +++ b/config/example/motd.txt @@ -1,5 +1,5 @@

    Welcome to Space Station 13!

    --This server is running Paradise's modification of the Baystation 12 and /tg/station13 SS13 code. +-This server is running Paradise's modification of the Baystation 12 and /tg/station13 SS13 code.

    GitHub: https://github.com/ParadiseSS13/Paradise diff --git a/config/example/rules.html b/config/example/rules.html index c7a717aca63..ef37effcea4 100644 --- a/config/example/rules.html +++ b/config/example/rules.html @@ -4,7 +4,7 @@ diff --git a/goon/browserassets/js/browserOutput.js b/goon/browserassets/js/browserOutput.js index 094e8258562..40a69245188 100644 --- a/goon/browserassets/js/browserOutput.js +++ b/goon/browserassets/js/browserOutput.js @@ -416,7 +416,8 @@ function handleClientData(ckey, ip, compid) { } } - if (opts.clientData.length >= opts.clientDataLimit) { + //Lets make sure we obey our limit (can connect from server with higher limit) + while (opts.clientData.length >= opts.clientDataLimit) { opts.clientData.shift(); } } else { @@ -1005,7 +1006,7 @@ $(function() { '
    ' + '
    Choose up to '+opts.highlightLimit+' strings that will highlight the line when they appear in chat.
    '+ 'Enable Regex'+ - '
    See here for details
    ' + + '
    See here for details
    ' + '
    ' + termInputs + '
    next_time_to_clear) + next_time_to_clear = world.time + (3 SECONDS) + total_checks = 0 + total_checks += 1 + if(total_checks > SPAM_TRIGGER_AUTOMUTE) + message_admins("[key_name(owner)] kicked for goonchat topic spam") + qdel(owner) + return + if(!cookie) return @@ -145,13 +162,21 @@ var/list/chatResources = list( if(connData && islist(connData) && connData.len > 0 && connData["connData"]) connectionHistory = connData["connData"] var/list/found = new() + if(connectionHistory.len > MAX_COOKIE_LENGTH) + message_admins("[key_name(src.owner)] was kicked for an invalid ban cookie)") + qdel(owner) + return for(var/i = connectionHistory.len; i >= 1; i--) + if(QDELETED(owner)) + //he got cleaned up before we were done + return var/list/row = connectionHistory[i] if(!row || row.len < 3 || !(row["ckey"] && row["compid"] && row["ip"])) return - if(world.IsBanned(row["ckey"], row["ip"], row["compid"], FALSE)) + if(world.IsBanned(key=row["ckey"], address=row["ip"], computer_id=row["compid"], type=null, check_ipintel=FALSE)) found = row break + CHECK_TICK //Add autoban using the DB_ban_record function //Uh oh this fucker has a history of playing on a banned account!! if (found.len > 0) @@ -284,3 +309,5 @@ var/to_chat_src to_chat_immediate(target, message, flag) return SSchat.queue(target, message, flag) + +#undef MAX_COOKIE_LENGTH \ No newline at end of file diff --git a/html/changelog.html b/html/changelog.html index e16a576f43d..3ffad2b6c96 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -25,8 +25,7 @@
    Paradise Station
    -

    - Visit our Discord channel:-Click Here- +

    diff --git a/html/changelogs/AutoChangeLog-pr-12571.yml b/html/changelogs/AutoChangeLog-pr-12571.yml new file mode 100644 index 00000000000..d9d46a5766f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12571.yml @@ -0,0 +1,5 @@ +author: "JKnutson101" +delete-after: True +changes: + - tweak: "Combined the Rite of Tribute and Rite of Enlightenment into one Rite of Offering." + - bugfix: "Sacrificing now properly puts victims that have at one point had CKeys into soul stones, or polls dead-chat to do so." diff --git a/html/changelogs/AutoChangeLog-pr-12596.yml b/html/changelogs/AutoChangeLog-pr-12596.yml new file mode 100644 index 00000000000..ca0b0e32f0d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12596.yml @@ -0,0 +1,6 @@ +author: "Ionward" +delete-after: True +changes: + - tweak: "Grey, Tajaran, Unathi, and Vulpkanin now properly have species specific fits for soft space suits." + - tweak: "Vox can now wear soft space suits, such as EVA (Clown and Mime included), NASA Void, and Syndicate suits." + - imageadd: "Added Vox soft suit sprites." diff --git a/html/changelogs/AutoChangeLog-pr-12600.yml b/html/changelogs/AutoChangeLog-pr-12600.yml new file mode 100644 index 00000000000..0b84030ed0a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12600.yml @@ -0,0 +1,5 @@ +author: "SteelSlayer" +delete-after: True +changes: + - bugfix: "Fixes the \"List SSDs and AFKs panel\" showing everyone as the target of an assassinate objective" + - bugfix: "The global objectives list is now viewable in the MC Globals menu" diff --git a/html/changelogs/AutoChangeLog-pr-12717.yml b/html/changelogs/AutoChangeLog-pr-12717.yml new file mode 100644 index 00000000000..6f11a3b38d0 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12717.yml @@ -0,0 +1,5 @@ +author: "moxian" +delete-after: True +changes: + - bugfix: "being in a locker no longer interferes with tracking implant tracking" + - bugfix: "locator no longer locates tracking implants on other z levels." diff --git a/html/changelogs/AutoChangeLog-pr-12720.yml b/html/changelogs/AutoChangeLog-pr-12720.yml new file mode 100644 index 00000000000..0efc114b24e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12720.yml @@ -0,0 +1,4 @@ +author: "moxian" +delete-after: True +changes: + - bugfix: "fixed singulo being unable to expand when placed next to containment wall" diff --git a/html/changelogs/AutoChangeLog-pr-12725.yml b/html/changelogs/AutoChangeLog-pr-12725.yml new file mode 100644 index 00000000000..24b8ec37da8 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12725.yml @@ -0,0 +1,4 @@ +author: "TDSSS" +delete-after: True +changes: + - bugfix: "blobbernaut vision blur now clears as intended." diff --git a/html/changelogs/AutoChangeLog-pr-12740.yml b/html/changelogs/AutoChangeLog-pr-12740.yml new file mode 100644 index 00000000000..b2e1d3fff39 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12740.yml @@ -0,0 +1,4 @@ +author: "Drakeven" +delete-after: True +changes: + - bugfix: "Fixed mislabeled traitor and mindslave special role." diff --git a/html/changelogs/AutoChangeLog-pr-12747.yml b/html/changelogs/AutoChangeLog-pr-12747.yml new file mode 100644 index 00000000000..ca9e96e84c1 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12747.yml @@ -0,0 +1,5 @@ +author: "Cazdon" +delete-after: True +changes: + - bugfix: "Admin Roles no longer appear on manifest." + - tweak: "Central Command PDA's no longer appear on the messenger list." diff --git a/html/changelogs/AutoChangeLog-pr-12751.yml b/html/changelogs/AutoChangeLog-pr-12751.yml new file mode 100644 index 00000000000..1dc7c27f527 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12751.yml @@ -0,0 +1,4 @@ +author: "TDSSS" +delete-after: True +changes: + - bugfix: "fixed a bug preventing ticket system from working under some circumstances." diff --git a/html/changelogs/AutoChangeLog-pr-12756.yml b/html/changelogs/AutoChangeLog-pr-12756.yml new file mode 100644 index 00000000000..50e5e5e4bd9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12756.yml @@ -0,0 +1,4 @@ +author: "SteelSlayer" +delete-after: True +changes: + - bugfix: "Reverts some terrible changes that are causing some bugs with traitors" diff --git a/html/changelogs/AutoChangeLog-pr-12757.yml b/html/changelogs/AutoChangeLog-pr-12757.yml new file mode 100644 index 00000000000..9cba05e588f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12757.yml @@ -0,0 +1,4 @@ +author: "VeteranKyl" +delete-after: True +changes: + - bugfix: "DNA Samplers now check if the target species has DNA." diff --git a/html/changelogs/AutoChangeLog-pr-12760.yml b/html/changelogs/AutoChangeLog-pr-12760.yml new file mode 100644 index 00000000000..92600e6ed76 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12760.yml @@ -0,0 +1,4 @@ +author: "SteelSlayer" +delete-after: True +changes: + - bugfix: "Fixes AIs with the combat module not being able to hack APCs" diff --git a/html/changelogs/AutoChangeLog-pr-12761.yml b/html/changelogs/AutoChangeLog-pr-12761.yml new file mode 100644 index 00000000000..7355e826a7b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12761.yml @@ -0,0 +1,4 @@ +author: "VeteranKyl" +delete-after: True +changes: + - bugfix: "Fixed the envenomed blob's spore toxin not causing harm." diff --git a/html/changelogs/AutoChangeLog-pr-12765.yml b/html/changelogs/AutoChangeLog-pr-12765.yml new file mode 100644 index 00000000000..b1ee7b0dd05 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12765.yml @@ -0,0 +1,4 @@ +author: "Cazdon" +delete-after: True +changes: + - bugfix: "Potential Convertee's being unable to be converted." diff --git a/html/templates/header.html b/html/templates/header.html index fac4d7b280a..5d499bbc347 100644 --- a/html/templates/header.html +++ b/html/templates/header.html @@ -25,7 +25,7 @@
    Paradise Station
    -

    +

    Visit our Discord channel:-Click Here- diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi index c0c259af7ac..549304a43f3 100644 Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ diff --git a/icons/mob/inhands/clothing_lefthand.dmi b/icons/mob/inhands/clothing_lefthand.dmi index 745dd19aac7..69e602fc652 100644 Binary files a/icons/mob/inhands/clothing_lefthand.dmi and b/icons/mob/inhands/clothing_lefthand.dmi differ diff --git a/icons/mob/inhands/clothing_righthand.dmi b/icons/mob/inhands/clothing_righthand.dmi index e4e9fc0f859..3b62b05b314 100644 Binary files a/icons/mob/inhands/clothing_righthand.dmi and b/icons/mob/inhands/clothing_righthand.dmi differ diff --git a/icons/mob/species/drask/eyes.dmi b/icons/mob/species/drask/eyes.dmi index 818c719a541..92b8d7c2190 100644 Binary files a/icons/mob/species/drask/eyes.dmi and b/icons/mob/species/drask/eyes.dmi differ diff --git a/icons/mob/species/drask/uniform.dmi b/icons/mob/species/drask/uniform.dmi index 0828c290e05..25cfb51013c 100644 Binary files a/icons/mob/species/drask/uniform.dmi and b/icons/mob/species/drask/uniform.dmi differ diff --git a/icons/mob/species/grey/eyes.dmi b/icons/mob/species/grey/eyes.dmi index 937474d97dc..c3914dfd0be 100644 Binary files a/icons/mob/species/grey/eyes.dmi and b/icons/mob/species/grey/eyes.dmi differ diff --git a/icons/mob/species/grey/uniform.dmi b/icons/mob/species/grey/uniform.dmi index 1636097f72e..c956187ffa1 100644 Binary files a/icons/mob/species/grey/uniform.dmi and b/icons/mob/species/grey/uniform.dmi differ diff --git a/icons/mob/species/vox/eyes.dmi b/icons/mob/species/vox/eyes.dmi index 3e3705d2a90..dfa565dd2a7 100644 Binary files a/icons/mob/species/vox/eyes.dmi and b/icons/mob/species/vox/eyes.dmi differ diff --git a/icons/mob/species/vox/helmet.dmi b/icons/mob/species/vox/helmet.dmi index 67fafc2b51a..7aba8b0d3d8 100644 Binary files a/icons/mob/species/vox/helmet.dmi and b/icons/mob/species/vox/helmet.dmi differ diff --git a/icons/mob/species/vox/suit.dmi b/icons/mob/species/vox/suit.dmi index 07c7bf5d415..467dcd713aa 100644 Binary files a/icons/mob/species/vox/suit.dmi and b/icons/mob/species/vox/suit.dmi differ diff --git a/icons/mob/species/vox/uniform.dmi b/icons/mob/species/vox/uniform.dmi index 6f050370f7c..3eb4fec6f6f 100644 Binary files a/icons/mob/species/vox/uniform.dmi and b/icons/mob/species/vox/uniform.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 9bcabb11e78..6c622704fc7 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi index b67023a9935..1e185efd9c5 100644 Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi index 15a4adb9f41..bb7a1ce9188 100644 Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ diff --git a/icons/obj/toy.dmi b/icons/obj/toy.dmi index 17ebf4c9219..511b578ad4a 100644 Binary files a/icons/obj/toy.dmi and b/icons/obj/toy.dmi differ diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi index 2265194d678..a612d889222 100644 Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ diff --git a/interface/interface.dm b/interface/interface.dm index 8edded38e93..4a140769f18 100644 --- a/interface/interface.dm +++ b/interface/interface.dm @@ -47,9 +47,10 @@ set desc = "Visit the forum." set hidden = 1 if(config.forumurl) - if(alert("This will open the forum in your browser. Are you sure?",,"Yes","No")=="No") - return - src << link(config.forumurl) + if(alert("Open the forum in your browser?",,"Yes","No")=="Yes") + if(config.forum_link_url && prefs && !prefs.fuid) + link_forum_account() + src << link(config.forumurl) else to_chat(src, "The forum URL is not set in the server configuration.") @@ -79,13 +80,17 @@ set name = "Discord" set desc = "Join our Discord server." set hidden = 1 - if(config.discordurl) - if(alert("This will invite you to our Discord server. Are you sure?",,"Yes","No")=="No") - return - src << link(config.discordurl) - else + + var/durl = config.discordurl + if(config.forum_link_url && prefs && prefs.fuid && config.discordforumurl) + durl = config.discordforumurl + if(!durl) to_chat(src, "The Discord URL is not set in the server configuration.") - + return + if(alert("This will invite you to our Discord server. Are you sure?",,"Yes","No")=="No") + return + src << link(durl) + /client/verb/donate() set name = "Donate" set desc = "Donate to help with hosting costs." @@ -96,7 +101,7 @@ src << link(config.donationsurl) else to_chat(src, "The rules URL is not set in the server configuration.") - + /client/verb/hotkeys_help() set name = "Hotkey Help" set category = "OOC" diff --git a/nano/package-lock.json b/nano/package-lock.json new file mode 100644 index 00000000000..e32e80ce187 --- /dev/null +++ b/nano/package-lock.json @@ -0,0 +1,6195 @@ +{ + "name": "nanoui", + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@gulp-sourcemaps/identity-map": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", + "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", + "dev": true, + "requires": { + "acorn": "^5.0.3", + "css": "^2.2.1", + "normalize-path": "^2.1.1", + "source-map": "^0.6.0", + "through2": "^2.0.3" + } + }, + "@gulp-sourcemaps/map-sources": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", + "dev": true, + "requires": { + "normalize-path": "^2.0.1", + "through2": "^2.0.3" + } + }, + "@webassemblyjs/ast": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", + "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", + "requires": { + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", + "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", + "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", + "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==" + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", + "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", + "requires": { + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", + "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==" + }, + "@webassemblyjs/helper-module-context": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", + "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "mamacro": "^0.0.3" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", + "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", + "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", + "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", + "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", + "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", + "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/helper-wasm-section": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-opt": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", + "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", + "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", + "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", + "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/floating-point-hex-parser": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-code-frame": "1.8.5", + "@webassemblyjs/helper-fsm": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", + "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "accord": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/accord/-/accord-0.29.0.tgz", + "integrity": "sha512-3OOR92FTc2p5/EcOzPcXp+Cbo+3C15nV9RXHlOUBCBpHhcB+0frbSNR9ehED/o7sTcyGVtqGJpguToEdlXhD0w==", + "dev": true, + "requires": { + "convert-source-map": "^1.5.0", + "glob": "^7.0.5", + "indx": "^0.2.3", + "lodash.clone": "^4.3.2", + "lodash.defaults": "^4.0.1", + "lodash.flatten": "^4.2.0", + "lodash.merge": "^4.4.0", + "lodash.partialright": "^4.1.4", + "lodash.pick": "^4.2.1", + "lodash.uniq": "^4.3.0", + "resolve": "^1.5.0", + "semver": "^5.3.0", + "uglify-js": "^2.8.22", + "when": "^3.7.8" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + } + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + } + } + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "ajv": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==" + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "optional": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "optional": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" + }, + "async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "dev": true, + "requires": { + "async-done": "^1.2.2" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "optional": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "autoprefixer": { + "version": "8.6.5", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-8.6.5.tgz", + "integrity": "sha512-PLWJN3Xo/rycNkx+mp8iBDMTm3FeWe4VmYaZDSqL5QQB9sLsQkG5k8n+LNDFnhh9kdq2K+egL/icpctOmDHwig==", + "dev": true, + "requires": { + "browserslist": "^3.2.8", + "caniuse-lite": "^1.0.30000864", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^6.0.23", + "postcss-value-parser": "^3.2.3" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "optional": true + }, + "aws4": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", + "optional": true + }, + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "dev": true, + "requires": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" + }, + "binaryextensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.2.0.tgz", + "integrity": "sha512-bHhs98rj/7i/RZpCSJ3uk55pLXOItjIrh2sRQZSM6OoktScX+LxJzvlU+FELp9j3TdcddTmmYArLSGptCTwjuw==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "cacache": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", + "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + }, + "dependencies": { + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001025", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001025.tgz", + "integrity": "sha512-SKyFdHYfXUZf5V85+PJgLYyit27q4wgvZuf8QTOk1osbypcROihMBlx9GRar2/pIcKH2r4OehdlBr9x6PXetAQ==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "optional": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + } + } + }, + "chownr": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", + "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==" + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "clean-css": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", + "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", + "requires": { + "source-map": "~0.6.0" + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "dev": true, + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/color/-/color-0.10.1.tgz", + "integrity": "sha1-wEGI34KiCd3rzOzazT7DIPGTc58=", + "dev": true, + "requires": { + "color-convert": "^0.5.3", + "color-string": "^0.3.0" + }, + "dependencies": { + "color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=", + "dev": true + } + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-string": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", + "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", + "dev": true, + "requires": { + "color-name": "^1.0.0" + } + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + } + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "copy-props": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "dev": true, + "requires": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + } + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "debug-fabulous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", + "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", + "dev": true, + "requires": { + "debug": "3.X", + "memoizee": "0.4.X", + "object-assign": "4.X" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "requires": { + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" + }, + "domurl": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domurl/-/domurl-2.3.0.tgz", + "integrity": "sha512-KoPGBykwI0AnDjWuEz3SQECab4FbwvE/1CJk1qTBGiIdyquCFRLs0eldfl6ESrpSKd1GGjMnzS2g7+Xl12obqg==" + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "optional": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "editions": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", + "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.345", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.345.tgz", + "integrity": "sha512-f8nx53+Z9Y+SPWGg3YdHrbYYfIJAtbUjpFfW4X1RwTZ94iUG7geg9tV8HqzAXX7XTNgyWgAFvce4yce8ZKxKmg==", + "dev": true + }, + "elliptic": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", + "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz", + "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==", + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es5-shim": { + "version": "4.5.13", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.13.tgz", + "integrity": "sha512-xi6hh6gsvDE0MaW4Vp1lgNEBpVcCXRWfPXj5egDvtgLz4L9MEvNwYEMdJH+JJinWkwa8c3c3o5HduV7dB/e1Hw==" + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "events": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", + "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + } + } + }, + "filter-gradient": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/filter-gradient/-/filter-gradient-1.0.1.tgz", + "integrity": "sha1-ikFRiyIoQ1H6ymNqb9sba5BMogc=", + "dev": true, + "requires": { + "color": "^0.10.1" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "font-awesome": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", + "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "optional": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "optional": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", + "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1", + "node-pre-gyp": "*" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.3", + "bundled": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.7", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.6", + "bundled": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "bundled": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "minipass": { + "version": "2.9.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "needle": { + "version": "2.4.0", + "bundled": true, + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "bundled": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.7", + "bundled": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.7.1", + "bundled": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "optional": true + }, + "semver": { + "version": "5.7.1", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "4.4.13", + "bundled": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "yallist": { + "version": "3.1.1", + "bundled": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + } + }, + "glob-watcher": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", + "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "object.defaults": "^1.1.0" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" + }, + "gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "requires": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "dependencies": { + "gulp-cli": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.2.0.tgz", + "integrity": "sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.1.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.0.1", + "yargs": "^7.1.0" + } + } + } + }, + "gulp-clean-css": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/gulp-clean-css/-/gulp-clean-css-3.10.0.tgz", + "integrity": "sha512-7Isf9Y690o/Q5MVjEylH1H7L8WeZ89woW7DnhD5unTintOdZb67KdOayRgp9trUFo+f9UyJtuatV42e/+kghPg==", + "requires": { + "clean-css": "4.2.1", + "plugin-error": "1.0.1", + "through2": "2.0.3", + "vinyl-sourcemaps-apply": "0.2.1" + } + }, + "gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", + "dev": true, + "requires": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + } + }, + "gulp-less": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/gulp-less/-/gulp-less-4.0.1.tgz", + "integrity": "sha512-hmM2k0FfQp7Ptm3ZaqO2CkMX3hqpiIOn4OHtuSsCeFym63F7oWlEua5v6u1cIjVUKYsVIs9zPg9vbqTEb/udpA==", + "dev": true, + "requires": { + "accord": "^0.29.0", + "less": "2.6.x || ^3.7.1", + "object-assign": "^4.0.1", + "plugin-error": "^0.1.2", + "replace-ext": "^1.0.0", + "through2": "^2.0.0", + "vinyl-sourcemaps-apply": "^0.2.0" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "^1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + } + } + } + }, + "gulp-order": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gulp-order/-/gulp-order-1.2.0.tgz", + "integrity": "sha512-RduLhxbEye1NT6fnvev3792VUsZA8F+5zRFczAgpOSELz587Fv1Nn7l4ZiaiQzFPV7aECh1WRc2dPWjjcxCa0g==", + "dev": true, + "requires": { + "minimatch": "~3.0.4", + "stable": "~0.1.8", + "through": "~2.3.8" + } + }, + "gulp-postcss": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/gulp-postcss/-/gulp-postcss-8.0.0.tgz", + "integrity": "sha512-Wtl6vH7a+8IS/fU5W9IbOpcaLqKxd5L1DUOzaPmlnCbX1CrG0aWdwVnC3Spn8th0m8D59YbysV5zPUe1n/GJYg==", + "dev": true, + "requires": { + "fancy-log": "^1.3.2", + "plugin-error": "^1.0.1", + "postcss": "^7.0.2", + "postcss-load-config": "^2.0.0", + "vinyl-sourcemaps-apply": "^0.2.1" + } + }, + "gulp-replace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.0.0.tgz", + "integrity": "sha512-lgdmrFSI1SdhNMXZQbrC75MOl1UjYWlOWNbNRnz+F/KHmgxt3l6XstBoAYIdadwETFyG/6i+vWUSCawdC3pqOw==", + "dev": true, + "requires": { + "istextorbinary": "2.2.1", + "readable-stream": "^2.0.1", + "replacestream": "^4.0.0" + } + }, + "gulp-sourcemaps": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.5.tgz", + "integrity": "sha512-SYLBRzPTew8T5Suh2U8jCSDKY+4NARua4aqjj8HOysBh2tSgT9u4jc1FYirAdPx1akUxxDeK++fqw6Jg0LkQRg==", + "dev": true, + "requires": { + "@gulp-sourcemaps/identity-map": "1.X", + "@gulp-sourcemaps/map-sources": "1.X", + "acorn": "5.X", + "convert-source-map": "1.X", + "css": "2.X", + "debug-fabulous": "1.X", + "detect-newline": "2.X", + "graceful-fs": "4.X", + "source-map": "~0.6.0", + "strip-bom-string": "1.X", + "through2": "2.X" + } + }, + "gulp-uglify": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.2.tgz", + "integrity": "sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg==", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "extend-shallow": "^3.0.2", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "isobject": "^3.0.1", + "make-error-cause": "^1.1.1", + "safe-buffer": "^5.1.2", + "through2": "^2.0.0", + "uglify-js": "^3.0.5", + "vinyl-sourcemaps-apply": "^0.2.0" + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "^1.0.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "optional": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "optional": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", + "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", + "dev": true + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "optional": true + }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "dev": true, + "requires": { + "import-from": "^2.1.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "indx": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/indx/-/indx-0.2.3.tgz", + "integrity": "sha1-Fdz1bunPZcAjTFE8J/vVgOcPvFA=", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "optional": true + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "optional": true + }, + "istextorbinary": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", + "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", + "dev": true, + "requires": { + "binaryextensions": "2", + "editions": "^1.3.3", + "textextensions": "2" + } + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "optional": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "optional": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "just-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", + "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" + } + }, + "less": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/less/-/less-3.11.0.tgz", + "integrity": "sha512-dAui5qzfxuWY7BIEt9/gy5EbDhwDb44rqaIUFYeu8wEE8huMZ/PzB+gNFONEG5DUPrOrOGcAjGeYVg6AFiA9KQ==", + "requires": { + "clone": "^2.1.2", + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "mime": "^1.4.1", + "mkdirp": "^0.5.0", + "promise": "^7.1.1", + "request": "^2.83.0", + "source-map": "~0.6.0" + } + }, + "less-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-5.0.0.tgz", + "integrity": "sha512-bquCU89mO/yWLaUq0Clk7qCsKhsF/TZpJUzETRvJa9KSVEL9SO3ovCvdEHISBhrC81OwC8QSVX7E0bzElZj9cg==", + "requires": { + "clone": "^2.1.1", + "loader-utils": "^1.1.0", + "pify": "^4.0.1" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } + } + }, + "less-plugin-autoprefix": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/less-plugin-autoprefix/-/less-plugin-autoprefix-2.0.0.tgz", + "integrity": "sha512-UktaMtHAhCVTIQxjlceo1MiiQiUZws7gi3hfcpxkCLn1CJdVdlRGCb4n1/M64hniw2DLd7YzOl7ojshs1tWYcQ==", + "dev": true, + "requires": { + "autoprefixer": "^8.6.3", + "postcss": "^6.0.22" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==" + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + } + } + }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "dev": true + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.partialright": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.partialright/-/lodash.partialright-4.2.1.tgz", + "integrity": "sha1-ATDYDoM2MmTUAHTzKbij56ihzEs=", + "dev": true + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", + "dev": true + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } + } + }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, + "make-error-cause": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", + "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", + "dev": true, + "requires": { + "make-error": "^1.2.0" + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==" + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "dev": true, + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "dependencies": { + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "memoizee": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.45", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.5" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "optional": true + }, + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" + }, + "mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "requires": { + "mime-db": "1.43.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "requires": { + "once": "^1.3.2" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + } + }, + "object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onecolor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/onecolor/-/onecolor-3.1.0.tgz", + "integrity": "sha512-YZSypViXzu3ul5LMu/m6XjJ9ol8qAy9S2VjHl5E6UlhUH1KGKWabyEJifn0Jjpw23bYDzC2ucKMPGiH5kfwSGQ==", + "dev": true + }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "p-limit": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "parse-asn1": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", + "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "optional": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + } + } + }, + "pleeease-filters": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pleeease-filters/-/pleeease-filters-4.0.0.tgz", + "integrity": "sha1-ZjKy+wVkjSdY2GU4T7zteeHMrsc=", + "dev": true, + "requires": { + "onecolor": "^3.0.4", + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "postcss": { + "version": "7.0.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.26.tgz", + "integrity": "sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-color-rgba-fallback": { + "version": "git+https://github.com/postcss/postcss-color-rgba-fallback.git#96cda7e1587175322dcbfee601e3f6eb110899f3", + "from": "git+https://github.com/postcss/postcss-color-rgba-fallback.git", + "dev": true, + "requires": { + "postcss": "^7.0.17", + "postcss-value-parser": "^4.0.2", + "rgb-hex": "^3.0.0" + } + }, + "postcss-filter-gradient": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postcss-filter-gradient/-/postcss-filter-gradient-1.0.0.tgz", + "integrity": "sha1-68KOUX8yzjZVHxUwLqTXihZMyIY=", + "dev": true, + "requires": { + "filter-gradient": "^1.0.1", + "postcss": "^6.0.0" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-load-config": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz", + "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" + } + }, + "postcss-opacity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-opacity/-/postcss-opacity-5.0.0.tgz", + "integrity": "sha512-n6LgHk5HWIsyEHgPqM2jwXrkh4SuH+cZOIWh4tUp4ug3P7FkzxiJuqrpEaBvNwH/dKs5PHjHL2vPeR+nLbs+Mw==", + "dev": true, + "requires": { + "postcss": "^6.0.7" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-value-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz", + "integrity": "sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ==", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "optional": true, + "requires": { + "asap": "~2.0.3" + } + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "psl": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", + "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==", + "optional": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "optional": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } + }, + "replacestream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", + "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.3", + "object-assign": "^4.0.1", + "readable-stream": "^2.0.2" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "optional": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "rgb-hex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rgb-hex/-/rgb-hex-3.0.0.tgz", + "integrity": "sha512-8h7ZcwxCBDKvchSWbWngJuSCqJGQ6nDuLLg+QcRyQDbX9jMWt+PpPeXAhSla0GOooEomk3lCprUpGkMdsLjKyg==", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "requires": { + "aproba": "^1.1.1" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "schema-utils": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.4.tgz", + "integrity": "sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ==", + "requires": { + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "requires": { + "sver-compat": "^1.5.0" + } + }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "optional": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "dev": true + }, + "style-loader": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.1.3.tgz", + "integrity": "sha512-rlkH7X/22yuwFYK357fMN/BxYOorfnfq0eD7+vqlemSK4wEcejFF1dg4zxP0euBW8NrYx2WZzZ8PPFevr7D+Kw==", + "requires": { + "loader-utils": "^1.2.3", + "schema-utils": "^2.6.4" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" + }, + "terser": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.3.tgz", + "integrity": "sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "terser-webpack-plugin": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz", + "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==", + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^2.1.2", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "textextensions": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.6.0.tgz", + "integrity": "sha512-49WtAWS+tcsy93dRt6P0P3AMD2m5PvXRhuEA0kaXos5ZLlujtYmpmFsB+QvWUSxE1ZsstmYXfQ7L40+EcQgpAQ==", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", + "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", + "requires": { + "setimmediate": "^1.0.4" + } + }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "^2.0.3" + } + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "optional": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "optional": true + } + } + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "optional": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "uglify-js": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.7.7.tgz", + "integrity": "sha512-FeSU+hi7ULYy6mn8PKio/tXsdSXN35lm4KgV2asx00kzrLU9Pi3oAslcJT70Jdj7PHX29gGUPOT6+lXGBbemhA==", + "dev": true, + "requires": { + "commander": "~2.20.3", + "source-map": "~0.6.1" + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "undertaker": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", + "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + } + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "optional": true + }, + "v8flags": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", + "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + }, + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "requires": { + "source-map": "^0.5.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + } + }, + "webpack": { + "version": "4.41.5", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.5.tgz", + "integrity": "sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/wasm-edit": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "acorn": "^6.2.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.6.0", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==" + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "when": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", + "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "requires": { + "camelcase": "^3.0.0" + } + } + } +} diff --git a/nano/package.json b/nano/package.json index 9bfa118075b..6c81eede229 100644 --- a/nano/package.json +++ b/nano/package.json @@ -6,18 +6,23 @@ "es5-shim": "^4.5.12", "font-awesome": "^4.7.0", "gulp-clean-css": "^3.10.0", - "js-url": "git+https://github.com/websanova/js-url.git" + "js-url": "git+https://github.com/websanova/js-url.git", + "less": "^3.11.0", + "less-loader": "^5.0.0", + "style-loader": "^1.1.3", + "tslib": "^1.10.0", + "webpack": "^4.41.5" }, "devDependencies": { "fs-extra": "^7.0.1", - "gulp": "^4.0.0", + "gulp": "^4.0.2", "gulp-concat": "^2.6.1", "gulp-less": "^4.0.1", "gulp-order": "^1.2.0", "gulp-postcss": "^8.0.0", "gulp-replace": "^1.0.0", - "gulp-sourcemaps": "^2.6.4", - "gulp-uglify": "^3.0.1", + "gulp-sourcemaps": "^2.6.5", + "gulp-uglify": "^3.0.2", "less-plugin-autoprefix": "^2.0.0", "merge-stream": "^1.0.1", "pleeease-filters": "^4.0.0", diff --git a/paradise.dme b/paradise.dme index 62d9624cf5c..c5d936d7597 100644 --- a/paradise.dme +++ b/paradise.dme @@ -65,6 +65,7 @@ #include "code\__DEFINES\station_goals.dm" #include "code\__DEFINES\status_effects.dm" #include "code\__DEFINES\subsystems.dm" +#include "code\__DEFINES\tools.dm" #include "code\__DEFINES\typeids.dm" #include "code\__DEFINES\vv.dm" #include "code\__DEFINES\zlevel.dm" @@ -89,6 +90,7 @@ #include "code\__HELPERS\sanitize_values.dm" #include "code\__HELPERS\text.dm" #include "code\__HELPERS\time.dm" +#include "code\__HELPERS\tool_helpers.dm" #include "code\__HELPERS\traits.dm" #include "code\__HELPERS\type2type.dm" #include "code\__HELPERS\typelists.dm" @@ -869,7 +871,6 @@ #include "code\game\objects\items\devices\lightreplacer.dm" #include "code\game\objects\items\devices\machineprototype.dm" #include "code\game\objects\items\devices\megaphone.dm" -#include "code\game\objects\items\devices\multitool.dm" #include "code\game\objects\items\devices\paicard.dm" #include "code\game\objects\items\devices\pipe_painter.dm" #include "code\game\objects\items\devices\pizza_bomb.dm" @@ -917,6 +918,13 @@ #include "code\game\objects\items\stacks\sheets\sheets.dm" #include "code\game\objects\items\stacks\tiles\tile_mineral.dm" #include "code\game\objects\items\stacks\tiles\tile_types.dm" +#include "code\game\objects\items\tools\crowbar.dm" +#include "code\game\objects\items\tools\multitool.dm" +#include "code\game\objects\items\tools\screwdriver.dm" +#include "code\game\objects\items\tools\tool_behaviour.dm" +#include "code\game\objects\items\tools\welder.dm" +#include "code\game\objects\items\tools\wirecutters.dm" +#include "code\game\objects\items\tools\wrench.dm" #include "code\game\objects\items\weapons\AI_modules.dm" #include "code\game\objects\items\weapons\alien_specific.dm" #include "code\game\objects\items\weapons\bee_briefcase.dm" @@ -926,6 +934,7 @@ #include "code\game\objects\items\weapons\chrono_eraser.dm" #include "code\game\objects\items\weapons\cigs.dm" #include "code\game\objects\items\weapons\clown_items.dm" +#include "code\game\objects\items\weapons\conversion_kit.dm" #include "code\game\objects\items\weapons\cosmetics.dm" #include "code\game\objects\items\weapons\courtroom.dm" #include "code\game\objects\items\weapons\defib.dm" @@ -970,7 +979,6 @@ #include "code\game\objects\items\weapons\tape.dm" #include "code\game\objects\items\weapons\teleportation.dm" #include "code\game\objects\items\weapons\teleprod.dm" -#include "code\game\objects\items\weapons\tools.dm" #include "code\game\objects\items\weapons\twohanded.dm" #include "code\game\objects\items\weapons\vending_items.dm" #include "code\game\objects\items\weapons\weaponry.dm" diff --git a/rust_g.dll b/rust_g.dll index 80d09ac19ca..9707322d7d1 100644 Binary files a/rust_g.dll and b/rust_g.dll differ diff --git a/sound/goonstation/voice/deathgasp_1.ogg b/sound/goonstation/voice/deathgasp_1.ogg new file mode 100644 index 00000000000..71788a14f45 Binary files /dev/null and b/sound/goonstation/voice/deathgasp_1.ogg differ diff --git a/sound/goonstation/voice/deathgasp_2.ogg b/sound/goonstation/voice/deathgasp_2.ogg new file mode 100644 index 00000000000..38daa763fc4 Binary files /dev/null and b/sound/goonstation/voice/deathgasp_2.ogg differ diff --git a/sound/goonstation/voice/female_dying_gasp_1.ogg b/sound/goonstation/voice/female_dying_gasp_1.ogg new file mode 100644 index 00000000000..0e329374617 Binary files /dev/null and b/sound/goonstation/voice/female_dying_gasp_1.ogg differ diff --git a/sound/goonstation/voice/female_dying_gasp_2.ogg b/sound/goonstation/voice/female_dying_gasp_2.ogg new file mode 100644 index 00000000000..76857f4ee92 Binary files /dev/null and b/sound/goonstation/voice/female_dying_gasp_2.ogg differ diff --git a/sound/goonstation/voice/female_dying_gasp_3.ogg b/sound/goonstation/voice/female_dying_gasp_3.ogg new file mode 100644 index 00000000000..e6e0898062c Binary files /dev/null and b/sound/goonstation/voice/female_dying_gasp_3.ogg differ diff --git a/sound/goonstation/voice/female_dying_gasp_4.ogg b/sound/goonstation/voice/female_dying_gasp_4.ogg new file mode 100644 index 00000000000..516f763f864 Binary files /dev/null and b/sound/goonstation/voice/female_dying_gasp_4.ogg differ diff --git a/sound/goonstation/voice/female_dying_gasp_5.ogg b/sound/goonstation/voice/female_dying_gasp_5.ogg new file mode 100644 index 00000000000..cb076af860a Binary files /dev/null and b/sound/goonstation/voice/female_dying_gasp_5.ogg differ diff --git a/sound/goonstation/voice/gasp.ogg b/sound/goonstation/voice/gasp.ogg new file mode 100644 index 00000000000..b1fe8bc177f Binary files /dev/null and b/sound/goonstation/voice/gasp.ogg differ diff --git a/sound/goonstation/voice/male_dying_gasp_1.ogg b/sound/goonstation/voice/male_dying_gasp_1.ogg new file mode 100644 index 00000000000..767d6ecb995 Binary files /dev/null and b/sound/goonstation/voice/male_dying_gasp_1.ogg differ diff --git a/sound/goonstation/voice/male_dying_gasp_2.ogg b/sound/goonstation/voice/male_dying_gasp_2.ogg new file mode 100644 index 00000000000..8a545f53265 Binary files /dev/null and b/sound/goonstation/voice/male_dying_gasp_2.ogg differ diff --git a/sound/goonstation/voice/male_dying_gasp_3.ogg b/sound/goonstation/voice/male_dying_gasp_3.ogg new file mode 100644 index 00000000000..acfbfe913ec Binary files /dev/null and b/sound/goonstation/voice/male_dying_gasp_3.ogg differ diff --git a/sound/goonstation/voice/male_dying_gasp_4.ogg b/sound/goonstation/voice/male_dying_gasp_4.ogg new file mode 100644 index 00000000000..516f763f864 Binary files /dev/null and b/sound/goonstation/voice/male_dying_gasp_4.ogg differ diff --git a/sound/goonstation/voice/male_dying_gasp_5.ogg b/sound/goonstation/voice/male_dying_gasp_5.ogg new file mode 100644 index 00000000000..cb076af860a Binary files /dev/null and b/sound/goonstation/voice/male_dying_gasp_5.ogg differ