Merge remote-tracking branch 'upstream/master' into bnuuy

This commit is contained in:
hal9000PR
2021-10-26 19:53:15 +01:00
798 changed files with 24230 additions and 25764 deletions
+1
View File
@@ -5,6 +5,7 @@
### AffectedArc07
# Actual Code
/code/controllers/subsystem/instancing.dm @AffectedArc07
/code/controllers/subsystem/mapping.dm @AffectedArc07
/code/controllers/subsystem/ticker.dm @AffectedArc07
/tgui/ @AffectedArc07
+12 -5
View File
@@ -38,6 +38,11 @@ actual development.
of a pull request needs to be removed/changed, you may simply modify that single commit.
Due to limitations of the engine, this may not always be possible; but do try your best.
* Keep your pull requests small and reviewable whenever possible. Do not bundle unrelated
fixes even if not bundling them generates more pull requests. In case of mapping PRs that add features -
consult a maintainer on whether it would be appropriate to split up the PR to add the
feature to multiple maps individually.
* Document and explain your pull requests thoroughly. Failure to do so will delay a PR as
we question why changes were made. This is especially important if you're porting a PR
from another codebase (i.e. TG) and divert from the original. Explaining with single
@@ -460,7 +465,7 @@ SS13 has a lot of legacy code that's never been updated. Here are some examples
```DM
//Bad
var/datum/db_query/query_watch = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey='[target_ckey]'")
//Good
var/datum/db_query/query_watch = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey=:target_ckey", list(
"target_ckey" = target_ckey
@@ -497,11 +502,13 @@ in the SQL/updates folder.
* Queries must never specify the database, be it in code, or in text files in the repo.
### Mapping Standards
* For map edit PRs, we do not accept 'change for the sake of change' remaps, unless you have very good reasoning to do so. Maintainers reserve the right to close your PR if we disagree with your reasoning.
* Map Merge
* The following guideline for map merging applies to people who are **NOT** using StrongDMM, please see the StrongDMM section if you are.
* You **MUST** run Map Merge prior to opening your PR when updating existing maps to minimize the change differences (even when using third party mapping programs such as FastDMM.)
* Failure to run Map Merge on a map after using third party mapping programs (such as FastDMM) greatly increases the risk of the map's key dictionary becoming corrupted by future edits after running map merge. Resolving the corruption issue involves rebuilding the map's key dictionary;
* StrongDMM
* When using StrongDMM, the following options **MUST** be enabled to avoid file bloat. They can be found under `File > Preferences > Save Options` in SDMM.
* Map save format: This **MUST** be set to **TGM** if you do not want to run Map Merge. Enabling this setting means SDMM will automatically map merge, letting you skip manual merging.
@@ -521,10 +528,10 @@ in the SQL/updates folder.
* NEVER run cables under wall turfs.
* Keep floor turf variations to a minimum. Generally, more than 3 floor turf types in one room is bad design.
* Run air pipes together where possible. The first example below is to be avoided, the second is optimal:
![image](https://user-images.githubusercontent.com/12197162/120011088-d22c7400-bfd5-11eb-867f-7b137ac5b1b2.png) ![image](https://user-images.githubusercontent.com/12197162/120011126-dfe1f980-bfd5-11eb-96b2-c83238a9cdcf.png)
* Pipe layouts should be logical and predictable, easy to understand at a glance. Always avoid complex layouts like in this example:
* Pipe layouts should be logical and predictable, easy to understand at a glance. Always avoid complex layouts like in this example:
![image](https://user-images.githubusercontent.com/12197162/120619480-ecda6f00-c453-11eb-9d9f-abf0d1a99c34.png)
* Decals are to be used sparingly. Good map design does not require warning tape around everything. Decal overuse contributes to maptick slowdown.
+1
View File
@@ -0,0 +1 @@
patreon: ParadiseStation
+4
View File
@@ -55,6 +55,9 @@ jobs:
unit_tests_and_sql:
name: Unit Tests + SQL Validation
runs-on: ubuntu-20.04
strategy:
matrix:
maptype: ['/datum/map/cyberiad', '/datum/map/delta', '/datum/map/metastation']
services:
mariadb:
image: mariadb:latest
@@ -86,6 +89,7 @@ jobs:
tools/ci/install_byond.sh
source $HOME/BYOND/byond/bin/byondsetup
tools/ci/dm.sh -DCIBUILDING paradise.dme
echo '${{ matrix.maptype }}' > data/next_map.txt
tools/ci/run_server.sh
windows_dll_tests:
+5 -3
View File
@@ -2,7 +2,8 @@ name: Generate Documentation
on:
schedule:
- cron: "0 0 * * *" # Every day at the very start of the day
- cron: "0 0 * * *" # Every day at the very start of the day. Except it happens an hour and a half later because actions backlog
workflow_dispatch:
jobs:
generate_docs:
@@ -14,10 +15,11 @@ jobs:
with:
fetch-depth: 1
ref: master
- name: 'Install DMDOC'
run: bash tools/ci/install_dmdoc.sh
- name: 'Generate Documentation'
run: |
./tools/github-actions/doc-generator
~/dmdoc
touch dmdoc/.nojekyll
# Nojekyll is important to disable jeykll syntax, which can mess with files that start with underscores
+32 -2
View File
@@ -114,6 +114,7 @@ CREATE TABLE `death` (
`pod` text NOT NULL COMMENT 'Place of death',
`coord` text NOT NULL COMMENT 'X, Y, Z POD',
`tod` datetime NOT NULL COMMENT 'Time of death',
`server_id` TEXT NULL DEFAULT NULL,
`job` text NOT NULL,
`special` text NOT NULL,
`name` text NOT NULL,
@@ -197,6 +198,7 @@ CREATE TABLE `ban` (
`bantime` datetime NOT NULL,
`ban_round_id` INT(11) NULL DEFAULT NULL,
`serverip` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL,
`server_id` VARCHAR(50) NULL DEFAULT NULL COLLATE utf8mb4_general_ci,
`bantype` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL,
`reason` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
`job` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
@@ -320,6 +322,7 @@ CREATE TABLE `karma` (
`receiverspecial` text,
`isnegative` tinyint(1) DEFAULT NULL,
`spenderip` text NOT NULL,
`server_id` TEXT NULL DEFAULT NULL,
`time` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=73614 DEFAULT CHARSET=utf8mb4;
@@ -374,6 +377,7 @@ CREATE TABLE `legacy_population` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`playercount` int(11) DEFAULT NULL,
`admincount` int(11) DEFAULT NULL,
`server_id` VARCHAR(50) NULL DEFAULT NULL,
`time` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2550 DEFAULT CHARSET=utf8mb4;
@@ -532,6 +536,7 @@ CREATE TABLE `connection_log` (
`ckey` varchar(32) NOT NULL,
`ip` varchar(32) NOT NULL,
`computerid` varchar(32) NOT NULL,
`server_id` VARCHAR(50) NULL DEFAULT NULL,
`result` ENUM('ESTABLISHED','DROPPED - IPINTEL','DROPPED - BANNED','DROPPED - INVALID') NOT NULL DEFAULT 'ESTABLISHED' COLLATE 'utf8mb4_general_ci',
PRIMARY KEY (`id`),
KEY `ckey` (`ckey`),
@@ -584,6 +589,7 @@ CREATE TABLE `round` (
`shuttle_name` VARCHAR(64) NULL,
`map_name` VARCHAR(32) NULL,
`station_name` VARCHAR(80) NULL,
`server_id` VARCHAR(50) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
@@ -597,5 +603,29 @@ CREATE TABLE `2fa_secrets` (
`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;
) COLLATE='utf8mb4_general_ci' ENGINE=InnoDB;
--
-- Table structure for table `pai_saves`
--
CREATE TABLE `pai_saves` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`ckey` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
`pai_name` LONGTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
`description` LONGTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
`preferred_role` LONGTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
`ooc_comments` LONGTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `ckey` (`ckey`) USING BTREE
) COLLATE='utf8mb4_general_ci' ENGINE=InnoDB;
--
-- Table structure for table `instance_data_cache`
--
CREATE TABLE `instance_data_cache` (
`server_id` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
`key_name` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
`key_value` VARCHAR(12345) NOT NULL COLLATE 'utf8mb4_general_ci',
`last_updated` TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`server_id`, `key_name`) USING HASH
) COLLATE='utf8mb4_general_ci' ENGINE=MEMORY;
+13
View File
@@ -0,0 +1,13 @@
# Updates DB from 25-25, -AffectedArc07
# Adds a pAI saves table to the DB
CREATE TABLE `pai_saves` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`ckey` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
`pai_name` LONGTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
`description` LONGTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
`preferred_role` LONGTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
`ooc_comments` LONGTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `ckey` (`ckey`) USING BTREE
) COLLATE='utf8mb4_general_ci' ENGINE=InnoDB;
+32
View File
@@ -0,0 +1,32 @@
# Updates DB from 26 to 27 -AffectedArc07
# Adds a new table for instance data caching, and server_id fields on other tables
CREATE TABLE `instance_data_cache` (
`server_id` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
`key_name` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
`key_value` VARCHAR(12345) NOT NULL COLLATE 'utf8mb4_general_ci',
`last_updated` TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`server_id`, `key_name`) USING HASH
) COLLATE='utf8mb4_general_ci' ENGINE=MEMORY;
ALTER TABLE `ban`
ADD COLUMN `server_id` VARCHAR(50) NULL DEFAULT NULL AFTER `serverip`;
ALTER TABLE `connection_log`
ADD COLUMN `server_id` VARCHAR(50) NULL DEFAULT NULL AFTER `computerid`;
ALTER TABLE `death`
ADD COLUMN `server_id` TEXT NULL AFTER `tod`;
ALTER TABLE `karma`
ADD COLUMN `server_id` TEXT NULL AFTER `spenderip`;
ALTER TABLE `legacy_population`
ADD COLUMN `server_id` VARCHAR(50) NULL DEFAULT NULL AFTER `admincount`;
# Notes already has a column for this
ALTER TABLE `notes`
CHANGE COLUMN `server` `server` VARCHAR(50) NULL COLLATE 'utf8mb4_general_ci' AFTER `edits`;
ALTER TABLE `round`
ADD COLUMN `server_id` VARCHAR(50) NULL DEFAULT NULL AFTER `station_name`;
+3 -3
View File
@@ -1,9 +1,9 @@
# This file has all the information on what versions of libraries are thrown into the code
# For dreamchecker
export SPACEMANDMM_TAG=suite-1.6
export SPACEMANDMM_TAG=suite-1.7.1
# For TGUI
export NODE_VERSION=12
# Byond Major
export BYOND_MAJOR=513
export BYOND_MAJOR=514
# Byond Minor
export BYOND_MINOR=1528
export BYOND_MINOR=1566
+11072 -12572
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -362,12 +362,6 @@
"bf" = (
/turf/simulated/wall/mineral/plastitanium/nodiagonal,
/area/syndicate_depot/outer)
"bg" = (
/obj/effect/spawner/random_spawners/syndicate/layout/spacepod,
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
/area/syndicate_depot/core)
"bh" = (
/obj/machinery/light{
dir = 1;
@@ -1758,7 +1752,7 @@ aD
aM
at
aD
bg
aD
bn
bu
bz
@@ -290,8 +290,13 @@
/turf/simulated/floor/plating,
/area/shuttle/abandoned)
"by" = (
/obj/structure/spacepoddoor,
/turf/simulated/floor/plating,
/obj/machinery/door_control{
id = "whiteshippoddoor";
name = "Pod Door Control";
pixel_x = -24;
pixel_y = 24
},
/turf/simulated/floor/mineral/titanium,
/area/shuttle/abandoned)
"bz" = (
/obj/machinery/door/airlock/public/glass{
@@ -304,11 +309,10 @@
/turf/simulated/floor/plating,
/area/shuttle/abandoned)
"bC" = (
/obj/structure/spacepoddoor,
/obj/machinery/door/poddoor/multi_tile/two_tile_ver{
id_tag = "whiteshippoddoor"
},
/turf/simulated/floor/plating,
/turf/simulated/floor/mineral/titanium,
/area/shuttle/abandoned)
"bD" = (
/obj/machinery/door_control{
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -886,7 +886,7 @@
},
/obj/effect/decal/cleanable/cobweb,
/obj/machinery/computer/prisoner{
dir = 1
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 6
@@ -4371,6 +4371,7 @@
"sO" = (
/obj/effect/decal/cleanable/dirt,
/obj/machinery/computer/security{
dir = 4;
network = list("Labor Camp")
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
@@ -5275,7 +5276,7 @@
/area/mine/production)
"VJ" = (
/obj/machinery/computer/secure_data{
dir = 1
dir = 8
},
/turf/simulated/floor/plasteel{
dir = 1;
+134 -48
View File
@@ -651,7 +651,9 @@
/turf/simulated/floor/mineral/plastitanium/red,
/area/shuttle/administration)
"cH" = (
/obj/machinery/computer/shuttle/ferry,
/obj/machinery/computer/shuttle/ferry{
dir = 8
},
/turf/simulated/floor/plating,
/area/centcom/evac)
"cI" = (
@@ -661,7 +663,9 @@
/turf/simulated/floor/plating/airless,
/area/shuttle/specops)
"cK" = (
/obj/machinery/computer/shuttle/admin,
/obj/machinery/computer/shuttle/admin{
dir = 8
},
/turf/simulated/floor/plating,
/area/centcom/evac)
"cL" = (
@@ -1387,7 +1391,9 @@
/turf/simulated/floor/wood,
/area/syndicate_mothership)
"fi" = (
/obj/machinery/computer/shuttle/syndicate/recall,
/obj/machinery/computer/shuttle/syndicate/recall{
dir = 1
},
/turf/simulated/floor/wood,
/area/syndicate_mothership)
"fj" = (
@@ -1411,8 +1417,8 @@
/turf/simulated/wall/indestructible/riveted,
/area/centcom/gamma)
"fn" = (
/obj/machinery/computer/library/checkout,
/obj/structure/table/wood,
/obj/machinery/computer/library/checkout,
/turf/simulated/floor/engine/cult,
/area/wizard_station)
"fo" = (
@@ -2028,7 +2034,9 @@
/turf/simulated/floor/plasteel/dark,
/area/syndicate_mothership)
"hP" = (
/obj/machinery/computer/communications,
/obj/machinery/computer/communications{
dir = 8
},
/turf/simulated/floor/mineral/plastitanium/red,
/area/shuttle/administration)
"hQ" = (
@@ -3500,7 +3508,9 @@
/turf/simulated/floor/carpet,
/area/centcom/control)
"mP" = (
/obj/machinery/computer/pod/deathsquad,
/obj/machinery/computer/pod/deathsquad{
dir = 8
},
/turf/simulated/floor/plasteel/dark{
dir = 1;
icon_state = "vault"
@@ -3523,7 +3533,9 @@
/turf/simulated/floor/wood,
/area/centcom/control)
"mV" = (
/obj/machinery/computer/card/centcom,
/obj/machinery/computer/card/centcom{
dir = 8
},
/turf/simulated/floor/wood,
/area/centcom/control)
"mW" = (
@@ -3588,7 +3600,9 @@
/turf/simulated/floor/carpet,
/area/centcom/control)
"nh" = (
/obj/machinery/computer/communications,
/obj/machinery/computer/communications{
dir = 8
},
/turf/simulated/floor/carpet,
/area/centcom/control)
"nj" = (
@@ -4013,9 +4027,9 @@
/area/syndicate_mothership)
"oB" = (
/obj/structure/closet/secure_closet/guncabinet,
/obj/item/ammo_box/shotgun/buck,
/obj/item/ammo_box/shotgun/buck,
/obj/item/ammo_box/shotgun/buck,
/obj/item/ammo_box/shotgun/beanbag,
/obj/item/ammo_box/shotgun/beanbag,
/obj/item/ammo_box/shotgun/beanbag,
/obj/item/gun/projectile/shotgun/automatic/combat,
/obj/item/gun/projectile/shotgun/automatic/combat,
/obj/item/gun/projectile/shotgun/automatic/combat,
@@ -4306,7 +4320,9 @@
d2 = 8;
icon_state = "0-8"
},
/obj/machinery/computer/mech_bay_power_console,
/obj/machinery/computer/mech_bay_power_console{
dir = 1
},
/turf/simulated/floor/mineral/plastitanium/red,
/area/shuttle/gamma/space)
"pu" = (
@@ -4417,12 +4433,12 @@
/turf/simulated/floor/carpet,
/area/centcom/specops)
"pP" = (
/obj/structure/table/wood,
/obj/machinery/computer/security/telescreen{
desc = "Used for watching the Special Ops.";
name = "Special Ops. Monitor";
network = list("ERT")
},
/obj/structure/table/wood,
/turf/simulated/floor/carpet,
/area/centcom/specops)
"pQ" = (
@@ -4430,10 +4446,12 @@
/turf/simulated/floor/plasteel/dark,
/area/centcom/specops)
"pR" = (
/obj/machinery/computer/station_alert,
/obj/structure/sign/poster/official/nanotrasen_logo{
pixel_x = 32
},
/obj/machinery/computer/station_alert{
dir = 8
},
/turf/simulated/floor/plasteel{
dir = 5;
icon_state = "darkyellow"
@@ -4940,7 +4958,9 @@
},
/area/centcom/evac)
"rz" = (
/obj/machinery/computer/communications,
/obj/machinery/computer/communications{
dir = 8
},
/turf/simulated/floor/plasteel/dark,
/area/centcom/specops)
"rA" = (
@@ -5185,10 +5205,12 @@
/turf/simulated/floor/wood,
/area/centcom/evac)
"sy" = (
/obj/machinery/computer/secure_data,
/obj/machinery/light/spot{
dir = 8
},
/obj/machinery/computer/secure_data{
dir = 4
},
/turf/simulated/floor/mineral/plastitanium/red,
/area/centcom/evac)
"sz" = (
@@ -6168,7 +6190,9 @@
/turf/simulated/floor/plasteel/grimy,
/area/centcom/specops)
"vf" = (
/obj/machinery/computer/secure_data,
/obj/machinery/computer/secure_data{
dir = 4
},
/turf/simulated/floor/plasteel,
/area/centcom/control)
"vg" = (
@@ -6185,7 +6209,9 @@
/turf/simulated/floor/plasteel,
/area/admin)
"vi" = (
/obj/machinery/computer/med_data,
/obj/machinery/computer/med_data{
dir = 8
},
/turf/simulated/floor/plasteel,
/area/centcom/control)
"vj" = (
@@ -6235,11 +6261,11 @@
/turf/simulated/floor/plasteel,
/area/admin)
"vp" = (
/obj/machinery/computer/mech_bay_power_console,
/obj/structure/cable{
d2 = 2;
icon_state = "0-2"
},
/obj/machinery/computer/mech_bay_power_console,
/turf/simulated/floor/plasteel,
/area/admin)
"vr" = (
@@ -6257,24 +6283,33 @@
/area/admin)
"vs" = (
/obj/machinery/computer/security{
dir = 1;
network = list("SS13","Telecomms","Research Outpost","Mining Outpost","ERT","CentComm","Thunderdome")
},
/turf/simulated/floor/plasteel,
/area/centcom/control)
"vt" = (
/obj/machinery/computer/station_alert,
/obj/machinery/computer/station_alert{
dir = 1
},
/turf/simulated/floor/plasteel,
/area/centcom/control)
"vu" = (
/obj/machinery/computer/communications,
/obj/machinery/computer/communications{
dir = 1
},
/turf/simulated/floor/plasteel,
/area/centcom/control)
"vv" = (
/obj/machinery/computer/robotics,
/obj/machinery/computer/robotics{
dir = 1
},
/turf/simulated/floor/plasteel,
/area/centcom/control)
"vw" = (
/obj/machinery/computer/crew,
/obj/machinery/computer/crew{
dir = 1
},
/turf/simulated/floor/plasteel,
/area/centcom/control)
"vx" = (
@@ -6852,8 +6887,10 @@
/turf/simulated/floor/carpet,
/area/admin)
"wS" = (
/obj/machinery/computer/secure_data,
/obj/item/paper/sop,
/obj/machinery/computer/secure_data{
dir = 8
},
/turf/simulated/floor/carpet,
/area/admin)
"wT" = (
@@ -6881,11 +6918,15 @@
/turf/simulated/floor/carpet,
/area/admin)
"wY" = (
/obj/machinery/computer/communications,
/obj/machinery/computer/communications{
dir = 4
},
/turf/simulated/floor/carpet,
/area/admin)
"wZ" = (
/obj/machinery/computer/med_data,
/obj/machinery/computer/med_data{
dir = 8
},
/turf/simulated/floor/carpet,
/area/admin)
"xa" = (
@@ -7363,7 +7404,9 @@
},
/area/trader_station/sol)
"yJ" = (
/obj/machinery/computer/communications,
/obj/machinery/computer/communications{
dir = 1
},
/turf/simulated/floor/plasteel,
/area/admin)
"yK" = (
@@ -7380,7 +7423,9 @@
},
/area/trader_station/sol)
"yP" = (
/obj/machinery/computer/atmos_alert,
/obj/machinery/computer/atmos_alert{
dir = 1
},
/turf/simulated/floor/plasteel,
/area/admin)
"yQ" = (
@@ -7390,12 +7435,15 @@
},
/area/centcom/evac)
"yR" = (
/obj/machinery/computer/message_monitor,
/obj/item/paper/monitorkey,
/obj/machinery/computer/message_monitor{
dir = 1
},
/turf/simulated/floor/plasteel,
/area/admin)
"yS" = (
/obj/machinery/computer/account_database{
dir = 1;
name = "Admin Accounts Database"
},
/turf/simulated/floor/plasteel,
@@ -7407,7 +7455,9 @@
/turf/simulated/floor/plating,
/area/centcom/evac)
"yU" = (
/obj/machinery/computer/secure_data,
/obj/machinery/computer/secure_data{
dir = 1
},
/turf/simulated/floor/plasteel,
/area/admin)
"yV" = (
@@ -7452,7 +7502,9 @@
/turf/simulated/floor/plasteel,
/area/admin)
"zc" = (
/obj/machinery/computer/arcade,
/obj/machinery/computer/arcade{
dir = 8
},
/turf/simulated/floor/mineral/titanium/blue,
/area/centcom/evac)
"zd" = (
@@ -7473,7 +7525,9 @@
/turf/simulated/floor/plasteel/dark,
/area/admin)
"zh" = (
/obj/machinery/computer/card,
/obj/machinery/computer/card{
dir = 4
},
/turf/simulated/floor/mineral/plastitanium/red,
/area/centcom/evac)
"zi" = (
@@ -7944,7 +7998,9 @@
/turf/simulated/floor/plasteel,
/area/admin)
"AS" = (
/obj/machinery/computer/teleporter,
/obj/machinery/computer/teleporter{
dir = 1
},
/turf/simulated/floor/plasteel,
/area/admin)
"AT" = (
@@ -8000,11 +8056,15 @@
/turf/simulated/floor/plasteel/dark,
/area/syndicate_mothership)
"Bb" = (
/obj/machinery/computer/crew,
/obj/machinery/computer/crew{
dir = 4
},
/turf/simulated/floor/mineral/titanium/blue,
/area/centcom/evac)
"Bc" = (
/obj/machinery/computer/communications,
/obj/machinery/computer/communications{
dir = 8
},
/turf/simulated/floor/mineral/titanium/blue,
/area/centcom/evac)
"Bd" = (
@@ -8040,6 +8100,7 @@
/area/centcom/evac)
"Bj" = (
/obj/machinery/computer{
dir = 1;
name = "EMERGENCY SHUTTLE COMPUTER"
},
/turf/simulated/floor/mineral/titanium/blue,
@@ -8100,7 +8161,9 @@
/turf/simulated/floor/plasteel/dark,
/area/syndicate_mothership)
"Bv" = (
/obj/machinery/computer/camera_advanced,
/obj/machinery/computer/camera_advanced{
dir = 8
},
/turf/simulated/floor/plasteel/dark,
/area/syndicate_mothership)
"Bw" = (
@@ -8117,6 +8180,7 @@
/area/syndicate_mothership)
"By" = (
/obj/machinery/computer/shuttle/syndicate{
dir = 1;
name = "Nuclear Operatives Shuttle Console"
},
/turf/simulated/floor/plasteel/dark,
@@ -9000,7 +9064,9 @@
/turf/simulated/floor/mineral/titanium/blue,
/area/shuttle/supply)
"FJ" = (
/obj/machinery/computer/secure_data,
/obj/machinery/computer/secure_data{
dir = 4
},
/turf/simulated/floor/plasteel{
dir = 10;
icon_state = "darkred"
@@ -9043,7 +9109,9 @@
},
/area/shuttle/escape)
"Ga" = (
/obj/machinery/computer/shuttle/ert,
/obj/machinery/computer/shuttle/ert{
dir = 1
},
/turf/simulated/floor/plasteel/dark,
/area/centcom/specops)
"Gd" = (
@@ -9119,7 +9187,9 @@
/turf/simulated/wall/mineral/plastitanium,
/area/shuttle/syndicate_sit)
"GD" = (
/obj/machinery/computer/camera_advanced/shuttle_docker/syndicate/sst,
/obj/machinery/computer/camera_advanced/shuttle_docker/syndicate/sst{
dir = 1
},
/turf/simulated/floor/mineral/plastitanium/red,
/area/shuttle/syndicate_elite)
"GJ" = (
@@ -9376,10 +9446,12 @@
/turf/simulated/floor/plating,
/area/tdome/tdome2)
"Il" = (
/obj/machinery/computer/communications,
/obj/item/radio/intercom/specops{
pixel_y = -28
},
/obj/machinery/computer/communications{
dir = 1
},
/turf/simulated/floor/mineral/plastitanium/red,
/area/shuttle/specops)
"Io" = (
@@ -9622,7 +9694,9 @@
/turf/simulated/floor/mineral/plastitanium/red/nitrogen,
/area/shuttle/vox)
"JH" = (
/obj/machinery/computer/camera_advanced/shuttle_docker/syndicate/sit,
/obj/machinery/computer/camera_advanced/shuttle_docker/syndicate/sit{
dir = 1
},
/turf/simulated/floor/mineral/plastitanium/red,
/area/shuttle/syndicate_sit)
"JM" = (
@@ -9636,6 +9710,7 @@
/area/shuttle/administration)
"JO" = (
/obj/machinery/computer/security{
dir = 1;
network = list("SS13","Research Outpost","Mining Outpost")
},
/turf/simulated/floor/mineral/plastitanium/red,
@@ -10628,7 +10703,9 @@
},
/area/shuttle/escape)
"PU" = (
/obj/machinery/computer/shuttle/sit,
/obj/machinery/computer/shuttle/sit{
dir = 1
},
/turf/simulated/floor/mineral/plastitanium/red,
/area/shuttle/syndicate_sit)
"PX" = (
@@ -11190,12 +11267,13 @@
},
/area/holodeck/source_thunderdomecourt)
"TA" = (
/obj/machinery/computer/security{
network = list("SS13","Research Outpost","Mining Outpost","Telecomms")
},
/obj/structure/sign/poster/official/nanotrasen_logo{
pixel_x = -32
},
/obj/machinery/computer/security{
dir = 4;
network = list("SS13","Research Outpost","Mining Outpost","Telecomms")
},
/turf/simulated/floor/plasteel{
dir = 9;
icon_state = "darkred"
@@ -11379,7 +11457,9 @@
},
/area/holodeck/source_knightarena)
"UJ" = (
/obj/machinery/computer/shuttle/sst,
/obj/machinery/computer/shuttle/sst{
dir = 1
},
/turf/simulated/floor/mineral/plastitanium/red,
/area/shuttle/syndicate_elite)
"UK" = (
@@ -11495,6 +11575,7 @@
/area/shuttle/escape)
"Vr" = (
/obj/machinery/computer/camera_advanced/shuttle_docker/admin{
dir = 8;
name = "NTV Argos shuttle navigation computer"
},
/turf/simulated/floor/mineral/plastitanium/red,
@@ -11568,7 +11649,9 @@
},
/area/shuttle/escape)
"VS" = (
/obj/machinery/computer/atmos_alert,
/obj/machinery/computer/atmos_alert{
dir = 8
},
/turf/simulated/floor/plasteel{
dir = 6;
icon_state = "darkyellow"
@@ -11600,6 +11683,7 @@
/area/shuttle/vox)
"Wc" = (
/obj/machinery/computer/shuttle/admin{
dir = 8;
name = "NTV Argos shuttle console"
},
/turf/simulated/floor/mineral/plastitanium/red,
@@ -12043,7 +12127,6 @@
},
/area/shuttle/escape)
"YV" = (
/obj/machinery/computer/shuttle/trade/sol,
/obj/machinery/door_control{
id = "soltrader_south";
name = "Trade Deposits Door";
@@ -12057,6 +12140,9 @@
pixel_x = 24;
pixel_y = -8
},
/obj/machinery/computer/shuttle/trade/sol{
dir = 8
},
/turf/simulated/floor/mineral/titanium/blue,
/area/shuttle/trade/sol)
"YW" = (
+6 -6
View File
@@ -565,11 +565,11 @@
layer = 2.9
},
/obj/structure/rack,
/obj/item/gun/projectile/shotgun/riot/buckshot{
/obj/item/gun/projectile/shotgun/riot{
pixel_x = -3;
pixel_y = 3
},
/obj/item/gun/projectile/shotgun/riot/buckshot,
/obj/item/gun/projectile/shotgun/riot,
/turf/simulated/floor/mineral/plastitanium/red,
/area/shuttle/administration)
"Gx" = (
@@ -705,11 +705,11 @@
layer = 2.9
},
/obj/structure/rack,
/obj/item/gun/projectile/shotgun/riot/buckshot{
/obj/item/gun/projectile/shotgun/riot{
pixel_x = -3;
pixel_y = 3
},
/obj/item/gun/projectile/shotgun/riot/buckshot,
/obj/item/gun/projectile/shotgun/riot,
/turf/simulated/floor/mineral/plastitanium/red,
/area/shuttle/administration)
"Ns" = (
@@ -914,11 +914,11 @@
/obj/structure/window/reinforced{
dir = 4
},
/obj/item/gun/projectile/shotgun/riot/buckshot{
/obj/item/gun/projectile/shotgun/riot{
pixel_x = -3;
pixel_y = 3
},
/obj/item/gun/projectile/shotgun/riot/buckshot,
/obj/item/gun/projectile/shotgun/riot,
/turf/simulated/floor/mineral/plastitanium/red,
/area/shuttle/administration)
+2
View File
@@ -0,0 +1,2 @@
/// Version of RUST-G that this codebase wants
#define RUST_G_VERSION "0.5.0-P"
+2 -2
View File
@@ -66,8 +66,8 @@
#define ACCESS_PARAMEDIC 66
#define ACCESS_BLUESHIELD 67
#define ACCESS_SALVAGE_CAPTAIN 69 // Salvage ship captain's quarters
#define ACCESS_MECHANIC 70
#define ACCESS_PILOT 71
// #define ACCESS_MECHANIC 70 // AA07 2021-10-02 - Removed: Kept for history sake
// #define ACCESS_PILOT 71 // AA07 2021-10-02 - Removed: Kept for history sake
#define ACCESS_NTREP 73
#define ACCESS_MAGISTRATE 74
#define ACCESS_MINISAT 75
+9
View File
@@ -114,3 +114,12 @@
#define PIPE_COLOR_GREEN "#00ff00"
#define PIPE_COLOR_YELLOW "#ffcc00"
#define PIPE_COLOR_PURPLE "#5c1ec0"
///Main colors for UI themes
#define COLOR_THEME_MIDNIGHT "#6086A0"
#define COLOR_THEME_PLASMAFIRE "#FFB200"
#define COLOR_THEME_RETRO "#24CA00"
#define COLOR_THEME_SLIMECORE "#4FB259"
#define COLOR_THEME_OPERATIVE "#B8221F"
#define COLOR_THEME_GLASS "#75A4C4"
#define COLOR_THEME_CLOCKWORK "#CFBA47"
+23
View File
@@ -10,6 +10,18 @@
#define STAMINA "stamina"
#define BRAIN "brain"
//damage flags
#define MELEE "melee"
#define BULLET "bullet"
#define LASER "laser"
#define ENERGY "energy"
#define BOMB "bomb"
#define BIO "bio"
#define RAD "rad"
#define FIRE "fire"
#define ACID "acid"
#define MAGIC "magic"
#define STUN "stun"
#define WEAKEN "weaken"
#define PARALYZE "paralize"
@@ -112,6 +124,17 @@
#define WEAPON_MEDIUM 2
#define WEAPON_HEAVY 3
//His Grace.
#define HIS_GRACE_SATIATED 0 //He hungers not. If bloodthirst is set to this, His Grace is asleep.
#define HIS_GRACE_PECKISH 20 //Slightly hungry.
#define HIS_GRACE_HUNGRY 60 //Getting closer. Increases damage up to a minimum of 20.
#define HIS_GRACE_FAMISHED 100 //Dangerous. Increases damage up to a minimum of 25 and cannot be dropped.
#define HIS_GRACE_STARVING 120 //Incredibly close to breaking loose. Increases damage up to a minimum of 30.
#define HIS_GRACE_CONSUME_OWNER 140 //His Grace consumes His owner at this point and becomes aggressive.
#define HIS_GRACE_FALL_ASLEEP 160 //If it reaches this point, He falls asleep and resets.
#define HIS_GRACE_FORCE_BONUS 4 //How much force is gained per kill.
#define EXPLODE_NONE 0 //Don't even ask me why we need this.
#define EXPLODE_DEVASTATE 1
#define EXPLODE_HEAVY 2
+1
View File
@@ -103,6 +103,7 @@
#define PASSBLOB 8
#define PASSMOB 16
#define LETPASSTHROW 32
#define PASSFENCE 64
//turf-only flags
#define NOJAUNT 1
+15 -1
View File
@@ -7,12 +7,14 @@
#define FOOTSTEP_WATER "water"
#define FOOTSTEP_LAVA "lava"
#define FOOTSTEP_MEAT "meat"
#define FOOTSTEP_GLASS "glass"
//barefoot sounds
#define FOOTSTEP_WOOD_BAREFOOT "woodbarefoot"
#define FOOTSTEP_WOOD_CLAW "woodclaw"
#define FOOTSTEP_HARD_BAREFOOT "hardbarefoot"
#define FOOTSTEP_HARD_CLAW "hardclaw"
#define FOOTSTEP_CARPET_BAREFOOT "carpetbarefoot"
#define FOOTSTEP_GLASS_BAREFOOT "glassbarefoot"
//misc footstep sounds
#define FOOTSTEP_GENERIC_HEAVY "heavy"
@@ -83,7 +85,11 @@ GLOBAL_LIST_INIT(footstep, list(
'sound/effects/footstep/lava2.ogg',
'sound/effects/footstep/lava3.ogg'), 100, 0),
FOOTSTEP_MEAT = list(list(
'sound/effects/meatslap.ogg'), 100, 0)
'sound/effects/meatslap.ogg'), 100, 0),
FOOTSTEP_GLASS = list(list(
'sound/effects/footstep/glass1.ogg',
'sound/effects/footstep/glass2.ogg',
'sound/effects/footstep/glass3.ogg'), 100, 1),
))
//bare footsteps lists
GLOBAL_LIST_INIT(barefootstep, list(
@@ -127,6 +133,10 @@ GLOBAL_LIST_INIT(barefootstep, list(
'sound/effects/footstep/lava3.ogg'), 100, 0),
FOOTSTEP_MEAT = list(list(
'sound/effects/meatslap.ogg'), 100, 0),
FOOTSTEP_GLASS_BAREFOOT = list(list(
'sound/effects/footstep/glassbarefoot1.ogg',
'sound/effects/footstep/glassbarefoot2.ogg',
'sound/effects/footstep/glassbarefoot3.ogg'), 100, 1),
))
//claw footsteps lists
@@ -171,6 +181,10 @@ GLOBAL_LIST_INIT(clawfootstep, list(
'sound/effects/footstep/lava3.ogg'), 100, 0),
FOOTSTEP_MEAT = list(list(
'sound/effects/meatslap.ogg'), 100, 0),
FOOTSTEP_GLASS_BAREFOOT = list(list(
'sound/effects/footstep/glassbarefoot1.ogg',
'sound/effects/footstep/glassbarefoot2.ogg',
'sound/effects/footstep/glassbarefoot3.ogg'), 100, 1),
))
//heavy footsteps list
-1
View File
@@ -74,7 +74,6 @@
//Species traits.
#define NO_BLOOD "no_blood"
#define NOTRANSSTING "no_trans_sting"
#define IS_WHITELISTED "whitelisted"
#define LIPS "lips"
#define EXOTIC_COLOR "exotic_blood_color"
+4 -3
View File
@@ -25,8 +25,9 @@
#define PLANT_PEST_HUD "20"// Pest level
#define PLANT_WEED_HUD "21"// Weed level
#define DIAG_TRACK_HUD "22"// Mech tracking beacon
#define DIAG_PATH_HUD "23"//Bot path indicators
#define GLAND_HUD "24"//Gland indicators for abductors
#define DIAG_AIRLOCK_HUD "23" // Airlock shock overlay
#define DIAG_PATH_HUD "24"//Bot path indicators
#define GLAND_HUD "25"//Gland indicators for abductors
//by default everything in the hud_list of an atom is an image
//a value in hud_list with one of these will change that behavior
@@ -38,7 +39,7 @@
#define DATA_HUD_SECURITY_ADVANCED 2
#define DATA_HUD_MEDICAL_BASIC 3
#define DATA_HUD_MEDICAL_ADVANCED 4
#define DATA_HUD_DIAGNOSTIC 5
#define DATA_HUD_DIAGNOSTIC_BASIC 5
#define DATA_HUD_DIAGNOSTIC_ADVANCED 6
#define DATA_HUD_HYDROPONIC 7
//antag HUD defines
-2
View File
@@ -18,8 +18,6 @@
#define ismecha(A) (istype(A, /obj/mecha))
#define isspacepod(A) (istype(A, /obj/spacepod))
#define iseffect(A) (istype(A, /obj/effect))
#define isclothing(A) (istype(A, /obj/item/clothing))
+26 -25
View File
@@ -7,58 +7,59 @@
#define JOBCAT_ENGSEC (1<<0)
#define JOB_CAPTAIN (1<<0)
#define JOB_HOS (1<<1)
#define JOB_WARDEN (1<<2)
#define JOB_CAPTAIN (1<<0)
#define JOB_HOS (1<<1)
#define JOB_WARDEN (1<<2)
#define JOB_DETECTIVE (1<<3)
#define JOB_OFFICER (1<<4)
#define JOB_OFFICER (1<<4)
#define JOB_CHIEF (1<<5)
#define JOB_ENGINEER (1<<6)
#define JOB_ATMOSTECH (1<<7)
#define JOB_AI (1<<8)
#define JOB_CYBORG (1<<9)
#define JOB_CENTCOM (1<<10)
#define JOB_AI (1<<8)
#define JOB_CYBORG (1<<9)
#define JOB_CENTCOM (1<<10)
#define JOB_SYNDICATE (1<<11)
#define JOB_JUDGE (1<<12)
#define JOBCAT_MEDSCI (1<<1)
#define JOB_RD (1<<0)
#define JOB_RD (1<<0)
#define JOB_SCIENTIST (1<<1)
#define JOB_CHEMIST (1<<2)
#define JOB_CMO (1<<3)
#define JOB_DOCTOR (1<<4)
#define JOB_GENETICIST (1<<5)
#define JOB_VIROLOGIST (1<<6)
#define JOB_CHEMIST (1<<2)
#define JOB_CMO (1<<3)
#define JOB_DOCTOR (1<<4)
#define JOB_GENETICIST (1<<5)
#define JOB_VIROLOGIST (1<<6)
#define JOB_PSYCHIATRIST (1<<7)
#define JOB_ROBOTICIST (1<<8)
#define JOB_ROBOTICIST (1<<8)
#define JOB_PARAMEDIC (1<<9)
#define JOB_CORONER (1<<10)
#define JOB_CORONER (1<<10)
#define JOBCAT_SUPPORT (1<<2)
#define JOB_HOP (1<<0)
#define JOB_HOP (1<<0)
#define JOB_BARTENDER (1<<1)
#define JOB_BOTANIST (1<<2)
#define JOB_CHEF (1<<3)
#define JOB_JANITOR (1<<4)
#define JOB_JANITOR (1<<4)
#define JOB_LIBRARIAN (1<<5)
#define JOB_QUARTERMASTER (1<<6)
#define JOB_CARGOTECH (1<<7)
#define JOB_MINER (1<<8)
#define JOB_LAWYER (1<<9)
#define JOB_LAWYER (1<<9)
#define JOB_CHAPLAIN (1<<10)
#define JOB_CLOWN (1<<11)
#define JOB_MIME (1<<12)
#define JOB_CIVILIAN (1<<13)
#define JOB_EXPLORER (1<<14)
#define JOBCAT_KARMA (1<<3)
#define JOBCAT_KARMA (1<<3)
#define JOB_NANO (1<<0)
#define JOB_BLUESHIELD (1<<1)
#define JOB_BARBER (1<<3)
#define JOB_MECHANIC (1<<4)
#define JOB_BRIGDOC (1<<5)
#define JOB_JUDGE (1<<6)
#define JOB_PILOT (1<<7)
#define JOB_BLUESHIELD (1<<1)
#define JOB_BARBER (1<<3)
// #define JOB_MECHANIC (1<<4) // AA07 2021-10-02 - Removed: Kept for history sake
#define JOB_BRIGDOC (1<<5)
// #define JOB_JUDGE (1<<6) // AA07 2021-10-09 - Moved to ENGSEC (Non karma): Define kept for history sake
// #define JOB_PILOT (1<<7) // AA07 2021-10-02 - Removed: Kept for history sake
+2
View File
@@ -26,11 +26,13 @@
#define DISPOSAL_PIPE_LAYER 2.3
#define GAS_PIPE_HIDDEN_LAYER 2.35
#define WIRE_LAYER 2.4
#define TRANSPARENT_TURF_LAYER 2.41
#define WIRE_TERMINAL_LAYER 2.45
#define GAS_SCRUBBER_LAYER 2.46
#define GAS_PIPE_VISIBLE_LAYER 2.47
#define GAS_FILTER_LAYER 2.48
#define GAS_PUMP_LAYER 2.49
#define HOLOPAD_LAYER 2.491
#define CONVEYOR_LAYER 2.495
#define LOW_OBJ_LAYER 2.5
#define LOW_SIGIL_LAYER 2.52
+1 -1
View File
@@ -25,7 +25,7 @@
#define AUTOLATHE 4 //Uses glass/metal only.
#define CRAFTLATHE 8 //Uses fuck if I know. For use eventually.
#define MECHFAB 16 //Remember, objects utilising this flag should have construction_time and construction_cost vars.
#define PODFAB 32 //Used by the spacepod part fabricator. Same idea as the mechfab
// #define PODFAB 32 //Used by the spacepod part fabricator. Same idea as the mechfab // AA 2021-10-02 - Removed. Kept for flag consistency.
#define BIOGENERATOR 64 //Uses biomass
#define SMELTER 128 //uses various minerals
//Note: More then one of these can be added to a design but imprinter and lathe designs are incompatable.
+1 -1
View File
@@ -365,7 +365,7 @@
#define INVESTIGATE_BOMB "bombs"
// The SQL version required by this version of the code
#define SQL_VERSION 25
#define SQL_VERSION 27
// Vending machine stuff
#define CAT_NORMAL 1
+11 -2
View File
@@ -56,10 +56,11 @@
#define PREFTOGGLE_2_REVERB_DISABLE 512
#define PREFTOGGLE_2_FORCE_WHITE_RUNECHAT 1024
#define PREFTOGGLE_2_SIMPLE_STAT_PANEL 2048
#define PREFTOGGLE_2_SEE_ITEM_OUTLINES 4096
#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_TOTAL 8191 // 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)
#define TOGGLES_2_DEFAULT (PREFTOGGLE_2_FANCYUI|PREFTOGGLE_2_ITEMATTACK|PREFTOGGLE_2_WINDOWFLASHING|PREFTOGGLE_2_RUNECHAT|PREFTOGGLE_2_DEATHMESSAGE|PREFTOGGLE_2_EMOTE_BUBBLE|PREFTOGGLE_2_SEE_ITEM_OUTLINES)
// Sanity checks
#if TOGGLES_TOTAL > 16777215
@@ -114,3 +115,11 @@
#define _2FA_ENABLED_IP "ENABLED_IP"
/// Client will be prompted for 2FA always
#define _2FA_ENABLED_ALWAYS "ENABLED_ALWAYS"
#define MAX_SAVE_SLOTS 30 // Save slots for regular players
#define MAX_SAVE_SLOTS_MEMBER 30 // Save slots for BYOND members
#define TAB_CHAR 0
#define TAB_GAME 1
#define TAB_GEAR 2
+102 -41
View File
@@ -1,80 +1,130 @@
// rust_g.dm - DM API for rust_g extension library
//
// To configure, create a `rust_g.config.dm` and set what you care about from
// the following options:
//
// #define RUST_G "path/to/rust_g"
// Override the .dll/.so detection logic with a fixed path or with detection
// logic of your own.
//
// #define RUSTG_OVERRIDE_BUILTINS
// Enable replacement rust-g functions for certain builtins. Off by default.
#ifndef RUST_G
/// Locator for the RUSTG DLL or SO depending on system type. Override if needed.
#define RUST_G (world.system_type == UNIX ? "./librust_g.so" : "./rust_g.dll")
// Default automatic RUST_G detection.
// On Windows, looks in the standard places for `rust_g.dll`.
// On Linux, looks in `.`, `$LD_LIBRARY_PATH`, and `~/.byond/bin` for either of
// `librust_g.so` (preferred) or `rust_g` (old).
/* This comment bypasses grep checks */ /var/__rust_g
/proc/__detect_rust_g()
if (world.system_type == UNIX)
if (fexists("./librust_g.so"))
// No need for LD_LIBRARY_PATH badness.
return __rust_g = "./librust_g.so"
else if (fexists("./rust_g"))
// Old dumb filename.
return __rust_g = "./rust_g"
else if (fexists("[world.GetConfig("env", "HOME")]/.byond/bin/rust_g"))
// Old dumb filename in `~/.byond/bin`.
return __rust_g = "rust_g"
else
// It's not in the current directory, so try others
return __rust_g = "librust_g.so"
else
return __rust_g = "rust_g.dll"
#define RUST_G (__rust_g || __detect_rust_g())
#endif
// Gets the version of RUSTG
/// Gets the version of rust_g
/proc/rustg_get_version() return call(RUST_G, "get_version")()
// Defines for internal job subsystem //
#define RUSTG_JOB_NO_RESULTS_YET "NO RESULTS YET"
#define RUSTG_JOB_NO_SUCH_JOB "NO SUCH JOB"
#define RUSTG_JOB_ERROR "JOB PANICKED"
// Cellular Noise Operations //
// DMI related operations //
/**
* This proc generates a cellular automata noise grid which can be used in procedural generation methods.
*
* Returns a single string that goes row by row, with values of 1 representing an alive cell, and a value of 0 representing a dead cell.
*
* Arguments:
* * percentage: The chance of a turf starting closed
* * smoothing_iterations: The amount of iterations the cellular automata simulates before returning the results
* * birth_limit: If the number of neighboring cells is higher than this amount, a cell is born
* * death_limit: If the number of neighboring cells is lower than this amount, a cell dies
* * width: The width of the grid.
* * height: The height of the grid.
*/
#define rustg_cnoise_generate(percentage, smoothing_iterations, birth_limit, death_limit, width, height) \
call(RUST_G, "cnoise_generate")(percentage, smoothing_iterations, birth_limit, death_limit, width, height)
// DMI Operations //
#define rustg_dmi_strip_metadata(fname) call(RUST_G, "dmi_strip_metadata")(fname)
#define rustg_dmi_create_png(path, width, height, data) call(RUST_G, "dmi_create_png")(path, width, height, data)
#define rustg_dmi_resize_png(path, width, height, resizetype) call(RUST_G, "dmi_resize_png")(path, width, height, resizetype)
// Noise related operations //
#define rustg_noise_get_at_coordinates(seed, x, y) call(RUST_G, "noise_get_at_coordinates")(seed, x, y)
// File related operations //
// File Operations //
#define rustg_file_read(fname) call(RUST_G, "file_read")(fname)
#define rustg_file_exists(fname) call(RUST_G, "file_exists")(fname)
#define rustg_file_write(text, fname) call(RUST_G, "file_write")(text, fname)
#define rustg_file_append(text, fname) call(RUST_G, "file_append")(text, fname)
#ifdef RUSTG_OVERRIDE_BUILTINS
#define file2text(fname) rustg_file_read(fname)
#define text2file(text, fname) rustg_file_append(text, fname)
#define file2text(fname) rustg_file_read("[fname]")
#define text2file(text, fname) rustg_file_append(text, "[fname]")
#endif
// Git related operations //
// Git Operations //
#define rustg_git_revparse(rev) call(RUST_G, "rg_git_revparse")(rev)
#define rustg_git_commit_date(rev) call(RUST_G, "rg_git_commit_date")(rev)
// Hash related operations //
// Hashing Operations //
#define rustg_hash_string(algorithm, text) call(RUST_G, "hash_string")(algorithm, text)
#define rustg_hash_file(algorithm, fname) call(RUST_G, "hash_file")(algorithm, fname)
#define rustg_hash_generate_totp(seed) call(RUST_G, "generate_totp")(seed)
#define rustg_hash_generate_totp_tolerance(seed, tolerance) call(RUST_G, "generate_totp_tolerance")(seed, tolerance)
#define RUSTG_HASH_MD5 "md5"
#define RUSTG_HASH_SHA1 "sha1"
#define RUSTG_HASH_SHA256 "sha256"
#define RUSTG_HASH_SHA512 "sha512"
#define RUSTG_HASH_XXH64 "xxh64"
#define RUSTG_HASH_BASE64 "base64"
#ifdef RUSTG_OVERRIDE_BUILTINS
#define md5(thing) (isfile(thing) ? rustg_hash_file(RUSTG_HASH_MD5, "[thing]") : rustg_hash_string(RUSTG_HASH_MD5, thing))
#define md5(thing) (isfile(thing) ? rustg_hash_file(RUSTG_HASH_MD5, "[thing]") : rustg_hash_string(RUSTG_HASH_MD5, thing))
#endif
// Logging stuff //
#define rustg_log_write(fname, text) call(RUST_G, "log_write")(fname, text)
/proc/rustg_log_close_all() return call(RUST_G, "log_close_all")()
// URL encoding stuff
#define rustg_url_encode(text) call(RUST_G, "url_encode")(text)
#define rustg_url_decode(text) call(RUST_G, "url_decode")(text)
#ifdef RUSTG_OVERRIDE_BUILTINS
#define url_encode(text) rustg_url_encode(text)
#define url_decode(text) rustg_url_decode(text)
#endif
// HTTP library stuff //
// HTTP Operations //
#define RUSTG_HTTP_METHOD_GET "get"
#define RUSTG_HTTP_METHOD_PUT "put"
#define RUSTG_HTTP_METHOD_DELETE "delete"
#define RUSTG_HTTP_METHOD_PATCH "patch"
#define RUSTG_HTTP_METHOD_HEAD "head"
#define RUSTG_HTTP_METHOD_POST "post"
// Commented out because this thing locks up the entire DD process when you use it
// DO NOT USE FOR THE LOVE OF GOD
// #define rustg_http_request_blocking(method, url, body, headers) call(RUST_G, "http_request_blocking")(method, url, body, headers)
#define rustg_http_request_async(method, url, body, headers) call(RUST_G, "http_request_async")(method, url, body, headers)
#define rustg_http_request_blocking(method, url, body, headers, options) call(RUST_G, "http_request_blocking")(method, url, body, headers, options)
#define rustg_http_request_async(method, url, body, headers, options) call(RUST_G, "http_request_async")(method, url, body, headers, options)
#define rustg_http_check_request(req_id) call(RUST_G, "http_check_request")(req_id)
/proc/rustg_create_async_http_client() return call(RUST_G, "start_http_client")()
/proc/rustg_close_async_http_client() return call(RUST_G, "shutdown_http_client")()
// SQL stuff //
// Jobs Subsystem Operations //
#define RUSTG_JOB_NO_RESULTS_YET "NO RESULTS YET"
#define RUSTG_JOB_NO_SUCH_JOB "NO SUCH JOB"
#define RUSTG_JOB_ERROR "JOB PANICKED"
// JSON Operations //
#define rustg_json_is_valid(text) (call(RUST_G, "json_is_valid")(text) == "true")
// Logging Operations //
#define rustg_log_write(fname, text) call(RUST_G, "log_write")(fname, text)
/proc/rustg_log_close_all() return call(RUST_G, "log_close_all")()
// Noise Operations //
#define rustg_noise_get_at_coordinates(seed, x, y) call(RUST_G, "noise_get_at_coordinates")(seed, x, y)
// SQL Opeartions //
#define rustg_sql_connect_pool(options) call(RUST_G, "sql_connect_pool")(options)
#define rustg_sql_query_async(handle, query, params) call(RUST_G, "sql_query_async")(handle, query, params)
#define rustg_sql_query_blocking(handle, query, params) call(RUST_G, "sql_query_blocking")(handle, query, params)
@@ -82,8 +132,19 @@
#define rustg_sql_disconnect_pool(handle) call(RUST_G, "sql_disconnect_pool")(handle)
#define rustg_sql_check_query(job_id) call(RUST_G, "sql_check_query")("[job_id]")
// toml2json stuff //
#define rustg_toml2json(tomlfile) call(RUST_G, "toml2json")(tomlfile)
// TOML Operations //
#define rustg_read_toml_file(path) json_decode(call(RUST_G, "toml_file_to_json")(path) || "null")
// Unzip Operations //
#define rustg_unzip_download_async(url, unzip_directory) call(RUST_G, "unzip_download_async")(url, unzip_directory)
#define rustg_unzip_check(job_id) call(RUST_G, "unzip_check")("[job_id]")
// URL Encoder/Decoder Operations //
#define rustg_url_encode(text) call(RUST_G, "url_encode")("[text]")
#define rustg_url_decode(text) call(RUST_G, "url_decode")(text)
#ifdef RUSTG_OVERRIDE_BUILTINS
#define url_encode(text) rustg_url_encode(text)
#define url_decode(text) rustg_url_decode(text)
#endif
// RUSTG Version //
#define RUST_G_VERSION "0.4.5-P3"
+3 -2
View File
@@ -13,6 +13,8 @@
// BUFFS //
///////////
#define STATUS_EFFECT_HISGRACE /datum/status_effect/his_grace //His Grace.
#define STATUS_EFFECT_SHADOW_MEND /datum/status_effect/shadow_mend //Quick, powerful heal that deals damage afterwards. Heals 15 brute/burn every second for 3 seconds.
#define STATUS_EFFECT_VOID_PRICE /datum/status_effect/void_price //The price of healing yourself with void energy. Deals 3 brute damage every 3 seconds for 30 seconds.
#define STATUS_EFFECT_EXERCISED /datum/status_effect/exercised //Prevents heart disease
@@ -27,7 +29,6 @@
//#define STATUS_EFFECT_POWERREGEN /datum/status_effect/cyborg_power_regen //Regenerates power on a given cyborg over time
//#define STATUS_EFFECT_HISGRACE /datum/status_effect/his_grace //His Grace.
//#define STATUS_EFFECT_WISH_GRANTERS_GIFT /datum/status_effect/wish_granters_gift //If you're currently resurrecting with the Wish Granter
@@ -53,7 +54,7 @@
//#define MAX_MANIA_SEVERITY 100 //how high the mania severity can go
//#define MANIA_DAMAGE_TO_CONVERT 90 //how much damage is required before it'll convert affected targets
//#define STATUS_EFFECT_HISWRATH /datum/status_effect/his_wrath //His Wrath.
#define STATUS_EFFECT_HISWRATH /datum/status_effect/his_wrath //His Wrath.
#define STATUS_EFFECT_SUMMONEDGHOST /datum/status_effect/cultghost //is a cult ghost: can see dead people, can't manifest more ghosts
+18
View File
@@ -188,3 +188,21 @@
animate(A, transform = matrix(punchstr, MATRIX_ROTATE), pixel_y = 16, time = 2, color = "#eeeeee", easing = BOUNCE_EASING)
animate(transform = matrix(-punchstr, MATRIX_ROTATE), pixel_y = original_y, time = 2, color = "#ffffff", easing = BOUNCE_EASING)
animate(transform = null, time = 3, easing = BOUNCE_EASING)
/proc/animate_rumble(atom/A)
var/static/list/transforms
if(!transforms)
var/matrix/M1 = matrix()
var/matrix/M2 = matrix()
var/matrix/M3 = matrix()
var/matrix/M4 = matrix()
M1.Translate(-1, 0)
M2.Translate(0, 1)
M3.Translate(1, 0)
M4.Translate(0, -1)
transforms = list(M1, M2, M3, M4)
animate(A, transform = transforms[1], time = 0.2, loop = -1)
animate(transform = transforms[2], time = 0.1)
animate(transform = transforms[3], time = 0.2)
animate(transform = transforms[4], time = 0.3)
+3
View File
@@ -51,3 +51,6 @@
return A.plane - B.plane
else
return A.layer - B.layer
/proc/cmp_login_processor_priority(datum/client_login_processor/A, datum/client_login_processor/B)
return A.priority - B.priority
+11 -5
View File
@@ -77,13 +77,12 @@
for(var/geartype in subtypesof(/datum/gear))
var/datum/gear/G = geartype
var/use_name = initial(G.display_name)
var/use_category = initial(G.sort_category)
if(G == initial(G.subtype_path))
if(G == initial(G.main_typepath))
continue
if(!use_name)
if(!initial(G.display_name))
stack_trace("Loadout - Missing display name: [G]")
continue
if(!initial(G.cost))
@@ -96,8 +95,8 @@
if(!GLOB.loadout_categories[use_category])
GLOB.loadout_categories[use_category] = new /datum/loadout_category(use_category)
var/datum/loadout_category/LC = GLOB.loadout_categories[use_category]
GLOB.gear_datums[use_name] = new geartype
LC.gear[use_name] = GLOB.gear_datums[use_name]
GLOB.gear_datums[geartype] = new geartype
LC.gear[geartype] = GLOB.gear_datums[geartype]
GLOB.loadout_categories = sortAssoc(GLOB.loadout_categories)
for(var/loadout_category in GLOB.loadout_categories)
@@ -128,6 +127,13 @@
continue
GLOB.world_topic_handlers[wth.topic_key] = topic_handler_type
// Setup client login processors.
for(var/processor_type in subtypesof(/datum/client_login_processor))
var/datum/client_login_processor/CLP = new processor_type
GLOB.client_login_processors += CLP
// Sort them by priority, lowest first
sortTim(GLOB.client_login_processors, /proc/cmp_login_processor_priority)
/* // Uncomment to debug chemical reaction list.
/client/verb/debug_chemical_list()
+5 -2
View File
@@ -3,7 +3,7 @@
Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT
/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3)
/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3, parallel = TRUE)
if(!segments)
return
var/segment = 360/segments
@@ -19,7 +19,10 @@
speed /= segments
animate(src, transform = matrices[1], time = speed, loops)
if(parallel)
animate(src, transform = matrices[1], time = speed, loops , flags = ANIMATION_PARALLEL)
else
animate(src, transform = matrices[1], time = speed, loops)
for(var/i in 2 to segments) //2 because 1 is covered above
animate(transform = matrices[i], time = speed)
//doesn't have an object argument because this is "Stacking" with the animate call above
+14 -10
View File
@@ -272,15 +272,19 @@
update_all_mob_security_hud()
return 1
/*
Proc for attack log creation, because really why not
1 argument is the actor
2 argument is the target of action
3 is the full description of the action
4 is whether or not to message admins
This is always put in the attack log.
*/
/**
* Creates attack (old and new) logs for the user and defense logs for the target.
* Will message admins depending on the custom_level, user and target.
*
* custom_level will determine the log level set. Unless the target is SSD and there is a user doing it
* If custom_level is not set then the log level will be determined using the user and the target.
*
* * Arguments:
* * user - The thing doing it. Can be null
* * target - The target of the attack
* * what_done - What has happened
* * custom_level - The log level override
*/
/proc/add_attack_logs(atom/user, target, what_done, custom_level)
if(islist(target)) // Multi-victim adding
var/list/targets = target
@@ -323,7 +327,7 @@ This is always put in the attack log.
loglevel = ATKLOG_ALMOSTALL
else
loglevel = ATKLOG_ALL // Hitting an object. Not a mob
if(isLivingSSD(target)) // Attacks on SSDs are shown to admins with any log level except ATKLOG_NONE. Overrides custom level
if(user && isLivingSSD(target)) // Attacks on SSDs are shown to admins with any log level except ATKLOG_NONE. Overrides custom level
loglevel = ATKLOG_FEW
+4
View File
@@ -16,6 +16,10 @@
if(default) return default
if(List && List.len)return pick(List)
/proc/sanitize_json(json_input)
if(length(json_input) && istext(json_input))
return json_decode(json_input)
return list()
//more specialised stuff
+3
View File
@@ -164,6 +164,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_BLOODCRAWL_EAT "bloodcrawl_eat"
#define TRAIT_DWARF "dwarf"
#define TRAIT_SILENT_FOOTSTEPS "silent_footsteps" //makes your footsteps completely silent
#define TRAIT_MESON_VISION "meson_vision"
#define TRAIT_FLASH_PROTECTION "flash_protection"
#define TRAIT_NIGHT_VISION "night_vision"
#define TRAIT_COMIC_SANS "comic_sans"
#define TRAIT_NOFINGERPRINTS "no_fingerprints"
+12 -28
View File
@@ -464,12 +464,15 @@ Turf and target are seperate in case you want to teleport some distance from a t
if(GLOB.stealthminID[P] == txt)
return P
// Returns the atom sitting on the turf.
// For example, using this on a disk, which is in a bag, on a mob, will return the mob because it's on the turf.
/proc/get_atom_on_turf(atom/movable/M)
//Returns the atom sitting on the turf.
//For example, using this on a disk, which is in a bag, on a mob, will return the mob because it's on the turf.
//Optional arg 'type' to stop once it reaches a specific type instead of a turf.
/proc/get_atom_on_turf(atom/movable/M, stop_type)
var/atom/loc = M
while(loc && loc.loc && !istype(loc.loc, /turf/))
while(loc?.loc && !isturf(loc.loc))
loc = loc.loc
if(stop_type && istype(loc, stop_type))
break
return loc
/*
@@ -1536,7 +1539,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
shift.Translate(0,radius)
transform = shift
SpinAnimation(rotation_speed, -1, clockwise, rotation_segments)
SpinAnimation(rotation_speed, -1, clockwise, rotation_segments, parallel = FALSE)
while(orbiting && orbiting == A && A.loc)
var/targetloc = get_turf(A)
@@ -1551,7 +1554,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
if(orbiting == A) //make sure we haven't started orbiting something else.
orbiting = null
SpinAnimation(0, 0)
SpinAnimation(0, 0, parallel = FALSE)
transform = cached_transform
@@ -1774,8 +1777,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
/obj/item/robot_parts = "ROBOT_PARTS",
/obj/item/seeds = "SEED",
/obj/item/slime_extract = "SLIME_CORE",
/obj/item/spacepod_equipment/weaponry = "POD_WEAPON",
/obj/item/spacepod_equipment = "POD_EQUIP",
/obj/item/stack/sheet/mineral = "MINERAL",
/obj/item/stack/sheet = "SHEET",
/obj/item/stack/tile = "TILE",
@@ -1926,24 +1927,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
return pois
/proc/flash_color(mob_or_client, flash_color="#960000", flash_time=20)
var/client/C
if(istype(mob_or_client, /mob))
var/mob/M = mob_or_client
if(M.client)
C = M.client
else
return
else if(istype(mob_or_client, /client))
C = mob_or_client
if(!istype(C))
return
C.color = flash_color
spawn(0)
animate(C, color = initial(C.color), time = flash_time)
#define RANDOM_COLOUR (rgb(rand(0,255),rand(0,255),rand(0,255)))
/proc/make_bit_triplet()
@@ -2078,11 +2061,12 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
/proc/log_connection(ckey, ip, cid, connection_type)
ASSERT(connection_type in list(CONNECTION_TYPE_ESTABLISHED, CONNECTION_TYPE_DROPPED_IPINTEL, CONNECTION_TYPE_DROPPED_BANNED, CONNECTION_TYPE_DROPPED_INVALID))
var/datum/db_query/query_accesslog = SSdbcore.NewQuery("INSERT INTO connection_log (`datetime`, `ckey`, `ip`, `computerid`, `result`) VALUES(Now(), :ckey, :ip, :cid, :result)", list(
var/datum/db_query/query_accesslog = SSdbcore.NewQuery("INSERT INTO connection_log (`datetime`, `ckey`, `ip`, `computerid`, `result`, `server_id`) VALUES(Now(), :ckey, :ip, :cid, :result, :server_id)", list(
"ckey" = ckey,
"ip" = "[ip ? ip : ""]", // This is important. NULL is not the same as "", and if you directly open the `.dmb` file, you get a NULL IP.
"cid" = cid,
"result" = connection_type
"result" = connection_type,
"server_id" = GLOB.configuration.system.instance_id
))
query_accesslog.warn_execute()
qdel(query_accesslog)
+3 -3
View File
@@ -22,12 +22,12 @@
#define IS_MODE_COMPILED(MODE) (ispath(text2path("/datum/game_mode/"+(MODE))))
//Update this whenever you need to take advantage of more recent byond features
#define MIN_COMPILER_VERSION 513
#define MIN_COMPILER_BUILD 1514
#define MIN_COMPILER_VERSION 514
#define MIN_COMPILER_BUILD 1554
#if DM_VERSION < MIN_COMPILER_VERSION || DM_BUILD < MIN_COMPILER_BUILD
//Don't forget to update this part
#error Your version of BYOND is too out-of-date to compile this project. Go to https://secure.byond.com/download and update.
#error You need version 513.1514 or higher
#error You need version 514.1554 or higher
#endif
// Macros that must exist before world.dm
+3 -1
View File
@@ -5,7 +5,6 @@ GLOBAL_VAR_INIT(deafblock, 0)
GLOBAL_VAR_INIT(hulkblock, 0)
GLOBAL_VAR_INIT(teleblock, 0)
GLOBAL_VAR_INIT(fireblock, 0)
GLOBAL_VAR_INIT(xrayblock, 0)
GLOBAL_VAR_INIT(clumsyblock, 0)
GLOBAL_VAR_INIT(fakeblock, 0)
GLOBAL_VAR_INIT(coughblock, 0)
@@ -30,6 +29,9 @@ GLOBAL_VAR_INIT(hallucinationblock, 0)
GLOBAL_VAR_INIT(noprintsblock, 0)
GLOBAL_VAR_INIT(shockimmunityblock, 0)
GLOBAL_VAR_INIT(smallsizeblock, 0)
GLOBAL_VAR_INIT(mesonblock, 0)
GLOBAL_VAR_INIT(noflashblock, 0)
GLOBAL_VAR_INIT(nightvisionblock, 0)
///////////////////////////////
// Goon Stuff
+2
View File
@@ -56,3 +56,5 @@ GLOBAL_LIST_INIT(cooking_ingredients, list(RECIPE_MICROWAVE = list(), RECIPE_OVE
GLOBAL_LIST_INIT(cooking_reagents, list(RECIPE_MICROWAVE = list(), RECIPE_OVEN = list(), RECIPE_GRILL = list(), RECIPE_CANDY = list()))
#define EGG_LAYING_MESSAGES list("lays an egg.", "squats down and croons.", "begins making a huge racket.", "begins clucking raucously.")
GLOBAL_LIST_EMPTY(client_login_processors)
-1
View File
@@ -6,7 +6,6 @@ GLOBAL_LIST_INIT(landmarks_list, list()) //list of all landmarks created
GLOBAL_LIST_INIT(surgery_steps, list()) //list of all surgery steps |BS12
GLOBAL_LIST_INIT(side_effects, list()) //list of all medical sideeffects types by thier names |BS12
GLOBAL_LIST_INIT(mechas_list, list()) //list of all mechs. Used by hostile mobs target tracking.
GLOBAL_LIST_INIT(spacepods_list, list()) //list of all space pods. Used by hostile mobs target tracking.
GLOBAL_LIST_INIT(joblist, list()) //list of all jobstypes, minus borg and AI
GLOBAL_LIST_INIT(airlocks, list()) //list of all airlocks
GLOBAL_LIST_INIT(singularities, list()) //list of all singularities
+3
View File
@@ -46,6 +46,9 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_DWARF" = TRAIT_DWARF,
"TRAIT_SILENT_FOOTSTEPS" = TRAIT_SILENT_FOOTSTEPS,
"TRAIT_ALCOHOL_TOLERANCE" = TRAIT_ALCOHOL_TOLERANCE,
"TRAIT_MESON_VISION" = TRAIT_MESON_VISION,
"TRAIT_FLASH_PROTECTION" = TRAIT_FLASH_PROTECTION,
"TRAIT_NIGHT_VISION" = TRAIT_NIGHT_VISION,
"TRAIT_COMIC_SANS" = TRAIT_COMIC_SANS,
"TRAIT_NOFINGERPRINTS" = TRAIT_NOFINGERPRINTS,
+7
View File
@@ -622,6 +622,13 @@ so as to remain in compliance with the most up-to-date laws."
stone = null
return ..()
/obj/screen/alert/notify_mapvote
name = "Map Vote"
desc = "Vote on which map you would like to play on next!"
icon_state = "map_vote"
/obj/screen/alert/notify_mapvote/Click()
SSvote.browse_to(usr.client)
//OBJECT-BASED
+1 -1
View File
@@ -102,7 +102,7 @@
/obj/attacked_by(obj/item/I, mob/living/user)
if(I.force)
user.visible_message("<span class='danger'>[user] has hit [src] with [I]!</span>", "<span class='danger'>You hit [src] with [I]!</span>")
take_damage(I.force, I.damtype, "melee", 1)
take_damage(I.force, I.damtype, MELEE, 1)
/mob/living/attacked_by(obj/item/I, mob/living/user, def_zone)
send_item_attack_message(I, user)
@@ -46,6 +46,8 @@ GLOBAL_DATUM_INIT(configuration, /datum/server_configuration, new())
var/datum/configuration_section/url_configuration/url
/// Holder for the voting configuration datum
var/datum/configuration_section/vote_configuration/vote
/// Raw data. Stored here to avoid passing data between procs constantly
var/list/raw_data = list()
/datum/server_configuration/Destroy(force)
@@ -53,6 +55,16 @@ GLOBAL_DATUM_INIT(configuration, /datum/server_configuration, new())
// This is going to stay existing. I dont care.
return QDEL_HINT_LETMELIVE
/datum/server_configuration/vv_get_var(var_name)
if(var_name == "raw_data") // NO!
return FALSE
. = ..()
/datum/server_configuration/vv_edit_var(var_name, var_value)
if(var_name == "raw_data") // NO!
return FALSE
. = ..()
/datum/server_configuration/CanProcCall(procname)
return FALSE // No thanks
@@ -85,34 +97,66 @@ GLOBAL_DATUM_INIT(configuration, /datum/server_configuration, new())
var/config_file = "config/config.toml"
if(!fexists(config_file))
config_file = "config/example/config.toml" // Fallback to example if user hasnt setup config properly
var/raw_json = rustg_toml2json(config_file)
var/list/raw_config_data = json_decode(raw_json)
raw_data = rustg_read_toml_file(config_file)
// Now pass through all our stuff
admin.load_data(raw_config_data["admin_configuration"])
afk.load_data(raw_config_data["afk_configuration"])
custom_sprites.load_data(raw_config_data["custom_sprites_configuration"])
database.load_data(raw_config_data["database_configuration"])
discord.load_data(raw_config_data["discord_configuration"])
event.load_data(raw_config_data["event_configuration"])
gamemode.load_data(raw_config_data["gamemode_configuration"])
gateway.load_data(raw_config_data["gateway_configuration"])
general.load_data(raw_config_data["general_configuration"])
ipintel.load_data(raw_config_data["ipintel_configuration"])
jobs.load_data(raw_config_data["job_configuration"])
logging.load_data(raw_config_data["logging_configuration"])
mc.load_data(raw_config_data["mc_configuration"])
metrics.load_data(raw_config_data["metrics_configuration"])
movement.load_data(raw_config_data["movement_configuration"])
overflow.load_data(raw_config_data["overflow_configuration"])
ruins.load_data(raw_config_data["ruin_configuration"])
system.load_data(raw_config_data["system_configuration"])
url.load_data(raw_config_data["url_configuration"])
vote.load_data(raw_config_data["voting_configuration"])
load_all_sections()
// Clear our list to save RAM
raw_data = list()
// And report the load
DIRECT_OUTPUT(world.log, "Config loaded in [stop_watch(start)]s")
/datum/server_configuration/proc/load_all_sections()
safe_load(admin, "admin_configuration")
safe_load(afk, "afk_configuration")
safe_load(custom_sprites, "custom_sprites_configuration")
safe_load(database, "database_configuration")
safe_load(discord, "discord_configuration")
safe_load(event, "event_configuration")
safe_load(gamemode, "gamemode_configuration")
safe_load(gateway, "gateway_configuration")
safe_load(general, "general_configuration")
safe_load(ipintel, "ipintel_configuration")
safe_load(jobs, "job_configuration")
safe_load(logging, "logging_configuration")
safe_load(mc, "mc_configuration")
safe_load(metrics, "metrics_configuration")
safe_load(movement, "movement_configuration")
safe_load(overflow, "overflow_configuration")
safe_load(ruins, "ruin_configuration")
safe_load(system, "system_configuration")
safe_load(url, "url_configuration")
safe_load(vote, "voting_configuration")
// Proc to load up instance-specific overrides
/datum/server_configuration/proc/load_overrides()
var/override_file = "config/overrides_[world.port].toml"
if(!fexists(override_file))
DIRECT_OUTPUT(world.log, "Overrides not found for this instance.")
return
DIRECT_OUTPUT(world.log, "Overrides found for this instance. Loading them.")
var/start = start_watch() // Time tracking
raw_data = rustg_read_toml_file(override_file)
// Now safely load our overrides.
// Due to the nature of config wrappers, only vars that exist in the config file are applied to the config datums.
// This means that an override missing a key doesnt null it out from the main server
load_all_sections()
// Clear our list to save RAM
raw_data = list()
// And report the load
DIRECT_OUTPUT(world.log, "Config overrides loaded in [stop_watch(start)]s")
// Only loads the data for a config section if that key exists in the JSON
/datum/server_configuration/proc/safe_load(datum/configuration_section/CS, section)
if(!isnull(raw_data[section]))
CS.load_data(raw_data[section])
/datum/configuration_section
/// See __config_defines.dm
@@ -7,6 +7,8 @@
var/forward_all_ahelps = TRUE
/// Admin role to ping if no admins are online. Disables if empty string
var/admin_role_id = ""
/// Mentor role to ping if no mentors are online. Disables if empty string
var/mentor_role_id = ""
/// List of all URLs for the main webhooks
var/list/main_webhook_urls = list()
/// List of all URLs for the admin webhooks
@@ -21,6 +23,7 @@
CONFIG_LOAD_BOOL(webhooks_enabled, data["enable_discord_webhooks"])
CONFIG_LOAD_BOOL(forward_all_ahelps, data["forward_all_ahelps"])
CONFIG_LOAD_STR(admin_role_id, data["admin_role_id"])
CONFIG_LOAD_STR(mentor_role_id, data["mentor_role_id"])
CONFIG_LOAD_LIST(main_webhook_urls, data["main_webhook_urls"])
CONFIG_LOAD_LIST(mentor_webhook_urls, data["mentor_webhook_urls"])
CONFIG_LOAD_LIST(admin_webhook_urls, data["admin_webhook_urls"])
@@ -10,16 +10,23 @@
var/medal_hub_password = null
/// Do we want the server to kill on reboot instead of keeping the same DD session
var/shutdown_on_reboot = FALSE
/// Is this server a production server (Has higher security and requires 2FA)
var/is_production = FALSE
/// If above is true, you can run a shell command
var/shutdown_shell_command = null
/// 2FA backend server host
var/_2fa_auth_host = null
/// List of IP addresses which bypass world topic rate limiting
var/list/topic_ip_ratelimit_bypass = list()
/// Server instance ID
var/instance_id = "paradise_main"
/// Server internal IP
var/internal_ip = "127.0.0.1"
/datum/configuration_section/system_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_BOOL(shutdown_on_reboot, data["shutdown_on_reboot"])
CONFIG_LOAD_BOOL(is_production, data["is_production"])
CONFIG_LOAD_STR(topic_key, data["communications_password"])
CONFIG_LOAD_STR(medal_hub_address, data["medal_hub_address"])
@@ -28,3 +35,6 @@
CONFIG_LOAD_STR(_2fa_auth_host, data["_2fa_auth_host"])
CONFIG_LOAD_LIST(topic_ip_ratelimit_bypass, data["topic_ip_ratelimit_bypass"])
CONFIG_LOAD_STR(instance_id, data["instance_id"])
CONFIG_LOAD_STR(internal_ip, data["internal_ip"])
+1 -1
View File
@@ -62,7 +62,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
/// For scheduling different subsystems for different stages of the round
var/current_runlevel
/// Do we want to sleep until players log in?
var/sleep_offline_after_initializations = TRUE
var/sleep_offline_after_initializations = FALSE // No we dont
var/static/restart_clear = 0
var/static/restart_timeout = 0
+4 -3
View File
@@ -287,8 +287,8 @@ SUBSYSTEM_DEF(blackbox)
lakey = L.lastattackerckey
var/datum/db_query/deathquery = SSdbcore.NewQuery({"
INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord)
VALUES (:name, :key, :job, :special, :pod, NOW(), :laname, :lakey, :gender, :bruteloss, :fireloss, :brainloss, :oxyloss, :coord)"},
INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord, server_id)
VALUES (:name, :key, :job, :special, :pod, NOW(), :laname, :lakey, :gender, :bruteloss, :fireloss, :brainloss, :oxyloss, :coord, :server_id)"},
list(
"name" = L.real_name,
"key" = L.key,
@@ -302,7 +302,8 @@ SUBSYSTEM_DEF(blackbox)
"fireloss" = L.getFireLoss(),
"brainloss" = L.getBrainLoss(),
"oxyloss" = L.getOxyLoss(),
"coord" = "[L.x], [L.y], [L.z]"
"coord" = "[L.x], [L.y], [L.z]",
"server_id" = GLOB.configuration.system.instance_id
)
)
deathquery.warn_execute()
+2 -3
View File
@@ -54,9 +54,8 @@ SUBSYSTEM_DEF(changelog)
/datum/controller/subsystem/changelog/proc/UpdatePlayerChangelogDate(client/C)
if(!ss_ready)
return // Only return here, we dont have to worry about a queue list because this will be called from ShowChangelog()
// Technically this is only for the date but we can also do the UI button at the same time
var/datum/preferences/P = GLOB.preferences_datums[C.ckey]
if(P.toggles & PREFTOGGLE_UI_DARKMODE)
if(C.prefs.toggles & PREFTOGGLE_UI_DARKMODE)
winset(C, "rpane.changelog", "background-color=#40628a;font-color=#ffffff;font-style=none")
else
winset(C, "rpane.changelog", "background-color=none;font-style=none")
+2 -2
View File
@@ -160,8 +160,8 @@ SUBSYSTEM_DEF(dbcore)
if(!IsConnected())
return
var/datum/db_query/query_round_initialize = SSdbcore.NewQuery(
"INSERT INTO round (initialize_datetime, server_ip, server_port) VALUES (Now(), INET_ATON(:internet_address), :port)",
list("internet_address" = world.internet_address || "0", "port" = "[world.port]")
"INSERT INTO round (initialize_datetime, server_ip, server_port, server_id) VALUES (Now(), INET_ATON(:internet_address), :port, :server_id)",
list("internet_address" = world.internet_address || "0", "port" = "[world.port]", "server_id" = GLOB.configuration.system.instance_id)
)
query_round_initialize.Execute(async = FALSE)
GLOB.round_id = "[query_round_initialize.last_insert_id]"
+35 -2
View File
@@ -5,6 +5,8 @@ SUBSYSTEM_DEF(discord)
var/enabled = FALSE
/// Last time the administrator ping was dropped. This ensures administrators cannot be mass pinged if a large chunk of ahelps go off at once (IE: tesloose)
var/last_administration_ping = 0
/// Last time the mentor ping was dropped. This ensures mentors cannot be mass pinged if a large chunk of mhelps go off at once.
var/last_mentor_ping = 0
/datum/controller/subsystem/discord/Initialize(start_timeofday)
if(GLOB.configuration.discord.webhooks_enabled)
@@ -25,7 +27,7 @@ SUBSYSTEM_DEF(discord)
webhook_urls = GLOB.configuration.discord.mentor_webhook_urls
var/datum/discord_webhook_payload/dwp = new()
dwp.webhook_content = content
dwp.webhook_content = "**\[[GLOB.configuration.system.instance_id]]** [content]"
for(var/url in webhook_urls)
SShttp.create_async_request(RUSTG_HTTP_METHOD_POST, url, dwp.serialize2json(), list("content-type" = "application/json"))
@@ -71,10 +73,31 @@ SUBSYSTEM_DEF(discord)
var/message = "[content] [alerttext] [add_ping ? handle_administrator_ping() : ""]"
var/datum/discord_webhook_payload/dwp = new()
dwp.webhook_content = message
dwp.webhook_content = "**\[[GLOB.configuration.system.instance_id]]** [message]"
for(var/url in GLOB.configuration.discord.admin_webhook_urls)
SShttp.create_async_request(RUSTG_HTTP_METHOD_POST, url, dwp.serialize2json(), list("content-type" = "application/json"))
/datum/controller/subsystem/discord/proc/send2discord_simple_mentor(content)
var/alerttext
var/list/mentorcounter = staff_countup(R_MENTOR)
var/active_mentors = mentorcounter[1]
var/inactive_mentors = mentorcounter[3]
var/add_ping = FALSE
if(active_mentors <= 0)
add_ping = TRUE
if(inactive_mentors)
alerttext = "| **ALL MENTORS AFK**"
else
alerttext = "| **NO MENTORS ONLINE**"
var/message = "[content] [alerttext][add_ping ? handle_mentor_ping() : ""]"
var/datum/discord_webhook_payload/dwp = new()
dwp.webhook_content = "**\[[GLOB.configuration.system.instance_id]]** [message]"
for(var/url in GLOB.configuration.discord.mentor_webhook_urls)
SShttp.create_async_request(RUSTG_HTTP_METHOD_POST, url, dwp.serialize2json(), list("content-type" = "application/json"))
// Helper to make administrator ping easier
/datum/controller/subsystem/discord/proc/handle_administrator_ping()
// Check if a role is even set
@@ -86,3 +109,13 @@ SUBSYSTEM_DEF(discord)
return "<@&[GLOB.configuration.discord.admin_role_id]>"
return ""
/datum/controller/subsystem/discord/proc/handle_mentor_ping()
if(GLOB.configuration.discord.mentor_role_id)
if(last_mentor_ping > world.time)
return " *(Role pinged recently)*"
last_mentor_ping = world.time + 60 SECONDS
return " <@&[GLOB.configuration.discord.mentor_role_id]>"
return ""
+1 -1
View File
@@ -36,7 +36,7 @@ SUBSYSTEM_DEF(fires)
if(O.resistance_flags & ON_FIRE) //in case an object is extinguished while still in currentrun
if(!(O.resistance_flags & FIRE_PROOF))
O.take_damage(20, BURN, "fire", 0)
O.take_damage(20, BURN, FIRE, 0)
else
O.extinguish()
+184
View File
@@ -0,0 +1,184 @@
SUBSYSTEM_DEF(instancing)
name = "Instancing"
runlevels = RUNLEVEL_INIT | RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME
wait = 30 SECONDS
flags = SS_KEEP_TIMING
/datum/controller/subsystem/instancing/Initialize(start_timeofday)
// Dont even bother if we arent connected
if(!SSdbcore.IsConnected())
flags |= SS_NO_FIRE
return ..()
update_heartbeat() // Make sure you do this before announcing to peers, or no one will hear your announcement
var/startup_msg = "The server <code>[GLOB.configuration.general.server_name]</code> is now starting up. The map is [SSmapping.map_datum.fluff_name] ([SSmapping.map_datum.technical_name]). You can connect with the <code>Switch Server</code> verb."
message_all_peers(startup_msg)
return ..()
/datum/controller/subsystem/instancing/fire(resumed)
update_heartbeat()
update_playercache()
/**
* Playercache updater
*
* Updates the player cache in the DB. Different from heartbeat so we can force invoke it on player operations
*/
/datum/controller/subsystem/instancing/proc/update_playercache(optional_ckey)
// You may be wondering, why the fuck is an "optional ckey" variable here
// Well, this is invoked in client/New(), and needs to read from GLOB.clients
// However, this proc sleeps, and if you sleep during client/New() once the client is in GLOB.clients, stuff breaks bad
// (See my comment rambling in client/New())
// By passing the ckey through, we can sleep in this proc and still get the data
if(!SSdbcore.IsConnected())
return
// First iterate clients to get ckeys
var/list/ckeys = list()
for(var/client/C in GLOB.clients) // No code review. I am not doing the `as anything` bullshit, because we *do* need the type checks here to avoid null clients which do happen sometimes
ckeys += C.ckey
// Add our optional
if(optional_ckey)
ckeys += optional_ckey
// Note: We dont have to sort the list here. The only time this is read for is a search,
// and order doesnt matter for that.
var/ckey_json = json_encode(ckeys)
// Yes I care about performance savings this much here to mass execute this shit
var/list/datum/db_query/queries = list()
queries += SSdbcore.NewQuery("UPDATE instance_data_cache SET key_value=:json WHERE key_name='playerlist' AND server_id=:sid", list(
"json" = ckey_json,
"sid" = GLOB.configuration.system.instance_id
))
queries += SSdbcore.NewQuery("UPDATE instance_data_cache SET key_value=:count WHERE key_name='playercount' AND server_id=:sid", list(
"count" = length(ckeys),
"sid" = GLOB.configuration.system.instance_id
))
SSdbcore.MassExecute(queries, TRUE, TRUE, FALSE, FALSE)
/**
* Heartbeat updater
*
* Updates the heartbeat in the DB. Used so other servers can see when this one was alive
*/
/datum/controller/subsystem/instancing/proc/update_heartbeat()
// this could probably just go in fire() but clean code and profiler ease who cares
var/datum/db_query/dbq = SSdbcore.NewQuery("UPDATE instance_data_cache SET key_value=NOW() WHERE key_name='heartbeat' AND server_id=:sid", list(
"sid" = GLOB.configuration.system.instance_id
))
dbq.warn_execute()
qdel(dbq)
/**
* Seed data
*
* Seeds all our data into the DB for other servers to discover from.
* This is called during world/New() instead of on initialize so it can be done *instantly*
*/
/datum/controller/subsystem/instancing/proc/seed_data()
// We need to seed a lot of keys, so lets just use a key-value-pair-map to do this easily
var/list/kvp_map = list()
kvp_map["server_name"] = GLOB.configuration.general.server_name // Name of the server
kvp_map["server_port"] = world.port // Server port (used for redirection and topics)
kvp_map["topic_key"] = GLOB.configuration.system.topic_key // Server topic key (used for topics)
kvp_map["internal_ip"] = GLOB.configuration.system.internal_ip // Server internal IP (used for topics)
kvp_map["playercount"] = length(GLOB.clients) // Server client count (used for status info)
kvp_map["playerlist"] = json_encode(list()) // Server client list. Used for dupe login checks. This gets filled in later
kvp_map["heartbeat"] = SQLtime() // SQL timestamp for heartbeat purposes. Any server without a heartbeat in the last 60 seconds can be considered dead
// Also note for above. You may say "But AA you dont need to JSON encode it, just use "\[]"."
// Well to that I say, no. This is meant to be JSON regardless, and it should represent that. This proc is ran once during world/New()
// An extra nanosecond of load will make zero difference.
for(var/key in kvp_map)
var/datum/db_query/dbq = SSdbcore.NewQuery("INSERT INTO instance_data_cache (server_id, key_name, key_value) VALUES (:sid, :kn, :kv) ON DUPLICATE KEY UPDATE key_value=:kv2", // Is this necessary? Who knows!
list(
"sid" = GLOB.configuration.system.instance_id,
"kn" = key,
"kv" = "[kvp_map[key]]", // String encoding IS necessary since these tables use strings, not ints
"kv2" = "[kvp_map[key]]", // Dont know if I need the second but better to be safe
)
)
dbq.warn_execute(FALSE) // Do NOT async execute here because world/New() shouldnt sleep. EVER. You get issues if you do.
qdel(dbq)
/**
* Message all peers
*
* Wrapper for [topic_all_peers] to format the input into a message topic. Will send a server-wide announcement to the other servers
*
* Arguments:
* * message - Message to send to the other servers
*/
/datum/controller/subsystem/instancing/proc/message_all_peers(message)
if(!SSdbcore.IsConnected())
return
var/topic_string = "instance_announce&msg=[url_encode(message)]"
topic_all_peers(topic_string)
/**
* Sends a topic to all peers
*
* Sends a raw topic to the other servers. WILL APPEND &key=[commskey] ON THE END. PLEASE ACCOUNT FOR THIS.
*
* Arguments:
* * raw_topic - The raw topic to send to the other servers
*/
/datum/controller/subsystem/instancing/proc/topic_all_peers(raw_topic)
// Someone here is going to say "AA you shouldnt put load on the DB server you can do sorting in BYOND"
// Well let me put it this way. The DB server is an entirely different machine to BYOND, with this entire dataset being stored in its RAM, not even on disk
// By making the DB server do the work, we can offload from BYOND, which is already strained
var/datum/db_query/dbq1 = SSdbcore.NewQuery({"
SELECT server_id, key_name, key_value FROM instance_data_cache WHERE server_id IN
(SELECT server_id FROM instance_data_cache WHERE server_id !=:sid AND
key_name='heartbeat' AND last_updated BETWEEN NOW() - INTERVAL 60 SECOND AND NOW())
AND key_name IN ("topic_key", "internal_ip", "server_port")"}, list(
"sid" = GLOB.configuration.system.instance_id
))
if(!dbq1.warn_execute())
qdel(dbq1)
return
var/servers_outer = list()
while(dbq1.NextRow())
if(!servers_outer[dbq1.item[1]])
servers_outer[dbq1.item[1]] = list()
servers_outer[dbq1.item[1]][dbq1.item[2]] = dbq1.item[3] // This should assoc load our data
qdel(dbq1)
for(var/server in servers_outer)
var/server_data = servers_outer[server]
world.Export("byond://[server_data["internal_ip"]]:[server_data["server_port"]]?[raw_topic]&key=[server_data["topic_key"]]")
/**
* Player checker
*
* Check all connected peers to see if a player exists in the player cache
* This is used to make sure players dont log into 2 servers at once
* Arguments:
* ckey - The ckey to check if they are logged into another server
*/
/datum/controller/subsystem/instancing/proc/check_player(ckey)
// Please see above rant on L127
var/datum/db_query/dbq1 = SSdbcore.NewQuery({"
SELECT server_id, key_value FROM instance_data_cache WHERE server_id IN
(SELECT server_id FROM instance_data_cache WHERE server_id != :sid AND
key_name='heartbeat' AND last_updated BETWEEN NOW() - INTERVAL 60 SECOND AND NOW())
AND key_name IN ("playerlist")"}, list(
"sid" = GLOB.configuration.system.instance_id
))
if(!dbq1.warn_execute())
qdel(dbq1)
return
while(dbq1.NextRow())
var/list/other_server_cache = json_decode(dbq1.item[2])
if(ckey in other_server_cache)
var/target_server = dbq1.item[1] // Yes. This var is necessary.
qdel(dbq1)
return target_server
qdel(dbq1)
return null // If we are here, it means we didnt find our player on another server
+12 -12
View File
@@ -65,7 +65,7 @@ SUBSYSTEM_DEF(jobs)
return type_occupations[jobtype]
/datum/controller/subsystem/jobs/proc/GetPlayerAltTitle(mob/new_player/player, rank)
return player.client.prefs.GetPlayerAltTitle(GetJob(rank))
return player.client.prefs.active_character.GetPlayerAltTitle(GetJob(rank))
/datum/controller/subsystem/jobs/proc/AssignRole(mob/new_player/player, rank, latejoin = 0)
Debug("Running AR, Player: [player], Rank: [rank], LJ: [latejoin]")
@@ -121,7 +121,7 @@ SUBSYSTEM_DEF(jobs)
Debug("Running FOC, Job: [job], Level: [level], Flag: [flag]")
var/list/candidates = list()
for(var/mob/new_player/player in unassigned)
Debug(" - Player: [player] Banned: [jobban_isbanned(player, job.title)] Old Enough: [!job.player_old_enough(player.client)] AvInPlaytime: [job.available_in_playtime(player.client)] Flag && Be Special: [flag] && [player.client.prefs.be_special] Job Department: [player.client.prefs.GetJobDepartment(job, level)] Job Flag: [job.flag] Job Department Flag = [job.department_flag]")
Debug(" - Player: [player] Banned: [jobban_isbanned(player, job.title)] Old Enough: [!job.player_old_enough(player.client)] AvInPlaytime: [job.available_in_playtime(player.client)] Flag && Be Special: [flag] && [player.client.prefs.be_special] Job Department: [player.client.prefs.active_character.GetJobDepartment(job, level)] Job Flag: [job.flag] Job Department Flag = [job.department_flag]")
if(jobban_isbanned(player, job.title))
Debug("FOC isbanned failed, Player: [player]")
continue
@@ -140,7 +140,7 @@ SUBSYSTEM_DEF(jobs)
if(player.mind && (job.title in player.mind.restricted_roles))
Debug("FOC incompatbile with antagonist role, Player: [player]")
continue
if(player.client.prefs.GetJobDepartment(job, level) & job.flag)
if(player.client.prefs.active_character.GetJobDepartment(job, level) & job.flag)
Debug("FOC pass, Player: [player], Level:[level]")
candidates += player
return candidates
@@ -367,12 +367,12 @@ SUBSYSTEM_DEF(jobs)
continue
// If the player wants that job on this level, then try give it to him.
if(player.client.prefs.GetJobDepartment(job, level) & job.flag)
if(player.client.prefs.active_character.GetJobDepartment(job, level) & job.flag)
// If the job isn't filled
if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1)
Debug("DO pass, Player: [player], Level:[level], Job:[job.title]")
Debug(" - Job Flag: [job.flag] Job Department: [player.client.prefs.GetJobDepartment(job, level)] Job Current Pos: [job.current_positions] Job Spawn Positions = [job.spawn_positions]")
Debug(" - Job Flag: [job.flag] Job Department: [player.client.prefs.active_character.GetJobDepartment(job, level)] Job Current Pos: [job.current_positions] Job Spawn Positions = [job.spawn_positions]")
AssignRole(player, job.title)
unassigned -= player
break
@@ -380,7 +380,7 @@ SUBSYSTEM_DEF(jobs)
// Hand out random jobs to the people who didn't get any in the last check
// Also makes sure that they got their preference correct
for(var/mob/new_player/player in unassigned)
if(player.client.prefs.alternate_option == GET_RANDOM_JOB)
if(player.client.prefs.active_character.alternate_option == GET_RANDOM_JOB)
GiveRandomJob(player)
Debug("DO, Standard Check end")
@@ -390,7 +390,7 @@ SUBSYSTEM_DEF(jobs)
// Antags, who have to get in, come first
for(var/mob/new_player/player in unassigned)
if(player.mind.special_role)
if(player.client.prefs.alternate_option != BE_ASSISTANT)
if(player.client.prefs.active_character.alternate_option != BE_ASSISTANT)
GiveRandomJob(player)
if(player in unassigned)
AssignRole(player, "Civilian")
@@ -399,10 +399,10 @@ SUBSYSTEM_DEF(jobs)
// Then we assign what we can to everyone else.
for(var/mob/new_player/player in unassigned)
if(player.client.prefs.alternate_option == BE_ASSISTANT)
if(player.client.prefs.active_character.alternate_option == BE_ASSISTANT)
Debug("AC2 Assistant located, Player: [player]")
AssignRole(player, "Civilian")
else if(player.client.prefs.alternate_option == RETURN_TO_LOBBY)
else if(player.client.prefs.active_character.alternate_option == RETURN_TO_LOBBY)
player.ready = 0
unassigned -= player
@@ -564,11 +564,11 @@ SUBSYSTEM_DEF(jobs)
if(job.barred_by_disability(player.client))
disabled++
continue
if(player.client.prefs.GetJobDepartment(job, 1) & job.flag)
if(player.client.prefs.active_character.GetJobDepartment(job, 1) & job.flag)
high++
else if(player.client.prefs.GetJobDepartment(job, 2) & job.flag)
else if(player.client.prefs.active_character.GetJobDepartment(job, 2) & job.flag)
medium++
else if(player.client.prefs.GetJobDepartment(job, 3) & job.flag)
else if(player.client.prefs.active_character.GetJobDepartment(job, 3) & job.flag)
low++
else never++ //not selected
+9
View File
@@ -10,6 +10,8 @@ SUBSYSTEM_DEF(mapping)
var/list/teleportlocs
/// List of all areas that can be accessed via IC and OOC means
var/list/ghostteleportlocs
///List of areas that exist on the station this shift
var/list/existing_station_areas
// This has to be here because world/New() uses [station_name()], which looks this datum up
/datum/controller/subsystem/mapping/PreInit()
@@ -89,6 +91,13 @@ SUBSYSTEM_DEF(mapping)
ghostteleportlocs = sortAssoc(ghostteleportlocs)
// Now we make a list of areas that exist on the station. Good for if you don't want to select areas that exist for one station but not others. Directly references
existing_station_areas = list()
for(var/area/AR in world)
var/turf/picked = safepick(get_area_turfs(AR.type))
if(picked && is_station_level(picked.z))
existing_station_areas += AR
// World name
if(GLOB.configuration.general.server_name)
world.name = "[GLOB.configuration.general.server_name]: [station_name()]"
+2 -1
View File
@@ -23,11 +23,12 @@ SUBSYSTEM_DEF(metrics)
var/list/out = list()
out["@timestamp"] = time_stamp() // This is required by ElasticSearch, complete with this name. DO NOT REMOVE THIS.
out["cpu"] = world.cpu
// out["maptick"] = world.map_cpu // TODO: 514
out["maptick"] = world.map_cpu
out["elapsed_processed"] = world.time
out["elapsed_real"] = (REALTIMEOFDAY - world_init_time)
out["client_count"] = length(GLOB.clients)
out["round_id"] = text2num(GLOB.round_id) // This is so we can filter the metrics by a single round ID
out["server_id"] = GLOB.configuration.system.instance_id // And this is so we can filter by instance ID
// Funnel in all SS metrics
var/list/ss_data = list()
+3 -2
View File
@@ -18,10 +18,11 @@ SUBSYSTEM_DEF(statistics)
return
else
var/datum/db_query/statquery = SSdbcore.NewQuery(
"INSERT INTO legacy_population (playercount, admincount, time) VALUES (:playercount, :admincount, NOW())",
"INSERT INTO legacy_population (playercount, admincount, time, server_id) VALUES (:playercount, :admincount, NOW(), :server_id)",
list(
"playercount" = length(GLOB.clients),
"admincount" = length(GLOB.admins)
"admincount" = length(GLOB.admins),
"server_id" = GLOB.configuration.system.instance_id
)
)
statquery.warn_execute()
+55 -2
View File
@@ -287,7 +287,7 @@ SUBSYSTEM_DEF(ticker)
else
log_debug("Playercount: [playercount] versus trigger: [highpop_trigger] - keeping standard job config")
SSnightshift.check_nightshift()
SSnightshift.check_nightshift(TRUE)
#ifdef UNIT_TESTS
RunUnitTests()
@@ -408,12 +408,65 @@ SUBSYSTEM_DEF(ticker)
if(player.mind.assigned_role != player.mind.special_role)
SSjobs.AssignRank(player, player.mind.assigned_role, FALSE)
SSjobs.EquipRank(player, player.mind.assigned_role, FALSE)
EquipCustomItems(player)
equip_cuis(player)
if(captainless)
for(var/mob/M in GLOB.player_list)
if(!isnewplayer(M))
to_chat(M, "Captainship not forced on anyone.")
/datum/controller/subsystem/ticker/proc/equip_cuis(mob/living/carbon/human/H)
if(!H.client)
return // If they are spawning without a client (somehow), they *cant* have a CUI list
for(var/datum/custom_user_item/cui in H.client.cui_entries)
// Skip items with invalid character names
if((cui.characer_name != H.real_name) && !cui.all_characters_allowed)
continue
var/ok = FALSE
if(!cui.all_jobs_allowed)
var/alt_blocked = FALSE
if(H.mind.role_alt_title)
if(!(H.mind.role_alt_title in cui.allowed_jobs))
alt_blocked = TRUE
if(!(H.mind.assigned_role in cui.allowed_jobs) || alt_blocked)
continue
var/obj/item/I = new cui.object_typepath()
var/name_override = cui.item_name_override
var/desc_override = cui.item_desc_override
if(name_override)
I.name = name_override
if(desc_override)
I.desc = desc_override
if(istype(H.back, /obj/item/storage)) // Try to place it in something on the mob's back
var/obj/item/storage/S = H.back
if(length(S.contents) < S.storage_slots)
I.forceMove(H.back)
ok = TRUE
to_chat(H, "<span class='notice'>Your [I.name] has been added to your [H.back.name].</span>")
if(!ok)
for(var/obj/item/storage/S in H.contents) // Try to place it in any item that can store stuff, on the mob.
if(length(S.contents) < S.storage_slots)
I.forceMove(S)
ok = TRUE
to_chat(H, "<span class='notice'>Your [I.name] has been added to your [S.name].</span>")
break
if(!ok) // Finally, since everything else failed, place it on the ground
var/turf/T = get_turf(H)
if(T)
I.forceMove(T)
to_chat(H, "<span class='notice'>Your [I.name] is on the [T.name] below you.</span>")
else
to_chat(H, "<span class='notice'>Your [I.name] couldnt spawn anywhere on you or even on the floor below you. Please file a bug report.</span>")
qdel(I)
/datum/controller/subsystem/ticker/proc/send_tip_of_the_round()
var/m
if(selected_tip)
+6 -2
View File
@@ -209,7 +209,7 @@ SUBSYSTEM_DEF(vote)
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, code_invoked = FALSE)
if(!mode)
if(started_time != null && !check_rights(R_ADMIN))
if(usr && started_time != null && !check_rights(R_ADMIN)) // Allow the game to call votes whenever. But check other callers
var/next_allowed_time = (started_time + GLOB.configuration.vote.vote_delay)
if(next_allowed_time > world.time)
return 0
@@ -266,8 +266,12 @@ SUBSYSTEM_DEF(vote)
<a href='?src=[UID()];vote=open'>Click here or type vote to place your vote.</a>
You have [GLOB.configuration.vote.vote_time / 10] seconds to vote.</font>"})
switch(vote_type)
if("crew transfer", "gamemode", "custom", "map")
if("crew transfer", "gamemode", "custom")
SEND_SOUND(world, sound('sound/ambience/alarm4.ogg'))
if("map")
SEND_SOUND(world, sound('sound/ambience/alarm4.ogg'))
for(var/mob/M in GLOB.player_list)
M.throw_alert("Map Vote", /obj/screen/alert/notify_mapvote, timeout_override = GLOB.configuration.vote.vote_time)
if(mode == "gamemode" && SSticker.ticker_going)
SSticker.ticker_going = FALSE
to_chat(world, "<font color='red'><b>Round start has been delayed.</b></font>")
+7
View File
@@ -423,6 +423,13 @@
/datum/action/item_action/remove_badge
name = "Remove Holobadge"
// Clown Acrobat Shoes
/datum/action/item_action/slipping
name = "Tactical Slip"
desc = "Activates the clown shoes' ankle-stimulating module, allowing the user to do a short slip forward going under anyone."
button_icon_state = "clown"
// Jump boots
/datum/action/item_action/bhop
name = "Activate Jump Boots"
+1 -1
View File
@@ -52,7 +52,7 @@
return vars[rating]
/datum/armor/proc/getList()
return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic)
return list(MELEE = melee, BULLET = bullet, LASER = laser, ENERGY = energy, BOMB = bomb, BIO = bio, RAD = rad, FIRE = fire, ACID = acid, MAGIC = magic)
/datum/armor/proc/attachArmor(datum/armor/AA)
return getArmor(melee + AA.melee, bullet + AA.bullet, laser + AA.laser, energy + AA.energy, bomb + AA.bomb, bio + AA.bio, rad + AA.rad, fire + AA.fire, acid + AA.acid, magic + AA.magic)
+1 -1
View File
@@ -57,7 +57,7 @@ GLOBAL_DATUM_INIT(crew_repository, /datum/repository/crew, new())
if(C.sensor_mode >= SUIT_SENSOR_TRACKING)
var/area/A = get_area(H)
crewmemberData["area"] = sanitize(A.name)
crewmemberData["area"] = sanitize_simple(A.name)
crewmemberData["x"] = pos.x
crewmemberData["y"] = pos.y
@@ -49,6 +49,10 @@
var/mat_path = possible_mats[id]
materials[id] = new mat_path()
/datum/component/material_container/Destroy(force, silent)
QDEL_LIST_ASSOC_VAL(materials)
return ..()
/datum/component/material_container/proc/OnExamine(datum/source, mob/user, list/examine_list)
if(show_on_examine)
for(var/I in materials)
+66
View File
@@ -0,0 +1,66 @@
/**
* # Custom User Item
*
* Holder for CUIs
*
* This datum is a holder that is essentially a "model" of the `customuseritems`
* database table, and is used for giving people their CUIs on spawn.
* It is instanced as part of the client data loading framework on the client.
*
*/
/datum/custom_user_item
/// Can this be used on all characters?
var/all_characters_allowed = FALSE
/// Name of the character that can have this item.
var/characer_name
/// Are all jobs allowed?
var/all_jobs_allowed = FALSE
/// List of allowed jobs
var/list/allowed_jobs = list()
/// Custom item typepath
var/object_typepath
/// Custom item name override
var/item_name_override
/// Custom item description override
var/item_desc_override
/// Raw job mask
var/raw_job_mask
/**
* CUI Info Parser
*
* Parses all the raw info into usable stuff, and also does validity checks
* Returns TRUE if its a valid item, and FALSE if not
*
* Arguments:
* * owning_ckey - Player who owns this item. Used for logging purposes.
*/
/datum/custom_user_item/proc/parse_info(owning_ckey)
. = FALSE // Setting this here means it will return false even if it runtimes
// Sort path
if(!object_typepath || !ispath(object_typepath))
stack_trace("Incorrect database entry found in table 'customuseritems' path value is [object_typepath ? object_typepath : "(NULL)"], which doesnt exist. Ask the host to look at CUI entries for [owning_ckey]")
return
// Sort job mask
if(raw_job_mask == "*")
all_jobs_allowed = TRUE
else
var/list/local_allowed_jobs = splittext(raw_job_mask, ",")
for(var/i in 1 to length(local_allowed_jobs))
if(istext(local_allowed_jobs[i]))
local_allowed_jobs[i] = trim(local_allowed_jobs[i])
allowed_jobs = local_allowed_jobs
// Sort character name
if(characer_name == "*")
all_characters_allowed = TRUE
return TRUE
/datum/custom_user_item/vv_edit_var(var_name, var_value)
return FALSE // fuck off
-8
View File
@@ -461,10 +461,6 @@ GLOBAL_VAR_INIT(record_id_num, 1001)
clothes_s = new /icon('icons/mob/clothing/uniform.dmi', "detective_s")
clothes_s.Blend(new /icon('icons/mob/clothing/feet.dmi', "brown"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/clothing/suit.dmi', "detective"), ICON_OVERLAY)
if("Security Pod Pilot")
clothes_s = new /icon('icons/mob/clothing/uniform.dmi', "secred_s")
clothes_s.Blend(new /icon('icons/mob/clothing/feet.dmi', "jackboots"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/clothing/suit.dmi', "bomber"), ICON_OVERLAY)
if("Brig Physician")
clothes_s = new /icon('icons/mob/clothing/uniform.dmi', "medical_s")
clothes_s.Blend(new /icon('icons/mob/clothing/feet.dmi', "white"), ICON_UNDERLAY)
@@ -484,10 +480,6 @@ GLOBAL_VAR_INIT(record_id_num, 1001)
clothes_s = new /icon('icons/mob/clothing/uniform.dmi', "atmos_s")
clothes_s.Blend(new /icon('icons/mob/clothing/feet.dmi', "black"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/clothing/belt.dmi', "utility"), ICON_OVERLAY)
if("Mechanic")
clothes_s = new /icon('icons/mob/clothing/uniform.dmi', "mechanic_s")
clothes_s.Blend(new /icon('icons/mob/clothing/feet.dmi', "orange"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/clothing/belt.dmi', "utility"), ICON_OVERLAY)
if("Roboticist")
clothes_s = new /icon('icons/mob/clothing/uniform.dmi', "robotics_s")
clothes_s.Blend(new /icon('icons/mob/clothing/feet.dmi', "black"), ICON_UNDERLAY)
+3 -3
View File
@@ -893,10 +893,10 @@
if(!result || !A)
return TRUE
A.armor = A.armor.setRating(armorlist["melee"], armorlist["bullet"], armorlist["laser"], armorlist["energy"], armorlist["bomb"], armorlist["bio"], armorlist["rad"], armorlist["fire"], armorlist["acid"], armorlist["magic"])
A.armor = A.armor.setRating(armorlist[MELEE], armorlist[BULLET], armorlist[LASER], armorlist[ENERGY], armorlist[BOMB], armorlist[BIO], armorlist[RAD], armorlist[FIRE], armorlist[ACID], armorlist[MAGIC])
log_admin("[key_name(usr)] modified the armor on [A] to: melee = [armorlist["melee"]], bullet = [armorlist["bullet"]], laser = [armorlist["laser"]], energy = [armorlist["energy"]], bomb = [armorlist["bomb"]], bio = [armorlist["bio"]], rad = [armorlist["rad"]], fire = [armorlist["fire"]], acid = [armorlist["acid"]], magic = [armorlist["magic"]]")
message_admins("<span class='notice'>[key_name(usr)] modified the armor on [A] to: melee = [armorlist["melee"]], bullet = [armorlist["bullet"]], laser = [armorlist["laser"]], energy = [armorlist["energy"]], bomb = [armorlist["bomb"]], bio = [armorlist["bio"]], rad = [armorlist["rad"]], fire = [armorlist["fire"]], acid = [armorlist["acid"]], magic = [armorlist["magic"]]")
log_admin("[key_name(usr)] modified the armor on [A] to: melee = [armorlist[MELEE]], bullet = [armorlist[BULLET]], laser = [armorlist[LASER]], energy = [armorlist[ENERGY]], bomb = [armorlist[BOMB]], bio = [armorlist[BIO]], rad = [armorlist[RAD]], fire = [armorlist[FIRE]], acid = [armorlist[ACID]], magic = [armorlist[MAGIC]]")
message_admins("<span class='notice'>[key_name(usr)] modified the armor on [A] to: melee = [armorlist[MELEE]], bullet = [armorlist[BULLET]], laser = [armorlist[LASER]], energy = [armorlist[ENERGY]], bomb = [armorlist[BOMB]], bio = [armorlist[BIO]], rad = [armorlist[RAD]], fire = [armorlist[FIRE]], acid = [armorlist[ACID]], magic = [armorlist[MAGIC]]")
return TRUE
else if(href_list["addreagent"]) /* Made on /TG/, credit to them. */
+6 -2
View File
@@ -17,6 +17,7 @@
var/list/stage5 = list("Oh the humanity!")
var/transformation_text = null
var/new_form = /mob/living/carbon/human
var/job_role = null
/datum/disease/transformation/stage_act()
..()
@@ -40,8 +41,8 @@
if(istype(affected_mob, /mob/living/carbon) && affected_mob.stat != DEAD)
if(stage5)
to_chat(affected_mob, pick(stage5))
if(jobban_isbanned(affected_mob, new_form))
affected_mob.death(1)
if(jobban_isbanned(affected_mob, job_role))
affected_mob.death()
return
if(affected_mob.notransform)
return
@@ -133,6 +134,7 @@
stage4 = list("<span class='danger'>Your skin feels very loose.</span>", "<span class='danger'>You can feel... something...inside you.</span>")
stage5 = list("<span class='danger'>Your skin feels as if it's about to burst off!</span>")
new_form = /mob/living/silicon/robot
job_role = "Cyborg"
/datum/disease/transformation/robot/stage_act()
@@ -165,6 +167,7 @@
stage4 = list("<span class='danger'>Your skin feels very tight.</span>", "<span class='danger'>Your blood boils!</span>", "<span class='danger'>You can feel... something...inside you.</span>")
stage5 = list("<span class='danger'>Your skin feels as if it's about to burst off!</span>")
new_form = /mob/living/carbon/alien/humanoid/hunter
job_role = ROLE_ALIEN
/datum/disease/transformation/xeno/stage_act()
..()
@@ -248,3 +251,4 @@
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
job_role = ROLE_MORPH
@@ -6,6 +6,7 @@
var/list/steps
var/atom/holder
var/result
var/index
var/list/steps_desc
var/taskpath = null // Path of job objective completed.
@@ -128,7 +129,6 @@
return TRUE
/datum/construction/reversible
var/index
/datum/construction/reversible/New(atom)
..()
@@ -168,7 +168,6 @@
#define state_prev "prev"
/datum/construction/reversible2
var/index
var/base_icon = "durand"
/datum/construction/reversible2/New(atom)
+16 -3
View File
@@ -19,6 +19,8 @@
var/headers
/// URL that the request is being sent to
var/url
/// If present, response body will be saved to this file.
var/output_file
/// The raw response, which will be decoeded into a [/datum/http_response]
var/_raw_response
/// Callback for executing after async requests. Will be called with an argument of [/datum/http_response] as first argument
@@ -42,7 +44,7 @@ THE METHODS IN THIS FILE ARE TO BE USED BY THE SUBSYSTEM AS A MANGEMENT HUB
* * _body - The body of the request, if applicable
* * _headers - Associative list of HTTP headers to send, if applicab;e
*/
/datum/http_request/proc/prepare(_method, _url, _body = "", list/_headers)
/datum/http_request/proc/prepare(_method, _url, _body = "", list/_headers, _output_file)
if(!length(_headers))
headers = ""
else
@@ -51,6 +53,7 @@ THE METHODS IN THIS FILE ARE TO BE USED BY THE SUBSYSTEM AS A MANGEMENT HUB
method = _method
url = _url
body = _body
output_file = _output_file
/**
* Blocking executor
@@ -60,7 +63,7 @@ THE METHODS IN THIS FILE ARE TO BE USED BY THE SUBSYSTEM AS A MANGEMENT HUB
*/
/datum/http_request/proc/execute_blocking()
CRASH("Attempted to execute a blocking HTTP request")
// _raw_response = rustg_http_request_blocking(method, url, body, headers)
// _raw_response = rustg_http_request_blocking(method, url, body, headers, build_options())
/**
* Async execution starter
@@ -73,7 +76,7 @@ THE METHODS IN THIS FILE ARE TO BE USED BY THE SUBSYSTEM AS A MANGEMENT HUB
if(in_progress)
CRASH("Attempted to re-use a request object.")
id = rustg_http_request_async(method, url, body, headers)
id = rustg_http_request_async(method, url, body, headers, build_options())
if(isnull(text2num(id)))
_raw_response = "Proc error: [id]"
@@ -81,6 +84,16 @@ THE METHODS IN THIS FILE ARE TO BE USED BY THE SUBSYSTEM AS A MANGEMENT HUB
else
in_progress = TRUE
/**
* Options builder
*
* Builds options for if we want to download files with SShttp
*/
/datum/http_request/proc/build_options()
if(output_file)
return json_encode(list("output_filename" = output_file, "body_filename" = null))
return null
/**
* Async completion checker
*
+22 -22
View File
@@ -2,28 +2,28 @@
GLOBAL_LIST_EMPTY(all_huds)
///GLOBAL HUD LIST
GLOBAL_LIST_INIT(huds, list( \
DATA_HUD_SECURITY_BASIC = new/datum/atom_hud/data/human/security/basic(), \
DATA_HUD_SECURITY_ADVANCED = new/datum/atom_hud/data/human/security/advanced(), \
DATA_HUD_MEDICAL_BASIC = new/datum/atom_hud/data/human/medical/basic(), \
DATA_HUD_MEDICAL_ADVANCED = new/datum/atom_hud/data/human/medical/advanced(), \
DATA_HUD_DIAGNOSTIC = new/datum/atom_hud/data/diagnostic(), \
DATA_HUD_DIAGNOSTIC_ADVANCED = new/datum/atom_hud/data/diagnostic/advanced(), \
DATA_HUD_HYDROPONIC = new/datum/atom_hud/data/hydroponic(), \
ANTAG_HUD_CULT = new/datum/atom_hud/antag(), \
ANTAG_HUD_REV = new/datum/atom_hud/antag(), \
ANTAG_HUD_OPS = new/datum/atom_hud/antag(), \
ANTAG_HUD_WIZ = new/datum/atom_hud/antag(), \
ANTAG_HUD_SHADOW = new/datum/atom_hud/antag(), \
ANTAG_HUD_TRAITOR = new/datum/atom_hud/antag/hidden(),\
ANTAG_HUD_NINJA = new/datum/atom_hud/antag/hidden(),\
ANTAG_HUD_CHANGELING = new/datum/atom_hud/antag/hidden(),\
ANTAG_HUD_VAMPIRE = new/datum/atom_hud/antag/hidden(),\
ANTAG_HUD_ABDUCTOR = new/datum/atom_hud/antag/hidden(),\
DATA_HUD_ABDUCTOR = new/datum/atom_hud/abductor(),\
ANTAG_HUD_EVENTMISC = new/datum/atom_hud/antag/hidden(),\
ANTAG_HUD_BLOB = new/datum/atom_hud/antag/hidden()\
))
GLOBAL_LIST_INIT(huds, list(
DATA_HUD_SECURITY_BASIC = new/datum/atom_hud/data/human/security/basic(),
DATA_HUD_SECURITY_ADVANCED = new/datum/atom_hud/data/human/security/advanced(),
DATA_HUD_MEDICAL_BASIC = new/datum/atom_hud/data/human/medical/basic(),
DATA_HUD_MEDICAL_ADVANCED = new/datum/atom_hud/data/human/medical/advanced(),
DATA_HUD_DIAGNOSTIC_BASIC = new/datum/atom_hud/data/diagnostic/basic(),
DATA_HUD_DIAGNOSTIC_ADVANCED = new/datum/atom_hud/data/diagnostic/advanced(),
DATA_HUD_HYDROPONIC = new/datum/atom_hud/data/hydroponic(),
ANTAG_HUD_CULT = new/datum/atom_hud/antag(),
ANTAG_HUD_REV = new/datum/atom_hud/antag(),
ANTAG_HUD_OPS = new/datum/atom_hud/antag(),
ANTAG_HUD_WIZ = new/datum/atom_hud/antag(),
ANTAG_HUD_SHADOW = new/datum/atom_hud/antag(),
ANTAG_HUD_TRAITOR = new/datum/atom_hud/antag/hidden(),
ANTAG_HUD_NINJA = new/datum/atom_hud/antag/hidden(),
ANTAG_HUD_CHANGELING = new/datum/atom_hud/antag/hidden(),
ANTAG_HUD_VAMPIRE = new/datum/atom_hud/antag/hidden(),
ANTAG_HUD_ABDUCTOR = new/datum/atom_hud/antag/hidden(),
DATA_HUD_ABDUCTOR = new/datum/atom_hud/abductor(),
ANTAG_HUD_EVENTMISC = new/datum/atom_hud/antag/hidden(),
ANTAG_HUD_BLOB = new/datum/atom_hud/antag/hidden()
))
/datum/atom_hud
var/list/atom/hudatoms = list() //list of all atoms which display this hud
+4
View File
@@ -85,6 +85,10 @@
original = null
return ..()
/datum/mind/proc/get_display_key()
var/clientKey = current?.client?.get_display_key()
return clientKey ? clientKey : key
/datum/mind/proc/transfer_to(mob/living/new_character)
var/datum/atom_hud/antag/hud_to_transfer = antag_hud //we need this because leave_hud() will clear this list
var/mob/living/old_current = current
+2 -2
View File
@@ -14,9 +14,9 @@
EXCEPTION("Invalid target given")
if(goal_number)
goal = goal_number
bar = image('icons/effects/progessbar.dmi', target, "prog_bar_0", HUD_LAYER)
bar = image('icons/effects/progessbar.dmi', target, "prog_bar_0", ABOVE_HUD_LAYER)
bar.alpha = 0
bar.plane = HUD_PLANE
bar.plane = ABOVE_HUD_PLANE
bar.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
user = User
if(user)
+10 -5
View File
@@ -55,12 +55,17 @@
sleep(jaunt_in_time)
qdel(holder)
if(!QDELETED(target))
if(mobloc.density)
if(!(target.Move(mobloc)))
for(var/turf/T in orange(7))
if(T)
if(target.Move(T))
break
target.canmove = 1
if(isspaceturf(T))
continue
if(T && target.Move(T))
target.canmove = TRUE
return
for(var/turf/space/S in orange(7)) //loop for space turfs in case there were no normal ones last loop
if(S && target.Move(S))
break
target.canmove = TRUE //if there are no valid tiles in a range of 7, just let them spawn wherever they are currently
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/jaunt_steam(mobloc)
var/datum/effect_system/steam_spread/steam = new /datum/effect_system/steam_spread()
+1 -1
View File
@@ -30,7 +30,7 @@
var/obj/item/clothing/mask/horsehead/magichead = new /obj/item/clothing/mask/horsehead
magichead.flags |= NODROP | DROPDEL //curses!
magichead.flags_inv = null //so you can still see their face
magichead.voicechange = 1 //NEEEEIIGHH
magichead.voicechange = TRUE //NEEEEIIGHH
target.visible_message( "<span class='danger'>[target]'s face lights up in fire, and after the event a horse's head takes its place!</span>", \
"<span class='danger'>Your face burns up, and shortly after the fire you realise you have the face of a horse!</span>")
if(!target.unEquip(target.wear_mask))
+3 -3
View File
@@ -96,10 +96,10 @@
invocation_type = "none"
action_icon_state = "vampire_bats"
shapeshift_type = /mob/living/simple_animal/hostile/scarybat/batswarm
current_shapes = list(/mob/living/simple_animal/hostile/scarybat/batswarm)
shapeshift_type = /mob/living/simple_animal/hostile/scarybat/adminvampire
current_shapes = list(/mob/living/simple_animal/hostile/scarybat/adminvampire)
current_casters = list()
possible_shapes = list(/mob/living/simple_animal/hostile/scarybat/batswarm)
possible_shapes = list(/mob/living/simple_animal/hostile/scarybat/adminvampire)
/obj/effect/proc_holder/spell/targeted/shapeshift/hellhound
name = "Lesser Hellhound Form"
+53
View File
@@ -1,5 +1,58 @@
//Largely beneficial effects go here, even if they have drawbacks. An example is provided in Shadow Mend.
/datum/status_effect/his_grace
id = "his_grace"
duration = -1
tick_interval = 4
alert_type = /obj/screen/alert/status_effect/his_grace
var/bloodlust = 0
/obj/screen/alert/status_effect/his_grace
name = "His Grace"
desc = "His Grace hungers, and you must feed Him."
icon_state = "his_grace"
alerttooltipstyle = "hisgrace"
/obj/screen/alert/status_effect/his_grace/MouseEntered(location, control, params)
desc = initial(desc)
var/datum/status_effect/his_grace/HG = attached_effect
desc += "<br><font size=3><b>Current Bloodthirst: [HG.bloodlust]</b></font>\
<br>Becomes undroppable at <b>[HIS_GRACE_FAMISHED]</b>\
<br>Will consume you at <b>[HIS_GRACE_CONSUME_OWNER]</b>"
..()
/datum/status_effect/his_grace/on_apply()
add_attack_logs(owner, owner, "gained His Grace's stun immunity", ATKLOG_ALL)
owner.add_stun_absorption("hisgrace", INFINITY, 3, null, "His Grace protects you from the stun!")
return ..()
/datum/status_effect/his_grace/tick()
bloodlust = 0
var/graces = 0
var/list/held_items = list()
held_items += owner.l_hand
held_items += owner.r_hand
for(var/obj/item/his_grace/HG in held_items)
if(HG.bloodthirst > bloodlust)
bloodlust = HG.bloodthirst
if(HG.awakened)
graces++
if(!graces)
owner.apply_status_effect(STATUS_EFFECT_HISWRATH)
qdel(src)
return
var/grace_heal = bloodlust * 0.05
owner.adjustBruteLoss(-grace_heal)
owner.adjustFireLoss(-grace_heal)
owner.adjustToxLoss(-grace_heal)
owner.adjustOxyLoss(-(grace_heal * 2))
owner.adjustCloneLoss(-grace_heal)
/datum/status_effect/his_grace/on_remove()
add_attack_logs(owner, owner, "lost His Grace's stun immunity", ATKLOG_ALL)
if(islist(owner.stun_absorption) && owner.stun_absorption["hisgrace"])
owner.stun_absorption -= "hisgrace"
/datum/status_effect/shadow_mend
id = "shadow_mend"
duration = 30
+23
View File
@@ -1,5 +1,28 @@
//OTHER DEBUFFS
/datum/status_effect/his_wrath //does minor damage over time unless holding His Grace
id = "his_wrath"
duration = -1
tick_interval = 4
alert_type = /obj/screen/alert/status_effect/his_wrath
/obj/screen/alert/status_effect/his_wrath
name = "His Wrath"
desc = "You fled from His Grace instead of feeding Him, and now you suffer."
icon_state = "his_grace"
alerttooltipstyle = "hisgrace"
/datum/status_effect/his_wrath/tick()
var/list/held_items = list()
held_items += owner.l_hand
held_items += owner.r_hand
for(var/obj/item/his_grace/HG in held_items)
qdel(src)
return
owner.adjustBruteLoss(0.1)
owner.adjustFireLoss(0.1)
owner.adjustToxLoss(0.2)
/datum/status_effect/cultghost //is a cult ghost and can't use manifest runes
id = "cult_ghost"
duration = -1
+50 -30
View File
@@ -193,14 +193,6 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
containername = "special ops crate"
hidden = 1
/datum/supply_packs/emergency/syndicate
name = "ERROR_NULL_ENTRY"
contains = list(/obj/item/storage/box/syndicate)
cost = 140
containertype = /obj/structure/closet/crate
containername = "crate"
hidden = 1
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// Security ////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
@@ -228,6 +220,13 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
contains = list(/obj/item/vending_refill/security)
containername = "SecTech supply crate"
/datum/supply_packs/security/vending/clothingvendor
name = "Security Clothing Vendors Crate"
cost = 40
contains = list(/obj/item/vending_refill/secdrobe,
/obj/item/vending_refill/detdrobe)
containername = "security clothing vendor crate"
////// Armor: Basic
/datum/supply_packs/security/helmets
@@ -405,28 +404,6 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
cost = 80
containername = "combat shotgun crate"
/datum/supply_packs/security/armory/buckshotammo
name = "Buckshot Ammo Crate"
contains = list(/obj/item/ammo_box/shotgun/buck,
/obj/item/storage/box/buck,
/obj/item/storage/box/buck,
/obj/item/storage/box/buck,
/obj/item/storage/box/buck,
/obj/item/storage/box/buck)
cost = 45
containername = "buckshot ammo crate"
/datum/supply_packs/security/armory/slugammo
name = "Slug Ammo Crate"
contains = list(/obj/item/ammo_box/shotgun,
/obj/item/storage/box/slug,
/obj/item/storage/box/slug,
/obj/item/storage/box/slug,
/obj/item/storage/box/slug,
/obj/item/storage/box/slug)
cost = 45
containername = "slug ammo crate"
/datum/supply_packs/security/armory/expenergy
name = "Energy Guns Crate"
contains = list(/obj/item/gun/energy/gun,
@@ -578,6 +555,13 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
/obj/item/vending_refill/youtool)
containername = "engineering supply crate"
/datum/supply_packs/engineering/vending/clothingvendor
name = "Engineering Clothing Vendors Crate"
cost = 20
contains = list(/obj/item/vending_refill/engidrobe,
/obj/item/vending_refill/atmosdrobe)
containername = "engineering clothing vendor crate"
/datum/supply_packs/engineering/powergamermitts
name = "Insulated Gloves Crate"
contains = list(/obj/item/clothing/gloves/color/yellow,
@@ -896,6 +880,14 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
/obj/item/vending_refill/wallmed)
containername = "medical vending crate"
/datum/supply_packs/medical/vending/clothingvendor
name = "Medical Clothing Vendors Crate"
cost = 20
contains = list(/obj/item/vending_refill/medidrobe,
/obj/item/vending_refill/chemdrobe,
/obj/item/vending_refill/virodrobe)
containername = "medical clothing vendors crate"
/datum/supply_packs/medical/bloodpacks
name = "Blood Pack Variety Crate"
contains = list(/obj/item/reagent_containers/iv_bag,
@@ -1043,6 +1035,14 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
containertype = /obj/structure/largecrate
containername = "oil tank crate"
/datum/supply_packs/science/vending/clothingvendor
name = "Science Clothing Vendors Crate"
cost = 20
contains = list(/obj/item/vending_refill/scidrobe,
/obj/item/vending_refill/robodrobe,
/obj/item/vending_refill/genedrobe,)
containername = "science clothing vendor crate"
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// Organic /////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
@@ -1462,6 +1462,12 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
containertype = /obj/structure/closet/crate/secure
containername = "shaft miner starter kit"
/datum/supply_packs/misc/carpet
name = "Carpet Crate"
cost = 20
contains = list(/obj/item/stack/tile/carpet/twenty)
containername = "carpet crate"
///////////// Paper Work
@@ -1820,6 +1826,20 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
cost = 15
containername = "boxing supply crate"
/datum/supply_packs/misc/vending/clothingvendor
name = "Service Clothing Vendors Crate"
cost = 20
contains = list(/obj/item/vending_refill/bardrobe,
/obj/item/vending_refill/chefdrobe,
/obj/item/vending_refill/hydrodrobe)
containername = "service clothing vendor crate"
/datum/supply_packs/misc/vending/clothingvendor/cargo
name = "Cargo Clothing Vendors Crate"
cost = 20
contains = list(/obj/item/vending_refill/cargodrobe)
containername = "cargo clothing vendor crate"
///////////// Station Goals
/datum/supply_packs/misc/station_goal
+24 -11
View File
@@ -167,18 +167,19 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
//Clown
/datum/uplink_item/jobspecific/clowngrenade
name = "Banana Grenade"
desc = "A grenade that explodes into HONK! brand banana peels that are genetically modified to be extra slippery and extrude caustic acid when stepped on"
desc = "A grenade that explodes into HONK! brand banana peels that are genetically modified to be extra slippery and extrude caustic acid when stepped on."
reference = "BG"
item = /obj/item/grenade/clown_grenade
cost = 5
job = list("Clown")
/datum/uplink_item/jobspecific/clownmagboots
name = "Clown Magboots"
desc = "A pair of modified clown shoes fitted with an advanced magnetic traction system. Look and sound exactly like regular clown shoes unless closely inspected."
reference = "CM"
item = /obj/item/clothing/shoes/magboots/clown
/datum/uplink_item/jobspecific/clownslippers
name = "Clown Acrobatic Shoes"
desc = "A pair of modified clown shoes fitted with a built-in propulsion system that allows the user to perform a short slip below anyone. Turning on the waddle dampeners removes the slowdown on the shoes."
reference = "CAS"
item = /obj/item/clothing/shoes/clown_shoes/slippers
cost = 3
surplus = 75
job = list("Clown")
/datum/uplink_item/jobspecific/trick_revolver
@@ -257,10 +258,13 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
job = list("Chaplain")
/datum/uplink_item/jobspecific/artistic_toolbox
name = "Artistic Toolbox"
desc = "An accursed toolbox that grants its followers extreme power at the cost of requiring repeated sacrifices to it. If sacrifices are not provided, it will turn on its follower."
reference = "HGAT"
item = /obj/item/storage/toolbox/green/memetic
name = "His Grace"
desc = "An incredibly dangerous weapon recovered from a station overcome by the grey tide. Once activated, He will thirst for blood and must be used to kill to sate that thirst. \
His Grace grants gradual regeneration and complete stun immunity to His wielder, but be wary: if He gets too hungry, He will become impossible to drop and eventually kill you if not fed. \
However, if left alone for long enough, He will fall back to slumber. \
To activate His Grace, simply unlatch Him."
reference = "HG"
item = /obj/item/his_grace
cost = 20
job = list("Chaplain")
surplus = 0 //No lucky chances from the crate; if you get this, this is ALL you're getting
@@ -1171,6 +1175,15 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 4
excludefrom = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_tools/voice_modulator
name = "Chameleon Voice Modulator Mask"
desc = "A syndicate tactical mask equipped with chameleon technology and a sound modulator for disguising your voice. \
While the mask is active, your voice will sound unrecognizable to others"
reference = "CVMM"
item = /obj/item/clothing/mask/gas/voice_modulator/chameleon
cost = 1
excludefrom = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_tools/chameleon/nuke
reference = "NCHAM"
cost = 6
@@ -1524,7 +1537,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/implants/freedom
name = "Freedom Implant"
desc = "An implant injected into the body and later activated manually to break out of any restraints. Can be activated up to 4 times."
desc = "An implant injected into the body and later activated manually to break out of any restraints or grabs. Can be activated up to 4 times."
reference = "FI"
item = /obj/item/implanter/freedom
cost = 5
@@ -32,7 +32,7 @@
/datum/weather/rad_storm/weather_act(mob/living/L)
var/resist = L.getarmor(null, "rad")
var/resist = L.getarmor(null, RAD)
if(prob(40))
if(ishuman(L))
var/mob/living/carbon/human/H = L
+3 -1
View File
@@ -44,12 +44,13 @@ GLOBAL_DATUM_INIT(event_announcement, /datum/announcement/priority/command/event
title = "Security Announcement"
announcement_type = "Security Announcement"
/datum/announcement/proc/Announce(message as text, new_title = "", new_sound = null, do_newscast = newscast, msg_sanitized = 0, from, msg_language)
/datum/announcement/proc/Announce(message as text, new_title = "", new_sound = null, do_newscast = newscast, msg_sanitized = 0, from, msg_language, new_sound2 = null)
if(!message)
return
var/message_title = new_title ? new_title : title
var/message_sound = new_sound ? sound(new_sound) : sound
var/message_sound2 = new_sound2 ? sound(new_sound2) : sound
if(!msg_sanitized)
message = trim_strip_html_properly(message, allow_lines = 1)
@@ -74,6 +75,7 @@ GLOBAL_DATUM_INIT(event_announcement, /datum/announcement/priority/command/event
NewsCast(message, message_title)
Sound(message_sound, combined_receivers[1] + combined_receivers[2])
Sound(message_sound2, combined_receivers[1] + combined_receivers[2])
Log(message, message_title)
/datum/announcement/proc/Get_Receivers(datum/language/message_language)
-7
View File
@@ -147,13 +147,6 @@
detected_mech = TRUE
increase_alert("Hostile mecha detected: [E]")
/area/syndicate_depot/core/proc/saw_pod(obj/spacepod/P)
if(detected_pod)
return
detected_pod = TRUE
if(!called_backup)
increase_alert("Hostile spacepod detected: [P]")
/area/syndicate_depot/core/proc/saw_double_agent(mob/living/M)
if(detected_double_agent)
return
+1 -13
View File
@@ -1112,14 +1112,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "\improper Chief Engineer's office"
icon_state = "engine_control"
/area/engine/mechanic_workshop
name = "\improper Mechanic Workshop"
icon_state = "engine"
/area/engine/mechanic_workshop/hanger
name = "\improper Hanger Bay"
icon_state = "engine"
/area/engine/supermatter
name = "\improper Supermatter Engine"
icon_state = "engine"
@@ -1488,10 +1480,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "\improper Head of Security's Office"
icon_state = "sec_hos"
/area/security/podbay
name = "\improper Security Podbay"
icon_state = "securitypodbay"
/area/security/detectives_office
name = "\improper Detective's Office"
icon_state = "detective"
@@ -1544,7 +1532,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/security/vacantoffice2
name = "\improper Vacant Office"
icon_state = "security"
/area/security/permasolitary
name = "Solitary Confinement"
icon_state = "solitary"
+37 -40
View File
@@ -657,9 +657,6 @@
GLOBAL_LIST_EMPTY(blood_splatter_icons)
/atom/proc/blood_splatter_index()
return "\ref[initial(icon)]-[initial(icon_state)]"
//returns the mob's dna info as a list, to be inserted in an object's blood_DNA list
/mob/living/proc/get_blood_dna_list()
if(get_blood_id() != "blood")
@@ -726,56 +723,52 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
return add_blood(blood_dna, bloodcolor)
//to add blood onto something, with blood dna info to include.
/atom/proc/add_blood(list/blood_dna, color)
/atom/proc/add_blood(list/blood_dna, b_color)
return FALSE
/obj/add_blood(list/blood_dna, color)
/obj/add_blood(list/blood_dna, b_color)
return transfer_blood_dna(blood_dna)
/obj/item/add_blood(list/blood_dna, color)
var/blood_count = !blood_DNA ? 0 : blood_DNA.len
/obj/item/add_blood(list/blood_dna, b_color)
var/blood_count = !blood_DNA ? 0 : length(blood_DNA)
if(!..())
return FALSE
if(!blood_count)//apply the blood-splatter overlay if it isn't already in there
add_blood_overlay(color)
blood_color = b_color // update the blood color
if(!blood_count) //apply the blood-splatter overlay if it isn't already in there
add_blood_overlay()
return TRUE //we applied blood to the item
/obj/item/clothing/gloves/add_blood(list/blood_dna, color)
/obj/item/clothing/gloves/add_blood(list/blood_dna, b_color)
. = ..()
transfer_blood = rand(2, 4)
/turf/add_blood(list/blood_dna, color)
/turf/add_blood(list/blood_dna, b_color)
var/obj/effect/decal/cleanable/blood/splatter/B = locate() in src
if(!B)
B = new /obj/effect/decal/cleanable/blood/splatter(src)
B.transfer_blood_dna(blood_dna) //give blood info to the blood decal.
B.basecolor = color
B.basecolor = b_color
return TRUE //we bloodied the floor
/mob/living/carbon/human/add_blood(list/blood_dna, color)
/mob/living/carbon/human/add_blood(list/blood_dna, b_color)
if(wear_suit)
wear_suit.add_blood(blood_dna, color)
wear_suit.blood_color = color
wear_suit.add_blood(blood_dna, b_color)
update_inv_wear_suit()
else if(w_uniform)
w_uniform.add_blood(blood_dna, color)
w_uniform.blood_color = color
w_uniform.add_blood(blood_dna, b_color)
update_inv_w_uniform()
if(head)
head.add_blood(blood_dna, color)
head.blood_color = color
head.add_blood(blood_dna, b_color)
update_inv_head()
if(glasses)
glasses.add_blood(blood_dna, color)
glasses.blood_color = color
glasses.add_blood(blood_dna, b_color)
update_inv_glasses()
if(gloves)
var/obj/item/clothing/gloves/G = gloves
G.add_blood(blood_dna, color)
G.blood_color = color
G.add_blood(blood_dna, b_color)
verbs += /mob/living/carbon/human/proc/bloody_doodle
else
hand_blood_color = color
hand_blood_color = b_color
bloody_hands = rand(2, 4)
transfer_blood_dna(blood_dna)
verbs += /mob/living/carbon/human/proc/bloody_doodle
@@ -783,21 +776,13 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
update_inv_gloves() //handles bloody hands overlays and updating
return TRUE
/obj/item/proc/add_blood_overlay(color)
/obj/item/proc/add_blood_overlay()
if(initial(icon) && initial(icon_state))
//try to find a pre-processed blood-splatter. otherwise, make a new one
var/index = blood_splatter_index()
var/icon/blood_splatter_icon = GLOB.blood_splatter_icons[index]
if(!blood_splatter_icon)
blood_splatter_icon = icon(initial(icon), initial(icon_state), , 1) //we only want to apply blood-splatters to the initial icon_state for each object
blood_splatter_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent)
blood_splatter_icon.Blend(icon('icons/effects/blood.dmi', "itemblood"), ICON_MULTIPLY) //adds blood and the remaining white areas become transparant
blood_splatter_icon = fcopy_rsc(blood_splatter_icon)
GLOB.blood_splatter_icons[index] = blood_splatter_icon
blood_overlay = image(blood_splatter_icon)
blood_overlay.color = color
overlays += blood_overlay
var/list/params = GLOB.blood_splatter_icons["[blood_color]"]
if(!params)
params = layering_filter(icon = icon('icons/effects/blood.dmi', "itemblood"), color = blood_color, blend_mode = BLEND_INSET_OVERLAY)
GLOB.blood_splatter_icons["[blood_color]"] = params
add_filter("blood_splatter", 1, params)
/atom/proc/clean_blood(radiation_clean = FALSE)
germ_level = 0
@@ -828,8 +813,8 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
/obj/item/clean_blood(radiation_clean = FALSE)
. = ..()
if(.)
if(blood_overlay)
overlays -= blood_overlay
if(initial(icon) && initial(icon_state))
remove_filter("blood_splatter")
/obj/item/clothing/gloves/clean_blood(radiation_clean = FALSE)
. = ..()
@@ -1153,3 +1138,15 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
if(degrees)
appearance_flags |= PIXEL_SCALE
transform = M
/*
Setter for the `density` variable.
Arguments:
* new_value - the new density you would want it to set.
Returns: Either null if identical to existing density, or the new density if different.
*/
/atom/proc/set_density(new_value)
if(density == new_value)
return
. = density
density = new_value
+4 -5
View File
@@ -90,13 +90,11 @@
/atom/movable/proc/stop_pulling()
if(pulling)
pulling.pulledby = null
var/mob/living/ex_pulled = pulling
pulling.pulledby = null
pulling = null
pulledby = null
if(isliving(ex_pulled))
var/mob/living/L = ex_pulled
L.update_canmove()// mob gets up if it was lyng down in a chokehold
if(!QDELETED(ex_pulled) && istype(ex_pulled))
ex_pulled.update_canmove()// mob gets up if it was lyng down in a chokehold
/atom/movable/proc/check_pulling()
if(pulling)
@@ -420,6 +418,7 @@
if(spin && !no_spin && !no_spin_thrown)
SpinAnimation(5, 1)
SEND_SIGNAL(src, COMSIG_MOVABLE_POST_THROW, TT, spin)
SSthrowing.processing[src] = TT
TT.tick()
+14 -2
View File
@@ -44,10 +44,12 @@
hud_icons = list(ID_HUD, IMPTRACK_HUD, IMPMINDSHIELD_HUD, IMPCHEM_HUD, WANTED_HUD)
/datum/atom_hud/data/diagnostic
hud_icons = list (DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD)
/datum/atom_hud/data/diagnostic/basic
hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD)
/datum/atom_hud/data/diagnostic/advanced
hud_icons = list (DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD, DIAG_PATH_HUD)
hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD, DIAG_PATH_HUD)
/datum/atom_hud/data/bot_path
hud_icons = list(DIAG_PATH_HUD)
@@ -473,6 +475,16 @@
return
holder.icon_state = "hudweed[RoundPlantBar(weedlevel/10)]"
/*~~~~~~~~~~~~
Airlocks!
~~~~~~~~~~~~~*/
/obj/machinery/door/airlock/proc/diag_hud_set_electrified()
var/image/holder = hud_list[DIAG_AIRLOCK_HUD]
if(isElectrified())
holder.icon_state = "electrified"
else
holder.icon_state = ""
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I'll just put this somewhere near the end...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+4 -4
View File
@@ -156,7 +156,7 @@
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>")
to_chat(usr, "<span class='boldnotice'>Subject may not hold anything in their hands.</span>")
return
if(usr.has_buckled_mobs()) //mob attached to us
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>")
@@ -194,7 +194,7 @@
if(!istype(L) || L.buckled)
return
if(L.abiotic())
to_chat(user, "<span class='danger'>Subject cannot have abiotic items on.</span>")
to_chat(user, "<span class='danger'>Subject may not hold anything in their hands.</span>")
return
if(L.has_buckled_mobs()) //mob attached to us
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>")
@@ -232,7 +232,7 @@
to_chat(user, "<span class='boldnotice'>The scanner is already occupied!</span>")
return
if(G.affecting.abiotic())
to_chat(user, "<span class='boldnotice'>Subject cannot have abiotic items on.</span>")
to_chat(user, "<span class='boldnotice'>Subject may not hold anything in their hands.</span>")
return
if(G.affecting.has_buckled_mobs()) //mob attached to us
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>")
@@ -315,7 +315,7 @@
if(HAS_TRAIT(occupant, TRAIT_GENELESS))
return TRUE
var/radiation_protection = occupant.run_armor_check(null, "rad")
var/radiation_protection = occupant.run_armor_check(null, RAD)
if(radiation_protection > NEGATE_MUTATION_THRESHOLD)
return TRUE
return FALSE
+6 -2
View File
@@ -140,12 +140,16 @@
/datum/mutation/disability/colourblindness/activate(mob/M)
..()
M.update_client_colour() //Handle the activation of the colourblindness on the mob.
M.update_icons() //Apply eyeshine as needed.
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.update_misc_effects()
/datum/mutation/disability/colourblindness/deactivate(mob/M)
..()
M.update_client_colour() //Handle the deactivation of the colourblindness on the mob.
M.update_icons() //Remove eyeshine as needed.
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.update_misc_effects()
/datum/mutation/disability/deaf
name = "Deafness"
+55 -22
View File
@@ -158,28 +158,6 @@
M.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH //temporary fix until the problem can be solved.
to_chat(M, "<span class='danger'>You suddenly feel very weak.</span>")
/datum/mutation/xray
name = "X-Ray Vision"
activation_messages = list("The walls suddenly disappear.")
deactivation_messages = list("The walls around you re-appear.")
instability = GENE_INSTABILITY_MAJOR
traits_to_add = list(TRAIT_XRAY_VISION)
activation_prob = 15
/datum/mutation/xray/New()
..()
block = GLOB.xrayblock
/datum/mutation/xray/activate(mob/living/M)
..()
M.update_sight()
M.update_icons() //Apply eyeshine as needed.
/datum/mutation/xray/deactivate(mob/living/M)
..()
M.update_sight()
M.update_icons() //Remove eyeshine as needed.
/datum/mutation/tk
name = "Telekenesis"
activation_messages = list("You feel smarter.")
@@ -1181,3 +1159,58 @@
else
H.remoteview_target = null
H.reset_perspective()
/datum/mutation/meson_vision
name = "Meson Vision"
activation_messages = list("More information seems to reach your eyes...")
deactivation_messages = list("The amount of information reaching your eyes fades...")
instability = GENE_INSTABILITY_MINOR
traits_to_add = list(TRAIT_MESON_VISION)
/datum/mutation/meson_vision/New()
..()
block = GLOB.mesonblock
/datum/mutation/meson_vision/activate(mob/living/M)
..()
M.update_sight()
/datum/mutation/meson_vision/deactivate(mob/living/M)
..()
M.update_sight()
/datum/mutation/night_vision
name = "Night Vision"
activation_messages = list("Were the lights always that bright?")
deactivation_messages = list("The ambient light level returns to normal...")
instability = GENE_INSTABILITY_MODERATE
traits_to_add = list(TRAIT_NIGHT_VISION)
/datum/mutation/night_vision/New()
..()
block = GLOB.nightvisionblock
/datum/mutation/night_vision/activate(mob/living/M)
..()
M.update_sight()
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.update_misc_effects()
/datum/mutation/night_vision/deactivate(mob/living/M)
..()
M.update_sight()
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.update_misc_effects()
/datum/mutation/flash_protection
name = "Flash Protection"
activation_messages = list("You stop noticing the glare from lights...")
deactivation_messages = list("Lights begin glaring again...")
instability = GENE_INSTABILITY_MINOR
traits_to_add = list(TRAIT_FLASH_PROTECTION)
/datum/mutation/flash_protection/New()
..()
block = GLOB.noflashblock
+2 -2
View File
@@ -91,8 +91,8 @@
is_zombie = TRUE
if(H.wear_suit)
var/obj/item/clothing/suit/armor/A = H.wear_suit
if(A.armor && A.armor.getRating("melee"))
maxHealth += A.armor.getRating("melee") //That zombie's got armor, I want armor!
if(A.armor && A.armor.getRating(MELEE))
maxHealth += A.armor.getRating(MELEE) //That zombie's got armor, I want armor!
maxHealth += 40
health = maxHealth
name = "blob zombie"
+2 -2
View File
@@ -3,7 +3,7 @@
icon = 'icons/mob/blob.dmi'
icon_state = "blank_blob"
max_integrity = 400
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 75, "acid" = 90)
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 75, ACID = 90)
fire_resist = 2
point_return = -1
var/overmind_get_delay = 0 // we don't want to constantly try to find an overmind, do it every 5 minutes
@@ -48,7 +48,7 @@
/obj/structure/blob/core/ex_act(severity)
var/damage = 50 - 10 * severity //remember, the core takes half brute damage, so this is 20/15/10 damage based on severity
take_damage(damage, BRUTE, "bomb", 0)
take_damage(damage, BRUTE, BOMB, 0)
/obj/structure/blob/core/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir, overmind_reagent_trigger = 1)
. = ..()
+1 -1
View File
@@ -3,7 +3,7 @@
icon = 'icons/mob/blob.dmi'
icon_state = "blank_blob"
max_integrity = 200
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 65, "acid" = 90)
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 65, ACID = 90)
point_return = 18
/obj/structure/blob/node/Initialize(mapload)
+1 -1
View File
@@ -7,7 +7,7 @@
brute_resist = 0.25
explosion_block = 3
atmosblock = TRUE
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 90, ACID = 90)
/obj/structure/blob/shield/core
point_return = 0
+2 -2
View File
@@ -66,10 +66,10 @@
return
if(src.client)
if(client.prefs.muted & MUTE_IC)
if(check_mute(client.ckey, MUTE_IC))
to_chat(src, "You cannot send IC messages (muted).")
return
if(src.client.handle_spam_prevention(message,MUTE_IC))
if(src.client.handle_spam_prevention(message, MUTE_IC))
return
if(stat)
+1 -1
View File
@@ -237,7 +237,7 @@
blobber.AIStatus = AI_OFF
blobber.LoseTarget()
spawn()
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a blobbernaut?", ROLE_BLOB, TRUE, 10 SECONDS, source = blobber)
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a blobbernaut?", ROLE_BLOB, TRUE, 10 SECONDS, source = blobber, role_cleanname = "blobbernaut")
if(length(candidates) && !QDELETED(blobber))
var/mob/C = pick(candidates)
if(C)

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