mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-24 20:47:10 +01:00
Merge remote-tracking branch 'upstream/master' into flyswatter-fix
This commit is contained in:
@@ -2,13 +2,13 @@
|
||||
<!-- You can view Contributing.MD for a detailed description of the pull request process. -->
|
||||
|
||||
## What Does This PR Do
|
||||
<!-- Include a small to medium description of what your PR changes. Document every changes or this may delay review or even discourage maintainers from merging your PR! -->
|
||||
<!-- Include a small to medium description of what your PR changes. Document all changes, as not doing this may delay reviews or even discourage maintainers from merging your PR! -->
|
||||
|
||||
## Why It's Good For The Game
|
||||
<!-- Please add a short description of why you think these changes would benefit the game. If you can't justify it in words, it might not be worth adding. -->
|
||||
<!-- Add a short description of why you think these changes would benefit the game. If you can't justify it in words, it might not be worth adding. -->
|
||||
|
||||
## Images of changes
|
||||
<!-- If you did not make a map or sprite edit, you may delete this section. You may include a gif of your feature if you want -->
|
||||
<!-- If you did not make a map or sprite edit, you may delete this section. You may include a gif or mp4 of your feature if you want. -->
|
||||
|
||||
## Changelog
|
||||
:cl:
|
||||
@@ -27,3 +27,4 @@ experiment: Added an experimental thingy
|
||||
|
||||
<!-- Both :cl:'s are required for the changelog to work! You can put your name to the right of the first :cl: if you want to overwrite your GitHub username as author ingame. -->
|
||||
<!-- You can use multiple of the same prefix (they're only used for the icon ingame) and delete the unneeded ones. Despite some of the tags, changelogs should generally represent how a player might be affected by the changes rather than a summary of the PR's contents. -->
|
||||
<!-- If a PR has no impact on players (i.e. a code refactor that does not change functionality) then the entire Changelog heading and contents can be removed. -->
|
||||
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
tools/ci/install_byond.sh
|
||||
source $HOME/BYOND/byond/bin/byondsetup
|
||||
tools/ci/generate_maplist.sh
|
||||
tools/ci/dm.sh -Mci_map_testing paradise.dme
|
||||
tools/ci/dm.sh -DCIMAP paradise.dme
|
||||
|
||||
unit_tests_and_sql:
|
||||
name: Unit Tests + SQL Validation
|
||||
|
||||
Vendored
+4
-7
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"workbench.editorAssociations": [
|
||||
{
|
||||
"filenamePattern": "*.dmi",
|
||||
"viewType": "imagePreview.previewEditor"
|
||||
}
|
||||
]
|
||||
}
|
||||
"workbench.editorAssociations": {
|
||||
"*.dmi": "imagePreview.previewEditor"
|
||||
}
|
||||
}
|
||||
+22
-8
@@ -99,7 +99,7 @@ CREATE TABLE `customuseritems` (
|
||||
`cuiJobMask` text NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `cuiCKey` (`cuiCKey`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=56 DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=56 DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@@ -126,7 +126,7 @@ CREATE TABLE `death` (
|
||||
`fireloss` int(11) NOT NULL,
|
||||
`oxyloss` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=166546 DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=166546 DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@@ -241,7 +241,7 @@ CREATE TABLE `feedback` (
|
||||
`version` tinyint(3) UNSIGNED NOT NULL,
|
||||
`json` LONGTEXT NOT NULL COLLATE 'utf8mb4_general_ci',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=257638 DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=257638 DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@@ -277,6 +277,7 @@ CREATE TABLE `player` (
|
||||
`fupdate` smallint(4) DEFAULT '0',
|
||||
`parallax` tinyint(1) DEFAULT '8',
|
||||
`byond_date` DATE DEFAULT NULL,
|
||||
`2fa_status` ENUM('DISABLED','ENABLED_IP','ENABLED_ALWAYS') NOT NULL DEFAULT 'DISABLED' COLLATE 'utf8mb4_general_ci',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ckey` (`ckey`),
|
||||
KEY `lastseen` (`lastseen`),
|
||||
@@ -321,7 +322,7 @@ CREATE TABLE `karma` (
|
||||
`spenderip` text NOT NULL,
|
||||
`time` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=73614 DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=73614 DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@@ -338,7 +339,7 @@ CREATE TABLE `karmatotals` (
|
||||
`karmaspent` int(11) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `byondkey` (`byondkey`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=25715 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=25715 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@@ -359,7 +360,7 @@ CREATE TABLE `library` (
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ckey` (`ckey`),
|
||||
KEY `flagged` (`flagged`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=4537 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=4537 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@@ -375,7 +376,7 @@ CREATE TABLE `legacy_population` (
|
||||
`admincount` int(11) DEFAULT NULL,
|
||||
`time` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=2550 DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2550 DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@@ -392,7 +393,7 @@ CREATE TABLE `whitelist` (
|
||||
`species` mediumtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ckey` (`ckey`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=4080 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=4080 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||
|
||||
@@ -585,3 +586,16 @@ CREATE TABLE `round` (
|
||||
`station_name` VARCHAR(80) NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
|
||||
--
|
||||
-- Table structure for table `2fa_secrets`
|
||||
--
|
||||
CREATE TABLE `2fa_secrets` (
|
||||
`ckey` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
|
||||
`secret` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
|
||||
`date_setup` DATETIME NOT NULL DEFAULT current_timestamp(),
|
||||
`last_time` DATETIME NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`ckey`) USING BTREE
|
||||
)
|
||||
COLLATE='utf8mb4_general_ci' ENGINE=InnoDB;
|
||||
|
||||
@@ -98,7 +98,7 @@ CREATE TABLE `SS13_customuseritems` (
|
||||
`cuiPropAdjust` text,
|
||||
`cuiJobMask` text NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=56 DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=56 DEFAULT CHARSET=utf8mb4;
|
||||
ALTER TABLE `SS13_customuseritems` ADD INDEX(`cuiCKey`);
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@@ -126,7 +126,7 @@ CREATE TABLE `SS13_death` (
|
||||
`fireloss` int(11) NOT NULL,
|
||||
`oxyloss` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=166546 DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=166546 DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@@ -240,7 +240,7 @@ CREATE TABLE `SS13_feedback` (
|
||||
`version` tinyint(3) UNSIGNED NOT NULL,
|
||||
`json` LONGTEXT NOT NULL COLLATE 'utf8mb4_general_ci',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=257638 DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=257638 DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@@ -276,6 +276,7 @@ CREATE TABLE `SS13_player` (
|
||||
`fupdate` smallint(4) DEFAULT '0',
|
||||
`parallax` tinyint(1) DEFAULT '8',
|
||||
`byond_date` DATE DEFAULT NULL,
|
||||
`2fa_status` ENUM('DISABLED','ENABLED_IP','ENABLED_ALWAYS') NOT NULL DEFAULT 'DISABLED' COLLATE 'utf8mb4_general_ci',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ckey` (`ckey`),
|
||||
KEY `lastseen` (`lastseen`),
|
||||
@@ -320,7 +321,7 @@ CREATE TABLE `SS13_karma` (
|
||||
`spenderip` text NOT NULL,
|
||||
`time` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=73614 DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=73614 DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@@ -337,7 +338,7 @@ CREATE TABLE `SS13_karmatotals` (
|
||||
`karmaspent` int(11) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `byondkey` (`byondkey`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=25715 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=25715 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@@ -358,7 +359,7 @@ CREATE TABLE `SS13_library` (
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ckey` (`ckey`),
|
||||
KEY `flagged` (`flagged`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=4537 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=4537 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@@ -374,7 +375,7 @@ CREATE TABLE `SS13_legacy_population` (
|
||||
`admincount` int(11) DEFAULT NULL,
|
||||
`time` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=2550 DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2550 DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@@ -391,7 +392,7 @@ CREATE TABLE `SS13_whitelist` (
|
||||
`species` mediumtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ckey` (`ckey`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=4080 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=4080 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||
|
||||
@@ -582,3 +583,15 @@ CREATE TABLE `SS13_round` (
|
||||
`station_name` VARCHAR(80) NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
--
|
||||
-- Table structure for table `2fa_secrets`
|
||||
--
|
||||
CREATE TABLE `SS13_2fa_secrets` (
|
||||
`ckey` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
|
||||
`secret` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
|
||||
`date_setup` DATETIME NOT NULL DEFAULT current_timestamp(),
|
||||
`last_time` DATETIME NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`ckey`) USING BTREE
|
||||
)
|
||||
COLLATE='utf8mb4_general_ci' ENGINE=InnoDB;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# Updating SQL from version 22 to 23 -AffectedArc07
|
||||
# Converts existing MyISAM tables to InnoDB
|
||||
|
||||
ALTER TABLE `customuseritems` ENGINE=InnoDB;
|
||||
ALTER TABLE `death` ENGINE=InnoDB;
|
||||
ALTER TABLE `feedback` ENGINE=InnoDB;
|
||||
ALTER TABLE `karma` ENGINE=InnoDB;
|
||||
ALTER TABLE `karmatotals` ENGINE=InnoDB;
|
||||
ALTER TABLE `legacy_population` ENGINE=InnoDB;
|
||||
ALTER TABLE `library` ENGINE=InnoDB;
|
||||
ALTER TABLE `whitelist` ENGINE=InnoDB;
|
||||
@@ -0,0 +1,13 @@
|
||||
# Updates DB from 23 to 24 -AffectedArc07
|
||||
# Add new column to player table for 2FA status
|
||||
ALTER TABLE `player` ADD COLUMN `2fa_status` ENUM('DISABLED','ENABLED_IP','ENABLED_ALWAYS') NOT NULL DEFAULT 'DISABLED' AFTER `byond_date`;
|
||||
|
||||
# Create new table for 2FA tokens
|
||||
CREATE TABLE `2fa_secrets` (
|
||||
`ckey` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
|
||||
`secret` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
|
||||
`date_setup` DATETIME NOT NULL DEFAULT current_timestamp(),
|
||||
`last_time` DATETIME NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`ckey`) USING BTREE
|
||||
)
|
||||
COLLATE='utf8mb4_general_ci' ENGINE=InnoDB;
|
||||
@@ -0,0 +1,5 @@
|
||||
#include "map_files\generic\centcomm.dmm"
|
||||
#define CC_TRANSITION_CONFIG DECLARE_LEVEL(CENTCOMM, SELFLOOPING, list(ADMIN_LEVEL, BLOCK_TELEPORT, IMPEDES_MAGIC))
|
||||
#ifdef CIMAP
|
||||
#include "ci_map_testing.dm"
|
||||
#endif
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
All z-levels should be identical in size. Their numbers should not matter.
|
||||
The order of z-levels should not matter as long as their attributes are properly defined at MAP_TRANSITION_CONFIG.
|
||||
Old code checked for the number of the z-level (for example whether there are any revheads on Z1),
|
||||
currently it should check for the define (for example whether there are any revheads on any z-levels defined as STATION_LEVEL).
|
||||
z1 = centcomm
|
||||
z2 = station
|
||||
z3 = lavaland
|
||||
*/
|
||||
|
||||
#if !defined(USING_MAP_DATUM)
|
||||
#include "map_files\generic\centcomm.dmm"
|
||||
#include "map_files\cyberiad\cyberiad.dmm"
|
||||
#include "map_files\generic\Lavaland.dmm"
|
||||
|
||||
#define MAP_TRANSITION_CONFIG list(\
|
||||
DECLARE_LEVEL(CENTCOMM, SELFLOOPING, list(ADMIN_LEVEL, BLOCK_TELEPORT, IMPEDES_MAGIC)),\
|
||||
DECLARE_LEVEL(MAIN_STATION, CROSSLINKED, list(STATION_LEVEL, STATION_CONTACT, REACHABLE, AI_OK)),\
|
||||
DECLARE_LEVEL(MINING, SELFLOOPING, list(ORE_LEVEL, REACHABLE, STATION_CONTACT, HAS_WEATHER, AI_OK)))
|
||||
|
||||
#define USING_MAP_DATUM /datum/map/cyberiad
|
||||
|
||||
#elif !defined(MAP_OVERRIDE)
|
||||
|
||||
#warn a map has already been included, ignoring Cyberiad.
|
||||
|
||||
#endif
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
All z-levels should be identical in size. Their numbers should not matter.
|
||||
The order of z-levels should not matter as long as their attributes are properly defined at MAP_TRANSITION_CONFIG.
|
||||
Old code checked for the number of the z-level (for example whether there are any revheads on Z1),
|
||||
currently it should check for the define (for example whether there are any revheads on any z-levels defined as STATION_LEVEL).
|
||||
z1 = centcomm
|
||||
z2 = station
|
||||
z3 = lavaland
|
||||
|
||||
Original design by Okand37 of TG Station
|
||||
Lovingly ported by Purpose2 to Paradise
|
||||
*/
|
||||
|
||||
#if !defined(USING_MAP_DATUM)
|
||||
#include "map_files\generic\centcomm.dmm"
|
||||
#include "map_files\delta\delta.dmm"
|
||||
#include "map_files\generic\Lavaland.dmm"
|
||||
|
||||
#define MAP_TRANSITION_CONFIG list(\
|
||||
DECLARE_LEVEL(CENTCOMM, SELFLOOPING, list(ADMIN_LEVEL, BLOCK_TELEPORT, IMPEDES_MAGIC)),\
|
||||
DECLARE_LEVEL(MAIN_STATION, CROSSLINKED, list(STATION_LEVEL, STATION_CONTACT, REACHABLE, AI_OK)),\
|
||||
DECLARE_LEVEL(MINING, SELFLOOPING, list(ORE_LEVEL, REACHABLE, STATION_CONTACT, HAS_WEATHER, AI_OK)))
|
||||
|
||||
#define USING_MAP_DATUM /datum/map/delta
|
||||
|
||||
#elif !defined(MAP_OVERRIDE)
|
||||
|
||||
#warn a map has already been included, ignoring Delta.
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
// See code/modules/mapping for map datums
|
||||
+10494
-17177
File diff suppressed because it is too large
Load Diff
@@ -132,7 +132,7 @@
|
||||
/area/ruin/powered/beach)
|
||||
"ax" = (
|
||||
/obj/machinery/disco/immobile,
|
||||
/turf/simulated/floor/light/colour_cycle,
|
||||
/turf/simulated/floor/light,
|
||||
/area/ruin/powered/beach)
|
||||
"ay" = (
|
||||
/obj/machinery/door/airlock/sandstone{
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
},
|
||||
/turf/simulated/floor/beach/away/water/deep/sand_floor,
|
||||
/area/awaymission/undersea)
|
||||
"af" = (
|
||||
/obj/structure/constructshell,
|
||||
/turf/simulated/floor/beach/away/water/deep/wood_floor,
|
||||
/area/awaymission/undersea)
|
||||
"ag" = (
|
||||
/obj/structure/chair/wood/wings,
|
||||
/turf/simulated/floor/beach/away/water/deep/wood_floor,
|
||||
@@ -46312,7 +46308,7 @@ ad
|
||||
ad
|
||||
ad
|
||||
ah
|
||||
af
|
||||
ah
|
||||
ah
|
||||
ah
|
||||
ar
|
||||
@@ -46823,7 +46819,7 @@ av
|
||||
av
|
||||
ad
|
||||
ad
|
||||
af
|
||||
ah
|
||||
ah
|
||||
ah
|
||||
ah
|
||||
@@ -48108,7 +48104,7 @@ av
|
||||
av
|
||||
ad
|
||||
ad
|
||||
af
|
||||
ah
|
||||
ah
|
||||
ah
|
||||
ah
|
||||
@@ -48625,7 +48621,7 @@ ad
|
||||
ad
|
||||
ad
|
||||
ah
|
||||
af
|
||||
ah
|
||||
ah
|
||||
ah
|
||||
ah
|
||||
|
||||
@@ -11168,6 +11168,9 @@
|
||||
icon_state = "tube1";
|
||||
tag = "icon-tube1 (WEST)"
|
||||
},
|
||||
/obj/structure/chair/comfy/shuttle{
|
||||
dir = 4
|
||||
},
|
||||
/turf/simulated/floor/mineral/plastitanium/red,
|
||||
/area/shuttle/specops)
|
||||
"QL" = (
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
All z-levels should be identical in size. Their numbers should not matter.
|
||||
The order of z-levels should not matter as long as their attributes are properly defined at MAP_TRANSITION_CONFIG.
|
||||
Old code checked for the number of the z-level (for example whether there are any revheads on Z1),
|
||||
currently it should check for the define (for example whether there are any revheads on any z-levels defined as STATION_LEVEL).
|
||||
z1 = centcomm
|
||||
z2 = station
|
||||
z3 = lavaland
|
||||
*/
|
||||
|
||||
#if !defined(USING_MAP_DATUM)
|
||||
#include "map_files\generic\centcomm.dmm"
|
||||
#include "map_files\MetaStation\MetaStation.dmm"
|
||||
#include "map_files\generic\Lavaland.dmm"
|
||||
|
||||
#define MAP_TRANSITION_CONFIG list(\
|
||||
DECLARE_LEVEL(CENTCOMM, SELFLOOPING, list(ADMIN_LEVEL, BLOCK_TELEPORT, IMPEDES_MAGIC)),\
|
||||
DECLARE_LEVEL(MAIN_STATION, CROSSLINKED, list(STATION_LEVEL, STATION_CONTACT, REACHABLE, AI_OK)),\
|
||||
DECLARE_LEVEL(MINING, SELFLOOPING, list(ORE_LEVEL, REACHABLE, STATION_CONTACT, HAS_WEATHER, AI_OK)))
|
||||
|
||||
#define USING_MAP_DATUM /datum/map/metastation
|
||||
|
||||
#elif !defined(MAP_OVERRIDE)
|
||||
|
||||
#warn a map has already been included, ignoring MetaStation.
|
||||
|
||||
#endif
|
||||
@@ -363,7 +363,7 @@
|
||||
#define INVESTIGATE_BOMB "bombs"
|
||||
|
||||
// The SQL version required by this version of the code
|
||||
#define SQL_VERSION 22
|
||||
#define SQL_VERSION 24
|
||||
|
||||
// Vending machine stuff
|
||||
#define CAT_NORMAL 1
|
||||
|
||||
@@ -55,8 +55,9 @@
|
||||
// Yes I know this being an "enable to disable" is misleading, but it avoids having to tweak all existing pref entries
|
||||
#define PREFTOGGLE_2_REVERB_DISABLE 512
|
||||
#define PREFTOGGLE_2_FORCE_WHITE_RUNECHAT 1024
|
||||
#define PREFTOGGLE_2_SIMPLE_STAT_PANEL 2048
|
||||
|
||||
#define TOGGLES_2_TOTAL 2047 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined.
|
||||
#define TOGGLES_2_TOTAL 4095 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined.
|
||||
|
||||
#define TOGGLES_2_DEFAULT (PREFTOGGLE_2_FANCYUI|PREFTOGGLE_2_ITEMATTACK|PREFTOGGLE_2_WINDOWFLASHING|PREFTOGGLE_2_RUNECHAT|PREFTOGGLE_2_DEATHMESSAGE|PREFTOGGLE_2_EMOTE_BUBBLE)
|
||||
|
||||
@@ -94,7 +95,7 @@
|
||||
#define EXP_TYPE_SERVICE "Service"
|
||||
#define EXP_TYPE_WHITELIST "Whitelist"
|
||||
|
||||
#define EXP_DEPT_TYPE_LIST list(EXP_TYPE_SERVICE, EXP_TYPE_MEDICAL, EXP_TYPE_ENGINEERING, EXP_TYPE_SCIENCE, EXP_TYPE_SECURITY, EXP_TYPE_COMMAND, EXP_TYPE_SILICON, EXP_TYPE_SPECIAL)
|
||||
#define EXP_DEPT_TYPE_LIST list(EXP_TYPE_SUPPLY, EXP_TYPE_SERVICE, EXP_TYPE_MEDICAL, EXP_TYPE_ENGINEERING, EXP_TYPE_SCIENCE, EXP_TYPE_SECURITY, EXP_TYPE_COMMAND, EXP_TYPE_SILICON, EXP_TYPE_SPECIAL, EXP_TYPE_GHOST)
|
||||
|
||||
// Defines just for parallax because its levels make storing it in the regular prefs a pain in the ass
|
||||
// These dont need to be bitflags because there isnt going to be more than one at a time of these active
|
||||
@@ -104,3 +105,12 @@
|
||||
#define PARALLAX_MED 4
|
||||
#define PARALLAX_HIGH 8
|
||||
#define PARALLAX_INSANE 16
|
||||
|
||||
// 2FA Defines. These are the same as the schema DB enums //
|
||||
|
||||
/// Client has 2FA disabled
|
||||
#define _2FA_DISABLED "DISABLED"
|
||||
/// Client will be prompted for 2FA on IP changes
|
||||
#define _2FA_ENABLED_IP "ENABLED_IP"
|
||||
/// Client will be prompted for 2FA always
|
||||
#define _2FA_ENABLED_ALWAYS "ENABLED_ALWAYS"
|
||||
|
||||
@@ -134,9 +134,6 @@ GLOBAL_PROTECT(log_end)
|
||||
/proc/log_href(text)
|
||||
rustg_log_write(GLOB.world_href_log, "HREF: [html_decode(text)][GLOB.log_end]")
|
||||
|
||||
/proc/log_asset(text)
|
||||
rustg_log_write(GLOB.world_asset_log, "ASSET: [text][GLOB.log_end]")
|
||||
|
||||
/proc/log_runtime_summary(text)
|
||||
rustg_log_write(GLOB.runtime_summary_log, "[text][GLOB.log_end]")
|
||||
|
||||
@@ -147,6 +144,9 @@ GLOBAL_PROTECT(log_end)
|
||||
rustg_log_write(GLOB.sql_log, "[text][GLOB.log_end]")
|
||||
SEND_TEXT(world.log, text) // Redirect it to DD too
|
||||
|
||||
/proc/log_chat_debug(text)
|
||||
rustg_log_write(GLOB.chat_debug_log, "[text][GLOB.log_end]")
|
||||
|
||||
// A logging proc that only outputs after setup is done, to
|
||||
// help devs test initialization stuff that happens a lot
|
||||
/proc/log_after_setup(message)
|
||||
|
||||
@@ -15,9 +15,9 @@ GLOBAL_VAR(church_name)
|
||||
|
||||
return name
|
||||
|
||||
GLOBAL_VAR(command_name)
|
||||
// TODO: Remove this. Its always gonna be NAS Trurl
|
||||
/proc/command_name()
|
||||
return GLOB.using_map.dock_name
|
||||
return "NAS Trurl"
|
||||
|
||||
GLOBAL_VAR(religion_name)
|
||||
/proc/religion_name()
|
||||
@@ -31,11 +31,8 @@ GLOBAL_VAR(religion_name)
|
||||
|
||||
return capitalize(name)
|
||||
|
||||
/proc/system_name()
|
||||
return GLOB.using_map.starsys_name
|
||||
|
||||
/proc/station_name()
|
||||
return GLOB.using_map.station_name
|
||||
return SSmapping.map_datum.fluff_name
|
||||
|
||||
/proc/new_station_name()
|
||||
var/random = rand(1,5)
|
||||
|
||||
@@ -513,6 +513,8 @@
|
||||
text = replacetext(text, "\[cell\]", "<td>")
|
||||
text = replacetext(text, "\[logo\]", "​<img src = ntlogo.png>")
|
||||
text = replacetext(text, "\[time\]", "[station_time_timestamp()]") // TO DO
|
||||
text = replacetext(text, "\[date\]", "[GLOB.current_date_string]")
|
||||
text = replacetext(text, "\[station\]", "[SSmapping.map_datum.fluff_name]")
|
||||
if(!no_font)
|
||||
if(P)
|
||||
text = "<font face=\"[deffont]\" color=[P ? P.colour : "black"]>[text]</font>"
|
||||
@@ -651,3 +653,79 @@
|
||||
|
||||
// return the split html object to the caller
|
||||
return s
|
||||
|
||||
//Used for applying byonds text macros to strings that are loaded at runtime
|
||||
/proc/apply_text_macros(string)
|
||||
var/next_backslash = findtext(string, "\\")
|
||||
if(!next_backslash)
|
||||
return string
|
||||
|
||||
var/leng = length(string)
|
||||
|
||||
var/next_space = findtext(string, " ", next_backslash + length(string[next_backslash]))
|
||||
if(!next_space)
|
||||
next_space = leng - next_backslash
|
||||
|
||||
if(!next_space) //trailing bs
|
||||
return string
|
||||
|
||||
var/base = next_backslash == 1 ? "" : copytext(string, 1, next_backslash)
|
||||
var/macro = lowertext(copytext(string, next_backslash + length(string[next_backslash]), next_space))
|
||||
var/rest = next_backslash > leng ? "" : copytext(string, next_space + length(string[next_space]))
|
||||
|
||||
//See https://secure.byond.com/docs/ref/info.html#/DM/text/macros
|
||||
switch(macro)
|
||||
//prefixes/agnostic
|
||||
if("the")
|
||||
rest = text("\the []", rest)
|
||||
if("a")
|
||||
rest = text("\a []", rest)
|
||||
if("an")
|
||||
rest = text("\an []", rest)
|
||||
if("proper")
|
||||
rest = text("\proper []", rest)
|
||||
if("improper")
|
||||
rest = text("\improper []", rest)
|
||||
if("roman")
|
||||
rest = text("\roman []", rest)
|
||||
//postfixes
|
||||
if("th")
|
||||
base = text("[]\th", rest)
|
||||
if("s")
|
||||
base = text("[]\s", rest)
|
||||
if("he")
|
||||
base = text("[]\he", rest)
|
||||
if("she")
|
||||
base = text("[]\she", rest)
|
||||
if("his")
|
||||
base = text("[]\his", rest)
|
||||
if("himself")
|
||||
base = text("[]\himself", rest)
|
||||
if("herself")
|
||||
base = text("[]\herself", rest)
|
||||
if("hers")
|
||||
base = text("[]\hers", rest)
|
||||
|
||||
. = base
|
||||
if(rest)
|
||||
. += .(rest)
|
||||
|
||||
/**
|
||||
* Proc to generate a "rank colour" from a client
|
||||
*
|
||||
* This takes the client and looks at various factors in order, such as patreon status, staff rank, and more
|
||||
* Arguments:
|
||||
* * C - The client were looking up
|
||||
*/
|
||||
/proc/client2rankcolour(client/C)
|
||||
// First check if end user is an admin
|
||||
if(C.holder)
|
||||
if(C.holder.rank in GLOB.rank_colour_map)
|
||||
// Return their rank colour if they are in here
|
||||
return GLOB.rank_colour_map[C.holder.rank]
|
||||
|
||||
// If they arent an admin, see if they are a patreon. Just accept any level
|
||||
if(C.donator_level)
|
||||
return "#e67e22" // Patreon orange
|
||||
return null
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
Remember to update _globalvars/traits.dm if you're adding/removing/renaming traits.
|
||||
*/
|
||||
|
||||
//mob traits
|
||||
//***** MOB TRAITS *****//
|
||||
#define TRAIT_BLIND "blind"
|
||||
#define TRAIT_MUTE "mute"
|
||||
#define TRAIT_DEAF "deaf"
|
||||
@@ -152,8 +152,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_NOEXAMINE "no_examine"
|
||||
#define TRAIT_NOPAIN "no_pain"
|
||||
|
||||
/// Blowing kisses actually does damage to the victim
|
||||
#define TRAIT_KISS_OF_DEATH "kiss_of_death"
|
||||
//***** ITEM TRAITS *****//
|
||||
/// Show what machine/door wires do when held.
|
||||
#define TRAIT_SHOW_WIRE_INFO "show_wire_info"
|
||||
|
||||
//
|
||||
// common trait sources
|
||||
|
||||
@@ -2072,7 +2072,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
|
||||
return _list
|
||||
|
||||
/// Waits at a line of code until X is true
|
||||
#define UNTIL(X) while(!(X)) stoplag()
|
||||
#define UNTIL(X) while(!(X)) sleep(world.tick_lag)
|
||||
|
||||
// Check if the source atom contains another atom
|
||||
/atom/proc/contains(atom/location)
|
||||
|
||||
@@ -54,4 +54,7 @@ GLOBAL_LIST_INIT(cooking_recipes, list(RECIPE_MICROWAVE = list(), RECIPE_OVEN =
|
||||
GLOBAL_LIST_INIT(cooking_ingredients, list(RECIPE_MICROWAVE = list(), RECIPE_OVEN = list(), RECIPE_GRILL = list(), RECIPE_CANDY = list()))
|
||||
GLOBAL_LIST_INIT(cooking_reagents, list(RECIPE_MICROWAVE = list(), RECIPE_OVEN = list(), RECIPE_GRILL = list(), RECIPE_CANDY = list()))
|
||||
|
||||
/// Associative list of admin rank to colour. Set in config/rank_colours.txt
|
||||
GLOBAL_LIST_EMPTY(rank_colour_map)
|
||||
|
||||
#define EGG_LAYING_MESSAGES list("lays an egg.", "squats down and croons.", "begins making a huge racket.", "begins clucking raucously.")
|
||||
|
||||
@@ -18,6 +18,7 @@ GLOBAL_LIST_INIT(cell_logs, list())
|
||||
GLOBAL_LIST_INIT(navigation_computers, list())
|
||||
|
||||
GLOBAL_LIST_INIT(all_areas, list())
|
||||
GLOBAL_LIST_INIT(all_unique_areas, list()) // List of all unique areas. AKA areas with there_can_be_many = FALSE
|
||||
GLOBAL_LIST_INIT(machines, list())
|
||||
GLOBAL_LIST_INIT(rcd_list, list()) //list of Rapid Construction Devices.
|
||||
|
||||
|
||||
@@ -11,8 +11,6 @@ GLOBAL_VAR(world_qdel_log)
|
||||
GLOBAL_PROTECT(world_qdel_log)
|
||||
GLOBAL_VAR(world_href_log)
|
||||
GLOBAL_PROTECT(world_href_log)
|
||||
GLOBAL_VAR(world_asset_log)
|
||||
GLOBAL_PROTECT(world_asset_log)
|
||||
GLOBAL_VAR(runtime_summary_log)
|
||||
GLOBAL_PROTECT(runtime_summary_log)
|
||||
GLOBAL_VAR(tgui_log)
|
||||
@@ -21,6 +19,8 @@ GLOBAL_VAR(http_log)
|
||||
GLOBAL_PROTECT(http_log)
|
||||
GLOBAL_VAR(sql_log)
|
||||
GLOBAL_PROTECT(sql_log)
|
||||
GLOBAL_VAR(chat_debug_log)
|
||||
GLOBAL_PROTECT(chat_debug_log)
|
||||
GLOBAL_VAR(round_id)
|
||||
GLOBAL_PROTECT(round_id)
|
||||
|
||||
|
||||
@@ -8,9 +8,6 @@ GLOBAL_LIST_INIT(alldirs, list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, S
|
||||
GLOBAL_LIST_INIT(alldirs2, list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST, NORTH, SOUTH, EAST, WEST))
|
||||
GLOBAL_LIST_INIT(diagonals, list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST))
|
||||
|
||||
// This must exist early on or shit breaks bad
|
||||
GLOBAL_DATUM_INIT(using_map, /datum/map, new USING_MAP_DATUM)
|
||||
|
||||
GLOBAL_LIST(global_map) // This is the array of zlevels | list(list(1,5),list(4,3)) | becomes a 2D array of zlevels
|
||||
//Resulting sector map looks like
|
||||
//|_1_|_4_|
|
||||
|
||||
@@ -86,13 +86,9 @@ GLOBAL_VAR_INIT(copier_items_printed, 0)
|
||||
GLOBAL_VAR_INIT(copier_max_items, 300)
|
||||
GLOBAL_VAR_INIT(copier_items_printed_logged, FALSE)
|
||||
|
||||
|
||||
GLOBAL_VAR(map_name) // Self explanatory
|
||||
|
||||
GLOBAL_DATUM_INIT(data_core, /datum/datacore, new) // Station datacore, manifest, etc
|
||||
|
||||
GLOBAL_VAR_INIT(panic_bunker_enabled, FALSE) // Is the panic bunker enabled
|
||||
GLOBAL_VAR_INIT(pending_server_update, FALSE)
|
||||
|
||||
GLOBAL_LIST_EMPTY(ability_verbs) // Create-level abilities
|
||||
GLOBAL_LIST_INIT(pipe_colors, list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_RED, "blue" = PIPE_COLOR_BLUE, "cyan" = PIPE_COLOR_CYAN, "green" = PIPE_COLOR_GREEN, "yellow" = PIPE_COLOR_YELLOW, "purple" = PIPE_COLOR_PURPLE))
|
||||
|
||||
@@ -45,7 +45,6 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_DWARF" = TRAIT_DWARF,
|
||||
"TRAIT_SILENT_FOOTSTEPS" = TRAIT_SILENT_FOOTSTEPS,
|
||||
"TRAIT_ALCOHOL_TOLERANCE" = TRAIT_ALCOHOL_TOLERANCE,
|
||||
"TRAIT_KISS_OF_DEATH" = TRAIT_KISS_OF_DEATH,
|
||||
|
||||
"TRAIT_COMIC_SANS" = TRAIT_COMIC_SANS,
|
||||
"TRAIT_NOFINGERPRINTS" = TRAIT_NOFINGERPRINTS,
|
||||
@@ -57,7 +56,12 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_NOGERMS" = TRAIT_NOGERMS,
|
||||
"TRAIT_NODECAY" = TRAIT_NODECAY,
|
||||
"TRAIT_NOEXAMINE" = TRAIT_NOEXAMINE,
|
||||
"TRAIT_NOPAIN" = TRAIT_NOPAIN)))
|
||||
"TRAIT_NOPAIN" = TRAIT_NOPAIN
|
||||
),
|
||||
/obj/item = list(
|
||||
"TRAIT_SHOW_WIRE_INFO" = TRAIT_SHOW_WIRE_INFO
|
||||
)
|
||||
))
|
||||
|
||||
/// value -> trait name, generated on use from trait_by_type global
|
||||
GLOBAL_LIST(trait_name_map)
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
|
||||
/obj/item/badminBook/attack_self(mob/living/user as mob)
|
||||
if(user.middleClickOverride)
|
||||
to_chat(user, "<span class='warning'>You try to draw power from the [src], but you cannot hold the power at this time!</span>")
|
||||
to_chat(user, "<span class='warning'>You try to draw power from [src], but you cannot hold the power at this time!</span>")
|
||||
return
|
||||
user.middleClickOverride = clickBehavior
|
||||
to_chat(user, "<span class='notice'>You draw a bit of power from the [src], you can use <b>middle click</b> or <b>alt click</b> to release the power!</span>")
|
||||
to_chat(user, "<span class='notice'>You draw a bit of power from [src], you can use <b>middle click</b> or <b>alt click</b> to release the power!</span>")
|
||||
|
||||
/datum/middleClickOverride/badminClicker
|
||||
var/summon_path = /obj/item/reagent_containers/food/snacks/cookie
|
||||
|
||||
@@ -122,12 +122,12 @@
|
||||
icon_state = "too_much_oxy"
|
||||
|
||||
/obj/screen/alert/not_enough_nitro
|
||||
name = "Choking (No N)"
|
||||
name = "Choking (No N2)"
|
||||
desc = "You're not getting enough nitrogen. Find some good air before you pass out!"
|
||||
icon_state = "not_enough_nitro"
|
||||
|
||||
/obj/screen/alert/too_much_nitro
|
||||
name = "Choking (N)"
|
||||
name = "Choking (N2)"
|
||||
desc = "There's too much nitrogen in the air, and you're breathing it in! Find some good air before you pass out!"
|
||||
icon_state = "too_much_nitro"
|
||||
|
||||
|
||||
@@ -132,6 +132,8 @@
|
||||
if(isovermind(usr))
|
||||
var/mob/camera/blob/B = usr
|
||||
B.split_consciousness()
|
||||
if(B.split_used) // Destroys split proc if the split is succesfully used
|
||||
qdel(src)
|
||||
|
||||
/datum/hud/blob_overmind/New(mob/user)
|
||||
..()
|
||||
@@ -194,6 +196,8 @@
|
||||
using.screen_loc = ui_storage2
|
||||
static_inventory += using
|
||||
|
||||
using = new /obj/screen/blob/Split()
|
||||
using.screen_loc = ui_acti
|
||||
static_inventory += using
|
||||
var/mob/camera/blob/B = user
|
||||
if(!B.is_offspring) // Checks if the blob is an offspring, to not create split button if it is
|
||||
using = new /obj/screen/blob/Split()
|
||||
using.screen_loc = ui_acti
|
||||
static_inventory += using
|
||||
|
||||
@@ -78,15 +78,6 @@
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.toggle_ionpulse()
|
||||
|
||||
/obj/screen/robot/panel
|
||||
name = "installed modules"
|
||||
icon_state = "panel"
|
||||
|
||||
/obj/screen/robot/panel/Click()
|
||||
if(issilicon(usr))
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.installed_modules()
|
||||
|
||||
/obj/screen/robot/mov_intent
|
||||
name = "fast/slow toggle"
|
||||
icon_state = "running"
|
||||
@@ -224,16 +215,6 @@
|
||||
var/x = -4 //Start at CENTER-4,SOUTH+1
|
||||
var/y = 1
|
||||
|
||||
//Unfortunately adding the emag module to the list of modules has to be here. This is because a borg can
|
||||
//be emagged before they actually select a module. - or some situation can cause them to get a new module
|
||||
// - or some situation might cause them to get de-emagged or something.
|
||||
if(R.emagged || R.weapons_unlock)
|
||||
if(!(R.module.emag in R.module.modules))
|
||||
R.module.modules.Add(R.module.emag)
|
||||
else
|
||||
if(R.module.emag in R.module.modules)
|
||||
R.module.modules.Remove(R.module.emag)
|
||||
|
||||
for(var/atom/movable/A in R.module.modules)
|
||||
if( (A != R.module_state_1) && (A != R.module_state_2) && (A != R.module_state_3) )
|
||||
//Module is not currently active
|
||||
|
||||
@@ -275,6 +275,12 @@
|
||||
/// Enable auto profiler of rounds
|
||||
var/auto_profile = FALSE
|
||||
|
||||
// Enable map voting
|
||||
var/map_voting_enabled = FALSE
|
||||
|
||||
// 2FA auth host
|
||||
var/_2fa_auth_host = null
|
||||
|
||||
/datum/configuration/New()
|
||||
for(var/T in subtypesof(/datum/game_mode))
|
||||
var/datum/game_mode/M = T
|
||||
@@ -770,6 +776,10 @@
|
||||
max_client_cid_history = text2num(value)
|
||||
if("enable_auto_profiler")
|
||||
auto_profile = TRUE
|
||||
if("enable_map_voting")
|
||||
map_voting_enabled = TRUE
|
||||
if("2fa_host")
|
||||
_2fa_auth_host = value
|
||||
else
|
||||
log_config("Unknown setting in configuration: '[name]'")
|
||||
|
||||
@@ -925,3 +935,34 @@
|
||||
runnable_modes[M] = probabilities[M.config_tag]
|
||||
// to_chat(world, "DEBUG: runnable_mode\[[runnable_modes.len]\] = [M.config_tag]")
|
||||
return runnable_modes
|
||||
|
||||
/datum/configuration/proc/load_rank_colour_map()
|
||||
var/list/lines = file2list("config/rank_colours.txt")
|
||||
|
||||
for(var/line in lines)
|
||||
// Skip newlines
|
||||
if(!length(line))
|
||||
continue
|
||||
// Skip comments
|
||||
if(line[1] == "#")
|
||||
continue
|
||||
|
||||
//Split the line at every " - "
|
||||
var/list/split_holder = splittext(line, " - ")
|
||||
if(!length(split_holder))
|
||||
continue
|
||||
|
||||
// Rank is before the " - "
|
||||
var/rank = split_holder[1]
|
||||
if(!rank)
|
||||
continue
|
||||
|
||||
// Color is after the " - "
|
||||
var/colour = ""
|
||||
if(length(split_holder) >= 2)
|
||||
colour = split_holder[2]
|
||||
|
||||
if(rank && colour)
|
||||
GLOB.rank_colour_map[rank] = colour
|
||||
else
|
||||
stack_trace("Invalid colour for rank '[rank]' in config/rank_colours.txt")
|
||||
|
||||
@@ -65,7 +65,7 @@ SUBSYSTEM_DEF(blackbox)
|
||||
sqlversion = versions[FV.key]
|
||||
|
||||
var/datum/db_query/query_feedback_save = SSdbcore.NewQuery({"
|
||||
INSERT DELAYED IGNORE INTO [format_table_name("feedback")] (datetime, round_id, key_name, key_type, version, json)
|
||||
INSERT IGNORE INTO [format_table_name("feedback")] (datetime, round_id, key_name, key_type, version, json)
|
||||
VALUES (NOW(), :rid, :keyname, :keytype, :version, :json)"}, list(
|
||||
"rid" = text2num(GLOB.round_id),
|
||||
"keyname" = FV.key,
|
||||
|
||||
@@ -193,7 +193,7 @@ SUBSYSTEM_DEF(dbcore)
|
||||
if(!IsConnected())
|
||||
return
|
||||
var/datum/db_query/query_round_end = SSdbcore.NewQuery(
|
||||
"UPDATE [format_table_name("round")] SET end_datetime = Now(), game_mode_result = :game_mode_result, station_name = :station_name WHERE id = :round_id",
|
||||
"UPDATE [format_table_name("round")] SET end_datetime = Now(), game_mode_result = :game_mode_result WHERE id = :round_id",
|
||||
list("game_mode_result" = SSticker.mode_result, "station_name" = station_name(), "round_id" = GLOB.round_id)
|
||||
)
|
||||
query_round_end.Execute()
|
||||
|
||||
@@ -12,8 +12,11 @@ SUBSYSTEM_DEF(http)
|
||||
/// Total requests the SS has processed in a round
|
||||
var/total_requests
|
||||
|
||||
/datum/controller/subsystem/http/Initialize(start_timeofday)
|
||||
/datum/controller/subsystem/http/PreInit()
|
||||
. = ..()
|
||||
rustg_create_async_http_client() // Open the door
|
||||
|
||||
/datum/controller/subsystem/http/Initialize(start_timeofday)
|
||||
active_async_requests = list()
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -1,31 +1,51 @@
|
||||
SUBSYSTEM_DEF(mapping)
|
||||
name = "Mapping"
|
||||
init_order = INIT_ORDER_MAPPING // 9
|
||||
flags = SS_NO_FIRE
|
||||
name = "Mapping"
|
||||
init_order = INIT_ORDER_MAPPING // 9
|
||||
flags = SS_NO_FIRE
|
||||
/// What map datum are we using
|
||||
var/datum/map/map_datum
|
||||
/// What map will be used next round
|
||||
var/datum/map/next_map
|
||||
|
||||
// This has to be here because world/New() uses [station_name()], which looks this datum up
|
||||
/datum/controller/subsystem/mapping/PreInit()
|
||||
. = ..()
|
||||
if(map_datum) // Dont do this again if we are recovering
|
||||
return
|
||||
if(fexists("data/next_map.txt"))
|
||||
var/list/lines = file2list("data/next_map.txt")
|
||||
// Check its valid
|
||||
try
|
||||
map_datum = text2path(lines[1])
|
||||
map_datum = new map_datum
|
||||
catch
|
||||
map_datum = new /datum/map/cyberiad // Assume cyberiad if non-existent
|
||||
fdel("data/next_map.txt") // Remove to avoid the same map existing forever
|
||||
else
|
||||
map_datum = new /datum/map/cyberiad // Assume cyberiad if non-existent
|
||||
|
||||
/datum/controller/subsystem/mapping/Shutdown()
|
||||
if(next_map) // Save map for next round
|
||||
var/F = file("data/next_map.txt")
|
||||
F << next_map.type
|
||||
|
||||
/datum/controller/subsystem/mapping/Initialize(timeofday)
|
||||
// Load all Z level templates
|
||||
preloadTemplates()
|
||||
|
||||
// Load the station
|
||||
loadStation()
|
||||
|
||||
// Load lavaland
|
||||
loadLavaland()
|
||||
|
||||
// Pick a random away mission.
|
||||
if(!config.disable_away_missions)
|
||||
load_away_mission()
|
||||
|
||||
// Seed space ruins
|
||||
if(!config.disable_space_ruins)
|
||||
// load in extra levels of space ruins
|
||||
var/load_zlevels_timer = start_watch()
|
||||
log_startup_progress("Creating random space levels...")
|
||||
var/num_extra_space = rand(config.extra_space_ruin_levels_min, config.extra_space_ruin_levels_max)
|
||||
for(var/i = 1, i <= num_extra_space, i++)
|
||||
GLOB.space_manager.add_new_zlevel("Ruin Area #[i]", linkage = CROSSLINKED, traits = list(REACHABLE, SPAWN_RUINS))
|
||||
log_startup_progress("Loaded random space levels in [stop_watch(load_zlevels_timer)]s.")
|
||||
|
||||
// Now spawn ruins, random budget between 20 and 30 for all zlevels combined.
|
||||
// While this may seem like a high number, the amount of ruin Z levels can be anywhere between 3 and 7.
|
||||
// Note that this budget is not split evenly accross all zlevels
|
||||
log_startup_progress("Seeding ruins...")
|
||||
var/seed_ruins_timer = start_watch()
|
||||
seedRuins(levels_by_trait(SPAWN_RUINS), rand(20, 30), /area/space, GLOB.space_ruins_templates)
|
||||
log_startup_progress("Successfully seeded ruins in [stop_watch(seed_ruins_timer)]s.")
|
||||
handleRuins()
|
||||
|
||||
// Makes a blank space level for the sake of randomness
|
||||
GLOB.space_manager.add_new_zlevel("Empty Area", linkage = CROSSLINKED, traits = list(REACHABLE))
|
||||
@@ -63,12 +83,6 @@ SUBSYSTEM_DEF(mapping)
|
||||
|
||||
GLOB.ghostteleportlocs = sortAssoc(GLOB.ghostteleportlocs)
|
||||
|
||||
// Map name. Break these down into SSmapping controller vars instaed of GLOBs at some point
|
||||
if(GLOB.using_map && GLOB.using_map.name)
|
||||
GLOB.map_name = "[GLOB.using_map.name]"
|
||||
else
|
||||
GLOB.map_name = "Unknown"
|
||||
|
||||
// World name
|
||||
if(config && config.server_name)
|
||||
world.name = "[config.server_name]: [station_name()]"
|
||||
@@ -77,6 +91,56 @@ SUBSYSTEM_DEF(mapping)
|
||||
|
||||
return ..()
|
||||
|
||||
// Do not confuse with seedRuins()
|
||||
/datum/controller/subsystem/mapping/proc/handleRuins()
|
||||
// load in extra levels of space ruins
|
||||
var/load_zlevels_timer = start_watch()
|
||||
log_startup_progress("Creating random space levels...")
|
||||
var/num_extra_space = rand(config.extra_space_ruin_levels_min, config.extra_space_ruin_levels_max)
|
||||
for(var/i in 1 to num_extra_space)
|
||||
GLOB.space_manager.add_new_zlevel("Ruin Area #[i]", linkage = CROSSLINKED, traits = list(REACHABLE, SPAWN_RUINS))
|
||||
log_startup_progress("Loaded random space levels in [stop_watch(load_zlevels_timer)]s.")
|
||||
|
||||
// Now spawn ruins, random budget between 20 and 30 for all zlevels combined.
|
||||
// While this may seem like a high number, the amount of ruin Z levels can be anywhere between 3 and 7.
|
||||
// Note that this budget is not split evenly accross all zlevels
|
||||
log_startup_progress("Seeding ruins...")
|
||||
var/seed_ruins_timer = start_watch()
|
||||
seedRuins(levels_by_trait(SPAWN_RUINS), rand(20, 30), /area/space, GLOB.space_ruins_templates)
|
||||
log_startup_progress("Successfully seeded ruins in [stop_watch(seed_ruins_timer)]s.")
|
||||
|
||||
// Loads in the station
|
||||
/datum/controller/subsystem/mapping/proc/loadStation()
|
||||
ASSERT(map_datum.map_path)
|
||||
if(!fexists(map_datum.map_path))
|
||||
// Make a VERY OBVIOUS error
|
||||
to_chat(world, "<span class='narsie'>ERROR: The path specified for the map to load is invalid. No station has been loaded!</span>")
|
||||
return
|
||||
|
||||
var/watch = start_watch()
|
||||
log_startup_progress("Loading [map_datum.fluff_name]...")
|
||||
// This should always be Z2, but you never know
|
||||
var/map_z_level = GLOB.space_manager.add_new_zlevel(MAIN_STATION, linkage = CROSSLINKED, traits = list(STATION_LEVEL, STATION_CONTACT, REACHABLE, AI_OK))
|
||||
GLOB.maploader.load_map(file(map_datum.map_path), z_offset = map_z_level)
|
||||
log_startup_progress("Loaded [map_datum.fluff_name] in [stop_watch(watch)]s")
|
||||
|
||||
// Save station name in the DB
|
||||
if(!SSdbcore.IsConnected())
|
||||
return
|
||||
var/datum/db_query/query_set_map = SSdbcore.NewQuery(
|
||||
"UPDATE [format_table_name("round")] SET start_datetime=NOW(), map_name=:mapname, station_name=:stationname WHERE id=:round_id",
|
||||
list("mapname" = map_datum.technical_name, "stationname" = map_datum.fluff_name, "round_id" = GLOB.round_id)
|
||||
)
|
||||
query_set_map.Execute(async = FALSE) // This happens during a time of intense server lag, so should be non-async
|
||||
qdel(query_set_map)
|
||||
|
||||
// Loads in lavaland
|
||||
/datum/controller/subsystem/mapping/proc/loadLavaland()
|
||||
var/watch = start_watch()
|
||||
log_startup_progress("Loading Lavaland...")
|
||||
var/lavaland_z_level = GLOB.space_manager.add_new_zlevel(MINING, linkage = SELFLOOPING, traits = list(ORE_LEVEL, REACHABLE, STATION_CONTACT, HAS_WEATHER, AI_OK))
|
||||
GLOB.maploader.load_map(file("_maps/map_files/generic/Lavaland.dmm"), z_offset = lavaland_z_level)
|
||||
log_startup_progress("Loaded Lavaland in [stop_watch(watch)]s")
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = /area/space, list/potentialRuins)
|
||||
if(!z_levels || !z_levels.len)
|
||||
|
||||
@@ -135,8 +135,6 @@ SUBSYSTEM_DEF(shuttle)
|
||||
to_chat(user, "The emergency shuttle has been disabled by Centcom.")
|
||||
return
|
||||
|
||||
call_reason = trim(html_encode(call_reason))
|
||||
|
||||
if(length(call_reason) < CALL_SHUTTLE_REASON_LENGTH)
|
||||
to_chat(user, "Reason is too short. [CALL_SHUTTLE_REASON_LENGTH] character minimum.")
|
||||
return
|
||||
|
||||
@@ -16,8 +16,6 @@ SUBSYSTEM_DEF(title)
|
||||
else if(L.len > 1)
|
||||
if(use_rare_screens && lowertext(L[1]) == "rare")
|
||||
title_screens += S
|
||||
else if(GLOB.using_map && (lowertext(L[1]) == lowertext(GLOB.using_map.name)))
|
||||
title_screens += S
|
||||
|
||||
if(!isemptylist(title_screens))
|
||||
if(length(title_screens) > 1)
|
||||
|
||||
@@ -177,6 +177,16 @@ SUBSYSTEM_DEF(vote)
|
||||
if("crew_transfer")
|
||||
if(. == "Initiate Crew Transfer")
|
||||
init_shift_change(null, 1)
|
||||
if("map")
|
||||
// Find target map.
|
||||
var/datum/map/top_voted_map
|
||||
for(var/x in subtypesof(/datum/map))
|
||||
var/datum/map/M = x
|
||||
// Set top voted map
|
||||
if(. == "[initial(M.fluff_name)] ([initial(M.technical_name)])")
|
||||
top_voted_map = M
|
||||
to_chat(world, "<font color='purple'>Map for next round: [initial(top_voted_map.fluff_name)] ([initial(top_voted_map.technical_name)])</font>")
|
||||
SSmapping.next_map = new top_voted_map
|
||||
|
||||
|
||||
if(restart)
|
||||
@@ -197,7 +207,7 @@ SUBSYSTEM_DEF(vote)
|
||||
return vote
|
||||
return 0
|
||||
|
||||
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key)
|
||||
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, code_invoked = FALSE)
|
||||
if(!mode)
|
||||
if(started_time != null && !check_rights(R_ADMIN))
|
||||
var/next_allowed_time = (started_time + config.vote_delay)
|
||||
@@ -223,6 +233,14 @@ SUBSYSTEM_DEF(vote)
|
||||
return 0
|
||||
question = "End the shift?"
|
||||
choices.Add("Initiate Crew Transfer", "Continue The Round")
|
||||
if("map")
|
||||
if(!(check_rights(R_SERVER) || code_invoked))
|
||||
return FALSE
|
||||
question = "Map for next round"
|
||||
for(var/x in subtypesof(/datum/map))
|
||||
var/datum/map/M = x
|
||||
choices.Add("[initial(M.fluff_name)] ([initial(M.technical_name)])")
|
||||
|
||||
if("custom")
|
||||
question = html_encode(input(usr,"What is the vote for?") as text|null)
|
||||
if(!question) return 0
|
||||
@@ -248,11 +266,7 @@ SUBSYSTEM_DEF(vote)
|
||||
<a href='?src=[UID()];vote=open'>Click here or type vote to place your vote.</a>
|
||||
You have [config.vote_period/10] seconds to vote.</font>"})
|
||||
switch(vote_type)
|
||||
if("crew_transfer")
|
||||
SEND_SOUND(world, sound('sound/ambience/alarm4.ogg'))
|
||||
if("gamemode")
|
||||
SEND_SOUND(world, sound('sound/ambience/alarm4.ogg'))
|
||||
if("custom")
|
||||
if("crew_transfer", "gamemode", "custom", "map")
|
||||
SEND_SOUND(world, sound('sound/ambience/alarm4.ogg'))
|
||||
if(mode == "gamemode" && SSticker.ticker_going)
|
||||
SSticker.ticker_going = FALSE
|
||||
@@ -321,6 +335,12 @@ SUBSYSTEM_DEF(vote)
|
||||
if(admin)
|
||||
dat += "\t(<a href='?src=[UID()];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
|
||||
|
||||
dat += "</li><li>"
|
||||
if(admin)
|
||||
dat += "<a href='?src=[UID()];vote=map'>Map</a>"
|
||||
else
|
||||
dat += "<font color='grey'>Map (Disallowed)</font>"
|
||||
|
||||
dat += "</li>"
|
||||
//custom
|
||||
if(admin)
|
||||
@@ -381,6 +401,9 @@ SUBSYSTEM_DEF(vote)
|
||||
if("gamemode")
|
||||
if(config.allow_vote_mode || admin)
|
||||
initiate_vote("gamemode",usr.key)
|
||||
if("map")
|
||||
if(admin)
|
||||
initiate_vote("map", usr.key)
|
||||
if("crew_transfer")
|
||||
if(config.allow_vote_restart || admin)
|
||||
initiate_vote("crew_transfer",usr.key)
|
||||
|
||||
@@ -383,6 +383,9 @@
|
||||
/datum/action/item_action/hands_free/activate
|
||||
name = "Activate"
|
||||
|
||||
/datum/action/item_action/hands_free/activate/always
|
||||
check_flags = null
|
||||
|
||||
/datum/action/item_action/toggle_research_scanner
|
||||
name = "Toggle Research Scanner"
|
||||
button_icon_state = "scan_mode"
|
||||
@@ -426,6 +429,7 @@
|
||||
desc = "Activates the jump boot's internal propulsion system, allowing the user to dash over 4-wide gaps."
|
||||
icon_icon = 'icons/mob/actions/actions.dmi'
|
||||
button_icon_state = "jetboot"
|
||||
use_itemicon = FALSE
|
||||
|
||||
///prset for organ actions
|
||||
/datum/action/item_action/organ_action
|
||||
|
||||
@@ -130,13 +130,13 @@
|
||||
|
||||
/datum/component/material_container/proc/insert_stack(obj/item/stack/S, amt, multiplier = 1)
|
||||
if(isnull(amt))
|
||||
amt = S.amount
|
||||
amt = S.get_amount()
|
||||
|
||||
if(amt <= 0)
|
||||
return FALSE
|
||||
|
||||
if(amt > S.amount)
|
||||
amt = S.amount
|
||||
if(amt > S.get_amount())
|
||||
amt = S.get_amount()
|
||||
|
||||
var/material_amt = get_item_material_amount(S)
|
||||
if(!material_amt)
|
||||
|
||||
@@ -5,129 +5,6 @@
|
||||
//This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
|
||||
var/list/locked = list()
|
||||
|
||||
/datum/datacore/proc/get_manifest(monochrome, OOC)
|
||||
var/list/heads = new()
|
||||
var/list/sec = new()
|
||||
var/list/eng = new()
|
||||
var/list/med = new()
|
||||
var/list/sci = new()
|
||||
var/list/ser = new()
|
||||
var/list/sup = new()
|
||||
var/list/bot = new()
|
||||
var/list/misc = new()
|
||||
var/list/isactive = new()
|
||||
var/dat = {"
|
||||
<head><style>
|
||||
.manifest {border-collapse:collapse;}
|
||||
.manifest td, th {border:1px solid [monochrome?"black":"#DEF; background-color:white; color:black"]; padding:.25em}
|
||||
.manifest th {height: 2em; [monochrome?"border-top-width: 3px":"background-color: #48C; color:white"]}
|
||||
.manifest tr.head th { [monochrome?"border-top-width: 1px":"background-color: #488;"] }
|
||||
.manifest td:first-child {text-align:right}
|
||||
.manifest tr.alt td {[monochrome?"border-top-width: 2px":"background-color: #DEF"]}
|
||||
</style></head>
|
||||
<table class="manifest" width='350px'>
|
||||
<tr class='head'><th>Name</th><th>Rank</th><th>Activity</th></tr>
|
||||
"}
|
||||
var/even = 0
|
||||
// sort mobs
|
||||
for(var/datum/data/record/t in GLOB.data_core.general)
|
||||
var/name = t.fields["name"]
|
||||
var/rank = t.fields["rank"]
|
||||
var/real_rank = t.fields["real_rank"]
|
||||
if(OOC)
|
||||
var/activetext = "Inactive"
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/H = thing
|
||||
if(H.real_name != name)
|
||||
continue
|
||||
if(H.client && H.client.inactivity <= 6000)
|
||||
activetext = "Active"
|
||||
break
|
||||
if(isLivingSSD(H))
|
||||
activetext = "SSD"
|
||||
break
|
||||
isactive[name] = activetext
|
||||
else
|
||||
isactive[name] = t.fields["p_stat"]
|
||||
var/department = 0
|
||||
if(real_rank in GLOB.command_positions)
|
||||
heads[name] = rank
|
||||
department = 1
|
||||
if(real_rank in GLOB.security_positions)
|
||||
sec[name] = rank
|
||||
department = 1
|
||||
if(real_rank in GLOB.engineering_positions)
|
||||
eng[name] = rank
|
||||
department = 1
|
||||
if(real_rank in GLOB.medical_positions)
|
||||
med[name] = rank
|
||||
department = 1
|
||||
if(real_rank in GLOB.science_positions)
|
||||
sci[name] = rank
|
||||
department = 1
|
||||
if(real_rank in GLOB.service_positions)
|
||||
ser[name] = rank
|
||||
department = 1
|
||||
if(real_rank in GLOB.supply_positions)
|
||||
sup[name] = rank
|
||||
department = 1
|
||||
if(real_rank in GLOB.nonhuman_positions)
|
||||
bot[name] = rank
|
||||
department = 1
|
||||
if(!department && !(name in heads))
|
||||
misc[name] = rank
|
||||
if(heads.len > 0)
|
||||
dat += "<tr><th colspan=3>Heads</th></tr>"
|
||||
for(var/name in heads)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[heads[name]]</td><td>[isactive[name]]</td></tr>"
|
||||
even = !even
|
||||
if(sec.len > 0)
|
||||
dat += "<tr><th colspan=3>Security</th></tr>"
|
||||
for(var/name in sec)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sec[name]]</td><td>[isactive[name]]</td></tr>"
|
||||
even = !even
|
||||
if(eng.len > 0)
|
||||
dat += "<tr><th colspan=3>Engineering</th></tr>"
|
||||
for(var/name in eng)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[eng[name]]</td><td>[isactive[name]]</td></tr>"
|
||||
even = !even
|
||||
if(med.len > 0)
|
||||
dat += "<tr><th colspan=3>Medical</th></tr>"
|
||||
for(var/name in med)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[med[name]]</td><td>[isactive[name]]</td></tr>"
|
||||
even = !even
|
||||
if(sci.len > 0)
|
||||
dat += "<tr><th colspan=3>Science</th></tr>"
|
||||
for(var/name in sci)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sci[name]]</td><td>[isactive[name]]</td></tr>"
|
||||
even = !even
|
||||
if(ser.len > 0)
|
||||
dat += "<tr><th colspan=3>Service</th></tr>"
|
||||
for(var/name in ser)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[ser[name]]</td><td>[isactive[name]]</td></tr>"
|
||||
even = !even
|
||||
if(sup.len > 0)
|
||||
dat += "<tr><th colspan=3>Supply</th></tr>"
|
||||
for(var/name in sup)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sup[name]]</td><td>[isactive[name]]</td></tr>"
|
||||
even = !even
|
||||
if(bot.len > 0)
|
||||
dat += "<tr><th colspan=3>Silicon</th></tr>"
|
||||
for(var/name in bot)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[bot[name]]</td><td>[isactive[name]]</td></tr>"
|
||||
even = !even
|
||||
if(misc.len > 0)
|
||||
dat += "<tr><th colspan=3>Miscellaneous</th></tr>"
|
||||
for(var/name in misc)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[misc[name]]</td><td>[isactive[name]]</td></tr>"
|
||||
even = !even
|
||||
|
||||
dat += "</table>"
|
||||
dat = replacetext(dat, "\n", "") // so it can be placed on paper correctly
|
||||
dat = replacetext(dat, "\t", "")
|
||||
return dat
|
||||
|
||||
|
||||
/*
|
||||
We can't just insert in HTML into the TGUI so we need the raw data to play with.
|
||||
Instead of creating this list over and over when someone leaves their PDA open to the page
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
/datum/construction/proc/custom_action(step, used_atom, user)
|
||||
if(istype(used_atom, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/C = used_atom
|
||||
if(C.amount<4)
|
||||
if(C.get_amount() < 4)
|
||||
to_chat(user, ("<span class='warning'>There's not enough cable to finish the task.</span>"))
|
||||
return 0
|
||||
else
|
||||
@@ -55,7 +55,7 @@
|
||||
playsound(holder, C.usesound, 50, 1)
|
||||
else if(istype(used_atom, /obj/item/stack))
|
||||
var/obj/item/stack/S = used_atom
|
||||
if(S.amount < 5)
|
||||
if(S.get_amount() < 5)
|
||||
to_chat(user, ("<span class='warning'>There's not enough material in this stack.</span>"))
|
||||
return 0
|
||||
else
|
||||
@@ -113,7 +113,7 @@
|
||||
// STACKS
|
||||
if(istype(used_atom,/obj/item/stack))
|
||||
var/obj/item/stack/stack=used_atom
|
||||
if(stack.amount < amount)
|
||||
if(stack.get_amount() < amount)
|
||||
to_chat(user, "<span class='warning'>You don't have enough [stack]! You need at least [amount].</span>")
|
||||
return 0
|
||||
stack.use(amount)
|
||||
|
||||
+12
-38
@@ -1375,46 +1375,20 @@
|
||||
switch(href_list["silicon"])
|
||||
if("unemag")
|
||||
var/mob/living/silicon/robot/R = current
|
||||
if(istype(R))
|
||||
R.emagged = 0
|
||||
if(R.module)
|
||||
if(R.activated(R.module.emag))
|
||||
R.module_active = null
|
||||
if(R.module_state_1 == R.module.emag)
|
||||
R.module_state_1 = null
|
||||
R.contents -= R.module.emag
|
||||
else if(R.module_state_2 == R.module.emag)
|
||||
R.module_state_2 = null
|
||||
R.contents -= R.module.emag
|
||||
else if(R.module_state_3 == R.module.emag)
|
||||
R.module_state_3 = null
|
||||
R.contents -= R.module.emag
|
||||
R.clear_supplied_laws()
|
||||
R.laws = new /datum/ai_laws/crewsimov
|
||||
log_admin("[key_name(usr)] has un-emagged [key_name(current)]")
|
||||
message_admins("[key_name_admin(usr)] has un-emagged [key_name_admin(current)]")
|
||||
if(!istype(R))
|
||||
return
|
||||
R.unemag()
|
||||
log_admin("[key_name(usr)] has un-emagged [key_name(current)]")
|
||||
message_admins("[key_name_admin(usr)] has un-emagged [key_name_admin(current)]")
|
||||
|
||||
if("unemagcyborgs")
|
||||
if(isAI(current))
|
||||
var/mob/living/silicon/ai/ai = current
|
||||
for(var/mob/living/silicon/robot/R in ai.connected_robots)
|
||||
R.emagged = 0
|
||||
if(R.module)
|
||||
if(R.activated(R.module.emag))
|
||||
R.module_active = null
|
||||
if(R.module_state_1 == R.module.emag)
|
||||
R.module_state_1 = null
|
||||
R.contents -= R.module.emag
|
||||
else if(R.module_state_2 == R.module.emag)
|
||||
R.module_state_2 = null
|
||||
R.contents -= R.module.emag
|
||||
else if(R.module_state_3 == R.module.emag)
|
||||
R.module_state_3 = null
|
||||
R.contents -= R.module.emag
|
||||
R.clear_supplied_laws()
|
||||
R.laws = new /datum/ai_laws/crewsimov
|
||||
log_admin("[key_name(usr)] has unemagged [key_name(ai)]'s cyborgs")
|
||||
message_admins("[key_name_admin(usr)] has unemagged [key_name_admin(ai)]'s cyborgs")
|
||||
if(!isAI(current))
|
||||
return
|
||||
var/mob/living/silicon/ai/ai = current
|
||||
for(var/mob/living/silicon/robot/R in ai.connected_robots)
|
||||
R.unemag()
|
||||
log_admin("[key_name(usr)] has unemagged [key_name(ai)]'s cyborgs")
|
||||
message_admins("[key_name_admin(usr)] has unemagged [key_name_admin(ai)]'s cyborgs")
|
||||
|
||||
else if(href_list["common"])
|
||||
switch(href_list["common"])
|
||||
|
||||
@@ -111,6 +111,8 @@
|
||||
|
||||
for(var/path in backpack_contents)
|
||||
var/number = backpack_contents[path]
|
||||
if(!number)
|
||||
number = 1
|
||||
for(var/i in 1 to number)
|
||||
H.equip_or_collect(new path(H), slot_in_backpack)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
/datum/outfit/admin/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
. = ..()
|
||||
if(!visualsOnly)
|
||||
if(!visualsOnly && H.mind)
|
||||
H.mind.assigned_role = name
|
||||
H.job = name
|
||||
|
||||
@@ -627,6 +627,10 @@
|
||||
/obj/item/implanter/death_alarm = 1,
|
||||
)
|
||||
|
||||
implants = list(/obj/item/implant/mindshield,
|
||||
/obj/item/implant/death_alarm
|
||||
)
|
||||
|
||||
/datum/outfit/admin/solgov_rep/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
. = ..()
|
||||
if(visualsOnly)
|
||||
@@ -634,33 +638,44 @@
|
||||
|
||||
var/obj/item/card/id/I = H.wear_id
|
||||
if(istype(I))
|
||||
apply_to_card(I, H, get_all_accesses(), name, "lifetimeid")
|
||||
apply_to_card(I, H, get_all_centcom_access(), name, "lifetimeid")
|
||||
I.assignment = "Solar Federation Representative"
|
||||
H.sec_hud_set_ID()
|
||||
|
||||
|
||||
/datum/outfit/admin/solgov
|
||||
name = "Solar Federation Marine"
|
||||
|
||||
uniform = /obj/item/clothing/under/solgov
|
||||
suit = /obj/item/clothing/suit/armor/bulletproof
|
||||
back = /obj/item/storage/backpack/security
|
||||
belt = /obj/item/storage/belt/military/assault
|
||||
head = /obj/item/clothing/head/soft/solgov
|
||||
glasses = /obj/item/clothing/glasses/hud/security/night
|
||||
belt = /obj/item/storage/belt/military/assault/marines/full
|
||||
head = /obj/item/clothing/head/soft/solgov/marines
|
||||
glasses = /obj/item/clothing/glasses/night
|
||||
gloves = /obj/item/clothing/gloves/combat
|
||||
shoes = /obj/item/clothing/shoes/combat
|
||||
l_ear = /obj/item/radio/headset/ert
|
||||
id = /obj/item/card/id
|
||||
l_hand = /obj/item/gun/projectile/automatic/ar
|
||||
l_hand = /obj/item/gun/projectile/automatic/shotgun/bulldog
|
||||
suit_store = /obj/item/gun/projectile/automatic/pistol/m1911
|
||||
r_pocket = /obj/item/flashlight/seclite
|
||||
pda = /obj/item/pda
|
||||
backpack_contents = list(
|
||||
/obj/item/storage/box/responseteam = 1,
|
||||
/obj/item/ammo_box/magazine/m556 = 3,
|
||||
/obj/item/clothing/shoes/magboots = 1,
|
||||
/obj/item/gun/projectile/automatic/pistol/m1911 = 1,
|
||||
/obj/item/ammo_box/magazine/m45 = 2
|
||||
/obj/item/whetstone = 1,
|
||||
/obj/item/clothing/mask/gas/explorer/marines = 1,
|
||||
/obj/item/reagent_containers/hypospray/autoinjector/survival = 1
|
||||
)
|
||||
var/is_tsf_lieutenant = FALSE
|
||||
cybernetic_implants = list(
|
||||
/obj/item/organ/internal/cyberimp/arm/flash,
|
||||
/obj/item/organ/internal/cyberimp/chest/nutriment,
|
||||
/obj/item/organ/internal/cyberimp/eyes/hud/security
|
||||
)
|
||||
implants = list(/obj/item/implant/mindshield,
|
||||
/obj/item/implant/death_alarm
|
||||
)
|
||||
|
||||
var/is_solgov_lieutenant = FALSE
|
||||
|
||||
|
||||
/datum/outfit/admin/solgov/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
@@ -668,31 +683,80 @@
|
||||
if(visualsOnly)
|
||||
return
|
||||
|
||||
if(is_tsf_lieutenant)
|
||||
if(is_solgov_lieutenant)
|
||||
H.real_name = "Lieutenant [pick(GLOB.last_names)]"
|
||||
else
|
||||
H.real_name = "[pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant First Class", "Master Sergeant", "Sergeant Major")] [pick(GLOB.last_names)]"
|
||||
H.name = H.real_name
|
||||
var/obj/item/card/id/I = H.wear_id
|
||||
if(istype(I))
|
||||
apply_to_card(I, H, get_all_accesses(), name, "lifetimeid")
|
||||
I.assignment = name
|
||||
if(istype(I) && is_solgov_lieutenant)
|
||||
apply_to_card(I, H, get_centcom_access("Emergency Response Team Leader"), name, "lifetimeid")
|
||||
else if(istype(I))
|
||||
apply_to_card(I, H, get_centcom_access("Emergency Response Team Member"), name, "lifetimeid")
|
||||
H.sec_hud_set_ID()
|
||||
|
||||
/datum/outfit/admin/solgov/lieutenant
|
||||
name = "Solar Federation Lieutenant"
|
||||
|
||||
uniform = /obj/item/clothing/under/solgov/command
|
||||
head = /obj/item/clothing/head/soft/solgov/command
|
||||
head = /obj/item/clothing/head/beret/solgov/command
|
||||
glasses = /obj/item/clothing/glasses/night
|
||||
back = /obj/item/storage/backpack/satchel
|
||||
l_ear = /obj/item/radio/headset/ert/alt/commander
|
||||
l_hand = null
|
||||
belt = /obj/item/melee/baton/loaded
|
||||
suit_store = /obj/item/gun/projectile/automatic/pistol/deagle
|
||||
l_pocket = /obj/item/pinpointer/advpinpointer
|
||||
backpack_contents = list(
|
||||
/obj/item/storage/box/responseteam = 1,
|
||||
/obj/item/melee/classic_baton/telescopic = 1,
|
||||
/obj/item/storage/box/handcuffs = 1,
|
||||
/obj/item/clothing/shoes/magboots/advance = 1,
|
||||
/obj/item/gun/projectile/automatic/pistol/deagle = 1,
|
||||
/obj/item/ammo_box/magazine/m50 = 2
|
||||
/obj/item/reagent_containers/hypospray/autoinjector/survival = 1,
|
||||
/obj/item/clothing/mask/gas/explorer/marines = 1,
|
||||
/obj/item/ammo_box/magazine/m50 = 3
|
||||
)
|
||||
is_tsf_lieutenant = TRUE
|
||||
is_solgov_lieutenant = TRUE
|
||||
|
||||
/datum/outfit/admin/solgov/elite
|
||||
name = "Solar Federation Specops Marine"
|
||||
uniform = /obj/item/clothing/under/solgov/elite
|
||||
head = /obj/item/clothing/head/soft/solgov/marines/elite
|
||||
belt = /obj/item/storage/belt/military/assault/marines/elite/full
|
||||
l_hand = /obj/item/gun/projectile/automatic/ar
|
||||
backpack_contents = list(
|
||||
/obj/item/storage/box/responseteam = 1,
|
||||
/obj/item/clothing/shoes/magboots/advance = 1,
|
||||
/obj/item/whetstone = 1,
|
||||
/obj/item/clothing/mask/gas/explorer/marines = 1,
|
||||
/obj/item/reagent_containers/hypospray/autoinjector/survival = 1
|
||||
)
|
||||
cybernetic_implants = list(
|
||||
/obj/item/organ/internal/cyberimp/eyes/hud/security,
|
||||
/obj/item/organ/internal/cyberimp/chest/nutriment,
|
||||
/obj/item/organ/internal/cyberimp/brain/anti_stun/hardened,
|
||||
/obj/item/organ/internal/cyberimp/arm/flash,
|
||||
/obj/item/organ/internal/eyes/cybernetic/shield
|
||||
)
|
||||
/datum/outfit/admin/solgov/elite/lieutenant
|
||||
name = "Solar Federation Specops Lieutenant"
|
||||
uniform = /obj/item/clothing/under/solgov/command/elite
|
||||
head = /obj/item/clothing/head/beret/solgov/command/elite
|
||||
glasses = /obj/item/clothing/glasses/night
|
||||
back = /obj/item/storage/backpack/satchel
|
||||
belt = /obj/item/melee/baton/loaded
|
||||
l_hand = null
|
||||
suit_store = /obj/item/gun/projectile/automatic/pistol/deagle
|
||||
l_pocket = /obj/item/pinpointer/advpinpointer
|
||||
l_ear = /obj/item/radio/headset/ert/alt/commander
|
||||
backpack_contents = list(
|
||||
/obj/item/storage/box/responseteam = 1,
|
||||
/obj/item/storage/box/handcuffs = 1,
|
||||
/obj/item/clothing/shoes/magboots/advance = 1,
|
||||
/obj/item/clothing/mask/gas/explorer/marines = 1,
|
||||
/obj/item/reagent_containers/hypospray/autoinjector/survival = 1,
|
||||
/obj/item/ammo_box/magazine/m50 = 3
|
||||
)
|
||||
is_solgov_lieutenant = TRUE
|
||||
|
||||
/datum/outfit/admin/sol_trader
|
||||
name = "Sol Trader"
|
||||
@@ -720,6 +784,7 @@
|
||||
var/obj/item/card/id/I = H.wear_id
|
||||
if(istype(I))
|
||||
apply_to_card(I, H, list(ACCESS_TRADE_SOL, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS), name)
|
||||
H.sec_hud_set_ID()
|
||||
|
||||
/datum/outfit/admin/chrono
|
||||
name = "Chrono Legionnaire"
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone
|
||||
name = "Summon Soulstone"
|
||||
desc = "This spell reaches into Nar'Sie's realm, summoning one of the legendary fragments across time and space"
|
||||
desc = "This spell reaches into Redspace, summoning one of the legendary fragments across time and space"
|
||||
action_icon_state = "summonsoulstone"
|
||||
action_background_icon_state = "bg_cult"
|
||||
school = "conjuration"
|
||||
@@ -68,7 +68,7 @@
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/pylon
|
||||
name = "Cult Pylon"
|
||||
desc = "This spell conjures a fragile crystal from Nar'Sie's realm. Makes for a convenient light source."
|
||||
desc = "This spell conjures a fragile crystal from Redspace. Makes for a convenient light source."
|
||||
action_icon_state = "pylon"
|
||||
action_background_icon_state = "bg_cult"
|
||||
school = "conjuration"
|
||||
@@ -118,7 +118,12 @@
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/do_jaunt(mob/living/target)
|
||||
target.set_light(0)
|
||||
..()
|
||||
target.set_light(2, 3, l_color = SSticker.cultdat ? SSticker.cultdat.construct_glow : LIGHT_COLOR_BLOOD_MAGIC)
|
||||
if(isconstruct(target))
|
||||
var/mob/living/simple_animal/hostile/construct/C = target
|
||||
if(C.holy)
|
||||
C.set_light(3, 5, LIGHT_COLOR_DARK_BLUE)
|
||||
else
|
||||
C.set_light(2, 3, l_color = SSticker.cultdat ? SSticker.cultdat.construct_glow : LIGHT_COLOR_BLOOD_MAGIC)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/jaunt_steam(mobloc)
|
||||
return
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
if((ABSTRACT in item.flags) || (NODROP in item.flags))
|
||||
continue
|
||||
marked_item = item
|
||||
to_chat(M, "<span class='warning'>You begin to focus your very being into the [item.name]...</span>")
|
||||
to_chat(M, "<span class='warning'>You begin to focus your very being into [item]...</span>")
|
||||
break
|
||||
|
||||
if(!marked_item)
|
||||
@@ -104,7 +104,7 @@
|
||||
|
||||
spawn(50)
|
||||
if(marked_item.loc != M) //I changed my mind I don't want to put my soul in a cheeseburger!
|
||||
to_chat(M, "<span class='warning'>Your soul snaps back to your body as you drop the [marked_item.name]!</span>")
|
||||
to_chat(M, "<span class='warning'>Your soul snaps back to your body as you drop [marked_item]!</span>")
|
||||
marked_item = null
|
||||
return
|
||||
name = "RISE!"
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
if(!usr.mind.miming)
|
||||
to_chat(usr, "<span class='notice'>You must dedicate yourself to silence first.</span>")
|
||||
return
|
||||
invocation = "<B>[usr.real_name]</B> looks as if a wall is in front of [usr.p_them()]."
|
||||
invocation = "<B>[usr.name]</B> looks as if a wall is in front of [usr.p_them()]."
|
||||
else
|
||||
invocation_type ="none"
|
||||
..()
|
||||
@@ -86,7 +86,7 @@
|
||||
if(!usr.mind.miming)
|
||||
to_chat(usr, "<span class='notice'>You must dedicate yourself to silence first.</span>")
|
||||
return
|
||||
invocation = "<B>[usr.real_name]</B> looks as if a blockade is in front of [usr.p_them()]."
|
||||
invocation = "<B>[usr.name]</B> looks as if a blockade is in front of [usr.p_them()]."
|
||||
else
|
||||
invocation_type ="none"
|
||||
..()
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
var/obj/item/organ/external/part = X
|
||||
if(item_to_retrieve in part.embedded_objects)
|
||||
part.embedded_objects -= item_to_retrieve
|
||||
to_chat(C, "<span class='warning'>The [item_to_retrieve] that was embedded in your [part] has mysteriously vanished. How fortunate!</span>")
|
||||
to_chat(C, "<span class='warning'>\The [item_to_retrieve] that was embedded in your [part] has mysteriously vanished. How fortunate!</span>")
|
||||
if(!C.has_embedded_objects())
|
||||
C.clear_alert("embeddedobject")
|
||||
break
|
||||
@@ -99,7 +99,7 @@
|
||||
if(!item_to_retrieve)
|
||||
return
|
||||
|
||||
item_to_retrieve.loc.visible_message("<span class='warning'>The [item_to_retrieve.name] suddenly disappears!</span>")
|
||||
item_to_retrieve.loc.visible_message("<span class='warning'>\The [item_to_retrieve] suddenly disappears!</span>")
|
||||
|
||||
|
||||
if(target.hand) //left active hand
|
||||
@@ -112,10 +112,10 @@
|
||||
butterfingers = 1
|
||||
if(butterfingers)
|
||||
item_to_retrieve.loc = target.loc
|
||||
item_to_retrieve.loc.visible_message("<span class='caution'>The [item_to_retrieve.name] suddenly appears!</span>")
|
||||
item_to_retrieve.loc.visible_message("<span class='caution'>\The [item_to_retrieve] suddenly appears!</span>")
|
||||
playsound(get_turf(target),'sound/magic/summonitems_generic.ogg',50,1)
|
||||
else
|
||||
item_to_retrieve.loc.visible_message("<span class='caution'>The [item_to_retrieve.name] suddenly appears in [target]'s hand!</span>")
|
||||
item_to_retrieve.loc.visible_message("<span class='caution'>\The [item_to_retrieve] suddenly appears in [target]'s hand!</span>")
|
||||
playsound(get_turf(target),'sound/magic/summonitems_generic.ogg',50,1)
|
||||
|
||||
if(message)
|
||||
|
||||
@@ -935,6 +935,14 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
|
||||
containername = "surgery crate"
|
||||
access = ACCESS_MEDICAL
|
||||
|
||||
/datum/supply_packs/medical/gloves
|
||||
name = "Nitrile Glove Crate"
|
||||
contains = list(/obj/item/clothing/gloves/color/latex/nitrile,
|
||||
/obj/item/clothing/gloves/color/latex/nitrile,
|
||||
/obj/item/clothing/gloves/color/latex/nitrile,
|
||||
/obj/item/clothing/gloves/color/latex/nitrile)
|
||||
cost = 50
|
||||
containername = "nitrile glove crate"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Science /////////////////////////////////////////
|
||||
|
||||
@@ -1,39 +1,53 @@
|
||||
/// Will our restart be slower?
|
||||
GLOBAL_VAR_INIT(slower_restart, FALSE)
|
||||
|
||||
/proc/server_announce_global(announcement_text)
|
||||
to_chat(world, "<span style='color: #ff00ff'>\[Server] [announcement_text]</span>")
|
||||
|
||||
/proc/server_announce_adminonly(announcement_text)
|
||||
to_chat(GLOB.admins, "<span style='color: #ff00ff'>\[Server] \[Admin] [announcement_text]</span>")
|
||||
|
||||
/datum/tgs_event_handler/impl
|
||||
var/datum/timedevent/reattach_timer
|
||||
|
||||
|
||||
/datum/tgs_event_handler/impl/HandleEvent(event_code, ...)
|
||||
switch(event_code)
|
||||
if(TGS_EVENT_REBOOT_MODE_CHANGE)
|
||||
var/list/reboot_mode_lookup = list ("[TGS_REBOOT_MODE_NORMAL]" = "be normal", "[TGS_REBOOT_MODE_SHUTDOWN]" = "shutdown the server", "[TGS_REBOOT_MODE_RESTART]" = "hard restart the server")
|
||||
var/old_reboot_mode = args[2]
|
||||
var/new_reboot_mode = args[3]
|
||||
message_admins("\[Server]\[Info] Reboot will no longer [reboot_mode_lookup["[old_reboot_mode]"]], it will instead [reboot_mode_lookup["[new_reboot_mode]"]]")
|
||||
if(new_reboot_mode == TGS_REBOOT_MODE_SHUTDOWN)
|
||||
GLOB.slower_restart = TRUE
|
||||
else
|
||||
GLOB.slower_restart = FALSE
|
||||
server_announce_adminonly("\[Info] Reboot will no longer [reboot_mode_lookup["[old_reboot_mode]"]], it will instead [reboot_mode_lookup["[new_reboot_mode]"]]")
|
||||
if(TGS_EVENT_PORT_SWAP)
|
||||
message_admins("\[Server]\[Info] Changing port from [world.port] to [args[2]]")
|
||||
server_announce_adminonly("\[Info] Changing port from [world.port] to [args[2]]")
|
||||
if(TGS_EVENT_INSTANCE_RENAMED)
|
||||
message_admins("\[Server]\[Info] Instance renamed to from [world.TgsInstanceName()] to [args[2]]")
|
||||
server_announce_adminonly("\[Info] Instance renamed to from [world.TgsInstanceName()] to [args[2]]")
|
||||
if(TGS_EVENT_COMPILE_START)
|
||||
message_admins("\[Server]\[Info] Code deployment started, new game version incoming next round...")
|
||||
server_announce_adminonly("\[Info] Code deployment started, new game version incoming next round...")
|
||||
if(TGS_EVENT_COMPILE_CANCELLED)
|
||||
message_admins("\[Server]\[Warning] Code deployment cancelled!")
|
||||
server_announce_adminonly("\[Warning] Code deployment cancelled! Consult a maintainer/host to see if this was intentional!")
|
||||
if(TGS_EVENT_COMPILE_FAILURE)
|
||||
message_admins("\[Server]\[Error] Code deployment failed! Inform a maintainer/host immediately!")
|
||||
server_announce_adminonly("\[Error] Code deployment failed! Inform a maintainer/host immediately!")
|
||||
if(TGS_EVENT_DEPLOYMENT_COMPLETE)
|
||||
message_admins("\[Server]\[Info] Code deployment complete!")
|
||||
to_chat(world, "<span class='boldannounce'>Server updated, changes will be applied on the next round...</span>")
|
||||
server_announce_adminonly("\[Info] Code deployment complete!")
|
||||
server_announce_global("Server update complete. Changes will be applied on the next round.")
|
||||
if(TGS_EVENT_WATCHDOG_DETACH)
|
||||
message_admins("\[Server]\[Info] Server manager restarting...")
|
||||
server_announce_adminonly("\[Info] Server manager restarting...")
|
||||
reattach_timer = addtimer(CALLBACK(src, .proc/LateOnReattach), 1 MINUTES, TIMER_STOPPABLE)
|
||||
if(TGS_EVENT_WATCHDOG_REATTACH)
|
||||
var/datum/tgs_version/old_version = world.TgsVersion()
|
||||
var/datum/tgs_version/new_version = args[2]
|
||||
if(!old_version.Equals(new_version))
|
||||
message_admins("\[Server]\[Info] Manager back online. TGS has been updated to v[new_version.deprefixed_parameter]")
|
||||
server_announce_adminonly("\[Info] Server manager back online. TGS has been updated to v[new_version.deprefixed_parameter]")
|
||||
else
|
||||
message_admins("\[Server]\[Info] Manager back online")
|
||||
server_announce_adminonly("\[Info] Server manager back online")
|
||||
if(reattach_timer)
|
||||
deltimer(reattach_timer)
|
||||
reattach_timer = null
|
||||
|
||||
/datum/tgs_event_handler/impl/proc/LateOnReattach()
|
||||
message_admins("\[Server]\[Warning] TGS hasn't notified us of it coming back for a full minute! Is there a problem?")
|
||||
server_announce_adminonly("\[Warning] TGS hasn't notified us of it coming back for a full minute! Is there a problem?")
|
||||
|
||||
@@ -864,6 +864,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
reference = "CQC"
|
||||
item = /obj/item/CQC_manual
|
||||
cost = 13
|
||||
cant_discount = TRUE
|
||||
|
||||
/datum/uplink_item/stealthy_weapons/cameraflash
|
||||
name = "Camera Flash"
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
/**
|
||||
* Proc called to determine if the user can see wire define information, such as "Contraband", "Door Bolts", etc.
|
||||
*
|
||||
* If the user is an admin, or has a multitool which reveals wire information in their active hand, the proc returns TRUE.
|
||||
* If the user is an admin, or has an item which reveals wire information in their active hand, the proc returns TRUE.
|
||||
*
|
||||
* Arguments:
|
||||
* * user - the mob who is interacting with the wires.
|
||||
@@ -217,10 +217,9 @@
|
||||
/datum/wires/proc/can_see_wire_info(mob/user)
|
||||
if(user.can_admin_interact())
|
||||
return TRUE
|
||||
else if(istype(user.get_active_hand(), /obj/item/multitool))
|
||||
var/obj/item/multitool/M = user.get_active_hand()
|
||||
if(M.shows_wire_information)
|
||||
return TRUE
|
||||
var/obj/item/held_item = user.get_active_hand()
|
||||
if(istype(held_item) && HAS_TRAIT(held_item, TRAIT_SHOW_WIRE_INFO))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
|
||||
@@ -75,6 +75,12 @@
|
||||
///Used to decide what the maximum time between ambience is
|
||||
var/max_ambience_cooldown = 90 SECONDS
|
||||
|
||||
/area/New(loc, ...)
|
||||
if(!there_can_be_many) // Has to be done in New else the maploader will fuck up and find subtypes for the parent
|
||||
GLOB.all_unique_areas[type] = src
|
||||
..()
|
||||
|
||||
|
||||
/area/Initialize(mapload)
|
||||
GLOB.all_areas += src
|
||||
icon_state = ""
|
||||
|
||||
+81
-124
@@ -607,53 +607,75 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "fpmaint"
|
||||
|
||||
/area/maintenance/fpmaint
|
||||
name = "EVA Maintenance"
|
||||
name = "Fore-Port Maintenance"
|
||||
icon_state = "fpmaint"
|
||||
|
||||
/area/maintenance/fpmaint2
|
||||
name = "Arrivals North Maintenance"
|
||||
name = "Fore-Port Secondary Maintenance"
|
||||
icon_state = "fpmaint"
|
||||
|
||||
/area/maintenance/fsmaint
|
||||
name = "Dormitory Maintenance"
|
||||
name = "Fore-Starboard Maintenance"
|
||||
icon_state = "fsmaint"
|
||||
|
||||
/area/maintenance/fsmaint2
|
||||
name = "Bar Maintenance"
|
||||
name = "Fore-Starboard Secondary Maintenance"
|
||||
icon_state = "fsmaint"
|
||||
|
||||
/area/maintenance/asmaint
|
||||
name = "Medbay Maintenance"
|
||||
name = "Aft-Starboard Maintenance"
|
||||
icon_state = "asmaint"
|
||||
|
||||
/area/maintenance/asmaint2
|
||||
name = "Science Maintenance"
|
||||
name = "Aft-Starboard Secondary Maintenance"
|
||||
icon_state = "asmaint"
|
||||
|
||||
/area/maintenance/apmaint
|
||||
name = "Cargo Maintenance"
|
||||
name = "Aft-Port Maintenance"
|
||||
icon_state = "apmaint"
|
||||
|
||||
/area/maintenance/apmaint2
|
||||
name = "Aft-Port Secondary Maintenance"
|
||||
icon_state = "apmaint"
|
||||
|
||||
/area/maintenance/maintcentral
|
||||
name = "Bridge Maintenance"
|
||||
name = "Central Maintenance"
|
||||
icon_state = "maintcentral"
|
||||
|
||||
/area/maintenance/maintcentral2
|
||||
name = "Central Secondary Maintenance"
|
||||
icon_state = "maintcentral"
|
||||
/area/maintenance/fore
|
||||
name = "Fore Maintenance"
|
||||
icon_state = "fmaint"
|
||||
|
||||
/area/maintenance/fore2
|
||||
name = "Fore Secondary Maintenance"
|
||||
icon_state = "fmaint"
|
||||
|
||||
/area/maintenance/aft
|
||||
name = "Aft Maintenance"
|
||||
icon_state = "amaint"
|
||||
|
||||
/area/maintenance/aft2
|
||||
name = "Aft Secondary Maintenance"
|
||||
icon_state = "amaint"
|
||||
|
||||
/area/maintenance/starboard
|
||||
name = "Starboard Maintenance"
|
||||
icon_state = "smaint"
|
||||
|
||||
/area/maintenance/starboard2
|
||||
name = "Starboard Secondary Maintenance"
|
||||
icon_state = "smaint"
|
||||
|
||||
/area/maintenance/port
|
||||
name = "Locker Room Maintenance"
|
||||
name = "Port Maintenance"
|
||||
icon_state = "pmaint"
|
||||
|
||||
/area/maintenance/aft
|
||||
name = "Engineering Maintenance"
|
||||
icon_state = "amaint"
|
||||
|
||||
/area/maintenance/port2
|
||||
name = "Port Secondary Maintenance"
|
||||
icon_state = "pmaint"
|
||||
/area/maintenance/storage
|
||||
name = "Atmospherics Maintenance"
|
||||
icon_state = "green"
|
||||
@@ -677,18 +699,18 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
|
||||
/area/maintenance/electrical
|
||||
name = "Electrical Maintenance"
|
||||
icon_state = "yellow"
|
||||
icon_state = "elec"
|
||||
|
||||
/area/maintenance/abandonedbar
|
||||
name = "Maintenance Bar"
|
||||
icon_state = "yellow"
|
||||
icon_state = "oldbar"
|
||||
power_equip = 0
|
||||
power_light = 0
|
||||
power_environ = 0
|
||||
|
||||
/area/maintenance/electrical_shop
|
||||
name ="Electronics Den"
|
||||
icon_state = "yellow"
|
||||
icon_state = "elec"
|
||||
|
||||
/area/maintenance/gambling_den
|
||||
name = "Gambling Den"
|
||||
@@ -696,7 +718,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
|
||||
/area/maintenance/consarea
|
||||
name = "Alternate Construction Area"
|
||||
icon_state = "yellow"
|
||||
icon_state = "construction"
|
||||
|
||||
|
||||
//Hallway
|
||||
@@ -836,7 +858,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
|
||||
/area/comms
|
||||
name = "\improper Communications Relay"
|
||||
icon_state = "tcomsatcham"
|
||||
icon_state = "tcomms"
|
||||
sound_environment = SOUND_AREA_STANDARD_STATION
|
||||
|
||||
/area/server
|
||||
@@ -846,11 +868,11 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
|
||||
/area/ntrep
|
||||
name = "\improper Nanotrasen Representative's Office"
|
||||
icon_state = "bluenew"
|
||||
icon_state = "ntrep"
|
||||
|
||||
/area/blueshield
|
||||
name = "\improper Blueshield's Office"
|
||||
icon_state = "blueold"
|
||||
icon_state = "blueshield"
|
||||
|
||||
/area/centcomdocks
|
||||
name = "\improper Central Command Docks"
|
||||
@@ -919,7 +941,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
|
||||
/area/crew_quarters/bar
|
||||
name = "\improper Bar"
|
||||
icon_state = "bar"
|
||||
icon_state = "barstation"
|
||||
sound_environment = SOUND_AREA_WOODFLOOR
|
||||
|
||||
/area/crew_quarters/bar/atrium
|
||||
@@ -1048,45 +1070,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
/area/holodeck/source_knightarena
|
||||
name = "\improper Holodeck - Knight Arena"
|
||||
|
||||
|
||||
//Embassies
|
||||
/area/embassy/
|
||||
name = "\improper Embassy Hallway"
|
||||
|
||||
/area/embassy/tajaran
|
||||
name = "\improper Tajaran Embassy"
|
||||
icon_state = "tajaran"
|
||||
|
||||
/area/embassy/skrell
|
||||
name = "\improper Skrell Embassy"
|
||||
icon_state = "skrell"
|
||||
|
||||
/area/embassy/unathi
|
||||
name = "\improper Unathi Embassy"
|
||||
icon_state = "unathi"
|
||||
|
||||
/area/embassy/kidan
|
||||
name = "\improper Kidan Embassy"
|
||||
icon_state = "kidan"
|
||||
|
||||
/area/embassy/diona
|
||||
name = "\improper Diona Embassy"
|
||||
icon_state = "diona"
|
||||
|
||||
/area/embassy/slime
|
||||
name = "\improper Slime Person Embassy"
|
||||
icon_state = "slime"
|
||||
|
||||
/area/embassy/grey
|
||||
name = "\improper Grey Embassy"
|
||||
icon_state = "grey"
|
||||
|
||||
/area/embassy/vox
|
||||
name = "\improper Vox Embassy"
|
||||
icon_state = "vox"
|
||||
|
||||
|
||||
|
||||
//Engineering
|
||||
/area/engine
|
||||
ambientsounds = ENGINEERING_SOUNDS
|
||||
@@ -1108,7 +1091,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
sound_environment = SOUND_AREA_SMALL_ENCLOSED
|
||||
|
||||
/area/engine/equipmentstorage
|
||||
name = "\improper Engineering Equipment Storage"
|
||||
name = "Engineering Equipment Storage"
|
||||
icon_state = "storage"
|
||||
sound_environment = SOUND_AREA_SMALL_ENCLOSED
|
||||
|
||||
@@ -1260,7 +1243,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
|
||||
|
||||
/area/medical/biostorage
|
||||
name = "\improper Medical Storage"
|
||||
name = "Medical Storage"
|
||||
icon_state = "medbaysecstorage"
|
||||
|
||||
/area/medical/reception
|
||||
@@ -1285,19 +1268,19 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "patientsward"
|
||||
|
||||
/area/medical/patient_a
|
||||
name = "\improper Isolation A"
|
||||
name = "Isolation A"
|
||||
icon_state = "medbayisoa"
|
||||
|
||||
/area/medical/patient_b
|
||||
name = "\improper Isolation B"
|
||||
name = "Isolation B"
|
||||
icon_state = "medbayisob"
|
||||
|
||||
/area/medical/patient_c
|
||||
name = "\improper Isolation C"
|
||||
name = "Isolation C"
|
||||
icon_state = "medbayisoc"
|
||||
|
||||
/area/medical/iso_access
|
||||
name = "\improper Isolation Access"
|
||||
name = "Isolation Access"
|
||||
icon_state = "medbayisoaccess"
|
||||
|
||||
/area/medical/cmo
|
||||
@@ -1305,23 +1288,19 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "CMO"
|
||||
|
||||
/area/medical/cmostore
|
||||
name = "\improper Medical Secondary Storage"
|
||||
name = "Medical Secondary Storage"
|
||||
icon_state = "medbaysecstorage"
|
||||
|
||||
/area/medical/robotics
|
||||
name = "\improper Robotics"
|
||||
icon_state = "medresearch"
|
||||
name = "Robotics"
|
||||
icon_state = "research"
|
||||
|
||||
/area/medical/research
|
||||
name = "\improper Medical Research"
|
||||
icon_state = "medresearch"
|
||||
|
||||
/area/medical/research_shuttle_dock
|
||||
name = "\improper Research Shuttle Dock"
|
||||
icon_state = "medresearch"
|
||||
name = "Research Division"
|
||||
icon_state = "research"
|
||||
|
||||
/area/medical/virology
|
||||
name = "\improper Virology"
|
||||
name = "Virology"
|
||||
icon_state = "virology"
|
||||
|
||||
/area/medical/virology/lab
|
||||
@@ -1336,7 +1315,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
sound_environment = SOUND_AREA_SMALL_ENCLOSED
|
||||
|
||||
/area/medical/chemistry
|
||||
name = "\improper Chemistry"
|
||||
name = "Chemistry"
|
||||
icon_state = "chem"
|
||||
|
||||
/area/medical/surgery
|
||||
@@ -1344,19 +1323,19 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "surgery"
|
||||
|
||||
/area/medical/surgery1
|
||||
name = "\improper Surgery 1"
|
||||
name = "Surgery 1"
|
||||
icon_state = "surgery1"
|
||||
|
||||
/area/medical/surgery2
|
||||
name = "\improper Surgery 2"
|
||||
name = "Surgery 2"
|
||||
icon_state = "surgery2"
|
||||
|
||||
/area/medical/surgeryobs
|
||||
name = "\improper Surgery Observation"
|
||||
name = "Surgery Observation"
|
||||
icon_state = "surgery"
|
||||
|
||||
/area/medical/cryo
|
||||
name = "\improper Cryogenics"
|
||||
name = "Cryogenics"
|
||||
icon_state = "cryo"
|
||||
|
||||
/area/medical/exam_room
|
||||
@@ -1376,7 +1355,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "exam_room"
|
||||
|
||||
/area/medical/paramedic
|
||||
name = "\improper Paramedic"
|
||||
name = "Paramedic"
|
||||
icon_state = "medbay"
|
||||
|
||||
//Security
|
||||
@@ -1441,35 +1420,31 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "brig"
|
||||
|
||||
/area/security/execution
|
||||
name = "\improper Execution"
|
||||
name = "Execution"
|
||||
icon_state = "execution"
|
||||
can_get_auto_cryod = FALSE
|
||||
|
||||
/area/security/processing
|
||||
name = "\improper Prisoner Processing"
|
||||
name = "Prisoner Processing"
|
||||
icon_state = "prisonerprocessing"
|
||||
can_get_auto_cryod = FALSE
|
||||
|
||||
/area/security/interrogation
|
||||
name = "\improper Interrogation"
|
||||
name = "Interrogation"
|
||||
icon_state = "interrogation"
|
||||
can_get_auto_cryod = FALSE
|
||||
|
||||
/area/security/seceqstorage
|
||||
name = "\improper Security Equipment Storage"
|
||||
name = "Security Equipment Storage"
|
||||
icon_state = "securityequipmentstorage"
|
||||
|
||||
/area/security/interrogationhallway
|
||||
name = "\improper Interrogation Hallway"
|
||||
icon_state = "interrogationhall"
|
||||
|
||||
/area/security/courtroomdandp
|
||||
name = "\improper Courtroom Defense and Prosecution"
|
||||
icon_state = "seccourt"
|
||||
sound_environment = SOUND_AREA_LARGE_ENCLOSED
|
||||
|
||||
/area/security/interrogationobs
|
||||
name = "\improper Interrogation Observation"
|
||||
name = "Interrogation Observation"
|
||||
icon_state = "security"
|
||||
can_get_auto_cryod = FALSE
|
||||
|
||||
@@ -1505,7 +1480,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "secarmory"
|
||||
|
||||
/area/security/securehallway
|
||||
name = "\improper Security Secure Hallway"
|
||||
name = "\improper Brig Secure Hallway"
|
||||
icon_state = "securehall"
|
||||
|
||||
/area/security/hos
|
||||
@@ -1530,11 +1505,11 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "nuke_storage"
|
||||
|
||||
/area/security/customs
|
||||
name = "\improper Customs"
|
||||
name = "Customs"
|
||||
icon_state = "checkpoint1"
|
||||
|
||||
/area/security/customs2
|
||||
name = "\improper Customs"
|
||||
name = "Customs"
|
||||
icon_state = "security"
|
||||
|
||||
/area/security/checkpoint
|
||||
@@ -1601,7 +1576,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "mining"
|
||||
|
||||
/area/quartermaster/miningstorage
|
||||
name = "\improper Mining Storage"
|
||||
name = "Mining Storage"
|
||||
icon_state = "green"
|
||||
|
||||
/area/quartermaster/mechbay
|
||||
@@ -1614,7 +1589,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
sound_environment = SOUND_AREA_SMALL_ENCLOSED
|
||||
|
||||
/area/hydroponics
|
||||
name = "\improper Hydroponics"
|
||||
name = "Hydroponics"
|
||||
icon_state = "hydro"
|
||||
sound_environment = SOUND_AREA_STANDARD_STATION
|
||||
|
||||
@@ -1629,7 +1604,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
sound_environment = SOUND_AREA_STANDARD_STATION
|
||||
|
||||
/area/toxins/lab
|
||||
name = "\improper Research and Development"
|
||||
name = "Research and Development"
|
||||
icon_state = "toxlab"
|
||||
|
||||
/area/toxins/hallway
|
||||
@@ -1650,7 +1625,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
xenobiology_compatible = TRUE
|
||||
|
||||
/area/toxins/xenobiology/xenoflora_storage
|
||||
name = "\improper Xenoflora Storage"
|
||||
name = "Xenoflora Storage"
|
||||
icon_state = "toxlab"
|
||||
|
||||
/area/toxins/xenobiology/xenoflora
|
||||
@@ -1658,7 +1633,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "toxlab"
|
||||
|
||||
/area/toxins/storage
|
||||
name = "\improper Toxins Storage"
|
||||
name = "Toxins Storage"
|
||||
icon_state = "toxstorage"
|
||||
|
||||
/area/toxins/test_area
|
||||
@@ -1671,7 +1646,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "toxmix"
|
||||
|
||||
/area/toxins/launch
|
||||
name = "Toxins Launch Room"
|
||||
name = "\improper Toxins Launch Room"
|
||||
icon_state = "toxlaunch"
|
||||
|
||||
/area/toxins/misc_lab
|
||||
@@ -1739,7 +1714,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "auxstorage"
|
||||
|
||||
/area/storage/office
|
||||
name = "\improper Office Supplies"
|
||||
name = "Office Supplies"
|
||||
icon_state = "office_supplies"
|
||||
|
||||
// ENGIE OUTPOST
|
||||
@@ -2061,45 +2036,27 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
|
||||
/area/tcommsat/chamber
|
||||
name = "\improper Telecoms Central Compartment"
|
||||
icon_state = "tcomsatcham"
|
||||
icon_state = "tcomms"
|
||||
|
||||
// These areas are needed for MetaStation's AI sat
|
||||
/area/turret_protected/tcomsat
|
||||
name = "\improper Telecoms Satellite"
|
||||
icon_state = "tcomsatlob"
|
||||
ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
|
||||
|
||||
/area/turret_protected/tcomfoyer
|
||||
name = "\improper Telecoms Foyer"
|
||||
icon_state = "tcomsatentrance"
|
||||
ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
|
||||
|
||||
/area/turret_protected/tcomwest
|
||||
name = "\improper Telecoms West Wing"
|
||||
icon_state = "tcomsatwest"
|
||||
icon_state = "tcomms"
|
||||
ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
|
||||
|
||||
/area/turret_protected/tcomeast
|
||||
name = "\improper Telecoms East Wing"
|
||||
icon_state = "tcomsateast"
|
||||
icon_state = "tcomms"
|
||||
ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
|
||||
|
||||
/area/tcommsat/computer
|
||||
name = "\improper Telecoms Control Room"
|
||||
icon_state = "tcomsatcomp"
|
||||
icon_state = "tcomms"
|
||||
sound_environment = SOUND_AREA_MEDIUM_SOFTFLOOR
|
||||
|
||||
/area/tcommsat/server
|
||||
name = "\improper Telecoms Server Room"
|
||||
icon_state = "tcomsatcham"
|
||||
|
||||
/area/tcommsat/lounge
|
||||
name = "\improper Telecoms Lounge"
|
||||
icon_state = "tcomsatlounge"
|
||||
|
||||
/area/tcommsat/powercontrol
|
||||
name = "\improper Telecoms Power Control"
|
||||
icon_state = "tcomsatwest"
|
||||
icon_state = "tcomms"
|
||||
|
||||
// Away Missions
|
||||
/area/awaymission
|
||||
|
||||
+3
-3
@@ -413,6 +413,9 @@
|
||||
/atom/proc/emag_act()
|
||||
return
|
||||
|
||||
/atom/proc/unemag()
|
||||
return
|
||||
|
||||
/**
|
||||
* Respond to a radioactive wave hitting this atom
|
||||
*
|
||||
@@ -941,9 +944,6 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
|
||||
/atom/proc/narsie_act()
|
||||
return
|
||||
|
||||
/atom/proc/ratvar_act()
|
||||
return
|
||||
|
||||
/**
|
||||
* Respond to an electric bolt action on our item
|
||||
*
|
||||
|
||||
@@ -178,14 +178,19 @@
|
||||
/mob/living/carbon/med_hud_set_status()
|
||||
var/image/holder = hud_list[STATUS_HUD]
|
||||
var/mob/living/simple_animal/borer/B = has_brain_worms()
|
||||
var/dead = stat == DEAD || HAS_TRAIT(src, TRAIT_FAKEDEATH)
|
||||
// To the right of health bar
|
||||
if(dead)
|
||||
var/revivable = timeofdeath && (round(world.time - timeofdeath) < DEFIB_TIME_LIMIT)
|
||||
if(stat == DEAD || HAS_TRAIT(src, TRAIT_FAKEDEATH))
|
||||
var/revivable
|
||||
if(!ghost_can_reenter()) // DNR or AntagHUD
|
||||
revivable = FALSE
|
||||
else if(timeofdeath && (round(world.time - timeofdeath) < DEFIB_TIME_LIMIT))
|
||||
revivable = TRUE
|
||||
|
||||
if(revivable)
|
||||
holder.icon_state = "hudflatline"
|
||||
else
|
||||
holder.icon_state = "huddead"
|
||||
|
||||
else if(HAS_TRAIT(src, TRAIT_XENO_HOST))
|
||||
holder.icon_state = "hudxeno"
|
||||
else if(B && B.controlling)
|
||||
|
||||
@@ -14,6 +14,7 @@ GLOBAL_LIST_INIT(assigned_mutation_blocks, new(DNA_SE_LENGTH))
|
||||
// Used to determine what each block means (admin hax and species stuff on /vg/, mostly)
|
||||
GLOBAL_LIST_INIT(assigned_blocks, new(DNA_SE_LENGTH))
|
||||
|
||||
/// Assoc list. Key = type of the mutation, value = the mutation
|
||||
GLOBAL_LIST_EMPTY(dna_mutations)
|
||||
|
||||
GLOBAL_LIST_EMPTY(good_blocks)
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
// M: Mob to mess with
|
||||
// flags: See below, bitfield.
|
||||
/proc/domutcheck(mob/living/M, flags = 0)
|
||||
for(var/datum/mutation/mutation in GLOB.dna_mutations)
|
||||
for(var/mutation_type in GLOB.dna_mutations)
|
||||
var/datum/mutation/mutation = GLOB.dna_mutations[mutation_type]
|
||||
if(!M || !M.dna)
|
||||
return
|
||||
if(!mutation.block)
|
||||
@@ -32,7 +33,7 @@
|
||||
var/mutation_active = M.dna.GetSEState(mutation.block)
|
||||
|
||||
// Sanity checks, don't skip.
|
||||
if(!mutation.can_activate(M, flags) && mutation_active)
|
||||
if(mutation_active && !mutation.can_activate(M, flags))
|
||||
//testing("[M] - Failed to activate [gene.name] (can_activate fail).")
|
||||
return FALSE
|
||||
|
||||
@@ -46,11 +47,7 @@
|
||||
if(mutation_active)
|
||||
//testing("[gene.name] activated!")
|
||||
mutation.activate(M)
|
||||
if(M)
|
||||
M.active_mutations |= mutation.type
|
||||
// If Gene is NOT active:
|
||||
else
|
||||
//testing("[gene.name] deactivated!")
|
||||
mutation.deactivate(M)
|
||||
if(M)
|
||||
M.active_mutations -= mutation.type
|
||||
|
||||
@@ -150,16 +150,16 @@
|
||||
if(usr.incapacitated() || usr.buckled) //are you cuffed, dying, lying, stunned or other
|
||||
return
|
||||
if(!ishuman(usr)) //Make sure they're a mob that has dna
|
||||
to_chat(usr, "<span class='notice'>Try as you might, you can not climb up into the [src].</span>")
|
||||
to_chat(usr, "<span class='notice'>Try as you might, you can not climb up into [src].</span>")
|
||||
return
|
||||
if(occupant)
|
||||
to_chat(usr, "<span class='boldnotice'>The [src] is already occupied!</span>")
|
||||
to_chat(usr, "<span class='boldnotice'>[src] is already occupied!</span>")
|
||||
return
|
||||
if(usr.abiotic())
|
||||
to_chat(usr, "<span class='boldnotice'>Subject cannot have abiotic items on.</span>")
|
||||
return
|
||||
if(usr.has_buckled_mobs()) //mob attached to us
|
||||
to_chat(usr, "<span class='warning'>[usr] will not fit into the [src] because [usr.p_they()] [usr.p_have()] a slime latched onto [usr.p_their()] head.</span>")
|
||||
to_chat(usr, "<span class='warning'>[usr] will not fit into [src] because [usr.p_they()] [usr.p_have()] a slime latched onto [usr.p_their()] head.</span>")
|
||||
return
|
||||
usr.stop_pulling()
|
||||
usr.forceMove(src)
|
||||
@@ -188,7 +188,7 @@
|
||||
if(!istype(user.loc, /turf) || !istype(O.loc, /turf)) // are you in a container/closet/pod/etc?
|
||||
return
|
||||
if(occupant)
|
||||
to_chat(user, "<span class='boldnotice'>The [src] is already occupied!</span>")
|
||||
to_chat(user, "<span class='boldnotice'>[src] is already occupied!</span>")
|
||||
return
|
||||
var/mob/living/L = O
|
||||
if(!istype(L) || L.buckled)
|
||||
@@ -200,9 +200,9 @@
|
||||
to_chat(user, "<span class='warning'>[L] will not fit into [src] because [L.p_they()] [L.p_have()] a slime latched onto [L.p_their()] head.</span>")
|
||||
return
|
||||
if(L == user)
|
||||
visible_message("[user] climbs into the [src].")
|
||||
visible_message("<span class='notice'>[user] climbs into [src].</span>")
|
||||
else
|
||||
visible_message("[user] puts [L.name] into the [src].")
|
||||
visible_message("<span class='notice'>[user] puts [L.name] into [src].</span>")
|
||||
put_in(L)
|
||||
if(user.pulling == L)
|
||||
user.stop_pulling()
|
||||
@@ -235,7 +235,7 @@
|
||||
to_chat(user, "<span class='boldnotice'>Subject cannot have abiotic items on.</span>")
|
||||
return
|
||||
if(G.affecting.has_buckled_mobs()) //mob attached to us
|
||||
to_chat(user, "<span class='warning'>will not fit into the [src] because [G.affecting.p_they()] [G.affecting.p_have()] a slime latched onto [G.affecting.p_their()] head.</span>")
|
||||
to_chat(user, "<span class='warning'>[G] will not fit into [src] because [G.affecting.p_they()] [G.affecting.p_have()] a slime latched onto [G.affecting.p_their()] head.</span>")
|
||||
return
|
||||
if(panel_open)
|
||||
to_chat(usr, "<span class='boldnotice'>Close the maintenance panel first.</span>")
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
|
||||
// Called when the gene activates. Do your magic here.
|
||||
/datum/mutation/proc/activate(mob/living/M)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
M.gene_stability -= instability
|
||||
M.active_mutations |= type // |= is probably not required but just in case
|
||||
for(var/thing in traits_to_add)
|
||||
ADD_TRAIT(M, thing, GENETIC_MUTATION)
|
||||
if(length(activation_messages))
|
||||
@@ -42,7 +44,9 @@
|
||||
// Called when the gene deactivates. Undo your magic here.
|
||||
// Only called when the block is deactivated.
|
||||
/datum/mutation/proc/deactivate(mob/living/M)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
M.gene_stability += instability
|
||||
M.active_mutations -= type
|
||||
for(var/thing in traits_to_add)
|
||||
REMOVE_TRAIT(M, thing, GENETIC_MUTATION)
|
||||
if(length(deactivation_messages))
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
return ishuman(M)
|
||||
|
||||
/datum/mutation/monkey/activate(mob/living/carbon/human/H)
|
||||
..()
|
||||
if(!istype(H))
|
||||
return
|
||||
if(issmall(H))
|
||||
@@ -42,6 +43,7 @@
|
||||
return H
|
||||
|
||||
/datum/mutation/monkey/deactivate(mob/living/carbon/human/H)
|
||||
..()
|
||||
if(!istype(H))
|
||||
return
|
||||
if(!issmall(H))
|
||||
|
||||
@@ -15,7 +15,6 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
recommended_enemies = 1
|
||||
restricted_jobs = list("Cyborg", "AI")
|
||||
|
||||
var/declared = 0
|
||||
var/burst = 0
|
||||
|
||||
var/cores_to_spawn = 1
|
||||
@@ -75,8 +74,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
log_game("[key_name(blob)] has been selected as a Blob")
|
||||
greet_blob(blobmind)
|
||||
to_chat(blob, "<span class='userdanger'>You feel very tired and bloated! You don't have long before you burst!</span>")
|
||||
spawn(600)
|
||||
burst_blob(blobmind)
|
||||
addtimer(CALLBACK(src, .proc/burst_blob, blobmind), 60 SECONDS)
|
||||
return 1
|
||||
|
||||
/datum/game_mode/blob/proc/make_blobs(count)
|
||||
@@ -103,6 +101,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
to_chat(blob.current, "<b>Find a good location to spawn the core and then take control and overwhelm the station!</b>")
|
||||
to_chat(blob.current, "<b>When you have found a location, wait until you spawn; this will happen automatically and you cannot speed up the process.</b>")
|
||||
to_chat(blob.current, "<b>If you go outside of the station level, or in space, then you will die; make sure your location has lots of ground to cover.</b>")
|
||||
to_chat(blob.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Blob)</span>")
|
||||
SEND_SOUND(blob.current, sound('sound/magic/mutate.ogg'))
|
||||
return
|
||||
|
||||
@@ -127,8 +126,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
if(!warned)
|
||||
to_chat(C, "<span class='userdanger'>You feel ready to burst, but this isn't an appropriate place! You must return to the station!</span>")
|
||||
message_admins("[key_name_admin(C)] was in space when the blobs burst, and will die if [C.p_they()] [C.p_do()] not return to the station.")
|
||||
spawn(300)
|
||||
burst_blob(blob, 1)
|
||||
addtimer(CALLBACK(src, .proc/burst_blob, blob, 1), 30 SECONDS)
|
||||
else
|
||||
burst++
|
||||
log_admin("[key_name(C)] was in space when attempting to burst as a blob.")
|
||||
@@ -172,33 +170,22 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
|
||||
show_message("<span class='userdanger'>You feel like you are about to burst.</span>")
|
||||
|
||||
sleep(wait_time / 2)
|
||||
|
||||
burst_blobs()
|
||||
|
||||
// Stage 0
|
||||
sleep(wait_time)
|
||||
stage(0)
|
||||
addtimer(CALLBACK(src, .proc/burst_blobs), (wait_time / 2))
|
||||
|
||||
// Stage 1
|
||||
sleep(wait_time)
|
||||
stage(1)
|
||||
addtimer(CALLBACK(src, .proc/stage, 1), (wait_time * 2 + wait_time / 2))
|
||||
|
||||
// Stage 2
|
||||
sleep(30000)
|
||||
stage(2)
|
||||
addtimer(CALLBACK(src, .proc/stage, 2), 50 MINUTES)
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/blob/proc/stage(stage)
|
||||
switch(stage)
|
||||
if(0)
|
||||
send_intercept(1)
|
||||
declared = 1
|
||||
if(1)
|
||||
GLOB.event_announcement.Announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak5.ogg')
|
||||
if(2)
|
||||
send_intercept(2)
|
||||
send_intercept(1)
|
||||
|
||||
/datum/game_mode/proc/update_blob_icons_added(datum/mind/mob_mind)
|
||||
var/datum/atom_hud/antag/antaghud = GLOB.huds[ANTAG_HUD_BLOB]
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
to_chat(world, "<FONT size = 3><B>The staff has won!</B></FONT>")
|
||||
to_chat(world, "<B>The alien organism has been eradicated from the station</B>")
|
||||
log_game("Blob mode completed with a crew victory.")
|
||||
to_chat(world, "<span class='notice'>Rebooting in 30s</span>")
|
||||
..()
|
||||
return 1
|
||||
|
||||
|
||||
@@ -5,19 +5,6 @@
|
||||
if(0)
|
||||
return
|
||||
if(1)
|
||||
interceptname = "Level 5-6 Biohazard Response Procedures"
|
||||
intercepttext += "<FONT size = 3><B>Nanotrasen Update</B>: Biohazard Alert.</FONT><HR>"
|
||||
intercepttext += "Reports indicate the probable transfer of a biohazardous agent onto [station_name()] during the last crew deployment cycle.<BR>"
|
||||
intercepttext += "Preliminary analysis of the organism classifies it as a level 5 biohazard. Its origin is unknown.<BR>"
|
||||
intercepttext += "Nanotrasen has issued a directive 7-10 for [station_name()]. The station is to be considered quarantined.<BR>"
|
||||
intercepttext += "Orders for all [station_name()] personnel follows:<BR>"
|
||||
intercepttext += " 1. Do not leave the quarantine area.<BR>"
|
||||
intercepttext += " 2. Locate any outbreaks of the organism on the station.<BR>"
|
||||
intercepttext += " 3. If found, use any neccesary means to contain the organism.<BR>"
|
||||
intercepttext += " 4. Avoid damage to the capital infrastructure of the station.<BR>"
|
||||
intercepttext += "<BR>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.<BR>"
|
||||
intercepttext += "Message ends."
|
||||
if(2)
|
||||
var/nukecode = rand(10000, 99999)
|
||||
for(var/obj/machinery/nuclearbomb/bomb in GLOB.machines)
|
||||
if(bomb && bomb.r_code)
|
||||
|
||||
@@ -117,13 +117,13 @@
|
||||
|
||||
if(C && !QDELETED(src))
|
||||
var/mob/camera/blob/B = new(loc)
|
||||
B.is_offspring = is_offspring
|
||||
B.key = C.key
|
||||
B.blob_core = src
|
||||
overmind = B
|
||||
color = overmind.blob_reagent_datum.color
|
||||
if(B.mind && !B.mind.special_role)
|
||||
B.mind.make_Overmind()
|
||||
B.is_offspring = is_offspring
|
||||
|
||||
/obj/structure/blob/core/proc/lateblobtimer()
|
||||
addtimer(CALLBACK(src, .proc/lateblobcheck), 50)
|
||||
|
||||
@@ -147,6 +147,7 @@ GLOBAL_LIST_INIT(possible_changeling_IDs, list("Alpha","Beta","Gamma","Delta","E
|
||||
for(var/datum/objective/objective in changeling.objectives)
|
||||
to_chat(changeling.current, "<B>Objective #[obj_count]</B>: [objective.explanation_text]")
|
||||
obj_count++
|
||||
to_chat(changeling.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Changeling)</span>")
|
||||
return
|
||||
|
||||
/datum/game_mode/proc/remove_changeling(datum/mind/changeling_mind)
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
to_chat(user, "<span class='notice'>We stealthily stab [target] with a minor proboscis...</span>")
|
||||
to_chat(target, "<span class='userdanger'>You experience a stabbing sensation and your ears begin to ring...</span>")
|
||||
if(3)
|
||||
to_chat(user, "<span class='notice'>You mold the [target]'s mind like clay, [target.p_they()] can now speak in the hivemind!</span>")
|
||||
to_chat(user, "<span class='notice'>You mold [target]'s mind like clay, [target.p_they()] can now speak in the hivemind!</span>")
|
||||
to_chat(target, "<span class='userdanger'>A migraine throbs behind your eyes, you hear yourself screaming - but your mouth has not opened!</span>")
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
if(GLOB.all_languages["Changeling"] in M.languages)
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
/datum/action/changeling/weapon/sting_action(mob/user)
|
||||
if(!user.drop_item())
|
||||
to_chat(user, "The [user.get_active_hand()] is stuck to your hand, you cannot grow a [weapon_name_simple] over it!")
|
||||
to_chat(user, "[user.get_active_hand()] is stuck to your hand, you cannot grow a [weapon_name_simple] over it!")
|
||||
return
|
||||
var/obj/item/W = new weapon_type(user, silent)
|
||||
user.put_in_hands(W)
|
||||
@@ -173,8 +173,11 @@
|
||||
name = "Tentacle"
|
||||
desc = "We ready a tentacle to grab items or victims with. Costs 10 chemicals."
|
||||
helptext = "We can use it once to retrieve a distant item. If used on living creatures, the effect depends on the intent: \
|
||||
Help will simply drag them closer, Disarm will grab whatever they are holding instead of them, Grab will put the victim in our hold after catching it, \
|
||||
and Harm will stun it, and stab it if we are also holding a sharp weapon. Cannot be used while in lesser form."
|
||||
Help will drag the target closer. \
|
||||
Disarm will grab whatever the target is holding. \
|
||||
Grab will put the target in our grip after we catch it. \
|
||||
Harm will drag the target closer and stab it if we are holding a sharp weapon in our other hand. \
|
||||
Cannot be used while in our lesser form."
|
||||
button_icon_state = "tentacle"
|
||||
chemical_cost = 10
|
||||
dna_cost = 2
|
||||
@@ -209,7 +212,7 @@
|
||||
to_chat(loc, "<span class='notice'>You prepare to extend a tentacle.</span>")
|
||||
|
||||
/obj/item/gun/magic/tentacle/shoot_with_empty_chamber(mob/living/user as mob|obj)
|
||||
to_chat(user, "<span class='warning'>The [name] is not ready yet.</span>")
|
||||
to_chat(user, "<span class='warning'>[src] is not ready yet.</span>")
|
||||
|
||||
/obj/item/gun/magic/tentacle/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] coils [src] tightly around [user.p_their()] neck! It looks like [user.p_theyre()] trying to commit suicide.</span>")
|
||||
|
||||
@@ -249,7 +249,7 @@
|
||||
/datum/action/innate/cult/blood_spell/horror/Destroy()
|
||||
var/obj/effect/proc_holder/horror/destroy = PH
|
||||
. = ..()
|
||||
if(destroy && !QDELETED(destroy))
|
||||
if(!QDELETED(destroy))
|
||||
QDEL_NULL(destroy)
|
||||
|
||||
/datum/action/innate/cult/blood_spell/horror/Activate()
|
||||
@@ -264,7 +264,7 @@
|
||||
/obj/effect/proc_holder/horror/Destroy()
|
||||
var/datum/action/innate/cult/blood_spell/AA = attached_action
|
||||
. = ..()
|
||||
if(AA && !QDELETED(AA))
|
||||
if(!QDELETED(AA))
|
||||
QDEL_NULL(AA)
|
||||
|
||||
/obj/effect/proc_holder/horror/proc/toggle(mob/user)
|
||||
@@ -464,9 +464,15 @@
|
||||
var/list/potential_runes = list()
|
||||
var/list/teleportnames = list()
|
||||
var/list/duplicaterunecount = list()
|
||||
var/atom/movable/teleportee
|
||||
if(!iscultist(target) || !proximity)
|
||||
to_chat(user, "<span class='warning'>You can only teleport adjacent cultists with this spell!</span>")
|
||||
return
|
||||
if(user != target) // So that the teleport effect shows on the correct mob
|
||||
teleportee = target
|
||||
else
|
||||
teleportee = user
|
||||
|
||||
for(var/R in GLOB.teleport_runes)
|
||||
var/obj/effect/rune/teleport/T = R
|
||||
var/resultkey = T.listkey
|
||||
@@ -487,16 +493,15 @@
|
||||
log_game("Teleport spell failed - user in away mission")
|
||||
return
|
||||
|
||||
var/mob/living/L = target
|
||||
var/input_rune_key = input(user, "Choose a rune to teleport to.", "Rune to Teleport to") as null|anything in potential_runes //we know what key they picked
|
||||
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
|
||||
if(!src || QDELETED(src) || !user || user.l_hand != src && user.r_hand != src || user.incapacitated() || !actual_selected_rune)
|
||||
if(QDELETED(src) || !user || user.l_hand != src && user.r_hand != src || user.incapacitated() || !actual_selected_rune)
|
||||
return
|
||||
uses--
|
||||
|
||||
var/turf/origin = get_turf(user)
|
||||
var/turf/origin = get_turf(teleportee)
|
||||
var/turf/destination = get_turf(actual_selected_rune)
|
||||
INVOKE_ASYNC(actual_selected_rune, /obj/effect/rune/.proc/teleport_effect, user, origin, destination)
|
||||
INVOKE_ASYNC(actual_selected_rune, /obj/effect/rune/.proc/teleport_effect, teleportee, origin, destination)
|
||||
|
||||
if(is_mining_level(user.z) && !is_mining_level(destination.z)) //No effect if you stay on lavaland
|
||||
actual_selected_rune.handle_portal("lava")
|
||||
@@ -510,7 +515,7 @@
|
||||
target.visible_message("<span class='warning'>Dust flows from [user]'s hand, and [target] disappears in a flash of red light!</span>", \
|
||||
"<span class='cultitalic'>You suddenly find yourself somewhere else!</span>")
|
||||
destination.visible_message("<span class='warning'>There is a boom of outrushing air as something appears above the rune!</span>", null, "<i>You hear a boom.</i>")
|
||||
L.forceMove(destination)
|
||||
teleportee.forceMove(destination)
|
||||
return ..()
|
||||
|
||||
//Shackles
|
||||
@@ -658,7 +663,7 @@
|
||||
/obj/item/melee/blood_magic/empower/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
if(proximity_flag)
|
||||
|
||||
//Shielded suit
|
||||
// Shielded suit
|
||||
if(istype(target, /obj/item/clothing/suit/hooded/cultrobes/cult_shield))
|
||||
var/obj/item/clothing/suit/hooded/cultrobes/cult_shield/C = target
|
||||
if(C.current_charges < 3)
|
||||
@@ -672,7 +677,7 @@
|
||||
to_chat(user, "<span class='warning'>[target] is already at full charge!</span>")
|
||||
return
|
||||
|
||||
//Plasteel to runed metal
|
||||
// Veil Shifter
|
||||
else if(istype(target, /obj/item/cult_shift))
|
||||
var/obj/item/cult_shift/S = target
|
||||
if(S.uses < 4)
|
||||
@@ -846,39 +851,6 @@
|
||||
var/list/options = list("Blood Orb (50)", "Blood Recharge (75)", "Blood Spear (150)", "Blood Bolt Barrage (300)")
|
||||
var/choice = input(user, "Choose a greater blood rite...", "Greater Blood Rites") as null|anything in options
|
||||
switch(choice)
|
||||
if("Blood Spear (150)")
|
||||
if(uses < BLOOD_SPEAR_COST)
|
||||
to_chat(user, "<span class='warning'>You need [BLOOD_SPEAR_COST] charges to perform this rite.</span>")
|
||||
else
|
||||
uses -= BLOOD_SPEAR_COST
|
||||
var/turf/T = get_turf(user)
|
||||
qdel(src)
|
||||
var/datum/action/innate/cult/spear/S = new(user)
|
||||
var/obj/item/twohanded/cult_spear/rite = new(T)
|
||||
S.Grant(user, rite)
|
||||
rite.spear_act = S
|
||||
if(user.put_in_hands(rite))
|
||||
to_chat(user, "<span class='cult'>A [rite.name] appears in your hand!</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>A [rite.name] appears at [user]'s feet!</span>", \
|
||||
"<span class='cult'>A [rite.name] materializes at your feet.</span>")
|
||||
|
||||
if("Blood Bolt Barrage (300)")
|
||||
if(uses < BLOOD_BARRAGE_COST)
|
||||
to_chat(user, "<span class='cultitalic'>You need [BLOOD_BARRAGE_COST] charges to perform this rite.</span>")
|
||||
else
|
||||
var/obj/rite = new /obj/item/gun/projectile/shotgun/boltaction/enchanted/arcane_barrage/blood()
|
||||
uses -= BLOOD_BARRAGE_COST
|
||||
qdel(src)
|
||||
user.swap_hand()
|
||||
user.drop_item()
|
||||
if(user.put_in_hands(rite))
|
||||
to_chat(user, "<span class='cult'>Both of your hands glow with power!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need a free hand for this rite!</span>")
|
||||
uses += BLOOD_BARRAGE_COST // Refund the charges
|
||||
qdel(rite)
|
||||
|
||||
if("Blood Orb (50)")
|
||||
if(uses < BLOOD_ORB_COST)
|
||||
to_chat(user, "<span class='warning'>You need [BLOOD_ORB_COST] charges to perform this rite.</span>")
|
||||
@@ -898,7 +870,7 @@
|
||||
if(user.put_in_hands(rite))
|
||||
to_chat(user, "<span class='cult'>A [rite.name] appears in your hand!</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>A [rite.name] appears at [user]'s feet!</span>", \
|
||||
user.visible_message("<span class='warning'>A [rite.name] appears at [user]'s feet!</span>",
|
||||
"<span class='cult'>A [rite.name] materializes at your feet.</span>")
|
||||
|
||||
if("Blood Recharge (75)")
|
||||
@@ -914,3 +886,36 @@
|
||||
to_chat(user, "<span class='warning'>You need a free hand for this rite!</span>")
|
||||
uses += BLOOD_RECHARGE_COST // Refund the charges
|
||||
qdel(rite)
|
||||
|
||||
if("Blood Spear (150)")
|
||||
if(uses < BLOOD_SPEAR_COST)
|
||||
to_chat(user, "<span class='warning'>You need [BLOOD_SPEAR_COST] charges to perform this rite.</span>")
|
||||
else
|
||||
uses -= BLOOD_SPEAR_COST
|
||||
var/turf/T = get_turf(user)
|
||||
qdel(src)
|
||||
var/datum/action/innate/cult/spear/S = new(user)
|
||||
var/obj/item/twohanded/cult_spear/rite = new(T)
|
||||
S.Grant(user, rite)
|
||||
rite.spear_act = S
|
||||
if(user.put_in_hands(rite))
|
||||
to_chat(user, "<span class='cult'>A [rite.name] appears in your hand!</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>A [rite.name] appears at [user]'s feet!</span>",
|
||||
"<span class='cult'>A [rite.name] materializes at your feet.</span>")
|
||||
|
||||
if("Blood Bolt Barrage (300)")
|
||||
if(uses < BLOOD_BARRAGE_COST)
|
||||
to_chat(user, "<span class='cultitalic'>You need [BLOOD_BARRAGE_COST] charges to perform this rite.</span>")
|
||||
else
|
||||
var/obj/rite = new /obj/item/gun/projectile/shotgun/boltaction/enchanted/arcane_barrage/blood()
|
||||
uses -= BLOOD_BARRAGE_COST
|
||||
qdel(src)
|
||||
user.swap_hand()
|
||||
user.drop_item()
|
||||
if(user.put_in_hands(rite))
|
||||
to_chat(user, "<span class='cult'>Both of your hands glow with power!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need a free hand for this rite!</span>")
|
||||
uses += BLOOD_BARRAGE_COST // Refund the charges
|
||||
qdel(rite)
|
||||
|
||||
@@ -85,6 +85,9 @@ GLOBAL_LIST_EMPTY(all_cults)
|
||||
to_chat(cult_mind.current, CULT_GREETING)
|
||||
equip_cultist(cult_mind.current)
|
||||
cult_mind.current.faction |= "cult"
|
||||
var/datum/objective/servecult/obj = new
|
||||
obj.owner = cult_mind
|
||||
cult_mind.objectives += obj
|
||||
|
||||
if(cult_mind.assigned_role == "Clown")
|
||||
to_chat(cult_mind.current, "<span class='cultitalic'>A dark power has allowed you to overcome your clownish nature, letting you wield weapons without harming yourself.</span>")
|
||||
@@ -96,54 +99,11 @@ GLOBAL_LIST_EMPTY(all_cults)
|
||||
add_cult_actions(cult_mind)
|
||||
update_cult_icons_added(cult_mind)
|
||||
cult_objs.study(cult_mind.current)
|
||||
to_chat(cult_mind.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Cultist)</span>")
|
||||
cult_threshold_check()
|
||||
addtimer(CALLBACK(src, .proc/cult_threshold_check), 2 MINUTES) // Check again in 2 minutes for latejoiners
|
||||
..()
|
||||
|
||||
/**
|
||||
* Decides at the start of the round how many conversions are needed to rise/ascend.
|
||||
*
|
||||
* The number is decided by (Percentage * (Players - Cultists)), so for example at 110 players it would be 11 conversions for rise. (0.1 * (110 - 4))
|
||||
* These values change based on population because 20 cultists are MUCH more powerful if there's only 50 players, compared to 120.
|
||||
*
|
||||
* Below 100 players, [CULT_RISEN_LOW] and [CULT_ASCENDANT_LOW] are used.
|
||||
* Above 100 players, [CULT_RISEN_HIGH] and [CULT_ASCENDANT_HIGH] are used.
|
||||
*/
|
||||
/datum/game_mode/proc/cult_threshold_check()
|
||||
var/players = length(GLOB.player_list)
|
||||
var/cultists = get_cultists() // Don't count the starting cultists towards the number of needed conversions
|
||||
if(players >= CULT_POPULATION_THRESHOLD)
|
||||
// Highpop
|
||||
ascend_percent = CULT_ASCENDANT_HIGH
|
||||
rise_number = round(CULT_RISEN_HIGH * (players - cultists))
|
||||
ascend_number = round(CULT_ASCENDANT_HIGH * (players - cultists))
|
||||
else
|
||||
// Lowpop
|
||||
ascend_percent = CULT_ASCENDANT_LOW
|
||||
rise_number = round(CULT_RISEN_LOW * (players - cultists))
|
||||
ascend_number = round(CULT_ASCENDANT_LOW * (players - cultists))
|
||||
|
||||
/**
|
||||
* Returns the current number of cultists and constructs.
|
||||
*
|
||||
* Returns the number of cultists and constructs in a list ([1] = Cultists, [2] = Constructs), or as one combined number.
|
||||
*
|
||||
* * separate - Should the number be returned in two separate values (Humans and Constructs) or as one?
|
||||
*/
|
||||
/datum/game_mode/proc/get_cultists(separate = FALSE)
|
||||
var/cultists = 0
|
||||
var/constructs = 0
|
||||
for(var/I in cult)
|
||||
var/datum/mind/M = I
|
||||
if(ishuman(M.current) && !M.current.has_status_effect(STATUS_EFFECT_SUMMONEDGHOST))
|
||||
cultists++
|
||||
else if(isconstruct(M.current))
|
||||
constructs++
|
||||
if(separate)
|
||||
return list(cultists, constructs)
|
||||
else
|
||||
return cultists + constructs
|
||||
|
||||
/datum/game_mode/proc/equip_cultist(mob/living/carbon/human/H, metal = TRUE)
|
||||
if(!istype(H))
|
||||
return
|
||||
@@ -207,8 +167,84 @@ GLOBAL_LIST_EMPTY(all_cults)
|
||||
ascend(cult_mind.current)
|
||||
check_cult_size()
|
||||
cult_objs.study(cult_mind.current)
|
||||
to_chat(cult_mind.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Cultist)</span>")
|
||||
return TRUE
|
||||
|
||||
/datum/game_mode/proc/remove_cultist(datum/mind/cult_mind, show_message = TRUE, remove_gear = FALSE)
|
||||
if(!(cult_mind in cult)) // Not actually a cultist in the first place
|
||||
return
|
||||
|
||||
var/mob/cultist = cult_mind.current
|
||||
cult -= cult_mind
|
||||
cultist.faction -= "cult"
|
||||
cult_mind.special_role = null
|
||||
for(var/datum/objective/servecult/S in cult_mind.objectives)
|
||||
cult_mind.objectives -= S
|
||||
qdel(S)
|
||||
for(var/datum/action/innate/cult/C in cultist.actions)
|
||||
qdel(C)
|
||||
update_cult_icons_removed(cult_mind)
|
||||
|
||||
if(ishuman(cultist))
|
||||
var/mob/living/carbon/human/H = cultist
|
||||
REMOVE_TRAIT(H, CULT_EYES, null)
|
||||
H.change_eye_color(H.original_eye_color, FALSE)
|
||||
H.update_eyes()
|
||||
H.remove_overlay(HALO_LAYER)
|
||||
H.update_body()
|
||||
if(remove_gear) // No flagellants robe for non-cultists
|
||||
for(var/I in H.contents)
|
||||
if(is_type_in_list(I, CULT_CLOTHING))
|
||||
H.unEquip(I)
|
||||
check_cult_size()
|
||||
if(show_message)
|
||||
cultist.visible_message("<span class='cult'>[cultist] looks like [cultist.p_they()] just reverted to [cultist.p_their()] old faith!</span>",
|
||||
"<span class='userdanger'>An unfamiliar white light flashes through your mind, cleansing the taint of [SSticker.cultdat ? SSticker.cultdat.entity_title1 : "Nar'Sie"] and the memories of your time as their servant with it.</span>")
|
||||
|
||||
|
||||
/**
|
||||
* Decides at the start of the round how many conversions are needed to rise/ascend.
|
||||
*
|
||||
* The number is decided by (Percentage * (Players - Cultists)), so for example at 110 players it would be 11 conversions for rise. (0.1 * (110 - 4))
|
||||
* These values change based on population because 20 cultists are MUCH more powerful if there's only 50 players, compared to 120.
|
||||
*
|
||||
* Below 100 players, [CULT_RISEN_LOW] and [CULT_ASCENDANT_LOW] are used.
|
||||
* Above 100 players, [CULT_RISEN_HIGH] and [CULT_ASCENDANT_HIGH] are used.
|
||||
*/
|
||||
/datum/game_mode/proc/cult_threshold_check()
|
||||
var/players = length(GLOB.player_list)
|
||||
var/cultists = get_cultists() // Don't count the starting cultists towards the number of needed conversions
|
||||
if(players >= CULT_POPULATION_THRESHOLD)
|
||||
// Highpop
|
||||
ascend_percent = CULT_ASCENDANT_HIGH
|
||||
rise_number = round(CULT_RISEN_HIGH * (players - cultists))
|
||||
ascend_number = round(CULT_ASCENDANT_HIGH * (players - cultists))
|
||||
else
|
||||
// Lowpop
|
||||
ascend_percent = CULT_ASCENDANT_LOW
|
||||
rise_number = round(CULT_RISEN_LOW * (players - cultists))
|
||||
ascend_number = round(CULT_ASCENDANT_LOW * (players - cultists))
|
||||
|
||||
/**
|
||||
* Returns the current number of cultists and constructs.
|
||||
*
|
||||
* Returns the number of cultists and constructs in a list ([1] = Cultists, [2] = Constructs), or as one combined number.
|
||||
*
|
||||
* * separate - Should the number be returned as a list with two separate values (Humans and Constructs) or as one number.
|
||||
*/
|
||||
/datum/game_mode/proc/get_cultists(separate = FALSE)
|
||||
var/cultists = 0
|
||||
var/constructs = 0
|
||||
for(var/I in cult)
|
||||
var/datum/mind/M = I
|
||||
if(ishuman(M.current) && !M.current.has_status_effect(STATUS_EFFECT_SUMMONEDGHOST))
|
||||
cultists++
|
||||
else if(isconstruct(M.current))
|
||||
constructs++
|
||||
if(separate)
|
||||
return list(cultists, constructs)
|
||||
else
|
||||
return cultists + constructs
|
||||
|
||||
/datum/game_mode/proc/check_cult_size()
|
||||
if(cult_ascendant)
|
||||
@@ -238,6 +274,8 @@ GLOBAL_LIST_EMPTY(all_cults)
|
||||
/datum/game_mode/proc/rise(cultist)
|
||||
if(ishuman(cultist) && iscultist(cultist))
|
||||
var/mob/living/carbon/human/H = cultist
|
||||
if(!H.original_eye_color)
|
||||
H.original_eye_color = H.get_eye_color()
|
||||
H.change_eye_color(BLOODCULT_EYE, FALSE)
|
||||
H.update_eyes()
|
||||
ADD_TRAIT(H, CULT_EYES, CULT_TRAIT)
|
||||
@@ -249,29 +287,6 @@ GLOBAL_LIST_EMPTY(all_cults)
|
||||
new /obj/effect/temp_visual/cult/sparks(get_turf(H), H.dir)
|
||||
H.update_halo_layer()
|
||||
|
||||
|
||||
/datum/game_mode/proc/remove_cultist(datum/mind/cult_mind, show_message = TRUE)
|
||||
if(cult_mind in cult)
|
||||
var/mob/cultist = cult_mind.current
|
||||
cult -= cult_mind
|
||||
cultist.faction -= "cult"
|
||||
cult_mind.special_role = null
|
||||
for(var/datum/action/innate/cult/C in cultist.actions)
|
||||
qdel(C)
|
||||
update_cult_icons_removed(cult_mind)
|
||||
|
||||
if(ishuman(cultist))
|
||||
var/mob/living/carbon/human/H = cultist
|
||||
REMOVE_TRAIT(H, CULT_EYES, null)
|
||||
H.change_eye_color(H.original_eye_color, FALSE)
|
||||
H.update_eyes()
|
||||
H.remove_overlay(HALO_LAYER)
|
||||
H.update_body()
|
||||
check_cult_size()
|
||||
if(show_message)
|
||||
cultist.visible_message("<span class='cult'>[cultist] looks like [cultist.p_they()] just reverted to [cultist.p_their()] old faith!</span>",
|
||||
"<span class='userdanger'>An unfamiliar white light flashes through your mind, cleansing the taint of [SSticker.cultdat ? SSticker.cultdat.entity_title1 : "Nar'Sie"] and the memories of your time as their servant with it.</span>")
|
||||
|
||||
/datum/game_mode/proc/update_cult_icons_added(datum/mind/cult_mind)
|
||||
var/datum/atom_hud/antag/culthud = GLOB.huds[ANTAG_HUD_CULT]
|
||||
if(cult_mind.current)
|
||||
|
||||
@@ -316,7 +316,8 @@
|
||||
var/mob/living/carbon/C = user
|
||||
if(C.pulling)
|
||||
var/atom/movable/pulled = C.pulling
|
||||
pulled.forceMove(T)
|
||||
var/turf/turf_behind = get_turf(get_step(T, turn(C.dir, 180)))
|
||||
pulled.forceMove(turf_behind)
|
||||
. = pulled
|
||||
|
||||
/obj/item/cult_shift/attack_self(mob/user)
|
||||
@@ -324,7 +325,7 @@
|
||||
to_chat(user, "<span class='warning'>[src] is dull and unmoving in your hands.</span>")
|
||||
return
|
||||
if(!iscultist(user))
|
||||
user.unEquip(src, 1)
|
||||
user.unEquip(src, TRUE)
|
||||
step(src, pick(GLOB.alldirs))
|
||||
to_chat(user, "<span class='warning'>[src] flickers out of your hands, too eager to move!</span>")
|
||||
return
|
||||
@@ -332,36 +333,31 @@
|
||||
var/outer_tele_radius = 9
|
||||
|
||||
var/mob/living/carbon/C = user
|
||||
var/turf/mobloc = get_turf(C)
|
||||
var/list/turfs = new/list()
|
||||
for(var/turf/T in range(user, outer_tele_radius))
|
||||
var/list/turfs = list()
|
||||
for(var/turf/T in orange(user, outer_tele_radius))
|
||||
if(!is_teleport_allowed(T.z))
|
||||
break
|
||||
if(get_dir(C, T) != C.dir)
|
||||
if(get_dir(C, T) != C.dir) // This seems like a very bad way to do this
|
||||
continue
|
||||
if(T == mobloc)
|
||||
continue
|
||||
if(istype(T, /turf/space))
|
||||
if(isspaceturf(T))
|
||||
continue
|
||||
if(T.x > world.maxx-outer_tele_radius || T.x < outer_tele_radius)
|
||||
continue //putting them at the edge is dumb
|
||||
if(T.y > world.maxy-outer_tele_radius || T.y < outer_tele_radius)
|
||||
continue
|
||||
|
||||
turfs += T
|
||||
|
||||
if(turfs)
|
||||
if(length(turfs))
|
||||
uses--
|
||||
var/turf/mobloc = get_turf(C)
|
||||
var/turf/destination = pick(turfs)
|
||||
if(uses <= 0)
|
||||
icon_state ="shifter_drained"
|
||||
playsound(mobloc, "sparks", 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
icon_state = "shifter_drained"
|
||||
playsound(src, "sparks", 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
new /obj/effect/temp_visual/dir_setting/cult/phase/out(mobloc, C.dir)
|
||||
|
||||
var/atom/movable/pulled = handle_teleport_grab(destination, C)
|
||||
handle_teleport_grab(destination, C)
|
||||
C.forceMove(destination)
|
||||
if(pulled)
|
||||
C.start_pulling(pulled) //forcemove resets pulls, so we need to re-pull
|
||||
|
||||
new /obj/effect/temp_visual/dir_setting/cult/phase(destination, C.dir)
|
||||
playsound(destination, 'sound/effects/phasein.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
|
||||
@@ -133,13 +133,13 @@
|
||||
for(var/mob/living/carbon/human/H in GLOB.player_list)
|
||||
if(is_admin_level(H.z)) //We can't sacrifice people that are on the centcom z-level
|
||||
continue
|
||||
if(H.mind && !is_convertable_to_cult(H.mind) && (H.stat != DEAD) && (H.mind.offstation_role != TRUE))
|
||||
if(H.mind && !iscultist(H) && !is_convertable_to_cult(H.mind) && (H.stat != DEAD) && !H.mind.offstation_role)
|
||||
target_candidates += H.mind
|
||||
if(!length(target_candidates)) //There are no living unconvertables on the station. Looking for a Sacrifice Target among the ordinary crewmembers
|
||||
for(var/mob/living/carbon/human/H in GLOB.player_list)
|
||||
if(is_admin_level(H.z)) //We can't sacrifice people that are on the centcom z-level
|
||||
continue
|
||||
if(H.mind && !iscultist(H) && (H.stat != DEAD) && (H.mind.offstation_role != TRUE))
|
||||
if(H.mind && !iscultist(H) && (H.stat != DEAD) && !H.mind.offstation_role) // Same checks, but add them even if they could be converted
|
||||
target_candidates += H.mind
|
||||
if(length(target_candidates))
|
||||
target = pick(target_candidates)
|
||||
|
||||
@@ -84,6 +84,10 @@
|
||||
/obj/item/melee/cultblade/dagger/proc/can_scribe(mob/living/user)
|
||||
if(!src || !user || loc != user || user.incapacitated())
|
||||
return FALSE
|
||||
if(drawing_rune)
|
||||
to_chat(user, "<span class='warning'>You're already drawing a rune!</span>")
|
||||
return FALSE
|
||||
|
||||
var/turf/T = get_turf(user)
|
||||
if(isspaceturf(T))
|
||||
return FALSE
|
||||
@@ -135,12 +139,12 @@
|
||||
to_chat(user, "<span class='cultitalic'>The veil is not weak enough here to summon a cultist, you must be on station!</span>")
|
||||
return
|
||||
|
||||
var/old_color = user.color // we'll temporarily redden the user for better feedback to fellow cultists. Store this to revert them back.
|
||||
var/old_color = user.color // we'll temporarily redden the user for better feedback to fellow cultists. Store this to revert them back.
|
||||
if(narsie_rune)
|
||||
if(!narsie_rune_check(user, A))
|
||||
return // don't do shit
|
||||
var/list/summon_areas = gamemode.cult_objs.obj_summon.summon_spots
|
||||
if(!(A in summon_areas)) // Check again to make sure they didn't move
|
||||
if(!(A in summon_areas)) // Check again to make sure they didn't move
|
||||
to_chat(user, "<span class='cultlarge'>The ritual can only begin where the veil is weak - in [english_list(summon_areas)]!</span>")
|
||||
return
|
||||
GLOB.command_announcement.Announce("Figments from an eldritch god are being summoned into the [A.map_name] from an unknown dimension. Disrupt the ritual at all costs, before the station is destroyed! Space law and SOP are suspended. The entire crew must kill cultists on sight.", "Central Command Higher Dimensional Affairs", 'sound/AI/spanomalies.ogg')
|
||||
@@ -148,7 +152,7 @@
|
||||
var/turf/T = I
|
||||
var/obj/machinery/shield/cult/narsie/N = new(T)
|
||||
shields |= N
|
||||
user.color = "red"
|
||||
user.color = COLOR_RED
|
||||
|
||||
// Draw the rune
|
||||
var/mob/living/carbon/human/H = user
|
||||
@@ -161,12 +165,14 @@
|
||||
user.visible_message(others_message,
|
||||
"<span class='cultitalic'>You slice open your body and begin drawing a sigil of [SSticker.cultdat.entity_title3].</span>")
|
||||
|
||||
drawing_rune = TRUE // Only one at a time
|
||||
var/scribe_successful = do_after(user, initial(rune.scribe_delay) * scribe_multiplier, target = runeturf)
|
||||
for(var/V in shields) // Only used for the 'Tear Veil' rune
|
||||
var/obj/machinery/shield/S = V
|
||||
if(S && !QDELETED(S))
|
||||
qdel(S)
|
||||
user.color = old_color
|
||||
drawing_rune = FALSE
|
||||
if(!scribe_successful)
|
||||
return
|
||||
|
||||
|
||||
@@ -263,6 +263,8 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/mob/living/M in T)
|
||||
if(!iscultist(M) || (M.mind && is_sacrifice_target(M.mind)))
|
||||
if(isconstruct(M)) // No offering constructs please
|
||||
continue
|
||||
offer_targets += M
|
||||
|
||||
// Offering a head/brain
|
||||
@@ -364,6 +366,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
return
|
||||
|
||||
var/sacrifice_fulfilled
|
||||
var/worthless = FALSE
|
||||
var/datum/game_mode/gamemode = SSticker.mode
|
||||
if(offering.mind)
|
||||
GLOB.sacrificed += offering.mind
|
||||
@@ -377,13 +380,16 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
if(sacrifice_fulfilled)
|
||||
to_chat(M, "<span class='cultlarge'>\"Yes! This is the one I desire! You have done well.\"</span>")
|
||||
else
|
||||
if(ishuman(offering) || isrobot(offering))
|
||||
if(ishuman(offering) && offering.mind.offstation_role && offering.mind.special_role != SPECIAL_ROLE_ERT) //If you try it on a ghost role, you get nothing
|
||||
to_chat(M, "<span class='cultlarge'>\"This soul is of no use to either of us.\"</span>")
|
||||
worthless = TRUE
|
||||
else if(ishuman(offering) || isrobot(offering))
|
||||
to_chat(M, "<span class='cultlarge'>\"I accept this sacrifice.\"</span>")
|
||||
else
|
||||
to_chat(M, "<span class='cultlarge'>\"I accept this meager sacrifice.\"</span>")
|
||||
playsound(offering, 'sound/misc/demon_consume.ogg', 100, TRUE)
|
||||
|
||||
if((ishuman(offering) || isrobot(offering) || isbrain(offering)) && offering.mind)
|
||||
if(((ishuman(offering) || isrobot(offering) || isbrain(offering)) && offering.mind) && !worthless)
|
||||
var/obj/item/soulstone/stone = new /obj/item/soulstone(get_turf(src))
|
||||
stone.invisibility = INVISIBILITY_MAXIMUM // So it's not picked up during transfer_soul()
|
||||
stone.transfer_soul("FORCE", offering, user) // If it cannot be added
|
||||
@@ -418,6 +424,8 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
|
||||
/obj/effect/rune/teleport/Destroy()
|
||||
GLOB.teleport_runes -= src
|
||||
QDEL_NULL(inner_portal)
|
||||
QDEL_NULL(outer_portal)
|
||||
return ..()
|
||||
|
||||
/obj/effect/rune/teleport/invoke(list/invokers)
|
||||
@@ -452,7 +460,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
|
||||
var/input_rune_key = input(user, "Choose a rune to teleport to.", "Rune to Teleport to") as null|anything in potential_runes //we know what key they picked
|
||||
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
|
||||
if(!src || !Adjacent(user) || QDELETED(src) || user.incapacitated() || !actual_selected_rune)
|
||||
if(QDELETED(src) || QDELETED(actual_selected_rune) ||!Adjacent(user) || user.incapacitated())
|
||||
fail_invoke()
|
||||
return
|
||||
|
||||
@@ -587,7 +595,8 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
return
|
||||
sacrifices_used += SOULS_TO_REVIVE
|
||||
mob_to_revive.revive()
|
||||
mob_to_revive.grab_ghost()
|
||||
if(mob_to_revive.ghost_can_reenter())
|
||||
mob_to_revive.grab_ghost()
|
||||
|
||||
if(!mob_to_revive.client || mob_to_revive.client.is_afk())
|
||||
set waitfor = FALSE
|
||||
@@ -685,7 +694,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
cultists[M.current.real_name] = M.current
|
||||
var/input = input(user, "Who do you wish to call to [src]?", "Acolytes") as null|anything in cultists
|
||||
var/mob/living/cultist_to_summon = cultists[input]
|
||||
if(!src || QDELETED(src) || !Adjacent(user) || user.incapacitated())
|
||||
if(QDELETED(src) || !Adjacent(user) || user.incapacitated())
|
||||
return
|
||||
if(!cultist_to_summon)
|
||||
log_game("Summon Cultist rune failed - no target")
|
||||
@@ -882,6 +891,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
var/mob/living/carbon/human/new_human = new(T)
|
||||
new_human.real_name = ghost_to_spawn.real_name
|
||||
new_human.key = ghost_to_spawn.key
|
||||
new_human.gender = ghost_to_spawn.gender
|
||||
new_human.alpha = 150 //Makes them translucent
|
||||
new_human.equipOutfit(/datum/outfit/ghost_cultist) //give them armor
|
||||
new_human.apply_status_effect(STATUS_EFFECT_SUMMONEDGHOST) //ghosts can't summon more ghosts, also lets you see actual ghosts
|
||||
@@ -999,7 +1009,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
//BEGIN THE SUMMONING
|
||||
gamemode.cult_objs.succesful_summon()
|
||||
used = TRUE
|
||||
color = rgb(255, 0, 0)
|
||||
color = COLOR_RED
|
||||
..()
|
||||
SEND_SOUND(world, sound('sound/effects/dimensional_rend.ogg'))
|
||||
to_chat(world, "<span class='cultitalic'><b>The veil... <span class='big'>is...</span> <span class='reallybig'>TORN!!!--</span></b></span>")
|
||||
|
||||
@@ -181,6 +181,7 @@ GLOBAL_LIST_EMPTY(cortical_stacks) //Stacks for 'leave nobody behind' objective.
|
||||
to_chat(raider.current, "<span class='notice'>Vox are cowardly and will flee from larger groups, but corner one or find them en masse and they are vicious.</span>")
|
||||
to_chat(raider.current, "<span class='notice'>Use :V to voxtalk, :H to talk on your encrypted channel, and don't forget to turn on your nitrogen internals!</span>")
|
||||
to_chat(raider.current, "<span class='notice'>Choose to accomplish your objectives by either raiding the crew and taking what you need, or by attempting to trade with them.</span>")
|
||||
to_chat(raider.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Vox_Raider)</span>")
|
||||
spawn(25)
|
||||
show_objectives(raider)
|
||||
|
||||
|
||||
@@ -158,6 +158,7 @@
|
||||
to_chat(abductor.current, "<span class='notice'>You are an agent of [team_name]!</span>")
|
||||
to_chat(abductor.current, "<span class='notice'>With the help of your teammate, kidnap and experiment on station crew members!</span>")
|
||||
to_chat(abductor.current, "<span class='notice'>Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve.</span>")
|
||||
to_chat(abductor.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Abductor)</span>")
|
||||
|
||||
abductor.announce_objectives()
|
||||
|
||||
@@ -170,6 +171,7 @@
|
||||
to_chat(abductor.current, "<span class='notice'>You are a scientist of [team_name]!</span>")
|
||||
to_chat(abductor.current, "<span class='notice'>With the help of your teammate, kidnap and experiment on station crew members!</span>")
|
||||
to_chat(abductor.current, "<span class='notice'>Use your tool and ship consoles to support the agent and retrieve human specimens.</span>")
|
||||
to_chat(abductor.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Abductor)</span>")
|
||||
|
||||
abductor.announce_objectives()
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
if(target.has_buckled_mobs()) //mob attached to us
|
||||
to_chat(user, "<span class='warning'>[target] will not fit into [src] because [target.p_they()] [target.p_have()] a slime latched onto [target.p_their()] head.</span>")
|
||||
return
|
||||
visible_message("[user] puts [target] into the [src].")
|
||||
visible_message("<span class='notice'>[user] puts [target] into [src].</span>")
|
||||
|
||||
target.forceMove(src)
|
||||
occupant = target
|
||||
@@ -187,12 +187,12 @@
|
||||
if(isabductor(grabbed.affecting))
|
||||
return
|
||||
if(occupant)
|
||||
to_chat(user, "<span class='notice'>The [src] is already occupied!</span>")
|
||||
to_chat(user, "<span class='notice'>[src] is already occupied!</span>")
|
||||
return
|
||||
if(grabbed.affecting.has_buckled_mobs()) //mob attached to us
|
||||
to_chat(user, "<span class='warning'>[grabbed.affecting] will not fit into [src] because [grabbed.affecting.p_they()] [grabbed.affecting.p_have()] a slime latched onto [grabbed.affecting.p_their()] head.</span>")
|
||||
return
|
||||
visible_message("[user] puts [grabbed.affecting] into the [src].")
|
||||
visible_message("<span class='notice'>[user] puts [grabbed.affecting] into [src].</span>")
|
||||
var/mob/living/carbon/human/H = grabbed.affecting
|
||||
H.forceMove(src)
|
||||
occupant = H
|
||||
|
||||
@@ -837,6 +837,7 @@
|
||||
to_chat(src, "You are a brain slug that worms its way into the head of its victim. Use stealth, persuasion and your powers of mind control to keep you, your host and your eventual spawn safe and warm.")
|
||||
to_chat(src, "Sugar nullifies your abilities, avoid it at all costs!")
|
||||
to_chat(src, "You can speak to your fellow borers by prefixing your messages with ':bo'. Check out your Borer tab to see your abilities.")
|
||||
to_chat(src, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Cortical_Borer)</span>")
|
||||
|
||||
/proc/create_borer_mind(key)
|
||||
var/datum/mind/M = new /datum/mind(key)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
roundstart = FALSE
|
||||
important_info = "Follow your objectives, do not make the station inhospitable or try and kill crew."
|
||||
flavour_text = "You are a swarmer, a weapon of a long dead civilization. Until further orders from your original masters are received, you must continue to consume and replicate."
|
||||
description = {" Your goal is to create more of yourself by consuming the station. Clicking on any object will try to consume it, either deconstructing it into its components, destroying it, or integrating any materials it has into you if successful. Ctrl-Clicking on a mob will attempt to remove it from the area and place it in a safe environment for storage.
|
||||
description = {"Your goal is to create more of yourself by consuming the station. Clicking on any object will try to consume it, either deconstructing it into its components, destroying it, or integrating any materials it has into you if successful. Ctrl-Clicking on a mob will attempt to remove it from the area and place it in a safe environment for storage.
|
||||
Objectives:
|
||||
1. Consume resources and replicate until there are no more resources left.
|
||||
2. Ensure that this location is fit for invasion at a later date; do not perform actions that would render it dangerous or inhospitable.
|
||||
@@ -112,6 +112,7 @@
|
||||
to_chat(src, "1. Consume resources and replicate until there are no more resources left.")
|
||||
to_chat(src, "2. Ensure that the station is fit for invasion at a later date, do not perform actions that would render it dangerous or inhospitable.")
|
||||
to_chat(src, "3. Biological and sentient resources will be harvested at a later date, do not harm them.")
|
||||
to_chat(src, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Swarmer)</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/swarmer/New()
|
||||
..()
|
||||
|
||||
@@ -343,6 +343,7 @@
|
||||
to_chat(G, "You are capable of manifesting or recalling to your master with verbs in the Guardian tab. You will also find a verb to communicate with them privately there.")
|
||||
to_chat(G, "While personally invincible, you will die if [user.real_name] does, and any damage dealt to you will have a portion passed on to them as you feed upon them to sustain yourself.")
|
||||
to_chat(G, "[G.playstyle_string]")
|
||||
to_chat(G, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Guardian)</span>")
|
||||
G.faction = user.faction
|
||||
|
||||
var/color = pick(color_list)
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
/obj/item/guardian_bomb/proc/detonate(mob/living/user)
|
||||
if(!istype(user))
|
||||
return
|
||||
to_chat(user, "<span class='danger'>The [src] was boobytrapped!</span>")
|
||||
to_chat(user, "<span class='danger'>[src] was boobytrapped!</span>")
|
||||
if(istype(spawner, /mob/living/simple_animal/hostile/guardian))
|
||||
var/mob/living/simple_animal/hostile/guardian/G = spawner
|
||||
if(user == G.summoner)
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
F.icon = 'icons/turf/floors.dmi'
|
||||
F.name = "bluespace recieving pad"
|
||||
F.desc = "A recieving zone for bluespace teleportations. Building a wall over it should disable it."
|
||||
F.icon_state = "light_on-w"
|
||||
F.icon_state = "light_on"
|
||||
to_chat(src, "<span class='danger'>Beacon placed! You may now warp targets to it, including your user, via Alt+Click. </span>")
|
||||
if(beacon)
|
||||
beacon.ChangeTurf(/turf/simulated/floor/plating)
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
player_mind.special_role = SPECIAL_ROLE_MORPH
|
||||
SSticker.mode.traitors |= player_mind
|
||||
to_chat(S, S.playstyle_string)
|
||||
to_chat(S, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Morph)</span>")
|
||||
SEND_SOUND(S, sound('sound/magic/mutate.ogg'))
|
||||
message_admins("[key_of_morph] has been made into morph by an event.")
|
||||
log_game("[key_of_morph] was spawned as a morph by an event.")
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
to_chat(src, "<b>You are invincible and invisible to everyone but other ghosts. Most abilities will reveal you, rendering you vulnerable.</b>")
|
||||
to_chat(src, "<b>To function, you are to drain the life essence from humans. This essence is a resource, as well as your health, and will power all of your abilities.</b>")
|
||||
to_chat(src, "<b><i>You do not remember anything of your past lives, nor will you remember anything about this one after your death.</i></b>")
|
||||
to_chat(src, "<b>Be sure to read the wiki page at http://www.paradisestation.org/wiki/index.php/Revenant to learn more.</b>")
|
||||
to_chat(src, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Revenant)</span>")
|
||||
var/datum/objective/revenant/objective = new
|
||||
objective.owner = mind
|
||||
mind.objectives += objective
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
mind.objectives += fluffObjective
|
||||
to_chat(src, "<B>Objective #[1]</B>: [objective.explanation_text]")
|
||||
to_chat(src, "<B>Objective #[2]</B>: [fluffObjective.explanation_text]")
|
||||
to_chat(src, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Slaughter_Demon)</span>")
|
||||
|
||||
|
||||
/obj/effect/decal/cleanable/blood/innards
|
||||
|
||||
@@ -108,18 +108,23 @@
|
||||
var/agent_number = 1
|
||||
var/spawnpos = 1
|
||||
|
||||
var/obj/machinery/nuclearbomb/syndicate/the_bomb
|
||||
if(nuke_spawn && length(synd_spawn))
|
||||
the_bomb = new /obj/machinery/nuclearbomb/syndicate(nuke_spawn.loc)
|
||||
the_bomb.r_code = nuke_code
|
||||
|
||||
for(var/datum/mind/synd_mind in syndicates)
|
||||
if(spawnpos > synd_spawn.len)
|
||||
spawnpos = 2
|
||||
synd_mind.current.loc = synd_spawn[spawnpos]
|
||||
synd_mind.offstation_role = TRUE
|
||||
forge_syndicate_objectives(synd_mind)
|
||||
create_syndicate(synd_mind)
|
||||
create_syndicate(synd_mind, the_bomb)
|
||||
greet_syndicate(synd_mind)
|
||||
equip_syndicate(synd_mind.current)
|
||||
|
||||
if(!leader_selected)
|
||||
prepare_syndicate_leader(synd_mind, nuke_code)
|
||||
prepare_syndicate_leader(synd_mind, the_bomb)
|
||||
leader_selected = 1
|
||||
else
|
||||
synd_mind.current.real_name = "[syndicate_name()] Operative #[agent_number]"
|
||||
@@ -131,9 +136,6 @@
|
||||
|
||||
scale_telecrystals()
|
||||
share_telecrystals()
|
||||
if(nuke_spawn && synd_spawn.len > 0)
|
||||
var/obj/machinery/nuclearbomb/syndicate/the_bomb = new /obj/machinery/nuclearbomb/syndicate(nuke_spawn.loc)
|
||||
the_bomb.r_code = nuke_code
|
||||
|
||||
return ..()
|
||||
|
||||
@@ -160,7 +162,7 @@
|
||||
U.hidden_uplink.uses++
|
||||
remainder--
|
||||
|
||||
/datum/game_mode/proc/create_syndicate(datum/mind/synd_mind) // So we don't have inferior species as ops - randomize a human
|
||||
/datum/game_mode/proc/create_syndicate(datum/mind/synd_mind, obj/machinery/nuclearbomb/syndicate/the_bomb) // So we don't have inferior species as ops - randomize a human
|
||||
var/mob/living/carbon/human/M = synd_mind.current
|
||||
|
||||
M.set_species(/datum/species/human, TRUE)
|
||||
@@ -186,7 +188,11 @@
|
||||
M.regenerate_icons()
|
||||
M.update_body()
|
||||
|
||||
/datum/game_mode/proc/prepare_syndicate_leader(datum/mind/synd_mind, nuke_code)
|
||||
if(the_bomb)
|
||||
synd_mind.store_memory("<B>Syndicate [the_bomb.name] Code</B>: [the_bomb.r_code]")
|
||||
to_chat(synd_mind.current, "The code for \the [the_bomb.name] is: <B>[the_bomb.r_code]</B>")
|
||||
|
||||
/datum/game_mode/proc/prepare_syndicate_leader(datum/mind/synd_mind, obj/machinery/nuclearbomb/syndicate/the_bomb)
|
||||
var/leader_title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")
|
||||
synd_mind.current.real_name = "[syndicate_name()] Team [leader_title]"
|
||||
to_chat(synd_mind.current, "<B>You are the Syndicate leader 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.</B>")
|
||||
@@ -198,11 +204,9 @@
|
||||
|
||||
update_syndicate_id(synd_mind, leader_title, TRUE)
|
||||
|
||||
if(nuke_code)
|
||||
synd_mind.store_memory("<B>Syndicate Nuclear Bomb Code</B>: [nuke_code]", 0, 0)
|
||||
to_chat(synd_mind.current, "The nuclear authorization code is: <B>[nuke_code]</B>")
|
||||
if(the_bomb)
|
||||
var/obj/item/paper/P = new
|
||||
P.info = "The nuclear authorization code is: <b>[nuke_code]</b>"
|
||||
P.info = "The code for \the [the_bomb.name] is: <B>[the_bomb.r_code]</B>"
|
||||
P.name = "nuclear bomb code"
|
||||
var/obj/item/stamp/syndicate/stamp = new
|
||||
P.stamp(stamp)
|
||||
@@ -216,8 +220,6 @@
|
||||
H.equip_to_slot_or_del(P, slot_r_store, 0)
|
||||
H.update_icons()
|
||||
|
||||
else
|
||||
nuke_code = "code will be provided later"
|
||||
|
||||
/datum/game_mode/proc/update_syndicate_id(datum/mind/synd_mind, is_leader = FALSE)
|
||||
var/list/found_ids = synd_mind.current.search_contents_for(/obj/item/card/id)
|
||||
@@ -245,6 +247,7 @@
|
||||
for(var/datum/objective/objective in syndicate.objectives)
|
||||
to_chat(syndicate.current, "<B>Objective #[obj_count]</B>: [objective.explanation_text]")
|
||||
obj_count++
|
||||
to_chat(syndicate.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Nuclear_Agent)</span>")
|
||||
return
|
||||
|
||||
|
||||
@@ -452,10 +455,9 @@
|
||||
|
||||
for(var/obj/machinery/nuclearbomb/nuke in GLOB.machines)
|
||||
if(nuke.r_code == "Nope") continue
|
||||
var/turf/T = get_turf(nuke)
|
||||
var/area/A = T.loc
|
||||
var/area/A = get_area(nuke)
|
||||
|
||||
var/list/thousand_penalty = list(/area/wizard_station, /area/solar, /area)
|
||||
var/list/thousand_penalty = list(/area/solar)
|
||||
var/list/fiftythousand_penalty = list(/area/security/main, /area/security/brig, /area/security/armoury, /area/security/checkpoint2)
|
||||
|
||||
if(is_type_in_list(A, thousand_penalty))
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
|
||||
for(var/obj/machinery/computer/shuttle/syndicate/S in GLOB.machines)
|
||||
S.challenge = TRUE
|
||||
S.challenge_time = world.time
|
||||
|
||||
// No. of player - Min. Player to dec, divided by player per bonus, then multipled by TC per bonus. Rounded.
|
||||
total_tc = CHALLENGE_TELECRYSTALS + round((((GLOB.player_list.len - CHALLENGE_MIN_PLAYERS)/CHALLENGE_SCALE_PLAYER) * CHALLENGE_SCALE_BONUS))
|
||||
|
||||
@@ -359,8 +359,9 @@ GLOBAL_VAR(bomb_set)
|
||||
|
||||
var/off_station = 0
|
||||
var/turf/bomb_location = get_turf(src)
|
||||
var/area/A = get_area(src)
|
||||
if( bomb_location && is_station_level(bomb_location.z) )
|
||||
if( (bomb_location.x < (128-NUKERANGE)) || (bomb_location.x > (128+NUKERANGE)) || (bomb_location.y < (128-NUKERANGE)) || (bomb_location.y > (128+NUKERANGE)) )
|
||||
if( (bomb_location.x < (128 - NUKERANGE)) || (bomb_location.x > (128 + NUKERANGE)) || (bomb_location.y < (128 - NUKERANGE)) || (bomb_location.y > (128 + NUKERANGE)) && (!(A in GLOB.the_station_areas)))
|
||||
off_station = 1
|
||||
else
|
||||
off_station = 2
|
||||
@@ -381,9 +382,9 @@ GLOBAL_VAR(bomb_set)
|
||||
else if(off_station == 2)
|
||||
to_chat(world, "<b>A nuclear device was set off, but the device was not on the station!</b>")
|
||||
else
|
||||
to_chat(world, "<b>The station was destoyed by the nuclear blast!</b>")
|
||||
to_chat(world, "<b>The station was destroyed by the nuclear blast!</b>")
|
||||
|
||||
SSticker.mode.station_was_nuked = (off_station<2) //offstation==1 is a draw. the station becomes irradiated and needs to be evacuated.
|
||||
SSticker.mode.station_was_nuked = (off_station < 2) //offstation==1 is a draw. the station becomes irradiated and needs to be evacuated.
|
||||
//kinda shit but I couldn't get permission to do what I wanted to do.
|
||||
|
||||
if(!SSticker.mode.check_finished())//If the mode does not deal with the nuke going off so just reboot because everyone is stuck as is
|
||||
@@ -399,12 +400,12 @@ GLOBAL_VAR(bomb_set)
|
||||
if(safety == 1)
|
||||
if(!is_syndicate)
|
||||
set_security_level(previous_level)
|
||||
visible_message("<span class='notice'>The [src] quiets down.</span>")
|
||||
visible_message("<span class='notice'>[src] quiets down.</span>")
|
||||
if(!lighthack)
|
||||
if(icon_state == "nuclearbomb2")
|
||||
icon_state = "nuclearbomb1"
|
||||
else
|
||||
visible_message("<span class='notice'>The [src] emits a quiet whirling noise!</span>")
|
||||
visible_message("<span class='notice'>[src] emits a quiet whirling noise!</span>")
|
||||
|
||||
//==========DAT FUKKEN DISK===============
|
||||
/obj/item/disk/nuclear
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
to_chat(rev_mind.current, "<B>Objective #[obj_count]</B>: [objective.explanation_text]")
|
||||
rev_mind.special_role = SPECIAL_ROLE_HEAD_REV
|
||||
obj_count++
|
||||
to_chat(rev_mind.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Revolution)</span>")
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//This are equips the rev heads with their gear, and makes the clown not clumsy//
|
||||
|
||||
@@ -114,18 +114,21 @@
|
||||
if(G.block)
|
||||
if(G.block in blocks_assigned)
|
||||
warning("DNA2: Gene [G.name] trying to use already-assigned block [G.block] (used by [english_list(blocks_assigned[G.block])])")
|
||||
GLOB.dna_mutations.Add(G)
|
||||
GLOB.dna_mutations[mutation_type] = G
|
||||
var/list/assignedToBlock[0]
|
||||
if(blocks_assigned[G.block])
|
||||
assignedToBlock=blocks_assigned[G.block]
|
||||
assignedToBlock = blocks_assigned[G.block]
|
||||
assignedToBlock.Add(G.name)
|
||||
blocks_assigned[G.block]=assignedToBlock
|
||||
blocks_assigned[G.block] = assignedToBlock
|
||||
//testing("DNA2: Gene [G.name] assigned to block [G.block].")
|
||||
else
|
||||
qdel(G)
|
||||
|
||||
// I WILL HAVE A LIST OF MUTATIONS THAT MATCHES THE RANDOMIZED BLOCKS GODDAMNIT!
|
||||
for(var/block in 1 to DNA_SE_LENGTH)
|
||||
var/name = GLOB.assigned_blocks[block]
|
||||
for(var/datum/mutation/mutation in GLOB.dna_mutations)
|
||||
for(var/mutation_type in GLOB.dna_mutations)
|
||||
var/datum/mutation/mutation = GLOB.dna_mutations[mutation_type]
|
||||
if(mutation.name == name || mutation.block == block)
|
||||
if(mutation.block in GLOB.assigned_mutation_blocks)
|
||||
warning("DNA2: Mutation [mutation.name] trying to add to already assigned gene block list (used by [english_list(GLOB.assigned_mutation_blocks[block])])")
|
||||
|
||||
@@ -126,8 +126,7 @@ Made by Xhuis
|
||||
to_chat(shadow.current, "<b>Currently, you are disguised as an employee aboard [world.name].</b>")
|
||||
to_chat(shadow.current, "<b>In your limited state, you have two abilities: Hatch and Shadowling Hivemind (:8).</b>")
|
||||
to_chat(shadow.current, "<b>Any other shadowlings are your allies. You must assist them as they shall assist you.</b>")
|
||||
to_chat(shadow.current, "<b>If you are new to shadowling, or want to read about abilities, check the wiki page at https://www.paradisestation.org/wiki/index.php/Shadowling</b><br>")
|
||||
|
||||
to_chat(shadow.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Shadowling)</span>")
|
||||
|
||||
|
||||
/datum/game_mode/proc/process_shadow_objectives(datum/mind/shadow_mind)
|
||||
@@ -169,6 +168,7 @@ Made by Xhuis
|
||||
to_chat(new_thrall_mind.current, "<span class='shadowling'>Your body has been irreversibly altered. The attentive can see this - you may conceal it by wearing a mask.</span>")
|
||||
to_chat(new_thrall_mind.current, "<span class='shadowling'>Though not nearly as powerful as your masters, you possess some weak powers. These can be found in the Thrall Abilities tab.</span>")
|
||||
to_chat(new_thrall_mind.current, "<span class='shadowling'>You may communicate with your allies by speaking in the Shadowling Hivemind (:8).</span>")
|
||||
to_chat(new_thrall_mind.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Shadowling)</span>")
|
||||
if(jobban_isbanned(new_thrall_mind.current, ROLE_SHADOWLING) || jobban_isbanned(new_thrall_mind.current, ROLE_SYNDICATE))
|
||||
replace_jobbanned_player(new_thrall_mind.current, ROLE_SHADOWLING)
|
||||
if(!victory_warning_announced && (length(shadowling_thralls) >= warning_threshold))//are the slings very close to winning?
|
||||
|
||||
@@ -513,7 +513,7 @@
|
||||
target_apc.operating = 0
|
||||
target_apc.update()
|
||||
target_apc.update_icon()
|
||||
target_apc.visible_message("<span class='warning'>The [target_apc] flickers and begins to grow dark.</span>")
|
||||
target_apc.visible_message("<span class='warning'>[target_apc] flickers and begins to grow dark.</span>")
|
||||
|
||||
to_chat(user, "<span class='shadowling'>You dim the APC's screen and carefully begin siphoning its power into the void.</span>")
|
||||
if(!do_after(user, 200, target=target_apc))
|
||||
@@ -522,7 +522,7 @@
|
||||
target_apc.operating = 1
|
||||
target_apc.update()
|
||||
target_apc.update_icon()
|
||||
target_apc.visible_message("<span class='warning'>The [target_apc] begins glowing brightly!</span>")
|
||||
target_apc.visible_message("<span class='warning'>[target_apc] begins glowing brightly!</span>")
|
||||
else
|
||||
//We did it!
|
||||
to_chat(user, "<span class='shadowling'>You sent the APC's power to the void while overloading all it's lights!</span>")
|
||||
|
||||
@@ -193,8 +193,8 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
|
||||
for(var/datum/objective/objective in vampire.objectives)
|
||||
to_chat(vampire.current, "<B>Objective #[obj_count]</B>: [objective.explanation_text]")
|
||||
obj_count++
|
||||
to_chat(vampire.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Vampire)</span>")
|
||||
return
|
||||
|
||||
/datum/vampire
|
||||
var/bloodtotal = 0 // CHANGE TO ZERO WHEN PLAYTESTING HAPPENS
|
||||
var/bloodusable = 0 // CHANGE TO ZERO WHEN PLAYTESTING HAPPENS
|
||||
@@ -290,7 +290,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
|
||||
draining = null
|
||||
return
|
||||
add_attack_logs(owner, H, "vampirebit & is draining their blood.", ATKLOG_ALMOSTALL)
|
||||
owner.visible_message("<span class='danger'>[owner] grabs [H]'s neck harshly and sinks in [owner.p_their()] fangs!</span>", "<span class='danger'>You sink your fangs into [H] and begin to drain [owner.p_their()] blood.</span>", "<span class='notice'>You hear a soft puncture and a wet sucking noise.</span>")
|
||||
owner.visible_message("<span class='danger'>[owner] grabs [H]'s neck harshly and sinks in [owner.p_their()] fangs!</span>", "<span class='danger'>You sink your fangs into [H] and begin to drain [H.p_their()] blood.</span>", "<span class='notice'>You hear a soft puncture and a wet sucking noise.</span>")
|
||||
if(!iscarbon(owner))
|
||||
H.LAssailant = null
|
||||
else
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
new /obj/effect/particle_effect/smoke(H.loc)
|
||||
var/mob/living/carbon/human/M = new/mob/living/carbon/human(H.loc)
|
||||
M.key = C.key
|
||||
to_chat(M, "<B>You are the [H.real_name]'s apprentice! You are bound by magic contract to follow [H.p_their()] orders and help [H.p_them()] in accomplishing their goals.")
|
||||
to_chat(M, "<B>You are [H.real_name]'s apprentice! You are bound by magic contract to follow [H.p_their()] orders and help [H.p_them()] in accomplishing their goals.")
|
||||
switch(href_list["school"])
|
||||
if("destruction")
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(null))
|
||||
@@ -293,7 +293,7 @@ GLOBAL_LIST_EMPTY(multiverse)
|
||||
|
||||
/obj/item/multisword/attack(mob/living/M as mob, mob/living/user as mob) //to prevent accidental friendly fire or out and out grief.
|
||||
if(M.real_name == user.real_name)
|
||||
to_chat(user, "<span class='warning'>The [src] detects benevolent energies in your target and redirects your attack!</span>")
|
||||
to_chat(user, "<span class='warning'>[src] detects benevolent energies in your target and redirects your attack!</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
@@ -856,7 +856,7 @@ GLOBAL_LIST_EMPTY(multiverse)
|
||||
if(link)
|
||||
target = null
|
||||
link.loc = get_turf(src)
|
||||
to_chat(user, "<span class='notice'>You remove the [link] from the doll.</span>")
|
||||
to_chat(user, "<span class='notice'>You remove [link] from the doll.</span>")
|
||||
link = null
|
||||
update_targets()
|
||||
return
|
||||
|
||||
@@ -95,6 +95,10 @@
|
||||
to_chat(user, "<span class='cultlarge'>\"Come now, do not capture your fellow's soul.\"</span>")
|
||||
return ..()
|
||||
|
||||
if(M.mind.offstation_role && M.mind.special_role != SPECIAL_ROLE_ERT)
|
||||
to_chat(user, "<span class='warning'>This being's soul seems worthless. Not even the stone will absorb it.</span>")
|
||||
return ..()
|
||||
|
||||
if(optional)
|
||||
if(!M.ckey)
|
||||
to_chat(user, "<span class='warning'>They have no soul!</span>")
|
||||
@@ -253,17 +257,17 @@
|
||||
return ..()
|
||||
|
||||
////////////////////////////Proc for moving soul in and out off stone//////////////////////////////////////
|
||||
|
||||
// this whole proc is pain
|
||||
/obj/item/soulstone/proc/transfer_soul(choice, target, mob/user)
|
||||
switch(choice)
|
||||
if("FORCE")
|
||||
var/mob/living/T = target
|
||||
if(T.client != null)
|
||||
if(T.client && T.ghost_can_reenter()) // Haven't DC'd or ahudded
|
||||
init_shade(T, user)
|
||||
else
|
||||
else // Poll ghosts
|
||||
to_chat(user, "<span class='userdanger'>Capture failed!</span> The soul has already fled its mortal frame. You attempt to bring it back...")
|
||||
T.Paralyse(20)
|
||||
if(!get_cult_ghost(T, user))
|
||||
if(!get_cult_ghost(T, user, TRUE))
|
||||
T.dust() //If we can't get a ghost, kill the sacrifice anyway.
|
||||
|
||||
if("VICTIM")
|
||||
@@ -276,7 +280,7 @@
|
||||
else
|
||||
if(T.client == null)
|
||||
to_chat(user, "<span class='userdanger'>Capture failed!</span> The soul has already fled its mortal frame. You attempt to bring it back...")
|
||||
get_cult_ghost(T, user)
|
||||
get_cult_ghost(T, user, get_new_player = !T.ghost_can_reenter())
|
||||
else
|
||||
if(length(contents))
|
||||
to_chat(user, "<span class='danger'>Capture failed!</span> The soul stone is full! Use or free an existing soul to make room.")
|
||||
@@ -312,9 +316,9 @@
|
||||
"Wraith" = /mob/living/simple_animal/hostile/construct/wraith,
|
||||
"Artificer" = /mob/living/simple_animal/hostile/construct/builder)
|
||||
/// Custom construct icons for different cults
|
||||
var/list/construct_icons = list("Juggernaut" = image(icon = 'icons/mob/mob.dmi', icon_state = SSticker.cultdat.get_icon("juggernaut")),
|
||||
"Wraith" = image(icon = 'icons/mob/mob.dmi', icon_state = SSticker.cultdat.get_icon("wraith")),
|
||||
"Artificer" = image(icon = 'icons/mob/mob.dmi', icon_state = SSticker.cultdat.get_icon("builder")))
|
||||
var/list/construct_icons = list("Juggernaut" = image(icon = 'icons/mob/cult.dmi', icon_state = SSticker.cultdat.get_icon("juggernaut")),
|
||||
"Wraith" = image(icon = 'icons/mob/cult.dmi', icon_state = SSticker.cultdat.get_icon("wraith")),
|
||||
"Artificer" = image(icon = 'icons/mob/cult.dmi', icon_state = SSticker.cultdat.get_icon("builder")))
|
||||
|
||||
if(shade)
|
||||
var/construct_choice = show_radial_menu(user, shell, construct_icons, custom_check = CALLBACK(src, .proc/radial_check, user), require_near = TRUE)
|
||||
@@ -323,6 +327,7 @@
|
||||
var/mob/living/simple_animal/hostile/construct/C = new picked_class(shell.loc)
|
||||
C.init_construct(shade, src, shell)
|
||||
to_chat(C, C.playstyle_string)
|
||||
to_chat(C, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Construct)</span>")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Creation failed!</span>: The soul stone is empty! Go kill someone!")
|
||||
|
||||
@@ -339,13 +344,11 @@
|
||||
if(shade.mind)
|
||||
shade.mind.transfer_to(src)
|
||||
if(SS.purified)
|
||||
set_light(3, 5, LIGHT_COLOR_DARK_BLUE)
|
||||
name = "Holy [name]"
|
||||
real_name = "Holy [real_name]"
|
||||
|
||||
make_holy()
|
||||
// Replace regular soulstone summoning with purified soulstones
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone)
|
||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone/holy)
|
||||
if(is_type_in_list(/obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone, mob_spell_list))
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone)
|
||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone/holy)
|
||||
|
||||
else if(iscultist(src)) // Re-grant cult actions, lost in the transfer
|
||||
var/datum/action/innate/cult/comm/CC = new
|
||||
@@ -414,13 +417,14 @@
|
||||
return /mob/living/simple_animal/shade/holy
|
||||
return /mob/living/simple_animal/shade/cult
|
||||
|
||||
/obj/item/soulstone/proc/get_cult_ghost(mob/living/M, mob/user)
|
||||
/obj/item/soulstone/proc/get_cult_ghost(mob/living/M, mob/user, get_new_player = FALSE)
|
||||
var/mob/dead/observer/chosen_ghost
|
||||
|
||||
for(var/mob/dead/observer/ghost in GLOB.player_list) // We put them back in their body
|
||||
if(ghost.mind && ghost.mind.current == M && ghost.client)
|
||||
chosen_ghost = ghost
|
||||
break
|
||||
if(!get_new_player)
|
||||
for(var/mob/dead/observer/ghost in GLOB.player_list) // We put them back in their body
|
||||
if(ghost.mind && ghost.mind.current == M && ghost.client)
|
||||
chosen_ghost = ghost
|
||||
break
|
||||
|
||||
if(!chosen_ghost) // Failing that, we grab a ghost
|
||||
var/list/consenting_candidates
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
if(!S)
|
||||
S = new spell_type()
|
||||
var/dat =""
|
||||
dat += "<b>[initial(S.name)]</b>"
|
||||
dat += "<b>[name]</b>"
|
||||
if(S.charge_type == "recharge")
|
||||
dat += " Cooldown:[S.charge_max/10]"
|
||||
dat += " Cost:[cost]<br>"
|
||||
@@ -172,18 +172,6 @@
|
||||
log_name = "IG"
|
||||
category = "Offensive"
|
||||
|
||||
/datum/spellbook_entry/sacred_flame
|
||||
name = "Sacred Flame"
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/sacred_flame
|
||||
cost = 1
|
||||
log_name = "SF"
|
||||
refundable = 0 //You get fire immunity out of it, no.
|
||||
|
||||
/datum/spellbook_entry/sacred_flame/LearnSpell(mob/living/carbon/human/user, obj/item/spellbook/book, obj/effect/proc_holder/spell/newspell)
|
||||
..()
|
||||
user.dna.SetSEState(GLOB.coldblock, 1)
|
||||
singlemutcheck(user, GLOB.coldblock, MUTCHK_FORCED)
|
||||
|
||||
//Defensive
|
||||
/datum/spellbook_entry/disabletech
|
||||
name = "Disable Tech"
|
||||
@@ -239,6 +227,25 @@
|
||||
log_name = "TS"
|
||||
category = "Defensive"
|
||||
|
||||
/datum/spellbook_entry/sacred_flame
|
||||
name = "Sacred Flame and Fire Immunity"
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/sacred_flame
|
||||
cost = 1
|
||||
log_name = "SF"
|
||||
category = "Defensive"
|
||||
|
||||
/datum/spellbook_entry/sacred_flame/LearnSpell(mob/living/carbon/human/user, obj/item/spellbook/book, obj/effect/proc_holder/spell/newspell)
|
||||
to_chat(user, "<span class='notice'>You feel fireproof.</span>")
|
||||
ADD_TRAIT(user, TRAIT_RESISTHEAT, MAGIC_TRAIT)
|
||||
ADD_TRAIT(user, TRAIT_RESISTHIGHPRESSURE, MAGIC_TRAIT)
|
||||
return ..()
|
||||
|
||||
/datum/spellbook_entry/sacred_flame/Refund(mob/living/carbon/human/user, obj/item/spellbook/book)
|
||||
to_chat(user, "<span class='warning'>You no longer feel fireproof.</span>")
|
||||
REMOVE_TRAIT(user, TRAIT_RESISTHEAT, MAGIC_TRAIT)
|
||||
REMOVE_TRAIT(user, TRAIT_RESISTHIGHPRESSURE, MAGIC_TRAIT)
|
||||
return ..()
|
||||
|
||||
//Mobility
|
||||
/datum/spellbook_entry/knock
|
||||
name = "Knock"
|
||||
@@ -431,7 +438,7 @@
|
||||
category = "Artefacts"
|
||||
|
||||
/datum/spellbook_entry/item/voice_of_god
|
||||
name = "Voice of god"
|
||||
name = "Voice of God"
|
||||
desc = "A magical vocal cord that can be used to yell out with the voice of a god, be it to harm, help, or confuse the target."
|
||||
item_path = /obj/item/organ/internal/vocal_cords/colossus/wizard
|
||||
log_name = "VG"
|
||||
@@ -776,7 +783,7 @@
|
||||
owner = user
|
||||
return
|
||||
if(user != owner)
|
||||
to_chat(user, "<span class='warning'>The [name] does not recognize you as it's owner and refuses to open!</span>")
|
||||
to_chat(user, "<span class='warning'>[src] does not recognize you as it's owner and refuses to open!</span>")
|
||||
return
|
||||
user.set_machine(src)
|
||||
var/dat = ""
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user