diff --git a/.gitignore b/.gitignore
index 68a10788fcd..683e98071d3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,13 +1,10 @@
-#Files and folders specified here will never be tracked.
+###Files and folders specified here will never be tracked.
-*.ban
-*.bdb
-*.log
-*.sav
+#Ignore everything in datafolder and subdirectories
+/data/**/*
-#Compiled files and other files generated during compilation.
+#Ignore compiled files and other files generated during compilation.
*.dmb
*.rsc
*.lk
-*.int
-/data/mode.txt
+*.int
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index bdfd2504ed0..ac1a9c2dd01 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -88,6 +88,8 @@ There is no strict process when it comes to merging pull requests, pull requests
* You are going to be expected to document all your changes in the pull request, failing to do so will mean delaying it as we will have to question why you made the change. On the other hand you can speed up the process by making the pull request readable and easy to understand, with diagrams or before/after data.
+* We ask that you use the changelog system to document your change, this prevents our players from being caught unaware by changes - you can find more information about this here http://tgstation13.org/wiki/Guide_to_Changelogs
+
* If you are proposing multiple changes, which change many different aspects of the code, you are expected to section them off into different pull requests in order to make it easier to review them and to deny/accept the changes that are deemed acceptable.
* If your pull request is accepted, the code you add is no longer exclusively yours but everyones, everyone is free to work on it but you are also free to object to any changes being made, which will be noted by a Project Lead or Project Manager. It is a shame this has to be explicitly told but there have been cases where this would've saved some trouble.
diff --git a/README.md b/README.md
index 212c87e1e8d..3f8c4f97ec5 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
##DOWNLOADING
-There are a number of ways to download the source code. Some are described here, an alternative all-inclusive guide is also located at http://www.tgstation13.org/wiki/index.php/Downloading_the_source_code
+There are a number of ways to download the source code. Some are described here, an alternative all-inclusive guide is also located at http://www.tgstation13.org/wiki/Downloading_the_source_code
Option 1: Download the source code as a zip by clicking the ZIP button in the
code tab of https://github.com/tgstation/-tg-station
@@ -25,7 +25,7 @@ Then you simply search for the -tg-station repository and click the big clone
button.
Option 3:
-Follow this: http://www.tgstation13.org/wiki/index.php/Setting_up_git
+Follow this: http://www.tgstation13.org/wiki/Setting_up_git
(It's recommended that you use git-scm, as above, rather than the git CLI
suggested by the guide)
@@ -109,7 +109,7 @@ To enable an away mission open fileList.txt in the _maps/RandomZLevels directory
The SQL backend for the library and stats tracking requires a
MySQL server. Your server details go in /config/dbconfig.txt, and the SQL
-schema is in /SQL/tgstation_schema.sql. More detailed setup instructions are located here: http://www.tgstation13.org/wiki/index.php/Downloading_the_source_code#Setting_up_the_database
+schema is in /SQL/tgstation_schema.sql and /SQL/tgstation_schema_prefix.sql depending on if you want table prefixes. More detailed setup instructions are located here: http://www.tgstation13.org/wiki/Downloading_the_source_code#Setting_up_the_database
##IRC BOT SETUP
diff --git a/SQL/database_changelog.txt b/SQL/database_changelog.txt
index fe3c40342da..80af03e4561 100644
--- a/SQL/database_changelog.txt
+++ b/SQL/database_changelog.txt
@@ -1,3 +1,15 @@
+19 September 2014, by MrStonedOne
+
+Removed erro_ from table names. dbconfig.txt has a option allowing you to change the prefix used in code, defaults to "erro_" if left out for legacy reasons.
+
+If you are creating a new database and want to change the prefix, simply find and replace SS13_ to what ever you want (including nothing) and set the prefix value
+
+Two schema files are now included, one with prefixes and one without.
+
+If you have an existing database, and you want to rid your database of erros, you will have to rename all of the tables. A bit sql is included to do just that in errofreedatabase.sql Feel free to find and replace the prefix to what ever you want (or nothing)
+
+----------------------------------------------------
+
4 November 2013, by Errorage
The column 'deleted' was added to the erro_library table. If set to anything other than null, the book is interpreted as deleted.
@@ -12,4 +24,6 @@ UPDATE erro_library SET deleted = 1 WHERE id = someid
(Replace someid with the id of the book you want to soft delete.)
-----------------------------------------------------
\ No newline at end of file
+----------------------------------------------------
+
+
diff --git a/SQL/errofreedatabase.sql b/SQL/errofreedatabase.sql
new file mode 100644
index 00000000000..ae5c0d7ee1c
--- /dev/null
+++ b/SQL/errofreedatabase.sql
@@ -0,0 +1,15 @@
+ALTER TABLE erro_admin RENAME TO SS13_admin;
+ALTER TABLE erro_admin_log RENAME TO SS13_admin_log;
+ALTER TABLE erro_admin_ranks RENAME TO SS13_admin_ranks;
+ALTER TABLE erro_ban RENAME TO SS13_ban;
+ALTER TABLE erro_connection_log RENAME TO SS13_connection_log;
+ALTER TABLE erro_death RENAME TO SS13_death;
+ALTER TABLE erro_feedback RENAME TO SS13_feedback;
+ALTER TABLE erro_legacy_population RENAME TO SS13_legacy_population;
+ALTER TABLE erro_library RENAME TO SS13_library;
+ALTER TABLE erro_player RENAME TO SS13_player;
+ALTER TABLE erro_poll_option RENAME TO SS13_poll_option;
+ALTER TABLE erro_poll_question RENAME TO SS13_poll_question;
+ALTER TABLE erro_poll_textreply RENAME TO SS13_poll_textreply;
+ALTER TABLE erro_poll_vote RENAME TO SS13_poll_vote;
+ALTER TABLE erro_privacy RENAME TO SS13_privacy;
\ No newline at end of file
diff --git a/SQL/tgstation_schema.sql b/SQL/tgstation_schema.sql
index 5eb2e9d8d95..5e053d8e110 100644
--- a/SQL/tgstation_schema.sql
+++ b/SQL/tgstation_schema.sql
@@ -13,13 +13,13 @@ USE `feedback`;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
--- Table structure for table `erro_admin`
+-- Table structure for table `admin`
--
-DROP TABLE IF EXISTS `erro_admin`;
+DROP TABLE IF EXISTS `admin`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `erro_admin` (
+CREATE TABLE `admin` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ckey` varchar(32) NOT NULL,
`rank` varchar(32) NOT NULL DEFAULT 'Administrator',
@@ -31,13 +31,13 @@ CREATE TABLE `erro_admin` (
/*!40101 SET character_set_client = @saved_cs_client */;
--
--- Table structure for table `erro_admin_log`
+-- Table structure for table `admin_log`
--
-DROP TABLE IF EXISTS `erro_admin_log`;
+DROP TABLE IF EXISTS `admin_log`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `erro_admin_log` (
+CREATE TABLE `admin_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`datetime` datetime NOT NULL,
`adminckey` varchar(32) NOT NULL,
@@ -48,13 +48,13 @@ CREATE TABLE `erro_admin_log` (
/*!40101 SET character_set_client = @saved_cs_client */;
--
--- Table structure for table `erro_admin_ranks`
+-- Table structure for table `admin_ranks`
--
-DROP TABLE IF EXISTS `erro_admin_ranks`;
+DROP TABLE IF EXISTS `admin_ranks`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `erro_admin_ranks` (
+CREATE TABLE `admin_ranks` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rank` varchar(40) NOT NULL,
`flags` int(16) NOT NULL DEFAULT '0',
@@ -62,23 +62,23 @@ CREATE TABLE `erro_admin_ranks` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
-insert into erro_admin_ranks (rank, flags) values ('Moderator',2);
-insert into erro_admin_ranks (rank, flags) values ('Admin Candidate',2);
-insert into erro_admin_ranks (rank, flags) values ('Trial Admin',5638);
-insert into erro_admin_ranks (rank, flags) values ('Badmin',5727);
-insert into erro_admin_ranks (rank, flags) values ('Game Admin',8063);
-insert into erro_admin_ranks (rank, flags) values ('Game Master',65535);
-insert into erro_admin_ranks (rank, flags) values ('Host',65535);
-insert into erro_admin_ranks (rank, flags) values ('Coder',5168);
+insert into admin_ranks (rank, flags) values ('Moderator',2);
+insert into admin_ranks (rank, flags) values ('Admin Candidate',2);
+insert into admin_ranks (rank, flags) values ('Trial Admin',5638);
+insert into admin_ranks (rank, flags) values ('Badmin',5727);
+insert into admin_ranks (rank, flags) values ('Game Admin',8063);
+insert into admin_ranks (rank, flags) values ('Game Master',65535);
+insert into admin_ranks (rank, flags) values ('Host',65535);
+insert into admin_ranks (rank, flags) values ('Coder',5168);
--
--- Table structure for table `erro_ban`
+-- Table structure for table `ban`
--
-DROP TABLE IF EXISTS `erro_ban`;
+DROP TABLE IF EXISTS `ban`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `erro_ban` (
+CREATE TABLE `ban` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`bantime` datetime NOT NULL,
`serverip` varchar(32) NOT NULL,
@@ -107,13 +107,13 @@ CREATE TABLE `erro_ban` (
/*!40101 SET character_set_client = @saved_cs_client */;
--
--- Table structure for table `erro_connection_log`
+-- Table structure for table `connection_log`
--
-DROP TABLE IF EXISTS `erro_connection_log`;
+DROP TABLE IF EXISTS `connection_log`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `erro_connection_log` (
+CREATE TABLE `connection_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`datetime` datetime DEFAULT NULL,
`serverip` varchar(45) DEFAULT NULL,
@@ -125,13 +125,13 @@ CREATE TABLE `erro_connection_log` (
/*!40101 SET character_set_client = @saved_cs_client */;
--
--- Table structure for table `erro_death`
+-- Table structure for table `death`
--
-DROP TABLE IF EXISTS `erro_death`;
+DROP TABLE IF EXISTS `death`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `erro_death` (
+CREATE TABLE `death` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pod` text NOT NULL COMMENT 'Place of death',
`coord` text NOT NULL COMMENT 'X, Y, Z POD',
@@ -152,13 +152,13 @@ CREATE TABLE `erro_death` (
/*!40101 SET character_set_client = @saved_cs_client */;
--
--- Table structure for table `erro_feedback`
+-- Table structure for table `feedback`
--
-DROP TABLE IF EXISTS `erro_feedback`;
+DROP TABLE IF EXISTS `feedback`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `erro_feedback` (
+CREATE TABLE `feedback` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`time` datetime NOT NULL,
`round_id` int(8) NOT NULL,
@@ -170,13 +170,13 @@ CREATE TABLE `erro_feedback` (
/*!40101 SET character_set_client = @saved_cs_client */;
--
--- Table structure for table `erro_legacy_population`
+-- Table structure for table `legacy_population`
--
-DROP TABLE IF EXISTS `erro_legacy_population`;
+DROP TABLE IF EXISTS `legacy_population`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `erro_legacy_population` (
+CREATE TABLE `legacy_population` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`playercount` int(11) DEFAULT NULL,
`admincount` int(11) DEFAULT NULL,
@@ -186,11 +186,11 @@ CREATE TABLE `erro_legacy_population` (
/*!40101 SET character_set_client = @saved_cs_client */;
--
--- Table structure for table `erro_library`
+-- Table structure for table `library`
--
-DROP TABLE IF EXISTS `erro_library`;
-CREATE TABLE `erro_library` (
+DROP TABLE IF EXISTS `library`;
+CREATE TABLE `library` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`author` varchar(45) NOT NULL,
`title` varchar(45) NOT NULL,
@@ -203,13 +203,13 @@ CREATE TABLE `erro_library` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
--- Table structure for table `erro_player`
+-- Table structure for table `player`
--
-DROP TABLE IF EXISTS `erro_player`;
+DROP TABLE IF EXISTS `player`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `erro_player` (
+CREATE TABLE `player` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ckey` varchar(32) NOT NULL,
`firstseen` datetime NOT NULL,
@@ -223,13 +223,13 @@ CREATE TABLE `erro_player` (
/*!40101 SET character_set_client = @saved_cs_client */;
--
--- Table structure for table `erro_poll_option`
+-- Table structure for table `poll_option`
--
-DROP TABLE IF EXISTS `erro_poll_option`;
+DROP TABLE IF EXISTS `poll_option`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `erro_poll_option` (
+CREATE TABLE `poll_option` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pollid` int(11) NOT NULL,
`text` varchar(255) NOT NULL,
@@ -244,13 +244,13 @@ CREATE TABLE `erro_poll_option` (
/*!40101 SET character_set_client = @saved_cs_client */;
--
--- Table structure for table `erro_poll_question`
+-- Table structure for table `poll_question`
--
-DROP TABLE IF EXISTS `erro_poll_question`;
+DROP TABLE IF EXISTS `poll_question`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `erro_poll_question` (
+CREATE TABLE `poll_question` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`polltype` varchar(16) NOT NULL DEFAULT 'OPTION',
`starttime` datetime NOT NULL,
@@ -263,13 +263,13 @@ CREATE TABLE `erro_poll_question` (
/*!40101 SET character_set_client = @saved_cs_client */;
--
--- Table structure for table `erro_poll_textreply`
+-- Table structure for table `poll_textreply`
--
-DROP TABLE IF EXISTS `erro_poll_textreply`;
+DROP TABLE IF EXISTS `poll_textreply`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `erro_poll_textreply` (
+CREATE TABLE `poll_textreply` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`datetime` datetime NOT NULL,
`pollid` int(11) NOT NULL,
@@ -282,13 +282,13 @@ CREATE TABLE `erro_poll_textreply` (
/*!40101 SET character_set_client = @saved_cs_client */;
--
--- Table structure for table `erro_poll_vote`
+-- Table structure for table `poll_vote`
--
-DROP TABLE IF EXISTS `erro_poll_vote`;
+DROP TABLE IF EXISTS `poll_vote`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `erro_poll_vote` (
+CREATE TABLE `poll_vote` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`datetime` datetime NOT NULL,
`pollid` int(11) NOT NULL,
@@ -302,13 +302,13 @@ CREATE TABLE `erro_poll_vote` (
/*!40101 SET character_set_client = @saved_cs_client */;
--
--- Table structure for table `erro_privacy`
+-- Table structure for table `privacy`
--
-DROP TABLE IF EXISTS `erro_privacy`;
+DROP TABLE IF EXISTS `privacy`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `erro_privacy` (
+CREATE TABLE `privacy` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`datetime` datetime NOT NULL,
`ckey` varchar(32) NOT NULL,
diff --git a/SQL/tgstation_schema_prefixed.sql b/SQL/tgstation_schema_prefixed.sql
new file mode 100644
index 00000000000..c1b740b6874
--- /dev/null
+++ b/SQL/tgstation_schema_prefixed.sql
@@ -0,0 +1,330 @@
+CREATE DATABASE IF NOT EXISTS `feedback` /*!40100 DEFAULT CHARACTER SET latin1 */;
+USE `feedback`;
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `SS13_admin`
+--
+
+DROP TABLE IF EXISTS `SS13_admin`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `SS13_admin` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `ckey` varchar(32) NOT NULL,
+ `rank` varchar(32) NOT NULL DEFAULT 'Administrator',
+ `level` int(2) NOT NULL DEFAULT '0',
+ `flags` int(16) NOT NULL DEFAULT '0',
+ `email` varchar(45) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `SS13_admin_log`
+--
+
+DROP TABLE IF EXISTS `SS13_admin_log`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `SS13_admin_log` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `datetime` datetime NOT NULL,
+ `adminckey` varchar(32) NOT NULL,
+ `adminip` varchar(18) NOT NULL,
+ `log` text NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `SS13_admin_ranks`
+--
+
+DROP TABLE IF EXISTS `SS13_admin_ranks`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `SS13_admin_ranks` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `rank` varchar(40) NOT NULL,
+ `flags` int(16) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+insert into SS13_admin_ranks (rank, flags) values ('Moderator',2);
+insert into SS13_admin_ranks (rank, flags) values ('Admin Candidate',2);
+insert into SS13_admin_ranks (rank, flags) values ('Trial Admin',5638);
+insert into SS13_admin_ranks (rank, flags) values ('Badmin',5727);
+insert into SS13_admin_ranks (rank, flags) values ('Game Admin',8063);
+insert into SS13_admin_ranks (rank, flags) values ('Game Master',65535);
+insert into SS13_admin_ranks (rank, flags) values ('Host',65535);
+insert into SS13_admin_ranks (rank, flags) values ('Coder',5168);
+
+--
+-- Table structure for table `SS13_ban`
+--
+
+DROP TABLE IF EXISTS `SS13_ban`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `SS13_ban` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `bantime` datetime NOT NULL,
+ `serverip` varchar(32) NOT NULL,
+ `bantype` varchar(32) NOT NULL,
+ `reason` text NOT NULL,
+ `job` varchar(32) DEFAULT NULL,
+ `duration` int(11) NOT NULL,
+ `rounds` int(11) DEFAULT NULL,
+ `expiration_time` datetime NOT NULL,
+ `ckey` varchar(32) NOT NULL,
+ `computerid` varchar(32) NOT NULL,
+ `ip` varchar(32) NOT NULL,
+ `a_ckey` varchar(32) NOT NULL,
+ `a_computerid` varchar(32) NOT NULL,
+ `a_ip` varchar(32) NOT NULL,
+ `who` text NOT NULL,
+ `adminwho` text NOT NULL,
+ `edits` text,
+ `unbanned` int(2) DEFAULT NULL,
+ `unbanned_datetime` datetime DEFAULT NULL,
+ `unbanned_ckey` varchar(32) DEFAULT NULL,
+ `unbanned_computerid` varchar(32) DEFAULT NULL,
+ `unbanned_ip` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `SS13_connection_log`
+--
+
+DROP TABLE IF EXISTS `SS13_connection_log`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `SS13_connection_log` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `datetime` datetime DEFAULT NULL,
+ `serverip` varchar(45) DEFAULT NULL,
+ `ckey` varchar(45) DEFAULT NULL,
+ `ip` varchar(18) DEFAULT NULL,
+ `computerid` varchar(45) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `SS13_death`
+--
+
+DROP TABLE IF EXISTS `SS13_death`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `SS13_death` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `pod` text NOT NULL COMMENT 'Place of death',
+ `coord` text NOT NULL COMMENT 'X, Y, Z POD',
+ `tod` datetime NOT NULL COMMENT 'Time of death',
+ `job` text NOT NULL,
+ `special` text NOT NULL,
+ `name` text NOT NULL,
+ `byondkey` text NOT NULL,
+ `laname` text NOT NULL COMMENT 'Last attacker name',
+ `lakey` text NOT NULL COMMENT 'Last attacker key',
+ `gender` text NOT NULL,
+ `bruteloss` int(11) NOT NULL,
+ `brainloss` int(11) NOT NULL,
+ `fireloss` int(11) NOT NULL,
+ `oxyloss` int(11) NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `SS13_feedback`
+--
+
+DROP TABLE IF EXISTS `SS13_feedback`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `SS13_feedback` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `time` datetime NOT NULL,
+ `round_id` int(8) NOT NULL,
+ `var_name` varchar(32) NOT NULL,
+ `var_value` int(16) DEFAULT NULL,
+ `details` text,
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `SS13_legacy_population`
+--
+
+DROP TABLE IF EXISTS `SS13_legacy_population`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `SS13_legacy_population` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `playercount` int(11) DEFAULT NULL,
+ `admincount` int(11) DEFAULT NULL,
+ `time` datetime NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `SS13_library`
+--
+
+DROP TABLE IF EXISTS `SS13_library`;
+CREATE TABLE `SS13_library` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `author` varchar(45) NOT NULL,
+ `title` varchar(45) NOT NULL,
+ `content` text NOT NULL,
+ `category` varchar(45) NOT NULL,
+ `ckey` varchar(45) DEFAULT 'LEGACY',
+ `datetime` datetime DEFAULT NULL,
+ `deleted` tinyint(1) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `SS13_player`
+--
+
+DROP TABLE IF EXISTS `SS13_player`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `SS13_player` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `ckey` varchar(32) NOT NULL,
+ `firstseen` datetime NOT NULL,
+ `lastseen` datetime NOT NULL,
+ `ip` varchar(18) NOT NULL,
+ `computerid` varchar(32) NOT NULL,
+ `lastadminrank` varchar(32) NOT NULL DEFAULT 'Player',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `ckey` (`ckey`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `SS13_poll_option`
+--
+
+DROP TABLE IF EXISTS `SS13_poll_option`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `SS13_poll_option` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `pollid` int(11) NOT NULL,
+ `text` varchar(255) NOT NULL,
+ `percentagecalc` tinyint(1) NOT NULL DEFAULT '1',
+ `minval` int(3) DEFAULT NULL,
+ `maxval` int(3) DEFAULT NULL,
+ `descmin` varchar(32) DEFAULT NULL,
+ `descmid` varchar(32) DEFAULT NULL,
+ `descmax` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `SS13_poll_question`
+--
+
+DROP TABLE IF EXISTS `SS13_poll_question`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `SS13_poll_question` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `polltype` varchar(16) NOT NULL DEFAULT 'OPTION',
+ `starttime` datetime NOT NULL,
+ `endtime` datetime NOT NULL,
+ `question` varchar(255) NOT NULL,
+ `adminonly` tinyint(1) DEFAULT '0',
+ `multiplechoiceoptions` int(2) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `SS13_poll_textreply`
+--
+
+DROP TABLE IF EXISTS `SS13_poll_textreply`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `SS13_poll_textreply` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `datetime` datetime NOT NULL,
+ `pollid` int(11) NOT NULL,
+ `ckey` varchar(32) NOT NULL,
+ `ip` varchar(18) NOT NULL,
+ `replytext` text NOT NULL,
+ `adminrank` varchar(32) NOT NULL DEFAULT 'Player',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `SS13_poll_vote`
+--
+
+DROP TABLE IF EXISTS `SS13_poll_vote`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `SS13_poll_vote` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `datetime` datetime NOT NULL,
+ `pollid` int(11) NOT NULL,
+ `optionid` int(11) NOT NULL,
+ `ckey` varchar(255) NOT NULL,
+ `ip` varchar(16) NOT NULL,
+ `adminrank` varchar(32) NOT NULL,
+ `rating` int(2) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `SS13_privacy`
+--
+
+DROP TABLE IF EXISTS `SS13_privacy`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `SS13_privacy` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `datetime` datetime NOT NULL,
+ `ckey` varchar(32) NOT NULL,
+ `option` varchar(128) NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2013-03-24 18:02:35
\ No newline at end of file
diff --git a/_maps/RandomZLevels/fileList.txt b/_maps/RandomZLevels/fileList.txt
index 8b4138a1c7e..c2e08523502 100644
--- a/_maps/RandomZLevels/fileList.txt
+++ b/_maps/RandomZLevels/fileList.txt
@@ -17,4 +17,5 @@
#_maps/RandomZLevels/challenge.dmm
#_maps/RandomZLevels/listeningpost.dmm
#_maps/RandomZLevels/spacehotel.dmm
-#_maps/RandomZLevels/centcomAway.dmm
\ No newline at end of file
+#_maps/RandomZLevels/centcomAway.dmm
+#_maps/RandomZLevels/moonoutpost19.dmm
\ No newline at end of file
diff --git a/_maps/RandomZLevels/moonoutpost19.dmm b/_maps/RandomZLevels/moonoutpost19.dmm
new file mode 100644
index 00000000000..9c6f4f43367
--- /dev/null
+++ b/_maps/RandomZLevels/moonoutpost19.dmm
@@ -0,0 +1,915 @@
+"aa" = (/turf/unsimulated/wall{icon_state = "rock"},/area/mine/explored)
+"ab" = (/turf/simulated/mineral/random,/area/mine/explored)
+"ac" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/resin/wall,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"ad" = (/obj/structure/alien/weeds,/obj/structure/alien/resin/wall,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"ae" = (/turf/simulated/mineral/random/low_chance,/area/mine/explored)
+"af" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/alien/resin/wall,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"ag" = (/obj/structure/alien/weeds,/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"ah" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"ai" = (/obj/structure/alien/weeds,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"aj" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"ak" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/mob/living/simple_animal/hostile/alien,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"al" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"am" = (/obj/structure/alien/weeds/node,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"an" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/stool/bed/nest,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"ao" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/stool/bed/nest,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"ap" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/gibs,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/obj/item/weapon/gun/projectile/automatic/pistol,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"aq" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"ar" = (/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"as" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/resin/wall,/obj/structure/alien/resin/wall,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"at" = (/turf/simulated/wall/r_wall,/area/awaycontent/a4{name = "Syndicate Outpost"})
+"au" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"av" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/mob/living/simple_animal/hostile/alien/sentinel,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"aw" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood/gibs,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"ax" = (/obj/structure/alien/weeds/node,/obj/effect/decal/cleanable/blood,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"ay" = (/obj/structure/alien/weeds,/obj/effect/decal/cleanable/blood/gibs,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"az" = (/turf/simulated/floor{dir = 9; heat_capacity = 1e+006; icon_state = "darkred"; tag = "icon-darkred (NORTHWEST)"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aA" = (/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "darkredcorners"; tag = "icon-darkredcorners (NORTH)"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aB" = (/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "dark"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aC" = (/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "darkredcorners"; tag = "icon-darkredcorners (EAST)"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aD" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{dir = 5; heat_capacity = 1e+006; icon_state = "darkred"; tag = "icon-darkred (NORTHEAST)"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aE" = (/obj/structure/alien/weeds/node,/obj/structure/alien/resin/wall,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"aF" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/gibs,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/obj/item/clothing/under/rank/security/science,/obj/item/clothing/suit/armor/vest,/obj/item/weapon/melee/baton/loaded,/obj/item/clothing/head/helmet,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"aG" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "darkredcorners"; tag = "icon-darkredcorners (NORTH)"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aH" = (/obj/machinery/gateway{dir = 9},/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "vault"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aI" = (/obj/machinery/gateway{dir = 1},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "vault"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aJ" = (/obj/machinery/gateway{dir = 5},/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "vault"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aK" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/obj/effect/decal/cleanable/blood/gibs,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"aL" = (/obj/structure/alien/weeds,/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/obj/effect/decal/cleanable/blood,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"aM" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/effect/decal/cleanable/blood/gibs,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"aN" = (/obj/structure/alien/weeds,/mob/living/simple_animal/hostile/alien/drone,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"aO" = (/obj/machinery/light{dir = 8},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "dark"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aP" = (/obj/machinery/gateway{dir = 8},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "vault"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aQ" = (/obj/machinery/gateway/centeraway{calibrated = 0},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "dark"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aR" = (/obj/machinery/gateway{dir = 4},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "vault"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aS" = (/obj/machinery/light{icon_state = "tube1"; dir = 4},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "dark"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aT" = (/obj/item/weapon/ore/iron{pixel_x = 7; pixel_y = -6},/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"aU" = (/obj/structure/alien/weeds,/mob/living/simple_animal/hostile/alien/queen/large{desc = "A gigantic alien who is in charge of the hive and all of its loyal servants."; name = "alien queen"; pixel_x = -16},/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"aV" = (/turf/simulated/wall,/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aW" = (/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "darkredcorners"; tag = "icon-darkredcorners (WEST)"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aX" = (/obj/machinery/gateway{dir = 10},/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "vault"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aY" = (/obj/machinery/gateway,/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "vault"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"aZ" = (/obj/machinery/gateway{dir = 6},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "vault"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"ba" = (/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "darkredcorners"; tag = "icon-darkredcorners"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"bb" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/mob/living/simple_animal/hostile/alien/drone,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"bc" = (/obj/structure/alien/weeds,/obj/effect/decal/cleanable/blood,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"bd" = (/mob/living/simple_animal/hostile/alien/drone,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"be" = (/obj/machinery/vending/cola,/turf/simulated/floor{icon_state = "dark"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"bf" = (/obj/machinery/vending/cigarette,/obj/structure/sign/poster{icon_state = "poster7"; pixel_y = 32; serial_number = 7; subtype = 0},/turf/simulated/floor{icon_state = "dark"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"bg" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{dir = 10; heat_capacity = 1e+006; icon_state = "darkred"; tag = "icon-darkred (SOUTHWEST)"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"bh" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "dark"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"bi" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "darkredcorners"; tag = "icon-darkredcorners"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"bj" = (/turf/simulated/floor{dir = 6; heat_capacity = 1e+006; icon_state = "darkred"; tag = "icon-darkred (SOUTHEAST)"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"bk" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/obj/item/clothing/under/syndicate/combat,/obj/item/clothing/glasses/night,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"bl" = (/obj/structure/alien/weeds,/mob/living/simple_animal/hostile/alien/sentinel,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"bm" = (/turf/simulated/mineral/random/high_chance,/area/mine/explored)
+"bn" = (/obj/machinery/light/small{dir = 8},/obj/structure/sign/poster{icon_state = "poster17"; pixel_x = -32; pixel_y = 0; serial_number = 17; subtype = 0},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"bo" = (/obj/item/weapon/cigbutt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"bp" = (/obj/machinery/alarm{frequency = 1439; locked = 1; pixel_y = 23; req_access = "150"},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"bq" = (/obj/structure/table,/obj/machinery/microwave{pixel_x = -3; pixel_y = 6},/obj/machinery/light/small{dir = 4},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"br" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/table,/obj/item/device/radio/off{pixel_x = -4; pixel_y = 4},/obj/item/device/radio/off{pixel_x = 2},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"bs" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/table,/obj/item/weapon/paper_bin{pixel_x = 1; pixel_y = 9},/obj/item/weapon/pen,/obj/item/weapon/paper{info = "Log 1: We got our promised supply drop today. We were only meant to get it, what, a week ago? This bloody gateway keeps desyncing itself, and that means subsisting off recycled water and carb packs. No clue where the damn thing connects to on its off days, and HQ say we are 'not to touch it if it isn't linking to command.' We dumped off the assload of crates Jim filled, got our boxes of oxygen, food and drink, and closed the portal.
Log 2: Damn thing is acting up again. Three days no contact this time. I thought I heard clanking noises from it yesterday. Jim is going on about the NT base or some shit. We've been over this before - They don't know we're here, that engineer was too drunk to recognise his suit, especially since I had it painted orange. He's starting to get annoying. We're safe.
Log 2: Really dumb of me but I just waved at an engineer in the outpost, and he waved back. I hope to god he was too dumb or drunk to recognize the suit, because if he isn't then we might have to pull out before they come looking for us.
Log 3: That huge reinforced tumor in their science section has been making a lot of noise lately. I've been hearing some banging and scratching from the other side and I'm kind of glad now that they reinforced this thing so much. I'll be sleeping with my gun under my pillow from now on."; name = "Personal Log"},/turf/simulated/floor/wood{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"dt" = (/obj/structure/closet/secure_closet{desc = "It's a secure locker for personnel. The first card swiped gains control."; icon_broken = "cabinetdetective_broken"; icon_closed = "cabinetdetective"; icon_locked = "cabinetdetective_locked"; icon_off = "cabinetdetective_broken"; icon_opened = "cabinetdetective_open"; icon_state = "cabinetdetective_locked"; locked = 1; name = "personal closet"; req_access_txt = "150"},/obj/item/ammo_box/magazine/m10mm,/obj/item/ammo_box/magazine/m10mm,/obj/item/weapon/suppressor,/turf/simulated/floor/wood{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"du" = (/obj/structure/stool/bed,/obj/item/weapon/bedsheet/syndie,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/wood{heat_capacity = 1e+006},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"dv" = (/obj/structure/closet/secure_closet{desc = "It's a secure locker for personnel. The first card swiped gains control."; icon_broken = "cabinetdetective_broken"; icon_closed = "cabinetdetective"; icon_locked = "cabinetdetective_locked"; icon_off = "cabinetdetective_broken"; icon_opened = "cabinetdetective_open"; icon_state = "cabinetdetective"; locked = 0; name = "personal closet"; req_access_txt = "150"},/obj/item/weapon/spacecash/c50,/turf/simulated/floor/wood{heat_capacity = 1e+006},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"dw" = (/obj/machinery/door/airlock/external{density = 0; emagged = 1; icon_state = "door_open"; locked = 1; opacity = 0; req_access_txt = "150"},/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"dx" = (/obj/item/weapon/ore/iron,/obj/item/weapon/ore/iron{pixel_x = -7; pixel_y = -4},/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"dy" = (/obj/structure/dispenser/oxygen{oxygentanks = 9},/obj/machinery/light/small{active_power_usage = 0; dir = 1; icon_state = "bulb-broken"; status = 2},/turf/simulated/floor/plating{carbon_dioxide = 48.7; dir = 9; heat_capacity = 1e+006; icon_state = "warnplate"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"dz" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"dA" = (/obj/structure/rack,/obj/item/clothing/suit/space/syndicate/orange,/obj/item/clothing/mask/gas,/obj/item/weapon/pickaxe/drill,/obj/item/clothing/head/helmet/space/syndicate/orange,/turf/simulated/floor/plating{carbon_dioxide = 48.7; dir = 5; heat_capacity = 1e+006; icon_state = "warnplate"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-warnplate (NORTHEAST)"; temperature = 251},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"dB" = (/obj/item/weapon/ore/iron{pixel_x = -3; pixel_y = 9},/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"dC" = (/turf/simulated/mineral,/area/mine/explored)
+"dD" = (/obj/structure/sign/vacuum{desc = "A warning sign which reads 'HOSTILE ATMOSPHERE AHEAD'"; name = "\improper HOSTILE ATMOSPHERE AHEAD"; pixel_x = 0; pixel_y = -32},/obj/machinery/portable_atmospherics/canister/oxygen,/turf/simulated/floor/plating{carbon_dioxide = 48.7; dir = 10; heat_capacity = 1e+006; icon_state = "warnplate"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-warnplate (SOUTHWEST)"; temperature = 251},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"dE" = (/turf/simulated/floor/plating{broken = 1; carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "platingdmg1"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-platingdmg1"; temperature = 251},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"dF" = (/obj/structure/rack,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{carbon_dioxide = 48.7; dir = 6; heat_capacity = 1e+006; icon_state = "warnplate"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-warnplate (SOUTHEAST)"; temperature = 251},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"dG" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"dH" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_2"},/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"dI" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/obj/item/device/mining_scanner,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"dJ" = (/obj/item/device/flashlight/lantern{icon_state = "lantern-on"; on = 1},/obj/effect/decal/cleanable/blood/splatter,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"dK" = (/obj/machinery/door/airlock/external{density = 0; emagged = 1; icon_state = "door_open"; locked = 1; opacity = 0; req_access_txt = "150"},/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_plating = "asteroidplating"; icon_state = "asteroidplating"; nitrogen = 13.2; oxygen = 32.45; temperature = 251},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"dL" = (/obj/item/weapon/storage/bag/ore,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"dM" = (/obj/item/weapon/pickaxe/drill,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"dN" = (/obj/machinery/light/small{dir = 1},/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_plating = "asteroidplating"; icon_state = "asteroidplating"; nitrogen = 13.2; oxygen = 32.45; temperature = 251},/area/awaycontent/a4{name = "Syndicate Outpost"})
+"dO" = (/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_plating = "asteroidplating"; icon_state = "asteroidplating"; nitrogen = 13.2; oxygen = 32.45; temperature = 251},/area/mine/explored)
+"dP" = (/obj/item/weapon/ore/iron{pixel_x = -7; pixel_y = -4},/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"dQ" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/gibs,/obj/item/weapon/tank/oxygen,/obj/item/clothing/suit/space/syndicate/orange,/obj/item/clothing/mask/gas,/obj/item/clothing/head/helmet/space/syndicate/orange,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"dR" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood,/mob/living/simple_animal/hostile/alien/drone,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"dS" = (/obj/machinery/light/small,/turf/simulated/floor/plating/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/mine/explored)
+"dT" = (/turf/simulated/wall/r_wall/rust,/area/awaycontent/a2{name = "MO19 Research"})
+"dU" = (/turf/simulated/wall/r_wall,/area/awaycontent/a2{name = "MO19 Research"})
+"dV" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id = "Awaybiohazard"; name = "Acid-Proof biohazard containment door"; unacidable = 1},/obj/machinery/door/poddoor{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id = "Awaybiohazard"; layer = 2.9; name = "Acid-Proof biohazard containment door"; unacidable = 1},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"dW" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id = "Awaybiohazard"; name = "Acid-Proof biohazard containment door"; unacidable = 1},/obj/machinery/door/poddoor{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id = "Awaybiohazard"; layer = 2.9; name = "Acid-Proof biohazard containment door"; unacidable = 1},/obj/structure/window/reinforced{dir = 4; layer = 3.2},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"dX" = (/obj/structure/sign/biohazard,/turf/simulated/wall/r_wall,/area/awaycontent/a2{name = "MO19 Research"})
+"dY" = (/obj/machinery/vending/snack,/turf/simulated/floor{icon_state = "dark"},/area/awaycontent/a2{name = "MO19 Research"})
+"dZ" = (/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a2{name = "MO19 Research"})
+"ea" = (/obj/structure/stool/bed/chair{dir = 1},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"eb" = (/obj/machinery/atmospherics/portables_connector{dir = 4},/obj/machinery/portable_atmospherics/canister,/obj/structure/alien/weeds,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"ec" = (/obj/machinery/atmospherics/binary/pump{dir = 4},/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{name = "MO19 Research"})
+"ed" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/machinery/atmospherics/pipe/simple/general/visible{dir = 10},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"ee" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{name = "MO19 Research"})
+"ef" = (/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/machinery/shieldwallgen{locked = 0; req_access = null},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"eg" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/gibs,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"eh" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood/gibs,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"ei" = (/obj/structure/alien/weeds,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"ej" = (/obj/machinery/light{active_power_usage = 0; dir = 1; icon_state = "tube-broken"; status = 2},/obj/structure/alien/weeds,/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"ek" = (/obj/machinery/sparker{desc = "A wall-mounted ignition device. This one has been applied with an acid-proof coating."; id = "awayxenobio"; name = "Acid-Proof mounted igniter"; pixel_x = 0; pixel_y = 25; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"el" = (/obj/structure/alien/weeds,/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"em" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/gibs,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"en" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/gibs,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"eo" = (/obj/machinery/vending/coffee,/turf/simulated/floor{icon_state = "dark"},/area/awaycontent/a2{name = "MO19 Research"})
+"ep" = (/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"eq" = (/obj/machinery/light/small{active_power_usage = 0; dir = 4; icon_state = "bulb-broken"; status = 2},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a2{name = "MO19 Research"})
+"er" = (/obj/machinery/atmospherics/portables_connector{dir = 4},/obj/machinery/portable_atmospherics/canister,/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"es" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/atmospherics/pipe/manifold{dir = 4; icon_state = "manifold"; level = 2},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"et" = (/obj/structure/table/reinforced,/obj/item/weapon/paper_bin{pixel_x = 1; pixel_y = 9},/obj/item/weapon/pen,/obj/structure/alien/weeds,/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{name = "MO19 Research"})
+"eu" = (/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/structure/cable,/obj/structure/grille,/obj/structure/window/reinforced{dir = 4; layer = 2.9},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"ev" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'HIGH VOLTAGE'"; icon_state = "shock"; name = "HIGH VOLTAGE"},/turf/simulated/wall/r_wall,/area/awaycontent/a2{name = "MO19 Research"})
+"ew" = (/obj/structure/alien/weeds/node,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"ex" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"ey" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"ez" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"eA" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"eB" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/effect/decal/cleanable/blood/gibs,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"eC" = (/obj/structure/alien/weeds,/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"eD" = (/turf/simulated/wall,/area/awaycontent/a2{name = "MO19 Research"})
+"eE" = (/turf/simulated/wall/rust,/area/awaycontent/a2{name = "MO19 Research"})
+"eF" = (/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{name = "MO19 Research"})
+"eG" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{name = "MO19 Research"})
+"eH" = (/obj/machinery/light/small{active_power_usage = 0; dir = 8; icon_state = "bulb-broken"; status = 2},/turf/simulated/floor{dir = 6; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{name = "MO19 Research"})
+"eI" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/general/visible,/obj/structure/stool/bed/chair/office/light{dir = 4},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"eJ" = (/obj/structure/table/reinforced,/obj/machinery/door_control{id = "Awaylab"; name = "Containment Chamber Blast Doors"; pixel_x = 4; pixel_y = -2; req_access_txt = "201"},/obj/machinery/ignition_switch{id = "awayxenobio"; pixel_x = 4; pixel_y = 8},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{name = "MO19 Research"})
+"eK" = (/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/window/reinforced{dir = 8},/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/structure/cable,/obj/structure/grille,/obj/structure/window/reinforced{dir = 4; layer = 2.9},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"eL" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"eM" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"eN" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"eO" = (/obj/machinery/power/port_gen/pacman{desc = "A portable generator for emergency backup power. This one looks old and the knobs are rusted shut."; name = "Broken-down P.A.C.M.A.N.-type portable generator"},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"eP" = (/obj/machinery/power/port_gen/pacman/super{desc = "A portable generator for emergency backup power. This one looks old and the knobs are rusted shut."; name = "Broken-down S.U.P.E.R.P.A.C.M.A.N.-type portable generator"},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg2"; tag = "icon-platingdmg2"},/area/awaycontent/a2{name = "MO19 Research"})
+"eQ" = (/obj/machinery/space_heater,/obj/machinery/light/small{dir = 1},/obj/structure/sign/poster{icon_state = "poster5_legit"; pixel_x = 0; pixel_y = 32; serial_number = 21; subtype = 1},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"eR" = (/obj/machinery/power/terminal{dir = 4},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/machinery/alarm{frequency = 1439; locked = 0; pixel_y = 23; req_access = null},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"eS" = (/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/machinery/power/smes{charge = 1.5e+006; input_level = 10000; inputting = 0; output_level = 15000; outputting = 1},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"eT" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"eU" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/item/weapon/newspaper,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"eV" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg1"; tag = "icon-platingdmg1"},/area/awaycontent/a2{name = "MO19 Research"})
+"eW" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"eX" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"eY" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/airlock/maintenance{req_access_txt = "201"; req_one_access_txt = "0"},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"eZ" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 5; icon_state = "ltrails_1"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{name = "MO19 Research"})
+"fa" = (/obj/structure/sign/securearea{pixel_x = 32},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{name = "MO19 Research"})
+"fb" = (/obj/structure/table,/obj/machinery/reagentgrinder,/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a2{name = "MO19 Research"})
+"fc" = (/obj/structure/table,/obj/item/stack/sheet/mineral/plasma{layer = 2.9},/obj/machinery/light/small{active_power_usage = 0; dir = 1; icon_state = "bulb-broken"; status = 2},/obj/machinery/alarm{frequency = 1439; locked = 0; pixel_y = 23; req_access = null},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fd" = (/obj/machinery/firealarm{dir = 2; pixel_y = 24},/obj/structure/table,/obj/item/weapon/storage/box/beakers{pixel_x = 2; pixel_y = 2},/obj/item/weapon/storage/box/syringes,/obj/structure/alien/weeds,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fe" = (/obj/structure/closet/crate/freezer,/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/obj/item/xenos_claw,/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a2{name = "MO19 Research"})
+"ff" = (/obj/machinery/door/firedoor,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{name = "MO19 Research"})
+"fg" = (/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"fh" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/general/visible,/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"fi" = (/obj/structure/closet/l3closet/scientist,/obj/structure/window/reinforced,/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{name = "MO19 Research"})
+"fj" = (/obj/structure/cable,/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/structure/grille,/obj/structure/window/reinforced{dir = 4; layer = 2.9},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fk" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"fl" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/stool/bed/nest,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"fm" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fn" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/effect/decal/cleanable/dirt,/obj/effect/decal/cleanable/generic,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fo" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fp" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg1"; tag = "icon-platingdmg1"},/area/awaycontent/a2{name = "MO19 Research"})
+"fq" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fr" = (/obj/structure/extinguisher_cabinet{pixel_x = -26},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; icon_state = "ltrails_2"},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{name = "MO19 Research"})
+"fs" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/alien/weeds,/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{name = "MO19 Research"})
+"ft" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/research{density = 0; emagged = 1; icon_state = "door_open"; locked = 1; name = "Xenobiology Lab"; opacity = 0; req_access_txt = "201"},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fu" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a2{name = "MO19 Research"})
+"fv" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fw" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/firedoor,/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{name = "MO19 Research"})
+"fx" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/alien/weeds/node,/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"fy" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/general/visible{dir = 5},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"fz" = (/obj/machinery/atmospherics/pipe/simple/general/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/item/stack/rods,/obj/item/stack/cable_coil{amount = 5},/obj/item/weapon/shard{icon_state = "small"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{name = "MO19 Research"})
+"fA" = (/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/machinery/atmospherics/pipe/simple/general/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/item/stack/rods,/obj/item/stack/cable_coil{amount = 5},/obj/item/weapon/shard{icon_state = "medium"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"fB" = (/obj/machinery/atmospherics/pipe/simple/general/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"fC" = (/obj/machinery/atmospherics/pipe/simple/general/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"fD" = (/obj/machinery/atmospherics/pipe/simple/general/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"fE" = (/obj/machinery/atmospherics/pipe/simple/general/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/structure/alien/weeds,/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"fF" = (/obj/machinery/atmospherics/unary/outlet_injector{desc = "Has a valve and pump attached to it. This one has been applied with an acid-proof coating."; dir = 8; icon_state = "on"; name = "Acid-Proof Air Injector"; on = 1; unacidable = 1},/obj/structure/alien/weeds,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"fG" = (/obj/machinery/light{active_power_usage = 0; dir = 4; icon_state = "tube-broken"; status = 2},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"fH" = (/obj/machinery/portable_atmospherics/scrubber,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fI" = (/obj/item/weapon/cigbutt,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fJ" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fK" = (/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fL" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fM" = (/obj/machinery/door/airlock/maintenance{req_access_txt = "0"; req_one_access_txt = "0"},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fN" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/effect/decal/cleanable/oil,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fO" = (/obj/structure/filingcabinet,/obj/item/weapon/paper{info = "Entry One - 27/05/2554: I just arrived, and already I hate my job. I'm stuck on this shithole of an outpost, trying to avoid these damn eggheads running all over the place preparing for god knows what. There's no crimes to stop, no syndies to kill, and I'm not even allowed to beat the fuckin' assistant senseless! They said I was transferred from Space Station 13 for 'good behavior', but this feels more like a punishment than a reward. All I know is that if I don't get some action soon, I'm going to go insane.
Entry Two - 03/06/2554: Okay, so get this: we got a fuckin' deathsquad coming in today! I thought the day I saw one of them would be the day my employment was 'terminated', if you get my drift. They're escorting some sort of weird alien creature for the eggheads to study. I heard one of the docs telling the chef that this thing killed a whole security force before it was captured. I sure as hell hope that I don't have to fight it.
Entry Three - 08/06/2554: My first real bit of 'action' today, if you could call it that. Crazy Ivan got in a fight with Kuester today about his Booze-O-Mat. Apparently one of the crewmembers had stolen a couple bottles of booze from the machine after Ivan disabled the ID lock. Tell you the truth, I don't blame the thief. Everyone is going a little stir-crazy in here, and the bartender is being damn stingy with the alcohol. Either way, once they started to pick a fight, I had to take them down. It's a damn shame that we don't have a brig, though. I had to lock Ivan in a fuckin' freezer, for god's sake. Let's hope that we can keep our sanity together, at least for a while.
Entry Four - 10/06/2554: Jesus fucking Christ riding on a motorbike. These things the scientists are studying are terrifying! Fucking great huge purple bug things as tall as the ceiling, with blades for arms and drooling at the mouth. I don't think my taser will do jack shit against these damn things, but the eggheads say that they're safely contained. If they do, I have a feeling that it's only a matter of time before we're all screwed. These bastards look like walking death.
Entry Five - 18/06/2554: Finally caught who stole the booze from Kuester. It was that fuckin' loser assistant Steve! He was in the dorms, chugging his worries away. I took one of the bottles back to the barkeep, but no one has to know about this second one. I think I'm gonna enjoy this while watching tomorrow's Thunderdome match.
Entry Six - 19/06/2554: Oh, great. The chef is still sleeping, so we get Ivan's gruel for breakfast today. I overheard Sano and Douglas saying something about the aliens being restless, so we might get some action today. As long as it happens after the big game, I'm fine with it. I still got one beer to drink before I'm ready to die."; name = "Personal Log - Kenneth Cunningham"},/turf/simulated/floor{dir = 9; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{name = "MO19 Research"})
+"fP" = (/obj/structure/closet/secure_closet{icon_broken = "secbroken"; icon_closed = "sec"; icon_locked = "sec1"; icon_off = "secoff"; icon_opened = "secopen"; icon_state = "sec1"; locked = 1; name = "security officer's locker"; req_access_txt = "201"},/obj/item/clothing/suit/armor/vest,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/grenade/flashbang,/obj/item/weapon/storage/belt/security,/obj/item/weapon/reagent_containers/food/drinks/beer{pixel_x = -3; pixel_y = -2},/obj/machinery/alarm{frequency = 1439; locked = 0; pixel_y = 23; req_access = null},/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{name = "MO19 Research"})
+"fQ" = (/obj/structure/sign/poster{icon_state = "poster21_legit"; pixel_y = 32; serial_number = 21; subtype = 1},/turf/simulated/floor{dir = 5; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{name = "MO19 Research"})
+"fR" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fS" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{name = "MO19 Research"})
+"fT" = (/obj/structure/sign/biohazard{pixel_x = 32},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{name = "MO19 Research"})
+"fU" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fV" = (/obj/machinery/door/firedoor,/obj/structure/extinguisher_cabinet{pixel_x = 0; pixel_y = -29},/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{name = "MO19 Research"})
+"fW" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/closet/l3closet/scientist,/obj/structure/alien/weeds,/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{name = "MO19 Research"})
+"fX" = (/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/item/stack/cable_coil{amount = 1; icon_state = "coil_red1"; item_state = "coil_red1"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"fY" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood,/obj/item/stack/rods,/obj/item/weapon/shard{icon_state = "small"},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"fZ" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/gibs,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"ga" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"gb" = (/obj/structure/stool,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"gc" = (/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a2{name = "MO19 Research"})
+"gd" = (/obj/effect/decal/cleanable/oil,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"ge" = (/obj/structure/reagent_dispensers/peppertank{pixel_x = -30; pixel_y = 0},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{name = "MO19 Research"})
+"gf" = (/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{name = "MO19 Research"})
+"gg" = (/obj/machinery/door/airlock/glass_security{name = "Security Post"; req_access_txt = "201"},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"gh" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; icon_state = "ltrails_1"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{name = "MO19 Research"})
+"gi" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/firealarm{dir = 4; pixel_x = 28},/obj/structure/alien/weeds,/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{name = "MO19 Research"})
+"gj" = (/obj/structure/table,/obj/item/weapon/scalpel{pixel_y = 12},/obj/item/weapon/circular_saw,/obj/item/weapon/razor{pixel_y = 5},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "warnwhite"},/area/awaycontent/a2{name = "MO19 Research"})
+"gk" = (/obj/structure/alien/weeds/node,/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "warnwhite"},/area/awaycontent/a2{name = "MO19 Research"})
+"gl" = (/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "warnwhite"},/area/awaycontent/a2{name = "MO19 Research"})
+"gm" = (/obj/structure/table,/obj/item/device/mmi,/obj/item/device/mmi,/obj/item/device/mmi,/obj/structure/alien/weeds,/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "warnwhite"},/area/awaycontent/a2{name = "MO19 Research"})
+"gn" = (/obj/structure/sink{dir = 8; icon_state = "sink"; pixel_x = -12; pixel_y = 2},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"go" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/structure/alien/weeds,/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{name = "MO19 Research"})
+"gp" = (/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/window/reinforced{dir = 8},/obj/structure/disposalpipe/segment{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/structure/cable,/obj/structure/grille,/obj/structure/window/reinforced{dir = 4; layer = 2.9},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"gq" = (/obj/structure/disposalpipe/segment{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/structure/alien/weeds,/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"gr" = (/obj/structure/disposalpipe/segment{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; dir = 2; icon_state = "pipe-c"; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"gs" = (/obj/structure/table,/obj/effect/decal/cleanable/dirt,/obj/machinery/cell_charger,/obj/item/weapon/stock_parts/cell/high,/obj/item/device/radio/off,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"gt" = (/obj/structure/table,/obj/item/weapon/paper{info = "Ivan Volodin Stories:
Entry Won - 28/05/2554: Hello. I am Crazy Ivan. Boss say I must write. I do good job fixing outpost. Is very good job. Much better than mines. Many nice people. I cause no trouble.
Entry Too - 05/06/2554: I am finding problem with Booze-O-Mat. Is not problem. I solve very easy. Use yellow tool to make purple light go off. I am good engineer! Bartender will be very happy.
Entry Tree - 08/06/2554: Bartender is not happy. Security man is not happy. Cannot feel legs, is very cold in freezer. Is not good. Table is jammed into door, have no tools. Is very not good. But, on bright side, found meat! Shall chew to keep spirits up.
Entry Fore - 12/06/2554: Big nasty purple bug looked at me today. Make nervous. Blue wall wire can be broken, then bad thing happens. Very very bad thing. Man in orange spacesuit wave at me today too. He seem nice. Wonder who was?
Entry Fiv - 15/06/2554: I eat cornflakes today. Is good day. Sun shine for a while. Was nice. I also take ride on disposals chute. Was fun, but tiny. Get clog out of pipes, was vodka bottle. Is empty. This make many sads.
Entry Sex: 19/06/2554: Purple bugs jumpy today. When waved, get hiss. Maybe very bad. Maybe just ill. Do not know. Is science problem, is not engineer problem. I eat sandwich. Is glorious job. Wish to never end."; name = "Personal Log - Ivan Volodin"},/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a2{name = "MO19 Research"})
+"gu" = (/obj/machinery/light/small,/obj/structure/closet/toolcloset,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"gv" = (/obj/machinery/portable_atmospherics/canister/air,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"gw" = (/obj/machinery/computer/monitor,/obj/structure/cable,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"gx" = (/obj/structure/stool/bed/chair{dir = 4},/obj/machinery/newscaster/security_unit{pixel_x = -30; pixel_y = 0},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{name = "MO19 Research"})
+"gy" = (/obj/effect/decal/cleanable/blood/splatter,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"gz" = (/obj/item/stack/rods,/obj/item/weapon/shard{icon_state = "small"},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{name = "MO19 Research"})
+"gA" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/grille{density = 0; destroyed = 1; icon_state = "brokengrille"},/obj/item/stack/rods,/obj/item/stack/rods,/obj/item/weapon/shard,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"gB" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 6; icon_state = "ltrails_1"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{name = "MO19 Research"})
+"gC" = (/obj/structure/cable,/obj/machinery/power/apc{cell_type = 15000; dir = 4; locked = 0; name = "Worn-out APC"; pixel_x = 25; req_access = null; start_charge = 100},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{name = "MO19 Research"})
+"gD" = (/obj/structure/table,/obj/item/weapon/retractor,/obj/item/weapon/hemostat,/obj/structure/alien/weeds,/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"gE" = (/obj/structure/table,/obj/item/weapon/surgical_drapes,/obj/machinery/light/small{active_power_usage = 0; dir = 4; icon_state = "bulb-broken"; status = 2},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"gF" = (/obj/structure/filingcabinet/filingcabinet,/obj/machinery/light/small{active_power_usage = 0; dir = 8; icon_state = "bulb-broken"; status = 2},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 04/06/2554
Report: As expected, all that is left of the monkeys we sent in earlier is a group of xenomorph larvae. It is quite clear that the facehuggers are not selective in their hosts, and so far the gestation process has been shown to have a 100% success rate.
The larvae themselves have been behaving very differently from the lone larva we first observed, and despite shying away from humans they are clearly comfortable with others of their kind. Our previous suspicions on larvae have been confirmed with their demonstration of playfulness: they are not nearly as aggressive or violent when young, before molting to adulthood.
The majority of the play we observed involved a sort of hide-and-seek, and occasionally wrestling by tangling themselves and struggling out of it. While normally we would write these off as instinctual play for honing their skills when they molt, their growth period is so incredibly fast and they are still such adept killers that it would serve no practical purpose. The only explanation for this is perhaps to create bonds and friendships with each other, if that is even possible for such an incredibly hostile race. It may be that they are much more reasonable with each other than other life forms.
It had become clear that now was the best time to extract a xenomorph for dissecting, as these were all still larvae and the queen was still attached to its ovipositor and would be immobile. With the approval of the research director, we sent in our medical robot that had been dubbed 'Head Surgeon' into the containment pen, dropping the shields for only a fraction of a second to allow it entry. The larvae were cautious, but the curiosity of one had him within grabbing range of our robot. It was brought out and quickly euthanized through lethal injection, courtesy of our mechanical doctor."; name = "Larva Xenomorph Social Interactions & Capturing Procedure"},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 04/06/2554
Report: I have studied many interesting and diverse life-forms as a xenobiologist ranging from creatures as large as cows, to specimens too small see with the naked eye. This is by far the largest alien I have ever seen. The alien we were previously studying has molted and has become an absolutely enormous creature. Standing at over 15 feet tall and weighing in at likely two tons or more, the xenomorph queen is an absolutely breathtakingly large and cruel monster. Its behavior has changed drastically from when it was a drone, having become far more comfortable with sitting and staring at us, rather than smashing at the windows.
The queen, physiologically speaking, is fairly similar to the other xenomorphs, with a few key differences. Its enormous size demands large legs, while the back seems to be always hunched forward. The dorsal tubes on the back have changed to several large spikes, and we observed the alien now sports a second pair of smaller arms on its chest. The purpose of these secondary arms is still unknown. Finally, the queen's crown has become incredibly large, with what seems to be a retractable slot to hide its head in. The dome appears to be extremely thick near the front, and will likely be able to resist a lot of trauma. Despite the enormous size it has grown to, it is not that much slower than it used to be.
After two hours of doing relatively nothing but staring, the queen began to produce an unusually large amount of resin and weeds, quickly shaping up a large nest that it then hid behind. It then proceeded to smash out all the lights, leaving us with very little to see with our cameras. When we looked through the back cameras, we had discovered that it had grown a large ovipositor, and was releasing large eggs onto the ground. This had us all in agreement that this stage of the life cycle was the queen.
Over the next few hours, the eggs grew to their full sizes, and we provided the subject with new monkey hosts. When they approached the eggs, they opened to release more facehuggers. It seems that we have observed the full cycle of reproduction for this species. We can expect more larvae in the next few hours."; name = "Queen Xenomorph Physiology & Behavior Observation"},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 03/06/2554
Report: The other scientists and I can hardly believe our eyes. The snake-like larva has molted into a 7 foot tall insectoid nightmare in just a few hours. It's obvious now as to why such heavy duty containment was needed. It immediately tried to escape however by flinging itself at the window in a flurry of swipes and stabs. It seems its behavior has returned to a state that is very similar to the facehugger, though I doubt with the same intent! Thankfully, our glass and shields have shown to be more than sturdy enough for such a violent creature, and so far, any attempts at the creature escaping have been in vain.
As for its physiology, the creature has an elongated head with what appears to be have an exoskeleton resembling an external rib-cage on the torso. The alien is also fairly skinny with a lean body. The little amount of meat on the alien appears to be entirely muscle. We assume this makes it deceptively strong, while remaining agile at the same time. One of the most interesting things we have seen is its pharyngeal jaw. It has some what of an inner mouth capable of being fired externally at extremely high speeds. It has already caused many dents in the walls and a few small cracks in the window with it. The alien also has a couple of dorsal tubes on its back, their purpose unknown. Finally, this monster sports a long ridged tail, complete with a large and extremely sharp blade at the tip.
Normally I would be absolutely terrified of something like this, but I'm putting my trust in Nanotrasen with the containment. After all, they wouldn't build a cell that could fail to contain its subject, would they?"; name = "Adult Xenomorph Physiology & Behavior Observation"},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 03/06/2554
Report: When the larva first emerged from the chest of the monkey, it seemed very curious. It would wander around aimlessly for awhile and then sit still. We are unable to determine the gender of the larva, or even determine if it has a gender. After some time had passed, it seemed to lose interest in its surroundings and sat mostly still while occasionally wagging its tail. We decided to throw in a live mouse to see if it would consume it. The larva quickly attacked and ate the mouse and seemed to get larger very suddenly, this suggests that the larvae are capable of metabolizing and directing all the energy towards growth at previously thought impossible speeds. It is a shame that we cannot observe the process more closely, as we do not currently know how dangerous or violent this creature is or will become as it matures fully.
It is tempting to imagine the possibilities of utilizing such a mechanism. The capability of skipping years of growth time for children, repairing bodily damage in a matter of moments, even its usage in existing cloning technology."; name = "Larva Xenomorph Physiology & Behavior Observation"},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 03/06/2554
Report: The test subject we were provided with truly is alien. It is a small spider-like creature with bony legs leading to a smooth body. It has a long tail connected to it, and it has shown extremely aggressive behavior by flinging its entire body at the glass and shields to no avail. While doing so, we noticed there was a small pink hole in the middle of the body.
When we sent in a monkey through the crude but effective disposal tube, the alien immediately jumped at its face and latched on. The monkey was quickly suffocated by its constricting tail, unable to pry off the fingers. The monkey at first seemed to be dead, but was observed to be breathing. The recently named alien 'facehugger' fell off dead and curled its legs up like a spider moments after it had finished with the monkey's body.
While the monkey appeared to be unharmed, we kept it in the cell for a couple more hours until we were horrified to discover it screaming out in pain as a snake-like creature erupted from the monkey's chest! It appears that the 'facehugger' is only the start of this life cycle. The impregnation cycle involving the creatures growing inside the chests of their hosts seems to only be the beginning."; name = "'Facehugger' Xenomorph Physiology & Behavior Observation"},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"gG" = (/obj/structure/table/reinforced,/obj/item/device/radio/off,/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{name = "MO19 Research"})
+"gH" = (/obj/structure/cable,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/grille,/obj/structure/window/reinforced{dir = 4; layer = 2.9},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"gI" = (/obj/structure/disposalpipe/segment{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"gJ" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/item/stack/rods,/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a2{name = "MO19 Research"})
+"gK" = (/obj/machinery/door_control{id = "Awaybiohazard"; name = "Biohazard Shutter Control"; pixel_x = -25; pixel_y = 0; req_access_txt = "201"},/obj/machinery/light/small{dir = 8},/obj/structure/table,/obj/item/device/radio/off,/obj/item/weapon/screwdriver{pixel_y = 10},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{name = "MO19 Research"})
+"gL" = (/obj/structure/stool/bed/chair/office/dark,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"gM" = (/obj/structure/table,/obj/machinery/recharger{pixel_y = 4},/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{name = "MO19 Research"})
+"gN" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"gO" = (/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{name = "MO19 Research"})
+"gP" = (/obj/machinery/light{active_power_usage = 0; dir = 4; icon_state = "tube-broken"; status = 2},/obj/machinery/alarm{dir = 8; frequency = 1439; locked = 0; pixel_x = 23; pixel_y = 0; req_access = null},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{name = "MO19 Research"})
+"gQ" = (/obj/structure/optable,/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{name = "MO19 Research"})
+"gR" = (/obj/machinery/computer/operating,/obj/structure/alien/weeds,/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{name = "MO19 Research"})
+"gS" = (/obj/structure/table,/obj/item/clothing/gloves/latex,/obj/item/clothing/mask/surgical,/obj/item/clothing/suit/apron/surgical,/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{name = "MO19 Research"})
+"gT" = (/obj/structure/filingcabinet/filingcabinet,/obj/item/weapon/paper{info = "Researcher: Dr. Mark Douglas Date: 17/06/2554
Report: Earlier today we have observed a new phenomenon with our subjects. While feeding them our last monkey subject and throwing out the box, the aliens merely looked at us instead of infecting the monkey right away. They looked to be collectively distressed as they would no longer be given hosts, where instead we would move to the next phase of the experiment. When I glanced at the gas tanks and piping leading to their cell, I looked back to see all of them were up against the glass, even the queen! It was as if they all understood what was going to happen, even though we knew only the queen had the cognitive capability to do so.
The only explanation for this is a form of communication between the aliens, but we have seen no such action take place anywhere in the cell until now. We also know that regular drone and hunter xenomorphs have no personality or instinct to survive by themselves. Perhaps the queen has a direct link to them? A form of a commander or overseer that controls their every move? A hivemind?"; name = "The Hivemind Hypothesis"},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 08/06/2554
Report: The xenomorphs we have come to study here are a remarkable species. They are almost universally aggressive across all castes, showing no remorse or guilt or pause before or after acts of violence. They appear to be a species entirely designed to kill. Oddly enough, even their method of reproduction is a brutal two-for-one method of birthing a new xenomorph and killing its host.
The lone xenomorph we studied only five days ago showed little sign of intelligence. Only a simple drone that flung itself at the safety glass and shields repeatedly and thankfully without success. Once the drone molted into a queen, it became much more calm and calculating, merely looking at us and waiting while building its nest. As the hive grew in size and in numbers, so too did the intelligence of the common hunter and drone. We are still researching how they can communicate with one another and the relationship between the different castes and the queen. We will continue to update our research as we learn more about the species."; name = "A Preliminary Study of Alien Behavior"},/obj/item/weapon/paper{info = "Researcher: Dr. Mark Douglas Date: 06/06/2554
Report: While observing the growing number of aliens in the containment cell, we began to notice subtle differences that were consistently repeating. Like ants, these creatures clearly have different specialized variations that determine their roles in the hive. We have dubbed the three currently observed castes as Hunters, Drones, and Sentinels.
Hunters have been observed to be by far the most aggressive and agile of the three, constantly running on every surface and frequently swiping at the windows. They are also remarkably good at camouflaging themselves in darkness and on their resin structures, appearing almost invisible to the unwary observer. They are always the first to reach the monkeys we send in leading us to believe that this caste is primarily used for finding and retrieving hosts.
Drones on the other hand are much more docile and seem more shy by comparison, though not any less aggressive than the other castes. They have been observed to have a much wider head and lack dorsal tubes. They have shown to be less agile and visibly more fragile than any other caste. The drone however has never been observed to interact with the monkeys directly and instead preferring maintenance of the hive by building walls of resin and moving eggs around the nest. As far as we know, we have only ever observed a drone become a queen, and we have no way of knowing if the other castes have that capability.
Lastly, we have the Sentinels, which appear at first glance to be the guards of the hive. They have so far been only observed to remain near the queen and the eggs, frequently curled up against the walls. We have only observed one instance where they have interacted with a monkey who strayed too closely to the queen, and was pounced and held down immediately until it was applied with a facehugger. Their lack of movement makes it difficult to determine their exact purpose as guards, sentries, or other role."; name = "The Xenomorph 'Castes'"},/obj/item/weapon/paper{info = "Researcher: Dr. Mark Douglas Date: 04/06/2554
Report: After an extremely dangerous, time consuming and costly dissection, we have managed to record and identify several of the organs inside of the first stage of the xenomorph cycle: the larva. This procedure took an extensive amount of time because these creatures have incredibly, almost-comically acidic blood that can melt through almost anything in a few moments. We had to use over a dozen scalpels and retractors to complete the autopsy.
The larva seems to possess far fewer and quite different organs than that of a human. There is a stomach, with no digestive tract, a heart, which seems to lack any blood-oxygen circulation purpose, and an elongated brain, even though its as dumb as any large cat. It also lacks any liver, kidneys, or other basic organs.
We can't determine the exact nature of how these creatures grow, nor if they gain organs as they become adults. The larger breeds of xenomorph are too dangerous to kill and capture to give us an accurate answer to these questions. All that we can conclude is that being able to function with so little and yet be so deadly means that these creatures are highly evolved and likely to be extremely durable to various hazards that would otherwise be lethal to humans."; name = "Larva Xenomorph Autopsy Report"},/obj/structure/alien/weeds,/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"gU" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"gV" = (/obj/effect/decal/cleanable/dirt,/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{name = "MO19 Research"})
+"gW" = (/obj/machinery/shieldwallgen{locked = 0; req_access = null},/obj/structure/cable,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"gX" = (/obj/structure/disposaloutlet{desc = "An outlet for the pneumatic disposal system. This one has been applied with an acid-proof coating."; dir = 1; name = "Acid-Proof disposal outlet"; unacidable = 1},/obj/structure/disposalpipe/trunk{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; dir = 1; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"gY" = (/obj/machinery/light{active_power_usage = 0; dir = 2; icon_state = "tube-broken"; status = 2},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"gZ" = (/obj/machinery/sparker{desc = "A wall-mounted ignition device. This one has been applied with an acid-proof coating."; id = "awayxenobio"; name = "Acid-Proof mounted igniter"; pixel_x = 0; pixel_y = -25; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{name = "MO19 Research"})
+"ha" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/effect/decal/cleanable/cobweb,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"hb" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"hc" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"hd" = (/obj/structure/table,/obj/item/weapon/book/manual/wiki/security_space_law,/obj/machinery/computer/security/telescreen/entertainment{pixel_x = -32; pixel_y = 0},/turf/simulated/floor{dir = 10; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{name = "MO19 Research"})
+"he" = (/obj/structure/table,/obj/item/weapon/folder/red,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{name = "MO19 Research"})
+"hf" = (/obj/structure/table,/obj/item/weapon/paper_bin{pixel_x = 1; pixel_y = 9},/obj/item/weapon/pen,/turf/simulated/floor{dir = 6; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{name = "MO19 Research"})
+"hg" = (/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"hh" = (/obj/structure/closet/secure_closet{icon_broken = "secureresbroken"; icon_closed = "secureres"; icon_locked = "secureres1"; icon_off = "secureresoff"; icon_opened = "secureresopen"; icon_state = "secureres"; locked = 0; name = "scientist's locker"; req_access_txt = "201"},/obj/item/clothing/suit/labcoat,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"hi" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"hj" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"hk" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"hl" = (/obj/structure/window/reinforced,/obj/structure/closet/secure_closet{icon_broken = "secureresbroken"; icon_closed = "secureres"; icon_locked = "secureres1"; icon_off = "secureresoff"; icon_opened = "secureresopen"; icon_state = "secureres1"; locked = 1; name = "scientist's locker"; req_access_txt = "201"},/obj/item/clothing/suit/labcoat,/obj/item/weapon/tank/air,/obj/item/clothing/mask/gas,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"hm" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"hn" = (/obj/machinery/vending/medical{req_access_txt = "201"},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{name = "MO19 Research"})
+"ho" = (/obj/structure/closet/crate/bin,/obj/item/clothing/gloves/latex,/obj/item/trash/chips,/obj/effect/decal/cleanable/dirt,/obj/machinery/light/small{active_power_usage = 0; dir = 1; icon_state = "bulb-broken"; status = 2},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{name = "MO19 Research"})
+"hp" = (/obj/structure/table,/obj/item/weapon/storage/box/gloves{pixel_x = 0; pixel_y = 0},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitecorner"},/area/awaycontent/a2{name = "MO19 Research"})
+"hq" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/effect/decal/cleanable/oil,/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a2{name = "MO19 Research"})
+"hr" = (/obj/structure/closet/secure_closet{icon_broken = "rdsecurebroken"; icon_closed = "rdsecure"; icon_locked = "rdsecure1"; icon_off = "rdsecureoff"; icon_opened = "rdsecureopen"; icon_state = "rdsecure1"; locked = 1; name = "\proper research director's locker"; req_access_txt = "201"},/obj/item/weapon/storage/backpack/satchel_tox,/obj/item/clothing/gloves/latex,/obj/item/clothing/suit/labcoat/science,/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{name = "MO19 Research"})
+"hs" = (/obj/structure/table,/obj/item/weapon/cartridge/signal/toxins,/obj/item/weapon/cartridge/signal/toxins{pixel_x = -4; pixel_y = 2},/obj/machinery/firealarm{dir = 2; pixel_y = 24},/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{name = "MO19 Research"})
+"ht" = (/obj/structure/filingcabinet/chestdrawer,/obj/machinery/light/small{active_power_usage = 0; dir = 1; icon_state = "bulb-broken"; status = 2},/obj/machinery/alarm{frequency = 1439; locked = 0; pixel_y = 23; req_access = null},/obj/item/weapon/paper{info = "Personal Log for Research Director Gerald Rosswell
Entry One - 17/05/2554: You know, I can't believe I took this position so suddenly. I saw that corporate needed a research director for one of it's outposts and thought it would be a cakewalk, there isn't going to be a lot of research to be done on a tiny outpost. Mainly just running scans on the gas giant we are orbiting or some basic RnD. However, they conveniently forgot to tell me that me and my science staff would have to pull double duty as medical staff and that there is no one higher up on the chain of command here, so I get to pull triple duty as acting captain as well! This shit is probably allowed in some 3 point fine print buried underneath the literally thousands of pages of contracts. Well, at least the research will be easy work.
Entry Two - 25/05/2554: Well, we all expected it at the outpost, CentComm has decided to completely change what research we are doing. They've decided that we should be research the species known as 'xenomporphs'. They announced this change 4 days ago and along with it, sadly, the termination of our current science staff barring me. Not to mention the constant noise made by the construction detail they sent to staple on an xenobiology lab ensuring no one has been able to sleep decently ever since they announced the shift. To make matters worse our current security guard actually died of a heart attack today. Just goes to show that 75 year old men shouldn't be security guards. Still can't believe that they decided to do this major change less than a month after the outpost was established.
Entry Three - 27/05/2554: The new security guard arrived today. Apparently transferred here from the research station that also is orbiting the gas giant. He seems to be rather angry about his transfer. Considering the rumors I've heard about the research station he's probably caught off guard by the fact that Steve hasn't tried to force an IED down his throat.
Entry Four - 06/06/2554: My requests for additional security and containment measures for the 'xenomorph' has been denied. Does Central Command not notice how dangerous these creatures are? The only thing keeping them in is a force field, a minor problem with the power grid and the entire hive is loose. What would stop them then, the lone security guard with a dinky little taser? Kenneth can barely handle a short-tempered engineer. We are under equipped and under staffed, we are inevitably going to be destroyed unless we get the equipment and staff we need.
Entry Five - 10/06/2554: Cunningham got a good look at the xenomorph in containment. He was frightened for the rest of the day, rather amusing if it wasn't for the fact that we are all trapped on this scrap heap with naught but a force field keeping those xenomorphs in.
Entry Six - 17/06/2554: The reactions from the specimens today has shown that they possess strange mental properties. Mark hypothesizes that they possibly have a sort of hive mind, while nothing is certain this would explain how xenomorphs seem to have vastly increased intellect when a 'queen' is present. Of course, to test this hypothesis would require many complicated procedures which we will not be able to undertake. But we do not know the full extend of the xenomorph mind, it may or may not be able to find a way to circumvent our containment system. I will resend my request for additional security measures along with this new found information."; name = "Personal Log - Gerald Rosswell"},/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{name = "MO19 Research"})
+"hu" = (/obj/structure/closet/crate/bin,/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{name = "MO19 Research"})
+"hv" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/machinery/door/poddoor{id = "AwayRD"; layer = 2.9; name = "privacy shutter"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"hw" = (/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{name = "MO19 Research"})
+"hx" = (/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{name = "MO19 Research"})
+"hy" = (/obj/structure/window/reinforced,/obj/structure/grille{density = 0; destroyed = 1; icon_state = "brokengrille"},/obj/item/stack/rods,/obj/item/stack/rods,/obj/item/weapon/shard{icon_state = "medium"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{name = "MO19 Research"})
+"hz" = (/obj/item/stack/rods,/obj/item/weapon/shard{icon_state = "small"},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"hA" = (/obj/effect/decal/cleanable/robot_debris,/obj/effect/decal/cleanable/oil,/obj/item/weapon/storage/firstaid/regular{empty = 1; name = "First-Aid (empty)"},/obj/item/device/healthanalyzer{pixel_x = 6; pixel_y = -5},/obj/item/device/assembly/prox_sensor{pixel_x = -5; pixel_y = -2},/obj/item/robot_parts/l_arm,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "white"},/area/awaycontent/a2{name = "MO19 Research"})
+"hB" = (/obj/structure/table,/obj/item/weapon/storage/firstaid/fire{pixel_x = 0; pixel_y = 0},/obj/machinery/firealarm{dir = 4; pixel_x = 28},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{name = "MO19 Research"})
+"hC" = (/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{name = "MO19 Research"})
+"hD" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{name = "MO19 Research"})
+"hE" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/command{density = 0; emagged = 1; icon_state = "door_open"; locked = 1; name = "Research Director's Office"; opacity = 0; req_access_txt = "201"; req_one_access_txt = "0"},/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{name = "MO19 Research"})
+"hF" = (/obj/structure/noticeboard{dir = 1; pixel_y = -32},/obj/machinery/light/small{active_power_usage = 0; dir = 2; icon_state = "bulb-broken"; status = 2},/obj/item/weapon/paper{info = "
In The Event of Xenobiology Breach: Evacuate staff, Lock down Xenobiology, Notify on-site superiors and/or Central Command immediatly.
"
@@ -748,7 +749,7 @@ var/global/datum/controller/supply_shuttle/supply_shuttle
temp += " Main Menu"
*/
else if (href_list["viewrequests"])
- temp = "Main Menu
Current requests:
"
+ temp = "Current requests:
"
for(var/S in supply_shuttle.requestlist)
var/datum/supply_order/SO = S
temp += "#[SO.ordernum] - [SO.object.name] requested by [SO.orderedby] [supply_shuttle.moving ? "":supply_shuttle.at_station ? "":"ApproveRemove"] "
@@ -793,5 +794,7 @@ var/global/datum/controller/supply_shuttle/supply_shuttle
frequency.post_signal(src, status_signal)
+/obj/machinery/computer/supplycomp/say_quote(text)
+ return "flashes, \"[text]\""
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index e98fec043ed..4f8b2e771e7 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -81,7 +81,7 @@
var/record_id_num = 1001
/obj/effect/datacore/proc/manifest_inject(var/mob/living/carbon/human/H)
- if(H.mind && (H.mind.assigned_role != "MODE"))
+ if(H.mind && (H.mind.need_job_assign))
var/assignment
if(H.mind.assigned_role)
assignment = H.mind.assigned_role
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index 2fb8c9bd852..c072fc6ae39 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -639,7 +639,7 @@ body
reagent_options[R.name] = r_id
if(reagent_options.len)
- reagent_options = sortAssoc(reagent_options)
+ sortList(reagent_options)
reagent_options.Insert(1, "CANCEL")
var/chosen = input(usr, "Choose a reagent to add.", "Choose a reagent.") in reagent_options
diff --git a/code/datums/disease.dm b/code/datums/disease.dm
index 3a37ce32022..d7d98405710 100644
--- a/code/datums/disease.dm
+++ b/code/datums/disease.dm
@@ -52,6 +52,8 @@ var/list/diseases = typesof(/datum/disease) - /datum/disease
var/requires = 0
var/list/required_limb = list()
+ var/const/non_threat = "Non-Threat"
+
/datum/disease/proc/stage_act()
var/cure_present = has_cure()
@@ -204,7 +206,7 @@ var/list/diseases = typesof(/datum/disease) - /datum/disease
/datum/disease/proc/GetDiseaseID()
return src.type
-/*
+
/datum/disease/Del()
active_diseases.Remove(src)
-*/
+ ..()
diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm
index 52e20c2c07b..b356109b1b2 100644
--- a/code/datums/diseases/advance/advance.dm
+++ b/code/datums/diseases/advance/advance.dm
@@ -182,7 +182,7 @@ var/list/advance_cures = list(
CRASH("We did not have any symptoms before generating properties.")
return
- var/list/properties = list("resistance" = 1, "stealth" = 1, "stage_rate" = 1, "transmittable" = 1, "severity" = 1)
+ var/list/properties = list("resistance" = 1, "stealth" = 1, "stage_rate" = 1, "transmittable" = 1, "severity" = 0)
for(var/datum/symptom/S in symptoms)
@@ -190,7 +190,7 @@ var/list/advance_cures = list(
properties["stealth"] += S.stealth
properties["stage_rate"] += S.stage_speed
properties["transmittable"] += S.transmittable
- properties["severity"] = max(properties["severity"], S.level) // severity is based on the highest level symptom
+ properties["severity"] = max(properties["severity"], S.severity) // severity is based on the highest severity symptom
return properties
@@ -234,7 +234,7 @@ var/list/advance_cures = list(
switch(level_sev)
if(-INFINITY to 0)
- severity = "Non-Threat"
+ severity = non_threat
if(1)
severity = "Minor"
if(2)
diff --git a/code/datums/diseases/advance/symptoms/beard.dm b/code/datums/diseases/advance/symptoms/beard.dm
index 3ef4df27119..d56c8421f2d 100644
--- a/code/datums/diseases/advance/symptoms/beard.dm
+++ b/code/datums/diseases/advance/symptoms/beard.dm
@@ -22,6 +22,7 @@ BONUS
stage_speed = -3
transmittable = -1
level = 4
+ severity = 1
/datum/symptom/beard/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/choking.dm b/code/datums/diseases/advance/symptoms/choking.dm
index f5b21f08dca..e068adf4835 100644
--- a/code/datums/diseases/advance/symptoms/choking.dm
+++ b/code/datums/diseases/advance/symptoms/choking.dm
@@ -23,6 +23,7 @@ Bonus
stage_speed = -2
transmittable = -4
level = 3
+ severity = 3
/datum/symptom/choking/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/confusion.dm b/code/datums/diseases/advance/symptoms/confusion.dm
index 9bc2b6769c2..0fbc941a32f 100644
--- a/code/datums/diseases/advance/symptoms/confusion.dm
+++ b/code/datums/diseases/advance/symptoms/confusion.dm
@@ -23,6 +23,7 @@ Bonus
stage_speed = -3
transmittable = 0
level = 4
+ severity = 2
/datum/symptom/confusion/Activate(var/datum/disease/advance/A)
diff --git a/code/datums/diseases/advance/symptoms/cough.dm b/code/datums/diseases/advance/symptoms/cough.dm
index 5e0675c40c4..2c50271aa92 100644
--- a/code/datums/diseases/advance/symptoms/cough.dm
+++ b/code/datums/diseases/advance/symptoms/cough.dm
@@ -23,6 +23,7 @@ BONUS
stage_speed = 1
transmittable = 2
level = 1
+ severity = 1
/datum/symptom/cough/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/deafness.dm b/code/datums/diseases/advance/symptoms/deafness.dm
index 2b210fc1f60..a5394222876 100644
--- a/code/datums/diseases/advance/symptoms/deafness.dm
+++ b/code/datums/diseases/advance/symptoms/deafness.dm
@@ -23,6 +23,7 @@ Bonus
stage_speed = -1
transmittable = -3
level = 4
+ severity = 3
/datum/symptom/deafness/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/dizzy.dm b/code/datums/diseases/advance/symptoms/dizzy.dm
index 14a01866ff4..a7109a316ac 100644
--- a/code/datums/diseases/advance/symptoms/dizzy.dm
+++ b/code/datums/diseases/advance/symptoms/dizzy.dm
@@ -23,6 +23,7 @@ Bonus
stage_speed = -3
transmittable = -1
level = 4
+ severity = 2
/datum/symptom/dizzy/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/fever.dm b/code/datums/diseases/advance/symptoms/fever.dm
index f24e789810f..749bab09fea 100644
--- a/code/datums/diseases/advance/symptoms/fever.dm
+++ b/code/datums/diseases/advance/symptoms/fever.dm
@@ -23,6 +23,7 @@ Bonus
stage_speed = 3
transmittable = 2
level = 2
+ severity = 2
/datum/symptom/fever/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/flesh_eating.dm b/code/datums/diseases/advance/symptoms/flesh_eating.dm
index 2d8a9027613..8c71d05f2bd 100644
--- a/code/datums/diseases/advance/symptoms/flesh_eating.dm
+++ b/code/datums/diseases/advance/symptoms/flesh_eating.dm
@@ -23,6 +23,7 @@ Bonus
stage_speed = 0
transmittable = -4
level = 6
+ severity = 5
/datum/symptom/flesh_eating/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/genetics.dm b/code/datums/diseases/advance/symptoms/genetics.dm
index fdf3975ecba..065bf9d3ed1 100644
--- a/code/datums/diseases/advance/symptoms/genetics.dm
+++ b/code/datums/diseases/advance/symptoms/genetics.dm
@@ -23,6 +23,7 @@ Bonus
stage_speed = 0
transmittable = -3
level = 6
+ severity = 3
var/good_mutations = 0
var/archived_dna = null
@@ -78,4 +79,5 @@ Bonus
stage_speed = -7
transmittable = -7
level = 6
- good_mutations = 1
\ No newline at end of file
+ good_mutations = 1
+ severity = 0
\ No newline at end of file
diff --git a/code/datums/diseases/advance/symptoms/hallucigen.dm b/code/datums/diseases/advance/symptoms/hallucigen.dm
index 5e0f0aa4731..4854b8d3261 100644
--- a/code/datums/diseases/advance/symptoms/hallucigen.dm
+++ b/code/datums/diseases/advance/symptoms/hallucigen.dm
@@ -23,6 +23,7 @@ Bonus
stage_speed = -3
transmittable = -1
level = 5
+ severity = 3
/datum/symptom/hallucigen/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/headache.dm b/code/datums/diseases/advance/symptoms/headache.dm
index 691b7bf3122..abbb0c44f9b 100644
--- a/code/datums/diseases/advance/symptoms/headache.dm
+++ b/code/datums/diseases/advance/symptoms/headache.dm
@@ -24,6 +24,7 @@ BONUS
stage_speed = 2
transmittable = 0
level = 1
+ severity = 1
/datum/symptom/headache/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/itching.dm b/code/datums/diseases/advance/symptoms/itching.dm
index f4b69c364ab..e7302c4345a 100644
--- a/code/datums/diseases/advance/symptoms/itching.dm
+++ b/code/datums/diseases/advance/symptoms/itching.dm
@@ -24,6 +24,7 @@ BONUS
stage_speed = 3
transmittable = 1
level = 1
+ severity = 1
/datum/symptom/itching/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/shedding.dm b/code/datums/diseases/advance/symptoms/shedding.dm
index 69ffefad263..d1c2317b868 100644
--- a/code/datums/diseases/advance/symptoms/shedding.dm
+++ b/code/datums/diseases/advance/symptoms/shedding.dm
@@ -22,6 +22,7 @@ BONUS
stage_speed = -1
transmittable = 2
level = 4
+ severity = 1
/datum/symptom/shedding/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/shivering.dm b/code/datums/diseases/advance/symptoms/shivering.dm
index e87b395b13a..ac13329d12c 100644
--- a/code/datums/diseases/advance/symptoms/shivering.dm
+++ b/code/datums/diseases/advance/symptoms/shivering.dm
@@ -23,6 +23,7 @@ Bonus
stage_speed = 2
transmittable = 2
level = 2
+ severity = 2
/datum/symptom/shivering/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/sneeze.dm b/code/datums/diseases/advance/symptoms/sneeze.dm
index 155e71839a4..f26a0c78b66 100644
--- a/code/datums/diseases/advance/symptoms/sneeze.dm
+++ b/code/datums/diseases/advance/symptoms/sneeze.dm
@@ -24,6 +24,7 @@ Bonus
stage_speed = 0
transmittable = 4
level = 1
+ severity = 1
/datum/symptom/sneeze/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/symptoms.dm b/code/datums/diseases/advance/symptoms/symptoms.dm
index 349809b973e..4b06cb505db 100644
--- a/code/datums/diseases/advance/symptoms/symptoms.dm
+++ b/code/datums/diseases/advance/symptoms/symptoms.dm
@@ -12,8 +12,10 @@ var/global/const/SYMPTOM_ACTIVATION_PROB = 3
var/resistance = 0
var/stage_speed = 0
var/transmittable = 0
- // The type level of the symptom. Higher is more lethal and harder to generate.
+ // The type level of the symptom. Higher is harder to generate.
var/level = 0
+ // The severity level of the symptom. Higher is more dangerous.
+ var/severity = 0
// The hash tag for our diseases, we will add it up with our other symptoms to get a unique id! ID MUST BE UNIQUE!!!
var/id = ""
diff --git a/code/datums/diseases/advance/symptoms/visionloss.dm b/code/datums/diseases/advance/symptoms/visionloss.dm
index 466809d32e8..47303b9643a 100644
--- a/code/datums/diseases/advance/symptoms/visionloss.dm
+++ b/code/datums/diseases/advance/symptoms/visionloss.dm
@@ -23,6 +23,7 @@ Bonus
stage_speed = -4
transmittable = -3
level = 5
+ severity = 4
/datum/symptom/visionloss/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/vitiligo.dm b/code/datums/diseases/advance/symptoms/vitiligo.dm
index 21036166dbe..e24be2c36b5 100644
--- a/code/datums/diseases/advance/symptoms/vitiligo.dm
+++ b/code/datums/diseases/advance/symptoms/vitiligo.dm
@@ -22,6 +22,7 @@ BONUS
stage_speed = -1
transmittable = -2
level = 5
+ severity = 1
/datum/symptom/vitiligo/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/voice_change.dm b/code/datums/diseases/advance/symptoms/voice_change.dm
index 655cbc65c10..02f352f3550 100644
--- a/code/datums/diseases/advance/symptoms/voice_change.dm
+++ b/code/datums/diseases/advance/symptoms/voice_change.dm
@@ -23,6 +23,7 @@ Bonus
stage_speed = -3
transmittable = -1
level = 6
+ severity = 2
/datum/symptom/voice_change/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/advance/symptoms/vomit.dm b/code/datums/diseases/advance/symptoms/vomit.dm
index 79a3d82c7c4..67f53564deb 100644
--- a/code/datums/diseases/advance/symptoms/vomit.dm
+++ b/code/datums/diseases/advance/symptoms/vomit.dm
@@ -27,6 +27,7 @@ Bonus
stage_speed = 0
transmittable = 1
level = 3
+ severity = 4
/datum/symptom/vomit/Activate(var/datum/disease/advance/A)
..()
@@ -78,6 +79,7 @@ Bonus
stage_speed = -1
transmittable = 1
level = 4
+ severity = 5
/datum/symptom/vomit/blood/Vomit(var/mob/living/M)
diff --git a/code/datums/diseases/advance/symptoms/weight.dm b/code/datums/diseases/advance/symptoms/weight.dm
index 911efef1a7d..3734176978c 100644
--- a/code/datums/diseases/advance/symptoms/weight.dm
+++ b/code/datums/diseases/advance/symptoms/weight.dm
@@ -23,6 +23,7 @@ Bonus
stage_speed = -2
transmittable = -2
level = 4
+ severity = 1
/datum/symptom/weight_gain/Activate(var/datum/disease/advance/A)
..()
@@ -64,6 +65,7 @@ Bonus
stage_speed = -2
transmittable = -2
level = 3
+ severity = 1
/datum/symptom/weight_loss/Activate(var/datum/disease/advance/A)
..()
diff --git a/code/datums/diseases/appendicitis.dm b/code/datums/diseases/appendicitis.dm
index f5d6ceef2bd..8a628eefd62 100644
--- a/code/datums/diseases/appendicitis.dm
+++ b/code/datums/diseases/appendicitis.dm
@@ -9,7 +9,7 @@
permeability_mod = 1
contagious_period = 9001 //slightly hacky, but hey! whatever works, right?
desc = "If left untreated the subject will become very weak, and may vomit often."
- severity = "Medium"
+ severity = "Dangerous!"
longevity = 1000
hidden = list(0, 1)
requires = 1
@@ -35,7 +35,8 @@
if(prob(1))
if (affected_mob.nutrition > 100)
affected_mob.Stun(rand(4,6))
- affected_mob.show_message("[affected_mob] throws up!")
+ affected_mob.visible_message("[affected_mob] throws up!", \
+ "[affected_mob] throws up!")
playsound(affected_mob.loc, 'sound/effects/splat.ogg', 50, 1)
var/turf/location = affected_mob.loc
if(istype(location, /turf/simulated))
diff --git a/code/datums/diseases/brainrot.dm b/code/datums/diseases/brainrot.dm
index 782e518ffd7..971755d070d 100644
--- a/code/datums/diseases/brainrot.dm
+++ b/code/datums/diseases/brainrot.dm
@@ -10,7 +10,7 @@
curable = 0
cure_chance = 15//higher chance to cure, since two reagents are required
desc = "This disease destroys the braincells, causing brain fever, brain necrosis and general intoxication."
- severity = "Major"
+ severity = "Dangerous!"
requires = 1
required_limb = list(/obj/item/organ/limb/head)
diff --git a/code/datums/diseases/cold9.dm b/code/datums/diseases/cold9.dm
index e22016eb01f..0e7847588fa 100644
--- a/code/datums/diseases/cold9.dm
+++ b/code/datums/diseases/cold9.dm
@@ -8,7 +8,7 @@
agent = "ICE9-rhinovirus"
affected_species = list("Human")
desc = "If left untreated the subject will slow, as if partly frozen."
- severity = "Moderate"
+ severity = "Medium"
/datum/disease/cold9/stage_act()
..()
diff --git a/code/datums/diseases/fake_gbs.dm b/code/datums/diseases/fake_gbs.dm
index a56e62c28d0..9700cd120a5 100644
--- a/code/datums/diseases/fake_gbs.dm
+++ b/code/datums/diseases/fake_gbs.dm
@@ -8,7 +8,7 @@
agent = "Gravitokinetic Bipotential SADS-"
affected_species = list("Human", "Monkey")
desc = "If left untreated death will occur."
- severity = "Major"
+ severity = "BIOHAZARD THREAT!"
/datum/disease/fake_gbs/stage_act()
..()
diff --git a/code/datums/diseases/fluspanish.dm b/code/datums/diseases/fluspanish.dm
index ef85ab1961d..6d8a9c9a290 100644
--- a/code/datums/diseases/fluspanish.dm
+++ b/code/datums/diseases/fluspanish.dm
@@ -9,7 +9,7 @@
affected_species = list("Human")
permeability_mod = 0.75
desc = "If left untreated the subject will burn to death for being a heretic."
- severity = "Serious"
+ severity = "Dangerous!"
/datum/disease/inquisition/stage_act()
..()
diff --git a/code/datums/diseases/gbs.dm b/code/datums/diseases/gbs.dm
index 9a677b7111c..9579d8f2036 100644
--- a/code/datums/diseases/gbs.dm
+++ b/code/datums/diseases/gbs.dm
@@ -10,6 +10,7 @@
affected_species = list("Human")
curable = 0
permeability_mod = 1
+ severity = "BIOHAZARD THREAT!"
/datum/disease/gbs/stage_act()
..()
diff --git a/code/datums/diseases/plasmatoid.dm b/code/datums/diseases/plasmatoid.dm
index 232371cd3b2..499edcb5fa1 100644
--- a/code/datums/diseases/plasmatoid.dm
+++ b/code/datums/diseases/plasmatoid.dm
@@ -2,4 +2,5 @@
name = "Plasmatoid"
max_stages = 4
cure = "None"
- affected_species = list("Monkey", "Human")
\ No newline at end of file
+ affected_species = list("Monkey", "Human")
+ severity = "Unknown"
\ No newline at end of file
diff --git a/code/datums/diseases/retrovirus.dm b/code/datums/diseases/retrovirus.dm
index 3c6450ccd8a..40b56b05bf6 100644
--- a/code/datums/diseases/retrovirus.dm
+++ b/code/datums/diseases/retrovirus.dm
@@ -8,7 +8,7 @@
agent = ""
affected_species = list("Human")
desc = "A DNA-altering retrovirus that scrambles the structural and unique enzymes of a host constantly."
- severity = "Severe"
+ severity = "Dangerous!"
permeability_mod = 0.4
stage_prob = 2
var/SE
diff --git a/code/datums/diseases/rhumba_beat.dm b/code/datums/diseases/rhumba_beat.dm
index 9de82ceaac0..09225bf25b1 100644
--- a/code/datums/diseases/rhumba_beat.dm
+++ b/code/datums/diseases/rhumba_beat.dm
@@ -8,6 +8,7 @@
agent = "Unknown"
affected_species = list("Human")
permeability_mod = 1
+ severity = "BIOHAZARD THREAT!"
/datum/disease/rhumba_beat/stage_act()
..()
diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm
index bb806676109..71dbe67181e 100644
--- a/code/datums/diseases/transformation.dm
+++ b/code/datums/diseases/transformation.dm
@@ -7,7 +7,7 @@
cure = "A coder's love (theoretical)."
agent = "Shenanigans"
affected_species = list("Human", "Monkey", "Alien")
- severity = "Major"
+ severity = "Harmful"
stage_prob = 10
hidden = list(1, 1)
var/list/stage1 = list("You feel unremarkable.")
@@ -58,7 +58,6 @@
var/mob/living/new_mob = new new_form(affected_mob.loc)
if(istype(new_mob))
new_mob.a_intent = "harm"
- new_mob.universal_speak = 1
if(affected_mob.mind)
affected_mob.mind.transfer_to(new_mob)
else
@@ -79,7 +78,7 @@
curable = 0
longevity = 30
desc = "Monkeys with this disease will bite humans, causing humans to mutate into a monkey."
- severity = "Major"
+ severity = "BIOHAZARD THREAT!"
hidden = list(0, 0)//Not hidden, with the exception of the starting ape.
stage_prob = 4
agent = "Kongey Vibrion M-909"
@@ -124,6 +123,7 @@
cure_chance = 5
agent = "R2D2 Nanomachines"
desc = "This disease, actually acute nanomachine infection, converts the victim into a cyborg."
+ severity = "Dangerous!"
hidden = list(0, 0)
stage1 = null
stage2 = list("Your joints feel stiff.", "Beep...boop..")
@@ -132,6 +132,7 @@
stage5 = list("Your skin feels as if it's about to burst off!")
new_form = /mob/living/silicon/robot
+
/datum/disease/transformation/robot/stage_act()
..()
switch(stage)
@@ -153,6 +154,8 @@
cure_id = list("spaceacillin", "glycerol")
cure_chance = 5
agent = "Rip-LEY Alien Microbes"
+ desc = "This disease changes the victim into a xenomorph."
+ severity = "BIOHAZARD THREAT!"
hidden = list(0, 0)
stage1 = null
stage2 = list("Your throat feels scratchy.", "Kill...")
@@ -180,6 +183,7 @@
cure_chance = 80
agent = "Advanced Mutation Toxin"
desc = "This highly concentrated extract converts anything into more of itself."
+ severity = "BIOHAZARD THREAT!"
hidden = list(0, 0)
stage1 = list("You don't feel very well.")
stage2 = list("You are turning a little green.")
@@ -205,6 +209,7 @@
name = "The Barkening"
cure = "Death"
agent = "Fell Doge Majicks"
+ desc = "This disease transforms the victim into a corgi."
hidden = list(0, 0)
stage1 = list("BARK.")
stage2 = list("You feel the need to wear silly hats.")
diff --git a/code/datums/diseases/wizarditis.dm b/code/datums/diseases/wizarditis.dm
index 42579215037..c8cf37d77aa 100644
--- a/code/datums/diseases/wizarditis.dm
+++ b/code/datums/diseases/wizarditis.dm
@@ -10,7 +10,7 @@
curable = 1
permeability_mod = 0.75
desc = "Some speculate, that this virus is the cause of Wizard Federation existance. Subjects affected show the signs of mental retardation, yelling obscure sentences or total gibberish. On late stages subjects sometime express the feelings of inner power, and, cite, 'the ability to control the forces of cosmos themselves!' A gulp of strong, manly spirits usually reverts them to normal, humanlike, condition."
- severity = "Major"
+ severity = "Harmful"
requires = 1
required_limb = list(/obj/item/organ/limb/head)
diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm
index 2c43d367ce0..a4897448f17 100644
--- a/code/datums/helper_datums/getrev.dm
+++ b/code/datums/helper_datums/getrev.dm
@@ -33,5 +33,8 @@ client/verb/showrevinfo()
src << "[revdata.revision]"
else
src << "Revision unknown"
- src << "Current Infomational Settings: Protect Authority Roles From Traitor: [config.protect_roles_from_antagonist] Allow Latejoin Antagonists: [config.allow_latejoin_antagonists]"
+ src << "Current Infomational Settings:"
+ src << "Protect Authority Roles From Traitor: [config.protect_roles_from_antagonist]"
+ src << "Enforce Human Authority: [config.enforce_human_authority]"
+ src << "Allow Latejoin Antagonists: [config.allow_latejoin_antagonists]"
return
\ No newline at end of file
diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm
index 45922040d7f..c5bff0660e2 100644
--- a/code/datums/helper_datums/teleport.dm
+++ b/code/datums/helper_datums/teleport.dm
@@ -118,6 +118,11 @@
if(teleatom.Move(destturf))
playSpecials(destturf,effectout,soundout)
+ if(isliving(teleatom))
+ var/mob/living/L = teleatom
+ if(L.buckled)
+ L.buckled.unbuckle()
+
destarea.Entered(teleatom)
return 1
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 089c9cb2cf1..b8efb6fa02d 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -37,6 +37,7 @@
var/memory
+ var/need_job_assign = 1 //Whether the job controller should give them a job
var/assigned_role
var/special_role
@@ -45,8 +46,6 @@
var/list/datum/objective/objectives = list()
var/list/datum/objective/special_verbs = list()
- var/has_been_rev = 0//Tracks if this mind has been a rev or not
-
var/list/cult_words = list()
var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button.
@@ -161,6 +160,11 @@
remove_objectives()
remove_antag_equip()
+
+/datum/mind/proc/remove_gang()
+ ticker.mode.remove_gangster(src,0,1)
+ remove_objectives()
+
/datum/mind/proc/remove_malf()
if(src in ticker.mode.malf_ai)
ticker.mode.malf_ai -= src
@@ -196,6 +200,7 @@
remove_cultist()
remove_rev()
remove_malf()
+ remove_gang()
/datum/mind/proc/show_memory(mob/recipient, window=1)
if(!recipient)
@@ -224,6 +229,7 @@
var/list/sections = list(
"revolution",
+ "gang",
"cult",
"wizard",
"changeling",
@@ -267,6 +273,56 @@
text += "head|loyal|EMPLOYEE|headrev|rev"
sections["revolution"] = text
+ /** GANG ***/
+ text = "gang"
+ if (ticker.mode.config_tag=="gang")
+ text = uppertext(text)
+ text = "[text]: "
+ if (src in ticker.mode.A_bosses)
+ text += "loyal|none|(A)gangsterBOSS|(B) gangsterboss"
+ text += " Flash & Recaller: give"
+
+ var/list/L = current.get_contents()
+ var/obj/item/device/flash/flash = locate() in L
+ if (flash)
+ if(!flash.broken)
+ text += "|take equipment."
+ else
+ text += "|take equipment|repair flash."
+ else
+ text += "."
+
+ if (objectives.len==0)
+ text += " Objectives are empty! Set to kill all rival gang leaders."
+
+
+ else if (src in ticker.mode.B_bosses)
+ text += "loyal|none|(A) gangsterboss|(B)gangsterBOSS"
+ text += " Flash & Recaller: give"
+
+ var/list/L = current.get_contents()
+ var/obj/item/device/flash/flash = locate() in L
+ if (flash)
+ if(!flash.broken)
+ text += " take equipment."
+ else
+ text += " take equipment|repair flash."
+ else
+ text += "."
+
+ if (objectives.len==0)
+ text += " Objectives are empty! Set to kill all rival gang leaders."
+
+ else if (src in ticker.mode.A_gangsters)
+ text += "loyal|none|(A) GANGSTERboss|(B) gangsterboss"
+ else if (src in ticker.mode.B_gangsters)
+ text += "loyal|none|(A) gangsterboss|(B) GANGSTERboss"
+ else if(isloyal(current))
+ text += "LOYAL|none|(A) gangsterboss|(B) gangsterboss"
+ else
+ text += "loyal|NONE|(A) gangsterboss|(B) gangsterboss"
+ sections["gang"] = text
+
/** CULT ***/
text = "cult"
if (ticker.mode.config_tag=="cult")
@@ -448,7 +504,7 @@
out += "Announce objectives
"
- usr << browse(out, "window=edit_memory[src]")
+ usr << browse(out, "window=edit_memory[src];size=400x500")
/datum/mind/Topic(href, href_list)
if(!check_rights(R_ADMIN)) return
@@ -679,16 +735,83 @@
else
flash.broken = 0
- if("reequip")
+ else if (href_list["gang"])
+ switch(href_list["gang"])
+ if("clear")
+ remove_gang()
+ message_admins("[key_name_admin(usr)] has de-gang'ed [current].")
+ log_admin("[key_name(usr)] has de-gang'ed [current].")
+
+ if("agang")
+ if(src in ticker.mode.A_gangsters)
+ return
+ ticker.mode.remove_gangster(src, 0, 2)
+ ticker.mode.add_gangster(src,"A",0)
+ message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("A")] Gang (A).")
+ log_admin("[key_name(usr)] has added [current] to the [gang_name("A")] Gang (A).")
+
+ if("aboss")
+ if(src in ticker.mode.A_bosses)
+ return
+ ticker.mode.remove_gangster(src, 0, 2)
+ ticker.mode.A_bosses += src
+ src.special_role = "[gang_name("A")] Gang (A) Boss"
+ ticker.mode.update_gang_icons_added(src, "A")
+ current << "You are a [gang_name("A")] Gang Boss!"
+ message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("A")] Gang (A) leadership.")
+ log_admin("[key_name(usr)] has added [current] to the [gang_name("A")] Gang (A) leadership.")
+
+ if("bgang")
+ if(src in ticker.mode.B_gangsters)
+ return
+ ticker.mode.remove_gangster(src, 0, 2)
+ ticker.mode.add_gangster(src,"B",0)
+ message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("B")] Gang (B).")
+ log_admin("[key_name(usr)] has added [current] to the [gang_name("B")] Gang (B).")
+
+ if("bboss")
+ if(src in ticker.mode.B_bosses)
+ return
+ ticker.mode.remove_gangster(src, 0, 2)
+ ticker.mode.B_bosses += src
+ src.special_role = "[gang_name("B")] Gang (B) Boss"
+ ticker.mode.update_gang_icons_added(src, "B")
+ current << "You are a [gang_name("B")] Gang Boss!"
+ message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("B")] Gang (B) leadership.")
+ log_admin("[key_name(usr)] has added [current] to the [gang_name("B")] Gang (B) leadership.")
+
+ if("autoobjective")
+ ticker.mode.forge_gang_objectives(src)
+ ticker.mode.greet_gang(src,0)
+ usr << "Unable to equip flash!"
+ if(1)
+ usr << "Unable to equip recaller!"
+ if(0)
+ usr << "Unable to equip both flash and recaller!"
+
+ if("takeequip")
var/list/L = current.get_contents()
var/obj/item/device/flash/flash = locate() in L
+ if (!flash)
+ usr << "Deleting flash failed!"
qdel(flash)
- take_uplink()
- var/fail = 0
- fail |= !ticker.mode.equip_traitor(current, 1)
- fail |= !ticker.mode.equip_revolutionary(current)
- if (fail)
- usr << "Reequipping revolutionary goes wrong!"
+ var/obj/item/device/recaller/recaller = locate() in L
+ if (!recaller)
+ usr << "Deleting recaller failed!"
+ qdel(recaller)
+
+ if("repairflash")
+ var/list/L = current.get_contents()
+ var/obj/item/device/flash/flash = locate() in L
+ if (!flash)
+ usr << "Repairing flash failed!"
+ else
+ flash.broken = 0
else if (href_list["cult"])
switch(href_list["cult"])
@@ -760,7 +883,7 @@
ticker.mode.changelings += src
current.make_changeling()
special_role = "Changeling"
- current << "Your powers are awoken. A flash of memory returns to us...we are a changeling!"
+ current << "Your powers are awoken. A flash of memory returns to us...we are [changeling.changelingID], a changeling!"
message_admins("[key_name_admin(usr)] has changeling'ed [current].")
log_admin("[key_name(usr)] has changeling'ed [current].")
if("autoobjectives")
@@ -994,21 +1117,15 @@
ticker.mode.finalize_traitor(src)
ticker.mode.greet_traitor(src)
-/datum/mind/proc/make_Nuke()
+/datum/mind/proc/make_Nuke(var/turf/spawnloc,var/nuke_code,var/leader=0)
if(!(src in ticker.mode.syndicates))
ticker.mode.syndicates += src
ticker.mode.update_synd_icons_added(src)
- if (ticker.mode.syndicates.len==1)
- ticker.mode.prepare_syndicate_leader(src)
- else
- current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]"
special_role = "Syndicate"
- assigned_role = "MODE"
- current << "You are a [syndicate_name()] agent!"
ticker.mode.forge_syndicate_objectives(src)
ticker.mode.greet_syndicate(src)
- current.loc = get_turf(locate("landmark*Syndicate-Spawn"))
+ current.loc = spawnloc
var/mob/living/carbon/human/H = current
qdel(H.belt)
@@ -1023,6 +1140,15 @@
ticker.mode.equip_syndicate(current)
+ if (nuke_code)
+ store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 0, 0)
+ current << "The nuclear authorization code is: [nuke_code]"
+
+ if (leader)
+ ticker.mode.prepare_syndicate_leader(src,nuke_code)
+ else
+ current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]"
+
/datum/mind/proc/make_Changling()
if(!(src in ticker.mode.changelings))
ticker.mode.changelings += src
@@ -1035,7 +1161,6 @@
if(!(src in ticker.mode.wizards))
ticker.mode.wizards += src
special_role = "Wizard"
- assigned_role = "MODE"
//ticker.mode.learn_basic_spells(current)
if(!wizardstart.len)
current.loc = pick(latejoin)
@@ -1115,6 +1240,13 @@
fail |= !ticker.mode.equip_revolutionary(current)
+/datum/mind/proc/make_Gang(var/gang)
+ special_role = "[(gang=="A") ? "[gang_name("A")] Gang (A)" : "[gang_name("B")] Gang (B)"] Boss"
+ ticker.mode.update_gang_icons_added(src, gang)
+ ticker.mode.forge_gang_objectives(src, gang)
+ ticker.mode.greet_gang(src)
+ ticker.mode.equip_gang(current)
+
/mob/proc/sync_mind()
mind_initialize() //updates the mind (or creates and initializes one if one doesn't exist)
mind.active = 1 //indicates that the mind is currently synced with a client
@@ -1145,11 +1277,13 @@
//slime
/mob/living/carbon/slime/mind_initialize()
..()
+ mind.special_role = "slime"
mind.assigned_role = "slime"
//XENO
/mob/living/carbon/alien/mind_initialize()
..()
+ mind.special_role = "Alien"
mind.assigned_role = "Alien"
//XENO HUMANOID
/mob/living/carbon/alien/humanoid/queen/mind_initialize()
@@ -1197,14 +1331,17 @@
/mob/living/simple_animal/mind_initialize()
..()
mind.assigned_role = "Animal"
+ mind.special_role = "Animal"
/mob/living/simple_animal/corgi/mind_initialize()
..()
mind.assigned_role = "Corgi"
+ mind.special_role = "Corgi"
/mob/living/simple_animal/shade/mind_initialize()
..()
mind.assigned_role = "Shade"
+ mind.special_role = "Shade"
/mob/living/simple_animal/construct/mind_initialize()
..()
diff --git a/code/datums/spells/mind_transfer.dm b/code/datums/spells/mind_transfer.dm
index 586fd7a2700..0c8032c9b7e 100644
--- a/code/datums/spells/mind_transfer.dm
+++ b/code/datums/spells/mind_transfer.dm
@@ -18,7 +18,7 @@ Urist: I don't feel like figuring out how you store object spells so I'm leaving
Make sure spells that are removed from spell_list are actually removed and deleted when mind transfering.
Also, you never added distance checking after target is selected. I've went ahead and did that.
*/
-/obj/effect/proc_holder/spell/targeted/mind_transfer/cast(list/targets,mob/user = usr)
+/obj/effect/proc_holder/spell/targeted/mind_transfer/cast(list/targets,mob/user = usr, distanceoverride)
if(!targets.len)
user << "No mind found."
return
@@ -29,7 +29,7 @@ Also, you never added distance checking after target is selected. I've went ahea
var/mob/living/target = targets[1]
- if(!(target in oview(range)))//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it.
+ if(!(target in oview(range)) && !distanceoverride)//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it.
user << "They are too far away!"
return
diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm
index 85f57ba6f3a..0c4398b1c34 100644
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -55,13 +55,10 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
manifest += "
"
for(var/path in contains)
if(!path) continue
- var/atom/movable/AM = new path()
- manifest += "
[AM.name]
"
-// del AM //just to make sure they're deleted, no longer garbage collected, as there are way to many objects in crates that have other references.
- qdel(AM) // How about we fix the issues rather than bypass them, mmkay?
+ var/atom/movable/AM = path
+ manifest += "
[initial(AM.name)]
"
manifest += "
"
-
////// Use the sections to keep things tidy please /Malkevin
//////////////////////////////////////////////////////////////////////////////
@@ -156,6 +153,13 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
containername = "special ops crate"
hidden = 1
+/datum/supply_packs/emergency/syndicate
+ name = "#ERROR_NULL_ENTRY"
+ contains = list(/obj/item/weapon/storage/box/syndicate)
+ cost = 140
+ containertype = /obj/structure/closet/crate
+ containername = "crate"
+ hidden = 1
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// Security ////////////////////////////////////////
@@ -494,6 +498,15 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
cost = 25
containername = "particle accelerator crate"
+/datum/supply_packs/engineering/engine/spacesuit
+ name = "Space Suit crate"
+ contains = list(/obj/item/clothing/suit/space,
+ /obj/item/clothing/head/helmet/space,
+ /obj/item/clothing/mask/breath,)
+ cost = 80
+ containertype = /obj/structure/closet/crate/secure
+ containername = "space suit crate"
+ access = access_eva
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// Medical /////////////////////////////////////////
@@ -649,6 +662,15 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
access = access_teleporter
+/datum/supply_packs/science/transfer_valves
+ name = "Tank Transfer Valves"
+ contains = list(/obj/item/device/transfer_valve,
+ /obj/item/device/transfer_valve)
+ cost = 60
+ containertype = /obj/structure/closet/crate/secure
+ containername = "transfer valves crate"
+ access = access_rd
+
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// Organic /////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
@@ -930,6 +952,16 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
cost = 40 // it costs so much because the Space Church is ran by Space Jews
containername = "religious supplies crate"
+/datum/supply_packs/misc/posters
+ name = "Corporate Posters Crate"
+ contains = list(/obj/item/weapon/contraband/poster/legit,
+ /obj/item/weapon/contraband/poster/legit,
+ /obj/item/weapon/contraband/poster/legit,
+ /obj/item/weapon/contraband/poster/legit,
+ /obj/item/weapon/contraband/poster/legit)
+ cost = 8
+ containername = "Corporate Posters Crate"
+
///////////// Paper Work
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index c63f2e428fb..fd78d4a70c9 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -46,7 +46,8 @@ var/list/uplink_items = list()
var/cost = 0
var/last = 0 // Appear last
var/list/gamemodes = list() // Empty list means it is in all the gamemodes. Otherwise place the gamemode name here.
- var/list/excludefrom = list()//Empty list does nothing. Place the name of gamemode you don't want this item to be available in here. This is so you dont have to list EVERY mode to exclude something.
+ var/list/excludefrom = list() //Empty list does nothing. Place the name of gamemode you don't want this item to be available in here. This is so you dont have to list EVERY mode to exclude something.
+ var/surplus = 100 //Chance of being included in the surplus crate (when pick() selects it)
/datum/uplink_item/proc/spawn_item(var/turf/loc, var/obj/item/device/uplink/U)
if(item)
@@ -64,9 +65,6 @@ var/list/uplink_items = list()
if (!user || user.stat || user.restrained())
return 0
- if (!( istype(user, /mob/living/carbon/human)))
- return 0
-
// If the uplink's holder is in the user's contents
if ((U.loc in user.contents || (in_range(U.loc, user) && istype(U.loc.loc, /turf))))
user.set_machine(U)
@@ -75,9 +73,10 @@ var/list/uplink_items = list()
var/obj/I = spawn_item(get_turf(user), U)
- if(istype(I, /obj/item) && ishuman(user))
- var/mob/living/carbon/human/A = user
- A.put_in_any_hand_if_possible(I)
+ if(istype(I, /obj/item))
+ if(ishuman(user))
+ var/mob/living/carbon/human/A = user
+ A.put_in_any_hand_if_possible(I)
if(istype(I,/obj/item/weapon/storage/box/) && I.contents.len>0)
for(var/atom/o in I)
@@ -104,96 +103,108 @@ var/list/uplink_items = list()
name = "Syndicate Revolver"
desc = "The syndicate revolver is a traditional handgun that fires .357 Magnum cartridges and has 7 chambers."
item = /obj/item/weapon/gun/projectile/revolver
- cost = 6
+ cost = 13
+ surplus = 50
/datum/uplink_item/dangerous/pistol
name = "Stechkin Pistol"
desc = "A small, easily concealable handgun that uses 10mm magazines and is compatible with suppressors."
item = /obj/item/weapon/gun/projectile/automatic/pistol
- cost = 5
+ cost = 9
/datum/uplink_item/dangerous/smg
name = "C-20r Submachine Gun"
desc = "A fully-loaded Scarborough Arms-developed submachine gun that fires 12mm automatic rounds with a 20-round magazine."
item = /obj/item/weapon/gun/projectile/automatic/c20r
- cost = 7
+ cost = 14
gamemodes = list(/datum/game_mode/nuclear)
+ surplus = 40
/datum/uplink_item/dangerous/machinegun
name = "L6 Squad Automatic Weapon"
- desc = "A traditionally constructed machine gun made by AA-2531. This deadly weapon has a massive 50-round magazine of 7.62×51mm ammunition."
+ desc = "A traditionally constructed machine gun made by AA-2531. This deadly weapon has a massive 50-round magazine of 7.62×51mm ammunition."
item = /obj/item/weapon/gun/projectile/automatic/l6_saw
- cost = 20
+ cost = 40
gamemodes = list(/datum/game_mode/nuclear)
+ surplus = 0
/datum/uplink_item/dangerous/crossbow
name = "Miniature Energy Crossbow"
desc = "A short bow mounted across a tiller in miniature. Small enough to fit into a pocket or slip into a bag unnoticed. It fires bolts tipped with toxin, a poison collected from an organism. \
Its bolts stun enemies for short periods, and replenish automatically."
item = /obj/item/weapon/gun/energy/crossbow
- cost = 5
+ cost = 12
excludefrom = list(/datum/game_mode/nuclear)
+ surplus = 50
/datum/uplink_item/dangerous/flamethrower
name = "Flamethrower"
desc = "A flamethrower, fueled by a portion of highly flammable biotoxins stolen previously from Nanotrasen stations. Make a statement by roasting the filth in their own greed. Use with caution."
item = /obj/item/weapon/flamethrower/full/tank
- cost = 6
+ cost = 11
gamemodes = list(/datum/game_mode/nuclear)
+ surplus = 40
/datum/uplink_item/dangerous/sword
name = "Energy Sword"
desc = "The energy sword is an edged weapon with a blade of pure energy. The sword is small enough to be pocketed when inactive. Activating it produces a loud, distinctive noise."
item = /obj/item/weapon/melee/energy/sword
- cost = 4
+ cost = 8
/datum/uplink_item/dangerous/emp
name = "EMP Kit"
desc = "A box that contains two EMP grenades, an EMP implant and a short ranged recharging device disguised as a flashlight. Useful to disrupt communication and silicon lifeforms."
item = /obj/item/weapon/storage/box/syndie_kit/emp
- cost = 3
+ cost = 5
/datum/uplink_item/dangerous/syndicate_minibomb
name = "Syndicate Minibomb"
desc = "The Minibomb is a grenade with a five-second fuse."
item = /obj/item/weapon/grenade/syndieminibomb
- cost = 3
+ cost = 6
/datum/uplink_item/dangerous/viscerators
name = "Viscerator Delivery Grenade"
desc = "A unique grenade that deploys a swarm of viscerators upon activation, which will chase down and shred any non-operatives in the area."
item = /obj/item/weapon/grenade/spawnergrenade/manhacks
- cost = 4
+ cost = 8
gamemodes = list(/datum/game_mode/nuclear)
+ surplus = 35
/datum/uplink_item/dangerous/bioterror
name = "Biohazardous Chemical Sprayer"
desc = "A chemical sprayer that allows a wide dispersal of selected chemicals. Especially tailored by the Tiger Cooperative, the deadly blend it comes stocked with will disorient, damage, and disable your foes... \
Use with extreme caution, to prevent exposure to yourself and your fellow operatives."
item = /obj/item/weapon/reagent_containers/spray/chemsprayer/bioterror
- cost = 10
+ cost = 20
gamemodes = list(/datum/game_mode/nuclear)
+ surplus = 0
/datum/uplink_item/dangerous/gygax
name = "Gygax Exosuit"
desc = "A lightweight exosuit, painted in a dark scheme. Its speed and equipment selection make it excellent for hit-and-run style attacks. \
This model lacks a method of space propulsion, and therefore it is advised to repair the mothership's teleporter if you wish to make use of it."
item = /obj/mecha/combat/gygax/dark/loaded
- cost = 45
+ cost = 90
gamemodes = list(/datum/game_mode/nuclear)
+ surplus = 0
/datum/uplink_item/dangerous/mauler
name = "Mauler Exosuit"
desc = "A massive and incredibly deadly Syndicate exosuit. Features long-range targetting, thrust vectoring, and deployable smoke."
item = /obj/mecha/combat/marauder/mauler/loaded
- cost = 70
+ cost = 140
gamemodes = list(/datum/game_mode/nuclear)
+ surplus = 0
+
/datum/uplink_item/dangerous/syndieborg
name = "Syndicate Cyborg"
desc = "A cyborg designed and programmed for systematic extermination of non-Syndicate personnel."
item = /obj/item/weapon/antag_spawner/borg_tele
- cost = 25
+ cost = 50
gamemodes = list(/datum/game_mode/nuclear)
+ surplus = 0
+
//for refunding the syndieborg teleporter
/datum/uplink_item/dangerous/syndieborg/spawn_item()
var/obj/item/weapon/antag_spawner/borg_tele/T = ..()
@@ -204,18 +215,19 @@ var/list/uplink_items = list()
/datum/uplink_item/ammo
category = "Ammunition"
+ surplus = 40
/datum/uplink_item/ammo/revolver
name = "Ammo-357"
desc = "A box that contains seven additional rounds for the revolver, made using an automatic lathe."
item = /obj/item/ammo_box/a357
- cost = 2
+ cost = 4
/datum/uplink_item/ammo/smg
name = "Ammo-12mm"
desc = "A 20-round .45 ACP magazine for use in the C-20r submachine gun."
item = /obj/item/ammo_box/magazine/c20m
- cost = 1
+ cost = 2
gamemodes = list(/datum/game_mode/nuclear)
/datum/uplink_item/ammo/pistol
@@ -224,13 +236,35 @@ var/list/uplink_items = list()
item = /obj/item/ammo_box/magazine/m10mm
cost = 1
-/datum/uplink_item/ammo/machinegun
- name = "Ammo-7.62×51mm"
- desc = "A 50-round magazine of 7.62×51mm ammunition for use in the L6 SAW machinegun. By the time you need to use this, you'll already be on a pile of corpses."
- item = /obj/item/ammo_box/magazine/m762
- cost = 6
+/datum/uplink_item/ammo/bullstun
+ name = "Ammo-12g Stun Slug"
+ desc = "An additional 8-round stun slug magazine for use in the Bulldog shotgun. Saying that they're non-lethal would be lying."
+ item = /obj/item/ammo_box/magazine/m12g
+ cost = 2
gamemodes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/ammo/bullbuck
+ name = "Ammo-12g Buckshot"
+ desc = "An alternative 8-round buckshot magazine for use in the Bulldog shotgun. Front towards enemy."
+ item = /obj/item/ammo_box/magazine/m12g/buckshot
+ cost = 2
+ gamemodes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/ammo/bulldragon
+ name = "Ammo-12g Dragon's Breath"
+ desc = "An alternative 8-round dragon's breath magazine for use in the Bulldog shotgun. I'm a fire starter, twisted fire starter!"
+ item = /obj/item/ammo_box/magazine/m12g/dragon
+ cost = 3
+ gamemodes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/ammo/machinegun
+ name = "Ammo-7.62×51mm"
+ desc = "A 50-round magazine of 7.62×51mm ammunition for use in the L6 SAW machinegun. By the time you need to use this, you'll already be on a pile of corpses."
+ item = /obj/item/ammo_box/magazine/m762
+ cost = 12
+ gamemodes = list(/datum/game_mode/nuclear)
+ surplus = 0
+
// STEALTHY WEAPONS
/datum/uplink_item/stealthy_weapons
@@ -241,7 +275,7 @@ var/list/uplink_items = list()
desc = "A syringe disguised as a functional pen, filled with a potent mix of drugs, including a strong anaesthetic and a chemical that is capable of blocking the movement of the vocal chords. \
The pen holds one dose of the mixture, and cannot be refilled."
item = /obj/item/weapon/pen/sleepy
- cost = 3
+ cost = 4
excludefrom = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_weapons/soap
@@ -249,19 +283,21 @@ var/list/uplink_items = list()
desc = "A sinister-looking surfactant used to clean blood stains to hide murders and prevent DNA analysis. You can also drop it underfoot to slip people."
item = /obj/item/weapon/soap/syndie
cost = 1
+ surplus = 50
/datum/uplink_item/stealthy_weapons/detomatix
name = "Detomatix PDA Cartridge"
desc = "When inserted into a personal digital assistant, this cartridge gives you five opportunities to detonate PDAs of crewmembers who have their message feature enabled. \
The concussive effect from the explosion will knock the recipient out for a short period, and deafen them for longer. It has a chance to detonate your PDA."
item = /obj/item/weapon/cartridge/syndicate
- cost = 3
+ cost = 6
/datum/uplink_item/stealthy_weapons/suppressor
name = "Stetchkin Suppressor"
desc = "Fitted for use on the Stetchkin pistol, this suppressor will make its shots quieter when equipped onto it."
item = /obj/item/weapon/suppressor
- cost = 2
+ cost = 3
+ surplus = 10
// STEALTHY TOOLS
@@ -272,44 +308,53 @@ var/list/uplink_items = list()
name = "Chameleon Jumpsuit"
desc = "A jumpsuit used to imitate the uniforms of Nanotrasen crewmembers."
item = /obj/item/clothing/under/chameleon
- cost = 3
+ cost = 4
/datum/uplink_item/stealthy_tools/chameleon_stamp
name = "Chameleon Stamp"
- desc = "A stamp that can be activated to imitate an official Nanotrasen Stamp™. The disguised stamp will work exactly like the real stamp and will allow you to forge false documents to gain access or equipment; \
+ desc = "A stamp that can be activated to imitate an official Nanotrasen Stamp™. The disguised stamp will work exactly like the real stamp and will allow you to forge false documents to gain access or equipment; \
it can also be used in a washing machine to forge clothing."
item = /obj/item/weapon/stamp/chameleon
cost = 1
+ surplus = 35
/datum/uplink_item/stealthy_tools/syndigolashes
name = "No-Slip Brown Shoes"
desc = "These allow you to run on wet floors. They do not work on lubricated surfaces."
item = /obj/item/clothing/shoes/syndigaloshes
- cost = 2
+ cost = 4
/datum/uplink_item/stealthy_tools/agent_card
name = "Agent Identification card"
desc = "Agent cards prevent artificial intelligences from tracking the wearer, and can copy access from other identification cards. The access is cumulative, so scanning one card does not erase the access gained from another."
item = /obj/item/weapon/card/id/syndicate
- cost = 2
+ cost = 3
/datum/uplink_item/stealthy_tools/voice_changer
name = "Voice Changer"
item = /obj/item/clothing/mask/gas/voice
desc = "A conspicuous gas mask that mimics the voice named on your identification card. When no identification is worn, the mask will render your voice unrecognizable."
- cost = 4
+ cost = 5
/datum/uplink_item/stealthy_tools/chameleon_proj
name = "Chameleon-Projector"
desc = "Projects an image across a user, disguising them as an object scanned with it, as long as they don't move the projector from their hand. The disguised user cannot run and rojectiles pass over them."
item = /obj/item/device/chameleon
- cost = 4
+ cost = 7
/datum/uplink_item/stealthy_tools/camera_bug
name = "Camera Bug"
desc = "Enables you to bug cameras to view them remotely. Adding particular items to it alters its functions."
item = /obj/item/device/camera_bug
cost = 2
+ surplus = 90
+
+/datum/uplink_item/stealthy_tools/smugglersatchel
+ name = "Smuggler's Satchel"
+ desc = "This satchel is thin enough to be hidden in the gap between plating and tiling, great for stashing your stolen goods. Comes with a crowbar and a floor tile inside."
+ item = /obj/item/weapon/storage/backpack/satchel_flat
+ cost = 2
+ surplus = 30
// DEVICE AND TOOLS
@@ -320,7 +365,7 @@ var/list/uplink_items = list()
name = "Cryptographic Sequencer"
desc = "The emag is a small card that unlocks hidden functions in electronic devices, subverts intended functions and characteristically breaks security mechanisms."
item = /obj/item/weapon/card/emag
- cost = 3
+ cost = 6
/datum/uplink_item/device_tools/toolbox
name = "Full Syndicate Toolbox"
@@ -333,28 +378,29 @@ var/list/uplink_items = list()
desc = "The syndicate medkit is a suspicious black and red. Included is a combat stimulant injector for rapid healing, a medical hud for quick identification of injured comrades, \
and other medical supplies helpful for a medical field operative.."
item = /obj/item/weapon/storage/firstaid/tactical
- cost = 5
+ cost = 9
gamemodes = list(/datum/game_mode/nuclear)
/datum/uplink_item/device_tools/space_suit
name = "Syndicate Space Suit"
desc = "The red and black syndicate space suit is less encumbering than Nanotrasen variants, fits inside bags, and has a weapon slot. Nanotrasen crewmembers are trained to report red space suit sightings."
item = /obj/item/weapon/storage/box/syndie_kit/space
- cost = 3
+ cost = 5
/datum/uplink_item/device_tools/thermal
name = "Thermal Imaging Glasses"
desc = "These glasses are thermals disguised as engineers' optical meson scanners. \
They allow you to see organisms through walls by capturing the upper portion of the infrared light spectrum, emitted as heat and light by objects. \
- Hotter objects, such as warm bodies, cybernetic organisms and artificial intelligence cores emit more of this light than cooler objects like walls and airlocks."
+ Hotter objects, such as warm bodies, cybernetic organisms and artificial intelligence cores emit more of this light than cooler objects like walls and airlocks." //THEN WHY CANT THEY SEE PLASMA FIRES????
item = /obj/item/clothing/glasses/thermal/syndi
- cost = 3
+ cost = 6
/datum/uplink_item/device_tools/binary
name = "Binary Translator Key"
desc = "A key, that when inserted into a radio headset, allows you to listen to and talk with artificial intelligences and cybernetic organisms in binary. "
item = /obj/item/device/encryptionkey/binary
- cost = 3
+ cost = 6
+ surplus = 75
/datum/uplink_item/device_tools/ai_detector
name = "Artificial Intelligence Detector" // changed name in case newfriends thought it detected disguised ai's
@@ -366,13 +412,21 @@ var/list/uplink_items = list()
name = "Hacked AI Law Upload Module"
desc = "When used with an upload console, this module allows you to upload priority laws to an artificial intelligence. Be careful with their wording, as artificial intelligences may look for loopholes to exploit."
item = /obj/item/weapon/aiModule/syndicate
- cost = 7
+ cost = 14
-/datum/uplink_item/device_tools/plastic_explosives
+/datum/uplink_item/device_tools/magboots
+ name = "Blood-Red Magboots"
+ desc = "A pair of magnetic boots with a Syndicate paintjob that assist with freer movement in space or on-station during gravitational generator failures. \
+ These reverse-engineered knockoffs of Nanotrasen's 'Advanced Magboots' slow you down in simulated-gravity environments much like the standard issue variety."
+ item = /obj/item/clothing/shoes/magboots/syndie
+ cost = 5
+ gamemodes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/device_tools/c4
name = "Composition C-4"
desc = "C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls or connect a signaler to its wiring to make it remotely detonable. \
It has a modifiable timer with a minimum setting of 10 seconds."
- item = /obj/item/weapon/plastique
+ item = /obj/item/weapon/c4
cost = 1
/datum/uplink_item/device_tools/powersink
@@ -380,7 +434,7 @@ var/list/uplink_items = list()
desc = "When screwed to wiring attached to an electric grid, then activated, this large device places excessive load on the grid, causing a stationwide blackout. The sink cannot be carried because of its excessive size. \
Ordering this sends you a small beacon that will teleport the power sink to your location on activation."
item = /obj/item/device/powersink
- cost = 5
+ cost = 10
/datum/uplink_item/device_tools/singularity_beacon
name = "Singularity Beacon"
@@ -388,14 +442,14 @@ var/list/uplink_items = list()
Does not work when the singularity is still in containment. A singularity beacon can cause catastrophic damage to a space station, \
leading to an emergency evacuation. Because of its size, it cannot be carried. Ordering this sends you a small beacon that will teleport the larger beacon to your location on activation."
item = /obj/item/device/sbeacondrop
- cost = 7
+ cost = 14
/datum/uplink_item/device_tools/syndicate_bomb
name = "Syndicate Bomb"
desc = "The Syndicate Bomb has an adjustable timer with a minimum setting of 60 seconds. Ordering the bomb sends you a small beacon, which will teleport the explosive to your location when you activate it. \
You can wrench the bomb down to prevent removal. The crew may attempt to defuse the bomb."
item = /obj/item/device/sbeacondrop/bomb
- cost = 5
+ cost = 11
excludefrom = list(/datum/game_mode/traitor/double_agents)
/datum/uplink_item/device_tools/rad_laser
@@ -403,29 +457,31 @@ var/list/uplink_items = list()
desc = "A radioactive microlaser disguised as a standard Nanotrasen health analyzer. When used, it emits a powerful burst of radiation, which, after a short delay, can incapitate all but the most protected of humanoids. \
It has two settings: intensity, which controls the power of the radiation, and wavelength, which controls how long the radiation delay is."
item = /obj/item/device/rad_laser
- cost = 4
+ cost = 6
/datum/uplink_item/device_tools/syndicate_detonator
name = "Syndicate Detonator"
desc = "The Syndicate Detonator is a companion device to the Syndicate Bomb. Simply press the included button and an encrypted radio frequency will instruct all live syndicate bombs to detonate. \
Useful for when speed matters or you wish to synchronize multiple bomb blasts. Be sure to stand clear of the blast radius before using the detonator."
item = /obj/item/device/syndicatedetonator
- cost = 1
+ cost = 3
gamemodes = list(/datum/game_mode/nuclear)
/datum/uplink_item/device_tools/teleporter
name = "Teleporter Circuit Board"
desc = "A printed circuit board that completes the teleporter onboard the mothership. Advise you test fire the teleporter before entering it, as malfunctions can occur."
item = /obj/item/weapon/circuitboard/teleporter
- cost = 20
+ cost = 40
gamemodes = list(/datum/game_mode/nuclear)
+ surplus = 0
/datum/uplink_item/device_tools/shield
name = "Energy Shield"
desc = "An incredibly useful personal shield projector, capable of reflecting energy projectiles and defending against other attacks."
item = /obj/item/weapon/shield/energy
- cost = 8
+ cost = 16
gamemodes = list(/datum/game_mode/nuclear)
+ surplus = 20
// IMPLANTS
@@ -437,31 +493,33 @@ var/list/uplink_items = list()
name = "Freedom Implant"
desc = "An implant injected into the body and later activated using a bodily gesture to attempt to slip restraints."
item = /obj/item/weapon/storage/box/syndie_kit/imp_freedom
- cost = 3
+ cost = 5
/datum/uplink_item/implants/uplink
name = "Uplink Implant"
desc = "An implant injected into the body, and later activated using a bodily gesture to open an uplink with 5 telecrystals. \
The ability for an agent to open an uplink after their posessions have been stripped from them makes this implant excellent for escaping confinement."
item = /obj/item/weapon/storage/box/syndie_kit/imp_uplink
- cost = 10
+ cost = 20
+ surplus = 0
/datum/uplink_item/implants/adrenal
name = "Adrenal Implant"
desc = "An implant injected into the body, and later activated using a bodily gesture to inject a chemical cocktail, which has a mild healing effect along with removing all stuns and increasing his speed."
item = /obj/item/weapon/storage/box/syndie_kit/imp_adrenal
- cost = 4
+ cost = 8
// POINTLESS BADASSERY
/datum/uplink_item/badass
category = "(Pointless) Badassery"
+ surplus = 0
/datum/uplink_item/badass/bundle
name = "Syndicate Bundle"
desc = "Syndicate Bundles are specialised groups of items that arrive in a plain box. These items are collectively worth more than 10 telecrystals, but you do not know which specialisation you will receive."
item = /obj/item/weapon/storage/box/syndicate
- cost = 10
+ cost = 20
excludefrom = list(/datum/game_mode/nuclear)
/datum/uplink_item/badass/syndiecards
@@ -471,12 +529,13 @@ var/list/uplink_items = list()
item = /obj/item/toy/cards/deck/syndicate
cost = 1
excludefrom = list(/datum/game_mode/nuclear)
+ surplus = 40
/datum/uplink_item/badass/balloon
name = "For showing that you are The Boss"
desc = "A useless red balloon with the syndicate logo on it, which can blow the deepest of covers."
item = /obj/item/toy/syndicateballoon
- cost = 10
+ cost = 20
/datum/uplink_item/badass/random
name = "Random Item"
@@ -502,3 +561,35 @@ var/list/uplink_items = list()
U.uses -= max(0, I.cost)
feedback_add_details("traitor_uplink_items_bought","RN")
return new I.item(loc)
+
+/datum/uplink_item/badass/surplus_crate
+ name = "Syndicate Surplus Crate"
+ desc = "A crate containing 50 telecrystals worth of random syndicate leftovers."
+ cost = 20
+ item = /obj/item/weapon/storage/box/syndicate
+ excludefrom = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/badass/surplus_crate/spawn_item(turf/loc, obj/item/device/uplink/U)
+ var/obj/structure/closet/crate/C = new(loc)
+ var/list/temp_uplink_list = get_uplink_items()
+ var/list/buyable_items = list()
+ for(var/category in temp_uplink_list)
+ buyable_items += temp_uplink_list[category]
+ var/list/bought_items = list()
+ U.uses -= cost
+ var/remaining_TC = 50
+
+ var/datum/uplink_item/I
+ while(remaining_TC)
+ I = pick(buyable_items)
+ if(!I.surplus)
+ continue
+ if(I.cost > remaining_TC)
+ continue
+ if((I.item in bought_items) && prob(33)) //To prevent people from being flooded with the same thing over and over again.
+ continue
+ bought_items += I.item
+ remaining_TC -= I.cost
+
+ for(var/item in bought_items)
+ new item(C)
diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm
index 372578e6038..48691c47bff 100644
--- a/code/datums/wires/airlock.dm
+++ b/code/datums/wires/airlock.dm
@@ -36,7 +36,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
. += ..()
. += text(" \n[] \n[] \n[] \n[] \n[] \n[] \n[]", (A.locked ? "The door bolts have fallen!" : "The door bolts look up."),
(A.lights ? "The door bolt lights are on." : "The door bolt lights are off!"),
- ((A.arePowerSystemsOn() && !(A.stat & NOPOWER)) ? "The test light is on." : "The test light is off!"),
+ ((A.hasPower()) ? "The test light is on." : "The test light is off!"),
((A.aiControlDisabled==0 && !A.emagged) ? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."),
(A.safe==0 ? "The 'Check Wiring' light is on." : "The 'Check Wiring' light is off."),
(A.normalspeed==0 ? "The 'Check Timing Mechanism' light is on." : "The 'Check Timing Mechanism' light is off."),
@@ -124,7 +124,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
switch(index)
if(AIRLOCK_WIRE_IDSCAN)
//Sending a pulse through this disables emergency access and flashes the red light on the door (if the door has power).
- if((A.arePowerSystemsOn()) && (!(A.stat & NOPOWER)) && A.density)
+ if(A.hasPower() && A.density)
A.do_animate("deny")
if(A.emergency)
A.emergency = 0
@@ -140,7 +140,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
for(var/mob/M in range(1, A))
M << "You hear a click from the bottom of the door."
else
- if(A.arePowerSystemsOn()) //only can raise bolts if power's on
+ if(A.hasPower()) //only can raise bolts if power's on
A.locked = 0
for(var/mob/M in range(1, A))
M << "You hear a click from the bottom of the door."
diff --git a/code/datums/wires/explosive.dm b/code/datums/wires/explosive.dm
index 5ba362ba2fd..7a43c1bde8d 100644
--- a/code/datums/wires/explosive.dm
+++ b/code/datums/wires/explosive.dm
@@ -17,16 +17,16 @@ var/const/WIRE_EXPLODE = 1
if(!mended)
explode()
-/datum/wires/explosive/plastic
- holder_type = /obj/item/weapon/plastique
+/datum/wires/explosive/c4
+ holder_type = /obj/item/weapon/c4
-/datum/wires/explosive/plastic/CanUse(var/mob/living/L)
- var/obj/item/weapon/plastique/P = holder
+/datum/wires/explosive/c4/CanUse(var/mob/living/L)
+ var/obj/item/weapon/c4/P = holder
if(P.open_panel)
return 1
return 0
-/datum/wires/explosive/plastic/explode()
- var/obj/item/weapon/plastique/P = holder
+/datum/wires/explosive/c4/explode()
+ var/obj/item/weapon/c4/P = holder
P.explode(get_turf(P))
diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm
index 05025fbc6f5..42ebeec3ef0 100644
--- a/code/defines/obj/weapon.dm
+++ b/code/defines/obj/weapon.dm
@@ -166,11 +166,6 @@
w_class = 2.0
attack_verb = list("warned", "cautioned", "smashed")
-/obj/item/weapon/caution/cone
- desc = "This cone is trying to warn you of something!"
- name = "warning cone"
- icon_state = "cone"
-
/obj/item/weapon/rack_parts
name = "rack parts"
desc = "Parts of a rack."
diff --git a/code/defines/procs/priority_announce.dm b/code/defines/procs/priority_announce.dm
index c191abe3265..c397b3fd00c 100644
--- a/code/defines/procs/priority_announce.dm
+++ b/code/defines/procs/priority_announce.dm
@@ -37,11 +37,14 @@
C.messagetitle.Add("[title]")
C.messagetext.Add(text)
-/proc/minor_announce(var/message, var/title = "Attention:")
+/proc/minor_announce(var/message, var/title = "Attention:", var/alert)
if(!message)
return
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player) && !M.ear_deaf)
- M << "[title] [message]"
- M << sound('sound/misc/notice2.ogg')
\ No newline at end of file
+ M << "[title] [message] "
+ if(alert)
+ M << sound('sound/misc/notice1.ogg')
+ else
+ M << sound('sound/misc/notice2.ogg')
\ No newline at end of file
diff --git a/code/defines/procs/statistics.dm b/code/defines/procs/statistics.dm
index e0a97085222..06c076af6ac 100644
--- a/code/defines/procs/statistics.dm
+++ b/code/defines/procs/statistics.dm
@@ -10,7 +10,7 @@ proc/sql_poll_players()
log_game("SQL ERROR during player polling. Failed to connect.")
else
var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
- var/DBQuery/query = dbcon.NewQuery("INSERT INTO erro_legacy_population (playercount, time) VALUES ([playercount], '[sqltime]')")
+ var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("legacy_population")] (playercount, time) VALUES ([playercount], '[sqltime]')")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during player polling. Error : \[[err]\]\n")
@@ -25,7 +25,7 @@ proc/sql_poll_admins()
log_game("SQL ERROR during admin polling. Failed to connect.")
else
var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
- var/DBQuery/query = dbcon.NewQuery("INSERT INTO erro_legacy_population (admincount, time) VALUES ([admincount], '[sqltime]')")
+ var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("legacy_population")] (admincount, time) VALUES ([admincount], '[sqltime]')")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during admin polling. Error : \[[err]\]\n")
@@ -69,7 +69,7 @@ proc/sql_report_death(var/mob/living/carbon/human/H)
if(!dbcon.IsConnected())
log_game("SQL ERROR during death reporting. Failed to connect.")
else
- var/DBQuery/query = dbcon.NewQuery("INSERT INTO erro_death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')")
+ var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during death reporting. Error : \[[err]\]\n")
@@ -104,7 +104,7 @@ proc/sql_report_cyborg_death(var/mob/living/silicon/robot/H)
if(!dbcon.IsConnected())
log_game("SQL ERROR during death reporting. Failed to connect.")
else
- var/DBQuery/query = dbcon.NewQuery("INSERT INTO erro_death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')")
+ var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during death reporting. Error : \[[err]\]\n")
@@ -137,7 +137,7 @@ proc/sql_commit_feedback()
log_game("SQL ERROR during feedback reporting. Failed to connect.")
else
- var/DBQuery/max_query = dbcon.NewQuery("SELECT MAX(roundid) AS max_round_id FROM erro_feedback")
+ var/DBQuery/max_query = dbcon.NewQuery("SELECT MAX(roundid) AS max_round_id FROM [format_table_name("feedback")]")
max_query.Execute()
var/newroundid
@@ -157,7 +157,7 @@ proc/sql_commit_feedback()
var/variable = item.get_variable()
var/value = item.get_value()
- var/DBQuery/query = dbcon.NewQuery("INSERT INTO erro_feedback (id, roundid, time, variable, value) VALUES (null, [newroundid], Now(), '[variable]', '[value]')")
+ var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("feedback")] (id, roundid, time, variable, value) VALUES (null, [newroundid], Now(), '[variable]', '[value]')")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during feedback reporting. Error : \[[err]\]\n")
\ No newline at end of file
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index 8ac516f431d..21a38a9ccef 100644
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -380,17 +380,25 @@ proc/process_ghost_teleport_locs()
/area/tdome
name = "\improper Thunderdome"
- icon_state = "thunder"
+ icon_state = "yellow"
requires_power = 0
has_gravity = 1
+/area/tdome/arena
+ name = "\improper Thunderdome Arena"
+ icon_state = "thunder"
+
+/area/tdome/arena_source
+ name = "\improper Thunderdome Arena Template"
+ icon_state = "thunder"
+
/area/tdome/tdome1
name = "\improper Thunderdome (Team 1)"
icon_state = "green"
/area/tdome/tdome2
name = "\improper Thunderdome (Team 2)"
- icon_state = "yellow"
+ icon_state = "green"
/area/tdome/tdomeadmin
name = "\improper Thunderdome (Admin.)"
@@ -833,11 +841,10 @@ proc/process_ghost_teleport_locs()
/area/engine/engine_smes
name = "\improper Engineering SMES"
icon_state = "engine_smes"
- requires_power = 0//This area only covers the batteries and they deal with their own power
/area/engine/engineering
name = "Engineering"
- icon_state = "engine_smes"
+ icon_state = "engine"
/area/engine/break_room
name = "\improper Engineering Foyer"
@@ -855,7 +862,6 @@ proc/process_ghost_teleport_locs()
name = "Gravity Generator Room"
icon_state = "blue"
-
//Solars
/area/solar
@@ -1542,6 +1548,198 @@ proc/process_ghost_teleport_locs()
has_gravity = 1
ambientsounds = list('sound/ambience/shore.ogg', 'sound/ambience/seag1.ogg','sound/ambience/seag2.ogg','sound/ambience/seag2.ogg')
+/area/spacecontent
+ name = "space"
+
+/area/spacecontent/a1
+ icon_state = "spacecontent1"
+
+/area/spacecontent/a2
+ icon_state = "spacecontent2"
+
+/area/spacecontent/a3
+ icon_state = "spacecontent3"
+
+/area/spacecontent/a4
+ icon_state = "spacecontent4"
+
+/area/spacecontent/a5
+ icon_state = "spacecontent5"
+
+/area/spacecontent/a6
+ icon_state = "spacecontent6"
+
+/area/spacecontent/a7
+ icon_state = "spacecontent7"
+
+/area/spacecontent/a8
+ icon_state = "spacecontent8"
+
+/area/spacecontent/a9
+ icon_state = "spacecontent9"
+
+/area/spacecontent/a10
+ icon_state = "spacecontent10"
+
+/area/spacecontent/a11
+ icon_state = "spacecontent11"
+
+/area/spacecontent/a11
+ icon_state = "spacecontent12"
+
+/area/spacecontent/a12
+ icon_state = "spacecontent13"
+
+/area/spacecontent/a13
+ icon_state = "spacecontent14"
+
+/area/spacecontent/a14
+ icon_state = "spacecontent14"
+
+/area/spacecontent/a15
+ icon_state = "spacecontent15"
+
+/area/spacecontent/a16
+ icon_state = "spacecontent16"
+
+/area/spacecontent/a17
+ icon_state = "spacecontent17"
+
+/area/spacecontent/a18
+ icon_state = "spacecontent18"
+
+/area/spacecontent/a19
+ icon_state = "spacecontent19"
+
+/area/spacecontent/a20
+ icon_state = "spacecontent20"
+
+/area/spacecontent/a21
+ icon_state = "spacecontent21"
+
+/area/spacecontent/a22
+ icon_state = "spacecontent22"
+
+/area/spacecontent/a23
+ icon_state = "spacecontent23"
+
+/area/spacecontent/a24
+ icon_state = "spacecontent24"
+
+/area/spacecontent/a25
+ icon_state = "spacecontent25"
+
+/area/spacecontent/a26
+ icon_state = "spacecontent26"
+
+/area/spacecontent/a27
+ icon_state = "spacecontent27"
+
+/area/spacecontent/a28
+ icon_state = "spacecontent28"
+
+/area/spacecontent/a29
+ icon_state = "spacecontent29"
+
+/area/spacecontent/a30
+ icon_state = "spacecontent30"
+
+/area/awaycontent
+ name = "space"
+
+/area/awaycontent/a1
+ icon_state = "awaycontent1"
+
+/area/awaycontent/a2
+ icon_state = "awaycontent2"
+
+/area/awaycontent/a3
+ icon_state = "awaycontent3"
+
+/area/awaycontent/a4
+ icon_state = "awaycontent4"
+
+/area/awaycontent/a5
+ icon_state = "awaycontent5"
+
+/area/awaycontent/a6
+ icon_state = "awaycontent6"
+
+/area/awaycontent/a7
+ icon_state = "awaycontent7"
+
+/area/awaycontent/a8
+ icon_state = "awaycontent8"
+
+/area/awaycontent/a9
+ icon_state = "awaycontent9"
+
+/area/awaycontent/a10
+ icon_state = "awaycontent10"
+
+/area/awaycontent/a11
+ icon_state = "awaycontent11"
+
+/area/awaycontent/a11
+ icon_state = "awaycontent12"
+
+/area/awaycontent/a12
+ icon_state = "awaycontent13"
+
+/area/awaycontent/a13
+ icon_state = "awaycontent14"
+
+/area/awaycontent/a14
+ icon_state = "awaycontent14"
+
+/area/awaycontent/a15
+ icon_state = "awaycontent15"
+
+/area/awaycontent/a16
+ icon_state = "awaycontent16"
+
+/area/awaycontent/a17
+ icon_state = "awaycontent17"
+
+/area/awaycontent/a18
+ icon_state = "awaycontent18"
+
+/area/awaycontent/a19
+ icon_state = "awaycontent19"
+
+/area/awaycontent/a20
+ icon_state = "awaycontent20"
+
+/area/awaycontent/a21
+ icon_state = "awaycontent21"
+
+/area/awaycontent/a22
+ icon_state = "awaycontent22"
+
+/area/awaycontent/a23
+ icon_state = "awaycontent23"
+
+/area/awaycontent/a24
+ icon_state = "awaycontent24"
+
+/area/awaycontent/a25
+ icon_state = "awaycontent25"
+
+/area/awaycontent/a26
+ icon_state = "awaycontent26"
+
+/area/awaycontent/a27
+ icon_state = "awaycontent27"
+
+/area/awaycontent/a28
+ icon_state = "awaycontent28"
+
+/area/awaycontent/a29
+ icon_state = "awaycontent29"
+
+/area/awaycontent/a30
+ icon_state = "awaycontent30"
+
/////////////////////////////////////////////////////////////////////
/*
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index e997d1ec9f8..3769ed485af 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -68,6 +68,12 @@
a.cancelAlarm("Power", src, source)
else
a.triggerAlarm("Power", src, cameras, source)
+ for(var/mob/living/simple_animal/drone/D in mob_list)
+ if(D.z == source.z)
+ if(state == 1)
+ D.cancelAlarm("Power", src, source)
+ else
+ D.triggerAlarm("Power", src, cameras, source)
return
/area/proc/atmosalert(danger_level)
@@ -86,11 +92,15 @@
aiPlayer.triggerAlarm("Atmosphere", src, cameras, src)
for(var/obj/machinery/computer/station_alert/a in machines)
a.triggerAlarm("Atmosphere", src, cameras, src)
+ for(var/mob/living/simple_animal/drone/D in mob_list)
+ D.triggerAlarm("Atmosphere", src, cameras, src)
else if (src.atmosalm == 2)
for(var/mob/living/silicon/aiPlayer in player_list)
aiPlayer.cancelAlarm("Atmosphere", src, src)
for(var/obj/machinery/computer/station_alert/a in machines)
a.cancelAlarm("Atmosphere", src, src)
+ for(var/mob/living/simple_animal/drone/D in mob_list)
+ D.cancelAlarm("Atmosphere", src, src)
src.atmosalm = danger_level
return 1
return 0
@@ -118,6 +128,8 @@
a.triggerAlarm("Fire", src, cameras, src)
for (var/mob/living/silicon/aiPlayer in player_list)
aiPlayer.triggerAlarm("Fire", src, cameras, src)
+ for (var/mob/living/simple_animal/drone/D in mob_list)
+ D.triggerAlarm("Fire", src, cameras, src)
return
/area/proc/firereset()
@@ -138,6 +150,8 @@
aiPlayer.cancelAlarm("Fire", src, src)
for (var/obj/machinery/computer/station_alert/a in machines)
a.cancelAlarm("Fire", src, src)
+ for (var/mob/living/simple_animal/drone/D in mob_list)
+ D.cancelAlarm("Fire", src, src)
return
/area/proc/burglaralert(var/obj/trigger)
diff --git a/code/game/asteroid.dm b/code/game/asteroid.dm
index 9f29bedef73..eff9492c13c 100644
--- a/code/game/asteroid.dm
+++ b/code/game/asteroid.dm
@@ -113,8 +113,8 @@ proc/make_mining_asteroid_secret()
if("speakeasy")
theme = "speakeasy"
floortypes = list(/turf/simulated/floor,/turf/simulated/floor/wood)
- treasureitems = list(/obj/item/weapon/melee/energy/sword/pirate=1,/obj/item/weapon/gun/projectile/revolver/doublebarrel=1, /obj/machinery/reagentgrinder=2,
- /obj/structure/reagent_dispensers/beerkeg=5, /obj/machinery/computer/security/wooden_tv=4, /obj/machinery/vending/coffee=3)
+ treasureitems = list(/obj/item/weapon/melee/energy/sword/pirate=1,/obj/item/weapon/gun/projectile/revolver/doublebarrel=1,/obj/item/weapon/storage/backpack/satchel_flat=1,
+ /obj/machinery/reagentgrinder=2, /obj/machinery/computer/security/wooden_tv=4, /obj/machinery/vending/coffee=3)
fluffitems = list(/obj/structure/table/woodentable=2,/obj/structure/reagent_dispensers/beerkeg=1,/obj/item/weapon/spacecash/c500=4,
/obj/item/weapon/reagent_containers/food/drinks/shaker=1,/obj/item/weapon/reagent_containers/food/drinks/bottle/wine=3,
/obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey=3,/obj/item/clothing/shoes/laceup=2)
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 22a06b41da6..48bc30e5b41 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -10,6 +10,7 @@
var/throw_range = 7
var/moved_recently = 0
var/mob/pulledby = null
+ var/languages = 0 //For say() and Hear()
glide_size = 8
/atom/movable/Move()
diff --git a/code/game/communications.dm b/code/game/communications.dm
index 7f724237cf7..ac4576042c2 100644
--- a/code/game/communications.dm
+++ b/code/game/communications.dm
@@ -60,6 +60,31 @@
If receiving object don't know right key, it must ignore encrypted signal in its receive_signal.
*/
+/* the radio controller is a confusing piece of shit and didnt work
+ so i made radios not use the radio controller.
+*/
+var/list/all_radios = list()
+/proc/add_radio(var/obj/item/radio, freq)
+ if(!freq || !radio)
+ return
+ if(!all_radios["[freq]"])
+ all_radios["[freq]"] = list(radio)
+ return freq
+
+ all_radios["[freq]"] |= radio
+ return freq
+
+/proc/remove_radio(var/obj/item/radio, freq)
+ if(!freq || !radio)
+ return
+ if(!all_radios["[freq]"])
+ return
+
+ all_radios["[freq]"] -= radio
+
+/proc/remove_radio_all(var/obj/item/radio)
+ for(var/freq in all_radios)
+ all_radios["[freq]"] -= radio
/*
Frequency range: 1200 to 1600
@@ -109,8 +134,23 @@ var/list/radiochannels = list(
"Syndicate" = 1213,
"Supply" = 1347,
"Service" = 1349,
- "AI Private" = 1447,
+ "AI Private" = 1447
)
+
+var/list/radiochannelsreverse = list(
+ "1459" = "Common",
+ "1351" = "Science",
+ "1353" = "Command",
+ "1355" = "Medical",
+ "1357" = "Engineering",
+ "1359" = "Security",
+ "1441" = "Deathsquad",
+ "1213" = "Syndicate",
+ "1347" = "Supply",
+ "1349" = "Service",
+ "1447" = "AI Private"
+)
+
//depenging helpers
var/const/SYND_FREQ = 1213 //nuke op frequency, coloured dark brown in chat window
var/const/SUPP_FREQ = 1347 //supply, coloured light brown in chat window
@@ -129,7 +169,7 @@ var/const/AIPRIV_FREQ = 1447 //AI private, colored magenta in chat window
/* filters */
var/const/RADIO_TO_AIRALARM = "1"
var/const/RADIO_FROM_AIRALARM = "2"
-var/const/RADIO_CHAT = "3"
+var/const/RADIO_CHAT = "3" //deprecated
var/const/RADIO_ATMOSIA = "4"
var/const/RADIO_NAVBEACONS = "5"
var/const/RADIO_AIRLOCK = "6"
@@ -282,7 +322,7 @@ var/list/pointers = list()
src << S.debug_print()
/obj/proc/receive_signal(datum/signal/signal, receive_method, receive_param)
- return null
+ return
/datum/signal
var/obj/source
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
new file mode 100644
index 00000000000..8cea24b69b5
--- /dev/null
+++ b/code/game/data_huds.dm
@@ -0,0 +1,182 @@
+/* Using the HUD procs is simple. Call these procs in the life.dm of the intended mob.
+Use the regular_hud_updates() proc before process_med_hud(mob) or process_sec_hud(mob) so
+the HUD updates properly! */
+
+//Deletes the current HUD images so they can be refreshed with new ones.
+mob/proc/regular_hud_updates() //Used in the life.dm of mobs that can use HUDs.
+ if(client)
+ for(var/image/hud in client.images)
+ if(copytext(hud.icon_state,1,4) == "hud")
+ client.images -= hud
+ med_hud_users -= src
+ sec_hud_users -= src
+
+
+//Medical HUD procs
+
+proc/RoundHealth(health)
+
+ switch(health)
+ if(100 to INFINITY)
+ return "health100"
+ if(70 to 100)
+ return "health80"
+ if(50 to 70)
+ return "health60"
+ if(30 to 50)
+ return "health40"
+ if(18 to 30)
+ return "health25"
+ if(5 to 18)
+ return "health10"
+ if(1 to 5)
+ return "health1"
+ if(-99 to 0)
+ return "health0"
+ else
+ return "health-100"
+ return "0"
+
+/*Called by the Life() proc of the mob using it, usually. Items can call it as well.
+Called with this syntax: (The user mob, the type of hud in use, the advanced or basic version of the hud,eye object in the case of an AI) */
+
+proc/process_data_hud(var/mob/M, var/hud_type, var/hud_mode, var/mob/eye)
+ #define DATA_HUD_MEDICAL 1
+ #define DATA_HUD_SECURITY 2
+
+ #define DATA_HUD_BASIC 1
+ #define DATA_HUD_ADVANCED 2
+
+ if(!M)
+ return
+ if(!M.client)
+ return
+
+ var/turf/T
+ if(eye)
+ T = get_turf(eye)
+ else
+ T = get_turf(M)
+
+
+ for(var/mob/living/carbon/human/H in mob_list)
+ if(get_dist(H, T) > M.client.view) //Ignores any humans outside of the user's view distance.
+ continue
+
+ switch(hud_type)
+ if(DATA_HUD_MEDICAL)
+ med_hud_users |= M
+ process_med_hud(M,hud_mode,T,H)
+
+ if(DATA_HUD_SECURITY)
+ sec_hud_users |= M //Used for Security HUD alerts.
+ process_sec_hud(M,hud_mode,T,H)
+
+/***********************************************
+Medical HUD outputs! Advanced mode ignores suit sensors.
+************************************************/
+proc/process_med_hud(var/mob/M, var/mode, var/turf/T, var/mob/living/carbon/human/patient)
+
+ var/client/C = M.client
+
+ if(mode == DATA_HUD_BASIC && !med_hud_suit_sensors(patient)) //Used for the AI's MedHUD, only works if the patient has activated suit sensors.
+ return
+
+
+ var/foundVirus = med_hud_find_virus(patient) //Detects non-hidden diseases in a patient, returns as a binary value.
+
+ C.images += med_hud_get_health(patient) //Generates a patient's health bar.
+ C.images += med_hud_get_status(patient, foundVirus) //Determines the type of status icon to show.
+
+
+proc/med_hud_suit_sensors(var/mob/living/carbon/human/patient)
+ if(istype(patient.w_uniform, /obj/item/clothing/under))
+ var/obj/item/clothing/under/U = patient.w_uniform
+ if(U.sensor_mode > 2)
+ return 1
+ else
+ return 0
+
+proc/med_hud_find_virus(var/mob/living/carbon/human/patient)
+ for(var/datum/disease/D in patient.viruses)
+ if(!D.hidden[SCANNER])
+ if(D.severity != D.non_threat)
+ return 1
+
+proc/med_hud_get_health(var/mob/living/carbon/human/patient)
+ var/image/holder = patient.hud_list[HEALTH_HUD]
+ if(patient.stat == 2)
+ holder.icon_state = "hudhealth-100"
+ else
+ holder.icon_state = "hud[RoundHealth(patient.health)]"
+ return holder
+
+proc/med_hud_get_status(var/mob/living/carbon/human/patient, var/foundVirus)
+ var/image/holder = patient.hud_list[STATUS_HUD]
+ if(patient.stat == 2)
+ holder.icon_state = "huddead"
+ else if(patient.status_flags & XENO_HOST)
+ holder.icon_state = "hudxeno"
+ else if(foundVirus)
+ holder.icon_state = "hudill"
+ else
+ holder.icon_state = "hudhealthy"
+ return holder
+
+
+/***********************************************
+ Security HUDs.
+ Pass a value for the second argument to enable implant viewing or other special features.
+************************************************/
+proc/process_sec_hud(var/mob/M, var/mode, var/turf/T, var/mob/living/carbon/human/perp)
+
+ var/client/C = M.client
+
+ sec_hud_get_ID(C, perp) //Provides the perp's job icon.
+
+ if(mode == DATA_HUD_ADVANCED) //If not set to "DATA_HUD_ADVANCED, the Sec HUD will only display the job.
+ sec_hud_get_implants(C, perp) //Returns the perp's implants, if any.
+ sec_hud_get_security_status(C, perp) //Gives the perp's arrest record, if there is one.
+
+
+proc/sec_hud_get_ID(var/client/C, var/mob/living/carbon/human/perp)
+ var/image/holder
+ holder = perp.hud_list[ID_HUD]
+ holder.icon_state = "hudno_id"
+ if(perp.wear_id)
+ holder.icon_state = "hud[ckey(perp.wear_id.GetJobName())]"
+ C.images += holder
+
+proc/sec_hud_get_implants(var/client/C, var/mob/living/carbon/human/perp)
+ var/image/holder
+ for(var/obj/item/weapon/implant/I in perp)
+ if(I.implanted)
+ if(istype(I,/obj/item/weapon/implant/tracking))
+ holder = perp.hud_list[IMPTRACK_HUD]
+ holder.icon_state = "hud_imp_tracking"
+ else if(istype(I,/obj/item/weapon/implant/loyalty))
+ holder = perp.hud_list[IMPLOYAL_HUD]
+ holder.icon_state = "hud_imp_loyal"
+ else if(istype(I,/obj/item/weapon/implant/chem))
+ holder = perp.hud_list[IMPCHEM_HUD]
+ holder.icon_state = "hud_imp_chem"
+ else
+ continue
+ C.images += holder
+ break
+
+proc/sec_hud_get_security_status(var/client/C, var/mob/living/carbon/human/perp)
+ var/image/holder
+ var/perpname = perp.get_face_name(perp.get_id_name(""))
+ if(perpname)
+ var/datum/data/record/R = find_record("name", perpname, data_core.security)
+ if(R)
+ holder = perp.hud_list[WANTED_HUD]
+ switch(R.fields["criminal"])
+ if("*Arrest*") holder.icon_state = "hudwanted"
+ if("Incarcerated") holder.icon_state = "hudincarcerated"
+ if("Parolled") holder.icon_state = "hudparolled"
+ if("Discharged") holder.icon_state = "huddischarged"
+ else
+ return
+ C.images += holder
\ No newline at end of file
diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm
index 8629d682434..9bcc166edfd 100644
--- a/code/game/gamemodes/blob/blob.dm
+++ b/code/game/gamemodes/blob/blob.dm
@@ -16,6 +16,7 @@ var/list/blob_nodes = list()
recommended_enemies = 1
restricted_jobs = list("Cyborg", "AI")
+ pre_setup_before_jobs = 1
var/declared = 0
@@ -110,10 +111,6 @@ var/list/blob_nodes = list()
else
ERROR("Events variable is null in blob gamemode post setup.")
- spawn(10)
- start_state = new /datum/station_state()
- start_state.count()
-
spawn(0)
var/wait_time = rand(waittime_l, waittime_h)
@@ -135,11 +132,11 @@ var/list/blob_nodes = list()
burst_blobs()
// Stage 0
- sleep(40)
+ sleep(wait_time)
stage(0)
// Stage 1
- sleep(2000)
+ sleep(wait_time)
stage(1)
// Stage 2
diff --git a/code/game/gamemodes/blob/blob_finish.dm b/code/game/gamemodes/blob/blob_finish.dm
index 80e2f54e93e..f83550796b7 100644
--- a/code/game/gamemodes/blob/blob_finish.dm
+++ b/code/game/gamemodes/blob/blob_finish.dm
@@ -12,27 +12,22 @@
/datum/game_mode/blob/declare_completion()
if(blobwincount <= blobs.len)
- feedback_set_details("round_end_result","loss - blob took over")
+ feedback_set_details("round_end_result","win - blob took over")
world << "The blob has taken over the station!"
world << "The entire station was eaten by the Blob"
- log_game("Blob mode was lost.")
+ log_game("Blob mode completed with a blob victory.")
else if(station_was_nuked)
feedback_set_details("round_end_result","halfwin - nuke")
world << "Partial Win: The station has been destroyed!"
world << "Directive 7-12 has been successfully carried out preventing the Blob from spreading."
- log_game("Blob mode was tie (station destroyed).")
+ log_game("Blob mode completed with a tie (station destroyed).")
else if(!blob_cores.len)
- feedback_set_details("round_end_result","win - blob eliminated")
+ feedback_set_details("round_end_result","loss - blob eliminated")
world << "The staff has won!"
world << "The alien organism has been eradicated from the station"
-
- var/datum/station_state/end_state = new /datum/station_state()
- end_state.count()
- var/percent = round( 100.0 * start_state.score(end_state), 0.1)
- world << "The station is [percent]% intact."
- log_game("Blob mode was won with station [percent]% intact.")
+ log_game("Blob mode completed with a crew victory.")
world << "Rebooting in 30s"
..()
return 1
diff --git a/code/game/gamemodes/blob/blob_report.dm b/code/game/gamemodes/blob/blob_report.dm
index 2277b961c1b..1bece2f8ccd 100644
--- a/code/game/gamemodes/blob/blob_report.dm
+++ b/code/game/gamemodes/blob/blob_report.dm
@@ -2,13 +2,11 @@
/datum/game_mode/blob/send_intercept(var/report = 1)
var/intercepttext = ""
- var/interceptname = "Error"
switch(report)
if(0)
..()
return
if(1)
- interceptname = "Biohazard Alert"
intercepttext += "NanoTrasen Update: Biohazard Alert."
intercepttext += "Reports indicate the probable transfer of a biohazardous agent onto [station_name()] during the last crew deployment cycle. "
intercepttext += "Preliminary analysis of the organism classifies it as a level 5 biohazard. Its origin is unknown. "
@@ -21,12 +19,12 @@
intercepttext += " Note in the event of a quarantine breach or uncontrolled spread of the biohazard, the directive 7-10 may be upgraded to a directive 7-12. "
intercepttext += "Message ends."
if(2)
- var/nukecode = "ERROR"
+ var/nukecode = rand(10000, 99999)
for(var/obj/machinery/nuclearbomb/bomb in world)
if(bomb && bomb.r_code)
if(bomb.z == 1)
- nukecode = bomb.r_code
- interceptname = "Directive 7-12"
+ bomb.r_code = nukecode
+
intercepttext += "NanoTrasen Update: Biohazard Alert."
intercepttext += "Directive 7-12 has been issued for [station_name()]. "
intercepttext += "The biohazard has grown out of control and will soon reach critical mass. "
@@ -42,7 +40,7 @@
aiPlayer.set_zeroth_law(law)
aiPlayer << "Laws Updated: [law]"
- print_command_report(intercepttext,interceptname)
+ print_command_report(intercepttext,"Classified [command_name()] Update")
priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg');
return
diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm
index 6844ffe118f..c10d36e7558 100644
--- a/code/game/gamemodes/changeling/changeling.dm
+++ b/code/game/gamemodes/changeling/changeling.dm
@@ -13,9 +13,8 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
required_players = 15
required_enemies = 1
recommended_enemies = 4
+ pre_setup_before_jobs = 1
- uplink_welcome = "Syndicate Uplink Console:"
- uplink_uses = 10
var/const/prob_int_murder_target = 50 // intercept names the assassination target half the time
var/const/prob_right_murder_target_l = 25 // lower bound on probability of naming right assassination target
@@ -48,7 +47,7 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
var/num_changelings = 1
if(config.changeling_scaling_coeff)
- num_changelings = max(1, round((num_players())/(config.changeling_scaling_coeff)))
+ num_changelings = max(1, min( round(num_players()/(config.changeling_scaling_coeff*2))+2, round(num_players()/config.changeling_scaling_coeff) ))
else
num_changelings = max(1, min(num_players(), changeling_amount))
@@ -79,10 +78,10 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
return
/datum/game_mode/changeling/make_antag_chance(var/mob/living/carbon/human/character) //Assigns changeling to latejoiners
- var/changelingcap = round(joined_player_list.len / config.changeling_scaling_coeff)
+ var/changelingcap = min( round(joined_player_list.len/(config.changeling_scaling_coeff*2))+2, round(joined_player_list.len/config.changeling_scaling_coeff) )
if(changelings.len >= changelingcap) //Caps number of latejoin antagonists
return
- if(changelings.len <= (changelingcap - 2) || prob(100 / config.changeling_scaling_coeff))
+ if(changelings.len <= (changelingcap - 2) || prob(100 - (config.changeling_scaling_coeff*2)))
if(character.client.prefs.be_special & BE_CHANGELING)
if(!jobban_isbanned(character.client, "changeling") && !jobban_isbanned(character.client, "Syndicate"))
if(!(character.job in ticker.mode.restricted_jobs))
@@ -101,7 +100,7 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
changeling.objectives += absorb_objective
var/list/active_ais = active_ais()
- if(active_ais.len && prob(2))
+ if(active_ais.len && prob(100/joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = changeling
destroy_objective.find_target()
@@ -138,8 +137,7 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
/datum/game_mode/proc/greet_changeling(var/datum/mind/changeling, var/you_are=1)
if (you_are)
- changeling.current << "You are a changeling! You have absorbed and taken the form of a human."
- changeling.current << "Use say \":g message\" to communicate with your fellow changelings."
+ changeling.current << "You are [changeling.changeling.changelingID], a changeling! You have absorbed and taken the form of a human."
changeling.current << "You must complete the following tasks:"
if (changeling.current.mind)
@@ -180,19 +178,10 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
var/text = " The changelings were:"
for(var/datum/mind/changeling in changelings)
var/changelingwin = 1
-
- text += " [changeling.key] was [changeling.name] ("
- if(changeling.current)
- if(changeling.current.stat == DEAD)
- text += "died"
- else
- text += "survived"
- if(changeling.current.real_name != changeling.name)
- text += " as [changeling.current.real_name]"
- else
- text += "body destroyed"
+ if(!changeling.current)
changelingwin = 0
- text += ")"
+
+ text += printplayer(changeling)
//Removed sanity if(changeling) because we -want- a runtime to inform us that the changelings list is incorrect and needs to be fixed.
text += " Changeling ID: [changeling.changeling.changelingID]."
@@ -235,10 +224,11 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
var/changelingID = "Changeling"
var/geneticdamage = 0
var/isabsorbing = 0
- var/geneticpoints = 5
+ var/geneticpoints = 10
var/purchasedpowers = list()
var/mimicing = ""
var/canrespec = 0
+ var/changeling_speak = 0
var/datum/dna/chosen_dna
var/obj/effect/proc_holder/changeling/sting/chosen_sting
diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm
index 3365038e721..c7ff6471f7b 100644
--- a/code/game/gamemodes/changeling/evolution_menu.dm
+++ b/code/game/gamemodes/changeling/evolution_menu.dm
@@ -316,6 +316,10 @@ var/list/sting_paths
user << "We have already evolved this ability!"
return
+ if(thepower.dna_cost < 0)
+ user << "We cannot evolve this ability."
+ return
+
if(geneticpoints < thepower.dna_cost)
user << "We have reached our capacity for abilities."
return
@@ -370,12 +374,14 @@ var/list/sting_paths
chem_storage = initial(chem_storage)
chem_recharge_rate = initial(chem_recharge_rate)
chem_charges = min(chem_charges, chem_storage)
+ chem_recharge_slowdown = initial(chem_recharge_slowdown)
mimicing = ""
/mob/proc/remove_changeling_powers(var/keep_free_powers=0)
if(ishuman(src) || ismonkey(src))
if(mind && mind.changeling)
digitalcamo = 0
+ mind.changeling.changeling_speak = 0
mind.changeling.reset()
for(var/obj/effect/proc_holder/changeling/p in mind.changeling.purchasedpowers)
if(!(p.dna_cost == 0 && keep_free_powers))
diff --git a/code/game/gamemodes/changeling/powers/epinephrine.dm b/code/game/gamemodes/changeling/powers/epinephrine.dm
index 20fe4a677b9..973f01f9b54 100644
--- a/code/game/gamemodes/changeling/powers/epinephrine.dm
+++ b/code/game/gamemodes/changeling/powers/epinephrine.dm
@@ -3,7 +3,7 @@
desc = "We evolve additional sacs of adrenaline throughout our body."
helptext = "Removes all stuns instantly and adds a short-term reduction in further stuns. Can be used while unconscious. Continued use poisons the body."
chemical_cost = 30
- dna_cost = 1
+ dna_cost = 2
req_human = 1
req_stat = UNCONSCIOUS
diff --git a/code/game/gamemodes/changeling/powers/fakedeath.dm b/code/game/gamemodes/changeling/powers/fakedeath.dm
index 7a0ed702059..16c3ccbb237 100644
--- a/code/game/gamemodes/changeling/powers/fakedeath.dm
+++ b/code/game/gamemodes/changeling/powers/fakedeath.dm
@@ -1,7 +1,7 @@
/obj/effect/proc_holder/changeling/fakedeath
name = "Regenerative Stasis"
desc = "We fall into a stasis, allowing us to regenerate."
- chemical_cost = 20
+ chemical_cost = 15
dna_cost = 0
req_dna = 1
req_stat = DEAD
diff --git a/code/game/gamemodes/changeling/powers/fleshmend.dm b/code/game/gamemodes/changeling/powers/fleshmend.dm
index 9f67ef05d84..7a58c554dfc 100644
--- a/code/game/gamemodes/changeling/powers/fleshmend.dm
+++ b/code/game/gamemodes/changeling/powers/fleshmend.dm
@@ -2,8 +2,8 @@
name = "Fleshmend"
desc = "Our flesh rapidly regenerates, healing our wounds."
helptext = "Heals a moderate amount of damage over a short period of time. Can be used while unconscious."
- chemical_cost = 30
- dna_cost = 1
+ chemical_cost = 25
+ dna_cost = 2
req_stat = UNCONSCIOUS
//Starts healing you every second for 10 seconds. Can be used whilst unconscious.
diff --git a/code/game/gamemodes/changeling/powers/glands.dm b/code/game/gamemodes/changeling/powers/glands.dm
index b6f6aaf5e47..ca36093a9f7 100644
--- a/code/game/gamemodes/changeling/powers/glands.dm
+++ b/code/game/gamemodes/changeling/powers/glands.dm
@@ -2,7 +2,7 @@
name = "Engorged Chemical Glands"
desc = "Our chemical glands swell, permitting us to store more chemicals inside of them."
helptext = "Allows us to store an extra 25 units of chemicals, and doubles production rate."
- dna_cost = 1
+ dna_cost = 2
chemical_cost = -1
/obj/effect/proc_holder/changeling/glands/on_purchase(var/mob/user)
diff --git a/code/game/gamemodes/changeling/powers/hivemind.dm b/code/game/gamemodes/changeling/powers/hivemind.dm
index 3f9aa14b702..2ccb9a3a4e4 100644
--- a/code/game/gamemodes/changeling/powers/hivemind.dm
+++ b/code/game/gamemodes/changeling/powers/hivemind.dm
@@ -1,11 +1,32 @@
+//HIVEMIND COMMUNICATION (:g)
+/obj/effect/proc_holder/changeling/hivemind_comms
+ name = "Hivemind Communication"
+ desc = "We tune our senses to the airwaves to allow us to discreetly communicate and exchange DNA with other changelings."
+ helptext = "We will be able to talk with other changelings with :g. Exchanged DNA do not count towards absorb objectives."
+ dna_cost = 2
+ chemical_cost = -1
+
+/obj/effect/proc_holder/changeling/hivemind_comms/on_purchase(var/mob/user)
+ ..()
+ var/datum/changeling/changeling=user.mind.changeling
+ changeling.changeling_speak = 1
+ user << "Use say \":g message\" to communicate with the other changelings."
+ var/obj/effect/proc_holder/changeling/hivemind_upload/S1 = new
+ if(!changeling.has_sting(S1))
+ changeling.purchasedpowers+=S1
+ var/obj/effect/proc_holder/changeling/hivemind_download/S2 = new
+ if(!changeling.has_sting(S2))
+ changeling.purchasedpowers+=S2
+ return
+
// HIVE MIND UPLOAD/DOWNLOAD DNA
var/list/datum/dna/hivemind_bank = list()
/obj/effect/proc_holder/changeling/hivemind_upload
- name = "Hive Channel"
+ name = "Hive Channel DNA"
desc = "Allows us to channel DNA in the airwaves to allow other changelings to absorb it."
chemical_cost = 10
- dna_cost = 0
+ dna_cost = -1
/obj/effect/proc_holder/changeling/hivemind_upload/sting_action(var/mob/user)
var/datum/changeling/changeling = user.mind.changeling
@@ -32,10 +53,10 @@ var/list/datum/dna/hivemind_bank = list()
return 1
/obj/effect/proc_holder/changeling/hivemind_download
- name = "Hive Absorb"
+ name = "Hive Absorb DNA"
desc = "Allows us to absorb DNA that has been channeled to the airwaves. Does not count towards absorb objectives."
- chemical_cost = 20
- dna_cost = 0
+ chemical_cost = 10
+ dna_cost = -1
/obj/effect/proc_holder/changeling/hivemind_download/can_sting(var/mob/living/carbon/user)
if(!..())
diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm
index 7bb219b5e00..5781e7e7208 100644
--- a/code/game/gamemodes/changeling/powers/mutations.dm
+++ b/code/game/gamemodes/changeling/powers/mutations.dm
@@ -110,10 +110,10 @@
desc = "We reform one of our arms into a deadly blade."
helptext = "Cannot be used while in lesser form."
chemical_cost = 20
- dna_cost = 1
+ dna_cost = 2
genetic_damage = 10
req_human = 1
- max_genetic_damage = 11
+ max_genetic_damage = 20
weapon_type = /obj/item/weapon/melee/arm_blade
weapon_name_simple = "blade"
@@ -156,7 +156,7 @@
if(!A.requiresID() || A.allowed(user)) //This is to prevent stupid shit like hitting a door with an arm blade, the door opening because you have acces and still getting a "the airlocks motors resist our efforts to force it" message.
return
- if(A.arePowerSystemsOn() && !(A.stat & NOPOWER))
+ if(A.hasPower())
user << "The airlock's motors resist our efforts to force it."
return
@@ -175,18 +175,18 @@
\***************************************/
/obj/effect/proc_holder/changeling/weapon/shield
name = "Organic Shield"
- desc = "We reform one of our arms into hard shield."
+ desc = "We reform one of our arms into a hard shield."
helptext = "Organic tissue cannot resist damage forever, the shield will break after it is hit too much. The more genomes we absorb, the stronger it is. Cannot be used while in lesser form."
chemical_cost = 20
dna_cost = 1
genetic_damage = 12
req_human = 1
- max_genetic_damage = 10
+ max_genetic_damage = 20
weapon_type = /obj/item/weapon/shield/changeling
weapon_name_simple = "shield"
-/obj/effect/proc_holder/changeling/shield/sting_action(var/mob/user)
+/obj/effect/proc_holder/changeling/weapon/shield/sting_action(var/mob/user)
var/datum/changeling/changeling = user.mind.changeling //So we can read the absorbedcount.
if(!changeling)
return
@@ -236,10 +236,10 @@
desc = "We grow an organic suit to protect ourselves from space exposure."
helptext = "We must constantly repair our form to make it space-proof, reducing chemical production while we are protected. Retreating the suit damages our genomes. Cannot be used in lesser form."
chemical_cost = 20
- dna_cost = 1
+ dna_cost = 2
genetic_damage = 8
req_human = 1
- max_genetic_damage = 8
+ max_genetic_damage = 20
suit_type = /obj/item/clothing/suit/space/changeling
helmet_type = /obj/item/clothing/head/helmet/space/changeling
@@ -288,11 +288,11 @@
name = "Chitinous Armor"
desc = "We turn our skin into tough chitin to protect us from damage."
helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Retreating the armor damages our genomes. Cannot be used in lesser form."
- chemical_cost = 25
- dna_cost = 1
+ chemical_cost = 20
+ dna_cost = 2
genetic_damage = 11
req_human = 1
- max_genetic_damage = 10
+ max_genetic_damage = 20
suit_type = /obj/item/clothing/suit/armor/changeling
helmet_type = /obj/item/clothing/head/helmet/changeling
diff --git a/code/game/gamemodes/changeling/powers/panacea.dm b/code/game/gamemodes/changeling/powers/panacea.dm
index d18d2e33a7a..35067080403 100644
--- a/code/game/gamemodes/changeling/powers/panacea.dm
+++ b/code/game/gamemodes/changeling/powers/panacea.dm
@@ -1,8 +1,8 @@
/obj/effect/proc_holder/changeling/panacea
name = "Anatomic Panacea"
- desc = "Expels impurifications from our form; curing diseases, genetic disabilities, and removing toxins and radiation."
+ desc = "Expels impurifications from our form; curing diseases, removing toxins and radiation, and resetting our genetic code completely."
helptext = "Can be used while unconscious."
- chemical_cost = 25
+ chemical_cost = 20
dna_cost = 1
req_stat = UNCONSCIOUS
diff --git a/code/game/gamemodes/changeling/powers/shriek.dm b/code/game/gamemodes/changeling/powers/shriek.dm
index 046d8f9512e..026a0aa4a1b 100644
--- a/code/game/gamemodes/changeling/powers/shriek.dm
+++ b/code/game/gamemodes/changeling/powers/shriek.dm
@@ -2,13 +2,13 @@
name = "Resonant Shriek"
desc = "Our lungs and vocal chords shift, allowing us to briefly emit a noise that deafens and confuses the weak-minded."
helptext = "Emits a high-frequency sound that confuses and deafens humans, blows out nearby lights and overloads cyborg sensors."
- chemical_cost = 25
+ chemical_cost = 20
dna_cost = 1
req_human = 1
//A flashy ability, good for crowd control and sewing chaos.
/obj/effect/proc_holder/changeling/resonant_shriek/sting_action(var/mob/user)
- for(var/mob/living/M in hearers(4, user))
+ for(var/mob/living/M in get_hearers_in_view(4, user))
if(iscarbon(M))
if(!M.mind || !M.mind.changeling)
M.ear_deaf += 30
diff --git a/code/game/gamemodes/changeling/powers/spiders.dm b/code/game/gamemodes/changeling/powers/spiders.dm
index cc4bcea557a..693c38ee449 100644
--- a/code/game/gamemodes/changeling/powers/spiders.dm
+++ b/code/game/gamemodes/changeling/powers/spiders.dm
@@ -2,7 +2,7 @@
name = "Spread Infestation"
desc = "Our form divides, creating arachnids which will grow into deadly beasts."
helptext = "The spiders are thoughtless creatures, and may attack their creators when fully grown. Requires at least 5 DNA absorptions."
- chemical_cost = 50
+ chemical_cost = 45
dna_cost = 1
req_dna = 5
diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm
index 5aa17bd17d9..5ebff603d96 100644
--- a/code/game/gamemodes/changeling/powers/tiny_prick.dm
+++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm
@@ -64,7 +64,7 @@
helptext = "Does not provide a warning to others. The victim will transform much like a changeling would."
sting_icon = "sting_transform"
chemical_cost = 40
- dna_cost = 1
+ dna_cost = 2
var/datum/dna/selected_dna = null
/obj/effect/proc_holder/changeling/sting/transformation/Click()
@@ -117,7 +117,7 @@ obj/effect/proc_holder/changeling/sting/mute
helptext = "Does not provide a warning to the victim that they have been stung, until they try to speak and cannot."
sting_icon = "sting_mute"
chemical_cost = 20
- dna_cost = 1
+ dna_cost = 2
/obj/effect/proc_holder/changeling/sting/mute/sting_action(var/mob/user, var/mob/living/carbon/target)
add_logs(user, target, "stung", object="mute sting")
@@ -128,7 +128,7 @@ obj/effect/proc_holder/changeling/sting/mute
obj/effect/proc_holder/changeling/sting/blind
name = "Blind Sting"
desc = "Temporarily blinds the target."
- helptext = "This sting completely blinds a target for a short time. The target does not notice they have been stung."
+ helptext = "This sting completely blinds a target for a short time."
sting_icon = "sting_blind"
chemical_cost = 25
dna_cost = 1
@@ -145,9 +145,9 @@ obj/effect/proc_holder/changeling/sting/blind
obj/effect/proc_holder/changeling/sting/LSD
name = "Hallucination Sting"
desc = "Causes terror in the target."
- helptext = "We evolve the ability to sting a target with a powerful hallucinogenic chemical. The target does not notice they have been stung. The effect occurs after 30 to 60 seconds."
+ helptext = "We evolve the ability to sting a target with a powerful hallucinogenic chemical. The target does not notice they have been stung, and the effect occurs after 30 to 60 seconds."
sting_icon = "sting_lsd"
- chemical_cost = 5
+ chemical_cost = 10
dna_cost = 1
/obj/effect/proc_holder/changeling/sting/LSD/sting_action(var/mob/user, var/mob/living/carbon/target)
@@ -164,7 +164,7 @@ obj/effect/proc_holder/changeling/sting/cryo
helptext = "Does not provide a warning to the victim, though they will likely realize they are suddenly freezing."
sting_icon = "sting_cryo"
chemical_cost = 15
- dna_cost = 1
+ dna_cost = 2
/obj/effect/proc_holder/changeling/sting/cryo/sting_action(var/mob/user, var/mob/target)
add_logs(user, target, "stung", object="cryo sting")
diff --git a/code/game/gamemodes/changeling/traitor_chan.dm b/code/game/gamemodes/changeling/traitor_chan.dm
index 2b0b30948b5..7f6e843c85b 100644
--- a/code/game/gamemodes/changeling/traitor_chan.dm
+++ b/code/game/gamemodes/changeling/traitor_chan.dm
@@ -31,9 +31,9 @@
var/num_changelings = 1
if(config.changeling_scaling_coeff)
- num_changelings = max(1, round((num_players())/(config.changeling_scaling_coeff*2)))
+ num_changelings = max(1, min( round(num_players()/(config.changeling_scaling_coeff*4))+2, round(num_players()/(config.changeling_scaling_coeff*2)) ))
else
- num_changelings = max(1, min(num_players(), changeling_amount))
+ num_changelings = max(1, min(num_players(), changeling_amount/2))
for(var/datum/mind/player in possible_changelings)
for(var/job in restricted_jobs)//Removing robots from the list
@@ -61,11 +61,11 @@
return
/datum/game_mode/traitor/changeling/make_antag_chance(var/mob/living/carbon/human/character) //Assigns changeling to latejoiners
- var/changelingcap = round(joined_player_list.len / (config.changeling_scaling_coeff * 2))
+ var/changelingcap = min( round(joined_player_list.len/(config.changeling_scaling_coeff*4))+2, round(joined_player_list.len/(config.changeling_scaling_coeff*2)) )
if(changelings.len >= changelingcap) //Caps number of latejoin antagonists
..()
return
- if(changelings.len <= (changelingcap - 2) || prob(100 / (config.changeling_scaling_coeff * 2)))
+ if(changelings.len <= (changelingcap - 2) || prob(100 / (config.changeling_scaling_coeff * 4)))
if(character.client.prefs.be_special & BE_CHANGELING)
if(!jobban_isbanned(character.client, "changeling") && !jobban_isbanned(character.client, "Syndicate"))
if(!(character.job in ticker.mode.restricted_jobs))
diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index bc51727f202..0c7f68f88ee 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -29,9 +29,8 @@
required_players = 20
required_enemies = 6
recommended_enemies = 6
+ pre_setup_before_jobs = 1
- uplink_welcome = "Nar-Sie Uplink Console:"
- uplink_uses = 10
var/finished = 0
@@ -75,6 +74,7 @@
var/datum/mind/cultist = pick(antag_candidates)
antag_candidates -= cultist
cult += cultist
+ cultist.special_role = "Cultist"
log_game("[cultist.key] (ckey) has been selected as a cultist")
return (cult.len>=required_enemies)
@@ -105,7 +105,6 @@
update_cult_icons_added(cult_mind)
cult_mind.current << "You are a member of the cult!"
memorize_cult_objectives(cult_mind)
- cult_mind.special_role = "Cultist"
..()
@@ -332,7 +331,7 @@
feedback_set("round_end_result",acolytes_survived)
world << "The staff managed to stop the cult!"
- var/text = "Cultists escaped: [acolytes_survived]"
+ var/text = ""
if(cult_objectives.len)
text += " The cultists' objectives were:"
@@ -341,10 +340,10 @@
switch(cult_objectives[obj_count])
if("survive")
if(!check_survive())
- explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. Success!"
+ explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) Success!"
feedback_add_details("cult_objective","cult_survive|SUCCESS|[acolytes_needed]")
else
- explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. Fail."
+ explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) Fail."
feedback_add_details("cult_objective","cult_survive|FAIL|[acolytes_needed]")
if("sacrifice")
if(sacrifice_target)
@@ -375,18 +374,8 @@
if( cult.len || (ticker && istype(ticker.mode,/datum/game_mode/cult)) )
var/text = " The cultists were:"
for(var/datum/mind/cultist in cult)
+ text += printplayer(cultist)
- text += " [cultist.key] was [cultist.name] ("
- if(cultist.current)
- if(cultist.current.stat == DEAD)
- text += "died"
- else
- text += "survived"
- if(cultist.current.real_name != cultist.name)
- text += " as [cultist.current.real_name]"
- else
- text += "body destroyed"
- text += ")"
text += " "
world << text
diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm
index 970e1a4bea4..33f9322f2f5 100644
--- a/code/game/gamemodes/cult/ritual.dm
+++ b/code/game/gamemodes/cult/ritual.dm
@@ -63,9 +63,9 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
usr.say("O bidai nabora se[pick("'","`")]sma!")
sleep(10)
usr.say("[input]")
- for(var/datum/mind/H in ticker.mode.cult)
- if (H.current)
- H.current << "[input]"
+ for(var/mob/M in mob_list)
+ if((M.mind && (M.mind in ticker.mode.cult)) || (M in dead_mob_list))
+ M << "[input]"
return
#undef CHECK_STATUS
@@ -173,7 +173,7 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
user << "You are unable to speak the words of the rune."
return
if(!word1 || !word2 || !word3 || prob(user.getBrainLoss()))
- return fizzle()
+ return fizzle(user)
if(word1 == wordtravel && word2 == wordself)
return teleport(src.word3)
if(word1 == wordsee && word2 == wordblood && word3 == wordhell)
@@ -227,16 +227,18 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
else
user.take_overall_damage(30, 0)
user << "You feel the life draining from you, as if Lord Nar-Sie is displeased with you."
- return fizzle()
+ return fizzle(user)
-/obj/effect/rune/proc/fizzle()
- if(istype(src,/obj/effect/rune))
- usr.say(pick("B'ADMINES SP'WNIN SH'T","IC'IN O'OC","RO'SHA'M I'SA GRI'FF'N ME'AI","TOX'IN'S O'NM FI'RAH","IA BL'AME TOX'IN'S","FIR'A NON'AN RE'SONA","A'OI I'RS ROUA'GE","LE'OAN JU'STA SP'A'C Z'EE SH'EF","IA PT'WOBEA'RD, IA A'DMI'NEH'LP"))
- else
- usr.whisper(pick("B'ADMINES SP'WNIN SH'T","IC'IN O'OC","RO'SHA'M I'SA GRI'FF'N ME'AI","TOX'IN'S O'NM FI'RAH","IA BL'AME TOX'IN'S","FIR'A NON'AN RE'SONA","A'OI I'RS ROUA'GE","LE'OAN JU'STA SP'A'C Z'EE SH'EF","IA PT'WOBEA'RD, IA A'DMI'NEH'LP"))
- for (var/mob/V in viewers(src))
- V.show_message("The markings pulse with a small burst of light, then fall dark.", 3, "You hear a faint fizzle.", 2)
+/obj/effect/rune/proc/fizzle(var/mob/living/cultist = null)
+ var/gibberish = pick("B'ADMINES SP'WNIN SH'T","IC'IN O'OC","RO'SHA'M I'SA GRI'FF'N ME'AI","TOX'IN'S O'NM FI'RAH","IA BL'AME TOX'IN'S","FIR'A NON'AN RE'SONA","A'OI I'RS ROUA'GE","LE'OAN JU'STA SP'A'C Z'EE SH'EF","IA PT'WOBEA'RD, IA A'DMI'NEH'LP")
+
+ if(cultist)
+ if(istype(src,/obj/effect/rune))
+ cultist.say(gibberish)
+ else
+ cultist.whisper(gibberish)
+ visible_message("The markings pulse with a small burst of light, then fall dark.", 3, "You hear a faint fizzle.", 2)
return
/obj/effect/rune/proc/check_icon()
@@ -557,7 +559,7 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
usr.whisper("[input]")
for(var/datum/mind/H in ticker.mode.cult)
if (H.current)
- H.current << "[input]"
+ H.current << "[input]"
return
if("Notes")
if(usr.get_active_hand() != src)
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index d1f9b2885dc..fb07c3c966c 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -31,7 +31,7 @@ var/list/sacrificed = list()
user.loc = allrunesloc[rand(1,index)]
return
if(istype(src,/obj/effect/rune))
- return fizzle() //Use friggin manuals, Dorf, your list was of zero length.
+ return fizzle(user) //Use friggin manuals, Dorf, your list was of zero length.
else
call(/obj/effect/rune/proc/fizzle)()
return
@@ -53,7 +53,7 @@ var/list/sacrificed = list()
IP = R
runecount++
if(runecount >= 2)
- user << "You feel pain, as rune disappears in reality shift caused by too much wear of space-time fabric"
+ user << "You feel pain, as the rune disappears in reality shift caused by too much wear of space-time fabric"
if (istype(user, /mob/living))
user.take_overall_damage(5, 0)
qdel(src)
@@ -61,7 +61,7 @@ var/list/sacrificed = list()
if(iscultist(C) && !C.stat)
culcount++
if(user.loc==src.loc)
- return fizzle()
+ return fizzle(user)
if(culcount>=1)
user.say("Sas[pick("'","`")]so c'arta forbici tarem!")
user.visible_message("You feel air moving from the rune - like as it was swapped with somewhere else.", \
@@ -74,7 +74,7 @@ var/list/sacrificed = list()
M.loc = IP.loc
return
- return fizzle()
+ return fizzle(user)
/////////////////////////////////////////SECOND RUNE
@@ -110,7 +110,7 @@ var/list/sacrificed = list()
C.say("Mah[pick("'","`")]weyh pleggh at e'ntrath!")
if(cultsinrange.len >= 3)
M.visible_message("[M] writhes in pain as the markings below him glow a bloody red.", \
- "AAAAAAHHHH!.", \
+ "AAAAAAHHHH!", \
"You hear an anguished scream.")
if(is_convertable_to_cult(M.mind))
ticker.mode.add_cultist(M.mind)
@@ -152,9 +152,10 @@ var/list/sacrificed = list()
/obj/effect/rune/proc/tearreality()
var/list/mob/living/carbon/human/cultist_count = list()
+ var/mob/living/user = usr
+ user.say("Tok-lyr rqa'nap g[pick("'","`")]lt-ulotf!")
for(var/mob/M in range(1,src))
if(iscultist(M) && !M.stat)
- M.say("Tok-lyr rqa'nap g[pick("'","`")]lt-ulotf!")
cultist_count += M
if(cultist_count.len >= 9)
if(ticker.mode.name == "cult")
@@ -374,7 +375,7 @@ var/list/sacrificed = list()
return
if(istype(src,/obj/effect/rune))
- return fizzle()
+ return fizzle()
else
call(/obj/effect/rune/proc/fizzle)()
return
@@ -424,7 +425,6 @@ var/list/sacrificed = list()
"A shape forms in the center of the rune. A shape of... a man.", \
"You hear liquid flowing.")
D.real_name = "[pick(first_names_male)] [pick(last_names)]"
- D.universal_speak = 1
D.status_flags = CANSTUN|CANWEAKEN|CANPARALYSE|CANPUSH
D.key = ghost.key
@@ -574,9 +574,9 @@ var/list/sacrificed = list()
usr.say("[input]")
else
usr.whisper("[input]")
- for(var/datum/mind/H in ticker.mode.cult)
- if (H.current)
- H.current << "[input]"
+ for(var/mob/M in mob_list)
+ if((M.mind && (M.mind in ticker.mode.cult)) || (M in dead_mob_list))
+ M << "[input]"
return 1
/////////////////////////////////////////FIFTEENTH RUNE
@@ -770,7 +770,7 @@ var/list/sacrificed = list()
return
return
if(istype(W,/obj/effect/rune))
- return fizzle()
+ return fizzle()
if(istype(W,/obj/item/weapon/paper/talisman))
call(/obj/effect/rune/proc/fizzle)()
return
@@ -803,7 +803,7 @@ var/list/sacrificed = list()
if(users.len>=1)
var/mob/living/carbon/cultist = input("Choose the one who you want to free", "Followers of Geometer") as null|anything in (cultists - users)
if(!cultist)
- return fizzle()
+ return fizzle(user)
if (cultist == user) //just to be sure.
return
if(!(cultist.buckled || \
@@ -836,7 +836,7 @@ var/list/sacrificed = list()
user.take_overall_damage(15, 0)
C.say("Khari[pick("'","`")]d! Gual'te nikka!")
qdel(src)
- return fizzle()
+ return fizzle(user)
/////////////////////////////////////////NINETEENTH RUNE
@@ -853,12 +853,12 @@ var/list/sacrificed = list()
if(users.len>=3)
var/mob/living/carbon/cultist = input("Choose the one who you want to summon", "Followers of Geometer") as null|anything in (cultists - user)
if(!cultist)
- return fizzle()
+ return fizzle(user)
if(cultist == user) //just to be sure.
return
if(cultist.buckled || cultist.handcuffed || (!isturf(cultist.loc) && !istype(cultist.loc, /obj/structure/closet)))
user << "You cannot summon the [cultist], for his shackles of blood are strong"
- return fizzle()
+ return fizzle(user)
cultist.loc = src.loc
cultist.Weaken(5)
cultist.regenerate_icons()
@@ -870,7 +870,7 @@ var/list/sacrificed = list()
"You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a body.", \
"You hear a pop and smell ozone.")
qdel(src)
- return fizzle()
+ return fizzle(user)
/////////////////////////////////////////TWENTIETH RUNES
diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm
index 0becbca3c94..1fd9ea37360 100644
--- a/code/game/gamemodes/cult/talisman.dm
+++ b/code/game/gamemodes/cult/talisman.dm
@@ -69,7 +69,6 @@
dat += "Kla'atu barada nikt'o! - Allows you to conceal the runes you placed on the floor. "
dat += "O bidai nabora se'sma! - Allows you to coordinate with others of your cult. "
dat += "Fuu ma'jin - Allows you to stun a person by attacking them with the talisman. "
- dat += "Sa tatha najin - Allows you to summon armored robes and an unholy blade "
dat += "Kal om neth - Summons a soul stone "
dat += "Da A'ig Osk - Summons a construct shell for use with captured souls. It is too large to carry on your person. "
usr << browse(dat, "window=id_com;size=350x200")
@@ -123,4 +122,4 @@
/obj/item/weapon/paper/talisman/supply
imbue = "supply"
- uses = 3
\ No newline at end of file
+ uses = 3
diff --git a/code/game/gamemodes/extended/extended.dm b/code/game/gamemodes/extended/extended.dm
index 04dc0d29685..77e754ee36f 100644
--- a/code/game/gamemodes/extended/extended.dm
+++ b/code/game/gamemodes/extended/extended.dm
@@ -3,9 +3,6 @@
config_tag = "extended"
required_players = 0
- uplink_welcome = "Syndicate Uplink Console:"
- uplink_uses = 10
-
/datum/game_mode/announce()
world << "The current game mode is - Extended Role-Playing!"
world << "Just have fun and role-play!"
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 4f84c8e1fdc..7974819cefb 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -27,8 +27,6 @@
var/required_enemies = 0
var/recommended_enemies = 0
var/pre_setup_before_jobs = 0
- var/uplink_welcome = "Syndicate Uplink Console:"
- var/uplink_uses = 10
var/antag_flag = null //preferences flag such as BE_WIZARD that need to be turned on for players to be antag
var/datum/mind/sacrifice_target = null
@@ -81,6 +79,8 @@
if(report)
spawn (rand(waittime_l, waittime_h))
send_intercept(0)
+ start_state = new /datum/station_state()
+ start_state.count()
return 1
///make_antag_chance()
@@ -218,6 +218,7 @@
if(BE_OPERATIVE) roletext="operative"
if(BE_WIZARD) roletext="wizard"
if(BE_REV) roletext="revolutionary"
+ if(BE_GANG) roletext="gangster"
if(BE_CULTIST) roletext="cultist"
if(BE_MONKEY) roletext="monkey"
@@ -384,4 +385,20 @@ proc/display_roundstart_logout_report()
for(var/mob/M in mob_list)
if(M.client && M.client.holder)
- M << msg
\ No newline at end of file
+ M << msg
+
+/datum/game_mode/proc/printplayer(var/datum/mind/ply)
+ var/role = "\improper[ply.assigned_role]"
+ var/text = " [ply.name]([ply.key]) as \a [role] ("
+ if(ply.current)
+ if(ply.current.stat == DEAD)
+ text += "died"
+ else
+ text += "survived"
+ if(ply.current.real_name != ply.name)
+ text += " as [ply.current.real_name]"
+ else
+ text += "body destroyed"
+ text += ")"
+
+ return text
diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm
index fcc318999e8..8e2a9c15a14 100644
--- a/code/game/gamemodes/gameticker.dm
+++ b/code/game/gamemodes/gameticker.dm
@@ -198,6 +198,11 @@ var/round_start_time = 0
world << sound('sound/effects/explosionfar.ogg')
flick("station_intact_fade_red",cinematic)
cinematic.icon_state = "summary_nukefail"
+ if("fake") //The round isn't over, we're just freaking people out for fun
+ flick("intro_nuke",cinematic)
+ sleep(35)
+ world << sound('sound/items/bikehorn.ogg')
+ flick("summary_selfdes",cinematic)
else
flick("intro_nuke",cinematic)
sleep(35)
@@ -270,11 +275,12 @@ var/round_start_time = 0
/datum/controller/gameticker/proc/equip_characters()
var/captainless=1
for(var/mob/living/carbon/human/player in player_list)
+ if(!player.mind.need_job_assign)
+ continue
if(player && player.mind && player.mind.assigned_role)
if(player.mind.assigned_role == "Captain")
captainless=0
- if(player.mind.assigned_role != "MODE")
- job_master.EquipRank(player, player.mind.assigned_role, 0)
+ job_master.EquipRank(player, player.mind.assigned_role, 0)
if(captainless)
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player))
@@ -325,23 +331,47 @@ var/round_start_time = 0
/datum/controller/gameticker/proc/declare_completion()
+ var/station_evacuated
+ if(emergency_shuttle.location > 0)
+ station_evacuated = 1
+ var/num_survivors = 0
+ var/num_escapees = 0
+
world << "
The round has ended."
- for(var/mob/Player in player_list)
- if(Player.mind)
- if(Player.stat != DEAD)
- if(emergency_shuttle.location > 0) //If the shuttle has already left the station
+
+ //Player status report
+ for(var/mob/Player in mob_list)
+ if(Player.mind && !isnewplayer(Player))
+ if(Player.stat != DEAD && !isbrain(Player))
+ num_survivors++
+ if(station_evacuated) //If the shuttle has already left the station
var/turf/playerTurf = get_turf(Player)
if(playerTurf.z != 2)
Player << "You managed to survive, but were marooned on [station_name()]..."
else
+ num_escapees++
Player << "You managed to survive the events on [station_name()] as [Player.real_name]."
else
Player << "You managed to survive the events on [station_name()] as [Player.real_name]."
else
Player << "You did not survive the events on [station_name()]..."
+ //Round statistics report
+ var/datum/station_state/end_state = new /datum/station_state()
+ end_state.count()
+ var/station_integrity = round( 100.0 * start_state.score(end_state), 0.1)
+
+ world << " [TAB]Shift Duration: [round(world.time / 36000)]:[add_zero("[world.time / 600 % 60]", 2)]:[world.time / 100 % 6][world.time / 100 % 10]"
+ world << " [TAB]Station Integrity: [mode.station_was_nuked ? "Destroyed" : "[station_integrity]%"]"
+ if(joined_player_list.len)
+ world << " [TAB]Total Population: [joined_player_list.len]"
+ if(station_evacuated)
+ world << " [TAB]Evacuation Rate: [num_escapees] ([round((num_escapees/joined_player_list.len)*100, 0.1)]%)"
+ else
+ world << " [TAB]Survival Rate: [num_survivors] ([round((num_survivors/joined_player_list.len)*100, 0.1)]%)"
world << " "
+ //Silicon laws report
for (var/mob/living/silicon/ai/aiPlayer in mob_list)
if (aiPlayer.stat != 2 && aiPlayer.mind)
world << "[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws at the end of the round were:"
diff --git a/code/game/gamemodes/gang/gang.dm b/code/game/gamemodes/gang/gang.dm
new file mode 100644
index 00000000000..a9faa393a0a
--- /dev/null
+++ b/code/game/gamemodes/gang/gang.dm
@@ -0,0 +1,449 @@
+//gang.dm
+//Gang War Game Mode
+
+/datum/game_mode
+ var/list/datum/mind/A_bosses = list() //gang A bosses
+ var/list/datum/mind/A_gangsters = list() //gang A Members
+ var/list/datum/mind/B_bosses = list() //gang B bosses
+ var/list/datum/mind/B_gangsters = list() //gang B Members
+
+/datum/game_mode/gang
+ name = "gang war"
+ config_tag = "gang"
+ antag_flag = BE_GANG
+ restricted_jobs = list("Security Officer", "Warden", "Detective", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
+ required_players = 20
+ required_enemies = 2
+ recommended_enemies = 4
+
+ var/finished = 0
+ var/checkwin_counter = 0
+///////////////////////////
+//Announces the game type//
+///////////////////////////
+/datum/game_mode/gang/announce()
+ world << "The current game mode is - Gang War!"
+ world << "A violent turf war has erupted on the station! Gangsters - Take over the station by killing the rival gang's bosses! Recruit gangsters by flashing them! Security - Protect the Crew! Identify and stop the mob bosses!"
+
+
+///////////////////////////////////////////////////////////////////////////////
+//Gets the round setup, cancelling if there's not enough players at the start//
+///////////////////////////////////////////////////////////////////////////////
+/datum/game_mode/gang/pre_setup()
+ if(config.protect_roles_from_antagonist)
+ restricted_jobs += protected_jobs
+
+ for(var/datum/mind/player in antag_candidates)
+ for(var/job in restricted_jobs)//Removing heads and such from the list
+ if(player.assigned_role == job)
+ antag_candidates -= player
+
+ if(antag_candidates.len >= 2)
+ assign_bosses()
+ if(antag_candidates.len > 20)
+ assign_bosses()
+
+ if(!A_bosses.len || !B_bosses.len)
+ return 0
+
+//Set a temporary special_role so the job controller doesn't hand out invalid jobs for these antags
+ for(var/datum/mind/boss_mind in A_bosses)
+ boss_mind.special_role = "Gang member"
+ for(var/datum/mind/boss_mind in B_bosses)
+ boss_mind.special_role = "Gang member"
+
+ return 1
+
+
+/datum/game_mode/gang/post_setup()
+ spawn(rand(10,100))
+ for(var/datum/mind/boss_mind in A_bosses)
+ update_gang_icons_added(boss_mind, "A")
+ forge_gang_objectives(boss_mind, "A")
+ greet_gang(boss_mind)
+ equip_gang(boss_mind.current)
+
+ for(var/datum/mind/boss_mind in B_bosses)
+ update_gang_icons_added(boss_mind, "B")
+ forge_gang_objectives(boss_mind, "B")
+ greet_gang(boss_mind)
+ equip_gang(boss_mind.current)
+
+ modePlayer += A_bosses
+ modePlayer += B_bosses
+ ..()
+
+
+/datum/game_mode/gang/process()
+ checkwin_counter++
+ if(checkwin_counter >= 5)
+ if(!finished)
+ ticker.mode.check_win()
+ checkwin_counter = 0
+ return 0
+
+/datum/game_mode/gang/proc/assign_bosses()
+ var/datum/mind/boss = pick(antag_candidates)
+ A_bosses += boss
+ antag_candidates -= boss
+ boss.special_role = "[gang_name("A")] Gang (A) Boss"
+ log_game("[boss.key] has been selected as a boss for the [gang_name("A")] Gang (A)")
+
+ boss = pick(antag_candidates)
+ B_bosses += boss
+ antag_candidates -= boss
+ boss.special_role = "[gang_name("B")] Gang (B) Boss"
+ log_game("[boss.key] has been selected as a boss for the [gang_name("B")] Gang (B)")
+
+/datum/game_mode/proc/forge_gang_objectives(var/datum/mind/boss_mind)
+ var/datum/objective/rival_obj = new
+ rival_obj.owner = boss_mind
+ rival_obj.explanation_text = "Assassinate or exile the [(boss_mind in A_bosses) ? gang_name("B") : gang_name("A")] Gang's bosses."
+ boss_mind.objectives += rival_obj
+
+
+/datum/game_mode/proc/greet_gang(var/datum/mind/boss_mind, var/you_are=1)
+ var/obj_count = 1
+ if (you_are)
+ boss_mind.current << "You are a [(boss_mind in A_bosses) ? gang_name("A") : gang_name("B")] Gang Boss!"
+ for(var/datum/objective/objective in boss_mind.objectives)
+ boss_mind.current << "Objective #[obj_count]: [objective.explanation_text]"
+ obj_count++
+
+///////////////////////////////////////////////////////////////////////////
+//This equips the bosses with their gear, and makes the clown not clumsy//
+///////////////////////////////////////////////////////////////////////////
+/datum/game_mode/proc/equip_gang(mob/living/carbon/human/mob)
+ if(!istype(mob))
+ return
+
+ if (mob.mind)
+ if (mob.mind.assigned_role == "Clown")
+ mob << "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself."
+ mob.mutations.Remove(CLUMSY)
+
+
+ var/obj/item/device/flash/T = new(mob)
+ var/obj/item/device/recaller/recaller = new(mob)
+
+ var/list/slots = list (
+ "backpack" = slot_in_backpack,
+ "left pocket" = slot_l_store,
+ "right pocket" = slot_r_store,
+ "left hand" = slot_l_hand,
+ "right hand" = slot_r_hand,
+ )
+
+ . = 0
+
+ var/where2 = mob.equip_in_one_of_slots(recaller, slots)
+ if (!where2)
+ mob << "Your Syndicate benefactors were unfortunately unable to get you a Recaller."
+ else
+ mob << "The Recaller in your [where2] will allow you to prevent the station from prematurely evacuating. Use it to recall the emergency shuttle from anywhere on the station."
+ . += 2
+
+ var/where = mob.equip_in_one_of_slots(T, slots)
+ if (!where)
+ mob << "Your Syndicate benefactors were unfortunately unable to get you a flash."
+ else
+ mob << "The flash in your [where] will help you to persuade the crew to work for you."
+ mob << "Keep in mind that your underlings can only identify their bosses, but not each other. You must coordinate your gang effectively to beat out the competition."
+ . += 1
+
+ mob.update_icons()
+
+ return .
+
+/////////////////////////////////////////////
+//Checks if the either gang have won or not//
+/////////////////////////////////////////////
+/datum/game_mode/gang/check_win()
+ var/A_victory = check_gang_victory(B_bosses) //Check if B bosses are dead or exiled
+ var/B_victory = check_gang_victory(A_bosses) //Check if A bosses are dead or exiled
+
+ if(A_victory && B_victory)
+ finished = "Draw" //Both teams fail. Allow for draws in case they're all incapacitated at the same time.
+
+ else if(A_victory)
+ finished = "A" //Gang A wins
+
+ else if(B_victory)
+ finished = "B" //Gang B wins
+
+///////////////////////////////
+//Checks if the round is over//
+///////////////////////////////
+/datum/game_mode/gang/check_finished()
+ if(finished) //Check for Gang Boss death
+ return 1
+ return ..() //Check for evacuation/nuke
+
+///////////////////////////////////////////
+//Deals with converting players to a gang//
+///////////////////////////////////////////
+/datum/game_mode/proc/add_gangster(datum/mind/gangster_mind, var/gang, var/check = 1)
+ if(check && isloyal(gangster_mind.current)) //Check to see if the potential gangster is implanted
+ return 0
+ if((gangster_mind in A_bosses) || (gangster_mind in A_gangsters) || (gangster_mind in B_bosses) || (gangster_mind in B_gangsters))
+ return 0
+ if(gang == "A")
+ A_gangsters += gangster_mind
+ else
+ B_gangsters += gangster_mind
+ gangster_mind.current << "You are now a member of the [gang=="A" ? gang_name("A") : gang_name("B")] Gang!"
+ gangster_mind.current << "Help your bosses take over the station by defeating their rivals. You can identify your bosses by the brown \"B\" icons, but only they know who the other members of your gang are! Work with your boss to avoid attacking your own gang."
+ gangster_mind.current.attack_log += "\[[time_stamp()]\] Has been converted to the [gang=="A" ? "[gang_name("A")] Gang (A)" : "[gang_name("B")] Gang (B)"]!"
+ gangster_mind.special_role = "[gang=="A" ? "[gang_name("A")] Gang (A)" : "[gang_name("B")] Gang (B)"]"
+ update_gang_icons_added(gangster_mind,gang)
+ return 1
+//////////////////////////////////////////////////////////////
+//Deals with players going straight (Not a gangster anymore)//
+//////////////////////////////////////////////////////////////
+/datum/game_mode/proc/remove_gangster(datum/mind/gangster_mind, var/beingborged, var/silent)
+ var/gang
+
+ if(gangster_mind in A_bosses)
+ A_bosses -= gangster_mind
+ gang = "A"
+
+ else if(gangster_mind in A_gangsters)
+ A_gangsters -= gangster_mind
+ gang = "A"
+
+ else if(gangster_mind in B_bosses)
+ B_bosses -= gangster_mind
+ gang = "B"
+
+ else if(gangster_mind in B_gangsters)
+ B_gangsters -= gangster_mind
+ gang = "B"
+
+ if(!gang) //not a valid gangster
+ return
+
+ gangster_mind.special_role = null
+ if(silent < 2)
+ gangster_mind.current.attack_log += "\[[time_stamp()]\] Has reformed and defected from the [gang=="A" ? "[gang_name("A")] Gang (A)" : "[gang_name("B")] Gang (B)"]!"
+
+ if(beingborged)
+ if(!silent)
+ gangster_mind.current.visible_message("The frame beeps contentedly from the MMI before initalizing it.")
+ gangster_mind.current << "The frame's firmware detects and deletes your criminal behavior! You are no longer a gangster!"
+ message_admins("[key_name_admin(gangster_mind.current)] ? has been borged while being a member of the [gang=="A" ? "[gang_name("A")] Gang (A)" : "[gang_name("B")] Gang (B)"] Gang. They are no longer a gangster.")
+ else
+ if(!silent)
+ gangster_mind.current.visible_message("[gangster_mind.current] looks like they've given up the life of crime!")
+ gangster_mind.current << "You have been reformed! You are no longer a gangster!"
+
+ update_gang_icons_removed(gangster_mind)
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+//Keeps track of players having the correct icons////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////
+/datum/game_mode/proc/update_all_gang_icons()
+ spawn(0)
+ var/list/all_gangsters = A_bosses + B_bosses + A_gangsters + B_gangsters
+
+ //Delete all gang icons
+ for(var/datum/mind/gang_mind in all_gangsters)
+ if(gang_mind.current)
+ if(gang_mind.current.client)
+ for(var/image/I in gang_mind.current.client.images)
+ if(I.icon_state == "gangster" || I.icon_state == "gang_boss")
+ del(I)
+
+ update_gang_icons("A")
+ update_gang_icons("B")
+
+/datum/game_mode/proc/update_gang_icons(var/gang)
+ var/list/bosses
+ var/list/gangsters
+ if(gang == "A")
+ bosses = A_bosses
+ gangsters = A_gangsters
+ else if(gang == "B")
+ bosses = B_bosses
+ gangsters = B_gangsters
+ else
+ world << "ERROR: Invalid gang in update_gang_icons()"
+
+ //Update gang icons for boss' visions
+ for(var/datum/mind/boss_mind in bosses)
+ if(boss_mind.current)
+ if(boss_mind.current.client)
+ for(var/datum/mind/gangster_mind in gangsters)
+ if(gangster_mind.current)
+ var/I = image('icons/mob/mob.dmi', loc = gangster_mind.current, icon_state = "gangster")
+ boss_mind.current.client.images += I
+ for(var/datum/mind/boss2_mind in bosses)
+ if(boss2_mind.current)
+ var/I = image('icons/mob/mob.dmi', loc = boss2_mind.current, icon_state = "gang_boss")
+ boss_mind.current.client.images += I
+
+ //Update boss and self icons for gangsters' visions
+ for(var/datum/mind/gangster_mind in gangsters)
+ if(gangster_mind.current)
+ if(gangster_mind.current.client)
+ for(var/datum/mind/boss_mind in bosses)
+ if(boss_mind.current)
+ var/I = image('icons/mob/mob.dmi', loc = boss_mind.current, icon_state = "gang_boss")
+ gangster_mind.current.client.images += I
+ //Tag themselves to see
+ var/K
+ if(gangster_mind in bosses) //If the new gangster is a boss himself
+ K = image('icons/mob/mob.dmi', loc = gangster_mind.current, icon_state = "gang_boss")
+ else
+ K = image('icons/mob/mob.dmi', loc = gangster_mind.current, icon_state = "gangster")
+ gangster_mind.current.client.images += K
+
+/////////////////////////////////////////////////
+//Assigns icons when a new gangster is recruited//
+/////////////////////////////////////////////////
+/datum/game_mode/proc/update_gang_icons_added(datum/mind/recruit_mind, var/gang)
+ var/list/bosses
+ if(gang == "A")
+ bosses = A_bosses
+ else if(gang == "B")
+ bosses = B_bosses
+ if(!gang)
+ world << "ERROR: Invalid gang in update_gang_icons_added()"
+
+ spawn(0)
+ for(var/datum/mind/boss_mind in bosses)
+ //Tagging the new gangster for the bosses to see
+ if(boss_mind.current)
+ if(boss_mind.current.client)
+ var/I
+ if(recruit_mind in bosses) //If the new gangster is a boss himself
+ I = image('icons/mob/mob.dmi', loc = recruit_mind.current, icon_state = "gang_boss")
+ else
+ I = image('icons/mob/mob.dmi', loc = recruit_mind.current, icon_state = "gangster")
+ boss_mind.current.client.images += I
+ //Tagging every boss for the new gangster to see
+ if(recruit_mind.current)
+ if(recruit_mind.current.client)
+ var/image/J = image('icons/mob/mob.dmi', loc = boss_mind.current, icon_state = "gang_boss")
+ recruit_mind.current.client.images += J
+ //Tag themselves to see
+ if(recruit_mind.current)
+ if(recruit_mind.current.client)
+ var/K
+ if(recruit_mind in bosses) //If the new gangster is a boss himself
+ K = image('icons/mob/mob.dmi', loc = recruit_mind.current, icon_state = "gang_boss")
+ else
+ K = image('icons/mob/mob.dmi', loc = recruit_mind.current, icon_state = "gangster")
+ recruit_mind.current.client.images += K
+
+////////////////////////////////////////
+//Keeps track of deconverted gangsters//
+////////////////////////////////////////
+/datum/game_mode/proc/update_gang_icons_removed(datum/mind/defector_mind)
+ var/list/all_gangsters = A_bosses + B_bosses + A_gangsters + B_gangsters
+
+ spawn(0)
+ //Remove defector's icon from gangsters' visions
+ for(var/datum/mind/boss_mind in all_gangsters)
+ if(boss_mind.current)
+ if(boss_mind.current.client)
+ for(var/image/I in boss_mind.current.client.images)
+ if((I.icon_state == "gangster" || I.icon_state == "gang_boss") && I.loc == defector_mind.current)
+ del(I)
+
+ //Remove gang icons from defector's vision
+ if(defector_mind.current)
+ if(defector_mind.current.client)
+ for(var/image/I in defector_mind.current.client.images)
+ if(I.icon_state == "gangster" || I.icon_state == "gang_boss")
+ del(I)
+
+///////////////////////////
+//Checks for gang victory//
+///////////////////////////
+/datum/game_mode/gang/proc/check_gang_victory(var/list/boss_list)
+ if(!boss_list.len)
+ return 0
+ for(var/datum/mind/boss_mind in boss_list)
+ if(boss_mind.current)
+ if(boss_mind.current.stat == DEAD || !ishuman(boss_mind.current) || !boss_mind.current.ckey || !boss_mind.current.client)
+ return 1
+ var/turf/T = get_turf(boss_mind.current)
+ if(T && (T.z != 1)) //If they leave the station they count as dead for this
+ return 1
+ return 0
+ return 1
+
+//////////////////////////////////////////////////////////////////////
+//Announces the end of the game with all relavent information stated//
+//////////////////////////////////////////////////////////////////////
+/datum/game_mode/gang/declare_completion()
+ if(!finished)
+ world << "The station was [station_was_nuked ? "destroyed!" : "evacuated before either gang could claim it!"]"
+ else if(finished == "Draw")
+ world << "All gang bosses have been killed or exiled!"
+ else
+ world << "The [finished=="A" ? gang_name("A") : gang_name("B")] Gang defeated their rivals!"
+ ..()
+ return 1
+
+/datum/game_mode/proc/auto_declare_completion_gang()
+ var/winner
+ var/datum/game_mode/gang/game_mode = ticker.mode
+ if(istype(game_mode))
+ winner = game_mode.finished
+
+ var/num_ganga = 0
+ var/list/agang = A_gangsters + A_bosses
+ for(var/datum/mind/agangster in agang)
+ if(agangster.current)
+ if(agangster.current in living_mob_list)
+ num_ganga++
+
+ var/num_gangb = 0
+ var/list/bgang = B_gangsters + B_bosses
+ for(var/datum/mind/bgangster in bgang)
+ if(bgangster.current)
+ if(bgangster.current in living_mob_list)
+ num_gangb++
+
+ var/num_survivors = 0
+ for(var/mob/living/carbon/survivor in living_mob_list)
+ if(survivor.key)
+ num_survivors++
+
+ if(A_bosses.len || A_gangsters.len)
+ if(winner == "A" || winner == "B")
+ world << " The [gang_name("A")] Gang was [winner=="A" ? "victorious" : "defeated"] with [round((num_ganga/num_survivors)*100, 0.1)]% influence."
+ world << " The [gang_name("A")] Gang bosses were:"
+ gang_membership_report(A_bosses)
+ world << " The [gang_name("A")] Gangsters were:"
+ gang_membership_report(A_gangsters)
+
+ if(B_bosses.len || B_gangsters.len)
+ if(winner == "A" || winner == "B")
+ world << " The [gang_name("B")] Gang was [winner=="B" ? "victorious" : "defeated"] with [round((num_gangb/num_survivors)*100, 0.1)]% influence."
+ world << " The [gang_name("B")] Gang bosses were:"
+ gang_membership_report(B_bosses)
+ world << " The [gang_name("B")] Gangsters were:"
+ gang_membership_report(B_gangsters)
+
+/datum/game_mode/proc/gang_membership_report(var/list/membership)
+ var/text = ""
+ for(var/datum/mind/gang_mind in membership)
+ text += " [gang_mind.key] was [gang_mind.name] ("
+ if(gang_mind.current)
+ if(gang_mind.current.stat == DEAD || isbrain(gang_mind.current))
+ text += "died"
+ else if(gang_mind.current.z != 1)
+ text += "fled the station"
+ else
+ text += "survived"
+ if(gang_mind.current.real_name != gang_mind.name)
+ text += " as [gang_mind.current.real_name]"
+ else
+ text += "body destroyed"
+ text += ")"
+ text += "
"
+
+ world << text
diff --git a/code/game/gamemodes/intercept_report.dm b/code/game/gamemodes/intercept_report.dm
index 05ab6f49f63..93ec09810de 100644
--- a/code/game/gamemodes/intercept_report.dm
+++ b/code/game/gamemodes/intercept_report.dm
@@ -61,6 +61,10 @@
src.text = ""
src.build_rev(correct_person)
return src.text
+ if("gang")
+ src.text = ""
+ src.build_gang(correct_person)
+ return src.text
if("cult")
src.text = ""
src.build_cult(correct_person)
@@ -220,6 +224,10 @@
src.text += " However, if this information is acted on without substantial evidence, those responsible will face severe repercussions."
*/
+/datum/intercept_text/proc/build_gang(datum/mind/correct_person)
+ src.text += "
Syndicate forces may be supplying opposing criminal organizations within your sector in an attempt at destabilizing our operations."
+ src.text += "Ensure law and order is maintained on the station and be on the lookout for violent confrontations between station factions."
+ src.text += "Central Command retains an interest in any criminal leaders captured by station security. The execution or exile of these persons are ill-advised."
/datum/intercept_text/proc/build_wizard(datum/mind/correct_person)
var/SWF_desc = pick(SWF_names)
diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm
index 1eea8712125..4ca3488ed64 100644
--- a/code/game/gamemodes/malfunction/Malf_Modules.dm
+++ b/code/game/gamemodes/malfunction/Malf_Modules.dm
@@ -164,8 +164,7 @@
for(var/datum/AI_Module/small/overload_machine/overload in current_modules)
if(overload.uses > 0)
overload.uses --
- for(var/mob/V in hearers(M, null))
- V.show_message("You hear a loud electrical buzzing sound!", 2)
+ audible_message("You hear a loud electrical buzzing sound!")
src << "Overloading machine circuitry..."
spawn(50)
if(M)
@@ -191,8 +190,7 @@
for(var/datum/AI_Module/small/override_machine/override in current_modules)
if(override.uses > 0)
override.uses --
- for(var/mob/V in hearers(M, null))
- V.show_message("You hear a loud electrical buzzing sound!", 2)
+ audible_message("You hear a loud electrical buzzing sound!")
src << "Reprogramming machine behaviour..."
spawn(50)
if(M)
diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm
index c5428a993a0..8cf8a3ec813 100644
--- a/code/game/gamemodes/malfunction/malfunction.dm
+++ b/code/game/gamemodes/malfunction/malfunction.dm
@@ -10,12 +10,8 @@
recommended_enemies = 1
pre_setup_before_jobs = 1
- uplink_welcome = "Crazy AI Uplink Console:"
- uplink_uses = 10
-
-
- var/AI_win_timeleft = 1800 //started at 1800, in case I change this for testing round end.
+ var/AI_win_timeleft = 5400 //started at 5400, in case I change this for testing round end.
var/malf_mode_declared = 0
var/station_captured = 0
var/to_nuke_or_not_to_nuke = 0
@@ -52,7 +48,7 @@
if (malf_ai.len < required_enemies)
return 0
for(var/datum/mind/ai_mind in malf_ai)
- ai_mind.assigned_role = "MODE" //So they aren't chosen for other jobs.
+ ai_mind.need_job_assign = 0
ai_mind.special_role = "malfunctioning AI"//So they actually have a special role/N
log_game("[ai_mind.key] (ckey) has been selected as a malf AI")
return 1
@@ -102,8 +98,8 @@
return
/datum/game_mode/malfunction/process()
- if (apcs >= 3 && malf_mode_declared)
- AI_win_timeleft -= ((apcs/6)*last_tick_duration) //Victory timer now de-increments based on how many APCs are hacked. --NeoFite
+ if ((apcs > 0) && malf_mode_declared)
+ AI_win_timeleft -= apcs * last_tick_duration //Victory timer de-increments based on how many APCs are hacked
..()
if (AI_win_timeleft<=0)
check_win()
@@ -164,7 +160,7 @@
set name = "System Override"
set desc = "Start the victory timer"
if (!istype(ticker.mode,/datum/game_mode/malfunction))
- usr << "You cannot begin a takeover in this round type!."
+ usr << "You cannot begin a takeover in this round type!"
return
if (ticker.mode:malf_mode_declared)
usr << "You've already begun your takeover."
diff --git a/code/game/gamemodes/meteor/meteor.dm b/code/game/gamemodes/meteor/meteor.dm
index 76f3b1215f4..234f205e0d2 100644
--- a/code/game/gamemodes/meteor/meteor.dm
+++ b/code/game/gamemodes/meteor/meteor.dm
@@ -5,9 +5,6 @@
var/nometeors = 1
required_players = 0
- uplink_welcome = "EVIL METEOR Uplink Console:"
- uplink_uses = 10
-
/datum/game_mode/meteor/announce()
world << "The current game mode is - Meteor!"
diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm
index f7caf7be4e9..b9ed5c88c54 100644
--- a/code/game/gamemodes/meteor/meteors.dm
+++ b/code/game/gamemodes/meteor/meteors.dm
@@ -8,72 +8,66 @@
/var/list/meteorsC = list(/obj/effect/meteor/dust) //for space dust event
-
-/proc/meteor_wave(var/number = 50) //this proc's unused now.
- if(!ticker || wavesecret)
- return
-
- wavesecret = 1
- for(var/i = 0 to number)
- spawn(rand(10,100))
- spawn_meteor()
- spawn(meteor_wave_delay)
- wavesecret = 0
-
-
/proc/spawn_meteors(var/number = 10, var/list/meteortypes)
for(var/i = 0; i < number; i++)
- spawn(0)
- spawn_meteor(meteortypes)
+ spawn_meteor(meteortypes)
/proc/spawn_meteor(var/list/meteortypes)
-
- var/startx
- var/starty
- var/endx
- var/endy
var/turf/pickedstart
var/turf/pickedgoal
var/max_i = 10//number of tries to spawn meteor.
-
- do
- switch(pick(1,2,3,4))
- if(1) //NORTH
- starty = world.maxy-(TRANSITIONEDGE+1)
- startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
- endy = TRANSITIONEDGE
- endx = rand(TRANSITIONEDGE, world.maxx-TRANSITIONEDGE)
- if(2) //EAST
- starty = rand((TRANSITIONEDGE+1),world.maxy-(TRANSITIONEDGE+1))
- startx = world.maxx-(TRANSITIONEDGE+1)
- endy = rand(TRANSITIONEDGE, world.maxy-TRANSITIONEDGE)
- endx = TRANSITIONEDGE
- if(3) //SOUTH
- starty = (TRANSITIONEDGE+1)
- startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
- endy = world.maxy-TRANSITIONEDGE
- endx = rand(TRANSITIONEDGE, world.maxx-TRANSITIONEDGE)
- if(4) //WEST
- starty = rand((TRANSITIONEDGE+1), world.maxy-(TRANSITIONEDGE+1))
- startx = (TRANSITIONEDGE+1)
- endy = rand(TRANSITIONEDGE,world.maxy-TRANSITIONEDGE)
- endx = world.maxx-TRANSITIONEDGE
-
- pickedstart = locate(startx, starty, 1)
- pickedgoal = locate(endx, endy, 1)
+ while (!istype(pickedstart, /turf/space) || pickedstart.loc.name != "Space" )
+ var/startSide = pick(cardinal)
+ pickedstart = spaceDebrisStartLoc(startSide, 1)
+ pickedgoal = spaceDebrisFinishLoc(startSide, 1)
max_i--
- if(max_i<=0) return
- while (!istype(pickedstart, /turf/space) || pickedstart.loc.name != "Space" ) //FUUUCK, should never happen.
-
-
+ if(max_i<=0)
+ return
var/Me = pickweight(meteortypes)
var/obj/effect/meteor/M = new Me(pickedstart)
-
M.dest = pickedgoal
+ M.z_original = 1
spawn(0)
walk_towards(M, M.dest, 1)
return
+/proc/spaceDebrisStartLoc(startSide, Z)
+ var/starty
+ var/startx
+ switch(startSide)
+ if(1) //NORTH
+ starty = world.maxy-(TRANSITIONEDGE+1)
+ startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
+ if(2) //EAST
+ starty = rand((TRANSITIONEDGE+1),world.maxy-(TRANSITIONEDGE+1))
+ startx = world.maxx-(TRANSITIONEDGE+1)
+ if(3) //SOUTH
+ starty = (TRANSITIONEDGE+1)
+ startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
+ if(4) //WEST
+ starty = rand((TRANSITIONEDGE+1), world.maxy-(TRANSITIONEDGE+1))
+ startx = (TRANSITIONEDGE+1)
+ var/turf/T = locate(startx, starty, Z)
+ return T
+
+/proc/spaceDebrisFinishLoc(startSide, Z)
+ var/endy
+ var/endx
+ switch(startSide)
+ if(1) //NORTH
+ endy = TRANSITIONEDGE
+ endx = rand(TRANSITIONEDGE, world.maxx-TRANSITIONEDGE)
+ if(2) //EAST
+ endy = rand(TRANSITIONEDGE, world.maxy-TRANSITIONEDGE)
+ endx = TRANSITIONEDGE
+ if(3) //SOUTH
+ endy = world.maxy-TRANSITIONEDGE
+ endx = rand(TRANSITIONEDGE, world.maxx-TRANSITIONEDGE)
+ if(4) //WEST
+ endy = rand(TRANSITIONEDGE,world.maxy-TRANSITIONEDGE)
+ endx = world.maxx-TRANSITIONEDGE
+ var/turf/T = locate(endx, endy, Z)
+ return T
/obj/effect/meteor
@@ -89,10 +83,20 @@
pass_flags = PASSTABLE
var/heavy = 0
var/meteorsound = 'sound/effects/meteorimpact.ogg'
+ var/z_original
var/meteordrop = /obj/item/weapon/ore/iron
var/dropamt = 2
+/obj/effect/meteor/Move()
+ if(z != z_original || loc == dest)
+ qdel(src)
+ return ..()
+
+/obj/effect/meteor/Destroy()
+ walk(src,0) //this cancels the walk_towards() proc
+ ..()
+
/obj/effect/meteor/dust
name = "space dust"
icon_state = "dust"
diff --git a/code/game/gamemodes/monkey/monkey.dm b/code/game/gamemodes/monkey/monkey.dm
index 266a7c35e06..c12ba003926 100644
--- a/code/game/gamemodes/monkey/monkey.dm
+++ b/code/game/gamemodes/monkey/monkey.dm
@@ -11,6 +11,7 @@
recommended_enemies = 1
restricted_jobs = list("Cyborg", "AI")
+ pre_setup_before_jobs = 1
var/carriers_to_make = 1
var/list/carriers = list()
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index aefcfc70c47..f0c1de856b8 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -11,9 +11,6 @@
pre_setup_before_jobs = 1
antag_flag = BE_OPERATIVE
- uplink_welcome = "Corporate Backed Uplink Console:"
- uplink_uses = 10
-
var/const/agents_possible = 5 //If we ever need more syndicate agents.
var/nukes_left = 1 // Call 3714-PRAY right now and order more nukes! Limited offer!
@@ -43,7 +40,7 @@
agent_number--
for(var/datum/mind/synd_mind in syndicates)
- synd_mind.assigned_role = "MODE" //So they aren't chosen for other jobs.
+ synd_mind.need_job_assign = 0
synd_mind.special_role = "Syndicate"//So they actually have a special role/N
log_game("[synd_mind.key] (ckey) has been selected as a nuclear operative")
return 1
@@ -100,7 +97,6 @@
for(var/obj/effect/landmark/A in landmarks_list)
if(A.name == "Syndicate-Spawn")
synd_spawn += get_turf(A)
- qdel(A)
continue
var/obj/effect/landmark/uplinklocker = locate("landmark*Syndicate-Uplink") //i will be rewriting this shortly
@@ -113,13 +109,17 @@
for(var/datum/mind/synd_mind in syndicates)
if(spawnpos > synd_spawn.len)
- spawnpos = 1
+ spawnpos = 2
synd_mind.current.loc = synd_spawn[spawnpos]
forge_syndicate_objectives(synd_mind)
greet_syndicate(synd_mind)
equip_syndicate(synd_mind.current)
+ if (nuke_code)
+ synd_mind.store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 0, 0)
+ synd_mind.current << "The nuclear authorization code is: [nuke_code]"
+
if(!leader_selected)
prepare_syndicate_leader(synd_mind, nuke_code)
leader_selected = 1
@@ -145,20 +145,25 @@
spawn(1)
NukeNameAssign(nukelastname(synd_mind.current),syndicates) //allows time for the rest of the syndies to be chosen
synd_mind.current.real_name = "[syndicate_name()] [leader_title]"
+ synd_mind.current << "You are the Syndicate [leader_title] for this mission. You are responsible for the distribution of telecrystals and your ID is the only one who can open the launch bay doors."
+ synd_mind.current << "If you feel you are not up to this task, give your ID to another operative."
+
+ var/list/foundIDs = synd_mind.current.search_contents_for(/obj/item/weapon/card/id)
+ if(foundIDs.len)
+ for(var/obj/item/weapon/card/id/ID in foundIDs)
+ ID.name = "lead agent card"
+ ID.access += access_syndicate_leader
+ else
+ message_admins("Warning: Nuke Ops spawned without access to leave their spawn area!")
+
if (nuke_code)
- synd_mind.store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 0, 0)
- synd_mind.current << "The nuclear authorization code is: [nuke_code]"
var/obj/item/weapon/paper/P = new
P.info = "The nuclear authorization code is: [nuke_code]"
P.name = "nuclear bomb code"
- if (ticker.mode.config_tag=="nuclear")
- P.loc = synd_mind.current.loc
- else
- var/mob/living/carbon/human/H = synd_mind.current
- P.loc = H.loc
- H.equip_to_slot_or_del(P, slot_r_store, 0)
- H.update_icons()
-
+ var/mob/living/carbon/human/H = synd_mind.current
+ P.loc = H.loc
+ H.equip_to_slot_or_del(P, slot_r_hand, 0)
+ H.update_icons()
else
nuke_code = "code will be provided later"
return
@@ -206,7 +211,7 @@
var/obj/item/device/radio/uplink/U = new /obj/item/device/radio/uplink(synd_mob)
U.hidden_uplink.uplink_owner="[synd_mob.key]"
- U.hidden_uplink.uses = 10
+ U.hidden_uplink.uses = 20
synd_mob.equip_to_slot_or_del(U, slot_in_backpack)
var/obj/item/weapon/implant/explosive/E = new/obj/item/weapon/implant/explosive(synd_mob)
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index 9b4368d960f..8a78f9b33ae 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -17,10 +17,6 @@ var/bomb_set
use_power = 0
var/previous_level = ""
-/obj/machinery/nuclearbomb/New()
- ..()
- r_code = "[rand(10000, 99999.0)]"//Creates a random code upon object spawn.
-
/obj/machinery/nuclearbomb/process()
if (src.timing)
bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed.
@@ -236,8 +232,8 @@ var/bomb_set
if(blobstart.len > 0)
var/obj/item/weapon/disk/nuclear/NEWDISK = new(pick(blobstart))
transfer_fingerprints_to(NEWDISK)
- message_admins("[src] has been destroyed. Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z]).")
- log_game("[src] has been destroyed. Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z]).")
+ message_admins("[src] has been destroyed in ([x], [y] ,[z] - JMP). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z] - JMP).")
+ log_game("[src] has been destroyed in ([x], [y] ,[z]). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z]).")
del(src) //Needed to clear all references to it
else
ERROR("[src] was supposed to be destroyed, but we were unable to locate a blobstart landmark to spawn a new one.")
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index e0b45a6fc85..8e8c6a4f021 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -90,7 +90,7 @@ datum/objective/mutiny/check_completion()
datum/objective/mutiny/update_explanation_text()
..()
if(target && target.current)
- explanation_text = "Assassinate [target.current.real_name], the [!target_role_type ? target.assigned_role : target.special_role]."
+ explanation_text = "Assassinate or exile [target.current.real_name], the [!target_role_type ? target.assigned_role : target.special_role]."
else
explanation_text = "Free Objective"
diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm
index a5f494187fc..e850f817e52 100644
--- a/code/game/gamemodes/revolution/revolution.dm
+++ b/code/game/gamemodes/revolution/revolution.dm
@@ -19,14 +19,13 @@
required_players = 20
required_enemies = 3
recommended_enemies = 3
-
-
- uplink_welcome = "Revolutionary Uplink Console:"
- uplink_uses = 10
+ pre_setup_before_jobs = 1
var/finished = 0
- var/checkwin_counter = 0
- var/const/max_headrevs = 3
+ var/check_counter = 0
+ var/max_headrevs = 3
+ var/list/datum/mind/heads_to_kill = list()
+
///////////////////////////
//Announces the game type//
///////////////////////////
@@ -54,6 +53,10 @@
if(player.assigned_role == job)
antag_candidates -= player
+ var/list/heads = get_living_heads()
+ if(heads.len < max_headrevs)
+ max_headrevs = heads.len
+
for (var/i=1 to max_headrevs)
if (antag_candidates.len==0)
break
@@ -71,18 +74,17 @@
/datum/game_mode/revolution/post_setup()
var/list/heads = get_living_heads()
+ heads_to_kill = heads
+
for(var/datum/mind/rev_mind in head_revolutionaries)
for(var/datum/mind/head_mind in heads)
- var/datum/objective/mutiny/rev_obj = new
- rev_obj.owner = rev_mind
- rev_obj.target = head_mind
- rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]."
- rev_mind.objectives += rev_obj
+ mark_for_death(rev_mind, head_mind)
- // equip_traitor(rev_mind.current, 1) //changing how revs get assigned their uplink so they can get PDA uplinks. --NEO
- // Removing revolutionary uplinks. -Pete
- equip_revolutionary(rev_mind.current)
- update_rev_icons_added(rev_mind)
+ spawn(rand(10,100))
+ // equip_traitor(rev_mind.current, 1) //changing how revs get assigned their uplink so they can get PDA uplinks. --NEO
+ // Removing revolutionary uplinks. -Pete
+ equip_revolutionary(rev_mind.current)
+ update_rev_icons_added(rev_mind)
for(var/datum/mind/rev_mind in head_revolutionaries)
greet_revolutionary(rev_mind)
@@ -93,11 +95,12 @@
/datum/game_mode/revolution/process()
- checkwin_counter++
- if(checkwin_counter >= 5)
+ check_counter++
+ if(check_counter >= 5)
if(!finished)
+ check_heads()
ticker.mode.check_win()
- checkwin_counter = 0
+ check_counter = 0
return 0
@@ -107,7 +110,7 @@
var/datum/objective/mutiny/rev_obj = new
rev_obj.owner = rev_mind
rev_obj.target = head_mind
- rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]."
+ rev_obj.explanation_text = "Assassinate or exile [head_mind.name], the [head_mind.assigned_role]."
rev_mind.objectives += rev_obj
/datum/game_mode/proc/greet_revolutionary(var/datum/mind/rev_mind, var/you_are=1)
@@ -149,6 +152,44 @@
mob.update_icons()
return 1
+/////////////////////////////////
+//Gives head revs their targets//
+/////////////////////////////////
+/datum/game_mode/revolution/proc/mark_for_death(var/datum/mind/rev_mind, var/datum/mind/head_mind)
+ var/datum/objective/mutiny/rev_obj = new
+ rev_obj.owner = rev_mind
+ rev_obj.target = head_mind
+ rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]."
+ rev_mind.objectives += rev_obj
+
+////////////////////////////////////////////
+//Checks if new heads have joined midround//
+////////////////////////////////////////////
+/datum/game_mode/revolution/proc/check_heads()
+ var/list/heads = get_all_heads()
+ if(heads_to_kill.len < heads.len)
+ var/list/new_heads = heads - heads_to_kill
+ for(var/datum/mind/head_mind in new_heads)
+ for(var/datum/mind/rev_mind in head_revolutionaries)
+ mark_for_death(rev_mind, head_mind)
+
+ if(max_headrevs < initial(max_headrevs) && max_headrevs < heads.len)
+ latejoin_headrev()
+
+///////////////////////////////
+//Adds a new headrev midround//
+///////////////////////////////
+/datum/game_mode/revolution/proc/latejoin_headrev()
+ if(revolutionaries) //Head Revs are not in this list
+ var/datum/mind/stalin = pick(revolutionaries)
+ revolutionaries -= stalin
+ head_revolutionaries += stalin
+ log_game("[stalin.key] (ckey) has been promoted to a head rev")
+ equip_revolutionary(stalin.current)
+ forge_revolutionary_objectives(stalin)
+ greet_revolutionary(stalin)
+ ++max_headrevs
+
//////////////////////////////////////
//Checks if the revs have won or not//
//////////////////////////////////////
@@ -200,7 +241,8 @@
rev_mind.current.attack_log += "\[[time_stamp()]\] Has renounced the revolution!"
if(beingborged)
- rev_mind.current << "The frame's firmware detects and deletes your neural reprogramming! You remember nothing from the moment you were flashed until now."
+ rev_mind.current << "The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you."
+ message_admins("[key_name_admin(rev_mind.current)] ? has been borged while being a member of the revolution.")
else
rev_mind.current << "You have been brainwashed! You are no longer a revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you..."
@@ -268,20 +310,36 @@
/datum/game_mode/proc/update_rev_icons_added(datum/mind/rev_mind)
spawn(0)
for(var/datum/mind/head_rev_mind in head_revolutionaries)
+
+ //Tagging the new rev for revheads to see
if(head_rev_mind.current)
if(head_rev_mind.current.client)
- var/I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev")
+ var/I
+ if(rev_mind in head_revolutionaries) //If the new rev is a head rev
+ I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev_head")
+ else
+ I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev")
head_rev_mind.current.client.images += I
+
+ //Tagging the revheads for new rev to see
if(rev_mind.current)
if(rev_mind.current.client)
var/image/J = image('icons/mob/mob.dmi', loc = head_rev_mind.current, icon_state = "rev_head")
rev_mind.current.client.images += J
for(var/datum/mind/rev_mind_1 in revolutionaries)
+
+ //Tagging the new rev for fellow revs to see
if(rev_mind_1.current)
if(rev_mind_1.current.client)
- var/I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev")
+ var/I
+ if(rev_mind in head_revolutionaries) //If the new rev is a head rev
+ I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev_head")
+ else
+ I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev")
rev_mind_1.current.client.images += I
+
+ //Tagging fellow revs for the new rev to see
if(rev_mind.current)
if(rev_mind.current.client)
var/image/J = image('icons/mob/mob.dmi', loc = rev_mind_1.current, icon_state = "rev")
@@ -340,7 +398,7 @@
/datum/game_mode/revolution/declare_completion()
if(finished == 1)
feedback_set_details("round_end_result","win - heads killed")
- world << "The heads of staff were killed or abandoned the station! The revolutionaries win!"
+ world << "The heads of staff were killed or exiled! The revolutionaries win!"
else if(finished == 2)
feedback_set_details("round_end_result","loss - rev heads killed")
world << "The heads of staff managed to stop the revolution!"
@@ -351,6 +409,18 @@
var/list/targets = list()
if(head_revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution))
+ var/num_revs = 0
+ var/num_survivors = 0
+ for(var/mob/living/carbon/survivor in living_mob_list)
+ if(survivor.ckey)
+ num_survivors++
+ if(survivor.mind)
+ if((survivor.mind in head_revolutionaries) || (survivor.mind in revolutionaries))
+ num_revs++
+
+ if(num_survivors)
+ world << "[TAB]Command's Approval Rating: [100 - round((num_revs/num_survivors)*100, 0.1)]%" // % of loyal crew
+
var/text = " The head revolutionaries were:"
for(var/datum/mind/headrev in head_revolutionaries)
@@ -380,7 +450,7 @@
for(var/datum/mind/rev in revolutionaries)
text += " [rev.key] was [rev.name] ("
if(rev.current)
- if(rev.current.stat == DEAD)
+ if(rev.current.stat == DEAD || isbrain(rev.current))
text += "died"
else if(rev.current.z != 1)
text += "fled the station"
@@ -406,7 +476,7 @@
text += ""
text += " [head.key] was [head.name] ("
if(head.current)
- if(head.current.stat == DEAD)
+ if(head.current.stat == DEAD || isbrain(head.current))
text += "died"
else if(head.current.z != 1)
text += "fled the station"
@@ -421,10 +491,4 @@
text += ""
text += " "
- world << text
-
-/proc/is_convertable_to_rev(datum/mind/mind)
- return istype(mind) && \
- istype(mind.current, /mob/living/carbon/human) && \
- !(mind.assigned_role in command_positions) && \
- !(mind.assigned_role in list("Security Officer", "Detective", "Warden"))
+ world << text
diff --git a/code/game/gamemodes/sandbox/h_sandbox.dm b/code/game/gamemodes/sandbox/h_sandbox.dm
index d2f36a2ee7e..9b3045d62a1 100644
--- a/code/game/gamemodes/sandbox/h_sandbox.dm
+++ b/code/game/gamemodes/sandbox/h_sandbox.dm
@@ -233,7 +233,7 @@ datum/hSB/Topic(href, href_list)
var/list/all_items = typesof(/obj/item/clothing) - /obj/item/clothing
for(var/typekey in spawn_forbidden)
all_items -= typesof(typekey)
- for(var/O in reverselist(all_items))
+ for(var/O in reverseRange(all_items))
clothinfo += "[O] "
usr << browse(clothinfo,"window=sandbox")
@@ -247,7 +247,7 @@ datum/hSB/Topic(href, href_list)
var/list/all_items = typesof(/obj/item/weapon/reagent_containers) - /obj/item/weapon/reagent_containers
for(var/typekey in spawn_forbidden)
all_items -= typesof(typekey)
- for(var/O in reverselist(all_items))
+ for(var/O in reverseRange(all_items))
reaginfo += "[O] "
usr << browse(reaginfo,"window=sandbox")
@@ -262,7 +262,7 @@ datum/hSB/Topic(href, href_list)
for(var/typekey in spawn_forbidden)
all_items -= typesof(typekey)
- for(var/O in reverselist(all_items))
+ for(var/O in reverseRange(all_items))
objinfo += "[O] "
usr << browse(objinfo,"window=sandbox")
diff --git a/code/game/gamemodes/sandbox/sandbox.dm b/code/game/gamemodes/sandbox/sandbox.dm
index 475c3d22aa5..8ebb488267a 100644
--- a/code/game/gamemodes/sandbox/sandbox.dm
+++ b/code/game/gamemodes/sandbox/sandbox.dm
@@ -3,9 +3,6 @@
config_tag = "sandbox"
required_players = 0
- uplink_welcome = "Syndicate Uplink Console:"
- uplink_uses = 10
-
/datum/game_mode/sandbox/announce()
world << "The current game mode is - Sandbox!"
world << "Build your own station with the sandbox-panel command!"
diff --git a/code/game/gamemodes/traitor/double_agents.dm b/code/game/gamemodes/traitor/double_agents.dm
index b252b7a6aba..0f30a1af738 100644
--- a/code/game/gamemodes/traitor/double_agents.dm
+++ b/code/game/gamemodes/traitor/double_agents.dm
@@ -5,11 +5,12 @@
required_players = 25
required_enemies = 5
recommended_enemies = 8
+ pre_setup_before_jobs = 1
traitor_name = "double agent"
- traitors_possible = 8 //hard limit on traitors if scaling is turned off
- scale_modifier = 0.5 // Nearly twice as many double agents
+ traitors_possible = 10 //hard limit on traitors if scaling is turned off
+ num_modifier = 6 // Six additional traitors
var/list/target_list = list()
var/list/late_joining_list = list()
diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm
index 802b3c57bee..2c4d9aaab5b 100644
--- a/code/game/gamemodes/traitor/traitor.dm
+++ b/code/game/gamemodes/traitor/traitor.dm
@@ -15,13 +15,10 @@
required_players = 0
required_enemies = 1
recommended_enemies = 4
-
-
- uplink_welcome = "Syndicate Uplink Console:"
- uplink_uses = 10
+ pre_setup_before_jobs = 1
var/traitors_possible = 4 //hard limit on traitors if scaling is turned off
- var/scale_modifier = 1 // Used for gamemodes, that are a child of traitor, that need more than the usual.
+ var/num_modifier = 0 // Used for gamemodes, that are a child of traitor, that need more than the usual.
/datum/game_mode/traitor/announce()
@@ -37,7 +34,7 @@
var/num_traitors = 1
if(config.traitor_scaling_coeff)
- num_traitors = max(1, round((num_players())/((config.traitor_scaling_coeff * scale_modifier))))
+ num_traitors = max(1, min( round(num_players()/(config.traitor_scaling_coeff*2))+ 2 + num_modifier, round(num_players()/(config.traitor_scaling_coeff)) + num_modifier ))
else
num_traitors = max(1, min(num_players(), traitors_possible))
@@ -74,10 +71,10 @@
return 1
/datum/game_mode/traitor/make_antag_chance(var/mob/living/carbon/human/character) //Assigns traitor to latejoiners
- var/traitorcap = round(joined_player_list.len / (config.traitor_scaling_coeff * scale_modifier))
+ var/traitorcap = min(round(joined_player_list.len / (config.traitor_scaling_coeff * 2)) + 2 + num_modifier, round(joined_player_list.len/config.traitor_scaling_coeff) + num_modifier )
if(traitors.len >= traitorcap) //Upper cap for number of latejoin antagonists
return
- if(traitors.len <= (traitorcap - 2) || prob(100 / (config.traitor_scaling_coeff * scale_modifier)))
+ if(traitors.len <= (traitorcap - 2) || prob(100 / (config.traitor_scaling_coeff * 2)))
if(character.client.prefs.be_special & BE_TRAITOR)
if(!jobban_isbanned(character.client, "traitor") && !jobban_isbanned(character.client, "Syndicate"))
if(!(character.job in ticker.mode.restricted_jobs))
@@ -121,27 +118,27 @@
objective_count += 1 //Exchange counts towards number of objectives
var/list/active_ais = active_ais()
for(var/i = objective_count, i < config.traitor_objectives_amount, i++)
- if(active_ais.len && prob(1))
- var/datum/objective/destroy/destroy_objective = new
- destroy_objective.owner = traitor
- destroy_objective.find_target()
- traitor.objectives += destroy_objective
- else switch(rand(1,100))
- if(1 to 15)
+ if(prob(50))
+ if(active_ais.len && prob(100/joined_player_list.len))
+ var/datum/objective/destroy/destroy_objective = new
+ destroy_objective.owner = traitor
+ destroy_objective.find_target()
+ traitor.objectives += destroy_objective
+ else if(prob(30))
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = traitor
maroon_objective.find_target()
traitor.objectives += maroon_objective
- if(16 to 50)
+ else
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = traitor
kill_objective.find_target()
traitor.objectives += kill_objective
- else
- var/datum/objective/steal/steal_objective = new
- steal_objective.owner = traitor
- steal_objective.find_target()
- traitor.objectives += steal_objective
+ else
+ var/datum/objective/steal/steal_objective = new
+ steal_objective.owner = traitor
+ steal_objective.find_target()
+ traitor.objectives += steal_objective
if(is_hijacker && objective_count <= config.traitor_objectives_amount) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount
if (!(locate(/datum/objective/hijack) in traitor.objectives))
@@ -204,18 +201,7 @@
for(var/datum/mind/traitor in traitors)
var/traitorwin = 1
- text += " [traitor.key] was [traitor.name] ("
- if(traitor.current)
- if(traitor.current.stat == DEAD)
- text += "died"
- else
- text += "survived"
- if(traitor.current.real_name != traitor.name)
- text += " as [traitor.current.real_name]"
- else
- text += "body destroyed"
- text += ")"
-
+ text += printplayer(traitor)
var/TC_uses = 0
var/uplink_true = 0
diff --git a/code/game/gamemodes/wizard/rightandwrong.dm b/code/game/gamemodes/wizard/rightandwrong.dm
index 1cc217b188f..e8560103ecc 100644
--- a/code/game/gamemodes/wizard/rightandwrong.dm
+++ b/code/game/gamemodes/wizard/rightandwrong.dm
@@ -1,13 +1,14 @@
+//In this file: Summon Magic/Summon Guns/Summon Events
-
-/mob/proc/rightandwrong(var/summon_type) //0 = Summon Guns, 1 = Summon Magic
+/proc/rightandwrong(var/summon_type, var/mob/user) //0 = Summon Guns, 1 = Summon Magic
var/list/gunslist = list("taser","egun","laser","revolver","detective","smg","nuclear","deagle","gyrojet","pulse","suppressed","cannon","doublebarrel","shotgun","combatshotgun","mateba","smg","uzi","crossbow","saw")
var/list/magiclist = list("fireball","smoke","blind","mindswap","forcewall","knock","horsemask","charge","wandnothing", "wanddeath", "wandresurrection", "wandpolymorph", "wandteleport", "wanddoor", "wandfireball", "staffchange", "staffhealing", "armor", "scrying", "staffdoor", "special")
var/list/magicspeciallist = list("staffchange","staffanimation", "wandbelt", "contract", "staffchaos")
- usr << "You summoned [summon_type ? "magic" : "guns"]!"
- message_admins("[key_name_admin(usr, 1)] summoned [summon_type ? "magic" : "guns"]!")
- log_game("[key_name(usr)] summoned [summon_type ? "magic" : "guns"]!")
+ if(user) //in this case either someone holding a spellbook or a badmin
+ user << "You summoned [summon_type ? "magic" : "guns"]!"
+ message_admins("[key_name_admin(user, 1)] summoned [summon_type ? "magic" : "guns"]!")
+ log_game("[key_name(user)] summoned [summon_type ? "magic" : "guns"]!")
for(var/mob/living/carbon/human/H in player_list)
if(H.stat == 2 || !(H.client)) continue
if(H.mind)
@@ -100,6 +101,8 @@
new /obj/item/weapon/gun/magic/wand/teleport(get_turf(H))
if("wanddoor")
new /obj/item/weapon/gun/magic/wand/door(get_turf(H))
+ if("wandfireball")
+ new /obj/item/weapon/gun/magic/wand/fireball(get_turf(H))
if("staffhealing")
new /obj/item/weapon/gun/magic/staff/healing(get_turf(H))
if("staffdoor")
@@ -129,4 +132,22 @@
new /obj/item/weapon/antag_spawner/contract(get_turf(H))
if("staffchaos")
new /obj/item/weapon/gun/magic/staff/chaos(get_turf(H))
- H << "You suddenly feel lucky."
\ No newline at end of file
+ H << "You suddenly feel lucky."
+
+/proc/summonevents()
+ if(events) //if there isn't something is very wrong
+ if(!events.wizardmode)
+ events.frequency_lower = 600 //1 minute lower bound
+ events.frequency_upper = 3000 //5 minutes upper bound
+ events.toggleWizardmode()
+ events.reschedule()
+
+ else //Speed it up
+ events.frequency_lower = round(events.frequency_lower * 0.8) //1 minute | 48 seconds | 34.8 seconds | 30.7 seconds | 24.6 seconds
+ events.frequency_upper = round(events.frequency_upper * 0.6) //5 minutes | 3 minutes | 1 minute 48 seconds | 1 minute 4.8 seconds | 38.9 seconds
+ if(events.frequency_upper < events.frequency_lower)
+ events.frequency_upper = events.frequency_lower //this can't happen unless somehow multiple spellbooks are used, but just in case
+
+ events.reschedule()
+ message_admins("Summon Events intensifies, events will now occur every [events.frequency_lower / 600] to [events.frequency_upper / 600] minutes.")
+ log_game("Summon Events was increased!")
diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm
index 7b513e46cdc..09cad46c59b 100644
--- a/code/game/gamemodes/wizard/spellbook.dm
+++ b/code/game/gamemodes/wizard/spellbook.dm
@@ -112,6 +112,9 @@
dat += "Summon Magic (One time use, global spell) "
dat += "Share the wonders of magic with the crew and show them why they aren't to be trusted with it at the same time. "
+ dat += "Summon Events (One time use, persistent global spell) "
+ dat += "Give Murphy's law a little push and replace all events with special wizard ones that will confound and confuse everyone. Multiple castings increase the rate of these events. "
+
dat += ""
dat += "Return "
@@ -196,7 +199,7 @@
uses--
/*
*/
- var/list/available_spells = list(magicmissile = "Magic Missile", fireball = "Fireball", disintegrate = "Disintegrate", disabletech = "Disable Tech", smoke = "Smoke", blind = "Blind", mindswap = "Mind Transfer", forcewall = "Forcewall", blink = "Blink", teleport = "Teleport", mutate = "Mutate", etherealjaunt = "Ethereal Jaunt", knock = "Knock", horseman = "Curse of the Horseman", fleshtostone = "Flesh to Stone", summonguns = "Summon Guns", summonmagic = "Summon Magic", staffchange = "Staff of Change", soulstone = "Six Soul Stone Shards and the spell Artificer", armor = "Mastercrafted Armor Set", staffanimate = "Staff of Animation", staffchaos = "Staff of Chaos", staffdoor = "Staff of Door Creation", wands = "Wand Assortment")
+ var/list/available_spells = list(magicmissile = "Magic Missile", fireball = "Fireball", disintegrate = "Disintegrate", disabletech = "Disable Tech", smoke = "Smoke", blind = "Blind", mindswap = "Mind Transfer", forcewall = "Forcewall", blink = "Blink", teleport = "Teleport", mutate = "Mutate", etherealjaunt = "Ethereal Jaunt", knock = "Knock", horseman = "Curse of the Horseman", fleshtostone = "Flesh to Stone", summonguns = "Summon Guns", summonmagic = "Summon Magic", summonevents = "Summon Events", staffchange = "Staff of Change", soulstone = "Six Soul Stone Shards and the spell Artificer", armor = "Mastercrafted Armor Set", staffanimate = "Staff of Animation", staffchaos = "Staff of Chaos", staffdoor = "Staff of Door Creation", wands = "Wand Assortment")
var/already_knows = 0
for(var/obj/effect/proc_holder/spell/aspell in H.mind.spell_list)
if(available_spells[href_list["spell_choice"]] == initial(aspell.name))
@@ -292,14 +295,19 @@
temp = "You have learned flesh to stone."
if("summonguns")
feedback_add_details("wizard_spell_learned","SG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.rightandwrong(0)
+ rightandwrong(0, H)
max_uses--
temp = "You have cast summon guns."
if("summonmagic")
feedback_add_details("wizard_spell_learned","SU") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.rightandwrong(1)
+ rightandwrong(1, H)
max_uses--
temp = "You have cast summon magic."
+ if("summonevents")
+ feedback_add_details("wizard_spell_learned","SE") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
+ summonevents()
+ max_uses--
+ temp = "You have cast summon events."
if("staffchange")
feedback_add_details("wizard_spell_learned","ST") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
new /obj/item/weapon/gun/magic/staff/change(get_turf(H))
diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm
index 516c63e56b5..ef97dcc54cf 100644
--- a/code/game/gamemodes/wizard/wizard.dm
+++ b/code/game/gamemodes/wizard/wizard.dm
@@ -10,9 +10,6 @@
recommended_enemies = 1
pre_setup_before_jobs = 1
- uplink_welcome = "Wizardly Uplink Console:"
- uplink_uses = 10
-
var/finished = 0
/datum/game_mode/wizard/announce()
@@ -24,7 +21,7 @@
var/datum/mind/wizard = pick(antag_candidates)
wizards += wizard
modePlayer += wizard
- wizard.assigned_role = "MODE" //So they aren't chosen for other jobs.
+ wizard.need_job_assign = 0
wizard.special_role = "Wizard"
if(wizardstart.len == 0)
wizard.current << "A starting location for you could not be found, please report this bug!"
diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm
index a9ee8f00c16..cd7cb743573 100644
--- a/code/game/jobs/access.dm
+++ b/code/game/jobs/access.dm
@@ -79,6 +79,7 @@
//The Syndicate
/var/const/access_syndicate = 150//General Syndicate Access
+/var/const/access_syndicate_leader = 151//Nuke Op Leader Access
/obj/var/list/req_access = null
/obj/var/req_access_txt = "0"
@@ -103,6 +104,10 @@
//they can only hold things :(
if(src.check_access(george.get_active_hand()))
return 1
+ else if(isanimal(M))
+ var/mob/living/simple_animal/A = M
+ if(check_access(A.access_card))
+ return 1
return 0
/obj/item/proc/GetAccess()
@@ -206,7 +211,7 @@
return list(access_cent_general, access_cent_thunder, access_cent_specops, access_cent_medical, access_cent_living, access_cent_storage, access_cent_teleporter, access_cent_captain)
/proc/get_all_syndicate_access()
- return list(access_syndicate)
+ return list(access_syndicate, access_syndicate)
/proc/get_region_accesses(var/code)
switch(code)
diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm
index e4a9c21bb88..57365511158 100644
--- a/code/game/jobs/job_controller.dm
+++ b/code/game/jobs/job_controller.dm
@@ -46,6 +46,11 @@ var/global/datum/controller/occupations/job_master
if(!job) return 0
if(jobban_isbanned(player, rank)) return 0
if(!job.player_old_enough(player.client)) return 0
+ if(player.mind.special_role && ticker && ticker.mode)
+ if(job.title in ticker.mode.restricted_jobs)
+ return 0
+ if(!player.mind.need_job_assign)
+ return 0
var/position_limit = job.total_positions
if(!latejoin)
position_limit = job.spawn_positions
@@ -72,6 +77,19 @@ var/global/datum/controller/occupations/job_master
if(flag && (!player.client.prefs.be_special & flag))
Debug("FOC flag failed, Player: [player], Flag: [flag], ")
continue
+
+ if(config.enforce_human_authority && (job.title in command_positions) && player.client.prefs.pref_species.id != "human")
+ Debug("FOC non-human failed, Player: [player]")
+ continue
+
+ if(player.mind.special_role && ticker && ticker.mode)
+ if(job.title in ticker.mode.restricted_jobs)
+ Debug("FOC player has a special role and this job is blocked from this special role")
+ continue
+
+ if(!player.mind.need_job_assign)
+ continue
+
if(player.client.prefs.GetJobDepartment(job, level) & job.flag)
Debug("FOC pass, Player: [player], Level:[level]")
candidates += player
@@ -97,6 +115,18 @@ var/global/datum/controller/occupations/job_master
Debug("GRJ player not old enough, Player: [player]")
continue
+ if(config.enforce_human_authority && (job.title in command_positions) && player.client.prefs.pref_species.id != "human")
+ Debug("GRJ non-human failed, Player: [player]")
+ continue
+
+ if(player.mind.special_role && ticker && ticker.mode)
+ if(job.title in ticker.mode.restricted_jobs)
+ Debug("GRJ player has a special role and this job is blocked from this special role")
+ continue
+
+ if(!player.mind.need_job_assign)
+ continue
+
if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1)
Debug("GRJ Random job given, Player: [player], Job: [job]")
AssignRole(player, job.title)
@@ -248,6 +278,18 @@ var/global/datum/controller/occupations/job_master
Debug("DO player not old enough, Player: [player], Job:[job.title]")
continue
+ if(config.enforce_human_authority && (job.title in command_positions) && player.client.prefs.pref_species.id != "human")
+ Debug("DO non-human failed, Player: [player], Job:[job.title]")
+ continue
+
+ if(player.mind.special_role && ticker && ticker.mode)
+ if(job.title in ticker.mode.restricted_jobs)
+ Debug("DO player has a special role and this job is blocked from that special role")
+ continue
+
+ if(!player.mind.need_job_assign)
+ continue
+
// If the player wants that job on this level, then try give it to him.
if(player.client.prefs.GetJobDepartment(job, level) & job.flag)
@@ -276,6 +318,9 @@ var/global/datum/controller/occupations/job_master
//Gives the player the stuff he should have with his rank
/datum/controller/occupations/proc/EquipRank(var/mob/living/H, var/rank, var/joined_late = 0)
+ if(!H.mind.need_job_assign)
+ return 0
+
var/datum/job/job = GetJob(rank)
H.job = rank
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index 52c8c84e1aa..7e5801c56fe 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -17,8 +17,8 @@
var/min_health = 25
var/list/injection_chems = list() //list of injectable chems except inaprovaline, coz inaprovaline is always avalible
var/list/possible_chems = list(list("stoxin", "dexalin", "bicaridine", "kelotane"),
- list("stoxin", "dexalinp", "imidazoline", "dermaline", "bicaridine"),
- list("tricordrazine", "anti_toxin", "ryetalyn", "dermaline", "bicaridine", "imidazoline", "alkysine", "arithrazine"))
+ list("stoxin", "dexalinp", "bicaridine", "dermaline", "imidazoline"),
+ list("stoxin", "dexalinp", "bicaridine", "dermaline", "imidazoline", "anti_toxin", "ryetalyn", "alkysine", "arithrazine"))
/obj/machinery/sleeper/New()
..()
@@ -174,13 +174,17 @@
else
dat += "DEAD"
dat += " "
- dat += "
"
- //Make sure antags can't completely ruin rounds
-
- //Don't allow more than 1 Head / limit blacklisted jobs
- switch(can_open_job(j))
- if(1)
- dat += "Open Position "
- if(-1)
- dat += "You cannot open any more positions for this job. "
- if(-2)
- var/time_to_wait = round(change_position_cooldown - ((world.time / 10) - time_last_changed_position), 1)
- var/mins = round(time_to_wait / 60)
- var/seconds = time_to_wait - (60*mins)
- dat += "You have to wait [mins]:[(seconds < 10) ? "0[seconds]" : "[seconds]"] minutes before you can open this position."
- if(0)
- dat += "You cannot open positions for this job. "
-
-
- switch(can_close_job(j))
- if(1)
- dat += "Close Position"
- if(-1)
- dat += "You cannot close any more positions for this job. "
- if(-2)
- var/time_to_wait = round(change_position_cooldown - ((world.time / 10) - time_last_changed_position), 1)
- var/mins = round(time_to_wait / 60)
- var/seconds = time_to_wait - (60*mins)
- dat += "You have to wait [mins]:[(seconds < 10) ? "0[seconds]" : "[seconds]"] minutes before you can close this position."
- if(0)
- dat += "You cannot close positions for this job. "
- else
- dat = "Return"
- dat += "
Please insert your ID
"
- mode = 3
-
+ S = "--------"
+ dat += "[S]"
+ dat += "
"
+ dat += "
Job
Slots
Open job
Close job
"
+ var/ID
+ if(scan && (access_change_ids in scan.access))
+ ID = 1
+ else
+ ID = 0
+ for(var/datum/job/job in job_master.occupations)
+ dat += "
"
+ if(job.title in blacklisted)
+ continue
+ dat += "
", src)
dat += text("Delete Record (Security Only) ", src)
diff --git a/code/game/machinery/computer/shuttle.dm b/code/game/machinery/computer/shuttle.dm
index 653618f5898..414bd7a56f2 100644
--- a/code/game/machinery/computer/shuttle.dm
+++ b/code/game/machinery/computer/shuttle.dm
@@ -36,11 +36,11 @@
if (src.auth_need - src.authorized.len > 0)
message_admins("[key_name(user.client)](?) has authorized early shuttle launch in ([x],[y],[z] - JMP)",0,1)
log_game("[user.ckey]([user]) has authorized early shuttle launch in ([x],[y],[z])")
- minor_announce("[src.auth_need - src.authorized.len] more authorization(s) needed until shuttle is launched early")
+ minor_announce("[src.auth_need - src.authorized.len] more authorization(s) needed until shuttle is launched early",null,1)
else
message_admins("[key_name(user.client)](?) has launched the emergency shuttle in ([x],[y],[z] - JMP)",0,1)
log_game("[user.ckey]([user]) has launched the emergency shuttle in ([x],[y],[z])")
- minor_announce("The emergency shuttle will launch in 10 seconds")
+ minor_announce("The emergency shuttle will launch in 10 seconds",null,1)
emergency_shuttle.online = 1
emergency_shuttle.settimeleft(10)
//src.authorized = null
@@ -64,7 +64,7 @@
if("Launch")
message_admins("[key_name(user.client)](?) has emagged the emergency shuttle in ([x],[y],[z] - JMP)",0,1)
log_game("[user.ckey]([user]) has emagged the emergency shuttle in ([x],[y],[z])")
- minor_announce("The emergency shuttle will launch in 10 seconds", "System Error:")
+ minor_announce("The emergency shuttle will launch in 10 seconds", "SYSTEM ERROR:",null,1)
emergency_shuttle.settimeleft( 10 )
emagged = 1
if("Cancel")
diff --git a/code/game/machinery/computer/syndicate_shuttle.dm b/code/game/machinery/computer/syndicate_shuttle.dm
index 6757442453e..2c2b34faf52 100644
--- a/code/game/machinery/computer/syndicate_shuttle.dm
+++ b/code/game/machinery/computer/syndicate_shuttle.dm
@@ -1,40 +1,45 @@
#define SYNDICATE_SHUTTLE_MOVE_TIME 240
#define SYNDICATE_SHUTTLE_COOLDOWN 200
+/var/area/synd_shuttle_curr_location
+/var/synd_shuttle_moving = 0
+/var/synd_shuttle_lastMove = 0
+
/obj/machinery/computer/syndicate_station
name = "syndicate shuttle terminal"
icon = 'icons/obj/computer.dmi'
icon_state = "syndishuttle"
req_access = list(access_syndicate)
- var/area/curr_location
- var/moving = 0
- var/lastMove = 0
+ var/recall_only = 0
+/obj/machinery/computer/syndicate_station/recall
+ name = "syndicate shuttle recall terminal"
+ recall_only = 1
/obj/machinery/computer/syndicate_station/New()
- curr_location= locate(/area/syndicate_station/start)
+ synd_shuttle_curr_location= locate(/area/syndicate_station/start)
/obj/machinery/computer/syndicate_station/proc/syndicate_move_to(area/destination as area)
- if(moving) return
- if(lastMove + SYNDICATE_SHUTTLE_COOLDOWN > world.time) return
+ if(synd_shuttle_moving) return
+ if(synd_shuttle_lastMove + SYNDICATE_SHUTTLE_COOLDOWN > world.time) return
var/area/dest_location = locate(destination)
- if(curr_location == dest_location) return
+ if(synd_shuttle_curr_location == dest_location) return
- moving = 1
- lastMove = world.time
+ synd_shuttle_moving = 1
+ synd_shuttle_lastMove = world.time
- if(curr_location.z != dest_location.z)
+ if(synd_shuttle_curr_location.z != dest_location.z)
var/area/transit_location = locate(/area/syndicate_station/transit)
- curr_location.move_contents_to(transit_location)
- curr_location = transit_location
- curr_location.has_gravity = 0
+ synd_shuttle_curr_location.move_contents_to(transit_location)
+ synd_shuttle_curr_location = transit_location
+ synd_shuttle_curr_location.has_gravity = 0
transit_location.has_gravity = 1
sleep(SYNDICATE_SHUTTLE_MOVE_TIME)
- curr_location.move_contents_to(dest_location)
- curr_location = dest_location
- moving = 0
+ synd_shuttle_curr_location.move_contents_to(dest_location)
+ synd_shuttle_curr_location = dest_location
+ synd_shuttle_moving = 0
return 1
/obj/machinery/computer/syndicate_station/attack_hand(mob/user as mob)
@@ -44,17 +49,18 @@
user.set_machine(src)
- var/dat = {"Location: [curr_location]
- Ready to move[max(lastMove + SYNDICATE_SHUTTLE_COOLDOWN - world.time, 0) ? " in [max(round((lastMove + SYNDICATE_SHUTTLE_COOLDOWN - world.time) * 0.1), 0)] seconds" : ": now"]
- Syndicate Space
- North West of SS13 |
- North of SS13 |
- North East of SS13
- South West of SS13 |
- South of SS13 |
- South East of SS13
- North East of the Mining Asteroid
- Close"}
+ var/dat = {"Location: [synd_shuttle_curr_location]
+ Ready to move[max(synd_shuttle_lastMove + SYNDICATE_SHUTTLE_COOLDOWN - world.time, 0) ? " in [max(round((synd_shuttle_lastMove + SYNDICATE_SHUTTLE_COOLDOWN - world.time) * 0.1), 0)] seconds" : ": now"]
+ Syndicate Space "}
+ if(!recall_only)
+ dat += {"North West of SS13 |
+ North of SS13 |
+ North East of SS13
+ South West of SS13 |
+ South of SS13 |
+ South East of SS13
+ North East of the Mining Asteroid
+ Close"}
user << browse(dat, "window=computer;size=575x450")
onclose(user, "computer")
@@ -71,22 +77,21 @@
if(href_list["syndicate"])
syndicate_move_to(/area/syndicate_station/start)
- else if(href_list["station_nw"])
- syndicate_move_to(/area/syndicate_station/northwest)
- else if(href_list["station_n"])
- syndicate_move_to(/area/syndicate_station/north)
- else if(href_list["station_ne"])
- syndicate_move_to(/area/syndicate_station/northeast)
- else if(href_list["station_sw"])
- syndicate_move_to(/area/syndicate_station/southwest)
- else if(href_list["station_s"])
- syndicate_move_to(/area/syndicate_station/south)
- else if(href_list["station_se"])
- syndicate_move_to(/area/syndicate_station/southeast)
-// else if(href_list["commssat"])
-// syndicate_move_to(/area/syndicate_station/commssat)
- else if(href_list["mining"])
- syndicate_move_to(/area/syndicate_station/mining)
+ else if(!recall_only)
+ if(href_list["station_nw"])
+ syndicate_move_to(/area/syndicate_station/northwest)
+ else if(href_list["station_n"])
+ syndicate_move_to(/area/syndicate_station/north)
+ else if(href_list["station_ne"])
+ syndicate_move_to(/area/syndicate_station/northeast)
+ else if(href_list["station_sw"])
+ syndicate_move_to(/area/syndicate_station/southwest)
+ else if(href_list["station_s"])
+ syndicate_move_to(/area/syndicate_station/south)
+ else if(href_list["station_se"])
+ syndicate_move_to(/area/syndicate_station/southeast)
+ else if(href_list["mining"])
+ syndicate_move_to(/area/syndicate_station/mining)
updateUsrDialog()
return
\ No newline at end of file
diff --git a/code/game/machinery/computer/telecrystalconsoles.dm b/code/game/machinery/computer/telecrystalconsoles.dm
index 9f9c32260d2..72625aae8e8 100644
--- a/code/game/machinery/computer/telecrystalconsoles.dm
+++ b/code/game/machinery/computer/telecrystalconsoles.dm
@@ -1,4 +1,4 @@
-#define NUKESCALINGMODIFIER 0.5
+#define NUKESCALINGMODIFIER 1
var/list/possible_uplinker_IDs = list("Alfa","Bravo","Charlie","Delta","Echo","Foxtrot","Zero", "Niner")
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index 5bbec898938..4434006a2ef 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -64,6 +64,7 @@ for reference:
var/maxhealth = 100.0
/obj/structure/barricade/wooden/attackby(obj/item/W as obj, mob/user as mob)
+ user.changeNext_move(CLICK_CD_MELEE)
if (istype(W, /obj/item/stack/sheet/mineral/wood))
if (src.health < src.maxhealth)
visible_message("[user] begins to repair the [src]!")
diff --git a/code/game/machinery/door_control.dm b/code/game/machinery/door_control.dm
index 9ecedc5142e..a620d80585c 100644
--- a/code/game/machinery/door_control.dm
+++ b/code/game/machinery/door_control.dm
@@ -87,7 +87,7 @@
if(specialfunctions & IDSCAN)
D.aiDisabledIdScanner = !D.aiDisabledIdScanner
if(specialfunctions & BOLTS)
- if(!D.isWireCut(4) && D.arePowerSystemsOn())
+ if(!D.isWireCut(4) && D.hasPower())
D.locked = !D.locked
D.update_icon()
if(specialfunctions & SHOCK)
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 80d96a275ee..ed5e9f3f878 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -5,7 +5,7 @@
mend - mends a wire and makes any necessary state changes
canAIControl - 1 if the AI can control the airlock, 0 if not (then check canAIHack to see if it can hack in)
canAIHack - 1 if the AI can hack into the airlock to recover control, 0 if not. Also returns 0 if the AI does not *need* to hack it.
- arePowerSystemsOn - 1 if the main or backup power are functioning, 0 if not. Does not check whether the power grid is charged or an APC has equipment on or anything like that. (Check (stat & NOPOWER) for that)
+ hasPower - 1 if the main or backup power are functioning, 0 if not.
requiresIDs - 1 if the airlock is requiring IDs, 0 if not
isAllPowerCut - 1 if the main and backup power both have cut wires.
regainMainPower - handles the effect of main power coming back on.
@@ -282,6 +282,16 @@
var/mineral = "wood"
doortype = 35
+/obj/machinery/door/airlock/virology
+ icon = 'icons/obj/doors/Doorviro.dmi'
+ doortype = 36
+
+/obj/machinery/door/airlock/glass_virology
+ icon = 'icons/obj/doors/Doorviroglass.dmi'
+ opacity = 0
+ doortype = 37
+ glass = 1
+
/*
About the new airlock wires panel:
* An airlock wire dialog can be accessed by the normal way or by using wirecutters or a multitool on the door while the wire-panel is open. This would show the following wires, which you can either wirecut/mend or send a multitool pulse through. There are 9 wires.
@@ -334,8 +344,8 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/proc/canAIHack()
return ((src.aiControlDisabled==1) && (!hackProof) && (!src.isAllPowerCut()));
-/obj/machinery/door/airlock/proc/arePowerSystemsOn()
- return (src.secondsMainPowerLost==0 || src.secondsBackupPowerLost==0)
+/obj/machinery/door/airlock/hasPower()
+ return ((src.secondsMainPowerLost==0 || src.secondsBackupPowerLost==0) && !(stat & NOPOWER))
/obj/machinery/door/airlock/requiresID()
return !(src.isWireCut(AIRLOCK_WIRE_IDSCAN) || aiDisabledIdScanner)
@@ -389,7 +399,7 @@ About the new airlock wires panel:
// returns 1 if shocked, 0 otherwise
// The preceding comment was borrowed from the grille's shock script
/obj/machinery/door/airlock/proc/shock(mob/user, prb)
- if((stat & (NOPOWER)) || !src.arePowerSystemsOn()) // unpowered, no shock
+ if(!hasPower()) // unpowered, no shock
return 0
if(hasShocked)
return 0 //Already shocked someone recently?
@@ -513,7 +523,7 @@ About the new airlock wires panel:
t1 += text("Door bolts are up. Drop them? \n", src)
else
t1 += text("Door bolts are down.")
- if(src.arePowerSystemsOn())
+ if(src.hasPower())
t1 += text(" Raise? \n", src)
else
t1 += text(" Cannot raise door bolts due to power failure. \n")
@@ -775,7 +785,7 @@ About the new airlock wires panel:
else if(!src.locked)
usr << text("The door bolts are already up. \n")
else
- if(src.arePowerSystemsOn())
+ if(src.hasPower())
src.locked = 0
update_icon()
else
@@ -879,17 +889,15 @@ About the new airlock wires panel:
if((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density))
var/obj/item/weapon/weldingtool/W = C
user << "You begin [welded ? "unwelding":"welding"] the airlock..."
- playsound(loc, 'sound/items/Welder2.ogg', 40, 1)
+ playsound(loc, 'sound/items/Welder.ogg', 40, 1)
if(do_after(user,40,5,1))
if(density && !operating)//Door must be closed to weld.
if(W.remove_fuel(0,user))
- playsound(loc, 'sound/items/welder.ogg', 50, 1)
+ playsound(loc, 'sound/items/Welder2.ogg', 50, 1)
welded = !welded
user << "You [welded ? "welded the airlock shut":"unwelded the airlock"]"
update_icon()
user.visible_message("[src] has been [welded? "welded shut":"unwelded"] by [user.name].")
- else
- user << "You need more welding fuel to complete this task."
return
else if(istype(C, /obj/item/weapon/screwdriver))
src.p_open = !( src.p_open )
@@ -910,7 +918,7 @@ About the new airlock wires panel:
beingcrowbarred = 1 //derp, Agouri
else
beingcrowbarred = 0
- if( beingcrowbarred && (density && welded && !operating && src.p_open && (!src.arePowerSystemsOn() || stat & NOPOWER) && !src.locked) )
+ if( beingcrowbarred && (density && welded && !operating && src.p_open && (!hasPower()) && !src.locked) )
playsound(src.loc, 'sound/items/Crowbar.ogg', 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))
@@ -951,6 +959,8 @@ About the new airlock wires panel:
if(33) new/obj/structure/door_assembly/door_assembly_highsecurity(src.loc)
if(34) new/obj/structure/door_assembly/door_assembly_shuttle(src.loc)
if(35) new/obj/structure/door_assembly/door_assembly_wood(src.loc)
+ if(36) new/obj/structure/door_assembly/door_assembly_viro(src.loc)
+ if(37) new/obj/structure/door_assembly/door_assembly_viro/glass(src.loc)
if(emagged)
user << "You discard the damaged electronics."
qdel(src)
@@ -972,7 +982,7 @@ About the new airlock wires panel:
qdel(src)
return
- else if(arePowerSystemsOn() && !(stat & NOPOWER))
+ else if(hasPower())
user << " The airlock's motors resist your efforts to force it."
else if(locked)
user << " The airlock's bolts prevent it from being forced."
@@ -1013,7 +1023,7 @@ About the new airlock wires panel:
if( operating || welded || locked )
return 0
if(!forced)
- if( !arePowerSystemsOn() || (stat & NOPOWER) || isWireCut(AIRLOCK_WIRE_OPEN_DOOR) )
+ if( !hasPower() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR) )
return 0
if(forced < 2)
if(emagged)
@@ -1044,7 +1054,7 @@ About the new airlock wires panel:
if(operating || welded || locked)
return
if(!forced)
- if( !arePowerSystemsOn() || (stat & NOPOWER) || isWireCut(AIRLOCK_WIRE_DOOR_BOLTS) )
+ if( !hasPower() || isWireCut(AIRLOCK_WIRE_DOOR_BOLTS) )
return
if(safe)
if(locate(/mob/living) in get_turf(src))
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index ac6e9ab2720..8b03d1696c5 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -88,14 +88,17 @@
return !density || check_access(ID)
/obj/machinery/door/proc/bumpopen(mob/user as mob)
- if(operating) return
+ if(operating)
+ return
src.add_fingerprint(user)
if(!src.requiresID())
user = null
if(density && !emagged)
- if(allowed(user) || src.emergency == 1) open()
- else flick("door_deny", src)
+ if(allowed(user) || src.emergency == 1)
+ open()
+ else
+ flick("door_deny", src)
return
@@ -126,7 +129,7 @@
user = null
if(!src.requiresID())
user = null
- if(src.density && (istype(I, /obj/item/weapon/card/emag)||istype(I, /obj/item/weapon/melee/energy/blade)))
+ if(src.density && hasPower() && (istype(I, /obj/item/weapon/card/emag)||istype(I, /obj/item/weapon/melee/energy/blade)))
flick("door_spark", src)
sleep(6)
open()
@@ -269,6 +272,9 @@
/obj/machinery/door/proc/requiresID()
return 1
+/obj/machinery/door/proc/hasPower()
+ return !(stat & NOPOWER)
+
/obj/machinery/door/BlockSuperconductivity()
if(opacity || heat_proof)
return 1
diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm
index 6a1518e311b..910feb64a41 100644
--- a/code/game/machinery/doppler_array.dm
+++ b/code/game/machinery/doppler_array.dm
@@ -8,7 +8,6 @@ var/list/doppler_arrays = list()
density = 1
anchored = 1
-
/obj/machinery/doppler_array/New()
..()
doppler_arrays += src
@@ -74,10 +73,11 @@ var/list/doppler_arrays = list()
if(devastation_range < orig_dev_range || heavy_impact_range < orig_heavy_range || light_impact_range < orig_light_range)
messages += "Theoretical: Epicenter radius: [orig_dev_range]. Outer radius: [orig_heavy_range]. Shockwave radius: [orig_light_range]."
- for(var/mob/O in hearers(src, null))
- for(var/message in messages)
- O.show_message("[src] states coldly, \"[message]\"",2)
+ for(var/message in messages)
+ say(message)
+/obj/machinery/doppler_array/say_quote(text)
+ return "states coldly, \"[text]\""
/obj/machinery/doppler_array/power_change()
if(stat & BROKEN)
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index f56c9eaf2d2..a3468565a36 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -11,7 +11,7 @@ How it works:
AI clicks on holopad in camera view. View centers on holopad.
AI clicks again on the holopad to display a hologram. Hologram stays as long as AI is looking at the pad and it (the hologram) is in range of the pad.
AI can use the directional keys to move the hologram around, provided the above conditions are met and the AI in question is the holopad's master.
-Only one AI may project from a holopad at any given time.
+Any number of AIs can use a holopad. /Lo6
AI may cancel the hologram at any time by clicking on the holopad once more.
Possible to do for anyone motivated enough:
@@ -24,16 +24,20 @@ Possible to do for anyone motivated enough:
* Holopad
*/
-// HOLOPAD MODE
-// 0 = RANGE BASED
-// 1 = AREA BASED
-var/const/HOLOPAD_MODE = 0
+#define HOLOPAD_PASSIVE_POWER_USAGE 1
+#define HOLOGRAM_POWER_USAGE 2
+#define RANGE_BASED 4
+#define AREA_BASED 6
+
+var/const/HOLOPAD_MODE = RANGE_BASED
/obj/machinery/hologram/holopad
name = "\improper AI holopad"
desc = "It's a floor-mounted device for projecting holographic images. It is activated remotely."
icon_state = "holopad0"
- var/mob/living/silicon/ai/master//Which AI, if any, is controlling the object? Only one AI may control a hologram at any time.
+ flags = HEAR
+ languages = ROBOT | HUMAN
+ var/list/masters = list()//List of AIs that use the holopad
var/last_request = 0 //to prevent request spam. ~Carn
var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating.
@@ -59,85 +63,87 @@ var/const/HOLOPAD_MODE = 0
This may change in the future but for now will suffice.*/
if(user.eyeobj.loc != src.loc)//Set client eye on the object if it's not already.
user.eyeobj.setLoc(get_turf(src))
- else if(!hologram)//If there is no hologram, possibly make one.
+ else if(!masters[user])//If there is no hologram, possibly make one.
activate_holo(user)
- else if(master==user)//If there is a hologram, remove it. But only if the user is the master. Otherwise do nothing.
- clear_holo()
+ else//If there is a hologram, remove it.
+ clear_holo(user)
return
/obj/machinery/hologram/holopad/proc/activate_holo(mob/living/silicon/ai/user)
- if(!(stat & NOPOWER) && user.eyeobj.loc == src.loc)//If the projector has power and client eye is on it.
- if(!hologram)//If there is not already a hologram.
- create_holo(user)//Create one.
- src.visible_message("A holographic image of [user] flicks to life right before your eyes!")
- else
+ if(!(stat & NOPOWER) && user.eyeobj.loc == src.loc)//If the projector has power and client eye is on it
+ if (istype(user.current, /obj/machinery/hologram/holopad))
user << "ERROR: \black Image feed in progress."
+ return
+ create_holo(user)//Create one.
+ src.visible_message("A holographic image of [user] flicks to life right before your eyes!")
else
user << "ERROR: \black Unable to project hologram."
return
/*This is the proc for special two-way communication between AI and holopad/people talking near holopad.
For the other part of the code, check silicon say.dm. Particularly robot talk.*/
-/obj/machinery/hologram/holopad/hear_talk(mob/living/M, text)
- if(M&&hologram&&master)//Master is mostly a safety in case lag hits or something.
- if(!master.say_understands(M))//The AI will be able to understand most mobs talking through the holopad.
- text = stars(text)
- var/name_used = M.GetVoice()
- //This communication is imperfect because the holopad "filters" voices and is only designed to connect to the master only.
- var/rendered = "Holopad received, [name_used][M.say_quote(text)]"
- master.show_message(rendered, 2)
+/obj/machinery/hologram/holopad/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq)
+ if(speaker && masters.len && !radio_freq)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios.
+ for (var/mob/living/silicon/ai/master in masters)
+ if(masters[master] && speaker != master)
+ raw_message = master.lang_treat(speaker, message_langs, raw_message)
+ var/name_used = speaker.GetVoice()
+ var/rendered = "Holopad received, [name_used][speaker.say_quote(raw_message)]"
+ master.show_message(rendered, 2)
return
/obj/machinery/hologram/holopad/proc/create_holo(mob/living/silicon/ai/A, turf/T = loc)
- hologram = new(T)//Spawn a blank effect at the location.
- hologram.icon = A.holo_icon
- hologram.mouse_opacity = 0//So you can't click on it.
- hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
- hologram.anchored = 1//So space wind cannot drag it.
- hologram.name = "[A.name] (Hologram)"//If someone decides to right click.
- hologram.SetLuminosity(2) //hologram lighting
+ var/obj/effect/overlay/h = new(T)//Spawn a blank effect at the location.
+ h.icon = A.holo_icon
+ h.mouse_opacity = 0//So you can't click on it.
+ h.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
+ h.anchored = 1//So space wind cannot drag it.
+ h.name = "[A.name] (Hologram)"//If someone decides to right click.
+ h.SetLuminosity(2) //hologram lighting
+ masters[A] = h
SetLuminosity(2) //pad lighting
icon_state = "holopad1"
A.current = src
- master = A//AI is the master.
- use_power = 2//Active power usage.
+ use_power += HOLOGRAM_POWER_USAGE
return 1
-/obj/machinery/hologram/holopad/proc/clear_holo()
-// hologram.SetLuminosity(0)//Clear lighting. //handled by the lighting controller when its ower is deleted
- qdel(hologram)//Get rid of hologram.
- hologram = null
- if(master.current == src)
- master.current = null
- master = null//Null the master, since no-one is using it now.
- SetLuminosity(0) //pad lighting (hologram lighting will be handled automatically since its owner was deleted)
- icon_state = "holopad0"
- use_power = 1//Passive power usage.
+/obj/machinery/hologram/holopad/proc/clear_holo(mob/living/silicon/ai/user)
+ if(user.current == src)
+ user.current = null
+ qdel(masters[user])//Get rid of user's hologram
+ masters -= user //Discard AI from the list of those who use holopad
+ use_power = max(HOLOPAD_PASSIVE_POWER_USAGE, use_power - HOLOGRAM_POWER_USAGE)//Reduce power usage
+ if (!masters.len)//If no users left
+ SetLuminosity(0) //pad lighting (hologram lighting will be handled automatically since its owner was deleted)
+ icon_state = "holopad0"
+ use_power = HOLOPAD_PASSIVE_POWER_USAGE
return 1
/obj/machinery/hologram/holopad/process()
- if(hologram)//If there is a hologram.
- if(master && !master.stat && master.client && master.eyeobj)//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector.
- if(!(stat & NOPOWER))//If the machine has power.
- if((HOLOPAD_MODE == 0 && (get_dist(master.eyeobj, src) <= holo_range)))
- return 1
-
- else if (HOLOPAD_MODE == 1)
-
- var/area/holo_area = get_area(src)
- var/area/eye_area = get_area(master.eyeobj)
-
- if(eye_area in holo_area.master.related)
+ if(masters.len)//If there is a hologram.
+ for (var/mob/living/silicon/ai/master in masters)
+ if(master && !master.stat && master.client && master.eyeobj)//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector.
+ if(!(stat & NOPOWER))//If the machine has power.
+ if((HOLOPAD_MODE == RANGE_BASED && (get_dist(master.eyeobj, src) <= holo_range)))
return 1
- clear_holo()//If not, we want to get rid of the hologram.
+ else if (HOLOPAD_MODE == AREA_BASED)
+
+ var/area/holo_area = get_area(src)
+ var/area/eye_area = get_area(master.eyeobj)
+
+ if(eye_area in holo_area.master.related)
+ return 1
+
+ clear_holo(master)//If not, we want to get rid of the hologram.
return 1
-/obj/machinery/hologram/holopad/proc/move_hologram()
- if(hologram)
- step_to(hologram, master.eyeobj) // So it turns.
- hologram.loc = get_turf(master.eyeobj)
-
+/obj/machinery/hologram/holopad/proc/move_hologram(mob/living/silicon/ai/user)
+ if(masters[user])
+ step_to(masters[user], user.eyeobj) // So it turns.
+ var/obj/effect/overlay/H = masters[user]
+ H.loc = get_turf(user.eyeobj)
+ masters[user] = H
return 1
/*
@@ -149,7 +155,6 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
use_power = 1
idle_power_usage = 5
active_power_usage = 100
- var/obj/effect/overlay/hologram//The projection itself. If there is one, the instrument is on, off otherwise.
/obj/machinery/hologram/power_change()
if (powered())
@@ -175,8 +180,8 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
return
/obj/machinery/hologram/holopad/Destroy()
- if(hologram)
- clear_holo()
+ for (var/mob/living/silicon/ai/master in masters)
+ clear_holo(master)
..()
/*
@@ -207,4 +212,9 @@ Holographic project of everything else.
name = "hologram projector"
desc = "It makes a hologram appear...with magnets or something..."
icon = 'icons/obj/stationobjs.dmi'
- icon_state = "hologram0"
\ No newline at end of file
+ icon_state = "hologram0"
+
+#undef RANGE_BASED
+#undef AREA_BASED
+#undef HOLOPAD_PASSIVE_POWER_USAGE
+#undef HOLOGRAM_POWER_USAGE
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index 3c8292c53ae..44be02fadac 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -213,7 +213,7 @@ Class Procs:
return
/mob/dead/observer/canUseTopic()
- if(check_rights(R_ADMIN))
+ if(check_rights(R_ADMIN, 0))
return
/mob/living/canUseTopic(atom/movable/M, be_close = 0, no_dextery = 0)
@@ -264,9 +264,7 @@ Class Procs:
return 1
if(user.lying || user.stat)
return 1
- if ( ! (istype(usr, /mob/living/carbon/human) || \
- istype(usr, /mob/living/silicon) || \
- istype(usr, /mob/living/carbon/monkey)) )
+ if(!user.IsAdvancedToolUser())
usr << "You don't have the dexterity to do this!"
return 1
/*
diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm
index 6d82f6f054e..cbae21bc11e 100644
--- a/code/game/machinery/mass_driver.dm
+++ b/code/game/machinery/mass_driver.dm
@@ -23,8 +23,7 @@
if(!O.anchored || istype(O, /obj/mecha)) //Mechs need their launch platforms.
O_limit++
if(O_limit >= 20)
- for(var/mob/M in hearers(src, null))
- M << "[src] lets out a screech, it doesn't seem to be able to handle the load."
+ audible_message("[src] lets out a screech, it doesn't seem to be able to handle the load.")
break
use_power(500)
spawn(0)
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index 29ee00bd7e0..9e1bd0616fa 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -1027,10 +1027,8 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob)
// return //bode well with a newscaster network of 10+ machines. Let's just return it, as it's added in the machines list.
/obj/machinery/newscaster/proc/newsAlert(channel) //This isn't Agouri's work, for it is ugly and vile.
- var/turf/T = get_turf(src) //Who the fuck uses spawn(600) anyway, jesus christ
- if(channel)
- for(var/mob/O in hearers(world.view-1, T))
- O.show_message("[src.name] beeps, \"Breaking news from [channel]!\"",2)
+ if(channel) //Who the fuck uses spawn(600) anyway, jesus christ
+ say("Breaking news from [channel]!")
src.alert = 1
src.update_icon()
spawn(300)
@@ -1038,7 +1036,9 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob)
src.update_icon()
playsound(src.loc, 'sound/machines/twobeep.ogg', 75, 1)
else
- for(var/mob/O in hearers(world.view-1, T))
- O.show_message("[src.name] beeps, \"Attention! Wanted issue distributed!\"",2)
+ say("Attention! Wanted issue distributed!")
playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 75, 1)
- return
\ No newline at end of file
+ return
+
+/obj/machinery/newscaster/say_quote(text)
+ return "beeps, \"[text]\""
diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm
index 8d41384915c..ab94b08d5e7 100644
--- a/code/game/machinery/pipe/construction.dm
+++ b/code/game/machinery/pipe/construction.dm
@@ -254,8 +254,6 @@ Buildable meters
return 1
// no conflicts found
- var/pipefailtext = "There's nothing to connect this pipe section to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)"
-
switch(pipe_type)
if(PIPE_SIMPLE_STRAIGHT, PIPE_SIMPLE_BENT)
var/obj/machinery/atmospherics/pipe/simple/P = new( src.loc )
@@ -264,16 +262,13 @@ Buildable meters
var/turf/T = P.loc
P.level = T.intact ? 2 : 1
P.initialize()
- if (!P)
- usr << pipefailtext
- return 1
- P.build_network()
if (P.node1)
P.node1.initialize()
- P.node1.build_network()
+ P.node1.addMember(P)
if (P.node2)
P.node2.initialize()
- P.node2.build_network()
+ P.node2.addMember(P)
+ P.build_network()
if(PIPE_HE_STRAIGHT, PIPE_HE_BENT)
var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/P = new ( src.loc )
@@ -283,16 +278,13 @@ Buildable meters
//var/turf/T = P.loc
//P.level = T.intact ? 2 : 1
P.initialize()
- if (!P)
- usr << pipefailtext
- return 1
- P.build_network()
if (P.node1)
P.node1.initialize()
- P.node1.build_network()
+ P.node1.addMember(P)
if (P.node2)
P.node2.initialize()
- P.node2.build_network()
+ P.node2.addMember(P)
+ P.build_network()
if(PIPE_CONNECTOR) // connector
var/obj/machinery/atmospherics/portables_connector/C = new( src.loc )
@@ -310,26 +302,22 @@ Buildable meters
if(PIPE_MANIFOLD) //manifold
- var/obj/machinery/atmospherics/pipe/manifold/M = new( src.loc )
+ var/obj/machinery/atmospherics/pipe/manifold/M = new(loc)
M.dir = dir
M.initialize_directions = pipe_dir
- //M.New()
var/turf/T = M.loc
M.level = T.intact ? 2 : 1
M.initialize()
- if (!M)
- usr << "There's nothing to connect this manifold to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)"
- return 1
- M.build_network()
if (M.node1)
M.node1.initialize()
- M.node1.build_network()
+ M.node1.addMember(M)
if (M.node2)
M.node2.initialize()
- M.node2.build_network()
+ M.node2.addMember(M)
if (M.node3)
M.node3.initialize()
- M.node3.build_network()
+ M.node3.addMember(M)
+ M.build_network()
if(PIPE_JUNCTION)
var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/P = new ( src.loc )
@@ -339,16 +327,13 @@ Buildable meters
//var/turf/T = P.loc
//P.level = T.intact ? 2 : 1
P.initialize()
- if (!P)
- usr << "There's nothing to connect this junction to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)"
- return 1
- P.build_network()
if (P.node1)
P.node1.initialize()
- P.node1.build_network()
+ P.node1.addMember(P)
if (P.node2)
P.node2.initialize()
- P.node2.build_network()
+ P.node2.addMember(P)
+ P.build_network()
if(PIPE_UVENT) //unary vent
var/obj/machinery/atmospherics/unary/vent_pump/V = new( src.loc )
@@ -479,16 +464,13 @@ Buildable meters
var/turf/T = P.loc
P.level = T.intact ? 2 : 1
P.initialize()
- if (!P)
- usr << pipefailtext
- return 1
- P.build_network()
if (P.node1)
P.node1.initialize()
- P.node1.build_network()
+ P.node1.addMember(P)
if (P.node2)
P.node2.initialize()
- P.node2.build_network()
+ P.node2.addMember(P)
+ P.build_network()
if(PIPE_PASSIVE_GATE) //passive gate
var/obj/machinery/atmospherics/binary/passive_gate/P = new(src.loc)
diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm
index 905990105ca..a1aeefc9618 100644
--- a/code/game/machinery/pipe/pipe_dispenser.dm
+++ b/code/game/machinery/pipe/pipe_dispenser.dm
@@ -11,7 +11,7 @@
/obj/machinery/pipedispenser/attack_hand(user as mob)
if(..())
- return
+ return 1
var/dat = {"
Regular pipes: Pipe
@@ -46,10 +46,10 @@
/obj/machinery/pipedispenser/Topic(href, href_list)
if(..())
- return
+ return 1
if(!anchored|| !usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
usr << browse(null, "window=pipedispenser")
- return
+ return 1
usr.set_machine(src)
src.add_fingerprint(usr)
if(href_list["make"])
@@ -149,6 +149,7 @@ Nah
Bin Outlet Chute
+Sort Junction
"}
user << browse("[src][dat]", "window=pipedispenser")
@@ -163,9 +164,6 @@ Nah
usr.set_machine(src)
src.add_fingerprint(usr)
if(href_list["dmake"])
- if(!anchored || !usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
- usr << browse(null, "window=pipedispenser")
- return
if(!wait)
var/p_type = text2num(href_list["dmake"])
var/obj/structure/disposalconstruct/C = new (src.loc)
@@ -189,6 +187,8 @@ Nah
if(7)
C.ptype = 8
C.density = 1
+ if(8)
+ C.ptype = 9
C.add_fingerprint(usr)
C.update()
wait = 1
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index 11d49aef2bf..063ecc4496d 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -22,6 +22,7 @@
var/raising= 0 //if the turret is currently opening or closing its cover
var/health = 80 //the turret's health
var/locked = 1 //if the turret's behaviour control access is locked
+ var/controllock = 0 //if the turret responds to control panels
var/installation //the type of weapon installed
var/gun_charge = 0 //the charge of the gun inserted
@@ -269,6 +270,8 @@
user << "You short out [src]'s threat assessment circuits."
visible_message("[src] hums oddly...")
emagged = 1
+ iconholder = 1
+ controllock = 1
on = 0 //turns off the turret temporarily
sleep(60) //6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit
on = 1 //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here
@@ -603,7 +606,7 @@
A = new eprojectile(loc)
else
A = new projectile(loc)
- A.original = target.loc
+ A.original = target
if(!emagged)
use_power(reqpower)
else
@@ -615,6 +618,13 @@
spawn( 1 )
A.process()
+/obj/machinery/porta_turret/proc/setState(var/on, var/emagged)
+ if(controllock)
+ return
+ src.on = on
+ src.emagged = emagged
+ src.iconholder = emagged
+ src.power_change()
/*
Portable turret constructions
@@ -1004,3 +1014,146 @@ Status: [] "},
New()
installation = new/obj/item/weapon/gun/energy/laser(loc)
..()
+
+////////////////////////
+//Turret Control Panel//
+////////////////////////
+
+/obj/machinery/turretid
+ name = "turret control panel"
+ desc = "Used to control a room's automated defenses."
+ icon = 'icons/obj/machines/turret_control.dmi'
+ icon_state = "control_standby"
+ anchored = 1
+ density = 0
+ var/enabled = 1
+ var/lethal = 0
+ var/locked = 1
+ var/control_area //can be area name, path or nothing.
+ var/ailock = 0 // AI cannot use this
+ req_access = list(access_ai_upload)
+
+/obj/machinery/turretid/New()
+ ..()
+ if(!control_area)
+ var/area/CA = get_area(src)
+ if(CA.master && CA.master != CA)
+ control_area = CA.master
+ else
+ control_area = CA
+ else if(istext(control_area))
+ for(var/area/A in world)
+ if(A.name && A.name==control_area)
+ control_area = A
+ break
+ power_change() //Checks power and initial settings
+ //don't have to check if control_area is path, since get_area_all_atoms can take path.
+ return
+
+/obj/machinery/turretid/attackby(obj/item/weapon/W, mob/user)
+ if(stat & BROKEN) return
+ if (istype(user, /mob/living/silicon))
+ return src.attack_hand(user)
+
+ if (istype(W, /obj/item/weapon/card/emag) && !emagged)
+ user << "You short out the turret controls' access analysis module."
+ emagged = 1
+ locked = 0
+ if(user.machine==src)
+ src.attack_hand(user)
+
+ return
+
+ else if( get_dist(src, user) == 0 ) // trying to unlock the interface
+ if (src.allowed(usr))
+ if(emagged)
+ user << "The turret control is unresponsive."
+ return
+
+ locked = !locked
+ user << "You [ locked ? "lock" : "unlock"] the panel."
+ if (locked)
+ if (user.machine==src)
+ user.unset_machine()
+ user << browse(null, "window=turretid")
+ else
+ if (user.machine==src)
+ src.attack_hand(user)
+ else
+ user << "Access denied."
+
+/obj/machinery/turretid/attack_ai(mob/user as mob)
+ if(!ailock)
+ return attack_hand(user)
+ else
+ user << "There seems to be a firewall preventing you from accessing this device."
+
+/obj/machinery/turretid/attack_hand(mob/user as mob)
+ if ( get_dist(src, user) > 0 )
+ if ( !issilicon(user) )
+ user << "You are too far away."
+ user.unset_machine()
+ user << browse(null, "window=turretid")
+ return
+
+ user.set_machine(src)
+ var/loc = src.loc
+ if (istype(loc, /turf))
+ loc = loc:loc
+ if (!istype(loc, /area))
+ user << text("Turret badly positioned - loc.loc is [].", loc)
+ return
+ var/area/area = loc
+ var/t = ""
+
+ if(src.locked && (!istype(user, /mob/living/silicon)))
+ t += "
Swipe ID card to unlock interface
"
+ else
+ if (!istype(user, /mob/living/silicon))
+ t += "
Swipe ID card to lock interface
"
+ t += text("Turrets [] - []? \n", src.enabled?"activated":"deactivated", src, src.enabled?"Disable":"Enable")
+ t += text("Currently set for [] - Change to []? \n", src.lethal?"lethal":"stun repeatedly", src, src.lethal?"Stun repeatedly":"Lethal")
+
+ //user << browse(t, "window=turretid")
+ //onclose(user, "turretid")
+ var/datum/browser/popup = new(user, "turretid", "Turret Control Panel ([area.name])")
+ popup.set_content(t)
+ popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
+ popup.open()
+
+/obj/machinery/turretid/Topic(href, href_list)
+ if(..())
+ return
+ if (src.locked)
+ if (!istype(usr, /mob/living/silicon))
+ usr << "Control panel is locked!"
+ return
+ if (href_list["toggleOn"])
+ src.enabled = !src.enabled
+ src.updateTurrets()
+ else if (href_list["toggleLethal"])
+ src.lethal = !src.lethal
+ src.updateTurrets()
+ src.attack_hand(usr)
+
+/obj/machinery/turretid/proc/updateTurrets()
+ if(control_area)
+ for (var/obj/machinery/porta_turret/aTurret in get_area_all_atoms(control_area))
+ aTurret.setState(enabled, lethal)
+ src.update_icon()
+
+/obj/machinery/turretid/power_change()
+ ..()
+ update_icon()
+
+/obj/machinery/turretid/update_icon()
+ ..()
+ if(stat & NOPOWER)
+ icon_state = "control_off"
+ else if (enabled)
+ if (lethal)
+ icon_state = "control_kill"
+ else
+ icon_state = "control_stun"
+ else
+ icon_state = "control_standby"
\ No newline at end of file
diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm
index 0f0b7c069fe..9c1b8ee09cd 100644
--- a/code/game/machinery/requests_console.dm
+++ b/code/game/machinery/requests_console.dm
@@ -305,17 +305,15 @@ var/list/obj/machinery/requests_console/allConsoles = list()
pass = 1
if(pass)
-
for (var/obj/machinery/requests_console/Console in allConsoles)
if (ckey(Console.department) == ckey(href_list["department"]))
switch(priority)
- if(2) //High priority
+ if(2) //High priority
Console.createmessage(src, "PRIORITY Alert in [department]", sending, 2, 1)
if(3) // Extreme Priority
Console.createmessage(src, "EXTREME PRIORITY Alert in [department]", sending, 3, 1)
else // Normal priority
Console.createmessage(src, "Message from [department]", sending, 1, 1)
-
screen = 6
Console.luminosity = 2
@@ -325,8 +323,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
else
messages += "To: [dpt] [sending]"
else
- for (var/mob/O in hearers(4, src.loc))
- O.show_message("\icon[src] *The Requests Console beeps: 'NOTICE: No server detected!'")
+ say("NOTICE: No server detected!")
//Handle screen switching
@@ -369,7 +366,14 @@ var/list/obj/machinery/requests_console/allConsoles = list()
updateUsrDialog()
return
+
+/obj/machinery/say_quote(var/text)
+ var/ending = copytext(text, length(text) - 2)
+ if (ending == "!!!")
+ return "blares, \"[text]\""
+ return "beeps, \"[text]\""
+
/obj/machinery/requests_console/proc/createmessage(source, title, message, priority, paper)
var/linkedsender
var/unlinkedsender
@@ -389,8 +393,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
src.update_icon()
if(!src.silent)
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 1)
- for (var/mob/O in hearers(5, src.loc))
- O.show_message("\icon[src] *The Requests Console beeps: '[title]'")
+ say(title)
src.messages += "High Priority From: [linkedsender] [message]"
if(paper)
var/obj/item/weapon/paper/slip = new /obj/item/weapon/paper(src.loc)
@@ -403,8 +406,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
src.update_icon()
if(1)
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 1)
- for (var/mob/O in hearers(7, src.loc))
- O.show_message("\icon[src] *The Requests Console yells: '[title]'")
+ say(title)
src.messages += "!!!Extreme Priority!!! From: [linkedsender] [message]"
var/obj/item/weapon/paper/slip = new /obj/item/weapon/paper(src.loc)
if(paper)
@@ -421,14 +423,13 @@ var/list/obj/machinery/requests_console/allConsoles = list()
src.update_icon()
if(!src.silent)
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 1)
- for (var/mob/O in hearers(4, src.loc))
- O.show_message("\icon[src] *The Requests Console beeps: '[title]'")
+ say(title)
src.messages += "From: [linkedsender] [message]"
if(paper)
var/obj/item/weapon/paper/slip = new /obj/item/weapon/paper(src.loc)
slip.info = "From: [unlinkedsender] [message]"
slip.name = "Message - [unlinkedsender]"
- src.luminosity = 2
+ src.luminosity = 2
/obj/machinery/requests_console/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob)
if (istype(O, /obj/item/weapon/crowbar))
diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm
index d6a97d6723d..cf3453400d8 100644
--- a/code/game/machinery/shieldgen.dm
+++ b/code/game/machinery/shieldgen.dm
@@ -374,10 +374,9 @@
src.add_fingerprint(user)
/obj/machinery/shieldwallgen/process()
- spawn(100)
- power()
- if(power)
- storedpower -= 50 //this way it can survive longer and survive at all
+ power()
+ if(power)
+ storedpower -= 50 //this way it can survive longer and survive at all
if(storedpower >= maxstoredpower)
storedpower = maxstoredpower
if(storedpower <= 0)
@@ -389,14 +388,10 @@
if(!anchored)
src.active = 0
return
- spawn(1)
- setup_field(1)
- spawn(2)
- setup_field(2)
- spawn(3)
- setup_field(4)
- spawn(4)
- setup_field(8)
+ setup_field(1)
+ setup_field(2)
+ setup_field(4)
+ setup_field(8)
src.active = 2
if(src.active >= 1)
if(src.power == 0)
@@ -404,14 +399,10 @@
"You hear heavy droning fade out")
icon_state = "Shield_Gen"
src.active = 0
- spawn(1)
- src.cleanup(1)
- spawn(1)
- src.cleanup(2)
- spawn(1)
- src.cleanup(4)
- spawn(1)
- src.cleanup(8)
+ src.cleanup(1)
+ src.cleanup(2)
+ src.cleanup(4)
+ src.cleanup(8)
/obj/machinery/shieldwallgen/proc/setup_field(var/NSEW = 0)
var/turf/T = src.loc
diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm
index 410282a754f..add0390729f 100644
--- a/code/game/machinery/telecomms/broadcaster.dm
+++ b/code/game/machinery/telecomms/broadcaster.dm
@@ -56,11 +56,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
if(signal.data["type"] == 0)
/* ###### Broadcast a message using signal.data ###### */
- Broadcast_Message(signal.data["connection"], signal.data["mob"],
- signal.data["vmask"], signal.data["vmessage"],
- signal.data["radio"], signal.data["message"],
- signal.data["name"], signal.data["job"],
- signal.data["realname"], signal.data["vname"],, signal.data["compression"], signal.data["level"], signal.frequency)
+ Broadcast_Message(signal.data["mob"],
+ signal.data["vmask"], signal.data["radio"],
+ signal.data["message"], signal.data["name"], signal.data["job"], signal.data["realname"],
+ 0, signal.data["compression"], signal.data["level"], signal.frequency)
/** #### - Simple Broadcast - #### **/
@@ -80,12 +79,11 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/* ###### Broadcast a message using signal.data ###### */
// Parameter "data" as 4: AI can't track this person/mob
-
- Broadcast_Message(signal.data["connection"], signal.data["mob"],
- signal.data["vmask"], signal.data["vmessage"],
+ Broadcast_Message(signal.data["mob"],
+ signal.data["vmask"],
signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"],
- signal.data["realname"], signal.data["vname"], 4, signal.data["compression"], signal.data["level"], signal.frequency)
+ signal.data["realname"], 4, signal.data["compression"], signal.data["level"], signal.frequency)
if(!message_delay)
message_delay = 1
@@ -140,23 +138,12 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
sleep(signal.data["slow"]) // simulate the network lag if necessary
/* ###### Broadcast a message using signal.data ###### */
-
- var/datum/radio_frequency/connection = signal.data["connection"]
-
- if(connection.frequency == SYND_FREQ) // if syndicate broadcast, just
- Broadcast_Message(signal.data["connection"], signal.data["mob"],
- signal.data["vmask"], signal.data["vmessage"],
+ if(signal.frequency == SYND_FREQ) // if syndicate broadcast, just
+ Broadcast_Message(signal.data["mob"],
+ signal.data["vmask"],
signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"],
- signal.data["realname"], signal.data["vname"],, signal.data["compression"], list(0), connection.frequency)
- else
- if(intercept)
- Broadcast_Message(signal.data["connection"], signal.data["mob"],
- signal.data["vmask"], signal.data["vmessage"],
- signal.data["radio"], signal.data["message"],
- signal.data["name"], signal.data["job"],
- signal.data["realname"], signal.data["vname"], 3, signal.data["compression"], list(0), connection.frequency)
-
+ signal.data["realname"],, signal.data["compression"], list(0, z), signal.frequency)
/**
@@ -164,9 +151,6 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
Here is the big, bad function that broadcasts a message given the appropriate
parameters.
- @param connection:
- The datum generated in radio.dm, stored in signal.data["connection"].
-
@param M:
Reference to the mob/speaker, stored in signal.data["mob"]
@@ -216,198 +200,77 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
**/
-/proc/Broadcast_Message(var/datum/radio_frequency/connection, var/mob/M,
- var/vmask, var/vmessage, var/obj/item/device/radio/radio,
- var/message, var/name, var/job, var/realname, var/vname,
+
+/proc/Broadcast_Message(var/atom/movable/AM,
+ var/vmask, var/obj/item/device/radio/radio,
+ var/message, var/name, var/job, var/realname,
var/data, var/compression, var/list/level, var/freq)
- /* ###### Prepare the radio connection ###### */
-
- var/display_freq = freq
-
- var/list/obj/item/device/radio/radios = list()
-
- // Cut down on the message sizes.
-
message = copytext(message, 1, MAX_BROADCAST_LEN)
- vmessage = copytext(vmessage, 1, MAX_BROADCAST_LEN)
+ if(!message)
+ return
+
+ var/list/radios = list()
+
+ var/atom/movable/virtualspeaker/virt = PoolOrNew(/atom/movable/virtualspeaker,null)
+ virt.name = name
+ virt.job = job
+ virt.languages = AM.languages
+ virt.source = AM
+ virt.faketrack = data == 4 ? 1 : 0
+ virt.radio = radio
+
+ if(compression > 0)
+ message = Gibberish(message, compression + 40)
// --- Broadcast only to intercom devices ---
if(data == 1)
-
- for (var/obj/item/device/radio/intercom/R in connection.devices["[RADIO_CHAT]"])
- if(R.receive_range(display_freq, level) > -1)
+ for(var/obj/item/device/radio/intercom/R in all_radios["[freq]"])
+ if(R.receive_range(freq, level) > -1)
radios += R
// --- Broadcast only to intercoms and station-bounced radios ---
else if(data == 2)
- for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"])
-
+ for(var/obj/item/device/radio/R in all_radios["[freq]"])
if(istype(R, /obj/item/device/radio/headset))
continue
- if(R.receive_range(display_freq, level) > -1)
- radios += R
-
- // --- Broadcast to syndicate radio! ---
-
- else if(data == 3)
-
- var/datum/radio_frequency/syndicateconnection = radio_controller.return_frequency(SYND_FREQ)
-
- for (var/obj/item/device/radio/R in syndicateconnection.devices["[RADIO_CHAT]"])
-
- if(R.receive_range(SYND_FREQ, level) > -1)
+ if(R.receive_range(freq, level) > -1)
radios += R
// --- Broadcast to ALL radio devices ---
else
-
- for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"])
- if(R.receive_range(display_freq, level) > -1)
+ for(var/obj/item/device/radio/R in all_radios["[freq]"])
+ if(R.receive_range(freq, level) > -1)
radios += R
+ var/freqtext = num2text(freq)
+ for(var/obj/item/device/radio/R in all_radios["[SYND_FREQ]"]) //syndicate radios use magic that allows them to hear everything. this was already the case, now it just doesn't need the allinone anymore. solves annoying bugs that aren't worth solving.
+ if(R.receive_range(SYND_FREQ, list(R.z)) > -1 && freqtext in radiochannelsreverse)
+ radios |= R
+
// Get a list of mobs who can hear from the radios we collected.
- var/list/receive = get_mobs_in_radio_ranges(radios)
-
- /* ###### Organize the receivers into categories for displaying the message ###### */
-
- // Understood the message:
- var/list/heard_masked = list() // masked name or no real name
- var/list/heard_normal = list() // normal message
-
- // Did not understand the message:
- var/list/heard_voice = list() // voice message (ie "chimpers")
- var/list/heard_garbled = list() // garbled message (ie "f*c* **u, **i*er!")
- var/list/heard_gibberish= list() // completely screwed over message (ie "F%! (O*# *#!<>&**%!")
-
- for (var/mob/R in receive)
-
- /* --- Loop through the receivers and categorize them --- */
+ var/list/receive = get_mobs_in_radio_ranges(radios) //this includes all hearers.
+ for(var/mob/R in receive) //Filter receiver list.
if (R.client && !(R.client.prefs.toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
- continue
+ receive -= R
- if(istype(R, /mob/new_player)) // we don't want new players to hear messages. rare but generates runtimes.
- continue
-
-
- // --- Check for compression ---
- if(compression > 0)
- heard_gibberish += R
- continue
-
- // --- Can understand the speech ---
-
- if (!M || R.say_understands(M))
-
- // - Not human or wearing a voice mask -
- if (!M || !ishuman(M) || vmask)
- heard_masked += R
-
- // - Human and not wearing voice mask -
- else
- heard_normal += R
-
- // --- Can't understand the speech ---
-
- else
- // - The speaker has a prespecified "voice message" to display if not understood -
- if (vmessage)
- heard_voice += R
-
- // - Just display a garbled message -
- else
- heard_garbled += R
-
-
- /* ###### Begin formatting and sending the message ###### */
- if (length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled) || length(heard_gibberish))
-
- /* --- Some miscellaneous variables to format the string output --- */
- var/part_a = "" // goes in the actual output
- var/freq_text // the name of the channel
-
- // --- Set the name of the channel ---
- switch(display_freq)
-
- if(SYND_FREQ)
- freq_text = "#unkn"
- if(COMM_FREQ)
- freq_text = "Command"
- if(SCI_FREQ)
- freq_text = "Science"
- if(MED_FREQ)
- freq_text = "Medical"
- if(ENG_FREQ)
- freq_text = "Engineering"
- if(SEC_FREQ)
- freq_text = "Security"
- if(SERV_FREQ)
- freq_text = "Service"
- if(SUPP_FREQ)
- freq_text = "Supply"
- if(AIPRIV_FREQ)
- freq_text = "AI Private"
- //There's probably a way to use the list var of channels in code\game\communications.dm to make the dept channels non-hardcoded, but I wasn't in an experimentive mood. --NEO
-
-
- // --- If the frequency has not been assigned a name, just use the frequency as the name ---
-
- if(!freq_text)
- freq_text = format_frequency(display_freq)
-
- // --- Some more pre-message formatting ---
-
- var/part_b_extra = ""
- if(data == 3) // intercepted radio message
- part_b_extra = " (Intercepted)"
- var/part_b = " \[[freq_text]\][part_b_extra]"
- var/part_c = ""
-
- if (display_freq==SYND_FREQ)
- part_a = ""
- else if (display_freq==COMM_FREQ)
- part_a = ""
- else if (display_freq==SCI_FREQ)
- part_a = ""
- else if (display_freq==MED_FREQ)
- part_a = ""
- else if (display_freq==ENG_FREQ)
- part_a = ""
- else if (display_freq==SEC_FREQ)
- part_a = ""
- else if (display_freq==SERV_FREQ)
- part_a = ""
- else if (display_freq==SUPP_FREQ)
- part_a = ""
- else if (display_freq==DSQUAD_FREQ)
- part_a = ""
- else if (display_freq==AIPRIV_FREQ)
- part_a = ""
-
- // --- Filter the message; place it in quotes apply a verb ---
-
- var/quotedmsg = null
- if(M)
- quotedmsg = M.say_quote(message)
- else
- quotedmsg = "says, \"[message]\""
+ var/rendered = virt.compose_message(virt, virt.languages, message, freq) //Always call this on the virtualspeaker to advoid issues.
+ for(var/atom/movable/hearer in receive)
+ hearer.Hear(rendered, virt, AM.languages, message, freq)
+ if(length(receive))
// --- This following recording is intended for research and feedback in the use of department radio channels ---
- var/part_blackbox_b = " \[[freq_text]\]"
- var/blackbox_msg = "[part_a][name][part_blackbox_b][quotedmsg][part_c]"
- //var/blackbox_admin_msg = "[part_a][M.name] (Real name: [M.real_name])[part_blackbox_b][quotedmsg][part_c]"
-
- //BR.messages_admin += blackbox_admin_msg
+ var/blackbox_msg = "[AM] [AM.say_quote(message)]"
if(istype(blackbox))
- switch(display_freq)
+ switch(freq)
if(1459)
blackbox.msg_common += blackbox_msg
if(1351)
@@ -431,106 +294,8 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
else
blackbox.messages += blackbox_msg
- //End of research and feedback code.
-
- var/aitrack = ""
-
- /* ###### Send the message ###### */
-
-
- /* --- Process all the mobs that heard a masked voice (understood) --- */
-
- if (length(heard_masked))
- var/N = name
- var/J = job
- var/rendered = "[part_a][N][part_b][quotedmsg][part_c]"
- for (var/mob/R in heard_masked)
- aitrack = ""
- if(data == 4)
- aitrack = ""
-
- if(istype(R, /mob/living/silicon/ai))
- R.show_message("[part_a][aitrack][N] ([J]) [part_b][quotedmsg][part_c]", 2)
- else
- R.show_message(rendered, 2)
-
- /* --- Process all the mobs that heard the voice normally (understood) --- */
-
- if (length(heard_normal))
- var/rendered = "[part_a][realname][part_b][quotedmsg][part_c]"
-
- for (var/mob/R in heard_normal)
- aitrack = ""
- if(data == 4)
- aitrack = ""
-
- if(istype(R, /mob/living/silicon/ai))
- R.show_message("[part_a][aitrack][realname] ([job]) [part_b][quotedmsg][part_c]", 2)
- else
- R.show_message(rendered, 2)
-
- /* --- Process all the mobs that heard the voice normally (did not understand) --- */
- // Does not display message; displayes the mob's voice_message (ie "chimpers")
-
- if (length(heard_voice))
- var/rendered = "[part_a][vname][part_b][vmessage][part_c]"
-
- for (var/mob/R in heard_voice)
- aitrack = ""
- if(data == 4)
- aitrack = ""
-
-
- if(istype(R, /mob/living/silicon/ai))
- R.show_message("[part_a][aitrack][vname] ([job]) [part_b][vmessage]][part_c]", 2)
- else
- R.show_message(rendered, 2)
-
- /* --- Process all the mobs that heard a garbled voice (did not understand) --- */
- // Displays garbled message (ie "f*c* **u, **i*er!")
-
- if (length(heard_garbled))
- if(M)
- quotedmsg = M.say_quote(stars(message))
- else
- quotedmsg = stars(quotedmsg)
-
- var/rendered = "[part_a][vname][part_b][quotedmsg][part_c]"
-
- for (var/mob/R in heard_garbled)
- aitrack = ""
- if(data == 4)
- aitrack = ""
-
-
- if(istype(R, /mob/living/silicon/ai))
- R.show_message("[part_a][aitrack][vname][part_b][quotedmsg][part_c]", 2)
- else
- R.show_message(rendered, 2)
-
-
- /* --- Complete gibberish. Usually happens when there's a compressed message --- */
-
- if (length(heard_gibberish))
- if(M)
- quotedmsg = M.say_quote(Gibberish(message, compression + 50))
- else
- quotedmsg = Gibberish(quotedmsg, compression + 50)
-
- var/rendered = "[part_a][Gibberish(name, compression + 50)][part_b][quotedmsg][part_c]"
-
- for (var/mob/R in heard_gibberish)
- aitrack = ""
- if(data == 4)
- aitrack = ""
-
-
- if(istype(R, /mob/living/silicon/ai))
- R.show_message("[part_a][aitrack][Gibberish(realname, compression + 50)] ([Gibberish(job, compression + 50)]) [part_b][quotedmsg][part_c]", 2)
- else
- R.show_message(rendered, 2)
-
-
+ spawn(50)
+ PlaceInPool(virt)
/proc/Broadcast_SimpleMessage(var/source, var/frequency, var/text, var/data, var/mob/M, var/compression, var/level)
@@ -613,7 +378,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- Can understand the speech ---
- if (R.say_understands(M))
+ if (R.languages & M.languages)
heard_normal += R
@@ -791,7 +556,5 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
sleep(rand(10,25))
- //world.log << "Level: [signal.data["level"]] - Done: [signal.data["done"]]"
-
return signal
diff --git a/code/game/machinery/telecomms/logbrowser.dm b/code/game/machinery/telecomms/logbrowser.dm
index 5a5dbb3ff2f..a6de46e209e 100644
--- a/code/game/machinery/telecomms/logbrowser.dm
+++ b/code/game/machinery/telecomms/logbrowser.dm
@@ -80,27 +80,32 @@
if(mobtype in humans)
race = "Human"
-
+ language = race
+
+ else if(mobtype in slimes) // NT knows a lot about slimes, but not aliens. Can identify slimes
+ race = "Slime"
+ language = race
+
else if(mobtype in monkeys)
race = "Monkey"
- language = race
+ language = race
else if(mobtype in silicons || C.parameters["job"] == "AI") // sometimes M gets deleted prematurely for AIs... just check the job
race = "Artificial Life"
-
- else if(mobtype in slimes) // NT knows a lot about slimes, but not aliens. Can identify slimes
- race = "slime"
language = race
+
+ else if(istype(mobtype, /obj))
+ race = "Machinery"
+ language = race
else if(mobtype in animals)
race = "Domestic Animal"
language = race
-
+
else
race = "Unidentifiable"
language = race
-
// -- If the orator is a human, or universal translate is active, OR mob has universal speech on --
if(language == "Human" || universal_translate || C.parameters["uspeech"])
diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm
index ff0ec5208cc..599c5a20429 100644
--- a/code/game/machinery/telecomms/telecomunications.dm
+++ b/code/game/machinery/telecomms/telecomunications.dm
@@ -43,7 +43,6 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
if(!on)
return
- //world << "[src] ([src.id]) - [signal.debug_print()]"
var/send_count = 0
//signal.data["slow"] == 0 // apply some lag based on integrity
@@ -79,12 +78,9 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
"name" = signal.data["name"],
"job" = signal.data["job"],
"key" = signal.data["key"],
- "vmessage" = signal.data["vmessage"],
- "vname" = signal.data["vname"],
"vmask" = signal.data["vmask"],
"compression" = signal.data["compression"],
"message" = signal.data["message"],
- "connection" = signal.data["connection"],
"radio" = signal.data["radio"],
"slow" = signal.data["slow"],
"traffic" = signal.data["traffic"],
@@ -281,7 +277,6 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
return
if(!check_receive_level(signal))
return
-
if(signal.transmission_method == 2)
if(is_freq_listening(signal)) // detect subspace signals
@@ -370,7 +365,6 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
var/receiving = 1
/obj/machinery/telecomms/relay/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
-
// Add our level and send it back
if(can_send(signal))
signal.data["level"] |= listening_level
@@ -422,7 +416,6 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
/obj/machinery/telecomms/bus/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
if(is_freq_listening(signal))
-
if(change_frequency)
signal.frequency = change_frequency
@@ -541,7 +534,6 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
..()
/obj/machinery/telecomms/server/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
-
if(signal.data["message"])
if(is_freq_listening(signal))
@@ -557,22 +549,16 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
update_logs()
var/datum/comm_log_entry/log = new
- var/mob/M = signal.data["mob"]
// Copy the signal.data entries we want
log.parameters["mobtype"] = signal.data["mobtype"]
log.parameters["job"] = signal.data["job"]
log.parameters["key"] = signal.data["key"]
- log.parameters["vmessage"] = signal.data["message"]
- log.parameters["vname"] = signal.data["vname"]
log.parameters["message"] = signal.data["message"]
log.parameters["name"] = signal.data["name"]
log.parameters["realname"] = signal.data["realname"]
- if(!istype(M, /mob/new_player) && M)
- log.parameters["uspeech"] = M.universal_speak
- else
- log.parameters["uspeech"] = 0
+ log.parameters["uspeech"] = signal.data["languages"] & HUMAN //good enough
// If the signal is still compressed, make the log entry gibberish
if(signal.data["compression"] > 0)
@@ -580,7 +566,6 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
log.parameters["job"] = Gibberish(signal.data["job"], signal.data["compression"] + 50)
log.parameters["name"] = Gibberish(signal.data["name"], signal.data["compression"] + 50)
log.parameters["realname"] = Gibberish(signal.data["realname"], signal.data["compression"] + 50)
- log.parameters["vname"] = Gibberish(signal.data["vname"], signal.data["compression"] + 50)
log.input_type = "Corrupt File"
// Log and store everything that needs to be logged
diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm
index a34d7cec517..f178b810d39 100644
--- a/code/game/machinery/turrets.dm
+++ b/code/game/machinery/turrets.dm
@@ -308,106 +308,6 @@
spawn(13)
qdel(src)
-/obj/machinery/turretid
- name = "turret deactivation control"
- icon = 'icons/obj/device.dmi'
- icon_state = "motion3"
- anchored = 1
- density = 0
- var/enabled = 1
- var/lethal = 0
- var/locked = 1
- var/control_area //can be area name, path or nothing.
- var/ailock = 0 // AI cannot use this
- req_access = list(access_ai_upload)
-
-/obj/machinery/turretid/New()
- ..()
- if(!control_area)
- var/area/CA = get_area(src)
- if(CA.master && CA.master != CA)
- control_area = CA.master
- else
- control_area = CA
- else if(istext(control_area))
- for(var/area/A in world)
- if(A.name && A.name==control_area)
- control_area = A
- break
- //don't have to check if control_area is path, since get_area_all_atoms can take path.
- return
-
-/obj/machinery/turretid/attackby(obj/item/weapon/W, mob/user)
- if(stat & BROKEN) return
- if (istype(user, /mob/living/silicon))
- return src.attack_hand(user)
-
- if (istype(W, /obj/item/weapon/card/emag) && !emagged)
- user << "You short out the turret controls' access analysis module."
- emagged = 1
- locked = 0
- if(user.machine==src)
- src.attack_hand(user)
-
- return
-
- else if( get_dist(src, user) == 0 ) // trying to unlock the interface
- if (src.allowed(usr))
- if(emagged)
- user << "The turret control is unresponsive."
- return
-
- locked = !locked
- user << "You [ locked ? "lock" : "unlock"] the panel."
- if (locked)
- if (user.machine==src)
- user.unset_machine()
- user << browse(null, "window=turretid")
- else
- if (user.machine==src)
- src.attack_hand(user)
- else
- user << "Access denied."
-
-/obj/machinery/turretid/attack_ai(mob/user as mob)
- if(!ailock)
- return attack_hand(user)
- else
- user << "There seems to be a firewall preventing you from accessing this device."
-
-/obj/machinery/turretid/attack_hand(mob/user as mob)
- if ( get_dist(src, user) > 0 )
- if ( !issilicon(user) )
- user << "You are too far away."
- user.unset_machine()
- user << browse(null, "window=turretid")
- return
-
- user.set_machine(src)
- var/loc = src.loc
- if (istype(loc, /turf))
- loc = loc:loc
- if (!istype(loc, /area))
- user << text("Turret badly positioned - loc.loc is [].", loc)
- return
- var/area/area = loc
- var/t = ""
-
- if(src.locked && (!istype(user, /mob/living/silicon)))
- t += "
Swipe ID card to unlock interface
"
- else
- if (!istype(user, /mob/living/silicon))
- t += "
Swipe ID card to lock interface
"
- t += text("Turrets [] - []? \n", src.enabled?"activated":"deactivated", src, src.enabled?"Disable":"Enable")
- t += text("Currently set for [] - Change to []? \n", src.lethal?"lethal":"stun repeatedly", src, src.lethal?"Stun repeatedly":"Lethal")
-
- //user << browse(t, "window=turretid")
- //onclose(user, "turretid")
- var/datum/browser/popup = new(user, "turretid", "Turret Control Panel ([area.name])")
- popup.set_content(t)
- popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
- popup.open()
-
/obj/machinery/turret/attack_animal(mob/living/simple_animal/M as mob)
M.changeNext_move(CLICK_CD_MELEE)
@@ -439,45 +339,9 @@
return
-
-/obj/machinery/turretid/Topic(href, href_list)
- if(..())
- return
- if (src.locked)
- if (!istype(usr, /mob/living/silicon))
- usr << "Control panel is locked!"
- return
- if (href_list["toggleOn"])
- src.enabled = !src.enabled
- src.updateTurrets()
- else if (href_list["toggleLethal"])
- src.lethal = !src.lethal
- src.updateTurrets()
- src.attack_hand(usr)
-
-/obj/machinery/turretid/proc/updateTurrets()
- if(control_area)
- for (var/obj/machinery/turret/aTurret in get_area_all_atoms(control_area))
- aTurret.setState(enabled, lethal)
- src.update_icons()
-
-/obj/machinery/turretid/proc/update_icons()
- if (src.enabled)
- if (src.lethal)
- icon_state = "motion1"
- else
- icon_state = "motion3"
- else
- icon_state = "motion0"
- //CODE FIXED BUT REMOVED
-// if(control_area) //USE: updates other controls in the area
-// for (var/obj/machinery/turretid/Turret_Control in world) //I'm not sure if this is what it was
-// if( Turret_Control.control_area != src.control_area ) continue //supposed to do. Or whether the person
-// Turret_Control.icon_state = icon_state //who coded it originally was just tired
-// Turret_Control.enabled = enabled //or something. I don't see any situation
-// Turret_Control.lethal = lethal //in which this would be used on the current map.
- //If he wants it back he can uncomment it
-
+//////////////
+//Gun Turret//
+//////////////
/obj/machinery/gun_turret //related to turrets but work way differentely because of being mounted on a moving ship.
name = "machine gun turret"
@@ -621,3 +485,147 @@
spawn(0)
A.process()
return
+
+
+////////////////////////
+//Turret Control Panel//
+////////////////////////
+
+/obj/machinery/areaturretid
+ name = "turret control panel"
+ desc = "Used to control a room's automated defenses."
+ icon = 'icons/obj/machines/turret_control.dmi'
+ icon_state = "control_standby"
+ anchored = 1
+ density = 0
+ var/enabled = 1
+ var/lethal = 0
+ var/locked = 1
+ var/control_area //can be area name, path or nothing.
+ var/ailock = 0 // AI cannot use this
+ req_access = list(access_ai_upload)
+
+/obj/machinery/areaturretid/New()
+ ..()
+ if(!control_area)
+ var/area/CA = get_area(src)
+ if(CA.master && CA.master != CA)
+ control_area = CA.master
+ else
+ control_area = CA
+ else if(istext(control_area))
+ for(var/area/A in world)
+ if(A.name && A.name==control_area)
+ control_area = A
+ break
+ power_change() //Checks power and initial settings
+ //don't have to check if control_area is path, since get_area_all_atoms can take path.
+ return
+
+/obj/machinery/areaturretid/attackby(obj/item/weapon/W, mob/user)
+ if(stat & BROKEN) return
+ if (istype(user, /mob/living/silicon))
+ return src.attack_hand(user)
+
+ if (istype(W, /obj/item/weapon/card/emag) && !emagged)
+ user << "You short out the turret controls' access analysis module."
+ emagged = 1
+ locked = 0
+ if(user.machine==src)
+ src.attack_hand(user)
+
+ return
+
+ else if( get_dist(src, user) == 0 ) // trying to unlock the interface
+ if (src.allowed(usr))
+ if(emagged)
+ user << "The turret control is unresponsive."
+ return
+
+ locked = !locked
+ user << "You [ locked ? "lock" : "unlock"] the panel."
+ if (locked)
+ if (user.machine==src)
+ user.unset_machine()
+ user << browse(null, "window=turretid")
+ else
+ if (user.machine==src)
+ src.attack_hand(user)
+ else
+ user << "Access denied."
+
+/obj/machinery/areaturretid/attack_ai(mob/user as mob)
+ if(!ailock)
+ return attack_hand(user)
+ else
+ user << "There seems to be a firewall preventing you from accessing this device."
+
+/obj/machinery/areaturretid/attack_hand(mob/user as mob)
+ if ( get_dist(src, user) > 0 )
+ if ( !issilicon(user) )
+ user << "You are too far away."
+ user.unset_machine()
+ user << browse(null, "window=turretid")
+ return
+
+ user.set_machine(src)
+ var/loc = src.loc
+ if (istype(loc, /turf))
+ loc = loc:loc
+ if (!istype(loc, /area))
+ user << text("Turret badly positioned - loc.loc is [].", loc)
+ return
+ var/area/area = loc
+ var/t = ""
+
+ if(src.locked && (!istype(user, /mob/living/silicon)))
+ t += "
Swipe ID card to unlock interface
"
+ else
+ if (!istype(user, /mob/living/silicon))
+ t += "
[P]"
if (istype(cartridge, /obj/item/weapon/cartridge/syndicate) && P.detonate)
@@ -730,6 +731,9 @@ var/global/list/obj/item/device/pda/PDAs = list()
var/datum/signal/signal = src.telecomms_process()
+ if(emped)
+ t = Gibberish(t, 100)
+
var/useTC = 0
if(signal)
if(signal.data["done"])
@@ -751,9 +755,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
P.tnote += "← From [owner] ([ownjob]): [t] "
if (!P.silent)
- playsound(P.loc, 'sound/machines/twobeep.ogg', 50, 1)
- for (var/mob/O in hearers(3, P.loc))
- if(!P.silent) O.show_message(text("\icon[P] *[P.ttone]*"))
+ P.loc.audible_message("\icon[P] *[P.ttone]*", null, 3)
//Search for holder of the PDA.
var/mob/living/L = null
if(P.loc && isliving(P.loc))
@@ -1071,6 +1073,9 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/emp_act(severity)
for(var/atom/A in src)
A.emp_act(severity)
+ emped += 1
+ spawn(200 * severity)
+ emped -= 1
/proc/get_viewable_pdas()
. = list()
diff --git a/code/game/objects/items/devices/PDA/radio.dm b/code/game/objects/items/devices/PDA/radio.dm
index 0281a7b0e9c..e576cc2e109 100644
--- a/code/game/objects/items/devices/PDA/radio.dm
+++ b/code/game/objects/items/devices/PDA/radio.dm
@@ -227,10 +227,10 @@
..()
if(radio_controller)
initialize()
-
+
/obj/item/radio/integrated/signal/initialize()
if (src.frequency < 1441 || src.frequency > 1489)
- src.frequency = sanitize_frequency(src.frequency)
+ src.frequency = sanitize_frequency(src.frequency)
set_frequency(frequency)
diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm
index d0374abb08c..27b7ead9398 100644
--- a/code/game/objects/items/devices/aicard.dm
+++ b/code/game/objects/items/devices/aicard.dm
@@ -18,13 +18,6 @@
transfer_ai("AICORE", "AICARD", M, user)
return
-/obj/item/device/aicard/attack(mob/living/silicon/decoy/M as mob, mob/user as mob)
- if (!istype (M, /mob/living/silicon/decoy))
- return ..()
- else
- M.death()
- user << "ERROR ERROR ERROR"
-
/obj/item/device/aicard/attack_self(mob/user)
if (!in_range(src, user))
return
@@ -63,7 +56,7 @@
dat += "AI nonfunctional"
else
if (!src.flush)
- dat += {"Wipe AI"}
+ dat += {"Wipe AI"}
else
dat += "Wipe in progress"
dat += " "
diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm
index 24edb356243..da1bcf84de8 100644
--- a/code/game/objects/items/devices/camera_bug.dm
+++ b/code/game/objects/items/devices/camera_bug.dm
@@ -103,7 +103,7 @@
if(NETWORK_BUG,ADMIN_BUG)
if(length(list("SS13","MINE")&camera.network))
bugged_cameras[camera.c_tag] = camera
- bugged_cameras = sortAssoc(bugged_cameras)
+ sortList(bugged_cameras)
return bugged_cameras
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index c719a49a664..ae0c9ab83c2 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -74,21 +74,25 @@
flick("e_flash", M.flash)
if(ishuman(M) && ishuman(user) && M.stat != DEAD)
- if(user.mind && user.mind in ticker.mode.head_revolutionaries)
+ if(user.mind && ((user.mind in ticker.mode.head_revolutionaries) || (user.mind in ticker.mode.A_bosses) || (user.mind in ticker.mode.B_bosses)))
if(M.client)
if(M.stat == CONSCIOUS)
- var/revsafe = 0
- if(isloyal(M))
- revsafe = 1
M.mind_initialize() //give them a mind datum if they don't have one.
-// if(M.mind.has_been_rev)
-// revsafe = 2
- if(!revsafe)
- M.mind.has_been_rev = 1
- ticker.mode.add_revolutionary(M.mind)
- else if(revsafe == 1)
- user << "Something seems to be blocking the flash!"
+ var/resisted
+ if(!isloyal(M))
+ if(user.mind in ticker.mode.head_revolutionaries)
+ if(!ticker.mode.add_revolutionary(M.mind))
+ resisted = 1
+ if(user.mind in ticker.mode.A_bosses)
+ if(!ticker.mode.add_gangster(M.mind,"A"))
+ resisted = 1
+ if(user.mind in ticker.mode.B_bosses)
+ if(!ticker.mode.add_gangster(M.mind,"B"))
+ resisted = 1
else
+ resisted = 1
+
+ if(resisted)
user << "This mind seems resistant to the flash!"
else
user << "They must be conscious before you can convert them!"
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 980aace1ff1..f3d85bccb70 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -52,7 +52,7 @@
if(((CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50)) //too dumb to use flashlight properly
return ..() //just hit them in the head
- if(!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") //don't have dexterity
+ if(!user.IsAdvancedToolUser())
user << "You don't have the dexterity to do this!"
return
diff --git a/code/game/objects/items/devices/radio/beacon.dm b/code/game/objects/items/devices/radio/beacon.dm
index 28f9936054a..a8e111e3097 100644
--- a/code/game/objects/items/devices/radio/beacon.dm
+++ b/code/game/objects/items/devices/radio/beacon.dm
@@ -6,7 +6,7 @@
var/code = "electronic"
origin_tech = "bluespace=1"
-/obj/item/device/radio/beacon/hear_talk()
+/obj/item/device/radio/beacon/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq)
return
diff --git a/code/game/objects/items/devices/radio/electropack.dm b/code/game/objects/items/devices/radio/electropack.dm
index 482db3a9d23..fe503966e2a 100644
--- a/code/game/objects/items/devices/radio/electropack.dm
+++ b/code/game/objects/items/devices/radio/electropack.dm
@@ -11,6 +11,13 @@
m_amt = 10000
var/code = 2
+/obj/item/device/radio/electropack/initialize()
+ radio_controller.add_object(src, frequency, RADIO_CHAT)
+
+/obj/item/device/radio/electropack/New()
+ if(radio_controller)
+ radio_controller.add_object(src, frequency, RADIO_CHAT)
+
/obj/item/device/radio/electropack/attack_hand(mob/user)
if(iscarbon(user))
var/mob/living/carbon/C = user
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 324d941cffc..c765eff2eb3 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -275,13 +275,16 @@
src.syndie = 1
- for (var/ch_name in channels)
+ for(var/ch_name in channels)
+ //this is the most hilarious piece of code i have seen this week, so im not going to remove it
+ /*
if(!radio_controller)
sleep(30) // Waiting for the radio_controller to be created.
if(!radio_controller)
src.name = "broken radio headset"
return
+ */
- secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
+ secure_radio_connections[ch_name] = add_radio(src, radiochannels[ch_name])
return
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index 3e49179e76f..1397c2d1575 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -5,7 +5,6 @@
anchored = 1
w_class = 4.0
canhear_range = 2
- flags = CONDUCT
var/number = 0
var/anyai = 1
var/mob/living/silicon/ai/ai = list()
@@ -51,8 +50,8 @@
return canhear_range
-/obj/item/device/radio/intercom/hear_talk(mob/M as mob, msg)
- if(!src.anyai && !(M in src.ai))
+/obj/item/device/radio/intercom/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq)
+ if(!anyai && !(speaker in ai))
return
..()
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 59a98993112..e41c84f971f 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -1,8 +1,3 @@
-var/GLOBAL_RADIO_TYPE = 1 // radio type to use
- // 0 = old radios
- // 1 = new radios (subspace technology)
-
-
/obj/item/device/radio
icon = 'icons/obj/radio.dmi'
name = "station bounced radio"
@@ -16,6 +11,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
var/canhear_range = 3 // the range which mobs can hear this radio from
var/obj/item/device/radio/patch_link = null
var/datum/wires/radio/wires = null
+ var/list/secure_radio_connections
var/prison_radio = 0
var/b_stat = 0
var/broadcasting = 0
@@ -27,8 +23,9 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
var/maxf = 1499
var/emped = 0 //Highjacked to track the number of consecutive EMPs on the radio, allowing consecutive EMP's to stack properly.
// "Example" = FREQ_LISTENING|FREQ_BROADCASTING
- flags = CONDUCT
+ flags = CONDUCT | HEAR
slot_flags = SLOT_BELT
+ languages = HUMAN | ROBOT
throw_speed = 3
throw_range = 7
w_class = 2
@@ -39,14 +36,9 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
var/const/FREQ_LISTENING = 1
//FREQ_BROADCASTING = 2
-/obj/item/device/radio
- var/datum/radio_frequency/radio_connection
- var/list/datum/radio_frequency/secure_radio_connections
-
- proc/set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
- frequency = new_frequency
- radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT)
+/obj/item/device/radio/proc/set_frequency(new_frequency)
+ remove_radio(src, frequency)
+ frequency = add_radio(src, new_frequency)
/obj/item/device/radio/New()
wires = new(src)
@@ -57,6 +49,8 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
if(radio_controller)
initialize()
+/obj/item/device/radio/Destroy()
+ remove_radio_all(src) //Just to be sure.
/obj/item/device/radio/MouseDrop(obj/over_object as obj, src_location, over_location)
var/mob/M = usr
@@ -66,7 +60,6 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
/obj/item/device/radio/initialize()
-
if(freerange)
if(frequency < 1200 || frequency > 1600)
frequency = sanitize_frequency(frequency, maxf)
@@ -78,7 +71,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
set_frequency(frequency)
for (var/ch_name in channels)
- secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
+ secure_radio_connections[ch_name] = add_radio(src, radiochannels[ch_name])
/obj/item/device/radio/attack_self(mob/user as mob)
@@ -202,8 +195,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
/obj/item/device/radio/proc/isWireCut(var/index)
return wires.IsIndexCut(index)
-/obj/item/device/radio/talk_into(mob/living/M as mob, message, channel)
-
+/obj/item/device/radio/talk_into(atom/movable/M, message, channel)
if(!on) return // the device has to be on
// Fix for permacell radios, but kinda eh about actually fixing them.
if(!M || !message) return
@@ -216,395 +208,188 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
if(!M.IsVocal())
return
- if(GLOBAL_RADIO_TYPE == 1) // NEW RADIO SYSTEMS: By Doohl
+ /* Quick introduction:
+ This new radio system uses a very robust FTL signaling technology unoriginally
+ dubbed "subspace" which is somewhat similar to 'blue-space' but can't
+ actually transmit large mass. Headsets are the only radio devices capable
+ of sending subspace transmissions to the Communications Satellite.
- /* Quick introduction:
- This new radio system uses a very robust FTL signaling technology unoriginally
- dubbed "subspace" which is somewhat similar to 'blue-space' but can't
- actually transmit large mass. Headsets are the only radio devices capable
- of sending subspace transmissions to the Communications Satellite.
+ A headset sends a signal to a subspace listener/reciever elsewhere in space,
+ the signal gets processed and logged, and an audible transmission gets sent
+ to each individual headset.
+ */
+
+ /*
+ be prepared to disregard any comments in all of tcomms code. i tried my best to keep them somewhat up-to-date, but eh
+ */
- A headset sends a signal to a subspace listener/reciever elsewhere in space,
- the signal gets processed and logged, and an audible transmission gets sent
- to each individual headset.
- */
-
- //#### Grab the connection datum ####//
- var/datum/radio_frequency/connection = null
- if(channel && channels && channels.len > 0)
- if (channel == "department")
- //world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\""
- channel = channels[1]
- connection = secure_radio_connections[channel]
- if (!channels[channel]) // if the channel is turned off, don't broadcast
- return
- else
- connection = radio_connection
- channel = null
- if (!istype(connection))
- return
- if (!connection)
+ //get the frequency you buttface. radios no longer use the radio_controller. confusing for future generations, convenient for me.
+ var/freq
+ if(channel && channels && channels.len > 0)
+ if (channel == "department")
+ channel = channels[1]
+ freq = secure_radio_connections[channel]
+ if (!channels[channel]) // if the channel is turned off, don't broadcast
return
+ else
+ freq = frequency
+ channel = null
- var/turf/position = get_turf(src)
+ var/turf/position = get_turf(src)
- //#### Tagging the signal with all appropriate identity values ####//
+ //#### Tagging the signal with all appropriate identity values ####//
- // ||-- The mob's name identity --||
- var/displayname = M.name // grab the display name (name you get when you hover over someone's icon)
- var/real_name = M.real_name // mob's real name
- var/mobkey = "none" // player key associated with mob
- var/voicemask = 0 // the speaker is wearing a voice mask
- if(M.client)
- mobkey = M.key // assign the mob's key
+ // ||-- The mob's name identity --||
+ var/real_name = M.name // mob's real name
+ var/mobkey = "none" // player key associated with mob
+ var/voicemask = 0 // the speaker is wearing a voice mask
+ var/voice = M.GetVoice() // Why reinvent the wheel when there is a proc that does nice things already
+ if(ismob(M))
+ var/mob/speaker = M
+ real_name = speaker.real_name
+ if(speaker.client)
+ mobkey = speaker.key // assign the mob's key
- var/jobname // the mob's "job"
+ var/jobname // the mob's "job"
- // --- Human: use their job as seen on the crew manifest - makes it unneeded to carry an ID for an AI to see their job
- if (ishuman(M))
- var/voice = M.GetVoice() // Why reinvent the wheel when there is a proc that does nice things already
- var/datum/data/record/findjob = find_record("name", voice, data_core.general)
+ // --- Human: use their job as seen on the crew manifest - makes it unneeded to carry an ID for an AI to see their job
+ if (ishuman(M))
+ var/datum/data/record/findjob = find_record("name", voice, data_core.general)
- if(voice != real_name)
- displayname = voice
- voicemask = 1
- if(findjob)
- jobname = findjob.fields["rank"]
- else
- jobname = "Unknown"
-
- // --- Carbon Nonhuman ---
- else if (iscarbon(M)) // Nonhuman carbon mob
- jobname = "No id"
-
- // --- AI ---
- else if (isAI(M))
- jobname = "AI"
-
- // --- Cyborg ---
- else if (isrobot(M))
- var/mob/living/silicon/robot/B = M
- jobname = "[B.designation] Cyborg"
-
- // --- Personal AI (pAI) ---
- else if (istype(M, /mob/living/silicon/pai))
- jobname = "Personal AI"
-
- // --- Unidentifiable mob ---
+ if(voice != real_name)
+ voicemask = 1
+ if(findjob)
+ jobname = findjob.fields["rank"]
else
jobname = "Unknown"
+ // --- Carbon Nonhuman ---
+ else if (iscarbon(M)) // Nonhuman carbon mob
+ jobname = "No id"
+ // --- AI ---
+ else if (isAI(M))
+ jobname = "AI"
- /* ###### Radio headsets can only broadcast through subspace ###### */
+ // --- Cyborg ---
+ else if (isrobot(M))
+ var/mob/living/silicon/robot/B = M
+ jobname = "[B.designation] Cyborg"
- if(subspace_transmission)
- // First, we want to generate a new radio signal
- var/datum/signal/signal = new
- signal.transmission_method = 2 // 2 would be a subspace transmission.
- // transmission_method could probably be enumerated through #define. Would be neater.
+ // --- Personal AI (pAI) ---
+ else if (istype(M, /mob/living/silicon/pai))
+ jobname = "Personal AI"
- // --- Finally, tag the actual signal with the appropriate values ---
- signal.data = list(
- // Identity-associated tags:
- "mob" = M, // store a reference to the mob
- "mobtype" = M.type, // the mob's type
- "realname" = real_name, // the mob's real name
- "name" = displayname, // the mob's display name
- "job" = jobname, // the mob's job
- "key" = mobkey, // the mob's key
- "vmessage" = M.voice_message, // the message to display if the voice wasn't understood
- "vname" = M.voice_name, // the name to display if the voice wasn't understood
- "vmask" = voicemask, // 1 if the mob is using a voice gas mask
+ // --- Cold, emotionless machines. ---
+ else if(isobj(M))
+ jobname = "Machine"
- // We store things that would otherwise be kept in the actual mob
- // so that they can be logged even AFTER the mob is deleted or something
-
- // Other tags:
- "compression" = rand(45,50), // compressed radio signal
- "message" = message, // the actual sent message
- "connection" = connection, // the radio connection to use
- "radio" = src, // stores the radio used for transmission
- "slow" = 0, // how much to sleep() before broadcasting - simulates net lag
- "traffic" = 0, // dictates the total traffic sum that the signal went through
- "type" = 0, // determines what type of radio input it is: normal broadcast
- "server" = null, // the last server to log this signal
- "reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery
- "level" = position.z // The source's z level
- )
- signal.frequency = connection.frequency // Quick frequency set
-
- //#### Sending the signal to all subspace receivers ####//
-
- for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
- R.receive_signal(signal)
-
- // Allinone can act as receivers.
- for(var/obj/machinery/telecomms/allinone/R in telecomms_list)
- R.receive_signal(signal)
-
- // Receiving code can be located in Telecommunications.dm
- return
-
-
- /* ###### Intercoms and station-bounced radios ###### */
-
- var/filter_type = 2
-
- /* --- Intercoms can only broadcast to other intercoms, but bounced radios can broadcast to bounced radios and intercoms --- */
- if(istype(src, /obj/item/device/radio/intercom))
- filter_type = 1
+ // --- Unidentifiable mob ---
+ else
+ jobname = "Unknown"
+ /* ###### Radio headsets can only broadcast through subspace ###### */
+ if(subspace_transmission)
+ // First, we want to generate a new radio signal
var/datum/signal/signal = new
- signal.transmission_method = 2
-
-
- /* --- Try to send a normal subspace broadcast first */
-
+ signal.transmission_method = 2 // 2 would be a subspace transmission.
+ // transmission_method could probably be enumerated through #define. Would be neater.
+ // --- Finally, tag the actual signal with the appropriate values ---
signal.data = list(
-
+ // Identity-associated tags:
"mob" = M, // store a reference to the mob
"mobtype" = M.type, // the mob's type
"realname" = real_name, // the mob's real name
- "name" = displayname, // the mob's display name
+ "name" = voice, // the mob's voice name
"job" = jobname, // the mob's job
"key" = mobkey, // the mob's key
- "vmessage" = M.voice_message, // the message to display if the voice wasn't understood
- "vname" = M.voice_name, // the name to display if the voice wasn't understood
- "vmask" = voicemask, // 1 if the mob is using a voice gas mas
+ "vmask" = voicemask, // 1 if the mob is using a voice gas mask
- "compression" = 0, // uncompressed radio signal
+ // We store things that would otherwise be kept in the actual mob
+ // so that they can be logged even AFTER the mob is deleted or something
+
+ // Other tags:
+ "compression" = rand(35,65), // compressed radio signal
"message" = message, // the actual sent message
- "connection" = connection, // the radio connection to use
"radio" = src, // stores the radio used for transmission
- "slow" = 0,
- "traffic" = 0,
- "type" = 0,
- "server" = null,
- "reject" = 0,
- "level" = position.z
- )
- signal.frequency = connection.frequency // Quick frequency set
+ "slow" = 0, // how much to sleep() before broadcasting - simulates net lag
+ "traffic" = 0, // dictates the total traffic sum that the signal went through
+ "type" = 0, // determines what type of radio input it is: normal broadcast
+ "server" = null, // the last server to log this signal
+ "reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery
+ "level" = position.z, // The source's z level
+ "languages" = M.languages //The languages M is talking in.
+ )
+ signal.frequency = freq
+
+ //#### Sending the signal to all subspace receivers ####//
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
R.receive_signal(signal)
+ // Allinone can act as receivers.
+ for(var/obj/machinery/telecomms/allinone/R in telecomms_list)
+ R.receive_signal(signal)
- sleep(rand(10,25)) // wait a little...
+ // Receiving code can be located in Telecommunications.dm
+ return
+
+
+ /* ###### Intercoms and station-bounced radios ###### */
+
+ var/filter_type = 2
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 2
+
+
+ /* --- Try to send a normal subspace broadcast first */
+
+ signal.data = list(
+ "mob" = M, // store a reference to the mob
+ "mobtype" = M.type, // the mob's type
+ "realname" = real_name, // the mob's real name
+ "name" = voice, // the mob's voice name
+ "job" = jobname, // the mob's job
+ "key" = mobkey, // the mob's key
+ "vmask" = voicemask, // 1 if the mob is using a voice gas mas
+
+ "compression" = 0, // uncompressed radio signal
+ "message" = message, // the actual sent message
+ "radio" = src, // stores the radio used for transmission
+ "slow" = 0,
+ "traffic" = 0,
+ "type" = 0,
+ "server" = null,
+ "reject" = 0,
+ "level" = position.z
+ )
+ signal.frequency = text2num(freq) // Quick frequency set
+ for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
+ R.receive_signal(signal)
+
+
+ spawn(20) // wait a little...
if(signal.data["done"] && position.z in signal.data["level"])
// we're done here.
return
- // Oh my god; the comms are down or something because the signal hasn't been broadcasted yet in our level.
- // Send a mundane broadcast with limited targets:
+ // Oh my god; the comms are down or something because the signal hasn't been broadcasted yet in our level.
+ // Send a mundane broadcast with limited targets:
+ Broadcast_Message(M, voicemask,
+ src, message, voice, jobname, real_name,
+ filter_type, signal.data["compression"], list(position.z), freq)
- //THIS IS TEMPORARY.
- if(!connection) return //~Carn
-
- Broadcast_Message(connection, M, voicemask, M.voice_message,
- src, message, displayname, jobname, real_name, M.voice_name,
- filter_type, signal.data["compression"], list(position.z), connection.frequency)
-
-
-
- else // OLD RADIO SYSTEMS: By Goons?
-
- var/datum/radio_frequency/connection = null
- if(channel && channels && channels.len > 0)
- if (channel == "department")
- //world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\""
- channel = channels[1]
- connection = secure_radio_connections[channel]
- else
- connection = radio_connection
- channel = null
- if (!istype(connection))
- return
- var/display_freq = connection.frequency
-
- //world << "DEBUG: used channel=\"[channel]\" frequency= \"[display_freq]\" connection.devices.len = [connection.devices.len]"
-
- var/eqjobname
-
- if (ishuman(M))
- eqjobname = M:get_assignment()
- else if (iscarbon(M))
- eqjobname = "No id" //only humans can wear ID
- else if (isAI(M))
- eqjobname = "AI"
- else if (isrobot(M))
- eqjobname = "Cyborg"//Androids don't really describe these too well, in my opinion.
- else if (istype(M, /mob/living/silicon/pai))
- eqjobname = "Personal AI"
- else
- eqjobname = "Unknown"
-
- if (isWireCut(WIRE_TRANSMIT))
- return
-
- var/list/receive = list()
-
- //for (var/obj/item/device/radio/R in radio_connection.devices)
- for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"])
- //if(R.accept_rad(src, message))
- receive |= R.send_hear(display_freq, 0)
-
- //world << "DEBUG: receive.len=[receive.len]"
- var/list/heard_masked = list() // masked name or no real name
- var/list/heard_normal = list() // normal message
- var/list/heard_voice = list() // voice message
- var/list/heard_garbled = list() // garbled message
-
- for (var/mob/R in receive)
- if (R.client && !(R.client.prefs.toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
- continue
- if (R.say_understands(M))
- if (ishuman(M) && M.GetVoice() != M.real_name)
- heard_masked += R
- else
- heard_normal += R
- else
- if (M.voice_message)
- heard_voice += R
- else
- heard_garbled += R
-
- if (length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled))
- var/part_a = ""
- //var/part_b = " \icon[src]\[[format_frequency(frequency)]\]"
- var/freq_text
- switch(display_freq)
- if(SYND_FREQ)
- freq_text = "#unkn"
- if(COMM_FREQ)
- freq_text = "Command"
- if(SCI_FREQ)
- freq_text = "Science"
- if(MED_FREQ)
- freq_text = "Medical"
- if(ENG_FREQ)
- freq_text = "Engineering"
- if(SEC_FREQ)
- freq_text = "Security"
- if(SERV_FREQ)
- freq_text = "Service"
- if(SUPP_FREQ)
- freq_text = "Supply"
- if(AIPRIV_FREQ)
- freq_text = "AI Private"
- //There's probably a way to use the list var of channels in code\game\communications.dm to make the dept channels non-hardcoded, but I wasn't in an experimentive mood. --NEO
-
- if(!freq_text)
- freq_text = format_frequency(display_freq)
-
- var/part_b = " \[[freq_text]\]"
- var/part_c = ""
-
- if (display_freq==SYND_FREQ)
- part_a = ""
- else if (display_freq==COMM_FREQ)
- part_a = ""
- else if (display_freq==SCI_FREQ)
- part_a = ""
- else if (display_freq==MED_FREQ)
- part_a = ""
- else if (display_freq==ENG_FREQ)
- part_a = ""
- else if (display_freq==SEC_FREQ)
- part_a = ""
- else if (display_freq==SERV_FREQ)
- part_a = ""
- else if (display_freq==SUPP_FREQ)
- part_a = ""
- else if (display_freq==DSQUAD_FREQ)
- part_a = ""
- else if (display_freq==AIPRIV_FREQ)
- part_a = ""
- var/quotedmsg = M.say_quote(message)
-
- //This following recording is intended for research and feedback in the use of department radio channels.
-
- var/part_blackbox_b = " \[[freq_text]\]"
- var/blackbox_msg = "[part_a][M.name][part_blackbox_b][quotedmsg][part_c]"
- //var/blackbox_admin_msg = "[part_a][M.name] (Real name: [M.real_name])[part_blackbox_b][quotedmsg][part_c]"
- if(istype(blackbox))
- //BR.messages_admin += blackbox_admin_msg
- switch(display_freq)
- if(1459)
- blackbox.msg_common += blackbox_msg
- if(1351)
- blackbox.msg_science += blackbox_msg
- if(1353)
- blackbox.msg_command += blackbox_msg
- if(1355)
- blackbox.msg_medical += blackbox_msg
- if(1357)
- blackbox.msg_engineering += blackbox_msg
- if(1359)
- blackbox.msg_security += blackbox_msg
- if(1441)
- blackbox.msg_deathsquad += blackbox_msg
- if(1213)
- blackbox.msg_syndicate += blackbox_msg
- if(1349)
- blackbox.msg_service += blackbox_msg
- if(1347)
- blackbox.msg_cargo += blackbox_msg
- else
- blackbox.messages += blackbox_msg
-
- //End of research and feedback code.
-
- if (length(heard_masked))
- var/N = M.name
- var/J = eqjobname
- if(ishuman(M) && M.GetVoice() != M.real_name)
- N = M.GetVoice()
- J = "Unknown"
- var/rendered = "[part_a][N][part_b][quotedmsg][part_c]"
- for (var/mob/R in heard_masked)
- if(istype(R, /mob/living/silicon/ai))
- R.show_message("[part_a][N] ([J]) [part_b][quotedmsg][part_c]", 2)
- else
- R.show_message(rendered, 2)
-
- if (length(heard_normal))
- var/rendered = "[part_a][M.real_name][part_b][quotedmsg][part_c]"
-
- for (var/mob/R in heard_normal)
- if(istype(R, /mob/living/silicon/ai))
- R.show_message("[part_a][M.real_name] ([eqjobname]) [part_b][quotedmsg][part_c]", 2)
- else
- R.show_message(rendered, 2)
-
- if (length(heard_voice))
- var/rendered = "[part_a][M.voice_name][part_b][M.voice_message][part_c]"
-
- for (var/mob/R in heard_voice)
- if(istype(R, /mob/living/silicon/ai))
- R.show_message("[part_a][M.voice_name] ([eqjobname]) [part_b][M.voice_message][part_c]", 2)
- else
- R.show_message(rendered, 2)
-
- if (length(heard_garbled))
- quotedmsg = M.say_quote(stars(message))
- var/rendered = "[part_a][M.voice_name][part_b][quotedmsg][part_c]"
-
- for (var/mob/R in heard_voice)
- if(istype(R, /mob/living/silicon/ai))
- R.show_message("[part_a][M.voice_name][part_b][quotedmsg][part_c]", 2)
- else
- R.show_message(rendered, 2)
-
-/obj/item/device/radio/hear_talk(mob/M as mob, msg)
-
- if (broadcasting)
- if(get_dist(src, M) <= canhear_range)
- talk_into(M, msg)
+/obj/item/device/radio/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq)
+ if(radio_freq)
+ return
+ if(broadcasting)
+ if(get_dist(src, speaker) <= canhear_range)
+ talk_into(speaker, raw_message)
/*
/obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R as obj, message)
@@ -632,21 +417,21 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
if(!position || !(position.z in level))
return -1
if(freq == SYND_FREQ)
- if(!(src.syndie))//Checks to see if it's allowed on that frequency, based on the encryption keys
+ if(!(src.syndie)) //Checks to see if it's allowed on that frequency, based on the encryption keys
return -1
if (!on)
return -1
- if (!freq) //recieved on main frequency
+ if (!freq) //received on main frequency
if (!listening)
return -1
else
var/accept = (freq==frequency && listening)
if (!accept)
- for (var/ch_name in channels)
- var/datum/radio_frequency/RF = secure_radio_connections[ch_name]
- if (RF.frequency==freq && (channels[ch_name]&FREQ_LISTENING))
- accept = 1
- break
+ for(var/ch_name in channels)
+ if(channels[ch_name] & FREQ_LISTENING)
+ if(radiochannels[ch_name] == text2num(freq) || syndie) //the radiochannels list is located in communications.dm
+ accept = 1
+ break
if (!accept)
return -1
return canhear_range
@@ -655,7 +440,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
var/range = receive_range(freq, level)
if(range > -1)
- return get_mobs_in_view(canhear_range, src)
+ return get_hearers_in_view(canhear_range, src)
/obj/item/device/radio/examine(mob/user)
@@ -777,7 +562,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
src.name = "broken radio"
return
- secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
+ secure_radio_connections[ch_name] = add_radio(src, radiochannels[ch_name])
return
@@ -817,7 +602,5 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
onclose(user, "radio")
return
-
-
/obj/item/device/radio/off // Station bounced radios, their only difference is spawning with the speakers off, this was made to help the lag.
listening = 0 // And it's nice to have a subtype too for future features.
diff --git a/code/game/objects/items/devices/recaller.dm b/code/game/objects/items/devices/recaller.dm
new file mode 100644
index 00000000000..efe0ae00066
--- /dev/null
+++ b/code/game/objects/items/devices/recaller.dm
@@ -0,0 +1,40 @@
+//Recaller device
+//Allows gang leaders to recall the shuttle
+/obj/item/device/recaller
+ name = "suspicious device"
+ desc = "A strange device of sorts. Hard to really make out what it actually does just by looking."
+ icon_state = "recaller"
+ item_state = "walkietalkie"
+ throwforce = 0
+ w_class = 1.0
+ throw_speed = 3
+ throw_range = 7
+ flags = CONDUCT
+ var/recalling = 0
+
+/obj/item/device/recaller/attack_self(mob/user)
+ if(recalling)
+ return
+ if((user.mind in ticker.mode.A_bosses) || (user.mind in ticker.mode.B_bosses))
+ var/turf/userturf = get_turf(user)
+ if(userturf.z != 1)
+ user << "\icon[src]Error: Device out of range of station communication arrays."
+ return
+
+ if(emergency_shuttle.location==0)
+ if (emergency_shuttle.online)
+ recalling = 1
+ loc << "\icon[src]Generating shuttle recall order with codes retrieved from last call signal..."
+ sleep(rand(10,30))
+ loc << "\icon[src]Shuttle recall order generated. Accessing station long-range communication arrays..."
+ sleep(rand(10,30))
+ loc << "\icon[src]Comm arrays accessed. Broadcasting recall signal..."
+ sleep(rand(10,30))
+ recalling = 0
+ log_game("[key_name(user)] has recalled the shuttle with a recaller.")
+ message_admins("[key_name_admin(user)] has recalled the shuttle with a recaller.", 1)
+ if(!cancel_call_proc(user))
+ loc << "\icon[src]No response recieved. Emergency shuttle cannot be recalled at this time."
+ return
+
+ user << "\icon[src]Emergency shuttle cannot be recalled at this time."
\ No newline at end of file
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 8d25a62be7e..cd44cf0ae72 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -22,7 +22,7 @@ MASS SPECTROMETER
/obj/item/device/t_scanner/attack_self(mob/user)
on = !on
- icon_state = "t-ray[on]"
+ icon_state = copytext(icon_state, 1, length(icon_state))+"[on]"
if(on)
processing_objects.Add(src)
@@ -32,6 +32,9 @@ MASS SPECTROMETER
if(!on)
processing_objects.Remove(src)
return null
+ scan()
+
+/obj/item/device/t_scanner/proc/scan()
for(var/turf/T in range(1, src.loc) )
@@ -142,7 +145,7 @@ MASS SPECTROMETER
user.show_message("Subject appears to be suffering from fatigue.", 1)
if (M.getCloneLoss())
- user.show_message("Subject appears to have been imperfectly cloned.", 1)
+ user.show_message("Subject appears to have [M.getCloneLoss() > 30 ? "severe" : "minor"] cellular damage.", 1)
for(var/datum/disease/D in M.viruses)
if(!D.hidden[SCANNER])
@@ -269,7 +272,7 @@ MASS SPECTROMETER
if (crit_fail)
user << " This device has critically failed and is no longer functional!"
return
- if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
+ if (!user.IsAdvancedToolUser())
user << " You don't have the dexterity to do this!"
return
if(reagents.total_volume)
diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm
index 0f41db11eb3..02867db2e4d 100644
--- a/code/game/objects/items/devices/taperecorder.dm
+++ b/code/game/objects/items/devices/taperecorder.dm
@@ -4,7 +4,9 @@
icon_state = "taperecorder_empty"
item_state = "analyzer"
w_class = 2
+ flags = HEAR
slot_flags = SLOT_BELT
+ languages = ALL //this is a translator, after all.
m_amt = 60
g_amt = 30
force = 2
@@ -88,24 +90,10 @@
icon_state = "taperecorder_idle"
-/obj/item/device/taperecorder/hear_talk(mob/living/M as mob, msg)
+/obj/item/device/taperecorder/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq)
if(mytape && recording)
- var/ending = copytext(msg, length(msg))
mytape.timestamp += mytape.used_capacity
- if(M.stuttering)
- mytape.storedinfo += "\[[time2text(mytape.used_capacity * 10,"mm:ss")]\] [M.name] stammers, \"[msg]\""
- return
- if(M.getBrainLoss() >= 60)
- mytape.storedinfo += "\[[time2text(mytape.used_capacity * 10,"mm:ss")]\] [M.name] gibbers, \"[msg]\""
- return
- if(ending == "?")
- mytape.storedinfo += "\[[time2text(mytape.used_capacity * 10,"mm:ss")]\] [M.name] asks, \"[msg]\""
- return
- else if(ending == "!")
- mytape.storedinfo += "\[[time2text(mytape.used_capacity * 10,"mm:ss")]\] [M.name] exclaims, \"[msg]\""
- return
- mytape.storedinfo += "\[[time2text(mytape.used_capacity * 10,"mm:ss")]\] [M.name] says, \"[msg]\""
-
+ mytape.storedinfo += "\[[time2text(mytape.used_capacity * 10,"mm:ss")]\] [strip_html_properly(message)]"
/obj/item/device/taperecorder/verb/record()
set name = "Start Recording"
@@ -193,19 +181,16 @@
break
if(mytape.storedinfo.len < i)
break
- var/turf/T = get_turf(src)
- T.visible_message("Tape Recorder: [mytape.storedinfo[i]]")
+ say(mytape.storedinfo[i])
if(mytape.storedinfo.len < i + 1)
playsleepseconds = 1
sleep(10)
- T = get_turf(src)
- T.visible_message("Tape Recorder: End of recording.")
+ say("End of recording.")
else
playsleepseconds = mytape.timestamp[i + 1] - mytape.timestamp[i]
if(playsleepseconds > 14)
sleep(10)
- T = get_turf(src)
- T.visible_message("Tape Recorder: Skipping [playsleepseconds] seconds of silence")
+ say("Skipping [playsleepseconds] seconds of silence")
playsleepseconds = 1
i++
@@ -298,4 +283,4 @@
//Random colour tapes
/obj/item/device/tape/random/New()
- icon_state = "tape_[pick("white", "blue", "red", "yellow", "purple")]"
\ No newline at end of file
+ icon_state = "tape_[pick("white", "blue", "red", "yellow", "purple")]"
diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm
index 4126181ea89..64951705275 100644
--- a/code/game/objects/items/devices/transfer_valve.dm
+++ b/code/game/objects/items/devices/transfer_valve.dm
@@ -64,11 +64,6 @@
if(!attached_device) return
attached_device.HasProximity(AM)
return
-/obj/item/device/transfer_valve/hear_talk(mob/living/M, msg)
- if(!attached_device) return
- attached_device.hear_talk(M, msg)
- return
-
/obj/item/device/transfer_valve/attack_self(mob/user as mob)
user.set_machine(src)
var/dat = {" Valve properties:
diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm
index 770a1159de5..a50eabc6017 100644
--- a/code/game/objects/items/devices/uplinks.dm
+++ b/code/game/objects/items/devices/uplinks.dm
@@ -9,8 +9,8 @@ A list of items and costs is stored under the datum of every game mode, alongsid
var/list/world_uplinks = list()
/obj/item/device/uplink
- var/welcome // Welcoming menu message
- var/uses // Numbers of crystals
+ var/welcome = "Syndicate Uplink Console:" // Welcoming menu message
+ var/uses = 20 // Numbers of crystals
// List of items not to shove in their hands.
var/purchase_log = ""
var/show_description = null
@@ -22,8 +22,6 @@ var/list/world_uplinks = list()
/obj/item/device/uplink/New()
..()
world_uplinks+=src
- welcome = ticker.mode.uplink_welcome
- uses = ticker.mode.uplink_uses
/obj/item/device/uplink/Destroy()
world_uplinks-=src
@@ -211,7 +209,7 @@ var/list/world_uplinks = list()
/obj/item/device/radio/headset/uplink/New()
..()
hidden_uplink = new(src)
- hidden_uplink.uses = 10
+ hidden_uplink.uses = 20
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index 98040a52653..3deee5d8cdc 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -196,7 +196,7 @@
user << "Sticking a dead brain into the frame would sort of defeat the purpose."
return
- if(M.brainmob.mind in ticker.mode.head_revolutionaries)
+ if((M.brainmob.mind in ticker.mode.head_revolutionaries) || (M.brainmob.mind in ticker.mode.A_bosses) || (M.brainmob.mind in ticker.mode.B_bosses))
user << "The frame's firmware lets out a shrill sound, and flashes 'Abnormal Memory Engram'. It refuses to accept the MMI."
return
@@ -253,6 +253,8 @@
else
user << "The MMI must go in after everything else!"
+ if(istype(W,/obj/item/weapon/pen))
+ user << "You need to use a multitool to name [src]."
return
/obj/item/robot_parts/robot_suit/proc/Interact(mob/user)
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index b203f1f3bdd..17e2190d6f6 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -25,9 +25,7 @@
user << "\The [src] cannot be applied to [M]!"
return 1
- if ( ! (istype(user, /mob/living/carbon/human) || \
- istype(user, /mob/living/silicon) || \
- istype(user, /mob/living/carbon/monkey)) )
+ if(!user.IsAdvancedToolUser())
user << "You don't have the dexterity to do this!"
return 1
diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
index fabece80e32..57d716488b1 100644
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ b/code/game/objects/items/stacks/sheets/glass.dm
@@ -323,7 +323,7 @@
if(G.amount >= G.max_amount)
continue
G.attackby(NG, user)
- user << "You add the newly-formed glass to the stack. It now contains [NG.amount] sheet\s."
+ user << "You add the newly-formed glass to the stack. It now contains [NG.amount] sheet\s."
qdel(src)
..()
diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm
index b6f782ad1fa..069b0cc091a 100644
--- a/code/game/objects/items/stacks/sheets/mineral.dm
+++ b/code/game/objects/items/stacks/sheets/mineral.dm
@@ -34,6 +34,7 @@ Mineral Sheets
var/global/list/datum/stack_recipe/sandstone_recipes = list ( \
new/datum/stack_recipe("pile of dirt", /obj/machinery/hydroponics/soil, 3, time = 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("sandstone door", /obj/structure/mineral_door/sandstone, 10, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("Assistant Statue", /obj/structure/statue/sandstone/assistant, 5, one_per_turf = 1, on_floor = 1), \
/* new/datum/stack_recipe("sandstone wall", ???), \
new/datum/stack_recipe("sandstone floor", ???),\ */
)
@@ -60,6 +61,10 @@ var/global/list/datum/stack_recipe/sandstone_recipes = list ( \
var/global/list/datum/stack_recipe/diamond_recipes = list ( \
new/datum/stack_recipe("diamond door", /obj/structure/mineral_door/transparent/diamond, 10, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("diamond tile", /obj/item/stack/tile/mineral/diamond, 1, 4, 20), \
+ new/datum/stack_recipe("Captain Statue", /obj/structure/statue/diamond/captain, 5, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("AI Hologram Statue", /obj/structure/statue/diamond/ai1, 5, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("AI Core Statue", /obj/structure/statue/diamond/ai2, 5, one_per_turf = 1, on_floor = 1), \
)
/obj/item/stack/sheet/mineral/diamond/New(var/loc, var/amount=null)
@@ -85,6 +90,9 @@ var/global/list/datum/stack_recipe/diamond_recipes = list ( \
var/global/list/datum/stack_recipe/uranium_recipes = list ( \
new/datum/stack_recipe("uranium door", /obj/structure/mineral_door/uranium, 10, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("uranium tile", /obj/item/stack/tile/mineral/uranium, 1, 4, 20), \
+ new/datum/stack_recipe("Nuke Statue", /obj/structure/statue/uranium/nuke, 5, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("Engineer Statue", /obj/structure/statue/uranium/eng, 5, one_per_turf = 1, on_floor = 1), \
)
/obj/item/stack/sheet/mineral/uranium/New(var/loc, var/amount=null)
@@ -110,6 +118,8 @@ var/global/list/datum/stack_recipe/uranium_recipes = list ( \
var/global/list/datum/stack_recipe/plasma_recipes = list ( \
new/datum/stack_recipe("plasma door", /obj/structure/mineral_door/transparent/plasma, 10, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("plasma tile", /obj/item/stack/tile/mineral/plasma, 1, 4, 20), \
+ new/datum/stack_recipe("Scientist Statue", /obj/structure/statue/plasma/scientist, 5, one_per_turf = 1, on_floor = 1), \
)
/obj/item/stack/sheet/mineral/plasma/New(var/loc, var/amount=null)
@@ -135,6 +145,12 @@ var/global/list/datum/stack_recipe/plasma_recipes = list ( \
var/global/list/datum/stack_recipe/gold_recipes = list ( \
new/datum/stack_recipe("golden door", /obj/structure/mineral_door/gold, 10, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("gold tile", /obj/item/stack/tile/mineral/gold, 1, 4, 20), \
+ new/datum/stack_recipe("HoS Statue", /obj/structure/statue/gold/hos, 5, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("HoP Statue", /obj/structure/statue/gold/hop, 5, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("CE Statue", /obj/structure/statue/gold/ce, 5, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("RD Statue", /obj/structure/statue/gold/rd, 5, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("CMO Statue", /obj/structure/statue/gold/cmo, 5, one_per_turf = 1, on_floor = 1), \
)
/obj/item/stack/sheet/mineral/gold/New(var/loc, var/amount=null)
@@ -160,6 +176,12 @@ var/global/list/datum/stack_recipe/gold_recipes = list ( \
var/global/list/datum/stack_recipe/silver_recipes = list ( \
new/datum/stack_recipe("silver door", /obj/structure/mineral_door/silver, 10, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("silver tile", /obj/item/stack/tile/mineral/silver, 1, 4, 20), \
+ new/datum/stack_recipe("Med Officer Statue", /obj/structure/statue/silver/md, 5, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("Janitor Statue", /obj/structure/statue/silver/janitor, 5, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("Sec Officer Statue", /obj/structure/statue/silver/sec, 5, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("Sec Borg Statue", /obj/structure/statue/silver/secborg, 5, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("Med Borg Statue", /obj/structure/statue/silver/medborg, 5, one_per_turf = 1, on_floor = 1), \
)
/obj/item/stack/sheet/mineral/silver/New(var/loc, var/amount=null)
@@ -171,7 +193,7 @@ var/global/list/datum/stack_recipe/silver_recipes = list ( \
/*
* Clown
*/
-/obj/item/stack/sheet/mineral/clown
+/obj/item/stack/sheet/mineral/bananium
name = "bananium"
icon_state = "sheet-clown"
singular_name = "bananium sheet"
@@ -183,7 +205,13 @@ var/global/list/datum/stack_recipe/silver_recipes = list ( \
origin_tech = "materials=4"
sheettype = "clown"
-/obj/item/stack/sheet/mineral/clown/New(var/loc, var/amount=null)
+var/global/list/datum/stack_recipe/clown_recipes = list ( \
+ new/datum/stack_recipe("bananium tile", /obj/item/stack/tile/mineral/bananium, 1, 4, 20), \
+ new/datum/stack_recipe("Clown Statue", /obj/structure/statue/bananium/clown, 5, one_per_turf = 1, on_floor = 1), \
+ )
+
+/obj/item/stack/sheet/mineral/bananium/New(var/loc, var/amount=null)
+ recipes = clown_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index f27f1e696ad..38c95e33cfd 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -29,6 +29,7 @@
return // Not supposed to be destroyed
if (usr && usr.machine==src)
usr << browse(null, "window=stack")
+ src.loc = null
..()
/obj/item/stack/examine(mob/user)
@@ -133,23 +134,32 @@
usr << "Building [R.title] ..."
if (!do_after(usr, R.time))
return
- if (src.get_amount() < R.req_amount*multiplier)
- return
+ if (src.get_amount() < R.req_amount*multiplier)
+ return
+
var/atom/O = new R.result_type( usr.loc )
O.dir = usr.dir
+ use(R.req_amount * multiplier)
+
+ //is it a stack ?
if (R.max_res_amount > 1)
var/obj/item/stack/new_item = O
new_item.amount = R.res_amount*multiplier
- new_item.add_to_stacks(usr)
- use(R.req_amount * multiplier)
+ new_item.add_to_stacks(usr) //try to merge with existing stacks on current tile
+
+ if(new_item.amount <= 0)//if the stack is empty, i.e it has been merged with an existing stack and has been garbage collected
+ return
+
if (istype(O,/obj/item))
usr.put_in_hands(O)
O.add_fingerprint(usr)
+
//BubbleWrap - so newly formed boxes are empty
if ( istype(O, /obj/item/weapon/storage) )
for (var/obj/item/I in O)
qdel(I)
//BubbleWrap END
+
if (src && usr.machine==src) //do not reopen closed window
spawn( 0 )
src.interact(usr)
@@ -186,7 +196,7 @@
continue
oldsrc.attackby(item, usr)
usr << "You add new [item.singular_name] to the stack. It now contains [item.amount] [item.singular_name]\s."
- if(!oldsrc)
+ if(oldsrc.amount <= 0)
break
/obj/item/stack/attack_hand(mob/user as mob)
@@ -204,7 +214,7 @@
return
/obj/item/stack/attackby(obj/item/W as obj, mob/user as mob)
- ..()
+
if (istype(W, src.type))
var/obj/item/stack/S = W
if (S.is_cyborg)
@@ -229,7 +239,9 @@
src.use(to_transfer)
if (src && usr.machine==src)
spawn(0) src.interact(usr)
- else return ..()
+
+ else
+ ..()
/obj/item/stack/proc/copy_evidences(obj/item/stack/from as obj)
src.blood_DNA = from.blood_DNA
diff --git a/code/game/objects/items/stacks/tiles/plasteel.dm b/code/game/objects/items/stacks/tiles/plasteel.dm
index a76a3e35da4..5e922c9a6c5 100644
--- a/code/game/objects/items/stacks/tiles/plasteel.dm
+++ b/code/game/objects/items/stacks/tiles/plasteel.dm
@@ -25,7 +25,7 @@
return
/obj/item/stack/tile/plasteel/attackby(obj/item/W as obj, mob/user as mob)
- ..()
+
if (istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
@@ -45,7 +45,8 @@
if (!R && replace)
user.put_in_hands(new_item)
return
- ..()
+ else
+ ..()
/*
/obj/item/stack/tile/plasteel/attack_self(mob/user as mob)
diff --git a/code/game/objects/items/stacks/tiles/tile_mineral.dm b/code/game/objects/items/stacks/tiles/tile_mineral.dm
new file mode 100644
index 00000000000..05177a54409
--- /dev/null
+++ b/code/game/objects/items/stacks/tiles/tile_mineral.dm
@@ -0,0 +1,78 @@
+/obj/item/stack/tile/mineral/plasma
+ name = "plasma tile"
+ singular_name = "plasma floor tile"
+ desc = "A tile made out of highly flammable plasma. This can only end well."
+ icon_state = "tile_plasma"
+ w_class = 3.0
+ force = 1.0
+ throwforce = 1.0
+ throw_speed = 3
+ throw_range = 7
+ max_amount = 60
+ origin_tech = "plasma=1"
+
+/obj/item/stack/tile/mineral/uranium
+ name = "uranium tile"
+ singular_name = "uranium floor tile"
+ desc = "A tile made out of uranium. You feel a bit woozy."
+ icon_state = "tile_uranium"
+ w_class = 3.0
+ force = 1.0
+ throwforce = 1.0
+ throw_speed = 3
+ throw_range = 7
+ max_amount = 60
+ origin_tech = "material=1"
+
+/obj/item/stack/tile/mineral/gold
+ name = "gold tile"
+ singular_name = "gold floor tile"
+ desc = "A tile made out of gold, the swag seems strong here."
+ icon_state = "tile_gold"
+ w_class = 3.0
+ force = 1.0
+ throwforce = 1.0
+ throw_speed = 3
+ throw_range = 7
+ max_amount = 60
+ origin_tech = "material=1"
+
+/obj/item/stack/tile/mineral/silver
+ name = "silver tile"
+ singular_name = "silver floor tile"
+ desc = "A tile made out of silver, the light shining from it is blinding."
+ icon_state = "tile_silver"
+ w_class = 3.0
+ force = 1.0
+ throwforce = 1.0
+ throw_speed = 3
+ throw_range = 7
+ max_amount = 60
+ origin_tech = "material=1"
+
+/obj/item/stack/tile/mineral/diamond
+ name = "diamond tile"
+ singular_name = "diamond floor tile"
+ desc = "A tile made out of diamond. Wow, just, wow."
+ icon_state = "tile_diamond"
+ w_class = 3.0
+ force = 1.0
+ throwforce = 1.0
+ throw_speed = 3
+ throw_range = 7
+ max_amount = 60
+ origin_tech = "material=2"
+
+/obj/item/stack/tile/mineral/bananium
+ name = "bananium tile"
+ singular_name = "bananium floor tile"
+ desc = "A tile made out of bananium, HOOOOOOOOONK!"
+ icon_state = "tile_bananium"
+ w_class = 3.0
+ force = 1.0
+ throwforce = 1.0
+ throw_speed = 3
+ throw_range = 7
+ max_amount = 60
+ origin_tech = "material=1"
+
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 020de3650ce..df72dcfe7fd 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -149,7 +149,7 @@
/obj/item/toy/gun/afterattack(atom/target as mob|obj|turf|area, mob/user as mob, flag)
if (flag)
return
- if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
+ if(!user.IsAdvancedToolUser())
usr << "You don't have the dexterity to do this!"
return
src.add_fingerprint(user)
diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm
index 23243aef5cd..a848cb4dc3f 100644
--- a/code/game/objects/items/weapons/cigs_lighters.dm
+++ b/code/game/objects/items/weapons/cigs_lighters.dm
@@ -269,6 +269,12 @@ CIGARETTE PACKETS ARE IN FANCY.DM
src.pixel_x = rand(-5.0, 5)
src.pixel_y = rand(-5.0, 5)
+/obj/item/clothing/mask/cigarette/rollie/trippy/New()
+ ..()
+ reagents.add_reagent("mushroomhallucinogen", 50)
+ light()
+ //for(var/mob/M in player_list) M << 'sound/misc/Smoke_Weed_Everyday.ogg'
+
/obj/item/weapon/cigbutt/roach
name = "roach"
diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm
index 74e2371756d..48bdca424f6 100644
--- a/code/game/objects/items/weapons/dna_injector.dm
+++ b/code/game/objects/items/weapons/dna_injector.dm
@@ -42,7 +42,7 @@
return
/obj/item/weapon/dnainjector/attack(mob/target, mob/user)
- if(!ishuman(user))
+ if(!user.IsAdvancedToolUser())
user << "You don't have the dexterity to do this!"
return
add_logs(user, target, "attempted to inject", object="[name]")
diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm
index 0059be158c8..6d7cb64a37f 100644
--- a/code/game/objects/items/weapons/explosives.dm
+++ b/code/game/objects/items/weapons/explosives.dm
@@ -1,7 +1,7 @@
-//In this file: Plastic explosives (C4) and Syndicate Bombs
+//In this file: C4 and Syndicate Bombs
-/obj/item/weapon/plastique
- name = "plastic explosives"
+/obj/item/weapon/c4
+ name = "C-4"
desc = "Used to put holes in specific areas without too much extra hole."
gender = PLURAL
icon = 'icons/obj/assemblies.dmi'
@@ -10,20 +10,20 @@
flags = NOBLUDGEON
w_class = 2.0
origin_tech = "syndicate=2"
- var/datum/wires/explosive/plastic/wires = null
+ var/datum/wires/explosive/c4/wires = null
var/timer = 10
var/atom/target = null
var/open_panel = 0
var/image_overlay = null
-/obj/item/weapon/plastique/New()
+/obj/item/weapon/c4/New()
wires = new(src)
image_overlay = image('icons/obj/assemblies.dmi', "plastic-explosive2")
..()
-/obj/item/weapon/plastique/suicide_act(var/mob/user)
+/obj/item/weapon/c4/suicide_act(var/mob/user)
. = BRUTELOSS
- user.visible_message("[user] activates the C4 and holds it above his head! It looks like \he's going out with a bang!")
+ user.visible_message("[user] activates the [src.name] and holds it above his head! It looks like \he's going out with a bang!")
var/message_say = "FOR NO RAISIN!"
if(user.mind)
if(user.mind.special_role)
@@ -36,11 +36,11 @@
message_say = "FOR NARSIE!"
user.say(message_say)
target = user
- message_admins("[key_name(user, user.client)](?) suicided with C4 at ([x],[y],[z] - JMP)",0,1)
+ message_admins("[key_name(user, user.client)](?) suicided with [src.name] at ([x],[y],[z] - JMP)",0,1)
explode(get_turf(user))
return .
-/obj/item/weapon/plastique/attackby(var/obj/item/I, var/mob/user)
+/obj/item/weapon/c4/attackby(var/obj/item/I, var/mob/user)
if(istype(I, /obj/item/weapon/screwdriver))
open_panel = !open_panel
user << "You [open_panel ? "open" : "close"] the wire panel."
@@ -49,14 +49,14 @@
else
..()
-/obj/item/weapon/plastique/attack_self(mob/user as mob)
+/obj/item/weapon/c4/attack_self(mob/user as mob)
var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num
if(user.get_active_hand() == src)
newtime = Clamp(newtime, 10, 60000)
timer = newtime
user << "Timer set for [timer] seconds."
-/obj/item/weapon/plastique/afterattack(atom/movable/target, mob/user, flag)
+/obj/item/weapon/c4/afterattack(atom/movable/target, mob/user, flag)
if (!flag)
return
if (ismob(target) || istype(target, /turf/unsimulated) || istype(target, /turf/simulated/shuttle) || istype(target, /obj/item/weapon/storage/))
@@ -71,19 +71,19 @@
if (ismob(target))
add_logs(user, target, "planted [name] on")
user.visible_message("[user.name] finished planting an explosive on [target.name]!")
- message_admins("[key_name(user, user.client)](?) planted C4 on [key_name(target)](?) with [timer] second fuse",0,1)
- log_game("[key_name(user)] planted C4 on [key_name(target)] with [timer] second fuse")
+ message_admins("[key_name(user, user.client)](?) planted [src.name] on [key_name(target)](?) with [timer] second fuse",0,1)
+ log_game("[key_name(user)] planted [src.name] on [key_name(target)] with [timer] second fuse")
else
- message_admins("[key_name(user, user.client)](?) planted C4 on [target.name] at ([target.x],[target.y],[target.z] - JMP) with [timer] second fuse",0,1)
- log_game("[key_name(user)] planted C4 on [target.name] at ([target.x],[target.y],[target.z]) with [timer] second fuse")
+ message_admins("[key_name(user, user.client)](?) planted [src.name] on [target.name] at ([target.x],[target.y],[target.z] - JMP) with [timer] second fuse",0,1)
+ log_game("[key_name(user)] planted [src.name] on [target.name] at ([target.x],[target.y],[target.z]) with [timer] second fuse")
target.overlays += image_overlay
user << "Bomb has been planted. Timer counting down from [timer]."
spawn(timer*10)
explode(get_turf(target))
-/obj/item/weapon/plastique/proc/explode(var/location)
+/obj/item/weapon/c4/proc/explode(var/location)
if(!target)
target = get_atom_on_turf(src)
if(!target)
@@ -101,5 +101,5 @@
target.overlays -= image_overlay
qdel(src)
-/obj/item/weapon/plastique/attack(mob/M as mob, mob/user as mob, def_zone)
+/obj/item/weapon/c4/attack(mob/M as mob, mob/user as mob, def_zone)
return
diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm
index 3c4c39a7825..b6201fbefba 100644
--- a/code/game/objects/items/weapons/extinguisher.dm
+++ b/code/game/objects/items/weapons/extinguisher.dm
@@ -19,7 +19,7 @@
var/sprite_name = "fire_extinguisher"
/obj/item/weapon/extinguisher/mini
- name = "fire extinguisher"
+ name = "pocket fire extinguisher"
desc = "A light and compact fibreglass-framed model fire extinguisher."
icon_state = "miniFE0"
item_state = "miniFE"
diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm
index dc4e9729489..2078dfc93bf 100644
--- a/code/game/objects/items/weapons/grenades/chem_grenade.dm
+++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm
@@ -153,12 +153,6 @@
if(nadeassembly)
nadeassembly.on_found(finder)
-/obj/item/weapon/grenade/chem_grenade/hear_talk(mob/living/M, msg)
- if(nadeassembly)
- nadeassembly.hear_talk(M, msg)
-
-
-
/obj/item/weapon/grenade/chem_grenade/prime()
if(stage != READY)
return
diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm
index ff92bf3ab64..4d74030235a 100644
--- a/code/game/objects/items/weapons/grenades/flashbang.dm
+++ b/code/game/objects/items/weapons/grenades/flashbang.dm
@@ -8,21 +8,17 @@
/obj/item/weapon/grenade/flashbang/prime()
update_mob()
var/flashbang_turf = get_turf(src)
- for(var/obj/structure/closet/L in view(7, flashbang_turf))
- for(var/mob/living/M in L)
- bang(get_turf(M), M)
-
- for(var/mob/living/M in view(7, flashbang_turf))
+ for(var/mob/living/M in get_hearers_in_view(7, flashbang_turf))
bang(get_turf(M), M)
- for(var/obj/effect/blob/B in view(8,flashbang_turf)) //Blob damage here
+ for(var/obj/effect/blob/B in get_hear(8,flashbang_turf)) //Blob damage here
var/damage = round(30/(get_dist(B,get_turf(src))+1))
B.health -= damage
B.update_icon()
qdel(src)
/obj/item/weapon/grenade/flashbang/proc/bang(var/turf/T , var/mob/living/M)
- M << "BANG"
+ M.show_message("BANG", 2)
playsound(src.loc, 'sound/effects/bang.ogg', 25, 1)
//Checking for protections
@@ -141,4 +137,4 @@
walk_away(src,temploc,stepdist)
var/dettime = rand(15,60)
spawn(dettime)
- prime()
\ No newline at end of file
+ prime()
diff --git a/code/game/objects/items/weapons/implants/implantuplink.dm b/code/game/objects/items/weapons/implants/implantuplink.dm
index 394c736c3cc..e3cae95152e 100644
--- a/code/game/objects/items/weapons/implants/implantuplink.dm
+++ b/code/game/objects/items/weapons/implants/implantuplink.dm
@@ -6,7 +6,7 @@
/obj/item/weapon/implant/uplink/New()
activation_emote = pick("blink", "blink_r", "eyebrow", "chuckle", "twitch_s", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink")
hidden_uplink = new(src)
- hidden_uplink.uses = 5
+ hidden_uplink.uses = 10
..()
return
diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm
index 2cf82cb10eb..d82736e7200 100644
--- a/code/game/objects/items/weapons/manuals.dm
+++ b/code/game/objects/items/weapons/manuals.dm
@@ -665,7 +665,7 @@
Try to get a fingerprint card of your perp, as if used in the computer, the prints will be completed on their dossier.
Assuming you have enough of a print to see it, grab the biggest complete piece of the print and search the security records for it.
Since you now have both your dossier and the name of the person, print both out as evidence, and get security to nab your baddie.
-
Give yourself a pat on the back and a bottle of the ships finest vodka, you did it!.
+
Give yourself a pat on the back and a bottle of the ships finest vodka, you did it!
It really is that easy! Good luck!
diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm
index bce56df922d..776dca795a5 100644
--- a/code/game/objects/items/weapons/storage/backpack.dm
+++ b/code/game/objects/items/weapons/storage/backpack.dm
@@ -14,7 +14,7 @@
desc = "You wear this on your back and put items into it."
icon_state = "backpack"
item_state = "backpack"
- w_class = 4.0
+ w_class = 4
slot_flags = SLOT_BACK //ERROOOOO
max_w_class = 3
max_combined_w_class = 21
@@ -35,10 +35,6 @@
max_w_class = 5
max_combined_w_class = 35
-/obj/item/weapon/storage/backpack/holding/New()
- ..()
- return
-
/obj/item/weapon/storage/backpack/holding/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(crit_fail)
user << "The Bluespace generator isn't working."
@@ -73,9 +69,9 @@
icon_state = "giftbag0"
item_state = "giftbag"
w_class = 4.0
- storage_slots = 20
+ storage_slots = 20 //Can store a lot.
max_w_class = 3
- max_combined_w_class = 400 // can store a ton of shit!
+ max_combined_w_class = 60
/obj/item/weapon/storage/backpack/cultpack
name = "trophy rack"
@@ -89,6 +85,12 @@
icon_state = "clownpack"
item_state = "clownpack"
+/obj/item/weapon/storage/backpack/mime
+ name = "Parcel Parceaux"
+ desc = "A silent backpack made for those silent workers. Silence Co."
+ icon_state = "mimepack"
+ item_state = "mimepack"
+
/obj/item/weapon/storage/backpack/medic
name = "medical backpack"
desc = "It's a backpack especially designed for use in a sterile environment."
@@ -122,10 +124,9 @@
desc = "It's a very fancy satchel made with fine leather."
icon_state = "satchel"
-/obj/item/weapon/storage/backpack/satchel/withwallet
- New()
- ..()
- new /obj/item/weapon/storage/wallet/random( src )
+/obj/item/weapon/storage/backpack/satchel/withwallet/New()
+ ..()
+ new /obj/item/weapon/storage/wallet/random( src )
/obj/item/weapon/storage/backpack/satchel_norm
name = "satchel"
@@ -181,8 +182,27 @@
icon_state = "satchel-cap"
item_state = "captainpack"
-/obj/item/weapon/storage/backpack/mime
- name = "Parcel Parceaux"
- desc = "A silent backpack made for those silent workers. Silence Co."
- icon_state = "mimepack"
- item_state = "mimepack"
\ No newline at end of file
+/obj/item/weapon/storage/backpack/satchel_flat
+ name = "smuggler's satchel"
+ desc = "A very slim satchel that can easily fit into tight spaces."
+ icon_state = "satchel-flat"
+ w_class = 3 //Can fit in backpacks itself.
+ storage_slots = 5
+ max_combined_w_class = 15
+ level = 1
+ cant_hold = list(/obj/item/weapon/storage/backpack/satchel_flat) //muh recursive backpacks
+
+/obj/item/weapon/storage/backpack/satchel_flat/hide(var/intact)
+ if(intact)
+ invisibility = 101
+ anchored = 1 //otherwise you can start pulling, cover it, and drag around an invisible backpack.
+ icon_state = "[initial(icon_state)]2"
+ else
+ invisibility = initial(invisibility)
+ anchored = 0
+ icon_state = initial(icon_state)
+
+/obj/item/weapon/storage/backpack/satchel_flat/New()
+ ..()
+ new /obj/item/stack/tile/plasteel(src)
+ new /obj/item/weapon/crowbar(src)
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index 8176a178ea0..716958d35f6 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -50,8 +50,9 @@
/obj/item/device/flashlight,
/obj/item/stack/cable_coil,
/obj/item/device/t_scanner,
- /obj/item/device/analyzer)
-
+ /obj/item/device/analyzer,
+ /obj/item/weapon/extinguisher/mini
+ )
/obj/item/weapon/storage/belt/utility/full/New()
..()
@@ -71,6 +72,7 @@
new /obj/item/weapon/crowbar(src)
new /obj/item/weapon/wirecutters(src)
new /obj/item/device/t_scanner(src)
+ new /obj/item/weapon/extinguisher/mini(src)
@@ -91,8 +93,9 @@
/obj/item/weapon/storage/fancy/cigarettes,
/obj/item/weapon/storage/pill_bottle,
/obj/item/stack/medical,
- /obj/item/device/flashlight/pen
- )
+ /obj/item/device/flashlight/pen,
+ /obj/item/weapon/extinguisher/mini
+ )
/obj/item/weapon/storage/belt/security
diff --git a/code/game/objects/items/weapons/storage/book.dm b/code/game/objects/items/weapons/storage/book.dm
index 3becca92514..59f2a0f6589 100644
--- a/code/game/objects/items/weapons/storage/book.dm
+++ b/code/game/objects/items/weapons/storage/book.dm
@@ -52,7 +52,7 @@
add_logs(user, M, "attacked", object="[src.name]")
- if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
+ if (!user.IsAdvancedToolUser())
user << "You don't have the dexterity to do this!"
return
if(!chaplain)
@@ -127,7 +127,7 @@
user << " You purify [A]."
var/unholy2clean = A.reagents.get_reagent_amount("unholywater")
A.reagents.del_reagent("unholywater")
- A.reagents.add_reagent("cleaner",unholy2clean) //it cleans their soul, get it? I'll get my coat...
+ A.reagents.add_reagent("holywater",unholy2clean)
/obj/item/weapon/storage/book/bible/attackby(obj/item/weapon/W as obj, mob/user as mob)
playsound(src.loc, "rustle", 50, 1, -5)
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index 4507b1e0bb5..b85693e867f 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -33,6 +33,7 @@
if(!foldable)
return
if(contents.len)
+ user << "You can't fold this box with items still inside."
return
if(!ispath(foldable))
return
@@ -537,4 +538,4 @@
new /obj/item/clothing/tie/armband/deputy(src)
new /obj/item/clothing/tie/armband/deputy(src)
new /obj/item/clothing/tie/armband/deputy(src)
- new /obj/item/clothing/tie/armband/deputy(src)
+ new /obj/item/clothing/tie/armband/deputy(src)
diff --git a/code/game/objects/items/weapons/storage/briefcase.dm b/code/game/objects/items/weapons/storage/briefcase.dm
index 94ce4c9fb7b..93a6fdc2679 100644
--- a/code/game/objects/items/weapons/storage/briefcase.dm
+++ b/code/game/objects/items/weapons/storage/briefcase.dm
@@ -4,11 +4,13 @@
icon_state = "briefcase"
flags = CONDUCT
force = 8.0
+ hitsound = "swing_hit"
throw_speed = 2
throw_range = 4
w_class = 4.0
max_w_class = 3
max_combined_w_class = 21
+ attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked")
/obj/item/weapon/storage/briefcase/New()
..()
diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm
index 32ff2abea71..1e0414ff121 100644
--- a/code/game/objects/items/weapons/storage/fancy.dm
+++ b/code/game/objects/items/weapons/storage/fancy.dm
@@ -148,7 +148,7 @@
throwforce = 0
slot_flags = SLOT_BELT
storage_slots = 6
- can_hold = list(/obj/item/clothing/mask/cigarette)
+ can_hold = list(/obj/item/clothing/mask/cigarette,/obj/item/weapon/lighter)
icon_type = "cigarette"
/obj/item/weapon/storage/fancy/cigarettes/New()
@@ -163,24 +163,26 @@
desc = "There are [contents.len] cig\s left!"
return
-/obj/item/weapon/storage/fancy/cigarettes/remove_from_storage(obj/item/W as obj, atom/new_location)
- var/obj/item/clothing/mask/cigarette/C = W
- if(!istype(C)) return // what
- reagents.trans_to(C, (reagents.total_volume/contents.len))
- ..()
+/obj/item/weapon/storage/fancy/cigarettes/remove_from_storage(obj/item/W, atom/new_location)
+ if(istype(W,/obj/item/clothing/mask/cigarette))
+ reagents.trans_to(W,(reagents.total_volume/contents.len))
+ ..()
/obj/item/weapon/storage/fancy/cigarettes/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
if(!istype(M, /mob))
return
-
- if(M == user && user.zone_sel.selecting == "mouth" && contents.len > 0 && !user.wear_mask)
- var/obj/item/clothing/mask/cigarette/W = contents[1]
- remove_from_storage(W, M)
- M.equip_to_slot_if_possible(W, slot_wear_mask)
- contents -= W
- user << "You take a cigarette out of the pack."
+ var/obj/item/clothing/mask/cigarette/cig = locate(/obj/item/clothing/mask/cigarette) in contents
+ if(cig)
+ if(M == user && user.zone_sel.selecting == "mouth" && contents.len > 0 && !user.wear_mask)
+ var/obj/item/clothing/mask/cigarette/W = cig
+ remove_from_storage(W, M)
+ M.equip_to_slot_if_possible(W, slot_wear_mask)
+ contents -= W
+ user << "You take a cigarette out of the pack."
+ else
+ ..()
else
- ..()
+ user << "There are no cigarettes left in the pack."
/obj/item/weapon/storage/fancy/cigarettes/dromedaryco
name = "\improper DromedaryCo packet"
diff --git a/code/game/objects/items/weapons/storage/secure.dm b/code/game/objects/items/weapons/storage/secure.dm
index 98835caaf70..fee8cb5347a 100644
--- a/code/game/objects/items/weapons/storage/secure.dm
+++ b/code/game/objects/items/weapons/storage/secure.dm
@@ -152,11 +152,13 @@
item_state = "sec-case"
desc = "A large briefcase with a digital locking system."
force = 8.0
+ hitsound = "swing_hit"
throw_speed = 2
throw_range = 4
w_class = 4.0
max_w_class = 3
max_combined_w_class = 21
+ attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked")
/obj/item/weapon/storage/secure/briefcase/New()
..()
diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm
index bc1466f3ba2..a12ce7377d2 100644
--- a/code/game/objects/items/weapons/storage/storage.dm
+++ b/code/game/objects/items/weapons/storage/storage.dm
@@ -25,7 +25,7 @@
/obj/item/weapon/storage/MouseDrop(obj/over_object)
- if(iscarbon(usr)) //all the check for item manipulation are in other places, you can safely open any storages as anything and its not buggy, i checked
+ if(iscarbon(usr) || isdrone(usr)) //all the check for item manipulation are in other places, you can safely open any storages as anything and its not buggy, i checked
var/mob/M = usr
if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech
@@ -68,7 +68,7 @@
/obj/item/weapon/storage/proc/show_to(mob/user)
- if(user.s_active != src)
+ if(user.s_active != src && (user.stat == CONSCIOUS))
for(var/obj/item/I in src)
if(I.on_found(user))
return
diff --git a/code/game/objects/items/weapons/storage/toolbox.dm b/code/game/objects/items/weapons/storage/toolbox.dm
index f67e07c11b8..b894effd228 100644
--- a/code/game/objects/items/weapons/storage/toolbox.dm
+++ b/code/game/objects/items/weapons/storage/toolbox.dm
@@ -83,3 +83,18 @@
new /obj/item/stack/cable_coil(src,30,color)
new /obj/item/weapon/wirecutters(src)
new /obj/item/device/multitool(src)
+
+/obj/item/weapon/storage/toolbox/drone
+ name = "mechanical toolbox"
+ icon_state = "blue"
+ item_state = "toolbox_blue"
+
+/obj/item/weapon/storage/toolbox/drone/New()
+ ..()
+ new /obj/item/weapon/screwdriver(src)
+ new /obj/item/weapon/wrench(src)
+ new /obj/item/weapon/weldingtool(src)
+ new /obj/item/weapon/crowbar(src)
+ new /obj/item/stack/cable_coil(src,30,color)
+ new /obj/item/weapon/wirecutters(src)
+ new /obj/item/device/multitool(src)
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index b8664ed01e6..68b62e95706 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -7,7 +7,9 @@
new /obj/item/clothing/under/chameleon(src)
new /obj/item/clothing/mask/gas/voice(src)
new /obj/item/weapon/card/id/syndicate(src)
+ new /obj/item/weapon/card/id/syndicate(src)
new /obj/item/clothing/shoes/syndigaloshes(src)
+ new /obj/item/device/camera_bug(src)
return
if("stealth")
@@ -22,6 +24,7 @@
new /obj/item/ammo_box/magazine/m10mm(src)
new /obj/item/ammo_box/magazine/m10mm(src)
new /obj/item/clothing/under/chameleon(src)
+ new /obj/item/weapon/card/id/syndicate(src)
return
if("screwed")
@@ -36,7 +39,7 @@
new /obj/item/weapon/gun/projectile/revolver(src)
new /obj/item/ammo_box/a357(src)
new /obj/item/weapon/card/emag(src)
- new /obj/item/weapon/plastique(src)
+ new /obj/item/weapon/c4(src)
return
if("murder")
diff --git a/code/game/objects/items/weapons/table_rack_parts.dm b/code/game/objects/items/weapons/table_rack_parts.dm
index d8cbe11c631..ecea8326990 100644
--- a/code/game/objects/items/weapons/table_rack_parts.dm
+++ b/code/game/objects/items/weapons/table_rack_parts.dm
@@ -17,7 +17,7 @@
new /obj/item/stack/sheet/metal( user.loc )
//SN src = null
qdel(src)
- if (istype(W, /obj/item/stack/rods))
+ if (istype(W, /obj/item/stack/rods))
var/obj/item/stack/rods/V = W
if (V.use(4))
new /obj/item/weapon/table_parts/reinforced( user.loc )
@@ -25,12 +25,13 @@
qdel(src)
else
user << "You need four rods to reinforce table parts."
- return
+ return
/obj/item/weapon/table_parts/attack_self(mob/user as mob)
user << "Constructing table.."
if (do_after(user, construct_delay))
- new table_type( user.loc )
+ var/obj/new_table = new table_type( user.loc )
+ new_table.add_fingerprint(user)
user.drop_item()
qdel(src)
return
@@ -93,4 +94,4 @@
R.add_fingerprint(user)
user.drop_item()
qdel(src)
- return
+ return
diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm
index 62f7a68cbb8..be5bc7c9402 100644
--- a/code/game/objects/items/weapons/teleportation.dm
+++ b/code/game/objects/items/weapons/teleportation.dm
@@ -162,8 +162,7 @@ Frequency:
user.show_message("\The [src] is recharging!")
return
var/T = L[t1]
- for(var/mob/O in hearers(user, null))
- O.show_message("Locked In.", 2)
+ user.show_message("Locked In.", 2)
var/obj/effect/portal/P = new /obj/effect/portal(get_turf(src), T, src)
try_move_adjacent(P)
active_portals++
diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm
index f25a1bd8705..e4bdb4cd5f2 100644
--- a/code/game/objects/items/weapons/tools.dm
+++ b/code/game/objects/items/weapons/tools.dm
@@ -175,7 +175,6 @@
item_heal_robotic(H, user, 30, 0)
return
else
- user << "Need more welding fuel!"
return
else
return ..()
@@ -418,16 +417,16 @@
*/
/obj/item/weapon/crowbar
- name = "crowbar"
- desc = "Used to hit floors"
+ 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/items.dmi'
icon_state = "crowbar"
flags = CONDUCT
slot_flags = SLOT_BELT
- force = 5.0
- throwforce = 7.0
+ force = 5
+ throwforce = 7
item_state = "crowbar"
- w_class = 2.0
+ w_class = 2
m_amt = 50
origin_tech = "engineering=1"
attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked")
@@ -436,3 +435,13 @@
icon = 'icons/obj/items.dmi'
icon_state = "red_crowbar"
item_state = "crowbar_red"
+
+/obj/item/weapon/crowbar/large
+ name = "crowbar"
+ desc = "It's a big crowbar. It doesn't fit in your pockets, because it's big."
+ force = 12
+ w_class = 3
+ throw_speed = 3
+ throw_range = 3
+ m_amt = 66
+ icon_state = "crowbar_large"
diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm
index 3edaf0d1358..1891f5bd801 100644
--- a/code/game/objects/items/weapons/weaponry.dm
+++ b/code/game/objects/items/weapons/weaponry.dm
@@ -85,6 +85,9 @@
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
+/obj/item/weapon/katana/cursed
+ slot_flags = null
+
/obj/item/weapon/katana/suicide_act(mob/user)
user.visible_message("[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.")
return(BRUTELOSS)
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index dac4c8ba93b..f45a8b5766f 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -1,4 +1,5 @@
/obj
+ languages = HUMAN
//var/datum/module/mod //not used
var/m_amt = 0 // metal
var/g_amt = 0 // glass
@@ -126,18 +127,6 @@
/obj/proc/hide(h)
return
-
-/obj/proc/hear_talk(mob/M as mob, text)
-/*
- var/mob/mo = locate(/mob) in src
- if(mo)
- var/rendered = "[M.name]: [text]"
- mo.show_message(rendered, 2)
- */
- return
-
-
-
//If a mob logouts/logins in side of an object you can use this proc
/obj/proc/on_log()
..()
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index 8952a88a1b5..54d65faa2b2 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -15,4 +15,9 @@ obj/structure/ex_act(severity)
qdel(src)
return
if(3.0)
- return
\ No newline at end of file
+ return
+
+obj/structure/Destroy()
+ if(opacity)
+ UpdateAffectingLights()
+ ..()
\ No newline at end of file
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 1ce6e22f988..5da6def05ae 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -180,11 +180,11 @@
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
user << "You begin cutting the [src] apart..."
- playsound(loc, 'sound/items/Welder2.ogg', 40, 1)
+ playsound(loc, 'sound/items/Welder.ogg', 40, 1)
if(do_after(user,40,5,1))
if(src.opened)
if(WT.remove_fuel(0,user))
- playsound(loc, 'sound/items/welder.ogg', 50, 1)
+ playsound(loc, 'sound/items/Welder2.ogg', 50, 1)
new /obj/item/stack/sheet/metal(src.loc)
for(var/mob/M in viewers(src))
M.show_message("\The [src] has been cut apart by [user] with \the [WT].", 3, "You hear welding.", 2)
@@ -249,8 +249,8 @@
user << "It won't budge!"
if(!lastbang)
lastbang = 1
- for (var/mob/M in hearers(src, null))
- M << text("BANG, bang!", max(0, 5 - get_dist(src, M)))
+ for (var/mob/M in get_hearers_in_view(src, null))
+ M.show_message("BANG, bang!", 2)
spawn(30)
lastbang = 0
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
index 30c0268575f..5b25d80bc0e 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
@@ -95,8 +95,8 @@
user << "The locker is locked!"
if(world.time > lastbang+5)
lastbang = world.time
- for(var/mob/M in hearers(src, null))
- M << "BANG, bang!"
+ for(var/mob/M in get_hearers_in_view(src, null))
+ M.show_message("BANG, bang!", 2)
return
/obj/structure/closet/secure_closet/attack_hand(mob/user as mob)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index a1e7aacfcc1..2cf32731138 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -293,18 +293,3 @@
else
icon_state = icon_opened
-
- /obj/structure/closet/secure_closet/ammunitionlocker
- name = "ammunition locker"
- req_access = list(access_armory)
-
-/obj/structure/closet/secure_closet/ammunitionlocker/New()
- new /obj/item/ammo_casing/shotgun/beanbag(src)
- new /obj/item/ammo_casing/shotgun/beanbag(src)
- new /obj/item/ammo_casing/shotgun/beanbag(src)
- new /obj/item/ammo_casing/shotgun/beanbag(src)
- new /obj/item/ammo_casing/shotgun/beanbag(src)
- new /obj/item/ammo_casing/shotgun/beanbag(src)
- new /obj/item/ammo_casing/shotgun/beanbag(src)
- new /obj/item/ammo_casing/shotgun/beanbag(src)
-
diff --git a/code/game/objects/structures/crates_lockers/closets/syndicate.dm b/code/game/objects/structures/crates_lockers/closets/syndicate.dm
index d0aed1ca894..6029b0821af 100644
--- a/code/game/objects/structures/crates_lockers/closets/syndicate.dm
+++ b/code/game/objects/structures/crates_lockers/closets/syndicate.dm
@@ -7,7 +7,7 @@
/obj/structure/closet/syndicate/personal
- desc = "It's a storage unit for operative gear."
+ desc = "It's a personal storage unit for operative gear."
/obj/structure/closet/syndicate/personal/New()
..()
@@ -24,7 +24,7 @@
/obj/structure/closet/syndicate/nuclear
- desc = "It's a storage unit for nuclear-operative gear."
+ desc = "It's a storage unit for a Syndicate boarding party."
/obj/structure/closet/syndicate/nuclear/New()
..()
@@ -37,11 +37,11 @@
new /obj/item/weapon/storage/box/handcuffs(src)
new /obj/item/weapon/storage/box/flashbangs(src)
new /obj/item/weapon/storage/box/teargas(src)
- new /obj/item/weapon/gun/energy/gun(src)
- new /obj/item/weapon/gun/energy/gun(src)
- new /obj/item/weapon/gun/energy/gun(src)
- new /obj/item/weapon/gun/energy/gun(src)
- new /obj/item/weapon/gun/energy/gun(src)
+ new /obj/item/weapon/gun/projectile/automatic/bulldog(src)
+ new /obj/item/weapon/gun/projectile/automatic/bulldog(src)
+ new /obj/item/weapon/gun/projectile/automatic/bulldog(src)
+ new /obj/item/weapon/gun/projectile/automatic/bulldog(src)
+ new /obj/item/weapon/gun/projectile/automatic/bulldog(src)
new /obj/item/weapon/pinpointer/nukeop(src)
new /obj/item/weapon/pinpointer/nukeop(src)
new /obj/item/weapon/pinpointer/nukeop(src)
@@ -121,7 +121,7 @@
/obj/item/stack/sheet/mineral/plasma,
/obj/item/stack/sheet/mineral/uranium,
/obj/item/stack/sheet/mineral/diamond,
- /obj/item/stack/sheet/mineral/clown,
+ /obj/item/stack/sheet/mineral/bananium,
/obj/item/stack/sheet/plasteel,
/obj/item/stack/rods
)
diff --git a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm
index d9f4944a19b..abf7b810513 100644
--- a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm
@@ -217,4 +217,22 @@
if(!opened)
icon_state = icon_closed
else
- icon_state = icon_opened
\ No newline at end of file
+ icon_state = icon_opened
+
+/*
+ * Ammunition
+ */
+/obj/structure/closet/ammunitionlocker
+ name = "ammunition locker"
+
+/obj/structure/closet/ammunitionlocker/New()
+ ..()
+ new /obj/item/ammo_casing/shotgun/beanbag(src)
+ new /obj/item/ammo_casing/shotgun/beanbag(src)
+ new /obj/item/ammo_casing/shotgun/beanbag(src)
+ new /obj/item/ammo_casing/shotgun/beanbag(src)
+ new /obj/item/ammo_casing/shotgun/beanbag(src)
+ new /obj/item/ammo_casing/shotgun/beanbag(src)
+ new /obj/item/ammo_casing/shotgun/beanbag(src)
+ new /obj/item/ammo_casing/shotgun/beanbag(src)
+
diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm
index bdef9f967bf..ab62e1ee84a 100644
--- a/code/game/objects/structures/door_assembly.dm
+++ b/code/game/objects/structures/door_assembly.dm
@@ -142,8 +142,10 @@ obj/structure/door_assembly/New()
/obj/structure/door_assembly/door_assembly_med
name = "medical airlock assembly"
icon_state = "door_as_med1"
+ glass_base_icon_state = "door_as_gmed"
typetext = "medical"
icontext = "med"
+ glass_type = /obj/machinery/door/airlock/glass_medical
airlock_type = /obj/machinery/door/airlock/medical
anchored = 1
density = 1
@@ -315,6 +317,22 @@ obj/structure/door_assembly/New()
state = 1
mineral = "wood"
+/obj/structure/door_assembly/door_assembly_viro
+ name = "virology airlock assembly"
+ icon_state = "door_as_viro1"
+ glass_base_icon_state = "door_as_gviro"
+ typetext = "virology"
+ icontext = "viro"
+ glass_type = /obj/machinery/door/airlock/glass_virology
+ airlock_type = /obj/machinery/door/airlock/virology
+ anchored = 1
+ density = 1
+ state = 1
+
+/obj/structure/door_assembly/door_assembly_viro/glass
+ mineral = "glass"
+ icon_state = "door_as_gviro1"
+
/obj/structure/door_assembly/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W, /obj/item/weapon/pen))
var/t = copytext(stripped_input(user, "Enter the name for the door.", src.name, src.created_name),1,MAX_NAME_LEN)
@@ -439,7 +457,6 @@ obj/structure/door_assembly/New()
new M(get_turf(src))
qdel(src)
else
- user << " You need more welding fuel to dissassemble the airlock assembly."
return
else if(istype(W, /obj/item/weapon/wrench) && !anchored )
diff --git a/code/game/objects/structures/electricchair.dm b/code/game/objects/structures/electricchair.dm
index 1a0c2441907..c35f898f96e 100644
--- a/code/game/objects/structures/electricchair.dm
+++ b/code/game/objects/structures/electricchair.dm
@@ -2,7 +2,6 @@
name = "electric chair"
desc = "Looks absolutely SHOCKING!"
icon_state = "echair0"
- var/on = 0
var/obj/item/assembly/shock_kit/part = null
var/last_time = 1.0
@@ -23,20 +22,6 @@
return
return
-/obj/structure/stool/bed/chair/e_chair/verb/toggle()
- set name = "Toggle Electric Chair"
- set category = "Object"
- set src in oview(1)
-
- if(on)
- on = 0
- icon_state = "echair0"
- else
- on = 1
- icon_state = "echair1"
- usr << "You switch [on ? "on" : "off"] [src]."
- return
-
/obj/structure/stool/bed/chair/e_chair/rotate()
..()
overlays.Cut()
@@ -44,8 +29,6 @@
return
/obj/structure/stool/bed/chair/e_chair/proc/shock()
- if(!on)
- return
if(last_time + 50 > world.time)
return
last_time = world.time
diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm
index 46730d0332f..bb0dc4486f6 100644
--- a/code/game/objects/structures/false_walls.dm
+++ b/code/game/objects/structures/false_walls.dm
@@ -118,7 +118,7 @@
user << "You can't reach, close it first!"
if(istype(W, /obj/item/weapon/pickaxe/plasmacutter) || istype(W, /obj/item/weapon/pickaxe/diamonddrill) || istype(W, /obj/item/weapon/melee/energy/blade))
- dismantle()
+ dismantle(user)
/obj/structure/falsewall/proc/dismantle(mob/user)
user.visible_message("[user] dismantles the false wall.", "You dismantle the false wall.")
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index df18f1b114e..340933e8184 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -37,7 +37,7 @@
if(HULK in user.mutations)
health -= 5
else
- health -= 3
+ health -= rand(1,2)
healthcheck()
/obj/structure/grille/attack_alien(mob/user as mob)
@@ -62,7 +62,7 @@
"You smash against [src].", \
"You hear twisting metal.")
- health -= rand(2,3)
+ health -= rand(1,2)
healthcheck()
return
@@ -94,8 +94,8 @@
if(!Proj)
return
..()
- if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
- src.health -= Proj.damage*0.2
+ if((Proj.damage_type != STAMINA)) //Grilles can't be exhausted to death
+ src.health -= Proj.damage*0.3
healthcheck()
return
@@ -172,12 +172,13 @@
playsound(loc, 'sound/effects/grillehit.ogg', 80, 1)
health -= W.force * 0.1
else if(!shock(user, 70))
- playsound(loc, 'sound/effects/grillehit.ogg', 80, 1)
switch(W.damtype)
- if("fire")
- health -= W.force
- if("brute")
- health -= W.force * 0.1
+ if(BURN)
+ playsound(loc, 'sound/items/welder.ogg', 80, 1)
+ else
+ playsound(loc, 'sound/effects/grillehit.ogg', 80, 1)
+ health -= W.force * 0.3
+
healthcheck()
..()
return
diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm
index ea89e95dfa6..73c9e58a568 100644
--- a/code/game/objects/structures/lattice.dm
+++ b/code/game/objects/structures/lattice.dm
@@ -59,9 +59,8 @@
var/obj/item/weapon/weldingtool/WT = C
if(WT.remove_fuel(0, user))
user << "Slicing lattice joints ..."
- new /obj/item/stack/rods(src.loc)
- qdel(src)
-
+ new /obj/item/stack/rods(src.loc)
+ qdel(src)
return
/obj/structure/lattice/proc/updateOverlays()
diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm
index 657acb8b02c..e163f334470 100644
--- a/code/game/objects/structures/mineral_doors.dm
+++ b/code/game/objects/structures/mineral_doors.dm
@@ -249,25 +249,3 @@
for(var/i = 1, i <= oreAmount, i++)
new/obj/item/stack/sheet/mineral/wood(get_turf(src))
qdel(src)
-
-/obj/structure/mineral_door/resin
- mineralType = "resin"
- hardness = 1
- close_delay = 100
- openSound = 'sound/effects/attackblob.ogg'
- closeSound = 'sound/effects/attackblob.ogg'
-
-/obj/structure/mineral_door/resin/TryToSwitchState(atom/user)
- if(isalien(user))
- return ..()
-
-/obj/structure/mineral_door/resin/Dismantle(devastated = 0)
- qdel(src)
-
-/obj/structure/mineral_door/resin/CheckHardness()
- playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
- ..()
-
-/obj/structure/mineral_door/resin/BlockSuperconductivity()
- if(opacity)
- return 1
\ No newline at end of file
diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm
index 1330585324e..061fdd3b141 100644
--- a/code/game/objects/structures/musician.dm
+++ b/code/game/objects/structures/musician.dm
@@ -57,7 +57,7 @@
return
// and play
var/turf/source = get_turf(instrumentObj)
- for(var/mob/M in hearers(15, source))
+ for(var/mob/M in get_hearers_in_view(15, source))
M.playsound_local(source, soundfile, 100, falloff = 5)
/datum/song/proc/updateDialog(mob/user as mob)
diff --git a/code/game/objects/structures/spirit_board.dm b/code/game/objects/structures/spirit_board.dm
new file mode 100644
index 00000000000..cda3b1d422a
--- /dev/null
+++ b/code/game/objects/structures/spirit_board.dm
@@ -0,0 +1,83 @@
+/obj/structure/spirit_board
+ name = "spirit board"
+ desc = "A wooden board with letters etched into it, used in seances."
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "spirit_board"
+ density = 1
+ anchored = 0
+ var/virgin = 1
+ var/cooldown = 0
+ var/planchette = "A"
+ var/lastuser = null
+
+/obj/structure/spirit_board/examine()
+ desc = "[initial(desc)] The planchette is sitting at \"[planchette]\"."
+ ..()
+
+/obj/structure/spirit_board/attack_hand(mob/user as mob)
+ if(..())
+ return
+ spirit_board_pick_letter(user)
+
+
+/obj/structure/spirit_board/attack_ghost(mob/dead/observer/user as mob)
+ spirit_board_pick_letter(user)
+
+
+/obj/structure/spirit_board/proc/spirit_board_pick_letter(var/mob/M)
+ if(!spirit_board_checks(M))
+ return 0
+
+ if(virgin)
+ virgin = 0
+ notify_ghosts("Someone has begun playing with a [src.name] in [get_area(src)]!")
+
+ planchette = input("Choose the letter.", "Seance!") in list("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z")
+ add_logs(M, src, "picked a letter on", addition="which was \"[planchette]\".")
+ cooldown = world.time
+ lastuser = M.ckey
+
+ var/turf/T = loc
+ sleep(rand(20,30))
+ if(T == loc)
+ visible_message("The planchette slowly moves... and stops at the letter \"[planchette]\".")
+
+
+/obj/structure/spirit_board/proc/spirit_board_checks(var/mob/M)
+ //cooldown
+ var/bonus = 0
+ if(M.ckey == lastuser)
+ bonus = 10 //Give some other people a chance, hog.
+
+ if(cooldown > world.time - (30 + bonus))
+ return 0 //No feedback here, hiding the cooldown a little makes it harder to tell who's really picking letters.
+
+ //lighting check
+ var/light_amount = 0
+ var/turf/T = get_turf(src)
+ var/area/A = T.loc
+
+ if(A)
+ if(A.lighting_use_dynamic)
+ light_amount = T.lighting_lumcount
+ else
+ light_amount = 10
+
+ if(light_amount > 2)
+ M << "It's too bright here to use [src.name]!"
+ return 0
+
+ //mobs in range check
+ var/users_in_range = 0
+ for(var/mob/living/L in orange(1,src))
+ if(L.ckey && L.client)
+ if((world.time - L.client.inactivity) < (world.time - 300) || L.stat != CONSCIOUS || L.restrained())//no playing with braindeads or corpses or handcuffed dudes.
+ M << "[L] doesn't seem to be paying attention..."
+ else
+ users_in_range++
+
+ if(users_in_range < 2)
+ M << "There aren't enough people to use the [src.name]!"
+ return 0
+
+ return 1
\ No newline at end of file
diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm
new file mode 100644
index 00000000000..ba98fa3d0de
--- /dev/null
+++ b/code/game/objects/structures/statues.dm
@@ -0,0 +1,276 @@
+
+
+
+/obj/structure/statue
+ name = "Statue"
+ desc = "Placeholder. Yell at Firecage if you SOMEHOW see this."
+ icon = 'icons/obj/statue.dmi'
+ icon_state = ""
+ density = 1
+ anchored = 1
+ var/hardness = 1
+ var/oreAmount = 7
+ var/mineralType = "metal"
+ var/last_event = 0
+ var/active = null
+ var/spam_flag = 0
+
+/obj/structure/statue/Destroy()
+ density = 0
+ ..()
+
+/obj/structure/statue/attackby(obj/item/weapon/W, mob/user)
+ hardness -= W.force/100
+ user << "You hit the [name] with your [W.name]!"
+ CheckHardness()
+
+/obj/structure/statue/attack_hand(mob/user)
+ visible_message("[user] rubs some dust off from the [name]'s surface.")
+
+/obj/structure/statue/CanAtmosPass()
+ return !density
+
+/obj/structure/statue/bullet_act(obj/item/projectile/Proj)
+ hardness -= Proj.damage
+ ..()
+ CheckHardness()
+ return
+
+/obj/structure/statue/proc/CheckHardness()
+ if(hardness <= 0)
+ Dismantle(1)
+
+/obj/structure/statue/proc/Dismantle(devastated = 0)
+ if(!devastated)
+ if (mineralType == "metal")
+ var/ore = /obj/item/stack/sheet/metal
+ for(var/i = 1, i <= oreAmount, i++)
+ new ore(get_turf(src))
+ else
+ var/ore = text2path("/obj/item/stack/sheet/mineral/[mineralType]")
+ for(var/i = 1, i <= oreAmount, i++)
+ new ore(get_turf(src))
+ else
+ if (mineralType == "metal")
+ var/ore = /obj/item/stack/sheet/metal
+ for(var/i = 3, i <= oreAmount, i++)
+ new ore(get_turf(src))
+ else
+ var/ore = text2path("/obj/item/stack/sheet/mineral/[mineralType]")
+ for(var/i = 3, i <= oreAmount, i++)
+ new ore(get_turf(src))
+ qdel(src)
+
+/obj/structure/statue/ex_act(severity = 1)
+ switch(severity)
+ if(1)
+ Dismantle(1)
+ if(2)
+ if(prob(20))
+ Dismantle(1)
+ else
+ hardness--
+ CheckHardness()
+ if(3)
+ hardness -= 0.1
+ CheckHardness()
+ return
+
+//////////////////////////////////////STATUES/////////////////////////////////////////////////////////////
+////////////////////////uranium///////////////////////////////////
+
+/obj/structure/statue/uranium
+ hardness = 3
+ luminosity = 2
+ mineralType = "uranium"
+
+/obj/structure/statue/uranium/nuke
+ name = "Statue of a Nuclear Fission Explosive"
+ desc = "This is a grand statue of a Nuclear Explosive. It has a sickening green colour."
+ icon_state = "nuke"
+
+/obj/structure/statue/uranium/eng
+ name = "Statue of an engineer"
+ desc = "This statue has a sickening green colour."
+ icon_state = "eng"
+
+/obj/structure/statue/uranium/attackby(obj/item/weapon/W, mob/user)
+ radiate()
+ ..()
+
+/obj/structure/statue/uranium/Bumped(atom/user)
+ radiate()
+
+/obj/structure/statue/uranium/attack_hand(mob/user)
+ radiate()
+ ..()
+
+/obj/structure/statue/uranium/attack_paw(mob/user)
+ radiate()
+
+/obj/structure/statue/uranium/proc/radiate()
+ if(!active)
+ if(world.time > last_event+15)
+ active = 1
+ for(var/mob/living/L in range(3,src))
+ L.apply_effect(12,IRRADIATE,0)
+ last_event = world.time
+ active = null
+ return
+ return
+
+////////////////////////////plasma///////////////////////////////////////////////////////////////////////
+
+/obj/structure/statue/plasma
+ hardness = 2
+ mineralType = "plasma"
+ desc = "This statue is suitably made from plasma."
+
+/obj/structure/statue/plasma/scientist
+ name = "Statue of a Scientist"
+ icon_state = "sci"
+
+/obj/structure/statue/plasma/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ if(exposed_temperature > 300)
+ PlasmaBurn(exposed_temperature)
+
+
+/obj/structure/statue/plasma/bullet_act(var/obj/item/projectile/Proj)
+ if(istype(Proj,/obj/item/projectile/beam))
+ PlasmaBurn(2500)
+ else if(istype(Proj,/obj/item/projectile/ion))
+ PlasmaBurn(500)
+ ..()
+
+/obj/structure/statue/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(is_hot(W) > 300)//If the temperature of the object is over 300, then ignite
+ message_admins("Plasma statue ignited by [key_name(user, user.client)](?) in ([x],[y],[z] - JMP)",0,1)
+ log_game("Plasma statue ignited by [user.ckey]([user]) in ([x],[y],[z])")
+ ignite(is_hot(W))
+ return
+ ..()
+
+/obj/structure/statue/plasma/proc/PlasmaBurn()
+ atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, 400)
+ hardness = 0
+ CheckHardness()
+
+/obj/structure/statue/plasma/proc/ignite(exposed_temperature)
+ if(exposed_temperature > 300)
+ PlasmaBurn(exposed_temperature)
+
+//////////////////////gold///////////////////////////////////////
+
+/obj/structure/statue/gold
+ hardness = 3
+ mineralType = "gold"
+ desc = "This is a highly valuable statue made from gold."
+
+/obj/structure/statue/gold/hos
+ name = "Statue of the Head of Security"
+ icon_state = "hos"
+
+/obj/structure/statue/gold/hop
+ name = "Statue of the Head of Personnel"
+ icon_state = "hop"
+
+/obj/structure/statue/gold/cmo
+ name = "Statue of the Chief Medical Officer"
+ icon_state = "cmo"
+
+/obj/structure/statue/gold/ce
+ name = "Statue of the Chief Engineer"
+ icon_state = "ce"
+
+/obj/structure/statue/gold/rd
+ name = "Statue of the Research Director"
+ icon_state = "rd"
+
+//////////////////////////silver///////////////////////////////////////
+
+/obj/structure/statue/silver
+ hardness = 3
+ mineralType = "silver"
+ desc = "This is a valuable statue made from silver."
+
+/obj/structure/statue/silver/md
+ name = "Statue of a Medical Officer"
+ icon_state = "md"
+
+/obj/structure/statue/silver/janitor
+ name = "Statue of a Janitor"
+ icon_state = "jani"
+
+/obj/structure/statue/silver/sec
+ name = "Statue of a Security Officer"
+ icon_state = "sec"
+
+/obj/structure/statue/silver/secborg
+ name = "Statue of a Security Cyborg"
+ icon_state = "secborg"
+
+/obj/structure/statue/silver/medborg
+ name = "Statue of a Medical Cyborg"
+ icon_state = "medborg"
+
+/////////////////////////diamond/////////////////////////////////////////
+
+/obj/structure/statue/diamond
+ hardness = 10
+ mineralType = "diamond"
+ desc = "This is a very expensive diamond statue"
+
+/obj/structure/statue/diamond/captain
+ name = "Statue of THE Captain."
+ icon_state = "cap"
+
+/obj/structure/statue/diamond/ai1
+ name = "Statue of the AI hologram."
+ icon_state = "ai1"
+
+/obj/structure/statue/diamond/ai2
+ name = "Statue of the AI core."
+ icon_state = "ai2"
+
+////////////////////////bananium///////////////////////////////////////
+
+/obj/structure/statue/bananium
+ hardness = 3
+ mineralType = "clown"
+ desc = "A bananium statue with a small engraving:'HOOOOOOONK'."
+
+/obj/structure/statue/bananium/clown
+ name = "Statue of a clown"
+ icon_state = "clown"
+
+/obj/structure/statue/bananium/Bumped(atom/user)
+ honk()
+
+/obj/structure/statue/bananium/attackby(obj/item/weapon/W, mob/user)
+ honk()
+ ..()
+
+/obj/structure/statue/bananium/attack_hand(mob/user)
+ honk()
+ ..()
+
+/obj/structure/statue/bananium/attack_paw(mob/user)
+ honk()
+
+/obj/structure/statue/bananium/proc/honk()
+ if(spam_flag == 0)
+ spam_flag = 1
+ playsound(src.loc, 'sound/items/bikehorn.ogg', 50, 1)
+ spawn(20)
+ spam_flag = 0
+
+/////////////////////sandstone/////////////////////////////////////////
+
+/obj/structure/statue/sandstone
+ hardness = 0.5
+ mineralType = "sandstone"
+
+/obj/structure/statue/sandstone/assistant
+ name = "Statue of an assistant"
+ desc = "A cheap statue of sandstone for a greyshirt."
+ icon_state = "assist"
diff --git a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm
index 4512e2b45cc..5428ec16cd3 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm
@@ -13,6 +13,7 @@
"[user.name] pulls you free from the gelatinous resin.",\
"You hear squelching...")
buckled_mob.pixel_y = 0
+ buckled_mob.pixel_x = 0
unbuckle()
/obj/structure/stool/bed/nest/unbuckle_myself(mob/user as mob)
@@ -23,6 +24,7 @@
spawn(600)
if(user && buckled_mob && user.buckled == src)
buckled_mob.pixel_y = 0
+ buckled_mob.pixel_x = 0
unbuckle()
/obj/structure/stool/bed/nest/buckle_mob(mob/M as mob, mob/user as mob)
@@ -47,11 +49,17 @@
M.loc = src.loc
M.dir = src.dir
M.update_canmove()
- M.pixel_y = 6
+ M.pixel_y = 1
+ M.pixel_x = 2
src.buckled_mob = M
src.add_fingerprint(user)
+ src.overlays += image('icons/mob/alien.dmi', "nestoverlay", layer=6)
return
+/obj/structure/stool/bed/nest/unbuckle()
+ overlays.Cut()
+ ..()
+
/obj/structure/stool/bed/nest/attackby(obj/item/weapon/W as obj, mob/user as mob)
var/aforce = W.force
health = max(0, health - aforce)
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 778c0ff308d..3b9747ba171 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -262,6 +262,7 @@
while(amt > 0)
I = locate(B) in loc
Deletion.Add(I)
+ I.loc = null //remove it from the table loc so that we don't locate the same item every time (will be relocated inside the crafted item in construct_item())
amt--
break item_loop
else
@@ -286,6 +287,7 @@
if(!istype(B, A))
Deletion.Remove(B)
qdel(B)
+
return Deletion
/obj/structure/table/interact(mob/user)
@@ -295,7 +297,7 @@
var/dat = "
Construction menu
"
dat += "
"
if(busy)
- dat += "Construction inprogress...
"
+ dat += "Construction in progress..."
else
for(var/datum/table_recipe/R in table_recipes)
if(check_contents(R))
@@ -585,8 +587,14 @@
return
if (istype(I, /obj/item/weapon/wrench))
- table_destroy(2, user)
- return
+ if(istype(src, /obj/structure/table/reinforced))
+ var/obj/structure/table/reinforced/RT = src
+ if(RT.status == 1)
+ table_destroy(2, user)
+ return
+ else
+ table_destroy(2, user)
+ return
if (istype(I, /obj/item/weapon/storage/bag/tray))
var/obj/item/weapon/storage/bag/tray/T = I
@@ -632,24 +640,13 @@ Destroy type values:
return
if(destroy_type == 2)
- if(istype(src, /obj/structure/table/reinforced))
- var/obj/structure/table/reinforced/RT = src
- if(RT.status == 1)
- user << "Now disassembling the reinforced table"
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- if (do_after(user, 50))
- new parts( src.loc )
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
- qdel(src)
- return
- else
- user << "Now disassembling table"
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- if (do_after(user, 50))
- new parts( src.loc )
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
- qdel(src)
- return
+ user << "Now disassembling the [src.name]"
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
+ if (do_after(user, 50))
+ new parts( src.loc )
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ qdel(src)
+ return
@@ -701,6 +698,24 @@ Destroy type values:
return
..()
+/obj/structure/table/MouseDrop_T(mob/target, mob/living/carbon/human/user)
+ if(istype(target) && user == target && istype(user))
+ if(user.canmove)
+ climb_table(user)
+
+/obj/structure/table/proc/climb_table(mob/user)
+ src.add_fingerprint(user)
+ user.visible_message("[user] starts climbing onto [src].", \
+ "[user] starts climbing onto [src].")
+ if(do_mob(user, user, 20))
+ user.pass_flags += PASSTABLE
+ step(user,get_dir(user,src.loc))
+ user.pass_flags -= PASSTABLE
+ user.visible_message("[user] climbs onto [src].", \
+ "[user] climbs onto [src].")
+ add_logs(user, src, "climbed onto")
+ user.Stun(2)
+
/*
* Racks
*/
@@ -805,4 +820,3 @@ Destroy type values:
qdel(src)
/obj/structure/rack/attack_tk() // no telehulk sorry
return
-
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 26a0e40042a..62b181272f2 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -153,9 +153,14 @@
/obj/machinery/shower/attack_hand(mob/M)
on = !on
update_icon()
+ add_fingerprint(M)
if(on)
for (var/atom/movable/G in loc)
- Crossed(G)
+ wash(G)
+ else
+ if(istype(loc, /turf/simulated))
+ var/turf/simulated/tile = loc
+ tile.MakeSlippery()
/obj/machinery/shower/attackby(obj/item/I, mob/user)
@@ -171,7 +176,9 @@
watertemp = "boiling"
if("boiling")
watertemp = "normal"
- user.visible_message("[user] adjusts the shower with the [I].", "You adjust the shower with the [I].")
+ user.visible_message("[user] adjusts the shower with the [I].", "You adjust the shower with the [I] to [watertemp] temperature.")
+ log_game("[key_name(user)] has wrenched a shower to [watertemp] at ([x],[y],[z])")
+ add_hiddenprint(user)
/obj/machinery/shower/update_icon() //this is terribly unreadable, but basically it makes the shower mist up
@@ -203,9 +210,10 @@
/obj/machinery/shower/Crossed(atom/movable/O)
..()
wash(O)
- if(ismob(O))
- mobpresent += 1
- check_heat(O)
+ if(iscarbon(O) && on)
+ var/mob/living/carbon/M=O
+ M.slip(4,2,null,NO_SLIP_WHEN_WALKING)
+
/obj/machinery/shower/Uncrossed(atom/movable/O)
@@ -217,7 +225,9 @@
//Yes, showers are super powerful as far as washing goes.
/obj/machinery/shower/proc/wash(atom/movable/O)
if(!on) return
-
+ if(ismob(O))
+ mobpresent += 1
+ check_heat(O)
if(isliving(O))
var/mob/living/L = O
L.ExtinguishMob()
@@ -303,6 +313,7 @@
check_heat(C)
+
/obj/machinery/shower/proc/check_heat(mob/M)
if(!on || watertemp == "normal") return
if(iscarbon(M))
diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm
index 281594704e1..b9b561e42e8 100644
--- a/code/game/objects/structures/windoor_assembly.dm
+++ b/code/game/objects/structures/windoor_assembly.dm
@@ -89,7 +89,6 @@ obj/structure/windoor_assembly/Destroy()
R.add_fingerprint(user)
qdel(src)
else
- user << "You need more welding fuel to dissassemble the windoor assembly."
return
//Wrenching an unsecure assembly anchors it in place. Step 4 complete
@@ -166,7 +165,7 @@ obj/structure/windoor_assembly/Destroy()
if(do_after(user, 40))
if(!src) return
- user << "You cut the windoor wires.!"
+ user << "You cut the windoor wires!"
new/obj/item/stack/cable_coil(get_turf(user), 1)
src.state = "01"
if(src.secure)
diff --git a/code/game/pooling/atom_pool.dm b/code/game/pooling/atom_pool.dm
new file mode 100644
index 00000000000..ca6f8f19341
--- /dev/null
+++ b/code/game/pooling/atom_pool.dm
@@ -0,0 +1,93 @@
+
+/*
+/tg/station13 /atom/movable Pool:
+---------------------------------
+By RemieRichards
+
+Creation/Deletion is laggy, so let's reduce reuse and recycle!
+
+Locked to /atom/movable and it's subtypes due to Loc being a const var on /atom
+but being read&write on /movable due to how they... move.
+
+*/
+
+var/global/list/GlobalPool = list()
+
+//You'll be using this proc 90% of the time.
+//It grabs a type from the pool if it can
+//And if it can't, it creates one
+//The pool is flexible and will expand to fit
+//The new created atom when it eventually
+//Goes into the pool
+
+/proc/PoolOrNew(var/get_type,var/new_loc)
+ if(!get_type)
+ return
+
+ var/atom/movable/AM
+ if(new_loc)
+ AM = GetFromPool(get_type,new_loc)
+ else
+ AM = GetFromPool(get_type,null)
+
+ if(!AM)
+ if(ispath(get_type))
+ if(new_loc)
+ AM = new get_type (new_loc)
+ else
+ AM = new get_type (null)
+
+ if(AM)
+ return AM
+
+
+
+/proc/GetFromPool(var/get_type,var/new_loc)
+ if(!get_type)
+ return 0
+
+ if(isnull(GlobalPool[get_type]))
+ return 0
+
+ if(length(GlobalPool[get_type]) == 0)
+ return 0
+
+ var/atom/movable/AM = pick_n_take(GlobalPool[get_type])
+ if(AM)
+ AM.ResetVars()
+ AM.New()
+ if(new_loc)
+ AM.loc = new_loc
+ return AM
+ return 0
+
+
+
+/proc/PlaceInPool(var/atom/movable/AM)
+ if(!istype(AM))
+ return
+
+ if(AM in GlobalPool[AM.type])
+ return
+
+ AM.ResetVars()
+
+ if(!GlobalPool[AM.type])
+ GlobalPool[AM.type] = list()
+
+ GlobalPool[AM.type] += AM
+
+
+
+/atom/movable/proc/ResetVars()
+ var/list/excluded = list("loc", "locs", "parent_type", "vars", "verbs", "type")
+
+ for(var/V in vars)
+ if(V in excluded)
+ continue
+
+ vars[V] = initial(vars[V])
+
+ vars["loc"] = null
+
+
diff --git a/code/game/say.dm b/code/game/say.dm
new file mode 100644
index 00000000000..c4dfd8454a0
--- /dev/null
+++ b/code/game/say.dm
@@ -0,0 +1,144 @@
+/*
+ Miauw's big Say() rewrite.
+ This file has the basic atom/movable level speech procs.
+ And the base of the send_speech() proc, which is the core of saycode.
+*/
+var/list/freqtospan = list(
+ "1351" = "sciradio",
+ "1355" = "medradio",
+ "1357" = "engradio",
+ "1347" = "suppradio",
+ "1349" = "servradio",
+ "1359" = "secradio",
+ "1353" = "comradio",
+ "1447" = "aiprivradio",
+ "1213" = "syndradio",
+ "1441" = "dsquadradio"
+ )
+
+/atom/movable/proc/say(message)
+ if(!can_speak())
+ return
+ if(message == "" || !message)
+ return
+ send_speech(message)
+
+/atom/movable/proc/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq)
+ return
+
+/atom/movable/proc/can_speak()
+ return 1
+
+/atom/movable/proc/send_speech(message, range)
+ var/rendered = compose_message(src, languages, message)
+ for(var/atom/movable/AM in get_hearers_in_view(range, src))
+ AM.Hear(rendered, src, languages, message)
+
+/atom/movable/proc/compose_message(atom/movable/speaker, message_langs, raw_message, radio_freq)
+ //This proc uses text() because it is faster than appending strings. Thanks BYOND.
+ //Basic span
+ var/spanpart1 = ""
+ //Start name span.
+ var/spanpart2 = ""
+ //Radio freq/name display
+ var/freqpart = radio_freq ? "\[[get_radio_name(radio_freq)]\] " : ""
+ //Speaker name
+ var/namepart = "[speaker.GetVoice()][speaker.get_alt_name()]"
+ //End name span.
+ var/endspanpart = ""
+ //Message
+ var/messagepart = " [lang_treat(speaker, message_langs, raw_message)]"
+
+ return "[spanpart1][spanpart2][freqpart][compose_track_href(speaker, message_langs, raw_message, radio_freq)][namepart][compose_job(speaker, message_langs, raw_message, radio_freq)][endspanpart][messagepart]"
+
+/atom/movable/proc/compose_track_href(atom/movable/speaker, message_langs, raw_message, radio_freq)
+ return ""
+
+/atom/movable/proc/compose_job(atom/movable/speaker, message_langs, raw_message, radio_freq)
+ return ""
+
+/atom/movable/proc/say_quote(var/text)
+ if(!text)
+ return "says, \"...\"" //not the best solution, but it will stop a large number of runtimes. The cause is somewhere in the Tcomms code
+ var/ending = copytext(text, length(text))
+ if (ending == "?")
+ return "asks, \"[text]\""
+ if (ending == "!")
+ return "exclaims, \"[text]\""
+
+ return "says, \"[text]\""
+
+/atom/movable/proc/lang_treat(atom/movable/speaker, message_langs, raw_message)
+ if(languages & message_langs)
+ var/atom/movable/AM = speaker.GetSource()
+ if(AM)
+ return AM.say_quote(raw_message)
+ else
+ return speaker.say_quote(raw_message)
+ else if(message_langs & HUMAN)
+ var/atom/movable/AM = speaker.GetSource()
+ if(AM)
+ return AM.say_quote(stars(raw_message))
+ else
+ return speaker.say_quote(stars(raw_message))
+ else if(message_langs & MONKEY)
+ return "chimpers."
+ else if(message_langs & ALIEN)
+ return "hisses."
+ else if(message_langs & ROBOT)
+ return "beeps rapidly."
+ else if(message_langs & DRONE)
+ return "chitters."
+ else
+ return "makes a strange sound."
+
+/proc/get_radio_span(freq)
+ var/returntext = freqtospan["[freq]"]
+ if(returntext)
+ return returntext
+ return "radio"
+
+/proc/get_radio_name(freq)
+ var/returntext = radiochannelsreverse["[freq]"]
+ if(returntext)
+ return returntext
+ return "[copytext("[freq]", 1, 4)].[copytext("[freq]", 4, 5)]"
+
+/atom/movable/proc/GetVoice()
+ return name
+
+/atom/movable/proc/IsVocal()
+ return 1
+
+/atom/movable/proc/get_alt_name()
+ return
+
+//these exist mostly to deal with the AIs hrefs and job stuff.
+/atom/movable/proc/GetJob()
+ return
+
+/atom/movable/proc/GetTrack()
+ return
+
+/atom/movable/proc/GetSource()
+ return
+
+/atom/movable/proc/GetRadio()
+
+/atom/movable/virtualspeaker
+ var/job
+ var/faketrack
+ var/atom/movable/source
+ var/obj/item/device/radio/radio
+
+/atom/movable/virtualspeaker/GetJob()
+ return job
+
+/atom/movable/virtualspeaker/GetTrack()
+ return faketrack
+
+/atom/movable/virtualspeaker/GetSource()
+ return source
+
+/atom/movable/virtualspeaker/GetRadio()
+ return radio
diff --git a/code/game/smoothwall.dm b/code/game/smoothwall.dm
index 29800a163e8..e98c839150a 100644
--- a/code/game/smoothwall.dm
+++ b/code/game/smoothwall.dm
@@ -81,6 +81,9 @@
for(var/obj/structure/falsewall/W in range(src,1))
W.relativewall()
W.update_icon()//Refreshes the wall to make sure the icons don't desync
+ for(var/obj/structure/alien/resin/W in range(src,1))
+ W.relativewall()
+ W.update_icon()
return
/turf/simulated/wall/New()
@@ -129,4 +132,17 @@
junction |= get_dir(src,W)
var/turf/simulated/wall/wall = src
wall.icon_state = "[wall.walltype][junction]"
+ return
+
+
+/obj/structure/alien/resin/relativewall()
+
+ var/junction = 0 //will be used to determine from which side the wall is connected to other walls
+
+ for(var/obj/structure/alien/resin/W in orange(src,1))
+ if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls
+ junction |= get_dir(src,W)
+ var/obj/structure/alien/resin/resin = src
+ resin.icon_state = "[resin.resintype][junction]"
+
return
\ No newline at end of file
diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm
index 4de300cff1f..8e38ac30808 100644
--- a/code/game/turfs/simulated.dm
+++ b/code/game/turfs/simulated.dm
@@ -33,10 +33,7 @@
overlays -= wet_overlay
/turf/simulated/Entered(atom/A, atom/OL)
- if(movement_disabled && usr.ckey != movement_disabled_exception)
- usr << "Movement is admin-disabled." //This is to identify lag problems
- return
-
+ ..()
if (istype(A,/mob/living/carbon))
var/mob/living/carbon/M = A
if(M.lying) return
@@ -60,7 +57,4 @@
return
if(2) //lube
- M.slip(0, 10, null, (STEP|SLIDE|GALOSHES_DONT_HELP))
-
-
- ..()
\ No newline at end of file
+ M.slip(0, 10, null, (STEP|SLIDE|GALOSHES_DONT_HELP))
\ No newline at end of file
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index 12ef24729a1..4e8ae18a48c 100644
--- a/code/game/turfs/simulated/floor.dm
+++ b/code/game/turfs/simulated/floor.dm
@@ -17,6 +17,12 @@ var/list/plating_icons = list("plating","platingdmg1","platingdmg2","platingdmg3
"ironsand8", "ironsand9", "ironsand10", "ironsand11",
"ironsand12", "ironsand13", "ironsand14", "ironsand15")
var/list/wood_icons = list("wood","wood-broken")
+var/list/gold_icons = list("gold","gold_dam")
+var/list/silver_icons = list("silver","silver_dam")
+var/list/plasma_icons = list("plasma","plasma_dam")
+var/list/diamond_icons = list("diamond","diamond_dam")
+var/list/uranium_icons = list("uranium","uranium_dam")
+var/list/bananium_icons = list("bananium","bananium_dam")
/turf/simulated/floor
@@ -34,6 +40,7 @@ var/list/wood_icons = list("wood","wood-broken")
var/broken = 0
var/burnt = 0
var/mineral = "metal"
+ var/floortype = "metal"
var/obj/item/stack/tile/floor_tile = new/obj/item/stack/tile/plasteel
@@ -161,6 +168,37 @@ turf/simulated/floor/proc/update_icon()
if( !(icon_state in wood_icons) )
icon_state = "wood"
//world << "[icon_state]y's got [icon_state]"
+
+ else if(is_gold_floor())
+ if(!broken && !burnt)
+ if( !(icon_state in gold_icons) )
+ icon_state = "gold"
+
+ else if(is_silver_floor())
+ if(!broken && !burnt)
+ if( !(icon_state in silver_icons) )
+ icon_state = "silver"
+
+ else if(is_plasma_floor())
+ if(!broken && !burnt)
+ if( !(icon_state in plasma_icons) )
+ icon_state = "plasma"
+
+ else if(is_uranium_floor())
+ if(!broken && !burnt)
+ if( !(icon_state in uranium_icons) )
+ icon_state = "uranium"
+
+ else if(is_diamond_floor())
+ if(!broken && !burnt)
+ if( !(icon_state in diamond_icons) )
+ icon_state = "diamond"
+
+ else if(is_bananium_floor())
+ if(!broken && !burnt)
+ if( !(icon_state in bananium_icons) )
+ icon_state = "bananium"
+
spawn(1)
if(istype(src,/turf/simulated/floor)) //Was throwing runtime errors due to a chance of it changing to space halfway through.
if(air)
@@ -211,19 +249,55 @@ turf/simulated/floor/proc/update_icon()
return 0
/turf/simulated/floor/is_grass_floor()
- if(istype(floor_tile,/obj/item/stack/tile/grass))
+ if(istype(floor_tile, /obj/item/stack/tile/grass))
return 1
else
return 0
/turf/simulated/floor/is_wood_floor()
- if(istype(floor_tile,/obj/item/stack/tile/wood))
+ if(istype(floor_tile, /obj/item/stack/tile/wood))
+ return 1
+ else
+ return 0
+
+/turf/simulated/floor/is_gold_floor()
+ if(istype(floor_tile, /obj/item/stack/tile/mineral/gold))
+ return 1
+ else
+ return 0
+
+/turf/simulated/floor/is_silver_floor()
+ if(istype(floor_tile, /obj/item/stack/tile/mineral/silver))
+ return 1
+ else
+ return 0
+
+/turf/simulated/floor/is_plasma_floor()
+ if(istype(floor_tile, /obj/item/stack/tile/mineral/plasma))
+ return 1
+ else
+ return 0
+
+/turf/simulated/floor/is_uranium_floor()
+ if(istype(floor_tile, /obj/item/stack/tile/mineral/uranium))
+ return 1
+ else
+ return 0
+
+/turf/simulated/floor/is_diamond_floor()
+ if(istype(floor_tile, /obj/item/stack/tile/mineral/diamond))
+ return 1
+ else
+ return 0
+
+/turf/simulated/floor/is_bananium_floor()
+ if(istype(floor_tile, /obj/item/stack/tile/mineral/bananium))
return 1
else
return 0
/turf/simulated/floor/is_carpet_floor()
- if(istype(floor_tile,/obj/item/stack/tile/carpet))
+ if(istype(floor_tile, /obj/item/stack/tile/carpet))
return 1
else
return 0
@@ -256,6 +330,24 @@ turf/simulated/floor/proc/update_icon()
else if(is_grass_floor())
src.icon_state = "sand[pick("1","2","3")]"
broken = 1
+ else if(is_gold_floor())
+ src.icon_state = "gold_dam"
+ broken = 1
+ else if(is_silver_floor())
+ src.icon_state = "silver_dam"
+ broken = 1
+ else if(is_diamond_floor())
+ src.icon_state = "diamond_dam"
+ broken = 1
+ else if(is_bananium_floor())
+ src.icon_state = "bananium_dam"
+ broken = 1
+ else if(is_uranium_floor())
+ src.icon_state = "uranium_dam"
+ broken = 1
+ else if(is_plasma_floor())
+ src.icon_state = "plasma_dam"
+ broken = 1
/turf/simulated/floor/proc/burn_tile()
if(istype(src,/turf/simulated/floor/engine)) return
@@ -279,6 +371,21 @@ turf/simulated/floor/proc/update_icon()
else if(is_grass_floor())
src.icon_state = "sand[pick("1","2","3")]"
burnt = 1
+ else if(is_gold_floor())
+ src.icon_state = "gold_dam"
+ burnt = 1
+ else if(is_silver_floor())
+ src.icon_state = "silver_dam"
+ burnt = 1
+ else if(is_diamond_floor())
+ src.icon_state = "diamond_dam"
+ burnt = 1
+ else if(is_bananium_floor())
+ src.icon_state = "bananium_dam"
+ burnt = 1
+ else if(is_uranium_floor())
+ src.icon_state = "uranium_dam"
+ burnt = 1
//This proc will delete the floor_tile and the update_iocn() proc will then change the icon_state of the turf
//This proc auto corrects the grass tiles' siding.
@@ -342,78 +449,18 @@ turf/simulated/floor/proc/update_icon()
update_icon()
levelupdate()
+/turf/simulated/floor/proc/make_floor(floor_tile, T)
+ broken = 0
+ burnt = 0
+ intact = 1
+ if(T)
+ floor_tile = T
+ update_icon()
+ levelupdate()
+ return
//This proc will make the turf a light floor tile. The expected argument is the tile to make the turf with
//If none is given it will make a new object. dropping or unequipping must be handled before or after calling
//this proc.
-/turf/simulated/floor/proc/make_light_floor(var/obj/item/stack/tile/light/T = null)
- broken = 0
- burnt = 0
- intact = 1
- if(T)
- if(istype(T,/obj/item/stack/tile/light))
- floor_tile = T
- update_icon()
- levelupdate()
- return
- //if you gave a valid parameter, it won't get thisf ar.
- floor_tile = new/obj/item/stack/tile/light
-
- update_icon()
- levelupdate()
-
-//This proc will make a turf into a grass patch. Fun eh? Insert the grass tile to be used as the argument
-//If no argument is given a new one will be made.
-/turf/simulated/floor/proc/make_grass_floor(var/obj/item/stack/tile/grass/T = null)
- broken = 0
- burnt = 0
- intact = 1
- if(T)
- if(istype(T,/obj/item/stack/tile/grass))
- floor_tile = T
- update_icon()
- levelupdate()
- return
- //if you gave a valid parameter, it won't get thisf ar.
- floor_tile = new/obj/item/stack/tile/grass
-
- update_icon()
- levelupdate()
-
-//This proc will make a turf into a wood floor. Fun eh? Insert the wood tile to be used as the argument
-//If no argument is given a new one will be made.
-/turf/simulated/floor/proc/make_wood_floor(var/obj/item/stack/tile/wood/T = null)
- broken = 0
- burnt = 0
- intact = 1
- if(T)
- if(istype(T,/obj/item/stack/tile/wood))
- floor_tile = T
- update_icon()
- levelupdate()
- return
- //if you gave a valid parameter, it won't get thisf ar.
- floor_tile = new/obj/item/stack/tile/wood
-
- update_icon()
- levelupdate()
-
-//This proc will make a turf into a carpet floor. Fun eh? Insert the carpet tile to be used as the argument
-//If no argument is given a new one will be made.
-/turf/simulated/floor/proc/make_carpet_floor(var/obj/item/stack/tile/carpet/T = null)
- broken = 0
- burnt = 0
- intact = 1
- if(T)
- if(istype(T,/obj/item/stack/tile/carpet))
- floor_tile = T
- update_icon()
- levelupdate()
- return
- //if you gave a valid parameter, it won't get thisf ar.
- floor_tile = new/obj/item/stack/tile/carpet
-
- update_icon()
- levelupdate()
/turf/simulated/floor/attackby(obj/item/C as obj, mob/user as mob)
@@ -541,5 +588,3 @@ turf/simulated/floor/proc/update_icon()
icon_state = icon_plating
burnt = 0
broken = 0
- else
- user << "You need more welding fuel to complete this task."
diff --git a/code/game/turfs/simulated/floor_mineral.dm b/code/game/turfs/simulated/floor_mineral.dm
new file mode 100644
index 00000000000..f281fd6c471
--- /dev/null
+++ b/code/game/turfs/simulated/floor_mineral.dm
@@ -0,0 +1,53 @@
+
+/turf/simulated/floor/mineral
+ name = "mineral floor"
+ icon_state = ""
+ var/last_event = 0
+ var/active = null
+
+/turf/simulated/floor/mineral/plasma
+ name = "plasma floor"
+ icon_state = "plasma"
+ mineral = "plasma"
+ floortype = "plasma"
+ floor_tile = new/obj/item/stack/tile/mineral/plasma
+
+/turf/simulated/floor/mineral/gold
+ name = "gold floor"
+ icon_state = "gold"
+ mineral = "gold"
+ floortype = "gold"
+ floor_tile = new/obj/item/stack/tile/mineral/gold
+
+/turf/simulated/floor/mineral/silver
+ name = "silver floor"
+ icon_state = "silver"
+ mineral = "silver"
+ floortype = "silver"
+ floor_tile = new/obj/item/stack/tile/mineral/silver
+
+/turf/simulated/floor/mineral/bananium
+ name = "bananium floor"
+ icon_state = "bananium"
+ mineral = "clown"
+ floortype = "clown"
+ floor_tile = new/obj/item/stack/tile/mineral/bananium
+
+/turf/simulated/floor/mineral/bananium/airless
+ oxygen = 0.01
+ nitrogen = 0.01
+ temperature = TCMB
+
+/turf/simulated/floor/mineral/diamond
+ name = "diamond floor"
+ icon_state = "diamond"
+ mineral = "diamond"
+ floortype = "diamond"
+ floor_tile = new/obj/item/stack/tile/mineral/diamond
+
+/turf/simulated/floor/mineral/uranium
+ name = "uranium floor"
+ icon_state = "uranium"
+ mineral = "uranium"
+ floortype = "uranium"
+ floor_tile = new/obj/item/stack/tile/mineral/uranium
\ No newline at end of file
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index 540c9d2d88f..d18d8c1ca9c 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -146,7 +146,7 @@
/turf/simulated/wall/attackby(obj/item/weapon/W as obj, mob/user as mob)
user.changeNext_move(CLICK_CD_MELEE)
- if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
+ if (!user.IsAdvancedToolUser())
user << "You don't have the dexterity to do this!"
return
@@ -228,7 +228,6 @@
user << "You remove the outer plating."
dismantle_wall()
else
- user << "You need more welding fuel to complete this task."
return
else if( istype(W, /obj/item/weapon/pickaxe/plasmacutter) )
diff --git a/code/game/turfs/simulated/walls_misc.dm b/code/game/turfs/simulated/walls_misc.dm
index b1a06f6e88a..d7dbcb56300 100644
--- a/code/game/turfs/simulated/walls_misc.dm
+++ b/code/game/turfs/simulated/walls_misc.dm
@@ -2,4 +2,18 @@
name = "wall"
desc = "The patterns engraved on the wall seem to shift as you try to focus on them. You feel sick"
icon_state = "cult"
- walltype = "cult"
\ No newline at end of file
+ walltype = "cult"
+
+/turf/simulated/wall/rust
+ name = "rusted wall"
+ desc = "A rusted metal wall."
+ icon_state = "arust"
+ walltype = "arust"
+ hardness = 45
+
+/turf/simulated/wall/r_wall/rust
+ name = "rusted reinforced wall"
+ desc = "A huge chunk of rusted reinforced metal."
+ icon_state = "rrust"
+ walltype = "rrust"
+ hardness = 15
\ No newline at end of file
diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm
index 8126029fc18..7364cc147bc 100644
--- a/code/game/turfs/simulated/walls_reinforced.dm
+++ b/code/game/turfs/simulated/walls_reinforced.dm
@@ -12,7 +12,7 @@
/turf/simulated/wall/r_wall/attackby(obj/item/W as obj, mob/user as mob)
- if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
+ if (!user.IsAdvancedToolUser())
user << "You don't have the dexterity to do this!"
return
@@ -102,8 +102,6 @@
src.d_state = 3
src.icon_state = "r_wall-3"
user << "You press firmly on the cover, dislodging it."
- else
- user << "You need more welding fuel to complete this task."
return
if( istype(W, /obj/item/weapon/pickaxe/plasmacutter) )
@@ -166,8 +164,6 @@
src.icon_state = "r_wall-6"
new /obj/item/stack/rods( src )
user << "The support rods drop out as you cut them loose from the frame."
- else
- user << "You need more welding fuel to complete this task."
return
if( istype(W, /obj/item/weapon/pickaxe/plasmacutter) )
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index 4a595d5f0e7..314b81d1dac 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -8,6 +8,10 @@
thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
heat_capacity = 700000
+ var/transition //These is used in transistions as a way to tell where on the "cube" of space you're transitioning from/to
+ var/destination_x
+ var/destination_y
+
/turf/space/New()
if(!istype(src, /turf/space/transit))
icon_state = "[((x + y) ^ ~(x * y) + z) % 25]"
@@ -15,216 +19,171 @@
/turf/space/attack_paw(mob/user as mob)
return src.attack_hand(user)
-/turf/space/attackby(obj/item/C as obj, mob/user as mob)
-
- if (istype(C, /obj/item/stack/rods))
+/turf/space/attackby(obj/item/C, mob/user)
+ if(istype(C, /obj/item/stack/rods))
var/obj/item/stack/rods/R = C
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
if(L)
user << "There is already a lattice."
return
- if (R.use(1))
+ if(R.use(1))
user << "Constructing support lattice..."
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
ReplaceWithLattice()
else
user << "You need one rod to build lattice."
- return
return
-
- if (istype(C, /obj/item/stack/tile/plasteel))
+ if(istype(C, /obj/item/stack/tile/plasteel))
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
if(L)
var/obj/item/stack/tile/plasteel/S = C
- if (S.use(1))
+ if(S.use(1))
qdel(L)
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
user << "You build a floor."
S.build(src)
else
user << "You need one floor tile to build a floor."
- return
- return
else
user << "The plating is going to need some support. Place metal rods first."
- return
-
-// Ported from unstable r355
-
-/turf/space/Entered(atom/movable/A as mob|obj)
- if(movement_disabled)
- usr << "Movement is admin-disabled." //This is to identify lag problems
- return
+/turf/space/Entered(atom/movable/A)
..()
- if ((!(A) || src != A.loc)) return
+ if ((!(A) || src != A.loc))
+ return
inertial_drift(A)
- if(ticker && ticker.mode)
+ if(transition)
- // Okay, so let's make it so that people can travel z levels but not nuke disks!
- // if(ticker.mode.name == "nuclear emergency") return
- if(A.z > 6) return
- if (A.x <= TRANSITIONEDGE || A.x >= (world.maxx - TRANSITIONEDGE - 1) || A.y <= TRANSITIONEDGE || A.y >= (world.maxy - TRANSITIONEDGE - 1))
- if(istype(A, /obj/effect/meteor))
- qdel(A)
- return
+ if(destination_x)
+ A.x = destination_x
- var/move_to_z = src.z
- var/safety = 1
+ if(destination_y)
+ A.y = destination_y
- //Check if it's a mob pulling an object
- var/atom/movable/was_pulling = null
- var/mob/living/MOB = null
- if(isliving(A))
- MOB = A
- if(MOB.pulling)
- was_pulling = MOB.pulling //Store the object to transition later
+ A.z = text2num(transition)
- while(move_to_z == src.z)
- var/move_to_z_str = pickweight(accessable_z_levels)
- move_to_z = text2num(move_to_z_str)
- safety++
- if(safety > 10)
- break
+ if(isliving(A))
+ var/mob/living/L = A
+ if(L.pulling)
+ var/turf/T = get_step(L.loc,turn(A.dir, 180))
+ L.pulling.loc = T
- if(!move_to_z)
- return
-
- A.z = move_to_z
-
- if(src.x <= TRANSITIONEDGE)
- A.x = world.maxx - TRANSITIONEDGE - 2
- A.y = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2)
-
- else if (A.x >= (world.maxx - TRANSITIONEDGE - 1))
- A.x = TRANSITIONEDGE + 1
- A.y = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2)
-
- else if (src.y <= TRANSITIONEDGE)
- A.y = world.maxy - TRANSITIONEDGE -2
- A.x = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2)
-
- else if (A.y >= (world.maxy - TRANSITIONEDGE - 1))
- A.y = TRANSITIONEDGE + 1
- A.x = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2)
-
- spawn (0)
- if(was_pulling && MOB) //Carry the object they were pulling over when they transition
- was_pulling.loc = MOB.loc
- MOB.start_pulling(was_pulling)
- if ((A && A.loc))
- A.loc.Entered(A)
-
-/turf/space/proc/Sandbox_Spacemove(atom/movable/A as mob|obj)
+/turf/space/proc/Sandbox_Spacemove(atom/movable/A)
var/cur_x
var/cur_y
- var/next_x
- var/next_y
+ var/next_x = src.x
+ var/next_y = src.y
var/target_z
var/list/y_arr
+ var/list/cur_pos = src.get_global_map_pos()
+ if(!cur_pos)
+ return
+ cur_x = cur_pos["x"]
+ cur_y = cur_pos["y"]
if(src.x <= 1)
- if(istype(A, /obj/effect/meteor))
- qdel(A)
- return
-
- var/list/cur_pos = src.get_global_map_pos()
- if(!cur_pos) return
- cur_x = cur_pos["x"]
- cur_y = cur_pos["y"]
next_x = (--cur_x||global_map.len)
y_arr = global_map[next_x]
target_z = y_arr[cur_y]
-/*
- //debug
- world << "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]"
- world << "Target Z = [target_z]"
- world << "Next X = [next_x]"
- //debug
-*/
- if(target_z)
- A.z = target_z
- A.x = world.maxx - 2
- spawn (0)
- if ((A && A.loc))
- A.loc.Entered(A)
+ next_x = world.maxx - 2
else if (src.x >= world.maxx)
- if(istype(A, /obj/effect/meteor))
- qdel(A)
- return
-
- var/list/cur_pos = src.get_global_map_pos()
- if(!cur_pos) return
- cur_x = cur_pos["x"]
- cur_y = cur_pos["y"]
next_x = (++cur_x > global_map.len ? 1 : cur_x)
y_arr = global_map[next_x]
target_z = y_arr[cur_y]
-/*
- //debug
- world << "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]"
- world << "Target Z = [target_z]"
- world << "Next X = [next_x]"
- //debug
-*/
- if(target_z)
- A.z = target_z
- A.x = 3
- spawn (0)
- if ((A && A.loc))
- A.loc.Entered(A)
+ next_x = 3
else if (src.y <= 1)
- if(istype(A, /obj/effect/meteor))
- qdel(A)
- return
- var/list/cur_pos = src.get_global_map_pos()
- if(!cur_pos) return
- cur_x = cur_pos["x"]
- cur_y = cur_pos["y"]
y_arr = global_map[cur_x]
next_y = (--cur_y||y_arr.len)
target_z = y_arr[next_y]
-/*
- //debug
- world << "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]"
- world << "Next Y = [next_y]"
- world << "Target Z = [target_z]"
- //debug
-*/
- if(target_z)
- A.z = target_z
- A.y = world.maxy - 2
- spawn (0)
- if ((A && A.loc))
- A.loc.Entered(A)
-
+ next_y = world.maxy - 2
else if (src.y >= world.maxy)
- if(istype(A, /obj/effect/meteor))
- qdel(A)
- return
- var/list/cur_pos = src.get_global_map_pos()
- if(!cur_pos) return
- cur_x = cur_pos["x"]
- cur_y = cur_pos["y"]
y_arr = global_map[cur_x]
next_y = (++cur_y > y_arr.len ? 1 : cur_y)
target_z = y_arr[next_y]
-/*
- //debug
- world << "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]"
- world << "Next Y = [next_y]"
- world << "Target Z = [target_z]"
- //debug
-*/
- if(target_z)
- A.z = target_z
- A.y = 3
- spawn (0)
- if ((A && A.loc))
- A.loc.Entered(A)
- return
+ next_y = 3
+
+ var/turf/T = locate(next_x, next_y, target_z)
+ A.Move(T)
/turf/space/handle_slip()
return
+
+/turf/space/proc/Assign_Destination()
+
+ if(transition)
+ if(x <= TRANSITIONEDGE) //west
+ destination_x = world.maxx - TRANSITIONEDGE - 2
+ else if (x >= (world.maxx - TRANSITIONEDGE - 1)) //east
+ destination_x = TRANSITIONEDGE + 1
+ else if (y <= TRANSITIONEDGE) //south
+ destination_y = world.maxy - TRANSITIONEDGE - 2
+ else if (y >= (world.maxy - TRANSITIONEDGE - 1)) //north
+ destination_y = TRANSITIONEDGE + 1
+
+/datum/controller/game_controller/proc/setup_map_transistions() //listamania
+
+ var/list/unplaced_z_levels = accessable_z_levels
+ var/list/free_zones = list("A", "B", "C", "D", "E", "F")
+ var/list/zone_connections = list("D ","C ","B ","E ","A ","C ","F ","E ","A ","D ","F ","B ","A ","E ","F ","C ","A ","B ","F ","D ","D ","C ","B ","E") //This describes the borders of a cube based on free zones, really!
+ var/text_zone_connections = list2text(zone_connections)
+ var/list/final_zone_connections = list()
+ var/list/turfs_needing_transition = list()
+ var/list/turfs_needing_destinations = list()
+ var/list/z_level_order = list()
+ var/z_level
+ var/placement
+
+ for(var/turf/space/S in world) //Define the transistions of the z levels
+ if (S.x == TRANSITIONEDGE || S.x == (world.maxx - TRANSITIONEDGE - 1) || S.y == TRANSITIONEDGE || S.y == (world.maxy - TRANSITIONEDGE - 1))
+ turfs_needing_transition += S
+
+ while(free_zones.len != 0) //Assign the sides of the cube
+ if(!unplaced_z_levels) //if we're somehow unable to fill the cube, pad with deep space
+ z_level = 6
+ else
+ z_level = pick(unplaced_z_levels)
+ if(z_level > world.maxz) //A safety if one of the unplaced_z_levels doesn't actually exist
+ z_level = 6
+ placement = pick(free_zones)
+ text_zone_connections = replacetext(text_zone_connections, placement, "[z_level]")
+
+ for(var/turf/space/S in turfs_needing_transition) //pass the identity zone to the relevent turfs
+ if(S.transition && prob(50)) //In z = 6 (deep space) it's a bit of a crapshoot in terms of navigation
+ continue
+ if(S.z == z_level)
+ S.transition = num2text(z_level)
+ if(!(S in turfs_needing_destinations))
+ turfs_needing_destinations += S
+ if(S.z != 6) //deep space turfs need to hang around in case they get reassigned a zone
+ turfs_needing_transition -= S
+
+ z_level_order += num2text(z_level)
+ unplaced_z_levels -= z_level
+ free_zones -= placement
+
+ zone_connections = text2list(replacetext(text_zone_connections, " ", "\n")) //Convert the string back into a list
+
+ final_zone_connections.len = z_level_order.len
+
+ var/list/temp = list()
+
+ for(var/j=1, j<= 24, j++)
+ temp += zone_connections[j]
+ if(temp.len == 4) //Chunks of cardinal directions
+ final_zone_connections[z_level_order[j/4]] += temp
+ temp = list()
+
+ for(var/turf/space/S in turfs_needing_destinations) //replace the identity zone with the destination z-level
+ var/list/directions = final_zone_connections[S.transition]
+ if(S.x <= TRANSITIONEDGE)
+ S.transition = directions[Z_WEST]
+ else if(S.x >= (world.maxx - TRANSITIONEDGE - 1))
+ S.transition = directions[Z_EAST]
+ else if(S.y <= TRANSITIONEDGE)
+ S.transition = directions[Z_SOUTH]
+ else
+ S.transition = directions[Z_NORTH]
+
+ S.Assign_Destination()
\ No newline at end of file
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 5e74b05aa31..c5a7f9d6c33 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -27,10 +27,8 @@
/turf/New()
..()
- for(var/atom/movable/AM as mob|obj in src)
- spawn( 0 )
- src.Entered(AM)
- return
+ for(var/atom/movable/AM in src)
+ Entered(AM)
return
// Adds the adjacent turfs to the current atmos processing
@@ -50,9 +48,6 @@
return 0
/turf/Enter(atom/movable/mover as mob|obj, atom/forget as mob|obj|turf|area)
- if(movement_disabled && usr.ckey != movement_disabled_exception)
- usr << "Movement is admin-disabled." //This is to identify lag problems
- return
if (!mover)
return 1
// First, make sure it can leave its square
@@ -85,28 +80,7 @@
return 0
return 1 //Nothing found to block so return success!
-/turf/Entered(atom/atom as mob|obj)
- if(movement_disabled)
- usr << "Movement is admin-disabled." //This is to identify lag problems
- return
- ..()
-//vvvvv Infared beam stuff vvvvv
-
- if ((atom && atom.density && !( istype(atom, /obj/effect/beam) )))
- for(var/obj/effect/beam/i_beam/I in src)
- spawn( 0 )
- if (I)
- I.hit()
- break
-
-//^^^^^ Infared beam stuff ^^^^^
-
- if(!istype(atom, /atom/movable))
- return
-
- var/atom/movable/M = atom
-
- var/loopsanity = 100
+/turf/Entered(atom/movable/M)
if(ismob(M))
var/mob/O = M
if(!O.lastarea)
@@ -117,16 +91,13 @@
inertial_drift(O)
else if(!istype(src, /turf/space))
O.inertia_dir = 0
- ..()
- var/objects = 0
- for(var/atom/A as mob|obj|turf|area in range(1))
- if(objects > loopsanity) break
- objects++
- spawn( 0 )
- if ((A && M))
- A.HasProximity(M, 1)
- return
- return
+
+ var/loopsanity = 100
+ for(var/atom/A in range(1))
+ if(loopsanity == 0)
+ break
+ loopsanity--
+ A.HasProximity(M, 1)
/turf/proc/is_plating()
return 0
@@ -140,6 +111,18 @@
return 0
/turf/proc/is_wood_floor()
return 0
+/turf/proc/is_gold_floor()
+ return 0
+/turf/proc/is_silver_floor()
+ return 0
+/turf/proc/is_plasma_floor()
+ return 0
+/turf/proc/is_uranium_floor()
+ return 0
+/turf/proc/is_bananium_floor()
+ return 0
+/turf/proc/is_diamond_floor()
+ return 0
/turf/proc/is_carpet_floor()
return 0
/turf/proc/return_siding_icon_state() //used for grass floors, which have siding.
diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm
index f87c93a181c..c7d9b68037d 100644
--- a/code/modules/admin/DB ban/functions.dm
+++ b/code/modules/admin/DB ban/functions.dm
@@ -75,7 +75,7 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration =
computerid = bancid
ip = banip
- var/DBQuery/query = dbcon.NewQuery("SELECT id FROM erro_player WHERE ckey = '[ckey]'")
+ var/DBQuery/query = dbcon.NewQuery("SELECT id FROM [format_table_name("player")] WHERE ckey = '[ckey]'")
query.Execute()
var/validckey = 0
if(query.NextRow())
@@ -116,7 +116,7 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration =
reason = sql_sanitize_text(reason)
if(maxadminbancheck)
- var/DBQuery/adm_query = dbcon.NewQuery("SELECT count(id) AS num FROM erro_ban WHERE (a_ckey = '[a_ckey]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
+ var/DBQuery/adm_query = dbcon.NewQuery("SELECT count(id) AS num FROM [format_table_name("ban")] WHERE (a_ckey = '[a_ckey]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
adm_query.Execute()
if(adm_query.NextRow())
var/adm_bans = text2num(adm_query.item[1])
@@ -124,10 +124,10 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration =
usr << "You already logged [MAX_ADMIN_BANS_PER_ADMIN] admin ban(s) or more. Do not abuse this function!"
return
- var/sql = "INSERT INTO erro_ban (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`) VALUES (null, Now(), '[serverip]', '[bantype_str]', '[reason]', '[job]', [(duration)?"[duration]":"0"], [(rounds)?"[rounds]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[ckey]', '[computerid]', '[ip]', '[a_ckey]', '[a_computerid]', '[a_ip]', '[who]', '[adminwho]', '', null, null, null, null, null)"
+ var/sql = "INSERT INTO [format_table_name("ban")] (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`) VALUES (null, Now(), '[serverip]', '[bantype_str]', '[reason]', '[job]', [(duration)?"[duration]":"0"], [(rounds)?"[rounds]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[ckey]', '[computerid]', '[ip]', '[a_ckey]', '[a_computerid]', '[a_ip]', '[who]', '[adminwho]', '', null, null, null, null, null)"
var/DBQuery/query_insert = dbcon.NewQuery(sql)
query_insert.Execute()
- usr << "Ban saved to database."
+ usr << "Ban saved to database."
message_admins("[key_name_admin(usr)] has added a [bantype_str] for [ckey] [(job)?"([job])":""] [(duration > 0)?"([duration] minutes)":""] with the reason: \"[reason]\" to the ban database.",1)
if(announceinirc)
@@ -178,7 +178,7 @@ datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "")
else
bantype_sql = "bantype = '[bantype_str]'"
- var/sql = "SELECT id FROM erro_ban WHERE ckey = '[ckey]' AND [bantype_sql] AND (unbanned is null OR unbanned = false)"
+ var/sql = "SELECT id FROM [format_table_name("ban")] WHERE ckey = '[ckey]' AND [bantype_sql] AND (unbanned is null OR unbanned = false)"
if(job)
sql += " AND job = '[job]'"
@@ -219,7 +219,7 @@ datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null)
usr << "Cancelled"
return
- var/DBQuery/query = dbcon.NewQuery("SELECT ckey, duration, reason FROM erro_ban WHERE id = [banid]")
+ var/DBQuery/query = dbcon.NewQuery("SELECT ckey, duration, reason FROM [format_table_name("ban")] WHERE id = [banid]")
query.Execute()
var/eckey = usr.ckey //Editing admin ckey
@@ -247,7 +247,7 @@ datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null)
usr << "Cancelled"
return
- var/DBQuery/update_query = dbcon.NewQuery("UPDATE erro_ban SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from \\\"[reason]\\\" to \\\"[value]\\\" ') WHERE id = [banid]")
+ var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("ban")] SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from \\\"[reason]\\\" to \\\"[value]\\\" ') WHERE id = [banid]")
update_query.Execute()
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s reason from [reason] to [value]",1)
if("duration")
@@ -257,7 +257,7 @@ datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null)
usr << "Cancelled"
return
- var/DBQuery/update_query = dbcon.NewQuery("UPDATE erro_ban SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value] '), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]")
+ var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("ban")] SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value] '), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]")
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s duration from [duration] to [value]",1)
update_query.Execute()
if("unban")
@@ -275,7 +275,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
if(!check_rights(R_BAN)) return
- var/sql = "SELECT ckey FROM erro_ban WHERE id = [id]"
+ var/sql = "SELECT ckey FROM [format_table_name("ban")] WHERE id = [id]"
establish_db_connection()
if(!dbcon.IsConnected())
@@ -305,7 +305,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
var/unban_computerid = src.owner:computer_id
var/unban_ip = src.owner:address
- var/sql_update = "UPDATE erro_ban SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey = '[unban_ckey]', unbanned_computerid = '[unban_computerid]', unbanned_ip = '[unban_ip]' WHERE id = [id]"
+ var/sql_update = "UPDATE [format_table_name("ban")] SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey = '[unban_ckey]', unbanned_computerid = '[unban_computerid]', unbanned_ip = '[unban_ip]' WHERE id = [id]"
message_admins("[key_name_admin(usr)] has lifted [pckey]'s ban.",1)
var/DBQuery/query_update = dbcon.NewQuery(sql_update)
@@ -365,7 +365,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
output += ""
for(var/j in nonhuman_positions)
output += ""
- for(var/j in list("traitor","changeling","operative","revolutionary","cultist","wizard"))
+ for(var/j in list("traitor","changeling","operative","revolutionary", "gangster","cultist","wizard"))
output += ""
output += ""
output += "Reason:
"
@@ -409,7 +409,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
if(playerckey)
playersearch = "AND ckey = '[playerckey]' "
- var/DBQuery/select_query = dbcon.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits FROM erro_ban WHERE 1 [playersearch] [adminsearch] ORDER BY bantime DESC")
+ var/DBQuery/select_query = dbcon.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits FROM [format_table_name("ban")] WHERE 1 [playersearch] [adminsearch] ORDER BY bantime DESC")
select_query.Execute()
while(select_query.NextRow())
diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm
index b354b25d031..404d7c07a06 100644
--- a/code/modules/admin/IsBanned.dm
+++ b/code/modules/admin/IsBanned.dm
@@ -16,7 +16,7 @@ world/IsBanned(key,address,computer_id)
diary << "Ban database connection failure. Admin [ckeytext] not checked"
return
- var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM erro_ban WHERE (ckey = '[ckeytext]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
+ var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
query.Execute()
@@ -44,7 +44,7 @@ world/IsBanned(key,address,computer_id)
//Guest Checking
if(!guests_allowed && IsGuestKey(key))
log_access("Failed Login: [key] - Guests not allowed")
- message_admins("Failed Login: [key] - Guests not allowed")
+ message_admins("Failed Login: [key] - Guests not allowed")
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.")
if(config.ban_legacy_system)
@@ -53,7 +53,7 @@ world/IsBanned(key,address,computer_id)
. = CheckBan( ckey(key), computer_id, address )
if(.)
log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
- message_admins("Failed Login: [key] id:[computer_id] ip:[address] - Banned [.["reason"]]")
+ message_admins("Failed Login: [key] id:[computer_id] ip:[address] - Banned [.["reason"]]")
return .
return ..() //default pager ban stuff
@@ -80,7 +80,7 @@ world/IsBanned(key,address,computer_id)
failedcid = 0
cidquery = " OR computerid = '[computer_id]' "
- var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM erro_ban WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
+ var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
query.Execute()
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index bb2de77eb09..3459e1ebe67 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -6,7 +6,6 @@ var/global/floorIsLava = 0
////////////////////////////////
/proc/message_admins(var/msg)
msg = "ADMIN LOG:[msg]"
- log_adminwarn(msg)
admins << msg
@@ -434,7 +433,10 @@ var/global/floorIsLava = 0
dat += {"
Fun Secrets
+ Reset Thunderdome to default state
+ Trigger a Virus Outbreak Turn all humans into monkeys
+ Change the species of all humans Make all areas powered Make all areas unpowered Power all SMES
@@ -442,6 +444,7 @@ var/global/floorIsLava = 0
Everyone is the traitor Summon Guns Summon Magic
+ Summon Events (Toggle) There can only be one! Make all players retarded Egalitarian Station Mode
@@ -488,7 +491,7 @@ var/global/floorIsLava = 0
if(confirm == "Cancel")
return
if(confirm == "Yes")
- world << "Restarting world! Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key]!"
+ world << "Restarting world! Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key]!"
log_admin("[key_name(usr)] initiated a reboot.")
feedback_set_details("end_error","admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]")
@@ -511,7 +514,7 @@ var/global/floorIsLava = 0
if(message)
if(!check_rights(R_SERVER,0))
message = adminscrub(message,500)
- world << "[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:\n \t [message]"
+ world << "[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:\n \t [message]"
log_admin("Announce: [key_name(usr)] : [message]")
feedback_add_details("admin_verb","A") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -532,7 +535,7 @@ var/global/floorIsLava = 0
else
message_admins("[key_name(usr)] set the admin notice.")
log_admin("[key_name(usr)] set the admin notice:\n[new_admin_notice]")
- world << "Admin Notice:\n \t [new_admin_notice]"
+ world << "Admin Notice:\n \t [new_admin_notice]"
feedback_add_details("admin_verb","SAN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
admin_notice = new_admin_notice
return
@@ -592,7 +595,7 @@ var/global/floorIsLava = 0
else
world << "New players may now enter the game."
log_admin("[key_name(usr)] toggled new player game entering.")
- message_admins("[key_name_admin(usr)] toggled new player game entering.", 1)
+ message_admins("[key_name_admin(usr)] toggled new player game entering.", 1)
world.update_status()
feedback_add_details("admin_verb","TE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -618,7 +621,7 @@ var/global/floorIsLava = 0
world << "You may now respawn."
else
world << "You may no longer respawn :("
- message_admins("[key_name_admin(usr)] toggled respawn to [abandon_allowed ? "On" : "Off"].", 1)
+ message_admins("[key_name_admin(usr)] toggled respawn to [abandon_allowed ? "On" : "Off"].", 1)
log_admin("[key_name(usr)] toggled respawn to [abandon_allowed ? "On" : "Off"].")
world.update_status()
feedback_add_details("admin_verb","TR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -645,7 +648,7 @@ var/global/floorIsLava = 0
if(!usr.client.holder) return
if( alert("Reboot server?",,"Yes","No") == "No")
return
- world << "Rebooting world!Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key]!"
+ world << "Rebooting world!Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key]!"
log_admin("[key_name(usr)] initiated an immediate reboot.")
feedback_set_details("end_error","immediate admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]")
@@ -759,7 +762,7 @@ var/global/floorIsLava = 0
else
world << "Guests may now enter the game."
log_admin("[key_name(usr)] toggled guests game entering [guests_allowed?"":"dis"]allowed.")
- message_admins("[key_name_admin(usr)] toggled guests game entering [guests_allowed?"":"dis"]allowed.", 1)
+ message_admins("[key_name_admin(usr)] toggled guests game entering [guests_allowed?"":"dis"]allowed.", 1)
feedback_add_details("admin_verb","TGU") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/unjobban_panel()
diff --git a/code/modules/admin/admin_memo.dm b/code/modules/admin/admin_memo.dm
index b3f9e451ee3..89f9116aeaf 100644
--- a/code/modules/admin/admin_memo.dm
+++ b/code/modules/admin/admin_memo.dm
@@ -21,13 +21,15 @@
if(null)
return
if("")
+ message_admins("[src.ckey] removed their own Memo")
+ log_admin("[src.ckey] removed their own Memo")
F.dir.Remove(ckey)
- src << "Memo removed"
return
if( findtext(memo,"
+
+
+
+
+
+ Visit our IRC channel: #tgstation13 on irc.rizon.net
+
+
+
+
+
+
+
+ Current Project Maintainers:-Click Here-
+ Currently Active GitHub contributor list:-Click Here-
+ Coders: TLE, NEO, Errorage, muskets, veryinky, Skie, Noise, Numbers, Agouri, Noka, Urist McDorf, Uhangi, Darem, Mport, rastaf0, Doohl, Superxpdude, Rockdtben, ConstantA, Petethegoat, Kor, Polymorph, Carn, Nodrak, Donkie, Sieve, Giacom, Ikarrus, trubble_bass, Aranclanos, Cael_Aislinn, Cheridan, Intigracy, Malkevin, SuperSayu, DumpDavidson, Tastyfish, Yvar, Elo001, Fleure, ManeaterMildred, Miauw, MrPerson
+ Spriters: Agouri, Cheridan, Cruazy Guest, Deeaych, Deuryn, Matty406, Microwave, ShiftyEyesShady, Skie, Uhangi, Veyveyr, Petethegoat, Kor, Ricotez, Ausops, TankNut, Pewtershmitz, Firecage, Nienhaus2
+ Sounds: Skie, Lasty/Vinyl
+ Main Testers: Tenebrosity, Anyone who has submitted a bug to the issue tracker
+ Thanks to: Baystation 12, /vg/station, NTstation, CDK Station devs, FacepunchStation, GoonStation devs, the original SpaceStation developers and Invisty for the title image. Also a thanks to anybody who has contributed who is not listed here :( Ask to be added here on irc.
+ Have a bug to report? Visit our Issue Tracker.
+ Please ensure that the bug has not already been reported and use the template provided here.
+
+
+
+
+
diff --git a/icons/PSD files/locker_template.psd b/icons/PSD files/locker_template.psd
new file mode 100644
index 00000000000..9e88ad90eda
Binary files /dev/null and b/icons/PSD files/locker_template.psd differ
diff --git a/icons/mecha/mech_construct.dmi b/icons/mecha/mech_construct.dmi
index 4eb606b1aea..bdce08c8022 100644
Binary files a/icons/mecha/mech_construct.dmi and b/icons/mecha/mech_construct.dmi differ
diff --git a/icons/mecha/mech_construction.dmi b/icons/mecha/mech_construction.dmi
index d7f3722c64a..d0a145caff5 100644
Binary files a/icons/mecha/mech_construction.dmi and b/icons/mecha/mech_construction.dmi differ
diff --git a/icons/mecha/mecha.dmi b/icons/mecha/mecha.dmi
index 060554e4d71..772b4fa1513 100644
Binary files a/icons/mecha/mecha.dmi and b/icons/mecha/mecha.dmi differ
diff --git a/icons/mob/alien.dmi b/icons/mob/alien.dmi
index f679da87931..4cefc09930b 100644
Binary files a/icons/mob/alien.dmi and b/icons/mob/alien.dmi differ
diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi
index de5a8113a54..6466f049aed 100644
Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ
diff --git a/icons/mob/back.dmi b/icons/mob/back.dmi
index 5c0f93e93d8..23555098a29 100644
Binary files a/icons/mob/back.dmi and b/icons/mob/back.dmi differ
diff --git a/icons/mob/corgi_back.dmi b/icons/mob/corgi_back.dmi
index 2947ea587cb..ced75e39a42 100644
Binary files a/icons/mob/corgi_back.dmi and b/icons/mob/corgi_back.dmi differ
diff --git a/icons/mob/corgi_head.dmi b/icons/mob/corgi_head.dmi
index 411dbb988c7..e9fdbd53072 100644
Binary files a/icons/mob/corgi_head.dmi and b/icons/mob/corgi_head.dmi differ
diff --git a/icons/mob/drone.dmi b/icons/mob/drone.dmi
new file mode 100644
index 00000000000..b5437a95d89
Binary files /dev/null and b/icons/mob/drone.dmi differ
diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi
index 9683a624847..b55685323e7 100644
Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ
diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi
index f5bfde269cb..e0bf5ed4cb0 100644
Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ
diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi
index 5530db7dc60..648866f97d7 100644
Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ
diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi
index 6446a854770..47328e6fa81 100644
Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ
diff --git a/icons/mob/items_lefthand.dmi b/icons/mob/items_lefthand.dmi
index 6285e998e27..dad29da8b55 100644
Binary files a/icons/mob/items_lefthand.dmi and b/icons/mob/items_lefthand.dmi differ
diff --git a/icons/mob/items_righthand.dmi b/icons/mob/items_righthand.dmi
index 15e87b5f724..6b34620664a 100644
Binary files a/icons/mob/items_righthand.dmi and b/icons/mob/items_righthand.dmi differ
diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi
index 28451ff9fc2..2cfaf2b0015 100644
Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ
diff --git a/icons/mob/screen_alien.dmi b/icons/mob/screen_alien.dmi
index 255a03d9919..8d58cdba6c8 100644
Binary files a/icons/mob/screen_alien.dmi and b/icons/mob/screen_alien.dmi differ
diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi
index 5bc9546152e..f4292641d52 100644
Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ
diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi
index 94ff50ba91a..21b840b0fda 100644
Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ
diff --git a/icons/obj/atmospherics/pipe_manifold.dmi b/icons/obj/atmospherics/pipe_manifold.dmi
index a252c8ac8a8..f516eac7da9 100644
Binary files a/icons/obj/atmospherics/pipe_manifold.dmi and b/icons/obj/atmospherics/pipe_manifold.dmi differ
diff --git a/icons/obj/atmospherics/red_pipe.dmi b/icons/obj/atmospherics/red_pipe.dmi
index ff9d9e8a59a..a5a84439efe 100644
Binary files a/icons/obj/atmospherics/red_pipe.dmi and b/icons/obj/atmospherics/red_pipe.dmi differ
diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi
index bb4c308ca05..27190678b95 100644
Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ
diff --git a/icons/obj/contraband.dmi b/icons/obj/contraband.dmi
index c5914bb5876..03f6c8d17f8 100644
Binary files a/icons/obj/contraband.dmi and b/icons/obj/contraband.dmi differ
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index db879f05ce4..e68aa0b2318 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/icons/obj/doors/door_assembly.dmi b/icons/obj/doors/door_assembly.dmi
index 94b91be6c09..94ed8ac6c2d 100644
Binary files a/icons/obj/doors/door_assembly.dmi and b/icons/obj/doors/door_assembly.dmi differ
diff --git a/icons/obj/doors/doorviro.dmi b/icons/obj/doors/doorviro.dmi
new file mode 100644
index 00000000000..fbf35abdef5
Binary files /dev/null and b/icons/obj/doors/doorviro.dmi differ
diff --git a/icons/obj/doors/doorviroglass.dmi b/icons/obj/doors/doorviroglass.dmi
new file mode 100644
index 00000000000..250a82be855
Binary files /dev/null and b/icons/obj/doors/doorviroglass.dmi differ
diff --git a/icons/obj/food.dmi b/icons/obj/food.dmi
index a2a27697840..b54a3b38536 100644
Binary files a/icons/obj/food.dmi and b/icons/obj/food.dmi differ
diff --git a/icons/obj/gun.dmi b/icons/obj/gun.dmi
index c76b374a7cb..65ed8cb6deb 100644
Binary files a/icons/obj/gun.dmi and b/icons/obj/gun.dmi differ
diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi
index 95f63945904..985c7403434 100644
Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ
diff --git a/icons/obj/machines/turret_control.dmi b/icons/obj/machines/turret_control.dmi
new file mode 100644
index 00000000000..b7c81cd923e
Binary files /dev/null and b/icons/obj/machines/turret_control.dmi differ
diff --git a/icons/obj/objects.dmi b/icons/obj/objects.dmi
index 99650ce656c..201a73b0905 100644
Binary files a/icons/obj/objects.dmi and b/icons/obj/objects.dmi differ
diff --git a/icons/obj/pipes.dmi b/icons/obj/pipes.dmi
index 59909fb6f54..25d15984b4c 100644
Binary files a/icons/obj/pipes.dmi and b/icons/obj/pipes.dmi differ
diff --git a/icons/obj/pipes/heat.dmi b/icons/obj/pipes/heat.dmi
index 6d1ed47e7ef..4b6f4b7b741 100644
Binary files a/icons/obj/pipes/heat.dmi and b/icons/obj/pipes/heat.dmi differ
diff --git a/icons/obj/pipes/junction.dmi b/icons/obj/pipes/junction.dmi
index 70286bde155..88d96929eaa 100644
Binary files a/icons/obj/pipes/junction.dmi and b/icons/obj/pipes/junction.dmi differ
diff --git a/icons/obj/power_cond/power_cond_blue.dmi b/icons/obj/power_cond/power_cond_blue.dmi
index e224fa549c3..5cd500c4f10 100644
Binary files a/icons/obj/power_cond/power_cond_blue.dmi and b/icons/obj/power_cond/power_cond_blue.dmi differ
diff --git a/icons/obj/power_cond/power_cond_cyan.dmi b/icons/obj/power_cond/power_cond_cyan.dmi
index 34d981f55f7..742d1f76eab 100644
Binary files a/icons/obj/power_cond/power_cond_cyan.dmi and b/icons/obj/power_cond/power_cond_cyan.dmi differ
diff --git a/icons/obj/power_cond/power_cond_green.dmi b/icons/obj/power_cond/power_cond_green.dmi
index c8aa279bc29..d7a391d505b 100644
Binary files a/icons/obj/power_cond/power_cond_green.dmi and b/icons/obj/power_cond/power_cond_green.dmi differ
diff --git a/icons/obj/power_cond/power_cond_orange.dmi b/icons/obj/power_cond/power_cond_orange.dmi
index e3c3d0aa8c8..4777ddd6654 100644
Binary files a/icons/obj/power_cond/power_cond_orange.dmi and b/icons/obj/power_cond/power_cond_orange.dmi differ
diff --git a/icons/obj/power_cond/power_cond_pink.dmi b/icons/obj/power_cond/power_cond_pink.dmi
index 931d486e1e2..5ebda7c9899 100644
Binary files a/icons/obj/power_cond/power_cond_pink.dmi and b/icons/obj/power_cond/power_cond_pink.dmi differ
diff --git a/icons/obj/power_cond/power_cond_red.dmi b/icons/obj/power_cond/power_cond_red.dmi
index 962936479ae..ffa8eb2405f 100644
Binary files a/icons/obj/power_cond/power_cond_red.dmi and b/icons/obj/power_cond/power_cond_red.dmi differ
diff --git a/icons/obj/power_cond/power_cond_white.dmi b/icons/obj/power_cond/power_cond_white.dmi
index 9036341ee13..313348dc859 100644
Binary files a/icons/obj/power_cond/power_cond_white.dmi and b/icons/obj/power_cond/power_cond_white.dmi differ
diff --git a/icons/obj/power_cond/power_cond_yellow.dmi b/icons/obj/power_cond/power_cond_yellow.dmi
index 7506cc23857..908e22b7788 100644
Binary files a/icons/obj/power_cond/power_cond_yellow.dmi and b/icons/obj/power_cond/power_cond_yellow.dmi differ
diff --git a/icons/obj/power_cond/power_local.dmi b/icons/obj/power_cond/power_local.dmi
index b2b4373505b..f23a456c177 100644
Binary files a/icons/obj/power_cond/power_local.dmi and b/icons/obj/power_cond/power_local.dmi differ
diff --git a/icons/obj/statue.dmi b/icons/obj/statue.dmi
index 46dec2a0033..e598551ae84 100644
Binary files a/icons/obj/statue.dmi and b/icons/obj/statue.dmi differ
diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi
index 1ae599f3511..b6789863ebc 100644
Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ
diff --git a/icons/obj/wizard.dmi b/icons/obj/wizard.dmi
index 4f8a97b2475..b87ea13bf30 100644
Binary files a/icons/obj/wizard.dmi and b/icons/obj/wizard.dmi differ
diff --git a/icons/turf/areas.dmi b/icons/turf/areas.dmi
index 19ae3bde070..738a6964f27 100644
Binary files a/icons/turf/areas.dmi and b/icons/turf/areas.dmi differ
diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi
index 54387ecdb04..3aac66228a6 100644
Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ
diff --git a/icons/turf/walls.dmi b/icons/turf/walls.dmi
index fc4c615a4b5..6d65684a300 100644
Binary files a/icons/turf/walls.dmi and b/icons/turf/walls.dmi differ
diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm
index a63f92049a3..f9153693e70 100644
--- a/interface/stylesheet.dm
+++ b/interface/stylesheet.dm
@@ -54,6 +54,7 @@ h1.alert, h2.alert {color: #000000;}
.info {color: #0000CC;}
.notice {color: #000099;}
.boldnotice {color: #000099; font-weight: bold;}
+.adminnotice {color: #0000ff;}
.unconscious {color: #0000ff; font-weight: bold;}
.suicide {color: #ff5050; font-style: italic;}
diff --git a/sound/AI/aimalf.ogg b/sound/AI/aimalf.ogg
index 50b7688d5ae..b7996916b47 100644
Binary files a/sound/AI/aimalf.ogg and b/sound/AI/aimalf.ogg differ
diff --git a/sound/AI/intercept.ogg b/sound/AI/intercept.ogg
index 040b4e4f8db..3569a07d401 100644
Binary files a/sound/AI/intercept.ogg and b/sound/AI/intercept.ogg differ
diff --git a/sound/misc/notice1.ogg b/sound/misc/notice1.ogg
new file mode 100644
index 00000000000..da6454ce3cf
Binary files /dev/null and b/sound/misc/notice1.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index da6e81f5e41..2c2a61f85cf 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -30,6 +30,7 @@
#include "code\__DEFINES\sight.dm"
#include "code\__DEFINES\stat.dm"
#include "code\__HELPERS\_logging.dm"
+#include "code\__HELPERS\cmp.dm"
#include "code\__HELPERS\files.dm"
#include "code\__HELPERS\game.dm"
#include "code\__HELPERS\global_lists.dm"
@@ -44,6 +45,10 @@
#include "code\__HELPERS\time.dm"
#include "code\__HELPERS\type2type.dm"
#include "code\__HELPERS\unsorted.dm"
+#include "code\__HELPERS\sorts\__main.dm"
+#include "code\__HELPERS\sorts\InsertSort.dm"
+#include "code\__HELPERS\sorts\MergeSort.dm"
+#include "code\__HELPERS\sorts\TimSort.dm"
#include "code\_globalvars\configuration.dm"
#include "code\_globalvars\database.dm"
#include "code\_globalvars\game_modes.dm"
@@ -71,6 +76,7 @@
#include "code\_onclick\hud\ai.dm"
#include "code\_onclick\hud\alien.dm"
#include "code\_onclick\hud\alien_larva.dm"
+#include "code\_onclick\hud\drones.dm"
#include "code\_onclick\hud\hud.dm"
#include "code\_onclick\hud\human.dm"
#include "code\_onclick\hud\monkey.dm"
@@ -220,7 +226,9 @@
#include "code\game\atoms.dm"
#include "code\game\atoms_movable.dm"
#include "code\game\communications.dm"
+#include "code\game\data_huds.dm"
#include "code\game\dna.dm"
+#include "code\game\say.dm"
#include "code\game\shuttle_engines.dm"
#include "code\game\skincmd.dm"
#include "code\game\smoothwall.dm"
@@ -276,6 +284,7 @@
#include "code\game\gamemodes\cult\runes.dm"
#include "code\game\gamemodes\cult\talisman.dm"
#include "code\game\gamemodes\extended\extended.dm"
+#include "code\game\gamemodes\gang\gang.dm"
#include "code\game\gamemodes\malfunction\Malf_Modules.dm"
#include "code\game\gamemodes\malfunction\malfunction.dm"
#include "code\game\gamemodes\meteor\meteor.dm"
@@ -501,6 +510,7 @@
#include "code\game\objects\items\devices\multitool.dm"
#include "code\game\objects\items\devices\paicard.dm"
#include "code\game\objects\items\devices\powersink.dm"
+#include "code\game\objects\items\devices\recaller.dm"
#include "code\game\objects\items\devices\scanners.dm"
#include "code\game\objects\items\devices\taperecorder.dm"
#include "code\game\objects\items\devices\traitordevices.dm"
@@ -531,6 +541,7 @@
#include "code\game\objects\items\stacks\sheets\sheets.dm"
#include "code\game\objects\items\stacks\tiles\light.dm"
#include "code\game\objects\items\stacks\tiles\plasteel.dm"
+#include "code\game\objects\items\stacks\tiles\tile_mineral.dm"
#include "code\game\objects\items\stacks\tiles\tile_types.dm"
#include "code\game\objects\items\weapons\AI_modules.dm"
#include "code\game\objects\items\weapons\airlock_painter.dm"
@@ -622,6 +633,7 @@
#include "code\game\objects\structures\OpTable.dm"
#include "code\game\objects\structures\safe.dm"
#include "code\game\objects\structures\signs.dm"
+#include "code\game\objects\structures\statues.dm"
#include "code\game\objects\structures\tables_racks.dm"
#include "code\game\objects\structures\tank_dispenser.dm"
#include "code\game\objects\structures\target_stake.dm"
@@ -661,11 +673,13 @@
#include "code\game\objects\structures\transit_tubes\station.dm"
#include "code\game\objects\structures\transit_tubes\transit_tube.dm"
#include "code\game\objects\structures\transit_tubes\transit_tube_pod.dm"
+#include "code\game\pooling\atom_pool.dm"
#include "code\game\turfs\simulated.dm"
#include "code\game\turfs\turf.dm"
#include "code\game\turfs\unsimulated.dm"
#include "code\game\turfs\simulated\dirtystation.dm"
#include "code\game\turfs\simulated\floor.dm"
+#include "code\game\turfs\simulated\floor_mineral.dm"
#include "code\game\turfs\simulated\floor_types.dm"
#include "code\game\turfs\simulated\walls.dm"
#include "code\game\turfs\simulated\walls_mineral.dm"
@@ -842,6 +856,21 @@
#include "code\modules\events\wormholes.dm"
#include "code\modules\events\holiday\halloween.dm"
#include "code\modules\events\holiday\xmas.dm"
+#include "code\modules\events\wizard\aid.dm"
+#include "code\modules\events\wizard\blobies.dm"
+#include "code\modules\events\wizard\curseditems.dm"
+#include "code\modules\events\wizard\departmentrevolt.dm"
+#include "code\modules\events\wizard\fakeexplosion.dm"
+#include "code\modules\events\wizard\ghost.dm"
+#include "code\modules\events\wizard\greentext.dm"
+#include "code\modules\events\wizard\imposter.dm"
+#include "code\modules\events\wizard\invincible.dm"
+#include "code\modules\events\wizard\lava.dm"
+#include "code\modules\events\wizard\magicarp.dm"
+#include "code\modules\events\wizard\petsplosion.dm"
+#include "code\modules\events\wizard\race.dm"
+#include "code\modules\events\wizard\shuffle.dm"
+#include "code\modules\events\wizard\summons.dm"
#include "code\modules\flufftext\Dreaming.dm"
#include "code\modules\flufftext\Hallucination.dm"
#include "code\modules\flufftext\TextFilters.dm"
@@ -937,6 +966,7 @@
#include "code\modules\mob\living\carbon\carbon_defines.dm"
#include "code\modules\mob\living\carbon\emote.dm"
#include "code\modules\mob\living\carbon\inventory.dm"
+#include "code\modules\mob\living\carbon\say.dm"
#include "code\modules\mob\living\carbon\update_icons.dm"
#include "code\modules\mob\living\carbon\alien\alien.dm"
#include "code\modules\mob\living\carbon\alien\alien_defense.dm"
@@ -1032,12 +1062,8 @@
#include "code\modules\mob\living\silicon\ai\freelook\eye.dm"
#include "code\modules\mob\living\silicon\ai\freelook\read_me.dm"
#include "code\modules\mob\living\silicon\ai\freelook\update_triggers.dm"
-#include "code\modules\mob\living\silicon\decoy\death.dm"
-#include "code\modules\mob\living\silicon\decoy\decoy.dm"
-#include "code\modules\mob\living\silicon\decoy\life.dm"
#include "code\modules\mob\living\silicon\pai\death.dm"
#include "code\modules\mob\living\silicon\pai\examine.dm"
-#include "code\modules\mob\living\silicon\pai\hud.dm"
#include "code\modules\mob\living\silicon\pai\life.dm"
#include "code\modules\mob\living\silicon\pai\pai.dm"
#include "code\modules\mob\living\silicon\pai\personality.dm"
@@ -1063,6 +1089,7 @@
#include "code\modules\mob\living\simple_animal\friendly\cat.dm"
#include "code\modules\mob\living\simple_animal\friendly\corgi.dm"
#include "code\modules\mob\living\simple_animal\friendly\crab.dm"
+#include "code\modules\mob\living\simple_animal\friendly\drone.dm"
#include "code\modules\mob\living\simple_animal\friendly\farm_animals.dm"
#include "code\modules\mob\living\simple_animal\friendly\lizard.dm"
#include "code\modules\mob\living\simple_animal\friendly\mouse.dm"
diff --git a/tools/makeChangelog.bat b/tools/makeChangelog.bat
new file mode 100644
index 00000000000..f0646caeca0
--- /dev/null
+++ b/tools/makeChangelog.bat
@@ -0,0 +1,4 @@
+@echo off
+rem Cheridan asked for this. - N3X
+call python ss13_genchangelog.py ../html/changelog.html ../html/changelogs
+pause
\ No newline at end of file
diff --git a/tools/ss13_genchangelog.py b/tools/ss13_genchangelog.py
new file mode 100644
index 00000000000..ff908ba20b6
--- /dev/null
+++ b/tools/ss13_genchangelog.py
@@ -0,0 +1,212 @@
+'''
+Usage:
+ $ python ss13_genchangelog.py [--dry-run] html/changelog.html html/changelogs/
+
+ss13_genchangelog.py - Generate changelog from YAML.
+
+Copyright 2013 Rob "N3X15" Nelson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+'''
+
+from __future__ import print_function
+import yaml, os, glob, sys, re, time, argparse
+from datetime import datetime, date
+from time import time
+
+today = date.today()
+
+dateformat = "%d %B %Y"
+
+opt = argparse.ArgumentParser()
+opt.add_argument('-d', '--dry-run', dest='dryRun', default=False, action='store_true', help='Only parse changelogs and, if needed, the targetFile. (A .dry_changelog.yml will be output for debugging purposes.)')
+opt.add_argument('targetFile', help='The HTML changelog we wish to update.')
+opt.add_argument('ymlDir', help='The directory of YAML changelogs we will use.')
+
+args = opt.parse_args()
+
+all_changelog_entries = {}
+
+validPrefixes = [
+ 'bugfix',
+ 'wip',
+ 'tweak',
+ 'soundadd',
+ 'sounddel',
+ 'rscdel',
+ 'rscadd',
+ 'imageadd',
+ 'imagedel',
+ 'spellcheck',
+ 'experiment',
+ 'tgs'
+]
+
+def dictToTuples(inp):
+ return [(k, v) for k, v in inp.items()]
+
+changelog_cache = os.path.join(args.ymlDir, '.all_changelog.yml')
+
+failed_cache_read = True
+if os.path.isfile(changelog_cache):
+ try:
+ with open(changelog_cache) as f:
+ (_, all_changelog_entries) = yaml.load_all(f)
+ failed_cache_read = False
+
+ # Convert old timestamps to newer format.
+ new_entries = {}
+ for _date in all_changelog_entries.keys():
+ ty = type(_date).__name__
+ # print(ty)
+ if ty in ['str', 'unicode']:
+ temp_data = all_changelog_entries[_date]
+ _date = datetime.strptime(_date, dateformat).date()
+ new_entries[_date] = temp_data
+ else:
+ new_entries[_date] = all_changelog_entries[_date]
+ all_changelog_entries = new_entries
+ except Exception as e:
+ print("Failed to read cache:")
+ print(e, file=sys.stderr)
+
+if args.dryRun:
+ changelog_cache = os.path.join(args.ymlDir, '.dry_changelog.yml')
+
+if failed_cache_read and os.path.isfile(args.targetFile):
+ from bs4 import BeautifulSoup
+ from bs4.element import NavigableString
+ print(' Generating cache...')
+ with open(args.targetFile, 'r') as f:
+ soup = BeautifulSoup(f)
+ for e in soup.find_all('div', {'class':'commit'}):
+ entry = {}
+ date = datetime.strptime(e.h2.string.strip(), dateformat).date() # key
+ for authorT in e.find_all('h3', {'class':'author'}):
+ author = authorT.string
+ # Strip suffix
+ if author.endswith('updated:'):
+ author = author[:-8]
+ author = author.strip()
+
+ # Find
+ ulT = authorT.next_sibling
+ while(ulT.name != 'ul'):
+ ulT = ulT.next_sibling
+ changes = []
+
+ for changeT in ulT.children:
+ if changeT.name != 'li': continue
+ val = changeT.decode_contents(formatter="html")
+ newdat = {changeT['class'][0] + '': val + ''}
+ if newdat not in changes:
+ changes += [newdat]
+
+ if len(changes) > 0:
+ entry[author] = changes
+ if date in all_changelog_entries:
+ all_changelog_entries[date].update(entry)
+ else:
+ all_changelog_entries[date] = entry
+
+del_after = []
+print('Reading changelogs...')
+for fileName in glob.glob(os.path.join(args.ymlDir, "*.yml")):
+ name, ext = os.path.splitext(os.path.basename(fileName))
+ if name.startswith('.'): continue
+ if name == 'example': continue
+ fileName = os.path.abspath(fileName)
+ print(' Reading {}...'.format(fileName))
+ cl = {}
+ with open(fileName, 'r') as f:
+ cl = yaml.load(f)
+ f.close()
+ if today not in all_changelog_entries:
+ all_changelog_entries[today] = {}
+ author_entries = all_changelog_entries[today].get(cl['author'], [])
+ if len(cl['changes']):
+ new = 0
+ for change in cl['changes']:
+ if change not in author_entries:
+ (change_type, _) = dictToTuples(change)[0]
+ if change_type not in validPrefixes:
+ print(' {0}: Invalid prefix {1}'.format(fileName, change_type), file=sys.stderr)
+ author_entries += [change]
+ new += 1
+ all_changelog_entries[today][cl['author']] = author_entries
+ if new > 0:
+ print(' Added {0} new changelog entries.'.format(new))
+
+ if cl.get('delete-after', False):
+ if os.path.isfile(fileName):
+ if args.dryRun:
+ print(' Would delete {0} (delete-after set)...'.format(fileName))
+ else:
+ del_after += [fileName]
+
+ if args.dryRun: continue
+
+ cl['changes'] = []
+ with open(fileName, 'w') as f:
+ yaml.dump(cl, f, default_flow_style=False)
+
+targetDir = os.path.dirname(args.targetFile)
+
+with open(args.targetFile.replace('.htm', '.dry.htm') if args.dryRun else args.targetFile, 'w') as changelog:
+ with open(os.path.join(targetDir, 'templates', 'header.html'), 'r') as h:
+ for line in h:
+ changelog.write(line)
+
+ for _date in reversed(sorted(all_changelog_entries.keys())):
+ entry_htm = '\n'
+ entry_htm += '\t\t
\n'
+ entry_htm += '\t\t\t
{date}
\n'.format(date=_date.strftime(dateformat))
+ write_entry = False
+ for author in sorted(all_changelog_entries[_date].keys()):
+ if len(all_changelog_entries[_date]) == 0: continue
+ author_htm = '\t\t\t
{author} updated:
\n'.format(author=author)
+ author_htm += '\t\t\t
\n'
+ changes_added = []
+ for (css_class, change) in (dictToTuples(e)[0] for e in all_changelog_entries[_date][author]):
+ if change in changes_added: continue
+ write_entry = True
+ changes_added += [change]
+ author_htm += '\t\t\t\t
\n'
+ if write_entry:
+ changelog.write(entry_htm)
+
+ with open(os.path.join(targetDir, 'templates', 'footer.html'), 'r') as h:
+ for line in h:
+ changelog.write(line)
+
+
+with open(changelog_cache, 'w') as f:
+ cache_head = 'DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.'
+ yaml.dump_all([cache_head, all_changelog_entries], f, default_flow_style=False)
+
+if len(del_after):
+ print('Cleaning up...')
+ for fileName in del_after:
+ if os.path.isfile(fileName):
+ print(' Deleting {0} (delete-after set)...'.format(fileName))
+ os.remove(fileName)