Merge remote-tracking branch 'upstream/master' into just-defibrillator-things

This commit is contained in:
E-MonaRhg
2021-07-09 00:03:38 +02:00
632 changed files with 15669 additions and 22631 deletions
+4 -3
View File
@@ -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. -->
+1 -1
View File
@@ -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
+5
View File
@@ -0,0 +1,5 @@
{
"workbench.editorAssociations": {
"*.dmi": "imagePreview.previewEditor"
}
}
+22 -8
View File
@@ -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;
+21 -8
View File
@@ -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;
+11
View File
@@ -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;
+13
View File
@@ -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;
+32 -6
View File
@@ -1,12 +1,38 @@
[langserver]
dreamchecker = true
# Keep the keys in this file alphabetical please
[code_standards]
disallow_relative_type_definitions = true
disallow_relative_proc_definitions = true
disallow_relative_type_definitions = true
[debugger]
engine = "auxtools"
[dmdoc]
use_typepath_names = true
[debugger]
engine = "auxtools"
[langserver]
dreamchecker = true
[map_renderer]
hide_invisible = [
"/obj/effect/landmark",
"/obj/effect/mapping_helpers",
"/obj/effect/spawner/random_barrier",
"/obj/effect/spawner/random_spawners",
]
[map_renderer.fancy_layers]
# -10
"/turf/simulated/floor/plating" = -10
"/turf/space" = -10
# -2
"/turf/simulated/floor/bluegrid" = -2
"/turf/simulated/floor/carpet" = -2
"/turf/simulated/floor/engine" = -2
"/turf/simulated/floor/plasteel" = -2
"/turf/simulated/floor/wood" = -2
"/turf/simulated/wall" = -2
[map_renderer.render_passes]
icon-smoothing = false
icon-smoothing-2016 = true
smart-cables = false
+5
View File
@@ -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
-27
View File
@@ -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
-30
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
// See code/modules/mapping for map datums
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{
@@ -146,7 +146,7 @@
/turf/simulated/floor/plating/airless,
/area/space/nearstation)
"F" = (
/obj/structure/computerframe/HONKputer,
/obj/structure/computerframe,
/turf/simulated/floor/plasteel/airless,
/area/space/nearstation)
"G" = (
@@ -1,4 +1,78 @@
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
"aa" = (
/obj/structure/cable{
d1 = 4;
d2 = 8;
icon_state = "4-8";
pixel_y = 0;
tag = ""
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4;
level = 1
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
/obj/effect/turf_decal/stripes/line{
dir = 4
},
/obj/effect/turf_decal/stripes/line{
dir = 8
},
/obj/structure/fans/tiny,
/obj/machinery/door/poddoor{
id_tag = "SSBtestchamber";
name = "Syndicate Test Lab Blast Door"
},
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
/area/ruin/unpowered/syndicate_space_base/testlab)
"ab" = (
/obj/machinery/door_control{
id = "SSBtestchamber";
name = "Blast Door Control"
},
/turf/simulated/wall/mineral/plastitanium/nodiagonal,
/area/ruin/unpowered/syndicate_space_base/testlab)
"ac" = (
/obj/effect/turf_decal/stripes/line{
dir = 8
},
/obj/effect/turf_decal/stripes/line{
dir = 4
},
/obj/structure/fans/tiny,
/obj/machinery/door/poddoor{
id_tag = "SSBtestchamber";
name = "Syndicate Test Lab Blast Door"
},
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
/area/ruin/unpowered/syndicate_space_base/testlab)
"ad" = (
/obj/machinery/light{
dir = 8
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/camera/emp_proof{
c_tag = "Test Lab West";
dir = 4;
network = list("SyndicateTestLab")
},
/turf/simulated/floor/engine,
/area/ruin/unpowered/syndicate_space_base/testlab)
"ae" = (
/obj/machinery/camera/emp_proof{
c_tag = "Test Lab East";
dir = 9;
network = list("SyndicateTestLab")
},
/turf/simulated/floor/engine,
/area/ruin/unpowered/syndicate_space_base/testlab)
"aj" = (
/obj/effect/spawner/window/reinforced,
/turf/simulated/floor/plasteel{
@@ -1191,18 +1265,6 @@
icon_state = "dark"
},
/area/ruin/unpowered/syndicate_space_base/telecomms)
"mE" = (
/obj/effect/turf_decal/stripes/line{
dir = 8
},
/obj/effect/turf_decal/stripes/line{
dir = 4
},
/obj/structure/fans/tiny,
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
/area/ruin/unpowered/syndicate_space_base/testlab)
"mP" = (
/obj/machinery/power/generator,
/obj/structure/cable/yellow,
@@ -1404,14 +1466,6 @@
icon_state = "brown"
},
/area/ruin/unpowered/syndicate_space_base/cargo)
"ol" = (
/obj/machinery/light{
dir = 8
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/turf/simulated/floor/engine,
/area/ruin/unpowered/syndicate_space_base/testlab)
"ow" = (
/obj/structure/closet/crate/medical,
/obj/item/storage/firstaid/fire{
@@ -1861,32 +1915,6 @@
icon_state = "dark"
},
/area/ruin/unpowered/syndicate_space_base/main)
"un" = (
/obj/structure/cable{
d1 = 4;
d2 = 8;
icon_state = "4-8";
pixel_y = 0;
tag = ""
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4;
level = 1
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
/obj/effect/turf_decal/stripes/line{
dir = 4
},
/obj/effect/turf_decal/stripes/line{
dir = 8
},
/obj/structure/fans/tiny,
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
/area/ruin/unpowered/syndicate_space_base/testlab)
"uq" = (
/turf/simulated/floor/plasteel{
icon_state = "freezerfloor"
@@ -2388,7 +2416,7 @@
},
/area/ruin/unpowered/syndicate_space_base/main)
"yf" = (
/obj/machinery/computer/monitor{
/obj/machinery/computer/monitor/secret{
name = "Engine Grid Power Monitoring Computer"
},
/obj/structure/cable/yellow,
@@ -4114,7 +4142,7 @@
icon_state = "0-2";
pixel_y = 1
},
/obj/machinery/computer/monitor{
/obj/machinery/computer/monitor/secret{
name = "Output Grid Power Monitoring Computer"
},
/turf/simulated/floor/plating,
@@ -4926,6 +4954,13 @@
icon_state = "dark"
},
/area/ruin/unpowered/syndicate_space_base/main)
"ZG" = (
/obj/machinery/computer/security/telescreen{
name = "Test Lab Monitor";
network = list("SyndicateTestLab")
},
/turf/simulated/wall/mineral/plastitanium/nodiagonal,
/area/ruin/unpowered/syndicate_space_base/testlab)
"ZR" = (
/turf/simulated/floor/plasteel{
icon_state = "dark"
@@ -6837,8 +6872,8 @@ TD
TD
rr
CM
TD
TD
ZG
ab
TD
CM
ZR
@@ -6897,13 +6932,13 @@ ia
ia
ia
TD
un
aa
TD
ia
ia
ia
TD
mE
ac
TD
AV
AV
@@ -7022,7 +7057,7 @@ fH
fH
RC
uN
ol
ad
RF
RF
dH
@@ -7952,7 +7987,7 @@ qv
Vl
Vl
Vl
Vl
ae
Vl
Vl
Vl
@@ -133,7 +133,7 @@
},
/area/derelict/bridge)
"av" = (
/obj/machinery/computer/monitor,
/obj/machinery/computer/monitor/secret,
/turf/simulated/floor/plasteel{
dir = 1;
icon_state = "darkblue"
@@ -3697,7 +3697,7 @@
name = "Derelict Annex"
})
"hD" = (
/obj/machinery/computer/monitor,
/obj/machinery/computer/monitor/secret,
/turf/simulated/floor/plasteel{
icon_state = "caution";
dir = 5
@@ -6735,7 +6735,7 @@
})
"nS" = (
/obj/structure/table/wood,
/obj/item/reagent_containers/food/snacks/beetsoup,
/obj/item/reagent_containers/food/snacks/soup/beetsoup,
/turf/simulated/floor/plasteel{
icon_state = "bar"
},
+4 -8
View File
@@ -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
@@ -2536,7 +2536,7 @@
icon_state = "0-4";
d2 = 4
},
/obj/machinery/computer/monitor,
/obj/machinery/computer/monitor/secret,
/obj/effect/decal/warning_stripes/west,
/turf/simulated/floor/plasteel,
/area/awaymission/BMPship/Aft)
@@ -2785,7 +2785,7 @@
d2 = 8;
icon_state = "0-8"
},
/obj/machinery/computer/monitor,
/obj/machinery/computer/monitor/secret,
/turf/simulated/floor/plasteel{
icon_state = "yellow"
},
@@ -1308,7 +1308,7 @@
icon_state = "0-4";
d2 = 4
},
/obj/machinery/computer/monitor,
/obj/machinery/computer/monitor/secret,
/obj/structure/cable{
d1 = 4;
d2 = 8;
@@ -5160,7 +5160,7 @@
/turf/simulated/floor/plating,
/area/awaycontent/a7)
"hm" = (
/obj/machinery/computer/monitor,
/obj/machinery/computer/monitor/secret,
/obj/structure/cable,
/turf/simulated/floor/plating,
/area/awaycontent/a7)
@@ -666,7 +666,7 @@
/area/awaymission/spacebattle/cruiser)
"cS" = (
/obj/structure/table/reinforced,
/obj/item/reagent_containers/food/snacks/stew,
/obj/item/reagent_containers/food/snacks/soup/stew,
/turf/simulated/floor/plasteel{
icon_state = "cafeteria";
dir = 2
@@ -7975,7 +7975,7 @@
icon_state = "0-4";
d2 = 4
},
/obj/machinery/computer/monitor{
/obj/machinery/computer/monitor/secret{
name = "primary power monitoring console"
},
/obj/structure/sign/nosmoking_2{
@@ -10652,7 +10652,7 @@
/turf/simulated/floor/plating/asteroid/airless,
/area/awaymission/UO71/outside)
"vV" = (
/obj/machinery/computer/monitor,
/obj/machinery/computer/monitor/secret,
/turf/simulated/floor/plasteel,
/area/awaymission/UO71/bridge)
"vW" = (
@@ -11805,7 +11805,7 @@
},
/area/awaymission/UO71/eng)
"yc" = (
/obj/machinery/computer/monitor{
/obj/machinery/computer/monitor/secret{
name = "primary power monitoring console"
},
/obj/structure/cable,
@@ -11078,7 +11078,7 @@
icon_state = "0-4";
d2 = 4
},
/obj/machinery/computer/monitor{
/obj/machinery/computer/monitor/secret{
name = "primary power monitoring console"
},
/obj/structure/sign/nosmoking_2{
@@ -15909,7 +15909,7 @@
name = "UO45 Engineering"
})
"xg" = (
/obj/machinery/computer/monitor{
/obj/machinery/computer/monitor/secret{
name = "primary power monitoring console"
},
/obj/structure/cable,
+1 -1
View File
@@ -1217,7 +1217,7 @@
},
/area/awaymission/wwgov)
"dy" = (
/obj/item/reagent_containers/food/snacks/stew,
/obj/item/reagent_containers/food/snacks/soup/stew,
/turf/simulated/floor/plasteel{
tag = "icon-stage_bleft";
icon_state = "stage_bleft"
File diff suppressed because it is too large Load Diff
-27
View File
@@ -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
-1
View File
@@ -32,7 +32,6 @@
#define SPECIAL_ROLE_FREE_GOLEM "Free Golem"
#define SPECIAL_ROLE_GOLEM "Golem"
#define SPECIAL_ROLE_HEAD_REV "Head Revolutionary"
#define SPECIAL_ROLE_HONKSQUAD "Honksquad"
#define SPECIAL_ROLE_REV "Revolutionary"
#define SPECIAL_ROLE_MORPH "Morph"
#define SPECIAL_ROLE_MULTIVERSE "Multiverse Traveller"
-2
View File
@@ -22,8 +22,6 @@
#define iseffect(A) (istype(A, /obj/effect))
#define is_cleanable(A) (istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/rune)) //if something is cleanable
#define isclothing(A) (istype(A, /obj/item/clothing))
#define is_pen(W) (istype(W, /obj/item/pen))
+1 -1
View File
@@ -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
+12 -2
View File
@@ -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"
+3 -3
View File
@@ -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)
+3 -6
View File
@@ -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)
+78
View File
@@ -513,6 +513,8 @@
text = replacetext(text, "\[cell\]", "<td>")
text = replacetext(text, "\[logo\]", "&ZeroWidthSpace;<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
+5 -3
View File
@@ -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"
@@ -119,6 +119,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_XENO_HOST "xeno_host" //Tracks whether we're gonna be a baby alien's mummy.
#define TRAIT_SHOCKIMMUNE "shock_immunity"
#define TRAIT_TESLA_SHOCKIMMUNE "tesla_shock_immunity"
#define TRAIT_TELEKINESIS "telekinesis"
#define TRAIT_RESISTHEAT "resist_heat"
#define TRAIT_RESISTHEATHANDS "resist_heat_handsonly" //For when you want to be able to touch hot things, but still want fire to be an issue.
#define TRAIT_RESISTCOLD "resist_cold"
@@ -152,8 +153,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
+12 -15
View File
@@ -31,19 +31,20 @@
return 1
/proc/Get_Angle(atom/movable/start,atom/movable/end)//For beams.
if(!start || !end) return 0
/proc/get_angle(atom/movable/start, atom/movable/end)//For beams.
if(!start || !end)
return 0
var/dy
var/dx
dy=(32*end.y+end.pixel_y)-(32*start.y+start.pixel_y)
dx=(32*end.x+end.pixel_x)-(32*start.x+start.pixel_x)
dy = (32 * end.y + end.pixel_y) - (32 * start.y + start.pixel_y)
dx = (32 * end.x + end.pixel_x) - (32 * start.x + start.pixel_x)
if(!dy)
return (dx>=0)?90:270
.=arctan(dx/dy)
if(dy<0)
.+=180
else if(dx<0)
.+=360
return (dx >= 0) ? 90 : 270
. = arctan(dx / dy)
if(dy < 0)
. += 180
else if(dx < 0)
. += 360
//Returns location. Returns null if no location was found.
/proc/get_teleport_loc(turf/location,mob/target,distance = 1, density = 0, errorx = 0, errory = 0, eoffsetx = 0, eoffsety = 0)
@@ -1246,10 +1247,6 @@ GLOBAL_LIST_INIT(wall_items, typecacheof(list(/obj/machinery/power/apc, /obj/mac
return 1
return 0
/proc/get_angle(atom/a, atom/b)
return atan2(b.y - a.y, b.x - a.x)
/proc/atan2(x, y)
if(!x && !y) return 0
return y >= 0 ? arccos(x / sqrt(x * x + y * y)) : -arccos(x / sqrt(x * x + y * y))
@@ -2072,7 +2069,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)
+5 -1
View File
@@ -30,7 +30,8 @@ GLOBAL_LIST_INIT(restricted_camera_networks, list(
"UO45",
"UO45R",
"UO71",
"Xeno"
"Xeno",
"SyndicateTestLab"
)) //Those networks can only be accessed by preexisting terminals. AIs and new terminals can't use them.
GLOBAL_LIST_INIT(ruin_landmarks, list())
@@ -54,4 +55,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.")
+1
View File
@@ -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.
+1 -1
View File
@@ -40,7 +40,7 @@ GLOBAL_LIST_INIT(drinks, list("beer2","hot_coco","orangejuice","tomatojuice","li
"booger","bloodymary","gargleblaster","bravebull","tequilasunrise","toxinsspecial",
"beepskysmash","salglu_solution","irishcream","manlydorf","longislandicedtea",
"moonshine","b52","irishcoffee","margarita","blackrussian","manhattan",
"manhattan_proj","whiskeysoda","antifreeze","barefoot","snowwhite","demonsblood",
"manhattan_proj","whiskeysoda","adminfreeze","antifreeze","barefoot","snowwhite","demonsblood",
"vodkatonic","ginfizz","bahama_mama","singulo","sbiten","devilskiss","red_mead",
"mead","iced_beer","grog","aloe","andalusia","alliescocktail","soy_latte",
"cafe_latte","acidspit","amasec","neurotoxin","hippiesdelight","bananahonk",
+2 -2
View File
@@ -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)
-3
View File
@@ -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_|
-4
View File
@@ -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))
+7 -2
View File
@@ -24,6 +24,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_XENO_HOST" = TRAIT_XENO_HOST,
"TRAIT_SHOCKIMMUNE" = TRAIT_SHOCKIMMUNE,
"TRAIT_TESLA_SHOCKIMMUNE" = TRAIT_TESLA_SHOCKIMMUNE,
"TRAIT_TELEKINESIS" = TRAIT_TELEKINESIS,
"TRAIT_RESISTHEAT" = TRAIT_RESISTHEAT,
"TRAIT_RESISTHEATHANDS" = TRAIT_RESISTHEATHANDS,
"TRAIT_RESISTCOLD" = TRAIT_RESISTCOLD,
@@ -45,7 +46,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 +57,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)
-8
View File
@@ -215,11 +215,3 @@
if(!ai_control_check(user))
return
toggle_light(user)
// AI-CONTROLLED SLIP GENERATOR IN AI CORE
/obj/machinery/ai_slipper/AICtrlClick(mob/living/silicon/ai/user) //Turns liquid dispenser on or off
ToggleOn()
/obj/machinery/ai_slipper/AIAltClick() //Dispenses liquid if on
Activate()
+2 -2
View File
@@ -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
-10
View File
@@ -169,16 +169,6 @@
/obj/machinery/power/apc/BorgCtrlClick(mob/living/silicon/robot/user) // turns off/on APCs. Forwards to AI code.
AICtrlClick(user)
// AI SLIPPER
/obj/machinery/ai_slipper/BorgCtrlClick(mob/living/silicon/robot/user) //Turns liquid dispenser on or off
ToggleOn()
/obj/machinery/ai_slipper/BorgAltClick(mob/living/silicon/robot/user) //Dispenses liquid if on
Activate()
// TURRETCONTROL
/obj/machinery/turretid/BorgCtrlClick(mob/living/silicon/robot/user) //turret control on/off. Forwards to AI code.
+2 -2
View File
@@ -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"
+7 -3
View File
@@ -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
-19
View File
@@ -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
+1 -1
View File
@@ -45,7 +45,7 @@
if(HAS_TRAIT(src, TRAIT_LASEREYES) && a_intent == INTENT_HARM)
LaserEyes(A)
if(dna.GetSEState(GLOB.teleblock))
if(HAS_TRAIT(src, TRAIT_TELEKINESIS))
A.attack_tk(src)
if(isturf(A) && get_dist(src, A) <= 1)
+8 -2
View File
@@ -39,7 +39,7 @@
/obj/item/attack_tk(mob/user)
if(user.stat || !isturf(loc))
return
if(user.dna?.GetSEState(GLOB.teleblock) && !user.get_active_hand()) // both should already be true to get here
if(HAS_TRAIT(user, TRAIT_TELEKINESIS) && !user.get_active_hand()) // both should already be true to get here
var/obj/item/tk_grab/O = new(src)
O.form_grab(user, src)
else
@@ -109,7 +109,7 @@
if(!host || host != user)
qdel(src)
return
if(!host.dna?.GetSEState(GLOB.teleblock))
if(!HAS_TRAIT(host, TRAIT_TELEKINESIS))
qdel(src)
return
if(isobj(target) && !isturf(target.loc))
@@ -139,6 +139,12 @@
else
if(focus.buckled_mobs)
to_chat(user, "<span class='notice'>This object is too heavy to move with something buckled to it!</span>")
return
if(length(focus.client_mobs_in_contents))
to_chat(user, "<span class='notice'>This object is too heavy to move with something inside of it!</span>")
return
apply_focus_overlay()
focus.throw_at(target, 10, 1, user)
last_throw = world.time
+41
View File
@@ -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")
+1 -1
View File
@@ -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,
+16
View File
@@ -0,0 +1,16 @@
SUBSYSTEM_DEF(chat_pings)
name = "Chat Pings"
flags = SS_NO_INIT
runlevels = RUNLEVEL_INIT | RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME // ALL OF THEM
wait = 30 SECONDS // Chat pings every 30 seconds
/// List of all held chat datums
var/list/datum/chatOutput/chat_datums = list() // Do NOT put this in Initialize(). You will cause issues.
/datum/controller/subsystem/chat_pings/fire(resumed)
for(var/datum/chatOutput/CO as anything in chat_datums)
CO.updatePing()
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/chat_pings/stat_entry()
..("P: [length(chat_datums)]")
+1 -1
View File
@@ -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()
+4 -1
View File
@@ -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 ..()
+88 -24
View File
@@ -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)
-2
View File
@@ -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)
+29 -6
View File
@@ -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)
+4
View File
@@ -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
+1 -1
View File
@@ -58,7 +58,7 @@
return ..()
/datum/beam/proc/Draw()
var/Angle = round(Get_Angle(origin,target))
var/Angle = round(get_angle(origin, target))
var/matrix/rot_matrix = matrix()
rot_matrix.Turn(Angle)
+3 -3
View File
@@ -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)
-123
View File
@@ -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
+4
View File
@@ -15,6 +15,7 @@
var/list/stage3 = list("You feel utterly plain.")
var/list/stage4 = list("You feel white bread.")
var/list/stage5 = list("Oh the humanity!")
var/transformation_text = null
var/new_form = /mob/living/carbon/human
/datum/disease/transformation/stage_act()
@@ -44,6 +45,8 @@
return
if(affected_mob.notransform)
return
if(transformation_text)
to_chat(affected_mob, transformation_text)
affected_mob.notransform = 1
affected_mob.canmove = 0
affected_mob.icon = null
@@ -243,4 +246,5 @@
stage3 = list("<span class='danger'>Your appendages are melting away.</span>", "<span class='danger'>Your limbs begin to lose their shape.</span>")
stage4 = list("<span class='danger'>You're ravenous.</span>")
stage5 = list("<span class='danger'>You have become a morph.</span>")
transformation_text = "<span class='userdanger'>This transformation does NOT make you an antagonist if you were not one already. If you were not an antagonist, you should not eat any steal objectives or the contents of the armory.</span>"
new_form = /mob/living/simple_animal/hostile/morph
@@ -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
View File
@@ -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"])
+2
View File
@@ -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)
+151 -21
View File
@@ -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
@@ -84,7 +84,7 @@
shoes = /obj/item/clothing/shoes/magboots/syndie
r_pocket = /obj/item/radio/uplink/nuclear
l_pocket = /obj/item/pinpointer/advpinpointer
l_hand = /obj/item/tank/jetpack/oxygen/harness
l_hand = /obj/item/tank/internals/oxygen/red
backpack_contents = list(
/obj/item/storage/box/survival_syndi = 1,
@@ -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"
@@ -1158,3 +1223,68 @@
var/obj/item/radio/headset/R = H.l_ear
if(istype(R))
R.flags |= NODROP
/datum/outfit/admin/honksquad
name = "Honksquad"
uniform = /obj/item/clothing/under/rank/clown
mask = /obj/item/clothing/mask/gas/clown_hat
back = /obj/item/storage/backpack/clown
id = /obj/item/card/id/clown
backpack_contents = list(
/obj/item/storage/box/survival = 1,
/obj/item/bikehorn = 1,
/obj/item/stamp/clown = 1,
/obj/item/toy/crayon/rainbow = 1,
/obj/item/reagent_containers/spray/waterflower = 1,
/obj/item/reagent_containers/food/snacks/grown/banana = 1,
)
shoes = /obj/item/clothing/shoes/clown_shoes
suit = /obj/item/clothing/suit/storage/det_suit
pda = /obj/item/pda/clown
l_ear = /obj/item/radio/headset
r_pocket = /obj/item/reagent_containers/food/pill/patch/jestosterone
/datum/outfit/admin/honksquad/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
. = ..()
if(H.gender == FEMALE)
uniform = /obj/item/clothing/under/rank/clown/sexy
mask = /obj/item/clothing/mask/gas/clown_hat/sexy
if(prob(50))
// You have to do it like this to make it work with assoc lists without a runtime.
// Trust me.
backpack_contents.Add(/obj/item/gun/energy/clown)
backpack_contents[/obj/item/gun/energy/clown] = 1 // Amount. Not boolean. Do not TRUE this. You turkey.
else
backpack_contents.Add(/obj/item/gun/throw/piecannon)
backpack_contents[/obj/item/gun/throw/piecannon] = 1
/datum/outfit/admin/honksquad/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
. = ..()
if(visualsOnly)
return
// Setup their clumsy gene
H.dna.SetSEState(GLOB.clumsyblock, TRUE)
H.check_mutations = TRUE
// Setup their headset
var/obj/item/radio/R = H.l_ear
if(istype(R))
R.set_frequency(DTH_FREQ) // Clowns can be part of "special operations"
// And their PDA
var/obj/item/pda/P = H.wear_pda
if(istype(P))
P.owner = H.real_name
P.ownjob = "Clown"
P.name = "PDA-[H.real_name] ([P.ownjob])"
// And their ID
var/obj/item/card/id/I = H.wear_id
if(istype(I))
apply_to_card(I, H, list(ACCESS_CLOWN), "Clown")
H.sec_hud_set_ID()
+8 -3
View File
@@ -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
+2 -2
View File
@@ -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!"
+2 -2
View File
@@ -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"
..()
+4 -4
View File
@@ -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)
+1 -1
View File
@@ -374,7 +374,7 @@
for(var/am in thrownatoms)
var/atom/movable/AM = am
if(AM == user || AM.anchored)
if(AM == user || AM.anchored || AM.move_resist == INFINITY)
continue
throwtarget = get_edge_target_turf(user, get_dir(user, get_step_away(AM, user)))
+8
View File
@@ -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 /////////////////////////////////////////
+26 -12
View File
@@ -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?")
+3 -1
View File
@@ -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"
@@ -1016,6 +1017,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 11
surplus = 0
cant_discount = TRUE
hijack_only = TRUE
/datum/uplink_item/explosives/emp_bomb
name = "EMP bomb"
@@ -1425,7 +1427,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
name = "Power Sink"
desc = "When screwed to wiring attached to an electric grid, then activated, this large device places excessive load on the grid, causing a stationwide blackout. The sink cannot be carried because of its excessive size. Ordering this sends you a small beacon that will teleport the power sink to your location on activation."
reference = "PS"
item = /obj/item/powersink
item = /obj/item/radio/beacon/syndicate/power_sink
cost = 10
/datum/uplink_item/device_tools/singularity_beacon
+4 -5
View File
@@ -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
/**
+6
View File
@@ -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
View File
@@ -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
+12 -4
View File
@@ -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
*
@@ -1072,7 +1072,7 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
Returning TRUE here will override the above proc's result.
*/
/atom/proc/CanAStarPassTo(ID, dir, obj/destination)
return TRUE
return FALSE
/** Call this when you want to present a renaming prompt to the user.
@@ -1139,3 +1139,11 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
else
name = "[prefix][t]"
return t
/atom/proc/set_angle(degrees)
var/matrix/M = matrix()
M.Turn(degrees)
// If we aint 0, make it NN transform
if(degrees)
appearance_flags |= PIXEL_SCALE
transform = M
+8 -3
View File
@@ -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)
+1
View File
@@ -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 -6
View File
@@ -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
+7 -7
View File
@@ -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>")
+4
View File
@@ -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))
+2
View File
@@ -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))
+3 -2
View File
@@ -80,7 +80,7 @@
/datum/mutation/noprints
name = "No Prints"
activation_messages = list("Your fingers feel numb.")
deactivation_messages = list("your fingers no longer feel numb.")
deactivation_messages = list("Your fingers no longer feel numb.")
instability = GENE_INSTABILITY_MINOR
traits_to_add = list(TRAIT_NOFINGERPRINTS)
@@ -161,7 +161,7 @@
/datum/mutation/xray
name = "X-Ray Vision"
activation_messages = list("The walls suddenly disappear.")
deactivation_messages = list("the walls around you re-appear.")
deactivation_messages = list("The walls around you re-appear.")
instability = GENE_INSTABILITY_MAJOR
traits_to_add = list(TRAIT_XRAY_VISION)
activation_prob = 15
@@ -185,6 +185,7 @@
activation_messages = list("You feel smarter.")
deactivation_messages = list("You feel dumber.")
instability = GENE_INSTABILITY_MAJOR
traits_to_add = list(TRAIT_TELEKINESIS)
activation_prob = 15
/datum/mutation/tk/New()
+7 -20
View File
@@ -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]
-1
View File
@@ -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
-13
View File
@@ -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)
+1 -1
View File
@@ -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)
@@ -93,5 +93,7 @@ the same goes for Remove(). if you override Remove(), call parent or else your p
/datum/action/changeling/proc/transform_dna(mob/living/carbon/human/H, datum/dna/D)
if(!D)
return
H.change_dna(D, TRUE)
var/changesSpecies = TRUE
if (H.dna.species.name == D.species.name)
changesSpecies = FALSE
H.change_dna(D, changesSpecies)
@@ -1,11 +1,11 @@
/datum/action/changeling/digitalcamo
name = "Digital Camouflage"
desc = "By evolving the ability to distort our form and proprotions, we defeat common altgorithms used to detect lifeforms on cameras."
helptext = "We cannot be tracked by camera while using this skill. However, humans looking at us will find us... uncanny."
helptext = "We cannot be tracked by camera while using this skill."
button_icon_state = "digital_camo"
dna_cost = 1
//Prevents AIs tracking you but makes you easily detectable to the human-eye.
//Prevents AIs tracking you.
/datum/action/changeling/digitalcamo/sting_action(mob/user)
if(user.digitalcamo)
@@ -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>")
+54 -45
View File
@@ -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)
@@ -843,42 +848,13 @@
uses += max(1, temp)
/obj/item/melee/blood_magic/manipulator/attack_self(mob/living/user)
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
var/list/options = list("Blood Orb (50)" = image(icon = 'icons/obj/cult.dmi', icon_state = "summoning_orb"),
"Blood Recharge (75)" = image(icon = 'icons/mob/actions/actions_cult.dmi', icon_state = "blood_charge"),
"Blood Spear (150)" = image(icon = 'icons/mob/actions/actions_cult.dmi', icon_state = "bloodspear"),
"Blood Bolt Barrage (300)" = image(icon = 'icons/mob/actions/actions_cult.dmi', icon_state = "blood_barrage"))
var/choice = show_radial_menu(user, src, 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 +874,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 +890,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)
+82 -67
View File
@@ -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)
+12 -16
View File
@@ -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)

Some files were not shown because too many files have changed in this diff Show More