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 @@
[](http://forthebadge.com)
[](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 @@
-
+