diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000000..3eee43dc71
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+patreon: citadelstation
diff --git a/.gitignore b/.gitignore
index dd20fecd22..91a0ef08eb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,10 @@
#Ignore byond config folder.
/cfg/**/*
+#Ignore rust-g and auxmos libraries which are compiled with scripts
+*.so
+/tools/build/binaries/**/*
+
#Ignore compiled files and other files generated during compilation.
*.mdme
*.dmb
diff --git a/Build.sh b/Build.sh
new file mode 100755
index 0000000000..6fd691921e
--- /dev/null
+++ b/Build.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+cd "$(dirname "$(readlink -f "$0")")"
+cd ./tools/build
+sudo bash ./build.sh
diff --git a/_maps/RandomRuins/SpaceRuins/shuttlerelic.dmm b/_maps/RandomRuins/SpaceRuins/shuttlerelic.dmm
index a0fc5fa8a7..347d0a093f 100644
--- a/_maps/RandomRuins/SpaceRuins/shuttlerelic.dmm
+++ b/_maps/RandomRuins/SpaceRuins/shuttlerelic.dmm
@@ -64,11 +64,7 @@
dir = 1;
icon_state = "chairold"
},
-/obj/item/crowbar/large{
- desc = "It's a big crowbar. It doesn't fit in your pockets, because it's big. It feels oddly heavy..";
- force = 20;
- name = "heavy crowbar"
- },
+/obj/item/crowbar/large/heavy,
/turf/open/floor/oldshuttle,
/area/ruin/powered)
"o" = (
diff --git a/_maps/RandomRuins/StationRuins/Box/Engine/engine_am.dmm b/_maps/RandomRuins/StationRuins/Box/Engine/engine_am.dmm
index db2a4f6cd7..f7fa98fcf7 100644
--- a/_maps/RandomRuins/StationRuins/Box/Engine/engine_am.dmm
+++ b/_maps/RandomRuins/StationRuins/Box/Engine/engine_am.dmm
@@ -1367,7 +1367,7 @@ JZ
kK
Ch
Ch
-MJ
+Ch
MJ
MJ
MJ
diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm
index 1118576807..d3b421b5ed 100644
--- a/_maps/map_files/BoxStation/BoxStation.dmm
+++ b/_maps/map_files/BoxStation/BoxStation.dmm
@@ -6690,18 +6690,6 @@
"amC" = (
/turf/open/floor/plating,
/area/maintenance/port/fore)
-"amD" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/machinery/vending/coffee,
-/obj/machinery/light/small{
- dir = 8
- },
-/turf/open/floor/plating,
-/area/maintenance/port/fore)
-"amE" = (
-/obj/effect/spawner/structure/window,
-/turf/open/floor/plating,
-/area/maintenance/port/fore)
"amF" = (
/obj/machinery/atmospherics/components/unary/tank/air,
/turf/open/floor/plating,
@@ -6975,44 +6963,12 @@
},
/turf/open/floor/plating,
/area/maintenance/solars/port/fore)
-"anj" = (
-/obj/machinery/computer/slot_machine{
- balance = 15;
- money = 500
- },
-/turf/open/floor/plating,
-/area/maintenance/port/fore)
"ank" = (
/obj/machinery/door/airlock/maintenance/abandoned{
req_access_txt = "12"
},
/turf/open/floor/plating,
/area/maintenance/port/fore)
-"anl" = (
-/obj/structure/chair/stool{
- pixel_y = 8
- },
-/obj/item/cigbutt{
- pixel_x = -15;
- pixel_y = 16
- },
-/turf/open/floor/plating/rust,
-/area/maintenance/port/fore)
-"anm" = (
-/obj/structure/table,
-/obj/item/trash/chips{
- pixel_x = -4;
- pixel_y = 1
- },
-/obj/item/reagent_containers/food/drinks/beer/light{
- pixel_x = 7
- },
-/obj/item/cigbutt{
- pixel_x = 10;
- pixel_y = 17
- },
-/turf/open/floor/plating,
-/area/maintenance/port/fore)
"ann" = (
/obj/effect/spawner/lootdrop/maintenance,
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
@@ -11812,25 +11768,6 @@
/obj/item/ectoplasm,
/turf/open/floor/wood,
/area/maintenance/port/fore)
-"azH" = (
-/obj/effect/turf_decal/tile/blue{
- dir = 8
- },
-/obj/effect/turf_decal/tile/red{
- dir = 1
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/obj/effect/turf_decal/tile/red,
-/obj/structure/cable{
- icon_state = "1-8"
- },
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
- dir = 1
- },
-/turf/open/floor/plasteel,
-/area/service/theater)
"azK" = (
/obj/structure/disposalpipe/segment{
dir = 4
@@ -12304,15 +12241,6 @@
/obj/item/pen/fourcolor,
/turf/open/floor/plasteel,
/area/commons/dorms)
-"aBa" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/effect/spawner/structure/window/reinforced,
-/obj/structure/cable{
- icon_state = "0-2"
- },
-/obj/structure/cable,
-/turf/open/floor/plating,
-/area/command/gateway)
"aBh" = (
/obj/machinery/camera{
c_tag = "EVA Maintenance";
@@ -12449,11 +12377,6 @@
},
/turf/open/floor/plasteel,
/area/service/hydroponics/garden)
-"aBx" = (
-/obj/effect/decal/cleanable/vomit,
-/obj/effect/decal/cleanable/dirt,
-/turf/open/floor/plating,
-/area/maintenance/fore)
"aBy" = (
/obj/machinery/door/airlock{
desc = "A small bathroom with a sink, toilet and shower.";
@@ -12462,9 +12385,6 @@
},
/turf/open/floor/mineral/titanium/blue,
/area/commons/toilet)
-"aBz" = (
-/turf/open/floor/plasteel/freezer,
-/area/commons/toilet)
"aBA" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -12665,30 +12585,6 @@
},
/turf/open/floor/plasteel,
/area/ai_monitored/command/storage/eva)
-"aCh" = (
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/obj/effect/turf_decal/tile/red,
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/obj/structure/table/wood,
-/obj/item/flashlight/lamp/bananalamp{
- pixel_y = 3
- },
-/obj/machinery/light{
- dir = 1
- },
-/obj/machinery/requests_console{
- department = "Theatre";
- name = "theatre RC";
- pixel_y = 32
- },
-/turf/open/floor/plasteel/white/side{
- dir = 4
- },
-/area/service/theater)
"aCi" = (
/obj/structure/cable,
/obj/effect/spawner/structure/window/reinforced,
@@ -13230,18 +13126,6 @@
},
/turf/open/floor/plasteel/dark,
/area/ai_monitored/command/nuke_storage)
-"aDy" = (
-/obj/structure/table/wood,
-/obj/item/reagent_containers/food/snacks/baguette,
-/obj/structure/mirror{
- pixel_y = 32
- },
-/obj/item/toy/crayon/spraycan/mimecan,
-/obj/item/toy/dummy,
-/turf/open/floor/plasteel/white/side{
- dir = 4
- },
-/area/service/theater)
"aDz" = (
/obj/structure/rack,
/obj/effect/spawner/lootdrop/maintenance{
@@ -13370,24 +13254,6 @@
"aDM" = (
/turf/open/floor/mineral/titanium/blue,
/area/commons/toilet)
-"aDN" = (
-/obj/machinery/camera{
- c_tag = "Bathrooms";
- dir = 1
- },
-/obj/structure/sink{
- pixel_y = 25
- },
-/obj/structure/mirror{
- pixel_y = 32
- },
-/turf/open/floor/mineral/titanium/blue,
-/area/commons/toilet)
-"aDP" = (
-/obj/effect/decal/cleanable/cobweb,
-/obj/machinery/computer/arcade,
-/turf/open/floor/carpet/arcade,
-/area/commons/arcade)
"aDQ" = (
/obj/machinery/door/airlock{
desc = "A small bathroom with a sink, toilet and shower.";
@@ -13397,29 +13263,6 @@
/obj/machinery/door/firedoor,
/turf/open/floor/mineral/titanium/blue,
/area/commons/toilet)
-"aDR" = (
-/obj/item/reagent_containers/food/drinks/beer{
- pixel_x = -15
- },
-/obj/machinery/computer/arcade,
-/turf/open/floor/carpet/arcade,
-/area/commons/arcade)
-"aDT" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/machinery/shower,
-/turf/open/floor/plasteel/freezer,
-/area/commons/toilet)
-"aDU" = (
-/obj/item/radio/intercom{
- pixel_y = 25
- },
-/obj/machinery/shower,
-/turf/open/floor/plasteel/freezer,
-/area/commons/toilet)
-"aDY" = (
-/obj/machinery/computer/arcade,
-/turf/open/floor/carpet/arcade,
-/area/commons/arcade)
"aDZ" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -13447,16 +13290,6 @@
},
/turf/open/floor/plating,
/area/maintenance/starboard/fore)
-"aEc" = (
-/obj/machinery/vending/cigarette,
-/obj/effect/decal/cleanable/cobweb{
- icon_state = "cobweb2"
- },
-/obj/structure/sign/poster/contraband/fun_police{
- pixel_x = 32
- },
-/turf/open/floor/carpet/arcade,
-/area/commons/arcade)
"aEd" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -13731,13 +13564,6 @@
},
/turf/open/floor/plasteel/dark,
/area/ai_monitored/command/nuke_storage)
-"aEU" = (
-/obj/machinery/vending/autodrobe,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/turf/open/floor/plasteel/white/side{
- dir = 4
- },
-/area/service/theater)
"aEV" = (
/obj/structure/reagent_dispensers/watertank,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
@@ -13811,21 +13637,6 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel,
/area/commons/dorms)
-"aFk" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
-/turf/open/floor/carpet/arcade,
-/area/commons/arcade)
-"aFl" = (
-/obj/structure/chair/stool{
- pixel_y = 8
- },
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
- dir = 4
- },
-/turf/open/floor/carpet/arcade,
-/area/commons/arcade)
"aFm" = (
/obj/structure/disposalpipe/segment{
dir = 6
@@ -14175,16 +13986,6 @@
},
/turf/open/floor/plasteel,
/area/command/gateway)
-"aGf" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "46"
- },
-/obj/structure/cable{
- icon_state = "1-2"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/turf/open/floor/plating,
-/area/maintenance/fore)
"aGg" = (
/obj/structure/reagent_dispensers/fueltank,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
@@ -14286,42 +14087,12 @@
/obj/effect/turf_decal/tile/blue,
/turf/open/floor/plasteel,
/area/hallway/primary/fore)
-"aGw" = (
-/obj/structure/closet/crate/bin,
-/obj/item/coin/silver,
-/turf/open/floor/carpet/arcade,
-/area/commons/arcade)
"aGx" = (
/obj/item/radio/intercom{
pixel_x = -25
},
/turf/open/floor/mineral/titanium/blue,
/area/commons/toilet)
-"aGy" = (
-/obj/structure/disposalpipe/segment{
- dir = 4
- },
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
- dir = 8
- },
-/turf/open/floor/plating,
-/area/maintenance/starboard/fore)
-"aGz" = (
-/obj/structure/cable{
- icon_state = "1-4"
- },
-/obj/structure/disposalpipe/segment{
- dir = 5
- },
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/structure/cable{
- icon_state = "2-4"
- },
-/turf/open/floor/plating,
-/area/maintenance/starboard/fore)
"aGA" = (
/obj/structure/cable{
icon_state = "2-4"
@@ -14936,19 +14707,6 @@
},
/turf/open/floor/plating,
/area/maintenance/starboard/fore)
-"aHZ" = (
-/obj/structure/table,
-/obj/item/trash/tray,
-/obj/item/trash/boritos,
-/obj/item/trash/can,
-/obj/item/reagent_containers/food/drinks/sillycup{
- pixel_x = 8;
- pixel_y = 10
- },
-/turf/open/floor/plating{
- icon_state = "panelscorched"
- },
-/area/commons/arcade)
"aIa" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
@@ -14956,19 +14714,6 @@
},
/turf/open/floor/plating,
/area/maintenance/starboard/fore)
-"aIb" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 5
- },
-/obj/structure/cable,
-/obj/machinery/power/apc{
- areastring = "/area/commons/arcade";
- dir = 8;
- name = "Arcade Room";
- pixel_x = -25
- },
-/turf/open/floor/plating,
-/area/maintenance/starboard/fore)
"aIc" = (
/obj/machinery/power/apc{
areastring = "/area/service/bar";
@@ -15451,11 +15196,6 @@
},
/turf/open/floor/plasteel,
/area/ai_monitored/command/storage/eva)
-"aJk" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/obj/machinery/door/airlock/maintenance,
-/turf/open/floor/wood,
-/area/service/bar)
"aJl" = (
/obj/structure/tank_dispenser/oxygen,
/obj/machinery/light{
@@ -15903,13 +15643,6 @@
},
/turf/open/floor/wood,
/area/service/bar)
-"aKr" = (
-/obj/machinery/vending/snack/orange,
-/obj/machinery/light{
- dir = 1
- },
-/turf/open/floor/wood,
-/area/service/bar)
"aKs" = (
/obj/structure/disposalpipe/segment,
/obj/effect/spawner/structure/window,
@@ -15993,12 +15726,6 @@
/obj/structure/closet/secure_closet/hydroponics,
/turf/open/floor/plasteel,
/area/service/hydroponics)
-"aKJ" = (
-/obj/machinery/light{
- dir = 1
- },
-/turf/open/floor/wood,
-/area/service/bar)
"aKL" = (
/obj/machinery/airalarm{
pixel_y = 24
@@ -16025,23 +15752,6 @@
},
/turf/open/floor/wood,
/area/service/bar)
-"aKN" = (
-/obj/structure/table/wood/fancy,
-/obj/item/reagent_containers/food/condiment/saltshaker{
- pixel_x = -3;
- pixel_y = 20
- },
-/obj/item/reagent_containers/food/condiment/peppermill{
- dir = 1;
- pixel_x = 3;
- pixel_y = 20
- },
-/obj/structure/sign/poster/contraband/eat{
- pixel_y = 32;
- poster_item_desc = "This poster promotes obesity, it also promotes giving the Chef a reason to keep their job."
- },
-/turf/open/floor/wood,
-/area/service/bar)
"aKO" = (
/obj/machinery/disposal/bin,
/obj/structure/disposalpipe/trunk{
@@ -16379,14 +16089,6 @@
},
/turf/open/floor/plasteel,
/area/commons/storage/primary)
-"aLN" = (
-/obj/structure/disposalpipe/segment,
-/obj/structure/cable{
- icon_state = "1-2"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/turf/open/floor/plasteel,
-/area/hallway/primary/port)
"aLO" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 5
@@ -17232,20 +16934,6 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plating,
/area/maintenance/fore)
-"aOt" = (
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/obj/machinery/light,
-/obj/structure/disposalpipe/segment{
- dir = 9
- },
-/obj/structure/cable{
- icon_state = "1-8"
- },
-/obj/machinery/atmospherics/pipe/manifold/supply/hidden,
-/turf/open/floor/plasteel,
-/area/hallway/primary/port)
"aOv" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -19401,71 +19089,23 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/wood,
/area/commons/vacant_room/office)
-"aUn" = (
-/obj/machinery/light/small{
- dir = 1
- },
-/obj/structure/closet/crate/bin,
-/turf/open/floor/plating{
- icon_state = "platingdmg2"
- },
-/area/maintenance/port/fore)
"aUo" = (
-/obj/item/clothing/mask/cigarette{
- pixel_x = -6;
- pixel_y = 14
- },
-/turf/open/floor/plating,
-/area/maintenance/port/fore)
-"aUp" = (
-/obj/effect/turf_decal/tile/red{
- dir = 1
- },
-/obj/effect/turf_decal/tile/red{
- dir = 8
- },
-/obj/structure/window{
- dir = 8
- },
-/obj/effect/turf_decal/tile/red,
-/obj/effect/turf_decal/tile/red{
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/turf/open/floor/plasteel,
/area/commons/locker)
-"aUs" = (
-/obj/effect/turf_decal/tile/red{
- dir = 8
- },
-/obj/effect/turf_decal/tile/red,
-/obj/effect/turf_decal/tile/red{
- dir = 4
- },
-/obj/effect/turf_decal/tile/red{
- dir = 1
- },
-/turf/open/floor/plasteel,
-/area/commons/locker)
"aUt" = (
-/obj/item/broken_bottle,
-/turf/open/floor/plating,
-/area/maintenance/port/fore)
-"aUu" = (
-/obj/effect/landmark/start/assistant,
-/obj/structure/chair{
- dir = 1
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
},
-/obj/structure/sign/poster/contraband/lusty_xenomorph{
- pixel_x = 32
- },
-/turf/open/floor/plating{
- icon_state = "panelscorched"
- },
-/area/maintenance/port/fore)
+/turf/open/floor/plasteel,
+/area/commons/locker)
"aUv" = (
-/obj/structure/closet/wardrobe/black,
-/obj/item/clothing/shoes/jackboots,
-/obj/item/clothing/head/beret/black,
+/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
+ dir = 4
+ },
/turf/open/floor/plasteel,
/area/commons/locker)
"aUw" = (
@@ -19630,16 +19270,6 @@
/obj/item/flashlight/lamp/green,
/turf/open/floor/wood,
/area/commons/vacant_room/office)
-"aUX" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 5
- },
-/obj/machinery/camera{
- c_tag = "Locker Room West";
- dir = 1
- },
-/turf/open/floor/plasteel,
-/area/commons/locker)
"aUY" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -20237,18 +19867,11 @@
/turf/open/floor/wood,
/area/commons/vacant_room/office)
"aWn" = (
-/obj/structure/closet,
-/obj/item/poster/random_contraband,
-/obj/item/poster/random_contraband,
-/obj/item/poster/random_contraband,
+/obj/structure/closet/wardrobe/black,
+/obj/item/clothing/shoes/jackboots,
+/obj/item/clothing/head/beret/black,
/turf/open/floor/plasteel,
/area/commons/locker)
-"aWo" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/turf/open/floor/plating,
-/area/commons/locker)
"aWp" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -20306,10 +19929,9 @@
/turf/open/floor/plating,
/area/maintenance/port)
"aWy" = (
-/obj/structure/table,
-/obj/item/storage/secure/briefcase,
-/turf/open/floor/plasteel,
-/area/commons/locker)
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/turf/closed/wall,
+/area/commons/toilet/locker)
"aWz" = (
/obj/machinery/power/apc{
areastring = "/area/commons/storage/emergency/port";
@@ -20792,12 +20414,6 @@
},
/turf/open/floor/plasteel,
/area/service/hydroponics)
-"aXp" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
-/turf/open/floor/plasteel,
-/area/commons/locker)
"aXq" = (
/obj/structure/disposalpipe/segment{
dir = 4
@@ -20818,7 +20434,6 @@
/obj/effect/turf_decal/tile/red{
dir = 4
},
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel,
/area/commons/locker)
"aXt" = (
@@ -21113,13 +20728,6 @@
},
/turf/open/floor/wood,
/area/commons/vacant_room/office)
-"aYe" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
-/turf/open/floor/plasteel,
-/area/commons/locker)
"aYf" = (
/obj/structure/disposalpipe/segment{
dir = 4
@@ -21579,17 +21187,6 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/wood,
/area/commons/vacant_room/office)
-"aZo" = (
-/obj/structure/table/reinforced,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
-/obj/machinery/door/poddoor/shutters{
- id = "commissaryshutters";
- name = "Vacant Commissary Shutters"
- },
-/turf/open/floor/plasteel,
-/area/commons/locker)
"aZp" = (
/obj/structure/rack,
/obj/item/electronics/apc,
@@ -21624,64 +21221,39 @@
/turf/open/floor/plating,
/area/maintenance/port)
"aZt" = (
-/obj/effect/decal/cleanable/dirt{
- desc = "A thin layer of dust coating the floor.";
- name = "dust"
+/obj/structure/toilet/secret/low_loot{
+ dir = 4
},
-/turf/open/floor/plasteel,
-/area/commons/locker)
+/obj/structure/mirror{
+ pixel_y = 32
+ },
+/obj/structure/sink{
+ pixel_y = 25
+ },
+/obj/machinery/button/door{
+ id = "LockerShitter1";
+ name = "Door Bolt Control";
+ normaldoorcontrol = 1;
+ pixel_x = 14;
+ pixel_y = 38;
+ specialfunctions = 4
+ },
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/open/floor/mineral/titanium/blue,
+/area/commons/toilet/locker)
"aZu" = (
/obj/machinery/photocopier,
/turf/open/floor/wood,
/area/command/meeting_room)
"aZv" = (
-/obj/item/storage/secure/safe{
- pixel_y = 32
+/obj/machinery/door/airlock{
+ id_tag = "LockerShitter1";
+ name = "Unit 1"
},
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
- dir = 4
- },
-/turf/open/floor/plasteel,
-/area/commons/locker)
-"aZw" = (
-/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
- dir = 4
- },
-/obj/structure/table,
-/obj/machinery/button/door{
- id = "commissaryshutters";
- name = "Commissary Shutters Control";
- pixel_x = 24;
- pixel_y = 6;
- req_access_txt = null
- },
-/obj/item/paper_bin{
- pixel_x = -6;
- pixel_y = 4
- },
-/obj/item/pen,
-/turf/open/floor/plasteel,
-/area/commons/locker)
-"aZx" = (
-/obj/effect/turf_decal/tile/blue,
-/obj/effect/turf_decal/tile/red{
- dir = 1
- },
-/obj/effect/turf_decal/tile/yellow{
- dir = 8
- },
-/obj/structure/window,
-/obj/structure/window{
- dir = 8
- },
-/obj/effect/turf_decal/tile/yellow{
- dir = 4
- },
-/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
- dir = 4
- },
-/turf/open/floor/plasteel,
-/area/commons/locker)
+/turf/open/floor/mineral/titanium/blue,
+/area/commons/toilet/locker)
"aZy" = (
/obj/machinery/camera{
c_tag = "Conference Room"
@@ -22009,13 +21581,6 @@
},
/turf/open/floor/wood,
/area/service/library)
-"baw" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
-/turf/open/floor/plasteel,
-/area/commons/locker)
"bax" = (
/obj/structure/chair/comfy/black{
dir = 4
@@ -22146,17 +21711,6 @@
},
/turf/open/floor/plating,
/area/maintenance/port)
-"baO" = (
-/obj/structure/table/reinforced,
-/obj/machinery/door/poddoor/shutters{
- id = "commissaryshutters";
- name = "Vacant Commissary Shutters"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
-/turf/open/floor/plasteel,
-/area/commons/locker)
"baP" = (
/obj/structure/table/wood,
/obj/item/storage/fancy/donut_box,
@@ -22336,16 +21890,6 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/closed/wall/r_wall,
/area/ai_monitored/turret_protected/ai_upload)
-"bbq" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 6
- },
-/obj/structure/chair{
- dir = 4
- },
-/turf/open/floor/plasteel,
-/area/commons/locker)
"bbs" = (
/obj/structure/window/reinforced{
dir = 8
@@ -22493,14 +22037,12 @@
/turf/open/floor/plating,
/area/maintenance/port)
"bbL" = (
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
- dir = 4
+/obj/machinery/door/airlock{
+ id_tag = "LockerShitter2";
+ name = "Unit 2"
},
-/obj/structure/rack,
-/obj/item/storage/toolbox/emergency,
-/obj/machinery/light/small,
-/turf/open/floor/plasteel,
-/area/commons/locker)
+/turf/open/floor/mineral/titanium/blue,
+/area/commons/toilet/locker)
"bbM" = (
/obj/item/book/manual/wiki/security_space_law,
/obj/structure/table/wood,
@@ -22711,13 +22253,6 @@
},
/turf/open/floor/plasteel,
/area/hallway/primary/starboard)
-"bct" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/machinery/airalarm{
- pixel_y = 23
- },
-/turf/open/floor/plasteel/freezer,
-/area/commons/toilet/locker)
"bcu" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/machinery/door/airlock/maintenance{
@@ -23198,13 +22733,6 @@
},
/turf/open/floor/carpet,
/area/command/meeting_room)
-"bdJ" = (
-/obj/machinery/door/airlock{
- id_tag = "LockerShitter1";
- name = "Unit 1"
- },
-/turf/open/floor/mineral/titanium/blue,
-/area/commons/toilet/locker)
"bdK" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -23212,19 +22740,6 @@
/obj/machinery/holopad/secure,
/turf/open/floor/carpet,
/area/command/meeting_room)
-"bdL" = (
-/obj/machinery/light,
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 8
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 9
- },
-/turf/open/floor/plasteel/cafeteria,
-/area/commons/locker)
"bdN" = (
/obj/effect/spawner/structure/window,
/turf/open/floor/plating,
@@ -23885,22 +23400,6 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plating,
/area/maintenance/port)
-"bfr" = (
-/obj/structure/noticeboard{
- dir = 8;
- pixel_x = 27
- },
-/obj/machinery/light{
- dir = 4
- },
-/turf/open/floor/wood,
-/area/command/meeting_room)
-"bfs" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 5
- },
-/turf/closed/wall/r_wall,
-/area/ai_monitored/turret_protected/ai_upload)
"bft" = (
/obj/machinery/status_display/ai,
/obj/structure/cable{
@@ -23914,13 +23413,6 @@
},
/turf/closed/wall/r_wall,
/area/ai_monitored/turret_protected/ai_upload)
-"bfv" = (
-/turf/closed/wall/r_wall,
-/area/ai_monitored/turret_protected/ai_upload)
-"bfw" = (
-/obj/machinery/status_display/evac,
-/turf/closed/wall/r_wall,
-/area/ai_monitored/turret_protected/ai_upload)
"bfx" = (
/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
dir = 8
@@ -23943,12 +23435,6 @@
},
/turf/open/floor/wood,
/area/command/heads_quarters/captain)
-"bfz" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 9
- },
-/turf/closed/wall/r_wall,
-/area/ai_monitored/turret_protected/ai_upload)
"bfA" = (
/obj/structure/table/wood,
/obj/item/hand_tele,
@@ -24243,13 +23729,6 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plating,
/area/maintenance/port)
-"bgr" = (
-/obj/machinery/door/airlock{
- id_tag = "LockerShitter2";
- name = "Unit 2"
- },
-/turf/open/floor/mineral/titanium/blue,
-/area/commons/toilet/locker)
"bgt" = (
/obj/effect/spawner/lootdrop/maintenance,
/turf/open/floor/plating,
@@ -24405,40 +23884,6 @@
},
/turf/open/floor/plasteel/white,
/area/medical/medbay/lobby)
-"bgS" = (
-/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
- dir = 8
- },
-/turf/open/floor/plasteel,
-/area/commons/storage/primary)
-"bgT" = (
-/obj/machinery/computer/communications{
- dir = 8
- },
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/turf/open/floor/wood,
-/area/command/heads_quarters/captain)
-"bgU" = (
-/obj/structure/chair/comfy/brown{
- dir = 4
- },
-/obj/effect/landmark/start/captain,
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/turf/open/floor/wood,
-/area/command/heads_quarters/captain)
-"bgV" = (
-/obj/structure/table/wood,
-/obj/item/book/manual/wiki/security_space_law,
-/obj/item/coin/plasma,
-/turf/open/floor/wood,
-/area/command/heads_quarters/captain)
-"bgW" = (
-/obj/structure/cable{
- icon_state = "1-2"
- },
-/obj/machinery/holopad/secure,
-/turf/open/floor/wood,
-/area/command/heads_quarters/captain)
"bgX" = (
/obj/structure/table/wood,
/obj/machinery/airalarm{
@@ -39358,19 +38803,6 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel/white,
/area/science/circuit)
-"bPM" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 9
- },
-/obj/effect/turf_decal/stripes/line,
-/obj/structure/disposalpipe/segment{
- dir = 4
- },
-/obj/structure/cable{
- icon_state = "1-8"
- },
-/turf/open/floor/plasteel,
-/area/science/circuit)
"bPN" = (
/turf/closed/wall,
/area/science/misc_lab)
@@ -40556,15 +39988,6 @@
},
/turf/open/floor/engine,
/area/science/misc_lab)
-"bTo" = (
-/obj/structure/table/reinforced,
-/obj/item/paper_bin,
-/obj/item/pen,
-/obj/machinery/light{
- dir = 8
- },
-/turf/open/floor/plasteel/white,
-/area/science/circuit)
"bTp" = (
/obj/structure/table/reinforced,
/obj/item/stack/sheet/glass/fifty,
@@ -41347,11 +40770,16 @@
/turf/open/floor/plasteel,
/area/science/circuit)
"bVt" = (
-/obj/machinery/door/airlock{
- name = "Shower Room"
+/obj/machinery/airalarm{
+ dir = 8;
+ pixel_x = 24
},
-/turf/open/floor/plasteel/freezer,
-/area/commons/toilet)
+/obj/effect/turf_decal/stripes/line{
+ dir = 5
+ },
+/obj/structure/target_stake,
+/turf/open/floor/plasteel,
+/area/science/circuit)
"bVu" = (
/obj/structure/lattice,
/obj/machinery/atmospherics/pipe/simple/yellow/visible,
@@ -42088,13 +41516,6 @@
"bXs" = (
/turf/open/floor/plasteel/white,
/area/science/circuit)
-"bXt" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/obj/structure/cable{
- icon_state = "1-2"
- },
-/turf/open/floor/plasteel,
-/area/science/circuit)
"bXv" = (
/obj/item/stack/rods,
/turf/open/space,
@@ -45166,13 +44587,6 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/closed/wall/r_wall,
/area/science/misc_lab)
-"cfv" = (
-/obj/structure/plasticflaps/opaque,
-/obj/structure/sign/poster/contraband/free_drone{
- pixel_y = 32
- },
-/turf/open/floor/carpet/royalblue,
-/area/maintenance/starboard/aft)
"cfw" = (
/turf/closed/wall/r_wall,
/area/maintenance/solars/port/aft)
@@ -51580,17 +50994,6 @@
/obj/effect/landmark/event_spawn,
/turf/open/floor/plating,
/area/service/hydroponics)
-"cBh" = (
-/obj/effect/landmark/event_spawn,
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 8
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/turf/open/floor/plasteel/cafeteria,
-/area/commons/locker)
"cBi" = (
/obj/effect/landmark/event_spawn,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
@@ -51624,17 +51027,6 @@
/obj/machinery/light,
/turf/open/floor/plasteel,
/area/hallway/primary/starboard)
-"cBn" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/obj/structure/sink{
- dir = 4;
- pixel_x = 11
- },
-/obj/structure/mirror{
- pixel_x = 28
- },
-/turf/open/floor/plasteel/freezer,
-/area/commons/toilet/locker)
"cBo" = (
/obj/effect/landmark/event_spawn,
/turf/open/floor/wood,
@@ -52095,12 +51487,6 @@
/obj/structure/closet/boxinggloves,
/turf/open/floor/plasteel,
/area/commons/fitness)
-"cFG" = (
-/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
- dir = 4
- },
-/turf/open/floor/plasteel,
-/area/commons/locker)
"cGf" = (
/obj/structure/sign/poster/contraband/random{
pixel_y = 32
@@ -52669,15 +52055,6 @@
"cPb" = (
/turf/open/floor/wood/wood_diagonal,
/area/maintenance/port/fore)
-"cPn" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/machinery/light/small{
- dir = 4
- },
-/obj/item/soap,
-/obj/effect/landmark/xeno_spawn,
-/turf/open/floor/plasteel/freezer,
-/area/commons/toilet)
"cPA" = (
/obj/machinery/atmospherics/components/binary/valve{
dir = 4
@@ -53077,29 +52454,6 @@
},
/turf/open/floor/plating,
/area/maintenance/department/medical/morgue)
-"cTT" = (
-/obj/structure/cable{
- icon_state = "0-2"
- },
-/obj/effect/turf_decal/bot_white,
-/obj/effect/turf_decal/tile/neutral{
- dir = 1
- },
-/obj/effect/turf_decal/tile/neutral,
-/obj/effect/turf_decal/tile/neutral{
- dir = 4
- },
-/obj/effect/turf_decal/tile/neutral{
- dir = 8
- },
-/obj/structure/cable{
- icon_state = "2-4"
- },
-/obj/structure/cable{
- icon_state = "2-8"
- },
-/turf/open/floor/plasteel/dark,
-/area/command/gateway)
"cTX" = (
/obj/structure/cable{
icon_state = "0-2"
@@ -53122,6 +52476,17 @@
},
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
+"cUb" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/structure/disposalpipe/segment,
+/obj/structure/grille/broken,
+/obj/effect/decal/cleanable/blood/old,
+/obj/item/kirbyplants/random,
+/turf/open/floor/plating,
+/area/maintenance/starboard/aft)
"cUx" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/structure/cable{
@@ -53149,12 +52514,6 @@
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden,
/turf/open/floor/plasteel/white,
/area/science/circuit)
-"cVX" = (
-/mob/living/simple_animal/bot/secbot/grievous/toy{
- name = "Rave Bot 9001"
- },
-/turf/open/floor/light/colour_cycle/dancefloor_a,
-/area/maintenance/starboard/aft)
"cXU" = (
/obj/effect/turf_decal/tile/red,
/obj/machinery/light{
@@ -53221,19 +52580,12 @@
},
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
-"ddj" = (
-/obj/effect/turf_decal/tile/blue{
- dir = 4
+"ddl" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 6
},
-/obj/effect/turf_decal/tile/blue{
- dir = 8
- },
-/obj/structure/window{
- dir = 1
- },
-/obj/machinery/washing_machine,
-/turf/open/floor/plasteel/cafeteria,
-/area/commons/locker)
+/turf/open/floor/plasteel/freezer,
+/area/commons/toilet/locker)
"ddI" = (
/obj/machinery/door/airlock/public/glass{
name = "Central Access"
@@ -53250,21 +52602,6 @@
icon_state = "wood-broken6"
},
/area/maintenance/starboard/aft)
-"ddV" = (
-/obj/effect/spawner/structure/window/reinforced,
-/obj/structure/cable{
- icon_state = "0-2"
- },
-/obj/structure/cable,
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/turf/open/floor/plating,
-/area/command/gateway)
-"def" = (
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
- dir = 1
- },
-/turf/open/floor/plasteel/freezer,
-/area/commons/toilet/locker)
"dev" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -53287,20 +52624,20 @@
/turf/open/floor/plating,
/area/maintenance/port)
"dfh" = (
-/obj/structure/chair/stool{
- pixel_y = 8
+/obj/machinery/power/apc{
+ areastring = "/area/science/circuit";
+ dir = 4;
+ name = "Circuitry Lab APC";
+ pixel_x = 24
},
-/obj/machinery/light/small/broken{
- dir = 8
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
},
-/obj/item/glasswork/glass_base/glasses_frame_1{
- pixel_x = -6;
- pixel_y = 13
+/obj/structure/cable{
+ icon_state = "0-8"
},
-/turf/open/floor/plating{
- icon_state = "platingdmg3"
- },
-/area/commons/arcade)
+/turf/open/floor/plasteel,
+/area/science/circuit)
"dfL" = (
/obj/structure/reagent_dispensers/keg/gargle,
/turf/open/floor/wood,
@@ -53375,6 +52712,12 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/closed/wall/r_wall,
/area/maintenance/disposal/incinerator)
+"dsi" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/turf/open/floor/carpet/arcade,
+/area/commons/arcade)
"dsJ" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/structure/table/glass,
@@ -53383,13 +52726,19 @@
},
/turf/open/floor/wood/wood_large,
/area/service/chapel/main)
-"dtx" = (
-/obj/structure/cable{
- icon_state = "1-2"
+"dvb" = (
+/obj/structure/table,
+/obj/item/trash/tray,
+/obj/item/trash/boritos,
+/obj/item/trash/can,
+/obj/item/reagent_containers/food/drinks/sillycup{
+ pixel_x = 8;
+ pixel_y = 10
},
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/turf/open/floor/mineral/titanium/blue,
-/area/commons/toilet)
+/turf/open/floor/plating{
+ icon_state = "panelscorched"
+ },
+/area/commons/arcade)
"dvc" = (
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
dir = 4
@@ -53406,6 +52755,19 @@
/obj/machinery/gear_painter,
/turf/open/floor/wood,
/area/maintenance/bar)
+"dyC" = (
+/obj/effect/turf_decal/tile/red{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/red,
+/obj/effect/turf_decal/tile/red{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/turf/open/floor/plasteel,
+/area/commons/locker)
"dyE" = (
/obj/structure/cable{
icon_state = "0-4"
@@ -53446,23 +52808,6 @@
/obj/machinery/meter,
/turf/open/floor/plasteel,
/area/engineering/atmos)
-"dBm" = (
-/obj/structure/chair/stool{
- pixel_y = 8
- },
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
-/obj/item/cigbutt{
- pixel_x = -12;
- pixel_y = 22
- },
-/obj/item/cigbutt{
- pixel_x = -15;
- pixel_y = 16
- },
-/turf/open/floor/carpet/arcade,
-/area/commons/arcade)
"dCr" = (
/obj/structure/pool/Rboard,
/turf/open/floor/plasteel/yellowsiding{
@@ -53483,14 +52828,6 @@
},
/turf/open/floor/plasteel,
/area/security/range)
-"dEh" = (
-/obj/structure/window/reinforced,
-/obj/machinery/airalarm{
- dir = 8;
- pixel_x = 24
- },
-/turf/open/floor/wood,
-/area/service/theater)
"dEX" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/visible,
/obj/machinery/requests_console{
@@ -53504,12 +52841,17 @@
"dFX" = (
/turf/closed/wall,
/area/commons/fitness/pool)
-"dHp" = (
-/obj/machinery/shower{
- dir = 1
+"dGa" = (
+/obj/machinery/door/airlock/maintenance{
+ req_access_txt = "12"
},
-/turf/open/floor/plasteel/freezer,
-/area/commons/toilet)
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/turf/open/floor/plating{
+ icon_state = "platingdmg3"
+ },
+/area/commons/arcade)
"dIu" = (
/obj/structure/chair/sofa{
dir = 8
@@ -53597,6 +52939,14 @@
},
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
+"dYl" = (
+/obj/effect/spawner/structure/window/reinforced,
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/plating,
+/area/command/gateway)
"dYZ" = (
/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating,
@@ -53696,6 +53046,18 @@
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
+"eky" = (
+/obj/structure/table/wood,
+/obj/item/reagent_containers/food/snacks/baguette,
+/obj/structure/mirror{
+ pixel_y = 32
+ },
+/obj/item/toy/crayon/spraycan/mimecan,
+/obj/item/toy/dummy,
+/turf/open/floor/plasteel/white/side{
+ dir = 4
+ },
+/area/service/theater)
"elh" = (
/obj/structure/chair/comfy/black{
dir = 8
@@ -53820,6 +53182,12 @@
},
/turf/open/floor/plasteel,
/area/hallway/primary/port)
+"exX" = (
+/obj/machinery/door/airlock{
+ name = "Shower Room"
+ },
+/turf/open/floor/plasteel/freezer,
+/area/commons/toilet)
"eyq" = (
/obj/machinery/atmospherics/components/unary/outlet_injector/on,
/turf/open/floor/plating,
@@ -53850,6 +53218,12 @@
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
+"eAe" = (
+/obj/structure/dresser,
+/turf/open/floor/plasteel/white/side{
+ dir = 4
+ },
+/area/service/theater)
"eAG" = (
/obj/item/clothing/under/misc/pj/blue,
/obj/item/clothing/shoes/sneakers/white,
@@ -53916,20 +53290,6 @@
icon_state = "panelscorched"
},
/area/maintenance/starboard/aft)
-"eEe" = (
-/obj/effect/turf_decal/tile/blue{
- dir = 8
- },
-/obj/effect/turf_decal/tile/red{
- dir = 1
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/obj/effect/turf_decal/tile/red,
-/obj/effect/landmark/start/clown,
-/turf/open/floor/plasteel,
-/area/service/theater)
"eFx" = (
/obj/effect/turf_decal/tile/red{
dir = 1
@@ -53987,6 +53347,12 @@
},
/turf/open/floor/plating,
/area/maintenance/fore/secondary)
+"eOu" = (
+/obj/structure/table/wood,
+/obj/item/book/manual/wiki/security_space_law,
+/obj/item/coin/plasma,
+/turf/open/floor/wood,
+/area/command/heads_quarters/captain)
"eQb" = (
/turf/open/floor/carpet,
/area/commons/dorms)
@@ -54003,6 +53369,23 @@
/obj/structure/closet/secure_closet/personal/cabinet,
/turf/open/floor/carpet,
/area/commons/dorms)
+"eTA" = (
+/obj/structure/table/wood/fancy,
+/obj/item/reagent_containers/food/condiment/saltshaker{
+ pixel_x = -3;
+ pixel_y = 20
+ },
+/obj/item/reagent_containers/food/condiment/peppermill{
+ dir = 1;
+ pixel_x = 3;
+ pixel_y = 20
+ },
+/obj/structure/sign/poster/contraband/eat{
+ pixel_y = 32;
+ poster_item_desc = "This poster promotes obesity, it also promotes giving the Chef a reason to keep their job."
+ },
+/turf/open/floor/wood,
+/area/service/bar)
"eUy" = (
/obj/machinery/door/airlock{
name = "Starboard Emergency Storage"
@@ -54016,6 +53399,10 @@
},
/turf/open/space,
/area/space/nearstation)
+"eUX" = (
+/obj/machinery/jukebox/disco,
+/turf/open/floor/light/colour_cycle/dancefloor_b,
+/area/maintenance/starboard/aft)
"eVC" = (
/obj/effect/spawner/structure/window,
/obj/machinery/door/firedoor,
@@ -54063,15 +53450,6 @@
/obj/effect/landmark/start/paramedic,
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
-"eZu" = (
-/obj/machinery/door/airlock{
- name = "Unisex Restrooms"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
-/turf/open/floor/plasteel/freezer,
-/area/commons/toilet/locker)
"fbp" = (
/obj/structure/tank_dispenser,
/obj/effect/turf_decal/bot,
@@ -54122,20 +53500,11 @@
},
/turf/open/floor/wood,
/area/service/bar)
-"fgG" = (
-/obj/machinery/power/apc{
- areastring = "/area/service/theater";
- dir = 8;
- name = "Theatre APC";
- pixel_x = -25
- },
-/obj/structure/cable{
- icon_state = "0-4"
- },
-/turf/open/floor/plasteel/white/side{
- dir = 4
- },
-/area/service/theater)
+"fgl" = (
+/obj/structure/closet/crate/bin,
+/obj/item/coin/silver,
+/turf/open/floor/carpet/arcade,
+/area/commons/arcade)
"fhu" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -54146,6 +53515,13 @@
/obj/item/clothing/mask/gas/owl_mask,
/turf/open/floor/plating,
/area/maintenance/port/fore)
+"fiv" = (
+/obj/effect/spawner/lootdrop/cigars_cases,
+/obj/structure/table,
+/turf/open/floor/plating{
+ icon_state = "platingdmg1"
+ },
+/area/commons/arcade)
"fiy" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 10
@@ -54163,6 +53539,12 @@
/obj/structure/lattice,
/turf/open/space,
/area/space/nearstation)
+"fkh" = (
+/mob/living/simple_animal/bot/secbot/grievous/toy{
+ name = "Rave Bot 9001"
+ },
+/turf/open/floor/light/colour_cycle/dancefloor_a,
+/area/maintenance/starboard/aft)
"fkW" = (
/obj/structure/cable/white,
/obj/structure/cable/white{
@@ -54188,6 +53570,10 @@
},
/turf/open/floor/plasteel,
/area/commons/dorms)
+"flG" = (
+/obj/machinery/computer/arcade,
+/turf/open/floor/carpet/arcade,
+/area/commons/arcade)
"flP" = (
/obj/machinery/hydroponics/soil{
pixel_y = 8
@@ -54202,11 +53588,6 @@
},
/turf/open/floor/wood/wood_diagonal,
/area/maintenance/port/fore)
-"fne" = (
-/turf/open/floor/plasteel/white/side{
- dir = 4
- },
-/area/service/theater)
"fnC" = (
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
dir = 4
@@ -54220,6 +53601,25 @@
},
/turf/open/floor/plasteel,
/area/hallway/secondary/service)
+"fnE" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/red,
+/obj/structure/cable{
+ icon_state = "1-8"
+ },
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 1
+ },
+/turf/open/floor/plasteel,
+/area/service/theater)
"foT" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -54341,6 +53741,30 @@
/obj/structure/disposalpipe/segment,
/turf/closed/wall,
/area/medical/storage)
+"fvU" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/red,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/obj/structure/table/wood,
+/obj/item/flashlight/lamp/bananalamp{
+ pixel_y = 3
+ },
+/obj/machinery/light{
+ dir = 1
+ },
+/obj/machinery/requests_console{
+ department = "Theatre";
+ name = "theatre RC";
+ pixel_y = 32
+ },
+/turf/open/floor/plasteel/white/side{
+ dir = 4
+ },
+/area/service/theater)
"fvY" = (
/obj/machinery/computer/cryopod{
pixel_y = 26
@@ -54420,6 +53844,25 @@
},
/turf/open/floor/plating,
/area/service/abandoned_gambling_den)
+"fBW" = (
+/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
+ dir = 4
+ },
+/obj/structure/table,
+/obj/machinery/button/door{
+ id = "commissaryshutters";
+ name = "Commissary Shutters Control";
+ pixel_x = 24;
+ pixel_y = 6;
+ req_access_txt = null
+ },
+/obj/item/paper_bin{
+ pixel_x = -6;
+ pixel_y = 4
+ },
+/obj/item/pen,
+/turf/open/floor/plasteel,
+/area/commons/locker)
"fCx" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -54431,11 +53874,44 @@
},
/turf/open/floor/plasteel,
/area/commons/fitness)
-"fFh" = (
-/obj/effect/decal/cleanable/oil/slippery,
-/obj/structure/reagent_dispensers/beerkeg,
-/turf/open/floor/light/colour_cycle/dancefloor_a,
-/area/maintenance/starboard/aft)
+"fCJ" = (
+/obj/structure/sign/poster/contraband/missing_gloves{
+ pixel_x = -32
+ },
+/turf/open/floor/carpet/arcade,
+/area/commons/arcade)
+"fDn" = (
+/obj/structure/table,
+/obj/item/trash/chips{
+ pixel_x = -4;
+ pixel_y = 1
+ },
+/obj/item/reagent_containers/food/drinks/beer/light{
+ pixel_x = 7
+ },
+/obj/item/cigbutt{
+ pixel_x = 10;
+ pixel_y = 17
+ },
+/turf/open/floor/plating,
+/area/maintenance/port/fore)
+"fFl" = (
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 8
+ },
+/obj/structure/window{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/red,
+/obj/effect/turf_decal/tile/red{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/plasteel,
+/area/commons/locker)
"fFA" = (
/obj/effect/turf_decal/stripes/line{
dir = 4
@@ -54478,14 +53954,6 @@
/obj/effect/turf_decal/tile/red,
/turf/open/floor/plasteel,
/area/security/processing)
-"fKl" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/obj/effect/landmark/event_spawn,
-/obj/structure/cable{
- icon_state = "2-4"
- },
-/turf/open/floor/plasteel,
-/area/science/circuit)
"fKC" = (
/obj/structure/chair/office/dark{
dir = 1
@@ -54527,6 +53995,12 @@
},
/turf/open/floor/plasteel,
/area/hallway/secondary/entry)
+"fOK" = (
+/obj/machinery/shower{
+ dir = 1
+ },
+/turf/open/floor/plasteel/freezer,
+/area/commons/toilet)
"fPi" = (
/obj/effect/decal/cleanable/oil{
icon_state = "floor6"
@@ -54538,6 +54012,20 @@
/obj/structure/reagent_dispensers/water_cooler,
/turf/open/floor/plasteel/dark,
/area/hallway/primary/central)
+"fRe" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/structure/window{
+ dir = 1
+ },
+/obj/structure/bedsheetbin/color,
+/obj/structure/table,
+/turf/open/floor/plasteel/cafeteria,
+/area/commons/locker)
"fSO" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/visible,
/obj/machinery/atmospherics/pipe/simple/orange/visible{
@@ -54562,15 +54050,12 @@
/obj/item/pen/fountain,
/turf/open/floor/plasteel/dark,
/area/hallway/primary/central)
-"fVA" = (
-/obj/structure/chair/stool{
- pixel_y = 8
+"fWi" = (
+/obj/structure/sign/poster/contraband/robust_softdrinks{
+ pixel_y = 32
},
-/mob/living/simple_animal/opossum{
- name = "trash"
- },
-/turf/open/floor/carpet/royalblue,
-/area/maintenance/starboard/aft)
+/turf/open/floor/wood,
+/area/service/bar)
"fZm" = (
/obj/structure/chair/sofa/left,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
@@ -54578,6 +54063,12 @@
},
/turf/open/floor/plasteel,
/area/commons/fitness)
+"fZR" = (
+/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
+ dir = 8
+ },
+/turf/open/floor/plasteel,
+/area/commons/storage/primary)
"gav" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 5
@@ -54643,6 +54134,15 @@
},
/turf/open/floor/plating,
/area/maintenance/department/medical/morgue)
+"gcx" = (
+/obj/structure/chair/stool{
+ pixel_y = 8
+ },
+/mob/living/simple_animal/opossum{
+ name = "garbage"
+ },
+/turf/open/floor/carpet/royalblue,
+/area/maintenance/starboard/aft)
"gcF" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -54687,6 +54187,9 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel,
/area/commons/fitness)
+"giy" = (
+/turf/open/floor/carpet/arcade,
+/area/commons/arcade)
"giT" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -54710,6 +54213,13 @@
},
/turf/open/floor/plasteel,
/area/hallway/primary/central)
+"got" = (
+/obj/structure/closet,
+/obj/item/poster/random_contraband,
+/obj/item/poster/random_contraband,
+/obj/item/poster/random_contraband,
+/turf/open/floor/plasteel,
+/area/commons/locker)
"gpD" = (
/obj/effect/turf_decal/bot_white/left,
/obj/effect/turf_decal/tile/neutral{
@@ -54751,11 +54261,6 @@
},
/turf/open/floor/plasteel/dark,
/area/commons/fitness)
-"gsi" = (
-/obj/effect/spawner/lootdrop/maintenance,
-/obj/structure/closet,
-/turf/open/floor/plating,
-/area/maintenance/starboard/aft)
"gsM" = (
/obj/structure/table,
/obj/effect/spawner/lootdrop/maintenance,
@@ -54764,17 +54269,6 @@
"gvX" = (
/turf/open/floor/plasteel/yellowsiding,
/area/commons/fitness/pool)
-"gwd" = (
-/obj/machinery/airalarm{
- dir = 8;
- pixel_x = 24
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 5
- },
-/obj/structure/target_stake,
-/turf/open/floor/plasteel,
-/area/science/circuit)
"gxc" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -54800,6 +54294,9 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel,
/area/security/brig)
+"gyQ" = (
+/turf/open/floor/plasteel/freezer,
+/area/commons/toilet)
"gzf" = (
/obj/structure/window/reinforced/tinted{
dir = 8
@@ -54859,6 +54356,30 @@
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/wood,
/area/maintenance/starboard/aft)
+"gER" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/red,
+/turf/open/floor/plasteel/white/side{
+ dir = 4
+ },
+/area/service/theater)
+"gFs" = (
+/obj/effect/landmark/start/assistant,
+/obj/structure/chair{
+ dir = 1
+ },
+/obj/structure/sign/poster/contraband/lusty_xenomorph{
+ pixel_x = 32
+ },
+/turf/open/floor/plating{
+ icon_state = "panelscorched"
+ },
+/area/maintenance/port/fore)
+"gGK" = (
+/turf/open/floor/carpet/royalblue,
+/area/maintenance/starboard/aft)
"gIU" = (
/obj/effect/turf_decal/stripes/line{
dir = 9
@@ -54894,6 +54415,20 @@
/obj/structure/bedsheetbin/towel,
/turf/open/floor/wood/wood_diagonal,
/area/maintenance/port/fore)
+"gLw" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/red,
+/obj/effect/landmark/start/clown,
+/turf/open/floor/plasteel,
+/area/service/theater)
"gLz" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -54930,13 +54465,6 @@
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
-"gNC" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/machinery/shower{
- dir = 1
- },
-/turf/open/floor/plasteel/freezer,
-/area/commons/toilet)
"gNE" = (
/obj/structure/cable{
icon_state = "0-8"
@@ -54948,6 +54476,21 @@
},
/turf/open/floor/plating,
/area/security/brig)
+"gOF" = (
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
+ dir = 8
+ },
+/mob/living/simple_animal/bot/mulebot{
+ beacon_freq = 1400;
+ home_destination = "QM #1";
+ name = "Massive Load";
+ suffix = "#1"
+ },
+/obj/structure/sign/poster/official/high_class_martini{
+ pixel_x = -32
+ },
+/turf/open/floor/carpet/royalblue,
+/area/maintenance/starboard/aft)
"gOZ" = (
/obj/machinery/door/airlock/maintenance{
req_access_txt = "12"
@@ -54960,29 +54503,6 @@
},
/turf/open/floor/plating,
/area/maintenance/fore)
-"gQX" = (
-/obj/structure/toilet/secret/low_loot{
- dir = 4
- },
-/obj/structure/mirror{
- pixel_y = 32
- },
-/obj/structure/sink{
- pixel_y = 25
- },
-/obj/machinery/button/door{
- id = "LockerShitter2";
- name = "Door Bolt Control";
- normaldoorcontrol = 1;
- pixel_x = 14;
- pixel_y = 38;
- specialfunctions = 4
- },
-/obj/machinery/light/small{
- dir = 8
- },
-/turf/open/floor/mineral/titanium/blue,
-/area/commons/toilet/locker)
"gRV" = (
/turf/open/floor/wood{
icon_state = "wood-broken6"
@@ -55041,6 +54561,13 @@
},
/turf/open/floor/plating,
/area/maintenance/port/fore)
+"gZB" = (
+/obj/item/clothing/mask/cigarette{
+ pixel_x = -6;
+ pixel_y = 14
+ },
+/turf/open/floor/plating,
+/area/maintenance/port/fore)
"gZG" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -55129,6 +54656,13 @@
},
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
+"hlS" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/mineral/titanium/blue,
+/area/commons/toilet)
"hlT" = (
/obj/machinery/door/airlock/external{
name = "Labor Camp Shuttle Airlock";
@@ -55164,6 +54698,29 @@
},
/turf/open/floor/plating,
/area/security/range)
+"hoL" = (
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
+/obj/effect/turf_decal/bot_white,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/neutral,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/neutral{
+ dir = 8
+ },
+/obj/structure/cable{
+ icon_state = "2-4"
+ },
+/obj/structure/cable{
+ icon_state = "2-8"
+ },
+/turf/open/floor/plasteel/dark,
+/area/command/gateway)
"hrF" = (
/obj/structure/lattice/catwalk,
/obj/structure/cable{
@@ -55188,6 +54745,14 @@
/obj/item/kirbyplants/random,
/turf/open/floor/plating,
/area/maintenance/port/fore)
+"hty" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/effect/spawner/structure/window/reinforced,
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
+/turf/open/floor/plating,
+/area/command/gateway)
"hxn" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/machinery/atmospherics/pipe/simple/green/visible,
@@ -55232,11 +54797,12 @@
/turf/open/floor/plating,
/area/maintenance/starboard/fore)
"hIL" = (
-/obj/structure/sign/poster/contraband/missing_gloves{
- pixel_x = -32
+/obj/structure/sign/poster/contraband/space_up{
+ pixel_x = -32;
+ pixel_y = 32
},
-/turf/open/floor/carpet/arcade,
-/area/commons/arcade)
+/turf/open/floor/wood,
+/area/service/bar)
"hIM" = (
/obj/machinery/door/airlock{
name = "Unisex Restrooms"
@@ -55250,15 +54816,12 @@
/obj/item/pen,
/turf/open/floor/plasteel/dark,
/area/medical/morgue)
-"hOn" = (
-/obj/structure/chair/stool{
- pixel_y = 8
+"hNm" = (
+/obj/machinery/door/airlock/maintenance{
+ req_access_txt = "12"
},
-/mob/living/simple_animal/opossum{
- name = "garbage"
- },
-/turf/open/floor/carpet/royalblue,
-/area/maintenance/starboard/aft)
+/turf/open/floor/plating,
+/area/commons/locker)
"hOv" = (
/obj/structure/table/wood/fancy,
/obj/machinery/atmospherics/components/unary/vent_pump/on{
@@ -55268,12 +54831,6 @@
/obj/item/reagent_containers/food/snacks/burger/plain,
/turf/open/floor/wood,
/area/service/bar)
-"hPs" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 6
- },
-/turf/open/floor/plasteel/freezer,
-/area/commons/toilet/locker)
"hPP" = (
/obj/structure/disposalpipe/segment{
dir = 4
@@ -55283,6 +54840,15 @@
},
/turf/closed/wall,
/area/cargo/warehouse)
+"hQX" = (
+/obj/effect/spawner/structure/window/reinforced,
+/obj/structure/cable{
+ icon_state = "0-8"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/obj/structure/cable,
+/turf/open/floor/plating,
+/area/command/gateway)
"hQY" = (
/obj/machinery/atmospherics/pipe/simple/green/visible{
dir = 6
@@ -55341,9 +54907,6 @@
/obj/effect/spawner/structure/window/hollow/reinforced/directional,
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
-"hUJ" = (
-/turf/open/floor/carpet/royalblue,
-/area/maintenance/starboard/aft)
"hWd" = (
/obj/effect/turf_decal/tile/blue,
/obj/effect/turf_decal/tile/blue{
@@ -55363,18 +54926,6 @@
"ibK" = (
/turf/open/floor/plasteel,
/area/security/processing)
-"idD" = (
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 8
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
-/turf/open/floor/plasteel/cafeteria,
-/area/commons/locker)
"idK" = (
/obj/effect/turf_decal/tile/red{
dir = 1
@@ -55399,12 +54950,20 @@
},
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
-"igi" = (
-/turf/open/floor/carpet/arcade,
-/area/commons/arcade)
"ihR" = (
/turf/open/floor/plasteel/white,
/area/medical/medbay/lobby)
+"ihS" = (
+/obj/effect/landmark/event_spawn,
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/plasteel/cafeteria,
+/area/commons/locker)
"iiW" = (
/turf/open/floor/wood,
/area/maintenance/bar)
@@ -55486,16 +55045,6 @@
},
/turf/closed/wall,
/area/service/theater)
-"ior" = (
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
- dir = 1
- },
-/obj/machinery/camera{
- c_tag = "Locker Room Toilets";
- dir = 8
- },
-/turf/open/floor/plasteel/freezer,
-/area/commons/toilet/locker)
"iou" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/machinery/firealarm{
@@ -55522,13 +55071,6 @@
/obj/machinery/holopad,
/turf/open/floor/plasteel,
/area/security/brig)
-"itG" = (
-/obj/effect/spawner/lootdrop/cigars_cases,
-/obj/structure/table,
-/turf/open/floor/plating{
- icon_state = "platingdmg1"
- },
-/area/commons/arcade)
"itK" = (
/obj/structure/table,
/obj/effect/spawner/lootdrop/maintenance{
@@ -55572,17 +55114,6 @@
/obj/structure/table/optable,
/turf/open/floor/plasteel/white,
/area/medical/surgery)
-"ixd" = (
-/obj/structure/table,
-/obj/machinery/light/floor,
-/obj/item/reagent_containers/food/drinks/beer{
- pixel_x = -6
- },
-/obj/item/reagent_containers/blood/oilblood{
- pixel_x = 7
- },
-/turf/open/floor/carpet/royalblue,
-/area/maintenance/starboard/aft)
"iyG" = (
/obj/effect/decal/cleanable/dirt,
/obj/machinery/light/small{
@@ -55708,6 +55239,12 @@
/obj/machinery/atmospherics/components/unary/vent_pump/on,
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
+"iQg" = (
+/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
+ dir = 4
+ },
+/turf/open/floor/plating,
+/area/maintenance/starboard/aft)
"iRj" = (
/obj/effect/turf_decal/tile/red{
dir = 1
@@ -55860,6 +55397,24 @@
},
/turf/open/space,
/area/space)
+"jdu" = (
+/obj/structure/table,
+/obj/machinery/light/floor,
+/obj/machinery/light/floor,
+/obj/item/clothing/glasses/sunglasses/reagent,
+/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass{
+ pixel_x = -5;
+ pixel_y = 12
+ },
+/obj/item/storage/fancy/cigarettes/cigpack_uplift{
+ pixel_x = 8;
+ pixel_y = 8
+ },
+/obj/structure/sign/poster/contraband/borg_fancy_2{
+ pixel_y = -32
+ },
+/turf/open/floor/carpet/royalblue,
+/area/maintenance/starboard/aft)
"jdE" = (
/obj/effect/turf_decal/trimline/blue/filled/corner{
dir = 1
@@ -55891,10 +55446,27 @@
/obj/effect/landmark/blobstart,
/turf/open/floor/plating,
/area/maintenance/starboard/fore)
+"jfZ" = (
+/obj/machinery/computer/communications{
+ dir = 8
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/turf/open/floor/wood,
+/area/command/heads_quarters/captain)
"jgm" = (
-/obj/machinery/atmospherics/components/unary/vent_pump/on,
-/turf/open/floor/carpet/arcade,
-/area/commons/arcade)
+/obj/structure/disposalpipe/segment{
+ dir = 10
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 6
+ },
+/obj/machinery/camera{
+ c_tag = "Circuitry Lab";
+ dir = 8;
+ network = list("ss13","rd")
+ },
+/turf/open/floor/plasteel,
+/area/science/circuit)
"jgA" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 9
@@ -55930,6 +55502,12 @@
/obj/machinery/rnd/production/techfab/department/cargo,
/turf/open/floor/plasteel,
/area/cargo/office)
+"jmL" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 5
+ },
+/turf/closed/wall/r_wall,
+/area/ai_monitored/turret_protected/ai_upload)
"jmV" = (
/obj/structure/table/wood/fancy,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
@@ -55963,6 +55541,23 @@
icon_state = "wood-broken7"
},
/area/maintenance/bar)
+"jqD" = (
+/obj/structure/chair/stool{
+ pixel_y = 8
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/obj/item/cigbutt{
+ pixel_x = -12;
+ pixel_y = 22
+ },
+/obj/item/cigbutt{
+ pixel_x = -15;
+ pixel_y = 16
+ },
+/turf/open/floor/carpet/arcade,
+/area/commons/arcade)
"jrE" = (
/obj/item/beacon,
/turf/open/floor/plasteel/white,
@@ -56074,19 +55669,18 @@
/obj/machinery/atmospherics/pipe/manifold4w/general/visible,
/turf/open/floor/plasteel,
/area/engineering/atmos)
-"jCq" = (
-/obj/structure/disposalpipe/segment{
- dir = 5
- },
+"jBZ" = (
/obj/structure/cable{
- icon_state = "1-4"
+ icon_state = "4-8"
},
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 5
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
+ dir = 1
},
-/obj/effect/decal/cleanable/dirt,
-/turf/open/floor/plating,
-/area/maintenance/starboard/aft)
+/obj/effect/landmark/start/mime,
+/turf/open/floor/plasteel/white/side{
+ dir = 4
+ },
+/area/service/theater)
"jDr" = (
/obj/machinery/door/poddoor/preopen{
id = "atmos";
@@ -56117,6 +55711,10 @@
dir = 1
},
/area/commons/fitness)
+"jFd" = (
+/obj/effect/spawner/structure/window,
+/turf/open/floor/plating,
+/area/maintenance/port/fore)
"jFB" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 6
@@ -56261,17 +55859,42 @@
},
/turf/open/floor/plasteel,
/area/commons/fitness/pool)
+"jNr" = (
+/obj/structure/chair/stool{
+ pixel_y = 8
+ },
+/obj/item/cigbutt{
+ pixel_x = -15;
+ pixel_y = 16
+ },
+/turf/open/floor/plating/rust,
+/area/maintenance/port/fore)
"jRw" = (
/obj/machinery/computer/arcade/minesweeper{
dir = 4
},
/turf/open/floor/plasteel,
/area/security/prison)
+"jSD" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/plasteel,
+/area/hallway/primary/port)
"jSO" = (
-/obj/structure/table,
-/obj/item/flashlight/lamp,
-/turf/open/floor/carpet/arcade,
-/area/commons/arcade)
+/obj/machinery/light{
+ dir = 4
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/science/circuit)
"jUV" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -56412,6 +56035,13 @@
},
/turf/open/floor/plating,
/area/security/prison)
+"kgB" = (
+/obj/machinery/vending/snack/orange,
+/obj/machinery/light{
+ dir = 1
+ },
+/turf/open/floor/wood,
+/area/service/bar)
"khb" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 10
@@ -56437,6 +56067,22 @@
},
/turf/open/floor/plasteel/dark,
/area/hallway/primary/central)
+"kic" = (
+/obj/structure/table,
+/obj/item/circuitboard/machine/paystand{
+ pixel_x = 5;
+ pixel_y = -5
+ },
+/obj/effect/decal/cleanable/dirt{
+ desc = "A thin layer of dust coating the floor.";
+ name = "dust"
+ },
+/obj/effect/spawner/lootdrop/maintenance{
+ lootcount = 3;
+ name = "3maintenance loot spawner"
+ },
+/turf/open/floor/plasteel,
+/area/commons/locker)
"kil" = (
/obj/machinery/atmospherics/pipe/simple/dark/visible{
dir = 5
@@ -56462,6 +56108,13 @@
},
/turf/open/floor/plating,
/area/hallway/secondary/entry)
+"kkK" = (
+/obj/machinery/vending/autodrobe,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/turf/open/floor/plasteel/white/side{
+ dir = 4
+ },
+/area/service/theater)
"klN" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -56527,10 +56180,6 @@
/obj/machinery/gear_painter,
/turf/open/floor/plasteel,
/area/commons/fitness)
-"kqI" = (
-/obj/effect/decal/cleanable/vomit/old,
-/turf/open/floor/carpet/arcade,
-/area/commons/arcade)
"ktP" = (
/obj/machinery/power/smes{
charge = 5e+006
@@ -56559,6 +56208,19 @@
},
/turf/open/floor/plasteel,
/area/security/brig)
+"kuw" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 5
+ },
+/obj/structure/cable,
+/obj/machinery/power/apc{
+ areastring = "/area/commons/arcade";
+ dir = 8;
+ name = "Arcade Room";
+ pixel_x = -25
+ },
+/turf/open/floor/plating,
+/area/maintenance/starboard/fore)
"kuA" = (
/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
/obj/item/radio/intercom{
@@ -56612,6 +56274,15 @@
/obj/effect/landmark/xeno_spawn,
/turf/open/floor/wood,
/area/maintenance/bar)
+"kzn" = (
+/obj/effect/spawner/structure/window/reinforced,
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
+/obj/structure/cable,
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/plating,
+/area/command/gateway)
"kzT" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/closed/wall/r_wall,
@@ -56661,6 +56332,12 @@
/mob/living/simple_animal/opossum/poppy,
/turf/open/floor/plating,
/area/maintenance/port/aft)
+"kEJ" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 5
+ },
+/turf/open/floor/wood,
+/area/service/bar)
"kEY" = (
/obj/effect/landmark/stationroom/box/engine,
/turf/open/space/basic,
@@ -56750,6 +56427,14 @@
},
/turf/open/floor/plasteel,
/area/hallway/secondary/service)
+"kPi" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/cobweb,
+/obj/machinery/light/small/broken{
+ dir = 8
+ },
+/turf/open/floor/plating,
+/area/maintenance/starboard/aft)
"kPj" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -56891,6 +56576,16 @@
/obj/effect/decal/cleanable/blood/gibs/human/body,
/turf/open/floor/plasteel/dark,
/area/maintenance/starboard/aft)
+"lfu" = (
+/obj/machinery/light/small,
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
+ dir = 1
+ },
+/obj/structure/urinal{
+ pixel_y = 32
+ },
+/turf/open/floor/mineral/titanium/blue,
+/area/commons/toilet)
"lfV" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -56959,12 +56654,15 @@
},
/turf/open/floor/plasteel,
/area/command/gateway)
-"lld" = (
-/obj/structure/sign/poster/contraband/robust_softdrinks{
- pixel_y = 32
+"lkT" = (
+/obj/structure/cable{
+ icon_state = "1-2"
},
-/turf/open/floor/wood,
-/area/service/bar)
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/structure/disposalpipe/segment,
+/obj/structure/grille,
+/turf/open/floor/plating,
+/area/maintenance/starboard/aft)
"lnk" = (
/obj/item/radio/intercom{
pixel_y = 25
@@ -56979,6 +56677,15 @@
icon_state = "wood-broken6"
},
/area/maintenance/bar)
+"lpQ" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/effect/spawner/structure/window/reinforced,
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
+/obj/structure/cable,
+/turf/open/floor/plating,
+/area/command/gateway)
"lqO" = (
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
dir = 4
@@ -57008,6 +56715,25 @@
/obj/machinery/vending/kink,
/turf/open/floor/plasteel,
/area/commons/fitness)
+"lsS" = (
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 5
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/structure/cable{
+ icon_state = "2-4"
+ },
+/turf/open/floor/plating,
+/area/maintenance/starboard/fore)
+"ltv" = (
+/mob/living/simple_animal/bot/cleanbot{
+ name = "Honest Work"
+ },
+/turf/open/floor/carpet/royalblue,
+/area/maintenance/starboard/aft)
"ltK" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -57120,6 +56846,13 @@
"lLf" = (
/turf/closed/wall/r_wall,
/area/ai_monitored/command/nuke_storage)
+"lLA" = (
+/obj/machinery/computer/slot_machine{
+ balance = 15;
+ money = 500
+ },
+/turf/open/floor/plating,
+/area/maintenance/port/fore)
"lMg" = (
/obj/effect/turf_decal/stripes/line{
dir = 9
@@ -57145,12 +56878,32 @@
},
/turf/open/floor/plasteel,
/area/security/processing)
+"lOr" = (
+/obj/structure/table,
+/obj/machinery/light/floor,
+/obj/item/reagent_containers/food/drinks/beer{
+ pixel_x = -6
+ },
+/obj/item/reagent_containers/blood/oilblood{
+ pixel_x = 7
+ },
+/turf/open/floor/carpet/royalblue,
+/area/maintenance/starboard/aft)
"lPr" = (
/obj/item/kirbyplants{
icon_state = "applebush"
},
/turf/open/floor/plasteel,
/area/hallway/primary/port)
+"lPG" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/machinery/light/small{
+ dir = 4
+ },
+/obj/item/soap,
+/obj/effect/landmark/xeno_spawn,
+/turf/open/floor/plasteel/freezer,
+/area/commons/toilet)
"lQG" = (
/obj/effect/spawner/structure/window,
/turf/open/floor/plating,
@@ -57186,11 +56939,39 @@
/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
/turf/open/floor/carpet,
/area/commons/dorms)
+"lVy" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plating,
+/area/maintenance/starboard/aft)
+"lWD" = (
+/obj/effect/decal/cleanable/vomit/old,
+/turf/open/floor/carpet/arcade,
+/area/commons/arcade)
"lXy" = (
/obj/machinery/light,
/obj/item/light/tube/broken,
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
+"lZa" = (
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 8
+ },
+/obj/machinery/door/window/westright{
+ name = "Red Corner"
+ },
+/obj/effect/turf_decal/tile/red,
+/obj/effect/turf_decal/tile/red{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
+ dir = 1
+ },
+/turf/open/floor/plasteel,
+/area/commons/locker)
"lZl" = (
/obj/structure/closet,
/obj/effect/spawner/lootdrop/maintenance,
@@ -57231,6 +57012,20 @@
},
/turf/open/floor/wood/wood_diagonal,
/area/maintenance/port/fore)
+"mau" = (
+/obj/machinery/power/apc{
+ areastring = "/area/service/theater";
+ dir = 8;
+ name = "Theatre APC";
+ pixel_x = -25
+ },
+/obj/structure/cable{
+ icon_state = "0-4"
+ },
+/turf/open/floor/plasteel/white/side{
+ dir = 4
+ },
+/area/service/theater)
"maT" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/closed/wall,
@@ -57254,6 +57049,16 @@
/obj/effect/turf_decal/stripes/line,
/turf/open/floor/plating,
/area/security/range)
+"mcE" = (
+/obj/machinery/vending/cigarette,
+/obj/effect/decal/cleanable/cobweb{
+ icon_state = "cobweb2"
+ },
+/obj/structure/sign/poster/contraband/fun_police{
+ pixel_x = 32
+ },
+/turf/open/floor/carpet/arcade,
+/area/commons/arcade)
"meb" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/structure/bed,
@@ -57283,13 +57088,6 @@
},
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
-"mkO" = (
-/obj/structure/sign/poster/contraband/space_up{
- pixel_x = -32;
- pixel_y = 32
- },
-/turf/open/floor/wood,
-/area/service/bar)
"mkU" = (
/obj/machinery/door/airlock/external{
name = "Labor Camp Shuttle Airlock"
@@ -57314,6 +57112,13 @@
},
/turf/open/floor/plasteel,
/area/ai_monitored/security/armory)
+"mmx" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/machinery/airalarm{
+ pixel_y = 23
+ },
+/turf/open/floor/plasteel/freezer,
+/area/commons/toilet/locker)
"mnC" = (
/obj/structure/target_stake,
/obj/item/target/syndicate,
@@ -57387,6 +57192,17 @@
dir = 1
},
/area/hallway/secondary/entry)
+"mqH" = (
+/obj/structure/table/reinforced,
+/obj/machinery/door/poddoor/shutters{
+ id = "commissaryshutters";
+ name = "Vacant Commissary Shutters"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/commons/locker)
"mqZ" = (
/obj/item/reagent_containers/glass/beaker,
/turf/open/floor/plating,
@@ -57399,21 +57215,13 @@
/obj/structure/sign/departments/holy,
/turf/closed/wall,
/area/service/chapel/main)
-"mug" = (
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
- dir = 8
+"muv" = (
+/obj/item/radio/intercom{
+ pixel_y = 25
},
-/mob/living/simple_animal/bot/mulebot{
- beacon_freq = 1400;
- home_destination = "QM #1";
- name = "Massive Load";
- suffix = "#1"
- },
-/obj/structure/sign/poster/official/high_class_martini{
- pixel_x = -32
- },
-/turf/open/floor/carpet/royalblue,
-/area/maintenance/starboard/aft)
+/obj/machinery/shower,
+/turf/open/floor/plasteel/freezer,
+/area/commons/toilet)
"mvt" = (
/obj/machinery/airalarm{
dir = 1;
@@ -57421,6 +57229,16 @@
},
/turf/open/floor/plasteel,
/area/hallway/primary/starboard)
+"mwj" = (
+/obj/structure/noticeboard{
+ dir = 8;
+ pixel_x = 27
+ },
+/obj/machinery/light{
+ dir = 4
+ },
+/turf/open/floor/wood,
+/area/command/meeting_room)
"mwS" = (
/turf/open/floor/plating{
icon_state = "platingdmg3"
@@ -57454,6 +57272,14 @@
},
/turf/open/floor/wood,
/area/service/theater)
+"mzT" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/vending/coffee,
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/open/floor/plating,
+/area/maintenance/port/fore)
"mAH" = (
/obj/machinery/atmospherics/components/unary/tank/air{
dir = 8
@@ -57544,16 +57370,6 @@
/obj/item/electronics/airlock,
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
-"mJG" = (
-/obj/machinery/light{
- dir = 4;
- light_color = "#c1caff"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
-/turf/open/floor/wood,
-/area/service/theater)
"mLS" = (
/obj/effect/decal/cleanable/dirt/dust,
/turf/open/floor/plating{
@@ -57720,6 +57536,13 @@
},
/turf/open/floor/plasteel/dark,
/area/security/brig)
+"ncg" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/machinery/shower{
+ dir = 1
+ },
+/turf/open/floor/plasteel/freezer,
+/area/commons/toilet)
"ndq" = (
/turf/open/floor/plating,
/area/service/abandoned_gambling_den)
@@ -57893,6 +57716,19 @@
"nyi" = (
/turf/closed/wall,
/area/medical/paramedic)
+"nyn" = (
+/obj/structure/disposalpipe/segment{
+ dir = 5
+ },
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 5
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plating,
+/area/maintenance/starboard/aft)
"nzB" = (
/obj/machinery/hydroponics/soil{
pixel_y = 8
@@ -57913,6 +57749,20 @@
},
/turf/closed/wall,
/area/maintenance/port/fore)
+"nDd" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/obj/machinery/light,
+/obj/structure/disposalpipe/segment{
+ dir = 9
+ },
+/obj/structure/cable{
+ icon_state = "1-8"
+ },
+/obj/machinery/atmospherics/pipe/manifold/supply/hidden,
+/turf/open/floor/plasteel,
+/area/hallway/primary/port)
"nEj" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/structure/sign/warning/vacuum/external{
@@ -57948,6 +57798,11 @@
},
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
+"nGR" = (
+/obj/effect/decal/cleanable/cobweb,
+/obj/machinery/computer/arcade,
+/turf/open/floor/carpet/arcade,
+/area/commons/arcade)
"nJP" = (
/obj/machinery/atmospherics/pipe/heat_exchanging/simple{
dir = 5
@@ -57989,6 +57844,16 @@
},
/turf/open/floor/plasteel,
/area/commons/locker)
+"nNF" = (
+/obj/machinery/light{
+ dir = 1
+ },
+/turf/open/floor/wood,
+/area/service/bar)
+"nPr" = (
+/obj/item/broken_bottle,
+/turf/open/floor/plating,
+/area/maintenance/port/fore)
"nQi" = (
/obj/machinery/recharge_station,
/turf/open/floor/plating,
@@ -58035,6 +57900,9 @@
},
/turf/open/floor/plasteel,
/area/service/hydroponics)
+"nVz" = (
+/turf/closed/wall/r_wall,
+/area/ai_monitored/turret_protected/ai_upload)
"nXg" = (
/obj/structure/girder,
/obj/structure/grille,
@@ -58235,35 +58103,6 @@
/obj/machinery/holopad,
/turf/open/floor/plasteel,
/area/security/prison)
-"omY" = (
-/obj/structure/toilet/secret/low_loot{
- dir = 4
- },
-/obj/structure/mirror{
- pixel_y = 32
- },
-/obj/structure/sink{
- pixel_y = 25
- },
-/obj/machinery/button/door{
- id = "LockerShitter1";
- name = "Door Bolt Control";
- normaldoorcontrol = 1;
- pixel_x = 14;
- pixel_y = 38;
- specialfunctions = 4
- },
-/obj/machinery/light/small{
- dir = 8
- },
-/turf/open/floor/mineral/titanium/blue,
-/area/commons/toilet/locker)
-"opg" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 5
- },
-/turf/open/floor/wood,
-/area/service/bar)
"oqj" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
@@ -58285,6 +58124,10 @@
},
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
+"otC" = (
+/obj/machinery/status_display/evac,
+/turf/closed/wall/r_wall,
+/area/ai_monitored/turret_protected/ai_upload)
"ouf" = (
/obj/effect/turf_decal/trimline/blue/filled/corner{
dir = 4
@@ -58318,6 +58161,19 @@
},
/turf/open/floor/plasteel/dark,
/area/hallway/primary/central)
+"owx" = (
+/obj/machinery/light,
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 9
+ },
+/turf/open/floor/plasteel/cafeteria,
+/area/commons/locker)
"oxm" = (
/obj/structure/flora/ausbushes/fullgrass,
/obj/structure/flora/ausbushes/sparsegrass,
@@ -58360,9 +58216,6 @@
},
/turf/open/floor/plating,
/area/maintenance/fore/secondary)
-"oAb" = (
-/turf/closed/wall,
-/area/commons/arcade)
"oAB" = (
/obj/structure/fireplace{
pixel_y = -6
@@ -58389,6 +58242,12 @@
/obj/machinery/gulag_teleporter,
/turf/open/floor/plasteel,
/area/security/prison)
+"oDD" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/turf/open/floor/wood,
+/area/service/bar)
"oDN" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
@@ -58411,15 +58270,6 @@
"oHB" = (
/turf/open/floor/plasteel/dark,
/area/commons/dorms)
-"oHU" = (
-/obj/machinery/light{
- dir = 4
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 4
- },
-/turf/open/floor/plasteel,
-/area/science/circuit)
"oIJ" = (
/obj/structure/chair/comfy/brown{
dir = 8
@@ -58486,6 +58336,11 @@
/obj/machinery/door/firedoor,
/turf/open/floor/plasteel,
/area/security/range)
+"oTH" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/machinery/shower,
+/turf/open/floor/plasteel/freezer,
+/area/commons/toilet)
"oTW" = (
/obj/machinery/light{
dir = 1
@@ -58497,11 +58352,12 @@
/turf/open/floor/plasteel,
/area/hallway/primary/port)
"oUh" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
+/obj/structure/disposalpipe/trunk{
+ dir = 1
},
-/turf/open/floor/wood,
-/area/service/bar)
+/obj/machinery/disposal/bin,
+/turf/open/floor/plasteel/white,
+/area/science/circuit)
"oVo" = (
/obj/structure/pool/ladder,
/turf/open/pool,
@@ -58517,15 +58373,6 @@
},
/turf/closed/wall/r_wall,
/area/engineering/atmos)
-"oYQ" = (
-/obj/structure/chair/stool{
- pixel_y = 8
- },
-/mob/living/simple_animal/bot/medbot{
- name = "Doctor Love"
- },
-/turf/open/floor/carpet/royalblue,
-/area/maintenance/starboard/aft)
"oZl" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/structure/closet/wardrobe/pjs,
@@ -58546,14 +58393,12 @@
/obj/effect/landmark/blobstart,
/turf/open/floor/plating,
/area/maintenance/aft)
-"pcK" = (
-/obj/effect/landmark/blobstart,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/machinery/light{
- dir = 8
+"pcz" = (
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 1
},
-/turf/open/floor/plasteel/freezer,
-/area/commons/toilet/locker)
+/turf/open/floor/carpet/royalblue,
+/area/maintenance/starboard/aft)
"pcQ" = (
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -58635,17 +58480,6 @@
/obj/effect/decal/cleanable/blood/gibs/core,
/turf/open/floor/plasteel/dark,
/area/maintenance/starboard/aft)
-"plC" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
-/turf/open/floor/plating{
- icon_state = "platingdmg3"
- },
-/area/commons/arcade)
"plS" = (
/obj/machinery/door/window/brigdoor/security/cell{
id = "Cell 1";
@@ -58666,6 +58500,22 @@
},
/turf/open/floor/plasteel,
/area/security/brig)
+"pnc" = (
+/obj/effect/turf_decal/tile/blue,
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/structure/window{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/turf/open/floor/plasteel,
+/area/commons/locker)
"poc" = (
/obj/effect/turf_decal/stripes/line{
dir = 5
@@ -58765,15 +58615,6 @@
},
/turf/open/floor/plating,
/area/maintenance/port/fore)
-"pyC" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/effect/spawner/structure/window/reinforced,
-/obj/structure/cable{
- icon_state = "0-4"
- },
-/obj/structure/cable,
-/turf/open/floor/plating,
-/area/command/gateway)
"pzG" = (
/obj/item/radio/intercom{
name = "Station Intercom (General)";
@@ -58790,6 +58631,12 @@
},
/turf/open/floor/plating,
/area/maintenance/disposal/incinerator)
+"pzP" = (
+/obj/structure/sign/poster/contraband/punch_shit{
+ pixel_y = 32
+ },
+/turf/open/floor/wood,
+/area/maintenance/starboard/aft)
"pAK" = (
/obj/machinery/door/window/brigdoor/security/cell{
id = "Cell 3";
@@ -58824,6 +58671,13 @@
},
/turf/open/floor/plating,
/area/engineering/atmos)
+"pCE" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plasteel,
+/area/science/circuit)
"pDe" = (
/obj/machinery/door/window/southright{
name = "Target Storage"
@@ -58890,15 +58744,6 @@
},
/turf/open/floor/plasteel,
/area/hallway/primary/fore)
-"pIf" = (
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/obj/effect/turf_decal/tile/red,
-/turf/open/floor/plasteel/white/side{
- dir = 4
- },
-/area/service/theater)
"pJR" = (
/obj/structure/disposalpipe/segment,
/obj/structure/chair/comfy/brown{
@@ -58923,6 +58768,13 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel,
/area/hallway/primary/port)
+"pNS" = (
+/obj/effect/decal/cleanable/dirt{
+ desc = "A thin layer of dust coating the floor.";
+ name = "dust"
+ },
+/turf/open/floor/plasteel,
+/area/commons/locker)
"pPi" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -59009,14 +58861,6 @@
icon_state = "wood-broken2"
},
/area/maintenance/port/fore)
-"pVq" = (
-/obj/machinery/light/small{
- brightness = 3;
- dir = 8
- },
-/obj/effect/decal/cleanable/dirt,
-/turf/open/floor/plating,
-/area/maintenance/starboard/aft)
"pXG" = (
/obj/structure/table/wood,
/obj/item/candle{
@@ -59033,6 +58877,11 @@
},
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
+"qae" = (
+/obj/effect/decal/cleanable/vomit,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plating,
+/area/maintenance/fore)
"qaY" = (
/obj/structure/table/reinforced,
/obj/effect/turf_decal/tile/bar,
@@ -59042,14 +58891,6 @@
/obj/effect/turf_decal/stripes/line,
/turf/open/floor/plasteel,
/area/service/bar)
-"qcm" = (
-/obj/effect/spawner/structure/window/reinforced,
-/obj/structure/cable{
- icon_state = "0-2"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/turf/open/floor/plating,
-/area/command/gateway)
"qeb" = (
/obj/structure/cable{
icon_state = "0-8"
@@ -59118,6 +58959,15 @@
},
/turf/open/floor/plating,
/area/maintenance/port/fore)
+"qki" = (
+/obj/machinery/door/airlock{
+ name = "Unisex Restrooms"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/turf/open/floor/plasteel/freezer,
+/area/commons/toilet/locker)
"qkn" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/machinery/light{
@@ -59138,6 +58988,12 @@
},
/turf/closed/wall,
/area/maintenance/port/fore)
+"qlV" = (
+/obj/item/mop{
+ name = "Ain't Much"
+ },
+/turf/open/floor/light/colour_cycle/dancefloor_a,
+/area/maintenance/starboard/aft)
"qlY" = (
/obj/item/kirbyplants/random,
/turf/open/floor/plating{
@@ -59153,14 +59009,19 @@
/obj/machinery/door/firedoor,
/turf/open/floor/plasteel/white,
/area/medical/medbay/lobby)
-"qqs" = (
-/obj/structure/cable{
- icon_state = "4-8"
+"qoT" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 9
},
-/obj/item/papercutter,
-/obj/structure/table,
-/turf/open/floor/carpet,
-/area/command/heads_quarters/hop)
+/obj/effect/turf_decal/stripes/line,
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
+/obj/structure/cable{
+ icon_state = "1-8"
+ },
+/turf/open/floor/plasteel,
+/area/science/circuit)
"qtw" = (
/obj/machinery/door/airlock/external{
dir = 2;
@@ -59204,12 +59065,36 @@
},
/turf/open/floor/plasteel,
/area/commons/dorms)
+"qAu" = (
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
+ dir = 4
+ },
+/obj/structure/rack,
+/obj/item/storage/toolbox/emergency,
+/obj/machinery/light/small,
+/turf/open/floor/plasteel,
+/area/commons/locker)
"qBi" = (
/obj/effect/turf_decal/stripes/corner{
dir = 4
},
/turf/open/floor/plasteel,
/area/hallway/primary/port)
+"qCw" = (
+/obj/structure/chair/stool{
+ pixel_y = 8
+ },
+/obj/machinery/light/small/broken{
+ dir = 8
+ },
+/obj/item/glasswork/glass_base/glasses_frame_1{
+ pixel_x = -6;
+ pixel_y = 13
+ },
+/turf/open/floor/plating{
+ icon_state = "platingdmg3"
+ },
+/area/commons/arcade)
"qCR" = (
/obj/structure/musician/piano,
/obj/effect/decal/cleanable/cobweb,
@@ -59299,12 +59184,6 @@
/obj/effect/decal/cleanable/blood/gibs/core,
/turf/open/floor/plasteel/dark,
/area/maintenance/starboard/aft)
-"qNE" = (
-/mob/living/simple_animal/bot/cleanbot{
- name = "Honest Work"
- },
-/turf/open/floor/carpet/royalblue,
-/area/maintenance/starboard/aft)
"qOc" = (
/obj/effect/turf_decal/tile/green{
dir = 8
@@ -59335,6 +59214,18 @@
},
/turf/open/floor/plasteel/dark,
/area/medical/morgue)
+"qSo" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/turf/open/floor/plasteel/cafeteria,
+/area/commons/locker)
"qSF" = (
/obj/item/seeds/bee_balm/honey_balm,
/obj/machinery/atmospherics/components/unary/vent_pump/on{
@@ -59402,6 +59293,19 @@
},
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
+"rbH" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/structure/window{
+ dir = 1
+ },
+/obj/machinery/washing_machine,
+/turf/open/floor/plasteel/cafeteria,
+/area/commons/locker)
"rcD" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -59546,12 +59450,6 @@
},
/turf/open/floor/wood,
/area/service/bar)
-"rqW" = (
-/obj/structure/dresser,
-/turf/open/floor/plasteel/white/side{
- dir = 4
- },
-/area/service/theater)
"rrM" = (
/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
dir = 4
@@ -59599,10 +59497,6 @@
/obj/effect/turf_decal/tile/neutral,
/turf/open/floor/plasteel,
/area/commons/dorms)
-"ruZ" = (
-/obj/machinery/jukebox/disco,
-/turf/open/floor/light/colour_cycle/dancefloor_b,
-/area/maintenance/starboard/aft)
"rvr" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -59626,6 +59520,25 @@
},
/turf/open/floor/plasteel,
/area/security/prison)
+"rwj" = (
+/obj/machinery/light/small{
+ dir = 1
+ },
+/obj/structure/closet/crate/bin,
+/turf/open/floor/plating{
+ icon_state = "platingdmg2"
+ },
+/area/maintenance/port/fore)
+"rxD" = (
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 1
+ },
+/obj/machinery/camera{
+ c_tag = "Locker Room Toilets";
+ dir = 8
+ },
+/turf/open/floor/plasteel/freezer,
+/area/commons/toilet/locker)
"rxF" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/structure/table/glass,
@@ -59681,6 +59594,24 @@
},
/turf/open/floor/plasteel,
/area/security/brig)
+"rDh" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/red,
+/obj/structure/sign/poster/contraband/clown{
+ pixel_y = -32
+ },
+/obj/structure/closet/crate/wooden/toy,
+/obj/item/toy/crayon/spraycan/lubecan,
+/turf/open/floor/plasteel,
+/area/service/theater)
"rGo" = (
/obj/machinery/light/small{
dir = 1
@@ -59752,18 +59683,6 @@
/obj/machinery/status_display/evac,
/turf/closed/wall,
/area/ai_monitored/command/storage/eva)
-"rPU" = (
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
- dir = 1
- },
-/obj/effect/landmark/start/mime,
-/turf/open/floor/plasteel/white/side{
- dir = 4
- },
-/area/service/theater)
"rQJ" = (
/obj/machinery/light/small{
dir = 8
@@ -59792,17 +59711,6 @@
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
-"rTu" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
-/obj/structure/disposalpipe/segment,
-/obj/structure/cable{
- icon_state = "1-2"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/turf/open/floor/plasteel,
-/area/hallway/primary/port)
"rTD" = (
/turf/open/floor/plasteel,
/area/command/gateway)
@@ -59872,6 +59780,11 @@
/obj/effect/spawner/lootdrop/maintenance,
/turf/open/floor/plating,
/area/maintenance/port/fore)
+"rZE" = (
+/obj/structure/table,
+/obj/item/flashlight/lamp,
+/turf/open/floor/carpet/arcade,
+/area/commons/arcade)
"rZQ" = (
/obj/docking_port/stationary{
dir = 8;
@@ -59957,6 +59870,16 @@
/obj/effect/mapping_helpers/airlock/cyclelink_helper,
/turf/open/floor/plating,
/area/maintenance/department/medical/morgue)
+"smN" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 5
+ },
+/obj/machinery/camera{
+ c_tag = "Locker Room West";
+ dir = 1
+ },
+/turf/open/floor/plasteel,
+/area/commons/locker)
"smP" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -59979,11 +59902,6 @@
/obj/item/clothing/shoes/sneakers/white,
/turf/open/floor/plating,
/area/maintenance/fore)
-"sqp" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/effect/decal/cleanable/dirt,
-/turf/open/floor/plating,
-/area/maintenance/starboard/aft)
"srk" = (
/turf/open/floor/light/colour_cycle/dancefloor_a,
/area/maintenance/starboard/aft)
@@ -60021,6 +59939,14 @@
/obj/item/toy/poolnoodle/yellow,
/turf/open/floor/plasteel,
/area/commons/fitness/pool)
+"suN" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/obj/effect/landmark/event_spawn,
+/obj/structure/cable{
+ icon_state = "2-4"
+ },
+/turf/open/floor/plasteel,
+/area/science/circuit)
"sxs" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/structure/table,
@@ -60169,22 +60095,6 @@
/obj/structure/grille/broken,
/turf/open/floor/plating,
/area/maintenance/aft)
-"sLa" = (
-/obj/effect/turf_decal/tile/blue,
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/obj/structure/window{
- dir = 4
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 1
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 8
- },
-/turf/open/floor/plasteel,
-/area/commons/locker)
"sLj" = (
/obj/structure/chair/comfy/brown{
dir = 4
@@ -60207,23 +60117,11 @@
icon_state = "platingdmg3"
},
/area/maintenance/starboard/aft)
-"sNK" = (
-/obj/effect/turf_decal/tile/blue{
- dir = 8
- },
-/obj/effect/turf_decal/tile/red{
- dir = 1
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/obj/effect/turf_decal/tile/red,
-/obj/structure/closet/secure_closet/freezer/cream_pie,
-/obj/machinery/airalarm{
- pixel_y = 23
- },
+"sMI" = (
+/obj/structure/table,
+/obj/item/storage/secure/briefcase,
/turf/open/floor/plasteel,
-/area/service/theater)
+/area/commons/locker)
"sOs" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -60276,6 +60174,24 @@
/obj/structure/chair/office/light,
/turf/open/floor/plasteel/white,
/area/science/circuit)
+"sUx" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/effect/spawner/structure/window/reinforced,
+/obj/structure/cable{
+ icon_state = "0-4"
+ },
+/obj/structure/cable,
+/turf/open/floor/plating,
+/area/command/gateway)
+"sVt" = (
+/obj/item/storage/secure/safe{
+ pixel_y = 32
+ },
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/commons/locker)
"sVD" = (
/obj/structure/table/wood/poker,
/obj/item/storage/box/matches{
@@ -60314,16 +60230,46 @@
/obj/effect/turf_decal/vg_decals/atmos/mix,
/turf/open/floor/engine/vacuum,
/area/engineering/atmos)
-"sYR" = (
-/obj/machinery/light{
+"sYv" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/blue{
dir = 4
},
-/turf/open/floor/plasteel/white,
-/area/science/circuit)
+/obj/effect/turf_decal/tile/red,
+/obj/structure/closet/secure_closet/freezer/cream_pie,
+/obj/machinery/airalarm{
+ pixel_y = 23
+ },
+/turf/open/floor/plasteel,
+/area/service/theater)
"tal" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/closed/wall,
/area/hallway/secondary/service)
+"tcU" = (
+/obj/machinery/door/airlock/maintenance{
+ req_access_txt = "46"
+ },
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/plating,
+/area/maintenance/fore)
+"teS" = (
+/obj/structure/chair/stool{
+ pixel_y = 8
+ },
+/mob/living/simple_animal/opossum{
+ name = "trash"
+ },
+/turf/open/floor/carpet/royalblue,
+/area/maintenance/starboard/aft)
"tgH" = (
/obj/structure/filingcabinet/employment,
/turf/open/floor/wood,
@@ -60417,6 +60363,14 @@
},
/turf/open/floor/plasteel,
/area/security/courtroom)
+"trT" = (
+/obj/structure/disposalpipe/segment,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/plasteel,
+/area/hallway/primary/port)
"tsq" = (
/obj/structure/cable/white{
icon_state = "0-4"
@@ -60465,6 +60419,15 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
+"tyE" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/structure/disposalpipe/segment,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plating,
+/area/maintenance/starboard/aft)
"tyX" = (
/obj/effect/turf_decal/bot_white,
/obj/effect/turf_decal/tile/neutral{
@@ -60486,6 +60449,11 @@
/obj/item/soap,
/turf/open/floor/mineral/titanium/blue,
/area/commons/dorms)
+"tAy" = (
+/obj/effect/decal/cleanable/oil/slippery,
+/obj/structure/reagent_dispensers/beerkeg,
+/turf/open/floor/light/colour_cycle/dancefloor_a,
+/area/maintenance/starboard/aft)
"tAC" = (
/obj/structure/closet/athletic_mixed,
/obj/item/toy/poolnoodle/red,
@@ -60698,6 +60666,14 @@
},
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
+"tVB" = (
+/obj/effect/landmark/blobstart,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/machinery/light{
+ dir = 8
+ },
+/turf/open/floor/plasteel/freezer,
+/area/commons/toilet/locker)
"tVE" = (
/obj/item/chair/wood{
dir = 4
@@ -60725,6 +60701,18 @@
},
/turf/closed/wall/r_wall,
/area/maintenance/disposal/incinerator)
+"tZa" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
+ dir = 8
+ },
+/turf/open/floor/plating,
+/area/maintenance/starboard/fore)
"tZe" = (
/obj/effect/turf_decal/bot,
/obj/structure/sign/poster/official/pda_ad{
@@ -60732,6 +60720,9 @@
},
/turf/open/floor/plasteel,
/area/hallway/primary/central)
+"tZp" = (
+/turf/closed/wall,
+/area/commons/arcade)
"tZu" = (
/obj/machinery/light/small{
dir = 8
@@ -60750,25 +60741,6 @@
},
/turf/open/floor/wood,
/area/maintenance/bar)
-"ubj" = (
-/obj/effect/turf_decal/tile/red{
- dir = 1
- },
-/obj/effect/turf_decal/tile/red{
- dir = 8
- },
-/obj/machinery/door/window/westright{
- name = "Red Corner"
- },
-/obj/effect/turf_decal/tile/red,
-/obj/effect/turf_decal/tile/red{
- dir = 4
- },
-/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
- dir = 1
- },
-/turf/open/floor/plasteel,
-/area/commons/locker)
"ucq" = (
/obj/structure/sign/poster/contraband/red_rum{
pixel_y = 32
@@ -60851,13 +60823,6 @@
/obj/effect/decal/cleanable/blood/gibs/human/lizard/body,
/turf/open/floor/plasteel/dark,
/area/maintenance/starboard/aft)
-"ujg" = (
-/obj/structure/disposalpipe/trunk{
- dir = 1
- },
-/obj/machinery/disposal/bin,
-/turf/open/floor/plasteel/white,
-/area/science/circuit)
"ujv" = (
/obj/structure/sign/departments/restroom,
/turf/closed/wall,
@@ -60885,6 +60850,14 @@
},
/turf/open/floor/wood,
/area/service/bar)
+"unQ" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/obj/item/papercutter,
+/obj/structure/table,
+/turf/open/floor/carpet,
+/area/command/heads_quarters/hop)
"unR" = (
/turf/open/floor/plasteel/yellowsiding{
dir = 8
@@ -60920,10 +60893,6 @@
/obj/effect/decal/cleanable/dirt/dust,
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
-"urS" = (
-/obj/effect/landmark/event_spawn,
-/turf/open/floor/carpet/royalblue,
-/area/maintenance/starboard/aft)
"usE" = (
/obj/effect/spawner/lootdrop/maintenance,
/obj/structure/rack,
@@ -61045,6 +61014,15 @@
},
/turf/open/floor/plasteel/white,
/area/medical/medbay/lobby)
+"uCn" = (
+/obj/structure/table/reinforced,
+/obj/item/paper_bin,
+/obj/item/pen,
+/obj/machinery/light{
+ dir = 8
+ },
+/turf/open/floor/plasteel/white,
+/area/science/circuit)
"uCo" = (
/obj/structure/chair{
dir = 1
@@ -61161,20 +61139,11 @@
/obj/machinery/door/window,
/turf/open/floor/wood,
/area/service/theater)
-"uNu" = (
-/obj/structure/disposalpipe/segment{
- dir = 10
+"uOd" = (
+/turf/open/floor/plasteel/white/side{
+ dir = 4
},
-/obj/effect/turf_decal/stripes/line{
- dir = 6
- },
-/obj/machinery/camera{
- c_tag = "Circuitry Lab";
- dir = 8;
- network = list("ss13","rd")
- },
-/turf/open/floor/plasteel,
-/area/science/circuit)
+/area/service/theater)
"uOJ" = (
/obj/structure/cable{
icon_state = "1-8"
@@ -61192,30 +61161,12 @@
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
-"uQS" = (
-/obj/machinery/light/small,
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
- dir = 1
- },
-/obj/structure/urinal{
- pixel_y = 32
- },
-/turf/open/floor/mineral/titanium/blue,
-/area/commons/toilet)
"uRd" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 5
},
/turf/closed/wall/r_wall,
/area/engineering/gravity_generator)
-"uRn" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/decal/cleanable/cobweb,
-/obj/machinery/light/small/broken{
- dir = 8
- },
-/turf/open/floor/plating,
-/area/maintenance/starboard/aft)
"uRS" = (
/obj/structure/disposalpipe/segment,
/obj/structure/cable{
@@ -61226,6 +61177,16 @@
},
/turf/open/floor/plating,
/area/maintenance/fore)
+"uSc" = (
+/obj/machinery/light{
+ dir = 4;
+ light_color = "#c1caff"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/turf/open/floor/wood,
+/area/service/theater)
"uSC" = (
/obj/machinery/pool/drain,
/turf/open/pool,
@@ -61237,15 +61198,13 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel,
/area/security/brig)
-"uUi" = (
-/obj/structure/cable{
- icon_state = "1-2"
- },
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/structure/disposalpipe/segment,
+"uTL" = (
/obj/effect/decal/cleanable/dirt,
-/turf/open/floor/plating,
-/area/maintenance/starboard/aft)
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/commons/locker)
"uUP" = (
/obj/structure/cable/white,
/obj/structure/cable/white{
@@ -61281,24 +61240,12 @@
},
/turf/open/floor/plasteel,
/area/security/brig)
-"uYv" = (
-/obj/structure/table,
-/obj/machinery/light/floor,
-/obj/machinery/light/floor,
-/obj/item/clothing/glasses/sunglasses/reagent,
-/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass{
- pixel_x = -5;
- pixel_y = 12
+"uZM" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 9
},
-/obj/item/storage/fancy/cigarettes/cigpack_uplift{
- pixel_x = 8;
- pixel_y = 8
- },
-/obj/structure/sign/poster/contraband/borg_fancy_2{
- pixel_y = -32
- },
-/turf/open/floor/carpet/royalblue,
-/area/maintenance/starboard/aft)
+/turf/closed/wall/r_wall,
+/area/ai_monitored/turret_protected/ai_upload)
"vae" = (
/obj/effect/turf_decal/stripes/line{
dir = 4
@@ -61347,6 +61294,14 @@
},
/turf/open/floor/plating,
/area/security/range)
+"vde" = (
+/obj/structure/chair/comfy/brown{
+ dir = 4
+ },
+/obj/effect/landmark/start/captain,
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/wood,
+/area/command/heads_quarters/captain)
"vdo" = (
/obj/machinery/atmospherics/pipe/heat_exchanging/simple,
/obj/structure/lattice,
@@ -61390,20 +61345,6 @@
},
/turf/open/floor/plating,
/area/maintenance/fore)
-"vhb" = (
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 8
- },
-/obj/structure/window{
- dir = 1
- },
-/obj/structure/bedsheetbin/color,
-/obj/structure/table,
-/turf/open/floor/plasteel/cafeteria,
-/area/commons/locker)
"viF" = (
/obj/structure/disposalpipe/segment{
dir = 4
@@ -61452,6 +61393,19 @@
/obj/machinery/meter,
/turf/open/floor/plasteel,
/area/engineering/atmos)
+"voT" = (
+/obj/machinery/camera{
+ c_tag = "Bathrooms";
+ dir = 1
+ },
+/obj/structure/sink{
+ pixel_y = 25
+ },
+/obj/structure/mirror{
+ pixel_y = 32
+ },
+/turf/open/floor/mineral/titanium/blue,
+/area/commons/toilet)
"voW" = (
/obj/structure/pool/Lboard,
/turf/open/pool,
@@ -61572,6 +61526,17 @@
},
/turf/open/floor/plating,
/area/security/brig)
+"vyP" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/obj/structure/sink{
+ dir = 4;
+ pixel_x = 11
+ },
+/obj/structure/mirror{
+ pixel_x = 28
+ },
+/turf/open/floor/plasteel/freezer,
+/area/commons/toilet/locker)
"vzp" = (
/obj/structure/table/reinforced,
/obj/machinery/firealarm{
@@ -61596,14 +61561,6 @@
},
/turf/open/floor/plasteel,
/area/commons/fitness/pool)
-"vBa" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/effect/spawner/structure/window/reinforced,
-/obj/structure/cable{
- icon_state = "0-2"
- },
-/turf/open/floor/plating,
-/area/command/gateway)
"vCb" = (
/obj/machinery/rnd/production/techfab/department/service,
/turf/open/floor/plasteel,
@@ -61808,14 +61765,11 @@
/turf/open/space,
/area/solars/starboard/aft)
"vPE" = (
-/obj/structure/cable{
- icon_state = "1-2"
+/obj/machinery/light{
+ dir = 4
},
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/structure/disposalpipe/segment,
-/obj/structure/grille,
-/turf/open/floor/plating,
-/area/maintenance/starboard/aft)
+/turf/open/floor/plasteel/white,
+/area/science/circuit)
"vPQ" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/machinery/atmospherics/pipe/simple/yellow/visible{
@@ -61907,6 +61861,15 @@
/obj/structure/girder,
/turf/open/floor/plating/airless,
/area/space/nearstation)
+"wfC" = (
+/obj/structure/chair/stool{
+ pixel_y = 8
+ },
+/mob/living/simple_animal/bot/medbot{
+ name = "Doctor Love"
+ },
+/turf/open/floor/carpet/royalblue,
+/area/maintenance/starboard/aft)
"wfR" = (
/obj/item/electropack/shockcollar,
/obj/item/assembly/signaler,
@@ -62038,6 +62001,26 @@
},
/turf/open/floor/plasteel,
/area/hallway/secondary/service)
+"wrX" = (
+/obj/effect/turf_decal/tile/blue,
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/structure/window,
+/obj/structure/window{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/commons/locker)
"wuO" = (
/obj/effect/spawner/lootdrop/maintenance{
lootcount = 2;
@@ -62061,6 +62044,30 @@
/obj/item/stack/sheet/metal/ten,
/turf/open/floor/plasteel/white,
/area/science/circuit)
+"wwG" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 6
+ },
+/obj/structure/chair{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/commons/locker)
+"wxf" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/holopad/secure,
+/turf/open/floor/wood,
+/area/command/heads_quarters/captain)
+"wxk" = (
+/obj/item/reagent_containers/food/drinks/beer{
+ pixel_x = -15
+ },
+/obj/machinery/computer/arcade,
+/turf/open/floor/carpet/arcade,
+/area/commons/arcade)
"wxT" = (
/obj/structure/chair/sofa/left,
/obj/structure/window{
@@ -62081,11 +62088,13 @@
},
/turf/closed/wall,
/area/hallway/secondary/service)
-"wDY" = (
-/obj/item/mop{
- name = "Ain't Much"
+"wCQ" = (
+/obj/machinery/light/small{
+ brightness = 3;
+ dir = 8
},
-/turf/open/floor/light/colour_cycle/dancefloor_a,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plating,
/area/maintenance/starboard/aft)
"wHk" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
@@ -62093,6 +62102,14 @@
},
/turf/open/floor/plasteel,
/area/commons/fitness/pool)
+"wHm" = (
+/obj/structure/window/reinforced,
+/obj/machinery/airalarm{
+ dir = 8;
+ pixel_x = 24
+ },
+/turf/open/floor/wood,
+/area/service/theater)
"wHz" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 5
@@ -62103,6 +62120,11 @@
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden,
/turf/open/floor/plating,
/area/maintenance/starboard/fore)
+"wII" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/obj/machinery/door/airlock/maintenance,
+/turf/open/floor/wood,
+/area/service/bar)
"wJA" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
@@ -62138,8 +62160,10 @@
/turf/open/floor/plasteel,
/area/hallway/primary/central)
"wTk" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/turf/closed/wall,
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
+ dir = 1
+ },
+/turf/open/floor/plasteel/freezer,
/area/commons/toilet/locker)
"wUg" = (
/obj/effect/turf_decal/stripes/line{
@@ -62182,12 +62206,6 @@
/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating,
/area/engineering/atmos)
-"wWG" = (
-/obj/structure/sign/poster/contraband/punch_shit{
- pixel_y = 32
- },
-/turf/open/floor/wood,
-/area/maintenance/starboard/aft)
"wWT" = (
/obj/effect/landmark/start/roboticist,
/turf/open/floor/plasteel/white,
@@ -62216,6 +62234,13 @@
},
/turf/open/floor/plasteel,
/area/security/prison)
+"wYn" = (
+/obj/structure/plasticflaps/opaque,
+/obj/structure/sign/poster/contraband/free_drone{
+ pixel_y = 32
+ },
+/turf/open/floor/carpet/royalblue,
+/area/maintenance/starboard/aft)
"wZI" = (
/obj/machinery/light{
dir = 1
@@ -62296,9 +62321,7 @@
/turf/open/floor/plating,
/area/maintenance/port/aft)
"xgs" = (
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
- dir = 1
- },
+/obj/effect/landmark/event_spawn,
/turf/open/floor/carpet/royalblue,
/area/maintenance/starboard/aft)
"xgC" = (
@@ -62372,24 +62395,17 @@
},
/turf/open/floor/plasteel,
/area/commons/fitness)
-"xmo" = (
-/obj/effect/turf_decal/tile/blue{
- dir = 8
- },
-/obj/effect/turf_decal/tile/red{
- dir = 1
- },
-/obj/effect/turf_decal/tile/blue{
+"xlX" = (
+/obj/structure/table/reinforced,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
-/obj/effect/turf_decal/tile/red,
-/obj/structure/sign/poster/contraband/clown{
- pixel_y = -32
+/obj/machinery/door/poddoor/shutters{
+ id = "commissaryshutters";
+ name = "Vacant Commissary Shutters"
},
-/obj/structure/closet/crate/wooden/toy,
-/obj/item/toy/crayon/spraycan/lubecan,
/turf/open/floor/plasteel,
-/area/service/theater)
+/area/commons/locker)
"xmS" = (
/obj/structure/chair/comfy/beige{
dir = 8
@@ -62447,6 +62463,15 @@
},
/turf/open/floor/plasteel,
/area/maintenance/disposal/incinerator)
+"xwB" = (
+/obj/structure/chair/stool{
+ pixel_y = 8
+ },
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
+ dir = 4
+ },
+/turf/open/floor/carpet/arcade,
+/area/commons/arcade)
"xxi" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -62466,6 +62491,11 @@
"xxp" = (
/turf/open/floor/plating,
/area/security/range)
+"xzd" = (
+/obj/effect/spawner/lootdrop/maintenance,
+/obj/structure/closet,
+/turf/open/floor/plating,
+/area/maintenance/starboard/aft)
"xzv" = (
/obj/effect/turf_decal/tile/red{
dir = 1
@@ -62632,17 +62662,6 @@
/obj/effect/spawner/lootdrop/bedsheet,
/turf/open/floor/wood,
/area/commons/dorms)
-"xPY" = (
-/obj/structure/cable{
- icon_state = "1-2"
- },
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/structure/disposalpipe/segment,
-/obj/structure/grille/broken,
-/obj/effect/decal/cleanable/blood/old,
-/obj/item/kirbyplants/random,
-/turf/open/floor/plating,
-/area/maintenance/starboard/aft)
"xRa" = (
/obj/item/kirbyplants{
icon_state = "plant-20"
@@ -62782,36 +62801,28 @@
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
"ycd" = (
-/obj/structure/table,
-/obj/item/circuitboard/machine/paystand{
- pixel_x = 5;
- pixel_y = -5
- },
-/obj/effect/decal/cleanable/dirt{
- desc = "A thin layer of dust coating the floor.";
- name = "dust"
- },
-/obj/effect/spawner/lootdrop/maintenance{
- lootcount = 3;
- name = "3maintenance loot spawner"
- },
-/turf/open/floor/plasteel,
-/area/commons/locker)
-"ycu" = (
-/obj/machinery/power/apc{
- areastring = "/area/science/circuit";
- dir = 4;
- name = "Circuitry Lab APC";
- pixel_x = 24
- },
-/obj/effect/turf_decal/stripes/line{
+/obj/structure/toilet/secret/low_loot{
dir = 4
},
-/obj/structure/cable{
- icon_state = "0-8"
+/obj/structure/mirror{
+ pixel_y = 32
},
-/turf/open/floor/plasteel,
-/area/science/circuit)
+/obj/structure/sink{
+ pixel_y = 25
+ },
+/obj/machinery/button/door{
+ id = "LockerShitter2";
+ name = "Door Bolt Control";
+ normaldoorcontrol = 1;
+ pixel_x = 14;
+ pixel_y = 38;
+ specialfunctions = 4
+ },
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/open/floor/mineral/titanium/blue,
+/area/commons/toilet/locker)
"ycY" = (
/obj/effect/turf_decal/tile/red{
dir = 1
@@ -62843,21 +62854,16 @@
/obj/machinery/status_display/evac,
/turf/closed/wall,
/area/hallway/primary/central)
+"yfX" = (
+/obj/machinery/atmospherics/components/unary/vent_pump/on,
+/turf/open/floor/carpet/arcade,
+/area/commons/arcade)
"ygb" = (
/obj/machinery/atmospherics/pipe/heat_exchanging/simple{
dir = 4
},
/turf/open/floor/wood/wood_diagonal,
/area/maintenance/port/fore)
-"ygG" = (
-/obj/effect/spawner/structure/window/reinforced,
-/obj/structure/cable{
- icon_state = "0-8"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/obj/structure/cable,
-/turf/open/floor/plating,
-/area/command/gateway)
"yhx" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 5
@@ -62875,12 +62881,6 @@
},
/turf/open/floor/plasteel/dark,
/area/hallway/primary/central)
-"yle" = (
-/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
- dir = 4
- },
-/turf/open/floor/plating,
-/area/maintenance/starboard/aft)
(1,1,1) = {"
cNd
@@ -79197,7 +79197,7 @@ aTv
aUT
aPz
aPA
-aWo
+hNm
aPA
aPA
aXQ
@@ -79453,14 +79453,14 @@ aPA
aPA
aPA
aPA
-aWn
+got
+pNS
+sMI
+kic
+aXQ
aZt
-aWy
+aXQ
ycd
-aXQ
-omY
-aXQ
-gQX
bhQ
bjj
bkF
@@ -79711,13 +79711,13 @@ aTw
aUU
aPA
aPA
+sVt
+pNS
+qAu
+aXQ
aZv
-aZt
+aXQ
bbL
-aXQ
-bdJ
-aXQ
-bgr
bhQ
bjj
bkF
@@ -79966,15 +79966,15 @@ aQN
aQN
aQN
aQN
-aUv
+aWn
aPA
-aYe
-bbq
-aZw
+uTL
+wwG
+fBW
+aWy
+mmx
+tVB
wTk
-bct
-pcK
-def
bhQ
bjk
bkE
@@ -80223,15 +80223,15 @@ aQS
aQN
aSV
aYU
-aUX
+smN
aPA
-baO
-aZo
+mqH
+xlX
aPA
aXQ
-hPs
-cBn
-ior
+ddl
+vyP
+rxD
bhQ
bjk
bkF
@@ -80483,10 +80483,10 @@ aQN
aWq
aQN
aWq
-aXp
+aUt
aQN
aXQ
-eZu
+qki
aXQ
aXQ
bhQ
@@ -80706,8 +80706,8 @@ aaa
aaa
aaa
alU
-anj
-amD
+lLA
+mzT
aKY
alU
arG
@@ -80740,10 +80740,10 @@ aQN
aWq
aQN
aWq
-aXp
+aUt
aQN
-vhb
-idD
+fRe
+qSo
aPA
bgt
bhS
@@ -80963,8 +80963,8 @@ aaf
aaf
aaf
alU
-anl
-aUo
+jNr
+gZB
amC
ank
amC
@@ -80993,14 +80993,14 @@ aPC
aQN
aQN
aTz
-aUp
-ubj
aXr
-aZx
-baw
+lZa
+fFl
+wrX
+aUo
aYU
-cBh
-bdL
+ihS
+owx
aPA
bgt
bhR
@@ -81250,13 +81250,13 @@ aPD
aQT
aQN
aTC
-aUs
+dyC
aUY
aXv
aYS
-aXp
+aUt
aQN
-ddj
+rbH
bbO
aPA
aSg
@@ -81477,8 +81477,8 @@ aaa
aaa
aaa
alU
-aUn
-aUt
+rwj
+nPr
amC
alU
alU
@@ -81507,11 +81507,11 @@ aPA
pqs
aQN
aTC
-aUs
+dyC
mTG
aXt
ijG
-aXp
+aUt
aQN
aPA
aPA
@@ -81733,9 +81733,9 @@ aaa
aaa
aaa
aaa
-amE
-anm
-aUu
+jFd
+fDn
+gFs
aKY
alU
xFM
@@ -81768,7 +81768,7 @@ aXv
gxc
aXt
ijG
-aXp
+aUt
aQN
aZB
aPA
@@ -82009,7 +82009,7 @@ ayy
aAO
aBN
aDe
-bgS
+fZR
aFT
aDe
aIU
@@ -82021,11 +82021,11 @@ aPA
aiB
aQN
nLw
-sLa
+pnc
oyl
aXw
qfk
-aXp
+aUt
aQN
aZA
aPA
@@ -82282,7 +82282,7 @@ aTy
aWp
aTy
aTy
-cFG
+aUv
aTy
bbs
bcw
@@ -82775,9 +82775,9 @@ lZN
amC
jIW
nBI
-aDy
-fgG
-rqW
+eky
+mau
+eAe
wUr
tJi
aLP
@@ -83032,9 +83032,9 @@ alU
amC
ntt
ugq
-aEU
-rPU
-fne
+kkK
+jBZ
+uOd
wUr
aHI
fOA
@@ -83290,8 +83290,8 @@ aFJ
ntt
nBI
wUr
-aCh
-pIf
+fvU
+gER
kCo
aHK
aHK
@@ -83546,9 +83546,9 @@ alU
alU
awa
axp
-aGf
-azH
-eEe
+tcU
+fnE
+gLw
wUr
aCr
aLT
@@ -83804,12 +83804,12 @@ arP
avZ
xtP
wUr
-sNK
-xmo
+sYv
+rDh
wUr
mzB
-mJG
-dEh
+uSc
+wHm
qTG
aJe
aKw
@@ -84327,9 +84327,9 @@ aOs
ngs
uRS
fcn
-aLN
-rTu
-aOt
+trT
+jSD
+nDd
aPK
aPK
aPK
@@ -85081,7 +85081,7 @@ anO
aaa
aaa
arP
-aBx
+qae
aqR
arP
asQ
@@ -89491,7 +89491,7 @@ bmo
bnR
bpe
bqB
-qqs
+unQ
btD
buO
bwk
@@ -90253,7 +90253,7 @@ bbh
bcc
bdd
cVs
-bfr
+mwj
bbX
bif
aZM
@@ -90510,7 +90510,7 @@ bbk
bbk
bfu
bbk
-bfs
+jmL
aZM
aZM
aZM
@@ -91025,9 +91025,9 @@ aZR
bbm
bec
bfu
-vBa
-aBa
-pyC
+hty
+lpQ
+sUx
iZd
wql
wql
@@ -91538,7 +91538,7 @@ bbm
bbm
bdh
bee
-bfv
+nVz
xUL
tyX
gpD
@@ -91795,10 +91795,10 @@ cBj
bcf
bdg
bed
-bfv
+nVz
tyX
pst
-cTT
+hoL
alu
aEM
aGd
@@ -92052,7 +92052,7 @@ bbm
bbm
bdh
bef
-bfv
+nVz
gTx
tyX
xEB
@@ -92309,7 +92309,7 @@ aZR
aZR
aZR
aZR
-bfw
+otC
wZI
gDO
aBW
@@ -92567,9 +92567,9 @@ aZR
bbm
beh
bfx
-qcm
-ddV
-ygG
+dYl
+kzn
+hQX
iss
iss
lcx
@@ -93080,7 +93080,7 @@ bbp
bbp
bfx
bbp
-bfz
+uZM
aZV
aZV
aZV
@@ -93595,7 +93595,7 @@ bdk
mRQ
bek
bfB
-bgU
+vde
bdk
bjF
blc
@@ -93852,7 +93852,7 @@ bej
bdj
bej
bfA
-bgT
+jfZ
bil
bej
blb
@@ -94109,7 +94109,7 @@ baQ
wcB
bcQ
bfC
-bgV
+eOu
bim
bjG
aZV
@@ -94623,7 +94623,7 @@ bcm
bcm
bem
bfD
-bgW
+wxf
bfD
bjI
aZV
@@ -95630,7 +95630,7 @@ aAi
uIO
aCn
xBk
-dtx
+hlS
aGm
aHV
aDM
@@ -95887,10 +95887,10 @@ kmw
xrN
aAh
aAh
-bVt
+exX
aAh
aAh
-aDN
+voT
aAh
aMo
aNC
@@ -96143,9 +96143,9 @@ aze
awr
flE
aAh
-aDU
-aBz
-dHp
+muv
+gyQ
+fOK
aAh
dTI
ujv
@@ -96400,11 +96400,11 @@ awr
azX
aAZ
aCe
-aDT
-cPn
-gNC
+oTH
+lPG
+ncg
aCe
-uQS
+lfu
aAh
aJC
aJC
@@ -96914,13 +96914,13 @@ lgX
qvf
wqF
aAh
-aDP
-dfh
-hIL
-itG
+nGR
+qCw
+fCJ
+fiv
aJC
-lld
-mkO
+fWi
+hIL
aKR
fxe
aPY
@@ -97170,13 +97170,13 @@ axT
axW
aAl
cHf
-oAb
-aDR
-aFl
-kqI
-aHZ
+tZp
+wxk
+xwB
+lWD
+dvb
aJC
-aKJ
+nNF
aKR
aKR
wxT
@@ -97427,14 +97427,14 @@ axS
azk
aAk
tvi
-oAb
-aDY
-dBm
-igi
-jgm
-aJk
+tZp
+flG
+jqD
+giy
+yfX
+wII
aMu
-opg
+kEJ
aKR
aKR
aKR
@@ -97684,14 +97684,14 @@ awr
awr
aAn
rqk
-oAb
-aEc
-aFk
-aGw
-jSO
+tZp
+mcE
+dsi
+fgl
+rZE
aJC
-aKr
-oUh
+kgB
+oDD
aKR
sLj
sLj
@@ -97941,14 +97941,14 @@ awr
awr
aAn
jGW
-oAb
-oAb
-plC
-oAb
-oAb
+tZp
+tZp
+dGa
+tZp
+tZp
aJC
aKq
-oUh
+oDD
aNF
hOv
oax
@@ -98201,11 +98201,11 @@ uxY
aBC
aCt
aEA
-aGz
-aIb
+lsS
+kuw
aJC
-aKN
-oUh
+eTA
+oDD
aKR
aOJ
oIJ
@@ -98458,7 +98458,7 @@ vyp
aBB
aBB
aBB
-aGy
+tZa
aIa
cNE
aKM
@@ -111621,7 +111621,7 @@ mRe
olr
bPL
cVK
-bTo
+uCn
eaI
cbZ
bSl
@@ -112131,9 +112131,9 @@ cbe
bTp
vCt
bVs
-fKl
-bXt
-bPM
+suN
+pCE
+qoT
bZh
bXs
cbe
@@ -112385,14 +112385,14 @@ bEC
bSl
dMZ
bXs
-sYR
+vPE
bXs
-gwd
-ycu
-oHU
-uNu
-ujg
-sYR
+bVt
+dfh
+jSO
+jgm
+oUh
+vPE
bXs
bXs
bSl
@@ -112895,17 +112895,17 @@ bKb
cNX
cNZ
cNZ
-jCq
+nyn
bSl
bSl
bSl
bSl
-uRn
+kPi
cOe
cae
oMT
-pVq
-gsi
+wCQ
+xzd
bSl
bSl
bSl
@@ -113151,22 +113151,22 @@ bGL
bKd
cNY
bMC
-sqp
+lVy
jHt
bPO
kob
bSm
bTr
-uUi
-vPE
-xPY
-vPE
-uUi
+tyE
+lkT
+cUb
+lkT
+tyE
bTr
bTr
cbg
bTr
-uUi
+tyE
bTr
nGt
cbg
@@ -113684,11 +113684,11 @@ ccW
cNW
clt
cNW
-cfv
+wYn
cNW
-mug
-hUJ
-ixd
+gOF
+gGK
+lOr
cNW
gXs
aaf
@@ -113939,13 +113939,13 @@ cNW
wly
ccV
noa
-yle
+iQg
ccU
-xgs
+pcz
srk
-fFh
+tAy
srk
-oYQ
+wfC
cNW
aaa
aaf
@@ -114198,11 +114198,11 @@ pDG
cNW
ceT
cNW
-hUJ
+gGK
chH
-ruZ
+eUX
srk
-hUJ
+gGK
cNW
gXs
aaf
@@ -114455,11 +114455,11 @@ cNW
cNW
cPH
cNW
-urS
-wDY
+xgs
+qlV
srk
-cVX
-hOn
+fkh
+gcx
cNW
aaa
aaf
@@ -114713,10 +114713,10 @@ cNW
ceU
cNW
cgy
-qNE
-hUJ
-fVA
-uYv
+ltv
+gGK
+teS
+jdu
cNW
aaa
aaf
@@ -114950,7 +114950,7 @@ gXs
aaf
aaa
cNW
-wWG
+pzP
tsq
pkS
olh
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index 0f41cd3b1a..57a4831073 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -36739,14 +36739,12 @@
dir = 1
},
/turf/open/floor/plasteel,
-/area/science/misc_lab)
+/area/science/mixing)
"cAJ" = (
-/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
- dir = 8
- },
/obj/structure/cable/yellow{
icon_state = "1-2"
},
+/obj/machinery/atmospherics/pipe/manifold4w/supplymain/hidden,
/turf/open/floor/plasteel,
/area/science/mixing)
"cAK" = (
@@ -36755,7 +36753,7 @@
dir = 4
},
/turf/open/floor/plasteel,
-/area/science/misc_lab)
+/area/science/mixing)
"cAL" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -37139,7 +37137,7 @@
dir = 8
},
/turf/open/floor/plasteel,
-/area/science/misc_lab)
+/area/science/mixing)
"cBE" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/structure/cable/yellow{
@@ -37149,7 +37147,7 @@
dir = 4
},
/turf/open/floor/plasteel,
-/area/science/misc_lab)
+/area/science/mixing)
"cBF" = (
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
dir = 4
@@ -37158,7 +37156,7 @@
pixel_x = 32
},
/turf/open/floor/plasteel,
-/area/science/misc_lab)
+/area/science/mixing)
"cBG" = (
/obj/machinery/door/airlock/research{
name = "Toxins Launch Room";
@@ -37556,6 +37554,9 @@
/obj/machinery/light{
dir = 8
},
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 4
+ },
/turf/open/floor/plasteel,
/area/science/mixing)
"cCE" = (
@@ -54495,7 +54496,7 @@
"gLC" = (
/obj/structure/reagent_dispensers/water_cooler,
/turf/open/floor/plasteel,
-/area/science/misc_lab)
+/area/science/mixing)
"gLD" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -70548,11 +70549,11 @@
/turf/open/floor/grass,
/area/service/hydroponics/garden)
"qqg" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 6
+/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
+ dir = 1
},
/turf/open/floor/plasteel,
-/area/science/misc_lab)
+/area/science/mixing)
"qqK" = (
/obj/structure/cable/yellow{
icon_state = "1-2"
@@ -78267,7 +78268,7 @@
dir = 4
},
/turf/open/floor/plasteel,
-/area/science/misc_lab)
+/area/science/mixing)
"vhM" = (
/obj/machinery/teleport/hub,
/turf/open/floor/plating,
@@ -81108,7 +81109,7 @@
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel,
-/area/science/misc_lab)
+/area/science/mixing)
"wRz" = (
/obj/effect/landmark/xeno_spawn,
/obj/machinery/atmospherics/components/unary/vent_pump/on{
@@ -82282,8 +82283,12 @@
/area/service/library)
"xAp" = (
/obj/structure/chair/comfy,
+/obj/machinery/airalarm{
+ dir = 4;
+ pixel_x = -22
+ },
/turf/open/floor/plasteel,
-/area/science/misc_lab)
+/area/science/mixing)
"xAs" = (
/obj/machinery/door/firedoor,
/obj/machinery/door/airlock/grunge{
@@ -82583,6 +82588,16 @@
/obj/effect/turf_decal/tile/neutral,
/turf/open/floor/plasteel,
/area/commons/dorms)
+"xHe" = (
+/obj/structure/cable/yellow{
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/science/mixing)
"xHm" = (
/obj/machinery/holopad,
/obj/structure/cable/yellow{
@@ -118574,7 +118589,7 @@ cJa
cJa
gHh
wRy
-wRy
+xHe
wRy
cBE
cAJ
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index d749c51798..3f07daecc2 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -9531,6 +9531,9 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
+/obj/structure/mirror{
+ pixel_y = 30
+ },
/turf/open/floor/plasteel/freezer,
/area/command/heads_quarters/captain)
"avJ" = (
@@ -16873,10 +16876,10 @@
dir = 4
},
/obj/effect/landmark/start/assistant,
+/obj/machinery/light/small,
/turf/open/floor/plasteel/freezer,
/area/commons/toilet/auxiliary)
"aNd" = (
-/obj/machinery/light/small,
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 1
},
@@ -24652,12 +24655,6 @@
},
/turf/open/space,
/area/solars/starboard)
-"beW" = (
-/obj/machinery/atmospherics/pipe/simple/general/visible{
- dir = 5
- },
-/turf/open/floor/plasteel,
-/area/engineering/atmos)
"beY" = (
/obj/machinery/camera{
c_tag = "Arrivals Central";
@@ -34476,7 +34473,7 @@
dir = 8
},
/obj/structure/cable{
- icon_state = "4-8"
+ icon_state = "0-4"
},
/turf/open/floor/plasteel/dark,
/area/command/heads_quarters/rd)
@@ -40389,8 +40386,8 @@
icon_state = "1-2"
},
/obj/machinery/atmospherics/components/binary/pump/on{
- dir = 8;
- name = "Unfiltered to Mix"
+ dir = 4;
+ name = "Ports to Mix"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -41430,6 +41427,9 @@
/obj/structure/cable{
icon_state = "1-2"
},
+/obj/machinery/atmospherics/pipe/simple/general/visible{
+ dir = 10
+ },
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bPW" = (
@@ -42132,7 +42132,9 @@
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bRw" = (
-/obj/machinery/atmospherics/pipe/simple/general/visible,
+/obj/machinery/atmospherics/pipe/simple/general/visible{
+ dir = 5
+ },
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bRx" = (
@@ -55286,15 +55288,6 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel,
/area/construction/mining/aux_base)
-"hEi" = (
-/obj/structure/cable{
- icon_state = "1-2"
- },
-/obj/machinery/atmospherics/pipe/simple/general/visible{
- dir = 10
- },
-/turf/open/floor/plasteel,
-/area/engineering/atmos)
"hEX" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 6
@@ -61354,12 +61347,6 @@
},
/turf/open/floor/engine,
/area/engineering/main)
-"uST" = (
-/obj/machinery/atmospherics/components/binary/pump{
- name = "Mix to Ports"
- },
-/turf/open/floor/plasteel,
-/area/engineering/atmos)
"uUQ" = (
/obj/machinery/door/airlock/maintenance{
name = "Engineering Maintenance";
@@ -100505,7 +100492,7 @@ bOr
bPU
kWG
bRw
-beW
+bMf
bMf
bMf
bMf
@@ -100761,9 +100748,9 @@ bKV
bOX
eEd
bQL
-uST
pEM
bMf
+bMf
qQu
qQu
bSU
@@ -101019,7 +101006,7 @@ bMg
bNj
bOp
bPV
-hEi
+sGJ
sGJ
bUw
bUw
diff --git a/_maps/templates/shelter_5.dmm b/_maps/templates/shelter_5.dmm
index 60066dc0c0..643f744fb9 100644
--- a/_maps/templates/shelter_5.dmm
+++ b/_maps/templates/shelter_5.dmm
@@ -253,6 +253,10 @@
/obj/machinery/dish_drive,
/turf/open/floor/pod/dark,
/area/survivalpod/nonpowered)
+"Vv" = (
+/obj/machinery/biogenerator,
+/turf/open/floor/pod/dark,
+/area/survivalpod/nonpowered)
"Ws" = (
/obj/structure/dresser,
/turf/open/floor/pod/dark,
@@ -274,12 +278,8 @@
/obj/structure/table/survival_pod,
/obj/item/shovel,
/obj/item/pickaxe,
-/obj/item/clothing/gloves/chameleon/insulated,
/obj/item/storage/toolbox/electrical,
-/turf/open/floor/pod/dark,
-/area/survivalpod/nonpowered)
-"Zd" = (
-/obj/machinery/seed_extractor,
+/obj/item/clothing/gloves/color/yellow,
/turf/open/floor/pod/dark,
/area/survivalpod/nonpowered)
@@ -453,8 +453,8 @@ FZ
Ng
wI
Ng
-FZ
-Zd
+Vv
+Lv
xC
td
FZ
diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm
index 541b50e9bd..04eeb515c9 100644
--- a/code/__DEFINES/citadel_defines.dm
+++ b/code/__DEFINES/citadel_defines.dm
@@ -101,6 +101,7 @@
#define NO_AUTO_WAG (1<<12)
#define GENITAL_EXAMINE (1<<13)
#define VORE_EXAMINE (1<<14)
+#define TRASH_FORCEFEED (1<<15)
#define TOGGLES_CITADEL 0
//belly sound pref things
diff --git a/code/__DEFINES/construction.dm b/code/__DEFINES/construction.dm
index d3caedac22..f4b0fe1593 100644
--- a/code/__DEFINES/construction.dm
+++ b/code/__DEFINES/construction.dm
@@ -81,7 +81,6 @@
#define CAT_AMMO "Ammunition"
#define CAT_PARTS "Weapon Parts"
#define CAT_ROBOT "Robots"
-#define CAT_MISC "Misc"
#define CAT_MISCELLANEOUS "Miscellaneous"
#define CAT_TOOL "Tools & Storage"
#define CAT_FURNITURE "Furniture"
diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm
index 649e0a029b..7b727fcc5a 100644
--- a/code/__DEFINES/inventory.dm
+++ b/code/__DEFINES/inventory.dm
@@ -159,6 +159,18 @@
#define TINT_DARKENED 2 //Threshold of tint level to apply weld mask overlay
#define TINT_BLIND 3 //Threshold of tint level to obscure vision fully
+// defines for AFK theft
+/// How many messages you can remember while logged out before you stop remembering new ones
+#define AFK_THEFT_MAX_MESSAGES 10
+/// If someone logs back in and there are entries older than this, just tell them they can't remember who it was or when
+#define AFK_THEFT_FORGET_DETAILS_TIME 5 MINUTES
+/// The index of the entry in 'afk_thefts' with the person's visible name at the time
+#define AFK_THEFT_NAME 1
+/// The index of the entry in 'afk_thefts' with the text
+#define AFK_THEFT_MESSAGE 2
+/// The index of the entry in 'afk_thefts' with the time it happened
+#define AFK_THEFT_TIME 3
+
//Allowed equipment lists for security vests and hardsuits.
GLOBAL_LIST_INIT(advanced_hardsuit_allowed, typecacheof(list(
diff --git a/code/__DEFINES/maths.dm b/code/__DEFINES/maths.dm
index 9e96c6a559..f56cd76a71 100644
--- a/code/__DEFINES/maths.dm
+++ b/code/__DEFINES/maths.dm
@@ -4,6 +4,8 @@
#define NUM_E 2.71828183
+#define SQRT_2 1.414214
+
#define PI 3.1416
#define INFINITY 1e31 //closer then enough
diff --git a/code/__DEFINES/spans.dm b/code/__DEFINES/spans.dm
new file mode 100644
index 0000000000..45eae3ce76
--- /dev/null
+++ b/code/__DEFINES/spans.dm
@@ -0,0 +1,114 @@
+// Sorted alphabetically
+#define span_abductor(str) ("" + str + "")
+#define span_admin(str) ("" + str + "")
+#define span_adminhelp(str) ("" + str + "")
+#define span_adminnotice(str) ("" + str + "")
+#define span_adminobserverooc(str) ("" + str + "")
+#define span_adminooc(str) ("" + str + "")
+#define span_adminsay(str) ("" + str + "")
+#define span_aiprivradio(str) ("" + str + "")
+#define span_alert(str) ("" + str + "")
+#define span_alertalien(str) ("" + str + "")
+#define span_alertsyndie(str) ("" + str + "")
+#define span_alertwarning(str) ("" + str + "")
+#define span_alien(str) ("" + str + "")
+#define span_announce(str) ("" + str + "")
+#define span_big(str) ("" + str + "")
+#define span_bigicon(str) ("" + str + "")
+#define span_binarysay(str) ("" + str + "")
+#define span_blue(str) ("" + str + "")
+#define span_blueteamradio(str) ("" + str + "")
+#define span_bold(str) ("" + str + "")
+#define span_boldannounce(str) ("" + str + "")
+#define span_boldnotice(str) ("" + str + "")
+#define span_boldwarning(str) ("" + str + "")
+#define span_centcomradio(str) ("" + str + "")
+#define span_changeling(str) ("" + str + "")
+#define span_clown(str) ("" + str + "")
+#define span_colossus(str) ("" + str + "")
+#define span_command_headset(str) ("" + str + "")
+#define span_comradio(str) ("" + str + "")
+#define span_cult(str) ("" + str + "")
+#define span_cultbold(str) ("" + str + "")
+#define span_cultboldtalic(str) ("" + str + "")
+#define span_cultitalic(str) ("" + str + "")
+#define span_cultlarge(str) ("" + str + "")
+#define span_danger(str) ("" + str + "")
+#define span_deadsay(str) ("" + str + "")
+#define span_deconversion_message(str) ("" + str + "")
+#define span_drone(str) ("" + str + "")
+#define span_engradio(str) ("" + str + "")
+#define span_extremelybig(str) ("" + str + "")
+#define span_ghostalert(str) ("" + str + "")
+#define span_green(str) ("" + str + "")
+#define span_greenannounce(str) ("" + str + "")
+#define span_greenteamradio(str) ("" + str + "")
+#define span_greentext(str) ("" + str + "")
+#define span_hear(str) ("" + str + "")
+#define span_hidden(str) ("" + str + "")
+#define span_hierophant(str) ("" + str + "")
+#define span_hierophant_warning(str) ("" + str + "")
+#define span_highlight(str) ("" + str + "")
+#define span_his_grace(str) ("" + str + "")
+#define span_holoparasite(str) ("" + str + "")
+#define span_hypnophrase(str) ("" + str + "")
+#define span_icon(str) ("" + str + "")
+#define span_info(str) ("" + str + "")
+#define span_interface(str) ("" + str + "")
+#define span_looc(str) ("" + str + "")
+#define span_medal(str) ("" + str + "")
+#define span_medradio(str) ("" + str + "")
+#define span_memo(str) ("" + str + "")
+#define span_memoedit(str) ("" + str + "")
+#define span_mind_control(str) ("" + str + "")
+#define span_minorannounce(str) ("" + str + "")
+#define span_monkey(str) ("" + str + "")
+#define span_monkeyhive(str) ("" + str + "")
+#define span_monkeylead(str) ("" + str + "")
+#define span_name(str) ("" + str + "")
+#define span_narsie(str) ("" + str + "")
+#define span_narsiesmall(str) ("" + str + "")
+#define span_nicegreen(str) ("" + str + "")
+#define span_notice(str) ("" + str + "")
+#define span_noticealien(str) ("" + str + "")
+#define span_ooc(str) ("" + str + "")
+#define span_papyrus(str) ("" + str + "")
+#define span_phobia(str) ("" + str + "")
+#define span_prefix(str) ("" + str + "")
+#define span_purple(str) ("" + str + "")
+#define span_radio(str) ("" + str + "")
+#define span_reallybig(str) ("" + str + "")
+#define span_red(str) ("" + str + "")
+#define span_redteamradio(str) ("" + str + "")
+#define span_redtext(str) ("" + str + "")
+#define span_resonate(str) ("" + str + "")
+#define span_revenbignotice(str) ("" + str + "")
+#define span_revenboldnotice(str) ("" + str + "")
+#define span_revendanger(str) ("" + str + "")
+#define span_revenminor(str) ("" + str + "")
+#define span_revennotice(str) ("" + str + "")
+#define span_revenwarning(str) ("" + str + "")
+#define span_robot(str) ("" + str + "")
+#define span_rose(str) ("" + str + "")
+#define span_sans(str) ("" + str + "")
+#define span_sciradio(str) ("" + str + "")
+#define span_secradio(str) ("" + str + "")
+#define span_servradio(str) ("" + str + "")
+#define span_singing(str) ("" + str + "")
+#define span_slime(str) ("" + str + "")
+#define span_small(str) ("" + str + "")
+#define span_smallnotice(str) ("" + str + "")
+#define span_smallnoticeital(str) ("" + str + "")
+#define span_spider(str) ("" + str + "")
+#define span_suicide(str) ("" + str + "")
+#define span_suppradio(str) ("" + str + "")
+#define span_swarmer(str) ("" + str + "")
+#define span_syndradio(str) ("" + str + "")
+#define span_tape_recorder(str) ("" + str + "")
+#define span_tinynotice(str) ("" + str + "")
+#define span_tinynoticeital(str) ("" + str + "")
+#define span_unconscious(str) ("" + str + "")
+#define span_userdanger(str) ("" + str + "")
+#define span_warning(str) ("" + str + "")
+#define span_yell(str) ("" + str + "")
+#define span_yellowteamradio(str) ("" + str + "")
diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm
index fb0ec3d39c..30899c0ca2 100644
--- a/code/__DEFINES/subsystems.dm
+++ b/code/__DEFINES/subsystems.dm
@@ -215,6 +215,12 @@
#define SSAIR_ATMOSMACHINERY_AIR 12
#define SSAIR_DEFERRED_AIRS 13
+// Subsystem delta times or tickrates, in seconds. I.e, how many seconds in between each process() call for objects being processed by that subsystem.
+// Only use these defines if you want to access some other objects processing delta_time, otherwise use the delta_time that is sent as a parameter to process()
+#define SSFLUIDS_DT (SSfluids.wait/10)
+#define SSMACHINES_DT (SSmachines.wait/10)
+#define SSMOBS_DT (SSmobs.wait/10)
+#define SSOBJ_DT (SSobj.wait/10)
//! ## Overlays subsystem
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 3082856ccf..eb9bdccc22 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -221,6 +221,7 @@
#define TRAIT_LIVING_NO_DENSITY "living_no_density"
/// forces us to not render our overlays
#define TRAIT_HUMAN_NO_RENDER "human_no_render"
+#define TRAIT_TRASHCAN "trashcan"
// mobility flag traits
// IN THE FUTURE, IT WOULD BE NICE TO DO SOMETHING SIMILAR TO https://github.com/tgstation/tgstation/pull/48923/files (ofcourse not nearly the same because I have my.. thoughts on it)
diff --git a/code/__DEFINES/voreconstants.dm b/code/__DEFINES/voreconstants.dm
index d2eb034813..372c5b776c 100644
--- a/code/__DEFINES/voreconstants.dm
+++ b/code/__DEFINES/voreconstants.dm
@@ -8,17 +8,22 @@
#define DM_UNABSORB "Un-absorb"
#define DIGESTABLE (1<<0)
-#define SHOW_VORE_PREFS (1<<1)
-#define DEVOURABLE (1<<2)
-#define FEEDING (1<<3)
-#define NO_VORE (1<<4)
-#define OPEN_PANEL (1<<5)
-#define ABSORBED (1<<6)
-#define VORE_INIT (1<<7)
-#define VOREPREF_INIT (1<<8)
-#define LICKABLE (1<<9)
+#define DEVOURABLE (1<<1)
+#define FEEDING (1<<2)
+#define NO_VORE (1<<3)
+#define ABSORBED (1<<4)
+#define VORE_INIT (1<<5)
+#define VOREPREF_INIT (1<<6)
+#define LICKABLE (1<<7)
+/// Can be smelled?
+#define SMELLABLE (1<<8)
+/// Can get absorbed?
+#define ABSORBABLE (1<<9)
+/// Can get simplemob vored?
+#define MOBVORE (1<<10)
-#define MAX_VORE_FLAG (1<<10)-1 // change this whenever you add a vore flag, must be largest vore flag*2-1
+/// Change this whenever you add a vore flag, must be largest vore flag*2-1
+#define MAX_VORE_FLAG (1<<11)-1
#define isbelly(A) istype(A, /obj/belly)
diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm
index 7e2abebcf9..2d0601d839 100644
--- a/code/__HELPERS/_lists.dm
+++ b/code/__HELPERS/_lists.dm
@@ -19,6 +19,8 @@
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= length(L) ? L[I] : null) : L[I]) : null)
#define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V;
#define LAZYLEN(L) length(L)
+//Sets a list to null
+#define LAZYNULL(L) L = null
#define LAZYCLEARLIST(L) if(L) L.Cut()
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
#define reverseList(L) reverseRange(L.Copy())
diff --git a/code/__HELPERS/do_after.dm b/code/__HELPERS/do_after.dm
index c0c07e3620..3ec1aa9b08 100644
--- a/code/__HELPERS/do_after.dm
+++ b/code/__HELPERS/do_after.dm
@@ -75,7 +75,7 @@
while(timeleft > 0)
stoplag(1)
var/timepassed = world.time - tick_time
- timepassed = world.time
+ tick_time = world.time
progbar?.update(TIMELEFT)
if(QDELETED(user) || QDELETED(target) || (user.loc == null) || (target.loc == null))
. = FALSE
diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm
index b41b7356a8..daa4f5879d 100644
--- a/code/_globalvars/lists/maintenance_loot.dm
+++ b/code/_globalvars/lists/maintenance_loot.dm
@@ -112,6 +112,7 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
/obj/item/storage/box/marshmallow = 2,
/obj/item/clothing/gloves/tackler/offbrand = 1,
/obj/item/stack/sticky_tape = 1,
+ /obj/effect/spawner/lootdrop/grille_or_trash = 15,
"" = 3
))
diff --git a/code/controllers/configuration/entries/admin.dm b/code/controllers/configuration/entries/admin.dm
new file mode 100644
index 0000000000..3b5b437742
--- /dev/null
+++ b/code/controllers/configuration/entries/admin.dm
@@ -0,0 +1,64 @@
+/datum/config_entry/flag/admin_legacy_system //Defines whether the server uses the legacy admin system with admins.txt or the SQL system
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/flag/protect_legacy_admins //Stops any admins loaded by the legacy system from having their rank edited by the permissions panel
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/flag/protect_legacy_ranks //Stops any ranks loaded by the legacy system from having their flags edited by the permissions panel
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/flag/enable_localhost_rank //Gives the !localhost! rank to any client connecting from 127.0.0.1 or ::1
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/flag/load_legacy_ranks_only //Loads admin ranks only from legacy admin_ranks.txt, while enabled ranks are mirrored to the database
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/flag/mentors_mobname_only
+
+/datum/config_entry/flag/mentor_legacy_system //Defines whether the server uses the legacy mentor system with mentors.txt or the SQL system
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/flag/forbid_singulo_possession
+
+/datum/config_entry/flag/see_own_notes //Can players see their own admin notes
+
+/datum/config_entry/number/note_fresh_days
+ config_entry_value = null
+ min_val = 0
+ integer = FALSE
+
+/datum/config_entry/number/note_stale_days
+ config_entry_value = null
+ min_val = 0
+ integer = FALSE
+
+/datum/config_entry/flag/autoconvert_notes //if all connecting player's notes should attempt to be converted to the database
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/flag/announce_admin_logout
+
+/datum/config_entry/flag/announce_admin_login
+
+/datum/config_entry/string/centcom_ban_db // URL for the CentCom Galactic Ban DB API
+
+/datum/config_entry/flag/autoadmin // if autoadmin is enabled
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/string/autoadmin_rank // the rank for autoadmins
+ config_entry_value = "Game Master"
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/flag/allow_admin_ooccolor // Allows admins with relevant permissions to have their own ooc colour
+
+/datum/config_entry/flag/popup_admin_pm // adminPMs to non-admins show in a pop-up 'reply' window when set
+
+/datum/config_entry/flag/guest_jobban
+
+/datum/config_entry/flag/ban_legacy_system //Defines whether the server uses the legacy banning system with the files in /data or the SQL system.
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/flag/guest_ban
+
+/datum/config_entry/flag/automute_on //enables automuting/spam prevention
+
+/datum/config_entry/flag/debug_admin_hrefs
diff --git a/code/controllers/configuration/entries/alert.dm b/code/controllers/configuration/entries/alert.dm
new file mode 100644
index 0000000000..6177c602db
--- /dev/null
+++ b/code/controllers/configuration/entries/alert.dm
@@ -0,0 +1,26 @@
+/datum/config_entry/string/alert_green
+ config_entry_value = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced."
+
+/datum/config_entry/string/alert_blue_upto
+ config_entry_value = "The station has received reliable information about potential threats to the station. Security staff may have weapons visible, random searches are permitted."
+
+/datum/config_entry/string/alert_blue_downto
+ config_entry_value = "Significant confirmed threats have been neutralized. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still permitted."
+
+/datum/config_entry/string/alert_amber_upto
+ config_entry_value = "There are significant confirmed threats to the station. Security staff may have weapons unholstered at all times. Random searches are allowed and advised."
+
+/datum/config_entry/string/alert_amber_downto
+ config_entry_value = "The immediate threat has passed. Security is no longer authorized to use lethal force, but may continue to have weapons drawn. Access requirements have been restored."
+
+/datum/config_entry/string/alert_red_upto
+ config_entry_value = "There is an immediate serious threat to the station. Security is now authorized to use lethal force. Additionally, access requirements on some machines have been lifted."
+
+/datum/config_entry/string/alert_red_downto
+ config_entry_value = "The station's destruction has been averted. There is still however an immediate serious threat to the station. Security is still authorized to use lethal force."
+
+/datum/config_entry/string/alert_delta
+ config_entry_value = "Destruction of the station is imminent. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill."
+
+/datum/config_entry/number/minimum_secborg_alert //Minimum alert level for secborgs to be chosen.
+ config_entry_value = 3
diff --git a/code/controllers/configuration/entries/antag_rep.dm b/code/controllers/configuration/entries/antag_rep.dm
new file mode 100644
index 0000000000..c34eef4159
--- /dev/null
+++ b/code/controllers/configuration/entries/antag_rep.dm
@@ -0,0 +1,17 @@
+/datum/config_entry/flag/use_antag_rep // see game_options.txt for details
+
+/datum/config_entry/number/antag_rep_maximum
+ config_entry_value = 200
+ min_val = 0
+
+/datum/config_entry/number/default_antag_tickets
+ config_entry_value = 100
+ min_val = 0
+
+/datum/config_entry/number/max_tickets_per_roll
+ config_entry_value = 100
+ min_val = 0
+
+/datum/config_entry/keyed_list/antag_rep
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
diff --git a/code/controllers/configuration/entries/connections.dm b/code/controllers/configuration/entries/connections.dm
new file mode 100644
index 0000000000..acdf588e5a
--- /dev/null
+++ b/code/controllers/configuration/entries/connections.dm
@@ -0,0 +1,106 @@
+/datum/config_entry/flag/panic_bunker // prevents people the server hasn't seen before from connecting
+
+/datum/config_entry/number/panic_bunker_living // living time in minutes that a player needs to pass the panic bunker
+
+/datum/config_entry/string/panic_bunker_message
+ config_entry_value = "Sorry but the server is currently not accepting connections from never before seen players."
+
+/datum/config_entry/string/panic_server_name
+
+/datum/config_entry/string/panic_server_name/ValidateAndSet(str_val)
+ return str_val != "\[Put the name here\]" && ..()
+
+/datum/config_entry/string/panic_server_address //Reconnect a player this linked server if this server isn't accepting new players
+
+/datum/config_entry/string/panic_server_address/ValidateAndSet(str_val)
+ return str_val != "byond://address:port" && ..()
+
+/datum/config_entry/number/max_bunker_days
+ config_entry_value = 7
+ min_val = 1
+
+/datum/config_entry/number/notify_new_player_age // how long do we notify admins of a new player
+ min_val = -1
+
+/datum/config_entry/number/notify_new_player_account_age // how long do we notify admins of a new byond account
+ min_val = 0
+
+/datum/config_entry/flag/age_verification //are we using the automated age verification which asks users if they're 18+?
+ config_entry_value = TRUE
+
+/datum/config_entry/flag/irc_first_connection_alert // do we notify the irc channel when somebody is connecting for the first time?
+
+/datum/config_entry/flag/check_randomizer
+
+/datum/config_entry/string/ipintel_email
+
+/datum/config_entry/string/ipintel_email/ValidateAndSet(str_val)
+ return str_val != "ch@nge.me" && ..()
+
+/datum/config_entry/number/ipintel_rating_bad
+ config_entry_value = 1
+ integer = FALSE
+ min_val = 0
+ max_val = 1
+
+/datum/config_entry/number/ipintel_save_good
+ config_entry_value = 12
+ min_val = 0
+
+/datum/config_entry/number/ipintel_save_bad
+ config_entry_value = 1
+ min_val = 0
+
+/datum/config_entry/string/ipintel_domain
+ config_entry_value = "check.getipintel.net"
+
+/datum/config_entry/flag/aggressive_changelog
+
+/datum/config_entry/flag/allow_webclient
+
+/datum/config_entry/flag/webclient_only_byond_members
+
+/datum/config_entry/number/client_warn_version
+ config_entry_value = null
+ min_val = 500
+
+/datum/config_entry/number/client_warn_version
+ config_entry_value = null
+ min_val = 500
+
+/datum/config_entry/string/client_warn_message
+ config_entry_value = "Your version of byond may have issues or be blocked from accessing this server in the future."
+
+/datum/config_entry/flag/client_warn_popup
+
+/datum/config_entry/number/client_error_version
+ config_entry_value = null
+ min_val = 500
+
+/datum/config_entry/string/client_error_message
+ config_entry_value = "Your version of byond is too old, may have issues, and is blocked from accessing this server."
+
+/datum/config_entry/number/client_error_build
+ config_entry_value = null
+ min_val = 0
+
+/datum/config_entry/number/soft_popcap
+ config_entry_value = null
+ min_val = 0
+
+/datum/config_entry/number/hard_popcap
+ config_entry_value = null
+ min_val = 0
+
+/datum/config_entry/number/extreme_popcap
+ config_entry_value = null
+ min_val = 0
+
+/datum/config_entry/string/soft_popcap_message
+ config_entry_value = "Be warned that the server is currently serving a high number of users, consider using alternative game servers."
+
+/datum/config_entry/string/hard_popcap_message
+ config_entry_value = "The server is currently serving a high number of users, You cannot currently join. You may wait for the number of living crew to decline, observe, or find alternative servers."
+
+/datum/config_entry/string/extreme_popcap_message
+ config_entry_value = "The server is currently serving a high number of users, find alternative servers."
diff --git a/code/controllers/configuration/entries/debris.dm b/code/controllers/configuration/entries/debris.dm
new file mode 100644
index 0000000000..1cc2c2d7b7
--- /dev/null
+++ b/code/controllers/configuration/entries/debris.dm
@@ -0,0 +1,16 @@
+/// Amount of dirtyness tiles need to spawn dirt.
+/datum/config_entry/number/turf_dirt_threshold
+ config_entry_value = 100
+ min_val = 1
+ integer = TRUE
+
+/// Alpha dirt starts at
+/datum/config_entry/number/dirt_alpha_starting
+ config_entry_value = 127
+ max_val = 255
+ min_val = 0
+ integer = TRUE
+
+/// Dirtyness multiplier for making turfs dirty
+/datum/config_entry/number/turf_dirty_multiplier
+ config_entry_value = 1
diff --git a/code/controllers/configuration/entries/fetish_content.dm b/code/controllers/configuration/entries/fetish_content.dm
new file mode 100644
index 0000000000..1de796a11d
--- /dev/null
+++ b/code/controllers/configuration/entries/fetish_content.dm
@@ -0,0 +1,45 @@
+/datum/config_entry/keyed_list/breasts_cups_prefs
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_FLAG
+ config_entry_value = list("a", "b", "c", "d", "e") //keep these lowercase
+
+/datum/config_entry/number/penis_min_inches_prefs
+ config_entry_value = 1
+ min_val = 0
+
+/datum/config_entry/number/penis_max_inches_prefs
+ config_entry_value = 20
+ min_val = 0
+
+/datum/config_entry/keyed_list/safe_visibility_toggles
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_FLAG
+ config_entry_value = list(GEN_VISIBLE_NO_CLOTHES, GEN_VISIBLE_NO_UNDIES, GEN_VISIBLE_NEVER) //refer to cit_helpers for all toggles.
+
+//Body size configs, the feature will be disabled if both min and max have the same value.
+/datum/config_entry/number/body_size_min
+ config_entry_value = 0.9
+ min_val = 0.1 //to avoid issues with zeros and negative values.
+ max_val = RESIZE_DEFAULT_SIZE
+ integer = FALSE
+
+/datum/config_entry/number/body_size_max
+ config_entry_value = 1.25
+ min_val = RESIZE_DEFAULT_SIZE
+ integer = FALSE
+
+//Penalties given to characters with a body size smaller than this value,
+//to compensate for their smaller hitbox.
+//To disable, just make sure the value is lower than 'body_size_min'
+/datum/config_entry/number/threshold_body_size_penalty
+ config_entry_value = RESIZE_DEFAULT_SIZE
+ min_val = 0
+ max_val = RESIZE_DEFAULT_SIZE
+ integer = FALSE
+
+//multiplicative slowdown multiplier. See 'dna.update_body_size' for the operation.
+//doesn't apply to floating or crawling mobs
+/datum/config_entry/number/body_size_slowdown_multiplier
+ config_entry_value = 0
+ min_val = 0
+ integer = FALSE
diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm
deleted file mode 100644
index 08989469f5..0000000000
--- a/code/controllers/configuration/entries/game_options.dm
+++ /dev/null
@@ -1,619 +0,0 @@
-/datum/config_entry/number_list/repeated_mode_adjust
-
-/datum/config_entry/keyed_list/probability
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_NUM
-
-/datum/config_entry/keyed_list/probability/ValidateListEntry(key_name)
- return key_name in config.modes
-
-/datum/config_entry/keyed_list/chaos_level
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_NUM
-
-/datum/config_entry/keyed_list/chaos_level/ValidateListEntry(key_name)
- return key_name in config.modes
-
-/datum/config_entry/keyed_list/max_pop
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_NUM
-
-/datum/config_entry/keyed_list/max_pop/ValidateListEntry(key_name)
- return key_name in config.modes
-
-/datum/config_entry/keyed_list/min_pop
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_NUM
-
-/datum/config_entry/keyed_list/min_pop/ValidateListEntry(key_name, key_value)
- return key_name in config.modes
-
-/datum/config_entry/keyed_list/continuous // which roundtypes continue if all antagonists die
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_FLAG
-
-/datum/config_entry/keyed_list/continuous/ValidateListEntry(key_name, key_value)
- return key_name in config.modes
-
-/datum/config_entry/keyed_list/midround_antag // which roundtypes use the midround antagonist system
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_FLAG
-
-/datum/config_entry/keyed_list/midround_antag/ValidateListEntry(key_name, key_value)
- return key_name in config.modes
-
-/datum/config_entry/keyed_list/force_antag_count
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_FLAG
-
-/datum/config_entry/keyed_list/force_antag_count/ValidateListEntry(key_name, key_value)
- return key_name in config.modes
-
-/datum/config_entry/keyed_list/policy
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_TEXT
-
-/datum/config_entry/number/damage_multiplier
- config_entry_value = 1
- integer = FALSE
-
-/datum/config_entry/number/minimal_access_threshold //If the number of players is larger than this threshold, minimal access will be turned on.
- min_val = 0
-
-/datum/config_entry/flag/jobs_have_minimal_access //determines whether jobs use minimal access or expanded access.
-
-/datum/config_entry/flag/assistants_have_maint_access
-
-/datum/config_entry/flag/security_has_maint_access
-
-/datum/config_entry/flag/everyone_has_maint_access
-
-/datum/config_entry/flag/sec_start_brig //makes sec start in brig instead of dept sec posts
-
-/datum/config_entry/flag/force_random_names
-
-/datum/config_entry/flag/humans_need_surnames
-
-/datum/config_entry/flag/allow_ai // allow ai job
-
-/datum/config_entry/flag/allow_ai_multicam //whether the AI can use their multicam
-
-/datum/config_entry/flag/disable_human_mood
-
-/datum/config_entry/flag/disable_borg_flash_knockdown //Should borg flashes be capable of knocking humanoid entities down?
-
-/datum/config_entry/flag/weaken_secborg //Brings secborgs and k9s back in-line with the other borg modules
-
-/datum/config_entry/flag/disable_secborg // disallow secborg module to be chosen.
-
-/datum/config_entry/flag/disable_peaceborg
-
-/datum/config_entry/flag/economy //money money money money money money money money money money money money
-
-/datum/config_entry/number/minimum_secborg_alert //Minimum alert level for secborgs to be chosen.
- config_entry_value = 3
-
-/datum/config_entry/number/traitor_scaling_coeff //how much does the amount of players get divided by to determine traitors
- config_entry_value = 6
- min_val = 1
-
-/datum/config_entry/number/brother_scaling_coeff //how many players per brother team
- config_entry_value = 25
- min_val = 1
-
-/datum/config_entry/number/changeling_scaling_coeff //how much does the amount of players get divided by to determine changelings
- config_entry_value = 6
- min_val = 1
-
-/datum/config_entry/number/ecult_scaling_coeff //how much does the amount of players get divided by to determine e_cult
- config_entry_value = 6
- integer = FALSE
- min_val = 1
-
-/datum/config_entry/number/security_scaling_coeff //how much does the amount of players get divided by to determine open security officer positions
- config_entry_value = 8
- min_val = 1
-
-/datum/config_entry/number/abductor_scaling_coeff //how many players per abductor team
- config_entry_value = 15
- min_val = 1
-
-/datum/config_entry/number/traitor_objectives_amount
- config_entry_value = 2
- min_val = 0
-
-/datum/config_entry/number/brother_objectives_amount
- config_entry_value = 2
- min_val = 0
-
-/datum/config_entry/flag/reactionary_explosions //If we use reactionary explosions, explosions that react to walls and doors
-
-/datum/config_entry/flag/protect_roles_from_antagonist //If security and such can be traitor/cult/other
-
-/datum/config_entry/flag/protect_assistant_from_antagonist //If assistants can be traitor/cult/other
-
-/datum/config_entry/flag/enforce_human_authority //If non-human species are barred from joining as a head of staff
-
-/datum/config_entry/flag/allow_latejoin_antagonists // If late-joining players can be traitor/changeling
-
-/datum/config_entry/flag/use_antag_rep // see game_options.txt for details
-
-/datum/config_entry/number/antag_rep_maximum
- config_entry_value = 200
- min_val = 0
-
-/datum/config_entry/number/default_antag_tickets
- config_entry_value = 100
- min_val = 0
-
-/datum/config_entry/number/max_tickets_per_roll
- config_entry_value = 100
- min_val = 0
-
-/datum/config_entry/number/midround_antag_time_check // How late (in minutes you want the midround antag system to stay on, setting this to 0 will disable the system)
- config_entry_value = 60
- min_val = 0
-
-/datum/config_entry/number/midround_antag_life_check // A ratio of how many people need to be alive in order for the round not to immediately end in midround antagonist
- config_entry_value = 0.7
- integer = FALSE
- min_val = 0
- max_val = 1
-
-/datum/config_entry/number/suicide_reenter_round_timer
- config_entry_value = 30
- min_val = 0
-
-/datum/config_entry/number/roundstart_suicide_time_limit
- config_entry_value = 30
- min_val = 0
-
-/datum/config_entry/number/shuttle_refuel_delay
- config_entry_value = 12000
- min_val = 0
-
-/datum/config_entry/flag/show_game_type_odds //if set this allows players to see the odds of each roundtype on the get revision screen
-
-/datum/config_entry/keyed_list/roundstart_races //races you can play as from the get go.
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_FLAG
-
-/datum/config_entry/flag/join_with_mutant_humans //players can pick mutant bodyparts for humans before joining the game
-
-/datum/config_entry/flag/no_summon_guns //No
-
-/datum/config_entry/flag/no_summon_magic //Fun
-
-/datum/config_entry/flag/no_summon_events //Allowed
-
-/datum/config_entry/flag/no_summon_traumas //!
-
-/datum/config_entry/flag/no_intercept_report //Whether or not to send a communications intercept report roundstart. This may be overridden by gamemodes.
-
-/datum/config_entry/number/arrivals_shuttle_dock_window //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station
- config_entry_value = 55
- min_val = 30
-
-/datum/config_entry/flag/arrivals_shuttle_require_undocked //Require the arrivals shuttle to be undocked before latejoiners can join
-
-/datum/config_entry/flag/arrivals_shuttle_require_safe_latejoin //Require the arrivals shuttle to be operational in order for latejoiners to join
-
-/datum/config_entry/string/alert_green
- config_entry_value = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced."
-
-/datum/config_entry/string/alert_blue_upto
- config_entry_value = "The station has received reliable information about potential threats to the station. Security staff may have weapons visible, random searches are permitted."
-
-/datum/config_entry/string/alert_blue_downto
- config_entry_value = "Significant confirmed threats have been neutralized. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still permitted."
-
-/datum/config_entry/string/alert_amber_upto
- config_entry_value = "There are significant confirmed threats to the station. Security staff may have weapons unholstered at all times. Random searches are allowed and advised."
-
-/datum/config_entry/string/alert_amber_downto
- config_entry_value = "The immediate threat has passed. Security is no longer authorized to use lethal force, but may continue to have weapons drawn. Access requirements have been restored."
-
-/datum/config_entry/string/alert_red_upto
- config_entry_value = "There is an immediate serious threat to the station. Security is now authorized to use lethal force. Additionally, access requirements on some machines have been lifted."
-
-/datum/config_entry/string/alert_red_downto
- config_entry_value = "The station's destruction has been averted. There is still however an immediate serious threat to the station. Security is still authorized to use lethal force."
-
-/datum/config_entry/string/alert_delta
- config_entry_value = "Destruction of the station is imminent. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill."
-
-/datum/config_entry/flag/revival_pod_plants
-
-/datum/config_entry/flag/revival_cloning
-
-/datum/config_entry/number/revival_brain_life
- config_entry_value = -1
- min_val = -1
-
-/datum/config_entry/flag/ooc_during_round
-
-/datum/config_entry/flag/emojis
-
-/datum/config_entry/keyed_list/multiplicative_movespeed
- key_mode = KEY_MODE_TYPE
- value_mode = VALUE_MODE_NUM
- abstract_type = /datum/config_entry/keyed_list/multiplicative_movespeed
-
-/datum/config_entry/keyed_list/multiplicative_movespeed/ValidateAndSet()
- . = ..()
- if(.)
- update_config_movespeed_type_lookup(TRUE)
-
-/datum/config_entry/keyed_list/multiplicative_movespeed/vv_edit_var(var_name, var_value)
- . = ..()
- if(. && (var_name == NAMEOF(src, config_entry_value)))
- update_config_movespeed_type_lookup(TRUE)
-
-/datum/config_entry/keyed_list/multiplicative_movespeed/normal
- name = "multiplicative_movespeed"
- config_entry_value = list( //DEFAULTS
- /mob/living/simple_animal = 1,
- /mob/living/silicon/pai = 1,
- /mob/living/carbon/alien/humanoid/sentinel = 0.25,
- /mob/living/carbon/alien/humanoid/drone = 0.5,
- /mob/living/carbon/alien/humanoid/royal/praetorian = 1,
- /mob/living/carbon/alien/humanoid/royal/queen = 3
- )
-
-/datum/config_entry/keyed_list/multiplicative_movespeed/floating
- name = "multiplicative_movespeed_floating"
- config_entry_value = list(
- /mob/living = 0,
- /mob/living/carbon/alien/humanoid = 0,
- /mob/living/carbon/alien/humanoid/royal/praetorian = 0,
- /mob/living/carbon/alien/humanoid/royal/queen = 2
- )
-
-/datum/config_entry/number/sprintless_stagger_slowdown
- config_entry_value = 0
-
-/datum/config_entry/number/melee_stagger_factor
- config_entry_value = 1
-
-/datum/config_entry/number/sprintless_off_balance_slowdown
- config_entry_value = 0.85
-
-/datum/config_entry/number/movedelay //Used for modifying movement speed for mobs.
- abstract_type = /datum/config_entry/number/movedelay
- integer = FALSE
-
-/datum/config_entry/number/movedelay/ValidateAndSet()
- . = ..()
- if(.)
- update_mob_config_movespeeds()
-
-/datum/config_entry/number/movedelay/vv_edit_var(var_name, var_value)
- . = ..()
- if(. && (var_name == NAMEOF(src, config_entry_value)))
- update_mob_config_movespeeds()
-
-/datum/config_entry/number/movedelay/run_delay
-
-/datum/config_entry/number/movedelay/run_delay/ValidateAndSet()
- . = ..()
- var/datum/movespeed_modifier/config_walk_run/M = get_cached_movespeed_modifier(/datum/movespeed_modifier/config_walk_run/run)
- M.sync()
-
-/datum/config_entry/number/movedelay/walk_delay
-
-/datum/config_entry/number/movedelay/walk_delay/ValidateAndSet()
- . = ..()
- var/datum/movespeed_modifier/config_walk_run/M = get_cached_movespeed_modifier(/datum/movespeed_modifier/config_walk_run/walk)
- M.sync()
-
-/datum/config_entry/flag/sprint_enabled
- config_entry_value = TRUE
-
-/datum/config_entry/flag/sprint_enabled/ValidateAndSet(str_val)
- . = ..()
- for(var/datum/hud/human/H)
- H.assert_move_intent_ui()
- if(!config_entry_value) // disabled
- for(var/mob/living/L in world)
- L.disable_intentional_sprint_mode()
-
-/datum/config_entry/number/movedelay/sprint_speed_increase
- config_entry_value = 1
-
-/datum/config_entry/number/movedelay/sprint_max_tiles_increase
- config_entry_value = 5
-
-/datum/config_entry/number/movedelay/sprint_absolute_max_tiles
- config_entry_value = 13
-
-/datum/config_entry/number/movedelay/sprint_buffer_max
- config_entry_value = 24
-
-/datum/config_entry/number/movedelay/sprint_stamina_cost
- config_entry_value = 1.4
-
-/datum/config_entry/number/movedelay/sprint_buffer_regen_per_ds
- config_entry_value = 0.4
-
-/////////////////////////////////////////////////Outdated move delay
-/datum/config_entry/number/outdated_movedelay
- deprecated_by = /datum/config_entry/keyed_list/multiplicative_movespeed/normal
- abstract_type = /datum/config_entry/number/outdated_movedelay
-
- var/movedelay_type
-
-/datum/config_entry/number/outdated_movedelay/DeprecationUpdate(value)
- return "[movedelay_type] [value]"
-
-/datum/config_entry/number/outdated_movedelay/human_delay
- movedelay_type = /mob/living/carbon/human
-/datum/config_entry/number/outdated_movedelay/robot_delay
- movedelay_type = /mob/living/silicon/robot
-/datum/config_entry/number/outdated_movedelay/monkey_delay
- movedelay_type = /mob/living/carbon/monkey
-/datum/config_entry/number/outdated_movedelay/alien_delay
- movedelay_type = /mob/living/carbon/alien
-/datum/config_entry/number/outdated_movedelay/slime_delay
- movedelay_type = /mob/living/simple_animal/slime
-/datum/config_entry/number/outdated_movedelay/animal_delay
- movedelay_type = /mob/living/simple_animal
-/////////////////////////////////////////////////
-
-/datum/config_entry/flag/roundstart_away //Will random away mission be loaded.
-
-/datum/config_entry/flag/roundstart_vr //Will virtual reality missions be loaded?
-
-/datum/config_entry/number/gateway_delay //How long the gateway takes before it activates. Default is half an hour. Only matters if roundstart_away is enabled.
- config_entry_value = 18000
- min_val = 0
-
-/datum/config_entry/flag/ghost_interaction
-
-/datum/config_entry/flag/silent_ai
-/datum/config_entry/flag/silent_borg
-
-/datum/config_entry/flag/sandbox_autoclose // close the sandbox panel after spawning an item, potentially reducing griff
-
-/datum/config_entry/number/default_laws //Controls what laws the AI spawns with.
- config_entry_value = 0
- min_val = 0
- max_val = 3
-
-/datum/config_entry/number/silicon_max_law_amount
- config_entry_value = 12
- min_val = 0
-
-/datum/config_entry/keyed_list/random_laws
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_FLAG
-
-/datum/config_entry/keyed_list/law_weight
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_NUM
- splitter = ","
-
-/datum/config_entry/number/overflow_cap
- config_entry_value = -1
- min_val = -1
-
-/datum/config_entry/string/overflow_job
- config_entry_value = "Assistant"
-
-/datum/config_entry/flag/starlight
-/datum/config_entry/flag/grey_assistants
-
-/datum/config_entry/number/lavaland_budget
- config_entry_value = 60
- min_val = 0
-
-/datum/config_entry/number/space_budget
- config_entry_value = 16
- min_val = 0
-
-/datum/config_entry/number/icemoon_budget
- config_entry_value = 90
- integer = FALSE
- min_val = 0
-
-/datum/config_entry/number/station_space_budget
- config_entry_value = 10
- min_val = 0
-
-/datum/config_entry/flag/allow_random_events // Enables random events mid-round when set
-
-/datum/config_entry/number/events_min_time_mul // Multipliers for random events minimal starting time and minimal players amounts
- config_entry_value = 1
- min_val = 0
- integer = FALSE
-
-/datum/config_entry/number/events_min_players_mul
- config_entry_value = 1
- min_val = 0
- integer = FALSE
-
-/datum/config_entry/number/mice_roundstart
- config_entry_value = 10
- min_val = 0
-
-/datum/config_entry/number/bombcap
- config_entry_value = 14
- min_val = 4
-
-/datum/config_entry/number/bombcap/ValidateAndSet(str_val)
- . = ..()
- if(.)
- GLOB.MAX_EX_DEVESTATION_RANGE = round(config_entry_value / 4)
- GLOB.MAX_EX_HEAVY_RANGE = round(config_entry_value / 2)
- GLOB.MAX_EX_LIGHT_RANGE = config_entry_value
- GLOB.MAX_EX_FLASH_RANGE = config_entry_value
- GLOB.MAX_EX_FLAME_RANGE = config_entry_value
-
-/datum/config_entry/number/emergency_shuttle_autocall_threshold
- min_val = 0
- max_val = 1
- integer = FALSE
-
-/datum/config_entry/flag/ic_printing
-
-/datum/config_entry/flag/roundstart_traits
-
-/datum/config_entry/flag/enable_night_shifts
-
-/datum/config_entry/number/night_shift_public_areas_only
- config_entry_value = NIGHTSHIFT_AREA_PUBLIC
-
-/datum/config_entry/flag/nightshift_toggle_requires_auth
- config_entry_value = FALSE
-
-/datum/config_entry/flag/nightshift_toggle_public_requires_auth
- config_entry_value = TRUE
-
-/datum/config_entry/flag/randomize_shift_time
-
-/datum/config_entry/flag/shift_time_realtime
-
-/datum/config_entry/keyed_list/antag_rep
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_NUM
-
-/datum/config_entry/keyed_list/job_threat
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_NUM
-
-/datum/config_entry/keyed_list/antag_threat
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_NUM
-
-/datum/config_entry/number/monkeycap
- config_entry_value = 64
- min_val = 0
-
-/datum/config_entry/number/ratcap
- config_entry_value = 64
- min_val = 0
-
-/datum/config_entry/flag/disable_stambuffer
-
-/datum/config_entry/keyed_list/box_random_engine
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_NUM
- lowercase = FALSE
- splitter = ","
-
-/datum/config_entry/flag/pai_custom_holoforms
-
-/datum/config_entry/number/marauder_delay_non_reebe
- config_entry_value = 1800
- min_val = 0
-
-/datum/config_entry/flag/allow_clockwork_marauder_on_station
- config_entry_value = TRUE
-
-/datum/config_entry/flag/modetier_voting
-
-/datum/config_entry/flag/must_be_readied_to_vote_gamemode
-
-/datum/config_entry/number/dropped_modes
- config_entry_value = 3
-
-/datum/config_entry/flag/suicide_allowed
-
-/datum/config_entry/keyed_list/breasts_cups_prefs
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_FLAG
- config_entry_value = list("a", "b", "c", "d", "e") //keep these lowercase
-
-/datum/config_entry/number/penis_min_inches_prefs
- config_entry_value = 1
- min_val = 0
-
-/datum/config_entry/number/penis_max_inches_prefs
- config_entry_value = 20
- min_val = 0
-
-/datum/config_entry/keyed_list/safe_visibility_toggles
- key_mode = KEY_MODE_TEXT
- value_mode = VALUE_MODE_FLAG
- config_entry_value = list(GEN_VISIBLE_NO_CLOTHES, GEN_VISIBLE_NO_UNDIES, GEN_VISIBLE_NEVER) //refer to cit_helpers for all toggles.
-
-//Body size configs, the feature will be disabled if both min and max have the same value.
-/datum/config_entry/number/body_size_min
- config_entry_value = 0.9
- min_val = 0.1 //to avoid issues with zeros and negative values.
- max_val = RESIZE_DEFAULT_SIZE
- integer = FALSE
-
-/datum/config_entry/number/body_size_max
- config_entry_value = 1.25
- min_val = RESIZE_DEFAULT_SIZE
- integer = FALSE
-
-//Penalties given to characters with a body size smaller than this value,
-//to compensate for their smaller hitbox.
-//To disable, just make sure the value is lower than 'body_size_min'
-/datum/config_entry/number/threshold_body_size_penalty
- config_entry_value = RESIZE_DEFAULT_SIZE
- min_val = 0
- max_val = RESIZE_DEFAULT_SIZE
- integer = FALSE
-
-//multiplicative slowdown multiplier. See 'dna.update_body_size' for the operation.
-//doesn't apply to floating or crawling mobs
-/datum/config_entry/number/body_size_slowdown_multiplier
- config_entry_value = 0
- min_val = 0
- integer = FALSE
-
-//Allows players to set a hexadecimal color of their choice as skin tone, on top of the standard ones.
-/datum/config_entry/flag/allow_custom_skintones
-
-///Initial loadout points
-/datum/config_entry/number/initial_gear_points
- config_entry_value = 10
-
-/**
- * Enables the FoV component, which hides objects and mobs behind the parent from their sight, unless they turn around, duh.
- * Camera mobs, AIs, ghosts and some other are of course exempt from this. This also doesn't influence simplemob AI, for the best.
- */
-/datum/config_entry/flag/use_field_of_vision
-
-//Shuttle size limiter
-/datum/config_entry/number/max_shuttle_count
- config_entry_value = 6
-
-/datum/config_entry/number/max_shuttle_size
- config_entry_value = 500
-
-//wound config stuff (increases the max injury roll, making injuries more likely)
-/datum/config_entry/number/wound_exponent
- config_entry_value = WOUND_DAMAGE_EXPONENT
- min_val = 0
- integer = FALSE
-
-//adds a set amount to any injury rolls on a limb using get_damage() multiplied by this number
-/datum/config_entry/number/wound_damage_multiplier
- config_entry_value = 0.333
- min_val = 0
- integer = FALSE
-
-/// Amount of dirtyness tiles need to spawn dirt.
-/datum/config_entry/number/turf_dirt_threshold
- config_entry_value = 100
- min_val = 1
- integer = TRUE
-
-/// Alpha dirt starts at
-/datum/config_entry/number/dirt_alpha_starting
- config_entry_value = 127
- max_val = 255
- min_val = 0
- integer = TRUE
-
-/// Dirtyness multiplier for making turfs dirty
-/datum/config_entry/number/turf_dirty_multiplier
- config_entry_value = 1
-
-/datum/config_entry/flag/weigh_by_recent_chaos
-
-/datum/config_entry/number/chaos_exponent
- config_entry_value = 1
diff --git a/code/controllers/configuration/entries/gamemodes.dm b/code/controllers/configuration/entries/gamemodes.dm
new file mode 100644
index 0000000000..f11c6dd5f5
--- /dev/null
+++ b/code/controllers/configuration/entries/gamemodes.dm
@@ -0,0 +1,94 @@
+/datum/config_entry/number_list/repeated_mode_adjust
+
+/datum/config_entry/flag/weigh_by_recent_chaos
+
+/datum/config_entry/number/chaos_exponent
+ config_entry_value = 1
+
+/datum/config_entry/keyed_list/probability
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
+
+/datum/config_entry/keyed_list/probability/ValidateListEntry(key_name)
+ return key_name in config.modes
+
+/datum/config_entry/keyed_list/chaos_level
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
+
+/datum/config_entry/keyed_list/chaos_level/ValidateListEntry(key_name)
+ return key_name in config.modes
+
+/datum/config_entry/keyed_list/max_pop
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
+
+/datum/config_entry/keyed_list/max_pop/ValidateListEntry(key_name)
+ return key_name in config.modes
+
+/datum/config_entry/keyed_list/min_pop
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
+
+/datum/config_entry/keyed_list/min_pop/ValidateListEntry(key_name, key_value)
+ return key_name in config.modes
+
+/datum/config_entry/keyed_list/continuous // which roundtypes continue if all antagonists die
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_FLAG
+
+/datum/config_entry/keyed_list/continuous/ValidateListEntry(key_name, key_value)
+ return key_name in config.modes
+
+/datum/config_entry/keyed_list/midround_antag // which roundtypes use the midround antagonist system
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_FLAG
+
+/datum/config_entry/keyed_list/midround_antag/ValidateListEntry(key_name, key_value)
+ return key_name in config.modes
+
+/datum/config_entry/keyed_list/force_antag_count
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_FLAG
+
+/datum/config_entry/keyed_list/force_antag_count/ValidateListEntry(key_name, key_value)
+ return key_name in config.modes
+
+/datum/config_entry/number/traitor_scaling_coeff //how much does the amount of players get divided by to determine traitors
+ config_entry_value = 6
+ min_val = 1
+
+/datum/config_entry/number/brother_scaling_coeff //how many players per brother team
+ config_entry_value = 25
+ min_val = 1
+
+/datum/config_entry/number/changeling_scaling_coeff //how much does the amount of players get divided by to determine changelings
+ config_entry_value = 6
+ min_val = 1
+
+/datum/config_entry/number/ecult_scaling_coeff //how much does the amount of players get divided by to determine e_cult
+ config_entry_value = 6
+ integer = FALSE
+ min_val = 1
+
+/datum/config_entry/number/security_scaling_coeff //how much does the amount of players get divided by to determine open security officer positions
+ config_entry_value = 8
+ min_val = 1
+
+/datum/config_entry/number/abductor_scaling_coeff //how many players per abductor team
+ config_entry_value = 15
+ min_val = 1
+
+/datum/config_entry/number/traitor_objectives_amount
+ config_entry_value = 2
+ min_val = 0
+
+/datum/config_entry/number/brother_objectives_amount
+ config_entry_value = 2
+ min_val = 0
+
+/datum/config_entry/flag/protect_roles_from_antagonist //If security and such can be traitor/cult/other
+
+/datum/config_entry/flag/protect_assistant_from_antagonist //If assistants can be traitor/cult/other
+
+/datum/config_entry/flag/allow_latejoin_antagonists // If late-joining players can be traitor/changeling
diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm
index 63da60d7b5..8ecd7c0c60 100644
--- a/code/controllers/configuration/entries/general.dm
+++ b/code/controllers/configuration/entries/general.dm
@@ -1,21 +1,3 @@
-/datum/config_entry/flag/auto_profile // Automatically start profiler on server start
-
-/datum/config_entry/flag/autoadmin // if autoadmin is enabled
- protection = CONFIG_ENTRY_LOCKED
-
-/datum/config_entry/string/autoadmin_rank // the rank for autoadmins
- config_entry_value = "Game Master"
- protection = CONFIG_ENTRY_LOCKED
-
-/datum/config_entry/string/servername // server name (the name of the game window)
-
-/datum/config_entry/string/servertagline
- config_entry_value = "We forgot to set the server's tagline in config.txt"
-
-/datum/config_entry/string/serversqlname // short form server name used for the DB
-
-/datum/config_entry/string/stationname // station name (the name of the station in-game)
-
/datum/config_entry/number/lobby_countdown // In between round countdown.
config_entry_value = 120
min_val = 0
@@ -24,164 +6,11 @@
config_entry_value = 25
min_val = 0
-/datum/config_entry/flag/hub // if the game appears on the hub or not
-
-/datum/config_entry/flag/allow_admin_ooccolor // Allows admins with relevant permissions to have their own ooc colour
-
-/datum/config_entry/flag/allow_vote_restart // allow votes to restart
-
-/datum/config_entry/flag/allow_vote_mode // allow votes to change mode
-
-/datum/config_entry/number/vote_delay // minimum time between voting sessions (deciseconds, 10 minute default)
- config_entry_value = 6000
- min_val = 0
-
-/datum/config_entry/number/vote_period // length of voting period (deciseconds, default 1 minute)
- config_entry_value = 600
- min_val = 0
-
-/// Length of time before the first autotransfer vote is called (deciseconds, default 2 hours)
-/// Set to 0 to disable the subsystem altogether.
-/datum/config_entry/number/vote_autotransfer_initial
- config_entry_value = 72000
- min_val = 0
-
-///length of time to wait before subsequent autotransfer votes (deciseconds, default 30 minutes)
-/datum/config_entry/number/vote_autotransfer_interval
- config_entry_value = 18000
- min_val = 0
-
-/// maximum extensions until the round autoends.
-/// Set to 0 to force automatic crew transfer after the 'vote_autotransfer_initial' elapsed.
-/// Set to -1 to disable the maximum extensions cap.
-/datum/config_entry/number/vote_autotransfer_maximum
- config_entry_value = 4
- min_val = -1
-
-/datum/config_entry/flag/default_no_vote // vote does not default to nochange/norestart
-
-/datum/config_entry/flag/no_dead_vote // dead people can't vote
/datum/config_entry/flag/allow_metadata // Metadata is supported.
-/datum/config_entry/flag/popup_admin_pm // adminPMs to non-admins show in a pop-up 'reply' window when set
-
-/datum/config_entry/number/fps
- config_entry_value = 20
- min_val = 1
- max_val = 100 //byond will start crapping out at 50, so this is just ridic
- var/sync_validate = FALSE
-
-/datum/config_entry/number/fps/ValidateAndSet(str_val)
- . = ..()
- if(.)
- sync_validate = TRUE
- var/datum/config_entry/number/ticklag/TL = config.entries_by_type[/datum/config_entry/number/ticklag]
- if(!TL.sync_validate)
- TL.ValidateAndSet(10 / config_entry_value)
- sync_validate = FALSE
-
-/datum/config_entry/number/ticklag
- integer = FALSE
- var/sync_validate = FALSE
-
-/datum/config_entry/number/ticklag/New() //ticklag weirdly just mirrors fps
- var/datum/config_entry/CE = /datum/config_entry/number/fps
- config_entry_value = 10 / initial(CE.config_entry_value)
- ..()
-
-/datum/config_entry/number/ticklag/ValidateAndSet(str_val)
- . = text2num(str_val) > 0 && ..()
- if(.)
- sync_validate = TRUE
- var/datum/config_entry/number/fps/FPS = config.entries_by_type[/datum/config_entry/number/fps]
- if(!FPS.sync_validate)
- FPS.ValidateAndSet(10 / config_entry_value)
- sync_validate = FALSE
-
/datum/config_entry/flag/allow_holidays
-/datum/config_entry/number/tick_limit_mc_init //SSinitialization throttling
- config_entry_value = TICK_LIMIT_MC_INIT_DEFAULT
- min_val = 0 //oranges warned us
- integer = FALSE
-
-/datum/config_entry/flag/admin_legacy_system //Defines whether the server uses the legacy admin system with admins.txt or the SQL system
- protection = CONFIG_ENTRY_LOCKED
-
-/datum/config_entry/flag/protect_legacy_admins //Stops any admins loaded by the legacy system from having their rank edited by the permissions panel
- protection = CONFIG_ENTRY_LOCKED
-
-/datum/config_entry/flag/protect_legacy_ranks //Stops any ranks loaded by the legacy system from having their flags edited by the permissions panel
- protection = CONFIG_ENTRY_LOCKED
-
-/datum/config_entry/flag/enable_localhost_rank //Gives the !localhost! rank to any client connecting from 127.0.0.1 or ::1
- protection = CONFIG_ENTRY_LOCKED
-
-/datum/config_entry/flag/load_legacy_ranks_only //Loads admin ranks only from legacy admin_ranks.txt, while enabled ranks are mirrored to the database
- protection = CONFIG_ENTRY_LOCKED
-
-/datum/config_entry/flag/mentors_mobname_only
-
-/datum/config_entry/flag/mentor_legacy_system //Defines whether the server uses the legacy mentor system with mentors.txt or the SQL system
- protection = CONFIG_ENTRY_LOCKED
-
-/datum/config_entry/string/hostedby
-
-/datum/config_entry/flag/guest_jobban
-
-/datum/config_entry/flag/usewhitelist
-
-/datum/config_entry/flag/ban_legacy_system //Defines whether the server uses the legacy banning system with the files in /data or the SQL system.
- protection = CONFIG_ENTRY_LOCKED
-
-/datum/config_entry/flag/use_age_restriction_for_jobs //Do jobs use account age restrictions? --requires database
-
-/datum/config_entry/flag/use_account_age_for_jobs //Uses the time they made the account for the job restriction stuff. New player joining alerts should be unaffected.
-
-/datum/config_entry/flag/use_exp_tracking
-
-/datum/config_entry/flag/use_exp_restrictions_heads
-
-/datum/config_entry/number/use_exp_restrictions_heads_hours
- config_entry_value = 0
- min_val = 0
-
-/datum/config_entry/flag/use_exp_restrictions_heads_department
-
-/datum/config_entry/flag/use_exp_restrictions_other
-
-/datum/config_entry/flag/use_exp_restrictions_admin_bypass
-
-/datum/config_entry/string/server
-
-/datum/config_entry/string/banappeals
-
-/datum/config_entry/string/wikiurl
- config_entry_value = "https://katlin.dog/citadel-wiki"
-
-/datum/config_entry/string/wikiurltg
- config_entry_value = "http://www.tgstation13.org/wiki"
-
-/datum/config_entry/string/forumurl
- config_entry_value = "http://tgstation13.org/phpBB/index.php"
-
-/datum/config_entry/string/rulesurl
- config_entry_value = "http://www.tgstation13.org/wiki/Rules"
-
-/datum/config_entry/string/githuburl
- config_entry_value = "https://www.github.com/tgstation/-tg-station"
-
-/datum/config_entry/string/roundstatsurl
-
-/datum/config_entry/string/gamelogurl
-
-/datum/config_entry/number/githubrepoid
- config_entry_value = null
- min_val = 0
-
-/datum/config_entry/flag/guest_ban
-
/datum/config_entry/number/id_console_jobslot_delay
config_entry_value = 30
min_val = 0
@@ -208,181 +37,8 @@
/datum/config_entry/flag/load_jobs_from_txt
-/datum/config_entry/flag/forbid_singulo_possession
-
-/datum/config_entry/flag/automute_on //enables automuting/spam prevention
-
-/datum/config_entry/string/panic_server_name
-
-/datum/config_entry/string/panic_server_name/ValidateAndSet(str_val)
- return str_val != "\[Put the name here\]" && ..()
-
-/datum/config_entry/string/panic_server_address //Reconnect a player this linked server if this server isn't accepting new players
-
-/datum/config_entry/string/panic_server_address/ValidateAndSet(str_val)
- return str_val != "byond://address:port" && ..()
-
-/datum/config_entry/string/invoke_youtubedl
- protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
-
/datum/config_entry/flag/show_irc_name
-/datum/config_entry/flag/see_own_notes //Can players see their own admin notes
-
-/datum/config_entry/number/note_fresh_days
- config_entry_value = null
- min_val = 0
- integer = FALSE
-
-/datum/config_entry/number/note_stale_days
- config_entry_value = null
- min_val = 0
- integer = FALSE
-
-/datum/config_entry/flag/maprotation
-
-/datum/config_entry/flag/tgstyle_maprotation
-
-/datum/config_entry/string/map_vote_type
- config_entry_value = APPROVAL_VOTING
-
-/datum/config_entry/number/maprotatechancedelta
- config_entry_value = 0.75
- min_val = 0
- max_val = 1
- integer = FALSE
-
-/datum/config_entry/number/soft_popcap
- config_entry_value = null
- min_val = 0
-
-/datum/config_entry/number/hard_popcap
- config_entry_value = null
- min_val = 0
-
-/datum/config_entry/number/extreme_popcap
- config_entry_value = null
- min_val = 0
-
-/datum/config_entry/string/soft_popcap_message
- config_entry_value = "Be warned that the server is currently serving a high number of users, consider using alternative game servers."
-
-/datum/config_entry/string/hard_popcap_message
- config_entry_value = "The server is currently serving a high number of users, You cannot currently join. You may wait for the number of living crew to decline, observe, or find alternative servers."
-
-/datum/config_entry/string/extreme_popcap_message
- config_entry_value = "The server is currently serving a high number of users, find alternative servers."
-
-/datum/config_entry/flag/panic_bunker // prevents people the server hasn't seen before from connecting
-
-/datum/config_entry/number/panic_bunker_living // living time in minutes that a player needs to pass the panic bunker
-
-/datum/config_entry/string/panic_bunker_message
- config_entry_value = "Sorry but the server is currently not accepting connections from never before seen players."
-
-/datum/config_entry/number/notify_new_player_age // how long do we notify admins of a new player
- min_val = -1
-
-/datum/config_entry/number/notify_new_player_account_age // how long do we notify admins of a new byond account
- min_val = 0
-
-/datum/config_entry/flag/age_verification //are we using the automated age verification which asks users if they're 18+?
- config_entry_value = TRUE
-
-/datum/config_entry/flag/irc_first_connection_alert // do we notify the irc channel when somebody is connecting for the first time?
-
-/datum/config_entry/flag/check_randomizer
-
-/datum/config_entry/string/ipintel_email
-
-/datum/config_entry/string/ipintel_email/ValidateAndSet(str_val)
- return str_val != "ch@nge.me" && ..()
-
-/datum/config_entry/number/ipintel_rating_bad
- config_entry_value = 1
- integer = FALSE
- min_val = 0
- max_val = 1
-
-/datum/config_entry/number/ipintel_save_good
- config_entry_value = 12
- min_val = 0
-
-/datum/config_entry/number/ipintel_save_bad
- config_entry_value = 1
- min_val = 0
-
-/datum/config_entry/string/ipintel_domain
- config_entry_value = "check.getipintel.net"
-
-/datum/config_entry/flag/aggressive_changelog
-
-/datum/config_entry/flag/autoconvert_notes //if all connecting player's notes should attempt to be converted to the database
- protection = CONFIG_ENTRY_LOCKED
-
-/datum/config_entry/flag/allow_webclient
-
-/datum/config_entry/flag/webclient_only_byond_members
-
-/datum/config_entry/flag/announce_admin_logout
-
-/datum/config_entry/flag/announce_admin_login
-
-/datum/config_entry/flag/allow_map_voting
-
-/datum/config_entry/number/client_warn_version
- config_entry_value = null
- min_val = 500
-
-/datum/config_entry/number/client_warn_version
- config_entry_value = null
- min_val = 500
-
-/datum/config_entry/string/client_warn_message
- config_entry_value = "Your version of byond may have issues or be blocked from accessing this server in the future."
-
-/datum/config_entry/flag/client_warn_popup
-
-/datum/config_entry/number/client_error_version
- config_entry_value = null
- min_val = 500
-
-/datum/config_entry/string/client_error_message
- config_entry_value = "Your version of byond is too old, may have issues, and is blocked from accessing this server."
-
-/datum/config_entry/number/client_error_build
- config_entry_value = null
- min_val = 0
-
-/datum/config_entry/number/minute_topic_limit
- config_entry_value = null
- min_val = 0
-
-/datum/config_entry/number/second_topic_limit
- config_entry_value = null
- min_val = 0
-
-/datum/config_entry/number/minute_click_limit
- config_entry_value = 400
- min_val = 0
-
-/datum/config_entry/number/second_click_limit
- config_entry_value = 15
- min_val = 0
-
-/datum/config_entry/number/error_cooldown // The "cooldown" time for each occurrence of a unique error
- config_entry_value = 600
- min_val = 0
-
-/datum/config_entry/number/error_limit // How many occurrences before the next will silence them
- config_entry_value = 50
-
-/datum/config_entry/number/error_silence_time // How long a unique error will be silenced for
- config_entry_value = 6000
-
-/datum/config_entry/number/error_msg_delay // How long to wait between messaging admins about occurrences of a unique error
- config_entry_value = 50
-
/datum/config_entry/flag/irc_announce_new_game
deprecated_by = /datum/config_entry/string/chat_announce_new_game
@@ -390,54 +46,290 @@
return "" //default broadcast
/datum/config_entry/string/chat_announce_new_game
+
config_entry_value = null
-/datum/config_entry/flag/debug_admin_hrefs
-
-/datum/config_entry/number/mc_tick_rate/base_mc_tick_rate
- integer = FALSE
- config_entry_value = 1
-
-/datum/config_entry/number/mc_tick_rate/high_pop_mc_tick_rate
- integer = FALSE
- config_entry_value = 1.1
-
-/datum/config_entry/number/mc_tick_rate/high_pop_mc_mode_amount
- config_entry_value = 65
-
-/datum/config_entry/number/mc_tick_rate/disable_high_pop_mc_mode_amount
- config_entry_value = 60
-
-/datum/config_entry/number/mc_tick_rate
- abstract_type = /datum/config_entry/number/mc_tick_rate
-
-/datum/config_entry/number/mc_tick_rate/ValidateAndSet(str_val)
- . = ..()
- if (.)
- Master.UpdateTickRate()
-
-/datum/config_entry/flag/resume_after_initializations
-
-/datum/config_entry/flag/resume_after_initializations/ValidateAndSet(str_val)
- . = ..()
- if(. && Master.current_runlevel)
- world.sleep_offline = !config_entry_value
-
-/datum/config_entry/number/rounds_until_hard_restart
- config_entry_value = -1
- min_val = 0
-
/datum/config_entry/string/default_view
config_entry_value = "15x15"
/datum/config_entry/string/default_view_square
config_entry_value = "15x15"
-/datum/config_entry/number/max_bunker_days
- config_entry_value = 7
- min_val = 1
/datum/config_entry/flag/minimaps_enabled
config_entry_value = TRUE
-/datum/config_entry/string/centcom_ban_db // URL for the CentCom Galactic Ban DB API
+
+
+/datum/config_entry/number/damage_multiplier
+ config_entry_value = 1
+ integer = FALSE
+
+/datum/config_entry/number/minimal_access_threshold //If the number of players is larger than this threshold, minimal access will be turned on.
+ min_val = 0
+
+/datum/config_entry/flag/jobs_have_minimal_access //determines whether jobs use minimal access or expanded access.
+
+/datum/config_entry/flag/assistants_have_maint_access
+
+/datum/config_entry/flag/security_has_maint_access
+
+/datum/config_entry/flag/everyone_has_maint_access
+
+/datum/config_entry/flag/sec_start_brig //makes sec start in brig instead of dept sec posts
+
+/datum/config_entry/flag/force_random_names
+
+/datum/config_entry/flag/humans_need_surnames
+
+/datum/config_entry/flag/allow_ai // allow ai job
+
+/datum/config_entry/flag/allow_ai_multicam //whether the AI can use their multicam
+
+/datum/config_entry/flag/disable_human_mood
+
+/datum/config_entry/flag/disable_borg_flash_knockdown //Should borg flashes be capable of knocking humanoid entities down?
+
+/datum/config_entry/flag/weaken_secborg //Brings secborgs and k9s back in-line with the other borg modules
+
+/datum/config_entry/flag/disable_secborg // disallow secborg module to be chosen.
+
+/datum/config_entry/flag/disable_peaceborg
+
+/datum/config_entry/flag/economy //money money money money money money money money money money money money
+
+/datum/config_entry/flag/reactionary_explosions //If we use reactionary explosions, explosions that react to walls and doors
+
+/datum/config_entry/flag/enforce_human_authority //If non-human species are barred from joining as a head of staff
+
+/datum/config_entry/number/midround_antag_time_check // How late (in minutes you want the midround antag system to stay on, setting this to 0 will disable the system)
+ config_entry_value = 60
+ min_val = 0
+
+/datum/config_entry/number/midround_antag_life_check // A ratio of how many people need to be alive in order for the round not to immediately end in midround antagonist
+ config_entry_value = 0.7
+ integer = FALSE
+ min_val = 0
+ max_val = 1
+
+/datum/config_entry/number/suicide_reenter_round_timer
+ config_entry_value = 30
+ min_val = 0
+
+/datum/config_entry/number/roundstart_suicide_time_limit
+ config_entry_value = 30
+ min_val = 0
+
+/datum/config_entry/number/shuttle_refuel_delay
+ config_entry_value = 12000
+ min_val = 0
+
+/datum/config_entry/flag/show_game_type_odds //if set this allows players to see the odds of each roundtype on the get revision screen
+
+/datum/config_entry/keyed_list/roundstart_races //races you can play as from the get go.
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_FLAG
+
+/datum/config_entry/flag/join_with_mutant_humans //players can pick mutant bodyparts for humans before joining the game
+
+/datum/config_entry/flag/no_summon_guns //No
+
+/datum/config_entry/flag/no_summon_magic //Fun
+
+/datum/config_entry/flag/no_summon_events //Allowed
+
+/datum/config_entry/flag/no_summon_traumas //!
+
+/datum/config_entry/flag/no_intercept_report //Whether or not to send a communications intercept report roundstart. This may be overridden by gamemodes.
+
+/datum/config_entry/number/arrivals_shuttle_dock_window //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station
+ config_entry_value = 55
+ min_val = 30
+
+/datum/config_entry/flag/arrivals_shuttle_require_undocked //Require the arrivals shuttle to be undocked before latejoiners can join
+
+/datum/config_entry/flag/arrivals_shuttle_require_safe_latejoin //Require the arrivals shuttle to be operational in order for latejoiners to join
+
+
+/datum/config_entry/flag/revival_pod_plants
+
+/datum/config_entry/flag/revival_cloning
+
+/datum/config_entry/number/revival_brain_life
+ config_entry_value = -1
+ min_val = -1
+
+/datum/config_entry/flag/ooc_during_round
+
+/datum/config_entry/flag/emojis
+
+/datum/config_entry/flag/roundstart_away //Will random away mission be loaded.
+
+/datum/config_entry/flag/roundstart_vr //Will virtual reality missions be loaded?
+
+/datum/config_entry/number/gateway_delay //How long the gateway takes before it activates. Default is half an hour. Only matters if roundstart_away is enabled.
+ config_entry_value = 18000
+ min_val = 0
+
+/datum/config_entry/flag/ghost_interaction
+
+/datum/config_entry/flag/silent_ai
+/datum/config_entry/flag/silent_borg
+
+/datum/config_entry/flag/sandbox_autoclose // close the sandbox panel after spawning an item, potentially reducing griff
+
+/datum/config_entry/number/default_laws //Controls what laws the AI spawns with.
+ config_entry_value = 0
+ min_val = 0
+ max_val = 3
+
+/datum/config_entry/number/silicon_max_law_amount
+ config_entry_value = 12
+ min_val = 0
+
+/datum/config_entry/keyed_list/random_laws
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_FLAG
+
+/datum/config_entry/keyed_list/law_weight
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
+ splitter = ","
+
+/datum/config_entry/number/overflow_cap
+ config_entry_value = -1
+ min_val = -1
+
+/datum/config_entry/string/overflow_job
+ config_entry_value = "Assistant"
+
+/datum/config_entry/flag/starlight
+/datum/config_entry/flag/grey_assistants
+
+/datum/config_entry/number/lavaland_budget
+ config_entry_value = 60
+ min_val = 0
+
+/datum/config_entry/number/space_budget
+ config_entry_value = 16
+ min_val = 0
+
+/datum/config_entry/number/icemoon_budget
+ config_entry_value = 90
+ integer = FALSE
+ min_val = 0
+
+/datum/config_entry/number/station_space_budget
+ config_entry_value = 10
+ min_val = 0
+
+/datum/config_entry/flag/allow_random_events // Enables random events mid-round when set
+
+/datum/config_entry/number/events_min_time_mul // Multipliers for random events minimal starting time and minimal players amounts
+ config_entry_value = 1
+ min_val = 0
+ integer = FALSE
+
+/datum/config_entry/number/events_min_players_mul
+ config_entry_value = 1
+ min_val = 0
+ integer = FALSE
+
+/datum/config_entry/number/mice_roundstart
+ config_entry_value = 10
+ min_val = 0
+
+/datum/config_entry/number/bombcap
+ config_entry_value = 14
+ min_val = 4
+
+/datum/config_entry/number/bombcap/ValidateAndSet(str_val)
+ . = ..()
+ if(.)
+ GLOB.MAX_EX_DEVESTATION_RANGE = round(config_entry_value / 4)
+ GLOB.MAX_EX_HEAVY_RANGE = round(config_entry_value / 2)
+ GLOB.MAX_EX_LIGHT_RANGE = config_entry_value
+ GLOB.MAX_EX_FLASH_RANGE = config_entry_value
+ GLOB.MAX_EX_FLAME_RANGE = config_entry_value
+
+/datum/config_entry/number/emergency_shuttle_autocall_threshold
+ min_val = 0
+ max_val = 1
+ integer = FALSE
+
+/datum/config_entry/flag/ic_printing
+
+/datum/config_entry/flag/roundstart_traits
+
+/datum/config_entry/flag/enable_night_shifts
+
+/datum/config_entry/number/night_shift_public_areas_only
+ config_entry_value = NIGHTSHIFT_AREA_PUBLIC
+
+/datum/config_entry/flag/nightshift_toggle_requires_auth
+ config_entry_value = FALSE
+
+/datum/config_entry/flag/nightshift_toggle_public_requires_auth
+ config_entry_value = TRUE
+
+/datum/config_entry/flag/randomize_shift_time
+
+/datum/config_entry/flag/shift_time_realtime
+
+/datum/config_entry/number/monkeycap
+ config_entry_value = 64
+ min_val = 0
+
+/datum/config_entry/number/ratcap
+ config_entry_value = 64
+ min_val = 0
+
+/datum/config_entry/keyed_list/box_random_engine
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
+ lowercase = FALSE
+ splitter = ","
+
+/datum/config_entry/flag/pai_custom_holoforms
+
+/datum/config_entry/number/marauder_delay_non_reebe
+ config_entry_value = 1800
+ min_val = 0
+
+/datum/config_entry/flag/allow_clockwork_marauder_on_station
+ config_entry_value = TRUE
+
+/datum/config_entry/flag/suicide_allowed
+
+
+//Allows players to set a hexadecimal color of their choice as skin tone, on top of the standard ones.
+/datum/config_entry/flag/allow_custom_skintones
+
+///Initial loadout points
+/datum/config_entry/number/initial_gear_points
+ config_entry_value = 10
+
+/**
+ * Enables the FoV component, which hides objects and mobs behind the parent from their sight, unless they turn around, duh.
+ * Camera mobs, AIs, ghosts and some other are of course exempt from this. This also doesn't influence simplemob AI, for the best.
+ */
+/datum/config_entry/flag/use_field_of_vision
+
+//Shuttle size limiter
+/datum/config_entry/number/max_shuttle_count
+ config_entry_value = 6
+
+/datum/config_entry/number/max_shuttle_size
+ config_entry_value = 500
+
+//wound config stuff (increases the max injury roll, making injuries more likely)
+/datum/config_entry/number/wound_exponent
+ config_entry_value = WOUND_DAMAGE_EXPONENT
+ min_val = 0
+ integer = FALSE
+
+//adds a set amount to any injury rolls on a limb using get_damage() multiplied by this number
+/datum/config_entry/number/wound_damage_multiplier
+ config_entry_value = 0.333
+ min_val = 0
+ integer = FALSE
diff --git a/code/controllers/configuration/entries/jexp.dm b/code/controllers/configuration/entries/jexp.dm
new file mode 100644
index 0000000000..3d9754b4a6
--- /dev/null
+++ b/code/controllers/configuration/entries/jexp.dm
@@ -0,0 +1,17 @@
+/datum/config_entry/flag/use_age_restriction_for_jobs //Do jobs use account age restrictions? --requires database
+
+/datum/config_entry/flag/use_account_age_for_jobs //Uses the time they made the account for the job restriction stuff. New player joining alerts should be unaffected.
+
+/datum/config_entry/flag/use_exp_tracking
+
+/datum/config_entry/flag/use_exp_restrictions_heads
+
+/datum/config_entry/number/use_exp_restrictions_heads_hours
+ config_entry_value = 0
+ min_val = 0
+
+/datum/config_entry/flag/use_exp_restrictions_heads_department
+
+/datum/config_entry/flag/use_exp_restrictions_other
+
+/datum/config_entry/flag/use_exp_restrictions_admin_bypass
diff --git a/code/controllers/configuration/entries/logging.dm b/code/controllers/configuration/entries/logging.dm
index 1cb47d6ab7..25ca145939 100644
--- a/code/controllers/configuration/entries/logging.dm
+++ b/code/controllers/configuration/entries/logging.dm
@@ -9,6 +9,7 @@
/datum/config_entry/flag/log_admin // log admin actions
protection = CONFIG_ENTRY_LOCKED
+ config_entry_value = TRUE
/datum/config_entry/flag/log_prayer // log prayers
config_entry_value = TRUE
@@ -68,3 +69,16 @@
/// forces log_href for tgui
/datum/config_entry/flag/emergency_tgui_logging
config_entry_value = FALSE
+
+/datum/config_entry/number/error_cooldown // The "cooldown" time for each occurrence of a unique error
+ config_entry_value = 600
+ min_val = 0
+
+/datum/config_entry/number/error_limit // How many occurrences before the next will silence them
+ config_entry_value = 50
+
+/datum/config_entry/number/error_silence_time // How long a unique error will be silenced for
+ config_entry_value = 6000
+
+/datum/config_entry/number/error_msg_delay // How long to wait between messaging admins about occurrences of a unique error
+ config_entry_value = 50
diff --git a/code/controllers/configuration/entries/movespeed.dm b/code/controllers/configuration/entries/movespeed.dm
new file mode 100644
index 0000000000..b1c3818cd3
--- /dev/null
+++ b/code/controllers/configuration/entries/movespeed.dm
@@ -0,0 +1,124 @@
+/datum/config_entry/keyed_list/multiplicative_movespeed
+ key_mode = KEY_MODE_TYPE
+ value_mode = VALUE_MODE_NUM
+ abstract_type = /datum/config_entry/keyed_list/multiplicative_movespeed
+
+/datum/config_entry/keyed_list/multiplicative_movespeed/ValidateAndSet()
+ . = ..()
+ if(.)
+ update_config_movespeed_type_lookup(TRUE)
+
+/datum/config_entry/keyed_list/multiplicative_movespeed/vv_edit_var(var_name, var_value)
+ . = ..()
+ if(. && (var_name == NAMEOF(src, config_entry_value)))
+ update_config_movespeed_type_lookup(TRUE)
+
+/datum/config_entry/keyed_list/multiplicative_movespeed/normal
+ name = "multiplicative_movespeed"
+ config_entry_value = list( //DEFAULTS
+ /mob/living/simple_animal = 1,
+ /mob/living/silicon/pai = 1,
+ /mob/living/carbon/alien/humanoid/sentinel = 0.25,
+ /mob/living/carbon/alien/humanoid/drone = 0.5,
+ /mob/living/carbon/alien/humanoid/royal/praetorian = 1,
+ /mob/living/carbon/alien/humanoid/royal/queen = 3
+ )
+
+/datum/config_entry/keyed_list/multiplicative_movespeed/floating
+ name = "multiplicative_movespeed_floating"
+ config_entry_value = list(
+ /mob/living = 0,
+ /mob/living/carbon/alien/humanoid = 0,
+ /mob/living/carbon/alien/humanoid/royal/praetorian = 0,
+ /mob/living/carbon/alien/humanoid/royal/queen = 2
+ )
+
+/datum/config_entry/number/movedelay //Used for modifying movement speed for mobs.
+ abstract_type = /datum/config_entry/number/movedelay
+ integer = FALSE
+
+/datum/config_entry/number/movedelay/ValidateAndSet()
+ . = ..()
+ if(.)
+ update_mob_config_movespeeds()
+
+/datum/config_entry/number/movedelay/vv_edit_var(var_name, var_value)
+ . = ..()
+ if(. && (var_name == NAMEOF(src, config_entry_value)))
+ update_mob_config_movespeeds()
+
+/datum/config_entry/number/movedelay/run_delay
+
+/datum/config_entry/number/movedelay/run_delay/ValidateAndSet()
+ . = ..()
+ var/datum/movespeed_modifier/config_walk_run/M = get_cached_movespeed_modifier(/datum/movespeed_modifier/config_walk_run/run)
+ M.sync()
+
+/datum/config_entry/number/movedelay/walk_delay
+
+/datum/config_entry/number/movedelay/walk_delay/ValidateAndSet()
+ . = ..()
+ var/datum/movespeed_modifier/config_walk_run/M = get_cached_movespeed_modifier(/datum/movespeed_modifier/config_walk_run/walk)
+ M.sync()
+
+/datum/config_entry/flag/sprint_enabled
+ config_entry_value = TRUE
+
+/datum/config_entry/flag/sprint_enabled/ValidateAndSet(str_val)
+ . = ..()
+ for(var/datum/hud/human/H)
+ H.assert_move_intent_ui()
+ if(!config_entry_value) // disabled
+ for(var/mob/living/L in world)
+ L.disable_intentional_sprint_mode()
+
+/datum/config_entry/number/sprintless_stagger_slowdown
+ config_entry_value = 0
+
+/datum/config_entry/number/sprintless_off_balance_slowdown
+ config_entry_value = 0.85
+
+/datum/config_entry/number/melee_stagger_factor
+ config_entry_value = 1
+
+/datum/config_entry/number/movedelay/sprint_speed_increase
+ config_entry_value = 1
+
+/datum/config_entry/number/movedelay/sprint_max_tiles_increase
+ config_entry_value = 5
+
+/datum/config_entry/number/movedelay/sprint_absolute_max_tiles
+ config_entry_value = 13
+
+/datum/config_entry/number/movedelay/sprint_buffer_max
+ config_entry_value = 24
+
+/datum/config_entry/number/movedelay/sprint_stamina_cost
+ config_entry_value = 1.4
+
+/datum/config_entry/number/movedelay/sprint_buffer_regen_per_ds
+ config_entry_value = 0.4
+
+/////////////////////////////////////////////////Outdated move delay
+/datum/config_entry/number/outdated_movedelay
+ deprecated_by = /datum/config_entry/keyed_list/multiplicative_movespeed/normal
+ abstract_type = /datum/config_entry/number/outdated_movedelay
+
+ var/movedelay_type
+
+/datum/config_entry/number/outdated_movedelay/DeprecationUpdate(value)
+ return "[movedelay_type] [value]"
+
+/datum/config_entry/number/outdated_movedelay/human_delay
+ movedelay_type = /mob/living/carbon/human
+/datum/config_entry/number/outdated_movedelay/robot_delay
+ movedelay_type = /mob/living/silicon/robot
+/datum/config_entry/number/outdated_movedelay/monkey_delay
+ movedelay_type = /mob/living/carbon/monkey
+/datum/config_entry/number/outdated_movedelay/alien_delay
+ movedelay_type = /mob/living/carbon/alien
+/datum/config_entry/number/outdated_movedelay/slime_delay
+ movedelay_type = /mob/living/simple_animal/slime
+/datum/config_entry/number/outdated_movedelay/animal_delay
+ movedelay_type = /mob/living/simple_animal
+/////////////////////////////////////////////////
diff --git a/code/controllers/configuration/entries/policy.dm b/code/controllers/configuration/entries/policy.dm
index de611e1813..ea8973a4ce 100644
--- a/code/controllers/configuration/entries/policy.dm
+++ b/code/controllers/configuration/entries/policy.dm
@@ -3,9 +3,9 @@
config_entry_value = 300
integer = TRUE
-/datum/config_entry/keyed_list/policyconfig
+/datum/config_entry/keyed_list/policy
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_TEXT
-/datum/config_entry/keyed_list/policyconfig/preprocess_key(key)
+/datum/config_entry/keyed_list/policy/preprocess_key(key)
return uppertext(..())
diff --git a/code/controllers/configuration/entries/fail2topic.dm b/code/controllers/configuration/entries/security.dm
similarity index 62%
rename from code/controllers/configuration/entries/fail2topic.dm
rename to code/controllers/configuration/entries/security.dm
index 7ed09b378a..3a49c97d70 100644
--- a/code/controllers/configuration/entries/fail2topic.dm
+++ b/code/controllers/configuration/entries/security.dm
@@ -9,7 +9,6 @@
protection = CONFIG_ENTRY_LOCKED //affects physical server configuration, no touchies!!
/datum/config_entry/flag/fail2topic_enabled
- config_entry_value = TRUE
/datum/config_entry/number/topic_max_size
config_entry_value = 8192
@@ -17,3 +16,19 @@
/datum/config_entry/keyed_list/topic_rate_limit_whitelist
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_FLAG
+
+/datum/config_entry/number/minute_topic_limit
+ config_entry_value = null
+ min_val = 0
+
+/datum/config_entry/number/second_topic_limit
+ config_entry_value = null
+ min_val = 0
+
+/datum/config_entry/number/minute_click_limit
+ config_entry_value = 400
+ min_val = 0
+
+/datum/config_entry/number/second_click_limit
+ config_entry_value = 15
+ min_val = 0
diff --git a/code/controllers/configuration/entries/server.dm b/code/controllers/configuration/entries/server.dm
new file mode 100644
index 0000000000..1acf8a11ca
--- /dev/null
+++ b/code/controllers/configuration/entries/server.dm
@@ -0,0 +1,90 @@
+/datum/config_entry/flag/auto_profile // Automatically start profiler on server start
+
+/datum/config_entry/string/servername // server name (the name of the game window)
+
+/datum/config_entry/string/servertagline
+ config_entry_value = "We forgot to set the server's tagline in config.txt"
+
+/datum/config_entry/string/serversqlname // short form server name used for the DB
+
+/datum/config_entry/string/stationname // station name (the name of the station in-game)
+
+/datum/config_entry/number/fps
+ config_entry_value = 20
+ min_val = 1
+ max_val = 100 //byond will start crapping out at 50, so this is just ridic
+ var/sync_validate = FALSE
+
+/datum/config_entry/number/fps/ValidateAndSet(str_val)
+ . = ..()
+ if(.)
+ sync_validate = TRUE
+ var/datum/config_entry/number/ticklag/TL = config.entries_by_type[/datum/config_entry/number/ticklag]
+ if(!TL.sync_validate)
+ TL.ValidateAndSet(10 / config_entry_value)
+ sync_validate = FALSE
+
+/datum/config_entry/number/ticklag
+ integer = FALSE
+ var/sync_validate = FALSE
+
+/datum/config_entry/number/ticklag/New() //ticklag weirdly just mirrors fps
+ var/datum/config_entry/CE = /datum/config_entry/number/fps
+ config_entry_value = 10 / initial(CE.config_entry_value)
+ ..()
+
+/datum/config_entry/number/ticklag/ValidateAndSet(str_val)
+ . = text2num(str_val) > 0 && ..()
+ if(.)
+ sync_validate = TRUE
+ var/datum/config_entry/number/fps/FPS = config.entries_by_type[/datum/config_entry/number/fps]
+ if(!FPS.sync_validate)
+ FPS.ValidateAndSet(10 / config_entry_value)
+ sync_validate = FALSE
+
+/datum/config_entry/number/tick_limit_mc_init //SSinitialization throttling
+ config_entry_value = TICK_LIMIT_MC_INIT_DEFAULT
+ min_val = 0 //oranges warned us
+ integer = FALSE
+
+/datum/config_entry/flag/usewhitelist
+
+/datum/config_entry/string/hostedby
+
+/datum/config_entry/flag/hub // if the game appears on the hub or not
+
+/datum/config_entry/string/invoke_youtubedl
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/datum/config_entry/number/mc_tick_rate/base_mc_tick_rate
+ integer = FALSE
+ config_entry_value = 1
+
+/datum/config_entry/number/mc_tick_rate/high_pop_mc_tick_rate
+ integer = FALSE
+ config_entry_value = 1.1
+
+/datum/config_entry/number/mc_tick_rate/high_pop_mc_mode_amount
+ config_entry_value = 65
+
+/datum/config_entry/number/mc_tick_rate/disable_high_pop_mc_mode_amount
+ config_entry_value = 60
+
+/datum/config_entry/number/mc_tick_rate
+ abstract_type = /datum/config_entry/number/mc_tick_rate
+
+/datum/config_entry/number/mc_tick_rate/ValidateAndSet(str_val)
+ . = ..()
+ if (.)
+ Master.UpdateTickRate()
+
+/datum/config_entry/flag/resume_after_initializations
+
+/datum/config_entry/flag/resume_after_initializations/ValidateAndSet(str_val)
+ . = ..()
+ if(. && Master.current_runlevel)
+ world.sleep_offline = !config_entry_value
+
+/datum/config_entry/number/rounds_until_hard_restart
+ config_entry_value = -1
+ min_val = 0
diff --git a/code/controllers/configuration/entries/stamina_combat.dm b/code/controllers/configuration/entries/stamina_combat.dm
index 5c2c9d7ec5..681b903286 100644
--- a/code/controllers/configuration/entries/stamina_combat.dm
+++ b/code/controllers/configuration/entries/stamina_combat.dm
@@ -29,3 +29,5 @@
/// Factor to multiply by for stamina usage past buffer into health
/datum/config_entry/number/stamina_combat/overdraw_penalty_factor
config_entry_value = 1.5
+
+/datum/config_entry/flag/disable_stambuffer
diff --git a/code/controllers/configuration/entries/threat.dm b/code/controllers/configuration/entries/threat.dm
new file mode 100644
index 0000000000..3a3e03e149
--- /dev/null
+++ b/code/controllers/configuration/entries/threat.dm
@@ -0,0 +1,7 @@
+/datum/config_entry/keyed_list/job_threat
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
+
+/datum/config_entry/keyed_list/antag_threat
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
diff --git a/code/controllers/configuration/entries/urls.dm b/code/controllers/configuration/entries/urls.dm
new file mode 100644
index 0000000000..fe82574da0
--- /dev/null
+++ b/code/controllers/configuration/entries/urls.dm
@@ -0,0 +1,26 @@
+/datum/config_entry/string/server
+
+/datum/config_entry/string/banappeals
+
+/datum/config_entry/string/wikiurl
+ config_entry_value = "https://katlin.dog/citadel-wiki"
+
+/datum/config_entry/string/wikiurltg
+ config_entry_value = "http://www.tgstation13.org/wiki"
+
+/datum/config_entry/string/forumurl
+ config_entry_value = "http://tgstation13.org/phpBB/index.php"
+
+/datum/config_entry/string/rulesurl
+ config_entry_value = "http://www.tgstation13.org/wiki/Rules"
+
+/datum/config_entry/string/githuburl
+ config_entry_value = "https://www.github.com/tgstation/-tg-station"
+
+/datum/config_entry/string/roundstatsurl
+
+/datum/config_entry/string/gamelogurl
+
+/datum/config_entry/number/githubrepoid
+ config_entry_value = null
+ min_val = 0
diff --git a/code/controllers/configuration/entries/vote.dm b/code/controllers/configuration/entries/vote.dm
new file mode 100644
index 0000000000..545fd01e3c
--- /dev/null
+++ b/code/controllers/configuration/entries/vote.dm
@@ -0,0 +1,55 @@
+/datum/config_entry/flag/allow_vote_restart // allow votes to restart
+
+/datum/config_entry/flag/allow_vote_mode // allow votes to change mode
+
+/datum/config_entry/number/vote_delay // minimum time between voting sessions (deciseconds, 10 minute default)
+ config_entry_value = 6000
+ min_val = 0
+
+/datum/config_entry/number/vote_period // length of voting period (deciseconds, default 1 minute)
+ config_entry_value = 600
+ min_val = 0
+
+/// Length of time before the first autotransfer vote is called (deciseconds, default 2 hours)
+/// Set to 0 to disable the subsystem altogether.
+/datum/config_entry/number/vote_autotransfer_initial
+ config_entry_value = 72000
+ min_val = 0
+
+///length of time to wait before subsequent autotransfer votes (deciseconds, default 30 minutes)
+/datum/config_entry/number/vote_autotransfer_interval
+ config_entry_value = 18000
+ min_val = 0
+
+/// maximum extensions until the round autoends.
+/// Set to 0 to force automatic crew transfer after the 'vote_autotransfer_initial' elapsed.
+/// Set to -1 to disable the maximum extensions cap.
+/datum/config_entry/number/vote_autotransfer_maximum
+ config_entry_value = 4
+ min_val = -1
+
+/datum/config_entry/flag/default_no_vote // vote does not default to nochange/norestart
+
+/datum/config_entry/flag/no_dead_vote // dead people can't vote
+
+/datum/config_entry/flag/maprotation
+
+/datum/config_entry/flag/tgstyle_maprotation
+
+/datum/config_entry/string/map_vote_type
+ config_entry_value = APPROVAL_VOTING
+
+/datum/config_entry/number/maprotatechancedelta
+ config_entry_value = 0.75
+ min_val = 0
+ max_val = 1
+ integer = FALSE
+
+/datum/config_entry/flag/allow_map_voting
+
+/datum/config_entry/flag/modetier_voting
+
+/datum/config_entry/number/dropped_modes
+ config_entry_value = 3
+
+/datum/config_entry/flag/must_be_readied_to_vote_gamemode
diff --git a/code/controllers/subsystem/acid.dm b/code/controllers/subsystem/acid.dm
deleted file mode 100644
index 25d080a1b1..0000000000
--- a/code/controllers/subsystem/acid.dm
+++ /dev/null
@@ -1,37 +0,0 @@
-SUBSYSTEM_DEF(acid)
- name = "Acid"
- priority = FIRE_PRIORITY_ACID
- flags = SS_NO_INIT|SS_BACKGROUND
- runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
-
- var/list/currentrun = list()
- var/list/processing = list()
-
-/datum/controller/subsystem/acid/stat_entry(msg)
- msg = "P:[length(processing)]"
- return ..()
-
-
-/datum/controller/subsystem/acid/fire(resumed = 0)
- if (!resumed)
- src.currentrun = processing.Copy()
-
- //cache for sanic speed (lists are references anyways)
- var/list/currentrun = src.currentrun
-
- while (currentrun.len)
- var/obj/O = currentrun[currentrun.len]
- currentrun.len--
- if (!O || QDELETED(O))
- processing -= O
- if (MC_TICK_CHECK)
- return
- continue
-
- if(O.acid_level && O.acid_processing())
- else
- O.update_icon()
- processing -= O
-
- if (MC_TICK_CHECK)
- return
diff --git a/code/controllers/subsystem/fluid.dm b/code/controllers/subsystem/fluid.dm
index c4fa13d693..70903e0088 100644
--- a/code/controllers/subsystem/fluid.dm
+++ b/code/controllers/subsystem/fluid.dm
@@ -1,5 +1,5 @@
PROCESSING_SUBSYSTEM_DEF(fluids)
name = "Fluids"
- wait = 20
+ wait = 10
stat_tag = "FD" //its actually Fluid Ducts
- flags = SS_NO_INIT | SS_TICKER
+ flags = SS_NO_INIT
diff --git a/code/controllers/subsystem/nightshift.dm b/code/controllers/subsystem/nightshift.dm
index 78b2e63cf2..c45bd64702 100644
--- a/code/controllers/subsystem/nightshift.dm
+++ b/code/controllers/subsystem/nightshift.dm
@@ -42,6 +42,7 @@ SUBSYSTEM_DEF(nightshift)
update_nightshift(night_time, announcing)
/datum/controller/subsystem/nightshift/proc/update_nightshift(active, announce = TRUE, max_level_override)
+ set waitfor = FALSE
nightshift_active = active
if(announce)
if (active)
diff --git a/code/controllers/subsystem/processing/processing.dm b/code/controllers/subsystem/processing/processing.dm
index f5a423b353..661eafc2a5 100644
--- a/code/controllers/subsystem/processing/processing.dm
+++ b/code/controllers/subsystem/processing/processing.dm
@@ -47,5 +47,5 @@ SUBSYSTEM_DEF(processing)
* If you override this do not call parent, as it will return PROCESS_KILL. This is done to prevent objects that dont override process() from staying in the processing list
*/
/datum/proc/process(delta_time)
- // SHOULD_NOT_SLEEP(TRUE)
+ SHOULD_NOT_SLEEP(TRUE)
return PROCESS_KILL
diff --git a/code/datums/components/acid.dm b/code/datums/components/acid.dm
new file mode 100644
index 0000000000..2e3784dc97
--- /dev/null
+++ b/code/datums/components/acid.dm
@@ -0,0 +1,65 @@
+/datum/component/acid
+ dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
+ var/level = 0
+
+/datum/component/acid/Initialize(acidpwr, acid_volume)
+ if(!isobj(parent))
+ return COMPONENT_INCOMPATIBLE
+ var/obj/O = parent
+ var/acid_cap = acidpwr * 300
+ level = min(acidpwr * acid_volume, acid_cap)
+ START_PROCESSING(SSprocessing, src)
+ RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/add_acid_overlay)
+ if(isitem(parent))
+ RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand)
+ O.update_icon()
+
+/datum/component/acid/proc/on_attack_hand(datum/source, mob/user)
+ var/obj/item/I = parent
+ if(istype(I) && level > 20 && !ismob(I.loc))// so we can still remove the clothes on us that have acid.
+ var/mob/living/carbon/C = user
+ if(istype(C))
+ if(!C.gloves || (!(C.gloves.resistance_flags & (UNACIDABLE|ACID_PROOF))))
+ to_chat(user, "The acid on [I] burns your hand!")
+ var/obj/item/bodypart/affecting = C.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm")
+ if(affecting && affecting.receive_damage( 0, 5 )) // 5 burn damage
+ C.update_damage_overlays()
+
+/datum/component/acid/InheritComponent(datum/component/C, i_am_original, acidpwr, acid_volume)
+ if(!i_am_original)
+ return
+ var/acid_cap = acidpwr * 300
+ if(level < acid_cap)
+ if(C)
+ var/datum/component/acid/other = C
+ level = min(level + other.level, acid_cap)
+ else
+ level = min(level + acidpwr * acid_volume, acid_cap)
+
+/datum/component/acid/Destroy()
+ STOP_PROCESSING(SSprocessing, src)
+ var/obj/O = parent
+ level = 0
+ O.update_overlays()
+ return ..()
+
+/datum/component/acid/process()
+ var/obj/O = parent
+ if(!istype(O))
+ qdel(src)
+ return PROCESS_KILL
+ if(!(O.resistance_flags & ACID_PROOF))
+ if(prob(33))
+ playsound(O.loc, 'sound/items/welder.ogg', 150, 1)
+ O.take_damage(min(1 + round(sqrt(level)*0.3), 300), BURN, "acid", 0)
+
+ level = max(level - (5 + 3*round(sqrt(level))), 0)
+ if(level <= 0)
+ qdel(src)
+ return PROCESS_KILL
+ else
+ O.update_icon()
+ return TRUE
+
+/datum/component/acid/proc/add_acid_overlay(atom/source, list/overlay_list)
+ overlay_list += GLOB.acid_overlay
diff --git a/code/datums/components/activity.dm b/code/datums/components/activity.dm
index ae18ca01a2..7c4c758d49 100644
--- a/code/datums/components/activity.dm
+++ b/code/datums/components/activity.dm
@@ -16,7 +16,7 @@
RegisterSignal(L, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE, COMSIG_MOB_APPLY_DAMAGE), .proc/minor_activity)
/datum/component/activity/proc/log_activity()
- historical_activity_levels[world.time] = activity_level
+ historical_activity_levels["[world.time]"] = activity_level
/datum/component/activity/proc/minor_activity(datum/source)
activity_level += 1
diff --git a/code/datums/components/crafting/craft.dm b/code/datums/components/crafting/craft.dm
deleted file mode 100644
index 3283c514b8..0000000000
--- a/code/datums/components/crafting/craft.dm
+++ /dev/null
@@ -1,491 +0,0 @@
-/datum/component/personal_crafting/Initialize()
- if(!ismob(parent))
- return COMPONENT_INCOMPATIBLE
- RegisterSignal(parent, COMSIG_MOB_CLIENT_LOGIN, .proc/create_mob_button)
-
-/datum/component/personal_crafting/proc/create_mob_button(mob/user, client/CL)
- var/datum/hud/H = user.hud_used
- var/obj/screen/craft/C = new()
- C.icon = H.ui_style
- H.static_inventory += C
- if(!CL.prefs.widescreenpref)
- C.screen_loc = ui_boxcraft
- CL.screen += C
- RegisterSignal(C, COMSIG_CLICK, .proc/component_ui_interact)
-
-/datum/component/personal_crafting
- var/busy
- var/viewing_category = 1
- var/viewing_subcategory = 1
- var/list/categories = list(
- CAT_WEAPONRY = list(
- CAT_WEAPON,
- CAT_AMMO,
- ),
- CAT_ROBOT = CAT_NONE,
- CAT_MISC = list(
- CAT_MISCELLANEOUS,
- CAT_TOOL,
- CAT_FURNITURE,
- ),
- CAT_PRIMAL = CAT_NONE,
- CAT_FOOD = list(
- CAT_BREAD,
- CAT_BURGER,
- CAT_CAKE,
- CAT_DONUT,
- CAT_EGG,
- CAT_ICE,
- CAT_MEAT,
- CAT_MEXICAN,
- CAT_MISCFOOD,
- CAT_PASTRY,
- CAT_PIE,
- CAT_PIZZA,
- CAT_SEAFOOD,
- CAT_SALAD,
- CAT_SANDWICH,
- CAT_SOUP,
- CAT_SPAGHETTI,
- ),
- CAT_DRINK = CAT_NONE,
- CAT_CLOTHING = CAT_NONE,
- )
-
- var/cur_category = CAT_NONE
- var/cur_subcategory = CAT_NONE
- var/datum/action/innate/crafting/button
- var/display_craftable_only = FALSE
- var/display_compact = TRUE
-
-
-
-
-/* This is what procs do:
- get_environment - gets a list of things accessable for crafting by user
- get_surroundings - takes a list of things and makes a list of key-types to values-amounts of said type in the list
- check_contents - takes a recipe and a key-type list and checks if said recipe can be done with available stuff
- check_tools - takes recipe, a key-type list, and a user and checks if there are enough tools to do the stuff, checks bugs one level deep
- construct_item - takes a recipe and a user, call all the checking procs, calls do_after, checks all the things again, calls del_reqs, creates result, calls CheckParts of said result with argument being list returned by deel_reqs
- del_reqs - takes recipe and a user, loops over the recipes reqs var and tries to find everything in the list make by get_environment and delete it/add to parts list, then returns the said list
-*/
-
-
-
-/**
- * Check that the contents of the recipe meet the requirements.
- *
- * user: The /mob that initated the crafting.
- * R: The /datum/crafting_recipe being attempted.
- * contents: List of items to search for R's reqs.
- */
-/datum/component/personal_crafting/proc/check_contents(mob/user, datum/crafting_recipe/R, list/contents)
- var/list/item_instances = contents["instances"]
- contents = contents["other"]
-
- var/list/requirements_list = list()
-
- // Process all requirements
- for(var/requirement_path in R.reqs)
- // Check we have the appropriate amount available in the contents list
- var/needed_amount = R.reqs[requirement_path]
- for(var/content_item_path in contents)
- // Right path and not blacklisted
- if(!ispath(content_item_path, requirement_path) || R.blacklist.Find(requirement_path))
- continue
-
- needed_amount -= contents[content_item_path]
- if(needed_amount <= 0)
- break
-
- if(needed_amount > 0)
- return FALSE
-
- // Store the instances of what we will use for R.check_requirements() for requirement_path
- var/list/instances_list = list()
- for(var/instance_path in item_instances)
- if(ispath(instance_path, requirement_path))
- instances_list += item_instances[instance_path]
-
- requirements_list[requirement_path] = instances_list
-
- for(var/requirement_path in R.chem_catalysts)
- if(contents[requirement_path] < R.chem_catalysts[requirement_path])
- return FALSE
-
- return R.check_requirements(user, requirements_list)
-
-/datum/component/personal_crafting/proc/get_environment(mob/user)
- . = list()
- for(var/obj/item/I in user.held_items)
- . += I
- if(!isturf(user.loc))
- return
- var/list/L = block(get_step(user, SOUTHWEST), get_step(user, NORTHEAST))
- for(var/A in L)
- var/turf/T = A
- if(T.Adjacent(user))
- for(var/B in T)
- var/atom/movable/AM = B
- if(AM.flags_1 & HOLOGRAM_1)
- continue
- . += AM
- for(var/slot in list(SLOT_R_STORE, SLOT_L_STORE))
- . += user.get_item_by_slot(slot)
-
-/datum/component/personal_crafting/proc/get_surroundings(mob/user)
- . = list()
- .["tool_behaviour"] = list()
- .["other"] = list()
- .["instances"] = list()
- for(var/obj/item/I in get_environment(user))
- if(I.flags_1 & HOLOGRAM_1)
- continue
- if(.["instances"][I.type])
- .["instances"][I.type] += I
- else
- .["instances"][I.type] = list(I)
- if(istype(I, /obj/item/stack))
- var/obj/item/stack/S = I
- .["other"][I.type] += S.amount
- else if(I.tool_behaviour)
- .["tool_behaviour"] += I.tool_behaviour
- .["other"][I.type] += 1
- else
- if(istype(I, /obj/item/reagent_containers))
- var/obj/item/reagent_containers/RC = I
- if(RC.is_drainable())
- for(var/datum/reagent/A in RC.reagents.reagent_list)
- .["other"][A.type] += A.volume
- .["other"][I.type] += 1
-
-/datum/component/personal_crafting/proc/check_tools(mob/user, datum/crafting_recipe/R, list/contents)
- if(!R.tools.len)
- return TRUE
- var/list/possible_tools = list()
- var/list/present_qualities = list()
- present_qualities |= contents["tool_behaviour"]
- for(var/obj/item/I in user.contents)
- if(istype(I, /obj/item/storage))
- for(var/obj/item/SI in I.contents)
- possible_tools += SI.type
- if(SI.tool_behaviour)
- present_qualities.Add(SI.tool_behaviour)
-
- possible_tools += I.type
-
- if(I.tool_behaviour)
- present_qualities.Add(I.tool_behaviour)
-
- possible_tools |= contents["other"]
-
- main_loop:
- for(var/A in R.tools)
- if(A in present_qualities)
- continue
- else
- for(var/I in possible_tools)
- if(ispath(I, A))
- continue main_loop
- return FALSE
- return TRUE
-
-/datum/component/personal_crafting/proc/construct_item(mob/user, datum/crafting_recipe/R)
- var/list/contents = get_surroundings(user)
- var/send_feedback = TRUE
- if(check_contents(user, R, contents))
- if(check_tools(user, R, contents))
- if(do_after(user, R.time, target = user))
- contents = get_surroundings(user)
- if(!check_contents(user, R, contents))
- return ", missing component."
- if(!check_tools(user, R, contents))
- return ", missing tool."
- var/list/parts = del_reqs(R, user)
- var/atom/movable/I = new R.result (get_turf(user.loc))
- I.CheckParts(parts, R)
- if(isitem(I))
- if(isfood(I))
- var/obj/item/reagent_containers/food/food_result = I
- var/total_quality = 0
- var/total_items = 0
- for(var/obj/item/reagent_containers/food/ingredient in parts)
- total_items += 1
- total_quality += ingredient.food_quality
- if(total_items == 0)
- food_result.adjust_food_quality(50)
- else
- food_result.adjust_food_quality(total_quality / total_items)
- user.put_in_hands(I)
- if(send_feedback)
- SSblackbox.record_feedback("tally", "object_crafted", 1, I.type)
- log_craft("[I] crafted by [user] at [loc_name(I.loc)]")
- return FALSE
- return "."
- return ", missing tool."
- return ", missing component."
-
-
-/*Del reqs works like this:
-
- Loop over reqs var of the recipe
- Set var amt to the value current cycle req is pointing to, its amount of type we need to delete
- Get var/surroundings list of things accessable to crafting by get_environment()
- Check the type of the current cycle req
- If its reagent then do a while loop, inside it try to locate() reagent containers, inside such containers try to locate needed reagent, if there isnt remove thing from surroundings
- If there is enough reagent in the search result then delete the needed amount, create the same type of reagent with the same data var and put it into deletion list
- If there isnt enough take all of that reagent from the container, put into deletion list, substract the amt var by the volume of reagent, remove the container from surroundings list and keep searching
- While doing above stuff check deletion list if it already has such reagnet, if yes merge instead of adding second one
- If its stack check if it has enough amount
- If yes create new stack with the needed amount and put in into deletion list, substract taken amount from the stack
- If no put all of the stack in the deletion list, substract its amount from amt and keep searching
- While doing above stuff check deletion list if it already has such stack type, if yes try to merge them instead of adding new one
- If its anything else just locate() in in the list in a while loop, each find --s the amt var and puts the found stuff in deletion loop
-
- Then do a loop over parts var of the recipe
- Do similar stuff to what we have done above, but now in deletion list, until the parts conditions are satisfied keep taking from the deletion list and putting it into parts list for return
-
- After its done loop over deletion list and delete all the shit that wasnt taken by parts loop
-
- del_reqs return the list of parts resulting object will receive as argument of CheckParts proc, on the atom level it will add them all to the contents, on all other levels it calls ..() and does whatever is needed afterwards but from contents list already
-*/
-
-/datum/component/personal_crafting/proc/del_reqs(datum/crafting_recipe/R, mob/user)
- var/list/surroundings
- var/list/Deletion = list()
- . = list()
- var/data
- var/amt
- main_loop:
- for(var/A in R.reqs)
- amt = R.reqs[A]
- surroundings = get_environment(user)
- surroundings -= Deletion
- if(ispath(A, /datum/reagent))
- var/datum/reagent/RG = new A
- var/datum/reagent/RGNT
- while(amt > 0)
- var/obj/item/reagent_containers/RC = locate() in surroundings
- RG = RC.reagents.get_reagent(A)
- if(RG)
- if(!locate(RG.type) in Deletion)
- Deletion += new RG.type()
- if(RG.volume > amt)
- RG.volume -= amt
- data = RG.data
- RC.reagents.conditional_update(RC)
- RG = locate(RG.type) in Deletion
- RG.volume = amt
- RG.data += data
- continue main_loop
- else
- surroundings -= RC
- amt -= RG.volume
- RC.reagents.reagent_list -= RG
- RC.reagents.conditional_update(RC)
- RGNT = locate(RG.type) in Deletion
- RGNT.volume += RG.volume
- RGNT.data += RG.data
- qdel(RG)
- RC.on_reagent_change()
- else
- surroundings -= RC
- else if(ispath(A, /obj/item/stack))
- var/obj/item/stack/S
- var/obj/item/stack/SD
- while(amt > 0)
- S = locate(A) in surroundings
- if(S.amount >= amt)
- if(!locate(S.type) in Deletion)
- SD = new S.type()
- Deletion += SD
- S.use(amt)
- SD = locate(S.type) in Deletion
- SD.amount += amt
- continue main_loop
- else
- amt -= S.amount
- if(!locate(S.type) in Deletion)
- Deletion += S
- else
- data = S.amount
- S = locate(S.type) in Deletion
- S.add(data)
- surroundings -= S
- else
- var/atom/movable/I
- while(amt > 0)
- I = locate(A) in surroundings
- Deletion += I
- surroundings -= I
- amt--
- var/list/partlist = list(R.parts.len)
- for(var/M in R.parts)
- partlist[M] = R.parts[M]
- for(var/A in R.parts)
- if(istype(A, /datum/reagent))
- var/datum/reagent/RG = locate(A) in Deletion
- if(RG.volume > partlist[A])
- RG.volume = partlist[A]
- . += RG
- Deletion -= RG
- continue
- else if(istype(A, /obj/item/stack))
- var/obj/item/stack/ST = locate(A) in Deletion
- if(ST.amount > partlist[A])
- ST.amount = partlist[A]
- . += ST
- Deletion -= ST
- continue
- else
- while(partlist[A] > 0)
- var/atom/movable/AM = locate(A) in Deletion
- . += AM
- Deletion -= AM
- partlist[A] -= 1
- while(Deletion.len)
- var/DL = Deletion[Deletion.len]
- Deletion.Cut(Deletion.len)
- qdel(DL)
-
-/datum/component/personal_crafting/proc/component_ui_interact(obj/screen/craft/image, location, control, params, user)
- if(user == parent)
- ui_interact(user)
-
-/datum/component/personal_crafting/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_turf_state)
- ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
- if(!ui)
- cur_category = categories[1]
- if(islist(categories[cur_category]))
- var/list/subcats = categories[cur_category]
- cur_subcategory = subcats[1]
- else
- cur_subcategory = CAT_NONE
- ui = new(user, src, ui_key, "personal_crafting", "Crafting Menu", 700, 800, master_ui, state)
- ui.open()
-
-
-/datum/component/personal_crafting/ui_data(mob/user)
- var/list/data = list()
- data["busy"] = busy
- data["category"] = cur_category
- data["subcategory"] = cur_subcategory
- data["display_craftable_only"] = display_craftable_only
- data["display_compact"] = display_compact
-
- var/list/surroundings = get_surroundings(user)
- var/list/craftability = list()
- for(var/rec in GLOB.crafting_recipes)
- var/datum/crafting_recipe/R = rec
-
- if(!R.always_availible && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this.
- continue
-
- if((R.category != cur_category) || (R.subcategory != cur_subcategory))
- continue
-
- craftability["[REF(R)]"] = check_contents(user, R, surroundings)
-
- data["craftability"] = craftability
- return data
-
-/datum/component/personal_crafting/ui_static_data(mob/user)
- var/list/data = list()
-
- var/list/crafting_recipes = list()
- for(var/rec in GLOB.crafting_recipes)
- var/datum/crafting_recipe/R = rec
-
- if(R.name == "") //This is one of the invalid parents that sneaks in
- continue
-
- if(!R.always_availible && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this.
- continue
-
- if(isnull(crafting_recipes[R.category]))
- crafting_recipes[R.category] = list()
-
- if(R.subcategory == CAT_NONE)
- crafting_recipes[R.category] += list(build_recipe_data(R))
- else
- if(isnull(crafting_recipes[R.category][R.subcategory]))
- crafting_recipes[R.category][R.subcategory] = list()
- crafting_recipes[R.category]["has_subcats"] = TRUE
- crafting_recipes[R.category][R.subcategory] += list(build_recipe_data(R))
-
- data["crafting_recipes"] = crafting_recipes
- return data
-
-
-/datum/component/personal_crafting/ui_act(action, params)
- if(..())
- return
- switch(action)
- if("make")
- var/datum/crafting_recipe/TR = locate(params["recipe"]) in GLOB.crafting_recipes
- ui_interact(usr)
- if(busy)
- to_chat(usr, "You are already making something!")
- return
- busy = TRUE
- var/fail_msg = construct_item(usr, TR)
- if(!fail_msg)
- to_chat(usr, "[TR.name] constructed.")
- else
- to_chat(usr, "Construction failed[fail_msg]")
- busy = FALSE
- if("toggle_recipes")
- display_craftable_only = !display_craftable_only
- . = TRUE
- if("toggle_compact")
- display_compact = !display_compact
- . = TRUE
- if("set_category")
- if(!isnull(params["category"]))
- cur_category = params["category"]
- if(!isnull(params["subcategory"]))
- if(params["subcategory"] == "0")
- cur_subcategory = ""
- else
- cur_subcategory = params["subcategory"]
- . = TRUE
-
-/datum/component/personal_crafting/proc/build_recipe_data(datum/crafting_recipe/R)
- var/list/data = list()
- data["name"] = R.name
- data["ref"] = "[REF(R)]"
- var/req_text = ""
- var/tool_text = ""
- var/catalyst_text = ""
-
- for(var/a in R.reqs)
- //We just need the name, so cheat-typecast to /atom for speed (even tho Reagents are /datum they DO have a "name" var)
- //Also these are typepaths so sadly we can't just do "[a]"
- var/atom/A = a
- req_text += " [R.reqs[A]] [initial(A.name)],"
- req_text = replacetext(req_text,",","",-1)
- data["req_text"] = req_text
-
- for(var/a in R.chem_catalysts)
- var/atom/A = a //cheat-typecast
- catalyst_text += " [R.chem_catalysts[A]] [initial(A.name)],"
- catalyst_text = replacetext(catalyst_text,",","",-1)
- data["catalyst_text"] = catalyst_text
-
- for(var/a in R.tools)
- if(ispath(a, /obj/item))
- var/obj/item/b = a
- tool_text += " [initial(b.name)],"
- else
- tool_text += " [a],"
- tool_text = replacetext(tool_text,",","",-1)
- data["tool_text"] = tool_text
-
- return data
-
-//Mind helpers
-
-/datum/mind/proc/teach_crafting_recipe(R)
- if(!learned_recipes)
- learned_recipes = list()
- learned_recipes |= R
diff --git a/code/datums/components/crafting/crafting.dm b/code/datums/components/crafting/crafting.dm
index 1a9f4c0512..147dd287ca 100644
--- a/code/datums/components/crafting/crafting.dm
+++ b/code/datums/components/crafting/crafting.dm
@@ -4,6 +4,10 @@
/datum/component/personal_crafting/proc/create_mob_button(mob/user, client/CL)
var/datum/hud/H = user.hud_used
+ for(var/huds in H.static_inventory)
+ if(istype(huds, /obj/screen/craft))
+ return
+ //We don't want to be stacking multiple crafting huds on relogs
var/obj/screen/craft/C = new()
C.icon = H.ui_style
H.static_inventory += C
@@ -20,7 +24,7 @@
CAT_AMMO,
),
CAT_ROBOT = CAT_NONE,
- CAT_MISC = list(
+ CAT_MISCELLANEOUS = list(
CAT_MISCELLANEOUS,
CAT_TOOL,
CAT_FURNITURE,
diff --git a/code/datums/components/crafting/recipes/recipes_misc.dm b/code/datums/components/crafting/recipes/recipes_misc.dm
index 032dd0ea90..ad37f770ed 100644
--- a/code/datums/components/crafting/recipes/recipes_misc.dm
+++ b/code/datums/components/crafting/recipes/recipes_misc.dm
@@ -8,7 +8,7 @@
time = 1
reqs = list(/obj/item/stack/sheet/plastic = 1,
/obj/item/stack/sheet/mineral/wood = 1)
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
subcategory = CAT_TOOL
/datum/crafting_recipe/showercurtain
@@ -18,7 +18,7 @@
/obj/item/stack/rods = 1)
result = /obj/structure/curtain
subcategory = CAT_FURNITURE
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/guillotine
name = "Guillotine"
@@ -29,7 +29,7 @@
/obj/item/stack/cable_coil = 10)
tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/femur_breaker
name = "Femur Breaker"
@@ -39,7 +39,7 @@
/obj/item/stack/cable_coil = 30)
tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
// Blood Sucker stuff //
/datum/crafting_recipe/bloodsucker/blackcoffin
@@ -54,7 +54,7 @@
///obj/item/pipe = 2)
time = 150
subcategory = CAT_FURNITURE
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
always_availible = TRUE
/datum/crafting_recipe/bloodsucker/meatcoffin
@@ -66,7 +66,7 @@
/obj/item/restraints/handcuffs/cable = 1)
time = 150
subcategory = CAT_FURNITURE
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
always_availible = TRUE
/datum/crafting_recipe/bloodsucker/metalcoffin
@@ -77,7 +77,7 @@
reqs = list(/obj/item/stack/sheet/metal = 5)
time = 100
subcategory = CAT_FURNITURE
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
always_availible = TRUE
/datum/crafting_recipe/bloodsucker/vassalrack
@@ -100,7 +100,7 @@
// )
time = 150
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
always_availible = FALSE // Disabled until learned
@@ -117,7 +117,7 @@
)
time = 100
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
always_availible = FALSE // Disabled til learned
/datum/crafting_recipe/furnace
@@ -129,7 +129,7 @@
/obj/item/stack/rods = 2)
tools = list(TOOL_CROWBAR)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/tableanvil
name = "Table Anvil"
@@ -139,7 +139,7 @@
/obj/item/stack/rods = 2)
tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/sandvil
name = "Sandstone Anvil"
@@ -148,7 +148,7 @@
reqs = list(/obj/item/stack/sheet/mineral/sandstone = 24)
tools = list(TOOL_CROWBAR)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/basaltblock
name = "Sintered Basalt Block"
@@ -157,7 +157,7 @@
reqs = list(/obj/item/stack/ore/glass/basalt = 50)
tools = list(TOOL_WELDER)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/basaltanvil
name = "Basalt Anvil"
@@ -166,7 +166,7 @@
reqs = list(/obj/item/basaltblock = 5)
tools = list(TOOL_CROWBAR)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
///////////////////
//Tools & Storage//
///////////////////
@@ -177,7 +177,7 @@
time = 1
reqs = list(/obj/item/stack/medical/gauze = 1,
/datum/reagent/space_cleaner/sterilizine = 5)
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
subcategory = CAT_TOOL
/datum/crafting_recipe/brute_pack
@@ -186,7 +186,7 @@
time = 1
reqs = list(/obj/item/stack/medical/gauze/adv = 1,
/datum/reagent/medicine/styptic_powder = 10)
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
subcategory = CAT_TOOL
/datum/crafting_recipe/burn_pack
@@ -195,7 +195,7 @@
time = 1
reqs = list(/obj/item/stack/medical/gauze/adv = 1,
/datum/reagent/medicine/silver_sulfadiazine = 10)
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
subcategory = CAT_TOOL
/datum/crafting_recipe/ghettojetpack
@@ -206,7 +206,7 @@
/obj/item/extinguisher = 1,
/obj/item/pipe = 3,
/obj/item/stack/cable_coil = 30)
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
subcategory = CAT_TOOL
tools = list(TOOL_WRENCH, TOOL_WELDER, TOOL_WIRECUTTER)
@@ -220,7 +220,7 @@
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/toolboxhammer
name = "Toolbox Hammer"
@@ -231,7 +231,7 @@
/obj/item/stack/rods = 2)
time = 40
subcategory = CAT_TOOL
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/papersack
name = "Paper Sack"
@@ -239,7 +239,7 @@
time = 10
reqs = list(/obj/item/paper = 5)
subcategory = CAT_TOOL
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/smallcarton
name = "Small Carton"
@@ -247,7 +247,7 @@
time = 10
reqs = list(/obj/item/stack/sheet/cardboard = 1)
subcategory = CAT_TOOL
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/bronze_driver
name = "Bronze Plated Screwdriver"
@@ -259,7 +259,7 @@
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/bronze_welder
name = "Bronze Plated Welding Tool"
@@ -271,7 +271,7 @@
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/bronze_wirecutters
name = "Bronze Plated Wirecutters"
@@ -283,7 +283,7 @@
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/bronze_crowbar
name = "Bronze Plated Crowbar"
@@ -295,7 +295,7 @@
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/bronze_wrench
name = "Bronze Plated Wrench"
@@ -307,7 +307,7 @@
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/rcl
name = "Makeshift Rapid Cable Layer"
@@ -316,7 +316,7 @@
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WRENCH)
reqs = list(/obj/item/stack/sheet/metal = 15)
subcategory = CAT_TOOL
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/picket_sign
name = "Picket Sign"
@@ -325,7 +325,7 @@
/obj/item/stack/sheet/cardboard = 2)
time = 80
subcategory = CAT_TOOL
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/electrochromatic_kit
name = "Electrochromatic Kit"
@@ -334,7 +334,7 @@
/obj/item/stack/cable_coil = 1)
time = 5
subcategory = CAT_TOOL
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/blackmarket_uplink
name = "Black Market Uplink"
@@ -346,7 +346,7 @@
/obj/item/radio = 1,
/obj/item/analyzer = 1)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/heretic/codex
name = "Codex Cicatrix"
@@ -358,7 +358,7 @@
/obj/item/stack/sheet/animalhide/human = 1)
time = 150
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
always_availible = FALSE
////////////
@@ -372,7 +372,21 @@
/obj/item/stack/rods = 8)
time = 100
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
+
+/datum/crafting_recipe/motorized_wheelchair
+ name = "Hoverchair"
+ result = /obj/vehicle/ridden/wheelchair/motorized
+ reqs = list(/obj/item/stack/sheet/plasteel = 10,
+ /obj/item/stack/rods = 8,
+ /obj/item/stock_parts/manipulator = 2,
+ /obj/item/stock_parts/capacitor = 1)
+ parts = list(/obj/item/stock_parts/manipulator = 2,
+ /obj/item/stock_parts/capacitor = 1)
+ tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WRENCH)
+ time = 200
+ subcategory = CAT_MISCELLANEOUS
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/skateboard
name = "Skateboard"
@@ -381,7 +395,7 @@
reqs = list(/obj/item/stack/sheet/metal = 5,
/obj/item/stack/rods = 10)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/scooter
name = "Scooter"
@@ -390,7 +404,7 @@
reqs = list(/obj/item/stack/sheet/metal = 5,
/obj/item/stack/rods = 12)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/////////
//Toys///
@@ -401,28 +415,28 @@
reqs = list(/obj/item/light/bulb = 1, /obj/item/stack/cable_coil = 1, /obj/item/stack/sheet/plastic = 4)
result = /obj/item/toy/sword
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/extendohand
name = "Extendo-Hand"
reqs = list(/obj/item/bodypart/r_arm/robot = 1, /obj/item/clothing/gloves/boxing = 1)
result = /obj/item/extendohand
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/toyneb
name = "Non-Euplastic Blade"
reqs = list(/obj/item/light/tube = 1, /obj/item/stack/cable_coil = 1, /obj/item/stack/sheet/plastic = 4)
result = /obj/item/toy/sword/cx
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/catgirlplushie
name = "Catgirl Plushie"
reqs = list(/obj/item/toy/plush/hairball = 3)
result = /obj/item/toy/plush/catgirl
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
////////////
//Unsorted//
@@ -436,7 +450,7 @@
reqs = list(/obj/item/stack/sheet/mineral/wood = 1)
result = /obj/item/stick
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/swordhilt
@@ -445,14 +459,14 @@
reqs = list(/obj/item/stack/sheet/mineral/wood = 2)
result = /obj/item/swordhandle
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/blackcarpet
name = "Black Carpet"
reqs = list(/obj/item/stack/tile/carpet = 50, /obj/item/toy/crayon/black = 1)
result = /obj/item/stack/tile/carpet/black/fifty
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/paperframes
name = "Paper Frames"
@@ -460,7 +474,7 @@
time = 10
reqs = list(/obj/item/stack/sheet/mineral/wood = 5, /obj/item/paper = 20)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/naturalpaper
name = "Hand-Pressed Paper"
@@ -469,7 +483,7 @@
tools = list(/obj/item/hatchet)
result = /obj/item/paper_bin/bundlenatural
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/bluespacehonker
name = "Bluespace Bike horn"
@@ -479,7 +493,7 @@
/obj/item/toy/crayon/blue = 1,
/obj/item/bikehorn = 1)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/mousetrap
name = "Mouse Trap"
@@ -488,7 +502,7 @@
reqs = list(/obj/item/stack/sheet/cardboard = 1,
/obj/item/stack/rods = 1)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/flashlight_eyes
name = "Flashlight Eyes"
@@ -499,7 +513,7 @@
/obj/item/restraints/handcuffs/cable = 1
)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/pressureplate
name = "Pressure Plate"
@@ -510,7 +524,7 @@
/obj/item/stack/cable_coil = 2,
/obj/item/assembly/igniter = 1)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/gold_horn
name = "Golden Bike Horn"
@@ -519,7 +533,7 @@
reqs = list(/obj/item/stack/sheet/mineral/bananium = 5,
/obj/item/bikehorn = 1)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/spooky_camera
name = "Camera Obscura"
@@ -529,7 +543,7 @@
/datum/reagent/water/holywater = 10)
parts = list(/obj/item/camera = 1)
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/coconut_bong
name = "Coconut Bong"
@@ -538,7 +552,7 @@
/obj/item/reagent_containers/food/snacks/grown/coconut = 1)
time = 70
subcategory = CAT_MISCELLANEOUS
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
//////////////
//Banners/////
@@ -551,7 +565,7 @@
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/captain/parade = 1)
subcategory = CAT_FURNITURE
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/engineering_banner
name = "Engitopia Banner"
@@ -560,7 +574,7 @@
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/engineering/engineer = 1)
subcategory = CAT_FURNITURE
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/cargo_banner
name = "Cargonia Banner"
@@ -569,7 +583,7 @@
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/cargo/tech = 1)
subcategory = CAT_FURNITURE
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/science_banner
name = "Sciencia Banner"
@@ -578,7 +592,7 @@
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/rnd/scientist = 1)
subcategory = CAT_FURNITURE
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/medical_banner
name = "Meditopia Banner"
@@ -587,7 +601,7 @@
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/medical/doctor = 1)
subcategory = CAT_FURNITURE
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
/datum/crafting_recipe/security_banner
name = "Securistan Banner"
@@ -596,4 +610,4 @@
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/security/officer = 1)
subcategory = CAT_FURNITURE
- category = CAT_MISC
+ category = CAT_MISCELLANEOUS
diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm
index ec5ec19a6b..eca38fee34 100644
--- a/code/datums/components/embedded.dm
+++ b/code/datums/components/embedded.dm
@@ -265,6 +265,7 @@
/// Items embedded/stuck to carbons both check whether they randomly fall out (if applicable), as well as if the target mob and limb still exists.
/// Items harmfully embedded in carbons have an additional check for random pain (if applicable)
/datum/component/embedded/proc/processCarbon()
+ set waitfor = FALSE
var/mob/living/carbon/victim = parent
if(!victim || !limb) // in case the victim and/or their limbs exploded (say, due to a sticky bomb)
diff --git a/code/datums/components/lockon_aiming.dm b/code/datums/components/lockon_aiming.dm
index 2f4401862d..4acdece7e5 100644
--- a/code/datums/components/lockon_aiming.dm
+++ b/code/datums/components/lockon_aiming.dm
@@ -158,6 +158,7 @@
autolock()
/datum/component/lockon_aiming/proc/autolock()
+ set waitfor = FALSE
var/mob/M = parent
if(!M.client)
return FALSE
diff --git a/code/datums/components/orbiter.dm b/code/datums/components/orbiter.dm
index 26f52f6ba5..c34d56982a 100644
--- a/code/datums/components/orbiter.dm
+++ b/code/datums/components/orbiter.dm
@@ -90,7 +90,7 @@
return
SEND_SIGNAL(parent, COMSIG_ATOM_ORBIT_END, orbiter, refreshing)
UnregisterSignal(orbiter, COMSIG_MOVABLE_MOVED)
- orbiter.SpinAnimation(0, 0)
+ orbiter.SpinAnimation(0, 0, parallel = FALSE)
if(istype(orbiters[orbiter],/matrix)) //This is ugly.
orbiter.transform = orbiters[orbiter]
orbiters -= orbiter
diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm
index 2439ef4d53..0b4b3ef2dd 100644
--- a/code/datums/diseases/advance/symptoms/heal.dm
+++ b/code/datums/diseases/advance/symptoms/heal.dm
@@ -159,9 +159,9 @@
/datum/symptom/heal/metabolism/Heal(mob/living/carbon/C, datum/disease/advance/A, actual_power)
if(!istype(C))
return
- C.reagents.metabolize(C, can_overdose=TRUE) //this works even without a liver; it's intentional since the virus is metabolizing by itself
+ C.reagents.metabolize(C, SSMOBS_DT, 0, can_overdose=TRUE) //this works even without a liver; it's intentional since the virus is metabolizing by itself
if(triple_metabolism)
- C.reagents.metabolize(C, can_overdose=TRUE)
+ C.reagents.metabolize(C, SSMOBS_DT, 0, can_overdose=TRUE)
C.overeatduration = max(C.overeatduration - 2, 0)
var/lost_nutrition = 9 - (reduced_hunger * 5)
C.adjust_nutrition(-lost_nutrition * HUNGER_FACTOR) //Hunger depletes at 10x the normal speed
diff --git a/code/datums/dna.dm b/code/datums/dna.dm
index 248b669ab1..a2982a3caf 100644
--- a/code/datums/dna.dm
+++ b/code/datums/dna.dm
@@ -405,7 +405,7 @@
/mob/living/carbon/human/proc/hardset_dna(ui, list/mutation_index, newreal_name, newblood_type, datum/species/mrace, newfeatures, list/default_mutation_genes)
-
+ set waitfor = FALSE
if(newreal_name)
real_name = newreal_name
dna.generate_unique_enzymes()
diff --git a/code/datums/elements/earhealing.dm b/code/datums/elements/earhealing.dm
index 91c2120fc2..1c74777845 100644
--- a/code/datums/elements/earhealing.dm
+++ b/code/datums/elements/earhealing.dm
@@ -24,7 +24,8 @@
else
user_by_item -= source
-/datum/element/earhealing/process()
+/datum/element/earhealing/proc/do_process()
+ set waitfor = FALSE
for(var/i in user_by_item)
var/mob/living/carbon/user = user_by_item[i]
if(HAS_TRAIT(user, TRAIT_DEAF))
@@ -35,3 +36,6 @@
ears.deaf = max(ears.deaf - 0.25, (ears.damage < ears.maxHealth ? 0 : 1)) // Do not clear deafness if our ears are too damaged
ears.damage = max(ears.damage - 0.025, 0)
CHECK_TICK
+
+/datum/element/earhealing/process()
+ do_process()
diff --git a/code/datums/elements/photosynthesis.dm b/code/datums/elements/photosynthesis.dm
index 4fe0615b1f..8e1c8c53ff 100644
--- a/code/datums/elements/photosynthesis.dm
+++ b/code/datums/elements/photosynthesis.dm
@@ -59,7 +59,7 @@
var/mob/living/L = AM
if(L.stat == DEAD)
continue
- if(light_nutrition_gain)
+ if(light_nutrition_gain && L.nutrition < NUTRITION_LEVEL_WELL_FED)
L.adjust_nutrition(light_amount * light_nutrition_gain * attached_atoms[AM], NUTRITION_LEVEL_WELL_FED)
if(light_amount > bonus_lum || light_amount < malus_lum)
var/mult = ((light_amount > bonus_lum) ? 1 : -1) * attached_atoms[AM]
diff --git a/code/datums/elements/trash.dm b/code/datums/elements/trash.dm
new file mode 100644
index 0000000000..3a4d5b0150
--- /dev/null
+++ b/code/datums/elements/trash.dm
@@ -0,0 +1,19 @@
+/datum/element/trash
+ element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
+
+/datum/element/trash/Attach(datum/target)
+ . = ..()
+ RegisterSignal(target, COMSIG_ITEM_ATTACK, .proc/UseFromHand)
+
+/datum/element/trash/proc/UseFromHand(obj/item/source, mob/living/M, mob/living/user)
+ if((M == user || user.vore_flags & TRASH_FORCEFEED) && ishuman(user))
+ var/mob/living/carbon/human/H = user
+ if(HAS_TRAIT(H, TRAIT_TRASHCAN))
+ playsound(H.loc,'sound/items/eatfood.ogg', rand(10,50), 1)
+ if(H.vore_selected)
+ H.visible_message("[H] [H.vore_selected.vore_verb]s the [source] into their [H.vore_selected]",
+ "You [H.vore_selected.vore_verb]s the [source] into your [H.vore_selected]")
+ source.forceMove(H.vore_selected)
+ else
+ H.visible_message("[H] consumes the [source].")
+ qdel(source)
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index 7fc7da2ef7..ba5f2e1e18 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -199,6 +199,23 @@
movespeed_mod = /datum/movespeed_modifier/status_effect/tased/no_combat_mode
stamdmg_per_ds = 1
+/datum/status_effect/vtec_disabled
+ id = "vtec_disable"
+ tick = FALSE
+
+/datum/status_effect/vtec_disabled/on_creation(mob/living/new_owner, set_duration)
+ if(isnum(set_duration))
+ duration = set_duration
+ . = ..()
+ if(iscyborg(owner))
+ var/mob/living/silicon/robot/R = owner
+ R.vtec_disabled = TRUE
+
+/datum/status_effect/vtec_disabled/on_remove()
+ if(iscyborg(owner))
+ var/mob/living/silicon/robot/R = owner
+ R.vtec_disabled = FALSE
+ return ..()
//OTHER DEBUFFS
/datum/status_effect/his_wrath //does minor damage over time unless holding His Grace
diff --git a/code/datums/status_effects/status_effect.dm b/code/datums/status_effects/status_effect.dm
index b38b755f28..6d0c62a8b2 100644
--- a/code/datums/status_effects/status_effect.dm
+++ b/code/datums/status_effects/status_effect.dm
@@ -5,6 +5,8 @@
/datum/status_effect
var/id = "effect" //Used for screen alerts.
var/duration = -1 //How long the status effect lasts in DECISECONDS. Enter -1 for an effect that never ends unless removed through some means.
+ /// do we tick()?
+ var/tick = TRUE
var/tick_interval = 10 //How many deciseconds between ticks, approximately. Leave at 10 for every second.
var/next_tick //The scheduled time for the next tick.
var/mob/living/owner //The mob affected by the status effect.
diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm
index 18d565ed5a..2f0667d942 100644
--- a/code/datums/traits/neutral.dm
+++ b/code/datums/traits/neutral.dm
@@ -154,3 +154,11 @@
/datum/quirk/longtimer/on_spawn()
var/mob/living/carbon/C = quirk_holder
C.generate_fake_scars(rand(min_scars, max_scars))
+
+/datum/quirk/trashcan
+ name = "Trashcan"
+ desc = "You are able to consume and digest trash."
+ value = 0
+ gain_text = "You feel like munching on a can of soda."
+ lose_text = "You no longer feel like you should be eating trash."
+ mob_trait = TRAIT_TRASHCAN
diff --git a/code/datums/wires/_wires.dm b/code/datums/wires/_wires.dm
index 1c9c14ee3e..81f99cfa69 100644
--- a/code/datums/wires/_wires.dm
+++ b/code/datums/wires/_wires.dm
@@ -166,6 +166,7 @@
on_pulse(wire, user)
/datum/wires/proc/pulse_color(color, mob/living/user)
+ set waitfor = FALSE
LAZYINITLIST(current_users)
if(current_users[user])
return FALSE
diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm
index 55f91ba3d3..c7fee7df96 100644
--- a/code/game/gamemodes/dynamic/dynamic.dm
+++ b/code/game/gamemodes/dynamic/dynamic.dm
@@ -711,10 +711,15 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
update_playercounts()
if (storyteller.should_inject_antag())
SSblackbox.record_feedback("tally","dynamic",1,"Attempted midround injections")
- var/list/drafted_rules = storyteller.midround_draft()
- if (drafted_rules.len > 0)
- SSblackbox.record_feedback("tally","dynamic",1,"Successful midround injections")
- picking_midround_latejoin_rule(drafted_rules)
+ do_midround_injection()
+
+/datum/game_mode/dynamic/proc/do_midround_injection()
+ set waitfor = FALSE
+ var/list/drafted_rules = storyteller.midround_draft()
+ if (drafted_rules.len > 0)
+ SSblackbox.record_feedback("tally","dynamic",1,"Successful midround injections")
+ picking_midround_latejoin_rule(drafted_rules)
+
/// Updates current_players.
/datum/game_mode/dynamic/proc/update_playercounts()
diff --git a/code/game/gamemodes/gangs/dominator.dm b/code/game/gamemodes/gangs/dominator.dm
index ed17d830ba..a253aa906c 100644
--- a/code/game/gamemodes/gangs/dominator.dm
+++ b/code/game/gamemodes/gangs/dominator.dm
@@ -105,14 +105,18 @@
if(tempgang != gang)
tempgang.message_gangtools("WARNING: [gang.name] Gang takeover imminent. Their dominator at [domloc.map_name] must be destroyed!",1,1)
else
- Cinematic(CINEMATIC_MALF,world) //Here is the gang victory trigger on the dominator ending.
- gang.winner = TRUE
- SSticker.news_report = GANG_VICTORY
- SSticker.force_ending = TRUE
+ endgame()
if(!.)
STOP_PROCESSING(SSmachines, src)
+/obj/machinery/dominator/proc/endgame()
+ set waitfor = FALSE
+ Cinematic(CINEMATIC_MALF,world) //Here is the gang victory trigger on the dominator ending.
+ gang.winner = TRUE
+ SSticker.news_report = GANG_VICTORY
+ SSticker.force_ending = TRUE
+
/obj/machinery/dominator/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
switch(damage_type)
if(BRUTE)
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index e95543cffb..75c84bd2a8 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -173,10 +173,7 @@
clonemind.transfer_to(H)
else if(get_clone_mind == CLONEPOD_POLL_MIND)
- var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone? (Don't ERP without permission from the original)", null, null, null, 100, H, POLL_IGNORE_CLONE)
- if(LAZYLEN(candidates))
- var/mob/C = pick(candidates)
- H.key = C.key
+ poll_for_mind(H, clonename)
if(grab_ghost_when == CLONER_FRESH_CLONE)
H.grab_ghost()
@@ -206,6 +203,13 @@
attempting = FALSE
return TRUE
+/obj/machinery/clonepod/proc/poll_for_mind(mob/living/carbon/human/H, clonename)
+ set waitfor = FALSE
+ var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone? (Don't ERP without permission from the original)", null, null, null, 100, H, POLL_IGNORE_CLONE)
+ if(LAZYLEN(candidates))
+ var/mob/C = pick(candidates)
+ H.key = C.key
+
//Grow clones to maturity then kick them out. FREELOADERS
/obj/machinery/clonepod/process()
var/mob/living/mob_occupant = occupant
@@ -384,7 +388,7 @@
to_chat(occupant, "There is a bright flash! You feel like a new being.")
mob_occupant.flash_act()
- var/list/policies = CONFIG_GET(keyed_list/policyconfig)
+ var/list/policies = CONFIG_GET(keyed_list/policy)
var/policy = policies[POLICYCONFIG_ON_CLONE]
if(policy)
to_chat(occupant, policy)
diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm
index 97e2d4ea0a..f1cf187ff9 100644
--- a/code/game/machinery/computer/pod.dm
+++ b/code/game/machinery/computer/pod.dm
@@ -34,6 +34,7 @@
* Initiates launching sequence by checking if all components are functional, opening poddoors, firing mass drivers and then closing poddoors
*/
/obj/machinery/computer/pod/proc/alarm()
+ set waitfor = FALSE
if(stat & (NOPOWER|BROKEN))
return
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index aad64df6d9..231075a27d 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -459,11 +459,11 @@
else if(iscarbon(A))
var/mob/living/carbon/C = A
- //If not emagged, only target carbons that can use items
- if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || !(C.mobility_flags & MOBILITY_USE)))
+ //If not on lethal, only target carbons that aren't cuffed nor stamcrit or just plain crit.
+ if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || IS_STAMCRIT(C)))
continue
- //If emagged, target all but dead carbons
+ //If on lethal, target all but dead carbons
if(mode == TURRET_LETHAL && C.stat == DEAD)
continue
@@ -503,6 +503,7 @@
return 1
/obj/machinery/porta_turret/proc/popUp() //pops the turret up
+ set waitfor = FALSE
if(!anchored)
return
if(raising || raised)
@@ -521,6 +522,7 @@
layer = MOB_LAYER
/obj/machinery/porta_turret/proc/popDown() //pops the turret down
+ set waitfor = FALSE
if(raising || !raised)
return
if(stat & BROKEN)
diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
index 561daf433d..4009b1b56b 100644
--- a/code/game/machinery/syndicatebomb.dm
+++ b/code/game/machinery/syndicatebomb.dm
@@ -288,6 +288,7 @@
qdel(src)
/obj/item/bombcore/proc/defuse()
+ set waitfor = FALSE
//Note: Because of how var/defused is used you shouldn't override this UNLESS you intend to set the var to 0 or
// otherwise remove the core/reset the wires before the end of defuse(). It will repeatedly be called otherwise.
diff --git a/code/game/mecha/combat/neovgre.dm b/code/game/mecha/combat/neovgre.dm
index 584a2d007e..75470abe88 100644
--- a/code/game/mecha/combat/neovgre.dm
+++ b/code/game/mecha/combat/neovgre.dm
@@ -70,7 +70,6 @@
cell.charge = INFINITY
max_integrity = INFINITY
obj_integrity = max_integrity
- CHECK_TICK //Just to be on the safe side lag wise
else
if(cell.charge < cell.maxcharge)
for(var/obj/effect/clockwork/sigil/transmission/T in range(SIGIL_ACCESS_RANGE, src))
@@ -80,7 +79,6 @@
adjust_clockwork_power(-delta)
if(obj_integrity < max_integrity && istype(loc, /turf/open/floor/clockwork))
obj_integrity += min(max_integrity - obj_integrity, max_integrity / 200)
- CHECK_TICK
/obj/mecha/combat/neovgre/Initialize()
.=..()
diff --git a/code/game/objects/effects/alien_acid.dm b/code/game/objects/effects/alien_acid.dm
index 6496b392c3..40d950332c 100644
--- a/code/game/objects/effects/alien_acid.dm
+++ b/code/game/objects/effects/alien_acid.dm
@@ -9,6 +9,7 @@
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
layer = ABOVE_NORMAL_TURF_LAYER
var/turf/target
+ var/acid_level = 0 // Removed from obj, so it goes here now
/obj/effect/acid/Initialize(mapload, acid_pwr, acid_amt)
@@ -42,7 +43,7 @@
for(var/obj/O in target)
if(prob(20) && !(resistance_flags & UNACIDABLE))
- if(O.acid_level < acid_level*0.3)
+ if(O.acid_level() < acid_level*0.3)
var/acid_used = min(acid_level*0.05, 20)
O.acid_act(10, acid_used)
acid_level = max(0, acid_level - acid_used*10)
diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm
index 8f8b83bfde..66579c90f3 100644
--- a/code/game/objects/effects/anomalies.dm
+++ b/code/game/objects/effects/anomalies.dm
@@ -296,7 +296,7 @@
var/mob/C = pick(candidates)
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(S)])")
C.transfer_ckey(S, FALSE)
- var/list/policies = CONFIG_GET(keyed_list/policyconfig)
+ var/list/policies = CONFIG_GET(keyed_list/policy)
var/policy = policies[POLICYCONFIG_ON_PYROCLASTIC_SENTIENT]
if(policy)
to_chat(S,policy)
diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm
index 6b90cfd62c..752a5dff2c 100644
--- a/code/game/objects/effects/decals/misc.dm
+++ b/code/game/objects/effects/decals/misc.dm
@@ -24,55 +24,86 @@
var/range = 3
var/hits_left = 3
var/range_left = 3
+ var/firstmove = TRUE
+ var/list/hit
/obj/effect/decal/chempuff/blob_act(obj/structure/blob/B)
return
-/obj/effect/decal/chempuff/Initialize(mapload, stream_mode, speed, range, hits_left)
+/obj/effect/decal/chempuff/Initialize(mapload, stream_mode, speed, range, hits_left, size)
. = ..()
+ create_reagents(size, NONE, NO_REAGENTS_VALUE)
stream = stream_mode
src.speed = speed
src.range = src.range_left = range
src.hits_left = hits_left
+ hit = list()
-/obj/effect/decal/chempuff/proc/hit_thing(atom/A)
+/obj/effect/decal/chempuff/Destroy()
+ hit = null
+ return ..()
+
+/// proc called to handle us hitting something
+/obj/effect/decal/chempuff/proc/hit_thing(atom/A, bump_hit)
+ // if the thing is invisible it usually is abstract/underfloor. also, don't hit ourselves.
if(A == src || A.invisibility)
return
- if(!hits_left)
+ // don't hit anything on the first move unless overridden (see: we're colliding a wall blocking our move out of the first tile)
+ if(firstmove && !bump_hit)
return
- if(stream)
- if(ismob(A))
- var/mob/M = A
- if(!M.lying || !range_left)
- reagents.reaction(M, VAPOR)
- hits_left--
- else
- if(!range_left)
- reagents.reaction(A, VAPOR)
- else
- reagents.reaction(A)
- if(ismob(A))
- hits_left--
+ // we're out of hits or we already hit it
+ if(!hits_left || hit[A])
+ return
+ var/living = isliving(A)
+ // if it's not dense and we're a stream instead of a mist, and we're not out of range
+ if(!A.density && stream && range_left && !bump_hit)
+ return
+ // non living mobs are effectively abstract
+ if(ismob(A) && !living)
+ return
+ hit[A] = TRUE
+ reagents.reaction(A, VAPOR)
+ // mobs absorb enough to decrement hits_left, as well as stuff blocking us.
+ if(ismob(A) || bump_hit)
+ hits_left--
/obj/effect/decal/chempuff/Crossed(atom/movable/AM, oldloc)
. = ..()
+ // bump things moving into us as long as we're not on our first move/moving out of origin tile
hit_thing(AM)
+/obj/effect/decal/chempuff/Bump(atom/A)
+ . = ..()
+ // if we hit something blocking our movement, collide it regardless even if we're still on our origin tile
+ hit_thing(A, TRUE)
+
/obj/effect/decal/chempuff/proc/run_puff(atom/target)
- set waitfor = FALSE
- for(var/i in 1 to range)
+ var/safety = 255
+ while(range_left)
+ if(!safety--)
+ CRASH("Spray ran out of safety.")
+ // move towards new turf
+ step_towards(src, target)
+ if(firstmove)
+ // mark first movement so future Cross()es result in collisions
+ firstmove = FALSE
+ // decrement range
range_left--
+ // if we got nullspaced, exit
if(!isturf(loc))
break
+ // hit everything in it
for(var/atom/T in loc)
hit_thing(T)
+ // if we got deleted or ran out of hits, stop
if(!hits_left || !isturf(loc))
break
- if(hits_left && isturf(loc) && (!stream || !range_left))
- reagents.reaction(loc, VAPOR)
- hits_left--
- if(!hits_left)
+ if(!hits_left || !isturf(loc))
+ // yeah yeah sue me it's copypasted code but I don't want to declare a var.
break
+ // hit the turf
+ hit_thing(loc)
+ sleep(speed)
qdel(src)
/obj/effect/decal/fakelattice
diff --git a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm
index eb50ae43a7..2d6fb2c2a2 100644
--- a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm
+++ b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm
@@ -17,7 +17,7 @@
line = null
if(qdel_in)
QDEL_IN(PB, qdel_in)
-d
+
/obj/effect/projectile/tracer
name = "beam"
icon = 'icons/obj/projectiles_tracer.dmi'
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index cbfd5ef5a0..cd486ccf6b 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -352,15 +352,6 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
C.update_damage_overlays()
return
- if(acid_level > 20 && ismob(loc))// so we can still remove the clothes on us that have acid.
- var/mob/living/carbon/C = user
- if(istype(C))
- if(!C.gloves || (!(C.gloves.resistance_flags & (UNACIDABLE|ACID_PROOF))))
- to_chat(user, "The acid on [src] burns your hand!")
- var/obj/item/bodypart/affecting = C.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm")
- if(affecting && affecting.receive_damage( 0, 5 )) // 5 burn damage
- C.update_damage_overlays()
-
if(!(interaction_flags_item & INTERACT_ITEM_ATTACK_HAND_PICKUP)) //See if we're supposed to auto pickup.
return
diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm
index 4280e7105f..16ebe20e51 100644
--- a/code/game/objects/items/cigs_lighters.dm
+++ b/code/game/objects/items/cigs_lighters.dm
@@ -387,6 +387,10 @@ CIGARETTE PACKETS ARE IN FANCY.DM
throwforce = 0
grind_results = list(/datum/reagent/carbon = 2)
+/obj/item/cigbutt/Initialize()
+ . = ..()
+ AddElement(/datum/element/trash)
+
/obj/item/cigbutt/cigarbutt
name = "cigar butt"
desc = "A manky old cigar butt."
diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm
index c601624072..ee65bd5c96 100644
--- a/code/game/objects/items/defib.dm
+++ b/code/game/objects/items/defib.dm
@@ -620,7 +620,7 @@
if(req_defib)
if(defib.healdisk)
H.heal_overall_damage(25, 25)
- var/list/policies = CONFIG_GET(keyed_list/policyconfig)
+ var/list/policies = CONFIG_GET(keyed_list/policy)
var/timelimit = CONFIG_GET(number/defib_cmd_time_limit) * 10 //the config is in seconds, not deciseconds
var/late = timelimit && (tplus > timelimit)
var/policy = late? policies[POLICYCONFIG_ON_DEFIB_LATE] : policies[POLICYCONFIG_ON_DEFIB_INTACT]
diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm
index e7a9d51ebe..d54911528d 100644
--- a/code/game/objects/items/devices/paicard.dm
+++ b/code/game/objects/items/devices/paicard.dm
@@ -122,7 +122,7 @@
/obj/item/paicard/proc/setPersonality(mob/living/silicon/pai/personality)
src.pai = personality
src.add_overlay("pai-null")
- var/list/policies = CONFIG_GET(keyed_list/policyconfig)
+ var/list/policies = CONFIG_GET(keyed_list/policy)
var/policy = policies[POLICYCONFIG_PAI]
if(policy)
to_chat(personality, policy)
diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm
index 9ae8fb80db..60538b479b 100644
--- a/code/game/objects/items/handcuffs.dm
+++ b/code/game/objects/items/handcuffs.dm
@@ -1,6 +1,8 @@
/obj/item/restraints
breakouttime = 600
var/demoralize_criminals = TRUE // checked on carbon/carbon.dm to decide wheter to apply the handcuffed negative moodlet or not.
+ /// allow movement at all during breakout
+ var/allow_breakout_movement = FALSE
/obj/item/restraints/suicide_act(mob/living/carbon/user)
user.visible_message("[user] is strangling [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
@@ -243,6 +245,7 @@
throwforce = 0
w_class = WEIGHT_CLASS_NORMAL
slowdown = 7
+ allow_breakout_movement = TRUE
breakouttime = 300 //Deciseconds = 30s = 0.5 minute
/obj/item/restraints/legcuffs/proc/on_removed()
@@ -312,7 +315,7 @@
trap_damage = 0
item_flags = DROPDEL
flags_1 = NONE
- breakouttime = 25
+ breakouttime = 50
/obj/item/restraints/legcuffs/beartrap/energy/New()
..()
@@ -328,7 +331,7 @@
. = ..()
/obj/item/restraints/legcuffs/beartrap/energy/cyborg
- breakouttime = 20 // Cyborgs shouldn't have a strong restraint
+ breakouttime = 40 // Cyborgs shouldn't have a strong restraint
/obj/item/restraints/legcuffs/bola
name = "bola"
@@ -379,7 +382,7 @@
icon_state = "ebola"
hitsound = 'sound/weapons/taserhit.ogg'
w_class = WEIGHT_CLASS_SMALL
- breakouttime = 25
+ breakouttime = 50
/obj/item/restraints/legcuffs/bola/energy/on_removed()
do_sparks(1, TRUE, src)
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index a04bfb365b..dbfeb9d08f 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -73,14 +73,14 @@
/datum/block_parry_data/captain_saber
parry_time_windup = 0
- parry_time_active = 6
+ parry_time_active = 10
parry_time_spindown = 0
parry_time_perfect = 0.75
- parry_time_perfect_leeway = 0.75
+ parry_time_perfect_leeway = 1.5
parry_imperfect_falloff_percent = 30
parry_efficiency_perfect = 100
parry_failed_stagger_duration = 3 SECONDS
- parry_failed_clickcd_duration = 1 SECONDS
+ parry_failed_clickcd_duration = 0
parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK
parry_automatic_enabled = TRUE
@@ -179,19 +179,23 @@
// Fast, efficient parry.
/datum/block_parry_data/traitor_rapier
parry_time_windup = 0
- parry_time_active = 6
+ parry_time_active = 10
parry_time_spindown = 0
parry_time_active_visual_override = 3
parry_time_spindown_visual_override = 2
parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING
- parry_time_perfect = 1
- parry_time_perfect_leeway = 1
+ parry_time_perfect = 2
+ parry_time_perfect_leeway = 2
parry_time_perfect_leeway_override = list(
TEXT_ATTACK_TYPE_PROJECTILE = 1
)
parry_imperfect_falloff_percent = 30
- parry_efficiency_to_counterattack = INFINITY
+ parry_efficiency_to_counterattack = 100
parry_efficiency_considered_successful = 1
+ parry_data = list(
+ PARRY_KNOCKDOWN_ATTACKER = 10,
+ PARRY_DISARM_ATTACKER = TRUE
+ )
parry_efficiency_perfect = 100
parry_stamina_cost = 5
parry_failed_stagger_duration = 2 SECONDS
diff --git a/code/game/objects/items/pneumaticCannon.dm b/code/game/objects/items/pneumaticCannon.dm
index e62208f848..42e345b502 100644
--- a/code/game/objects/items/pneumaticCannon.dm
+++ b/code/game/objects/items/pneumaticCannon.dm
@@ -266,6 +266,7 @@
. += tank.icon_state
/obj/item/pneumatic_cannon/proc/fill_with_type(type, amount)
+ set waitfor = FALSE
if(!ispath(type, /obj) && !ispath(type, /mob))
return FALSE
var/loaded = 0
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index ed92623a37..88648bcbb7 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -90,7 +90,7 @@ as performing this in action() will cause the upgrade to end up in the borg inst
to_chat(user, "There's no room for another VTEC unit!")
return FALSE
- //R.speed = -2 // Gotta go fast.
+ //R.vtec = -2 // Gotta go fast.
//Citadel change - makes vtecs give an ability rather than reducing the borg's speed instantly
VC = new /obj/effect/proc_holder/silicon/cyborg/vtecControl
R.AddAbility(VC)
@@ -100,7 +100,7 @@ as performing this in action() will cause the upgrade to end up in the borg inst
. = ..()
if (.)
R.RemoveAbility(VC)
- R.speed = initial(R.speed)
+ R.vtec = initial(R.vtec)
R.cansprint = 1
/obj/item/borg/upgrade/disablercooler
@@ -690,11 +690,11 @@ as performing this in action() will cause the upgrade to end up in the borg inst
if(istype(user))
switch(currentState)
if (0)
- user.speed = initial(user.speed)
+ user.vtec = initial(user.vtec)
if (1)
- user.speed = initial(user.speed) - maxReduction * 0.5
+ user.vtec = initial(user.vtec) - maxReduction * 0.5
if (2)
- user.speed = initial(user.speed) - maxReduction * 1
+ user.vtec = initial(user.vtec) - maxReduction * 1
action.button_icon_state = "Chevron_State_[currentState]"
action.UpdateButtonIcon()
diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm
index f655e831d8..eeb673a0c7 100644
--- a/code/game/objects/items/stacks/sheets/leather.dm
+++ b/code/game/objects/items/stacks/sheets/leather.dm
@@ -13,6 +13,7 @@
GLOBAL_LIST_INIT(human_recipes, list( \
new/datum/stack_recipe("bloated human costume", /obj/item/clothing/suit/hooded/bloated_human, 5), \
+ new/datum/stack_recipe("human skin hat", /obj/item/clothing/head/human_leather, 1), \
))
/obj/item/stack/sheet/animalhide/human/get_main_recipes()
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 592b2e42cc..15153521ed 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -179,6 +179,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
GLOBAL_LIST_INIT(plasteel_recipes, list ( \
new/datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = TRUE), \
new/datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 50), \
+ new/datum/stack_recipe("plasteel keg", /obj/structure/custom_keg, 10, time = 50), \
new/datum/stack_recipe("micro powered fan assembly", /obj/machinery/fan_assembly, 5, time = 50, one_per_turf = TRUE, on_floor = TRUE), \
new /datum/stack_recipe_list("crates", list( \
new /datum/stack_recipe("gray crate", /obj/structure/closet/crate, 5, time = 50, one_per_turf = 1, on_floor = 1), \
diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm
index a733c282c6..62bde0e4e6 100644
--- a/code/game/objects/items/stunbaton.dm
+++ b/code/game/objects/items/stunbaton.dm
@@ -16,7 +16,7 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
attack_speed = CLICK_CD_MELEE
- var/stamina_loss_amount = 35
+ var/stamina_loss_amount = 40
var/turned_on = FALSE
var/knockdown = TRUE
/// block percent needed to prevent knockdown/disarm
@@ -25,7 +25,7 @@
var/hitcost = 750
var/throw_hit_chance = 35
var/preload_cell_type //if not empty the baton starts with this type of cell
- var/cooldown_duration = 5 SECONDS //How long our baton rightclick goes on cooldown for after applying a knockdown
+ var/cooldown_duration = 3.5 SECONDS //How long our baton rightclick goes on cooldown for after applying a knockdown
var/status_duration = 5 SECONDS //how long our status effects last for otherwise
COOLDOWN_DECLARE(shove_cooldown)
diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm
index f0fd29adbc..f481cab91f 100644
--- a/code/game/objects/items/tools/crowbar.dm
+++ b/code/game/objects/items/tools/crowbar.dm
@@ -67,6 +67,12 @@
item_state = "crowbar"
toolspeed = 0.5
+/obj/item/crowbar/large/heavy
+ name = "heavy crowbar"
+ desc = "It's a big crowbar. It doesn't fit in your pockets, because it's big. It feels oddly heavy.."
+ force = 20
+ icon_state = "crowbar_powergame"
+
/obj/item/crowbar/cyborg
name = "hydraulic crowbar"
desc = "A hydraulic prying tool, compact but powerful. Designed to replace crowbar in construction cyborgs."
diff --git a/code/game/objects/items/tools/wirecutters.dm b/code/game/objects/items/tools/wirecutters.dm
index ee72c7fed2..51bb046290 100644
--- a/code/game/objects/items/tools/wirecutters.dm
+++ b/code/game/objects/items/tools/wirecutters.dm
@@ -23,13 +23,13 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
var/random_color = TRUE
var/static/list/wirecutter_colors = list(
- "blue" = "#1861d5",
- "red" = "#951710",
- "pink" = "#d5188d",
- "brown" = "#a05212",
- "green" = "#0e7f1b",
- "cyan" = "#18a2d5",
- "yellow" = "#d58c18"
+ "blue" = rgb(24, 97, 213),
+ "red" = rgb(255, 0, 0),
+ "pink" = rgb(213, 24, 141),
+ "brown" = rgb(160, 82, 18),
+ "green" = rgb(14, 127, 27),
+ "cyan" = rgb(24, 162, 213),
+ "yellow" = rgb(255, 165, 0)
)
@@ -49,6 +49,23 @@
base_overlay.appearance_flags = RESET_COLOR
. += base_overlay
+/obj/item/wirecutters/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
+ . = ..()
+ if(isinhands && random_color)
+ var/mutable_appearance/M = mutable_appearance(icon_file, "cutters_cutty_thingy")
+ M.appearance_flags = RESET_COLOR
+ . += M
+
+/obj/item/wirecutters/get_belt_overlay()
+ if(random_color)
+ var/mutable_appearance/body = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "cutters")
+ var/mutable_appearance/head = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "cutters_cutty_thingy")
+ body.color = color
+ head.add_overlay(body)
+ return head
+ else
+ return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', icon_state)
+
/obj/item/wirecutters/attack(mob/living/carbon/C, mob/user)
if(istype(C) && C.handcuffed && istype(C.handcuffed, /obj/item/restraints/handcuffs/cable))
user.visible_message("[user] cuts [C]'s restraints with [src]!")
diff --git a/code/game/objects/items/trash.dm b/code/game/objects/items/trash.dm
index 2109d1038e..1816f26843 100644
--- a/code/game/objects/items/trash.dm
+++ b/code/game/objects/items/trash.dm
@@ -7,6 +7,10 @@
w_class = WEIGHT_CLASS_TINY
resistance_flags = FLAMMABLE
+/obj/item/trash/Initialize()
+ . = ..()
+ AddElement(/datum/element/trash)
+
/obj/item/trash/raisins
name = "\improper 4no raisins"
icon_state= "4no_raisins"
@@ -80,6 +84,3 @@
name = "boritos bag"
icon_state = "boritos"
grind_results = list(/datum/reagent/aluminium = 1) //from the mylar bag
-
-/obj/item/trash/attack(mob/M, mob/living/user)
- return
diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm
index 02f2009667..cc2e6412eb 100644
--- a/code/game/objects/obj_defense.dm
+++ b/code/game/objects/obj_defense.dm
@@ -204,32 +204,23 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
//the obj's reaction when touched by acid
/obj/acid_act(acidpwr, acid_volume)
if(!(resistance_flags & UNACIDABLE) && acid_volume)
-
- if(!acid_level)
- SSacid.processing[src] = src
- update_icon()
- var/acid_cap = acidpwr * 300 //so we cannot use huge amounts of weak acids to do as well as strong acids.
- if(acid_level < acid_cap)
- acid_level = min(acid_level + acidpwr * acid_volume, acid_cap)
+ AddComponent(/datum/component/acid, acidpwr, acid_volume)
return 1
-//the proc called by the acid subsystem to process the acid that's on the obj
-/obj/proc/acid_processing()
- . = 1
- if(!(resistance_flags & ACID_PROOF))
- if(prob(33))
- playsound(loc, 'sound/items/welder.ogg', 150, 1)
- take_damage(min(1 + round(sqrt(acid_level)*0.3), 300), BURN, "acid", 0)
-
- acid_level = max(acid_level - (5 + 3*round(sqrt(acid_level))), 0)
- if(!acid_level)
- return 0
-
//called when the obj is destroyed by acid.
/obj/proc/acid_melt()
- SSacid.processing -= src
+ var/datum/component/acid/acid = GetComponent(/datum/component/acid)
+ if(acid)
+ acid.RemoveComponent()
deconstruct(FALSE)
+/obj/proc/acid_level()
+ var/datum/component/acid/acid = GetComponent(/datum/component/acid)
+ if(acid)
+ return acid.level
+ else
+ return 0
+
//// FIRE
/obj/fire_act(exposed_temperature, exposed_volume)
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index a9a891464b..ca4428db57 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -22,8 +22,6 @@
var/resistance_flags = NONE // INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ON_FIRE | UNACIDABLE | ACID_PROOF
- var/acid_level = 0 //how much acid is on that obj
-
var/persistence_replacement //have something WAY too amazing to live to the next round? Set a new path here. Overuse of this var will make me upset.
var/current_skin //the item reskin
var/list/unique_reskin //List of options to reskin.
@@ -369,8 +367,6 @@
/obj/update_overlays()
. = ..()
- if(acid_level)
- . += GLOB.acid_overlay
if(resistance_flags & ON_FIRE)
. += GLOB.fire_overlay
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index 32040b8573..a70d9d4678 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -48,14 +48,34 @@
return // no message spam
..()
+/obj/structure/mirror/attacked_by(obj/item/I, mob/living/user)
+ if(broken || !istype(user) || !I.force)
+ return ..()
+
+ . = ..()
+ if(broken) // breaking a mirror truly gets you bad luck!
+ to_chat(user, "A chill runs down your spine as [src] shatters...")
+ user.AddComponent(/datum/component/omen, silent=TRUE) // we have our own message
+
+/obj/structure/mirror/bullet_act(obj/item/projectile/P)
+ if(broken || !isliving(P.firer) || !P.damage)
+ return ..()
+
+ . = ..()
+ if(broken) // breaking a mirror truly gets you bad luck!
+ var/mob/living/unlucky_dude = P.firer
+ to_chat(unlucky_dude, "A chill runs down your spine as [src] shatters...")
+ unlucky_dude.AddComponent(/datum/component/omen, silent=TRUE) // we have our own message
+
/obj/structure/mirror/obj_break(damage_flag, mapload)
- if(!broken && !(flags_1 & NODECONSTRUCT_1))
- icon_state = "mirror_broke"
- if(!mapload)
- playsound(src, "shatter", 70, 1)
- if(desc == initial(desc))
- desc = "Oh no, seven years of bad luck!"
- broken = TRUE
+ if(broken || (flags_1 & NODECONSTRUCT_1))
+ return
+ icon_state = "mirror_broke"
+ if(!mapload)
+ playsound(src, "shatter", 70, TRUE)
+ if(desc == initial(desc))
+ desc = "Oh no, seven years of bad luck!"
+ broken = TRUE
/obj/structure/mirror/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm
index 119026a66e..376725b262 100644
--- a/code/game/objects/structures/transit_tubes/station.dm
+++ b/code/game/objects/structures/transit_tubes/station.dm
@@ -121,6 +121,7 @@
/obj/structure/transit_tube/station/proc/launch_pod()
+ set waitfor = FALSE
if(launch_cooldown >= world.time)
return
for(var/obj/structure/transit_tube_pod/pod in loc)
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 01c62a7901..9a2b4aab1a 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -354,10 +354,10 @@
. = SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
. = O.clean_blood()
O.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- if(isitem(O))
- var/obj/item/I = O
- I.acid_level = 0
- I.extinguish()
+ var/datum/component/acid/acid = O.GetComponent(/datum/component/acid)
+ if(acid)
+ acid.level = 0
+ O.extinguish()
/obj/machinery/shower/proc/wash_turf()
if(isturf(loc))
@@ -601,7 +601,9 @@
busy = FALSE
SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
O.clean_blood()
- O.acid_level = 0
+ var/datum/component/acid/acid = O.GetComponent(/datum/component/acid)
+ if(acid)
+ acid.level = 0
create_reagents(5)
reagents.add_reagent(dispensedreagent, 5)
reagents.reaction(O, TOUCH)
diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm
index 35f8c59f7c..bb5ca6da1a 100644
--- a/code/game/turfs/change_turf.dm
+++ b/code/game/turfs/change_turf.dm
@@ -72,7 +72,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
// basic doesn't initialize and this will cause issues
// no warning though because this can happen naturaly as a result of it being built on top of
path = /turf/open/space
- if(!GLOB.use_preloader && path == type && !(flags & CHANGETURF_FORCEOP)) // Don't no-op if the map loader requires it to be reconstructed
+ if(!GLOB.use_preloader && path == type && !(flags & CHANGETURF_FORCEOP) && (baseturfs == new_baseturfs)) // Don't no-op if the map loader requires it to be reconstructed, or if this is a new set of baseturfs
return src
if(flags & CHANGETURF_SKIP)
return new path(src)
diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm
index b92b659183..4082a48e71 100644
--- a/code/modules/antagonists/_common/antag_datum.dm
+++ b/code/modules/antagonists/_common/antag_datum.dm
@@ -96,6 +96,7 @@ GLOBAL_LIST_EMPTY(antagonists)
//Proc called when the datum is given to a mind.
/datum/antagonist/proc/on_gain()
+ set waitfor = FALSE
if(!(owner?.current))
return
if(!silent)
diff --git a/code/modules/antagonists/changeling/powers/adrenaline.dm b/code/modules/antagonists/changeling/powers/adrenaline.dm
index 32171a036a..643458d05a 100644
--- a/code/modules/antagonists/changeling/powers/adrenaline.dm
+++ b/code/modules/antagonists/changeling/powers/adrenaline.dm
@@ -13,5 +13,5 @@
//Recover from stuns.
/obj/effect/proc_holder/changeling/adrenaline/sting_action(mob/living/user)
- user.do_adrenaline(0, FALSE, 70, 0, TRUE, list(/datum/reagent/medicine/epinephrine = 3, /datum/reagent/drug/methamphetamine/changeling = 10, /datum/reagent/medicine/changelingadrenaline = 5), "Energy rushes through us.", 0, 0.75, 0)
+ user.do_adrenaline(0, FALSE, 70, 0, TRUE, list(/datum/reagent/medicine/epinephrine = 3, /datum/reagent/medicine/changelinghaste = 10, /datum/reagent/medicine/changelingadrenaline = 5), "Energy rushes through us.", 0, 0.75, 0)
return TRUE
diff --git a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
index 34370faa0a..4b88d203d6 100644
--- a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
+++ b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
@@ -225,18 +225,22 @@
return ..()
/obj/effect/clockwork/sigil/transmission/process()
- var/power_drained = 0
- var/power_mod = 0.005
- for(var/t in spiral_range_turfs(SIGIL_ACCESS_RANGE, src))
- var/turf/T = t
- for(var/M in T)
- var/atom/movable/A = M
- power_drained += A.power_drain(TRUE)
+ do_process()
- CHECK_TICK
+/obj/effect/clockwork/sigil/transmission/proc/do_process()
+ set waitfor = FALSE
+ var/power_drained = 0
+ var/power_mod = 0.005
+ for(var/t in spiral_range_turfs(SIGIL_ACCESS_RANGE, src))
+ var/turf/T = t
+ for(var/M in T)
+ var/atom/movable/A = M
+ power_drained += A.power_drain(TRUE)
- adjust_clockwork_power(power_drained * power_mod * 15)
- new /obj/effect/temp_visual/ratvar/sigil/transmission(loc, 1 + (power_drained * 0.0035))
+ CHECK_TICK
+
+ adjust_clockwork_power(power_drained * power_mod * 15)
+ new /obj/effect/temp_visual/ratvar/sigil/transmission(loc, 1 + (power_drained * 0.0035))
/obj/effect/clockwork/sigil/transmission/proc/charge_cyborg(mob/living/silicon/robot/cyborg)
if(!cyborg_checks(cyborg))
diff --git a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm b/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm
index 5fc2a0ab63..8fcc36a456 100644
--- a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm
@@ -246,6 +246,36 @@
if(GATEWAY_RATVAR_COMING to INFINITY)
. += "The anomaly is stable! Something is coming through!"
+/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/fulfill_purpose()
+ set waitfor = FALSE
+ countdown.stop()
+ resistance_flags |= INDESTRUCTIBLE
+ purpose_fulfilled = TRUE
+ make_glow()
+ animate(glow, transform = matrix() * 1.5, alpha = 255, time = 125)
+ sound_to_playing_players(volume = 100, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/ratvar_rises.ogg')) //End the sounds
+ sleep(125)
+ make_glow()
+ animate(glow, transform = matrix() * 3, alpha = 0, time = 5)
+ QDEL_IN(src, 3)
+ sleep(3)
+ GLOB.clockwork_gateway_activated = TRUE
+ var/turf/T = SSmapping.get_station_center()
+ new /obj/structure/destructible/clockwork/massive/ratvar(T)
+ var/x0 = T.x
+ var/y0 = T.y
+ for(var/I in spiral_range_turfs(255, T, tick_checked = TRUE))
+ var/turf/T2 = I
+ if(!T2)
+ continue
+ var/dist = cheap_hypotenuse(T2.x, T2.y, x0, y0)
+ if(dist < 100)
+ dist = TRUE
+ else
+ dist = FALSE
+ T.ratvar_act(dist)
+ CHECK_TICK
+
/obj/structure/destructible/clockwork/massive/celestial_gateway/process()
adjust_clockwork_power(2.5) //Provides weak power generation on its own
if(seconds_until_activation)
@@ -306,33 +336,7 @@
glow.icon_state = "clockwork_gateway_closing"
if(GATEWAY_RATVAR_ARRIVAL to INFINITY)
if(!purpose_fulfilled)
- countdown.stop()
- resistance_flags |= INDESTRUCTIBLE
- purpose_fulfilled = TRUE
- make_glow()
- animate(glow, transform = matrix() * 1.5, alpha = 255, time = 125)
- sound_to_playing_players(volume = 100, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/ratvar_rises.ogg')) //End the sounds
- sleep(125)
- make_glow()
- animate(glow, transform = matrix() * 3, alpha = 0, time = 5)
- QDEL_IN(src, 3)
- sleep(3)
- GLOB.clockwork_gateway_activated = TRUE
- var/turf/T = SSmapping.get_station_center()
- new /obj/structure/destructible/clockwork/massive/ratvar(T)
- var/x0 = T.x
- var/y0 = T.y
- for(var/I in spiral_range_turfs(255, T, tick_checked = TRUE))
- var/turf/T2 = I
- if(!T2)
- continue
- var/dist = cheap_hypotenuse(T2.x, T2.y, x0, y0)
- if(dist < 100)
- dist = TRUE
- else
- dist = FALSE
- T.ratvar_act(dist)
- CHECK_TICK
+ fulfill_purpose()
//Converts nearby turfs into their clockwork equivalent, with ever-increasing range the closer the ark is to summoning Ratvar
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/conversion_pulse()
diff --git a/code/modules/antagonists/clockcult/clock_structures/prolonging_prism.dm b/code/modules/antagonists/clockcult/clock_structures/prolonging_prism.dm
index 73488d736a..ededd0174c 100644
--- a/code/modules/antagonists/clockcult/clock_structures/prolonging_prism.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/prolonging_prism.dm
@@ -60,12 +60,8 @@
delay_remaining += PRISM_DELAY_DURATION
toggle(0, user)
-/obj/structure/destructible/clockwork/powered/prolonging_prism/process()
- var/turf/own_turf = get_turf(src)
- if(SSshuttle.emergency.mode != SHUTTLE_CALL || delay_remaining <= 0 || !own_turf || !is_station_level(own_turf.z))
- forced_disable(FALSE)
- return
- . = ..()
+/obj/structure/destructible/clockwork/powered/prolonging_prism/proc/do_process()
+ set waitfor = FALSE
var/delay_amount = 40
delay_remaining -= delay_amount
var/efficiency = get_efficiency_mod()
@@ -114,6 +110,14 @@
new /obj/effect/temp_visual/ratvar/prolonging_prism(T)
CHECK_TICK //we may be going over a hell of a lot of turfs
+/obj/structure/destructible/clockwork/powered/prolonging_prism/process()
+ var/turf/own_turf = get_turf(src)
+ if(SSshuttle.emergency.mode != SHUTTLE_CALL || delay_remaining <= 0 || !own_turf || !is_station_level(own_turf.z))
+ forced_disable(FALSE)
+ return
+ . = ..()
+ do_process()
+
/obj/structure/destructible/clockwork/powered/prolonging_prism/proc/get_delay_cost()
return FLOOR(delay_cost, MIN_CLOCKCULT_POWER)
diff --git a/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm b/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm
index 24ad1af88a..51f8dc7101 100644
--- a/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm
@@ -110,6 +110,7 @@
//Put me in Reebe, will you? Ratvar has found and is going to do a hecking murder on Nar'Sie
/obj/structure/destructible/clockwork/massive/ratvar/proc/clash_of_the_titans(obj/singularity/narsie/narsie)
+ set waitfor = FALSE
var/winner = "Undeclared"
var/base_victory_chance = 1
while(src && narsie)
diff --git a/code/modules/antagonists/cult/cult_structures.dm b/code/modules/antagonists/cult/cult_structures.dm
index 25fd446b06..a0093e4da1 100644
--- a/code/modules/antagonists/cult/cult_structures.dm
+++ b/code/modules/antagonists/cult/cult_structures.dm
@@ -204,26 +204,31 @@
STOP_PROCESSING(SSfastprocess, src)
return ..()
+/obj/structure/destructible/cult/pylon/proc/heal_friends()
+ set waitfor = FALSE
+ for(var/mob/living/L in range(5, src))
+ if(iscultist(L) || isshade(L) || isconstruct(L))
+ if(L.health != L.maxHealth)
+ new /obj/effect/temp_visual/heal(get_turf(src), "#960000")
+ if(ishuman(L))
+ L.adjustBruteLoss(-1, 0, only_organic = FALSE)
+ L.adjustFireLoss(-1, 0, only_organic = FALSE)
+ L.updatehealth()
+ if(isshade(L) || isconstruct(L))
+ var/mob/living/simple_animal/M = L
+ if(M.health < M.maxHealth)
+ M.adjustHealth(-3)
+ if(ishuman(L) && L.blood_volume < (BLOOD_VOLUME_NORMAL * L.blood_ratio))
+ L.blood_volume += 1.0
+ CHECK_TICK
+
+
/obj/structure/destructible/cult/pylon/process()
if(!anchored)
return
if(last_heal <= world.time)
last_heal = world.time + heal_delay
- for(var/mob/living/L in range(5, src))
- if(iscultist(L) || isshade(L) || isconstruct(L))
- if(L.health != L.maxHealth)
- new /obj/effect/temp_visual/heal(get_turf(src), "#960000")
- if(ishuman(L))
- L.adjustBruteLoss(-1, 0, only_organic = FALSE)
- L.adjustFireLoss(-1, 0, only_organic = FALSE)
- L.updatehealth()
- if(isshade(L) || isconstruct(L))
- var/mob/living/simple_animal/M = L
- if(M.health < M.maxHealth)
- M.adjustHealth(-3)
- if(ishuman(L) && L.blood_volume < (BLOOD_VOLUME_NORMAL * L.blood_ratio))
- L.blood_volume += 1.0
- CHECK_TICK
+ heal_friends()
if(last_corrupt <= world.time)
var/list/validturfs = list()
var/list/cultturfs = list()
diff --git a/code/modules/antagonists/devil/devil.dm b/code/modules/antagonists/devil/devil.dm
index 3b6dc68986..65ce89d33f 100644
--- a/code/modules/antagonists/devil/devil.dm
+++ b/code/modules/antagonists/devil/devil.dm
@@ -515,7 +515,6 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
var/mob/living/silicon/robot_devil = owner.current
var/laws = list("You may not use violence to coerce someone into selling their soul.", "You may not directly and knowingly physically harm a devil, other than yourself.", GLOB.lawlorify[LAW][ban], GLOB.lawlorify[LAW][obligation], "Accomplish your objectives at all costs.")
robot_devil.set_law_sixsixsix(laws)
- sleep(10)
if(owner.assigned_role == "Clown" && ishuman(owner.current))
var/mob/living/carbon/human/S = owner.current
to_chat(S, "Your infernal nature has allowed you to overcome your clownishness.")
diff --git a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
index 0659655da5..fcc8bcade8 100644
--- a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
+++ b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
@@ -401,6 +401,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
next_announce += DOOMSDAY_ANNOUNCE_INTERVAL
/obj/machinery/doomsday_device/proc/detonate()
+ set waitfor = FALSE
sound_to_playing_players('sound/machines/alarm.ogg')
sleep(100)
for(var/i in GLOB.mob_living_list)
diff --git a/code/modules/arousal/arousal.dm b/code/modules/arousal/arousal.dm
index bd8b5dbf7a..36da6c73ba 100644
--- a/code/modules/arousal/arousal.dm
+++ b/code/modules/arousal/arousal.dm
@@ -197,6 +197,7 @@
//Here's the main proc itself
/mob/living/carbon/human/proc/mob_climax(forced_climax=FALSE,cause = "") //Forced is instead of the other proc, makes you cum if you have the tools for it, ignoring restraints
+ set waitfor = FALSE
if(mb_cd_timer > world.time)
if(!forced_climax) //Don't spam the message to the victim if forced to come too fast
to_chat(src, "You need to wait [DisplayTimeText((mb_cd_timer - world.time), TRUE)] before you can do that again!")
diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm
index 899eb12511..d0ed0f2436 100644
--- a/code/modules/assembly/infrared.dm
+++ b/code/modules/assembly/infrared.dm
@@ -81,6 +81,7 @@
return
/obj/item/assembly/infra/proc/refreshBeam()
+ set waitfor = FALSE
QDEL_LIST(beams)
if(throwing || !on || !secured)
return
diff --git a/code/modules/atmospherics/environmental/LINDA_fire.dm b/code/modules/atmospherics/environmental/LINDA_fire.dm
index c25e74fc5c..cfa3e7eb14 100644
--- a/code/modules/atmospherics/environmental/LINDA_fire.dm
+++ b/code/modules/atmospherics/environmental/LINDA_fire.dm
@@ -13,7 +13,7 @@
if(!air)
return
- if (air.get_oxidation_power(exposed_temperature) < 0.5)
+ if (air.get_oxidation_power(exposed_temperature) < 0.5 || air.get_moles(GAS_HYPERNOB) > 5)
return
var/has_fuel = air.get_moles(GAS_PLASMA) > 0.5 || air.get_moles(GAS_TRITIUM) > 0.5 || air.get_fuel_amount(exposed_temperature) > 0.5
if(active_hotspot)
@@ -152,7 +152,7 @@
if((temperature < FIRE_MINIMUM_TEMPERATURE_TO_EXIST) || (volume <= 1))
qdel(src)
return
- if(!location.air || location.air.get_oxidation_power() < 0.5 || (INSUFFICIENT(GAS_PLASMA) && INSUFFICIENT(GAS_TRITIUM) && location.air.get_fuel_amount() < 0.5))
+ if(!location.air || location.air.get_moles(GAS_HYPERNOB) > 5 || location.air.get_oxidation_power() < 0.5 || (INSUFFICIENT(GAS_PLASMA) && INSUFFICIENT(GAS_TRITIUM) && location.air.get_fuel_amount() < 0.5))
qdel(src)
return
diff --git a/code/modules/atmospherics/machinery/portable/canister.dm b/code/modules/atmospherics/machinery/portable/canister.dm
index cf4456789a..15c6475033 100644
--- a/code/modules/atmospherics/machinery/portable/canister.dm
+++ b/code/modules/atmospherics/machinery/portable/canister.dm
@@ -433,7 +433,7 @@
var/list/danger = list()
for(var/id in air_contents.get_gases())
var/gas = air_contents.get_moles(id)
- if(!GLOB.gas_data.flags[id] & GAS_FLAG_DANGEROUS)
+ if(!(GLOB.gas_data.flags[id] & GAS_FLAG_DANGEROUS))
continue
if(gas > (GLOB.gas_data.visibility[id] || MOLES_GAS_VISIBLE)) //if moles_visible is undefined, default to default visibility
danger[GLOB.gas_data.names[id]] = gas //ex. "plasma" = 20
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 251bcc72ad..0f0bf6a62c 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -187,6 +187,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/vore_flags = 0
var/list/belly_prefs = list()
var/vore_taste = "nothing in particular"
+ var/vore_smell = null
var/toggleeatingnoise = TRUE
var/toggledigestionnoise = TRUE
var/hound_sleeper = TRUE
@@ -1068,6 +1069,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "Voracious MediHound sleepers:[(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"] "
dat += "Hear Vore Sounds:[(cit_toggles & EATING_NOISES) ? "Yes" : "No"] "
dat += "Hear Vore Digestion Sounds:[(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"] "
+ dat += "Allow trash forcefeeding (requires Trashcan quirk)[(cit_toggles & TRASH_FORCEFEED) ? "Yes" : "No"] "
dat += "Forced Feminization:[(cit_toggles & FORCED_FEM) ? "Allowed" : "Disallowed"] "
dat += "Forced Masculinization:[(cit_toggles & FORCED_MASC) ? "Allowed" : "Disallowed"] "
dat += "Lewd Hypno:[(cit_toggles & HYPNO) ? "Allowed" : "Disallowed"] "
@@ -2800,6 +2802,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("toggledigestionnoise")
cit_toggles ^= DIGESTION_NOISES
+ if("toggleforcefeedtrash")
+ cit_toggles ^= TRASH_FORCEFEED
+
if("breast_enlargement")
cit_toggles ^= BREAST_ENLARGEMENT
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 45c5357c4d..d4d13dc40f 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -821,6 +821,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["vore_flags"] >> vore_flags
S["vore_taste"] >> vore_taste
+ S["vore_smell"] >> vore_smell
var/char_vr_path = "[vr_path]/character_[default_slot]_v2.json"
if(fexists(char_vr_path))
var/list/json_from_file = json_decode(file2text(char_vr_path))
@@ -994,6 +995,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
vore_flags = sanitize_integer(vore_flags, 0, MAX_VORE_FLAG, 0)
vore_taste = copytext(vore_taste, 1, MAX_TASTE_LEN)
+ vore_smell = copytext(vore_smell, 1, MAX_TASTE_LEN)
belly_prefs = SANITIZE_LIST(belly_prefs)
cit_character_pref_load(S)
@@ -1147,6 +1149,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["vore_flags"] , vore_flags)
WRITE_FILE(S["vore_taste"] , vore_taste)
+ WRITE_FILE(S["vore_smell"] , vore_smell)
var/char_vr_path = "[vr_path]/character_[default_slot]_v2.json"
var/belly_prefs_json = safe_json_encode(list("belly_prefs" = belly_prefs))
if(fexists(char_vr_path))
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index 124ece8fdc..fd181779f1 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -482,3 +482,9 @@
icon_state = "kabuto"
item_state = "kabuto"
flags_inv = HIDEHAIR|HIDEEARS
+
+/obj/item/clothing/head/human_leather
+ name = "human skin hat"
+ desc = "This will scare them. All will know my power."
+ icon_state = "human_leather"
+ item_state = "human_leather"
diff --git a/code/modules/events/cat_surgeon.dm b/code/modules/events/cat_surgeon.dm
index ebcd55d8aa..2d5651b9b1 100644
--- a/code/modules/events/cat_surgeon.dm
+++ b/code/modules/events/cat_surgeon.dm
@@ -5,7 +5,7 @@
weight = 8
/datum/round_event/cat_surgeon/announce(fake)
- priority_announce("One of our... ahem... 'special' cases has escaped. Our sensors now show their tracker implant on your station. On an unrelated note, has anyone seen our cats?",
+ priority_announce("One of our... ahem... 'special' cases has escaped. As it happens their last known location before their tracker went dead is your station so keep an eye out for them. On an unrelated note, has anyone seen our cats?",
sender_override = "Nanotrasen Psych Ward")
/datum/round_event/cat_surgeon/start()
diff --git a/code/modules/events/portal_storm.dm b/code/modules/events/portal_storm.dm
index 5ef30d0030..59bb22e9af 100644
--- a/code/modules/events/portal_storm.dm
+++ b/code/modules/events/portal_storm.dm
@@ -56,7 +56,10 @@
next_boss_spawn = startWhen + CEILING(2 * number_of_hostiles / number_of_bosses, 1)
/datum/round_event/portal_storm/announce(fake)
- set waitfor = 0
+ do_announce()
+
+/datum/round_event/portal_storm/proc/do_announce()
+ set waitfor = FALSE
sound_to_playing_players('sound/magic/lightning_chargeup.ogg')
sleep(80)
priority_announce("Massive bluespace anomaly detected en route to [station_name()]. Brace for impact.")
diff --git a/code/modules/events/wizard/fakeexplosion.dm b/code/modules/events/wizard/fakeexplosion.dm
index 5858064819..3ba20f4768 100644
--- a/code/modules/events/wizard/fakeexplosion.dm
+++ b/code/modules/events/wizard/fakeexplosion.dm
@@ -7,5 +7,4 @@
/datum/round_event/wizard/fake_explosion/start()
sound_to_playing_players('sound/machines/alarm.ogg')
- sleep(100)
- Cinematic(CINEMATIC_NUKE_FAKE,world)
+ addtimer(CALLBACK(GLOBAL_PROC,.proc/Cinematic, CINEMATIC_NUKE_FAKE, world), 100)
diff --git a/code/modules/fields/fields.dm b/code/modules/fields/fields.dm
index cb8d3e8dcf..8c7b414996 100644
--- a/code/modules/fields/fields.dm
+++ b/code/modules/fields/fields.dm
@@ -64,7 +64,8 @@
pass = FALSE
return pass
-/datum/proximity_monitor/advanced/process()
+/datum/proximity_monitor/advanced/proc/lag_checked_process()
+ set waitfor = FALSE
if(process_inner_turfs)
for(var/turf/T in field_turfs)
process_inner_turf(T)
@@ -72,7 +73,10 @@
if(process_edge_turfs)
for(var/turf/T in edge_turfs)
process_edge_turf(T)
- CHECK_TICK //Same here.
+ CHECK_TICK //Same here.
+
+/datum/proximity_monitor/advanced/process()
+ lag_checked_process()
/datum/proximity_monitor/advanced/proc/process_inner_turf(turf/T)
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index cc18207a29..7f81fb9993 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -31,7 +31,7 @@ GLOBAL_LIST_INIT(hallucination_list, list(
if(!hallucination)
return
- hallucination--
+ hallucination = max(hallucination-1, 0)
if(world.time < next_hallucination)
return
diff --git a/code/modules/hydroponics/fermenting_barrel.dm b/code/modules/hydroponics/fermenting_barrel.dm
index 76e36a1725..3d6b90eb2d 100644
--- a/code/modules/hydroponics/fermenting_barrel.dm
+++ b/code/modules/hydroponics/fermenting_barrel.dm
@@ -73,3 +73,40 @@
icon_state = "barrel_open"
else
icon_state = "barrel"
+
+/obj/structure/custom_keg
+ name = "Plasteel Keg"
+ desc = "A large plasteel keg. You can use it to hold liquids. You may wanna label this, too."
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "keg"
+ density = TRUE
+ anchored = FALSE
+ pressure_resistance = 2 * ONE_ATMOSPHERE
+ max_integrity = 300
+ var/open = FALSE
+
+/obj/structure/custom_keg/Initialize()
+ create_reagents(1000, DRAINABLE | AMOUNT_VISIBLE)
+ . = ..()
+
+/obj/structure/custom_keg/examine(mob/user)
+ . = ..()
+ . += "It is currently [open?"open, letting you pour liquids in.":"closed, letting you draw liquids from the tap."]"
+
+/obj/structure/custom_keg/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+ open = !open
+ if(open)
+ DISABLE_BITFIELD(reagents.reagents_holder_flags, DRAINABLE)
+ ENABLE_BITFIELD(reagents.reagents_holder_flags, REFILLABLE)
+ to_chat(user, "You open [src], letting you fill it.")
+ else
+ DISABLE_BITFIELD(reagents.reagents_holder_flags, REFILLABLE)
+ ENABLE_BITFIELD(reagents.reagents_holder_flags, DRAINABLE)
+ to_chat(user, "You close [src], letting you draw from its tap.")
+ update_icon()
+
+/obj/structure/custom_keg/update_icon_state()
+ if(open)
+ icon_state = "keg_open"
+ else
+ icon_state = "keg"
diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm
index aca727ad8d..fa7decc437 100644
--- a/code/modules/hydroponics/hydroponics.dm
+++ b/code/modules/hydroponics/hydroponics.dm
@@ -391,6 +391,7 @@
mutate(4, 10, 2, 4, 50, 4, 10, 3)
/obj/machinery/hydroponics/proc/mutatespecie() // Mutagent produced a new plant!
+ set waitfor = FALSE
if(!myseed || dead)
return
diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm
index 6cba540ca0..1adc951447 100644
--- a/code/modules/mining/machine_redemption.dm
+++ b/code/modules/mining/machine_redemption.dm
@@ -145,8 +145,11 @@
D.createmessage("Ore Redemption Machine", "New minerals available!", msg, 1, 0)
/obj/machinery/mineral/ore_redemption/process()
- if(!materials.mat_container || panel_open || !powered())
- return
+ if(materials.mat_container && !panel_open && powered())
+ process_all_ores()
+
+/obj/machinery/mineral/ore_redemption/proc/process_all_ores()
+ set waitfor = FALSE
var/atom/input = get_step(src, input_dir)
var/obj/structure/ore_box/OB = locate() in input
if(OB)
@@ -165,6 +168,7 @@
else if(!message_sent)
send_console_message()
+
/obj/machinery/mineral/ore_redemption/attackby(obj/item/W, mob/user, params)
if(default_unfasten_wrench(user, W))
return
diff --git a/code/modules/mining/machine_unloading.dm b/code/modules/mining/machine_unloading.dm
index dc7caa12c8..b39b0df6ab 100644
--- a/code/modules/mining/machine_unloading.dm
+++ b/code/modules/mining/machine_unloading.dm
@@ -10,22 +10,25 @@
output_dir = EAST
speed_process = TRUE
-/obj/machinery/mineral/unloading_machine/process()
- var/turf/T = get_step(src,input_dir)
- if(T)
- var/limit
- for(var/obj/structure/ore_box/B in T)
- for (var/obj/item/stack/ore/O in B)
- B.contents -= O
- unload_mineral(O)
- limit++
- if (limit>=10)
- return
- CHECK_TICK
- CHECK_TICK
- for(var/obj/item/I in T)
- unload_mineral(I)
+/obj/machinery/mineral/unloading_machine/proc/horrible_quadratic_monster(var/turf/T)
+ set waitfor = FALSE
+ var/limit = 0
+ for(var/obj/structure/ore_box/B in T)
+ for (var/obj/item/stack/ore/O in B)
+ B.contents -= O
+ unload_mineral(O)
limit++
if (limit>=10)
return
CHECK_TICK
+ for(var/obj/item/I in T)
+ unload_mineral(I)
+ limit++
+ if (limit>=10)
+ return
+ CHECK_TICK
+
+/obj/machinery/mineral/unloading_machine/process()
+ var/turf/T = get_step(src,input_dir)
+ if(T)
+ horrible_quadratic_monster(T)
diff --git a/code/modules/mining/mint.dm b/code/modules/mining/mint.dm
index 2a8e0f2516..f8a4ba4a72 100644
--- a/code/modules/mining/mint.dm
+++ b/code/modules/mining/mint.dm
@@ -64,8 +64,6 @@
if(materials.use_amount_mat(coin_mat, chosen))
for(var/coin_to_make in 1 to 5)
create_coins()
- produced_coins++
- CHECK_TICK
else
var/found_new = FALSE
for(var/datum/material/inserted_material in materials.materials)
@@ -131,6 +129,7 @@
return TRUE
/obj/machinery/mineral/mint/proc/create_coins()
+ set waitfor = FALSE
var/turf/T = get_step(src,output_dir)
var/temp_list = list()
temp_list[chosen] = 400
@@ -143,3 +142,5 @@
O.forceMove(bag_to_use) //don't bother sending the signal, the new bag is empty and all that.
SSblackbox.record_feedback("amount", "coins_minted", 1)
+ produced_coins++
+ CHECK_TICK
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/tails.dm b/code/modules/mob/dead/new_player/sprite_accessories/tails.dm
index e17dc43950..3834eb9231 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/tails.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/tails.dm
@@ -679,7 +679,7 @@
icon_state = "crow"
matrixed_sections = MATRIX_RED
-/datum/sprite_accessory/tails/mam_tail/cow
+/datum/sprite_accessory/tails/mam_tails/cow
name = "Cow"
icon_state = "cow"
matrixed_sections = MATRIX_RED
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index e4d6f5253e..44379660b6 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -358,7 +358,7 @@
return
I.item_flags |= BEING_REMOVED
breakouttime = I.breakouttime
- var/datum/cuffbreak_checker/cuffbreak_checker = new(get_turf(src))
+ var/datum/cuffbreak_checker/cuffbreak_checker = new(get_turf(src), istype(I, /obj/item/restraints)? I : null)
if(!cuff_break)
visible_message("[src] attempts to remove [I]!")
to_chat(src, "You attempt to remove [I]... (This will take around [DisplayTimeText(breakouttime)] and you need to stand still.)")
@@ -384,16 +384,22 @@
/datum/cuffbreak_checker
var/turf/last
+ var/obj/item/restraints/cuffs
-/datum/cuffbreak_checker/New(turf/initial_turf)
+/datum/cuffbreak_checker/New(turf/initial_turf, obj/item/restraints/R)
last = initial_turf
+ if(R)
+ cuffs = R
/datum/cuffbreak_checker/proc/check_movement(atom/user, delay, atom/target, time_left, do_after_flags, required_mobility_flags, required_combat_flags, mob_redirect, stage, initially_held_item, tool, list/passed_in)
if(get_turf(user) != last)
last = get_turf(user)
passed_in[1] = 0.5
+ if(cuffs && !cuffs.allow_breakout_movement)
+ return DO_AFTER_STOP
else
passed_in[1] = 1
+ return DO_AFTER_CONTINUE
/mob/living/carbon/proc/uncuff()
if (handcuffed)
@@ -961,7 +967,9 @@
/mob/living/carbon/ExtinguishMob()
for(var/X in get_equipped_items())
var/obj/item/I = X
- I.acid_level = 0 //washes off the acid on our clothes
+ var/datum/component/acid/acid = I.GetComponent(/datum/component/acid)
+ if(acid)
+ acid.level = 0
I.extinguish() //extinguishes our clothes
..()
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index a0088ead04..65bcddf0ad 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1101,9 +1101,9 @@
if(HAS_TRAIT(src, TRAIT_TOXINLOVER))
return ""
if(isplasmaman(src))
- return ""
if(isgolem(src))
- return ""
return ""
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 6f1fe57df3..de934318b3 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -15,7 +15,6 @@
block_parry_data = /datum/block_parry_data/unarmed/human
default_block_parry_data = /datum/block_parry_data/unarmed/human
- causes_dirt_buildup_on_floor = TRUE
//Hair colour and style
var/hair_color = "000"
@@ -52,6 +51,9 @@
var/obj/item/l_store = null
var/obj/item/s_store = null
+ /// When an braindead player has their equipment fiddled with, we log that info here for when they come back so they know who took their ID while they were DC'd for 30 seconds
+ var/list/afk_thefts
+
var/special_voice = "" // For changing our voice. Used by a symptom.
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index 1619d0f6de..54d6771c6c 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -90,13 +90,31 @@
//End bloody footprints
S.step_action()
+ if(movement_type & GROUND)
+ dirt_buildup()
/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) //Temporary laziness thing. Will change to handles by species reee.
if(dna.species.space_move(src))
return TRUE
return ..()
-/mob/living/carbon/human/dirt_buildup(strength)
+/mob/living/carbon/human/proc/dirt_buildup(strength = 1)
if(!shoes || !(shoes.body_parts_covered & FEET))
return // barefoot advantage
- return ..()
+ var/turf/open/T = loc
+ if(!istype(T) || !T.dirt_buildup_allowed)
+ return
+ var/area/A = T.loc
+ if(!A.dirt_buildup_allowed)
+ return
+ var/multiplier = CONFIG_GET(number/turf_dirty_multiplier)
+ strength *= multiplier
+ var/obj/effect/decal/cleanable/dirt/D = locate() in T
+ if(D)
+ D.dirty(strength)
+ else
+ T.dirtyness += strength
+ if(T.dirtyness >= (isnull(T.dirt_spawn_threshold)? CONFIG_GET(number/turf_dirt_threshold) : T.dirt_spawn_threshold))
+ D = new /obj/effect/decal/cleanable/dirt(T)
+ D.dirty(T.dirt_spawn_threshold - T.dirtyness)
+ T.dirtyness = 0 // reset.
diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/login.dm
index a89921143a..ebf76eeafa 100644
--- a/code/modules/mob/living/carbon/human/login.dm
+++ b/code/modules/mob/living/carbon/human/login.dm
@@ -2,3 +2,33 @@
..()
if(dna?.species?.has_field_of_vision && CONFIG_GET(flag/use_field_of_vision))
LoadComponent(/datum/component/field_of_vision, field_of_vision_type)
+
+ if(!LAZYLEN(afk_thefts))
+ return
+
+ var/list/print_msg = list()
+ print_msg += "*---------*"
+ print_msg += "As you snap back to consciousness, you recall people messing with your stuff..."
+
+ afk_thefts = reverseRange(afk_thefts)
+
+ for(var/list/iter_theft as anything in afk_thefts)
+ if(!islist(iter_theft) || LAZYLEN(iter_theft) != AFK_THEFT_TIME)
+ stack_trace("[src] ([ckey]) returned to their body and had a null/malformed afk_theft entry. Contents: [json_encode(iter_theft)]")
+ continue
+
+ var/thief_name = iter_theft[AFK_THEFT_NAME]
+ var/theft_message = iter_theft[AFK_THEFT_MESSAGE]
+ var/time_since = world.time - iter_theft[AFK_THEFT_TIME]
+
+ if(time_since > AFK_THEFT_FORGET_DETAILS_TIME)
+ print_msg += "\tSomeone [theft_message], but it was at least [DisplayTimeText(AFK_THEFT_FORGET_DETAILS_TIME)] ago."
+ else
+ print_msg += "\t[thief_name] [theft_message] roughly [DisplayTimeText(time_since, 10)] ago."
+
+ if(LAZYLEN(afk_thefts) >= AFK_THEFT_MAX_MESSAGES)
+ print_msg += "There may have been more, but that's all you can remember..."
+ print_msg += "*---------*"
+
+ to_chat(src, print_msg.Join("\n"))
+ LAZYNULL(afk_thefts)
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 0b12f3884e..f42661ca47 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -1,6 +1,6 @@
/mob/living/carbon/BiologicalLife(seconds, times_fired)
//Reagent processing needs to come before breathing, to prevent edge cases.
- handle_organs()
+ handle_organs(seconds, times_fired)
. = ..() // if . is false, we are dead.
if(stat == DEAD)
stop_sound_channel(CHANNEL_HEARTBEAT)
@@ -23,7 +23,7 @@
handle_brain_damage()
if(stat != DEAD)
- handle_liver()
+ handle_liver(seconds, times_fired)
if(stat != DEAD)
handle_corruption()
@@ -378,25 +378,25 @@
/mob/living/carbon/proc/handle_blood()
return
-/mob/living/carbon/proc/handle_bodyparts()
+/mob/living/carbon/proc/handle_bodyparts(seconds, times_fired)
for(var/I in bodyparts)
var/obj/item/bodypart/BP = I
if(BP.needs_processing)
- . |= BP.on_life()
+ . |= BP.on_life(seconds, times_fired)
-/mob/living/carbon/proc/handle_organs()
+/mob/living/carbon/proc/handle_organs(seconds, times_fired)
if(stat != DEAD)
for(var/V in internal_organs)
var/obj/item/organ/O = V
if(O)
- O.on_life()
+ O.on_life(seconds, times_fired)
else
if(reagents.has_reagent(/datum/reagent/toxin/formaldehyde, 1) || reagents.has_reagent(/datum/reagent/preservahyde, 1)) // No organ decay if the body contains formaldehyde. Or preservahyde.
return
for(var/V in internal_organs)
var/obj/item/organ/O = V
if(O)
- O.on_death() //Needed so organs decay while inside the body.
+ O.on_death(seconds, times_fired) //Needed so organs decay while inside the body.
/mob/living/carbon/handle_diseases()
for(var/thing in diseases)
@@ -687,16 +687,16 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
//LIVER//
/////////
-/mob/living/carbon/proc/handle_liver()
+/mob/living/carbon/proc/handle_liver(seconds, times_fired)
var/obj/item/organ/liver/liver = getorganslot(ORGAN_SLOT_LIVER)
if((!dna && !liver) || (NOLIVER in dna.species.species_traits))
return
if(!liver || liver.organ_flags & ORGAN_FAILING)
- liver_failure()
+ liver_failure(seconds, times_fired)
-/mob/living/carbon/proc/liver_failure()
+/mob/living/carbon/proc/liver_failure(seconds, times_fired)
reagents.end_metabolization(src, keep_liverless = TRUE) //Stops trait-based effects on reagents, to prevent permanent buffs
- reagents.metabolize(src, can_overdose=FALSE, liverless = TRUE)
+ reagents.metabolize(src, seconds, times_fired, can_overdose=FALSE, liverless = TRUE)
if(HAS_TRAIT(src, TRAIT_STABLELIVER))
return
adjustToxLoss(4, TRUE, TRUE)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index b0d340eed0..a3e6b28fd6 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -911,6 +911,12 @@
"[src] tries to remove your [what.name].", target = src,
target_message = "You try to remove [who]'s [what.name].")
what.add_fingerprint(src)
+ if(ishuman(who))
+ var/mob/living/carbon/human/victim_human = who
+ if(victim_human.key && !victim_human.client) // AKA braindead
+ if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
+ var/list/new_entry = list(list(src.name, "tried unequipping your [what]", world.time))
+ LAZYADD(victim_human.afk_thefts, new_entry)
else
to_chat(src,"You try to remove [who]'s [what.name].")
what.add_fingerprint(src)
@@ -957,6 +963,13 @@
to_chat(src, "\The [what.name] doesn't fit in that place!")
return
+ if(ishuman(who))
+ var/mob/living/carbon/human/victim_human = who
+ if(victim_human.key && !victim_human.client) // AKA braindead
+ if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
+ var/list/new_entry = list(list(src.name, "tried equipping you with [what]", world.time))
+ LAZYADD(victim_human.afk_thefts, new_entry)
+
who.visible_message("[src] tries to put [what] on [who].",
"[src] tries to put [what] on you.", target = src,
target_message = "You try to put [what] on [who].")
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 3b53eec64f..a76fbe4c4e 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -67,8 +67,6 @@
//Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects.
var/incorporeal_move = FALSE //FALSE is off, INCORPOREAL_MOVE_BASIC is normal, INCORPOREAL_MOVE_SHADOW is for ninjas
//and INCORPOREAL_MOVE_JAUNT is blocked by holy water/salt
- /// Do we make floors dirty as we move?
- var/causes_dirt_buildup_on_floor = FALSE
var/list/roundstart_quirks = list()
diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm
index bafa38ec5e..07b40b3ab1 100644
--- a/code/modules/mob/living/living_movement.dm
+++ b/code/modules/mob/living/living_movement.dm
@@ -102,31 +102,6 @@
if(lying && !buckled && prob(getBruteLoss()*200/maxHealth))
makeTrail(newloc, T, old_direction)
- if(causes_dirt_buildup_on_floor && (movement_type & GROUND))
- dirt_buildup()
-
-/**
- * Attempts to make the floor dirty.
- */
-/mob/living/proc/dirt_buildup(strength = 1)
- var/turf/open/T = loc
- if(!istype(T) || !T.dirt_buildup_allowed)
- return
- var/area/A = T.loc
- if(!A.dirt_buildup_allowed)
- return
- var/multiplier = CONFIG_GET(number/turf_dirty_multiplier)
- strength *= multiplier
- var/obj/effect/decal/cleanable/dirt/D = locate() in T
- if(D)
- D.dirty(strength)
- else
- T.dirtyness += strength
- if(T.dirtyness >= (isnull(T.dirt_spawn_threshold)? CONFIG_GET(number/turf_dirt_threshold) : T.dirt_spawn_threshold))
- D = new /obj/effect/decal/cleanable/dirt(T)
- D.dirty(T.dirt_spawn_threshold - T.dirtyness)
- T.dirtyness = 0 // reset.
-
/mob/living/Move_Pulled(atom/A)
. = ..()
if(!. || !isliving(A))
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index ce6a5dcda1..1f582b68bf 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -182,6 +182,7 @@
. = ..()
/mob/living/silicon/ai/proc/set_core_display_icon(input, client/C)
+ set waitfor = FALSE
if(client && !C)
C = client
if(!input && !C?.prefs?.preferred_ai_core_display)
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 47f9a794cf..8a400ad02d 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -966,7 +966,8 @@
upgrades.Cut()
- speed = 0
+ vtec = 0
+ vtec_disabled = FALSE
ionpulse = FALSE
revert_shell()
diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm
index 36f291bf36..5342638c03 100644
--- a/code/modules/mob/living/silicon/robot/robot_defense.dm
+++ b/code/modules/mob/living/silicon/robot/robot_defense.dm
@@ -82,6 +82,18 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real
if(!opened)
return ..()
+/mob/living/silicon/robot/disarm_shove(mob/living/carbon/human/H)
+ visible_message(span_danger("[src]'s motors grind as they are shoved by [H]!"))
+ vtec_disable(10 SECONDS)
+
+/mob/living/silicon/robot/proc/vtec_disable(time)
+ var/datum/status_effect/vtec_disabled/V = has_status_effect(/datum/status_effect/vtec_disabled)
+ if(V)
+ V.duration = max(V.duration, world.time + time)
+ else
+ apply_status_effect(/datum/status_effect/vtec_disabled, time)
+ update_movespeed()
+
/mob/living/silicon/robot/fire_act()
if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them
IgniteMob()
diff --git a/code/modules/mob/living/silicon/robot/robot_defines.dm b/code/modules/mob/living/silicon/robot/robot_defines.dm
index fe22ec1236..bf3bdcf707 100644
--- a/code/modules/mob/living/silicon/robot/robot_defines.dm
+++ b/code/modules/mob/living/silicon/robot/robot_defines.dm
@@ -61,7 +61,9 @@
var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list(), "Burglar"=list())
- var/speed = 0 // VTEC speed boost.
+ var/vtec = 0 // VTEC speed boost.
+ /// vtec shorted out
+ var/vtec_disabled = FALSE
var/magpulse = FALSE // Magboot-like effect.
var/ionpulse = FALSE // Jetpack-like effect.
var/ionpulse_on = FALSE // Jetpack-like effect.
diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm
index e3a640bca0..23500688ae 100644
--- a/code/modules/mob/living/silicon/robot/robot_movement.dm
+++ b/code/modules/mob/living/silicon/robot/robot_movement.dm
@@ -23,4 +23,4 @@
. = ..()
if(!resting && !(combat_flags & COMBAT_FLAG_SPRINT_ACTIVE))
. += 1
- . += speed
+ . += vtec_disabled? 0 : vtec
diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm
index 3377bf9601..fbd4daa1d3 100644
--- a/code/modules/mob/living/silicon/silicon_defense.dm
+++ b/code/modules/mob/living/silicon/silicon_defense.dm
@@ -79,6 +79,8 @@
M.visible_message("[M] pets [src].", \
"You pet [src].", target = src,
target_message = "[M] pets you.")
+ if(INTENT_DISARM)
+ disarm_shove(M)
if(INTENT_GRAB)
grabbedby(M)
else
@@ -88,6 +90,9 @@
"[M] punches you, but doesn't leave a dent.", null, COMBAT_MESSAGE_RANGE, null, M,
"You punch [src], but don't leave a dent.")
+/mob/living/silicon/proc/disarm_shove(mob/living/carbon/human/H)
+ visible_message(span_danger("[H] shoves [src], but doesn't manage to make much of an effect."))
+
/mob/living/silicon/attack_drone(mob/living/simple_animal/drone/M)
if(M.a_intent == INTENT_HARM)
return
diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm
index 98700ffaf0..1b0d210d9c 100644
--- a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm
@@ -133,6 +133,10 @@
chance_to_hold_onto_points = highest_cost*0.5
if(points != max_points && prob(chance_to_hold_onto_points))
return //Let's save our points for a better ability (unless we're at max points, in which case we can't save anymore!)
+ do_ability()
+
+/datum/boss_active_timed_battle/proc/do_ability()
+ set waitfor = FALSE
if(!boss.client)
abilities = shuffle(abilities)
for(var/ab in abilities)
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 95f8f2acc1..01a30bb90a 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -364,11 +364,10 @@
/mob/living/simple_animal/hostile/proc/AttackingTarget()
SEND_SIGNAL(src, COMSIG_HOSTILE_ATTACKINGTARGET, target)
in_melee = TRUE
- /* sorry for the simplemob vore fans
if(vore_active)
if(isliving(target))
var/mob/living/L = target
- if(!client && L.Adjacent(src) && CHECK_BITFIELD(L.vore_flags,DEVOURABLE)) // aggressive check to ensure vore attacks can be made
+ if(!client && L.Adjacent(src) && CHECK_BITFIELD(L.vore_flags, DEVOURABLE) && CHECK_BITFIELD(L.vore_flags, MOBVORE)) // aggressive check to ensure vore attacks can be made
if(prob(voracious_chance))
vore_attack(src,L,src)
else
@@ -379,7 +378,6 @@
return target.attack_animal(src)
else
return target.attack_animal(src)
- */
return target.attack_animal(src)
/mob/living/simple_animal/hostile/proc/Aggro()
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
index f2ece50af2..24e595ef7e 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
@@ -102,23 +102,13 @@
consume_bait()
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/proc/consume_bait()
- var/list/L = list()
- for(var/obj/O in view(src, 9))
- L += O
- var/obj/item/stack/ore/diamond/diamonds = locate(/obj/item/stack/ore/diamond) in L
- if(diamonds)
- var/distanced = 0
- distanced = get_dist(loc,diamonds.loc)
- if(distanced <= 1 && diamonds)
- qdel(diamonds)
- src.visible_message("[src] consumes [diamonds], and it disappears! ...At least, you think.")
- var/obj/item/pen/survival/bait = locate(/obj/item/pen/survival) in L
- if(bait)
- var/distanceb = 0
- distanceb = get_dist(loc,bait.loc)
- if(distanceb <= 1 && bait)
- qdel(bait)
- visible_message("[src] examines [bait] closer, and telekinetically shatters the pen.")
+ for(var/obj/O in view(1, src))
+ if(istype(O, /obj/item/stack/ore/diamond))
+ qdel(O)
+ src.visible_message("[src] consumes [O], and it disappears! ...At least, you think.")
+ else if(istype(O, /obj/item/pen/survival))
+ qdel(O)
+ src.visible_message("[src] examines [O] closer, and telekinetically shatters the pen.")
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/random/Initialize()
. = ..()
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 2af68eab46..f7d8a810ce 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -95,7 +95,7 @@
. = ..()
if((direction & (direction - 1)) && mob.loc == n) //moved diagonally successfully
- add_delay *= 2
+ add_delay *= SQRT_2
mob.set_glide_size(DELAY_TO_GLIDE_SIZE(add_delay), FALSE)
move_delay += add_delay
if(.) // If mob is null here, we deserve the runtime
diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm
index 131a098258..64c99e01bf 100644
--- a/code/modules/modular_computers/computers/item/computer.dm
+++ b/code/modules/modular_computers/computers/item/computer.dm
@@ -349,6 +349,7 @@
// Relays kill program request to currently active program. Use this to quit current program.
/obj/item/modular_computer/proc/kill_program(forced = FALSE)
+ set waitfor = FALSE
if(active_program)
active_program.kill_program(forced)
active_program = null
diff --git a/code/modules/movespeed/modifiers/reagents.dm b/code/modules/movespeed/modifiers/reagents.dm
index 1a03e8a602..ca0a74d749 100644
--- a/code/modules/movespeed/modifiers/reagents.dm
+++ b/code/modules/movespeed/modifiers/reagents.dm
@@ -2,17 +2,53 @@
blacklisted_movetypes = (FLYING|FLOATING)
/datum/movespeed_modifier/reagent/stimulants
- multiplicative_slowdown = -0.5
+ multiplicative_slowdown = -0.55
+
+/datum/movespeed_modifier/reagent/ephedrine
+ // strong painkiller effect that caps out at slightly above runspeed
+ multiplicative_slowdown = -1.5
+ priority = -100
+ complex_calculation = TRUE
+ absolute_max_tiles_per_second = 7
+
+/datum/movespeed_modifier/reagent/pepperspray
+ multiplicative_slowdown = 0.25
+
+/datum/movespeed_modifier/reagent/monkey_energy
+ multiplicative_slowdown = -0.35
/datum/movespeed_modifier/reagent/changelinghaste
- multiplicative_slowdown = -2
+ // extremely strong painkiller effect: allows user to run at old sprint speeds but not over by cancelling out slowdowns.
+ // however, will not make user go faster than that
+ multiplicative_slowdown = -4
+ priority = -100
+ complex_calculation = TRUE
+ absolute_max_tiles_per_second = 8
+
+/datum/movespeed_modifier/reagent/methamphetamine
+ // very strong painkiller effect that caps out at slightly above runspeed
+ multiplicative_slowdown = -2.5
+ priority = -100
+ complex_calculation = TRUE
+ absolute_max_tiles_per_second = 7.5
+
+/datum/movespeed_modifier/reagent/nitryl
+ multiplicative_slowdown = -0.65
+
+/datum/movespeed_modifier/reagent/freon
+ multiplicative_slowdown = 1.6
+
+/datum/movespeed_modifier/reagent/halon
+ multiplicative_slowdown = 1.8
+
+/datum/movespeed_modifier/reagent/lenturi
+ multiplicative_slowdown = 1.5
+
+/datum/movespeed_modifier/reagent/nuka_cola
+ multiplicative_slowdown = -0.35
+
+/datum/movespeed_modifier/reagent/nooartrium
+ multiplicative_slowdown = 2
/datum/movespeed_modifier/reagent/skooma
multiplicative_slowdown = -1
-
-/datum/movespeed_modifier/reagent/nitryl
- multiplicative_slowdown = -1
-
-/datum/movespeed_modifier/reagent/meth
- multiplicative_slowdown = -0.5
- absolute_max_tiles_per_second = 11
diff --git a/code/modules/movespeed/modifiers/status_effects.dm b/code/modules/movespeed/modifiers/status_effects.dm
index 1adfe8b4be..260ee17c21 100644
--- a/code/modules/movespeed/modifiers/status_effects.dm
+++ b/code/modules/movespeed/modifiers/status_effects.dm
@@ -51,3 +51,11 @@
/datum/movespeed_modifier/status_effect/off_balance
variable = TRUE
+
+/datum/movespeed_modifier/status_effect/slime/light_pink
+ // decently good painkiller + speedup effect
+ blacklisted_movetypes = FLYING | FLOATING
+ priority = -150 // someday we really need to make these defines lmao
+ multiplicative_slowdown = -2
+ complex_calculation = TRUE
+ absolute_max_tiles_per_second = 7
diff --git a/code/modules/ninja/suit/suit.dm b/code/modules/ninja/suit/suit.dm
index ed711771bf..15071a186f 100644
--- a/code/modules/ninja/suit/suit.dm
+++ b/code/modules/ninja/suit/suit.dm
@@ -77,6 +77,11 @@ Contents:
cell.name = "black power cell"
cell.icon_state = "bscell"
+/obj/item/clothing/suit/space/space_ninja/Destroy()
+ if(affecting)
+ unlock_suit()
+ return ..()
+
//Simply deletes all the attachments and self, killing all related procs.
/obj/item/clothing/suit/space/space_ninja/proc/terminate()
qdel(n_hood)
@@ -84,7 +89,6 @@ Contents:
qdel(n_shoes)
qdel(src)
-
//Randomizes suit parameters.
/obj/item/clothing/suit/space/space_ninja/proc/randomize_param()
s_cost = rand(1,20)
@@ -93,7 +97,6 @@ Contents:
s_bombs = rand(5,20)
a_boost = rand(1,7)
-
//This proc prevents the suit from being taken off.
/obj/item/clothing/suit/space/space_ninja/proc/lock_suit(mob/living/carbon/human/H)
if(!istype(H))
@@ -113,14 +116,14 @@ Contents:
return FALSE
affecting = H
ADD_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT) //colons make me go all |=
- slowdown = 0
n_hood = H.head
ADD_TRAIT(n_hood, TRAIT_NODROP, NINJA_SUIT_TRAIT)
n_shoes = H.shoes
ADD_TRAIT(n_shoes, TRAIT_NODROP, NINJA_SUIT_TRAIT)
- n_shoes.slowdown -= 0.5
+ n_shoes.slowdown = -0.25
n_gloves = H.gloves
ADD_TRAIT(n_gloves, TRAIT_NODROP, NINJA_SUIT_TRAIT)
+ ADD_TRAIT(affecting, TRAIT_TASED_RESISTANCE, NINJA_SUIT_TRAIT)
return TRUE
/obj/item/clothing/suit/space/space_ninja/proc/lockIcons(mob/living/carbon/human/H)
@@ -133,19 +136,19 @@ Contents:
/obj/item/clothing/suit/space/space_ninja/proc/unlock_suit()
affecting = null
REMOVE_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT)
- slowdown = 1
icon_state = "s-ninja"
if(n_hood)//Should be attached, might not be attached.
REMOVE_TRAIT(n_hood, TRAIT_NODROP, NINJA_SUIT_TRAIT)
if(n_shoes)
REMOVE_TRAIT(n_shoes, TRAIT_NODROP, NINJA_SUIT_TRAIT)
- n_shoes.slowdown += 0.5
+ n_shoes.slowdown = 0.25
if(n_gloves)
n_gloves.icon_state = "s-ninja"
n_gloves.item_state = "s-ninja"
REMOVE_TRAIT(n_gloves, TRAIT_NODROP, NINJA_SUIT_TRAIT)
n_gloves.candrain=0
n_gloves.draining=0
+ REMOVE_TRAIT(affecting, TRAIT_TASED_RESISTANCE, NINJA_SUIT_TRAIT)
/obj/item/clothing/suit/space/space_ninja/examine(mob/user)
diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm
index b1e1ff2208..16317bf9a3 100644
--- a/code/modules/power/supermatter/supermatter.dm
+++ b/code/modules/power/supermatter/supermatter.dm
@@ -241,7 +241,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
///How much the bullets damage should be multiplied by when it is added to the internal variables
var/bullet_energy = 2
///How much hallucination should we produce per unit of power?
- var/hallucination_power = 0.1
+ var/hallucination_power = 0.05 // 2 seconds per second at a distance of 7 with a typical nitrogen setup
///Our internal radio
var/obj/item/radio/radio
@@ -648,6 +648,8 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
for(var/mob/living/carbon/human/l in fov_viewers(src, HALLUCINATION_RANGE(power))) // If they can see it without mesons on. Bad on them.
if(!istype(l.glasses, /obj/item/clothing/glasses/meson))
var/D = sqrt(1 / max(1, get_dist(l, src)))
+ if(!l.hallucination)
+ to_chat(l, "Looking at the supermatter unprotected gives you a headache...")
l.hallucination += power * hallucination_power * D
l.hallucination = clamp(l.hallucination, 0, 200)
for(var/mob/living/l in range(src, round((power / 100) ** 0.25)))
diff --git a/code/modules/projectiles/projectile/energy/stun.dm b/code/modules/projectiles/projectile/energy/stun.dm
index 6f272dab40..acec1ef94f 100644
--- a/code/modules/projectiles/projectile/energy/stun.dm
+++ b/code/modules/projectiles/projectile/energy/stun.dm
@@ -31,6 +31,11 @@
else if(tase_duration && (C.status_flags & CANKNOCKDOWN) && !HAS_TRAIT(C, TRAIT_STUNIMMUNE) && !HAS_TRAIT(C, TRAIT_TASED_RESISTANCE))
C.apply_status_effect(strong_tase? STATUS_EFFECT_TASED : STATUS_EFFECT_TASED_WEAK, tase_duration)
addtimer(CALLBACK(C, /mob/living/carbon.proc/do_jitter_animation, jitter), 5)
+ else if(iscyborg(target))
+ target.visible_message(span_danger("A shower of sparks emit from [target] on impact from [src]!"))
+ do_sparks(1, TRUE, target)
+ var/mob/living/silicon/robot/R = target
+ R.vtec_disable(10 SECONDS)
/obj/item/projectile/energy/electrode/on_range() //to ensure the bolt sparks when it reaches the end of its range if it didn't hit a target yet
do_sparks(1, TRUE, src)
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index fd6204a8e3..afad323a27 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -280,71 +280,114 @@
R.handle_reactions()
return amount
-/datum/reagents/proc/metabolize(mob/living/carbon/C, can_overdose = FALSE, liverless = FALSE)
+/**
+ * Triggers metabolizing for all the reagents in this holder
+ *
+ * Arguments:
+ * * mob/living/carbon/carbon - The mob to metabolize in, if null it uses [/datum/reagents/var/my_atom]
+ * * delta_time - the time in server seconds between proc calls (when performing normally it will be 2)
+ * * times_fired - the number of times the owner's life() tick has been called aka The number of times SSmobs has fired
+ * * can_overdose - Allows overdosing
+ * * liverless - Stops reagents that aren't set as [/datum/reagent/var/self_consuming] from metabolizing
+ */
+/datum/reagents/proc/metabolize(mob/living/carbon/owner, delta_time, times_fired, can_overdose = FALSE, liverless = FALSE)
var/list/cached_reagents = reagent_list
- var/list/cached_addictions = addiction_list
- if(C)
- expose_temperature(C.bodytemperature, 0.25)
- var/need_mob_update = 0
- for(var/reagent in cached_reagents)
- var/datum/reagent/R = reagent
- if(QDELETED(R.holder))
- continue
- if(liverless && !R.self_consuming) //need to be metabolized
- continue
- if(!C)
- C = R.holder.my_atom
- if(!R.metabolizing)
- R.metabolizing = TRUE
- R.on_mob_metabolize(C)
- if(C && R)
- if(C.reagent_check(R) != 1)
- if(can_overdose)
- if(R.overdose_threshold)
- if(R.volume > R.overdose_threshold && !R.overdosed)
- R.overdosed = 1
- var/turf/CT = get_turf(C)
- log_reagent("OVERDOSE START: [key_name(C)] at [AREACOORD(CT)] started overdosing on [R.volume] units of [R].")
- need_mob_update += R.overdose_start(C)
- if(R.addiction_threshold)
- if(R.volume > R.addiction_threshold && !is_type_in_list(R, cached_addictions))
- var/datum/reagent/new_reagent = new R.type()
- cached_addictions.Add(new_reagent)
- if(R.overdosed)
- need_mob_update += R.overdose_process(C)
- if(is_type_in_list(R,cached_addictions))
- for(var/addiction in cached_addictions)
- var/datum/reagent/A = addiction
- if(istype(R, A))
- A.addiction_stage = -15 // you're satisfied for a good while.
- need_mob_update += R.on_mob_life(C)
-
+ if(owner)
+ expose_temperature(owner.bodytemperature, 0.25)
+ var/need_mob_update = FALSE
+ for(var/datum/reagent/reagent as anything in cached_reagents)
+ need_mob_update += metabolize_reagent(owner, reagent, delta_time, times_fired, can_overdose, liverless)
if(can_overdose)
if(addiction_tick == 6)
addiction_tick = 1
- for(var/addiction in cached_addictions)
+ for(var/addiction in addiction_list)
var/datum/reagent/R = addiction
- if(C && R)
+ if(owner && R)
R.addiction_stage++
if(1 <= R.addiction_stage && R.addiction_stage <= R.addiction_stage1_end)
- need_mob_update += R.addiction_act_stage1(C)
+ need_mob_update += R.addiction_act_stage1(owner)
else if(R.addiction_stage1_end < R.addiction_stage && R.addiction_stage <= R.addiction_stage2_end)
- need_mob_update += R.addiction_act_stage2(C)
+ need_mob_update += R.addiction_act_stage2(owner)
else if(R.addiction_stage2_end < R.addiction_stage && R.addiction_stage <= R.addiction_stage3_end)
- need_mob_update += R.addiction_act_stage3(C)
+ need_mob_update += R.addiction_act_stage3(owner)
else if(R.addiction_stage3_end < R.addiction_stage && R.addiction_stage <= R.addiction_stage4_end)
- need_mob_update += R.addiction_act_stage4(C)
+ need_mob_update += R.addiction_act_stage4(owner)
else if(R.addiction_stage4_end < R.addiction_stage)
remove_addiction(R)
else
- SEND_SIGNAL(C, COMSIG_CLEAR_MOOD_EVENT, "[R.type]_overdose")
+ SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "[R.type]_overdose")
addiction_tick++
- if(C && need_mob_update) //some of the metabolized reagents had effects on the mob that requires some updates.
- C.updatehealth()
- C.update_mobility()
- C.update_stamina()
+ if(owner && need_mob_update) //some of the metabolized reagents had effects on the mob that requires some updates.
+ owner.updatehealth()
+ owner.update_mobility()
+ owner.update_stamina()
update_total()
+/*
+ * Metabolises a single reagent for a target owner carbon mob. See above.
+ *
+ * Arguments:
+ * * mob/living/carbon/owner - The mob to metabolize in, if null it uses [/datum/reagents/var/my_atom]
+ * * delta_time - the time in server seconds between proc calls (when performing normally it will be 2)
+ * * times_fired - the number of times the owner's life() tick has been called aka The number of times SSmobs has fired
+ * * can_overdose - Allows overdosing
+ * * liverless - Stops reagents that aren't set as [/datum/reagent/var/self_consuming] from metabolizing
+ */
+/datum/reagents/proc/metabolize_reagent(mob/living/carbon/owner, datum/reagent/reagent, delta_time, times_fired, can_overdose = FALSE, liverless = FALSE)
+ var/need_mob_update = FALSE
+ if(QDELETED(reagent.holder))
+ return FALSE
+
+ if(!owner)
+ owner = reagent.holder.my_atom
+
+ if(owner && reagent)
+ if(!owner.reagent_check(reagent, delta_time, times_fired) != TRUE)
+ return
+ if(liverless && !reagent.self_consuming) //need to be metabolized
+ return
+ if(!reagent.metabolizing)
+ reagent.metabolizing = TRUE
+ reagent.on_mob_metabolize(owner)
+ if(can_overdose)
+ if(reagent.overdose_threshold)
+ if(reagent.volume >= reagent.overdose_threshold && !reagent.overdosed)
+ reagent.overdosed = TRUE
+ need_mob_update += reagent.overdose_start(owner)
+ log_game("[key_name(owner)] has started overdosing on [reagent.name] at [reagent.volume] units.")
+
+ // for(var/addiction in reagent.addiction_types)
+ // owner.mind?.add_addiction_points(addiction, reagent.addiction_types[addiction] * REAGENTS_METABOLISM)
+ if(reagent.addiction_threshold)
+ if(reagent.volume > reagent.addiction_threshold && !is_type_in_list(reagent, addiction_list))
+ var/datum/reagent/new_reagent = new reagent.type()
+ addiction_list.Add(new_reagent)
+ if(is_type_in_list(reagent, addiction_list))
+ for(var/addiction in addiction_list)
+ var/datum/reagent/A = addiction
+ if(istype(reagent, A))
+ A.addiction_stage = -15 // you're satisfied for a good while.
+
+ if(reagent.overdosed)
+ need_mob_update += reagent.overdose_process(owner, delta_time, times_fired)
+
+ need_mob_update += reagent.on_mob_life(owner, delta_time, times_fired)
+ return need_mob_update
+
+/// Signals that metabolization has stopped, triggering the end of trait-based effects
+/datum/reagents/proc/end_metabolization(mob/living/carbon/C, keep_liverless = TRUE)
+ var/list/cached_reagents = reagent_list
+ for(var/datum/reagent/reagent as anything in cached_reagents)
+ if(QDELETED(reagent.holder))
+ continue
+ if(keep_liverless && reagent.self_consuming) //Will keep working without a liver
+ continue
+ if(!C)
+ C = reagent.holder.my_atom
+ if(reagent.metabolizing)
+ reagent.metabolizing = FALSE
+ reagent.on_mob_end_metabolize(C)
+
/datum/reagents/proc/remove_addiction(datum/reagent/R)
to_chat(my_atom, "You feel like you've gotten over your need for [R.name].")
SEND_SIGNAL(my_atom, COMSIG_CLEAR_MOOD_EVENT, "[R.type]_overdose")
@@ -354,21 +397,6 @@
addiction_list.Remove(R)
qdel(R)
-//Signals that metabolization has stopped, triggering the end of trait-based effects
-/datum/reagents/proc/end_metabolization(mob/living/carbon/C, keep_liverless = TRUE)
- var/list/cached_reagents = reagent_list
- for(var/reagent in cached_reagents)
- var/datum/reagent/R = reagent
- if(QDELETED(R.holder))
- continue
- if(keep_liverless && R.self_consuming) //Will keep working without a liver
- continue
- if(!C)
- C = R.holder.my_atom
- if(R.metabolizing)
- R.metabolizing = FALSE
- R.on_mob_end_metabolize(C)
-
/datum/reagents/proc/conditional_update_move(atom/A, Running = 0)
var/list/cached_reagents = reagent_list
for(var/reagent in cached_reagents)
diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
index f4f5b90398..5059376954 100644
--- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
@@ -505,11 +505,11 @@
value = REAGENT_VALUE_COMMON
/datum/reagent/consumable/nuka_cola/on_mob_metabolize(mob/living/carbon/M)
- M.add_movespeed_modifier(/datum/movespeed_modifier/reagent/meth)
+ M.add_movespeed_modifier(/datum/movespeed_modifier/reagent/nuka_cola)
return ..()
/datum/reagent/consumable/nuka_cola/on_mob_end_metabolize(mob/living/carbon/M)
- M.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/meth)
+ M.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/nuka_cola)
return ..()
/datum/reagent/consumable/nuka_cola/on_mob_life(mob/living/carbon/M)
diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
index 96985514b5..ed80804f28 100644
--- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
@@ -164,62 +164,54 @@
/datum/reagent/drug/methamphetamine
name = "Methamphetamine"
- description = "Reduces stun times by about 300%, and allows the user to quickly recover stamina while dealing a small amount of Brain damage. If overdosed the subject will move randomly, laugh randomly, drop items and suffer from Toxin and Brain damage. If addicted the subject will constantly jitter and drool, before becoming dizzy and losing motor control and eventually suffer heavy toxin damage."
+ description = "Reduces stun times by about 300%, speeds the user up, and allows the user to quickly recover stamina while dealing a small amount of Brain damage. If overdosed the subject will move randomly, laugh randomly, drop items and suffer from Toxin and Brain damage. If addicted the subject will constantly jitter and drool, before becoming dizzy and losing motor control and eventually suffer heavy toxin damage."
reagent_state = LIQUID
color = "#FAFAFA"
overdose_threshold = 20
- addiction_threshold = 10
metabolization_rate = 0.75 * REAGENTS_METABOLISM
- var/brain_damage = TRUE
- var/jitter = TRUE
- var/confusion = TRUE
pH = 5
+ addiction_threshold = 10
value = REAGENT_VALUE_UNCOMMON
/datum/reagent/drug/methamphetamine/on_mob_metabolize(mob/living/L)
..()
- ADD_TRAIT(L, TRAIT_IGNOREDAMAGESLOWDOWN, type)
- L.update_movespeed()
- ADD_TRAIT(L, TRAIT_TASED_RESISTANCE, type)
- L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/meth)
+ L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/methamphetamine)
/datum/reagent/drug/methamphetamine/on_mob_end_metabolize(mob/living/L)
- REMOVE_TRAIT(L, TRAIT_IGNOREDAMAGESLOWDOWN, type)
- L.update_movespeed()
- REMOVE_TRAIT(L, TRAIT_TASED_RESISTANCE, type)
- L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/meth)
+ L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/methamphetamine)
..()
-/datum/reagent/drug/methamphetamine/on_mob_life(mob/living/carbon/M)
+/datum/reagent/drug/methamphetamine/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
var/high_message = pick("You feel hyper.", "You feel like you need to go faster.", "You feel like you can run the world.")
- if(prob(5))
- to_chat(M, "[high_message]")
- M.AdjustAllImmobility(-40, 0)
- M.AdjustUnconscious(-40, 0)
- M.adjustStaminaLoss(-7.5 * REM, 0)
- if(jitter)
- M.Jitter(2)
- if(brain_damage)
- M.adjustOrganLoss(ORGAN_SLOT_BRAIN, rand(1,4))
- M.heal_overall_damage(2, 2)
- if(prob(5))
+ if(DT_PROB(2.5, delta_time))
+ to_chat(M, span_notice("[high_message]"))
+ // SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "tweaking", /datum/mood_event/stimulant_medium, name)
+ M.AdjustStun(-40 * REM * delta_time)
+ M.AdjustKnockdown(-40 * REM * delta_time)
+ M.AdjustUnconscious(-40 * REM * delta_time)
+ M.AdjustParalyzed(-40 * REM * delta_time)
+ M.AdjustImmobilized(-40 * REM * delta_time)
+ M.adjustStaminaLoss(-2 * REM * delta_time, 0)
+ M.Jitter(2 * REM * delta_time)
+ M.adjustOrganLoss(ORGAN_SLOT_BRAIN, rand(1, 4) * REM * delta_time)
+ if(DT_PROB(2.5, delta_time))
M.emote(pick("twitch", "shiver"))
..()
- . = 1
+ . = TRUE
-/datum/reagent/drug/methamphetamine/overdose_process(mob/living/M)
+/datum/reagent/drug/methamphetamine/overdose_process(mob/living/M, delta_time, times_fired)
if(CHECK_MOBILITY(M, MOBILITY_MOVE) && !ismovable(M.loc))
- for(var/i in 1 to 4)
+ for(var/i in 1 to round(4 * REM * delta_time, 1))
step(M, pick(GLOB.cardinals))
- if(prob(20))
+ if(DT_PROB(10, delta_time))
M.emote("laugh")
- if(prob(33))
- M.visible_message("[M]'s hands flip out and flail everywhere!")
+ if(DT_PROB(18, delta_time))
+ M.visible_message(span_danger("[M]'s hands flip out and flail everywhere!"))
M.drop_all_held_items()
..()
- M.adjustToxLoss(1, 0)
- M.adjustOrganLoss(ORGAN_SLOT_BRAIN, pick(0.5, 0.6, 0.7, 0.8, 0.9, 1))
- . = 1
+ M.adjustToxLoss(1 * REM * delta_time, 0)
+ M.adjustOrganLoss(ORGAN_SLOT_BRAIN, (rand(5, 10) / 10) * REM * delta_time)
+ . = TRUE
/datum/reagent/drug/methamphetamine/addiction_act_stage1(mob/living/M)
M.Jitter(5)
@@ -256,14 +248,6 @@
..()
. = 1
-/datum/reagent/drug/methamphetamine/changeling
- name = "Changeling Adrenaline"
- addiction_threshold = 35
- overdose_threshold = 35
- jitter = FALSE
- brain_damage = FALSE
- value = REAGENT_VALUE_RARE
-
/datum/reagent/drug/bath_salts
name = "Bath Salts"
description = "Makes you impervious to stuns and grants a stamina regeneration buff, but you will be a nearly uncontrollable tramp-bearded raving lunatic."
diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm
index 90082c464b..a9bdff64b2 100644
--- a/code/modules/reagents/chemistry/reagents/food_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm
@@ -345,6 +345,8 @@
victim.confused = max(M.confused, 3)
victim.damageoverlaytemp = 60
victim.DefaultCombatKnockdown(80, override_hardstun = 0.1, override_stamdmg = min(reac_volume * 3, 15))
+ victim.add_movespeed_modifier(/datum/movespeed_modifier/reagent/pepperspray)
+ addtimer(CALLBACK(victim, /mob.proc/remove_movespeed_modifier, /datum/movespeed_modifier/reagent/pepperspray), 10 SECONDS)
return
else if ( eyes_covered ) // Eye cover is better than mouth cover
victim.blur_eyes(3)
@@ -358,6 +360,8 @@
victim.confused = max(M.confused, 6)
victim.damageoverlaytemp = 75
victim.DefaultCombatKnockdown(80, override_hardstun = 0.1, override_stamdmg = min(reac_volume * 5, 25))
+ victim.add_movespeed_modifier(/datum/movespeed_modifier/reagent/pepperspray)
+ addtimer(CALLBACK(victim, /mob.proc/remove_movespeed_modifier, /datum/movespeed_modifier/reagent/pepperspray), 10 SECONDS)
victim.update_damage_hud()
/datum/reagent/consumable/condensedcapsaicin/on_mob_life(mob/living/carbon/M)
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index 65443b65c7..fe843fff36 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -706,21 +706,42 @@
addiction_threshold = 30
pH = 12
-/datum/reagent/medicine/ephedrine/on_mob_life(mob/living/carbon/M)
- M.AdjustAllImmobility(-20, FALSE)
- M.AdjustUnconscious(-20, FALSE)
- M.adjustStaminaLoss(-4.5*REM, FALSE)
- M.Jitter(10)
- if(prob(50))
- M.confused = max(M.confused, 1)
+/datum/reagent/medicine/ephedrine/on_mob_metabolize(mob/living/L)
+ ..()
+ L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/ephedrine)
+ ADD_TRAIT(L, TRAIT_TASED_RESISTANCE, type)
+
+/datum/reagent/medicine/ephedrine/on_mob_end_metabolize(mob/living/L)
+ L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/ephedrine)
+ REMOVE_TRAIT(L, TRAIT_TASED_RESISTANCE, type)
+ ..()
+
+/datum/reagent/medicine/ephedrine/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
+ // if(DT_PROB(10 * (1-creation_purity), delta_time) && iscarbon(M))
+ // var/obj/item/I = M.get_active_held_item()
+ // if(I && M.dropItemToGround(I))
+ // to_chat(M, span_notice("Your hands spaz out and you drop what you were holding!"))
+ // M.Jitter(10)
+
+ M.AdjustAllImmobility(-20 * REM * delta_time)
+ M.adjustStaminaLoss(-1 * REM * delta_time, FALSE)
..()
return TRUE
-/datum/reagent/medicine/ephedrine/overdose_process(mob/living/M)
- if(prob(33))
- M.adjustToxLoss(0.5*REM, 0)
+/datum/reagent/medicine/ephedrine/overdose_process(mob/living/M, delta_time, times_fired)
+ if(DT_PROB(1, delta_time) && iscarbon(M))
+ var/datum/disease/D = new /datum/disease/heart_failure
+ M.ForceContractDisease(D)
+ to_chat(M, span_userdanger("You're pretty sure you just felt your heart stop for a second there.."))
+ M.playsound_local(M, 'sound/effects/singlebeat.ogg', 100, 0)
+
+ if(DT_PROB(3.5, delta_time))
+ to_chat(M, span_notice("[pick("Your head pounds.", "You feel a tight pain in your chest.", "You find it hard to stay still.", "You feel your heart practically beating out of your chest.")]"))
+
+ if(DT_PROB(18, delta_time))
+ M.adjustToxLoss(1, 0)
M.losebreath++
- . = 1
+ . = TRUE
return TRUE
/datum/reagent/medicine/ephedrine/addiction_act_stage1(mob/living/M)
@@ -981,7 +1002,7 @@
M.grab_ghost()
M.emote("gasp")
log_combat(M, M, "revived", src)
- var/list/policies = CONFIG_GET(keyed_list/policyconfig)
+ var/list/policies = CONFIG_GET(keyed_list/policy)
var/timelimit = CONFIG_GET(number/defib_cmd_time_limit) * 10 //the config is in seconds, not deciseconds
var/late = timelimit && (tplus > timelimit)
var/policy = late? policies[POLICYCONFIG_ON_DEFIB_LATE] : policies[POLICYCONFIG_ON_DEFIB_INTACT]
@@ -1415,37 +1436,42 @@
/datum/reagent/medicine/changelingadrenaline
name = "Changeling Adrenaline"
description = "Reduces the duration of unconciousness, knockdown and stuns. Restores stamina, but deals toxin damage when overdosed."
- color = "#918e53"
+ color = "#C1151D"
overdose_threshold = 30
value = REAGENT_VALUE_VERY_RARE
-/datum/reagent/medicine/changelingadrenaline/on_mob_metabolize(mob/living/L)
- ..()
- ADD_TRAIT(L, TRAIT_TASED_RESISTANCE, type)
-
-/datum/reagent/medicine/changelingadrenaline/on_mob_end_metabolize(mob/living/L)
- REMOVE_TRAIT(L, TRAIT_TASED_RESISTANCE, type)
- ..()
-
-/datum/reagent/medicine/changelingadrenaline/on_mob_life(mob/living/carbon/M as mob)
- M.AdjustUnconscious(-20, 0)
- M.AdjustAllImmobility(-20, 0)
- M.AdjustSleeping(-20, 0)
- M.adjustStaminaLoss(-30, 0)
+/datum/reagent/medicine/changelingadrenaline/on_mob_life(mob/living/carbon/metabolizer, delta_time, times_fired)
..()
+ metabolizer.AdjustAllImmobility(-20 * REM * delta_time)
+ metabolizer.adjustStaminaLoss(-10 * REM * delta_time, 0)
+ metabolizer.Jitter(10 * REM * delta_time)
+ metabolizer.Dizzy(10 * REM * delta_time)
return TRUE
-/datum/reagent/medicine/changelingadrenaline/overdose_process(mob/living/M as mob)
- M.adjustToxLoss(5, 0) //let's make this mildly more toxic because of the stamina buff
+/datum/reagent/medicine/changelingadrenaline/on_mob_metabolize(mob/living/L)
+ ..()
+ ADD_TRAIT(L, TRAIT_SLEEPIMMUNE, type)
+ ADD_TRAIT(L, TRAIT_TASED_RESISTANCE, type)
+ L.add_movespeed_mod_immunities(type, /datum/movespeed_modifier/damage_slowdown)
+
+/datum/reagent/medicine/changelingadrenaline/on_mob_end_metabolize(mob/living/L)
+ ..()
+ REMOVE_TRAIT(L, TRAIT_SLEEPIMMUNE, type)
+ REMOVE_TRAIT(L, TRAIT_TASED_RESISTANCE, type)
+ L.remove_movespeed_mod_immunities(type, /datum/movespeed_modifier/damage_slowdown)
+ L.Dizzy(0)
+ L.Jitter(0)
+
+/datum/reagent/medicine/changelingadrenaline/overdose_process(mob/living/metabolizer, delta_time, times_fired)
+ metabolizer.adjustToxLoss(1 * REM * delta_time, 0)
..()
return TRUE
/datum/reagent/medicine/changelinghaste
name = "Changeling Haste"
description = "Drastically increases movement speed, but deals toxin damage."
- color = "#669153"
- metabolization_rate = 1
- value = REAGENT_VALUE_VERY_RARE
+ color = "#AE151D"
+ metabolization_rate = 2.5 * REAGENTS_METABOLISM
/datum/reagent/medicine/changelinghaste/on_mob_metabolize(mob/living/L)
..()
@@ -1455,11 +1481,12 @@
L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/changelinghaste)
..()
-/datum/reagent/medicine/changelinghaste/on_mob_life(mob/living/carbon/M)
- M.adjustToxLoss(2, 0)
+/datum/reagent/medicine/changelinghaste/on_mob_life(mob/living/carbon/metabolizer, delta_time, times_fired)
+ metabolizer.adjustToxLoss(2 * REM * delta_time, 0)
..()
return TRUE
+
/datum/reagent/medicine/corazone
// Heart attack code will not do damage if corazone is present
// because it's SPACE MAGIC ASPIRIN
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 593d77f959..0c70f47c53 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -287,7 +287,9 @@
/datum/reagent/water/reaction_obj(obj/O, reac_volume)
O.extinguish()
- O.acid_level = 0
+ var/datum/component/acid/acid = O.GetComponent(/datum/component/acid)
+ if(acid)
+ acid.level = 0
// cubes
if(istype(O, /obj/item/reagent_containers/food/snacks/cube))
var/obj/item/reagent_containers/food/snacks/cube/cube = O
diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm
index 7df061c8aa..41c0ed717e 100644
--- a/code/modules/reagents/chemistry/recipes.dm
+++ b/code/modules/reagents/chemistry/recipes.dm
@@ -40,6 +40,7 @@
/datum/chemical_reaction/proc/on_reaction(datum/reagents/holder, multiplier, specialreact)
+ set waitfor = FALSE
return
//I recommend you set the result amount to the total volume of all components.
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index b90815d543..02c8a9802c 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -16,7 +16,7 @@
var/stream_mode = 0 //whether we use the more focused mode
var/current_range = 3 //the range of tiles the sprayer will reach.
var/spray_range = 3 //the range of tiles the sprayer will reach when in spray mode.
- var/stream_range = 1 //the range of tiles the sprayer will reach when in stream mode.
+ var/stream_range = 3 //the range of tiles the sprayer will reach when in stream mode.
var/stream_amount = 10 //the amount of reagents transfered when in stream mode.
/// Amount of time it takes for a spray to completely travel.
var/spray_delay = 8
@@ -74,19 +74,18 @@
return
var/range = clamp(get_dist(src, A), 1, current_range)
var/wait_step = CEILING(spray_delay * INVERSE(range), world.tick_lag)
- var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src), stream_mode, wait_step, range, stream_mode? 1 : range)
+ var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src), stream_mode, wait_step, range, stream_mode? 1 : range, amount_per_transfer_from_this)
var/turf/T = get_turf(src)
if(!T)
return
log_reagent("SPRAY: [key_name(usr)] fired [src] ([REF(src)]) [COORD(T)] at [A] ([REF(A)]) [COORD(A)] (chempuff: [D.reagents.log_list()])")
- D.create_reagents(amount_per_transfer_from_this, NONE, NO_REAGENTS_VALUE)
if(stream_mode)
reagents.trans_to(D, amount_per_transfer_from_this)
else
reagents.trans_to(D, amount_per_transfer_from_this, 1/range)
- D.color = mix_color_from_reagents(D.reagents.reagent_list)
+ D.add_atom_colour(mix_color_from_reagents(D.reagents.reagent_list), TEMPORARY_COLOUR_PRIORITY)
last_spray = world.time
- D.run_puff(A)
+ INVOKE_ASYNC(D, /obj/effect/decal/chempuff/proc/run_puff, A)
/obj/item/reagent_containers/spray/attack_self(mob/user)
stream_mode = !stream_mode
diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm
index aefb670dd3..e9c17ecc28 100644
--- a/code/modules/recycling/conveyor2.dm
+++ b/code/modules/recycling/conveyor2.dm
@@ -268,16 +268,19 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
// timed process
// if the switch changed, update the linked conveyors
-/obj/machinery/conveyor_switch/process()
- if(!operated)
- return
- operated = 0
-
+/obj/machinery/conveyor_switch/proc/do_process()
+ set waitfor = FALSE
for(var/obj/machinery/conveyor/C in GLOB.conveyors_by_id[id])
C.operating = position
C.update_move_direction()
CHECK_TICK
+/obj/machinery/conveyor_switch/process()
+ if(!operated)
+ return
+ operated = 0
+ do_process()
+
// attack with hand, switch position
/obj/machinery/conveyor_switch/interact(mob/user)
add_fingerprint(user)
diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
index f3e14993ed..8254e20761 100644
--- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
@@ -622,7 +622,9 @@
var/obj/O = owner.get_active_held_item()
if(O)
O.extinguish() //All shamelessly copied from water's reaction_obj, since I didn't seem to be able to get it here for some reason.
- O.acid_level = 0
+ var/datum/component/acid/acid = O.GetComponent(/datum/component/acid)
+ if(acid)
+ acid.level = 0
// Monkey cube
if(istype(O, /obj/item/reagent_containers/food/snacks/cube))
to_chat(owner, "[linked_extract] kept your hands wet! It makes [O] expand!")
@@ -702,16 +704,20 @@
/datum/status_effect/stabilized/sepia
id = "stabilizedsepia"
colour = "sepia"
- var/mod = 0
+ var/list/possible = list(
+ -0.5,
+ -0.25,
+ 0,
+ 0.5,
+ 1
+ )
+
+/datum/status_effect/stabilized/sepia/New(list/arguments)
+ . = ..()
+ possible = typelist(NAMEOF(src, possible), possible)
/datum/status_effect/stabilized/sepia/tick()
- if(prob(50) && mod > -1)
- mod--
- owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/status_effect/sepia, multiplicative_slowdown = 1)
- else if(mod < 1)
- mod++
- // yeah a value of 0 does nothing but replacing the trait in place is cheaper than removing and adding repeatedly
- owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/status_effect/sepia, multiplicative_slowdown = 0)
+ owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/status_effect/sepia, multiplicative_slowdown = safepick(possible))
return ..()
/datum/status_effect/stabilized/sepia/on_remove()
@@ -932,6 +938,7 @@
/datum/status_effect/stabilized/lightpink/on_apply()
ADD_TRAIT(owner, TRAIT_FREESPRINT, "stabilized_slime")
+ owner.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/slime/light_pink)
return ..()
/datum/status_effect/stabilized/lightpink/tick()
@@ -943,6 +950,7 @@
/datum/status_effect/stabilized/lightpink/on_remove()
REMOVE_TRAIT(owner, TRAIT_FREESPRINT, "stabilized_slime")
+ owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/slime/light_pink)
return ..()
/datum/status_effect/stabilized/adamantine
diff --git a/code/modules/ruins/spaceruin_code/caravanambush.dm b/code/modules/ruins/spaceruin_code/caravanambush.dm
index 740850524c..ab38ed8e4d 100644
--- a/code/modules/ruins/spaceruin_code/caravanambush.dm
+++ b/code/modules/ruins/spaceruin_code/caravanambush.dm
@@ -1,27 +1,27 @@
//caravan ambush
/obj/item/wrench/caravan
- color = "#ff0000"
+ icon_state = "wrench_caravan"
desc = "A prototype of a new wrench design, allegedly the red color scheme makes it go faster."
name = "experimental wrench"
toolspeed = 0.3
/obj/item/screwdriver/caravan
- color = "#ff0000"
+ icon_state = "screwdriver_caravan"
desc = "A prototype of a new screwdriver design, allegedly the red color scheme makes it go faster."
name = "experimental screwdriver"
toolspeed = 0.3
random_color = FALSE
/obj/item/wirecutters/caravan
- color = "#ff0000"
+ icon_state = "cutters_caravan"
desc = "A prototype of a new wirecutter design, allegedly the red color scheme makes it go faster."
name = "experimental wirecutters"
toolspeed = 0.3
random_color = FALSE
/obj/item/crowbar/red/caravan
- color = "#ff0000"
+ icon_state = "crowbar_caravan"
desc = "A prototype of a new crowbar design, allegedly the red color scheme makes it go faster."
name = "experimental crowbar"
toolspeed = 0.3
diff --git a/code/modules/surgery/advanced/revival.dm b/code/modules/surgery/advanced/revival.dm
index 0b864958a0..a8d7deb803 100644
--- a/code/modules/surgery/advanced/revival.dm
+++ b/code/modules/surgery/advanced/revival.dm
@@ -69,7 +69,7 @@
for(var/obj/item/organ/O in target.internal_organs)//zap those buggers back to life!
if(O.organ_flags & ORGAN_FAILING)
O.applyOrganDamage(-5)
- var/list/policies = CONFIG_GET(keyed_list/policyconfig)
+ var/list/policies = CONFIG_GET(keyed_list/policy)
var/timelimit = CONFIG_GET(number/defib_cmd_time_limit) * 10 //the config is in seconds, not deciseconds
var/late = timelimit && (tplus > timelimit)
var/policy = late? policies[POLICYCONFIG_ON_DEFIB_LATE] : policies[POLICYCONFIG_ON_DEFIB_INTACT]
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index e24268cc45..e929641367 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -188,7 +188,7 @@
needs_processing = .
//Return TRUE to get whatever mob this is in to update health.
-/obj/item/bodypart/proc/on_life()
+/obj/item/bodypart/proc/on_life(seconds, times_fired)
if(stam_heal_tick && stamina_dam > DAMAGE_PRECISION) //DO NOT update health here, it'll be done in the carbon's life.
if(heal_damage(brute = 0, burn = 0, stamina = (stam_heal_tick * (disabled ? 2 : 1)), only_robotic = FALSE, only_organic = FALSE, updating_health = FALSE))
. |= BODYPART_LIFE_UPDATE_HEALTH
diff --git a/code/modules/surgery/emergency_reboot.dm b/code/modules/surgery/emergency_reboot.dm
index 046edd884c..5023480b51 100644
--- a/code/modules/surgery/emergency_reboot.dm
+++ b/code/modules/surgery/emergency_reboot.dm
@@ -42,7 +42,7 @@
if(target.revive())
target.visible_message("...[target]'s posibrain flickers to life once again!")
target.emote("ping")
- var/list/policies = CONFIG_GET(keyed_list/policyconfig)
+ var/list/policies = CONFIG_GET(keyed_list/policy)
var/timelimit = CONFIG_GET(number/defib_cmd_time_limit) * 10 //the config is in seconds, not deciseconds
var/late = timelimit && (tplus > timelimit)
var/policy = late? policies[POLICYCONFIG_ON_DEFIB_LATE] : policies[POLICYCONFIG_ON_DEFIB_INTACT]
diff --git a/code/modules/surgery/organs/liver.dm b/code/modules/surgery/organs/liver.dm
index 2037547d36..5c6b66f702 100755
--- a/code/modules/surgery/organs/liver.dm
+++ b/code/modules/surgery/organs/liver.dm
@@ -25,7 +25,7 @@
var/cachedmoveCalc = 1
food_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/iron = 5)
-/obj/item/organ/liver/on_life()
+/obj/item/organ/liver/on_life(seconds, times_fired)
. = ..()
if(!. || !owner)//can't process reagents with a failing liver
return
@@ -40,7 +40,7 @@
damage += (thisamount*toxLethality)
//metabolize reagents
- owner.reagents.metabolize(owner, can_overdose=TRUE)
+ owner.reagents.metabolize(owner, seconds, times_fired, can_overdose=TRUE)
if(damage > 10 && prob(damage/3))//the higher the damage the higher the probability
to_chat(owner, "You feel a dull pain in your abdomen.")
diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm
index 6cdeadcbb3..f0f2a7ef19 100644
--- a/code/modules/surgery/organs/organ_internal.dm
+++ b/code/modules/surgery/organs/organ_internal.dm
@@ -92,18 +92,18 @@
on_death() //Kinda hate doing it like this, but I really don't want to call process directly.
//Sources; life.dm process_organs
-/obj/item/organ/proc/on_death() //Runs when outside AND inside.
+/obj/item/organ/proc/on_death(seconds, times_fired) //Runs when outside AND inside.
decay()
//Applys the slow damage over time decay
-/obj/item/organ/proc/decay()
+/obj/item/organ/proc/decay(seconds, times_fired)
if(!can_decay())
STOP_PROCESSING(SSobj, src)
return
is_cold()
if(organ_flags & ORGAN_FROZEN)
return
- applyOrganDamage(maxHealth * decay_factor)
+ applyOrganDamage(maxHealth * decay_factor * (seconds * 0.5))
/obj/item/organ/proc/can_decay()
if(CHECK_BITFIELD(organ_flags, ORGAN_NO_SPOIL | ORGAN_SYNTHETIC | ORGAN_FAILING))
@@ -151,7 +151,7 @@
organ_flags &= ~ORGAN_FROZEN
return FALSE
-/obj/item/organ/proc/on_life() //repair organ damage if the organ is not failing or synthetic
+/obj/item/organ/proc/on_life(seconds, times_fired) //repair organ damage if the organ is not failing or synthetic
if(organ_flags & ORGAN_FAILING || !owner)
return FALSE
if(organ_flags & ORGAN_SYNTHETIC_EMP) //Synthetic organ has been emped, is now failing.
diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm
index 12e282200c..e41980cdd3 100644
--- a/code/modules/surgery/organs/vocal_cords.dm
+++ b/code/modules/surgery/organs/vocal_cords.dm
@@ -1,8 +1,15 @@
-#define COOLDOWN_STUN 1200
-#define COOLDOWN_KNOCKDOWN 600
-#define COOLDOWN_DAMAGE 600
-#define COOLDOWN_MEME 300
-#define COOLDOWN_NONE 100
+#define COOLDOWN_STUN 300
+#define COOLDOWN_KNOCKDOWN 300
+#define COOLDOWN_DAMAGE 300
+#define COOLDOWN_MEME 150
+#define COOLDOWN_NONE 50
+
+/// anything above this requires adminbus, to prevent a cultist from stacking chaplain + cult + specific listener = 8x, which is enough to instantly kill someone with damage.
+#define VOG_MAX_STANDARD_POWER 3
+/// max damage we can do in one "blast" to a listener
+#define VOG_MAX_BURST_DAMAGE 40
+/// max healing we can do in one "blast" to a listener
+#define VOG_MAX_BURST_HEAL 40
/obj/item/organ/vocal_cords //organs that are activated through speech with the :x/MODE_KEY_VOCALCORDS channel
name = "vocal cords"
@@ -130,13 +137,11 @@
return 0 //no cooldown
var/log_message = uppertext(message)
- if(!span_list || !span_list.len)
- if(iscultist(user))
- span_list = list("narsiesmall")
- else if (is_servant_of_ratvar(user))
- span_list = list("ratvar")
- else
- span_list = list()
+ if(iscultist(user))
+ span_list = list("narsiesmall")
+ else if (is_servant_of_ratvar(user))
+ span_list = list("ratvar")
+ LAZYINITLIST(span_list)
user.say(message, spans = span_list, sanitize = FALSE)
@@ -156,39 +161,24 @@
cooldown = COOLDOWN_NONE
return cooldown
- var/power_multiplier = base_multiplier
-
- if(user.mind)
- //Chaplains are very good at speaking with the voice of god
- if(user.mind.assigned_role == "Chaplain")
- power_multiplier *= 2
- //Command staff has authority
- if(user.mind.assigned_role in GLOB.command_positions)
- power_multiplier *= 1.4
- //Why are you speaking
- if(user.mind.assigned_role == "Mime")
- power_multiplier *= 0.5
-
- //Cultists are closer to their gods and are more powerful, but they'll give themselves away
- if(iscultist(user))
- power_multiplier *= 2
- else if (is_servant_of_ratvar(user))
- power_multiplier *= 2
-
//Try to check if the speaker specified a name or a job to focus on
var/list/specific_listeners = list()
var/found_string = null
+ var/devil_target = FALSE
//Get the proper job titles
message = get_full_job_name(message)
+ // limitation: this only checks at the start of the message.
+ // if we wanted to check anywhere we'd have to make the user use delimiters to specify who they're talking to,
+ // as otherwise it'd be far too computationally and logically expensive to find out who we want.
for(var/V in listeners)
var/mob/living/L = V
var/datum/antagonist/devil/devilinfo = is_devil(L)
if(devilinfo && findtext(message, devilinfo.truename))
var/start = findtext(message, devilinfo.truename)
listeners = list(L) //Devil names are unique.
- power_multiplier *= 5 //if you're a devil and god himself addressed you, you fucked up
+ devil_target = TRUE //if you're a devil and god himself addressed you, you fucked up
//Cut out the name so it doesn't trigger commands
message = copytext(message, 1, start) + copytext(message, start + length(devilinfo.truename))
break
@@ -207,10 +197,14 @@
//Cut out the job so it doesn't trigger commands
found_string = L.mind.assigned_role
+ var/power_multiplier = get_vog_multiplier(user, base_multiplier, specific_listeners)
+ var/adminbus = power_multiplier > VOG_MAX_STANDARD_POWER // an admin is being a dunce, bypass hard scaling limits on this message
+ if(devil_target)
+ power_multiplier = max(power_multiplier, 5)
+
if(specific_listeners.len)
- listeners = specific_listeners
- power_multiplier *= (1 + (1/specific_listeners.len)) //2x on a single guy, 1.5x on two and so on
message = copytext(message, length(found_string) + 1)
+ listeners = specific_listeners.Copy()
var/static/regex/stun_words = regex("stop|wait|stand still|hold on|halt")
var/static/regex/knockdown_words = regex("drop|fall|trip|knockdown")
@@ -264,7 +258,7 @@
cooldown = COOLDOWN_STUN
for(var/V in listeners)
var/mob/living/L = V
- L.Stagger(60 * power_multiplier)
+ L.Stagger(40 * power_multiplier)
//KNOCKDOWN
else if(findtext(message, knockdown_words))
@@ -272,6 +266,7 @@
for(var/V in listeners)
var/mob/living/L = V
L.DefaultCombatKnockdown()
+ L.Stagger(10 * power_multiplier)
//VOMIT
else if((findtext(message, vomit_words)))
@@ -285,13 +280,13 @@
for(var/mob/living/carbon/C in listeners)
if(user.mind && (user.mind.assigned_role == "Curator" || user.mind.assigned_role == "Mime"))
power_multiplier *= 3
- C.silent += (10 * power_multiplier)
+ C.silent += (5 * power_multiplier)
//HALLUCINATE
else if((findtext(message, hallucinate_words)))
cooldown = COOLDOWN_MEME
for(var/mob/living/carbon/C in listeners)
- new /datum/hallucination/delusion(C, TRUE, null,150 * power_multiplier,0)
+ new /datum/hallucination/delusion(C, TRUE, null, 150 * power_multiplier, 0)
//WAKE UP
else if((findtext(message, wakeup_words)))
@@ -305,14 +300,14 @@
cooldown = COOLDOWN_DAMAGE
for(var/V in listeners)
var/mob/living/L = V
- L.heal_overall_damage(10 * power_multiplier, 10 * power_multiplier, 0, FALSE, FALSE)
+ L.heal_overall_damage(min(17.5 * power_multiplier, adminbus? INFINITY : VOG_MAX_BURST_HEAL), min(17.5 * power_multiplier, VOG_MAX_BURST_HEAL), 0, FALSE, FALSE)
//BRUTE DAMAGE
else if((findtext(message, hurt_words)))
cooldown = COOLDOWN_DAMAGE
for(var/V in listeners)
var/mob/living/L = V
- L.apply_damage(15 * power_multiplier, def_zone = BODY_ZONE_CHEST, wound_bonus=CANT_WOUND)
+ L.apply_damage(min(20 * power_multiplier, adminbus? INFINITY : VOG_MAX_BURST_DAMAGE), def_zone = BODY_ZONE_CHEST, wound_bonus = CANT_WOUND)
//BLEED
else if((findtext(message, bleed_words)))
@@ -334,14 +329,14 @@
cooldown = COOLDOWN_DAMAGE
for(var/V in listeners)
var/mob/living/L = V
- L.adjust_bodytemperature(50 * power_multiplier)
+ L.adjust_bodytemperature(75 * power_multiplier)
//COLD
else if((findtext(message, cold_words)))
cooldown = COOLDOWN_DAMAGE
for(var/V in listeners)
var/mob/living/L = V
- L.adjust_bodytemperature(-50 * power_multiplier)
+ L.adjust_bodytemperature(-75 * power_multiplier)
//REPULSE
else if((findtext(message, repulse_words)))
@@ -596,6 +591,34 @@
return cooldown
+/proc/get_vog_multiplier(mob/living/carbon/user, base_multiplier = 1, list/specific_listeners = list())
+ if(base_multiplier >= VOG_MAX_STANDARD_POWER)
+ return base_multiplier // an admin bussed you and they probably didn't realize you were a chaplain/cultist.
+
+ var/special_check = get_vog_special(user)
+ if(!special_check)
+ return 0
+
+ . = min(base_multiplier * special_check, VOG_MAX_STANDARD_POWER) // anything above should require conscious admin fuckery, as things are balanced around 3 multiplier tops (see: damage being 15*3)
+ if(!specific_listeners.len)
+ return
+ . = min(. * (1 + (1 / specific_listeners.len)), VOG_MAX_STANDARD_POWER)
+
+/// get special role multiplier for voice of god. No double dipping.
+/proc/get_vog_special(mob/living/carbon/user)
+ if(iscultist(user) || is_servant_of_ratvar(user))
+ return 2 // servant of god
+ if(user.mind)
+ // servant of god
+ if(user.mind.assigned_role == "Chaplain")
+ return 2
+ // shut up you broke your vow
+ if(user.mind.assigned_role == "Mime")
+ return 0.5
+ if(user.mind.assigned_role in GLOB.command_positions)
+ return 1.4 // heads are great at speaking with authority
+ return 1
+
//////////////////////////////////////
///////ENTHRAL VELVET CHORDS//////////
//////////////////////////////////////
diff --git a/code/modules/tgui/states/vorepanel.dm b/code/modules/tgui/states/vorepanel.dm
new file mode 100644
index 0000000000..b68dfb970a
--- /dev/null
+++ b/code/modules/tgui/states/vorepanel.dm
@@ -0,0 +1,18 @@
+ /**
+ * tgui state: vorepanel_state
+ *
+ * Only checks that the user and src_object are the same.
+ **/
+
+GLOBAL_DATUM_INIT(ui_vorepanel_state, /datum/ui_state/vorepanel_state, new)
+
+/datum/ui_state/vorepanel_state/can_use_topic(src_object, mob/user)
+ if(src_object != user)
+ // Note, in order to allow others to look at others vore panels, change this to
+ // UI_UPDATE
+ return UI_CLOSE
+ if(!user.client)
+ return UI_CLOSE
+ if(user.stat == DEAD)
+ return UI_DISABLED
+ return UI_INTERACTIVE
diff --git a/code/modules/tgui/tgui_alert.dm b/code/modules/tgui/tgui_alert.dm
index 1a86cca705..d144588ad9 100644
--- a/code/modules/tgui/tgui_alert.dm
+++ b/code/modules/tgui/tgui_alert.dm
@@ -9,7 +9,7 @@
* * buttons - The options that can be chosen by the user, each string is assigned a button on the UI.
* * timeout - The timeout of the alert, after which the modal will close and qdel itself. Set to zero for no timeout.
*/
-/proc/tgui_alert(mob/user, message, title, list/buttons, timeout = 60 SECONDS)
+/proc/tgui_alert(mob/user, message = null, title = null, list/buttons = list("Ok"), timeout = 0)
if (!user)
user = usr
if (!istype(user))
@@ -35,9 +35,9 @@
* * title - The of the alert modal, shown on the top of the TGUI window.
* * buttons - The options that can be chosen by the user, each string is assigned a button on the UI.
* * callback - The callback to be invoked when a choice is made.
- * * timeout - The timeout of the alert, after which the modal will close and qdel itself. Set to zero for no timeout.
+ * * timeout - The timeout of the alert, after which the modal will close and qdel itself. Disabled by default, can be set to seconds otherwise.
*/
-/proc/tgui_alert_async(mob/user, message, title, list/buttons, datum/callback/callback, timeout = 60 SECONDS)
+/proc/tgui_alert_async(mob/user, message = null, title = null, list/buttons = list("Ok"), datum/callback/callback, timeout = 0)
if (!user)
user = usr
if (!istype(user))
@@ -90,7 +90,7 @@
* the window was closed by the user.
*/
/datum/tgui_modal/proc/wait()
- while (!choice && !closed)
+ while (!choice && !closed && !QDELETED(src))
stoplag(1)
/datum/tgui_modal/ui_interact(mob/user, datum/tgui/ui)
@@ -124,10 +124,13 @@
if("choose")
if (!(params["choice"] in buttons))
return
- choice = params["choice"]
+ set_choice(params["choice"])
SStgui.close_uis(src)
return TRUE
+/datum/tgui_modal/proc/set_choice(choice)
+ src.choice = choice
+
/**
* # async tgui_modal
*
@@ -138,23 +141,17 @@
var/datum/callback/callback
/datum/tgui_modal/async/New(mob/user, message, title, list/buttons, callback, timeout)
- ..(user, title, message, buttons, timeout)
+ ..(user, message, title, buttons, timeout)
src.callback = callback
/datum/tgui_modal/async/Destroy(force, ...)
QDEL_NULL(callback)
. = ..()
-/datum/tgui_modal/async/ui_close(mob/user)
+/datum/tgui_modal/async/set_choice(choice)
. = ..()
- qdel(src)
-
-/datum/tgui_modal/async/ui_act(action, list/params)
- . = ..()
- if (!. || choice == null)
- return
- callback.InvokeAsync(choice)
- qdel(src)
+ if(!isnull(src.choice))
+ callback?.InvokeAsync(src.choice)
/datum/tgui_modal/async/wait()
return
diff --git a/code/modules/tooltip/tooltip.dm b/code/modules/tooltip/tooltip.dm
index fd45ea37d9..f9efd7d9c1 100644
--- a/code/modules/tooltip/tooltip.dm
+++ b/code/modules/tooltip/tooltip.dm
@@ -138,12 +138,10 @@ Notes:
. = ..()
if(tooltips)
if(!QDELETED(src))
- var/list/examine_list = examine(src)
- var/get_tooltip_data = get_tooltip_data()
- if(length(get_tooltip_data))
- examine_list = get_tooltip_data
- var/examine_data = examine_list.Join(" ")
- openToolTip(usr, src, params, title = name, content = examine_data)
+ var/list/tooltip_data = get_tooltip_data()
+ if(length(tooltip_data))
+ var/examine_data = tooltip_data.Join(" ")
+ openToolTip(usr, src, params, title = name, content = examine_data)
/atom/movable/MouseExited(location, control, params)
. = ..()
diff --git a/code/modules/unit_tests/metabolizing.dm b/code/modules/unit_tests/metabolizing.dm
index b7f8fc4f6a..6c0a635b13 100644
--- a/code/modules/unit_tests/metabolizing.dm
+++ b/code/modules/unit_tests/metabolizing.dm
@@ -11,7 +11,7 @@
/datum/unit_test/metabolization/proc/test_reagent(mob/living/carbon/C, reagent_type)
C.reagents.add_reagent(reagent_type, 10)
- C.reagents.metabolize(C, can_overdose = TRUE)
+ C.reagents.metabolize(C, SSMOBS_DT, 1, can_overdose = TRUE)
C.reagents.clear_reagents()
/datum/unit_test/metabolization/Destroy()
diff --git a/code/modules/vehicles/atv.dm b/code/modules/vehicles/atv.dm
index d125453e5a..d5ddfe63cc 100644
--- a/code/modules/vehicles/atv.dm
+++ b/code/modules/vehicles/atv.dm
@@ -9,7 +9,7 @@
/obj/vehicle/ridden/atv/Initialize()
. = ..()
var/datum/component/riding/D = LoadComponent(/datum/component/riding)
- D.vehicle_move_delay = 1
+ D.vehicle_move_delay = CONFIG_GET(number/movedelay/run_delay)
D.set_riding_offsets(RIDING_OFFSET_ALL, list(TEXT_NORTH = list(0, 4), TEXT_SOUTH = list(0, 4), TEXT_EAST = list(0, 4), TEXT_WEST = list( 0, 4)))
D.set_vehicle_dir_layer(SOUTH, ABOVE_MOB_LAYER)
D.set_vehicle_dir_layer(NORTH, OBJ_LAYER)
diff --git a/code/modules/vehicles/motorized_wheelchair.dm b/code/modules/vehicles/motorized_wheelchair.dm
new file mode 100644
index 0000000000..8e2d838066
--- /dev/null
+++ b/code/modules/vehicles/motorized_wheelchair.dm
@@ -0,0 +1,155 @@
+/obj/vehicle/ridden/wheelchair/motorized
+ name = "Hoverchair"
+ desc = "A chair with thrusters. It seems to have a motor in it."
+ icon = 'icons/obj/vehicles.dmi'
+ icon_state = "wheelchair_motorized"
+ max_integrity = 150
+ var/speed = 2
+ var/power_efficiency = 1
+ var/power_usage = 25
+ var/panel_open = FALSE
+ var/list/required_parts = list(/obj/item/stock_parts/manipulator,
+ /obj/item/stock_parts/manipulator,
+ /obj/item/stock_parts/capacitor)
+ var/obj/item/stock_parts/cell/power_cell
+
+/obj/vehicle/ridden/wheelchair/motorized/CheckParts(list/parts_list)
+ ..()
+ refresh_parts()
+
+/obj/vehicle/ridden/wheelchair/motorized/proc/refresh_parts()
+ speed = 1 // Should never be under 1
+ for(var/obj/item/stock_parts/manipulator/M in contents)
+ speed += M.rating
+ for(var/obj/item/stock_parts/capacitor/C in contents)
+ power_efficiency = C.rating
+ var/datum/component/riding/D = GetComponent(/datum/component/riding)
+ D.vehicle_move_delay = round((CONFIG_GET(number/movedelay/run_delay) * 2) / speed, world.tick_lag)
+
+/obj/vehicle/ridden/wheelchair/motorized/obj_destruction(damage_flag)
+ var/turf/T = get_turf(src)
+ for(var/atom/movable/A in contents)
+ A.forceMove(T)
+ if(isliving(A))
+ var/mob/living/L = A
+ L.update_mobility()
+ ..()
+
+/obj/vehicle/ridden/wheelchair/motorized/driver_move(mob/living/user, direction)
+ if(istype(user))
+ if(!canmove)
+ return FALSE
+ if(!power_cell)
+ to_chat(user, "There seems to be no cell installed in [src].")
+ canmove = FALSE
+ addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20)
+ return FALSE
+ if(power_cell.charge < power_usage / max(power_efficiency, 1))
+ to_chat(user, "The display on [src] blinks 'Out of Power'.")
+ canmove = FALSE
+ addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20)
+ return FALSE
+ if(user.get_num_arms() < arms_required)
+ to_chat(user, "You don't have enough arms to operate the motor controller!")
+ canmove = FALSE
+ addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20)
+ return FALSE
+ power_cell.use(power_usage / max(power_efficiency, 1))
+ return ..()
+
+/obj/vehicle/ridden/wheelchair/motorized/post_buckle_mob(mob/living/user)
+ . = ..()
+ density = TRUE
+
+/obj/vehicle/ridden/wheelchair/motorized/post_unbuckle_mob()
+ . = ..()
+ density = FALSE
+
+/obj/vehicle/ridden/wheelchair/motorized/attack_hand(mob/living/user)
+ if(power_cell && panel_open)
+ power_cell.update_icon()
+ user.put_in_hands(power_cell)
+ power_cell = null
+ to_chat(user, "You remove the power cell from [src].")
+ return
+ return ..()
+
+/obj/vehicle/ridden/wheelchair/motorized/attackby(obj/item/I, mob/user, params)
+ if(I.tool_behaviour == TOOL_SCREWDRIVER)
+ I.play_tool_sound(src)
+ panel_open = !panel_open
+ user.visible_message("[user] [panel_open ? "opens" : "closes"] the maintenance panel on [src].", "You [panel_open ? "open" : "close"] the maintenance panel.")
+ return
+ if(panel_open)
+ if(istype(I, /obj/item/stock_parts/cell))
+ if(power_cell)
+ to_chat(user, "There is a power cell already installed.")
+ else
+ I.forceMove(src)
+ power_cell = I
+ to_chat(user, "You install the [I].")
+ refresh_parts()
+ return
+ if(istype(I, /obj/item/stock_parts))
+ var/obj/item/stock_parts/B = I
+ var/P
+ for(var/obj/item/stock_parts/A in contents)
+ for(var/D in required_parts)
+ if(ispath(A.type, D))
+ P = D
+ break
+ if(istype(B, P) && istype(A, P))
+ if(B.get_part_rating() > A.get_part_rating())
+ B.forceMove(src)
+ user.put_in_hands(A)
+ user.visible_message("[user] replaces [A] with [B] in [src].", "You replace [A] with [B].")
+ break
+ refresh_parts()
+ return
+ return ..()
+
+/obj/vehicle/ridden/wheelchair/motorized/wrench_act(mob/living/user, obj/item/I)
+ to_chat(user, "You begin to detach the thrusters...")
+ if(I.use_tool(src, user, 40, volume=50))
+ to_chat(user, "You detach the thrusters and deconstruct the chair.")
+ new /obj/item/stack/rods(drop_location(), 8)
+ new /obj/item/stack/sheet/plasteel(drop_location(), 10)
+ var/turf/T = get_turf(src)
+ for(var/atom/movable/A in contents)
+ A.forceMove(T)
+ if(isliving(A))
+ var/mob/living/L = A
+ L.update_mobility()
+ qdel(src)
+ return TRUE
+
+/obj/vehicle/ridden/wheelchair/motorized/examine(mob/user)
+ . = ..()
+ if(panel_open)
+ . += "There is a small screen on it, [(in_range(user, src) || isobserver(user)) ? "[power_cell ? "it reads:" : "but it is dark."]" : "but you can't see it from here."]"
+ if(!power_cell || (!in_range(user, src) && !isobserver(user)))
+ return
+ . += "Speed: [speed]"
+ . += "Energy efficiency: [power_efficiency]"
+ . += "Power: [power_cell.charge] out of [power_cell.maxcharge]"
+
+/obj/vehicle/ridden/wheelchair/motorized/Bump(atom/movable/M)
+ . = ..()
+ // If the speed is higher than delay_multiplier throw the person on the wheelchair away
+ if(M.density && speed > 2 && has_buckled_mobs())
+ var/mob/living/H = buckled_mobs[1]
+ var/atom/throw_target = get_edge_target_turf(H, pick(GLOB.cardinals))
+ unbuckle_mob(H)
+ H.throw_at(throw_target, 2, 3)
+ H.Knockdown(100)
+ H.adjustStaminaLoss(40)
+ if(isliving(M))
+ var/mob/living/D = M
+ throw_target = get_edge_target_turf(D, pick(GLOB.cardinals))
+ D.throw_at(throw_target, 2, 3)
+ D.Knockdown(80)
+ D.adjustStaminaLoss(35)
+ visible_message("[src] crashes into [M], sending [H] and [D] flying!")
+ else
+ visible_message("[src] crashes into [M], sending [H] flying!")
+ playsound(src, 'sound/effects/bang.ogg', 50, 1)
diff --git a/code/modules/vehicles/wheelchair.dm b/code/modules/vehicles/wheelchair.dm
index a81dff37ad..28145ba8e1 100644
--- a/code/modules/vehicles/wheelchair.dm
+++ b/code/modules/vehicles/wheelchair.dm
@@ -26,8 +26,8 @@
AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE, CALLBACK(src, .proc/can_user_rotate),CALLBACK(src, .proc/can_be_rotated),null)
/obj/vehicle/ridden/wheelchair/obj_destruction(damage_flag)
- new /obj/item/stack/rods(drop_location(), 1)
- new /obj/item/stack/sheet/metal(drop_location(), 1)
+ new /obj/item/stack/rods(drop_location(), 8)
+ new /obj/item/stack/sheet/metal(drop_location(), 2)
..()
/obj/vehicle/ridden/wheelchair/Destroy()
@@ -53,7 +53,10 @@
/obj/vehicle/ridden/wheelchair/Moved()
. = ..()
cut_overlays()
- playsound(src, 'sound/effects/roll.ogg', 75, 1)
+ if(istype(src, /obj/vehicle/ridden/wheelchair/motorized))
+ playsound(src, 'sound/effects/chairwhoosh.ogg', 75, 1)
+ else
+ playsound(src, 'sound/effects/roll.ogg', 75, 1)
if(has_buckled_mobs())
handle_rotation_overlayed()
@@ -88,8 +91,12 @@
/obj/vehicle/ridden/wheelchair/proc/handle_rotation_overlayed()
cut_overlays()
- var/image/V = image(icon = icon, icon_state = "wheelchair_overlay", layer = FLY_LAYER, dir = src.dir)
- add_overlay(V)
+ if(istype(src, /obj/vehicle/ridden/wheelchair/motorized))
+ var/image/V = image(icon = icon, icon_state = "wheelchair_noverlay", layer = FLY_LAYER, dir = src.dir)
+ add_overlay(V)
+ else
+ var/image/V = image(icon = icon, icon_state = "wheelchair_overlay", layer = FLY_LAYER, dir = src.dir)
+ add_overlay(V)
diff --git a/code/modules/vore/eating/bellymodes.dm b/code/modules/vore/eating/bellymodes.dm
index 7cf36ebc50..8d64ee28f1 100644
--- a/code/modules/vore/eating/bellymodes.dm
+++ b/code/modules/vore/eating/bellymodes.dm
@@ -150,7 +150,7 @@
SEND_SOUND(M,prey_digest)
play_sound = pick(pred_digest)
- if(M.vore_flags & ABSORBED)
+ if(M.vore_flags & ABSORBED || !(M.vore_flags & ABSORBABLE)) //Negative.
continue
if(M.nutrition >= 100) //Drain them until there's no nutrients left. Slowly "absorb" them.
diff --git a/code/modules/vore/eating/living.dm b/code/modules/vore/eating/living.dm
index 41d7da16a1..6bc44e6489 100644
--- a/code/modules/vore/eating/living.dm
+++ b/code/modules/vore/eating/living.dm
@@ -1,17 +1,24 @@
///////////////////// Mob Living /////////////////////
/mob/living
var/vore_flags = 0
- var/showvoreprefs = TRUE // Determines if the mechanical vore preferences button will be displayed on the mob or not.
- var/obj/belly/vore_selected // Default to no vore capability.
- var/list/vore_organs = list() // List of vore containers inside a mob
- var/vore_taste = null // What the character tastes like
+ // Determines if the mechanical vore preferences button will be displayed on the mob or not.
+ var/showvoreprefs = TRUE
+ /// Default to no vore capability.
+ var/obj/belly/vore_selected
+ /// List of vore containers inside a mob
+ var/list/vore_organs = list()
+ /// What the character tastes like
+ var/vore_taste = null
+ /// What the character smells like
+ var/vore_smell = null
+ /// Next time vore sounds get played for the prey, do not change manually as it is intended to be set automatically
var/next_preyloop
//
// Hook for generic creation of stuff on new creatures
//
/hook/living_new/proc/vore_setup(mob/living/M)
- add_verb(M, list(/mob/living/proc/preyloop_refresh, /mob/living/proc/lick, /mob/living/proc/escapeOOC))
+ add_verb(M, list(/mob/living/proc/preyloop_refresh, /mob/living/proc/lick, /mob/living/proc/smell, /mob/living/proc/escapeOOC))
if(M.vore_flags & NO_VORE) //If the mob isn't supposed to have a stomach, let's not give it an insidepanel so it can make one for itself, or a stomach.
return TRUE
@@ -59,13 +66,14 @@
// Critical adjustments due to TG grab changes - Poojawa
/mob/living/proc/vore_attack(var/mob/living/user, var/mob/living/prey, var/mob/living/pred)
- lazy_init_belly()
+ set waitfor = FALSE
if(!user || !prey || !pred)
return
if(!isliving(pred)) //no badmin, you can't feed people to ghosts or objects.
return
+ lazy_init_belly()
if(pred == prey) //you click your target
if(!CHECK_BITFIELD(pred.vore_flags,FEEDING))
to_chat(user, "They aren't able to be fed.")
@@ -255,6 +263,7 @@
client.prefs.vore_flags = vore_flags // there's garbage data in here, but it doesn't matter
client.prefs.vore_taste = vore_taste
+ client.prefs.vore_smell = vore_smell
var/list/serialized = list()
for(var/belly in vore_organs)
@@ -263,6 +272,8 @@
client.prefs.belly_prefs = serialized
+ client.prefs.save_character()
+
return TRUE
//
@@ -273,8 +284,9 @@
to_chat(src,"You attempted to apply your vore prefs but somehow you're in this character without a client.prefs variable. Tell a dev.")
return FALSE
ENABLE_BITFIELD(vore_flags,VOREPREF_INIT)
- COPY_SPECIFIC_BITFIELDS(vore_flags,client.prefs.vore_flags,DIGESTABLE | DEVOURABLE | FEEDING | LICKABLE)
+ COPY_SPECIFIC_BITFIELDS(vore_flags, client.prefs.vore_flags, DIGESTABLE | DEVOURABLE | FEEDING | LICKABLE | SMELLABLE | ABSORBABLE | MOBVORE)
vore_taste = client.prefs.vore_taste
+ vore_smell = client.prefs.vore_smell
release_vore_contents(silent = TRUE)
QDEL_LIST(vore_organs)
@@ -378,6 +390,56 @@
else
taste_message += "a plain old normal [src]"
return taste_message
+
+//
+// Equally important as the above
+//
+/mob/living/proc/smell()
+ set name = "Smell Someone"
+ set category = "Vore"
+ set desc = "Smell someone nearby!"
+
+ if(incapacitated(ignore_restraints = TRUE))
+ to_chat(src, "You can't do that while incapacitated.")
+ return
+ if(!CheckActionCooldown())
+ to_chat(src, "You can't do that so fast, slow down.")
+ return
+
+ DelayNextAction(CLICK_CD_MELEE, flush = TRUE)
+
+ var/list/smellable = list()
+ for(var/mob/living/L in view(1))
+ if(L != src && (!L.ckey || L.client?.prefs.vore_flags & SMELLABLE) && Adjacent(L))
+ LAZYADD(smellable, L)
+ for(var/mob/living/listed in smellable)
+ smellable[listed] = new /mutable_appearance(listed)
+
+ if(!smellable)
+ return
+
+ var/mob/living/sniffed = show_radial_menu(src, src, smellable, radius = 40, require_near = TRUE)
+
+ if(QDELETED(sniffed) || (sniffed.ckey && !(sniffed.client?.prefs.vore_flags & SMELLABLE)) || !Adjacent(sniffed) || incapacitated(ignore_restraints = TRUE))
+ return
+
+ visible_message("[src] smells [sniffed]!","You smell [sniffed]. They smell like [sniffed.get_smell_message()].","Sniff!")
+
+/mob/living/proc/get_smell_message(allow_generic = TRUE, datum/species/mrace)
+ if(!vore_smell && !allow_generic)
+ return FALSE
+
+ var/smell_message = ""
+ if(vore_smell && (vore_smell != ""))
+ smell_message += "[vore_smell]"
+ else
+ if(ishuman(src))
+ var/mob/living/carbon/human/H = src
+ smell_message += "a normal [H.custom_species ? H.custom_species : H.dna.species]"
+ else
+ smell_message += "a plain old normal [src]"
+ return smell_message
+
// Check if an object is capable of eating things, based on vore_organs
//
/proc/has_vore_belly(var/mob/living/O)
diff --git a/code/modules/vore/eating/vorepanel.dm b/code/modules/vore/eating/vorepanel.dm
index aac8cbe745..a3adc89352 100644
--- a/code/modules/vore/eating/vorepanel.dm
+++ b/code/modules/vore/eating/vorepanel.dm
@@ -2,746 +2,730 @@
// Vore management panel for players
//
-#define BELLIES_MAX 20
+#define BELLIES_MAX 40
#define BELLIES_NAME_MIN 2
-#define BELLIES_NAME_MAX 24
+#define BELLIES_NAME_MAX 40
#define BELLIES_DESC_MAX 4096
+#define FLAVOR_MAX 400
+
+/mob/living
+ var/datum/vore_look/vorePanel
/mob/living/proc/insidePanel()
set name = "Vore Panel"
set category = "Vore"
- var/datum/vore_look/picker_holder = new()
- picker_holder.loop = picker_holder
- picker_holder.selected = vore_selected
+ if(!vorePanel)
+ log_game("VORE: [src] ([type], \ref[src]) didn't have a vorePanel and tried to use the verb.")
+ vorePanel = new(src)
- var/dat = picker_holder.gen_vui(src)
-
- picker_holder.popup = new(src, "insidePanel","Vore Panel", 450, 700, picker_holder)
- picker_holder.popup.set_content(dat)
- picker_holder.popup.open()
- vore_flags |= OPEN_PANEL
+ vorePanel.ui_interact(src)
/mob/living/proc/updateVRPanel() //Panel popup update call from belly events.
- if(vore_flags & OPEN_PANEL)
- var/datum/vore_look/picker_holder = new()
- picker_holder.loop = picker_holder
- picker_holder.selected = vore_selected
-
- var/dat = picker_holder.gen_vui(src)
-
- picker_holder.popup = new(src, "insidePanel","Vore Panel", 450, 700, picker_holder)
- picker_holder.popup.set_content(dat)
- picker_holder.popup.open()
+ SStgui.update_uis(vorePanel)
//
// Callback Handler for the Inside form
//
/datum/vore_look
- var/obj/belly/selected
- var/show_interacts = FALSE
- var/datum/browser/popup
- var/loop = null; // Magic self-reference to stop the handler from being GC'd before user takes action.
+ var/mob/living/host // Note, we do this in case we ever want to allow people to view others vore panels
+ var/unsaved_changes = FALSE
+ var/show_pictures = TRUE
+
+/datum/vore_look/New(mob/living/new_host)
+ if(istype(new_host))
+ host = new_host
+ . = ..()
/datum/vore_look/Destroy()
- loop = null
- selected = null
- ..() //this is a must
- return QDEL_HINT_HARDDEL
+ host = null
+ . = ..()
-/datum/vore_look/Topic(href,href_list[])
- if (vp_interact(href, href_list))
- popup.set_content(gen_vui(usr))
- usr << output(popup.get_content(), "insidePanel.browser")
+/datum/vore_look/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "VorePanel", "Vore Panel")
+ ui.open()
-/datum/vore_look/proc/gen_vui(var/mob/living/user)
- var/dat
- dat += "Remember to toggle the vore mode, it's to the left of your combat toggle. Open mouth means you're voracious! "
- dat += "Remember that the prey is blind, use audible mode subtle messages to communicate to them with posts! "
- dat += ""
- var/atom/userloc = user.loc
- if (isbelly(userloc))
- var/obj/belly/inside_belly = userloc
- var/mob/living/eater = inside_belly.owner
+// This looks weird, but all tgui_host is used for is state checking
+// So this allows us to use the self_state just fine.
+/datum/vore_look/ui_host(mob/user)
+ return host
- //Don't display this part if we couldn't find the belly since could be held in hand.
- if(inside_belly)
- dat += "You are currently [(user.vore_flags & ABSORBED) ? "absorbed into " : "inside "] [eater]'s [inside_belly]!
"
+// Note, in order to allow others to look at others vore panels, this state would need
+// to be modified.
+/datum/vore_look/ui_state(mob/user)
+ return GLOB.ui_vorepanel_state
- if(inside_belly.desc)
- dat += "[inside_belly.desc]
"
+/datum/vore_look
+ var/static/list/nom_icons
- if (inside_belly.contents.len > 1)
- dat += "You can see the following around you: "
- for (var/atom/movable/O in inside_belly)
- if(istype(O,/mob/living))
- var/mob/living/M = O
- //That's just you
- if(M == user)
- continue
+/datum/vore_look/proc/cached_nom_icon(atom/target)
+ LAZYINITLIST(nom_icons)
- //That's an absorbed person you're checking
- if(M.vore_flags & ABSORBED)
- if(user.vore_flags & ABSORBED)
- dat += "[O]"
- continue
- else
- continue
-
- //Anything else
- dat += "[O]"
-
- //Zero-width space, for wrapping
- dat += ""
+ var/key = ""
+ if(isobj(target))
+ key = "[target.type]"
+ else if(ismob(target))
+ var/mob/M = target
+ key = "\ref[target][M.real_name]"
+ if(nom_icons[key])
+ . = nom_icons[key]
else
- dat += "You aren't inside anyone."
-
- dat += ""
-
- dat += ""
- for(var/belly in user.vore_organs)
- var/obj/belly/B = belly
- if(B == selected)
- dat += "
"
- dat += ""
-
- // Selected Belly (contents, configuration)
- if(!selected)
- dat += "No belly selected. Click one to select it."
- else
- if(selected.contents.len)
- dat += "Contents: "
- for(var/O in selected)
-
- //Mobs can be absorbed, so treat them separately from everything else
- if(istype(O,/mob/living))
- var/mob/living/M = O
-
- //Absorbed gets special color OOoOOOOoooo
- if(M.vore_flags & ABSORBED)
- dat += "[O]"
- continue
-
- //Anything else
- dat += "[O]"
-
- //Zero-width space, for wrapping
- dat += ""
-
- //If there's more than one thing, add an [All] button
- if(selected.contents.len > 1)
- dat += "\[All\]"
-
- dat += ""
-
- //Belly Name Button
- dat += "Name:"
- dat += " '[selected.name]'"
-
- //Belly Type button
- dat += " Is Fleshy:"
- dat += "[selected.is_wet ? "Yes" : "No"]"
- if(selected.is_wet)
- dat += " Internal loop for prey?:"
- dat += "[selected.wet_loop ? "Yes" : "No"]"
-
- //Digest Mode Button
- dat += " Belly Mode:"
- dat += " [selected.digest_mode]"
-
- //Belly verb
- dat += " Vore Verb:"
- dat += " '[selected.vore_verb]'"
-
- //Inside flavortext
- dat += " Flavor Text:"
- dat += " '[selected.desc]'"
-
- //Belly sound
- dat += " Vore Sound: [selected.vore_sound]"
- dat += "Test"
-
- //Release sound
- dat += " Release Sound: [selected.release_sound]"
- dat += "Test"
-
- //Belly messages
- dat += " Belly Messages"
-
- //Can belly taste?
- dat += " Can Taste:"
- dat += " [selected.can_taste ? "Yes" : "No"]"
-
- //Minimum size prey must be to show up.
- dat += " Required examine size:"
- dat += " [selected.bulge_size*100]%"
-
- //Belly escapability
- dat += " Belly Interactions ([selected.escapable ? "On" : "Off"])"
- if(selected.escapable)
- dat += "[show_interacts ? "Hide" : "Show"]"
-
- if(show_interacts && selected.escapable)
- dat += ""
- dat += "Interaction Settings ?"
- dat += " Set Belly Escape Chance"
- dat += " [selected.escapechance]%"
-
- dat += " Set Belly Escape Time"
- dat += " [selected.escapetime/10]s"
-
- //Special here to add a gap
- dat += " "
- dat += " Set Belly Transfer Chance"
- dat += " [selected.transferchance]%"
-
- dat += " Set Belly Transfer Location"
- dat += " [selected.transferlocation ? selected.transferlocation : "Disabled"]"
-
- //Special here to add a gap
- dat += " "
- dat += " Set Belly Absorb Chance"
- dat += " [selected.absorbchance]%"
-
- dat += " Set Belly Digest Chance"
- dat += " [selected.digestchance]%"
- dat += ""
-
- //Delete button
- dat += " Delete Belly"
-
- dat += "Set Flavor"
-
- dat += ""
-
- //Under the last HR, save and stuff.
- dat += "Save Prefs"
- dat += "Refresh"
- dat += "Reload Slot Prefs"
-
- dat += ""
- var/pref_on = "#173d15"
- var/pref_off = "#990000"
- dat += " Toggle Digestable (Currently: [(user.vore_flags & DIGESTABLE) ? "ON" : "OFF"])"
- dat += " Toggle Devourable (Currently: [(user.vore_flags & DEVOURABLE) ? "ON" : "OFF"])"
- dat += " Toggle Feeding (Currently: [(user.vore_flags & FEEDING) ? "ON" : "OFF"])"
- if(user.client.prefs)
- dat += " Toggle Licking (Currently: [(user.client.prefs.vore_flags & LICKABLE) ? "ON" : "OFF"])"
- //Returns the dat html to the vore_look
- return dat
-
-/datum/vore_look/proc/vp_interact(href, href_list)
- var/mob/living/user = usr
- for(var/H in href_list)
-
- if(href_list["close"])
- qdel(src) // Cleanup
- user.vore_flags &= ~OPEN_PANEL
- return
-
- if(href_list["show_int"])
- show_interacts = !show_interacts
- return TRUE //Force update
-
- if(href_list["int_help"])
- alert("These control how your belly responds to someone using 'resist' while inside you. The percent chance to trigger each is listed below, \
- and you can change them to whatever you see fit. Setting them to 0% will disable the possibility of that interaction. \
- These only function as long as interactions are turned on in general. Keep in mind, the 'belly mode' interactions (digest/absorb) \
- will affect all prey in that belly, if one resists and triggers digestion/absorption. If multiple trigger at the same time, \
- only the first in the order of 'Escape > Transfer > Absorb > Digest' will occur.","Interactions Help")
- return FALSE //Force update
-
- if(href_list["outsidepick"])
- var/atom/movable/tgt = locate(href_list["outsidepick"])
- var/obj/belly/OB = locate(href_list["outsidebelly"])
- if(!istype(OB))
- return
- if(!(tgt in OB)) //Aren't here anymore, need to update menu.
- return TRUE
- var/intent = "Examine"
-
- if(istype(tgt,/mob/living))
- var/mob/living/M = tgt
- intent = alert("What do you want to do to them?","Query","Examine","Help Out","Devour")
- switch(intent)
- if("Examine") //Examine a mob inside another mob
- M.examine(user)
-
- if("Help Out") //Help the inside-mob out
- if(user.stat || user.vore_flags & ABSORBED || M.vore_flags & ABSORBED)
- to_chat(user,"You can't do that in your state!")
- return TRUE
-
- to_chat(user,"You begin to push [M] to freedom!")
- to_chat(M,"[usr] begins to push you to freedom!")
- to_chat(M.loc,"Someone is trying to escape from inside you!")
- sleep(50)
- if(prob(33))
- OB.release_specific_contents(M)
- to_chat(usr,"You manage to help [M] to safety!")
- to_chat(M,"[user] pushes you free!")
- to_chat(OB.owner,"[M] forces free of the confines of your body!")
- else
- to_chat(user,"[M] slips back down inside despite your efforts.")
- to_chat(M," Even with [user]'s help, you slip back inside again.")
- to_chat(OB.owner,"Your body efficiently shoves [M] back where they belong.")
-
- if("Devour") //Eat the inside mob
- if(user.vore_flags & ABSORBED || user.stat)
- to_chat(user,"You can't do that in your state!")
- return TRUE
-
- if(!user.vore_selected)
- to_chat(user,"Pick a belly on yourself first!")
- return TRUE
-
- var/obj/belly/TB = user.vore_selected
- to_chat(user,"You begin to [lowertext(TB.vore_verb)] [M] into your [lowertext(TB.name)]!")
- to_chat(M,"[user] begins to [lowertext(TB.vore_verb)] you into their [lowertext(TB.name)]!")
- to_chat(OB.owner,"Someone inside you is eating someone else!")
-
- sleep(TB.nonhuman_prey_swallow_time) //Can't do after, in a stomach, weird things abound.
- if((user in OB) && (M in OB)) //Make sure they're still here.
- to_chat(user,"You manage to [lowertext(TB.vore_verb)] [M] into your [lowertext(TB.name)]!")
- to_chat(M,"[user] manages to [lowertext(TB.vore_verb)] you into their [lowertext(TB.name)]!")
- to_chat(OB.owner,"Someone inside you has eaten someone else!")
- TB.nom_mob(M)
-
- else if(istype(tgt,/obj/item))
- var/obj/item/T = tgt
- if(!(tgt in OB))
- //Doesn't exist anymore, update.
- return TRUE
- intent = alert("What do you want to do to that?","Query","Examine","Use Hand")
- switch(intent)
- if("Examine")
- T.examine(user)
-
- if("Use Hand")
- if(user.stat)
- to_chat(user,"You can't do that in your state!")
- return TRUE
-
- user.ClickOn(T)
- sleep(5) //Seems to exit too fast for the panel to update
-
- if(href_list["insidepick"])
- var/intent
-
- //Handle the [All] choice. Ugh inelegant. Someone make this pretty.
- if(href_list["pickall"])
- intent = alert("Eject all, Move all?","Query","Eject all","Cancel","Move all")
- switch(intent)
- if("Cancel")
- return FALSE
-
- if("Eject all")
- if(user.stat)
- to_chat(user,"You can't do that in your state!")
- return FALSE
-
- selected.release_all_contents()
-
- if("Move all")
- if(user.stat)
- to_chat(user,"You can't do that in your state!")
- return FALSE
-
- var/obj/belly/choice = input("Move all where?","Select Belly") as null|anything in user.vore_organs
- if(!choice)
- return FALSE
-
- for(var/atom/movable/tgt in selected)
- to_chat(tgt,"You're squished from [user]'s [lowertext(selected)] to their [lowertext(choice.name)]!")
- selected.transfer_contents(tgt, choice, 1)
-
- var/atom/movable/tgt = locate(href_list["insidepick"])
- if(!(tgt in selected)) //Old menu, needs updating because they aren't really there.
- return TRUE //Forces update
- intent = "Examine"
- intent = alert("Examine, Eject, Move? Examine if you want to leave this box.","Query","Examine","Eject","Move")
- switch(intent)
- if("Examine")
- tgt.examine(user)
-
- if("Eject")
- if(user.stat)
- to_chat(user,"You can't do that in your state!")
- return FALSE
-
- selected.release_specific_contents(tgt)
-
- if("Move")
- if(user.stat)
- to_chat(user,"You can't do that in your state!")
- return FALSE
-
- var/obj/belly/choice = input("Move [tgt] where?","Select Belly") as null|anything in user.vore_organs
- if(!choice || !(tgt in selected))
- return FALSE
-
- to_chat(tgt,"You're squished from [user]'s [lowertext(selected.name)] to their [lowertext(choice.name)]!")
- selected.transfer_contents(tgt, choice)
-
- if(href_list["newbelly"])
- if(user.vore_organs.len >= BELLIES_MAX)
- return FALSE
-
- var/new_name = html_encode(input(usr,"New belly's name:","New Belly") as text|null)
-
- var/failure_msg
- if(length(new_name) > BELLIES_NAME_MAX || length(new_name) < BELLIES_NAME_MIN)
- failure_msg = "Entered belly name length invalid (must be longer than [BELLIES_NAME_MIN], no more than than [BELLIES_NAME_MAX])."
- // else if(whatever) //Next test here.
- else
- for(var/belly in user.vore_organs)
- var/obj/belly/B = belly
- if(lowertext(new_name) == lowertext(B.name))
- failure_msg = "No duplicate belly names, please."
- break
-
- if(failure_msg) //Something went wrong.
- alert(user,failure_msg,"Error!")
- return FALSE
-
- var/obj/belly/NB = new(user)
- NB.name = new_name
- selected = NB
-
- if(href_list["bellypick"])
- selected = locate(href_list["bellypick"])
- user.vore_selected = selected
-
- ////
- //Please keep these the same order they are on the panel UI for ease of coding
- ////
- if(href_list["b_name"])
- var/new_name = html_encode(input(usr,"Belly's new name:","New Name") as text|null)
-
- var/failure_msg
- if(length(new_name) > BELLIES_NAME_MAX || length(new_name) < BELLIES_NAME_MIN)
- failure_msg = "Entered belly name length invalid (must be longer than [BELLIES_NAME_MIN], no more than than [BELLIES_NAME_MAX])."
- // else if(whatever) //Next test here.
- else
- for(var/belly in user.vore_organs)
- var/obj/belly/B = belly
- if(lowertext(new_name) == lowertext(B.name))
- failure_msg = "No duplicate belly names, please."
- break
-
- if(failure_msg) //Something went wrong.
- alert(user,failure_msg,"Error!")
- return FALSE
-
- selected.name = new_name
-
- if(href_list["b_wetness"])
- selected.is_wet = !selected.is_wet
-
- if(href_list["b_wetloop"])
- selected.wet_loop = !selected.wet_loop
-
- if(href_list["b_mode"])
- var/list/menu_list = selected.digest_modes
-
- var/new_mode = input("Choose Mode (currently [selected.digest_mode])") as null|anything in menu_list
- if(!new_mode)
- return FALSE
- selected.digest_mode = new_mode
-
- if(href_list["b_desc"])
- var/new_desc = html_encode(input(usr,"Belly Description ([BELLIES_DESC_MAX] char limit):","New Description",selected.desc) as message|null)
-
- if(new_desc)
- new_desc = readd_quotes(new_desc)
- if(length(new_desc) > BELLIES_DESC_MAX)
- alert("Entered belly desc too long. [BELLIES_DESC_MAX] character limit.","Error")
- return FALSE
- selected.desc = new_desc
- else //Returned null
- return FALSE
-
- if(href_list["b_msgs"])
- var/list/messages = list(
- "Digest Message (to prey)",
- "Digest Message (to you)",
- "Struggle Message (outside)",
- "Struggle Message (inside)",
- "Examine Message (when full)",
- "Reset All To Default"
+ . = icon2base64(getFlatIcon(target,defdir=SOUTH,no_anim=TRUE))
+ nom_icons[key] = .
+
+/datum/vore_look/ui_data(mob/user)
+ var/list/data = list()
+
+ if(!host)
+ return data
+
+ data["unsaved_changes"] = unsaved_changes
+ data["show_pictures"] = show_pictures
+
+ var/atom/hostloc = host.loc
+ var/list/inside = list()
+ if(isbelly(hostloc))
+ var/obj/belly/inside_belly = hostloc
+ var/mob/living/pred = inside_belly.owner
+
+ inside = list(
+ "absorbed" = host.vore_flags & ABSORBED,
+ "belly_name" = inside_belly.name,
+ "belly_mode" = inside_belly.digest_mode,
+ "desc" = inside_belly.desc || "No description.",
+ "pred" = pred,
+ "ref" = "\ref[inside_belly]",
)
- alert(user,"Setting abusive or deceptive messages will result in a ban. Consider this your warning. Max 150 characters per message, max 10 messages per topic.","Really, don't.")
- var/choice = input(user,"Select a type to modify. Messages from each topic are pulled at random when needed.","Pick Type") as null|anything in messages
- var/help = " Press enter twice to separate messages. '%pred' will be replaced with your name. '%prey' will be replaced with the prey's name. '%belly' will be replaced with your belly's name."
+ var/list/inside_contents = list()
+ for(var/atom/movable/O in inside_belly)
+ if(O == host)
+ continue
- switch(choice)
- if("Digest Message (to prey)")
- var/new_message = input(user,"These are sent to prey when they expire. Write them in 2nd person ('you feel X'). Avoid using %prey in this type."+help,"Digest Message (to prey)",selected.get_messages("dmp")) as message
- if(new_message)
- selected.set_messages(new_message,"dmp")
+ var/list/info = list(
+ "name" = "[O]",
+ "absorbed" = FALSE,
+ "stat" = 0,
+ "ref" = "\ref[O]",
+ "outside" = FALSE,
+ )
+ if(show_pictures)
+ info["icon"] = cached_nom_icon(O)
+ if(isliving(O))
+ var/mob/living/M = O
+ info["stat"] = M.stat
+ if(M.vore_flags & ABSORBED)
+ info["absorbed"] = TRUE
+ inside_contents.Add(list(info))
+ inside["contents"] = inside_contents
+ data["inside"] = inside
- if("Digest Message (to you)")
- var/new_message = input(user,"These are sent to you when prey expires in you. Write them in 2nd person ('you feel X'). Avoid using %pred in this type."+help,"Digest Message (to you)",selected.get_messages("dmo")) as message
- if(new_message)
- selected.set_messages(new_message,"dmo")
+ var/list/our_bellies = list()
+ for(var/belly in host.vore_organs)
+ var/obj/belly/B = belly
+ our_bellies.Add(list(list(
+ "selected" = (B == host.vore_selected),
+ "name" = B.name,
+ "ref" = "\ref[B]",
+ "digest_mode" = B.digest_mode,
+ "contents" = LAZYLEN(B.contents),
+ )))
+ data["our_bellies"] = our_bellies
- if("Struggle Message (outside)")
- var/new_message = input(user,"These are sent to those nearby when prey struggles. Write them in 3rd person ('X's Y bulges')."+help,"Struggle Message (outside)",selected.get_messages("smo")) as message
- if(new_message)
- selected.set_messages(new_message,"smo")
+ var/list/selected_list = null
+ if(host.vore_selected)
+ var/obj/belly/selected = host.vore_selected
+ selected_list = list(
+ "belly_name" = selected.name,
+ "is_wet" = selected.is_wet,
+ "wet_loop" = selected.wet_loop,
+ "mode" = selected.digest_mode,
+ "verb" = selected.vore_verb,
+ "desc" = selected.desc,
+ "sound" = selected.vore_sound,
+ "release_sound" = selected.release_sound,
+ "can_taste" = selected.can_taste,
+ "bulge_size" = selected.bulge_size,
+ )
- if("Struggle Message (inside)")
- var/new_message = input(user,"These are sent to prey when they struggle. Write them in 2nd person ('you feel X'). Avoid using %prey in this type."+help,"Struggle Message (inside)",selected.get_messages("smi")) as message
- if(new_message)
- selected.set_messages(new_message,"smi")
+ selected_list["escapable"] = selected.escapable
+ selected_list["interacts"] = list()
+ if(selected.escapable)
+ selected_list["interacts"]["escapechance"] = selected.escapechance
+ selected_list["interacts"]["escapetime"] = selected.escapetime
+ selected_list["interacts"]["transferchance"] = selected.transferchance
+ selected_list["interacts"]["transferlocation"] = selected.transferlocation
+ selected_list["interacts"]["absorbchance"] = selected.absorbchance
+ selected_list["interacts"]["digestchance"] = selected.digestchance
- if("Examine Message (when full)")
- var/new_message = input(user,"These are sent to people who examine you when this belly has contents. Write them in 3rd person ('Their %belly is bulging')."+help,"Examine Message (when full)",selected.get_messages("em")) as message
- if(new_message)
- selected.set_messages(new_message,"em")
+ var/list/selected_contents = list()
+ for(var/O in selected)
+ var/list/info = list(
+ "name" = "[O]",
+ "absorbed" = FALSE,
+ "stat" = 0,
+ "ref" = "\ref[O]",
+ "outside" = TRUE,
+ )
+ if(show_pictures)
+ info["icon"] = cached_nom_icon(O)
+ if(isliving(O))
+ var/mob/living/M = O
+ info["stat"] = M.stat
+ if(M.vore_flags & ABSORBED)
+ info["absorbed"] = TRUE
+ selected_contents.Add(list(info))
+ selected_list["contents"] = selected_contents
- if("Reset All To Default")
- var/confirm = alert(user,"This will delete any custom messages. Are you sure?","Confirmation","DELETE","Cancel")
- if(confirm == "DELETE")
- selected.digest_messages_prey = initial(selected.digest_messages_prey)
- selected.digest_messages_owner = initial(selected.digest_messages_owner)
- selected.struggle_messages_outside = initial(selected.struggle_messages_outside)
- selected.struggle_messages_inside = initial(selected.struggle_messages_inside)
+ data["selected"] = selected_list
+ data["prefs"] = list(
+ "digestable" = CHECK_BITFIELD(host.vore_flags, DIGESTABLE),
+ "devourable" = CHECK_BITFIELD(host.vore_flags, DEVOURABLE),
+ "feeding" = CHECK_BITFIELD(host.vore_flags, FEEDING),
+ "absorbable" = CHECK_BITFIELD(host.vore_flags, ABSORBABLE),
+ "allowmobvore" = CHECK_BITFIELD(host.vore_flags, MOBVORE),
+ "vore_sounds" = CHECK_BITFIELD(host.client.prefs.cit_toggles, EATING_NOISES),
+ "digestion_sounds" = CHECK_BITFIELD(host.client.prefs.cit_toggles, DIGESTION_NOISES),
+ "lickable" = CHECK_BITFIELD(host.vore_flags, LICKABLE),
+ "smellable" = CHECK_BITFIELD(host.vore_flags, SMELLABLE),
+ )
- if(href_list["b_verb"])
- var/new_verb = html_encode(input(usr,"New verb when eating (infinitive tense, e.g. nom or swallow):","New Verb") as text|null)
+ return data
- if(length(new_verb) > BELLIES_NAME_MAX || length(new_verb) < BELLIES_NAME_MIN)
- alert("Entered verb length invalid (must be longer than [BELLIES_NAME_MIN], no longer than [BELLIES_NAME_MAX]).","Error")
- return FALSE
+/datum/vore_look/ui_act(action, params)
+ if(..())
+ return TRUE
- selected.vore_verb = new_verb
+ switch(action)
+ if("show_pictures")
+ show_pictures = !show_pictures
+ return TRUE
+ if("int_help")
+ tgui_alert(usr, "These control how your belly responds to someone using 'resist' while inside you. The percent chance to trigger each is listed below, \
+ and you can change them to whatever you see fit. Setting them to 0% will disable the possibility of that interaction. \
+ These only function as long as interactions are turned on in general. Keep in mind, the 'belly mode' interactions (digest/absorb) \
+ will affect all prey in that belly, if one resists and triggers digestion/absorption. If multiple trigger at the same time, \
+ only the first in the order of 'Escape > Transfer > Absorb > Digest' will occur.","Interactions Help")
+ return TRUE
- if(href_list["b_release"])
- var/choice = input(user,"Currently set to [selected.release_sound]","Select Sound") as null|anything in GLOB.pred_release_sounds
+ // Host is inside someone else, and is trying to interact with something else inside that person.
+ if("pick_from_inside")
+ return pick_from_inside(usr, params)
- if(!choice)
- return
+ // Host is trying to interact with something in host's belly.
+ if("pick_from_outside")
+ return pick_from_outside(usr, params)
- selected.release_sound = choice
-
- if(href_list["b_releasesoundtest"])
- var/sound/releasetest = GLOB.prey_release_sounds[selected.release_sound]
- if(releasetest)
- SEND_SOUND(user, releasetest)
-
- if(href_list["b_sound"])
- var/choice = input(user,"Currently set to [selected.vore_sound]","Select Sound") as null|anything in GLOB.pred_vore_sounds
-
- if(!choice)
- return
-
- selected.vore_sound = choice
-
- if(href_list["b_soundtest"])
- var/sound/voretest = GLOB.prey_vore_sounds[selected.vore_sound]
- if(voretest)
- SEND_SOUND(user, voretest)
-
- if(href_list["b_tastes"])
- selected.can_taste = !selected.can_taste
-
- if(href_list["b_bulge_size"])
- var/new_bulge = input(user, "Choose the required size prey must be to show up on examine, ranging from 25% to 200% Set this to 0 for no text on examine.", "Set Belly Examine Size.") as num|null
- if(new_bulge == null)
- return
- if(new_bulge == 0) //Disable.
- selected.bulge_size = 0
- to_chat(user,"Your stomach will not be seen on examine.")
- else if (!ISINRANGE(new_bulge,25,200))
- selected.bulge_size = 0.25 //Set it to the default.
- to_chat(user,"Invalid size.")
- else if(new_bulge)
- selected.bulge_size = (new_bulge/100)
-
- if(href_list["b_escapable"])
- if(selected.escapable == FALSE) //Possibly escapable and special interactions.
- selected.escapable = TRUE
- to_chat(usr,"Prey now have special interactions with your [lowertext(selected.name)] depending on your settings.")
- else if(selected.escapable == TRUE) //Never escapable.
- selected.escapable = FALSE
- to_chat(usr,"Prey will not be able to have special interactions with your [lowertext(selected.name)].")
- show_interacts = FALSE //Force the hiding of the panel
- else
- alert("Something went wrong. Your stomach will now not have special interactions. Press the button enable them again and tell a dev.","Error") //If they somehow have a varable that's not 0 or 1
- selected.escapable = FALSE
- show_interacts = FALSE //Force the hiding of the panel
-
- if(href_list["b_escapechance"])
- var/escape_chance_input = input(user, "Set prey escape chance on resist (as %)", "Prey Escape Chance") as num|null
- if(!isnull(escape_chance_input)) //These have to be 'null' because both cancel and 0 are valid, separate options
- selected.escapechance = sanitize_integer(escape_chance_input, 0, 100, initial(selected.escapechance))
-
- if(href_list["b_escapetime"])
- var/escape_time_input = input(user, "Set number of seconds for prey to escape on resist (1-60)", "Prey Escape Time") as num|null
- if(!isnull(escape_time_input))
- selected.escapetime = sanitize_integer(escape_time_input*10, 10, 600, initial(selected.escapetime))
-
- if(href_list["b_transferchance"])
- var/transfer_chance_input = input(user, "Set belly transfer chance on resist (as %). You must also set the location for this to have any effect.", "Prey Escape Time") as num|null
- if(!isnull(transfer_chance_input))
- selected.transferchance = sanitize_integer(transfer_chance_input, 0, 100, initial(selected.transferchance))
-
- if(href_list["b_transferlocation"])
- var/obj/belly/choice = input("Where do you want your [lowertext(selected.name)] to lead if prey resists?","Select Belly") as null|anything in (user.vore_organs + "None - Remove" - selected)
-
- if(!choice) //They cancelled, no changes
- return FALSE
- else if(choice == "None - Remove")
- selected.transferlocation = null
- else
- selected.transferlocation = choice.name
-
- if(href_list["b_absorbchance"])
- var/absorb_chance_input = input(user, "Set belly absorb mode chance on resist (as %)", "Prey Absorb Chance") as num|null
- if(!isnull(absorb_chance_input))
- selected.absorbchance = sanitize_integer(absorb_chance_input, 0, 100, initial(selected.absorbchance))
-
- if(href_list["b_digestchance"])
- var/digest_chance_input = input(user, "Set belly digest mode chance on resist (as %)", "Prey Digest Chance") as num|null
- if(!isnull(digest_chance_input))
- selected.digestchance = sanitize_integer(digest_chance_input, 0, 100, initial(selected.digestchance))
-
- if(href_list["b_del"])
- var/alert = alert("Are you sure you want to delete your [lowertext(selected.name)]?","Confirmation","Delete","Cancel")
- if(!alert == "Delete")
- return FALSE
-
- var/failure_msg = ""
-
- var/dest_for //Check to see if it's the destination of another vore organ.
- for(var/belly in user.vore_organs)
- var/obj/belly/B = belly
- if(B.transferlocation == selected)
- dest_for = B.name
- failure_msg += "This is the destiantion for at least '[dest_for]' belly transfers. Remove it as the destination from any bellies before deleting it. "
- break
-
- if(selected.contents.len)
- failure_msg += "You cannot delete bellies with contents! " //These end with spaces, to be nice looking. Make sure you do the same.
- if(selected.immutable)
- failure_msg += "This belly is marked as undeletable. "
- if(user.vore_organs.len == 1)
- failure_msg += "You must have at least one belly. "
-
- if(failure_msg)
- alert(user,failure_msg,"Error!")
- return FALSE
-
- qdel(selected)
- selected = user.vore_organs[1]
- user.vore_selected = user.vore_organs[1]
-
- if(href_list["saveprefs"])
- if(!(user.client?.prefs))
- return FALSE
- if(!user.copy_to_prefs_vr() || !user.client.prefs.save_character())
- to_chat(user, "Belly Preferences not saved!")
- log_admin("Could not save vore prefs on USER: [user].")
- else
- to_chat(user, "Belly Preferences were saved!")
-
- if(href_list["applyprefs"])
- var/alert = alert("Are you sure you want to reload the current slot preferences? This will remove your current vore organs and eject their contents.","Confirmation","Reload","Cancel")
- if(!alert == "Reload")
- return FALSE
- if(!user.copy_from_prefs_vr())
- alert("ERROR: Vore preferences failed to apply!","Error")
- else
- to_chat(user,"Vore preferences applied from active slot!")
-
- if(href_list["setflavor"])
- var/new_flavor = html_encode(input(usr,"What your character tastes like (40ch limit). This text will be printed to the pred after 'X tastes of...' so just put something like 'strawberries and cream':","Character Flavor",user.vore_taste) as text|null)
- if(!new_flavor)
- return FALSE
-
- new_flavor = readd_quotes(new_flavor)
- if(length(new_flavor) > MAX_TASTE_LEN)
- alert("Entered flavor/taste text too long. [MAX_TASTE_LEN] character limit.","Error!")
- return FALSE
- user.vore_taste = new_flavor
-
- if(href_list["toggledg"])
- var/choice = alert(user, "This button is for those who don't like being digested. It can make you undigestable to all mobs. Digesting you is currently: [(user.vore_flags & DIGESTABLE) ? "Allowed" : "Prevented"]", "", "Allow Digestion", "Cancel", "Prevent Digestion")
- if(!user || !user.client)
- return
- switch(choice)
- if("Cancel")
+ if("newbelly")
+ if(host.vore_organs.len >= BELLIES_MAX)
return FALSE
- if("Allow Digestion")
- user.vore_flags |= DIGESTABLE
- user.client.prefs.vore_flags |= DIGESTABLE
- if("Prevent Digestion")
- user.vore_flags &= ~DIGESTABLE
- user.client.prefs.vore_flags &= ~DIGESTABLE
- if(href_list["toggledvor"])
- var/choice = alert(user, "This button is for those who don't like vore at all. Devouring you is currently: [(user.vore_flags & DEVOURABLE) ? "Allowed" : "Prevented"]", "", "Allow Devourment", "Cancel", "Prevent Devourment")
- if(!user || !user.client)
- return
- switch(choice)
- if("Cancel")
+ var/new_name = html_encode(input(usr,"New belly's name:","New Belly") as text|null)
+
+ var/failure_msg
+ if(length(new_name) > BELLIES_NAME_MAX || length(new_name) < BELLIES_NAME_MIN)
+ failure_msg = "Entered belly name length invalid (must be longer than [BELLIES_NAME_MIN], no more than than [BELLIES_NAME_MAX])."
+ // else if(whatever) //Next test here.
+ else
+ for(var/belly in host.vore_organs)
+ var/obj/belly/B = belly
+ if(lowertext(new_name) == lowertext(B.name))
+ failure_msg = "No duplicate belly names, please."
+ break
+
+ if(failure_msg) //Something went wrong.
+ tgui_alert_async(usr, failure_msg, "Error!")
+ return TRUE
+
+ var/obj/belly/NB = new(host)
+ NB.name = new_name
+ host.vore_selected = NB
+ unsaved_changes = TRUE
+ return TRUE
+
+ if("bellypick")
+ host.vore_selected = locate(params["bellypick"])
+ return TRUE
+ if("move_belly")
+ var/dir = text2num(params["dir"])
+ if(LAZYLEN(host.vore_organs) <= 1)
+ to_chat(usr, "You can't sort bellies with only one belly to sort...")
+ return TRUE
+
+ var/current_index = host.vore_organs.Find(host.vore_selected)
+ if(current_index)
+ var/new_index = clamp(current_index + dir, 1, LAZYLEN(host.vore_organs))
+ host.vore_organs.Swap(current_index, new_index)
+ unsaved_changes = TRUE
+ return TRUE
+
+ if("set_attribute")
+ return set_attr(usr, params)
+
+ if("saveprefs")
+ if(!host.copy_to_prefs_vr())
+ tgui_alert_async(usr, "Belly Preferences not saved!", "Error")
+ log_admin("Could not save vore prefs on USER: [usr].")
+ else
+ to_chat(usr, "Belly Preferences were saved!")
+ unsaved_changes = FALSE
+ return TRUE
+ if("reloadprefs")
+ var/alert = tgui_alert(usr, "Are you sure you want to reload character slot preferences? This will remove your current vore organs and eject their contents.","Confirmation",list("Reload","Cancel"))
+ if(alert != "Reload")
return FALSE
- if("Allow Devourment")
- user.vore_flags |= DEVOURABLE
- user.client.prefs.vore_flags |= DEVOURABLE
- if("Prevent Devourment")
- user.vore_flags &= ~DEVOURABLE
- user.client.prefs.vore_flags &= ~DEVOURABLE
-
- if(href_list["toggledfeed"])
- var/choice = alert(user, "This button is to toggle your ability to be fed to others. Feeding predators is currently: [(user.vore_flags & FEEDING) ? "Allowed" : "Prevented"]", "", "Allow Feeding", "Cancel", "Prevent Feeding")
- if(!user || !user.client)
- return
- switch(choice)
- if("Cancel")
+ if(!host.copy_from_prefs_vr())
+ tgui_alert_async(usr, "ERROR: Virgo-specific preferences failed to apply!","Error")
+ else
+ to_chat(usr, "Vore preferences applied from active slot!")
+ unsaved_changes = FALSE
+ return TRUE
+ if("setflavor")
+ var/new_flavor = html_encode(input(usr,"What your character tastes like (400ch limit). This text will be printed to the pred after 'X tastes of...' so just put something like 'strawberries and cream':","Character Flavor",host.vore_taste) as text|null)
+ if(!new_flavor)
return FALSE
- if("Allow Feeding")
- user.vore_flags |= FEEDING
- user.client.prefs.vore_flags |= FEEDING
- if("Prevent Feeding")
- user.vore_flags &= ~FEEDING
- user.client.prefs.vore_flags &= ~FEEDING
- if(href_list["toggledlickable"])
- var/choice = alert(user, "This button is to toggle your ability to be licked. Being licked is currently: [(user.client.prefs.vore_flags & LICKABLE) ? "Allowed" : "Prevented"]", "", "Allow Licking", "Cancel", "Prevent Licking")
- if(!user || !user.client)
- return
- switch(choice)
- if("Cancel")
+ new_flavor = readd_quotes(new_flavor)
+ if(length(new_flavor) > FLAVOR_MAX)
+ tgui_alert_async(usr, "Entered flavor/taste text too long. [FLAVOR_MAX] character limit.","Error!")
+ return FALSE
+ host.vore_taste = new_flavor
+ unsaved_changes = TRUE
+ return TRUE
+ if("setsmell")
+ var/new_smell = html_encode(input(usr,"What your character smells like (400ch limit). This text will be printed to the pred after 'X smells of...' so just put something like 'strawberries and cream':","Character Smell",host.vore_smell) as text|null)
+ if(!new_smell)
return FALSE
- if("Allow Licking")
- user.client.prefs.vore_flags |= LICKABLE
- if("Prevent Licking")
- user.client.prefs.vore_flags &= ~LICKABLE
- //Refresh when interacted with, returning 1 makes vore_look.Topic update
- return TRUE
+ new_smell = readd_quotes(new_smell)
+ if(length(new_smell) > FLAVOR_MAX)
+ tgui_alert_async(usr, "Entered perfume/smell text too long. [FLAVOR_MAX] character limit.","Error!")
+ return FALSE
+ host.vore_smell = new_smell
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_digest")
+ TOGGLE_BITFIELD(host.vore_flags, DIGESTABLE)
+ if(host.client.prefs)
+ COPY_SPECIFIC_BITFIELDS(host.client.prefs.vore_flags, host.vore_flags, DIGESTABLE)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_devour")
+ TOGGLE_BITFIELD(host.vore_flags, DEVOURABLE)
+ if(host.client.prefs)
+ COPY_SPECIFIC_BITFIELDS(host.client.prefs.vore_flags, host.vore_flags, DEVOURABLE)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_feed")
+ TOGGLE_BITFIELD(host.vore_flags, FEEDING)
+ if(host.client.prefs)
+ COPY_SPECIFIC_BITFIELDS(host.client.prefs.vore_flags, host.vore_flags, FEEDING)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_absorbable")
+ TOGGLE_BITFIELD(host.vore_flags, ABSORBABLE)
+ if(host.client.prefs)
+ COPY_SPECIFIC_BITFIELDS(host.client.prefs.vore_flags, host.vore_flags, ABSORBABLE)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_mobvore")
+ TOGGLE_BITFIELD(host.vore_flags, MOBVORE)
+ if(host.client.prefs)
+ COPY_SPECIFIC_BITFIELDS(host.client.prefs.vore_flags, host.vore_flags, MOBVORE)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_vore_sounds")
+ TOGGLE_BITFIELD(host.client.prefs.cit_toggles, EATING_NOISES)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_digestion_sounds")
+ TOGGLE_BITFIELD(host.client.prefs.cit_toggles, DIGESTION_NOISES)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_lickable")
+ TOGGLE_BITFIELD(host.vore_flags, LICKABLE)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_smellable")
+ TOGGLE_BITFIELD(host.vore_flags, SMELLABLE)
+ unsaved_changes = TRUE
+ return TRUE
+
+/datum/vore_look/proc/pick_from_inside(mob/user, params)
+ var/atom/movable/target = locate(params["pick"])
+ var/obj/belly/OB = locate(params["belly"])
+
+ if(!(target in OB))
+ return TRUE // Aren't here anymore, need to update menu
+
+ var/intent = "Examine"
+ if(isliving(target))
+ intent = tgui_alert(usr, "What do you want to do to them?","Query",list("Examine","Help Out","Devour"))
+
+ else if(istype(target, /obj/item))
+ intent = tgui_alert(usr, "What do you want to do to that?","Query",list("Examine","Use Hand"))
+
+ switch(intent)
+ if("Examine") //Examine a mob inside another mob
+ var/list/results = target.examine(host)
+ if(!results || !results.len)
+ results = list("You were unable to examine that. Tell a developer!")
+ to_chat(user, jointext(results, " "))
+ return TRUE
+
+ if("Use Hand")
+ if(host.stat)
+ to_chat(user, "You can't do that in your state!")
+ return TRUE
+
+ host.ClickOn(target)
+ return TRUE
+
+ if(!isliving(target))
+ return
+
+ var/mob/living/M = target
+ switch(intent)
+ if("Help Out") //Help the inside-mob out
+ if(host.stat || host.vore_flags & ABSORBED || M.vore_flags & ABSORBED)
+ to_chat(user, "You can't do that in your state!")
+ return TRUE
+
+ to_chat(user,"You begin to push [M] to freedom!")
+ to_chat(M,"[host] begins to push you to freedom!")
+ to_chat(M.loc,"Someone is trying to escape from inside you!")
+ sleep(50)
+ if(prob(33))
+ OB.release_specific_contents(M)
+ to_chat(user,"You manage to help [M] to safety!")
+ to_chat(M,"[host] pushes you free!")
+ to_chat(OB.owner,"[M] forces free of the confines of your body!")
+ else
+ to_chat(user,"[M] slips back down inside despite your efforts.")
+ to_chat(M," Even with [host]'s help, you slip back inside again.")
+ to_chat(OB.owner,"Your body efficiently shoves [M] back where they belong.")
+ return TRUE
+
+ if("Devour") //Eat the inside mob
+ if(host.stat || host.vore_flags & ABSORBED)
+ to_chat(user,"You can't do that in your state!")
+ return TRUE
+
+ if(!host.vore_selected)
+ to_chat(user,"Pick a belly on yourself first!")
+ return TRUE
+
+ var/obj/belly/TB = host.vore_selected
+ to_chat(user,"You begin to [lowertext(TB.vore_verb)] [M] into your [lowertext(TB.name)]!")
+ to_chat(M,"[host] begins to [lowertext(TB.vore_verb)] you into their [lowertext(TB.name)]!")
+ to_chat(OB.owner,"Someone inside you is eating someone else!")
+
+ sleep(TB.nonhuman_prey_swallow_time) //Can't do after, in a stomach, weird things abound.
+ if((host in OB) && (M in OB)) //Make sure they're still here.
+ to_chat(user,"You manage to [lowertext(TB.vore_verb)] [M] into your [lowertext(TB.name)]!")
+ to_chat(M,"[host] manages to [lowertext(TB.vore_verb)] you into their [lowertext(TB.name)]!")
+ to_chat(OB.owner,"Someone inside you has eaten someone else!")
+ TB.nom_mob(M)
+
+/datum/vore_look/proc/pick_from_outside(mob/user, params)
+ var/intent
+
+ //Handle the [All] choice. Ugh inelegant. Someone make this pretty.
+ if(params["pickall"])
+ intent = tgui_alert(usr, "Eject all, Move all?","Query",list("Eject all","Cancel","Move all"))
+ switch(intent)
+ if("Cancel")
+ return TRUE
+
+ if("Eject all")
+ if(host.stat)
+ to_chat(user,"You can't do that in your state!")
+ return TRUE
+
+ host.vore_selected.release_all_contents()
+ return TRUE
+
+ if("Move all")
+ if(host.stat)
+ to_chat(user,"You can't do that in your state!")
+ return TRUE
+
+ var/obj/belly/choice = tgui_input_list(usr, "Move all where?","Select Belly", host.vore_organs)
+ if(!choice)
+ return FALSE
+
+ for(var/atom/movable/target in host.vore_selected)
+ to_chat(target,"You're squished from [host]'s [lowertext(host.vore_selected)] to their [lowertext(choice.name)]!")
+ host.vore_selected.transfer_contents(target, choice, 1)
+ return TRUE
+ return
+
+ var/atom/movable/target = locate(params["pick"])
+ if(!(target in host.vore_selected))
+ return TRUE // Not in our X anymore, update UI
+ var/list/available_options = list("Examine", "Eject", "Move")
+ if(ishuman(target))
+ available_options += "Transform"
+ intent = tgui_alert(user, "What would you like to do with [target]?", "Vore Pick", available_options)
+ switch(intent)
+ if("Examine")
+ var/list/results = target.examine(host)
+ if(!results || !results.len)
+ results = list("You were unable to examine that. Tell a developer!")
+ to_chat(user, jointext(results, " "))
+ return TRUE
+
+ if("Eject")
+ if(host.stat)
+ to_chat(user,"You can't do that in your state!")
+ return TRUE
+
+ host.vore_selected.release_specific_contents(target)
+ return TRUE
+
+ if("Move")
+ if(host.stat)
+ to_chat(user,"You can't do that in your state!")
+ return TRUE
+
+ var/obj/belly/choice = tgui_input_list(usr, "Move [target] where?","Select Belly", host.vore_organs)
+ if(!choice || !(target in host.vore_selected))
+ return TRUE
+
+ to_chat(target,"You're squished from [host]'s [lowertext(host.vore_selected.name)] to their [lowertext(choice.name)]!")
+ host.vore_selected.transfer_contents(target, choice)
+ return TRUE
+
+ if("Transform")
+ if(host.stat)
+ to_chat(user,"You can't do that in your state!")
+ return TRUE
+
+ var/mob/living/carbon/human/H = target
+ if(!istype(H))
+ return
+
+ return TRUE
+
+/datum/vore_look/proc/set_attr(mob/user, params)
+ if(!host.vore_selected)
+ tgui_alert_async(usr, "No belly selected to modify.")
+ return FALSE
+
+ var/attr = params["attribute"]
+ switch(attr)
+ if("b_name")
+ var/new_name = html_encode(input(usr,"Belly's new name:","New Name") as text|null)
+
+ var/failure_msg
+ if(length(new_name) > BELLIES_NAME_MAX || length(new_name) < BELLIES_NAME_MIN)
+ failure_msg = "Entered belly name length invalid (must be longer than [BELLIES_NAME_MIN], no more than than [BELLIES_NAME_MAX])."
+ // else if(whatever) //Next test here.
+ else
+ for(var/belly in host.vore_organs)
+ var/obj/belly/B = belly
+ if(lowertext(new_name) == lowertext(B.name))
+ failure_msg = "No duplicate belly names, please."
+ break
+
+ if(failure_msg) //Something went wrong.
+ tgui_alert_async(user,failure_msg,"Error!")
+ return FALSE
+
+ host.vore_selected.name = new_name
+ . = TRUE
+ if("b_wetness")
+ host.vore_selected.is_wet = !host.vore_selected.is_wet
+ . = TRUE
+ if("b_wetloop")
+ host.vore_selected.wet_loop = !host.vore_selected.wet_loop
+ . = TRUE
+ if("b_mode")
+ var/list/menu_list = host.vore_selected.digest_modes.Copy()
+ var/new_mode = tgui_input_list(usr, "Choose Mode (currently [host.vore_selected.digest_mode])", "Mode Choice", menu_list)
+ if(!new_mode)
+ return FALSE
+
+ host.vore_selected.digest_mode = new_mode
+ . = TRUE
+ if("b_desc")
+ var/new_desc = html_encode(input(usr,"Belly Description ([BELLIES_DESC_MAX] char limit):","New Description",host.vore_selected.desc) as message|null)
+
+ if(new_desc)
+ new_desc = readd_quotes(new_desc)
+ if(length(new_desc) > BELLIES_DESC_MAX)
+ tgui_alert_async(usr, "Entered belly desc too long. [BELLIES_DESC_MAX] character limit.","Error")
+ return FALSE
+ host.vore_selected.desc = new_desc
+ . = TRUE
+ if("b_msgs")
+ tgui_alert(user,"Setting abusive or deceptive messages will result in a ban. Consider this your warning. Max 150 characters per message (500 for idle messages), max 10 messages per topic.","Really, don't.") // Should remain tgui_alert() (blocking)
+ var/help = " Press enter twice to separate messages. '%pred' will be replaced with your name. '%prey' will be replaced with the prey's name. '%belly' will be replaced with your belly's name. '%count' will be replaced with the number of anything in your belly (will not work for absorbed examine). '%countprey' will be replaced with the number of living prey in your belly (or absorbed prey for absorbed examine)."
+ switch(params["msgtype"])
+ if("dmp")
+ var/new_message = input(user,"These are sent to prey when they expire. Write them in 2nd person ('you feel X'). Avoid using %prey in this type."+help,"Digest Message (to prey)",host.vore_selected.get_messages("dmp")) as message
+ if(new_message)
+ host.vore_selected.set_messages(new_message,"dmp")
+
+ if("dmo")
+ var/new_message = input(user,"These are sent to you when prey expires in you. Write them in 2nd person ('you feel X'). Avoid using %pred in this type."+help,"Digest Message (to you)",host.vore_selected.get_messages("dmo")) as message
+ if(new_message)
+ host.vore_selected.set_messages(new_message,"dmo")
+
+ if("smo")
+ var/new_message = input(user,"These are sent to those nearby when prey struggles. Write them in 3rd person ('X's Y bulges')."+help,"Struggle Message (outside)",host.vore_selected.get_messages("smo")) as message
+ if(new_message)
+ host.vore_selected.set_messages(new_message,"smo")
+
+ if("smi")
+ var/new_message = input(user,"These are sent to prey when they struggle. Write them in 2nd person ('you feel X'). Avoid using %prey in this type."+help,"Struggle Message (inside)",host.vore_selected.get_messages("smi")) as message
+ if(new_message)
+ host.vore_selected.set_messages(new_message,"smi")
+
+ if("em")
+ var/new_message = input(user,"These are sent to people who examine you when this belly has contents. Write them in 3rd person ('Their %belly is bulging')."+help,"Examine Message (when full)",host.vore_selected.get_messages("em")) as message
+ if(new_message)
+ host.vore_selected.set_messages(new_message,"em")
+
+ if("reset")
+ var/confirm = tgui_alert(user,"This will delete any custom messages. Are you sure?","Confirmation",list("Cancel","DELETE"))
+ if(confirm == "DELETE")
+ host.vore_selected.digest_messages_prey = initial(host.vore_selected.digest_messages_prey)
+ host.vore_selected.digest_messages_owner = initial(host.vore_selected.digest_messages_owner)
+ host.vore_selected.struggle_messages_outside = initial(host.vore_selected.struggle_messages_outside)
+ host.vore_selected.struggle_messages_inside = initial(host.vore_selected.struggle_messages_inside)
+ host.vore_selected.examine_messages = initial(host.vore_selected.examine_messages)
+ host.vore_selected.emote_lists = initial(host.vore_selected.emote_lists)
+ . = TRUE
+ if("b_verb")
+ var/new_verb = html_encode(input(usr,"New verb when eating (infinitive tense, e.g. nom or swallow):","New Verb") as text|null)
+
+ if(length(new_verb) > BELLIES_NAME_MAX || length(new_verb) < BELLIES_NAME_MIN)
+ tgui_alert_async(usr, "Entered verb length invalid (must be longer than [BELLIES_NAME_MIN], no longer than [BELLIES_NAME_MAX]).","Error")
+ return FALSE
+
+ host.vore_selected.vore_verb = new_verb
+ . = TRUE
+ if("b_release")
+ var/choice = tgui_input_list(user,"Currently set to [host.vore_selected.release_sound]","Select Sound", GLOB.pred_release_sounds)
+
+ if(!choice)
+ return FALSE
+
+ host.vore_selected.release_sound = choice
+ . = TRUE
+ if("b_releasesoundtest")
+ var/sound/releasetest = GLOB.pred_release_sounds[host.vore_selected.release_sound]
+
+ if(releasetest)
+ SEND_SOUND(user, releasetest)
+ . = FALSE //Testing sound, no changes.
+ if("b_sound")
+ var/choice = tgui_input_list(user,"Currently set to [host.vore_selected.vore_sound]","Select Sound", GLOB.prey_vore_sounds)
+
+ if(!choice)
+ return FALSE
+
+ host.vore_selected.vore_sound = choice
+ . = TRUE
+ if("b_soundtest")
+ var/sound/voretest = GLOB.prey_vore_sounds[host.vore_selected.vore_sound]
+ if(voretest)
+ SEND_SOUND(user, voretest)
+ . = FALSE //Testing sound, no changes.
+ if("b_tastes")
+ host.vore_selected.can_taste = !host.vore_selected.can_taste
+ . = TRUE
+ if("b_bulge_size")
+ var/new_bulge = input(user, "Choose the required size prey must be to show up on examine, ranging from 25% to 200% Set this to 0 for no text on examine.", "Set Belly Examine Size.") as num|null
+ if(new_bulge == null)
+ return FALSE
+ if(new_bulge == 0) //Disable.
+ host.vore_selected.bulge_size = 0
+ to_chat(user,"Your stomach will not be seen on examine.")
+ else if (!ISINRANGE(new_bulge,25,200))
+ host.vore_selected.bulge_size = 0.25 //Set it to the default.
+ to_chat(user,"Invalid size.")
+ else if(new_bulge)
+ host.vore_selected.bulge_size = (new_bulge/100)
+ . = TRUE
+ if("b_escapable")
+ if(host.vore_selected.escapable == 0) //Possibly escapable and special interactions.
+ host.vore_selected.escapable = 1
+ to_chat(usr,"Prey now have special interactions with your [lowertext(host.vore_selected.name)] depending on your settings.")
+ else if(host.vore_selected.escapable == 1) //Never escapable.
+ host.vore_selected.escapable = 0
+ to_chat(usr,"Prey will not be able to have special interactions with your [lowertext(host.vore_selected.name)].")
+ else
+ tgui_alert_async(usr, "Something went wrong. Your stomach will now not have special interactions. Press the button enable them again and tell a dev.","Error") //If they somehow have a varable that's not 0 or 1
+ host.vore_selected.escapable = 0
+ . = TRUE
+ if("b_escapechance")
+ var/escape_chance_input = input(user, "Set prey escape chance on resist (as %)", "Prey Escape Chance") as num|null
+ if(!isnull(escape_chance_input)) //These have to be 'null' because both cancel and 0 are valid, separate options
+ host.vore_selected.escapechance = sanitize_integer(escape_chance_input, 0, 100, initial(host.vore_selected.escapechance))
+ . = TRUE
+ if("b_escapetime")
+ var/escape_time_input = input(user, "Set number of seconds for prey to escape on resist (1-60)", "Prey Escape Time") as num|null
+ if(!isnull(escape_time_input))
+ host.vore_selected.escapetime = sanitize_integer(escape_time_input*10, 10, 600, initial(host.vore_selected.escapetime))
+ . = TRUE
+ if("b_transferchance")
+ var/transfer_chance_input = input(user, "Set belly transfer chance on resist (as %). You must also set the location for this to have any effect.", "Prey Escape Time") as num|null
+ if(!isnull(transfer_chance_input))
+ host.vore_selected.transferchance = sanitize_integer(transfer_chance_input, 0, 100, initial(host.vore_selected.transferchance))
+ . = TRUE
+ if("b_transferlocation")
+ var/obj/belly/choice = tgui_input_list(usr, "Where do you want your [lowertext(host.vore_selected.name)] to lead if prey resists?","Select Belly", (host.vore_organs + "None - Remove" - host.vore_selected))
+
+ if(!choice) //They cancelled, no changes
+ return FALSE
+ else if(choice == "None - Remove")
+ host.vore_selected.transferlocation = null
+ else
+ host.vore_selected.transferlocation = choice.name
+ . = TRUE
+ if("b_absorbchance")
+ var/absorb_chance_input = input(user, "Set belly absorb mode chance on resist (as %)", "Prey Absorb Chance") as num|null
+ if(!isnull(absorb_chance_input))
+ host.vore_selected.absorbchance = sanitize_integer(absorb_chance_input, 0, 100, initial(host.vore_selected.absorbchance))
+ . = TRUE
+ if("b_digestchance")
+ var/digest_chance_input = input(user, "Set belly digest mode chance on resist (as %)", "Prey Digest Chance") as num|null
+ if(!isnull(digest_chance_input))
+ host.vore_selected.digestchance = sanitize_integer(digest_chance_input, 0, 100, initial(host.vore_selected.digestchance))
+ . = TRUE
+ if("b_del")
+ var/alert = tgui_alert(usr, "Are you sure you want to delete your [lowertext(host.vore_selected.name)]?","Confirmation",list("Cancel","Delete"))
+ if(!(alert == "Delete"))
+ return FALSE
+
+ var/failure_msg = ""
+
+ var/dest_for //Check to see if it's the destination of another vore organ.
+ for(var/belly in host.vore_organs)
+ var/obj/belly/B = belly
+ if(B.transferlocation == host.vore_selected)
+ dest_for = B.name
+ failure_msg += "This is the destiantion for at least '[dest_for]' belly transfers. Remove it as the destination from any bellies before deleting it. "
+ break
+
+ if(host.vore_selected.contents.len)
+ failure_msg += "You cannot delete bellies with contents! " //These end with spaces, to be nice looking. Make sure you do the same.
+ if(host.vore_selected.immutable)
+ failure_msg += "This belly is marked as undeletable. "
+ if(host.vore_organs.len == 1)
+ failure_msg += "You must have at least one belly. "
+
+ if(failure_msg)
+ tgui_alert_async(user,failure_msg,"Error!")
+ return FALSE
+
+ qdel(host.vore_selected)
+ host.vore_selected = host.vore_organs[1]
+ . = TRUE
+
+ if(.)
+ unsaved_changes = TRUE
diff --git a/code/modules/zombie/organs.dm b/code/modules/zombie/organs.dm
index 2681f781a9..a724d26314 100644
--- a/code/modules/zombie/organs.dm
+++ b/code/modules/zombie/organs.dm
@@ -45,7 +45,7 @@
if(!owner)
return
if(!(src in owner.internal_organs))
- Remove(owner)
+ INVOKE_ASYNC(src,.proc/Remove,owner)
if(owner.mob_biotypes & MOB_MINERAL)//does not process in inorganic things
return
if (causes_damage && !iszombie(owner) && owner.stat != DEAD)
diff --git a/config/antag_rep.txt b/config/antag_rep.txt
deleted file mode 100644
index e8a7250686..0000000000
--- a/config/antag_rep.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-## Custom antag reputation values
-## List of job titles followed by antag rep value, all prefixed with ANTAG_REP. See code/modules/jobs/job_types for titles
-## e.g.
-## ANTAG_REP Captain 10
-## ANTAG_REP Assistant 0
diff --git a/config/config.txt b/config/config.txt
index 611d63cb24..c0c683373d 100644
--- a/config/config.txt
+++ b/config/config.txt
@@ -1,18 +1,7 @@
# You can use the "$include" directive to split your configs however you want
-$include game_options.txt
-$include dbconfig.txt
-$include comms.txt
-$include antag_rep.txt
-$include resources.txt
-# Cit-specific imports
-$include donator_groupings.txt
-$include dynamic_config.txt
-$include plushies/defines.txt
-$include job_threats.txt
-$include policy.txt
-$include persistence.txt
-$include respawns.txt
+# MAKE SURE ENTRIES ARE SORTED IN THE SAME FASHION THEY ARE IN THE .dm
+# if you don't do this i will find you and put lemons on your eyes.
# You can use the @ character at the beginning of a config option to lock it from being edited in-game
# Example usage:
@@ -22,523 +11,31 @@ $include respawns.txt
# Which explicitly disables LOG_TWITTER, as well as locking it.
# There are various options which are hard-locked for security reasons.
-## Server name: This appears at the top of the screen in-game and in the BYOND hub. Uncomment and replace 'tgstation' with the name of your choice.
-# SERVERNAME tgstation
-## Server tagline: This will appear right below the server's title.
-# SERVERTAGLINE A generic TG-based server
-
-## Server SQL name: This is the name used to identify the server to the SQL DB, distinct from SERVERNAME as it must be at most 32 characters.
-# SERVERSQLNAME tgstation
-
-## Station name: The name of the station as it is referred to in-game. If commented out, the game will generate a random name instead.
-STATIONNAME Space Station 13
-
-## Put on byond hub: Uncomment this to put your server on the byond hub.
-#HUB
-
-## Lobby time: This is the amount of time between rounds that players have to setup their characters and be ready.
-LOBBY_COUNTDOWN 120
-
-## Round End Time: This is the amount of time after the round ends that players have to murder death kill each other.
-ROUND_END_COUNTDOWN 90
-
-## Comment this out if you want to use the SQL based admin system, the legacy system uses admins.txt.
-## You need to set up your database to use the SQL based system.
-## This flag is automatically enabled if SQL_ENABLED isn't
-ADMIN_LEGACY_SYSTEM
-
-##Uncomment this to stop any admins loaded by the legacy system from having their rank edited by the permissions panel
-#PROTECT_LEGACY_ADMINS
-
-##Uncomment this to stop any ranks loaded by the legacy system from having their flags edited by the permissions panel
-#PROTECT_LEGACY_RANKS
-
-##Uncomment this to have admin ranks only loaded from the legacy admin_ranks.txt
-##If enabled, each time admins are loaded ranks the database will be updated with the current ranks and their flags
-#LOAD_LEGACY_RANKS_ONLY
-
-## Comment this out if you want to use the SQL based banning system. The legacy systems use the files in the data folder. You need to set up your database to use the SQL based system.
-BAN_LEGACY_SYSTEM
-
-## Comment this out to stop locally connected clients from being given the almost full access !localhost! admin rank
-ENABLE_LOCALHOST_RANK
-
-## Comment this out if you want to use the SQL based mentor system, the legacy system uses mentors.txt.
-## You need to set up your database to use the SQL based system.
-## This flag is automatically enabled if SQL_ENABLED isn't
-MENTOR_LEGACY_SYSTEM
-
-#Mentors only see ckeys by default. Uncomment to have them only see mob name
-#MENTORS_MOBNAME_ONLY
-
-## Uncomment this entry to have certain jobs require your account to be at least a certain number of days old to select. You can configure the exact age requirement for different jobs by editing
-## the minimal_player_age variable in the files in folder /code/game/jobs/job/.. for the job you want to edit. Set minimal_player_age to 0 to disable age requirement for that job.
-## REQUIRES the database set up to work. Keep it hashed if you don't have a database set up.
-## NOTE: If you have just set-up the database keep this DISABLED, as player age is determined from the first time they connect to the server with the database up. If you just set it up, it means
-## you have noone older than 0 days, since noone has been logged yet. Only turn this on once you have had the database up for 30 days.
-#USE_AGE_RESTRICTION_FOR_JOBS
-
-## Uncomment this to have the job system use the player's account creation date, rather than the when they first joined the server for job timers.
-#USE_ACCOUNT_AGE_FOR_JOBS
-
-## Unhash this to track player playtime in the database. Requires database to be enabled.
-#USE_EXP_TRACKING
-## Unhash this to enable playtime requirements for head jobs.
-#USE_EXP_RESTRICTIONS_HEADS
-## Unhash this to override head jobs' playtime requirements with this number of hours.
-## Leave this commented out to use the values defined in the job datums. Values in the datums are stored as minutes.
-#USE_EXP_RESTRICTIONS_HEADS_HOURS 3
-## Unhash this to change head jobs' playtime requirements so that they're based on department playtime, rather than crew playtime.
-#USE_EXP_RESTRICTIONS_HEADS_DEPARTMENT
-## Unhash this to enable playtime requirements for certain non-head jobs, like Engineer and Scientist.
-#USE_EXP_RESTRICTIONS_OTHER
-## Allows admins to bypass job playtime requirements.
-#USE_EXP_RESTRICTIONS_ADMIN_BYPASS
-
-## log OOC channel
-LOG_OOC
-
-## log client Say
-LOG_SAY
-
-## log admin actions
-LOG_ADMIN
-
-## log admin chat
-LOG_ADMINCHAT
-
-## log client access (logon/logoff)
-LOG_ACCESS
-
-## log game actions (start of round, results, etc.)
-LOG_GAME
-
-## log player votes
-LOG_VOTE
-
-## log player crafting
-LOG_CRAFT
-
-## log client Whisper
-LOG_WHISPER
-
-## log emotes
-LOG_EMOTE
-
-## log attack messages
-LOG_ATTACK
-
-## log pda messages
-LOG_PDA
-
-## log telecomms messages
-LOG_TELECOMMS
-
-## log prayers
-LOG_PRAYER
-
-## log lawchanges
-LOG_LAW
-
-## log crew manifest to seperate file
-LOG_MANIFEST
-
-## log job divide debugging information
-#LOG_JOB_DEBUG
-
-## log all world.Topic() calls
-# LOG_WORLD_TOPIC
-
-## enables use of the proc twitterize() that lets you take a large list of strings and turn it into a JSON file of tweet sized strings.
-## As an example of how this could be """useful""" look towards Poly (https://twitter.com/Poly_the_Parrot)
-# LOG_TWITTER
-
-## Enable logging pictures
-# LOG_PICTURES
-
-## log virus and actions
-LOG_VIRUS
-
-##Log camera pictures - Must have picture logging enabled
-PICTURE_LOGGING_CAMERA
-
-## period of time in seconds for players to be considered inactive
-# INACTIVITY_PERIOD 300
-
-## period of time in seconds for players to be considered afk and kickable
-# AFK_PERIOD 600
-
-## disconnect players who are considered afk
-# KICK_INACTIVE
-
-## Comment this out to stop admins being able to choose their personal ooccolor
-ALLOW_ADMIN_OOCCOLOR
-
-## Job slot open/close by identification consoles delay in seconds
-ID_CONSOLE_JOBSLOT_DELAY 30
-
-## allow players to initiate a restart vote
-#ALLOW_VOTE_RESTART
-
-## allow players to initate a mode-change start
-#ALLOW_VOTE_MODE
-
-## min delay (deciseconds) between voting sessions (default 10 minutes)
-VOTE_DELAY 6000
-
-## time period (deciseconds) which voting session will last (default 1 minute)
-VOTE_PERIOD 600
-
-## autovote initial delay (deciseconds) before first automatic transfer vote call (default 120 minutes)
-## Set to 0 to disable the subsystem altogether.
-VOTE_AUTOTRANSFER_INITIAL 72000
-
-## autovote delay (deciseconds) before sequential automatic transfer votes are called (default 30 minutes)
-VOTE_AUTOTRANSFER_INTERVAL 18000
-
-## autovote maximum votes until automatic transfer call. (default 4)
-## Set to 0 to force automatic crew transfer after the 'vote_autotransfer_initial' elapsed.
-## Set to -1 to disable the maximum votes cap.
-VOTE_AUTOTRANSFER_MAXIMUM 4
-
-## prevents dead players from voting or starting votes
-# NO_DEAD_VOTE
-
-## players' votes default to "No vote" (otherwise, default to "No change")
-# DEFAULT_NO_VOTE
-
-## disables calling del(src) on newmobs if they logout before spawnin in
-# DONT_DEL_NEWMOB
-
-## set a hosted by name for unix platforms
-HOSTEDBY Yournamehere
-
-## Set to jobban "Guest-" accounts from Captain, HoS, HoP, CE, RD, CMO, Warden, Security, Detective, and AI positions.
-## Set to 1 to jobban them from those positions, set to 0 to allow them.
-# GUEST_JOBBAN
-
-## Uncomment this to stop people connecting to your server without a registered ckey. (i.e. guest-* are all blocked from connecting)
-GUEST_BAN
-
-## Comment this out to disable checking for the cid randomizer dll. (disabled if database isn't enabled or connected)
-CHECK_RANDOMIZER
-
-## IPINTEL:
-## This allows you to detect likely proxies by checking ips against getipintel.net
-## Rating to warn at: (0.9 is good, 1 is 100% likely to be a spammer/proxy, 0.8 is 80%, etc) anything equal to or higher then this number triggers an admin warning
-#IPINTEL_RATING_BAD 0.9
-## Contact email, (required to use the service, leaving blank or default disables IPINTEL)
-#IPINTEL_EMAIL ch@nge.me
-## How long to save good matches (ipintel rate limits to 15 per minute and 500 per day. so this shouldn't be too low, getipintel.net suggests 6 hours, time is in hours) (Your ip will get banned if you go over 500 a day too many times)
-#IPINTEL_SAVE_GOOD 12
-## How long to save bad matches (these numbers can change as ips change hands, best not to save these for too long in case somebody gets a new ip used by a spammer/proxy before.)
-#IPINTEL_SAVE_BAD 3
-## Domain name to query (leave commented out for the default, only needed if you pay getipintel.net for more querys)
-#IPINTEL_DOMAIN check.getipintel.net
-
-## Uncomment to allow web client connections
-#ALLOW_WEBCLIENT
-
-## Uncomment to restrict web client connections to byond members
-## This makes for a nice pay gate to cut down on ban evading, as the webclient's cid system isn't that great
-## byond membership starts at $10 for 3 months, so to use the webclient to evade, they would have sink 10 bucks in each evade.
-#WEBCLIENT_ONLY_BYOND_MEMBERS
-
-## Set to prevent anyone but those ckeys listed in config/whitelist.txt and config/admins.txt from joining your server
-#USEWHITELIST
-
-## set a server location for world reboot. Don't include the byond://, just give the address and port.
-## Don't set this to the same server, BYOND will automatically restart players to the server when it has restarted.
-# SERVER ss13.example.com:2506
-
-## forum address
-# FORUMURL https://citadel-station.net/forum/
-
-## Wiki address
-# WIKIURL https://katlin.dog/citadel-wiki
-
-## Rules address
-# RULESURL https://katlin.dog/citadel-rules/main
-
-## Github address
-# GITHUBURL https://github.com/Citadel-Station-13/Citadel-Station-13
-
-## Round specific stats address
-## Link to round specific parsed logs; IE statbus. It is appended with the RoundID automatically by ticker/Reboot()
-## This will take priority over the game logs address during reboot.
-## Example: https://atlantaned.space/statbus/round.php?round=
-# ROUNDSTATSURL http://citadel-station.net/slimbus/
-
-## Game Logs address
-## Incase you don't have a fancy parsing system, but still want players to be able to find where you keep your server's logs.
-## Example: https://tgstation13.org/parsed-logs/basil/data/logs/
-# GAMELOGURL
-
-## Github repo id
-##This can be found by going to https://api.github.com/users//repos
-##Or https://api.github.com/orgs//repos if the repo owner is an organization
-# GITHUBREPOID 62485194
-
-## Ban appeals URL - usually for a forum or wherever people should go to contact your admins.
-# BANAPPEALS https://citadel-station.net/forum/viewforum.php?f=8&sid=a0ce5331d5594ef6d49661609c6f4ff9
-
-## System command that invokes youtube-dl, used by Play Internet Sound.
-## You can install youtube-dl with
-## "pip install youtube-dl" if you have pip installed
-## from https://github.com/rg3/youtube-dl/releases
-## or your package manager
-## The default value assumes youtube-dl is in your system PATH
-# INVOKE_YOUTUBEDL youtube-dl
-
-## In-game features
-##Toggle for having jobs load up from the .txt
-# LOAD_JOBS_FROM_TXT
-
-## Uncomment this to forbid admins from possessing the singularity.
-#FORBID_SINGULO_POSSESSION
-
-## Uncomment to show a popup 'reply to' window to every non-admin that receives an adminPM.
-## The intention is to make adminPMs more visible. (although I fnd popups annoying so this defaults to off)
-#POPUP_ADMIN_PM
-
-## Uncomment to allow special 'Easter-egg' events on special holidays such as seasonal holidays and stuff like 'Talk Like a Pirate Day' :3 YAARRR
-ALLOW_HOLIDAYS
-
-## Uncomment to show the names of the admin sending a pm from IRC instead of showing as a stealthmin.
-#SHOW_IRC_NAME
-
-## Defines the ticklimit for subsystem initialization (In percents of a byond tick). Lower makes world start smoother. Higher makes it faster.
-##This is currently a testing optimized setting. A good value for production would be 98.
-TICK_LIMIT_MC_INIT 500
-
-##Defines the ticklag for the world. Ticklag is the amount of time between game ticks (aka byond ticks) (in 1/10ths of a second).
-## This also controls the client network update rate, as well as the default client fps
-TICKLAG 0.5
-
-##Can also be set as per-second value, the following value is identical to the above.
-#FPS 20
-
-## Comment this out to disable automuting
-#AUTOMUTE_ON
-
-## Uncomment this to let players see their own notes (they can still be set by admins only)
-#SEE_OWN_NOTES
-
-### Comment these two out to prevent notes fading out over time for admins.
-## Notes older then this will start fading out.
-NOTE_FRESH_DAYS 91.31055
-## Notes older then this will be completely faded out.
-NOTE_STALE_DAYS 365.2422
-
-##Note: all population caps can be used with each other if desired.
-
-## Uncomment for 'soft' population caps, players will be warned while joining if the living crew exceeds the listed number.
-#SOFT_POPCAP 100
-
-## Message for soft cap
-SOFT_POPCAP_MESSAGE Be warned that the server is currently serving a high number of users, consider using alternative game servers.
-
-## Uncomment for 'hard' population caps, players will not be allowed to spawn if the living crew exceeds the listed number, though they may still observe or wait for the living crew to decrease in size.
-#HARD_POPCAP 150
-
-## Message for hard cap
-HARD_POPCAP_MESSAGE The server is currently serving a high number of users, You cannot currently join. You may wait for the number of living crew to decline, observe, or find alternative servers.
-
-## Uncomment for 'extreme' population caps, players will not be allowed to join the server if living crew exceeds the listed number.
-#EXTREME_POPCAP 200
-
-## Message for extreme cap
-EXTREME_POPCAP_MESSAGE The server is currently serving a high number of users, find alternative servers.
-
-## Notify admins when a new player connects for the first x days a player's been around. (0 for first connection only, -1 for never)
-## Requres database
-NOTIFY_NEW_PLAYER_AGE 0
-
-## Notify admins when a player connects if their byond account was created in the last X days
-## Requires database
-NOTIFY_NEW_PLAYER_ACCOUNT_AGE 1
-
-## Notify the irc channel when a new player makes their first connection
-## Requres database
-#IRC_FIRST_CONNECTION_ALERT
-
-## Deny all new connections by ckeys we haven't seen before (exempts admins and only denies the connection if the database is enabled and connected)
-## Requires database
-#PANIC_BUNKER
-
-## If a player connects during a bunker with less then or this amount of living time (Minutes), we deny the connection
-#PANIC_BUNKER_LIVING 90
-
-## The message the Panic Bunker gives when someone is rejected by it
-## %minutes% is replaced with PANIC_BUNKER_LIVING on runtime, remove it if you don't want this
-#PANIC_BUNKER_MESSAGE Sorry, but the server is currently not accepting connections from players with less than %minutes% minutes of living time.
-
-## If panic bunker is on and a player is rejected (see above), attempt to send them to this connected server (see below) instead.
-## You probably want this to be the same as CROSS_SERVER_ADDRESS
-#PANIC_SERVER_ADDRESS byond://address:port
-
-##Name of the place to send people rejected by the bunker
-#PANIC_SERVER_NAME [Put the name here]
-
-##Automated age verification, comment this out to not ask new users if they are 18+
-#AGE_VERIFICATION
-
-## Uncomment to have the changelog file automatically open when a user connects and hasn't seen the latest changelog
-#AGGRESSIVE_CHANGELOG
-
-## Comment this out if you've used the mass conversion sql proc for notes or want to stop converting notes
-AUTOCONVERT_NOTES
-
-## Comment this out to stop admin messages sent anytime an admin disconnects from a round in play, you can edit the messages in admin.dm
-ANNOUNCE_ADMIN_LOGOUT
-
-## Uncomment to have an admin message sent anytime an admin connects to a round in play, you can edit the messages in admin.dm
-#ANNOUNCE_ADMIN_LOGIN
-
-## Map rotation
-## You should edit maps.txt to match your configuration when you enable this.
-MAPROTATION
-
-## TG-style map rotation
-## By default, Citadel uses a more traditional method of map voting, where at the end of a round, players are given a full upfront vote.
-## This PR will disable that, and will make the server use TG's map rotation instead.
-#TGSTYLE_MAPROTATION
-
-## Map voting
-## Allows players to vote for their preffered map
-## When it's set to zero, the map will be randomly picked each round
-ALLOW_MAP_VOTING 1
-
-## Map voting type
-## Determines what kind of vote the map vote is
-## Options are:
-## PLURALITY (default, only vote for one option)
-## APPROVAL (can vote for as many as you want), I
-## IRV (vote by ranked choice, winner determined by instant runoff algorithm)
-## SCORE (give individual rankings of each choice, winner determined by majority judgement algorithm)
-MAP_VOTE_TYPE APPROVAL
-
-## Map rotate chance delta
-## This is the chance of map rotation factored to the round length.
-## A value of 1 would mean the map rotation chance is the round length in minutes (hour long round == 60% rotation chance)
-## A value of 0.5 would mean the map rotation chance is half of the round length in minutes (hour long round == 30% rotation chance)
-#MAPROTATIONCHANCEDELTA 0.75
-
-## AUTOADMIN
-## The default admin rank
-AUTOADMIN_RANK Game Master
-
-## Uncomment to automatically give that admin rank to all players
-#AUTOADMIN
-
-## CLIENT VERSION CONTROL
-## This allows you to configure the minimum required client version, as well as a warning version, and message for both.
-## These trigger for any version below (non-inclusive) the given version, so 510 triggers on 509 or lower.
-## These messages will be followed by one stating the clients current version and the required version for clarity.
-## If CLIENT_WARN_POPUP is uncommented a popup window with the message will be displayed instead
-#CLIENT_WARN_VERSION 511
-#CLIENT_WARN_POPUP
-#CLIENT_WARN_MESSAGE Byond released 511 as the stable release. You can set the framerate your client runs at, which makes the game feel very different and cool. Shortly after its release we will end up using 511 client features and you will be forced to update.
-CLIENT_ERROR_VERSION 511
-CLIENT_ERROR_MESSAGE Your version of byond is not supported. Please upgrade.
-## The minimum build needed for joining the server, if using 512, a good minimum build would be 1421 as that disables the Middle Mouse Button exploit.
-CLIENT_ERROR_BUILD 1421
-
-## TOPIC RATE LIMITING
-## This allows you to limit how many topic calls (clicking on an interface window) the client can do in any given game second and/or game minute.
-## Admins are exempt from these limits.
-## Hitting the minute limit notifies admins.
-## Set to 0 or comment out to disable.
-SECOND_TOPIC_LIMIT 10
-
-MINUTE_TOPIC_LIMIT 100
-
-
-## CLICK RATE LIMITING
-## Same as above, but applies to clicking on objects in the game window.
-## This should be a higher then the interface limit to allow for the spam clickly nature of most battles.
-## Admins are exempt from these limits.
-## Hitting the minute limit notifies admins.
-## Set to 0 to disable.
-SECOND_CLICK_LIMIT 15
-
-MINUTE_CLICK_LIMIT 400
-
-##Error handling related options
-## The "cooldown" time for each occurence of a unique error
-#ERROR_COOLDOWN 600
-## How many occurences before the next will silence them
-#ERROR_LIMIT 90
-## How long a unique error will be silenced for
-#ERROR_SILENCE_TIME 6000
-##How long to wait between messaging admins about occurences of a unique error
-#ERROR_MSG_DELAY 50
-
-## Chat Announce Options
-## Various messages to be sent to game chats
-## Uncommenting these will enable them, by default they will be broadcast to Game chat channels on TGS3 or non-admin channels on TGS4
-## If using TGS4, the string option can be set as a chat channel tag to limit the message to channels of that tag type (case-sensitive)
-## i.e. CHAT_ANNOUNCE_NEW_GAME chat_channel_tag
-
-## Send a message with the station name starting a new game
-#CHAT_ANNOUNCE_NEW_GAME
-
-## Allow admin hrefs that don't use the new token system, will eventually be removed
-DEBUG_ADMIN_HREFS
-
-###Master Controller High Pop Mode###
-
-##The Master Controller(MC) is the primary system controlling timed tasks and events in SS13 (lobby timer, game checks, lighting updates, atmos, etc)
-##Default base MC tick rate (1 = process every "byond tick" (see: tick_lag/fps config settings), 2 = process every 2 byond ticks, etc)
-## Setting this to 0 will prevent the Master Controller from ticking
-BASE_MC_TICK_RATE 1
-
-##High population MC tick rate
-## Byond rounds timer values UP, but the tick rate is modified with heuristics during lag spites so setting this to something like 2
-## will make it run every 2 byond ticks, but will also double the effect of anti-lag heuristics. You can instead set it to something like
-## 1.1 to make it run every 2 byond ticks, but only increase the effect of anti-lag heuristics by 10%. or 1.5 for 50%.
-## (As an aside, you could in theory also reduce the effect of anti-lag heuristics in the base tick rate by setting it to something like 0.5)
-HIGH_POP_MC_TICK_RATE 1.1
-
-##Engage high pop mode if player count raises above this (Player in this context means any connected user. Lobby, ghost or in-game all count)
-HIGH_POP_MC_MODE_AMOUNT 65
-
-##Disengage high pop mode if player count drops below this
-DISABLE_HIGH_POP_MC_MODE_AMOUNT 60
-
-## Uncomment to prevent the world from sleeping while no players are connected after initializations
-#RESUME_AFTER_INITIALIZATIONS
-
-## Uncomment to set the number of /world/Reboot()s before the DreamDaemon restarts itself. 0 means restart every round. Requires tgstation server tools.
-#ROUNDS_UNTIL_HARD_RESTART 10
-
-## Number of days for an individual panic bunker passthrough entry to be wiped. Note that they're also wiped as soon as a player is in the database.
-#MAX_BUNKER_DAYS 7
-
-##Default screen resolution, in tiles.
-## By default, this is 15x15, which gets simplified to 7 by BYOND, as it is a 1:1 screen ratio.
-## For reference, Goonstation uses a resolution of 21x15 for it's widescreen mode.
-## Do note that changing this value will affect the title screen. The title screen will have to be updated manually if this is changed.
-DEFAULT_VIEW 21x15
-
-### FAIL2TOPIC:
-### Automated IP bans for world/Topic() spammers
-### NOTE FOR WINDOWS HOSTS: This requires you to be running dreamdaemon as an administrator for it to work at all. TGS3 handles this automatically, and honestly there's no reason not to be using TGS3 if you're hosting on Windows.
-### NOTE FOR LINUX HOSTS: This requires manual setup of iptables. Beware that improper configuration of this can and will irreversibly fuck up a server, so please don't tinker with it if you don't know what you're doing.
-## Enabled
-#FAIL2TOPIC_ENABLED
-## Minimum wait time in deciseconds between valid requests
-FAIL2TOPIC_RATE_LIMIT 10
-## Number of requests after breaching rate limit that triggers a ban
-FAIL2TOPIC_MAX_FAILS 5
-## Firewall rule name used on physical server
-## FOR LINUX HOSTS: This is used as the chain name. The iptables chain doesn't get created or hooked up to INPUT automatically, so you'll have to get that set up yourself. Recommended name: BYOND
-FAIL2TOPIC_RULE_NAME _dd_fail2topic
-
-## Enable automatic profiling - Byond 513.1506 and newer only.
-#AUTO_PROFILE
-
-## Uncomment to enable global ban DB using the provided URL. The API should expect to receive a ckey at the end of the URL.
-## More API details can be found here: https://centcom.melonmesa.com
-CENTCOM_BAN_DB https://centcom.melonmesa.com/ban/search
+$include entries/admin.txt
+$include entries/alert.txt
+$include entries/antag_rep.txt
+$include entries/comms.txt
+$include entries/connections.txt
+$include entries/dbconfig.txt
+$include entries/debris.txt
+$include entries/donator.txt
+$include entries/dynamic.txt
+$include entries/fetish_content.txt
+$include entries/gamemodes.txt
+$include entries/general.txt
+$include entries/jexp.txt
+$include entries/logging.txt
+$include entries/movespeed.txt
+$include entries/persistence.txt
+$include entries/policy.txt
+$include entries/resources.txt
+$include entries/respawns.txt
+$include entries/security.txt
+$include entries/server.txt
+$include entries/stamina_combat.txt
+$include entries/threat.txt
+$include entries/urls.txt
+$include entries/vote.txt
+
+$include plushies/defines.txt
diff --git a/config/donator_groupings.txt b/config/donator_groupings.txt
deleted file mode 100644
index b26d1efe22..0000000000
--- a/config/donator_groupings.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-#this is a bad system but I'm lazy so it piggybacks off config loader system.
-#Specify group followed by ckey for each ckey.
-
-#TIER_1_DONATORS test_ckey
-
-#TIER_2_DONATORS test_ckey
-
-#TIER_3_DONATORS test_ckey
diff --git a/config/entries/admin.txt b/config/entries/admin.txt
new file mode 100644
index 0000000000..883bda9422
--- /dev/null
+++ b/config/entries/admin.txt
@@ -0,0 +1,79 @@
+## Comment this out if you want to use the SQL based admin system, the legacy system uses admins.txt.
+## You need to set up your database to use the SQL based system.
+## This flag is automatically enabled if SQL_ENABLED isn't
+ADMIN_LEGACY_SYSTEM
+
+##Uncomment this to stop any admins loaded by the legacy system from having their rank edited by the permissions panel
+#PROTECT_LEGACY_ADMINS
+
+##Uncomment this to stop any ranks loaded by the legacy system from having their flags edited by the permissions panel
+#PROTECT_LEGACY_RANKS
+
+##Uncomment this to have admin ranks only loaded from the legacy admin_ranks.txt
+##If enabled, each time admins are loaded ranks the database will be updated with the current ranks and their flags
+#LOAD_LEGACY_RANKS_ONLY
+
+## Comment this out if you want to use the SQL based banning system. The legacy systems use the files in the data folder. You need to set up your database to use the SQL based system.
+BAN_LEGACY_SYSTEM
+
+## Comment this out to stop locally connected clients from being given the almost full access !localhost! admin rank
+ENABLE_LOCALHOST_RANK
+
+## Comment this out if you want to use the SQL based mentor system, the legacy system uses mentors.txt.
+## You need to set up your database to use the SQL based system.
+## This flag is automatically enabled if SQL_ENABLED isn't
+MENTOR_LEGACY_SYSTEM
+
+#Mentors only see ckeys by default. Uncomment to have them only see mob name
+#MENTORS_MOBNAME_ONLY
+
+## Uncomment this to forbid admins from possessing the singularity.
+#FORBID_SINGULO_POSSESSION
+
+## Uncomment to show a popup 'reply to' window to every non-admin that receives an adminPM.
+## The intention is to make adminPMs more visible. (although I fnd popups annoying so this defaults to off)
+#POPUP_ADMIN_PM
+
+## Uncomment this to let players see their own notes (they can still be set by admins only)
+#SEE_OWN_NOTES
+
+### Comment these two out to prevent notes fading out over time for admins.
+## Notes older then this will start fading out.
+NOTE_FRESH_DAYS 91.31055
+## Notes older then this will be completely faded out.
+NOTE_STALE_DAYS 365.2422
+
+## Comment this out if you've used the mass conversion sql proc for notes or want to stop converting notes
+AUTOCONVERT_NOTES
+
+## Comment this out to stop admin messages sent anytime an admin disconnects from a round in play, you can edit the messages in admin.dm
+ANNOUNCE_ADMIN_LOGOUT
+
+## Uncomment to have an admin message sent anytime an admin connects to a round in play, you can edit the messages in admin.dm
+#ANNOUNCE_ADMIN_LOGIN
+
+## More API details can be found here: https://centcom.melonmesa.com
+CENTCOM_BAN_DB https://centcom.melonmesa.com/ban/search
+
+## AUTOADMIN
+## The default admin rank
+AUTOADMIN_RANK Game Master
+
+## Uncomment to automatically give that admin rank to all players
+#AUTOADMIN
+
+## Comment this out to stop admins being able to choose their personal ooccolor
+ALLOW_ADMIN_OOCCOLOR
+
+## Set to jobban "Guest-" accounts from Captain, HoS, HoP, CE, RD, CMO, Warden, Security, Detective, and AI positions.
+## Set to 1 to jobban them from those positions, set to 0 to allow them.
+# GUEST_JOBBAN
+
+## Uncomment this to stop people connecting to your server without a registered ckey. (i.e. guest-* are all blocked from connecting)
+GUEST_BAN
+
+## Comment this out to disable automuting
+#AUTOMUTE_ON
+
+## Allow admin hrefs that don't use the new token system, will eventually be removed
+DEBUG_ADMIN_HREFS
diff --git a/config/entries/alert.txt b/config/entries/alert.txt
new file mode 100644
index 0000000000..5a03eadaec
--- /dev/null
+++ b/config/entries/alert.txt
@@ -0,0 +1,13 @@
+## ALERT LEVELS ###
+ALERT_GREEN All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced.
+ALERT_BLUE_UPTO The station has received reliable information about potential threats to the station. Security staff may have weapons visible, random searches are permitted.
+ALERT_BLUE_DOWNTO Significant confirmed threats have been neutralized. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still permitted.
+ALERT_AMBER_UPTO There are signficant confirmed threats to the station. Security staff may have weapons unholstered at all times. Random searches are allowed and advised.
+ALERT_AMBER_DOWNTO The immediate threat has passed. Security is no longer authorized to use lethal force, but may continue to have weapons drawn. Access requirements have been restored.
+ALERT_RED_UPTO There is an immediate serious threat to the station. Security is now authorized to use lethal force. Additionally, access requirements on some machines have been lifted.
+ALERT_RED_DOWNTO The station's destruction has been averted. There is still however an immediate serious threat to the station. Security is still authorized to use lethal force.
+ALERT_DELTA Destruction of the station is imminent. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.
+
+## Determines the minimum alert level for the security cyborg model to be chosen
+## 0: Green, 1:Blue, 2:Amber, 3:Red, 4:Delta
+MINIMUM_SECBORG_ALERT 3
diff --git a/config/entries/antag_rep.txt b/config/entries/antag_rep.txt
new file mode 100644
index 0000000000..6cd9315a0c
--- /dev/null
+++ b/config/entries/antag_rep.txt
@@ -0,0 +1,19 @@
+## disclaimer: this is a confusing file. reading and understanding antag rep code is recommended for future headmins/server leads.
+
+## Use the antagonist reputation system
+# ANTAG_REP
+
+## Maximum antag roll ticketts someone can have
+# ANTAG_REP_MAXIMUM 200
+
+## "Free" tickets someone gets on roll
+# DEFAULT_ANTAG_TICKETS 100
+
+## Maximum **STORED** tickets used ontop of default per roll
+# MAX_TICKETS_PER_ROLL 100
+
+## Custom antag reputation values
+## List of job titles followed by antag rep value, all prefixed with ANTAG_REP. See code/modules/jobs/job_types for titles
+## e.g.
+## ANTAG_REP Captain 10
+## ANTAG_REP Assistant 0
diff --git a/config/comms.txt b/config/entries/comms.txt
similarity index 78%
rename from config/comms.txt
rename to config/entries/comms.txt
index ae336d484b..7af6a758d3 100644
--- a/config/comms.txt
+++ b/config/entries/comms.txt
@@ -7,9 +7,12 @@
#CROSS_SERVER ServerName byond:\\address:port
## Name that the server calls itself in communications
-#CROSS_COMMS_NAME
+# CROSS_COMMS_NAME Citadel Main
## Network-name used for cross-server broadcasts made from communication consoles.
## Servers that do not match this network-name will have their messages discarded.
## Leaving this commented will allow all messages through, regardless of network.
#CROSS_COMMS_NETWORK default_network
+
+## CITADEL CONFIG: List of cross server URLs, same as CROSS_SERVER, to send bunker override messages for
+## Format is the same as CROSS_SERVER.
diff --git a/config/entries/connections.txt b/config/entries/connections.txt
new file mode 100644
index 0000000000..6351a77fcf
--- /dev/null
+++ b/config/entries/connections.txt
@@ -0,0 +1,93 @@
+## Deny all new connections by ckeys we haven't seen before (exempts admins and only denies the connection if the database is enabled and connected)
+## Requires database
+#PANIC_BUNKER
+
+## If a player connects during a bunker with less then or this amount of living time (Minutes), we deny the connection
+#PANIC_BUNKER_LIVING 90
+
+## The message the Panic Bunker gives when someone is rejected by it
+## %minutes% is replaced with PANIC_BUNKER_LIVING on runtime, remove it if you don't want this
+#PANIC_BUNKER_MESSAGE Sorry, but the server is currently not accepting connections from players with less than %minutes% minutes of living time.
+
+## If panic bunker is on and a player is rejected (see above), attempt to send them to this connected server (see below) instead.
+## You probably want this to be the same as CROSS_SERVER_ADDRESS
+#PANIC_SERVER_ADDRESS byond://address:port
+
+##Name of the place to send people rejected by the bunker
+#PANIC_SERVER_NAME [Put the name here]
+
+## Number of days for an individual panic bunker passthrough entry to be wiped. Note that they're also wiped as soon as a player is in the database.
+#MAX_BUNKER_DAYS 7
+
+## Notify admins when a new player connects for the first x days a player's been around. (0 for first connection only, -1 for never)
+## Requres database
+NOTIFY_NEW_PLAYER_AGE 0
+
+## Notify admins when a player connects if their byond account was created in the last X days
+## Requires database
+NOTIFY_NEW_PLAYER_ACCOUNT_AGE 1
+
+##Automated age verification, comment this out to not ask new users if they are 18+
+#AGE_VERIFICATION
+
+## Notify the irc channel when a new player makes their first connection
+## Requres database
+#IRC_FIRST_CONNECTION_ALERT
+
+## Comment this out to disable checking for the cid randomizer dll. (disabled if database isn't enabled or connected)
+CHECK_RANDOMIZER
+
+## IPINTEL:
+## This allows you to detect likely proxies by checking ips against getipintel.net
+## Rating to warn at: (0.9 is good, 1 is 100% likely to be a spammer/proxy, 0.8 is 80%, etc) anything equal to or higher then this number triggers an admin warning
+#IPINTEL_RATING_BAD 0.9
+## Contact email, (required to use the service, leaving blank or default disables IPINTEL)
+#IPINTEL_EMAIL ch@nge.me
+## How long to save good matches (ipintel rate limits to 15 per minute and 500 per day. so this shouldn't be too low, getipintel.net suggests 6 hours, time is in hours) (Your ip will get banned if you go over 500 a day too many times)
+#IPINTEL_SAVE_GOOD 12
+## How long to save bad matches (these numbers can change as ips change hands, best not to save these for too long in case somebody gets a new ip used by a spammer/proxy before.)
+#IPINTEL_SAVE_BAD 3
+## Domain name to query (leave commented out for the default, only needed if you pay getipintel.net for more querys)
+#IPINTEL_DOMAIN check.getipintel.net
+
+## Uncomment to have the changelog file automatically open when a user connects and hasn't seen the latest changelog
+#AGGRESSIVE_CHANGELOG
+
+## Uncomment to allow web client connections
+#ALLOW_WEBCLIENT
+
+## Uncomment to restrict web client connections to byond members
+## This makes for a nice pay gate to cut down on ban evading, as the webclient's cid system isn't that great
+## byond membership starts at $10 for 3 months, so to use the webclient to evade, they would have sink 10 bucks in each evade.
+#WEBCLIENT_ONLY_BYOND_MEMBERS
+
+## CLIENT VERSION CONTROL
+## This allows you to configure the minimum required client version, as well as a warning version, and message for both.
+## These trigger for any version below (non-inclusive) the given version, so 510 triggers on 509 or lower.
+## These messages will be followed by one stating the clients current version and the required version for clarity.
+## If CLIENT_WARN_POPUP is uncommented a popup window with the message will be displayed instead
+#CLIENT_WARN_VERSION 511
+#CLIENT_WARN_POPUP
+#CLIENT_WARN_MESSAGE Byond released 511 as the stable release. You can set the framerate your client runs at, which makes the game feel very different and cool. Shortly after its release we will end up using 511 client features and you will be forced to update.
+CLIENT_ERROR_VERSION 511
+CLIENT_ERROR_MESSAGE Your version of byond is not supported. Please upgrade.
+## The minimum build needed for joining the server, if using 512, a good minimum build would be 1421 as that disables the Middle Mouse Button exploit.
+CLIENT_ERROR_BUILD 1421
+
+## Uncomment for 'soft' population caps, players will be warned while joining if the living crew exceeds the listed number.
+#SOFT_POPCAP 100
+
+## Message for soft cap
+SOFT_POPCAP_MESSAGE Be warned that the server is currently serving a high number of users, consider using alternative game servers.
+
+## Uncomment for 'hard' population caps, players will not be allowed to spawn if the living crew exceeds the listed number, though they may still observe or wait for the living crew to decrease in size.
+#HARD_POPCAP 150
+
+## Message for hard cap
+HARD_POPCAP_MESSAGE The server is currently serving a high number of users, You cannot currently join. You may wait for the number of living crew to decline, observe, or find alternative servers.
+
+## Uncomment for 'extreme' population caps, players will not be allowed to join the server if living crew exceeds the listed number.
+#EXTREME_POPCAP 200
+
+## Message for extreme cap
+EXTREME_POPCAP_MESSAGE The server is currently serving a high number of users, find alternative servers.
diff --git a/config/dbconfig.txt b/config/entries/dbconfig.txt
similarity index 93%
rename from config/dbconfig.txt
rename to config/entries/dbconfig.txt
index 3a058fe563..d5bc37bce7 100644
--- a/config/dbconfig.txt
+++ b/config/entries/dbconfig.txt
@@ -43,3 +43,6 @@ BSQL_THREAD_LIMIT 50
## Uncomment to enable verbose BSQL communication logs
#BSQL_DEBUG
+
+## Time to wait before considering a query as lingering too long
+@QUERY_DEBUG_LOG_TIMEOUT 70
diff --git a/config/entries/debris.txt b/config/entries/debris.txt
new file mode 100644
index 0000000000..345ce6610f
--- /dev/null
+++ b/config/entries/debris.txt
@@ -0,0 +1,8 @@
+## Default turf threshold to get dirt
+TURF_DIRT_THRESHOLD 100
+
+## Default alpha of dirt on spawn
+DIRT_ALPHA_STARTING 127
+
+## Multiplier for how dirty walking over a turf makes it
+TURF_DIRTY_MULTIPLIER 1
diff --git a/config/entries/donator.txt b/config/entries/donator.txt
new file mode 100644
index 0000000000..42c0461bf8
--- /dev/null
+++ b/config/entries/donator.txt
@@ -0,0 +1,11 @@
+## Citadel donator system
+## this is a bad system but I'm lazy so it piggybacks off config loader system.
+## File isn't properly documented because the donator system desperately needs a rewrite and I can't be arsed to right now.
+
+#Specify group followed by ckey for each ckey.
+
+#TIER_1_DONATORS test_ckey
+
+#TIER_2_DONATORS test_ckey
+
+#TIER_3_DONATORS test_ckey
diff --git a/config/dynamic_config.txt b/config/entries/dyanmic.txt
similarity index 98%
rename from config/dynamic_config.txt
rename to config/entries/dyanmic.txt
index 480f6d8ed8..e08fb7634d 100644
--- a/config/dynamic_config.txt
+++ b/config/entries/dyanmic.txt
@@ -307,3 +307,12 @@ DYNAMIC_ASSASSINATE_COST 2
DYNAMIC_WAROPS_REQUIREMENT 60
DYNAMIC_WAROPS_COST 10
+
+## Storyteller min players
+# STORYTELLER_MIN_PLAYERS CHAOTIC 35
+
+## Storyteller minimum chaos
+# STORYTELLER_MIN_CHAOS CHAOTIC 75
+
+## Storyteller maximum chaos
+# STORYTELLER_MAX_CHAOS CHAOTIC 250
diff --git a/config/entries/fetish_content.txt b/config/entries/fetish_content.txt
new file mode 100644
index 0000000000..6fabd095d8
--- /dev/null
+++ b/config/entries/fetish_content.txt
@@ -0,0 +1,33 @@
+## Breast cups selectable from the character creation menu. Keep em lowercase.
+BREASTS_CUPS_PREFS a
+BREASTS_CUPS_PREFS b
+BREASTS_CUPS_PREFS c
+BREASTS_CUPS_PREFS d
+BREASTS_CUPS_PREFS e
+BREASTS_CUPS_PREFS f
+BREASTS_CUPS_PREFS g
+BREASTS_CUPS_PREFS h
+
+## Minimum and maximum limits for penis length from the character creation menu.
+PENIS_MIN_INCHES_PREFS 1
+PENIS_MAX_INCHES_PREFS 24
+
+## Body size configs, the feature will be disabled if both min and max have the same value.
+BODY_SIZE_MIN 0.9
+BODY_SIZE_MAX 1.25
+
+## Allowed visibility toggles
+
+# SAFE_VISIBILITY_TOGGLES Always visible
+SAFE_VISIBILITY_TOGGLES Hidden by clothes
+SAFE_VISIBILITY_TOGGLES Hidden by underwear
+SAFE_VISIBILITY_TOGGLES Always hidden
+
+## Pun-Pun movement slowdown given to characters with a body size smaller than this value,
+## to compensate for their smaller hitbox.
+## To disable, just make sure the value is lower than 'body_size_min'
+THRESHOLD_BODY_SIZE_PENALTY 1
+
+## Multiplier used in the smaller strides slowdown calculation.
+## Doesn't apply to floating or crawling mobs.
+BODY_SIZE_SLOWDOWN_MULTIPLIER 0
diff --git a/config/entries/gamemodes.txt b/config/entries/gamemodes.txt
new file mode 100644
index 0000000000..f78c3743aa
--- /dev/null
+++ b/config/entries/gamemodes.txt
@@ -0,0 +1,178 @@
+## Comment to disable weighting modes by how chaotic recent mode rolls were.
+WEIGH_BY_RECENT_CHAOS
+
+## The weight adjustment will be proportional to this power relative to the "ideal" weight range.
+## e.g. if we have a weight range of 0-5, and an exponent of 1, 6 will be weighted 1/2, 7 1/3 etc.
+## if exponent is 2, it'll be 1/4, 1/9 etc.
+CHAOS_EXPONENT 1
+
+## Percent weight reductions for three of the most recent modes
+
+REPEATED_MODE_ADJUST 45 30 10
+
+## Probablities for game modes chosen in 'secret' and 'random' modes.
+## Default probablity is 1, increase to make that mode more likely to be picked.
+## Set to 0 to disable that mode.
+
+PROBABILITY TRAITOR 5
+PROBABILITY TRAITORBRO 2
+PROBABILITY TRAITORCHAN 4
+PROBABILITY INTERNAL_AFFAIRS 3
+PROBABILITY NUCLEAR 2
+PROBABILITY REVOLUTION 2
+PROBABILITY CULT 2
+PROBABILITY CHANGELING 2
+PROBABILITY WIZARD 4
+PROBABILITY MONKEY 0
+PROBABILITY METEOR 0
+PROBABILITY EXTENDED 0
+PROBABILITY SECRET_EXTENDED 0
+PROBABILITY DEVIL 0
+PROBABILITY DEVIL_AGENTS 0
+PROBABILITY CLOWNOPS 0
+PROBABILITY BLOODSUCKER 0
+
+## You probably want to keep sandbox off by default for secret and random.
+PROBABILITY SANDBOX 0
+
+## Toggles for continuous modes.
+## Modes that aren't continuous will end the instant all antagonists are dead.
+
+CONTINUOUS TRAITOR
+CONTINUOUS TRAITORBRO
+CONTINUOUS TRAITORCHAN
+CONTINUOUS INTERNAL_AFFAIRS
+#CONTINUOUS NUCLEAR
+#CONTINUOUS REVOLUTION
+CONTINUOUS CULT
+CONTINUOUS CLOCKWORK_CULT
+CONTINUOUS CHANGELING
+CONTINUOUS WIZARD
+#CONTINUOUS MONKEY
+CONTINUOUS BLOODSUCKER
+CONTINUOUS HERESY
+
+##Note: do not toggle continuous off for these modes, as they have no antagonists and would thus end immediately!
+
+CONTINUOUS METEOR
+CONTINUOUS EXTENDED
+CONTINUOUS SECRET_EXTENDED
+
+## Toggles for allowing midround antagonists (aka mulligan antagonists).
+## In modes that are continuous, if all antagonists should die then a new set of antagonists will be created.
+
+MIDROUND_ANTAG TRAITOR
+#MIDROUND_ANTAG TRAITORBRO
+MIDROUND_ANTAG TRAITORCHAN
+MIDROUND_ANTAG INTERNAL_AFFAIRS
+#MIDROUND_ANTAG NUCLEAR
+#MIDROUND_ANTAG REVOLUTION
+MIDROUND_ANTAG CULT
+MIDROUND_ANTAG CLOCKWORK_CULT
+MIDROUND_ANTAG CHANGELING
+MIDROUND_ANTAG WIZARD
+#MIDROUND_ANTAG MONKEY
+
+## Toggles for whether this mode should force antags even if not enough players have it enabled.
+## If it's off, it just won't roll as many antags.
+#FORCE_ANTAG_COUNT TRAITOR
+#FORCE_ANTAG_COUNT TRAITORBRO
+#FORCE_ANTAG_COUNT TRAITORCHAN
+#FORCE_ANTAG_COUNT INTERNAL_AFFAIRS
+FORCE_ANTAG_COUNT NUCLEAR
+FORCE_ANTAG_COUNT REVOLUTION
+FORCE_ANTAG_COUNT CULT
+FORCE_ANTAG_COUNT CLOCKWORK_CULT
+#FORCE_ANTAG_COUNT CHANGELING
+#FORCE_ANTAG_COUNT WIZARD
+#FORCE_ANTAG_COUNT MONKEY
+
+## A config for how much each game mode's chaos level is.
+## All of them have reasonable defaults, but this can be used to adjust them.
+## 0-9, where 0 is lowest chaos (should only be extended) and 9 is highest (wizard? nukies?)
+#CHAOS_LEVEL EXTENDED 0
+
+## Uncomment these for overrides of the minimum / maximum number of players in a round type.
+## If you set any of these occasionally check to see if you still need them as the modes
+## will still be actively rebalanced around the SUGGESTED populations, not your overrides.
+## Notes: For maximum number of players a value of -1 means no maximum. Setting minimums to
+## VERY low numbers (< 5) can lead to errors if the roundtypes were not designed for that.
+
+#MIN_POP TRAITOR 0
+#MAX_POP TRAITOR -1
+
+#MIN_POP TRAITORBRO 0
+#MAX_POP TRAITORBRO -1
+
+#MIN_POP TRAITORCHAN 15
+#MAX_POP TRAITORCHAN -1
+
+#MIN_POP DOUBLE_AGENTS 25
+#MAX_POP DOUBLE_AGENTS -1
+
+#MIN_POP NUCLEAR 0
+#MAX_POP NUCLEAR -1
+
+#MIN_POP REVOLUTION 20
+#MAX_POP REVOLUTION -1
+
+#MIN_POP CULT 24
+#MAX_POP CULT -1
+
+#MIN_POP CLOCKWORK_CULT 24
+#MAX_POP CLOCKWORK_CULT -1
+
+#MIN_POP CHANGELING 15
+#MAX_POP CHANGELING -1
+
+#MIN_POP WIZARD 20
+#MAX_POP WIZARD -1
+
+#MIN_POP MONKEY 20
+#MAX_POP MONKEY -1
+
+#MIN_POP METEOR 0
+#MAX_POP METEOR -1
+
+#MIN_POP DEVIL 0
+#MAX_POP DEVIL -1
+
+#MIN_POP DEVIL_AGENTS 25
+#MAX_POP DEVIL_AGENTS -1
+
+## Setting at least one mode to be playable at 0/1 players is required.
+#MIN_POP EXTENDED 0
+#MAX_POP EXTENDED -1
+
+## Variables calculate how number of antagonists will scale to population.
+## Used as (Antagonists = Population / Coeff)
+## Set to 0 to disable scaling and use default numbers instead.
+TRAITOR_SCALING_COEFF 6
+## per brother TEAM
+BROTHER_SCALING_COEFF 12
+CHANGELING_SCALING_COEFF 6
+## heretics
+ECULT_SCALING_COEFF 5
+## per abductor TEAM
+ABDUCTOR_SCALING_COEFF 15
+
+## Variables calculate how number of open security officer positions will scale to population.
+## Used as (Officers = Population / Coeff)
+## Set to 0 to disable scaling and use default numbers instead.
+SECURITY_SCALING_COEFF 8
+
+## The number of objectives traitors get.
+## Not including escaping/hijacking.
+TRAITOR_OBJECTIVES_AMOUNT 2
+BROTHER_OBJECTIVES_AMOUNT 2
+
+## Uncomment to prohibit jobs that start with loyalty
+## implants from being most antagonists.
+#PROTECT_ROLES_FROM_ANTAGONIST
+
+## Uncomment to prohibit assistants from becoming most antagonists.
+#PROTECT_ASSISTANT_FROM_ANTAGONIST
+
+
+## If late-joining players have a chance to become a traitor/changeling
+ALLOW_LATEJOIN_ANTAGONISTS
diff --git a/config/game_options.txt b/config/entries/general.txt
similarity index 63%
rename from config/game_options.txt
rename to config/entries/general.txt
index b9d763e5b0..3584af63c7 100644
--- a/config/game_options.txt
+++ b/config/entries/general.txt
@@ -1,3 +1,51 @@
+## Lobby time: This is the amount of time between rounds that players have to setup their characters and be ready.
+LOBBY_COUNTDOWN 120
+
+## Round End Time: This is the amount of time after the round ends that players have to murder death kill each other.
+ROUND_END_COUNTDOWN 90
+
+## period of time in seconds for players to be considered inactive
+# INACTIVITY_PERIOD 300
+
+## period of time in seconds for players to be considered afk and kickable
+# AFK_PERIOD 600
+
+## disconnect players who are considered afk
+# KICK_INACTIVE
+
+## Job slot open/close by identification consoles delay in seconds
+ID_CONSOLE_JOBSLOT_DELAY 30
+
+
+## disables calling del(src) on newmobs if they logout before spawnin in
+# DONT_DEL_NEWMOB
+
+## In-game features
+##Toggle for having jobs load up from the .txt
+# LOAD_JOBS_FROM_TXT
+
+
+## Uncomment to allow special 'Easter-egg' events on special holidays such as seasonal holidays and stuff like 'Talk Like a Pirate Day' :3 YAARRR
+ALLOW_HOLIDAYS
+
+## Uncomment to show the names of the admin sending a pm from IRC instead of showing as a stealthmin.
+#SHOW_IRC_NAME
+
+## Chat Announce Options
+## Various messages to be sent to game chats
+## Uncommenting these will enable them, by default they will be broadcast to Game chat channels on TGS3 or non-admin channels on TGS4
+## If using TGS4, the string option can be set as a chat channel tag to limit the message to channels of that tag type (case-sensitive)
+## i.e. CHAT_ANNOUNCE_NEW_GAME chat_channel_tag
+
+## Send a message with the station name starting a new game
+#CHAT_ANNOUNCE_NEW_GAME
+
+##Default screen resolution, in tiles.
+## By default, this is 15x15, which gets simplified to 7 by BYOND, as it is a 1:1 screen ratio.
+## For reference, Goonstation uses a resolution of 21x15 for it's widescreen mode.
+## Do note that changing this value will affect the title screen. The title screen will have to be updated manually if this is changed.
+DEFAULT_VIEW 21x15
+
## HEALTH ###
##Damage multiplier, effects both weapons and healing on all mobs. For example, 1.25 would result in 25% higher damage.
@@ -22,30 +70,6 @@ OOC_DURING_ROUND
## Comment this out if you want to disable emojis
EMOJIS
-## MOB MOVEMENT ###
-
-## We suggest editing these variables ingame to find a good speed for your server.
-## To do this you must be a high level admin. Open the 'debug' tab ingame.
-## Select "Debug Controller" and then, in the popup, select "Configuration". These variables should have the same name.
-
-## These values get directly added to values and totals ingame.
-## To speed things up make the number negative, to slow things down, make the number positive.
-
-## These modify the run/walk speed of all mobs before the mob-specific modifiers are applied.
-RUN_DELAY 1
-WALK_DELAY 4
-
-## The variables below affect the movement of specific mob types. THIS AFFECTS ALL SUBTYPES OF THE TYPE YOU CHOOSE!
-## Entries completely override all subtypes. Later entries have precedence over earlier entries.
-## This means if you put /mob 0 on the last entry, it will null out all changes, while if you put /mob as the first entry and
-## /mob/living/carbon/human on the last entry, the last entry will override the first.
-MULTIPLICATIVE_MOVESPEED /mob/living/carbon/human 1
-##MULTIPLICATIVE_MOVESPEED /mob/living/silicon/robot 0
-##MULTIPLICATIVE_MOVESPEED /mob/living/carbon/monkey 0
-##MULTIPLICATIVE_MOVESPEED /mob/living/carbon/alien 0
-##MULTIPLICATIVE_MOVESPEED /mob/living/simple_animal/slime 0
-MULTIPLICATIVE_MOVESPEED /mob/living/simple_animal 1
-
## NAMES ###
## If uncommented this adds a random surname to a player's name if they only specify one name.
@@ -54,205 +78,18 @@ MULTIPLICATIVE_MOVESPEED /mob/living/simple_animal 1
## If uncommented, this forces all players to use random names !and appearances!.
#FORCE_RANDOM_NAMES
-
-## ALERT LEVELS ###
-ALERT_GREEN All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced.
-ALERT_BLUE_UPTO The station has received reliable information about potential threats to the station. Security staff may have weapons visible, random searches are permitted.
-ALERT_BLUE_DOWNTO Significant confirmed threats have been neutralized. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still permitted.
-ALERT_AMBER_UPTO There are signficant confirmed threats to the station. Security staff may have weapons unholstered at all times. Random searches are allowed and advised.
-ALERT_AMBER_DOWNTO The immediate threat has passed. Security is no longer authorized to use lethal force, but may continue to have weapons drawn. Access requirements have been restored.
-ALERT_RED_UPTO There is an immediate serious threat to the station. Security is now authorized to use lethal force. Additionally, access requirements on some machines have been lifted.
-ALERT_RED_DOWNTO The station's destruction has been averted. There is still however an immediate serious threat to the station. Security is still authorized to use lethal force.
-ALERT_DELTA Destruction of the station is imminent. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.
-
-
-
## GAME MODES ###
## Uncomment to not send a roundstart intercept report. Gamemodes may override this.
#NO_INTERCEPT_REPORT
-## Comment to disable weighting modes by how chaotic recent mode rolls were.
-WEIGH_BY_RECENT_CHAOS
-
-## The weight adjustment will be proportional to this power relative to the "ideal" weight range.
-## e.g. if we have a weight range of 0-5, and an exponent of 1, 6 will be weighted 1/2, 7 1/3 etc.
-## if exponent is 2, it'll be 1/4, 1/9 etc.
-CHAOS_EXPONENT 1
-
-## Probablities for game modes chosen in 'secret' and 'random' modes.
-## Default probablity is 1, increase to make that mode more likely to be picked.
-## Set to 0 to disable that mode.
-
-PROBABILITY TRAITOR 5
-PROBABILITY TRAITORBRO 2
-PROBABILITY TRAITORCHAN 4
-PROBABILITY INTERNAL_AFFAIRS 3
-PROBABILITY NUCLEAR 2
-PROBABILITY REVOLUTION 2
-PROBABILITY CULT 2
-PROBABILITY CHANGELING 2
-PROBABILITY WIZARD 4
-PROBABILITY MONKEY 0
-PROBABILITY METEOR 0
-PROBABILITY EXTENDED 0
-PROBABILITY SECRET_EXTENDED 0
-PROBABILITY DEVIL 0
-PROBABILITY DEVIL_AGENTS 0
-PROBABILITY CLOWNOPS 0
-PROBABILITY BLOODSUCKER 0
-
-## You probably want to keep sandbox off by default for secret and random.
-PROBABILITY SANDBOX 0
-
-## Percent weight reductions for three of the most recent modes
-
-REPEATED_MODE_ADJUST 45 30 10
-
-## Toggles for continuous modes.
-## Modes that aren't continuous will end the instant all antagonists are dead.
-
-CONTINUOUS TRAITOR
-CONTINUOUS TRAITORBRO
-CONTINUOUS TRAITORCHAN
-CONTINUOUS INTERNAL_AFFAIRS
-#CONTINUOUS NUCLEAR
-#CONTINUOUS REVOLUTION
-CONTINUOUS CULT
-CONTINUOUS CLOCKWORK_CULT
-CONTINUOUS CHANGELING
-CONTINUOUS WIZARD
-#CONTINUOUS MONKEY
-CONTINUOUS BLOODSUCKER
-CONTINUOUS HERESY
-
-##Note: do not toggle continuous off for these modes, as they have no antagonists and would thus end immediately!
-
-CONTINUOUS METEOR
-CONTINUOUS EXTENDED
-CONTINUOUS SECRET_EXTENDED
-
-
-## Toggles for allowing midround antagonists (aka mulligan antagonists).
-## In modes that are continuous, if all antagonists should die then a new set of antagonists will be created.
-
-MIDROUND_ANTAG TRAITOR
-#MIDROUND_ANTAG TRAITORBRO
-MIDROUND_ANTAG TRAITORCHAN
-MIDROUND_ANTAG INTERNAL_AFFAIRS
-#MIDROUND_ANTAG NUCLEAR
-#MIDROUND_ANTAG REVOLUTION
-MIDROUND_ANTAG CULT
-MIDROUND_ANTAG CLOCKWORK_CULT
-MIDROUND_ANTAG CHANGELING
-MIDROUND_ANTAG WIZARD
-#MIDROUND_ANTAG MONKEY
-
-## Toggles for whether this mode should force antags even if not enough players have it enabled.
-## If it's off, it just won't roll as many antags.
-#FORCE_ANTAG_COUNT TRAITOR
-#FORCE_ANTAG_COUNT TRAITORBRO
-#FORCE_ANTAG_COUNT TRAITORCHAN
-#FORCE_ANTAG_COUNT INTERNAL_AFFAIRS
-FORCE_ANTAG_COUNT NUCLEAR
-FORCE_ANTAG_COUNT REVOLUTION
-FORCE_ANTAG_COUNT CULT
-FORCE_ANTAG_COUNT CLOCKWORK_CULT
-#FORCE_ANTAG_COUNT CHANGELING
-#FORCE_ANTAG_COUNT WIZARD
-#FORCE_ANTAG_COUNT MONKEY
-
-## A config for how much each game mode's chaos level is.
-## All of them have reasonable defaults, but this can be used to adjust them.
-## 0-9, where 0 is lowest chaos (should only be extended) and 9 is highest (wizard? nukies?)
-#CHAOS_LEVEL EXTENDED 0
-
-## Uncomment these for overrides of the minimum / maximum number of players in a round type.
-## If you set any of these occasionally check to see if you still need them as the modes
-## will still be actively rebalanced around the SUGGESTED populations, not your overrides.
-## Notes: For maximum number of players a value of -1 means no maximum. Setting minimums to
-## VERY low numbers (< 5) can lead to errors if the roundtypes were not designed for that.
-
-#MIN_POP TRAITOR 0
-#MAX_POP TRAITOR -1
-
-#MIN_POP TRAITORBRO 0
-#MAX_POP TRAITORBRO -1
-
-#MIN_POP TRAITORCHAN 15
-#MAX_POP TRAITORCHAN -1
-
-#MIN_POP DOUBLE_AGENTS 25
-#MAX_POP DOUBLE_AGENTS -1
-
-#MIN_POP NUCLEAR 0
-#MAX_POP NUCLEAR -1
-
-#MIN_POP REVOLUTION 20
-#MAX_POP REVOLUTION -1
-
-#MIN_POP CULT 24
-#MAX_POP CULT -1
-
-#MIN_POP CLOCKWORK_CULT 24
-#MAX_POP CLOCKWORK_CULT -1
-
-#MIN_POP CHANGELING 15
-#MAX_POP CHANGELING -1
-
-#MIN_POP WIZARD 20
-#MAX_POP WIZARD -1
-
-#MIN_POP MONKEY 20
-#MAX_POP MONKEY -1
-
-#MIN_POP METEOR 0
-#MAX_POP METEOR -1
-
-#MIN_POP DEVIL 0
-#MAX_POP DEVIL -1
-
-#MIN_POP DEVIL_AGENTS 25
-#MAX_POP DEVIL_AGENTS -1
-
-## Setting at least one mode to be playable at 0/1 players is required.
-#MIN_POP EXTENDED 0
-#MAX_POP EXTENDED -1
-
+## If non-human species are barred from joining as a head of staff
+#ENFORCE_HUMAN_AUTHORITY
## The amount of time it takes for the emergency shuttle to be called, from round start.
SHUTTLE_REFUEL_DELAY 12000
-## Variables calculate how number of antagonists will scale to population.
-## Used as (Antagonists = Population / Coeff)
-## Set to 0 to disable scaling and use default numbers instead.
-TRAITOR_SCALING_COEFF 6
-BROTHER_SCALING_COEFF 6
-CHANGELING_SCALING_COEFF 6
-
-## Variables calculate how number of open security officer positions will scale to population.
-## Used as (Officers = Population / Coeff)
-## Set to 0 to disable scaling and use default numbers instead.
-SECURITY_SCALING_COEFF 8
-
-## The number of objectives traitors get.
-## Not including escaping/hijacking.
-TRAITOR_OBJECTIVES_AMOUNT 2
-BROTHER_OBJECTIVES_AMOUNT 2
-
-## Uncomment to prohibit jobs that start with loyalty
-## implants from being most antagonists.
-#PROTECT_ROLES_FROM_ANTAGONIST
-
-## Uncomment to prohibit assistants from becoming most antagonists.
-#PROTECT_ASSISTANT_FROM_ANTAGONIST
-
-## If non-human species are barred from joining as a head of staff
-#ENFORCE_HUMAN_AUTHORITY
-
-## If late-joining players have a chance to become a traitor/changeling
-ALLOW_LATEJOIN_ANTAGONISTS
## Comment this out to disable the antagonist reputation system. This system rewards players who participate in the game instead of greytiding by giving them slightly higher odds to
## roll antagonist in subsequent rounds until they get it.
@@ -303,9 +140,6 @@ ALLOW_AI_MULTICAM
## Uncomment to prevent the security cyborg module from being chosen
#DISABLE_SECBORG
-## Determines the minimum alert level for the security cyborg model to be chosen
-## 0: Green, 1:Blue, 2:Amber, 3:Red, 4:Delta
-MINIMUM_SECBORG_ALERT 3
## Peacekeeper Borg ###
## Uncomment to prevent the peacekeeper cyborg module from being chosen
@@ -643,39 +477,10 @@ BOX_RANDOM_ENGINE Box Empty,0
BOX_RANDOM_ENGINE Box Antimatter,1
BOX_RANDOM_ENGINE Box P.A.C.M.A.N,1
-## Whether or not there's a mode tier list vote after the secret/extended vote.
-MODETIER_VOTING
-
-## Number of modes dropped by the modetier vote during mode selection, after vote.
-DROPPED_MODES 3
## Whether the suicide verb is allowed.
# SUICIDE_ALLOWED
-## Breast cups selectable from the character creation menu. Keep em lowercase.
-BREASTS_CUPS_PREFS a
-BREASTS_CUPS_PREFS b
-BREASTS_CUPS_PREFS c
-BREASTS_CUPS_PREFS d
-BREASTS_CUPS_PREFS e
-
-## Minimum and maximum limits for penis length from the character creation menu.
-PENIS_MIN_INCHES_PREFS 1
-PENIS_MAX_INCHES_PREFS 20
-
-## Body size configs, the feature will be disabled if both min and max have the same value.
-BODY_SIZE_MIN 0.9
-BODY_SIZE_MAX 1.25
-
-## Pun-Pun movement slowdown given to characters with a body size smaller than this value,
-## to compensate for their smaller hitbox.
-## To disable, just make sure the value is lower than 'body_size_min'
-THRESHOLD_BODY_SIZE_PENALTY 1
-
-## Multiplier used in the smaller strides slowdown calculation.
-## Doesn't apply to floating or crawling mobs.
-BODY_SIZE_SLOWDOWN_MULTIPLIER 0
-
## Allows players to set a hexadecimal color of their choice as skin tone, on top of the standard ones.
ALLOW_CUSTOM_SKINTONES
@@ -683,11 +488,6 @@ ALLOW_CUSTOM_SKINTONES
## Camera mobs, AIs, ghosts and some other are of course exempt from this. This also doesn't influence simplemob AI, for the best.
#USE_FIELD_OF_VISION
-## Default turf threshold to get dirt
-TURF_DIRT_THRESHOLD 100
-
-## Default alpha of dirt on spawn
-DIRT_ALPHA_STARTING 127
## Allows pAI custom holoforms
PAI_CUSTOM_HOLOFORMS
diff --git a/config/entries/jexp.txt b/config/entries/jexp.txt
new file mode 100644
index 0000000000..e46d743a66
--- /dev/null
+++ b/config/entries/jexp.txt
@@ -0,0 +1,23 @@
+## Uncomment this entry to have certain jobs require your account to be at least a certain number of days old to select. You can configure the exact age requirement for different jobs by editing
+## the minimal_player_age variable in the files in folder /code/game/jobs/job/.. for the job you want to edit. Set minimal_player_age to 0 to disable age requirement for that job.
+## REQUIRES the database set up to work. Keep it hashed if you don't have a database set up.
+## NOTE: If you have just set-up the database keep this DISABLED, as player age is determined from the first time they connect to the server with the database up. If you just set it up, it means
+## you have noone older than 0 days, since noone has been logged yet. Only turn this on once you have had the database up for 30 days.
+#USE_AGE_RESTRICTION_FOR_JOBS
+
+## Uncomment this to have the job system use the player's account creation date, rather than the when they first joined the server for job timers.
+#USE_ACCOUNT_AGE_FOR_JOBS
+
+## Unhash this to track player playtime in the database. Requires database to be enabled.
+#USE_EXP_TRACKING
+## Unhash this to enable playtime requirements for head jobs.
+#USE_EXP_RESTRICTIONS_HEADS
+## Unhash this to override head jobs' playtime requirements with this number of hours.
+## Leave this commented out to use the values defined in the job datums. Values in the datums are stored as minutes.
+#USE_EXP_RESTRICTIONS_HEADS_HOURS 3
+## Unhash this to change head jobs' playtime requirements so that they're based on department playtime, rather than crew playtime.
+#USE_EXP_RESTRICTIONS_HEADS_DEPARTMENT
+## Unhash this to enable playtime requirements for certain non-head jobs, like Engineer and Scientist.
+#USE_EXP_RESTRICTIONS_OTHER
+## Allows admins to bypass job playtime requirements.
+#USE_EXP_RESTRICTIONS_ADMIN_BYPASS
diff --git a/config/entries/logging.txt b/config/entries/logging.txt
new file mode 100644
index 0000000000..1690dbfacf
--- /dev/null
+++ b/config/entries/logging.txt
@@ -0,0 +1,85 @@
+## log OOC channel
+LOG_OOC
+
+## log client Say
+LOG_SAY
+
+## log admin actions
+@LOG_ADMIN
+
+## log admin chat
+@LOG_ADMINCHAT
+
+## log client access (logon/logoff)
+LOG_ACCESS
+
+## log game actions (start of round, results, etc.)
+LOG_GAME
+
+## log player votes
+LOG_VOTE
+
+## log player crafting
+LOG_CRAFT
+
+## log client Whisper
+LOG_WHISPER
+
+## log emotes
+LOG_EMOTE
+
+## log attack messages
+LOG_ATTACK
+
+## log pda messages
+LOG_PDA
+
+## log telecomms messages
+LOG_TELECOMMS
+
+## log prayers
+LOG_PRAYER
+
+## log lawchanges
+LOG_LAW
+
+## log crew manifest to seperate file
+LOG_MANIFEST
+
+## log job divide debugging information
+LOG_JOB_DEBUG
+
+## Log shuttle related actions
+LOG_SHUTTLE
+
+## log all world.Topic() calls
+LOG_WORLD_TOPIC
+
+## enables use of the proc twitterize() that lets you take a large list of strings and turn it into a JSON file of tweet sized strings.
+## As an example of how this could be """useful""" look towards Poly (https://twitter.com/Poly_the_Parrot)
+# LOG_TWITTER
+
+## Enable logging pictures
+LOG_PICTURES
+
+## Log camera pictures
+PICTURE_LOGGING_CAMERA
+
+## log virus and actions
+LOG_VIRUS
+
+## Log all raw hrefs of tgui, rather than letting tgui logging handle it. KEEP THIS OFF UNLESS YOU KNOW WHAT YOU ARE DOING.
+# EMERGENCY_TGUI_LOGGING
+
+## Cooldown time for each occurance of a unique runtime in deciseconds
+ERROR_COOLDOWN 600
+
+## Max runtimes of one type before silencing
+ERROR_LIMIT 50
+
+## How long an unique runtime will be silenced for when reaching limit in deciseconds
+ERROR_SILENCE_TIME 6000
+
+How long to wait between messaging admins about an unique runtime
+ERROR_MSG_DELAY 50
+
diff --git a/config/entries/movespeed.txt b/config/entries/movespeed.txt
new file mode 100644
index 0000000000..67f9ab503b
--- /dev/null
+++ b/config/entries/movespeed.txt
@@ -0,0 +1,56 @@
+## MOB MOVEMENT ###
+
+## We suggest editing these variables ingame to find a good speed for your server.
+## To do this you must be a high level admin. Open the 'debug' tab ingame.
+## Select "Debug Controller" and then, in the popup, select "Configuration". These variables should have the same name.
+
+## These values get directly added to values and totals ingame.
+## To speed things up make the number negative, to slow things down, make the number positive.
+
+## These modify the run/walk speed of all mobs before the mob-specific modifiers are applied.
+RUN_DELAY 1.5
+WALK_DELAY 4
+
+## The variables below affect the movement of specific mob types. THIS AFFECTS ALL SUBTYPES OF THE TYPE YOU CHOOSE!
+## Entries completely override all subtypes. Later entries have precedence over earlier entries.
+## This means if you put /mob 0 on the last entry, it will null out all changes, while if you put /mob as the first entry and
+## /mob/living/carbon/human on the last entry, the last entry will override the first.
+MULTIPLICATIVE_MOVESPEED /mob/living/carbon/alien -1
+MULTIPLICATIVE_MOVESPEED /mob/living/carbon/alien/humanoid/sentinel -0.75
+MULTIPLICATIVE_MOVESPEED /mob/living/carbon/alien/humanoid/drone -0.5
+MULTIPLICATIVE_MOVESPEED /mob/living/carbon/alien/humanoid/royal/praetorian 0
+MULTIPLICATIVE_MOVESPEED /mob/living/carbon/alien/humanoid/royal/queen 2
+
+## The above, only when a mob is FLOATING
+MULTIPLICATIVE_MOVESPEED_FLOATING /mob/living/carbon -0.5
+MULTIPLICATIVE_MOVESPEED_FLOATING /mob/living 0
+
+## Whether or not sprint is enabled
+SPRINT_ENABLED 0
+
+## When sprint is off, how much does getting staggered slow you
+SPRINTLESS_STAGGER_SLOWDOWN 0.5
+
+## When sprint is off, how much does getting shoved off balance slow you
+SPRINTLESS_OFF_BALANCE_SLOWDOWN 0.85
+
+## Melee stagger power multiplier
+MELEE_STAGGER_FACTOR 1
+
+## Sprint speed increase
+SPRINT_SPEED_INCREASE 1
+
+## Max tiles/second increase from sprint
+SPRINT_MAX_TILES_INCREASE 5
+
+## Absolute max speed sprint can make someone go (tiles/second)
+SPRINT_ABSOLUTE_MAX_TILES 13
+
+## Max sprint buffer
+SPRINT_BUFFER_MAX 24
+
+## Stamina/tile when bufer empty
+SPRINT_STAMINA_COST 1.4
+
+## Buffer regen/decisecond - 0.4 = 4/second
+SPRINT_BUFFER_REGEN_PER_DS 0.4
diff --git a/config/persistence.txt b/config/entries/persistence.txt
similarity index 100%
rename from config/persistence.txt
rename to config/entries/persistence.txt
diff --git a/config/entries/policy.txt b/config/entries/policy.txt
new file mode 100644
index 0000000000..07f64b5b2a
--- /dev/null
+++ b/config/entries/policy.txt
@@ -0,0 +1,24 @@
+## Policy configuration
+## Current valid keys are:
+## ON_CLONE - displayed after a successful cloning operation to the cloned person
+## ON_DEFIB_INTACT - displayed after defibbing before memory loss time threshold
+## ON_DEFIB_LATE - displayed after defibbing post memory loss time threshold
+## SDGF - displayed on SDGF clone spawning
+## SDGF_GOOD - displayed on SDGF clone spawning, if the clone is loyal
+## SDGF_BAD - displayed on SDGF clone spawning, if the clone is not loyal
+## PAI - displayed on PAI personality being loaded
+## EXAMPLE:
+## POLICY ON_CLONE insert text here span classes are fully supported
+
+POLICY ON_CLONE Your thoughts are hazy as the cloning algorithms reboot your consciousness. Unfortunately for you, the imperfect nature of the process has left out your more recent, less entrenched memories. You only remember vague details of your death, without clear recollection of who or what is specifically responsible for your demise. (If you were murdered, you do not remember the exact name or appearance of your killer, only vague details of how they killed you rather than the exact murder weapon. (ex: drank something and blanked out, felt an impact in the back and bled out) If you died to environmental hazards like ash storms or spacing, this is not as applicable -- however, keep in mind that if someone set you up to die to that, like being tossed forcefully into space, that the previous clause of not remembering killer name in a murder applies!
+
+POLICY ON_DEFIB_LATE Your mind barely responds as first as you are forcefully returned to the world of the living after all too long in a state of decay. While medicine may restore your brain functions, you can't seem to remember your latest memories... You only remember vague details of your death, without clear recollection of who or what is specifically responsible for your demise. (If you were murdered, you do not remember the exact name or appearance of your killer, only vague details of how they killed you rather than the exact murder weapon. (ex: drank something and blanked out, felt an impact in the back and bled out) If you died to environmental hazards like ash storms or spacing, this is not as applicable -- however, keep in mind that if someone set you up to die to that, like being tossed forcefully into space, that the previous clause of not remembering killer name in a murder applies!
+
+POLICY ON_DEFIB_INTACT You barely miss a beat as you gasp, awakening from the slumber of the deceased. The rapid resuscitation has saved you from the worst effects of brain damage. You recall all information leading up to your death and exact details on method of death and killer if applicable, as long as you were conscious to witness such.
+
+POLICY PAI If you are given an ERP-related directive without OOC consent, ahelp immediately.w
+
+## Misc entries for above
+
+## Defib time limit for "cloning memory disorder" memory loss in seconds
+DEFIB_CMD_TIME_LIMIT 300
diff --git a/config/resources.txt b/config/entries/resources.txt
similarity index 100%
rename from config/resources.txt
rename to config/entries/resources.txt
diff --git a/config/respawns.txt b/config/entries/respawns.txt
similarity index 90%
rename from config/respawns.txt
rename to config/entries/respawns.txt
index 804a856a93..41c76eaabc 100644
--- a/config/respawns.txt
+++ b/config/entries/respawns.txt
@@ -2,7 +2,7 @@
RESPAWNS_ENABLED
## Minutes delay before allowing respawns, either from death or observing. Not an integer.
-RESPAWN_DELAY 15.0
+RESPAWN_DELAY 10.0
## Minutes delay before allowing respawns, if the user cryo'd. Not an integer.
RESPAWN_DELAY_CRYO 5.0
@@ -16,8 +16,8 @@ ALLOW_NON_ASSISTANT_RESPAWN
## Allow respawning as the same character
# ALLOW_SAME_CHARACTER_RESPAWN
-## Observing is considered a respawn for the purposes of role lockouts. Defaults to disabled. When disabled, only RESPAWNING rather than returning from observe locks you out.
-# RESPAWN_PENALTY_INCLUDES_OBSERVE
+## Observing is considered a respawn for the purposes of role lockouts. Defaults to disabled. When disabled, only RESPAWNING rather than returning from observer locks you out.
+RESPAWN_PENALTY_INCLUDES_OBSERVE
## Time in minutes from round start before respawn is enabled
RESPAWN_MINIMUM_DELAY_ROUNDSTART 30.0
diff --git a/config/entries/security.txt b/config/entries/security.txt
new file mode 100644
index 0000000000..e6a13d5cdf
--- /dev/null
+++ b/config/entries/security.txt
@@ -0,0 +1,38 @@
+### FAIL2TOPIC:
+### Automated IP bans for world/Topic() spammers
+### NOTE FOR WINDOWS HOSTS: This requires you to be running dreamdaemon as an administrator for it to work at all. TGS3 handles this automatically, and honestly there's no reason not to be using TGS3 if you're hosting on Windows.
+### NOTE FOR LINUX HOSTS: This requires manual setup of iptables. Beware that improper configuration of this can and will irreversibly fuck up a server, so please don't tinker with it if you don't know what you're doing.
+## Enabled
+#FAIL2TOPIC_ENABLED
+## Minimum wait time in deciseconds between valid requests
+FAIL2TOPIC_RATE_LIMIT 10
+## Number of requests after breaching rate limit that triggers a ban
+FAIL2TOPIC_MAX_FAILS 5
+## Firewall rule name used on physical server
+## FOR LINUX HOSTS: This is used as the chain name. The iptables chain doesn't get created or hooked up to INPUT automatically, so you'll have to get that set up yourself. Recommended name: BYOND
+@FAIL2TOPIC_RULE_NAME _dd_fail2topic
+
+## Topic max size before it's rejected, using BYOND length()
+TOPIC_MAX_SIZE 8192
+
+## Fail2topic rate limit whitelist. Using any external IPs is not recommended.
+# TOPIC_RATE_LIMIT_WHITELIST 127.0.0.1:1337
+
+## TOPIC RATE LIMITING
+## This allows you to limit how many topic calls (clicking on an interface window) the client can do in any given game second and/or game minute.
+## Admins are exempt from these limits.
+## Hitting the minute limit notifies admins.
+## Set to 0 or comment out to disable.
+SECOND_TOPIC_LIMIT 10
+
+MINUTE_TOPIC_LIMIT 100
+
+## CLICK RATE LIMITING
+## Same as above, but applies to clicking on objects in the game window.
+## This should be a higher then the interface limit to allow for the spam clickly nature of most battles.
+## Admins are exempt from these limits.
+## Hitting the minute limit notifies admins.
+## Set to 0 to disable.
+SECOND_CLICK_LIMIT 15
+
+MINUTE_CLICK_LIMIT 400
diff --git a/config/entries/server.txt b/config/entries/server.txt
new file mode 100644
index 0000000000..0ffd5b21a3
--- /dev/null
+++ b/config/entries/server.txt
@@ -0,0 +1,68 @@
+## Enable automatic profiling - Byond 513.1506 and newer only.
+#AUTO_PROFILE
+
+## Server name: This appears at the top of the screen in-game and in the BYOND hub. Uncomment and replace 'tgstation' with the name of your choice.
+# SERVERNAME tgstation
+
+## Server tagline: This will appear right below the server's title.
+# SERVERTAGLINE A generic TG-based server
+
+## Server SQL name: This is the name used to identify the server to the SQL DB, distinct from SERVERNAME as it must be at most 32 characters.
+# SERVERSQLNAME tgstation
+
+## Station name: The name of the station as it is referred to in-game. If commented out, the game will generate a random name instead.
+STATIONNAME Space Station 13
+
+## Put on byond hub: Uncomment this to put your server on the byond hub.
+#HUB
+
+## Defines the ticklimit for subsystem initialization (In percents of a byond tick). Lower makes world start smoother. Higher makes it faster.
+##This is currently a testing optimized setting. A good value for production would be 98.
+TICK_LIMIT_MC_INIT 500
+
+##Defines the ticklag for the world. Ticklag is the amount of time between game ticks (aka byond ticks) (in 1/10ths of a second).
+## This also controls the client network update rate, as well as the default client fps
+TICKLAG 0.5
+
+##Can also be set as per-second value, the following value is identical to the above.
+#FPS 20
+
+## Set to prevent anyone but those ckeys listed in config/whitelist.txt and config/admins.txt from joining your server
+#USEWHITELIST
+
+## set a hosted by name for unix platforms
+HOSTEDBY Yournamehere
+
+## System command that invokes youtube-dl, used by Play Internet Sound.
+## You can install youtube-dl with
+## "pip install youtube-dl" if you have pip installed
+## from https://github.com/rg3/youtube-dl/releases
+## or your package manager
+## The default value assumes youtube-dl is in your system PATH
+# INVOKE_YOUTUBEDL youtube-dl
+
+###Master Controller High Pop Mode###
+
+##The Master Controller(MC) is the primary system controlling timed tasks and events in SS13 (lobby timer, game checks, lighting updates, atmos, etc)
+##Default base MC tick rate (1 = process every "byond tick" (see: tick_lag/fps config settings), 2 = process every 2 byond ticks, etc)
+## Setting this to 0 will prevent the Master Controller from ticking
+BASE_MC_TICK_RATE 1
+
+##High population MC tick rate
+## Byond rounds timer values UP, but the tick rate is modified with heuristics during lag spites so setting this to something like 2
+## will make it run every 2 byond ticks, but will also double the effect of anti-lag heuristics. You can instead set it to something like
+## 1.1 to make it run every 2 byond ticks, but only increase the effect of anti-lag heuristics by 10%. or 1.5 for 50%.
+## (As an aside, you could in theory also reduce the effect of anti-lag heuristics in the base tick rate by setting it to something like 0.5)
+HIGH_POP_MC_TICK_RATE 1.1
+
+##Engage high pop mode if player count raises above this (Player in this context means any connected user. Lobby, ghost or in-game all count)
+HIGH_POP_MC_MODE_AMOUNT 65
+
+##Disengage high pop mode if player count drops below this
+DISABLE_HIGH_POP_MC_MODE_AMOUNT 60
+
+## Uncomment to prevent the world from sleeping while no players are connected after initializations
+#RESUME_AFTER_INITIALIZATIONS
+
+## Uncomment to set the number of /world/Reboot()s before the DreamDaemon restarts itself. 0 means restart every round. Requires tgstation server tools.
+#ROUNDS_UNTIL_HARD_RESTART 10
diff --git a/config/entries/stamina_combat.txt b/config/entries/stamina_combat.txt
new file mode 100644
index 0000000000..5339502586
--- /dev/null
+++ b/config/entries/stamina_combat.txt
@@ -0,0 +1,28 @@
+## haha these keys are going to collide with other stuff for sure someday
+
+## OUT_OF_COMBAT_TIMER, PERCENT_REGENERATION_OUT_OF_COMBAT disabled - combat mode has been yanked from the codebase and made a UI toggle.
+
+## Maximum stamina buffer
+BUFFER_MAX 25
+
+## Seconds until out of combat regen kicks in
+# OUT_OF_COMBAT_TIMER 15
+
+## Base regen per second
+BASE_REGENERATION 3.5
+
+## Regenerate this % of total buffer when out of combat
+# PERCENT_REGENERATION_OUT_OF_COMBAT
+
+## Seconds after an action for which regeneration is penalized
+POST_ACTION_PENALTY_DELAY 5
+
+## Factor to multiply by for penalizing post action regen
+POST_ACTION_PENALTY_FACTOR 0.25
+
+## Factor to multiply by for stamina usage past buffer into health
+OVERDRAW_PENALTY_FACTOR 1.5
+
+## Completely disable stamina combat by giving people infinite buffers.
+## Has serious balance implications.
+# DISABLE_STAMBUFFER
diff --git a/config/job_threats.txt b/config/entries/threat.txt
similarity index 91%
rename from config/job_threats.txt
rename to config/entries/threat.txt
index e57edb66e4..fa7c5cffa5 100644
--- a/config/job_threats.txt
+++ b/config/entries/threat.txt
@@ -6,4 +6,4 @@
## Custom antag threat values, see above
## e.g.
-## ANTAG_THREAT Traitor 5
\ No newline at end of file
+## ANTAG_THREAT Traitor 5
diff --git a/config/entries/urls.txt b/config/entries/urls.txt
new file mode 100644
index 0000000000..f307245055
--- /dev/null
+++ b/config/entries/urls.txt
@@ -0,0 +1,37 @@
+## set a server location for world reboot. Don't include the byond://, just give the address and port.
+## Don't set this to the same server, BYOND will automatically restart players to the server when it has restarted.
+# SERVER ss13.example.com:2506
+
+## forum address
+# FORUMURL https://citadel-station.net/forum/
+
+## Wiki address
+# WIKIURL https://citadel-station.net/wikimain/index.php
+
+## Wiki address of upstream
+WIKIURLTG http://www.tgstation13.org/wiki
+
+## Rules address
+# RULESURL https://citadel-station.net/wikimain/index.php?title=Rules_-_Main
+
+## Github address
+# GITHUBURL https://github.com/Citadel-Station-13/Citadel-Station-13
+
+## Round specific stats address
+## Link to round specific parsed logs; IE statbus. It is appended with the RoundID automatically by ticker/Reboot()
+## This will take priority over the game logs address during reboot.
+## Example: https://atlantaned.space/statbus/round.php?round=
+# ROUNDSTATSURL http://citadel-station.net/slimbus/
+
+## Game Logs address
+## Incase you don't have a fancy parsing system, but still want players to be able to find where you keep your server's logs.
+## Example: https://tgstation13.org/parsed-logs/basil/data/logs/
+# GAMELOGURL
+
+## Github repo id
+##This can be found by going to https://api.github.com/users//repos
+##Or https://api.github.com/orgs//repos if the repo owner is an organization
+# GITHUBREPOID 62485194
+
+## Ban appeals URL - usually for a forum or wherever people should go to contact your admins.
+# BANAPPEALS https://citadel-station.net/forum/viewforum.php?f=8&sid=a0ce5331d5594ef6d49661609c6f4ff9
diff --git a/config/entries/vote.txt b/config/entries/vote.txt
new file mode 100644
index 0000000000..14c7c36a4e
--- /dev/null
+++ b/config/entries/vote.txt
@@ -0,0 +1,67 @@
+## allow players to initiate a restart vote
+#ALLOW_VOTE_RESTART
+
+## allow players to initate a mode-change start
+#ALLOW_VOTE_MODE
+
+## min delay (deciseconds) between voting sessions (default 10 minutes)
+VOTE_DELAY 6000
+
+## time period (deciseconds) which voting session will last (default 1 minute)
+VOTE_PERIOD 600
+
+## autovote initial delay (deciseconds) before first automatic transfer vote call (default 120 minutes)
+## Set to 0 to disable the subsystem altogether.
+VOTE_AUTOTRANSFER_INITIAL 72000
+
+## autovote delay (deciseconds) before sequential automatic transfer votes are called (default 30 minutes)
+VOTE_AUTOTRANSFER_INTERVAL 18000
+
+## autovote maximum votes until automatic transfer call. (default 4)
+## Set to 0 to force automatic crew transfer after the 'vote_autotransfer_initial' elapsed.
+## Set to -1 to disable the maximum votes cap.
+VOTE_AUTOTRANSFER_MAXIMUM 4
+
+## prevents dead players from voting or starting votes
+# NO_DEAD_VOTE
+
+## players' votes default to "No vote" (otherwise, default to "No change")
+# DEFAULT_NO_VOTE
+
+## Map rotation
+## You should edit maps.txt to match your configuration when you enable this.
+MAPROTATION
+
+## TG-style map rotation
+## By default, Citadel uses a more traditional method of map voting, where at the end of a round, players are given a full upfront vote.
+## This PR will disable that, and will make the server use TG's map rotation instead.
+#TGSTYLE_MAPROTATION
+
+## Map voting
+## Allows players to vote for their preffered map
+## When it's set to zero, the map will be randomly picked each round
+ALLOW_MAP_VOTING 1
+
+## Map voting type
+## Determines what kind of vote the map vote is
+## Options are:
+## PLURALITY (default, only vote for one option)
+## APPROVAL (can vote for as many as you want), I
+## IRV (vote by ranked choice, winner determined by instant runoff algorithm)
+## SCORE (give individual rankings of each choice, winner determined by majority judgement algorithm)
+MAP_VOTE_TYPE APPROVAL
+
+## Map rotate chance delta
+## This is the chance of map rotation factored to the round length.
+## A value of 1 would mean the map rotation chance is the round length in minutes (hour long round == 60% rotation chance)
+## A value of 0.5 would mean the map rotation chance is half of the round length in minutes (hour long round == 30% rotation chance)
+#MAPROTATIONCHANCEDELTA 0.75
+
+## Whether or not there's a mode tier list vote after the secret/extended vote.
+MODETIER_VOTING
+
+## Number of modes dropped by the modetier vote during mode selection, after vote.
+DROPPED_MODES 3
+
+## Whether or not you must be readied up to vote gamemode
+#MUST_BE_READIED_TO_VOTE_GAMEMODE
diff --git a/config/external_rsc_urls.txt b/config/external_rsc_urls.txt
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/config/policy.txt b/config/policy.txt
deleted file mode 100644
index 502b525ad0..0000000000
--- a/config/policy.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-## Policy configuration
-## Current valid keys are:
-## ON_CLONE - displayed after a successful cloning operation to the cloned person
-## ON_DEFIB_INTACT - displayed after defibbing before memory loss time threshold
-## ON_DEFIB_LATE - displayed after defibbing post memory loss time threshold
-## SDGF - displayed on SDGF clone spawning
-## SDGF_GOOD - displayed on SDGF clone spawning, if the clone is loyal
-## SDGF_BAD - displayed on SDGF clone spawning, if the clone is not loyal
-## PAI - displayed on PAI personality being loaded
-## EXAMPLE:
-## POLICYCONFIG ON_CLONE insert text here span classes are fully supported
-
-## Misc entries for above
-
-## Defib time limit for "cloning memory disorder" memory loss in seconds
-# DEFIB_CMD_TIME_LIMIT 300
diff --git a/dependencies.sh b/dependencies.sh
index 0fbad2153c..78f41e2dda 100644
--- a/dependencies.sh
+++ b/dependencies.sh
@@ -8,7 +8,10 @@ export BYOND_MAJOR=513
export BYOND_MINOR=1536
#rust_g git tag
-export RUST_G_VERSION=0.4.7
+export RUST_G_VERSION=0.4.8
+
+#auxmos git tag
+export AUXMOS_VERSION=v0.2.1
#node version
export NODE_VERSION=12
diff --git a/html/changelog.html b/html/changelog.html
index bf12874937..57a88744d0 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -50,6 +50,156 @@
-->
+
23 July 2021
+
silicons updated:
+
+
Batons are slightly more powerful.
+
+
+
19 July 2021
+
Arturlang updated:
+
+
The crafting button should no longer silently make more copies of itself on reconects
+
There are no longer two copies of the crafting component.
+
There is no longer a rogue d in tracer.dm tweak: Everything in Misc was moved to Miscelanious in the crafting menu, and Misc was nuked from orbit. Nobody will miss you.
+
+
MrJWhit updated:
+
+
Fixes a memory leak, there's a good chance that it's the same one that killed kilo.
+
+
SandPoot updated:
+
+
Put back mob vore with a pref.
+
Taken some stuff from tg for tgui_alert.
+
Refactored a lot of code on vore panel.
+
+
WanderingFox95 updated:
+
+
custom plasteel kegs
+
+
YakumoChen updated:
+
+
You can now wear the suffering of others on your head with just a sheet of human skin!
+
Human skin hats
+
+
keronshb updated:
+
+
Stripping/equipping things to a conscious braindead person (AKA a human owned by a disconnected player) will now give them a message with your visible name and roughly how long ago you touched their stuff when they login again. Touching someone's pockets or adjusting their gear other than equipping/unequipping is not logged. After 5 minutes, you'll have forgotten both their name and exactly how long ago past those 5 minutes it happened. (Credit to Ryll-Ryll)
+
LAZYNULL
+
Breaking mirrors now gives you a bad omen
+
+
timothyteakettle updated:
+
+
anthros can now select the cow tail
+
new quirk that allows you to eat trash
+
+
+
18 July 2021
+
timothyteakettle updated:
+
+
fixes photosynthesis stopping nutrition going past well fed from non-photosynthesis means
+
+
+
17 July 2021
+
cadyn updated:
+
+
precompile.sh updated
+
+
+
15 July 2021
+
Putnam3145 updated:
+
+
fixes a major source of lag
+
+
+
14 July 2021
+
Putnam3145 updated:
+
+
Acid is now a component
+
+
+
13 July 2021
+
MrJWhit updated:
+
+
Adds a mirror above the sink in the captains bedroom in pubby
+
+
+
12 July 2021
+
Putnam3145 updated:
+
+
causes_dirt_buildup_on_floor is now just a thing humans do instead of a weird var only true for humans
+
+
+
11 July 2021
+
shellspeed1 updated:
+
+
replaces the seed machine with a biogen in the survival pod.
+
corrected an issue regarding wrong pair of gloves in the pod for DYI wiring .
+
+
+
10 July 2021
+
WanderingFox95 updated:
+
+
Returns the wheelchair sprites to having, you know, wheels?
+
A motorized wheelchair addsound: Chairwhoosh.
+
+
+
09 July 2021
+
MrJWhit updated:
+
+
Made a light not exist on the same tile as a door on pubby.
+
Makes the RD APC automatically connect to the powernet with the correct wire on pubby.
+
Added another wall for the AM engine so it doesn't space the airlock roundstart.
+
+
+
07 July 2021
+
DeltaFire15 updated:
+
+
Golem / Plasmaman species color should work again.
+
+
+
05 July 2021
+
Putnam3145 updated:
+
+
Watchers no longer search 9 tiles away for stuff then throw the result away if it's more than 1 tile away
+
Auxmos pull now uses a tag instead of pulling straight from the main branch
+
+
WanderingFox95 updated:
+
+
Moved a sprite one pixel to the left.
+
+
zeroisthebiggay updated:
+
+
tg based tool resprites
+
wirecutters have proper overlays
+
+
+
04 July 2021
+
cadyn updated:
+
+
Updated server scripts for proper linux support
+
+
+
03 July 2021
+
DeltaFire15 updated:
+
+
Turrets on nonlethal mode now once again shoot till the target is stamcrit as opposed to unable to use items, resolving some issues.
+
+
Putnam3145 updated:
+
+
A bunch of sleeping process() calls now either don't sleep or make sure to call a proc with waitfor set to FALSE
+
+
WanderingFox95 updated:
+
+
The axolotl ears in the .dmi file actually exist to the game now.
+
+
+
02 July 2021
+
silicons updated:
+
+
spray bottles work again.
+
+
30 June 2021
WanderingFox95 updated:
@@ -429,220 +579,6 @@
adds a special hud for simple mobs.
a lot of >32x32 mobs now have icons for their health dolls
-
-
21 May 2021
-
Putnam3145 updated:
-
-
Fixed activity being attached to minds instead of mobs on antag attach.
-
-
-
20 May 2021
-
qweq12yt updated:
-
-
Fixed void cloak voiding itself into oblivion.
-
You can now order emag shuttles again.
-
-
timothyteakettle updated:
-
-
ports rp's marking system
-
-
-
19 May 2021
-
WanderingFox95 updated:
-
-
The E-Fink, a mending tool for food.
-
A backwards bladeslice. (Yes, for the E-fink)
-
And Icons for the E-fink, of course.
-
-
shellspeed1 updated:
-
-
Survival pods can now be designated as requiring power. Survival pods with this feature should include an APC when created and will run out of power rather quickly if no source is added. Perfect for true emergencies.
-
An empty survival pod has been added to the mining vendor. This is an extremely barebones pod featuring only a gps, table, apc, and the standard fridge for some donk pockets.
-
-
zeroisthebiggay updated:
-
-
New Alcohol Amaretto and various cocktails
-
more drink mixture flavortext
-
you're going to Baystation
-
-
-
15 May 2021
-
bunny232 updated:
-
-
Corrects the bot pathing by engineering on meta station
-
-
timothyteakettle updated:
-
-
borg spraycans have a five second delay before being able to knock someone down again
-
-
-
14 May 2021
-
keronshb updated:
-
-
Removes VOG sleep command since it was an undocumented readd.
-
-
zeroisthebiggay updated:
-
-
consealed
-
-
-
13 May 2021
-
Linzolle updated:
-
-
anthromorphic -> anthropomorphic
-
-
WanderingFox95 updated:
-
-
Pinot Mort (Necropolis Wine), a new, (totally healthy) mixed drink!
-
-
qweq12yt updated:
-
-
Fixed sleeping disky spam (it still sleeps soundly, but every minute instead of every two seconds)
-
Fixed Hulks not breaking cuffs, zipties, restraints.
-
-
silicons updated:
-
-
A deterministic wave explosion system has been added. Use it with wave_explosion().
-
-
zeroisthebiggay updated:
-
-
vegas style bunny ears
-
-
-
12 May 2021
-
DeltaFire15 updated:
-
-
find_safe_turf no longer always fails on safe oxygen levels(??)
-
Heretic bladeshatters now actually take the heretic's z into account as intended, instead of always being station z tweak: Message for failing the bladeshatter despite succeeding the do_after tweak: Improves bladeshatter a bit by making it safer codewise
-
-
-
11 May 2021
-
LetterN updated:
-
-
fixes emagging console shuttle purchases
-
syndie melee simplemobs has no more bullshit shield
-
-
bunny232 updated:
-
-
Delta station xenobiology department has received enhanced scrubbing and ventilation capabilities similar to box and meta
-
-
-
09 May 2021
-
Putnam3145 updated:
-
-
Priority announcement admeme verb
-
-
SandPoot updated:
-
-
Fixed Cyborg examines adding an extra weird line.
-
Everything can be set to have tooltips, and even coded to have neat tooltips.
-
Makes it so humans and borgs already have tooltips.
-
-
TheObserver-sys updated:
-
-
Fixes most of the weird handling bugs and improves cigarette case handling in general.
-
The Gorlex Marauders have seen fit to allow you to purchase the .45-70 GOVT rare ammo, at a premium cost. Don't waste it.
-
-
WanderingFox95 updated:
-
-
added the unrolling pin, an innovative solution to dough-based mishaps.
-
added visuals for the unrolling pin
-
-
dzahlus updated:
-
-
added new malf AI spawn and doomsday sound
-
removed old malf AI spawn and doomsday sound
-
-
zeroisthebiggay updated:
-
-
pirates now have a medbay and several other things qualifying as a buff
-
pirates lost their toilet
-
-
-
08 May 2021
-
Arturlang updated:
-
-
Synthblood bottles now have the proper color and probably won't poison you anymore
-
-
timothyteakettle updated:
-
-
lets humans have digi legs (and avian legs)
-
-
-
05 May 2021
-
The0bserver, with a great amount of advice from TripleZeta/TetraZeta updated:
-
-
Adds a new crate type, for use with any manner of cheeky breeki shenanigans, as well as with existing Russian contraband.
-
-
bunny232 updated:
-
-
There's some new vents and scrubbers in the meta station xenobiology department. Welders and wrenches not included*
-
-
keronshb updated:
-
-
Nightmare Shadow Jaunt threshold up to 0.4
-
Vendor and Engraved message light down to 0.3
-
-
-
03 May 2021
-
TripleShades updated:
-
-
Added two air alarms to Pubby Security, one in the evidence locker room and one in the main equipment back room
-
pAI Card back to outside Research in Meta Station
-
Pubby Disposals now shunts to space
-
Maintinence Areas being not applied to certain airlocks as well as stealing minor walls
-
Box Surgery Storage camera is now renamed to be on the network
-
Box Paramedic Station camera is now renamed to be on the network, and no longer steals the Morgue's cam tweak: Box Surgery Storage is now it's own proper room
-
-
-
01 May 2021
-
qweq12yt updated:
-
-
Restores the sprite for the Riot Suit.
-
-
-
30 April 2021
-
DrPainis updated:
-
-
Bubblegum's hallucinations are capitalized.
-
-
Melbert, SandPoot updated:
-
-
TGUI Limbgrower
-
Refactored the limbgrower to modernize the code and allow for more types of designs.
-
The limbgrower now supports plumbing ducts.
-
Fixes genitals not actually getting data from disks.
-
Adds two special helpers.
-
-
SandPoot updated:
-
-
The decal painter now has visible previews for your tile painting funs.
-
Fixes decal painter painting in the opposite direction.
-
-
TheObserver-sys updated:
-
-
Restores the access lock on crates that should have them, given the goods inside.
-
Makes the 10MM Surplus Rifle a less awful thing to use.
-
replaces unarmored things with their armored versions.
-
Illegal Tech Ammo actually is fucking reasonable, now.
-
Expensive Illegal Tech Ammo Boxes are now constructible, with actually justifiable prices.
-
-
WanderingFox95 updated:
-
-
There's finally a reason for the reagent dart gun to exist and be used!
-
-
akada updated:
-
-
Changes the space adaptation sprite to something less intrusive and more subtle.
-
-
necromanceranne updated:
-
-
Basic cybernetic organs: they're worse than organic! Basic stomachs, hearts, lungs and livers! For when you hate someone enough to not bother harvesting organs from a monkeyhuman!
-
Cybernetic organs have been adjusted into three tiers: 1 (basic), 2 (standard, better than organic) and 3 (absolutely better than organic but expensive to print)
-
Cybernetic organs that are emp'd instead suffer different effects based on the severity of the emp. The bigger the emp, the worse the effect is.
-
Rather than outright bricking, severely emp'd cyberorgans degrade over time very quickly, requiring replacement in the near future.
-
Fake blindfolds in the loadout. They don't obscure vision, for better or worse.
-
GoonStation 13 Development Team
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index 82e2f373c8..e876de4e3a 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -29606,3 +29606,102 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
Make sure to try and recover it.
- rscadd: Adds an extremely expensive survival pod to mining for people to work
towards. Get to work cracking rocks today.
+2021-07-02:
+ silicons:
+ - bugfix: spray bottles work again.
+2021-07-03:
+ DeltaFire15:
+ - bugfix: Turrets on nonlethal mode now once again shoot till the target is stamcrit
+ as opposed to unable to use items, resolving some issues.
+ Putnam3145:
+ - bugfix: A bunch of sleeping process() calls now either don't sleep or make sure
+ to call a proc with waitfor set to FALSE
+ WanderingFox95:
+ - bugfix: The axolotl ears in the .dmi file actually exist to the game now.
+2021-07-04:
+ cadyn:
+ - server: Updated server scripts for proper linux support
+2021-07-05:
+ Putnam3145:
+ - bugfix: Watchers no longer search 9 tiles away for stuff then throw the result
+ away if it's more than 1 tile away
+ - server: Auxmos pull now uses a tag instead of pulling straight from the main branch
+ WanderingFox95:
+ - bugfix: Moved a sprite one pixel to the left.
+ zeroisthebiggay:
+ - imageadd: tg based tool resprites
+ - bugfix: wirecutters have proper overlays
+2021-07-07:
+ DeltaFire15:
+ - bugfix: Golem / Plasmaman species color should work again.
+2021-07-09:
+ MrJWhit:
+ - bugfix: Made a light not exist on the same tile as a door on pubby.
+ - bugfix: Makes the RD APC automatically connect to the powernet with the correct
+ wire on pubby.
+ - rscadd: Added another wall for the AM engine so it doesn't space the airlock roundstart.
+2021-07-10:
+ WanderingFox95:
+ - imageadd: Returns the wheelchair sprites to having, you know, wheels?
+ - rscadd: 'A motorized wheelchair addsound: Chairwhoosh.'
+2021-07-11:
+ shellspeed1:
+ - balance: replaces the seed machine with a biogen in the survival pod.
+ - bugfix: corrected an issue regarding wrong pair of gloves in the pod for DYI wiring
+ .
+2021-07-12:
+ Putnam3145:
+ - refactor: causes_dirt_buildup_on_floor is now just a thing humans do instead of
+ a weird var only true for humans
+2021-07-13:
+ MrJWhit:
+ - rscadd: Adds a mirror above the sink in the captains bedroom in pubby
+2021-07-14:
+ Putnam3145:
+ - refactor: Acid is now a component
+2021-07-15:
+ Putnam3145:
+ - bugfix: fixes a major source of lag
+2021-07-17:
+ cadyn:
+ - server: precompile.sh updated
+2021-07-18:
+ timothyteakettle:
+ - bugfix: fixes photosynthesis stopping nutrition going past well fed from non-photosynthesis
+ means
+2021-07-19:
+ Arturlang:
+ - bugfix: The crafting button should no longer silently make more copies of itself
+ on reconects
+ - code_imp: There are no longer two copies of the crafting component.
+ - code_imp: 'There is no longer a rogue d in tracer.dm tweak: Everything in Misc
+ was moved to Miscelanious in the crafting menu, and Misc was nuked from orbit.
+ Nobody will miss you.'
+ MrJWhit:
+ - bugfix: Fixes a memory leak, there's a good chance that it's the same one that
+ killed kilo.
+ SandPoot:
+ - rscadd: Put back mob vore with a pref.
+ - code_imp: Taken some stuff from tg for tgui_alert.
+ - refactor: Refactored a lot of code on vore panel.
+ WanderingFox95:
+ - rscadd: custom plasteel kegs
+ YakumoChen:
+ - rscadd: You can now wear the suffering of others on your head with just a sheet
+ of human skin!
+ - imageadd: Human skin hats
+ keronshb:
+ - rscadd: Stripping/equipping things to a conscious braindead person (AKA a human
+ owned by a disconnected player) will now give them a message with your visible
+ name and roughly how long ago you touched their stuff when they login again.
+ Touching someone's pockets or adjusting their gear other than equipping/unequipping
+ is not logged. After 5 minutes, you'll have forgotten both their name and exactly
+ how long ago past those 5 minutes it happened. (Credit to Ryll-Ryll)
+ - rscadd: LAZYNULL
+ - rscadd: Breaking mirrors now gives you a bad omen
+ timothyteakettle:
+ - bugfix: anthros can now select the cow tail
+ - rscadd: new quirk that allows you to eat trash
+2021-07-23:
+ silicons:
+ - balance: Batons are slightly more powerful.
diff --git a/html/changelogs/AutoChangeLog-pr-14960.yml b/html/changelogs/AutoChangeLog-pr-14960.yml
new file mode 100644
index 0000000000..b5f8eba14f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-14960.yml
@@ -0,0 +1,5 @@
+author: "Putnam3145"
+delete-after: True
+changes:
+ - bugfix: "hallucination now bottoms out at 0"
+ - balance: "supermatter now causes only half the hallucinations"
diff --git a/html/changelogs/AutoChangeLog-pr-14963.yml b/html/changelogs/AutoChangeLog-pr-14963.yml
new file mode 100644
index 0000000000..644f58bf0b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-14963.yml
@@ -0,0 +1,4 @@
+author: "cadyn"
+delete-after: True
+changes:
+ - server: "auxmos bump for dependencies.sh"
diff --git a/icons/mob/clothing/head.dmi b/icons/mob/clothing/head.dmi
index 806f378323..51675c8d7d 100644
Binary files a/icons/mob/clothing/head.dmi and b/icons/mob/clothing/head.dmi differ
diff --git a/icons/mob/inhands/equipment/tools_lefthand.dmi b/icons/mob/inhands/equipment/tools_lefthand.dmi
index c25ea837da..27aaef50b1 100644
Binary files a/icons/mob/inhands/equipment/tools_lefthand.dmi and b/icons/mob/inhands/equipment/tools_lefthand.dmi differ
diff --git a/icons/mob/inhands/equipment/tools_righthand.dmi b/icons/mob/inhands/equipment/tools_righthand.dmi
index 65f1145278..54f8f6560d 100644
Binary files a/icons/mob/inhands/equipment/tools_righthand.dmi and b/icons/mob/inhands/equipment/tools_righthand.dmi differ
diff --git a/icons/obj/clothing/belt_overlays.dmi b/icons/obj/clothing/belt_overlays.dmi
index 5f31a65ffa..0799920a6c 100644
Binary files a/icons/obj/clothing/belt_overlays.dmi and b/icons/obj/clothing/belt_overlays.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index e5bd686603..854928f2ca 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index 34f9867ee9..b507b3bcdd 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/icons/obj/nuke_tools.dmi b/icons/obj/nuke_tools.dmi
index 799c4baabb..7f5c730fe5 100644
Binary files a/icons/obj/nuke_tools.dmi and b/icons/obj/nuke_tools.dmi differ
diff --git a/icons/obj/objects.dmi b/icons/obj/objects.dmi
index b9c891ddb9..6d29b8df8e 100644
Binary files a/icons/obj/objects.dmi and b/icons/obj/objects.dmi differ
diff --git a/icons/obj/tools.dmi b/icons/obj/tools.dmi
index 8414c8b95c..a720aff62c 100644
Binary files a/icons/obj/tools.dmi and b/icons/obj/tools.dmi differ
diff --git a/icons/obj/vehicles.dmi b/icons/obj/vehicles.dmi
index d12851f572..14b19caef8 100644
Binary files a/icons/obj/vehicles.dmi and b/icons/obj/vehicles.dmi differ
diff --git a/libauxmos.so b/libauxmos.so
deleted file mode 100644
index d7566ab1e4..0000000000
Binary files a/libauxmos.so and /dev/null differ
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
index 60c009bc29..043d9e5603 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
@@ -109,7 +109,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
ZI.Insert(SM)
log_reagent("FERMICHEM: [M] ckey: [M.key]'s zombie_infection has been transferred to their clone")
- var/list/policies = CONFIG_GET(keyed_list/policyconfig)
+ var/list/policies = CONFIG_GET(keyed_list/policy)
var/policy = policies[POLICYCONFIG_SDGF]
if(policy)
to_chat(SM,policy)
@@ -127,7 +127,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
else
to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. However, You find yourself indifferent to the goals you previously had, and take more interest in your newfound independence, but still have an indescribable care for the safety of your original.")
log_reagent("FERMICHEM: [SM] ckey: [SM.key]'s is not bound by [M] ckey [M.key]'s will, and is free to determine their own goals, while respecting and acting as their origin.")
-
+
to_chat(SM, "You feel a strange sensation building in your mind as you realise there's two of you. Before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with your original, a perfect clone of your origin.")
SM.client?.change_view(CONFIG_GET(string/default_view))
to_chat(M, "You feel a strange sensation building in your mind as you realise there's two of you. Before you get a chance to think about it, a mass splits from you, and find yourself face to face with yourself.")
diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm
index ab39e6f4a7..edaaeb19b2 100644
--- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm
@@ -28,6 +28,7 @@
//Called when temperature is above a certain threshold, or if purity is too low.
/datum/chemical_reaction/proc/FermiExplode(datum/reagents/R0, var/atom/my_atom, volume, temp, pH, Exploding = FALSE)
+ set waitfor = FALSE
if (Exploding == TRUE)
return
diff --git a/modular_citadel/icons/mob/mam_ears.dmi b/modular_citadel/icons/mob/mam_ears.dmi
index 51541619d4..dd3ea5f82b 100644
Binary files a/modular_citadel/icons/mob/mam_ears.dmi and b/modular_citadel/icons/mob/mam_ears.dmi differ
diff --git a/sound/effects/chairwhoosh.ogg b/sound/effects/chairwhoosh.ogg
new file mode 100644
index 0000000000..907659f7cb
Binary files /dev/null and b/sound/effects/chairwhoosh.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index ed85c32cc4..2da48b8f2f 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -109,6 +109,7 @@
#include "code\__DEFINES\sight.dm"
#include "code\__DEFINES\sound.dm"
#include "code\__DEFINES\spaceman_dmm.dm"
+#include "code\__DEFINES\spans.dm"
#include "code\__DEFINES\species.dm"
#include "code\__DEFINES\stat.dm"
#include "code\__DEFINES\stat_tracking.dm"
@@ -291,22 +292,33 @@
#include "code\controllers\subsystem.dm"
#include "code\controllers\configuration\config_entry.dm"
#include "code\controllers\configuration\configuration.dm"
+#include "code\controllers\configuration\entries\admin.dm"
+#include "code\controllers\configuration\entries\alert.dm"
+#include "code\controllers\configuration\entries\antag_rep.dm"
#include "code\controllers\configuration\entries\comms.dm"
+#include "code\controllers\configuration\entries\connections.dm"
#include "code\controllers\configuration\entries\dbconfig.dm"
+#include "code\controllers\configuration\entries\debris.dm"
#include "code\controllers\configuration\entries\donator.dm"
#include "code\controllers\configuration\entries\dynamic.dm"
-#include "code\controllers\configuration\entries\fail2topic.dm"
-#include "code\controllers\configuration\entries\game_options.dm"
+#include "code\controllers\configuration\entries\fetish_content.dm"
+#include "code\controllers\configuration\entries\gamemodes.dm"
#include "code\controllers\configuration\entries\general.dm"
+#include "code\controllers\configuration\entries\jexp.dm"
#include "code\controllers\configuration\entries\logging.dm"
+#include "code\controllers\configuration\entries\movespeed.dm"
#include "code\controllers\configuration\entries\persistence.dm"
#include "code\controllers\configuration\entries\plushies.dm"
#include "code\controllers\configuration\entries\policy.dm"
#include "code\controllers\configuration\entries\resources.dm"
#include "code\controllers\configuration\entries\respawns.dm"
+#include "code\controllers\configuration\entries\security.dm"
+#include "code\controllers\configuration\entries\server.dm"
#include "code\controllers\configuration\entries\stamina_combat.dm"
+#include "code\controllers\configuration\entries\threat.dm"
+#include "code\controllers\configuration\entries\urls.dm"
+#include "code\controllers\configuration\entries\vote.dm"
#include "code\controllers\subsystem\achievements.dm"
-#include "code\controllers\subsystem\acid.dm"
#include "code\controllers\subsystem\activity.dm"
#include "code\controllers\subsystem\adjacent_air.dm"
#include "code\controllers\subsystem\air.dm"
@@ -459,6 +471,7 @@
#include "code\datums\brain_damage\special.dm"
#include "code\datums\brain_damage\split_personality.dm"
#include "code\datums\components\_component.dm"
+#include "code\datums\components\acid.dm"
#include "code\datums\components\activity.dm"
#include "code\datums\components\anti_magic.dm"
#include "code\datums\components\armor_plate.dm"
@@ -639,6 +652,7 @@
#include "code\datums\elements\swimming.dm"
#include "code\datums\elements\sword_point.dm"
#include "code\datums\elements\tactical.dm"
+#include "code\datums\elements\trash.dm"
#include "code\datums\elements\turf_transparency.dm"
#include "code\datums\elements\update_icon_blocker.dm"
#include "code\datums\elements\update_icon_updates_onmob.dm"
@@ -3593,6 +3607,7 @@
#include "code\modules\tgui\states\observer.dm"
#include "code\modules\tgui\states\physical.dm"
#include "code\modules\tgui\states\self.dm"
+#include "code\modules\tgui\states\vorepanel.dm"
#include "code\modules\tgui\states\zlevel.dm"
#include "code\modules\tgui_panel\audio.dm"
#include "code\modules\tgui_panel\external.dm"
@@ -3630,6 +3645,7 @@
#include "code\modules\vehicles\wheelchair.dm"
#include "code\modules\vehicles\cars\car.dm"
#include "code\modules\vehicles\cars\clowncar.dm"
+#include "code\modules\vehicles\motorized_wheelchair.dm"
#include "code\modules\vending\_vending.dm"
#include "code\modules\vending\assist.dm"
#include "code\modules\vending\autodrobe.dm"
diff --git a/tgui/packages/tgui/interfaces/VorePanel.js b/tgui/packages/tgui/interfaces/VorePanel.js
new file mode 100644
index 0000000000..3e29c8bff4
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/VorePanel.js
@@ -0,0 +1,591 @@
+/* eslint-disable max-len */
+import { Fragment } from 'inferno';
+import { useBackend, useLocalState } from "../backend";
+import { Box, Button, Flex, Collapsible, Icon, LabeledList, NoticeBox, Section, Tabs } from "../components";
+import { Window } from "../layouts";
+
+const stats = [
+ null,
+ 'average',
+ 'bad',
+];
+
+const digestModeToColor = {
+ "Hold": null,
+ "Dragon": "blue",
+ "Digest": "red",
+ "Absorb": "purple",
+ "Unabsorb": "purple",
+};
+
+const digestModeToPreyMode = {
+ "Hold": "being held.",
+ "Digest": "being digested.",
+ "Absorb": "being absorbed.",
+ "Unabsorb": "being unabsorbed.",
+ "Dragon": "being digested by a powerful creature.",
+};
+
+/**
+ * There are three main sections to this UI.
+ * - The Inside Panel, where all relevant data for interacting with a belly you're in is located.
+ * - The Belly Selection Panel, where you can select what belly people will go into and customize the active one.
+ * - User Preferences, where you can adjust all of your vore preferences on the fly.
+ */
+export const VorePanel = (props, context) => {
+ const { act, data } = useBackend(context);
+ return (
+
+
+ {data.unsaved_changes && (
+
+
+
+ Warning: Unsaved Changes!
+
+
+
+
+
+ ) || null}
+
+
+
+
+
+ );
+};
+
+const VoreInsidePanel = (props, context) => {
+ const { act, data } = useBackend(context);
+
+ const {
+ absorbed,
+ belly_name,
+ belly_mode,
+ desc,
+ pred,
+ contents,
+ ref,
+ } = data.inside;
+
+ if (!belly_name) {
+ return (
+
+ You aren't inside anyone.
+
+ );
+ }
+
+ return (
+
+ You are currently {absorbed ? "absorbed into" : "inside"}
+ {pred}'s
+ {belly_name}
+ and you are
+ {digestModeToPreyMode[belly_mode]}
+
+ {desc}
+
+ {contents.length && (
+
+
+
+ ) || "There is nothing else around you."}
+
+ );
+};
+
+const VoreBellySelectionAndCustomization = (props, context) => {
+ const { act, data } = useBackend(context);
+
+ const {
+ our_bellies,
+ selected,
+ } = data;
+
+ return (
+
+
+ {our_bellies.map(belly => (
+ act("bellypick", { bellypick: belly.ref })}>
+
+ {belly.name} ({belly.contents})
+
+
+ ))}
+ act("newbelly")}>
+ New
+
+
+
+ {selected && }
+
+ );
+};
+
+/**
+ * Subtemplate of VoreBellySelectionAndCustomization
+ */
+const VoreSelectedBelly = (props, context) => {
+ const { act } = useBackend(context);
+
+ const { belly } = props;
+ const {
+ belly_name,
+ is_wet,
+ wet_loop,
+ mode,
+ verb,
+ desc,
+ sound,
+ release_sound,
+ can_taste,
+ bulge_size,
+ escapable,
+ interacts,
+ contents,
+ } = belly;
+
+ const [tabIndex, setTabIndex] = useLocalState(context, 'tabIndex', 0);
+
+ return (
+
+
+ setTabIndex(0)}>
+ Controls
+
+ setTabIndex(1)}>
+ Options
+
+ setTabIndex(2)}>
+ Contents ({contents.length})
+
+ setTabIndex(3)}>
+ Interactions
+
+
+ {tabIndex === 0 && (
+
+
+
+ }>
+ act("set_attribute", { attribute: "b_name" })}
+ content={belly_name} />
+
+
+ act("set_attribute", { attribute: "b_mode" })}
+ content={mode} />
+
+ act("set_attribute", { attribute: "b_desc" })}
+ icon="pen" />
+ }>
+ {desc}
+
+
+ act("set_attribute", { attribute: "b_verb" })}
+ content={verb} />
+
+
+ act("set_attribute", { attribute: "b_msgs", msgtype: "dmp" })}
+ content="Digest Message (to prey)" />
+ act("set_attribute", { attribute: "b_msgs", msgtype: "dmo" })}
+ content="Digest Message (to you)" />
+ act("set_attribute", { attribute: "b_msgs", msgtype: "smo" })}
+ content="Struggle Message (outside)" />
+ act("set_attribute", { attribute: "b_msgs", msgtype: "smi" })}
+ content="Struggle Message (inside)" />
+ act("set_attribute", { attribute: "b_msgs", msgtype: "em" })}
+ content="Examine Message (when full)" />
+ act("set_attribute", { attribute: "b_msgs", msgtype: "reset" })}
+ content="Reset Messages" />
+
+
+ ) || tabIndex === 1 && (
+
+
+
+
+ act("set_attribute", { attribute: "b_tastes" })}
+ icon={can_taste ? "toggle-on" : "toggle-off"}
+ selected={can_taste}
+ content={can_taste ? "Yes" : "No"} />
+
+
+ act("set_attribute", { attribute: "b_wetness" })}
+ icon={is_wet ? "toggle-on" : "toggle-off"}
+ selected={is_wet}
+ content={is_wet ? "Yes" : "No"} />
+
+
+ act("set_attribute", { attribute: "b_wetloop" })}
+ icon={wet_loop ? "toggle-on" : "toggle-off"}
+ selected={wet_loop}
+ content={wet_loop ? "Yes" : "No"} />
+
+
+
+
+
+
+ act("set_attribute", { attribute: "b_sound" })}
+ content={sound} />
+ act("set_attribute", { attribute: "b_soundtest" })}
+ icon="volume-up" />
+
+
+ act("set_attribute", { attribute: "b_release" })}
+ content={release_sound} />
+ act("set_attribute", { attribute: "b_releasesoundtest" })}
+ icon="volume-up" />
+
+
+ act("set_attribute", { attribute: "b_bulge_size" })}
+ content={bulge_size * 100 + "%"} />
+
+
+
+
+ act("set_attribute", { attribute: "b_del" })} />
+
+
+ ) || tabIndex === 2 && (
+
+ ) || tabIndex === 3 && (
+ act("set_attribute", { attribute: "b_escapable" })}
+ icon={escapable ? "toggle-on" : "toggle-off"}
+ selected={escapable}
+ content={escapable ? "Interactions On" : "Interactions Off"} />
+ }>
+ {escapable ? (
+
+
+ act("set_attribute", { attribute: "b_escapechance" })} />
+
+
+ act("set_attribute", { attribute: "b_escapetime" })} />
+
+
+
+ act("set_attribute", { attribute: "b_transferchance" })} />
+
+
+ act("set_attribute", { attribute: "b_transferlocation" })} />
+
+
+
+ act("set_attribute", { attribute: "b_absorbchance" })} />
+
+
+ act("set_attribute", { attribute: "b_digestchance" })} />
+
+
+ ) : "These options only display while interactions are turned on."}
+
+ ) || "Error"}
+
+ );
+};
+
+const VoreContentsPanel = (props, context) => {
+ const { act, data } = useBackend(context);
+ const {
+ show_pictures,
+ } = data;
+ const {
+ contents,
+ belly,
+ outside = false,
+ } = props;
+
+ return (
+
+ {outside && (
+ act("pick_from_outside", { "pickall": true })}>
+ All
+
+ ) || null}
+ {show_pictures && (
+
+ {contents.map(thing => (
+
+ act(thing.outside ? "pick_from_outside" : "pick_from_inside", {
+ "pick": thing.ref,
+ "belly": belly,
+ })}>
+
+
+ {thing.name}
+
+ ))}
+
+ ) || (
+
+ {contents.map(thing => (
+
+ act(thing.outside ? "pick_from_outside" : "pick_from_inside", {
+ "pick": thing.ref,
+ "belly": belly,
+ })}>
+ Interact
+
+
+ ))}
+
+ )}
+
+ );
+};
+
+const VoreUserPreferences = (props, context) => {
+ const { act, data } = useBackend(context);
+
+ const {
+ digestable,
+ devourable,
+ feeding,
+ absorbable,
+ allowmobvore,
+ vore_sounds,
+ digestion_sounds,
+ lickable,
+ smellable,
+ } = data.prefs;
+
+ const {
+ show_pictures,
+ } = data;
+
+ return (
+ act("show_pictures")}>
+ Contents Preference: {show_pictures ? "Show Pictures" : "Show List"}
+
+ }>
+
+
+ act("toggle_devour")}
+ icon={devourable ? "toggle-on" : "toggle-off"}
+ selected={devourable}
+ fluid
+ tooltip={"This button is to toggle your ability to be devoured by others. "
+ + (devourable ? "Click here to prevent being devoured." : "Click here to allow being devoured.")}
+ content={devourable ? "Devouring Allowed" : "No Devouring"} />
+
+
+ act("toggle_mobvore")}
+ icon={allowmobvore ? "toggle-on" : "toggle-off"}
+ selected={allowmobvore}
+ fluid
+ tooltip={"This button is for those who don't like being eaten by mobs. "
+ + (allowmobvore
+ ? "Click here to prevent being eaten by mobs."
+ : "Click here to allow being eaten by mobs.")}
+ tooltipPosition="bottom-right"
+ content={allowmobvore ? "Mobs eating you allowed" : "No Mobs eating you"} />
+
+
+ act("toggle_feed")}
+ icon={feeding ? "toggle-on" : "toggle-off"}
+ selected={feeding}
+ fluid
+ tooltip={"This button is to toggle your ability to be fed to or by others vorishly. "
+ + (feeding
+ ? "Click here to prevent being fed to/by other people."
+ : "Click here to allow being fed to/by other people.")}
+ content={feeding ? "Feeding Allowed" : "No Feeding"} />
+
+
+ act("toggle_digest")}
+ icon={digestable ? "toggle-on" : "toggle-off"}
+ selected={digestable}
+ fluid
+ tooltip={"This button is for those who don't like being digested. It can make you undigestable."
+ + (digestable ? " Click here to prevent digestion." : " Click here to allow digestion.")}
+ tooltipPosition="bottom-right"
+ content={digestable ? "Digestion Allowed" : "No Digestion"} />
+
+
+ act("toggle_absorbable")}
+ icon={absorbable ? "toggle-on" : "toggle-off"}
+ selected={absorbable}
+ fluid
+ tooltip={"This button allows preds to know whether you prefer or don't prefer to be absorbed. "
+ + (absorbable ? "Click here to disallow being absorbed." : "Click here to allow being absorbed.")}
+ content={absorbable ? "Absorption Allowed" : "No Absorption"} />
+
+
+ act("toggle_vore_sounds")}
+ icon={vore_sounds ? "volume-up" : "volume-mute"}
+ selected={vore_sounds}
+ fluid
+ tooltip={"Be able to hear vore sounds. "
+ + (vore_sounds
+ ? "Click here to turn off vore sounds."
+ : "Click here to turn on vore sounds.")}
+ content={vore_sounds ? "Vore Sounds Enabled" : "Vore Sounds Disabled"} />
+
+
+ act("toggle_digestion_sounds")}
+ icon={digestion_sounds ? "volume-up" : "volume-mute"}
+ selected={digestion_sounds}
+ fluid
+ tooltip={"Be able to hear digestion sounds. "
+ + (digestion_sounds
+ ? "Click here to turn off digestion sounds."
+ : "Click here to turn on digestion sounds.")}
+ content={digestion_sounds ? "Digestion Sounds Enabled" : "Digestion Sounds Disabled"} />
+
+
+ act("toggle_lickable")}
+ icon={lickable ? "toggle-on" : "toggle-off"}
+ selected={lickable}
+ fluid
+ tooltip={"Be able to be licked by others. "
+ + (lickable
+ ? "Click here to turn off being able to be licked."
+ : "Click here to turn on being able to be licked.")}
+ tooltipPosition="bottom-right"
+ content={lickable ? "Lickable" : "Unlickable"} />
+
+
+ act("setflavor")} />
+
+
+ act("toggle_smellable")}
+ icon={smellable ? "toggle-on" : "toggle-off"}
+ selected={smellable}
+ fluid
+ tooltip={"Be able to be smelled by others. "
+ + (smellable
+ ? "Click here to turn off being able to be smelled."
+ : "Click here to turn on being able to be smelled.")}
+ content={smellable ? "Smellable" : "Unsmellable"} />
+
+
+ act("setsmell")} />
+
+
+
+
+
+ act("saveprefs")} />
+
+
+ act("reloadprefs")} />
+
+
+
+
+ );
+};
diff --git a/tools/build/binaries/README.md b/tools/build/binaries/README.md
new file mode 100644
index 0000000000..625f337d98
--- /dev/null
+++ b/tools/build/binaries/README.md
@@ -0,0 +1 @@
+This directory is used to store temporary files to create binaries on linux
\ No newline at end of file
diff --git a/tools/build/build b/tools/build/build
index 0e202e1bba..cd4d804e8f 100755
--- a/tools/build/build
+++ b/tools/build/build
@@ -1,4 +1,6 @@
#!/bin/sh
+
+#Build TGUI
set -e
cd "$(dirname "$0")"
exec ../bootstrap/node build.js "$@"
diff --git a/tools/build/build.sh b/tools/build/build.sh
new file mode 100755
index 0000000000..5d050764d1
--- /dev/null
+++ b/tools/build/build.sh
@@ -0,0 +1,75 @@
+#!/bin/sh
+
+#Detect OS and use corresponding package manager for dependencies. Currently only works for arch, debian/ubuntu, and RHEL/fedora/CentOS
+if [[ -f '/etc/arch-release' ]]; then
+ echo -ne '\n y' | sudo pacman --needed -Sy base-devel git curl nodejs unzip
+fi
+if [[ -f '/etc/debian version' ]]; then
+ sudo dpkg --add-architecture i386
+ sudo apt-get update
+ sudo apt-get install -y build-essential git curl lib32z1 pkg-config libssl-dev:i386 libssl-dev nodejs unzip g++-multilib libc6-i386 libstdc++6:i386
+fi
+if [[ -f '/etc/centos-release' ]] || [[ -f '/etc/fedora-release' ]]; then #DNF should work for both of these
+ sudo dnf --refresh install make automake gcc gcc-c++ kernel-devel git curl unzip glibc-devel.i686 openssl-devel.i686 libgcc.i686 libstdc++-devel.i686
+fi
+
+cd binaries
+
+#Install rust if not present
+if ! [ -x "$has_cargo" ]; then
+ echo "Installing rust..."
+ curl https://sh.rustup.rs -sSf | sh -s -- -y
+ . ~/.profile
+fi
+
+#Download/update rust-g repo
+if [ ! -d "rust-g" ]; then
+ echo "Cloning rust-g..."
+ git clone https://github.com/tgstation/rust-g
+ cd rust-g
+ ~/.cargo/bin/rustup target add i686-unknown-linux-gnu
+else
+ echo "Fetching rust-g..."
+ cd rust-g
+ git fetch
+ ~/.cargo/bin/rustup target add i686-unknown-linux-gnu
+fi
+
+#Compile and move rust-g binary to repo root
+echo "Deploying rust-g..."
+git checkout "$RUST_G_VERSION"
+env PKG_CONFIG_ALLOW_CROSS=1 ~/.cargo/bin/cargo build --release --target=i686-unknown-linux-gnu
+mv target/i686-unknown-linux-gnu/release/librust_g.so ../../../../librust_g.so
+cd ..
+
+#Download/update auxmos repo
+if [ ! -d "auxmos" ]; then
+ echo "Cloning auxmos..."
+ git clone https://github.com/Putnam3145/auxmos
+ cd auxmos
+ ~/.cargo/bin/rustup target add i686-unknown-linux-gnu
+else
+ echo "Fetching auxmos..."
+ cd auxmos
+ git fetch
+ ~/.cargo/bin/rustup target add i686-unknown-linux-gnu
+fi
+
+#Compile and move auxmos binary to repo root
+echo "Deploying auxmos..."
+git checkout "$AUXMOS_VERSION"
+env PKG_CONFIG_ALLOW_CROSS=1 ~/.cargo/bin/cargo rustc --release --target=i686-unknown-linux-gnu --features "all_reaction_hooks" -- -C target-cpu=native
+mv target/i686-unknown-linux-gnu/release/libauxmos.so ../../../../libauxmos.so
+cd ../..
+
+#Install BYOND
+cd ../..
+./tools/ci/install_byond.sh
+source $HOME/BYOND/byond/bin/byondsetup
+
+cd tools/build
+
+#Build TGUI
+set -e
+cd "$(dirname "$0")"
+exec ../bootstrap/node build.js "$@"
diff --git a/tools/tgs4_scripts/PreCompile.sh b/tools/tgs4_scripts/PreCompile.sh
index f21036ab19..6463b1a0d6 100755
--- a/tools/tgs4_scripts/PreCompile.sh
+++ b/tools/tgs4_scripts/PreCompile.sh
@@ -66,31 +66,27 @@ env PKG_CONFIG_ALLOW_CROSS=1 ~/.cargo/bin/cargo build --release --target=i686-un
mv target/i686-unknown-linux-gnu/release/librust_g.so "$1/librust_g.so"
cd ..
-# get dependencies for extools
-apt-get install -y cmake build-essential gcc-multilib g++-multilib cmake wget
+# Auxtools dependencies
+apt-get install -y build-essential g++-multilib libc6-i386 libstdc++6:i386
-# update extools
-if [ ! -d "extools" ]; then
- echo "Cloning extools..."
- git clone https://github.com/MCHSL/extools
- cd extools/byond-extools
+# Update auxmos
+if [ ! -d "auxmos" ]; then
+ echo "Cloning auxmos..."
+ git clone https://github.com/Putnam3145/auxmos
+ cd auxmos
+ ~/.cargo/bin/rustup target add i686-unknown-linux-gnu
else
- echo "Fetching extools..."
- cd extools/byond-extools
+ echo "Fetching auxmos..."
+ cd auxmos
git fetch
+ ~/.cargo/bin/rustup target add i686-unknown-linux-gnu
fi
-echo "Deploying extools..."
-git checkout "$EXTOOLS_VERSION"
-if [ -d "build" ]; then
- rm -R build
-fi
-mkdir build
-cd build
-cmake ..
-make
-mv libbyond-extools.so "$1/libbyond-extools.so"
-cd ../../..
+echo "Deploying auxmos..."
+git checkout "$AUXMOS_VERSION"
+env PKG_CONFIG_ALLOW_CROSS=1 ~/.cargo/bin/cargo rustc --release --target=i686-unknown-linux-gnu --features "all_reaction_hooks" -- -C target-cpu=native
+mv -f target/i686-unknown-linux-gnu/release/libauxmos.so "$1/libauxmos.so"
+cd ..
# install or update youtube-dl when not present, or if it is present with pip3,
# which we assume was used to install it